Mob

Qualified name: algan.animatable\_base.mob.Mob

class Mob(location=tensor([0., 0., 0.]), basis=tensor([1., 0., 0., 0., 1., 0., 0., 0., 1.]), color=None, opacity=1, glow=0, **kwargs)[source]

Bases: MobHierarchyMixin, MobOrientationMixin, MobMovementMixin, MobLayoutMixin, MobMorphMixin, MobMaterialsMixin, Animatable

A Movable Object: an Animatable that exists at a point in 3-D space.

Mobs carry the animatable attributes location, basis (orientation and scale), scale_coefficient, color, opacity and glow – assigning to any of them records an animation. Mobs can have child Mobs, forming a hierarchy, and a change to a parent propagates to its descendants.

Parameters:
  • location (torch.Tensor) – Initial location in 3-D world space, in world units. Defaults to ORIGIN (the centre of the scene). Shape: (*, 3) where * denotes zero or more batch dimensions.

  • basis (torch.Tensor) – The Mob’s orientation and scale, as a 3x3 matrix. The rows are the right, upwards and forwards directions, and each row’s norm is the scale along that direction. Accepts either the (*, 3, 3) matrix or the (*, 9) flattened form it is stored in. Defaults to an identity matrix (no rotation, unit scale).

  • color (Color | None) – The color of the Mob: an Algan Color, a named constant such as BLUE, or anything Color() accepts. Defaults to None, meaning the class’s own default from get_default_color()BLACK for a plain Mob, PURPLE for a 2-D shape, GREEN for a Surface.

  • opacity (float) – How opaque the Mob is, from 0 (invisible) to 1 (fully opaque). Defaults to 1.

  • glow (float) – How much light the Mob emits of its own, on top of what it reflects. 0 is an ordinary unlit surface and 1 a strongly glowing one; larger values keep brightening. Defaults to 0.

  • **kwargs – Passed to Animatable – notably scene and add_to_scene.

two_sided, closed_shell, casts_shadows, receives_shadows

Plain (non-animatable) geometry declarations, documented individually below. All four are read once when the Mob is spawned, so they must be set before spawn().

Examples

Create a square and move it to the left:

Example: Example1Mob

from algan import *

square = Square().spawn()
square.move(LEFT)

Scene.save_video()

Create a mob with a specific color and scale:

Example: Example2Mob

from algan import *

circle = Circle(color=BLUE).scale(2).spawn()

Scene.save_video()

Methods

become

Transform any Mob hierarchy into any other Mob hierarchy.

despawn

Remove the Mob from the video.

detach_history

Hand this Mob's recorded animation to a hidden clone and start fresh.

get_normal

Get the Mob's surface normal, i.e. the way it faces.

get_parts_as_mobs

Flatten this Mob's hierarchy into a list.

map_animated_attribute

Animate an attribute to a function of its own current value, across this Mob and every descendant at once.

move

Move the Mob by a displacement from wherever it currently is.

move_to

Move the Mob to an absolute location.

on_create

Play this Mob's spawn-in animation: a fade from transparent.

on_destroy

Play this Mob's despawn animation: a fade to transparent.

owned_subtrees

The child subtrees this Mob built for itself, when it aggregates.

pulse_color

Flash the Mob a different color and let it settle back.

refresh_history

Clear this Mob's recorded spawn so it counts as never spawned.

rotate

Rotate the Mob about an axis, optionally around a point in space.

scale

Resize the Mob relative to its current size.

set

Set several animatable attributes at once, as one animation.

set_animated_attribute

Animate one animatable attribute to a new value, by name.

set_location

Set the Mob's location, with control over whether children follow.

set_non_recursive

Set attributes on this Mob only, leaving its children untouched.

set_opacity_via_color

Fade the Mob by writing opacity into its color rather than its opacity.

set_scale

Set the Mob's absolute scale, ignoring its current size.

spawn

Bring the Mob into the video.

wave_color

Send a color pulse travelling across the Mob.

Attributes

animation_manager

This mob's scene-owned animation manager.

basis

The Mob's orientation and scale, as a flattened 3x3 matrix of shape (*, 9).

casts_shadows

Whether this Mob's geometry blocks light on its way from a light source to another surface -- whether it casts a shadow.

children

The Mobs attached below this one, in attachment order.

closed_shell

Whether this Mob's triangles form a CLOSED shell -- every camera ray that enters the geometry crosses a second time on its way out.

