Skip to content

Game.UI.InGame.StatisticsUISystem

Assembly:
Namespace: Game.UI.InGame

Type: class

Base: UISystemBase

Summary:
StatisticsUISystem is the UI system that drives the in-game statistics / charts UI. It exposes UI bindings (categories, groups, datasets, selected items, sample range/count and triggers) and builds chart data from the game's CityStatistics data. The system caches available statistic entries (groups, subgroups and parameterized statistic entries), responds to UI triggers to add/remove statistics, and converts raw statistic samples into chart-friendly DataPoint sequences. It also reacts to the ICityStatisticsSystem.eventStatisticsUpdated event to update the UI when statistics change.


Fields

  • private const string kGroup = "statistics"
    Name used as the root group for UI bindings registered by the system.

  • private PrefabUISystem m_PrefabUISystem
    Reference to PrefabUISystem used for prefab-related UI binding helpers (e.g., requirement bindings).

  • private PrefabSystem m_PrefabSystem
    Reference to PrefabSystem for resolving prefabs (Statistic prefabs, ParametricStatistic, etc.).

  • private ResourceSystem m_ResourceSystem
    Reference to ResourceSystem for resource/market price lookups used when converting resource statistics to currency values.

  • private ICityStatisticsSystem m_CityStatisticsSystem
    Reference to the city statistics system (samples, sample count, data arrays). Subscribed to its eventStatisticsUpdated to refresh UI data.

  • private CityConfigurationSystem m_CityConfigurationSystem
    Reference used to check city configuration (e.g., unlimitedMoney) to filter out certain statistics.

  • private MapTilePurchaseSystem m_MapTilePurchaseSystem
    Used to determine whether MapTileUpkeep statistics should be shown depending on map tile upkeep setting.

  • private TimeUISystem m_TimeUISystem
    Used for time/tick conversions when building DataPoint.x values.

  • private EntityQuery m_StatisticsCategoryQuery
    Query used to enumerate statistic UI categories (UIObjectData + PrefabData + UIStatisticsCategoryData).

  • private EntityQuery m_TimeDataQuery
    Query used to obtain TimeData singleton.

  • private EntityQuery m_UnlockedPrefabQuery
    Query used to determine unlocked prefabs (used for unlocking requirements and re-binding when unlocked).

  • private List<StatItem> m_GroupCache
    Temporary list cache used to hold group children (for BindGroups / TryAddChildren).

  • private List<StatItem> m_SubGroupCache
    Temporary list cache used to hold subgroup children (for subgroup additions).

  • private List<StatItem> m_SelectedStatistics
    List of currently selected StatItem entries that are shown on the chart.

  • private List<StatItem> m_SelectedStatisticsTracker
    List used to track selection state including group tracker entries and subgroup tracker entries (used to preserve selection order and grouping behavior).

  • private Entity m_ActiveCategory
    Entity of the currently active category (UIStatisticsCategoryData).

  • private Entity m_ActiveGroup
    Entity of the currently active group (UIStatisticsGroupData or group entity).

  • private int m_SampleRange
    Range (in samples) used for building chart series (max number of samples shown).

  • private bool m_Stacked
    Whether the chart is in stacked mode (controls dataset "fill" and stacking behavior).

  • private RawMapBinding<Entity> m_GroupsMapBinding
    Binding for "statistics.groups" that enumerates children (groups) of a given category.

  • private ValueBinding<int> m_SampleRangeBinding
    Binding for "statistics.sampleRange" (reflects m_SampleRange).

  • private ValueBinding<int> m_SampleCountBinding
    Binding for "statistics.sampleCount" (reflects m_CityStatisticsSystem.sampleCount).

  • private GetterValueBinding<Entity> m_ActiveGroupBinding
    Getter binding for "statistics.activeGroup" (reads m_ActiveGroup).

  • private GetterValueBinding<Entity> m_ActiveCategoryBinding
    Getter binding for "statistics.activeCategory" (reads m_ActiveCategory).

  • private GetterValueBinding<bool> m_StackedBinding
    Getter binding for "statistics.stacked" (reads m_Stacked).

  • private RawValueBinding m_SelectedStatisticsBinding
    Binding for "statistics.selectedStatistics" which serializes current selected StatItem list.

  • private RawValueBinding m_CategoriesBinding
    Binding for "statistics.categories" which enumerates available statistic categories.

  • private RawValueBinding m_DataBinding
    Binding for "statistics.data" which serializes the datasets (chart series) for the UI.

  • private RawMapBinding<Entity> m_UnlockingRequirementsBinding
    Binding for "statistics.unlockingRequirements" to expose required unlocks for prefabs (uses PrefabUISystem helper).

  • private bool m_ClearActive = true
    Internal boolean used by removal logic to decide whether to clear active category/group on deep removals.

  • private int m_UnlockRequirementVersion
    Tracks component order/version for unlock requirements to know when to rebind unlocking requirements.

