Animatable¶
Qualified name: algan.animatable\_base.animatable.Animatable
- class Animatable(scene=None, add_to_scene=True, name=None, animation_manager=None, data_sub_inds=None, parent_batch_sizes=None, is_primitive=False, **unexpected)[source]¶
Bases:
objectAnything whose state can change over the course of a video.
This is the base every
Mobis built on, and what makes Algan’s central trick work: an object’s animatable attributes are ordinary attributes to read and assign, but assigning one records an animation rather than overwriting a value, somob.color = BLUEis a one-second cross-fade and not a change to a variable. It also owns the object’s lifetime in the video –spawn()anddespawn()– and the per-frame hooks,add_updater()and theanimate_function()family.You rarely construct one directly; subclass it when you need something that animates but has no position in space, and register its state with
register_attrs_as_animatable().- Parameters:
scene (Scene | None) – The
Scenethis object belongs to. Defaults toNone, meaning the active Scene – which is what you want unless you are building several Scenes in one script.add_to_scene (bool) – Whether to register the object with the Scene, and so whether it can appear in the render at all. Defaults to True. Pass
Falseto build a Mob that exists only as raw material – a morph target, a layout template, geometry you are about to attach to something else – which keeps it out of the render even if it is spawned. The Scene is still bound either way; only the registration is skipped, and a composite Mob passes the same choice down to the parts it builds.name (str | None) – A label for this object, used to identify it in
repr()and in any warning or error that mentions it – soSquare(name="title box")turns “Square” into “Square ‘title box’” wherever Algan reports a problem with it. Defaults toNone, meaning the class name alone.animation_manager (AnimationManager | None) – The
AnimationManagercontrolling animations applied to this object. Defaults toNone, meaning the Scene’s own.data_sub_inds (torch.Tensor | None) – Internal: which rows of the shared attribute buffers this object reads and writes, for sub-mobs that share one parent’s tensors.
parent_batch_sizes (torch.Tensor | None) – Internal: how a batched parent’s attribute modifications are expanded over this object’s rows.
is_primitive (bool) – Internal: whether this object carries geometry the renderer must keep at render time.
- animatable_attrs¶
Attribute names which will be treated as animatable. Whenever an animatable attribute is modified, the modification is recorded on this mob’s Scene timeline for replay at render time.
- Type:
list[str]
Examples
A subclass with an animatable attribute of its own:
class Countdown(Animatable): def __init__(self, **kwargs): self.register_attrs_as_animatable(["seconds_left"]) super().__init__(**kwargs) self.seconds_left = 10 timer = Countdown().spawn() timer.seconds_left = 0 # counts down over one second
Methods
Attach a function that runs every frame from now on.
Animate an arbitrary function of your own over this Mob.
Animate a function of your own, driven by elapsed seconds.
Make a copy of this Mob, by default spawned into the scene.
Remove the Mob from the video; an alias for
despawn().Remove the Mob from the video.
Get an animatable attribute's current authoring value.
Get the color this Mob uses when none was given.
Return this object unchanged.
Internal: run this Mob's initialization hooks.
Whether changes to this Mob would currently be recorded as animation.
Whether this Mob has been despawned.
Whether this Mob has been spawned into the video.
Whether this Mob or anything below it in the hierarchy has spawned.
Hook called by
spawn()to play an entrance animation.Hook called by
despawn()to play an exit animation.Hook called once when the Mob is constructed.
Make attributes animatable, so writing them animates.
Remove every updater attached to this Mob.
Stop an updater from running any further.
Record animation back at this Mob's retroactive timestamp.
Bring the Mob into the video.
Hold still for a while before the next animation.
Attributes
This mob's scene-owned animation manager.
The Mobs attached below this one, in attachment order.
This mob's [spawn, despawn) interval on its Scene timeline (a
Lifespan).The Mobs this one is attached to, in attachment order.
- add_updater(update_function, *args, **kwargs)[source]¶
Attach a function that runs every frame from now on.
Updaters are how you get behaviour that persists rather than a one-off animation: a Mob that always faces the camera, a label that tracks a moving dot, an idle bobbing motion. The function is called on every frame, with the seconds elapsed since it was added, and keeps running until it is removed.
Animation
Runs every frame for as long as it is attached, so it is unaffected by the current context’s runtime. It is applied once immediately at zero elapsed time, so the scene reflects it right away. Updaters are applied after recorded animations each frame, so an updater writing an attribute wins over an animation of that attribute.
- Parameters:
update_function – Callable taking
(mob, time_elapsed, *args, **kwargs), wheretime_elapsedis in seconds. It must be vectorized over the Mob’s batch.*args – Passed to
update_functionafter the elapsed time.**kwargs – Passed to
update_functionafter the elapsed time.
- Returns:
Id of the updater, for passing to
remove_updater(). An updater that is never removed runs for the rest of the video.- Return type:
int
Examples
Example: Example1AnimatableAddUpdater ¶
from algan import * square = Square().spawn() square.add_updater(lambda mob, t: mob.set(location=RIGHT * t)) Scene.wait(2) Scene.save_video()
- animate_function(function, t=1, *args, **kwargs)[source]¶
Animate an arbitrary function of your own over this Mob.
The function is called once per frame with a progress value that ramps up over the animation, which lets you drive any state you like – the escape hatch for effects Algan has no built-in method for.
Animation
Recorded as an animation: the function’s second argument sweeps from 0 to
tover the current context’s runtime (1 second by default). The function body must be vectorized over the Mob’s batch; it runs on tensors, not on one part at a time.- Parameters:
function – Callable taking
(mob, t, *args, **kwargs). Its second argument is the interpolated value.t – Value the second argument reaches at the end of the animation. Defaults to
1.*args – Passed to
functionafter the interpolated value.**kwargs – Passed to
functionafter the interpolated value.
- Returns:
This object, so calls can be chained.
- Return type:
See also
animate_function_of_time()Drive the function by elapsed seconds instead.
add_updater()Keep running every frame indefinitely.
- animate_function_of_time(function, time_elapsed=0, *args, **kwargs)[source]¶
Animate a function of your own, driven by elapsed seconds.
Like
animate_function(), but the function receives the seconds elapsed rather than a 0-to-1 progress value. Use it when the effect is defined in real time – a rotation of 90 degrees per second, say – and you would rather not know in advance how long the animation runs.Animation
Recorded as an animation over the current context’s runtime (1 second by default). The function’s second argument runs from 0 to that runtime, in seconds. The body must be vectorized over the Mob’s batch.
- Parameters:
function – Callable taking
(mob, time_elapsed, *args, **kwargs), wheretime_elapsedis in seconds.time_elapsed – Placeholder, overwritten per frame with the elapsed time. Defaults to
0; whatever you pass is ignored.*args – Passed to
functionafter the elapsed time.**kwargs – Passed to
functionafter the elapsed time.
- Returns:
This object, so calls can be chained.
- Return type:
- property animation_manager¶
This mob’s scene-owned animation manager.
- property children: list[Animatable]¶
The Mobs attached below this one, in attachment order.
The live list, not a copy: it changes as the hierarchy does. Edit it with
add_children(),remove_child()orreplace_children()rather than by assignment, so the children’sparentsare kept in step.
- clone(add_to_scene=True, spawn=True, animate_creation=False, recursive=True, clone_data=True)[source]¶
Make a copy of this Mob, by default spawned into the scene.
The copy starts out identical – same position, color, material, children – but is independent from then on: animating one does not affect the other. Use it to stamp out repeated shapes, or to get a second version of something you are about to change.
The copy has its own animation history rather than inheriting this Mob’s, so it does not replay the original’s past animations.
Animation
Not animated by default: the copy appears instantly, already in place. Pass
animate_creation=Truefor it to fade in over the current context’s runtime (1 second by default).- Parameters:
add_to_scene (bool) – Whether the copy is added to the scene. Defaults to True; False makes a detached Mob, useful purely as a source of values (this is what
become()does with its target).spawn (bool) – Whether the copy is spawned, i.e. visible. Defaults to True; pass False to configure it – including anything that must happen before spawning, such as
set_material()– and spawn it yourself later.animate_creation (bool) – Whether spawning the copy plays its entrance animation. Defaults to False, so the copy simply appears.
recursive (bool) – Whether children are copied too. Defaults to True; False copies this Mob alone, leaving it childless.
clone_data (bool) – Whether the copy gets its own animation data. Defaults to True. False produces a view that shares this Mob’s data and identity, so animating the view animates the original – what indexing (
mob[0]) uses.
- Returns:
The new copy. When
clone_datais False this is a view of this Mob rather than an independent object.- Return type:
Examples
Example: Example1AnimatableClone ¶
from algan import * square = Square(color=BLUE).spawn() copy = square.clone() copy.move(RIGHT * 2) copy.color = RED Scene.save_video()
- delete()[source]¶
Remove the Mob from the video; an alias for
despawn().Animation
Recorded as an animation: the Mob fades out over the current context’s runtime (1 second by default).
- Returns:
This object, so calls can be chained.
- Return type:
- despawn(animate=True)[source]¶
Remove the Mob from the video.
The Mob stops being drawn from this point on, but the animation already recorded for it is untouched – everything it did before still plays. A despawned Mob cannot be brought back; clone it before despawning if you need it again later.
Despawning is recursive: children despawn with their parent. Despawning a Mob that is already despawned does nothing.
Animation
Recorded as an animation over the current context’s runtime (1 second by default): the Mob fades out.
despawn(animate=False)removes it instantly, which is what you want for something already off-screen.- Parameters:
animate (bool) – Whether to play the exit animation, by default a fade-out (see
on_destroy()). Defaults to True.- Returns:
This object, so calls can be chained.
- Return type:
- get_animated_attribute(key, include_descendants=False, default=None, copy=True, _scope=None)[source]¶
Get an animatable attribute’s current authoring value.
This is the value as the scene is being authored – the state the Mob has reached at the current point in the timeline – not the value at any particular rendered frame. Plain attribute access (
mob.location) goes through this.- Parameters:
key – Name of the animatable attribute.
include_descendants (bool) – Whether to return descendants’ values as well, stacked into the batch dimension. Defaults to False.
default – Value used to seed the attribute if the Mob has none yet. Defaults to
None, meaning do not create one.copy (bool) – Whether to return a copy. Defaults to True; pass False only for a read you will not retain, since the underlying buffer is reused.
- Returns:
The attribute’s current value.
- Return type:
torch.Tensor
- get_default_color()[source]¶
Get the color this Mob uses when none was given.
Override in a subclass to give a shape its own default; the built-in shapes do exactly that.
- Returns:
BLACKfor the base class.- Return type:
- identity()[source]¶
Return this object unchanged.
A do-nothing placeholder for APIs that expect a transform function.
- Returns:
This object.
- Return type:
- init()[source]¶
Internal: run this Mob’s initialization hooks.
Calls
on_init()and lets the current context do its own setup. Construction always calls it; you never need to.- Returns:
This object, so calls can be chained.
- Return type:
- is_animating()[source]¶
Whether changes to this Mob would currently be recorded as animation.
True when the Mob is on screen (itself or through a child) and the current context records functions – so it is False inside
Off, and False before the Mob has spawned, which is why setup done pre-spawn costs no video time.- Returns:
Whether edits are being recorded right now.
- Return type:
bool
- is_despawned()[source]¶
Whether this Mob has been despawned.
- Returns:
Whether the Mob has a recorded despawn time. A Mob that was never spawned reports False here as well as from
is_spawned().- Return type:
bool
- is_spawned()[source]¶
Whether this Mob has been spawned into the video.
Stays True after
despawn()– it reports that the Mob has a spawn time, not that it is on screen right now. Pair it withis_despawned()for that.- Returns:
Whether the Mob has a recorded spawn time.
- Return type:
bool
- is_spawned_in_subtree()[source]¶
Whether this Mob or anything below it in the hierarchy has spawned.
Containers are routinely left unspawned while their contents are spawned individually (
for mob in group: mob.spawn()), and Group views (group[1:3]) never spawn at all. Such a container is on screen through its children, so modifications made to it must animate exactly as they do for a spawned mob: gating onis_spawned()alone applies them instantly and records no timeline event, so the animation also contributes no time to the rendered video.The answer only changes when the hierarchy changes or something spawns, so it is cached against those two global versions.
- Returns:
Whether this Mob or any descendant has a recorded spawn time.
- Return type:
bool
- property lifespan¶
This mob’s [spawn, despawn) interval on its Scene timeline (a
Lifespan). Sub-mobs created by indexing share their source’s id, and therefore its lifespan.
- on_create()[source]¶
Hook called by
spawn()to play an entrance animation.Does nothing at this level;
Moboverrides it with a fade-in. Override it to give a subclass its own entrance.- Returns:
This object, so calls can be chained.
- Return type:
- on_destroy()[source]¶
Hook called by
despawn()to play an exit animation.Does nothing at this level;
Moboverrides it with a fade-out. Override it to give a subclass its own exit.- Returns:
This object, so calls can be chained.
- Return type:
- on_init()[source]¶
Hook called once when the Mob is constructed.
Does nothing by default. Override it to run setup that must happen before spawning, e.g. building child Mobs.
- Returns:
This object, so calls can be chained.
- Return type:
- property parents: list[Animatable]¶
The Mobs this one is attached to, in attachment order.
The live list, not a copy. Edit it with
add_parent()orremove_parent()rather than by assignment, so the parents’childrenare kept in step.
- register_attrs_as_animatable(attrs, my_class=None)[source]¶
Make attributes animatable, so writing them animates.
Registered attributes get property getters and setters wired into the animation system: assigning to one records an interpolated change instead of overwriting a value. This is how a custom shader’s parameters become things you can animate, and how a subclass exposes its own animatable state.
Animation
Not animated: registration is setup. Call it in a subclass’s
__init__before assigning the attributes – registering after the first write leaves the value outside the animation system.- Parameters:
attrs (list[str]) – Attribute name, or list of names, to register.
my_class – Class to attach the properties to. Defaults to
None, meaning this object’s own class.
- remove_all_updaters()[source]¶
Remove every updater attached to this Mob.
Each one is removed as by
remove_updater(), so the Mob keeps whatever state the updaters left it in.Animation
Not animated. Takes effect at the current timestamp: frames before it keep the updaters, frames after do not.
- remove_updater(updater_id)[source]¶
Stop an updater from running any further.
The Mob keeps whatever state the updater left it in at this moment, rather than snapping back, so removing a “follow the dot” updater leaves the Mob where the dot last was.
Animation
Not animated. Takes effect at the current timestamp: the updater runs on frames before this point and not after. Removing an already-removed updater does nothing.
- Parameters:
updater_id – Id returned by
add_updater().-1removes the most recently added updater.
- retroactive()[source]¶
Record animation back at this Mob’s retroactive timestamp.
Inside the
withblock, authoring time is rewound, so anything recorded is inserted earlier in the video; the timestamp is restored on exit even if the block raises.Animation
The block’s own animations are recorded normally – only when they happen changes.
Examples
with mob.retroactive(): mob.color = BLUE # happens earlier in the video
- spawn(animate=True)[source]¶
Bring the Mob into the video.
The mob does not appear on screen until it is spawned. Changes made before spawning are not animated. After spawning, changes to the Mob animate by default and are controlled by
AnimationContext.Spawning is recursive: children spawn with their parent. Spawning a Mob that is already spawned does nothing.
Animation
Recorded as an animation over the current context’s runtime (1 second by default): the Mob fades in.
spawn(animate=False)makes it appear immediately, no animation.- Parameters:
animate (bool) – Whether to play the entrance animation, by default a fade-in (see
on_create()). Defaults to True.- Returns:
This object, so calls can be chained – which is what makes
square = Square().spawn()work.- Return type:
See also
despawn()Remove the Mob from the video again.
- wait(*args, **kwargs)[source]¶
Hold still for a while before the next animation.
Advances authoring time without changing anything, which leaves a pause in the video. Same as
wait(), reachable from a Mob so it can be chained between animations.Animation
Recorded on the timeline: it consumes video time and nothing else.
- Parameters:
*args – Passed to the current context’s
wait– notably the runtime in seconds, which defaults to 1.**kwargs – Passed to the current context’s
wait– notably the runtime in seconds, which defaults to 1.
- Returns:
This object, so calls can be chained.
- Return type: