Skip to content

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 ProceduralMesh

Input Events

All floor actions are expressed as FFloorInputEvent structs sent to UFloorInputService.HandleInputEvent.

FFloorInputEvent fields

FieldTypeDescription
KindEFloorInputKindThe type of action
PositionFVector3D world position of the cursor/action
PointsTArray<FVector2D>Optional: multiple 2D points at once
MaterialIdint32Material to apply
FloorTypeEFloorTypeFloor layer type
ApplyModeEFloorInputApplyModePreview or Commit
SessionIdint32Session identifier
bPointsAreRelativeboolWhether Points are relative positions

Input kinds (EFloorInputKind)

KindMeaningHandler
ClickPointPlace a single polygon at the cursor positionUClickPointResponsibilityHandler
FillFill the enclosed area of the node network at the cursorUFillEventResponsibilityHandler
PolygonStartBegin a multi-vertex polygon placementTODO verify: Blueprint-accessible?
PolygonAddVertexAdd a vertex to an in-progress polygonTODO verify: Blueprint-accessible?
PolygonCompleteFinalize a multi-vertex polygonTODO verify: Blueprint-accessible?
SetMaterialChange the material of an existing polygon
ToolChangeSwitch the active tool

Apply modes (EFloorInputApplyMode)

ModeDescription
PreviewWrites to the preview database only — no permanent change
CommitWrites 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 / FunctionDescription
OnBeginPlayInitializes the tool (tool shape, internal state)
CurrentMouseHitResultsCalled every tick with current cursor hit results — used to move the tool preview
LeftClickConfirms and commits the current position
RightClickAborts the placement and destroys the tool
setModifierOneToggles between fill mode and single-tile mode
FindValidHitResultValidates and optionally transforms the cursor hit result (e.g., to apply grid snapping)
ShowToolMoves the tool actor to the valid hit position
ShowFillPolygonDetects the enclosed polygon from the node network and displays it
ShowToolPolygonDisplays 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:

  1. Tool receives CurrentMouseHitResults
  2. FindValidHitResult validates the position
  3. ShowToolPolygon renders the preview polygon
  4. On left-click: send FFloorInputEvent with Kind = ClickPoint, ApplyMode = Commit
  5. UClickPointResponsibilityHandler adds the polygon to UPolygonDatabase
  6. UFloorPolygonChangeService notifies renderers

Fill mode

The tool detects the node network area enclosing the cursor and fills the entire enclosed polygon.

Flow:

  1. Tool receives CurrentMouseHitResults
  2. ShowFillPolygon calls the node network to find the enclosing polygon:
    • Gets the enclosing UBasicNodeNetwork via UNodeNetworkSubsystem.getNodeNetworkEnclosingPosition
    • Calls UBasicNodeNetwork.getFloorPolygonMeshDataEnclosingPosition to get the FFloorPolygon
  3. Preview polygon is displayed
  4. On left-click: send FFloorInputEvent with Kind = Fill, ApplyMode = Commit
  5. UFillEventResponsibilityHandler processes the fill and writes to UPolygonDatabase

The FloorPlacementControllerComponent

FloorPlacementControllerComponent sits in the Player Controller and is the bridge between raw player input and the active tool.

FunctionDescription
HandleLeftClickValidates the tool, collects objects under the cursor, calls the tool’s left-click handler. Destroys the tool if it is finished.
HandleRightClickForwards right-click to the tool
HandleShiftForwards the modifier key to the tool (setModifierOne)
SetActiveToolAssigns the currently active tool actor
ActivateComponentActivates this component (enables input forwarding)
DeactivateComponentDeactivates this component
GetObjectsUnderMouseCursorReturns 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 Database

Key operations:

FunctionDescription
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 / ExitPreviewModeToggle non-destructive preview state

How renderers receive updates

Once a polygon is written to the database, UFloorPolygonChangeService notifies all registered listeners:

EventWhen 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)
OnAllPolygonsTransferredEnd of a batch of changes — rebuild all meshes now

See also