draws_descendants

Whether get_render_primitives returns geometry belonging to this Mob's DESCENDANTS as well as its own.

forward

Get the direction the Mob is facing.

lifespan

This mob's [spawn, despawn) interval on its Scene timeline (a Lifespan).

location

The Mob's position in world space, shape (*, 3).

normalized_basis

The Mob's orientation with scale divided out, shape (*, 9).

parents

The Mobs this one is attached to, in attachment order.

receives_shadows

Whether this Mob's surfaces are darkened by shadows cast onto them.

right

Get the Mob's own rightward direction.

scale_coefficient

The Mob's scale along its own right, up and forward axes, shape (*, 3).

two_sided

Whether this Mob's geometry should be lit from whichever side the ray arrives on.

up

Get the Mob's own upward direction.

x

The Mob's x coordinate in world units, shape (*, 1).

xy

The Mob's x and y coordinates in world units, shape (*, 2).

y

The Mob's y coordinate in world units, shape (*, 1).

z

The Mob's z coordinate in world units, shape (*, 1).

property basis: Tensor

The Mob’s orientation and scale, as a flattened 3x3 matrix of shape (*, 9).

Unflattened, the three rows are the Mob’s own right, upward and forward directions in world space, and each row’s norm is the Mob’s scale along that axis. The identity matrix therefore means unrotated at unit scale.

Assigning to this animates the Mob to the new basis over the current context’s runtime (1 second by default), rotating and scaling its children with it. Concurrent writes compose rather than overwrite, so a rotate and a scale inside one Sync both take effect.

become(other_mob, *, detach_history=True, minimize_movement=False, strategy='auto')

Transform any Mob hierarchy into any other Mob hierarchy.

Structural containers are transparent to pairing: renderer-facing primitives are matched by concrete type, primitive family and either traversal order or spatial proximity. Same-kind pairs use structural point alignment and different primitive families convert through a cubic-PN triangle soup. ImageMob pairs cross-dissolve because image textures have no geometric adapter, and so does a pair that changes whether a circuit is filled: that flag is read once per render rather than per frame, so no morph can show it changing. The pairing prefers a counterpart that does not force the change. strategy may be "auto", "morph" (reject every non-geometric pair), or "dissolve" (dissolve the whole root).

With the default detach_history=True, the returned Mob has the target’s hierarchy and is spliced into this Mob’s parent slot; use it for later animation. Surplus target primitives fade in as they grow from collapsed, target-shaped geometry at nearby source points, while surplus sources fade out as they shrink to points. detach_history=False keeps identity for compatibility and therefore uses a dissolve where a target-class replacement would be required. Updaters remain attached to replaced sources rather than being migrated to replacements.

Notes

Cross-kind geometric morphs pair independent PN triangles, so a surface can show seams while triangles move to new counterparts. Bezier outlines are triangulated at the primitive-family swap, making the silhouette at that instant an approximation. A mesh-to-bezier morph likewise travels through the target’s filled triangulation rather than growing cubic curves. Cached glyph views held before a cross-kind replacement remain views of the replaced source; reacquire them from the returned Mob when it is text.

Parameters:
  • other_mob (Mob)

  • detach_history (bool)

  • minimize_movement (bool)

  • strategy (str)

Return type:

Mob

casts_shadows = True

Whether this Mob’s geometry blocks light on its way from a light source to another surface – whether it casts a shadow. True (the default) is what every Mob did before the flag existed. False makes the geometry invisible to shadow rays ONLY: it still renders to the camera, to reflections and to refraction exactly as it would have, and it still RECEIVES shadows unless receives_shadows says otherwise.

This is the per-Mob half of SETTINGS.raytracing.shadows, which remains the switch for the feature as a whole – with shadows off globally, neither flag does anything. Use it where a shadow is physically implied but pedagogically in the way: a label plate lying on the scene’s floor, a wireframe cage around the object being explained, an annotation arrow whose shadow reads as a second arrow.

Like two_sided, set it before the Mob is spawned – the render primitive reads it once – and note that it is a plain attribute, not an animatable one: it cannot change over the course of a render.

closed_shell = False

Whether this Mob’s triangles form a CLOSED shell – every camera ray that enters the geometry crosses a second time on its way out. False (the default) leaves opacity compositing once per crossing, which is right for anything open or unprovable: a 2-D shape, an uncapped Cone, a partial sphere, user polyhedron geometry whose closedness cannot be proven.

