Animation¶
This is the reference configuration for animating OptiFine's Custom Entity Models (CEMA).
Important
These apply inside of Models and this document is kept separate for organizational purposes only. It is not a separate file.
Each model variable which is to be animated is assigned a mathematical expression. The expression is evaluated every time the model is rendered and its value is assigned to the variable. This value controls the positions, scales, rotations, etc. of the parts of the model.
Important
Animations must be in the parent bone, not any sub-bone.
The variables and expressions are defined in the "animations" section of the JSON entity model (JEM):
{
"animations": [
{
"variable1": "expression1",
"variable2": "expression2"
}
]
}
Keys¶
Variables make up the keys of the items in the objects in the "animations" list. They are strings that refer to different values that control an entity.
For example, in the object {"a": 5}
, "a" is the key and 5 is the value.
Model variables¶
Model variables are specified in the format <model>.<variable_name>
.
The <model>
can be one of:
this
: the current custom model.part
: the original part model to which the custom model is attached.<part>
: the original model by part name.<id>
: the custom model by an assigned ID.<part>:<sub_id>:<sub_sub_id>:...
: (hierarchical) start with the original model by part name, then find its children by ID.<id>:<sub_id>:<sub_sub_id>:...
: (hierarchical) start with the original model by ID, then find children its by ID.
The first model found by part name or ID is used if there are duplicates. The model search by ID is deep, and is also deep when used in a hierarchical specification.
The hierarchical specification allows model groups (JSON part models) to be reused for different parts.
For example, one hand model (shoulder:upper_arm:elbow:forearm:palm:finger[1.5]
) can be used for both left and right hands;
left_hand:finger1
can be for the left thumb and right_hand:finger1
for the right thumb.
The intermediate parents in the hierarchical specification can be skipped.
Model variable names¶
tx
,ty
,tz
: translation x, y, z (movement).rx
,ry
,rz
: rotation x, y, z (spin, yaw, pitch).sx
,sy
,sz
: scale x, y, z (size).visible
: show model and submodels (boolean).visible_boxes
: show model only; this does not affect submodels (boolean).
Added in version H9: visible
and visible_boxes
Entity variables¶
Warning
Entity variables are not supported for block entities.
Entity variables are user-defined variables that contain a formula that is calculated every frame. These variables are associated with the rendered entity in-memory. They are not "stored" with the entity in the game itself; unloading and reloading the world will reset them.
Entity variables can be specified in 2 formats:
var.<name>
for floats (decimals, numbers).varb.<name>
for booleans (true, false).
Where <name>
may be any string; var.xyz
, var.last_rx
, var.cookies_in_the_cookie_jar
are all valid entity variables.
Their default value when first calculated is 0
or false
for var
and varb
, respectively.
For instance, the first calculation of "var.xyz": "var.xyz + 1"
is 1
(var.xyz = 0; var.xyz + 1 = 0 + 1 = 1
.
Entity variables are useful for storing animation data between frames or storing constants for animation configuration.
Added in version H9: varb
Render variables¶
Added in version H9.
render.shadow_size
: The size of the entity's shadow; this is a float from1.0
(opaque) to0.0
(invisible).render.shadow_opacity
: The opacity (solidness) of the entity's shadow.render.leash_offset_x
: When leashed, where the leash on the entity attachs to.render.leash_offset_y
render.leash_offset_z
render.shadow_offset_x
: An offset of the entity's shadow position.render.shadow_offset_z
Values¶
Expressions make up the values of the items in the objects in the "animations" list. They are general mathematical expressions with brackets, constants, variables, operators, parameters, and functions.
Hint
They most closely resemble the AsciiMath format, although they are not identical.
Optionally-grouped variables, constants, parameters, and functions are separated by operators and evaluated as normal math expressions.
For example, sin(35)+max(5,50,500)
evaluates to 500.5735764
.
Constants¶
Constants never change and always evaluate to the same value.
Name |
Type |
Meaning |
---|---|---|
|
Float, constant |
Floating point, equal to |
|
Boolean, constant |
Truthy boolean. |
|
Boolean, constant |
False boolean. |
Variables¶
Variables change and are most often used to change something with time.
Not to be confused with
Keys; these are expression variables.
Name |
Type |
Meaning |
---|---|---|
|
Any |
A model variable's value, see the Model variables section. |
|
Integer, ticks |
The total game time in ticks ( |
|
Integer, ticks |
|
|
Integer |
|
Render parameters¶
Render parameters are variables whose values are generally independent of the entity being rendered, but not always.
Name |
Type |
Meaning |
---|---|---|
|
Float |
Counts up in ticks from 0 as the entity continues to move. |
|
Float |
The current speed of the entity's limbs. Ranges from |
|
Float |
How long the entity has existed in the world, in ticks. |
|
Float |
Head yaw; x rotation. |
|
Float |
Head pitch; y rotation. |
|
Float |
|
|
Float |
|
|
Float |
|
|
Float |
|
|
Float |
|
|
Float |
|
|
Integer |
|
|
Integer |
|
Entity parameters¶
Entity parameters are variables that are generally unique to the entity itself: is the entity glowing, is it angry, etc.
Name |
Type |
Meaning |
---|---|---|
Floats |
||
|
Float |
Entity's current health. |
|
Float |
Time stage of when entity has been hurt once. Counts down from 10 to 0. |
|
Float |
|
|
Float |
|
|
Float |
Entity's maximum health. |
|
Float |
How much entity is moving forwards-backwards, currently broken. |
|
Float |
How much entity is moving left-right, currently broken. |
|
Float |
Entity's X position. |
|
Float |
Entity's Y position. |
|
Float |
Entity's Z position. |
|
Float |
|
|
Float |
|
|
Float |
How far through the attack animation the entity is; counts up from |
|
Float |
|
Booleans |
||
|
Boolean |
|
|
Boolean |
If the entity is alive; not dead. |
|
Boolean |
If the entity is burning. |
|
Boolean |
If the entity is a child. |
|
Boolean |
If the entity has the Glowing status effect. |
|
Boolean |
If the entity is taking damage. |
|
Boolean |
If the entity (items) is being held in your hand. |
|
Boolean |
|
|
Boolean |
If the entity is embedded into a block (arrows, tridents). |
|
Boolean |
If the entity is inside the GUI |
|
Boolean |
If the entity is touching lava. |
|
Boolean |
If the entity is touching water. |
|
Boolean |
If the entity has the Invisibility status effect. |
|
Boolean |
If the entity is on the ground; not flying. |
|
Boolean |
|
|
Boolean |
|
|
Boolean |
If the entity is being ridden by another entity. |
|
Boolean |
If the entity is riding atop of another entity. |
|
Boolean |
|
|
Boolean |
If the entity (cats) is crouching/sneaking. |
|
Boolean |
If the entity (cats) is sprinting. |
|
Boolean |
|
|
Boolean |
If the entity is under rain or is inside a water block. |
Operators¶
Name |
Meaning |
---|---|
|
add, subtract, multiply, divide, modulo |
|
negate, logical AND, logical OR |
|
greater than, greater than or equal to, less than, less than or equal to, is equal to, is not equal to |
Numerical functions¶
These functions return a number.
Name |
Parameters |
Return |
---|---|---|
|
|
Sine of degrees |
|
|
Cosine of degrees |
|
|
Arcsine of degrees |
|
|
Arccosine of degrees |
|
|
Tangent of degrees |
|
|
Arctangent of degrees |
|
|
Two-argument arctangent of |
|
|
|
|
|
|
|
|
The minimum of all given parameters. |
|
|
The maximum of all given parameters. |
|
|
|
|
|
The absolute value of |
|
|
The floor of |
|
|
The ceiling of |
|
|
e (Euler's constant) raised to the power of |
|
|
The decimal of |
|
|
The logarithm of |
|
|
Raise base |
|
|
|
|
|
Rounded |
|
|
The sign of |
|
|
The square root of |
|
|
Similar to Java's floorMod function, |
|
|
|
|
|
Select a value based on one of more conditions: return |
|
|
|
|
|
|
Boolean functions¶
These functions return either true or false.
Name |
Parameters |
Tests |
---|---|---|
|
|
Is |
|
|
Is the difference of |
|
|
Is |
Examples¶
Basic structure¶
{
"animations": [
{
"this.rx": "clamp(-0.5 * part.rx, 0, 90)",
"this.tx": "3 * sin(limb_swing / 4) - 2",
"this:Hoof.rx": "if(leg4:Hoof.rx > 90, leg4:Hoof.rx - 90, 0)"
}
]
}
Walking animation¶
x
is a multipler to control how fast the leg swings back and forth,
and y
is a multiplier to control how far it swings back and forth.
"left_leg.rx": "sin(limb_swing * x) * limb_speed * y"
Attack animation¶
x
is a multipler for how much it rotates.
"head.rx": "sin(swing_progress * pi) * x"
Hurt animation¶
x
is a multipler for how much it rotates.
"head.rx": "-sin(hurt_time / pi) * x"
Custom counter¶
This is a counter that will count up while an entity is in water, and count down again when it leaves.
"var.counter": "if(is_in_water, min(20, var.counter + 0.1 * frame_time * 20), max(0, var.counter - 0.1 * frame_time * 20))"
If statements¶
The leg will rotate by 45 degrees when the entity is not on the ground, otherwise it will stay at 0 deg.
"left_leg.rx": "if(!is_on_ground, torad(45), 0)"
The body will tilt forwards once the entity hits a certain movement speed.
"body.rx": "if(limb_speed > 0.7, torad(20), 0)"
Tutorial¶
JSON schema¶
{
"$schema": "http://json-schema.org/draft/2020-12/schema",
"$id": "https://gitlab.com/whoatemybutter/optifinedocs/-/blob/master/schemas/cem_anim.schema.json",
"title": "Custom Entity Models Animation",
"description": "CEM Animations change how a custom entity model walks, swims, idles, etc.",
"type": "object",
"properties": {
"animations": {
"type": "array",
"items": {
"type": "object",
"patternProperties": {
"^(this|part|[0-9a-zA-Z_]*((:[0-9a-z-A-Z_])*)?)\\.(t[xyz]|r[xyz]|s[xyz])$": {
"$ref": "#/$defs/expression"
},
"^(this|part|[0-9a-zA-Z_]*((:[0-9a-z-A-Z_])*)?)\\.(render\\.(shadow_size|shadow_opacity|leash_offset_[xyz]|shadow_offset_[xz]))$": {
"$ref": "#/$defs/expression"
},
"^(this|part|[0-9a-zA-Z_]*((:[0-9a-z-A-Z_])*)?)\\.(visible|visible_boxes)$": {
"type": "boolean"
},
"^varb?\\.(.+)$": {
"$ref": "#/$defs/expression"
}
}
}
}
},
"$defs": {
"expression": {
"type": "string",
"minLength": 1,
"anyOf": [
{
"pattern": "pi|true|false|time|day_time|day_count"
},
{
"pattern": "(this|part|[0-9a-zA-Z_]*((:[0-9a-z-A-Z_])*)?)\\.(.*?)"
},
{
"pattern": "limb_swing|limb_speed|age|head_yaw|head_pitch|player_pos_[xyz]|player_rot_[xyz]|frame_time|dimension|rule_index"
},
{
"pattern": "(max_)?health|(hurt|death|anger)_time|move_(forward|strafing)|pos_[xyz]|rot_[xy]|swing_progress|id"
},
{
"pattern": "is_(aggressive|alive|burning|child|glowing|hurt|in_(hand|item_frame|ground|gui|lava|water)|invisible|on_(head|shoulder|ground)|ridden|riding|sitting|sneaking|sprinting|tamed|wet)"
},
{
"pattern": "\\+|-|\\*|\/|%|add|subtract|multiply|divide|!|&&|\\|\\||[<>]=?|[!=]="
},
{
"pattern": "(sin|cos|asin|acos|tan|atan|to(rad|deg)|abs|floor|ceil|exp|frac|log|random|round|signum|sqrt)\\((-?\\d+(.\\d+)?)\\)"
},
{
"pattern": "(atan2|pow|fmod)\\((-?\\d+(.\\d+)?), (-?\\d+(.\\d+)?)\\)"
},
{
"pattern": "printb?\\((.*?), ?(-?\\d+(.\\d+)?), ?(.*?)\\)"
},
{
"pattern": "i[fn]\\(((.*?), ?(.*?))+\\)"
},
{
"pattern": "lerp|clamp|between|equals\\((-?\\d+(.\\d+)?), ?(-?\\d+(.\\d+)?), ?(-?\\d+(.\\d+)?)\\)"
},
{
"pattern": "m(in|ax)\\(((-?\\d+(.\\d+)?)(?:,\\s*(-?\\d+(.\\d+)?))?)\\)"
},
{
"pattern": "-?\\d+(.\\d+)?"
}
]
}
},
"additionalProperties": false
}