Properties

  • This class does not expose public properties. The UI surface is provided via the Raw/Value/Trigger bindings registered in OnCreate (see Summary for binding keys and triggers).

Constructors

  • public StatisticsUISystem()
    Default constructed UI system. Typical initialization happens in OnCreate override (system is created by the ECS world and OnCreate registers UI bindings and acquires system references).

Methods

  • protected override void OnCreate() : System.Void
    Initializes queries, caches, retrieves other systems (PrefabSystem, ResourceSystem, CityStatisticsSystem, etc.), subscribes to city statistics events, registers all UI bindings and triggers. Key bindings registered:
  • Value bindings: "statistics.sampleRange", "statistics.sampleCount", "statistics.activeGroup", "statistics.activeCategory", "statistics.stacked", "statistics.updatesPerDay"
  • Raw bindings: "statistics.groups" (map binding), "statistics.categories", "statistics.data", "statistics.selectedStatistics", "statistics.unlockingRequirements"
  • Triggers: "statistics.addStat" (StatItem), "statistics.addStatChildren" (StatItem), "statistics.removeStat" (StatItem), "statistics.clearStats" (), "statistics.setSampleRange" (int)

  • private void BindUnlockingRequirements(IJsonWriter writer, Entity prefabEntity) : System.Void
    Delegates to PrefabUISystem.BindPrefabRequirements to write unlocking requirement info for a prefab.

  • protected override void OnGameLoaded(Context serializationContext) : System.Void
    Called after game load — clears selected statistics and sets a default sample range (32).

  • protected override void OnUpdate() : System.Void
    Updates sample count and sample range bindings. Checks for changes in unlock requirements component order/version and triggers re-bind of unlockingRequirements, groups and categories when necessary.

  • protected override void OnDestroy() : System.Void
    Unsubscribes from m_CityStatisticsSystem.eventStatisticsUpdated and calls base.OnDestroy.

  • private void OnStatisticsUpdated() : System.Void
    Triggered when statistics change; updates the data binding so UI will re-fetch current chart datasets.

  • private void BindSelectedStatistics(IJsonWriter binder) : System.Void
    Serializes the currently selected statistics (m_SelectedStatistics) to the binder as an array of StatItem objects.

  • private void BindCategories(IJsonWriter binder) : System.Void
    Enumerates statistic categories (via GetSortedCategories), and writes array items containing entity, key (prefab.name) and locked state.

  • private NativeList<StatCategory> GetSortedCategories() : NativeList
    Collects UIObjectData + PrefabData + entity for all category entities matching m_StatisticsCategoryQuery, converts into a NativeList, sorts by UIObjectData.m_Priority and returns it.

  • private void CacheChildren(Entity parentEntity, List<StatItem> cache) : System.Void
    Fills the provided cache list with StatItem objects representing children of the provided entity. Handles group entries, parametric statistics (parameters buffer), UIStatisticsGroupData entries, StatisticsData entries, colors, locked state, stacking, and special filtering (e.g., MapTileUpkeep, unlimitedMoney). Uses PrefabSystem to resolve prefab names for labels.

  • private void CacheParameterChildren(Entity parent, bool locked, StatisticsData statisticsData, PrefabData prefabData, List<StatItem> cache) : System.Void
    Called for parametric statistics: enumerates StatisticParameterData buffer and creates StatItem entries per parameter.

  • private void BindGroups(IJsonWriter binder, Entity parent) : System.Void
    Caches children of parent and writes them as an array using StatItem writer.

  • private void BindData(IJsonWriter binder) : System.Void
    Writes all selected statistics datasets (m_SelectedStatistics) in reverse order to the binder. Each dataset is written by BindData(binder, stat).

  • private void BindData(IJsonWriter binder, StatItem stat) : System.Void
    Writes a single dataset: label, array of DataPoint objects (from GetStatisticData), borderColor (hex), backgroundColor (rgba with 0.5 alpha), and fill string ("origin" if stacked else "false").

  • private NativeList<DataPoint> GetStatisticData(StatItem stat) : NativeList
    Core routine that reads sample arrays from ICityStatisticsSystem for a given StatItem, handles parametric and subgroup aggregation, converts resource statistics to value using market price if necessary, handles population-normalized stats, ensures arrays have expected sample count (EnsureDataSize), and builds a NativeList representing the series (via GetDataPoints). Completes any pending writers with m_CityStatisticsSystem.CompleteWriters() at start.

  • private NativeArray<long> EnsureDataSize(NativeArray<long> data) : NativeArray
    If the provided statistic array is smaller than the current sampleCount, this creates a new temporary native array of length sampleCount, fills with leading zeros and the provided data at the end, and returns it. Used to align sample arrays.

  • private NativeList<DataPoint> GetDataPoints(int range, int samples, NativeArray<long> data, TimeData timeData) : NativeList
    Converts a long[] of samples into a NativeList. Chooses a sample interval using GetSampleInterval to downsample if necessary, builds x values based on sample frame indices and time ticks, and inserts first and last points to maintain chart continuity.

  • private int GetSampleInterval(int range) : int
    Computes a sampling interval for downsampling when range > 32. If range <= 32 returns 1, otherwise computes a reasonable interval to reduce the number of chart points.

  • private void CheckActiveCategory(StatItem stat) : System.Void
    If stat.category differs from m_ActiveCategory, clears current selections and sets the new active category (updates binding).

  • private void CheckActiveGroup(StatItem stat) : System.Void
    If active group isn't set or differs, clears current selections and sets m_ActiveGroup depending on whether the stat is a group entry or not (updates binding).

  • private void ProcessAddStat(StatItem stat) : System.Void
    Called by "statistics.addStat" trigger. Handles adding a stat based on whether it's a group, subgroup, or parameter/statistic entry. Respects locked state, manages selected lists, updates stacked status and triggers UI updates.

  • private void ProcessAddStatChildren(StatItem stat) : System.Void
    Called by "statistics.addStatChildren" trigger. For subgroup entries, attempts to add child parameter entries.

  • private void UpdateStackedStatus() : System.Void
    Determines whether chart should be stacked based on currently tracked selected statistics (checks UIStatisticsGroupData.m_Stacked and individual StatItem.stacked flags). Updates m_StackedBinding.

  • private void AddStat(StatItem stat, bool onlyTracker) : System.Void
    Adds a StatItem to the tracker list and optionally to the visible selected list.

  • private bool TryAddChildren(StatItem stat, List<StatItem> cache) : bool
    Caches children of stat.entity into cache and calls ProcessAddStat for each child. Returns true if any children exist.

  • private void DeepRemoveStat(StatItem stat) : System.Void
    Complex removal logic invoked by the "statistics.removeStat" trigger: removes stat and its children, handles special cases where a group/subgroup interplay exists, may clear active category/group, and updates state.

  • private void RemoveStatParent(StatItem stat) : System.Void
    If a parent subgroup is tracked and a parameter child is added, removes the parent subgroup tracker entry.

  • private void RemoveStatChildren(StatItem stat) : System.Void
    Removes children of the provided stat from both m_SelectedStatistics and m_SelectedStatisticsTracker depending on whether stat is a group or a subgroup.

  • private void RemoveStat(StatItem stat, bool keepTracker) : System.Void
    Removes stat from m_SelectedStatistics and optionally from m_SelectedStatisticsTracker based on keepTracker.

  • private void ClearStats() : System.Void
    Clears both selected lists, updates bindings and clears active category/group.

  • private void UpdateStats() : System.Void
    Sorts m_SelectedStatistics, and updates the selectedStatistics and data bindings so UI is refreshed.

  • private void ClearActive() : System.Void
    Sets active group and category to Entity.Null and updates corresponding bindings.

  • private void SetSampleRange(int range) : System.Void
    Sets m_SampleRange, updates its binding and triggers an UpdateStats().

  • private void BindGroups(IJsonWriter binder, Entity parent) : System.Void
    (duplicate entry listed above) Writes group list for a specific category (used by UI map binding).