On a closed shell, one attenuation of what is behind it IS the documented meaning of Mob.opacity – rendering at opacity a must give a * (the Mob rendered opaque) + (1 - a) * backdrop – so the renderer caps the shell’s total coverage per pixel instead of letting both shells composite (the far sheet would otherwise deliver the extra a * (1 - a) of coverage painted with the interior’s own shading). The built-in solids declare it; see tests/unit_tests/test_closed_shell_declaration.py for the proof that each declaration matches the geometry. Like two_sided, set it before the Mob is spawned: the render primitive reads it once.

Known limit: the rule reaches PRIMARY visibility only. A REFLECTION of a half-transparent solid – its image in a mirror – still composites both shells and so reads more opaque than the authored value, because the bounce loop that shades reflections carries no surface identity. The same is true of any render at samples_per_pixel > 1, which routes to the Monte Carlo tracer instead.

despawn(animate=True)

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:

Animatable

detach_history()[source]

Hand this Mob’s recorded animation to a hidden clone and start fresh.

The animation recorded so far keeps playing – it now belongs to a clone that despawns at this moment – while this Mob continues with a clean history from here. Use it before a change that cannot be interpolated from the old value, because the two states have different shapes: for example raising a Surface’s resolution, or a become between Mobs with different numbers of parts. Without detaching, the render-time replay tries to interpolate mismatched shapes and raises.

Animation

Not animated: the swap happens instantly, inside Off(), and the viewer sees no discontinuity. Everything recorded afterwards animates from the Mob’s state at this moment.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

draws_descendants = False

Whether get_render_primitives returns geometry belonging to this Mob’s DESCENDANTS as well as its own. Almost nothing does: a BezierCircuitCubic or a Surface draws its own rows and leaves its children to draw themselves. Polyhedron is the exception – it gathers every face under one _mesh_key – and the difference decides two things for become(): whether the Mob is one morph unit or several, and whether a descendant may be published to the Scene in its own right (doing so under an aggregator draws it twice, and draws geometry the aggregator deliberately omits, such as a Polyhedron’s vertex-and-edge graph).

get_normal()[source]

Get the Mob’s surface normal, i.e. the way it faces.

An alias for get_forward_direction(), named for the 2-D case: a flat shape’s normal is the direction it faces out of its own plane.

Returns:

Unit normal, shape (*, 3).

Return type:

torch.Tensor

get_parts_as_mobs()[source]

Flatten this Mob’s hierarchy into a list.

Returns:

This Mob followed by every descendant, depth-first. The Mobs are the live objects, not copies, so changing one changes the scene.

Return type:

list[Mob]

property location: Tensor

The Mob’s position in world space, shape (*, 3).

Assigning to this animates the Mob to the new position over the current context’s runtime (1 second by default), carrying its children along so their offsets from it are preserved. mob.location = ORIGIN and mob.move_to(ORIGIN) are the same operation.

This is also the point the Mob turns and scales about, so a shape is anchored at its own centroid – the point it balances on, which for a Triangle is a quarter of a unit below the middle of the box around it. get_center() reports that box’s midpoint instead, when what you want is the middle of what the viewer sees rather than the point it pivots on.

map_animated_attribute(attr, func)[source]

Animate an attribute to a function of its own current value, across this Mob and every descendant at once.

set_animated_attribute() animates towards a value you supply. This animates towards a value derived from what each part already has, which is what you want for “half as bright as it is now” or “everything a quarter of its current size” – operations where each part has a different starting point and a different target.

func receives every affected value stacked into one tensor of shape (1, N, D), where N counts the rows this Mob and its descendants own for attr and D is the attribute’s width (1 for opacity, 3 for location, 4 for color). It must return a tensor of that same shape – the target values, in the same order.

Reach for it instead of a Python loop over get_descendants(). A loop records one animation per descendant, which on a large group is thousands of separate recorded animations; this records one, and renders measurably faster for it.

Animation

Recorded as an animation: every affected value moves from what it is now to its target over the current context’s runtime (1 second by default), all together inside a Sync. func is evaluated once, at the moment of the call – it computes the destination, it is not re-run per frame. For a value that must be recomputed every frame, use add_updater() instead. Only spawned Mobs record; a Mob whose subtree is not on screen is changed immediately and silently.

