Animation¶
He has the bends.¶
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):
For example, in the object {"a": 5}, "a" is the key and 5 is the value.
"animations": [
{
"variable1": "expression1",
"variable2": "expression2"
}
]
Essentially, we are writing equations in JSON:
head.rx = swing_progress * 3 will be transformed into a key-value pair of "head.rx": "swing_progress * 3".
In this, head.rx is the destination or key, and swing_process * 3 is the source or value or expression.
Note
Some headers use {a, b, c}. This means it may be any one of these options (e.x. pos_{x, y, z} means pos_x or pos_y or pos_z).
Key: destination¶
The keys of the objects in the "animations" list are the targets for their value's expression. They are strings that refer to different values that control an entity.
Model, arbitrary, and render variables are all valid options.
Model variables¶
Model variables are specified in the format MODEL_TARGET.MODEL_VARIABLE. They refer to specific parts of the model.
Model target names¶
The first model found by part name or ID is used if there are duplicates.
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.
Name |
Description |
|---|---|
|
The current custom model. |
|
The original part model to which the custom model is attached. |
<part name> |
Placeholder; a part name. |
<id> |
Placeholder; the custom model by ID. |
<part name>:<id>:... |
Placeholders; hierarchical query for nested parts by their names and sub-IDs. There may be any number of |
<id>:<id>:... |
Placeholders; hierarchical query for nested parts by their ID and sub-IDs. There may be any number of later |
Model variable names¶
- tx, ty, tz¶
Translation in X, Y, Z coordinates (movement).
- sx, sy, sz¶
Scale in X, Y, Z coordinates (size).
- rx, ry, rz¶
Rotation in X, Y, Z coordinates (spin, yaw, pitch).
- visible¶
Whether to show model and submodels.
- visible_boxes¶
Whether to show this model box only and not affect submodels; boolean.
Arbitrary variables¶
Warning
Arbitrary variables are not supported for block entities.
Arbitrary 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.
They may be useful for storing animation data between frames or storing constants for animation configuration.
The placeholder NAME may be any valid string.
- var.NAME¶
Arbitrary variable name that stores floats.
Uninitialized value is
0. Therefore, The first calculation of"var.xyz": "var.xyz + 1"is1(var.xyz = 0; var.xyz + 1 => 0 + 1 = 1).
- varb.NAME¶
Arbitrary variable name that stores booleans.
Render variables¶
- render.shadow_size¶
The size of the entity's shadow.
- render.shadow_opacity¶
The opacity (alpha) of the entity's shadow.
- render.shadow_offset_{x, z}¶
An offset of the entity's shadow position.
- render.leash_offset_{x, y, z}¶
When leashed, where the leash on the entity attachs to.
Values: source¶
The values of the objects in the "animations" list are expressions that are evaluated and stored in their corresponding keys. They are strings of general mathematical expressions with brackets, constants, variables, operators, parameters, and functions.
For example, sin(35) + max(5, 50, 500) evaluates to 500.5735764.
Hint
They most closely resemble the AsciiMath format, although they are not identical.
Constants¶
Constants never change and always evaluate to the same value.
Note
A literal (such as 5) is also a constant, but has no special meaning apart from its value.
- true¶
True value.
- false¶
False value.
Variables¶
Variables are globally accessible names that can change.
Not to be confused with
Keys; these are to be used in expressions.
- MODEL.VAR¶
Another model variable's value, see the Model variables section.
Important
MODELandVARare placeholders.
- age¶
How long the entity has existed in the world for the client, in ticks.
- anger_time¶
The time the entity has been angry. 0 while neutral, 400 to 720 while aggressive, counts down to 0 when the target is lost.
- day_count¶
How many days have passed in this world.
- day_time¶
The current day time.
- death_time¶
Time stage on entity's death. Counts up from 0 to 20.
- dimension¶
Dimension ID.
ID
Dimension
1
The End
0
Overworld
-1
Nether
- frame_counter¶
Index of the current frame, wraps around at 10 minutes (0 to 27719).
- frame_time¶
Time in seconds since the last frame.
- head_yaw¶
Head yaw; X rotation.
- head_pitch¶
Head pitch; Y rotation.
- health¶
Current health.
- hurt_time¶
Time stage of when entity has been hurt once. Counts down from 10 to 0.
- id¶
A unique numeric identifier.
- is_aggressive¶
If the entity is aggressive towards another entity.
- is_alive¶
If the entity is alive; not dead.
- is_burning¶
If the entity is burning.
- is_child¶
If the entity is a child.
- is_hurt¶
If the entity is taking damage.
- is_in_hand¶
Item: if the entity is being held in the player's hand.
- is_in_item_frame¶
Item: if the entity is in an item frame.
- is_in_ground¶
Arrow, trident: if the entity is embedded into a block.
- is_in_gui¶
If the entity is inside the GUI
- is_in_lava¶
If the entity is touching lava.
- is_in_water¶
If the entity is touching water.
- is_invisible¶
If the entity has the Invisibility status effect.
- is_on_ground¶
If the entity is on the ground; not flying.
- is_on_head¶
Item: if the entity is on an armor head slot.
- is_on_shoulder¶
Parrot: if the entity is on a player's shoulder.
- is_ridden¶
If the entity is being ridden by another entity.
- is_riding¶
If the entity is riding atop of another entity.
- is_sitting¶
Cat, wolf, parrot: if the entity is sitting.
- is_sneaking¶
Cat, ocelot: if the entity crouching.
- is_sprinting¶
Cat, ocelot: if the entity is sprinting.
- is_tamed¶
Cat, wolf, parrot: if the entity is tamed.
- is_wet¶
If the entity is under rain or is touching water.
- limb_swing¶
Counts up in ticks from 0 as the entity continues to move.
- limb_speed¶
The current speed of the entity's limbs. Ranges from
0.0(still) to1.0(sprinting).
- max_health¶
Entity's maximum health.
- player_pos_{x, y, z}¶
Player's X, Y, Z position (not necessarily the same entity).
- player_rot_{x, y}¶
- pos_{x, y, z}¶
Entity's X, Y, Z position.
- rot_{x, y}¶
- rule_index¶
The index of the current matching random models rule.
- swing_progress¶
How far through the attack animation the entity is; counts up from 0.0 to 1.0.
- time¶
The total game time in ticks; not related to the daylight cycle.
Operators¶
Operators are symbols that operate on numbers. They are infix functions.
+: Add-: Subtract*: Multiply/: Divide%: Modulo!: Negate&&: Logical AND||: Logical OR<: Less than<=: Less than or equal to>: Greater than>=: Greater than or equalt o==: Equality!=: Inequality
Functions¶
- atan(x: number) number¶
Arctangent of
x.>>> atan(1.1917) 49.99873126...
- atan2(y: number, x: number) number¶
Two-argument arctangent of
yandx.>>> atan2(1, 3) 0.3217505544...
- clamp(x: number, min: number, max: number) number¶
The clamped value of
x, guaranteed to be betweenminandmaxvalues:If
x > max, returnx = maxIf
x < min, returnx = min
>>> clamp(6, 1, 5) 5 >>> clamp(4, -8, 10) 4
- abs(x: number) number¶
Absolute value of
x.If
x < 0, return-xIf
x >= 0, return`x`
>>> abs(-25.3) 25.3
- exp(x: number) number¶
Euler's constant (e) raised to the power of
x; \(e^x\)>>> exp(4) 54.59815003...
- frac(x: number) number¶
The fractional part (decimal) of
x.>>> frac(3.25) 0.25 >>> frac(-9.99992) -0.99992
- pow(base: number, power: number) number¶
Raise
baseto the powerpower; \(\mathit{base}^{\mathit{power}}\)>>> pow(4, 5) 1024 >>> pow(-53, 3) -148877
- random(seed: number | None) number¶
A random number between 0.0 and 1.0. Parameter
seedis optional and if given, randomizer is seeded with this value.>>> random() 0.53235...
- sqrt(x: number) number¶
The square root of positive
x.>>> sqrt(25) 5 >>> sqrt(27.5) 5.244044241...
- fmod(x: number, y: number) number¶
Java's floorMod function of
xandy. See linked Javadoc.>>> fmod(4, 3) 1 >>> fmod(4, -3) -2 >>> fmod(-4, -3) -1
- lerp(k: number, x: number, y: number) number¶
The linear interpolation of
kbetween the interval [x,y]:\(\left(\left(1 - k\right) \times x\right) + \left(k \times y\right)\)
- if(cond: predicate, val: number, **conds: predicate, val_else: number) number¶
Select a value based on one of more conditions (predicates):
Return
valifcondis true, else...Return
val2ifcond2is true, else...exhaust all condition pairs, else...
Return
val_elseif all ofcondare false
Additional isolated conditions may be specified as additional two-pair of
predicate, value. The first condition pair that is true is returned. If no pairs are true,val_elseis returned.A predicate is an expression that evaluates to a boolean (true or false). For example,
limb_speed > 0.7.>>> if(limb_speed > 0.7, 5, 0) 5 >>> if(true, 9, false, 3, 0) 9 >>> if(false, 0, true, 1, 2) 1 >>> if(false, 0, false, 1, false, 2, 3) 3
- ifb(cond: predicate, val: boolean, **conds: predicate, val_else: boolean) boolean¶
Select a boolean value based on one of more conditions (predicates):
Return
valifcondis true, else...Return
val2ifcond2is true, else...exhaust all condition pairs, else...
Return
val_elseif all ofcondare false
Additional isolated conditions may be specified as additional two-pair of
predicate, value. The first condition pair that is true is returned. If no pairs are true,val_elseis returned.A predicate is an expression that evaluates to a boolean (true or false). For example,
limb_speed > 0.7.>>> ifb(limb_speed > 0.7, true, false) true >>> ifb(true, false, true) false >>> ifb(1 > 0, false, true) false >>> ifb(0 == -1, false, 1 == -1, true, -1 == -1, true, false) true
- print(id: number, n: int, x: number) None:¶
Print number
xto the output log everyn-th frame, qualified withid.
- printb(id: int, n: int, x: boolean) None:¶
Print boolean
xto the output log everyn-th frame, qualified withid.
- between(x: number, min: number, max: number) boolean¶
Is
xbetweenminandmax; \(\mathit{min} <= x <= \mathit{max}\)>>> between(4, 0, 10) true >>> between(5, 1, 3) false
- equals(x: number, y: number, margin: number) boolean¶
Is the difference of
xandywithin error marginmargin; \(|x - y| < \mathit{margin}\)>>> equals(3, 6, 4) true >>> equals(0.05, 10, 10) true >>> equals(0.83, 0.06, 0.2) false
- in(x: number, *val: number) boolean¶
Is
xequal to any ofval?>>> in(1, 2, 3, 4, 1) true >>> in(7, 6, 4, 0) false
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)"
External links¶
Warning
These resources are not related to OptiDocs, but may provide some help.