↷ 2. Sections

↷ 3. List of infix notation operators

↷ 4. List of functions

↷ 5. List of variables

↷ 6. Performance

↷ 7. Tips

↷ 8. Example functions

↷ 9. Formal Grammar

Animated objects can be used in CSV/RW routes (unless explicitly disallowed by some commands), as train exterior objects via the

● | State changes - basically allowing to switch between different objects at any time |

● | Translation - moving objects in three independent directions |

● | Rotation - rotating objects around three independent axes |

● | Texture shifts - allowing to shift the texture coordinates of objects in two independent directions |

You can use the [Include] section to just include other objects, but without animating them. This allows you to use the ANIMATED object file as a container to group other objects. There can be any number of [Include] sections within the file.

[Include] |

FileName_{0}FileName_{1}FileName_{2}... |

Position = X, Y, Z |

You can use the [Object] section to create a single animation. This requires to set up at least one state via the

[Object] |

Position = X, Y, Z |

States = File, _{0}File, ..., _{1}File_{n-1} |

StateFunction = Formula |

TranslateXDirection = X, Y, ZTranslateYDirection = X, Y, ZTranslateZDirection = X, Y, Z |

This means that TranslateXFunction will move right by default, TranslateYFunction up and TranslateZFunction forward, which is also why TranslateXFunction and so on bear their names. If you define other directions, then simply think of the three functions and associated directions as three independent ways to move the object in that direction.

TranslateXFunction = FormulaTranslateYFunction = FormulaTranslateZFunction = Formula |

RotateXDirection = X, Y, ZRotateYDirection = X, Y, ZRotateZDirection = X, Y, Z |

This means that RotateXFunction will rotate around the x-axis by default, RotateYFunction around the Y-axis, and RotateZFunction around the z-axis, which is also why RotateXFunction and so on bear their names. If you define other directions, then simply think of the three functions and associated directions as three independent ways to rotate the object.

RotateXFunction = FormulaRotateYFunction = FormulaRotateZFunction = Formula |

RotateXDamping = NaturalFrequency, DampingRatioRotateYDamping = NaturalFrequency, DampingRatioRotateZDamping = NaturalFrequency, DampingRatio |

TextureShiftXDirection = X, YTextureShiftYDirection = X, Y |

This means that TextureShiftXFunction will shift the texture right by default, and TextureShiftYFunction down, which is also why TextureShiftXFunction and so on bear their names. If you define other directions, then simply think of the two functions and associated directions as two independent ways to shift textures on the objects.

TextureShiftXFunction = FormulaTextureShiftYFunction = Formula |

TrackFollowerFunction = Formula |

TextureOverride = Value |

RefreshRate = Seconds |

⚠ | openBVE 2 compatibility note: During the development of openBVE (v0.9) and during the development of the animated object format, there were certain commands in existance ending in RPN, such as TranslateXFunctionRPN. These commands never made it into any official release (v1.0) and were thus never meant to be used outside of development environments. While they are still available undocumentedly, they will be removed for openBVE 2. If you are using these commands, please get rid of them as soon as possible. |

⚠ | Please note that if the result of any mathematical operation or function would be infinity, indeterminate or non-real, 0 is returned. Numeric overflow is not prevented, so you need to take that into account yourself. |

Infix | Functional | Description |
---|---|---|

a + b | Plus[a,b, ...] | Represents addition |

a - b | Subtract[a,b] | Represents subtraction |

-a | Minus[a] | Negates the number |

a * b | Times[a,b,...] | Represents multiplication |

a / b | Divide[a,b] | Represents division |

Infix | Functional | Description |
---|---|---|

a == b | Equal[a,b] | True (1) if a equals b |

a != b | Unequal[a,b] | True (1) if a does not equal b |

a < b | Less[a,b] | True (1) if a is less than b |

a > b | Greater[a,b] | True (1) if a is greater than b |

a <= b | LessEqual[a,b] | True (1) if a is less than or equal to b |

a >= b | GreaterEqual[a,b] | True (1) if a is greater than or equal to b |

Infix | Functional | Description |
---|---|---|