Parameters:
  • attr (str) – Name of the animatable attribute, e.g. "opacity", "color", "location", "glow". It has to be one whose whole meaning is its per-row value, and two kinds are not, so both are rejected rather than silently half-applied. A derived property (scale_coefficient, the row norms of basis; Circle.radius; stroke_color) has no rows at all. A hierarchical one (basis) has rows, but they are only half the operation: a rotation or a scale has to carry the subtree’s locations along, which is why rotate(), scale() and plain assignment are what change those.

  • func (Callable) – Callable mapping the stacked current values to the stacked target values, both of shape (1, N, D). It is passed a copy, so it may modify its argument in place and return it.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

Raises:
  • ValueError – If func returns a tensor whose shape is not the shape it was given.

  • AttributeError – If attr is not an animatable attribute of this Mob, or is a derived or hierarchical one that cannot be mapped row-wise.

  • AlganConfigurationError – If func returns a NaN or an infinity for any row, or a value outside [0, 1] when attr is "opacity". Both are checked on the target func computed, at this line: the target is what every later frame interpolates towards, and a bad one renders as a blank or missing shape rather than raising.

See also

set_animated_attribute()

Animate an attribute to a value you supply, rather than to a function of the current one.

add_updater()

Recompute a value every frame instead of once.

Examples

Example: Example1MobMapAnimatedAttribute

from algan import *

row = Group([Square().move(LEFT * 2), Circle(), Triangle().move(RIGHT * 2)])
row.spawn()

# Dim everything to a tenth of however visible it already is,
# then pull every point halfway in towards the world origin.
row.map_animated_attribute('opacity', lambda o: o * 0.1)
row.map_animated_attribute('location', lambda p: p * 0.5)

Scene.save_video()
move(displacement, **kwargs)

Move the Mob by a displacement from wherever it currently is.

Animation

Recorded as an animation: the Mob travels the displacement over the current context’s runtime (1 second by default). Retime it with with Seq(runtime=2): mob.move(RIGHT), or apply it instantly with with Off(): mob.move(RIGHT). Applies to this Mob and its descendants.

Parameters:
  • displacement (torch.Tensor) – How far and in which direction to move, shape (*, 3), in world units. The spatial constants (RIGHT, UP, OUT, …) are unit vectors, so mob.move(RIGHT * 3) moves three units right.

  • **kwargs – Passed to move_to() – notably arc_angle to travel along a curve rather than a straight line.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

Examples

Example: Example1MobMove

from algan import *

square = Square().spawn()
square.move(RIGHT)
square.move(UP * 2 + LEFT)
square.move(DOWN, arc_angle=120)

Scene.save_video()
move_to(location, arc_angle=None, **kwargs)

Move the Mob to an absolute location.

The path is a straight line unless arc_angle is given, in which case the Mob swings to the target along a circular arc.

Animation

Recorded as an animation: the Mob travels from where it is to location over the current context’s runtime (1 second by default). Use with Off(): mob.move_to(...) to teleport it instead. Applies to this Mob and its descendants.

Parameters:
  • location (torch.Tensor) – The target location, shape (*, 3).

  • arc_angle (float | None) – Signed sweep of the curved path, in degrees. Defaults to None, meaning travel in a straight line.

  • **kwargs – Passed to set_location() (notably recursive), or to move_to_point_along_arc() when arc_angle is given (notably arc_normal).

Returns:

This Mob, so calls can be chained.

Return type:

Mob

See also

move()

Move by a relative displacement instead.

move_to_screen_position()

Place the Mob in screen space.

property normalized_basis: Tensor

The Mob’s orientation with scale divided out, shape (*, 9).

The same matrix as basis with every row normalized to unit length, so it carries the Mob’s rotation and nothing else. Read-only.

on_create()[source]

Play this Mob’s spawn-in animation: a fade from transparent.

Called by spawn() when animate=True. Override it in a subclass to give a Mob its own entrance; the override should record its animation the same way, and is free to ignore opacity entirely.

Animation

Recorded as an animation over the current context’s runtime (1 second by default). The opacity write is non-recursive, so descendants run their own on_create.

on_destroy()[source]

Play this Mob’s despawn animation: a fade to transparent.

Called by despawn() when animate=True. Override it in a subclass to give a Mob its own exit.

Animation

Recorded as an animation over the current context’s runtime (1 second by default).

owned_subtrees()[source]

The child subtrees this Mob built for itself, when it aggregates.

