An open.mp server component that adds textdraw easing and animation functionality. It is essentially a component-based version of the original pawn-easing-functions by alexchwoj, with improvements and optimized performance for large-scale animations.
Unlike the original pawn version which is hardcoded to 1024 slots, this component uses a dynamic memory pool that grows automatically as needed, resulting in a much smaller memory footprint and no hard limits on active animations.
-
Go to the Releases page and download the archive or binary matching your server platform (Windows
.dll, Linux.so). -
Extract it and place the component file into your open.mp server
components/directory. -
Copy
omp_easing.incinto the include directory used by your Pawn compiler (e.g.gamemodes/qawno/include/). -
Add
#include <omp_easing> to your gamemodes file, then recompile your scripts.
You can fully customize the behavior and performance of the component by adding an easing block to your server's config.json:
{
"easing": {
"update_rate_fps": 30,
"batch_process_limit": 100,
"expected_players": 512,
"initial_capacity": 64,
"callback_reserve": 128
}
}-
update_rate_fps(default:30): The framerate of the animations. Higher values make animations smoother but consume more server CPU. -
batch_process_limit(default:100): Maximum number of animations processed per update tick, to prevent CPU/network lag spikes during massive visual changes. Animations beyond the limit are never dropped: they are processed round-robin on the following ticks, so every animation still progresses and finishes correctly. Set to0to disable the limit (process all animations every tick).Trade-off: when the number of concurrently active animations exceeds this limit, the effective framerate of each animation drops proportionally. Example: 300 active animations with a limit of
100at 30 FPS means each animation only updates every 3rd tick (~10 FPS visually). Raise this value (e.g.500-1000) if your server runs large-scale animations and you want them to stay smooth; keep it low if you prioritize a stable server tick rate over animation smoothness. -
expected_players(default:512): Internal hint for the memory pre-allocator. Set this closer to your actual server player count. -
initial_capacity(default:64): Starting size of the dynamic animation pool. It will grow automatically if exceeded, but setting it accurately prevents initial re-allocations. -
callback_reserve(default:128): Pre-allocated buffer for pawn callbacks (OnAnimatorFinish).
// Utility
native Float:GetEasingValue(Float:t, easeType);
native Float:Lerp(Float:start, Float:end, Float:t);
native LerpColor(color1, color2, Float:t);
// Position
native PlayerText_MoveTo(playerid, PlayerText:textdraw, Float:x, Float:y, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveToX(playerid, PlayerText:textdraw, Float:x, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveToY(playerid, PlayerText:textdraw, Float:y, duration = 1000, easeType = EASE_NONE, bool:silent = false);
// Size
native PlayerText_MoveLetterSizeX(playerid, PlayerText:textdraw, Float:x, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveLetterSizeY(playerid, PlayerText:textdraw, Float:y, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveTextSizeX(playerid, PlayerText:textdraw, Float:x, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveTextSizeY(playerid, PlayerText:textdraw, Float:y, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_MoveSize(playerid, PlayerText:textdraw, Float:x, Float:y, duration = 1000, easeType = EASE_NONE, bool:silent = false);
// Color
native PlayerText_InterpolateColor(playerid, PlayerText:textdraw, color, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_InterpolateBoxColor(playerid, PlayerText:textdraw, color, duration = 1000, easeType = EASE_NONE, bool:silent = false);
native PlayerText_InterpolateBGColor(playerid, PlayerText:textdraw, color, duration = 1000, easeType = EASE_NONE, bool:silent = false);
// General
native PlayerText_PlaceOnTop(playerid, PlayerText:textdraw);
native PlayerText_StopAnimation(animator_id);
native IsAnimationActive(animator_id);
// Debug and monitoring
native GetActiveAnimationsCount();
native GetAnimationStats(&totalCreated, &peakConcurrent, &totalCallbacks, &silentAnimations = 0);OnAnimatorFinish(playerid, animatorid, textdrawid, type);Note:
animatorid(the value returned by the animation natives and passed here) is an opaque handle, not a sequential index. It encodes an internal generation counter, so the numbers are not small or ordered and recycled slots never reuse an old id. Just store it as-is, compare it, and pass it toIsAnimationActive/PlayerText_StopAnimation— do not use it as an array index.textdrawidis unaffected and remains the normal PlayerTextDraw id.
EASE_IN_SINE
EASE_OUT_SINE
EASE_IN_OUT_SINE
EASE_IN_QUAD
EASE_OUT_QUAD
EASE_IN_OUT_QUAD
EASE_IN_CUBIC
EASE_OUT_CUBIC
EASE_IN_OUT_CUBIC
EASE_IN_QUART
EASE_OUT_QUART
EASE_IN_OUT_QUART
EASE_IN_QUINT
EASE_OUT_QUINT
EASE_IN_OUT_QUINT
EASE_IN_EXPO
EASE_OUT_EXPO
EASE_IN_OUT_EXPO
EASE_IN_CIRC
EASE_OUT_CIRC
EASE_IN_OUT_CIRC
EASE_IN_BACK
EASE_OUT_BACK
EASE_IN_OUT_BACK
EASE_IN_ELASTIC
EASE_OUT_ELASTIC
EASE_IN_OUT_ELASTIC
EASE_IN_BOUNCE
EASE_OUT_BOUNCE
EASE_IN_OUT_BOUNCE
EASE_NONE
enum eAnimatorTypes
{
ANIMATOR_POSITION,
ANIMATOR_LETTER_SIZE,
ANIMATOR_TEXT_SIZE,
ANIMATOR_FULL_SIZE,
ANIMATOR_COLOR,
ANIMATOR_BOX_COLOR,
ANIMATOR_BACKGROUND_COLOR
}
You can preview each easing type visually here: https://easings.net/
- alexchwoj and all pawn-easing-functions contributors
- AmyrAhmady for the open.mp component SDK
- Yksir onav code refactor
- Fanorisky (me)