IntAnimationLib — Integer Animation Library
Animates integer properties of visual controls. While most visual properties (position, opacity, scale) are floats, integer animation excels at animating counters, scores, progress percentages, and Tag-based values with smooth interpolation. The Tag property — an integer available on every control — makes this library a powerful tool for driving custom logic via the onprocess callback. 46 functions.
| Category | Count | Description |
|---|---|---|
| Error Handling | 4 | intani_error, errormsg$, strerror$, clearerror |
| Creation & Destruction | 3 | intani# (2 overloads), intani_free |
| Playback Control | 3 | start, stop, stopatcurrent |
| Core Properties | 10 | propertyname, startvalue, stopvalue, duration, delay (get/set) |
| Behavior — Easing | 4 | animationtype, interpolation (get/set) |
| Behavior — Flags | 10 | autoreverse, inverse, loop, enabled, startfromcurrent (get/set) |
| State Queries | 3 | running, normalizedtime, name$ |
| Triggers | 4 | trigger, triggerinverse (get/set) |
| Events | 5 | onfinish, onprocess (get/set), clearcallbacks# |
Cross-Platform Support
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Full Support | Win32/Win64 |
| Linux | ✅ Full Support | GTK-based |
| Android | ✅ Full Support | Hardware-accelerated |
Error Handling
| Function | Signature | Description |
|---|---|---|
intani_error() | intani_error@ | Last error code (0 = no error) |
intani_errormsg$() | intani_errormsg$@ | Last error message as string |
intani_strerror$(code) | intani_strerror$@n | Description for a given error code |
intani_clearerror() | intani_clearerror@ | Clear the error state |
Error Codes
| Code | Constant | Description |
|---|---|---|
| 0 | ERR_NONE | No error |
| 1 | ERR_NIL_ANIMATION | Animation pointer is nil |
| 2 | ERR_INVALID_PROPERTY | Invalid property name or object |
| 3 | ERR_INVALID_VALUE | Invalid parameter value |
| 4 | ERR_ANIMATION_RUNNING | Cannot modify while animation is running |
How It Works
The integer animation smoothly transitions a single integer property from a start value to a stop value over a given duration. The most common pattern uses the Tag property (available on all controls) combined with an onprocess callback to update the UI on every frame:
' 1. Create the animation on a control let ani# = intani#(myLabel#) ' 2. REQUIRED: set which property to animate intani_propertyname#(ani#, "Tag") ' 3. Set integer range intani_startvalue#(ani#, 0) intani_stopvalue#(ani#, 100) ' 4. Set timing intani_duration#(ani#, 5.0) ' 5. Set callback to react to value changes intani_onprocess#(ani#, "OnUpdate") ' 6. Start! intani_start(ani#) function OnUpdate(sender#) local val val = label_tag(myLabel#) label_text#(myLabel#, "Value: " + str$(val)) endfunction
intani_propertyname# before starting the animation. Without it, the animation will not run. Use "Tag" as the property name for most use cases.Int vs Float Animation
Most FireMonkey visual properties (Position, Opacity, Scale, RotationAngle) are float-based. Use FloatAnimationLib for those. IntAnimationLib is designed specifically for:
| Use Case | Recommended Library | Why |
|---|---|---|
| Move a control (Position.X/Y) | FloatAnimationLib | Position is a float property |
| Fade a control (Opacity) | FloatAnimationLib | Opacity is a float (0.0–1.0) |
| Rotate a control (RotationAngle) | FloatAnimationLib | Angle is a float |
| Animate a counter (0 → 100) | IntAnimationLib | Tag is an integer |
| Animate a score display | IntAnimationLib | Scores are whole numbers |
| Drive a progress bar percentage | IntAnimationLib | Clean integer steps (0%–100%) |
| Countdown timer (10 → 0) | IntAnimationLib | Whole second display |
Interpolation & Easing
Interpolation Curves
| Interpolation | Character | Best For |
|---|---|---|
"Linear" | Constant speed | Counters, timers, steady progress |
"Quadratic" | Gentle curve | Smooth progress bars |
"Cubic" | Moderate curve | Score reveals |
"Quartic" | Pronounced curve | Dramatic number reveals |
"Quintic" | Very pronounced | Emphatic counter effects |
"Sinusoidal" | Sine-wave smoothness | Natural-feeling transitions |
"Exponential" | Sharp start or end | Fast ramp-up/ramp-down |
"Circular" | Arc-based | Orbital counting effects |
"Elastic" | Springy overshoot | Bouncy score counters |
"Back" | Overshoots then settles | Attention-grabbing numbers |
"Bounce" | Bouncing ball effect | Playful score reveals |
Easing Types (AnimationType)
| Type | Effect | Description |
|---|---|---|
"In" | Slow start → fast end | Acceleration at the beginning |
"Out" | Fast start → slow end | Deceleration at the end |
"InOut" | Slow → fast → slow | Accelerate then decelerate |
Creation & Destruction
| Function | Signature | Description |
|---|---|---|
intani#(parent#) | intani#@# | Create animation attached to parent control |
intani#(parent#, name$) | intani#@#$ | Create named animation attached to parent |
intani_free(ani#) | intani_free@# | Destroy animation object |
Playback Control
| Function | Signature | Description |
|---|---|---|
intani_start(ani#) | intani_start@# | Start the animation |
intani_stop(ani#) | intani_stop@# | Stop and reset to start value |
intani_stopatcurrent(ani#) | intani_stopatcurrent@# | Stop at current interpolated value |
Core Properties
Property Name
| Function | Signature | Description |
|---|---|---|
intani_propertyname#(ani#, name$) | intani_propertyname#@#$ | REQUIRED — Set which property to animate |
intani_propertyname$(ani#) | intani_propertyname$@# | Get the property name |
Value Range
| Function | Signature | Description |
|---|---|---|
intani_startvalue#(ani#, value) | intani_startvalue#@#n | Set starting integer value |
intani_startvalue(ani#) | intani_startvalue@# | Get starting value |
intani_stopvalue#(ani#, value) | intani_stopvalue#@#n | Set ending integer value |
intani_stopvalue(ani#) | intani_stopvalue@# | Get ending value |
Timing
| Function | Signature | Description |
|---|---|---|
intani_duration#(ani#, seconds) | intani_duration#@#n | Set duration in seconds |
intani_duration(ani#) | intani_duration@# | Get duration |
intani_delay#(ani#, seconds) | intani_delay#@#n | Set delay before animation starts |
intani_delay(ani#) | intani_delay@# | Get delay |
Behavior Flags
Easing & Interpolation
| Function | Signature | Description |
|---|---|---|
intani_animationtype#(ani#, type$) | intani_animationtype#@#$ | Set easing: "In", "Out", "InOut" |
intani_animationtype$(ani#) | intani_animationtype$@# | Get current easing type |
intani_interpolation#(ani#, type$) | intani_interpolation#@#$ | Set interpolation curve |
intani_interpolation$(ani#) | intani_interpolation$@# | Get current interpolation type |
Boolean Flags
| Function | Signature | Description |
|---|---|---|
intani_autoreverse#(ani#, flag) | intani_autoreverse#@#n | If 1, plays forward then backward |
intani_autoreverse(ani#) | intani_autoreverse@# | Get autoreverse flag |
intani_inverse#(ani#, flag) | intani_inverse#@#n | If 1, plays in reverse direction |
intani_inverse(ani#) | intani_inverse@# | Get inverse flag |
intani_loop#(ani#, flag) | intani_loop#@#n | If 1, loops indefinitely |
intani_loop(ani#) | intani_loop@# | Get loop flag |
intani_enabled#(ani#, flag) | intani_enabled#@#n | Enable or disable the animation |
intani_enabled(ani#) | intani_enabled@# | Get enabled state |
intani_startfromcurrent#(ani#, flag) | intani_startfromcurrent#@#n | If 1, begins from current property value |
intani_startfromcurrent(ani#) | intani_startfromcurrent@# | Get startfromcurrent flag |
State Queries
| Function | Signature | Description |
|---|---|---|
intani_running(ani#) | intani_running@# | Returns 1 if currently animating |
intani_normalizedtime(ani#) | intani_normalizedtime@# | Returns progress from 0.0 to 1.0 |
intani_name$(ani#) | intani_name$@# | Get the animation’s name |
Triggers
Triggers let an animation start or reverse automatically when a parent property changes, without calling intani_start manually.
| Function | Signature | Description |
|---|---|---|
intani_trigger#(ani#, expr$) | intani_trigger#@#$ | Set trigger expression (starts animation) |
intani_trigger$(ani#) | intani_trigger$@# | Get trigger expression |
intani_triggerinverse#(ani#, expr$) | intani_triggerinverse#@#$ | Set inverse trigger (reverses animation) |
intani_triggerinverse$(ani#) | intani_triggerinverse$@# | Get inverse trigger expression |
Events
Each event has a setter and a getter. Use intani_clearcallbacks# to disconnect all at once.
| Event Setter | Getter | Callback Signature | Description |
|---|---|---|---|
intani_onfinish#(ani#, func$) | intani_onfinish$(ani#) | function name(sender#) | Fired when animation completes |
intani_onprocess#(ani#, func$) | intani_onprocess$(ani#) | function name(sender#) | Fired on every animation frame |
intani_clearcallbacks#(ani#) | — | — | Disconnect all callbacks |
onprocess callback is the heart of integer animation. Inside it, read the control’s Tag property (which the animation is updating) and use that value to update your UI — labels, progress bars, or any other visual element.Complete Examples
Counter Animation (0 to 100)
let frm# = form#("Counter Demo", 400, 200) form_position#(frm#, 4) let lbl# = label#(frm#, "Count: 0") label_move#(lbl#, 130, 80) label_fontsize#(lbl#, 28) ' Animate Tag from 0 to 100 over 5 seconds let intAni# = intani#(lbl#) intani_propertyname#(intAni#, "Tag") intani_startvalue#(intAni#, 0) intani_stopvalue#(intAni#, 100) intani_duration#(intAni#, 5.0) intani_interpolation#(intAni#, "Linear") intani_onprocess#(intAni#, "updatecount") intani_start(intAni#) form_show(frm#) function updatecount(sender#) local tagval tagval = label_tag(lbl#) label_text#(lbl#, "Count: " + str$(tagval)) endfunction while form_visible(frm#) = 1 processmessages() end while
Countdown Timer (10 to 0)
let frm# = form#("Countdown Demo", 300, 200) form_position#(frm#, 4) let lbl# = label#(frm#, "10") label_move#(lbl#, 120, 70) label_fontsize#(lbl#, 48) let intAni# = intani#(lbl#) intani_propertyname#(intAni#, "Tag") intani_startvalue#(intAni#, 10) intani_stopvalue#(intAni#, 0) intani_duration#(intAni#, 10.0) intani_interpolation#(intAni#, "Linear") intani_onprocess#(intAni#, "showcountdown") intani_onfinish#(intAni#, "countdone") intani_start(intAni#) form_show(frm#) function showcountdown(sender#) local tagval tagval = label_tag(lbl#) label_text#(lbl#, str$(tagval)) endfunction function countdone(sender#) label_text#(lbl#, "Done!") endfunction while form_visible(frm#) = 1 processmessages() end while
Progress Bar
let frm# = form#("Progress Demo", 400, 150) form_position#(frm#, 4) let progressBg# = rectangle#(frm#, 50, 50, 300, 30) rectangle_fill#(progressBg#, "#ecf0f1") let progressBar# = rectangle#(frm#, 50, 50, 0, 30) rectangle_fill#(progressBar#, "#27ae60") let lbl# = label#(frm#, "0%") label_move#(lbl#, 180, 90) ' Animate Tag 0-100, use onprocess to update bar width let intAni# = intani#(progressBar#) intani_propertyname#(intAni#, "Tag") intani_startvalue#(intAni#, 0) intani_stopvalue#(intAni#, 100) intani_duration#(intAni#, 3.0) intani_interpolation#(intAni#, "Quadratic") intani_animationtype#(intAni#, "Out") intani_onprocess#(intAni#, "updateprogress") intani_start(intAni#) form_show(frm#) function updateprogress(sender#) local pct pct = rectangle_tag(progressBar#) label_text#(lbl#, str$(pct) + "%") rectangle_width#(progressBar#, pct * 3) endfunction while form_visible(frm#) = 1 processmessages() end while
Score with Bounce Effect
let frm# = form#("Score Demo", 400, 200) form_position#(frm#, 4) let lbl# = label#(frm#, "Score: 0") label_move#(lbl#, 120, 80) label_fontsize#(lbl#, 24) ' Bounce-eased score counter: 0 to 1000 let intAni# = intani#(lbl#) intani_propertyname#(intAni#, "Tag") intani_startvalue#(intAni#, 0) intani_stopvalue#(intAni#, 1000) intani_duration#(intAni#, 2.0) intani_interpolation#(intAni#, "Bounce") intani_animationtype#(intAni#, "Out") intani_onprocess#(intAni#, "updatescore") intani_start(intAni#) form_show(frm#) function updatescore(sender#) local score score = label_tag(lbl#) label_text#(lbl#, "Score: " + str$(score)) endfunction while form_visible(frm#) = 1 processmessages() end while
Best Practices
| Practice | Why |
|---|---|
Always set intani_propertyname#(ani#, "Tag") | Required — animation will not run without it |
Use "Tag" as the property for most cases | Available on all controls, perfect for driving onprocess logic |
Read the Tag in onprocess to update UI | The Tag is silently updated; you reflect the change visually |
| Declare local variables on the function line | Plan9Basic requires: function name(sender#) local var1, var2 |
Use "Linear" for timers and steady counters | Other curves make the counting speed uneven |
Use "Bounce" + "Out" for playful score reveals | Creates an engaging bouncing number effect |
Use "Quadratic" + "Out" for progress bars | Fast start, gentle deceleration feels natural |
| Prefer FloatAnimationLib for visual properties | Position, Opacity, Scale, RotationAngle are float properties |
Use onfinish for completion actions | Trigger next step, show “Done!” message, start another animation |
Quick Reference
| Function | Signature | Description |
|---|---|---|
intani_error / errormsg$ / strerror$ / clearerror | various | Error handling (4) |
intani#(parent#[, name$]) | intani#@# / intani#@#$ | Create (2 overloads) |
intani_free(ani#) | intani_free@# | Destroy |
intani_start / stop / stopatcurrent | various | Playback control (3) |
intani_propertyname# / propertyname$ | various | Target property (2) |
intani_startvalue / stopvalue | various | Value range (4) |
intani_duration / delay | various | Timing (4) |
intani_animationtype / interpolation | various | Easing & curves (4) |
intani_autoreverse / inverse / loop / enabled / startfromcurrent | various | Behavior flags (10) |
intani_running / normalizedtime / name$ | various | State queries (3) |
intani_trigger / triggerinverse | various | Automatic triggers (4) |
intani_onfinish / onprocess / clearcallbacks# | various | Events (5) |
46 functions. Part of the Plan9Basic Animation library system.