extends RefCounted
class_name BrushShape
## ONE PARAMETRIC SHAPE for the create tool (editor redesign E4, docs/editor-redesign.md §8b).
##
## TrenchBroom's DrawShapeToolExtension{name, icon, createBrushes(bbox, params)}: where the
## thing goes, which way it grows, what material it inherits and how it reaches the journal
## are decided ONCE by CreateBoxOperator; a shape only answers "which solids fill these
## bounds" and "which air do they need". A new shape is one script plus
## BrushShapes.register(), and the operator does not change.
##
## ctx, handed to every call (built by the operator from the same hit, so no call can read
## one frame's normal against another frame's aim):
## axis int which axis the aimed surface faces along
## normal Vector3 the aimed surface's normal
## view Vector3 the camera's look direction
## run_axis int the across-surface axis you are looking along (stairs climb / arches tunnel on it)
## grid_step float one grid step in metres
## grid_units float the grid in Quake units
## params Dictionary this shape's own values, by params() id
## fmt Callable length in Quake units -> the player's display string
## Durable-ish: the id names the shape in prefs (tool.box.shape), so do not rename one.
func id() -> String:
return "shape"
func label() -> String:
return id().capitalize()
## The shape's own settings, as tool-setting descriptors (see LevelOperator.tool_settings):
## {id, label, type, default, min, max, step, unit, tip}. `default` 0 on an int may mean
## "auto" — the shape says so in its own describe() and resolves it in pieces().
func params() -> Array:
return []
## The SOLIDS that fill [lo, hi]. Array of ShapeKit pieces.
func pieces(_lo: Vector3, _hi: Vector3, _ctx: Dictionary) -> Array:
return []
## The AIR those solids need (hyper-games #25 §2) — clearance brushes. Empty for a solid.
func clearance(_lo: Vector3, _hi: Vector3, _ctx: Dictionary) -> Array:
return []
## What the status line says the shape is ("stairs, 4 steps of 8u in …").
func describe(_lo: Vector3, _hi: Vector3, _ctx: Dictionary, size_text: String) -> String:
return "%s %s" % [id(), size_text]
## What the status line calls the cut, when clearance() is non-empty.
func clearance_name(_ctx: Dictionary) -> String:
return ""
## A param's value from ctx, falling back to its declared default.
func param(ctx: Dictionary, pid: String) -> Variant:
var p: Dictionary = ctx.get("params", {})
if p.has(pid):
return p[pid]
for d: Dictionary in params():
if String(d.get("id", "")) == pid:
return d.get("default")
return null