Game.MapPanelSystem
Assembly: Assembly-CSharp (game code)
Namespace: Game.UI.Editor
Type: class
Base: EditorPanelSystemBase
Summary:
MapPanelSystem implements the "Map" editor panel used in Cities: Skylines 2 editor mode. It builds and manages the UI widgets for map metadata and settings (map name/description, starting time, camera start position, preview/thumbnail selection, required content checklist, theme selection, starting tiles selection, save/load/share actions). The system coordinates with multiple world systems (TerrainSystem, SaveGameSystem, MapMetadataSystem, CityConfigurationSystem, MapTilePurchaseSystem, PrefabSystem, MapRequirementSystem, ClimateSystem, etc.), handles persistence (saving map metadata, map data, preview/thumbnail assets, localization) and responds to editor lifecycle events (OnCreate, OnGameLoaded, OnStartRunning, OnStopRunning, OnUpdate).
Fields
-
private Colossal.Hash128 m_CurrentSourceDataGuid
GUID of the currently loaded/edited MapMetadata source. Updated when loading/creating/saving a map. -
private TerrainSystem m_TerrainSystem
Reference to the TerrainSystem in the world. Used indirectly for map operations (initialized in OnCreate). -
private SaveGameSystem m_SaveGameSystem
Reference to SaveGameSystem used to serialize map data to a MapData asset when saving. -
private MapMetadataSystem m_MapMetadataSystem
Reference to MapMetadataSystem that stores map metadata state (map name, theme, resources, etc.). -
private CityConfigurationSystem m_CityConfigurationSystem
Holds city configuration such as camera start position; used to read/write camera fields in the UI. -
private IMapTilePurchaseSystem m_MapTilePurchaseSystem
Used to toggle and manage selecting starting tiles in the map editor. -
private EndFrameBarrier m_EndFrameBarrier
System barrier used to create an EntityCommandBuffer for deferred ECS component updates (e.g., ApplyTime uses it to SetComponent on the Time singleton). -
private PrefabSystem m_PrefabSystem
PrefabSystem reference used to enumerate theme prefabs and to save climate prefab when saving map. -
private EditorAssetUploadPanel m_AssetUploadPanel
Reference to the panel used to upload/share maps to the platform service. -
private EntityQuery m_TimeQuery
EntityQuery used to access TimeData singleton (starting year/month/time). -
private EntityQuery m_ThemeQuery
EntityQuery used to enumerate theme entities in the world. -
public bool m_MapNameAsCityName
Public flag toggled in UI indicating whether the map name should be used as default city name. -
public int m_StartingYear
Public field representing the chosen starting year in UI. When applied, propagated to TimeData (via ApplyTime). -
public int m_StartingMonth
Public field for the chosen starting month (1..12) in UI. -
public float m_StartingTime
Public field for the chosen starting time fraction (0..~1) in UI. -
public bool m_CurrentYearAsStartingYear
Public flag which when true disables custom starting year and uses current year. -
private IconButtonGroup m_ThemeButtonGroup
Group widget used to display theme choices as icon buttons. -
private LocalizationField m_MapNameLocalization
Widget for editing localized map name(s). -
private LocalizationField m_MapDescriptionLocalization
Widget for editing localized map description(s). -
private PreviewInfo m_Preview
Internal helper struct (PreviewInfo) storing preview image asset/texture and linked UI button for selecting/setting preview. -
private PreviewInfo m_Thumbnail
Similar to m_Preview, for the map thumbnail. -
private Button m_MapTileSelectionButton
Button widget that toggles selecting starting tiles; label is updated when toggling. -
private static readonly string kSelectStartingTilesPrompt = "Editor.SELECT_STARTING_TILES"
Localized prompt shown when starting tile selection can be started. -
private static readonly string kStopSelectingStartingTilesPrompt = "Editor.STOP_SELECTING_STARTING_TILES"
Localized prompt shown while selecting starting tiles (to stop selection). -
private MapRequirementSystem m_MapRequirementSystem
System used to compute/track map requirements and checklist (water, roads, resources, connections) used by the UI. -
private PagedList m_RequiredListWidget
UI widget listing required content (prerequisites) for the map. -
private EditorGenerator m_Generator
Editor UI generator helper used to build nested widgets (used to create prerequisites list widget). -
private PdxSdkPlatform m_Platform
Cached platform integration reference (PdxSdk) used to show/hide the "share map" option and handle uploads. -
(Nested) private struct PreviewInfo
Nested value-type helper that holds either an ImageAsset or a TextureAsset, and an associated IconButton. Contains helpers to load textures, copy ImageAsset into a TextureAsset in a target ILocalAssetDatabase, and to set the button icon.
Properties
- (No public C# properties are declared on this class; several public fields act as exposed settings, e.g. m_MapNameAsCityName, m_StartingYear, etc.)
Constructors
public MapPanelSystem()
Default constructor. The system is a managed World system and is created by the ECS world. Initialization of fields and UI is done in OnCreate.
Methods
-
protected override void OnCreate()
Initializes the system: creates EditorGenerator, resolves world-managed systems (TerrainSystem, SaveGameSystem, MapMetadataSystem, CityConfigurationSystem, PrefabSystem, MapTilePurchaseSystem, EndFrameBarrier, MapRequirementSystem, EditorAssetUploadPanel), prepares EntityQueries (TimeData, ThemeData), constructs UI widget hierarchy (sections for map settings, theme selection, prerequisites, preview/thumbnail widgets, checklist), prepares IconButton callbacks for preview/thumbnail pickers, sets up platform integration callback. This method builds the panel contents and binds widget actions (e.g., ShowLoadMapPanel, ShowSaveMapPanel, ToggleMapTileSelection, CaptureCameraProperties). -
protected override void OnGameLoaded(Context serializationContext)
Called when a game or map context is loaded. For Purpose.NewMap or Purpose.LoadMap, ensures a TimeData entity exists, updates prerequisites widget, fetches theme/time values, stores the instigatorGuid as current source data GUID, loads MapMetadata of the current guid and initializes MapMetadataSystem values, map localization and preview. -
protected override void OnStartRunning()
Marks activeSubPanel null and enables MapRequirementSystem (starts tracking map requirements). -
protected override void OnStopRunning()
Called when the system stops running: stops tile selection (m_MapTilePurchaseSystem.selecting = false) and disables MapRequirementSystem. -
protected override void OnUpdate()
Per-frame update: updates the map requirement system and updates the map tile selection UI state. If tile selection is active, updates button label to stop prompt and calls UpdateStartingTiles(); otherwise updates label to start prompt. -
private void FetchThemes()
Reads theme entities from m_ThemeQuery, converts each ThemePrefab into an IconButton with icon/tooltip/selected function/action, and assigns those buttons to m_ThemeButtonGroup.children. Uses ImageSystem.GetIcon(prefab) or a fallback icon. -
private void FetchTime()
Reads TimeData singleton and populates m_StartingYear, m_CurrentYearAsStartingYear, m_StartingMonth (converting stored 0-based month to 1-based) and m_StartingTime. -
private void SetStartingYear(int value)
Setter used by UI; updates m_StartingYear and calls ApplyTime() to write the new TimeData. -
private void SetStartingMonth(int value)
Updates m_StartingMonth and calls ApplyTime(). -
private void SetStartingTime(float value)
Updates m_StartingTime and calls ApplyTime(). -
private void ApplyTime()
Builds a TimeData struct from current UI fields and writes it to the TimeData singleton entity using an EntityCommandBuffer created from m_EndFrameBarrier (deferred SetComponent). Ensures ECS-safe update at end of frame. -
public void ShowLoadMapPanel()
Opens a LoadAssetPanel configured with available maps (GetMaps()) and callback OnLoadMap. -
public void ShowSaveMapPanel()
Opens a SaveAssetPanel listing existing maps (GetMaps()) and uses OnSaveMap as the save callback. Provides current m_CurrentSourceDataGuid as selected/overwrite candidate. -
private void ShowShareMapPanel()
Opens a SaveAssetPanel used for saving and then sharing; on save it calls OnSaveMap with ShareMap as the final callback. The share/save button is hidden if platform is not logged in. -
private IEnumerable<AssetItem> GetMaps()
Enumerates global MapMetadata assets (AssetDatabase.global.GetAssets) and yields AssetItem entries for user-editable maps (skips built-in game DB assets). Uses TryGetAssetItem to convert asset to AssetItem, catching errors. -
private bool TryGetAssetItem(MapMetadata asset, out AssetItem item)
Tries to convert MapMetadata to an AssetItem for UI lists. Extracts MapInfo target and SourceMeta (filename/display name, thumbnail) and constructs AssetItem with guid, fileName, displayName, image Uri, and remote badge if applicable. On exceptions logs and returns false. -
private void ShowPreviewPicker()
Opens an asset picker panel (LoadAssetPanel) populated with user images to select a preview image. Callback is OnSelectPreview. -
private void ShowThumbnailPicker()
Similar to ShowPreviewPicker but for thumbnail selection. Callback is OnSelectThumbnail. -
private void OnSelectPreview(Colossal.Hash128 guid)
Sets m_Preview to the ImageAsset corresponding to guid and closes the subpanel. -
private void OnSelectThumbnail(Colossal.Hash128 guid)
Sets m_Thumbnail to the ImageAsset corresponding to guid and closes the subpanel. -
private void OnLoadMap(Colossal.Hash128 guid)
Displays a confirmation dialog warning about progress loss; if user confirms (ret == 0) calls LoadMap(guid). -
public async Task LoadMap(Colossal.Hash128 guid)
Closes any open subpanel, tries to fetch MapMetadata from the global AssetDatabase for guid, then asynchronously calls GameManager.instance.Load(GameMode.Editor, Purpose.LoadMap, asset) to load the map in editor mode. Note: uses ConfigureAwait(false) inside the method. -
private void InitPreview(MapMetadata asset = null)
Initializes preview and thumbnail UI widgets from a given MapMetadata (uses asset.target.preview/thumbnail) or falls back to default assets (MenuHelpers.defaultPreview / defaultThumbnail). -
private void InitLocalization(MapMetadata asset = null)
Initializes m_MapNameLocalization and m_MapDescriptionLocalization: if MapMetadata provided, initializes fields using locale assets and keys built from the map display name; otherwise initializes empty localization fields. -
private void OnSaveMap(string fileName, Colossal.Hash128? overwriteGuid, Action<MapMetadata> callback = null)
Called when user requests save via UI. Updates MapMetadataSystem, then if overwriteGuid provided asks for overwrite confirmation and on confirm calls SaveMap with existing asset's database/path; otherwise closes the panel and calls SaveMap to create a new asset in the user asset database (embedLocalization = true). -
public async Task SaveMap(string fileName, Colossal.Hash128 overwriteGuid, MapInfo existing, ILocalAssetDatabase finalDb, AssetDataPath packagePath, bool embedLocalization, Action<MapMetadata> callback = null)
Performs the full save flow: - Sets m_MapMetadataSystem.mapName to fileName.
- Creates a transient local database for packaging.
- Builds MapInfo by merging existing with current UI/system values via GetMapInfo.
- Adds MapMetadata and MapData to transient DB, sets climate (via SaveClimate).
- Configures m_SaveGameSystem context and stream, awaits m_SaveGameSystem.RunOnce() to serialize map scene/data into MapData.
- Gathers referenced content into contentPrerequisites.
- Copies preview/thumbnail image assets into the transient DB (via m_Preview.CopyToTextureAsset / m_Thumbnail.CopyToTextureAsset) and saves them; sets MapInfo.preview/thumbnail.
- If embedLocalization true, calls SaveLocalization to write locale assets into DB and assigns to MapInfo.localeAssets.
- Saves metadata meta.Save() and then packages the transient DB into finalDb: if a PackageAsset already exists, replaces it preserving identifier, else adds new PackageAsset.
- If finalDb has a cache, triggers finalDb.ResaveCache() and logs text if returned.
-
On main thread, unlocks the Cartography achievement, calls InitPreview(meta), and invokes optional callback with the produced MapMetadata. This method is async and performs I/O on background threads where applicable.
-
private PrefabAsset SaveClimate(ILocalAssetDatabase database)
If the current climate prefab is non-built-in, clones the ClimatePrefab into a PrefabAsset inside the provided local database so the saved map package contains the climate prefab. Returns the saved PrefabAsset (or null for built-in climate). -
private LocaleAsset[] SaveLocalization(ILocalAssetDatabase db, string fileName)
Gathers localization entries from the two LocalizationField widgets and writes per-language LocaleAsset files into the provided DB. Returns an array of created LocaleAsset references. Uses GameManager.instance.localizationManager to map locale ids to languages and localized names. -
private void ShareMap(MapMetadata map)
Shows the EditorAssetUploadPanel for the provided MapMetadata, and sets it as activeSubPanel. -
private MapInfo GetMapInfo(MapInfo merge = null)
Constructs/merges a MapInfo instance containing current map metadata values (displayName, theme, climate ranges, latitude/longitude, area, water/ground water availability, resources, connections, nameAsCityName, startingYear (uses -1 if using current year), buildableLand, content prerequisites were assigned elsewhere). Returns the resulting MapInfo. -
private void CaptureCameraProperties()
If a CameraController instance is available, captures its pivot, angle and zoom and writes them into m_CityConfigurationSystem (used by the camera starting position fields). -
private void ToggleMapTileSelection()
Toggles the boolean m_MapTilePurchaseSystem.selecting which enables/disables tile selection mode. -
private void UpdateStartingTiles()
Placeholder method for updating visuals while selecting starting tiles. Current implementation is empty (stub). Map tile updating is handled elsewhere or intended for future logic. -
private void UpdateMapTileButton(string text)
Updates the m_MapTileSelectionButton.displayName to the provided localized text and marks the button properties changed if the text differs (to refresh UI). Used to switch between start/stop prompts. -
[Preserve] public MapPanelSystem()
System constructor (duplicate listed above): default public constructor used by ECS; class may include Preserve usage for methods to avoid stripping.
Usage Example
// Example: open the Save Map dialog from code (e.g., from another UI action)
var mapPanel = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<Game.UI.Editor.MapPanelSystem>();
mapPanel.ShowSaveMapPanel();
// Example: programmatically save current map into the player user database.
// (In real usage you would await this on an async-capable caller)
await mapPanel.SaveMap(
fileName: "MyCustomMap",
overwriteGuid: Colossal.Hash128.Empty,
existing: null,
finalDb: AssetDatabase.user,
packagePath: SaveHelpers.GetAssetDataPath<MapMetadata>(AssetDatabase.user, "MyCustomMap"),
embedLocalization: true,
callback: (meta) => UnityEngine.Debug.Log("Saved map: " + meta.id)
);