Properties on brushes
A room has things to say beyond its shape: what its floor is made of, how it sounds, how dear it is to cross. Core does not know any of that, and should not. An addon or a game declares the properties it needs, and the inspector shows them on exactly the brushes they apply to.
Derived things - rooms, portals, walls - are replaced every time the level compiles, so anything an author sets has to live on something authored: a brush, a face, or an entity.
1. Declare
A HammeriteBrushPropertySchema is one section of the
inspector: a namespace, a label, which brushes it applies to, and its properties with their defaults.
var stealth := HammeriteBrushPropertySchema.new(&"stealth", "Stealth")
stealth.tier = HammeriteBrushPropertySchema.Tier.AIR
stealth.structural_only = true
stealth.add(&"floor", "Floor", "stone").set_tooltip("What footsteps on it sound like")
stealth.add(&"cover", "Cover", 0.0).set_range(0.0, 1.0, 0.05)
HammeriteBrushPropertyRegistry.register(stealth)
- The tier filter says where it appears:
AIRfor rooms,SOLIDfor walls,ANYfor both.structural_onlyleaves out detail brushwork - a schema about a room wants it. - The default decides the type, and so the control: a float makes a spin box, a string a text
field, a bool a check box.
add_enum()makes a list. - The stored key is
<namespace>/<name>:stealth/floor.
Register from the running game - an autoload's _ready() - before a map is built, not only when the
editor is up. The declared default is what an untouched brush reads, and a shipped game without the
registration reads null.
2. Read
Storage is sparse: a brush holds only the values an author changed, and setting one back to its default erases it. So read through the brush, which falls back to the declared default:
var floor_kind: String = brush.get_property(&"stealth/floor")
never brush.properties["stealth/floor"], which is null on every brush nobody touched.
A room's properties are those of the air brush that carved it:
var cell: HammeriteCell = map.point_in_cell(map_3d.to_local(player.global_position + Vector3.UP * 32.0))
if cell:
var cover: float = map.get_cell_property(cell, &"stealth/cover")
A change is announced on the brush (property_changed) and the map (brush_property_changed). It does
not recompile the world: a property is data on the room, not part of its shape.
A side effect worth knowing: changing a declared default changes it on every map that never set the property. That is the trade sparse storage makes - choose defaults you will not want to move.
3. On a face
HammeriteFace.properties is the same kind of bag, with no registry and no
inspector: the reader supplies the default. It is where a value lives that belongs to one wall, or
that must outlast something derived from it - a doorway's name is stored on the faces it is punched
from, because the portal itself is replaced on every compile.
face.set_property(&"stealth/creaks", true)
var creaks: bool = face.get_property(&"stealth/creaks", false)
4. In the editor
A property whose legal values are a list the game knows - patrol groups, surface kinds - gets a dropdown:
map_editor.register_brush_property_choices(&"stealth/floor",
func(_map: HammeriteMap) -> PackedStringArray: return PackedStringArray(["stone", "wood", "carpet", "gravel"]))
A control of your own replaces the built-in one with register_brush_property_editor(key, factory),
whose factory returns a HammeritePropertyControl.
To see a property across the whole level, colour the 2D floorplan by it. An overlay is offered under Cells: on the toolbar; a fully transparent colour leaves a room plain:
map_editor.register_cell_overlay(&"stealth_cover", "Cover", _cover_colour)
func _cover_colour(cell: HammeriteCell, map: HammeriteMap) -> Color:
var cover: float = map.get_cell_property(cell, &"stealth/cover")
return Color(0.2, 0.3, 0.8, 0.6 * cover)
map_editor is the HammeriteMapEditor that
HammeriteEditor.integrate() builds.
See also
- Writing an entity class - properties on entities, whose defaults live in their type.
HammeriteBrushPropertyDef,HammeriteBrushPropertyRegistry,HammeriteBrush, andHammeriteReferencesfor a property that names a texture, a sound or anything else the game provides.