!a | Not[a] | True (1) if a is false |

a & b | And[a,b] | True (1) if both a and b are true |

a | b | Or[a,b] | True (1) if any of a or b are true |

a ^ b | Xor[a,b] | True (1) if either a or b is true |

a[...] |

- (Minus) |

/ |

* |

+, - (Subtract) |

==, !=, <, >, <=, >= |

! |

& |

^ |

| |

⚠ | Please note that some combinations of prefix and infix operators are not recognized. For example a*-b is not accepted. Use a*(-b) or -a*b instead. |

Function | Description |
---|---|

Reciprocal[x] | Returns the reciprocal, equal to 1/x |

Power[a,b,...] | Returns a raised to the b^{th} power. b must be a non-negative number. For consistency, Power[0,b] always returns 1, even in the degenerate case Power[0,0], and a being negative always returns 0. Adding more arguments will create a chain. Power[a,b,c] will return a^{bc}. |

Function | Description |
---|---|

Quotient[a,b] | Divides a by b and rounds the result down, equal to Floor[a/b]. |

Mod[a,b] | Returns the remainder of dividing a by b, equal to a-b*Floor[a/b]. |

Min[a,b,...] | Returns the smallest of the terms. |

Max[a,b,...] | Returns the largest of the terms. |

Abs[x] | Returns the absolute value. |

Sign[x] | Returns the sign of x, which is either -1, 0 or 1. |

Floor[x] | Rounds down to the nearest integer. |

Ceiling[x] | Rounds up to the nearest integer. |

Round[x] | Rounds to the nearest integer. Numbers ending in .5 are rounded to the nearest even integer. |

random[Minimum, Maximum] | Returns a new random floating-point number between Minimum and Maximum. |

randomInt[Minimum, Maximum] | Returns a new random integer between Minimum and Maximum. |

Function | Description |
---|---|

Exp[x] | The exponential function, or e to the x^{th} power. |

Log[x] | The natural logarithm, to base e. |

Sqrt[x] | The square root. |

Sin[x] | The sine (input in radians). |

Cos[x] | The cosine (input in radians). |

Tan[x] | The tangent (input in radians). |

ArcTan[x] | The inverse tangent (output in radians). |

Function | Description |
---|---|

If[cond,truevalue,falsevalue] | If cond is != 0, returns truevalue, otherwise falsevalue |

Variable | Description |
---|---|

value | The value returned by the function in the last evaluation. At the beginning of the simulation, this is 0. |

delta | The time difference since the last evaluation of the function in seconds. Please note that there is no guaranteed time that elapses between successive function calls. |

currentState | Returns the current numerical state of the object. |

Variable | Description |
---|---|

time | The current in-game time measured in seconds since midnight of the first day. |

cameraDistance | The non-negative cartesian distance measured from the object to the camera in meters. |

cameraMode | Returns 0 if the camera is currently in a 2D or 3D cab, 1 otherwise. |

In some of the following variables,

Variable | Description |
---|---|

cars | The number of cars the train has. |

speed | The signed actual speed of the current car in m/s. Is positive when the train travels forward, and negative when the train travels backward. |

speed[carIndex] | The signed actual speed of the car carIndex in m/s. Is positive when the train travels forward, and negative when the train travels backward. |

speedometer | The signed perceived speed of the current car in m/s as it would appear to a speedometer on wheel slip and wheel lock. |

speedometer[carIndex] | The signed perceived speed of the car carIndex in m/s as it would appear to a speedometer on wheel slip and wheel lock. |

acceleration | The actual acceleration of the current car in m/s². |

acceleration[carIndex] | The actual acceleration of the car carIndex in m/s². |

accelerationMotor | The acceleration which the motor of the first motor car currently generates in m/s². |

accelerationMotor[carIndex] | The acceleration which the motor of the car carIndex currently generates in m/s². |

distance | The non-negative cartesian distance measured from the object to the closest car in meters. Only meaningful for scenery objects. |

distance[carIndex] | The non-negative cartesian distance measured from the object to the car carIndex in meters, or 0 if the car does not exist. Only meaningful for scenery objects. |

