Game.UI.Editor.EditorAssetCategorySystem
Assembly: Assembly-CSharp (game code)
Namespace: Game.UI.Editor
Type: class
Base: GameSystemBase
Summary:
Manages the hierarchy of editor asset categories used by the in-game editor (Buildings, Vehicles, Props, Foliage, Roads, Tracks, Effects, Locations, etc.). The system builds category trees from prefab data and entity queries, applies filters (service type, zone type, passenger count, track type, theme, maintenance type, signature buildings, public transport type) and respects per-prefab overrides supplied through EditorAssetCategoryOverride prefabs. Categories are lazily regenerated when needed (m_Dirty) and exposed via enumerable APIs for UI code to consume. This is the central system for determining which prefabs belong in which editor categories for Cities: Skylines 2 modding.
Fields
-
private List<EditorAssetCategory> m_Categories
Holds the top-level categories (roots) created by GenerateCategories(). Each EditorAssetCategory can have subCategories and associated entity queries, filters, icons, inclusion/exclusion lists, etc. -
private Dictionary<string, EditorAssetCategory> m_PathMap
Lookup map from category path (e.g. "Buildings/Services/Police") to the corresponding EditorAssetCategory. Used when applying overrides and when creating categories dynamically. -
private PrefabSystem m_PrefabSystem
Reference to the PrefabSystem (retrieved in OnCreate) used to resolve prefab components, prefab names, icons and to convert theme or prefab Entity references to PrefabBase objects. -
private EntityQuery m_ServiceQuery
Query that returns ServiceData prefabs (used to generate per-service building categories). -
private EntityQuery m_ZoneQuery
Query that returns ZoneData prefabs (used to generate zone/area-specific categories such as Residential, Commercial, Industrial). -
private EntityQuery m_ThemeQuery
Query that returns ThemeData prefabs (used for tree/foliage categories and signature buildings per theme). -
private EntityQuery m_Overrides
Query that returns EditorAssetCategoryOverrideData prefabs. These overrides provide explicit include/exclude lists to modify category membership per-prefab. -
private EntityQuery m_PrefabModificationQuery
Query that detects prefab creations/deletions (Created/Deleted components) to mark the category list dirty for regeneration. -
private bool m_Dirty
If true, categories will be regenerated on next GetCategories/GetHierarchy call. Set by OnUpdate when prefab modifications are detected or when GenerateCategories is required. -
private TypeHandle __TypeHandle
Internal struct used to store an EntityTypeHandle for performing entity type checks inside EditorAssetCategory.IsEmpty and other operations requiring an EntityTypeHandle. -
private struct TypeHandle
Internal nested struct that contains an EntityTypeHandle and a helper to assign handles from a SystemState. Used for fast checks relying on entity type information.
Properties
- No public properties exposed by this system class. (All important data is exposed via the GetCategories and GetHierarchy enumerables and via the EditorAssetCategory objects.)
Constructors
public EditorAssetCategorySystem()
Default constructor. Marked/preserved for ECS; system is initialized by the game's world creation flow. No special runtime initialization beyond what OnCreate does.
Methods
-
protected override void OnCreate()
: System.Void
Initializes the system: obtains PrefabSystem, builds EntityQuery instances (services, zones, themes, overrides, prefab modification detection). Called once when the system is created. -
protected override void OnUpdate()
: System.Void
Checks m_PrefabModificationQuery to detect prefab creation/deletion events and marks the category data dirty (m_Dirty = true) so categories will be regenerated next time they are requested. -
public IEnumerable<EditorAssetCategory> GetCategories(bool ignoreEmpty = true)
: IEnumerable
Returns a flat enumerable of categories (top-level and subcategories) optionally excluding empty categories. Triggers GenerateCategories() when m_Dirty == true. -
public IEnumerable<HierarchyItem<EditorAssetCategory>> GetHierarchy(bool ignoreEmpty = true)
: IEnumerable>
Returns categories as hierarchy items (category + level) suitable for building hierarchical UI lists. Also triggers regeneration if m_Dirty == true. -
private void AddCategory(EditorAssetCategory category, EditorAssetCategory parent = null)
: System.Void
Adds category to either the list of roots or as a subcategory of parent; sets the category.path (concatenated parent.path + id) and registers the path in m_PathMap. -
private void ClearCategories()
: System.Void
Clears all categories and the path map. Called at the start of GenerateCategories(). -
private IEnumerable<(EditorAssetCategory, int)> GetCategoriesImpl(IEnumerable<EditorAssetCategory> categories, int level, bool ignoreEmpty)
: IEnumerable<(EditorAssetCategory, int)>
Recursive helper that enumerates categories and their subcategories, optionally skipping those that are empty (category.IsEmpty uses EntityManager + PrefabSystem and an EntityTypeHandle). -
private void GenerateCategories()
: System.Void
Top-level category generation routine. Clears existing categories and calls many sub-routines to create categories for Buildings, Vehicles, Props, Foliage, Characters, Areas, Surfaces, Bridges, Roads, Tracks, Effects, Locations and then applies overrides. Sets m_Dirty = false at the end. -
Building generation helpers:
private void GenerateBuildingCategories()
private void GenerateServiceBuildingCategories(EditorAssetCategory parent)
private void GenerateSpawnableBuildingCategories(EditorAssetCategory parent)
private void GenerateZoneCategories(AreaType areaType, bool office, EditorAssetCategory parent)
private void GenerateMiscBuildingCategory(EditorAssetCategory parent)
These methods create Building-related categories (Services, per-zone categories, signature buildings, Extractors, etc.) and use filters such as ServiceTypeFilter, ZoneTypeFilter and SignatureBuildingFilter.
- Vehicle generation helpers:
private void GenerateVehicleCategories()
private void GenerateResidentialVehicleCategory(EditorAssetCategory parent)
private void GenerateServiceVehicleCategories(EditorAssetCategory parent)
private void GeneratePublicTransportVehicleCategory(TransportType transportType, EditorAssetCategory parent)
private void GenerateIndustrialVehicleCategory(EditorAssetCategory parent)
These methods create vehicle categories (Residential, Service types, Aircraft, Police, Ambulance, Fire, Garbage, Parks, Roads, Public Transport types) and use filters like PassengerCountFilter, PublicTransportTypeFilter and MaintenanceTypeFilter.
- Prop / foliage / environment helpers:
private void GeneratePropCategories()
private void GenerateFoliageCategories()
private void GenerateTreeCategories(EditorAssetCategory parent)
-
private void GenerateBushCategories(EditorAssetCategory parent)
-
Roads, Tracks, Effects, Locations, Bridges, Characters, Areas & Surfaces:
private void GenerateRoadCategory()
private void GenerateTrackCategories()
private void GenerateTrackTypeCategory(TrackTypes trackTypes, EditorAssetCategory parent)
private void GenerateEffectCategories()
private void GenerateLocationCategories()
private void GenerateBridgeCategory()
private void GenerateCharacterCategories()
private void GenerateAreaCategories()
-
private void GenerateSurfaceCategories()
-
private void AddOverrides()
: System.Void
Applies per-prefab overrides by iterating the m_Overrides query, reading EditorAssetCategoryOverride from the prefab (via PrefabSystem.TryGetPrefab), and either adding explicit included categories or adding exclusions to existing categories. If an include path doesn't exist in m_PathMap, CreateCategory(string path) will create the hierarchy as needed. -
private EditorAssetCategory CreateCategory(string path)
: EditorAssetCategory
Splits a category path string by "/" and creates any missing intermediate categories, returning the final created/found EditorAssetCategory. Useful for EditorAssetCategoryOverride include entries that reference a custom path. -
protected override void OnCreateForCompiler()
: System.Void
Compiler-only initialization helper that assigns internal handles required by the generated code (calls __AssignQueries and TypeHandle.__AssignHandles). -
private void __AssignQueries(ref SystemState state)
: System.Void
Internal method used by the system's generated OnCreateForCompiler routine (no runtime logic beyond query initialization placeholder).
Notes on nested filter classes: - IEditorAssetCategoryFilter and its implementations (ServiceTypeFilter, ZoneTypeFilter, PassengerCountFilter, PublicTransportTypeFilter, MaintenanceTypeFilter, ThemeFilter, TrackTypeFilter, SignatureBuildingFilter) encapsulate rules to determine whether a prefab belongs to a category. Each filter implements Contains(Entity prefab, EntityManager entityManager, PrefabSystem prefabSystem) used during category emptiness checks and category assignment logic.
Usage Example
// Example: obtain categories from a system and iterate them
var editorCategorySystem = World.DefaultGameObjectInjectionWorld
.GetOrCreateSystemManaged<Game.UI.Editor.EditorAssetCategorySystem>();
// Get all categories (ignoring empty categories)
foreach (var category in editorCategorySystem.GetCategories(ignoreEmpty: true))
{
Debug.Log($"Category: {category.path} (id: {category.id})");
}
// Get hierarchical items for UI building
foreach (var item in editorCategorySystem.GetHierarchy(ignoreEmpty: true))
{
var category = item.Item;
var level = item.Level;
// Build UI entry using category.id, category.icon, category.path, and level
}
Additional modding tips: - EditorAssetCategorySystem caches generated categories and will only regenerate when it detects prefab creation/deletion (or when m_Dirty is set internally). If you programmatically add new prefabs or change prefab components at runtime, you can trigger regeneration by ensuring the Created/Deleted components are applied to the prefabs so the system's m_PrefabModificationQuery will mark m_Dirty = true. - To force specific prefab membership in a category, create a prefab with EditorAssetCategoryOverride (m_IncludeCategories and/or m_ExcludeCategories) and ensure it is present in the m_Overrides query — the system will apply these overrides on GenerateCategories. - Filters are executed using the EntityManager and PrefabSystem. If you need to replicate category logic, use the same filter semantics (e.g. ServiceTypeFilter checks ServiceObjectData and ServiceUpgradeBuilding buffer). - Categories are represented by EditorAssetCategory objects; inspect them to query their entityQuery, filter, icon and explicit includes/excludes if you need to render or modify the UI.