Only consulted when draws_descendants is set, and it narrows that claim: a Polyhedron speaks for the faces it draws and the vertex-and-edge graph it deliberately does not, but not for a child a user hung on it afterwards. Without the distinction, a morph into a Polyhedron carrying user geometry withheld that geometry from the Scene and it vanished. Returning an empty list means “everything below me”.

Return type:

list

pulse_color(color=None, opacity=None, recursive=True, new_color=None)[source]

Flash the Mob a different color and let it settle back.

A two-stage animation: the color travels out to color by the halfway point and back to new_color by the end. Good for drawing the eye to one part of a diagram without leaving it recolored.

Animation

Recorded as an animation over the current context’s runtime (1 second by default), with the peak of the pulse at the halfway mark. Color and opacity pulses run together inside a Sync.

Parameters:
  • color (Tensor) – Color to pulse to. Defaults to None, which pulses only the opacity (so pass at least one of color and opacity).

  • opacity (bool) – Alpha to hold for both stages of the pulse, 0 to 1. Defaults to None, leaving opacity alone.

  • recursive – Whether descendants pulse too. Defaults to True.

  • new_color – Color to end on. Defaults to None, meaning every affected part returns to its own current color.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

See also

wave_color()

Run the same pulse across the Mob as a travelling wave.

receives_shadows = True

Whether this Mob’s surfaces are darkened by shadows cast onto them. True (the default) is what every Mob did before the flag existed. False shades the Mob as though every light reached it unobstructed, which is strictly cheaper than the default: no shadow ray is traced for its fragments at all.

It does not change what the Mob does to OTHER surfaces – a Mob that receives no shadow still casts one unless casts_shadows says otherwise. Use it to keep a surface legible where a correct shadow would not be: a caption laid on a shadowed floor, a color key or legend that has to stay readable wherever it is placed.

Set it before the Mob is spawned, and like casts_shadows it is a plain attribute rather than an animatable one.

Two kinds of Mob ignore it, both because they were never shadowed to begin with: 2-D geometry (a shape, Text) renders unlit, and so does anything with set_shader() None. A Mob carrying a custom fragment pipeline (set_fragment_shader()) also ignores it, because the slot this rides in the material block belongs to that pipeline’s own parameters – the same reason a custom pipeline is never asked about two_sided. casts_shadows has none of these exceptions: all three still cast.

refresh_history()[source]

Clear this Mob’s recorded spawn so it counts as never spawned.

Resets the lifespan of this Mob and every descendant, which makes them behave as if freshly constructed. Mostly useful as part of detach_history(); calling it on a live Mob leaves the Mob visible in already-recorded animation while claiming it was never spawned, so reach for it only if you know you want that.

Animation

Not animated and not recorded. Takes effect immediately on the timeline.

rotate(angle, axis=tensor([0., 0., 1.]), about=None, *, degrees=True)

Rotate the Mob about an axis, optionally around a point in space.

With the default about=None only the Mob’s orientation changes and it stays where it is. Given an about point, the Mob also travels around the axis through that point, like a planet spinning as it orbits. To move around a point without re-orienting the Mob, use orbit().

Animation

Recorded as an animation: the rotation sweeps from 0 to angle over the current context’s runtime (1 second by default), so the Mob turns rather than snapping. Retime it with with Seq(runtime=3): mob.rotate(90), or apply it instantly with with Off(): mob.rotate(90). Applies to this Mob and its descendants.

Parameters:
  • angle (float | torch.Tensor) – How far to rotate, counter-clockwise when looking down axis, in degrees unless degrees is False. Accepts a tensor of shape (*, 1) to give each Mob of a batch its own angle.

  • axis (torch.Tensor) – Axis to rotate around; need not be normalized. Defaults to OUTWARD (the +z axis, pointing out of the screen), which spins a flat 2-D shape in the screen plane.

  • about (torch.Tensor | None) – Point to rotate around, shape (*, 3). Defaults to None, meaning rotate in place about the Mob’s own location, which for a shape is its centroid.

  • degrees (bool) – Whether angle is in degrees. Defaults to True; pass False to give it in radians.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

Examples

Example: Example1MobRotate

from algan import *

square = Square().spawn()
square.rotate(90)
square.rotate(180, axis=UP)
square.rotate(90, about=RIGHT * 2)

Scene.save_video()
scale(scale_factor, recursive=True)[source]

Resize the Mob relative to its current size.

The factor multiplies the size the Mob has now, so two calls to scale(2) leave it four times its original size. For an absolute target, use set_scale().

