afterglow.effects
Support functions for building the effects pipeline.
always-active
(always-active show snapshot)
An implementation of still-active? which simply always returns true
, useful for effects which run until you ask them to end.
blank
(blank)
(blank effect-name)
Create an effect which does nothing. This can be useful, for example, when you want to use fade to fade into an effect from a state where there was simply nothing happening (or where earlier and lower-priority effects can show through). If you want the blank effect to have a particular name, for example you are using it to set shared cue variables, you can pass a string argument.
build-head-assigner
(build-head-assigner kind head f)
Returns an assigner of the specified type which applies the specified assignment function to the provided head or fixture.
build-head-assigners
(build-head-assigners kind heads f)
Returns a list of assigners of the specified type which apply an assignment function to all the supplied heads or fixtures.
build-head-parameter-assigner
(build-head-parameter-assigner kind head param show snapshot)
Returns an assigner of the specified kind which applies a parameter to the supplied head or fixture. If the parameter is not frame-dynamic, it gets resolved when creating this assigner. Otherwise, resolution is deferred to frame rendering time.
build-head-parameter-assigners
(build-head-parameter-assigners kind heads param show)
Returns a list of assigners of the specified kind which apply a parameter to all the supplied heads or fixtures.
chase
(chase chase-name effects position & {:keys [beyond], :or {beyond :blank}})
Create an effect which moves through a list of other effects based on the value of a position
parameter. When position
is 1
, the first effect in effects
is used, 2
results in the second effect, and so on. Intermediate values produce a fade between the corresponding effects. The interpretation of values less than one or greater than the number of effects in effects
depends on the value passed with the optional keyword argument :beyond
. The default behavior (when :beyond
is omitted or passed with :blank
) is to treat any numbers outside the range of elements in effects
as if they refer to blank effects. This makes it easy to fade into the first effect by having position
grow from 0
to 1
, and to fade out of the last effect by having position
grow from the number of elements in effects
towards the next integer, at which point the final effect will be fully faded out. In this mode, when position
resolves to a value less than zero, or greater than the number of effects in effects
plus one, the chase will end. So a chase which fades in, fades between its effects, fades out, and ends, can be implemented by simply passing in a variable parameter for position
which smoothly grows from zero as time goes on.
Of course position
needs to be a dynamic parameter for the chase to progress over time; build-step-param is designed to conveniently create parameters for controlling chases in time with the show metronome. They can also be controlled by a dial on a physical controller that is bound to a show variable.
Passing a value of :loop
with the optional keyword argument :beyond
causes the chase to treat effects
as if it was an infinite list of copies of itself, so once the final effect is reached, the chase begins fading into the first effect again, and so on. Similarly, if position
drops below 1
, the chase starts fading in to the final effect. In this mode the chase continues until all of its underlying effects have ended (either on their own, or because they were asked to end by the operator), or position
resolves to nil
, which kills it instantly.
Finally, passing :bounce
with :beyond
is similar to :loop
, except that every other repetition of the list of effects is traversed in reverse order. In other words, if position
keeps growing steadily in value, and there are three effects in effects
, with a :beyond
value of :loop
you will see them in the order 1 → 2 → 3 → 1 → 2 → 3 → 1… while a value of :bounce
would give you 1 → 2 → 3 → 2 → 1 → 2 → 3 → 2….
Any element of effects
can be a scene, grouping many other effects, or blank, which will temporarily defer to whatever else was happening before the chase was activated.
code
(code f)
An effect which simply calls a function, then ends immediately, to allow arbitrary code to be easily run from the cue grid, for example to reset the metronome if the controller mapping doesn’t have a dedicated button for that.
f
must be a function which takes two arguments. It will be called with the show and metronome snapshot a single time, when the effect is first launched. It must return immediately, because this is taking place on the effect rendering pipeline, so any lengthy operations must be performed on another thread.
The effect stays running until asked to end, so that grid controllers can give visual feedback that it was started, but it doesn’t do anyting more after calling the function once when it starts.
conditional-effect
(conditional-effect effect-name condition effect)
Create an effect which makes the output of another effect conditional on whether a parameter has a non-zero value. Very useful when combined with variable-effect which can set that value to turn parts of a scene on or off independently. When condition
has the value 0
, this effect does nothing; when condition
has any other value, this effect behaves exactly like the effect passed in as effect
.
end-immediately
(end-immediately show snapshot)
An implementation of end which just reports that the effect is now finished by returning true
. Useful for effects which can simply be removed as soon as they are asked to end.
fade
(fade fade-name from-effect to-effect phase)
Create an effect which fades between two other effects as the value of a parameter changes from zero to one. When phase
is 0
(or less), this effect simply acts as if it were from-effect
. When phase
is 1
(or greater), this effect acts like to-effect
. For values of phase
between 0
and 1
, a proportional linear blend between from-effect
and to-effect
is created, so that at 0.5
each effect contributes the same amount.
Of course phase
can be a dynamic parameter; interesting results can be obtained with oscillated and variable parameters. And either or both of the effects being faded between can be a scene, grouping many other effects.
One of the effects may also be blank, which allows the other effect to be faded into or out of existence. When fading to or from a blank effect, the fade allows any previous or lower-priority effects to pass through as it approaches the blank effect. The same is true when fading between effects that do not include all the same fixtures, or affect different aspects of fixtures.
fade-assignment
(fade-assignment from-assignment to-assignment fraction show snapshot)
Calculates an intermediate value between two attribute assignments of the same kind (e.g. color, direction, channel value) for an element of a light show. The values of from-assignment
and to-assignment
may either be instances of afterglow.effects.Assignment
of the same :kind
, or they may be nil
, to indicate that the attribute is being faded to or from nothing. This function does the preparation and valiation needed in order to delegate safely to fade-between-assignments by promoting nil
values to empty assignments of the appropriate :kind
affecting the same target.
The amount contributed by each assignment is controlled by fraction
, which can range from 0
(or less), meaning that only from-assignment
is considered, to 1
(or greater), meaning that to-assignment
is simply returned. Intermediate values will ideally result in a blend between the two assignments, with 0.5
representing an equal contribution from each. Since the value of the assignments may still be dynamic parameters, the show and snapshot might be needed to resolve them in order to calculate the blended value. Some kinds of assignment may not support blending, in which case the default implementation will simply switch from from-assignment
to to-assignment
once fraction
reaches 0.5
.
fade-between-assignments
multimethod
Calculates an intermediate value between two attribute assignments of the same kind (e.g. color, direction, channel value) for an element of a light show. Most code will not call this directly, and will instead use the higher-level fade-assignment function to help set it up, or simply use a full-blown fade effect. This is the low-level mechanism which performs the fade calculations by dispatching to an appropriate implementation based on the :kind
value of from-assignment
, and it requires both from-assignment
and to-assignment
to be non-nil
instances of afterglow.effects.Assignment
of the same :kind
.
The amount contributed by each assignment is controlled by fraction
, which can range from 0
(or less), meaning that only from-assignment
is considered, to 1
(or greater), meaning that to-assignment
is simply returned. Intermediate values will ideally result in a blend between the two assignments, with 0.5
representing an equal contribution from each. Since the value of the assignments may still be dynamic parameters, the show and snapshot might be needed to resolve them in order to calculate the blended value. Some kinds of assignment may not support blending, in which case the default implementation will simply switch from from-assignment
to to-assignment
once fraction
reaches 0.5
.
IAssigner
protocol
Assign some attribute (color, direction, channel value) to an element of a light show at a given point in time. Any previous assignment to this element will be supplied as an argument, and may be tweaked or ignored as needs dictate. The target will be a subtree of the show’s fixtures, currently either a head or channel, or something defined by an extension to the rendering loop..
members
assign
(assign this show snapshot target previous-assignment)
Calculate the value the show
element target
should have at the moment in time represented by snapshot
. The previous-assignment
value is available order to support blending, highest-takes-priority, and other types of assignment which can be influenced by assigners which have run earlier (because they are associaed with effects running at lower priority or which started earlier). Returns a value appropriate for the kind of assignment, e.g. color object, channel value.
See the Assigner documentation for more discussion.
IEffect
protocol
The effect is the basic building block of an Afterglow light show. It generates a list of assignments that should be in effect at a given moment in the show. It can end on its own, or be asked to end. When asked, it may end immediately, or after some final activity, such as a fade. See The Effect Lifecycle for more discussion.
members
end
(end this show snapshot)
The effect has been asked to end. It should arrange to finish as soon as possible; return true
if it can end immediately, and it will be removed from the show. Otherwise it will be allowed to continue running as it performs its graceful shutdown until still-active? returns false
. If the user asks to end the effect a second time during this process, however, it will simply be removed from the show at that time.
generate
(generate this show snapshot)
List the asignments needed to implement the desired effect at this moment in time. Must return a sequence of afterglow.effects.Assigner
objects which will be merged into the current frame based on their kind, target, and the effect’s priority. If the effect currently has nothing to contribute, it may return an empty sequence.
still-active?
(still-active? this show snapshot)
An inquiry about whether this effect is finished, and can be cleaned up. A false
return value will remove the effect from the show.
resolve-assignment
multimethod
Translates an attribute assignment (e.g. color, direction, channel value) for an element of a light show to the actual DMX values that will implement it. Since the value of the assignment may still be a dynamic parameter, the show and snapshot might be needed to resolve it.
run-assigners
(run-assigners show snapshot assigners)
(run-assigners show snapshot assigners previous-assignment)
Returns the final assignment value that results from iterating over an assigner list that was gathered for a particular kind and target ID, feeding each intermediate result to the next assigner in the chain.
scene
(scene scene-name & effects)
Create an effect which combines multiple effects into one.
Scenes are a way to group a list of effects to run as a single effect. All of their assigners are combined into a single list, in the order in which the effects were added to the scene. Because of the way Afterglow evaluates assigners, that means that if any constituent effects try to assign to the same target, the later ones will have a chance to override or blend with the earlier ones.
wrap-fade-in-out
(wrap-fade-in-out effect-name effect & {:keys [step-in step-out]})
Create an effect which achieves the common goal of having another effect fade in when it starts, and then fade out again when it is asked to end.
By default the fade-in and fade-out both occur smoothly over a single beat, but you can adjust this by passing values for step-in
and step-out
. Each of these should be maps of arguments that will be merged on top of the default value {:fade-fraction 1.0}
and then passed as arguments to build-step-param. The arguments you will most likely want to use are :interval
(to fade over a bar or phrase), or :interval-ratio
to fade in over fractional or multiple beats/bars/phrases.