PlaceableDefinition Resource Guide A PlaceableDefinition is a Godot .tres resource that defines a placeable object in GridPlacement. It is the primary source of truth for all placeable properties including manipulation capabilities (rotate, flip horizontal, flip vertical, can delete).
PlaceableDefinition vs PlaceableType Aspect PlaceableType (Core)PlaceableDefinition (Godot Resource)Layer Core (pure C#, no engine deps) Godot (engine-specific Resource) Location Core/Configuration/PlaceableType.csaddons/grid_placement/placement/PlaceableDefinition.csUsed by ECS systems, YAML-first games GridPlacement’s Godot-side catalog Inheritance Extended by game-specific types (e.g., IdlePlaceableConfiguration) Wrapped by ToCore() conversion File format C# class .tres (text-based, AI-editable)
The relationship:
1
2
3
4
PlaceableDefinition.tres → ToCore() → CorePlaceable (Core)
↑
Can be extended by
game-specific types
Resource File Location Place PlaceableDefinition resources in:
1
res://addons/grid_placement/placeable_definitions/
This folder is the conventional location GridPlacement’s catalog loader scans for definitions.
Creating a PlaceableDefinition Option A: Godot Editor Right-click in FileSystem → Create New... → Resource Set script to PlaceableDefinition Configure properties in inspector Save to res://addons/grid_placement/placeable_definitions/ Option B: Script (Programmatic) 1
2
3
4
5
6
7
8
9
10
11
12
var definition = new PlaceableDefinition
{
display_name = "Barn" ,
packed_scene = ResourceLoader . Load < PackedScene >( "res://scenes/buildings/barn.tscn" ),
size = new Vector2I ( 2 , 2 ),
rotatable = true ,
flip_horizontal = true ,
flip_vertical = false ,
can_delete = true ,
tags = new Godot . Collections . Array < Resource >()
};
ResourceSaver . Save ( definition , "res://addons/grid_placement/placeable_definitions/barn.tres" );
Option C: From YAML (AI-Editable) Generate .tres files from YAML configuration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# placeables.yaml
placeables :
- id : barn
display_name : "Barn"
scene_path : "res://scenes/buildings/barn.tscn"
size : [ 2 , 2 ]
rotatable : true
flip_horizontal : true
flip_vertical : false
can_delete : true
category : buildings
tags :
- wooden
- large
Property Reference Required Properties Property Type Default Description display_nameStringName""Human-readable name shown in UI packed_scenePackedScene?nullThe scene to instantiate when placed
Size Property Type Default Description sizeVector2I(1, 1)Grid footprint. (2, 2) for multi-tile buildings
Manipulation Capabilities Property Type Default Description rotatablebooltrueCan player rotate this object during placement flip_horizontalbooltrueCan player flip horizontally flip_verticalbooltrueCan player flip vertically can_deletebooltrueCan player demolish after placement
Optional Properties Property Type Default Description iconTexture2D?nullIcon shown in selection UI tagsArray<Resource>[]PlaceableTagDefinition resources for categorizationplacement_rulesArray<Resource>[]PlacementRule resources for validationignore_base_rulesVariantfalseSkip global rules when true
Catalog Integration PlaceableDefinition resources are loaded into the PlaceableRuntimeCatalog via PlaceableCatalogBootstrap:
1
2
3
4
5
6
PlaceableDefinition.tres
│
▼ Load()
PlaceableRuntimeCatalog
└── Get(hash) → PlaceableEntry
└── Definition → PlaceableDefinition
Catalog Lookup When an entity is placed, its hash is stored in PlacedComponent.PlaceableHash. The adapter looks up capabilities:
1
2
3
// PlacementSceneAdapter.cs
var placeable = _nodeFactory . ResolvePlaceable ( placed . PlaceableHash );
// placeable.CanRotate, placeable.CanFlipHorizontal, etc.
Tags categorize placeables for filtering in UI:
1
2
3
4
5
6
[ gd_resource type = "Resource" script_class = "PlaceableTagDefinition" ... ]
[ resource ]
script = ExtResource ( "1" )
display_name = "Wooden"
tag_id = "wooden"
color = Color ( 0.6 , 0.4 , 0.2 , 1.0 )
Assign tags in PlaceableDefinition:
1
2
3
4
5
PlaceableDefinition.tres
tags = [
ExtResource("wooden_tag"),
ExtResource("building_tag")
]
Placement Rules Rules validate placement in real-time:
1
2
3
4
5
[ gd_resource type = "Resource" script_class = "TileCheckPlacementRule" ... ]
[ resource ]
script = ExtResource ( "1" )
rule_id = "tile_check_rule"
rule_type = "TileCheck"
Add rules to PlaceableDefinition:
1
2
3
4
PlaceableDefinition.tres
placement_rules = [
ExtResource("tile_check_rule")
]
Complete Example 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[ gd_resource type = "Resource" script_class = "PlaceableDefinition" load_steps = 4 format = 3 ]
[ ext_resource path = "res://addons/grid_placement/placement/PlaceableDefinition.cs" type = "Script" id = "1" ]
[ ext_resource path = "res://scenes/buildings/barn.tscn" type = "PackedScene" id = "2" ]
[ ext_resource path = "res://addons/grid_placement/placement/tags/building_tag.tres" type = "Resource" id = "3" ]
[ resource ]
script = ExtResource ( "1" )
display_name = "Barn"
packed_scene = ExtResource ( "2" )
size = Vector2i ( 2 , 2 )
rotatable = true
flip_horizontal = true
flip_vertical = false
can_delete = true
tags = [ ExtResource ( "3" )]
placement_rules = []
ignore_base_rules = false
Per-Instance Override with ManipulatableNode If a specific instance of a placed object needs different capabilities than the definition provides:
1
2
3
4
5
6
7
MyScene.tscn
├── Barn (placed via GridPlacement) ← Uses PlaceableDefinition capabilities
│ ├── Sprite2D
│ ├── CollisionShape2D
│ └── ManipulatableNode ← Per-instance override
│ rotatable = false ← Overrides definition
│ flip_horizontal = false
The ManipulatableNode facade on an instance takes precedence over the definition.
Debugging Verify Definition Loads 1
2
3
4
5
6
if ( _context . Catalog . TryGet ( hash , out var entry ))
{
GD . Print ( $"Loaded: {entry.Definition.display_name}" );
GD . Print ( $"Rotatable: {entry.Definition.rotatable}" );
GD . Print ( $"CanFlipH: {entry.Definition.flip_horizontal}" );
}
Check Entity Capabilities Query the ECS entity:
1
2
3
4
5
6
if ( entity . HasComponent < ManipulatableComponent >())
{
var mc = entity . GetComponent < ManipulatableComponent >();
GD . Print ( $"Entity CanRotate: {mc.CanRotate}" );
GD . Print ( $"Entity CanFlipHorizontal: {mc.CanFlipHorizontal}" );
}
Common Issues Capabilities Not Flowing to Entity Cause: packed_scene is null or invalidFix: Ensure packed_scene points to a valid PackedScene resource
Entity Has Wrong Capabilities After Placement Cause: Definition was modified after entity was placedFix: Capabilities are baked into ManipulatableComponent at placement time. Re-place the entity.
Tag Not Found Cause: Tag resource not in tags array or tag script class mismatchFix: Ensure tag is PlaceableTagDefinition type and properly assigned