Animation

Recorded as an animation: the Mob grows or shrinks over the current context’s runtime (1 second by default).

Parameters:
  • scale_factor (float | Tensor) – Multiplier on the current size: 2 for twice as big, 0.5 for half. A tensor of shape (*, 3) scales the Mob’s right, up and forward axes separately, which is how you stretch a shape.

  • recursive (bool) – Whether descendants scale too, keeping the Mob’s proportions. Defaults to True; False scales this Mob alone, so a Group’s children keep their own sizes.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

property scale_coefficient: Tensor

The Mob’s scale along its own right, up and forward axes, shape (*, 3).

Derived from basis as the norm of each of its rows, so (1, 1, 1) is unscaled. Assigning to this resizes the Mob without rotating it, animated over the current context’s runtime (1 second by default); scale() and set_scale() are the usual way to do that. Note that scale is a method (scale()), not an attribute – assigning to it raises.

set(**kwargs)[source]

Set several animatable attributes at once, as one animation.

The attributes change together rather than one after another, which is what you want for a single visual beat: mob.set(location=RIGHT, color=BLUE) slides and recolors in the same second, where two separate statements would take two seconds inside a Seq.

Animation

Recorded as an animation: all the writes go into one Sync spanning the current context’s runtime (1 second by default). Changes propagate to descendants; use set_non_recursive() if they should not.

Parameters:

**kwargs – Animatable attribute names and their target values, e.g. location, color, opacity, glow, scale_coefficient.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

Raises:

AttributeError – If a name is not an animatable attribute of this Mob. The message lists the ones that are.

Examples

Move a square to the right and change its color to blue:

Example: Example1MobSet

from algan import *

mob = Square().spawn()
mob.set(location=ORIGIN+RIGHT, color=BLUE)

Scene.save_video()
set_animated_attribute(attr, value, recursive=True)[source]

Animate one animatable attribute to a new value, by name.

The by-name equivalent of assigning to the attribute; useful when the attribute is chosen at runtime. To set several at once, use set(). Attributes whose write is more than a row write – derived ones (scale_coefficient, Circle.radius, stroke_color) and basis, which carries the subtree’s locations with it – are handed to their property setter, so every name behaves exactly as the assignment would.

Animation

Recorded as an animation: the attribute interpolates from its current value to value over the current context’s runtime (1 second by default).

Parameters:
  • attr (str) – Name of the animatable attribute, e.g. "location", "color", "opacity".

  • value – Target value. Must be broadcastable against the attribute’s current shape.

  • recursive (bool) – Whether the change propagates to descendants. Defaults to True.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

set_location(location, recursive=True)[source]

Set the Mob’s location, with control over whether children follow.

Same as move_to() without the arc option; the reason to reach for this one is recursive=False.

Animation

Recorded as an animation over the current context’s runtime (1 second by default).

Parameters:
  • location (Tensor) – The target location, shape (*, 3).

  • recursive (bool) – Whether children move along, keeping their offsets from this Mob. Defaults to True; False moves only this Mob, leaving its children behind.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

set_non_recursive(**kwargs)[source]

Set attributes on this Mob only, leaving its children untouched.

The non-propagating counterpart of set(). Use it when a parent’s own value should change while its children keep theirs – for instance recoloring a Group’s frame without recoloring its contents.

Animation

Recorded as an animation: every attribute given moves to its new value together inside a Sync, over the current context’s runtime (1 second by default).

Parameters:

**kwargs – Animatable attribute names and their target values, e.g. mob.set_non_recursive(color=BLUE, opacity=0.5).

Returns:

This Mob, so calls can be chained.

Return type:

Mob

set_opacity_via_color(opacity)[source]

Fade the Mob by writing opacity into its color rather than its opacity.

Each descendant’s own color gets the given alpha, which fades parts that carry their own colors without a parent-level opacity write flattening them. Prefer setting opacity for ordinary fades; this exists for composites where per-part color must be preserved.

Animation

Recorded as an animation. All descendants fade together inside a Sync, over the current context’s runtime (1 second by default).

Parameters:

opacity (float | Tensor) – Target alpha, 0 for fully transparent to 1 for fully opaque.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

set_scale(scale, recursive=True)[source]

Set the Mob’s absolute scale, ignoring its current size.

set_scale(1) returns the Mob to the size it was built at, whatever scaling has happened since. For a relative change, use scale().

