luvcraft/knobs.lisp
--------------------------------------------------------------------- The knob.
The represented-value declaration: representation type and quantity, and so the unit.
One live value: where it lives, what it measures, and -- by its class -- what SESSION must do after a change for the change to show.
A knob over a real, bounded and quantized.
A knob over a generalized boolean: on or off.
The groups the knobs fall in: those in *KNOB-GROUP-ORDER* first, in that
order, then the rest in order of first appearance.
--------------------------------------------------------------------- Realization: what has to happen after a change.
The realizations themselves are defined beside what they realize:
terminal-realization in TERMINAL-WALL.LISP, residency-realization in
STREAMING.LISP.
--------------------------------------------------------------------- Values.
value made fit for knob's place: clamped and of the place's type.
Set knob to value, made fit, and realize it in session.
Returns the value actually set.
Where knob's value sits in its range, 0 to 1.
--------------------------------------------------------------------- Units, as the metabar prints them.
The short spelling of the named unit, as it appears after a value or
inside a compound unit. The default spells the unit's name; the common
ones abbreviate.
The suffix a value in unit is printed with, space included where one is
wanted. unit is a unit designator: a name, or a list of (NAME EXPONENT).
What follows knob's value when printed.
knob's value as the control shows it.
At the precision of the step.
--------------------------------------------------------------------- Defining one.
Define name as a knob of CLASS over the setf-able place.
place may refer to SESSION, so a knob can live on the session -- its sky
clock, its player -- as well as in a special. quantity is a quantity plist
as define-quantity-constant takes, (:quantity ... :unit ...); it and type
make the knob's declaration, which value-declaration-for also answers for
name. MINIMUM, MAXIMUM, and step bound and quantize what a control may set
on a scalar knob; a switch knob wants none. How a change is realized is
CLASS's business.
--------------------------------------------------------------------- Knobs in shader source.
A knob named in a shader body folds to a literal of the knob's quantity; the pipeline that folded it rebuilds when the value moves. Only a knob whose place needs no session can stand in a shader, since the shader is parsed with none.
--------------------------------------------------------------------- Actions: things the game can be told to do, given a name and a label so a gadget can offer them as buttons.
--------------------------------------------------------------------- The metabar hook.
Slide session's metabar of knobs in or out, returning true when one is
available. LUVCRAFT/MCCLIM supplies the session method.
One live value: where it lives, what it measures, and -- by its class -- what SESSION must do after a change for the change to show.
(knob session)Do what SESSION needs after KNOB's value changed for the change to show. The primary method on KNOB does nothing: a value the renderer reads every frame is realized by the next frame. A realization mixin adds a method.
(name)The live value NAME stands for in shader source, or NIL when NAME names none. Returns (VALUES VALUE DECLARATION FOUND-P): VALUE is a real, and DECLARATION, when given, is a represented-value declaration whose quantity the literal takes on.
(name (&key label (group :grading) documentation
(class ''scalar-knob)
quantity (type 'single-float)
unit-label minimum maximum step)
place)Define NAME as a knob of CLASS over the setf-able PLACE. PLACE may refer to SESSION, so a knob can live on the session -- its sky clock, its player -- as well as in a special. QUANTITY is a quantity plist as DEFINE-QUANTITY-CONSTANT takes, (:quantity ... :unit ...); it and TYPE make the knob's declaration, which…
((name symbol) (type (eql 'arithmetic-operator)))PROPERTY: VALUES; -- the property a keyword, the values a list written space-separated.
(unit)The suffix a value in UNIT is printed with, space included where one is wanted. UNIT is a unit designator: a name, or a list of (NAME EXPONENT).
A knob over a real, bounded and quantized.
Compare compatible quantities and produce dimensionless values.
A knob over a generalized boolean: on or off.
Every defined knob, in definition order.
(knob)(name)The order the metabar shows groups in; a group not named here follows.
()The groups the knobs fall in: those in *KNOB-GROUP-ORDER* first, in that order, then the rest in order of first appearance.
(queue swapchain image-index
&key (wait-semaphores #()) present-id present-stage time-domain-id
target-time target-time-domain-present-stage)(group)The value is baked into terminal glyph instances; every terminal display must repopulate.
The value shapes the streaming window, which is only rebuilt when its centre moves; forget the centre so it rebuilds now.
(knob value session)VALUE made fit for KNOB's place: clamped and of the place's type.
The maximum of compatible quantities.
The minimum of compatible quantities.
Convert one scalar float or unsigned value to a 32-bit float.
Logical conjunction of tests and raw truth values.
(knob value session)Set KNOB to VALUE, made fit, and realize it in SESSION. Returns the value actually set.
(knob session direction &optional multiplier)Move KNOB by DIRECTION (+1 or -1) times MULTIPLIER steps in SESSION.
Multiplication and scalar scaling.
Addition over compatible quantities.
Division of two represented quantities.
(knob session)Logical negation of one test or raw truth value.
Subtraction or unary negation.
(declaration)Return DECLARATION's homogeneous quantity specification, or NIL.
(knob)The unit KNOB's value is measured in, as a designator: a unit name for one named unit to the first power, else a list of (NAME EXPONENT), else NIL for the identity.
(unit)The short spelling of the named UNIT, as it appears after a value or inside a compound unit. The default spells the unit's name; the common ones abbreviate.
The componentwise absolute value of a raw value.
(knob)Logical disjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
Construct a meaningful literal.
Headings, paragraphs, figures and their IDs, mentions, marks.
(name value &key type quantity documentation)Define an ordinary constant which publishes its represented quantity. The runtime value remains the unwrapped result of VALUE. TYPE states its Common Lisp representation independently of QUANTITY's semantic declaration; VALUE-DECLARATION-FOR retrieves the latter at definition boundaries.
(name)Return the represented-value declaration published by global NAME, or NIL.
(&key representation-type quantity-specification quantity-layout source-form)(options &key (default-tensor-order 0))Parse one source declaration plist into a quantity specification. Return NIL when OPTIONS contains no quantity attributes. This is the common source seam used by arithmetic parameters, shader interfaces, and semantic storage declarations; callers retain ownership of their source-specific error conditions and…
One named verb over a session.
Every defined action, in definition order.
(name (&key label) &body body)(action)(name)(action session)(session)Slide SESSION's metabar of knobs in or out, returning true when one is available. LUVCRAFT/MCCLIM supplies the session method.
Knobs: the live values of the game, as objects a gadget can turn.
The grading specials in RENDER.LISP, the sky's clock, the player's stride, the terminal's emissions, a literal in a shader: each has always been meant to be retuned from a live SLY eval. A knob is that value given a name, a declared quantity (so its unit is the one the arithmetic checks, and the one the metabar prints), a range and a step, a place to live -- a special, or a slot reached through SESSION -- and, the part that matters, one definite answer to "and then what": what has to happen for the change to be seen.
That answer is the knob's class. A plain
knobis read every frame and needs nothing. A knob mixing in a REALIZATION -- the terminal's, which bakes its values into glyph instances and must rebuild them; the streaming window's, which must be re-centred -- says so by its class, andrealize-knobdispatches on it. A knob folded into shader source needs no class of its own: the shader parser folds any knob's name into a literal throughshader-source-valueand remembers that it did, and the live pipeline rebuilds when the value it folded no longer holds.The protocol lives here, early; the knobs themselves are defined beside what they tune --
define-knobin RENDER.LISP for grading, SKY.LISP for the clock, SHADERS.LISP for the folded literals, and so on -- so a knob is found where its value is used. Reading a knob in a hot loop is a slot lookup and a funcall; take the reading once, at frame scope, and keep the dense loop dense.