Animation
Sprite animations and their player, animation assets, Animator keyframe clips, tweens, easing curves, state machines and skeletal animation.
Files: animation.odin, animation_player.odin, animation_sets.odin, animator.odin, tween.odin, easing.odin, state_machine.odin, skeleton.odin, dragonbones.odin.
File overviews
Section titled “File overviews”animation_sets.odin
Section titled “animation_sets.odin”Animation assets: a sheet and named animations that AnimatedSprite nodes share, so one set of animations (a hero’s idle, run, jump) is made once and used anywhere.
- Files: an
.anim.xmlfile (asset kind “Animation”:ParseAnimationSet, its format there), or an Aseprite file, read as one (AnimationSet_FromAseprite): its frames laid out on a sheet (Aseprite_SheetPixels; the texture is the file’s path plus ASEPRITE_SHEET_SUFFIX, which the resource manager turns into that sheet), one animation per tag (its frames, each frame’s duration, its direction, its repeats; a tag that doesn’t say how often loops, as in Aseprite), or, without tags, one “default” animation of every frame. - Scene files: an AnimatedSprite’s
animations="assets/hero.aseprite"plays the set instead of its own sheet and animations; itsautoplay(when set) picks the first one. - Code:
AnimatedSprite_UseAnimations(sprite, ANIMATION_HERO)switches a sprite to a set. Game_LoadAnimationSetreads each file once (Game.animationSets, in the game’s arena); editors fill that map with their in-memory sets before building, as they do components.
animator.odin
Section titled “animator.odin”Animator nodes: keyframe animation of any node’s properties (Godot’s AnimationPlayer). An
Animator holds clips (“intro”, “open”, “hit”); a clip has a length and tracks; a track
animates one property of one node through keys (a time and a value). Between two keys the
value moves along the first key’s easing curve (EaseType), or holds until the next key on a
step track. Uses: cutscenes, doors and platforms that move, UI that slides in, a hit flash,
a coin’s bob and spin.
<node kind="Animator" name="Anim" autoplay="bob"> <clip name="bob" length="1" loop="true"> <track node="Coin" property="position.y"> <key time="0" value="0" ease="InOutSine"/> <key time="0.5" value="-6" ease="InOutSine"/> <key time="1" value="0"/> </track> <track property="event"><key time="0.5" value="top"/></track> </clip></node>- Which node: a track’s
nodeis a path from the Animator’s parent (Node_FindPathfrom there: “Coin” is a sibling, “” or “.” the parent itself, “Coin/Shine” a child of it, “/World” from the top level). Put the Animator inside what it animates. - Properties (
ANIMATOR_PROPERTIES):position(a UI control’s offset from its anchor),position.x,position.y,rotation,scale,scale.x,scale.y,tint,opacity(the tint’s alpha, 0 to 1),visible,zIndex; an AnimatedSprite’sanimation(plays it by name); a Label’stextandcolor; a script’s exported field,script.<field>(numbers, vectors and colors move, the rest step). Values are text as in scene files:"12","10, -4","#ff8000","true". - Events: a track with the property
event(itsnodeunused) fires the Animator’sonEventwith the key’s value as each of its keys passes: listen to it in the inspector to call a script’s procedure at that moment (a footstep sound, a camera shake, a spawned enemy). - Playing:
autoplaystarts a clip when the scene starts; from codeAnimator_Play,Animator_Stop,Animator_Pause,Animator_Seek,speed. A clip that doesn’t loop stops at its end and firesonFinished(data: its name). The Animator follows its process mode like any node (a paused scene pauses it). - Order: an Animator sets values in its update, so a target updated after it (its own script) can still change them that frame.
- Clips can be made from code too:
Animator_SetClipswithAnimatorSettingsdata.
state_machine.odin
Section titled “state_machine.odin”State machines: a StateMachine node keeps one of a set of states (idle, run, jump, attack, hurt) and moves between them by transitions whose conditions read parameters your scripts set (a speed, whether it’s on the ground, a “jump” trigger). Each state can play an animation of an AnimatedSprite, so a character’s animation follows what it’s doing without code picking animations.
<node kind="StateMachine" name="Brain" start="idle"> <param name="speed" type="Float"/> <param name="grounded" type="Bool" value="true"/> <param name="jump" type="Trigger"/> <state name="idle" animation="idle"/> <state name="run" animation="run"/> <state name="jump" animation="jump"/> <transition from="idle" to="run" when="speed > 10"/> <transition from="run" to="idle" when="speed <= 10"/> <transition from="*" to="jump" when="jump"/> <transition from="jump" to="idle" when="grounded" after="0.2"/></node>- Parameters (
StateMachineParam): Float (a number), Bool (true or false) and Trigger (set, then cleared when a transition uses it). Scripts set them:StateMachine_SetFloat,StateMachine_SetBool,StateMachine_SetTrigger. - Transitions (
StateMachineTransition): from a state (or*: from any other state) to another, when its condition holds: clauses joined byand, eachname(a Bool that’s true, a Trigger that’s set),!name, orname <op> numberwith ==, !=, <, <=, >, >= (Bools compare as 1 and 0).after: not before that many seconds in the state;onFinished: only once the state’s animation ended (a non-looping one). They’re checked in order every update; the first that holds is taken (at most one per update). - Animations: a state’s
animationplays (from its start) on thetargetAnimatedSprite (a path from the StateMachine: “” its parent) when the state is entered. - Events:
onStateEnteredandonStateExited(data: the state’s name). Listen to them to do things on entering a state (a sound when attacking, damage when hurt). - Code:
StateMachine_Current,StateMachine_Is,StateMachine_TimeInState,StateMachine_Travel(go to a state now).
skeleton.odin
Section titled “skeleton.odin”Skeletal animation: bones, skinned meshes and inverse kinematics.
- Bone2D nodes are bones: a node like any other (position, rotation, scale relative to its
parent, so a bone’s children follow it), pointing along its local x axis for
lengthpixels. A tree of them under a Skeleton2D node is a character’s skeleton. Sprites under a bone move with it rigidly (a cut-out character); the Animator and the Timeline key bones’ rotation, position and scale like any node’s. - SkinnedMesh nodes bend one picture over several bones: a mesh of triangles over the
picture (
MeshData: vertices in the node’s space, the picture’s pixels under them, up to four weighted bones per vertex). The pose the scene file has is the rest pose: when the mesh is built, each bone’s place relative to the mesh is remembered (SkinnedMesh_Bind); every draw moves each vertex by its bones’ moves since, blended by their weights (linear blend skinning), and draws the triangles through the node’s transform. - IKChain nodes aim a chain of bones at a target (inverse kinematics: an arm reaching for a
point, a leg planted on the ground):
tipis the last bone of the chain,lengthhow many bones up from it move,targetthe node to reach. Two bones are solved exactly (the elbow or knee bending thebendPositiveway); longer chains with cyclic coordinate descent. Chains are solved after the scene’s nodes and tweens update (the Animator’s keys first, then IK), in the order they were made.
Scene files (format 13):
<node kind="Skeleton2D" name="Hero"> <node kind="Bone2D" name="Hip" boneLength="40"> <node kind="Bone2D" name="Thigh" rotation="90" boneLength="50"/> </node> <node kind="SkinnedMesh" name="Body" texture="assets/hero.png"> <mesh vertices="0,0 10,0 ..." uvs="0,0 10,0 ..." triangles="0,1,2 ..." bones="../Hip,../Hip/Thigh" weights="0:1;0:0.5 1:0.5;..."/> </node> <node kind="IKChain" name="LegIK" ikTip="../Hip/Thigh" ikLength="2" ikTarget="../Foot"/></node>DragonBones files are converted into these nodes (dragonbones.odin).
dragonbones.odin
Section titled “dragonbones.odin”DragonBones files (dragonbones.github.io, DragonBones Pro’s JSON export, format 5.x) converted into the engine’s own nodes (skeleton.odin), so a character made there plays like one made in the editor:
- the armature (
<name>_ske.json’s first one) becomes a Skeleton2D, its bones Bone2D nodes (position, rotation, scale and length as set up); - each slot’s display becomes a Sprite on its bone (an image) or a SkinnedMesh (a mesh:
its vertices, picture coordinates, triangles and bone weights), drawn in the slots’ order
(
zIndex); - the texture atlas (
<name>_tex.jsonand its picture) becomes an atlas (atlas.odin) the sprites and meshes draw regions of; - the animations become an Animator’s clips: each bone’s translate, rotate and scale frames as position, rotation and scale tracks (the setup pose plus the frame’s offset), looping when they play forever.
DragonBones_Convert does it in memory; editors write the result as a component and an atlas
asset (the Crossfire Editor’s import of a _ske.json).
Not converted (each reported in the warnings): slots switching displays or colors over time,
FFD (mesh vertex) animations, skins other than the first, nested armatures, bounding boxes,
IK constraints (add IKChain nodes), skewed bones (only rotation), rotated atlas regions, and
curve easings (they play linearly; tweenEasing null steps).
AnimationPlayMode
Section titled “AnimationPlayMode”AnimationPlayMode :: enum { // startFrame -> endFrame Forward, // endFrame -> startFrame Reverse, // startFrame -> endFrame -> startFrame. One full there-and-back counts as one loop PingPong, // endFrame -> startFrame -> endFrame (Aseprite's "Ping-pong Reverse") PingPongReverse,}How an animation steps through its frames.
enum. Source: animation.odin:11
Animation
Section titled “Animation”Animation :: struct { // Name the AnimationPlayer plays it by (owned, allocated with `allocator`) name: string, // First source frame played, inclusive startFrame: int, // Last source frame played, inclusive endFrame: int, // Frames per second. 0 or less holds the current frame fps: f32, // Restart after the last frame instead of ending loop: bool, // Times it plays before it ends, when it doesn't loop (0 or 1: once; Aseprite's tag repeats) repeat: int, // How it steps through its frames playMode: AnimationPlayMode, // Seconds each frame shows (relative frames: 0 is startFrame), overriding `fps` for the frames // it covers (Aseprite frames each have their own duration). Owned, with `allocator` durations: []f32, // Each frame's events, comma-separated ("" for none), sent by its player's `onFrameEvent` when // the frame shows (relative frames; owned, with `allocator`) events: []string,
// Number of frames this animation plays: endFrame - startFrame + 1 totalFrames: proc(animation: ^Animation) -> int, // Number of frames available in the source (sheet cells, textures) sourceFrameCount: proc(animation: ^Animation) -> int, // Native pixel size of a source frame frameSize: proc(animation: ^Animation, frame: int) -> [2]f32, // Draws a source frame into dest (world coordinates, camera aware) drawFrame: proc(animation: ^Animation, renderer: ^sdl.Renderer, frame: int, dest: sdl.FRect, rotation: f32, tint: sdl.Color, flip: sdl.FlipMode),
// Allocator the animation and its data were created with; used to free them allocator: mem.Allocator, // Frees subtype data. Called by Animation_Destroy destroyData: proc(animation: ^Animation),}Base type of every animation. Specific animation types embed it with using:
MyAnimation :: struct { using animation: Animation, ... // the frames' source data}and fill in the procedure fields, which is how the AnimationPlayer draws any animation type without knowing what it is. Use the Create* procedures rather than building one by hand.
Frames are numbered by the animation’s source (sprite sheet cell or texture index).
startFrame..endFrame (both inclusive) selects which of them this animation plays, so one
sprite sheet can hold several animations.
struct. Source: animation.odin:37
SpriteSheetAnimation
Section titled “SpriteSheetAnimation”SpriteSheetAnimation :: struct { // The animation part: name, frame range, fps, procedures using animation: Animation, // The sprite sheet (not owned: the resource manager's, usually) texture: ^sdl.Texture, // Number of cells across columns: int, // Number of cells down rows: int, // Pixels around the outside of the grid margin: f32, // Pixels between neighboring cells spacing: f32,}An animation whose frames are cells of one texture, laid out on a grid.
Cells are numbered left to right, then top to bottom, starting at 0:
+---+---+---+| 0 | 1 | 2 |+---+---+---+| 3 | 4 | 5 |+---+---+---+struct. Source: animation.odin:175
FrameAnimation
Section titled “FrameAnimation”FrameAnimation :: struct { // The animation part: name, frame range, fps, procedures using animation: Animation, // The frame textures, in order (the slice is owned; the textures aren't) frames: []^sdl.Texture,}An animation where every frame is a separate texture. Frames are numbered by their
position in frames, starting at 0.
struct. Source: animation.odin:316
AnimationPlayer
Section titled “AnimationPlayer”AnimationPlayer :: struct { // The animations it owns, by the index `AnimationPlayer_Add` returned animations: [dynamic]^Animation, // Animation name -> index in `animations` names: map[string]int,
// Index of the current animation, -1 if none current: int, // Index of the animation that was current before the last change, -1 if none previous: int, // Current frame, relative to the current animation's startFrame frame: int, // True while frames are advancing playing: bool, // True after a non-looping animation reached its end finished: bool, // Playback speed multiplier. 1 is normal, 2 double speed, 0 frozen speed: f32,
// Seconds spent on the current frame elapsed: f32, // +1 or -1: direction frames are currently moving (PingPong flips it) direction: int, // Times the current animation has played through (for its `repeat`) cycles: int,
// data: int, the new relative frame. Also sent when an animation starts on its first frame onFrameChanged: EventSubject `event:"The animation's frame changed (data: the frame)" data:"frame := data.(int)"`, // data: int, index of the new animation (the old one is in `previous`) onAnimationChanged: EventSubject `event:"Another animation plays (data: its index)" data:"index := data.(int)"`, // data: int, index of the animation that started (or restarted) onAnimationStarted: EventSubject `event:"An animation started or restarted (data: its index)" data:"index := data.(int)"`, // data: int, index of the animation. Sent when a non-looping animation finishes onAnimationEnded: EventSubject `event:"A non-looping animation finished (data: its index)" data:"index := data.(int)"`, // data: int, index of the animation. Sent each time a looping animation wraps around onAnimationLooped: EventSubject `event:"A looping animation wrapped around (data: its index)" data:"index := data.(int)"`, // data: int, index of the animation. Sent by AnimationPlayer_Stop onAnimationStopped: EventSubject `event:"The animation was stopped (data: its index)" data:"index := data.(int)"`, // data: string, an event of the frame that shows (one notification per event; Aseprite cels' // text or `event` property: `Animation.events`). Valid during the notification onFrameEvent: EventSubject `event:"A frame with an event shows (data: the event's name)" data:"name := data.(string)"`,
// Allocator of its lists and event listeners (`AnimationPlayer_Init`) allocator: mem.Allocator,}Holds a set of animations, plays one at a time and draws its current frame.
The player is a plain struct, not a Node: embed it in the node that uses it, call
AnimationPlayer_Update from the node’s update and AnimationPlayer_Draw from its draw.
Animations are referenced by name or by the index AnimationPlayer_Add returned. Frame
numbers reported by the player (events, frame) are relative to the playing animation:
0 is its startFrame, totalFrames() - 1 its endFrame.
Events: subscribe with player.onFrameChanged->subscribe(callback, userData). Every
event’s source is the ^AnimationPlayer; data is described on each event below.
Example
Enemy :: struct { using node: e.Node, pos: [2]f32, anim: e.AnimationPlayer,}
CreateEnemy :: proc(scene: ^e.Scene) -> ^Enemy { enemy := e.CreateNode(scene, Enemy) enemy.update = Enemy_update enemy.draw = Enemy_draw
rm := &scene.game.resourceManager allocator := e.Node_GetAllocator(enemy) // Animations and listeners are freed with the enemy
e.AnimationPlayer_Init(&enemy.anim, allocator) sheet := rm->loadTexture("enemy.png") // 6x1 grid e.AnimationPlayer_Add(&enemy.anim, e.CreateSpriteSheetAnimation("idle", sheet, 6, 1, fps = 6, loop = true, endFrame = 3, allocator = allocator)) e.AnimationPlayer_Add(&enemy.anim, e.CreateSpriteSheetAnimation("die", sheet, 6, 1, fps = 10, startFrame = 4, allocator = allocator))
// Remove the enemy once the death animation finishes. Its memory, including this // player, its animations and listeners, is freed at the start of the next update enemy.anim.onAnimationEnded->subscribe(proc(event: ^e.EventSubject, source: rawptr, data: e.EventData, userData: rawptr) { player := cast(^e.AnimationPlayer)source if e.AnimationPlayer_CurrentName(player) == "die" { enemy := cast(^Enemy)userData enemy.scene->removeNode(enemy.id) } }, enemy)
e.AnimationPlayer_Play(&enemy.anim, "idle") return enemy}
Enemy_update :: proc(node: ^e.Node, events: []sdl.Event, deltaTime: f64) { enemy := cast(^Enemy)node e.AnimationPlayer_Update(&enemy.anim, deltaTime)}
Enemy_draw :: proc(node: ^e.Node, renderer: ^sdl.Renderer) { enemy := cast(^Enemy)node size := e.AnimationPlayer_FrameSize(&enemy.anim) e.AnimationPlayer_Draw(&enemy.anim, renderer, {enemy.pos.x, enemy.pos.y, size.x, size.y})}struct. Source: animation_player.odin:66
AnimatorValueKind
Section titled “AnimatorValueKind”AnimatorValueKind :: enum { // A number: moves smoothly Float, // Two numbers ("x, y"): move smoothly Vector, // A color (`#rrggbb` or `#rrggbbaa`): moves smoothly, channel by channel Color, // true or false: steps Bool, // Text (an animation's name, a label's text, an enum's value): steps Text,}The kind of value a property holds, which says how keys move between each other
enum. Source: animator.odin:52
AnimatorProperty
Section titled “AnimatorProperty”AnimatorProperty :: struct { // Its name in scene files ("position.x") name: string, // The value it holds kind: AnimatorValueKind, // What tools show ("Position X") label: string, // The node type it needs (nil: any node). A type embedding it counts (`typeEmbeds`) type: typeid,}A property tracks can animate (ANIMATOR_PROPERTIES)
struct. Source: animator.odin:66
AnimatorKeyData
Section titled “AnimatorKeyData”AnimatorKeyData :: struct { // Seconds from the clip's start time: f32, // The value, as text ("12", "10, -4", "#ff8000", "true", an event's name) value: string, // The curve from this key to the next (Linear when absent) ease: EaseType,}A key in a scene file or in code (AnimatorTrackData.keys)
struct. Source: animator.odin:112
AnimatorTrackData
Section titled “AnimatorTrackData”AnimatorTrackData :: struct { // The animated node: a path from the Animator's parent ("" for the parent; unused by events) node: string, // The property (`ANIMATOR_PROPERTIES`, "script.<field>" or "event") property: string, // Values hold until the next key instead of moving (Bool and Text values always do) step: bool, // Its keys, in time order (`AnimatorSettings_Sort` sorts them) keys: [dynamic]AnimatorKeyData,}A track in a scene file or in code (AnimatorClipData.tracks)
struct. Source: animator.odin:122
AnimatorClipData
Section titled “AnimatorClipData”AnimatorClipData :: struct { // Its name (`Animator_Play`) name: string, // Seconds; keys past it never play length: f32, // Starts again at its end (else it stops there and fires `onFinished`) loop: bool, // Its tracks tracks: [dynamic]AnimatorTrackData,}A clip in a scene file or in code (AnimatorSettings.clips)
struct. Source: animator.odin:134
AnimatorSettings
Section titled “AnimatorSettings”AnimatorSettings :: struct { // Its clips clips: [dynamic]AnimatorClipData, // The clip it plays when the scene starts ("": none) autoplay: string, // How fast clips play (1: as made; 0 holds them) speed: f32,}An Animator’s settings from a scene file (SceneNodeData.animator): its clips, the one it starts
with, its speed. Owned data: free it with AnimatorSettings_Destroy.
struct. Source: animator.odin:149
AnimatorKey
Section titled “AnimatorKey”AnimatorKey :: struct { // Seconds from the clip's start time: f32, // The value (the track's kind) value: AnimatorValue, // The curve to the next key ease: EaseType,}A key ready to play: its value parsed
struct. Source: animator.odin:162
AnimatorValue
Section titled “AnimatorValue”AnimatorValue :: union { f32, [2]f32, sdl.Color, bool, string,}A parsed key value
union. Source: animator.odin:172
AnimatorTrack
Section titled “AnimatorTrack”AnimatorTrack :: struct { // The path from the Animator's parent path: string, // The property property: string, // The value's kind kind: AnimatorValueKind, // Values hold between keys step: bool, // The data's `step` (Bool and Text values step whatever it says) stepSet: bool, // Fires `onEvent` instead of setting a value event: bool, // Its keys in time order keys: []AnimatorKey, // The node found for the path, and its id (checked before each use: it may be gone) target: ^Node, targetId: EntityId, // The key whose value was set last by a stepping track (-2: none yet), so text and bools are // set only when they change applied: int,}A track ready to play (in the Animator’s arena)
struct. Source: animator.odin:181
AnimatorClip
Section titled “AnimatorClip”AnimatorClip :: struct { // Its name name: string, // Seconds length: f32, // Starts again at its end loop: bool, // Its tracks tracks: []AnimatorTrack,}A clip ready to play (in the Animator’s arena)
struct. Source: animator.odin:205
Animator
Section titled “Animator”Animator :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Its clips (node arena) clips: []AnimatorClip, // The clip playing or paused (-1: none) current: int, // Seconds into the current clip time: f32, // The clip is moving (false: stopped or paused) playing: bool, // How fast clips play (1: as made; 0 holds) speed: f32, // The clip to start when the scene starts ("": none; node arena) autoplay: string, // Whether autoplay has run started: bool, // A clip that doesn't loop reached its end onFinished: EventSubject `event:"A clip that doesn't loop reached its end (data: its name)" data:"clip := data.(string)"`, // An event key passed onEvent: EventSubject `event:"An event key of the playing clip passed (data: the key's value)" data:"name := data.(string)"`,}A node playing keyframe animations of other nodes’ properties: see the file’s overview. Made by
scene files (kind “Animator”) or CreateAnimator.
struct. Source: animator.odin:220
Tween :: struct { // The node it belongs to (nil: the scene's own, `Scene_CreateTween`) owner: ^Node, // The scene whose update runs it scene: ^Scene, // Its steps, in order (heap-allocated, freed with the tween) steps: [dynamic]TweenStep, // Index of the first step of the group running now current: int, // Seconds into the group running now elapsed: f32, // Times to play it again after the first (-1: forever) loops: int, // Multiplies its time (1 normal) speed: f32, // Set by Tween_Pause; it stays where it is paused: bool, // Finished or killed: freed at the next update done: bool, // The next step added runs together with the last one parallelNext: bool,}Tweens: values animated over time, step by step, with easing (easing.odin). A tween belongs to a
node: it runs while that node may process (Node_CanProcess: pausing stops it), at the game’s time
scale, and is killed when the node is removed, so it never writes into freed memory. Animate the
node’s own fields (or anything that lives as long as it does).
Steps run one after another; Tween_Parallel makes the next step run together with the previous
one. A value step starts from wherever the value is when the step begins (Tween_FromTo for a
set start).
Tweens are freed when they finish or are killed: making one per hit or per pickup is fine.
Example
// Given: coin: ^e.Node// A coin pops up and fades out, then goestween := e.Tween_Create(coin)e.Tween_To(tween, &coin.position, coin.position + {0, -24}, 0.4, .OutBack)e.Tween_Parallel(tween)e.Tween_To(tween, &coin.tint, sdl.Color{255, 255, 255, 0}, 0.4)e.Tween_Call(tween, proc(user: rawptr) { node := cast(^e.Node)user e.Scene_RemoveNode(node.scene, node.id)}, coin)struct. Source: tween.odin:30
TweenValue
Section titled “TweenValue”TweenValue :: union { ^f32, ^[2]f32, ^sdl.Color,}What a tween step changes
union. Source: tween.odin:54
TweenStep
Section titled “TweenStep”TweenStep :: struct { // The value it animates; nil for a delay or a callback target: TweenValue, // Its start and end (as up to 4 floats: f32, [2]f32 or a color's channels) from, to: [4]f32, // The start was given (Tween_FromTo); otherwise it's read when the step begins fromGiven: bool, // It has begun in the current play (reset each loop) started: bool, // Seconds it lasts (0 for a callback) duration: f32, // The curve from `from` to `to` (easing.odin) ease: EaseType, // Called when the step runs (a Tween_Call step) callback: proc(user: rawptr), // Passed to `callback` user: rawptr, // Runs together with the step before it parallel: bool,}One step of a tween
struct. Source: tween.odin:61
EaseType
Section titled “EaseType”EaseType :: enum { Linear, InQuad, OutQuad, InOutQuad, InCubic, OutCubic, InOutCubic, InSine, OutSine, InOutSine, InExpo, OutExpo, InOutExpo, InBack, OutBack, InOutBack, OutElastic, OutBounce,}Easing curves for animating a value over a fixed duration.
“In” curves start slow, “Out” curves end slow, “InOut” do both. Back curves overshoot
slightly past the ends, Elastic springs past the end and settles, Bounce bounces at the end.
See https://easings.net for a visual reference of each curve. Used by Ease, tweens and
camera pans.
enum. Source: easing.odin:13
StateMachineParamKind
Section titled “StateMachineParamKind”StateMachineParamKind :: enum { Float, Bool, // Set by code, cleared when a transition uses it Trigger,}What a parameter holds
enum. Source: state_machine.odin:46
StateMachineParam
Section titled “StateMachineParam”StateMachineParam :: struct { name: string, kind: StateMachineParamKind, // Its starting value as text ("0", "true") value: string,}A parameter in a scene file (StateMachineSettings.params)
struct. Source: state_machine.odin:54
StateMachineState
Section titled “StateMachineState”StateMachineState :: struct { name: string, // The target AnimatedSprite's animation it plays ("": none) animation: string, // Where editors draw it in the graph position: [2]f32,}A state in a scene file
struct. Source: state_machine.odin:62
StateMachineTransition
Section titled “StateMachineTransition”StateMachineTransition :: struct { // The state it leaves ("*": any other state) and the one it enters from, to: string, // Its condition ("": always), e.g. "speed > 10 and grounded" condition: string, // Seconds in the state before it can be taken (0: at once) after: f32, // Only once the state's animation ended onFinished: bool,}A transition in a scene file
struct. Source: state_machine.odin:71
StateMachineSettings
Section titled “StateMachineSettings”StateMachineSettings :: struct { // The state it starts in ("": the first) start: string, // The AnimatedSprite its states animate: a path from it ("": its parent) target: string, params: [dynamic]StateMachineParam, states: [dynamic]StateMachineState, transitions: [dynamic]StateMachineTransition,}A state machine’s settings (SceneNodeData.stateMachine). Owned: StateMachineSettings_Destroy.
struct. Source: state_machine.odin:85
StateMachine
Section titled “StateMachine”StateMachine :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Its states' names and animations (node arena) states: []StateMachineState, // Parameters' names, kinds and values (node arena) paramNames: []string, paramKinds: []StateMachineParamKind, values: []f32, transitions: []RuntimeTransition, // The current state (-1: before the first update) current: int, // Seconds in it timeInState: f32, // Its animation ended animationFinished: bool, // The start state's index, and the target's path (node arena) startIndex: int, targetPath: string, // The target AnimatedSprite, once found target: ^AnimatedSprite, targetId: EntityId, onStateEntered: EventSubject `event:"It entered a state (data: the state's name)" data:"state := data.(string)"`, onStateExited: EventSubject `event:"It left a state (data: the state's name)" data:"state := data.(string)"`,}A node moving between states: see the file’s overview
struct. Source: state_machine.odin:114
Bone2D
Section titled “Bone2D”Bone2D :: struct { using node: Node, // How long it is, in its own pixels (where its tip is: IK reaches with it; editors draw it) length: f32,}A bone: a node pointing along its x axis
struct. Source: skeleton.odin:46
Skeleton2D
Section titled “Skeleton2D”Skeleton2D :: struct { using node: Node,}The root of a skeleton: bones (and what they carry) are its descendants
struct. Source: skeleton.odin:53
VertexWeights
Section titled “VertexWeights”VertexWeights :: struct { bones: [4]i32, weights: [4]f32,}One vertex’s bones (indices into MeshData.bones, -1 unused) and weights (summing to 1)
struct. Source: skeleton.odin:58
MeshData
Section titled “MeshData”MeshData :: struct { // Each vertex in the node's space (the rest pose) vertices: [dynamic][2]f32, // Each vertex's place in the picture, in pixels (of the atlas region, when the texture is one) uvs: [dynamic][2]f32, // Three vertex indices per triangle triangles: [dynamic]i32, // The bones, as paths from the mesh node ("../Hip/Thigh") bones: [dynamic]string, // Each vertex's bones; none (or fewer than the vertices): those vertices don't move weights: [dynamic]VertexWeights,}A skinned mesh’s triangles over its picture and their bones (scene files’ <mesh>)
struct. Source: skeleton.odin:64
SkinnedMesh
Section titled “SkinnedMesh”SkinnedMesh :: struct { using node: Node, // The picture (and its part: an atlas region; zero for the whole) texture: ^sdl.Texture, region: sdl.FRect, mesh: MeshData, // Its bones found (`SkinnedMesh_Bind`): their ids, and where each was relative to the mesh then // (inverted) boneIds: [dynamic]EntityId, bind: [dynamic]Transform2D, bound: bool,}A picture bent over bones
struct. Source: skeleton.odin:78
IKSettings
Section titled “IKSettings”IKSettings :: struct { // Bones up from the tip that move (1: only the tip turns toward the target) length: int, // Two bones: which way the middle joint bends (true: clockwise, like a right arm's elbow) bendPositive: bool, // Whether the chain aims its bones (false leaves them as animated) enabled: bool,}An IK chain’s settings (scene files’ ikLength, ikBend, ikEnabled)
struct. Source: skeleton.odin:92
IKChain
Section titled “IKChain”IKChain :: struct { using node: Node, settings: IKSettings, // Paths from the IK node: the chain's last bone, and the node it reaches for (node arena) tip: string, target: string,}Aims a chain of bones at a target
struct. Source: skeleton.odin:106
DragonBonesResult
Section titled “DragonBonesResult”DragonBonesResult :: struct { // A component: the Skeleton2D root and everything under it (free with SceneData_Destroy) component: SceneData, // The atlas its sprites and meshes draw from (free with AtlasData_Destroy) atlas: AtlasData, // What wasn't converted (temp allocated) warnings: []string,}What DragonBones_Convert makes
struct. Source: dragonbones.odin:35
Procedures
Section titled “Procedures”Animation_TotalFrames
Section titled “Animation_TotalFrames”Animation_TotalFrames :: proc(animation: ^Animation) -> intNumber of frames an animation plays.
Inputs
- animation: Any animation
Returns
- endFrame - startFrame + 1
procedure. Source: animation.odin:83
Animation_FrameDuration
Section titled “Animation_FrameDuration”Animation_FrameDuration :: proc(animation: ^Animation, frame: int) -> f32How long a frame of an animation shows: its duration when the animation has one for it, else 1 / fps.
Inputs
- animation: Any animation
- frame: A frame relative to its startFrame
Returns
- Seconds (0: it holds, for an fps of 0 or less without a duration)
procedure. Source: animation.odin:98
Animation_SetDurations
Section titled “Animation_SetDurations”Animation_SetDurations :: proc(animation: ^Animation, durations: []f32)Sets how long each frame shows, overriding fps for those frames.
Inputs
- animation: Any animation
- durations: Seconds per frame, relative to its startFrame (copied; empty: back to fps)
Example
// Given: animation: ^e.Animatione.Animation_SetDurations(animation, {0.1, 0.1, 0.3})procedure. Source: animation.odin:114
Animation_SetEvents
Section titled “Animation_SetEvents”Animation_SetEvents :: proc(animation: ^Animation, events: []string)Sets each frame’s events, which the player sends with onFrameEvent as the frame shows.
Inputs
- animation: Any animation
- events: Per frame (relative to its startFrame), comma-separated names (“” for none); copied
Example
// Given: animation: ^e.Animatione.Animation_SetEvents(animation, {"", "step", "", "step,dust"})procedure. Source: animation.odin:134
Animation_Destroy
Section titled “Animation_Destroy”Animation_Destroy :: proc(animation: ^Animation)Frees an animation created by one of the Create* procedures. Animations added to an
AnimationPlayer are freed by AnimationPlayer_Destroy; don’t free them yourself.
Inputs
- animation: The animation to free
procedure. Source: animation.odin:150
CreateSpriteSheetAnimation
Section titled “CreateSpriteSheetAnimation”CreateSpriteSheetAnimation :: proc( name: string, texture: ^sdl.Texture, columns, rows: int, fps: f32, loop := false, startFrame := 0, endFrame := -1, playMode := AnimationPlayMode.Forward, margin: f32 = 0, spacing: f32 = 0, allocator := context.allocator,) -> ^SpriteSheetAnimationCreates an animation from a sprite sheet (texture atlas) divided into a grid.
Inputs
- name: Name used to play the animation from an AnimationPlayer
- texture: The sprite sheet
- columns: Number of cells across
- rows: Number of cells down
- fps: Frames per second
- loop: Restart after the last frame instead of ending
- startFrame: First cell played, inclusive
- endFrame: Last cell played, inclusive. -1 means the last cell of the sheet
- playMode: Forward, Reverse or PingPong
- margin: Pixels around the outside of the grid
- spacing: Pixels between neighboring cells
- allocator: Allocator for the animation. Use the owning node’s (
Node_GetAllocator) to free it with the node
Returns
- The new animation. Add it to a player with
AnimationPlayer_Add
Example
// A 4x2 sheet: walk is the top row, jump the bottom rowrm := &game.resourceManagersheet := rm->loadTexture("hero.png")walk := e.CreateSpriteSheetAnimation("walk", sheet, 4, 2, fps = 10, loop = true, startFrame = 0, endFrame = 3)jump := e.CreateSpriteSheetAnimation("jump", sheet, 4, 2, fps = 12, startFrame = 4, endFrame = 7)procedure. Source: animation.odin:217
SpriteSheetAnimation_FrameRect
Section titled “SpriteSheetAnimation_FrameRect”SpriteSheetAnimation_FrameRect :: proc(animation: ^SpriteSheetAnimation, frame: int) -> sdl.FRectPixel rectangle of a cell in a sprite sheet. Useful for drawing a single cell yourself.
Inputs
- animation: The sprite sheet animation
- frame: Cell index in the sheet
Returns
- The cell’s rectangle in texture pixels
procedure. Source: animation.odin:253
SpriteSheet_CellRect
Section titled “SpriteSheet_CellRect”SpriteSheet_CellRect :: proc(sheetSize: [2]f32, columns, rows: int, margin, spacing: f32, frame: int) -> sdl.FRectA cell’s rectangle in a sprite sheet of a given size, without an animation (editors use it for thumbnails). Cells are numbered left to right, top to bottom.
Inputs
- sheetSize: The texture’s size in pixels
- columns: Number of cells across
- rows: Number of cells down
- margin: Pixels around the grid
- spacing: Pixels between cells
- frame: The cell
Returns
- The cell’s rectangle in texture pixels
procedure. Source: animation.odin:280
CreateFrameAnimation
Section titled “CreateFrameAnimation”CreateFrameAnimation :: proc( name: string, frames: []^sdl.Texture, fps: f32, loop := false, startFrame := 0, endFrame := -1, playMode := AnimationPlayMode.Forward, allocator := context.allocator,) -> ^FrameAnimationCreates an animation from a list of textures, one per frame.
Inputs
- name: Name used to play the animation from an AnimationPlayer
- frames: The frame textures, in order. The list is copied
- fps: Frames per second
- loop: Restart after the last frame instead of ending
- startFrame: First frame played, inclusive
- endFrame: Last frame played, inclusive. -1 means the last texture
- playMode: Forward, Reverse or PingPong
- allocator: Allocator for the animation. Use the owning node’s (
Node_GetAllocator) to free it with the node
Returns
- The new animation. Add it to a player with
AnimationPlayer_Add
Example
rm := &game.resourceManagerblink := e.CreateFrameAnimation("blink", {rm->loadTexture("eye_open.png"), rm->loadTexture("eye_closed.png")}, fps = 4, loop = true)procedure. Source: animation.odin:343
CreateFrameAnimationFromFiles
Section titled “CreateFrameAnimationFromFiles”CreateFrameAnimationFromFiles :: proc( rm: ^ResourceManager, name: string, paths: []string, fps: f32, loop := false, startFrame := 0, endFrame := -1, playMode := AnimationPlayMode.Forward, allocator := context.allocator,) -> ^FrameAnimationCreates a FrameAnimation by loading each frame through the resource manager.
Inputs
- rm: Resource manager to load (and cache) the textures with
- name: Name used to play the animation from an AnimationPlayer
- paths: Image file paths, one per frame, in order
- fps: Frames per second
- loop: Restart after the last frame instead of ending
- startFrame: First frame played, inclusive
- endFrame: Last frame played, inclusive. -1 means the last texture
- playMode: Forward, Reverse or PingPong
- allocator: Allocator for the animation. Use the owning node’s (
Node_GetAllocator) to free it with the node
Returns
- The new animation
Example
rm := &game.resourceManagerlight := e.CreateFrameAnimationFromFiles(rm, "blink", {"light_off.png", "light_on.png"}, fps = 2, loop = true)procedure. Source: animation.odin:385
AnimationPlayer_Init
Section titled “AnimationPlayer_Init”AnimationPlayer_Init :: proc(player: ^AnimationPlayer, allocator := context.allocator)Prepares a player for use.
Inputs
- player: The player to initialize
- allocator: Allocator for the player’s lists and event listeners. Use the owning node’s
allocator (
Node_GetAllocator) so they are freed with the node
procedure. Source: animation_player.odin:120
AnimationPlayer_Destroy
Section titled “AnimationPlayer_Destroy”AnimationPlayer_Destroy :: proc(player: ^AnimationPlayer)Frees the player’s animations, lists and event listeners.
Not needed when the player and its animations use their node’s allocator
(Node_GetAllocator): everything, including event listeners, is freed with the node.
Inputs
- player: The player to free
procedure. Source: animation_player.odin:146
AnimationPlayer_Add
Section titled “AnimationPlayer_Add”AnimationPlayer_Add :: proc(player: ^AnimationPlayer, animation: ^Animation) -> intAdds an animation to the player, which takes ownership of it.
Inputs
- player: The player
- animation: Any animation type (SpriteSheetAnimation, FrameAnimation, …)
Returns
- The animation’s index, usable instead of its name. -1 (logged) if the name is already taken: the player then doesn’t own it, so free it yourself unless it uses a node’s allocator
Example
// Given: player: ^e.AnimationPlayer, sheet: ^sdl.Texturee.AnimationPlayer_Add(player, e.CreateSpriteSheetAnimation("run", sheet, 8, 1, fps = 12, loop = true))procedure. Source: animation_player.odin:176
AnimationPlayer_Play
Section titled “AnimationPlayer_Play”AnimationPlayer_Play :: proc{AnimationPlayer_PlayByName, AnimationPlayer_PlayByIndex}Starts playing an animation by name or index.
If that animation is already playing it keeps going unless restart is true, so it is safe
to call every frame (e.g. Play("run") while a movement key is held).
Sends onAnimationChanged (if it differs from the current one), onAnimationStarted and onFrameChanged for its first frame.
Inputs
- player: The player
- name: Which animation to play, by name (
AnimationPlayer_PlayByName; an unknown name is logged) - index: Or by the index
AnimationPlayer_Addreturned (AnimationPlayer_PlayByIndex) - restart: Restart from the first frame even if it is already playing
Returns
- false if no such animation exists
Example
// Given: player: ^e.AnimationPlayere.AnimationPlayer_Play(player, "thrust")e.AnimationPlayer_Play(player, 0, restart = true)procedure group. Source: animation_player.odin:210
AnimationPlayer_PlayByName
Section titled “AnimationPlayer_PlayByName”AnimationPlayer_PlayByName :: proc(player: ^AnimationPlayer, name: string, restart := false) -> boolAnimationPlayer_Play by the animation’s name
procedure. Source: animation_player.odin:213
AnimationPlayer_PlayByIndex
Section titled “AnimationPlayer_PlayByIndex”AnimationPlayer_PlayByIndex :: proc(player: ^AnimationPlayer, index: int, restart := false) -> boolAnimationPlayer_Play by the index AnimationPlayer_Add returned
procedure. Source: animation_player.odin:223
AnimationPlayer_Clear
Section titled “AnimationPlayer_Clear”AnimationPlayer_Clear :: proc(player: ^AnimationPlayer)Removes every animation (freeing them) and stops: nothing plays until animations are added again.
Inputs
- player: The player
procedure. Source: animation_player.odin:263
AnimationPlayer_Pause
Section titled “AnimationPlayer_Pause”AnimationPlayer_Pause :: proc(player: ^AnimationPlayer)Pauses playback on the current frame. Resume with AnimationPlayer_Resume.
Inputs
- player: The player
procedure. Source: animation_player.odin:283
AnimationPlayer_Resume
Section titled “AnimationPlayer_Resume”AnimationPlayer_Resume :: proc(player: ^AnimationPlayer)Continues a paused animation from its current frame. Does nothing if the animation finished.
Inputs
- player: The player
procedure. Source: animation_player.odin:293
AnimationPlayer_Stop
Section titled “AnimationPlayer_Stop”AnimationPlayer_Stop :: proc(player: ^AnimationPlayer)Stops playback and rewinds to the first frame of the current animation. Sends onAnimationStopped.
Inputs
- player: The player
procedure. Source: animation_player.odin:303
AnimationPlayer_SetFrame
Section titled “AnimationPlayer_SetFrame”AnimationPlayer_SetFrame :: proc(player: ^AnimationPlayer, frame: int)Jumps to a frame of the current animation without changing whether it is playing.
Inputs
- player: The player
- frame: Frame relative to the animation’s startFrame. Clamped to the animation’s frames
procedure. Source: animation_player.odin:327
AnimationPlayer_Update
Section titled “AnimationPlayer_Update”AnimationPlayer_Update :: proc(player: ^AnimationPlayer, deltaTime: f64)Advances the current animation. Call once per frame from the owning node’s update.
Inputs
- player: The player
- deltaTime: Seconds since the last frame
Example
// Given: player: ^e.AnimationPlayere.AnimationPlayer_Update(player, deltaTime)procedure. Source: animation_player.odin:348
AnimationPlayer_Draw
Section titled “AnimationPlayer_Draw”AnimationPlayer_Draw :: proc( player: ^AnimationPlayer, renderer: ^sdl.Renderer, dest: sdl.FRect, rotation: f32 = 0, tint := sdl.Color{255, 255, 255, 255}, flip := sdl.FlipMode.NONE,)Draws the current frame of the current animation. Camera aware, like DrawTexture.
Inputs
- player: The player
- renderer: The renderer to draw with
- dest: Where to draw, in world coordinates. Use
AnimationPlayer_FrameSizefor the native size - rotation: Degrees, clockwise around the center of
dest - tint: Multiplies the frame’s colors and alpha
- flip: Mirror horizontally and/or vertically, e.g. to face left
Example
// Given: player: ^e.AnimationPlayersize := e.AnimationPlayer_FrameSize(player)e.AnimationPlayer_Draw(player, renderer, {100, 100, size.x * 2, size.y * 2}, flip = .HORIZONTAL)procedure. Source: animation_player.odin:384
AnimationPlayer_FrameSize
Section titled “AnimationPlayer_FrameSize”AnimationPlayer_FrameSize :: proc(player: ^AnimationPlayer) -> [2]f32Native pixel size of the frame currently showing.
Inputs
- player: The player
Returns
- The frame’s width and height, or {0, 0} if nothing is playing
procedure. Source: animation_player.odin:406
AnimationPlayer_Get
Section titled “AnimationPlayer_Get”AnimationPlayer_Get :: proc{AnimationPlayer_GetByName, AnimationPlayer_GetByIndex}Looks up an animation by name or index.
Inputs
- player: The player
- name: Which animation, by name (
AnimationPlayer_GetByName) - index: Or by index (
AnimationPlayer_GetByIndex)
Returns
- The animation, or nil if there is none. Cast to the subtype to change type-specific settings
procedure group. Source: animation_player.odin:423
AnimationPlayer_GetByName
Section titled “AnimationPlayer_GetByName”AnimationPlayer_GetByName :: proc(player: ^AnimationPlayer, name: string) -> ^AnimationAnimationPlayer_Get by name
procedure. Source: animation_player.odin:426
AnimationPlayer_GetByIndex
Section titled “AnimationPlayer_GetByIndex”AnimationPlayer_GetByIndex :: proc(player: ^AnimationPlayer, index: int) -> ^AnimationAnimationPlayer_Get by index
procedure. Source: animation_player.odin:432
AnimationPlayer_IndexOf
Section titled “AnimationPlayer_IndexOf”AnimationPlayer_IndexOf :: proc(player: ^AnimationPlayer, name: string) -> (int, bool)Index of an animation by name.
Inputs
- player: The player
- name: The animation’s name
Returns
- The index and true, or -1 and false if there is no such animation
procedure. Source: animation_player.odin:447
AnimationPlayer_Current
Section titled “AnimationPlayer_Current”AnimationPlayer_Current :: proc(player: ^AnimationPlayer) -> ^AnimationThe current animation.
Inputs
- player: The player
Returns
- The animation, or nil if none has been played
procedure. Source: animation_player.odin:461
AnimationPlayer_CurrentName
Section titled “AnimationPlayer_CurrentName”AnimationPlayer_CurrentName :: proc(player: ^AnimationPlayer) -> stringName of the current animation.
Inputs
- player: The player
Returns
- The name (the animation’s string), or “” if none has been played
procedure. Source: animation_player.odin:474
AnimationPlayer_IsPlaying
Section titled “AnimationPlayer_IsPlaying”AnimationPlayer_IsPlaying :: proc(player: ^AnimationPlayer, name: string) -> boolWhether the named animation is the current one and is playing (not paused, stopped or finished).
Inputs
- player: The player
- name: The animation’s name
Returns
- true if it is playing
procedure. Source: animation_player.odin:489
AnimationSet_FromAseprite
Section titled “AnimationSet_FromAseprite”AnimationSet_FromAseprite :: proc(ase: ^Aseprite, path: string, allocator := context.allocator) -> AnimationSetDataAn Aseprite file as an animation set: every frame on a sheet, an animation per tag.
Inputs
- ase: The file
- path: Its path, relative to the project folder (the sheet’s texture is
path+ ASEPRITE_SHEET_SUFFIX) - allocator: For the set’s strings and lists
Returns
- The set (free it with
AnimationSetData_Destroy)
procedure. Source: animation_sets.odin:38
Game_LoadAnimationSet
Section titled “Game_LoadAnimationSet”Game_LoadAnimationSet :: proc(game: ^Game, path: string) -> (^AnimationSetData, bool)An animation asset’s set, read the first time and kept for the game’s life, in the game’s arena (sprites share it). A file that can’t be read is remembered too: it isn’t read again.
Inputs
- game: The game
- path: The
.anim.xmlor Aseprite file, relative to the project folder (Game.projectDir)
Returns
- The set (don’t free it), and false (logged) if it can’t be read
procedure. Source: animation_sets.odin:94
AnimatedSprite_SetAnimations
Section titled “AnimatedSprite_SetAnimations”AnimatedSprite_SetAnimations :: proc(sprite: ^AnimatedSprite, set: ^AnimationSetData, projectDir: string, autoplay := "") -> boolMakes a sprite play a set of animations: its animations become the set’s (its old ones go), on
the set’s sheet, and it plays autoplay (else the set’s own, else the first).
Inputs
- sprite: The AnimatedSprite
- set: The animations (
Game_LoadAnimationSet) - projectDir: The folder the set’s texture path is relative to
- autoplay: The animation to play (“”: the set’s choice)
Returns
- false (logged) if the set’s sheet can’t be loaded
procedure. Source: animation_sets.odin:131
AnimatedSprite_UseAnimations
Section titled “AnimatedSprite_UseAnimations”AnimatedSprite_UseAnimations :: proc(sprite: ^AnimatedSprite, asset: AnimationAsset, autoplay := "") -> boolSwitches an AnimatedSprite to an animation asset (an .anim.xml or Aseprite file), from a script.
Inputs
- sprite: The sprite
- asset: The animation asset (
ANIMATION_Xin scripts/assets.odin) - autoplay: The animation to play (“”: the asset’s choice)
Returns
- false (logged) if the asset can’t be read
Example
e.AnimatedSprite_UseAnimations(sprite, ANIMATION_HERO_ARMORED, "idle")procedure. Source: animation_sets.odin:170
Asset_Animations
Section titled “Asset_Animations”Asset_Animations :: proc(game: ^Game, asset: AnimationAsset) -> ^AnimationSetDataAn animation asset’s set (read once, kept by the game).
Inputs
- game: The game
- asset: The animation asset
Returns
- The set (the game’s), or nil (logged) if it can’t be read
procedure. Source: animation_sets.odin:188
CreateAnimator
Section titled “CreateAnimator”CreateAnimator :: proc(scene: ^Scene) -> ^AnimatorCreates an Animator node with no clips and adds it to the scene (at the start of the next
update). Give it clips with Animator_SetClips.
Inputs
- scene: The scene that owns it
Returns
- The Animator
Example
anim := e.CreateAnimator(scene)e.Node_AddChild(node, anim)procedure. Source: animator.odin:257
Animator_SetClips
Section titled “Animator_SetClips”Animator_SetClips :: proc(animator: ^Animator, settings: AnimatorSettings)Replaces an Animator’s clips with copies of these (parsed into its arena), and its autoplay clip and speed. A playing clip stops.
Inputs
- animator: The Animator
- settings: The clips (copied: the caller keeps them), autoplay and speed
Example
// Given: anim: ^e.Animator// Turns its parent once a second (the data is copied: temporary lists will do)track := e.AnimatorTrackData{property = "rotation", keys = make([dynamic]e.AnimatorKeyData, context.temp_allocator)}append(&track.keys, e.AnimatorKeyData{time = 0, value = "0"}, e.AnimatorKeyData{time = 1, value = "360"})clip := e.AnimatorClipData{name = "spin", length = 1, loop = true, tracks = make([dynamic]e.AnimatorTrackData, context.temp_allocator)}append(&clip.tracks, track)settings := e.AnimatorSettings{speed = 1, clips = make([dynamic]e.AnimatorClipData, context.temp_allocator)}append(&settings.clips, clip)e.Animator_SetClips(anim, settings)e.Animator_Play(anim, "spin")procedure. Source: animator.odin:287
Animator_Play
Section titled “Animator_Play”Animator_Play :: proc(animator: ^Animator, name: string, restart := false) -> boolPlays a clip from its start. The clip already playing goes on, and a paused one resumes, unless
restart. Event keys at time 0 fire.
Inputs
- animator: The Animator
- name: The clip’s name
- restart: Start again even when it’s the clip playing
Returns
- false when it has no clip of that name
Example
// Given: anim: ^e.Animatore.Animator_Play(anim, "open")procedure. Source: animator.odin:349
Animator_Stop
Section titled “Animator_Stop”Animator_Stop :: proc(animator: ^Animator, reset := false)Stops the current clip. Its values stay as they are, unless reset, which sets them to the
clip’s start.
Inputs
- animator: The Animator
- reset: Put the clip’s values back to its first keys
Example
// Given: anim: ^e.Animatore.Animator_Stop(anim, reset = true)procedure. Source: animator.odin:382
Animator_Pause
Section titled “Animator_Pause”Animator_Pause :: proc(animator: ^Animator, paused: bool)Pauses or resumes the current clip where it is.
Inputs
- animator: The Animator
- paused: true pauses, false resumes
Example
// Given: anim: ^e.Animatore.Animator_Pause(anim, true)procedure. Source: animator.odin:399
Animator_Seek
Section titled “Animator_Seek”Animator_Seek :: proc(animator: ^Animator, time: f32)Jumps the current clip to a time and sets its values there (no events fire).
Inputs
- animator: The Animator
- time: Seconds from the clip’s start (clamped to its length)
Example
// Given: anim: ^e.Animatore.Animator_Seek(anim, 0.5)procedure. Source: animator.odin:415
Animator_IsPlaying
Section titled “Animator_IsPlaying”Animator_IsPlaying :: proc(animator: ^Animator) -> boolWhether a clip is playing (not stopped, paused or finished).
Inputs
- animator: The Animator
Returns
- true while one plays
procedure. Source: animator.odin:431
Animator_CurrentClip
Section titled “Animator_CurrentClip”Animator_CurrentClip :: proc(animator: ^Animator) -> stringThe current clip’s name (playing, paused or finished; “” when none has played).
Inputs
- animator: The Animator
Returns
- Its name (the Animator’s)
procedure. Source: animator.odin:444
Animator_FindClip
Section titled “Animator_FindClip”Animator_FindClip :: proc(animator: ^Animator, name: string) -> intFinds a clip by name.
Inputs
- animator: The Animator
- name: The clip’s name
Returns
- Its index in
animator.clips, or -1
procedure. Source: animator.odin:458
Animator_Apply
Section titled “Animator_Apply”Animator_Apply :: proc(animator: ^Animator, clip: int, time: f32)Sets every track of a clip to its value at a time, without playing it or firing events: what an editor’s timeline shows while scrubbing.
Inputs
- animator: The Animator
- clip: The clip’s index
- time: Seconds from its start
procedure. Source: animator.odin:472
Animator_PropertyKind
Section titled “Animator_PropertyKind”Animator_PropertyKind :: proc(property: string) -> (AnimatorValueKind, bool)The kind of a built-in property’s value (ANIMATOR_PROPERTIES).
Inputs
- property: The property’s name
Returns
- Its kind, and false when it isn’t a built-in one (a script field, an event, or unknown)
procedure. Source: animator.odin:487
Animator_TypeHasProperty
Section titled “Animator_TypeHasProperty”Animator_TypeHasProperty :: proc(type: typeid, property: AnimatorProperty) -> boolWhether a node type has a property (a built-in one needing a type, like animation).
Inputs
- type: The node’s type (
node.type, or a kind’sSCENE_NODE_TYPES) - property: The property
Returns
- true when nodes of the type have it
procedure. Source: animator.odin:502
Animator_ScriptFieldKind
Section titled “Animator_ScriptFieldKind”Animator_ScriptFieldKind :: proc(type: ScriptFieldType) -> (AnimatorValueKind, bool)How a script field is animated: numbers, vectors and colors move, booleans step, and text, enums and asset handles step as text. Node fields can’t be animated.
Inputs
- type: The field’s type
Returns
- Its kind, and false for node fields
procedure. Source: animator.odin:516
Animator_ParseValue
Section titled “Animator_ParseValue”Animator_ParseValue :: proc(kind: AnimatorValueKind, text: string, allocator := context.allocator) -> (AnimatorValue, bool)Reads a key’s value of a kind from text.
Inputs
- kind: The value’s kind
- text: The text (“12”, “10, -4”, “#ff8000”, “true”)
- allocator: For text values
Returns
- The value, and false when the text isn’t one
procedure. Source: animator.odin:538
Animator_FormatValue
Section titled “Animator_FormatValue”Animator_FormatValue :: proc(value: AnimatorValue, allocator := context.allocator) -> stringWrites a value as key text (what Animator_ParseValue reads).
Inputs
- value: The value
- allocator: For the text
Returns
- Its text
procedure. Source: animator.odin:574
Animator_ReadProperty
Section titled “Animator_ReadProperty”Animator_ReadProperty :: proc(node: ^Node, property: string, allocator := context.allocator) -> (string, bool)A node’s current value of a property, as key text: what an editor records as a key. Script fields need the node’s script.
Inputs
- node: The node
- property: The property (
ANIMATOR_PROPERTIESor “script.<field>”) - allocator: For the text
Returns
- The text, and false when the node has no such property
procedure. Source: animator.odin:597
Node_WriteProperty
Section titled “Node_WriteProperty”Node_WriteProperty :: proc(node: ^Node, property: string, text: string) -> boolSets a node’s property from text: what tools that edit a running game use (the editor’s live
view). The properties are the Animator’s (ANIMATOR_PROPERTIES the node’s type has, and
“script.<field>” for its script’s exported fields).
Inputs
- node: The node
- property: The property (“position”, “script.speed”)
- text: The value as text (“10, 20”, “#ff8000”, “true”)
Returns
- false when the node has no such property or the text isn’t a value of it
Example
// Given: hero: ^e.Nodee.Node_WriteProperty(hero, "position", "100, 200")procedure. Source: animator.odin:620
Node_Properties
Section titled “Node_Properties”Node_Properties :: proc(node: ^Node, allocator := context.allocator) -> []stringThe properties a node has (as Node_WriteProperty and Animator_ReadProperty take them): the
built-in ones its type has, then its script’s fields (node fields left out).
Inputs
- node: The node
- allocator: For the list
Returns
- The property names
procedure. Source: animator.odin:647
AnimatorSettings_Sort
Section titled “AnimatorSettings_Sort”AnimatorSettings_Sort :: proc(settings: ^AnimatorSettings)Sorts every track’s keys by time (stable): call it after changing keys’ times.
Inputs
- settings: The settings
procedure. Source: animator.odin:673
AnimatorSettings_Clone
Section titled “AnimatorSettings_Clone”AnimatorSettings_Clone :: proc(settings: AnimatorSettings, allocator := context.allocator) -> AnimatorSettingsA deep copy of Animator settings.
Inputs
- settings: The settings to copy
- allocator: For the copy
Returns
- The copy (free it with
AnimatorSettings_Destroy)
procedure. Source: animator.odin:692
AnimatorSettings_Destroy
Section titled “AnimatorSettings_Destroy”AnimatorSettings_Destroy :: proc(settings: ^AnimatorSettings)Frees Animator settings (made by the parser or AnimatorSettings_Clone) and empties them.
Inputs
- settings: The settings
procedure. Source: animator.odin:715
AnimatorSettings_Equal
Section titled “AnimatorSettings_Equal”AnimatorSettings_Equal :: proc(a, b: AnimatorSettings) -> boolWhether two Animator settings are the same: every clip, track and key.
Inputs
- a, b: The settings
Returns
- true when equal
procedure. Source: animator.odin:740
AnimatorTrack_ValueAt
Section titled “AnimatorTrack_ValueAt”AnimatorTrack_ValueAt :: proc(track: ^AnimatorTrack, time: f32) -> (AnimatorValue, int)The value a track has at a time: the keys around it blended along the first one’s curve (or the key before it on stepping tracks).
Inputs
- track: The track (its keys in time order)
- time: Seconds from the clip’s start
Returns
- The value, and the index of the key at or before the time (-1 before the first: its value then)
procedure. Source: animator.odin:765
Tween_Create
Section titled “Tween_Create”Tween_Create :: proc(owner: ^Node) -> ^TweenMakes a tween owned by a node (in the node’s scene). Add steps to it right away; it starts on the scene’s next update.
Inputs
- owner: The node it belongs to: it runs while the node may process, and dies with it
Returns
- The tween (freed when it finishes or is killed; don’t keep the pointer past that)
Example
tween := e.Tween_Create(node)e.Tween_To(tween, &node.scale, [2]f32{1.2, 1.2}, 0.15, .OutQuad)e.Tween_To(tween, &node.scale, [2]f32{1, 1}, 0.15, .InQuad)procedure. Source: tween.odin:97
Scene_CreateTween
Section titled “Scene_CreateTween”Scene_CreateTween :: proc(scene: ^Scene) -> ^TweenMakes a tween that belongs to the scene itself (no node): it runs while the scene isn’t paused, and dies with the scene. Only animate values that live as long as the scene.
Inputs
- scene: The scene
Returns
- The tween (freed when it finishes or is killed; don’t keep the pointer past that)
procedure. Source: tween.odin:113
Tween_To
Section titled “Tween_To”Tween_To :: proc{Tween_ToF32, Tween_ToVector, Tween_ToColor}Adds a step that animates a value to to over duration seconds, from wherever it is when the
step begins.
Inputs
- tween: The tween
- target: The value: an f32, a [2]f32 (positions, scales) or an sdl.Color (tints)
- to: The value at the end
- duration: Seconds
- ease: The curve (easing.odin)
Returns
- The tween, to chain more steps
Example
// Given: tween: ^e.Tweene.Tween_To(tween, &node.position, node.position + {0, -40}, 0.5, .OutQuad)e.Tween_To(tween, &node.tint, sdl.Color{255, 255, 255, 0}, 0.3)procedure group. Source: tween.odin:147
Tween_ToF32
Section titled “Tween_ToF32”Tween_ToF32 :: proc(tween: ^Tween, target: ^f32, to: f32, duration: f32, ease := EaseType.Linear) -> ^TweenTween_To for an f32
procedure. Source: tween.odin:150
Tween_ToVector
Section titled “Tween_ToVector”Tween_ToVector :: proc(tween: ^Tween, target: ^[2]f32, to: [2]f32, duration: f32, ease := EaseType.Linear) -> ^TweenTween_To for a [2]f32 (positions, scales)
procedure. Source: tween.odin:155
Tween_ToColor
Section titled “Tween_ToColor”Tween_ToColor :: proc(tween: ^Tween, target: ^sdl.Color, to: sdl.Color, duration: f32, ease := EaseType.Linear) -> ^TweenTween_To for an sdl.Color (each channel animated, rounded to the nearest value)
procedure. Source: tween.odin:160
Tween_FromTo
Section titled “Tween_FromTo”Tween_FromTo :: proc{Tween_FromToF32, Tween_FromToVector, Tween_FromToColor}Like Tween_To, from a given start (the value jumps to from when the step begins, and again on
each loop).
Inputs
- tween: The tween
- target: The value: an f32, a [2]f32 (positions, scales) or an sdl.Color (tints)
- from: The value at the start
- to: The value at the end
- duration: Seconds
- ease: The curve (easing.odin)
Returns
- The tween, to chain more steps
Example
// Given: tween: ^e.Tweene.Tween_FromTo(tween, &node.tint, sdl.Color{255, 255, 255, 0}, sdl.Color{255, 255, 255, 255}, 0.5)procedure group. Source: tween.odin:183
Tween_FromToF32
Section titled “Tween_FromToF32”Tween_FromToF32 :: proc(tween: ^Tween, target: ^f32, from, to: f32, duration: f32, ease := EaseType.Linear) -> ^TweenTween_FromTo for an f32
procedure. Source: tween.odin:186
Tween_FromToVector
Section titled “Tween_FromToVector”Tween_FromToVector :: proc(tween: ^Tween, target: ^[2]f32, from, to: [2]f32, duration: f32, ease := EaseType.Linear) -> ^TweenTween_FromTo for a [2]f32 (positions, scales)
procedure. Source: tween.odin:193
Tween_FromToColor
Section titled “Tween_FromToColor”Tween_FromToColor :: proc(tween: ^Tween, target: ^sdl.Color, from, to: sdl.Color, duration: f32, ease := EaseType.Linear) -> ^TweenTween_FromTo for an sdl.Color
procedure. Source: tween.odin:200
Tween_Delay
Section titled “Tween_Delay”Tween_Delay :: proc(tween: ^Tween, seconds: f32) -> ^TweenAdds a pause before the next step.
Inputs
- tween: The tween
- seconds: Length of the pause (negative counts as 0)
Returns
- The tween, to chain more steps
procedure. Source: tween.odin:216
Tween_Call
Section titled “Tween_Call”Tween_Call :: proc(tween: ^Tween, callback: proc(user: rawptr), user: rawptr) -> ^TweenAdds a step that calls callback(user) (once per play, including each loop), then goes on.
Inputs
- tween: The tween
- callback: Called when the step is reached
- user: Passed to the callback (nil if unused); it must still be valid then
Returns
- The tween, to chain more steps
Example
// Given: tween: ^e.Tweene.Tween_Call(tween, proc(user: rawptr) { log.info("done") }, nil)procedure. Source: tween.odin:236
Tween_Parallel
Section titled “Tween_Parallel”Tween_Parallel :: proc(tween: ^Tween) -> ^TweenMakes the next step added run together with the last one. Consecutive parallel steps form a group, which ends with its longest step. Does nothing when the tween has no steps yet.
Inputs
- tween: The tween
Returns
- The tween, to chain more steps
procedure. Source: tween.odin:251
Tween_SetLoops
Section titled “Tween_SetLoops”Tween_SetLoops :: proc(tween: ^Tween, count: int) -> ^TweenSets how many more times the tween plays after the first. Each loop starts its steps again from
the values as they are then (Tween_FromTo steps jump back to their start).
Inputs
- tween: The tween
- count: Extra plays after the first (0: once, -1: forever)
Returns
- The tween, to chain more steps
procedure. Source: tween.odin:267
Tween_Pause
Section titled “Tween_Pause”Tween_Pause :: proc(tween: ^Tween, paused: bool)Pauses or resumes a tween where it is.
Inputs
- tween: The tween
- paused: true to pause, false to resume
procedure. Source: tween.odin:279
Tween_Kill
Section titled “Tween_Kill”Tween_Kill :: proc(tween: ^Tween)Stops a tween where it is; it’s freed at the scene’s next update. Its remaining callbacks don’t run.
Inputs
- tween: The tween
procedure. Source: tween.odin:289
Tween_IsRunning
Section titled “Tween_IsRunning”Tween_IsRunning :: proc(tween: ^Tween) -> boolTells whether a tween is still going. Only valid until the update that frees a finished tween: don’t call it on a pointer you kept longer.
Inputs
- tween: The tween
Returns
- true while it isn’t finished or killed (a paused tween is running)
procedure. Source: tween.odin:303
Ease :: proc(type: EaseType, t: f32) -> f32Applies an easing curve to a progress value.
Inputs
- type: The easing curve
- t: Progress from 0 (start) to 1 (end). Values outside 0..1 are clamped
Returns
- Eased progress. 0 at t = 0 and 1 at t = 1; Back and Elastic curves briefly go outside 0..1
Example
// Given: elapsed: f32, duration: f32, from: [2]f32, to: [2]f32t := elapsed / durationpos := from + (to - from) * e.Ease(.InOutCubic, t)procedure. Source: easing.odin:49
CreateStateMachine
Section titled “CreateStateMachine”CreateStateMachine :: proc(scene: ^Scene, settings: StateMachineSettings) -> ^StateMachineCreates a StateMachine with these settings (copied) and adds it to the scene (at the start of the next update). It enters its start state on its first update.
Inputs
- scene: The scene
- settings: Its states, transitions and parameters
Returns
- The state machine
procedure. Source: state_machine.odin:151
StateMachine_Current
Section titled “StateMachine_Current”StateMachine_Current :: proc(sm: ^StateMachine) -> stringThe current state’s name (“” before the first update, or without states).
procedure. Source: state_machine.odin:188
StateMachine_Is
Section titled “StateMachine_Is”StateMachine_Is :: proc(sm: ^StateMachine, state: string) -> boolWhether it’s in a state.
procedure. Source: state_machine.odin:195
StateMachine_TimeInState
Section titled “StateMachine_TimeInState”StateMachine_TimeInState :: proc(sm: ^StateMachine) -> f32Seconds since it entered its current state.
procedure. Source: state_machine.odin:202
StateMachine_StateIndex
Section titled “StateMachine_StateIndex”StateMachine_StateIndex :: proc(sm: ^StateMachine, name: string) -> intA state’s index by name (-1: none).
procedure. Source: state_machine.odin:209
StateMachine_Travel
Section titled “StateMachine_Travel”StateMachine_Travel :: proc(sm: ^StateMachine, state: string) -> boolGoes to a state now, whatever the transitions say (it’s entered again if it’s the current one).
Returns
- false when there’s no such state
Example
// Given: brain: ^e.StateMachinee.StateMachine_Travel(brain, "hurt")procedure. Source: state_machine.odin:224
StateMachine_SetFloat
Section titled “StateMachine_SetFloat”StateMachine_SetFloat :: proc(sm: ^StateMachine, name: string, value: f32)Sets a Float parameter.
Example
// Given: brain: ^e.StateMachine, velocity: [2]f32e.StateMachine_SetFloat(brain, "speed", abs(velocity.x))procedure. Source: state_machine.odin:238
StateMachine_SetBool
Section titled “StateMachine_SetBool”StateMachine_SetBool :: proc(sm: ^StateMachine, name: string, value: bool)Sets a Bool parameter.
Example
// Given: brain: ^e.StateMachine, mover: ^e.CharacterMovere.StateMachine_SetBool(brain, "grounded", mover.onFloor)procedure. Source: state_machine.odin:249
StateMachine_SetTrigger
Section titled “StateMachine_SetTrigger”StateMachine_SetTrigger :: proc(sm: ^StateMachine, name: string)Sets a Trigger: the next transition its condition is part of is taken, and the trigger cleared.
Example
// Given: brain: ^e.StateMachinee.StateMachine_SetTrigger(brain, "jump")procedure. Source: state_machine.odin:260
StateMachine_GetParam
Section titled “StateMachine_GetParam”StateMachine_GetParam :: proc(sm: ^StateMachine, name: string) -> f32A parameter’s value (Bools and Triggers: 1 or 0).
procedure. Source: state_machine.odin:267
StateMachine_ConditionProblem
Section titled “StateMachine_ConditionProblem”StateMachine_ConditionProblem :: proc(settings: ^StateMachineSettings, condition: string) -> stringWhether a condition is well formed for a set of parameters: “” when it is, else what’s wrong (editors show it).
Inputs
- settings: The machine’s settings (its parameters)
- condition: The condition
Returns
- The problem, or “”
procedure. Source: state_machine.odin:283
StateMachineSettings_Clone
Section titled “StateMachineSettings_Clone”StateMachineSettings_Clone :: proc(s: StateMachineSettings, allocator := context.allocator) -> StateMachineSettingsA deep copy of state machine settings.
procedure. Source: state_machine.odin:300
StateMachineSettings_Destroy
Section titled “StateMachineSettings_Destroy”StateMachineSettings_Destroy :: proc(s: ^StateMachineSettings)Frees state machine settings (the parser’s, StateMachineSettings_Clone’s) and empties them.
procedure. Source: state_machine.odin:314
StateMachineSettings_Equal
Section titled “StateMachineSettings_Equal”StateMachineSettings_Equal :: proc(a, b: StateMachineSettings) -> boolWhether two state machine settings are the same.
procedure. Source: state_machine.odin:339
CreateBone2D
Section titled “CreateBone2D”CreateBone2D :: proc(scene: ^Scene, length: f32 = 32) -> ^Bone2DMakes a bone (length pixels along its x axis)
procedure. Source: skeleton.odin:115
CreateSkeleton2D
Section titled “CreateSkeleton2D”CreateSkeleton2D :: proc(scene: ^Scene) -> ^Skeleton2DMakes a skeleton’s root
procedure. Source: skeleton.odin:122
CreateSkinnedMesh
Section titled “CreateSkinnedMesh”CreateSkinnedMesh :: proc(scene: ^Scene, texture: ^sdl.Texture, mesh: MeshData, region := sdl.FRect{}) -> ^SkinnedMeshMakes a skinned mesh: a picture bent over bones. Its mesh is copied into the node’s memory; it binds to its bones (their rest pose: where they are then) on its first update.
Inputs
- scene: The scene
- texture: The picture
- mesh: Its triangles, the picture’s pixels under them, its bones and weights
- region: The part of the texture (an atlas region; zero: all of it)
procedure. Source: skeleton.odin:136
CreateIKChain
Section titled “CreateIKChain”CreateIKChain :: proc(scene: ^Scene, tip, target: string, settings := DEFAULT_IK_SETTINGS) -> ^IKChainMakes an IK chain aiming the bones up from tip at target (paths from the IK node).
procedure. Source: skeleton.odin:161
SkinnedMesh_Bind
Section titled “SkinnedMesh_Bind”SkinnedMesh_Bind :: proc(mesh: ^SkinnedMesh) -> intRemembers where a skinned mesh’s bones are relative to it now: their rest pose. A vertex moves with its bones’ moves since. Done on its first update; call it again after changing the rest pose (editors do after moving bones) or the bones.
Returns
- How many of its bones were found (missing ones leave their vertices in place)
procedure. Source: skeleton.odin:191
SkinnedMesh_Deform
Section titled “SkinnedMesh_Deform”SkinnedMesh_Deform :: proc(mesh: ^SkinnedMesh) -> [][2]f32Where a skinned mesh’s vertices are now (its space), its bones’ moves blended by their weights.
Returns
- The vertices (temp allocated)
procedure. Source: skeleton.odin:219
Scene_SolveIK
Section titled “Scene_SolveIK”Scene_SolveIK :: proc(scene: ^Scene)Solves a scene’s IK chains (Scene_Update, after nodes and tweens): each turns its bones so the tip’s end reaches the target, or points at it when it’s out of reach.
procedure. Source: skeleton.odin:253
IKChain_Solve
Section titled “IKChain_Solve”IKChain_Solve :: proc(c: ^IKChain) -> boolSolves one IK chain now.
Returns
- false when its tip or target isn’t found
procedure. Source: skeleton.odin:263
Bone2D_Tip
Section titled “Bone2D_Tip”Bone2D_Tip :: proc(bone: ^Bone2D) -> [2]f32A bone’s tip in the world
procedure. Source: skeleton.odin:292
MeshData_Clone
Section titled “MeshData_Clone”MeshData_Clone :: proc(mesh: MeshData, allocator := context.allocator) -> MeshDataCopies mesh data into an allocator
procedure. Source: skeleton.odin:297
MeshData_Destroy
Section titled “MeshData_Destroy”MeshData_Destroy :: proc(mesh: ^MeshData, allocator := context.allocator)Frees what MeshData_Clone or ParseMesh made
procedure. Source: skeleton.odin:314
MeshData_Equal
Section titled “MeshData_Equal”MeshData_Equal :: proc(a, b: MeshData) -> boolWhether two meshes are the same
procedure. Source: skeleton.odin:325
FormatWeights
Section titled “FormatWeights”FormatWeights :: proc(weights: []VertexWeights) -> stringA mesh’s weights as scene files write them: per vertex bone:weight pairs separated by spaces,
vertices by ; (“0:1;0:0.5 1:0.5”).
Returns
- The text (temp allocated)
procedure. Source: skeleton.odin:342
ParseWeights
Section titled “ParseWeights”ParseWeights :: proc(text: string) -> ([]VertexWeights, bool)Reads FormatWeights’s text (temp allocated); false when it doesn’t parse
procedure. Source: skeleton.odin:359
FormatTriangles
Section titled “FormatTriangles”FormatTriangles :: proc(triangles: []i32) -> string“0,1,2 2,3,0”: a mesh’s triangles (temp allocated)
procedure. Source: skeleton.odin:380
ParseTriangles
Section titled “ParseTriangles”ParseTriangles :: proc(text: string) -> ([]i32, bool)Reads FormatTriangles’s text (temp allocated); false when it doesn’t parse or isn’t whole triangles
procedure. Source: skeleton.odin:390
DragonBones_Convert
Section titled “DragonBones_Convert”DragonBones_Convert :: proc(ske, tex: string, atlasPath, imagePath: string) -> (result: DragonBonesResult, ok: bool)Converts a DragonBones armature and its texture atlas into a component and an atlas.
Inputs
- ske: The
_ske.jsonfile’s text - tex: The
_tex.jsonfile’s text - atlasPath: Where the atlas will be (the sprites’
texture; “atlases/hero.atlas.xml”) - imagePath: Where the atlas’s picture will be (“atlases/hero.png”)
Returns
- The component and atlas, what wasn’t converted, and false when the texts aren’t DragonBones files (the reason is the first warning)
procedure. Source: dragonbones.odin:57
Constants and variables
Section titled “Constants and variables”ASEPRITE_SHEET_SUFFIX
Section titled “ASEPRITE_SHEET_SUFFIX”ASEPRITE_SHEET_SUFFIX :: "#sheet"The resource manager key suffix for an Aseprite file’s sheet of every frame (not its first frame)
constant. Source: animation_sets.odin:24
ASEPRITE_TILESET_SUFFIX
Section titled “ASEPRITE_TILESET_SUFFIX”ASEPRITE_TILESET_SUFFIX :: "#tileset"The resource manager key suffix for an Aseprite file’s tileset (#tileset0: its first; tilemap.odin)
constant. Source: animation_sets.odin:195
ANIMATOR_PROPERTIES
Section titled “ANIMATOR_PROPERTIES”ANIMATOR_PROPERTIES := [?]AnimatorProperty{ {"position", .Vector, "Position", nil}, {"position.x", .Float, "Position X", nil}, {"position.y", .Float, "Position Y", nil}, {"rotation", .Float, "Rotation", nil}, {"scale", .Vector, "Scale", nil}, {"scale.x", .Float, "Scale X", nil}, {"scale.y", .Float, "Scale Y", nil}, {"tint", .Color, "Tint", nil}, {"opacity", .Float, "Opacity", nil}, {"visible", .Bool, "Visible", nil}, {"zIndex", .Float, "Z index", nil}, {"animation", .Text, "Animation", AnimatedSprite}, {"text", .Text, "Text", Label}, {"color", .Color, "Text color", Label}, {"energy", .Float, "Light energy", Light2D}, {"lightRadius", .Float, "Light radius", Light2D}, {"lightColor", .Color, "Light color", Light2D}, {"state", .Text, "State", StateMachine},}The built-in properties an Animator’s tracks animate, in the order tools list them. A script’s
exported fields are animated as script.<field> besides these (Animator_ScriptFieldKind).
variable. Source: animator.odin:81
ANIMATOR_EVENT_PROPERTY
Section titled “ANIMATOR_EVENT_PROPERTY”ANIMATOR_EVENT_PROPERTY :: "event"The track property that fires the Animator’s onEvent instead of setting a value
constant. Source: animator.odin:103
ANIMATOR_SCRIPT_PREFIX
Section titled “ANIMATOR_SCRIPT_PREFIX”ANIMATOR_SCRIPT_PREFIX :: "script."The prefix of a script field’s property (“script.speed”)
constant. Source: animator.odin:106
ANIMATOR_SHADER_PREFIX
Section titled “ANIMATOR_SHADER_PREFIX”ANIMATOR_SHADER_PREFIX :: "shader."The prefix of a shader parameter’s property (“shader.amount”: shaders.odin; floats, vec2s and colors animate)
constant. Source: animator.odin:109
DEFAULT_ANIMATOR_SETTINGS
Section titled “DEFAULT_ANIMATOR_SETTINGS”DEFAULT_ANIMATOR_SETTINGS :: AnimatorSettings{speed = 1}An Animator’s settings when the scene file sets none
constant. Source: animator.odin:159
DEFAULT_IK_SETTINGS
Section titled “DEFAULT_IK_SETTINGS”DEFAULT_IK_SETTINGS :: IKSettings{length = 2, bendPositive = true, enabled = true}An IK chain’s settings when none are given (CreateIKChain, scene files): two bones, bending
clockwise, on
constant. Source: skeleton.odin:103
