Snap-category metadata for 3D placeables ( draft surface). Declares what a placeable IS ([member family]) and what it may attach to ([member snaps_with]). Matching is a directional accept-list: the entry being placed checks its own [member snaps_with] against the [member family] of already-placed neighbors. Families are arbitrary [StringName]s, so the granularity ("building", "floor", "wall_exterior", ...) is the game's choice — the plugin only provides the matching contract. See addons/grid_placement/guides/3d-object-placement.md for the design rationale (why accept-lists instead of mutual type equality). Runtime-instantiated: assigned on ScenePlacementEntry.snap_profile_3d and read by ObjectPlacementService3D. Do not mark @tool.
Source: addons/grid_placement/placement/placeable/placement_snap_profile_3d.gd
Syntax
class PlacementSnapProfile3D extends ResourceMembers
| Name | Kind | Summary |
|---|---|---|
snap_mode | Property | How this placeable attaches to the grid: - CELL: occupies whole columns; adjacency is checked against orthogonal neighbor columns (foundations, floors, furniture). Set [member occupy_columns] false for stacked overlays (roofs, gable ends) that sit on an already-built footprint. - EDGE: mounts on one of the four edges of a HOST cell (thin modular pieces like wall panels/fences). [member snaps_with] then names the families that may host it, and the piece is auto-rotated to run along the edge it snaps to. - FACE: mounts onto a registered vertical face at [member mount_height] (wall-hung pieces like paintings, shelves, sconces). The face normal determines yaw; pitch/roll are intentionally out of scope. - TOP: mounts on an occupied EDGE wall top (roof plane, gable) or on the cell-centered ridge when the edge vector is zero. Occupancy is distinct from the host EDGE so the wall and roof can coexist. - CORNER: mounts on one of the four XZ intersections of a HOST cell (structural corner posts). Occupancy is the canonical intersection key, not the cell centroid; yaw is derived from the two axes of that corner. Optional SMOOTH world-space sockets (bit flags). GRID [enum SnapMode] is unchanged. NONE = 0, ENDS = 1, PERIMETER = 2, FACE = 4, UP = 8. Attachment mode for this placeable. See [enum SnapMode]. |
attachment_requirement | Property | How strictly this entry must attach to a compatible provider. INHERIT defers to ObjectPlacementSettings3D.default_attachment_requirement, except that the legacy require_adjacent_snap=true still resolves REQUIRED so existing serialized profiles keep their behavior bit-for-bit. CORNER-only host-count policy, consulted only when CORNER attachment is REQUIRED. ANY_ONE accepts a single compatible host touching the intersection; TWO_ORTHOGONAL keeps the strict two-perpendicular-hosts contract. Zero-host CORNER placement is attachment OPTIONAL, not a topology value. Per-entry attachment override. INHERIT (default) uses the settings default; set explicitly on new profiles instead of require_adjacent_snap. |
corner_host_topology | Property | Per-entry CORNER topology override. INHERIT (default) uses the settings default; consulted only for REQUIRED CORNER attachment. |
occupy_columns | Property | CELL only. When true (default), the footprint reserves grid columns and conflicts with other CELL occupants. When false, preview/commit still run the GRID CELL path (ghost, adjacency, ground) but do not reserve or collide with column occupancy — for ground overlays such as floors and second-story overlays such as roofs. Overlays still publish [member family] on a separate channel, so attachment (walls mounting on floors, roofs neighboring floors) keeps working on shared columns. |
require_ground_cell | Property | CELL only. When true (default), the footprint columns must contain a GridMap ground item (ANDed with the settings-wide require_ground_cell). Vertical attachment-governed pieces such as walls set this false: they mount to neighboring providers, not to the floor, so missing ground off the slab edge must not block them. EDGE/FACE/TOP/CORNER mounts never consult ground regardless of this flag. |
require_all_cells_attached | Property | CELL only. When true, every footprint cell needs its own compatible neighbor; a multi-cell piece with only one supported tile fails attachment, and only the unsupported cells are marked. When false (default), any single compatible neighbor around the footprint satisfies the whole piece. Single-cell footprints behave identically either way. |
require_wall_support | Property | CELL only. When true, every footprint cell needs a load-bearing wall (an EDGE mount publishing family "wall") within 2 cells, measured Chebyshev from the cell to the wall's nearer adjacent column. Elevated art (roof slopes, gables) whose mesh floats above the ground plane sets this so a bare floor deck reads red until the supporting walls exist. This is a coarse anti-float gate, not structural analysis: one nearby wall stub satisfies every cell in radius. Default false: ground-hugging pieces are unaffected bit-for-bit. |
require_roof_span | Property | CELL only. When true, every footprint cell must sit within 4 cells of a family-"roof" overlay column (Chebyshev). Gable ends cap roof spans, so a gable in a roofless ring reads red until the slopes exist. Slopes must NOT set this (the first slope has no span yet). Default false. |
mount_height | Property | FACE-mode vertical band above the provider surface. Band 0 is the provider surface itself; each next band rises by one GridMap cell height. |
provides_mount_faces | Property | CELL-mode providers with rectangular footprints expose their perimeter vertical faces as mount sockets for FACE-mode consumers. EDGE-mode providers expose their mount edge's face the same way. |
edge_outward_facing | Property | EDGE only. When true, the mount yaw turns the piece's dressed (+Z) face along the mount normal (outward from the host cell) instead of the default along-edge yaw. For asymmetric pieces (dressed/plain sides) so every side of a ring faces outward; symmetric pieces leave this false. |
family | Property | Category this placeable belongs to (what neighbors will test against). |
snaps_with | Property | Families this placeable may snap/attach to. Order does not matter. |
replace_group | Property | Same-type replacement equivalence class for occupied-socket swaps. Two entries replace each other when their effective groups match, where the effective group is [member replace_group] when set, else [member family]. Empty (default) keeps the legacy family-equality contract. Author this when entries attach as different families but panel-swap as one kind — e.g. door frames (family "door", so leafs and corners still find them) that replace wall/window panels (family "wall") during placement. |
require_adjacent_snap | Property | Legacy attachment flag (compatibility alias). When attachment_requirement is INHERIT, true acts as REQUIRED and false defers to the settings default. Prefer attachment_requirement for new entries; the flag stays so existing entries behave bit-for-bit as before. When true, placement is only valid if at least one orthogonally adjacent cell holds an object whose family is in [member snaps_with]. When false, the profile is advisory (free placement; family still recorded so other objects can snap to this one). Deprecated: kept serialized so existing profiles resolve identically, but validators no longer read this — they read the resolved [enum AttachmentRequirement] policy instead. Do not set on new profiles; use [member attachment_requirement] explicitly. |
resolve_attachment | Method | |
resolve_corner_topology | Method | |
requires_attachment | Method | |
seam_close_to_partner | Property | GRID CELL seam closure: when true and adjacency finds a compatible partner, the committed origin shifts toward that partner so the mesh face nearest the partner lands exactly on the shared grid line. Default false = pure footprint-centroid (existing behavior bit-for-bit). Needs ScenePlacementEntry.seam_bounds_3d (mesh truth); without it, no-op. Symmetric meshes centered on origin yield shift zero even when enabled. |
smooth_sockets | Property | SMOOTH-only: which world sockets this placeable publishes after commit. Combine flags (e.g. PERIMETER | UP for a floor). Default NONE = free SMOOTH. |
smooth_snap_radius | Property | World-unit radius for consuming a published socket. 0 disables snap (free pose). |
smooth_socket_extent | Property | Half-length (ENDS) or half-side (PERIMETER) in world units. |
face_mount_anchor | Property | Node name of the optional declared mount anchor on a FACE-mode consumer scene: a Node3D child whose origin is the point that must land exactly on the provider's [member ObjectPlacementGeometry3D.FACE_SOCKET_NODE_NAME] plane (and whose -Z matches the socket's outward -Z). When both sides declare, the service composes the exact mate transform — flush by construction instead of a cell-derived offset guess. |
face_mount_outward | Property | Outward-first FACE socket derivation for this consumer. When true, the resolver mates the yaw-matching authored socket (the provider socket facing the requested face normal) before the legacy requesting-side socket, so one-sided dressing (shutters, art) lands on the clicked face instead of mirroring onto the far side. False (default) keeps the legacy requesting-side-first order, which thin straddling providers rely on. |
face_socket_symmetric | Property | Explicit rotational-symmetry opt-in for FACE socket derivation. When true, the provider's mesh is symmetric about its vertical axis, so the canonical FaceSocket may be yaw-rotated onto any face with no authored socket. NEVER inferred: asymmetric meshes (e.g. a rectangular wall) have different face-plane distances per side, and inferred derivation mates consumers inside the mesh. Leave false unless the mesh is truly symmetric. |
accepts_family | Method | |
effective_replace_group | Method | |
provides_smooth_role | Method | |
consume_smooth_roles | Method |