Nested types (brief):

  • StatCategory (struct) — simple container of entity, PrefabData and UIObjectData, implements IComparable to sort by UIObjectData.m_Priority.

  • DataPoint (struct) — represents a single chart sample { long x, long y } and implements IJsonWritable.

  • StatItem (struct) — serializable representation of a selectable statistic entry (category, group, entity, statisticType, unitType, parameterIndex, key, color, locked, isGroup/isSubgroup, stacked, priority). Implements IJsonReadable/IJsonWritable/IComparable. This is the structure that the UI and trigger bindings use to represent items.

Usage Example

// Typical internal usage is within the system: OnCreate registers bindings and triggers.
// Example: initialize sample range in OnGameLoaded (the system already does this).
[Preserve]
protected override void OnGameLoaded(Context serializationContext)
{
    base.OnGameLoaded(serializationContext);
    m_SelectedStatistics.Clear();
    m_SampleRange = 32; // default shown by the UI
}

// Example of programmatically changing the sample range from another system (if you have access)
// You can call the trigger binding if you have access to the UI binding system, or invoke the system method if accessible:
// Assuming you can get the StatisticsUISystem instance:
var statsSystem = world.GetOrCreateSystemManaged<StatisticsUISystem>();
// The SetSampleRange method is private; proper way from UI is to use the "statistics.setSampleRange" trigger with an int.
// How the UI expects StatItem is defined by StatItem fields: category, group, entity, statisticType, unitType, parameterIndex, key, color, locked...

