Floor Placement — Dynamic Floor Plugin
Floor Placement
This page explains how the floor placement pipeline works — from user input to a committed polygon in the database and a rendered mesh on screen.
Overview: the placement pipeline
Player Input ↓FloorPlacementControllerComponent ↓Active Tool Actor (BP_ExampleRuntimeFloorPolygonToolActor) ↓UFloorInputService (via UDynamicFloorPluginSubsystem) ↓Responsibility Handlers ├── UClickPointResponsibilityHandler (for ClickPoint events) └── UFillEventResponsibilityHandler (for Fill events) ↓UPolygonDatabase ↓UFloorPolygonChangeService → Notifies all IFloorPolygonChangeListener objects ↓BP_FloorPolygonRenderer → Updates ProceduralMeshInput Events
All floor actions are expressed as FFloorInputEvent structs sent to UFloorInputService.HandleInputEvent.
FFloorInputEvent fields
| Field | Type | Description |
|---|---|---|
Kind | EFloorInputKind | The type of action |
Position | FVector | 3D world position of the cursor/action |
Points | TArray<FVector2D> | Optional: multiple 2D points at once |
MaterialId | int32 | Material to apply |
FloorType | EFloorType | Floor layer type |
ApplyMode | EFloorInputApplyMode | Preview or Commit |
SessionId | int32 | Session identifier |
bPointsAreRelative | bool | Whether Points are relative positions |
Input kinds (EFloorInputKind)
| Kind | Meaning | Handler |
|---|---|---|
ClickPoint | Place a single polygon at the cursor position | UClickPointResponsibilityHandler |
Fill | Fill the enclosed area of the node network at the cursor | UFillEventResponsibilityHandler |
PolygonStart | Begin a multi-vertex polygon placement | TODO verify: Blueprint-accessible? |
PolygonAddVertex | Add a vertex to an in-progress polygon | TODO verify: Blueprint-accessible? |
PolygonComplete | Finalize a multi-vertex polygon | TODO verify: Blueprint-accessible? |
SetMaterial | Change the material of an existing polygon | — |
ToolChange | Switch the active tool | — |
Apply modes (EFloorInputApplyMode)
| Mode | Description |
|---|---|
Preview | Writes to the preview database only — no permanent change |
Commit | Writes permanently to the production polygon database |
The Tool Actor
BP_ExampleRuntimeFloorPolygonToolActor is the default placement tool. It implements UserFloorBpInterface and handles:
Key events and functions
| Event / Function | Description |
|---|---|
OnBeginPlay | Initializes the tool (tool shape, internal state) |
CurrentMouseHitResults | Called every tick with current cursor hit results — used to move the tool preview |
LeftClick | Confirms and commits the current position |
RightClick | Aborts the placement and destroys the tool |
setModifierOne | Toggles between fill mode and single-tile mode |
FindValidHitResult | Validates and optionally transforms the cursor hit result (e.g., to apply grid snapping) |
ShowTool | Moves the tool actor to the valid hit position |
ShowFillPolygon | Detects the enclosed polygon from the node network and displays it |
ShowToolPolygon | Displays the polygon defined by the tool’s ToolShape vector array |
Tool shape
The tool shape is stored in a Vector array property called ToolShape. The default shape is a rectangle. To use a different shape, subclass the tool and set ToolShape in your BeginPlay override.
See Examples for a triangle tool example.
Single-tile mode vs. fill mode
Single-tile mode
The tool displays a fixed polygon (defined by ToolShape) around the cursor. On left-click, that polygon is committed at the cursor position.
Flow:
- Tool receives
CurrentMouseHitResults FindValidHitResultvalidates the positionShowToolPolygonrenders the preview polygon- On left-click: send
FFloorInputEventwithKind = ClickPoint,ApplyMode = Commit UClickPointResponsibilityHandleradds the polygon toUPolygonDatabaseUFloorPolygonChangeServicenotifies renderers
Fill mode
The tool detects the node network area enclosing the cursor and fills the entire enclosed polygon.
Flow:
- Tool receives
CurrentMouseHitResults ShowFillPolygoncalls the node network to find the enclosing polygon:- Gets the enclosing
UBasicNodeNetworkviaUNodeNetworkSubsystem.getNodeNetworkEnclosingPosition - Calls
UBasicNodeNetwork.getFloorPolygonMeshDataEnclosingPositionto get theFFloorPolygon
- Gets the enclosing
- Preview polygon is displayed
- On left-click: send
FFloorInputEventwithKind = Fill,ApplyMode = Commit UFillEventResponsibilityHandlerprocesses the fill and writes toUPolygonDatabase
The FloorPlacementControllerComponent
FloorPlacementControllerComponent sits in the Player Controller and is the bridge between raw player input and the active tool.
| Function | Description |
|---|---|
HandleLeftClick | Validates the tool, collects objects under the cursor, calls the tool’s left-click handler. Destroys the tool if it is finished. |
HandleRightClick | Forwards right-click to the tool |
HandleShift | Forwards the modifier key to the tool (setModifierOne) |
SetActiveTool | Assigns the currently active tool actor |
ActivateComponent | Activates this component (enables input forwarding) |
DeactivateComponent | Deactivates this component |
GetObjectsUnderMouseCursor | Returns all hit objects under the cursor |
Registering polygons: the PolygonDatabase
All committed floor polygons are stored in UPolygonDatabase. You can access it via:
Get Game Instance Subsystem → DynamicFloorPluginSubsystem → Get Polygon DatabaseKey operations:
| Function | Description |
|---|---|
AddPolygon(Vertices, Height, MaterialId, FloorType) | Adds a polygon, returns its PolygonId |
InsertPolygonWithMaterialHandling(Vertices, Holes, Height, MaterialId, FloorType) | Adds a polygon with material-aware conflict handling |
RemovePolygonById(PolygonId) | Removes a polygon by ID |
GetPolygonsInBox(Box2D, HeightLevel) | Spatial query — returns polygons within a 2D bounding box |
EnterPreviewMode / ExitPreviewMode | Toggle non-destructive preview state |
How renderers receive updates
Once a polygon is written to the database, UFloorPolygonChangeService notifies all registered listeners:
| Event | When it fires |
|---|---|
OnPolygonAdded(FFloorPolygon) | A new polygon was committed |
OnPolygonRemoved(FFloorPolygon) | A polygon was deleted |
OnPolygonUpdated(FFloorPolygon) | A polygon was modified (not yet implemented in backend — reserved for future use) |
OnAllPolygonsTransferred | End of a batch of changes — rebuild all meshes now |
See also
- Grid and Snapping — implement grid snapping in
FindValidHitResult - Materials — how material IDs work
- Build Mode — activating/deactivating placement in a game context
- Examples — concrete usage examples