Animation

Recorded as an animation over the current context’s runtime (1 second by default).

Parameters:
  • scale (float | Tensor) – Target scale, where 1 is the Mob’s construction size. A tensor of shape (*, 3) sets the Mob’s right, up and forward axes separately.

  • recursive (bool) – Whether descendants are scaled too. Defaults to True.

Returns:

This Mob, so calls can be chained.

Return type:

Mob

spawn(animate=True)

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:

Animatable

See also

despawn()

Remove the Mob from the video again.

two_sided = True

Whether this Mob’s geometry should be lit from whichever side the ray arrives on. True (the default) is for geometry with no meaningful outside – a 2-D shape, Text, a parametric Surface, an imported mesh whose winding nobody has checked – where a back-facing hit is shaded with its normal flipped toward the viewer, so the surface is lit from behind instead of coming out black.

The built-in solids set it False: their normals face out (see tests/unit_tests/test_normal_orientation.py), so a back-facing hit is genuinely the inside of the solid and is shaded as such. That is what stops a half-transparent solid’s far shell from being lit like a second front shell – the bright and dark “planes” through a fading Octahedron. Set it True on an instance to get the old two-sided lighting back (an open Cone you want lit inside, say); it must be set before the Mob is spawned, since the render primitive reads it once.

wave_color(color=None, wave_length=2, reverse=False, direction=None, lag_duration=1, samples_per_wave=12, refine_resolution=True, restore_resolution=True, **kwargs)[source]

Send a color pulse travelling across the Mob.

Every renderable part of the Mob pulses, but each one starts a little later than the part behind it, so the color sweeps across the shape instead of flashing all at once. Parts are ordered by their position along direction.

The color is carried by the Mob’s vertices, so a Mob sampled more coarsely than the wave is wide would show the pulse as a few flat facets – a Surface shaped like a flat sheet has vertices only at its corners, and a filled BezierCircuitCubic has a single color sample by default. Such Mobs are re-sampled finely enough to draw the wave and, by default, dropped back to their original resolution once the block containing the wave is over; see samples_per_wave and restore_resolution.

Animation

Recorded as an animation. The total runtime is lag_duration plus one part’s pulse, so it is set by these parameters rather than by the current context’s runtime. Re-sampling a part is a topology change, so it splits that Mob’s history the way detach_history() does, at the start of the wave and, when restore_resolution is True, again when the enclosing block ends. The split is invisible, but it is why the resolution only drops back at the end of the block rather than at the end of the wave.

Parameters:
  • color (Tensor) – Color for the wave to pulse to. Defaults to None, which pulses only opacity (pass one through **kwargs).

  • wave_length (float) – How spread out the wave is: each part’s own pulse lasts wave_length / lag_duration seconds, so smaller values give a tighter, more sharply defined band. Defaults to 2.

  • reverse (bool) – Whether the wave travels the opposite way along direction. Defaults to False.

  • direction (Tensor | None) – Direction the wave travels, shape (*, 3). Defaults to None, meaning the Mob’s own upward direction (bottom to top).

  • lag_duration – Seconds between the first part starting its pulse and the last one starting theirs. Defaults to 1.

  • samples_per_wave (int | None) – How many color samples to fit across the width of the travelling band. Parts already sampled at least this finely along direction are left alone; coarser ones are temporarily refined. Defaults to 12 – a pulse is two straight ramps, which color interpolation reproduces exactly, so this only has to round off the peak between them and raising it buys geometry rather than smoothness. Pass None to leave every part’s resolution exactly as it is.

  • refine_resolution (bool) – Whether parts sampled too coarsely to show the wave may be refined at all. Defaults to True. False leaves every part exactly as authored, however coarse – the explicit form of samples_per_wave=None. Worth setting for small on-screen mobs: the refinement is judged in world units relative to the mob’s own extent, never in pixels, so a mob a few dozen pixels wide is refined as heavily as a full-screen one.

  • restore_resolution (bool) – Whether refined color grids return to their original resolution when the enclosing animation block ends. Defaults to True. Set to False when a newly spawned object must retain one stable topology throughout and after its materialization wave.

  • **kwargs – Passed to pulse_color() for each part – notably opacity and new_color. new_color may also be a callable receiving the primitive part being pulsed; this lets a composite settle to each part’s own target color after one shared wave.

Returns:

This Mob, so calls can be chained.

Return type:

Mob