trackDistance | The signed track distance measured from the object to the closest end of the nearest train in meters. Is positive when the train is in front of the object, negative when behind, and zero when the object lies between the ends of the train. |

trackDistance[carIndex] | The signed track distance measured from the object to the car carIndex of the nearest train in meters. Is positive when the center of the car is in front of the object, and negative if behind. Returns 0 if the car does not exist. Only meaningful for scenery objects. |

Variable | Description |
---|---|

mainReservoir | The current pressure in the main reservoir in this car, measured in Pa. |

mainReservoir[carIndex] | The current pressure in the main reservoir in car carIndex, measured in Pa. |

emergencyReservoir | The current pressure in the emergency reservoir in this car, measured in Pa. |

emergencyReservoir[carIndex] | The current pressure in the emergency reservoir in car carIndex, measured in Pa. |

brakePipe | The current pressure in the brake pipe in this car, measured in Pa. |

brakePipe[carIndex] | The current pressure in the brake pipe in car carIndex, measured in Pa. |

brakeCylinder | The current pressure in the brake cylinder in this car, measured in Pa. |

brakeCylinder[carIndex] | The current pressure in the brake cylinder in car carIndex, measured in Pa. |

straightAirPipe | The current pressure in the straight air pipe in this car, measured in Pa. |

straightAirPipe[carIndex] | The current pressure in the straight air pipe in car carIndex, measured in Pa. |

Variable | Description |
---|---|

doors | The state of the doors. Returns 0 if fully closed, 1 if fully opened, or any intermediate value, biasing doors that are in a more open state. |

doors[carIndex] | The state of the doors of car carIndex. Returns 0 if fully closed, 1 if fully opened, or any intermediate value, biasing doors that are in a more open state. |

leftDoors | The state of the left doors. Returns 0 if fully closed, 1 if fully opened, or any intermediate value, biasing doors that are in a more open state. |

leftDoors[carIndex] | The state of the left doors of car carIndex. Returns a value between 0 and 1, biasing doors that are in a more open state, or -1 if the car does not exist. |

rightDoors | The state of the right doors. Returns 0 if fully closed, 1 if fully opened, or any intermediate value, biasing doors that are in a more open state. |

rightDoors[carIndex] | The state of the right doors of car carIndex. Returns a value between 0 and 1, biasing doors that are in a more open state, or -1 if the car does not exist. |

leftDoorsTarget | The anticipated target state of the left doors. Returns either 0 (closed) or 1 (opened). |

leftDoorsTarget[carIndex] | The anticipated target state of the left doors of car carIndex. Returns either 0 (closed) or 1 (opened). |

rightDoorsTarget | The anticipated target state of the right doors. Returns either 0 (closed) or 1 (opened). |

rightDoorsTarget[carIndex] | The anticipated target state of the right doors of car carIndex. Returns either 0 (closed) or 1 (opened). |

leftDoorsButton | The state of the left doors button. Returns either 0 (released) or 1 (pressed). |

rightDoorsButton | The state of the right doors button. Returns either 0 (released) or 1 (pressed). |

Variable | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|

reverserNotch | The state of the reverser, which is either -1 (backward), 0 (neutral), or forward (1). | |||||||||

powerNotch | The current power notch, i.e. 0 for N, 1 for P1, 2 for P2, 3 for P3, etc. | |||||||||

powerNotches | The amount of power notches the train has. | |||||||||

brakeNotch | The current brake notch.
| |||||||||

brakeNotches | The amount of brake notches the train has. For trains with the automatic air brake, this returns 2. | |||||||||

brakeNotchLinear | A combination of brake notch, hold brake and emergency brake.
| |||||||||

brakeNotchesLinear | The highest value returned by brakeNotchesLinear.
| |||||||||

emergencyBrake | Whether the emergency brake is currently active (1) or not (0). | |||||||||

hasAirBrake | Whether the train has the automatic air brake (1) or not (0). | |||||||||

holdBrake | Whether the hold brake is currently active (1) or not (0). | |||||||||

hasHoldBrake | Whether the train has a hold brake (1) or not (0). | |||||||||

