Game.UI.InGame.PhotoModeUISystem
Assembly: Assembly-CSharp
Namespace: Game.UI.InGame
Type: class
Base: UISystemBase
Summary:
Manages the in-game Photo Mode UI: builds tabs and controls for photo-related properties, wires UI bindings and interactions with camera/rendering/tool systems, handles activating/deactivating photo mode, screenshot capture, presets injection and cinematic camera interactions. Intended for use by the game's UI system and modders who need to extend or hook into Photo Mode behavior (e.g., adding custom UI widgets or presets).
Fields
-
private ToolSystem m_ToolSystem
Manages active tools; used to override/restore tools when entering/exiting Photo Mode. -
private DefaultToolSystem m_DefaultToolSystem
Reference to the default tool so Photo Mode can switch to it when disabling other tools. -
private ToolRaycastSystem m_ToolRaycastSystem
Used to modify raycast flags (e.g., to disable free-camera interactions while photo mode overlays are hidden). -
private RenderingSystem m_RenderingSystem
Used to hide overlays and to control Photo Mode rendering options. -
private PlanetarySystem m_PlanetarySystem
Used to update planetary/day-night state when time-of-day changes are applied inside Photo Mode. -
private PhotoModeRenderSystem m_PhotoModeRenderSystem
Provides access to photo mode properties, presets, and applies/reads rendering properties. -
private CameraUpdateSystem m_CameraUpdateSystem
Used to switch between gameplay, cinematic and orbit camera controllers and to set camera states. -
private CinematicCameraUISystem m_CinematicCameraUISystem
Used to toggle cinematic camera modifiers (keyframes/capture property functionality). -
private BulldozeToolSystem m_BulldozeTool
Referenced to avoid overriding the bulldoze tool when hiding overlays. -
private InputBarrier m_ToolBarrier
Barrier used to block underlying tool input while Photo Mode is active. -
private ValueBinding<bool> m_OverlayHiddenBinding
Binding that tracks whether the UI overlay should be hidden. -
private GetterValueBinding<bool> m_OrbitCameraActiveBinding
Getter binding reporting whether the orbit camera is currently active. -
private GetterValueBinding<float> m_FieldOfViewBinding
(Declared but not referenced directly in this file) Typically used to bind the field-of-view UI control to the camera FOV. -
private GetterValueBinding<float> m_TimeOfDayBinding
(Declared) Binding for the in-UI time-of-day value. -
private GetterValueBinding<float> m_SaturationBinding
(Declared) Binding for saturation control. -
private RawMapBinding<Entity> m_AdjustmentCategoriesBinding
(Raw binding) Potentially used to expose adjustment categories to the UI. -
private bool m_TimeOfDayChanged
Flag set when time-of-day is changed; used to trigger planetary updates on the next update tick. -
private ValueBinding<bool> m_CinematicCameraVisibleBinding
Tracks whether the cinematic camera UI is visible (used to enable/disable capture buttons). -
private ValueBinding<string> m_ActiveTabBinding
Binding storing the currently active tab ID in the Photo Mode UI. -
private RawValueBinding m_TabNamesBinding
Binding that provides the list of tabs (names/icons) to the UI via a writer callback. -
private WidgetBindings m_WidgetBindings
Root widget bindings container used to swap the currently active tab's widgets into the UI. -
public bool orbitMode { get; set; }
Tracks whether the user is currently using orbit-mode camera (public property so other systems can inspect/change it). -
private List<Tab> tabs { get; set; } = new List<Tab>()
Internal collection of Tab objects that represent UI tabs; constructed during OnCreate.
Properties
-
public bool orbitMode { get; set; }
Indicates whether the orbit camera is active. The system toggles this when switching between orbit and cinematic controllers. Modders can read or set this to reconfigure camera mode logic externally. -
private List<Tab> tabs { get; set; }
Contains the Tab definitions used to build the Photo Mode UI. Each Tab holds id, icon and a list of IWidget items for that tab.
Constructors
public PhotoModeUISystem()
Default constructor. The real initialization happens in OnCreate; constructor kept for required Unity/ECS lifecycle usage. Marked with [Preserve] on OnCreate and constructor to avoid stripping.
Methods
-
[Preserve] protected override void OnCreate()
Initializes system references, builds tab controls, injects presets, registers UI bindings and default widget bindings. Called once when the system is created. Important: sets up input barrier and default active tab ("Camera"). -
public void Activate(bool enabled)
Enables or disables Photo Mode state: switches camera controllers (gameplay/cinematic/orbit), configures orbit mode settings (collision, follow mode), sets input barrier blocking, and enables/disables photo-mode rendering. Call to activate Photo Mode UI's runtime behavior. -
[Preserve] protected override void OnUpdate()
Runs each tick: applies overlay hiding behavior (ensuring bulldoze tool isn't overridden), updates planetary system if time-of-day changed. Also ensures appropriate raycast flags and tool selection when overlay is hidden. -
private void SetOverlayHidden(bool overlayHidden)
Toggles renderer overlay visibility and adjusts tool raycast flags and active tool accordingly. Updates internal overlay binding value. -
private void BindTabNames(IJsonWriter writer)
Writes the tabs collection to an IJsonWriter used by the UI binding layer. Each tab is serialized via Tab.Write. -
private void SetCinematicCameraVisible(bool visible)
Updates the binding that tracks cinematic camera UI visibility. Used by UI triggers to show/hide cinematic controls. -
private void SelectTab(string tabID)
Selects and activates a tab by ID: sets the ActiveTab binding and swaps the widget bindings children to the tab's items. -
private List<Tab> BuildProperties()
Constructs the tab list by iterating over m_PhotoModeRenderSystem.photoModeProperties, grouping them by property.group and building appropriate widgets per property. Handles multi-component properties and avoids duplicate grouped items. -
private void InjectPresets()
Iterates m_PhotoModeRenderSystem.presets and injects a UI control for each via InjectPreset. -
private void InjectPreset(PhotoModeUIPreset preset)
Injects a dropdown selector for a preset group into the corresponding tab. Creates a DelegateAccessorthat reads/writes preset options and builds a dropdown widget inserted next to the corresponding property UI. -
private static bool CheckMultiPropertyHandled(HashSet<string> handledGroupsCache, PhotoModeProperty property)
Helper to ensure multi-component properties (identified by id containing "/") are only handled once per root group. -
private Group BuildGroupTitle(PhotoModeProperty property)
Returns a Group widget used as a section title for properties without control (read-only headings). -
private Group BuildDropdownGroup(string groupName, List<DropdownItem<int>> items, DelegateAccessor<int> accessor)
Constructs a Group containing a DropdownField for the provided items and accessor. Used for presets injection. -
private Group BuildEnumGroup(PhotoModeProperty property, bool multiPropertyComponent = false)
Builds UI for an enum-based property: includes an EnumField and optional reset IconButton and common controls (enable toggle, add keyframe). Uses AutomaticSettings.GetEnumValues to populate enum members. -
private Group BuildValueGroup(PhotoModeProperty property, bool multiPropertyComponent = false)
Builds UI for numeric properties: either FloatInputField/FloatSliderField for fractional values, or IntInputField/IntSliderField for integer values. Adds common fields and optional reset button. Honors dynamic min/max, fraction digits and the property's enabled state. -
private void AddCommonFields(IList<IWidget> children, PhotoModeProperty property, bool multiPropertyComponent)
Adds controls common to many property groups: enable toggle (if applicable) and the "add keyframe" button (icon triggers cinematic camera modifier). Skips adding these when multiPropertyComponent is true for nested components. -
private IWidget BuildColorGroup(PhotoModeProperty property, IDictionary<string, PhotoModeProperty> allProperties)
Constructs a ColorField that groups r/g/b/(a) components into a single color control by creating a combined accessor. Supports HDR (no max) and optional alpha channel. -
private Group BuildCheckboxGroup(PhotoModeProperty property, bool multiPropertyComponent = false)
Builds a boolean toggle group backed by a numeric property (0/1 stored as float). Adds reset button if available and common fields. -
private Group BuildMultiPropertyGroup(PhotoModeProperty property, IDictionary<string, PhotoModeProperty> allProperties)
Builds a group representing a multi-component property (e.g., "ambient/color" splitting into r/g/b/a). Either builds a color picker if overrideControl is ColorField or adds individual controls for each component. -
private IWidget BuildControl(PhotoModeProperty property, bool multiPropertyComponent = false)
Main factory method: returns the appropriate widget for a given PhotoModeProperty by inspecting id (multi), overrideControl, enumType, and value/get/set availability. -
private void TakeScreenshot()
Triggers the Snapshot achievement and begins a coroutine to capture a screenshot (CaptureScreenshot). -
private void ToggleOrbitCameraActive()
Switches between orbit and cinematic camera controllers, matches positions appropriately, clears followedEntity when entering orbit, and updates the orbit camera binding. -
private static IEnumerator CaptureScreenshot()
Coroutine that disables the UI view for the end-of-frame, yields WaitForEndOfFrame, calls PlatformManager.instance.TakeScreenshot(), then re-enables the UI view. Ensures screenshots don't include the UI overlay.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Typical initialization is already implemented in PhotoModeUISystem.OnCreate.
// Example: programmatically enable photo mode and hide the overlay.
var photoUI = World.GetOrCreateSystemManaged<Game.UI.InGame.PhotoModeUISystem>();
photoUI.Activate(true); // enable photo mode (switches camera/controllers)
photoUI.SetOverlayHidden(true); // hides overlays and forces default tool
// To take a screenshot from code:
// photoUI.TakeScreenshot();
}
Additional notes for modders: - Tab and control construction is driven by PhotoModeRenderSystem.photoModeProperties and .presets. To add custom UI entries, provide or extend those collections or inject widgets after OnCreate runs. - Many of the widgets use DelegateAccessor to bind getters/setters; you can supply your own accessors tied to custom PhotoModeProperty implementations. - The system relies on camera controller swapping — be careful when changing camera controllers or properties from other systems to avoid unexpected state transitions. - The coroutine CaptureScreenshot disables ui.view during capture to avoid UI elements in screenshots; if you extend screenshot behavior, honor that pattern to avoid UI artifacts.