Skip to content

Grid Placement v6.3.0

Composition & Injection

How Grid Placement 6.3 services are composed and wired into a scene.

Status
Current
Version
v6.3.0
Source updated
2026-10-29
Generated on
2026-10-29

6.3. These pages document the 6.3 release, where placeable is now entry (what changed) and PlacementOwner is deprecated (migration). Still on 6.2? Your version's guides ship inside the plugin itself, under addons/grid_placement/guides/; the 6.2 URLs on this site now redirect to this series.

Grid Placement separates runtime logic from scene/game context. This is the canonical guide for host/session composition beyond the starter setup.

You usually interact with three layers:

  1. GridPlacementHost — routes the active interaction and composes runtime services.
  2. PlacementSession — stores per-player/controller state and configuration references.
  3. Context/provider adapters — connect the current level, player, and game facts to placement validation/services.

Default path

For a standard single-session scene, use the host/session path directly:

  1. Add a GridPlacementHost to the scene root or systems scene.
  2. Assign GridPlacementHost.session and enable auto_configure.
  3. Assign GridPlacementHost.grid_placement_bundle.
  4. Assign each GridPositioner2D.session (or GridPositioner3D.session) to the PlacementSession owned by that player/controller.
  5. Author PlacementLevelContext and PlacementOwner in the scene. PlacementLevelContext says where objects land (level-owned); PlacementOwner says who is placing (player/controller-owned). They are separate because levels and players often instance separately.

When GridPositioner2D.session is assigned, the positioner configures itself from that session and registers it with the nearest GridPlacementHost at runtime. With auto_configure enabled the host composes the services, registers the session, and binds scene consumers itself at _ready, so a single-session scene needs no script. A controller does that work instead when the game owns session lifetime.

A normal project also does not need to instantiate every placement service manually. The host composes the configured service group from the bundle/session. On a 3D-dimensions bundle it additionally builds the authoritative GRID object service itself from the bound level context, unless the scene already bound its own.

Explicit host configuration

Use explicit configuration when code owns the session lifecycle — split-screen or per-device sessions, sessions created at runtime, or sessions restored by save/load. Leave auto_configure off in this shape.

host.configure(session)

For independent controllers:

host.register_session(controller_root, session, device_id)

Unregister the controller/session when its owning scene or controller leaves. Keep one session per independent interaction; players that need separate selection, targeting, coordinate mode, or pending manipulation state should not share a session.

Consumers should use supported host/service entry points instead of depending on internal scene paths.

Binding scene consumers

GridPlacementHost.bind_scene_consumers(root, session) walks a scene subtree and calls each consumer's existing resolve_placement_dependencies and resolve_placement_runtime hooks. Controllers call it after configure() so UI, previews, and helpers receive their dependencies without per-node scene exports. With auto_configure enabled the host calls bind_scene_consumers() and watch_scene_consumers() itself at _ready, rooted at the current scene. Positioners self-register from their session export and are skipped.

Context injection

Use contexts/providers for facts that come from the current game scene, for example:

  • target TileMapLayer or GridMap surface (plus the maps list once a 2D level uses more than one gameplay layer);
  • placed-object parent;
  • placement owner/controller;
  • game-owned reserved/occupied zones;
  • inventory, cost, or world-state facts used by custom rules.

Do not copy those facts into long-lived plugin globals when their lifetime belongs to a level, session, or game system.

Shared placement world

Dimension-specific services still need to agree on the same committed placement world.

This matters for:

  • GRID vs SMOOTH conflicts;
  • CELL/EDGE/FACE/CORNER/TOP mount occupancy;
  • SMOOTH socket occupancy;
  • multiple sessions;
  • save/restore.

Do not build a second occupancy registry that can commit conflicting placement state.

When to inject a custom service/provider

Add custom composition only when the project needs a real policy or integration point. Examples:

  • a game-owned world-facts provider;
  • custom placement validation rule;
  • inventory/refund bridge;
  • custom input/controller/session setup.

Non-node helpers are plain RefCounted objects that read what they need from a PlacementSession. Do not write new integration code around removed PlacementContainer compatibility types.

Avoid replacing plugin services only to change naming or add logging.

Troubleshooting composition

Check these before changing plugin code:

  1. GridPlacementHost exists in the relevant scene/systems tree.
  2. The host actually started: auto_configure enabled with session assigned, or a controller that called configure() and register_session().
  3. GridPositioner2D.session is assigned for scene-authored controller wiring.
  4. The host and session use the intended GridPlacementBundle.
  5. PlacementLevelContext and PlacementOwner belong to the active level/controller lifetime.
  6. Scene consumers: verify host.bind_scene_consumers(root, session) ran for the active controller scope.

Using this in a game?

Grid Placement v6.3.0 — full source, playable demos, commercial license

The guide above is the same setup the shipped demos use. Try the build in your browser before you buy it.