Additional notes for modders: - Bindings registered by this system (root key "statistics") are: - Map bindings / values: "statistics.groups" (map), "statistics.categories" (list), "statistics.data" (chart datasets), "statistics.selectedStatistics" (list), "statistics.unlockingRequirements" (map) - Value bindings: "statistics.sampleRange", "statistics.sampleCount", "statistics.activeGroup", "statistics.activeCategory", "statistics.stacked", "statistics.updatesPerDay" - Trigger bindings: "statistics.addStat" (StatItem), "statistics.addStatChildren" (StatItem), "statistics.removeStat" (StatItem), "statistics.clearStats" (), "statistics.setSampleRange" (int) - The StatItem JSON shape is used for serializing / deserializing selected items. See StatItem.Read / Write to understand exact property names. - GetStatisticData aggregates and converts raw statistic arrays to chartable DataPoint arrays — it can multiply resource quantities by market price for resource-value statistics (StatisticType == 4). - Performance: the system uses NativeArray/NativeList and temporary allocations; it calls m_CityStatisticsSystem.CompleteWriters() before reading arrays — ensure mod code interacting with the underlying statistics system respects threading and completion semantics. - To add new statistics to be shown here, create prefabs/components consistent with StatisticsData/UIStatisticsGroupData/UIObjectData/PrefabData and register them in the prefab database so this system's queries pick them up.