constSpeed | Whether the const speed system is currently active (1) or not (0). | |||||||||

hasConstSpeed | Whether the train has a const speed system (1) or not (0). | |||||||||

hasPlugin | Whether the train uses a plugin (1) or not (0). | |||||||||

pluginState[i] | The state of the i^{th} plugin variable, returning an integer depending on the plugin. Is the same as atsi in the panel2.cfg. | |||||||||

FrontAxleCurveRadius[carIndex] | Returns the curve radius at the front axle position of car carIndex. | |||||||||

RearAxleCurveRadius[carIndex] | Returns the curve radius at the rear axle position of car carIndex. | |||||||||

CurveCant[carIndex] | Returns the cant value for car carIndex. | |||||||||

Odometer | Returns a signed number representing the distance in meters travelled by the current car. | |||||||||

Odometer[carIndex] | Returns a signed number representing the distance in meters travelled by car carIndex. | |||||||||

Klaxon | Returns the currently playing horn (if any) as follows: (0) No horns are playing (1) The primary horn is playing (2) The secondary horn is playing (3) The music horn is playing. Note If multiple horns are playing, the lowest value will be returned. | |||||||||

PrimaryKlaxon | Returns 1 if the primary horn is currently playing, 0 otherwise. | |||||||||

SecondaryKlaxon | Returns 1 if the secondary horn is currently playing, 0 otherwise. | |||||||||

MusicKlaxon | Returns 1 if the music horn is currently playing, 0 otherwise. |

If

i | English | 日本語 | Return values | pluginState[271] | Meaning | |
---|---|---|---|---|---|---|

256 | ATS | ATS | 0 (unlit) or 1 (lit) | 0 | ATC not available | |

257 | ATS RUN | ATS 作動 | 0 (unlit), 1 (lit) or 2 (flashing) | 1 | 0 km/h | |

258 | ATS RUN | ATS 作動 | 0 (unlit / non-flashing), 1 (lit / flashing) | 2 | 15 km/h | |

259 | P POWER | P 電源 | 0 (unlit) or 1 (lit) | 3 | 25 km/h | |

260 | PTN APPROACH | パターン接近 | 0 (unlit) or 1 (lit) | 4 | 45 km/h | |

261 | BRAKE RELEASE | ブレーキ開放 | 0 (unlit) or 1 (lit) | 5 | 55 km/h | |

262 | BRAKE APPLY | ブレーキ動作 | 0 (unlit) or 1 (lit) | 6 | 65 km/h | |

263 | ATS P | ATS-P | 0 (unlit) or 1 (lit) | 7 | 75 km/h | |

264 | FAILURE | 故障 | 0 (unlit) or 1 (lit) | 8 | 90 km/h | |

265 | ATC | ATC | 0 (unlit) or 1 (lit) | 9 | 100 km/h | |

266 | ATC POWER | ATC 電源 | 0 (unlit) or 1 (lit) | 10 | 110 km/h | |

267 | ATC SRV | ATC 常用 | 0 (unlit) or 1 (lit) | 11 | 120 km/h | |

268 | ATC EMG | ATC 非常 | 0 (unlit) or 1 (lit) | 12 | ATS is active | |

269 | CONST SPEED | 定速 | 0 (unlit) or 1 (lit) | |||

270 | EB | EB | 0 (unlit) or 1 (lit) | |||

271 | ATC speed indicator | 0 - 12, see table on the right |

Variable | Description |
---|---|

section | The value of the section aspect currently shown.If this variable is used outside of a Track.SigF context, the behavior is currently undefined and subject to change. |

Animation | Object | Performance |
---|---|---|

State changes | Has only opaque faces | Good |

State changes | Has partially transparent faces | Moderate |

Translation | Has only opaque faces | Good |

Translation | Has partially transparent faces | Moderate |

Rotation | Has only opaque faces | Good |

Rotation | Has partially transparent faces | Bad |

Texture shifts | Has only opaque faces | Bad |

Texture shifts | Has partially transparent faces | Bad |

Performance is generally better if the result of a function only infrequently changes. So, even if you set the

