Game.Tools.ObjectToolSystem
Assembly: Assembly-CSharp (game runtime)
Namespace: Game.Tools
Type: class
Base: ObjectToolBaseSystem
Summary:
ObjectToolSystem is the main in-game tool responsible for placing, moving, rotating, painting (brush), stamping and upgrading placeable objects (props, buildings, trees, net sub-replacements) in Cities: Skylines 2. It integrates with the game's ECS and job system (contains Burst-compiled jobs such as SnapJob and FindAttachmentBuildingJob) to perform expensive spatial queries (quad-tree searches, net searches, water/terrain sampling) and to compute snapping, alignment and placement rules. It also manages multi-point placement modes (Line, Curve), brush/stamp modes, net upgrade flows, and editor vs game-mode differences (auto-parenting, placeholders, surface/object snapping). The system exposes properties for tool configuration (distance, snap masks, prefab selection) and implements the tool lifecycle (OnCreate, OnStartRunning, OnUpdate, OnDestroy) and actions (Apply/Cancel/Update).
Fields
-
private NativeList<ControlPoint> m_ControlPoints
Holds the current control points used by the tool (last raycast point, start point, and additional points for line/curve/upgrade modes). Used by SnapJob and definition creation. -
private NativeList<SubSnapPoint> m_SubSnapPoints
Temporary list filled during snapping to store sub-snap points (e.g., net tangents/positions used for more advanced snapping). -
private NativeList<NetToolSystem.UpgradeState> m_UpgradeStates
Used when placing or previewing net sub-replacements / upgrades — stores upgrade state per segment. -
private NativeReference<Rotation> m_Rotation
Holds current rotation state for the object placement (rotation quaternion, parent rotation, alignment flag). -
private NativeReference<NetToolSystem.AppliedUpgrade> m_AppliedUpgrade
Holds the currently applied upgrade information (used when replacing/upgrading net segments). -
private ObjectPrefab m_Prefab
The internal prefab entity currently used for raycasting and placement definitions (Entity reference via Prefab system). -
private ObjectPrefab m_SelectedPrefab
The user-selected prefab (high-level PrefabBase) — assigned by UI/tool selection. -
private TransformPrefab m_TransformPrefab
Optional transform prefab used in editor mode for transform-only placement. -
private State m_State
Current state of the tool (Default, Rotating, Adding, Removing). -
private Mode mode
Public-settable mode enumeration (Create, Upgrade, Move, Brush, Stamp, Line, Curve). -
private IProxyAction m_PlaceObject
,m_MoveObject
,m_PaintObject
, ... (multiple proxy actions)
Input/action bindings used to map UI/game input into tool logic for apply/cancel/rotate/upgrade/etc. -
private RandomSeed m_RandomSeed
Random seed used for randomized rotations (e.g., trees placement) and for selection in brush/attachment jobs. -
private ControlPoint m_LastRaycastPoint
,m_StartPoint
Runtime raycast control points used to track current hover and brush start.
(There are many more internal fields exposed in the source — these are the most relevant to modders interacting with or extending the tool.)
Properties
-
public override string toolID { get; }
Returns the tool identifier ("Object Tool") used by the tool manager / UI. -
public override int uiModeIndex { get; }
Returns the integer used by UI mode to indicate which sub-mode is active (maps to Mode enum). -
public Mode mode { get; set; }
The user-set mode for the tool. Note that actualMode may differ when certain capabilities are unavailable (e.g., allowBrush false => Create). -
public Mode actualMode { get; }
Computed mode that takes into account enabled capabilities (allowCreate/allowBrush/allowLine/allowCurve/allowStamp) and returns the mode actually used. -
public bool isUpgradeMode { get; }
True when the tool currently represents an upgrade operation (net upgrades/sub-replacements). -
public AgeMask ageMask { get; set; }
Configured age mask (sapling/young/mature/elderly) used for tree/ageable object placement. -
public ObjectPrefab prefab { get; set; }
(exposed as high-levelprefab
/transform
)
Selected prefab instance; setting this updates internal flags (allowLine/allowBrush/allowStamp/allowRotation/allowAge) and fires EventPrefabChanged. -
public override Snap selectedSnap { get; set; }
The selected snap mask (Upright, NetArea, NetNode, ObjectSurface, etc.). The tool computes an actual snap by combining allowed masks and this setting. -
public float distance { get; set; }
Placement distance used for line/curve distance snapping. -
public float distanceScale { get; private set; }
Scale used for snapping distances; computed from object size and geometry flags. -
public bool underground { get; set; }
Whether the placement is targeting underground collisions. -
public bool allowCreate { get; private set; }
,allowLine
,allowCurve
,allowBrush
,allowStamp
,allowAge
,allowRotation
Flags computed from the selected prefab describing which placement modes/behaviours are allowed. -
public override bool brushing { get; }
True when actualMode == Mode.Brush. -
public State state { get; }
Exposes current tool state. -
private protected override IEnumerable<IProxyAction> toolActions { get; }
Enumerator exposing the list of registered actions for UI wiring (erase, move, paint, place, upgrade, rotate, place net control point, undo, upgrade/downgrade etc).
(There are other getters such as GetControlPoints/GetSubSnapPoints returning NativeList references and various service properties.)
Constructors
public ObjectToolSystem()
Constructor sets up the managed system instance. The actual runtime initialization happens inOnCreate
where queries, native lists, native references and input actions are allocated and configured.
Methods
-
protected override void OnCreate()
Initializes the system: creates required search system references, initializes NativeList/NativeReference fields, sets up EntityQueries (definitions, containers, brushes), registers input actions and default brush/parameters (distance, brush size/strength), and initializes rotation seed/state. -
protected override void OnDestroy()
Disposes NativeList and NativeReference allocations (m_ControlPoints, m_SubSnapPoints, m_UpgradeStates, m_Rotation, m_AppliedUpgrade) and calls base.OnDestroy. -
protected override void OnStartRunning()
Resets runtime state when the tool starts running (clears control points, resets applied upgrade, resets states like m_State/ m_MovingInitialized, set required layer flags and default area/net requirements depending on editor/game mode). -
protected override JobHandle OnUpdate(JobHandle inputDeps)
Main update function called each frame. Handles input polling (apply/cancel/secondary apply), transitions states (Default/Adding/Removing/Rotating), processes precise rotation input and mouse-based rotation, updates raycasts and calls SnapControlPoint / UpdateDefinitions / Apply / Cancel flow as necessary. Integrates job scheduling for SnapJob and later definition creation jobs. -
public override void InitializeRaycast()
Configures the ToolRaycastSystem for the currently selected prefab: sets ray offset, collision masks, TypeMask (terrain, water, nets, static objects), RaycastFlags (outside, partial surface, placeholders), and net layer masks depending on prefab flags (shoreline, floating, net snapping, object surface). Called when prefab changes or raycast context needs refresh. -
private JobHandle SnapControlPoint(JobHandle inputDeps)
Schedules the Burst-compiledSnapJob
which performs the heavy lifting of snapping the current control point to nets, nodes, zone blocks, objects, shoreline, existing geometry, and auto-parenting. SnapJob uses multiple quad-tree iterators (LoweredParentIterator, OriginalObjectIterator, ParentObjectIterator, NetIterator, ZoneBlockIterator) to discover best snap positions. After scheduling, the search system readers are registered with the returned job handle. -
private JobHandle UpdateDefinitions(JobHandle inputDeps)
Destroys existing preview definitions and schedules creation of new placement definitions (visual preview + ECS definitions) by calling CreateDefinitions job chain. Handles special cases such as sub-replacement/net upgrade definitions (UpdateSubReplacementDefinitions) and acquiring attachment prefabs (FindAttachmentBuildingJob) in non-editor contexts. -
private JobHandle UpdateSubReplacementDefinitions(JobHandle inputDeps)
Schedules NetToolSystem.CreateDefinitionsJob for the replace-mode (used by sub-replacement / repairs / upgrades) to produce preview definitions for net modifications. -
private JobHandle Apply(JobHandle inputDeps, bool singleFrameOnly = false)
Handles Apply interactions (placing or committing an action). Behaviour differs by mode: - Brush: toggles adding/removing brush strokes and updates definitions.
- Line/Curve: adds control points, on final point commits the placement and invokes definition/job creation.
-
Default Create: if allowed, commits placement and plays sound effects; handles special Lot creation handoff to AreaToolSystem. Also handles net upgrades (setting applied upgrades) and telemetric events when placing buildings.
-
private JobHandle Cancel(JobHandle inputDeps, bool singleFrameOnly = false)
Handles cancelling actions or rotating objects when no cancelable placement is in progress. Supports brush cancel behavior, net upgrade removal toggles, undoing last control point in multi-point modes, entering/exiting rotating state for fine rotation, and setting flags to request definition updates. -
private JobHandle Update(JobHandle inputDeps, bool fullUpdate)
Called every frame to process raycasts and update previews. If raycast hit is found, sets m_LastRaycastPoint and updates control points then schedules SnapControlPoint and UpdateDefinitions as needed. If no raycast hit, clears definitions. Handles Mode.Brush special logic and sampling. -
private void Rotate(float angle, bool fromStart, bool align)
Applies a rotation delta to the tool's rotation state. If align==true it snaps the rotation to the closest symmetry-aligned rotation based on parent rotation (calls SnapJob.AlignRotation). Supports wall-placement (Z-axis) vs ground-placement (Y-axis) differences. -
public static void SnapJob.AlignRotation(ref quaternion rotation, quaternion parentRotation, bool zAxis)
Static helper (declared inside SnapJob in the source) that aligns a rotation around discrete 45° increments relative to a parent rotation. Used to keep placed objects aligned to parent orientation when possible (supports wall-alignment and normal alignment). -
private void SetAppliedUpgrade(bool removing)
Computes and sets m_AppliedUpgrade from the last upgrade state and the pair of original entities/control points, so that the command buffer jobs know what upgrade/replacement to apply. -
private JobHandle FixNetControlPoints(JobHandle inputDeps)
Schedules NetToolSystem.FixControlPointsJob to correct control points for net placement (ensures nodes/edges correspond to current entity data). -
private JobHandle UpdateDefinitions(JobHandle inputDeps)
(See above) Creates visual preview and ECS definitions (CreateDefinitions) for the current control points and mode. -
private void GetAvailableSnapMask(out Snap onMask, out Snap offMask)
Computes which snap types should be available for the currently selected prefab in the current mode (Upright, NetArea, NetNode, ObjectSurface, OwnerSide, Shoreline, ExistingGeometry, etc.)—this influences raycast configuration and how ToolBaseSystem.GetActualSnap resolves the snap mask. -
public override bool TrySetPrefab(PrefabBase prefab)
Used to assign a prefab to the tool from UI or other tools. Supports ObjectPrefab and TransformPrefab, automatically switchesmode
to Upgrade in case of service upgrades (game mode). -
public void StartMoving(Entity movingObject)
Switches the tool into Move mode for the passed entity (used when user chooses "Relocate" for an existing object). Initializes rotation and plays UI sound. -
private void InitializeRotation(Entity entity, PlaceableObjectData placeableObjectData)
Reads rotation from the entity and its parent(s) to populate m_Rotation.Value (m_Rotation + m_ParentRotation), honoring wall vs normal placements and symmetry.
(There are many other helper/private methods in the source: SnapSurface, SnapNode, SnapShoreline, SnapSegmentAreas, FindLoweredParent, FindOriginalObject, HandleControlPoints, HandleStartDirection, HandleWorldSize, CheckSnapLine, AddSnapPosition, and static helpers such as SetHeightRange and GetMaxControlPointCount. Also nested job types: SnapJob and FindAttachmentBuildingJob and many iterators used by SnapJob. The class schedules and composes many jobs and integrates with the ToolOutputBarrier and search systems.)
Usage Example
// Example: initialize and set a prefab and placement mode from mod code (high-level)
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Assume 'objectTool' is the instance of ObjectToolSystem obtained from World/GetOrCreateSystemManaged
// Set a prefab (ObjectPrefab) previously loaded from the PrefabSystem:
objectTool.prefab = myObjectPrefab;
objectTool.mode = Game.Tools.ObjectToolSystem.Mode.Create;
objectTool.distance = 3f;
// Optionally set snapping preferences:
objectTool.selectedSnap = Snap.Upright | Snap.ObjectSurface;
}
Notes for modders: - ObjectToolSystem heavily relies on the game's PrefabSystem, ToolRaycastSystem, search trees and several EntityQueries. When interacting with or extending it, prefer scheduling jobs and using the provided ComponentLookup/BufferLookup patterns to remain thread-safe and compatible with the existing pipeline. - SnapJob and the iterators are performance-sensitive and Burst-compiled — modifications should keep that in mind. - To preview or inject custom definitions, use the same pattern the tool uses: create definitions jobs that produce preview entities and write through the ToolOutputBarrier's command buffer pattern.