AffineTransformEffectLib — Affine Transform Effect
Applies GPU-accelerated affine transformations (rotation, uniform scaling, center offset) to any visual control. The effect wraps FireMonkey’s TAffineTransformEffect and renders in real-time, making it ideal for image rotation controls, zoom effects, spinning animations, and interactive transform UIs. 18 functions.
| Category | Count | Description |
| Error Handling | 4 | affine_error, errormsg$, strerror$, clearerror |
| Creation & Destruction | 2 | affine# (create), affine_free (destroy) |
| Transform Properties | 8 | centerx, centery, rotation, scale (get/set) |
| Effect Control | 4 | enabled, trigger (get/set) |
ⓘ Effect Ownership: The effect is owned by its parent control, not managed by garbage collection. Destroying the parent control also destroys the effect. Use affine_free only if you need to remove the effect while keeping the parent alive.
Error Handling
All functions set an error code on failure. Check with affine_error() after operations. Error code 0 means success.
| Function | Signature | Description |
affine_error() | affine_error@ | Returns last error code (0 = no error) |
affine_errormsg$() | affine_errormsg$@ | Returns last error message as string |
affine_strerror$(code) | affine_strerror$@n | Converts an error code to descriptive text |
affine_clearerror() | affine_clearerror@ | Clears the error state |
Error Codes
| Code | Constant | Meaning |
| 0 | ERR_NONE | No error |
| 1 | ERR_NIL_EFFECT | Effect pointer is nil |
| 2 | ERR_INVALID_EFFECT | Pointer is not a valid TAffineTransformEffect |
| 3 | ERR_INVALID_VALUE | Property value out of range |
| 4 | ERR_NIL_PARENT | Parent control pointer is nil |
| 5 | ERR_INVALID_PARENT | Pointer is not a valid TFmxObject |
let aff# = affine#(img#)
if affine_error() <> 0 then
print "Error: " + affine_errormsg$()
else
print "Effect created successfully"
endif
Creation & Destruction
| Function | Signature | Description |
affine#(parent#) | affine#@# | Creates an affine transform effect attached to the given control. Returns the effect pointer. |
affine_free(effect#) | affine_free@# | Destroys the effect and removes it from the parent control. |
The parent# can be any visual control: images, rectangles, panels, buttons, labels, shapes, etc. The effect is applied immediately upon creation with default values (no rotation, scale = 1.0, center at 0.5, 0.5).
' Create effect on an image
let aff# = affine#(img#)
' Later, remove the effect
affine_free(aff#)
Effect Control
Enabled
Toggles the effect on or off without destroying it. When disabled, the control renders as if the effect does not exist.
| Function | Signature | Description |
affine_enabled#(effect#, value) | affine_enabled#@#n | Enables (1) or disables (0) the effect |
affine_enabled(effect#) | affine_enabled@# | Gets enabled state (1 = on, 0 = off) |
Trigger
The trigger property is a string used by FireMonkey’s animation system. Setting it starts the effect’s animation (if any). Primarily used for integration with animation components.
| Function | Signature | Description |
affine_trigger#(effect#, trigger$) | affine_trigger#@#$ | Sets trigger string |
affine_trigger$(effect#) | affine_trigger$@# | Gets current trigger string |
' Disable the effect (control renders normally)
affine_enabled#(aff#, 0)
' Re-enable it
affine_enabled#(aff#, 1)
' Check state
if affine_enabled(aff#) = 1 then
print "Effect is active"
endif
Complete Examples
Rotate an Image
Creates an image with a 15° rotation and slight scale-down applied as a visual effect.
let frm# = Pointer#(0)
let img# = Pointer#(0)
let aff# = Pointer#(0)
frm# = form#("Affine Transform Demo", 400, 350)
img# = image#(frm#)
image_bounds#(img#, 100, 30, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")
' Create affine transform effect
aff# = affine#(img#)
affine_rotation#(aff#, 15) ' Rotate 15 degrees
affine_scale#(aff#, 0.9) ' Scale down slightly
form_show(frm#)
Interactive Rotation Control
Uses a trackbar to interactively rotate an image from −180° to +180°.
╯ affine-rotation-control.bas─◻✕
let frm# = Pointer#(0)
let img# = Pointer#(0)
let aff# = Pointer#(0)
let trkRot# = Pointer#(0)
let lblRot# = Pointer#(0)
frm# = form#("Rotation Control", 450, 400)
img# = image#(frm#)
image_bounds#(img#, 125, 30, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")
aff# = affine#(img#)
affine_rotation#(aff#, 0)
' Rotation slider (-180 to 180)
lblRot# = label#(frm#, "Rotation: 0", 50, 200)
trkRot# = trackbar#(frm#)
trackbar_bounds#(trkRot#, 50, 230, 350, 30)
trackbar_max#(trkRot#, 360)
trackbar_value#(trkRot#, 180)
trackbar_onchange#(trkRot#, "OnRotChange")
form_show(frm#)
function OnRotChange(sender#) local deg
let deg = trackbar_value(trkRot#) - 180
affine_rotation#(aff#, deg)
label_text#(lblRot#, "Rotation: " + str$(deg))
endfunction
Scale and Rotate Combined
Combines a fixed rotation with an interactive scale slider (0.5× to 2.0×).
╯ affine-scale-control.bas─◻✕
let frm# = Pointer#(0)
let img# = Pointer#(0)
let aff# = Pointer#(0)
let trkScale# = Pointer#(0)
let lblScale# = Pointer#(0)
frm# = form#("Scale Control", 450, 400)
img# = image#(frm#)
image_bounds#(img#, 125, 30, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")
aff# = affine#(img#)
affine_rotation#(aff#, 10)
affine_scale#(aff#, 1.0)
' Scale slider (0.5 to 2.0)
lblScale# = label#(frm#, "Scale: 1.00", 50, 200)
trkScale# = trackbar#(frm#)
trackbar_bounds#(trkScale#, 50, 230, 350, 30)
trackbar_max#(trkScale#, 150)
trackbar_value#(trkScale#, 50)
trackbar_onchange#(trkScale#, "OnScaleChange")
form_show(frm#)
function OnScaleChange(sender#) local s
let s = 0.5 + (trackbar_value(trkScale#) / 100)
affine_scale#(aff#, s)
label_text#(lblScale#, "Scale: " + stri$(s, 2))
endfunction
Best Practices
| Practice | Why |
Use affine_enabled# to toggle instead of affine_free | Avoids destroying and recreating the effect; better performance for on/off scenarios |
| Keep center at (0.5, 0.5) for symmetric transforms | Rotation and scaling around the visual center looks most natural |
Combine with FloatAnimationLib for animated rotation | Animate the rotation property for smooth spinning effects |
| Use scale values between 0.1 and 5.0 | Extreme values may cause rendering artifacts or performance issues |
| Adjust center before rotation for pivot effects | Setting center to (0, 0) makes the control rotate around its top-left corner |
Check affine_error() after creation | Catches nil or invalid parent controls early |
| One effect per control is typical | Multiple affine effects stack but may produce unexpected results; use one and combine rotation + scale |
| Scale down slightly when rotating to avoid clipping | Rotated corners may extend beyond the original bounding box |
Quick Reference
| Function | Signature | Description |
| ERROR HANDLING |
affine_error() | affine_error@ | Last error code |
affine_errormsg$() | affine_errormsg$@ | Last error message |
affine_strerror$(code) | affine_strerror$@n | Error code to text |
affine_clearerror() | affine_clearerror@ | Clear error state |
| CREATION & DESTRUCTION |
affine#(parent#) | affine#@# | Create effect on control |
affine_free(effect#) | affine_free@# | Destroy effect |
| TRANSFORM PROPERTIES |
affine_centerx#(effect#, val) | affine_centerx#@#n | Set center X (0.0–1.0) |
affine_centerx(effect#) | affine_centerx@# | Get center X |
affine_centery#(effect#, val) | affine_centery#@#n | Set center Y (0.0–1.0) |
affine_centery(effect#) | affine_centery@# | Get center Y |
affine_rotation#(effect#, deg) | affine_rotation#@#n | Set rotation (degrees) |
affine_rotation(effect#) | affine_rotation@# | Get rotation |
affine_scale#(effect#, val) | affine_scale#@#n | Set uniform scale |
affine_scale(effect#) | affine_scale@# | Get scale |
| EFFECT CONTROL |
affine_enabled#(effect#, val) | affine_enabled#@#n | Enable (1) / disable (0) |
affine_enabled(effect#) | affine_enabled@# | Get enabled state |
affine_trigger#(effect#, str$) | affine_trigger#@#$ | Set trigger string |
affine_trigger$(effect#) | affine_trigger$@# | Get trigger string |
18 functions. Part of the Plan9Basic visual effects library system.
See Also
- PerspectiveTransformEffectLib — 3D perspective transforms with depth
- MagnifyEffectLib — Magnifying glass effect for zoom regions
- SwirlEffectLib — Swirl distortion around a center point
- FloatAnimationLib — Animate numeric properties (combine with rotation/scale for animated transforms)