OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / maps / shapes / brush_shape.gd

68 lines · gd ref:
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