Generally, you should avoid using animation with partially transparent faces and stick to opaque faces when possible. Also, try to avoid texture shifts, and consider using state changes or translation where possible.

● | Generally speaking, try to keep the complexity of functions as low as possible. This is not the most critical aspect, though, as most of the performance impact will result from applying the results of a function, e.g. rotating the object, and not evaluating the function. |

● | Use the RefreshRate parameter when possible to optimize performance. Usually, you can use this parameter when you don't need a smooth animation, or when you deliberately want the functions to only update in intervals. |

● | Don't use functions which always evaluate to the same constant. For example, don't use RotateXFunction = 3.14159, but rotate the underlying CSV/B3D/X object directly. |

● | State changes are very cheap as long as the state doesn't actually change in between two executions of the StateFunction. If a change occurs, this is a relatively expensive operation, though. |

● | Try to optimize out if conditions. Especially try to avoid nested if functions. Often, there is an elegant mathematical solution. |

● | Certain functions, e.g. Exp, Sin, Cos, etc., are relatively expensive. Use them only if absolutely necessary for an effect. Don't include unnecessary operations. For example, the result of StateFunction is automatically rounded toward the nearest integer, so don't apply an additional explicit Round. |

● | When working with car objects, bear in mind that some variables have an optional car index. You should use this index if you want to query the state of a particular car (that is, not necessarily the one the object is attached to). If, however, you just want to query the value of the particular car the object is attached to, use the variable without the index. For scenery objects, you should not generally use car indices as you can't be sure how many cars the queried train has. |

Template for a blinking light:
| |

▶ |
States = OBJECT0, OBJECT1StateFunction = value == 0 RefreshRate = SECONDS |

Template for the code used in an exterior car object:
| |

▶ |
States = OBJECTRotateXFunction = value + delta * speedometer / RADIUS_OF_THE_WHEEL |

Template for objects that are to be cycled through:
| |

▶ |
States = OBJECT0, OBJECT1, OBJECT2, ...StateFunction = mod[value + 1, AMOUNT_OF_OBJECTS]RefreshRate = TIME_PER_OBJECT |

▶ |
States = RED_OBJECT, YELLOW_OBJECT, GREEN_OBJECTStateFunction = section / 2 |

Template for an approach-controlled delay in a signal with two aspects:
| |

▶ |
States = RED_OBJECT, GREEN_OBJECTStateFunction = if[trackDistance>DISTANCE | section==0, 0, min[value + 0.5*delta/DELAY, 1]] |

Template for an approach-controlled delay in a signal with any number of aspects:
| |

▶ |
States = RED_OBJECT, ..., GREEN_OBJECTStateFunction = if[trackDistance>DISTANCE | section==0, 0, if[value<0.5, value + 0.5*value/DELAY, section]] |

The formal grammar for the language may not match up perfectly with the implimentation included in OpenBVE. An example is a*-b which is valid under the grammar but the parser rejects it. |

▶ |
<expression> ::= <xor_expression> "" <expression> | <xor_expression><xor_expression> ::= <or_expression> "^" <xor_expression> | <or_expression> <or_expression> ::= <not_expression> "|" <or_expression> | <not_expression> <not_expression> ::= "!" <equal_expression> | <equal_expression> <equal_expression> ::= <plus_expression> "==" <equal_expression> | <plus_expression> "!=" <equal_expression> | <plus_expression> ">" <equal_expression> | <plus_expression> "<" <equal_expression> | <plus_expression> "<=" <equal_expression> | <plus_expression> "<=" <equal_expression> | <plus_expression> <plus_expression> ::= <times_expression> "+" <plus_expression> | <times_expression> "-" <plus_expression> | <times_expression> <times_expression> ::= <divide_expression> "*" <times_expression> | <divide_expression> <divide_expression> ::= <minus_expression> "/" <divide_expression> | <minus_expression> <minus_expression> ::= "-" <function_call> | <function_call> <function_call> ::= <name> "[" <expression> ("," <expression>)* "]" | <term> <term> ::= "(" <expression> ")" | <name> | <number> <number> ::= <digit>* <name> ::= <letter> (<letter> | <digit>)* <letter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" <digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |