# File Formats

- Legend
- File Types
- Game Config
- Scene
  - Node
  - Camera
  - Light
- Materials
- Physics
  - Collision Objects
  - Constraints
- Animation
  - Animation Clip
- Audio
- Drawables
  - Terrain
  - Sprite
  - TileSet
  - Text
  - Particles
- UI Forms
  - Form
  - Theme

## Legend

Legend |
--- | ---
[0..1] | Zero or one. Denotes an optional property.
[0..*] | Zero or many. The property may appear many times.
[1..*] | One or many. Required property and may appear many times.
required | Required property.
Italics | Non-literal
// Comment | Just like in C++
A | B | C | A or B or C. (Shows the valid enumeration values)

Types |
--- | ---
block | A block property that contains other properties.
string | A string of characters with no quotations.
bool | true or false
float | Floating point number. Decimal is optional, don't include "f".
int | Integer
uint | Unsigned integer
axis angle | Rotation axis angle (4 floats): x, y, z, angle_in_degrees
color | Hex color in the format #RRGGBBAA. (#FF6A00FF)
ref | Reference within the current file.

xref

External reference.
This can be

- a file path (res/common/game.scene)
- a reference to a named object in a property file (res/common/duck)
- a deep reference to a named object in a property file (res/common/game.scene#city/fifth_ave/empire_state_building)

lua xref | External reference to a lua function.
file path | A path to a file. This should be a relative path for the purpose of being cross platform.

image path

A path to an image.

- A file path (res/wood.png)
- An alias for an image that will be defined in game config file for the purpose of using different compressed textures on different platforms. (@wood).

Note:

- The order of the properties does not matter.
- Blocks do not require an id.

## File Types

Gameplay property files | blocks
--- | ---
.config | Game config definitions. | window, graphics, scripts, aliases, gamepads, ui
.scene | Scene definition | scene, node, physics, camera, light
.material | Material definitions | material, technique, pass
.physics | Collision objects and physics constraints | physics, collisionObject, constraint
.animation | Animation and animation clip definitions | animation, clip
.audio | Audio source definitions | audio
.sprite | Sprite definitions | sprite
.tileset | TileSet definitions | tileset
.particle | Particle emitter definitions | particle
.form | UI form definitions | form
.theme | UI theme definitions | theme

Gameplay files
.gpb | Gameplay Bundle | Binary encoded scene that is created by the gameplay-encoder from a .fbx file.
.vert | Vertex shader | GLSL vertex shader source.
.frag | Fragment shader | GLSL fragment shader source.

Other file extensions
.fbx | Autodesk FBX Scene
.tmx | Tiled "Tile Map XML"
.ttf | TrueType Font
.lua | Lua Script
.png .dds, .pvr | Compressed Texture

## Game Config

window |  |
{ |  |
width = pixels | [0..1] | int
height = pixels | [0..1] | int
x = x_offset_from_top_left | [0..1] | int
y = y_offset_from_top_left | [0..1] | int
fullscreen = bool | [0..1] | bool
resizable = bool | [0..1] | bool
title = Hello World | [0..1] | string
samples = multisampling_state | [0..1] | int
} |  |

graphics |  |
{ |  |
shaderDefines = semicolon separated list | [0..1] | string
} |  |

scripts |  |
{ |  |
initialize = res/game.lua#initialize | [0..1] | lua xref
update = res/game.lua#update | [0..1] | lua xref
render = res/game.lua#render | [0..1] | lua xref
finalize = res/game.lua#finalize | [0..1] | lua xref
resizeEvent = res/game.lua#resizeEvent | [0..1] | lua xref
keyEvent = res/game.lua#keyEvent | [0..1] | lua xref
touchEvent = res/game.lua#touchEvent | [0..1] | lua xref
mouseEvent = res/game.lua#mouseEvent | [0..1] | lua xref
gamepadEvent = res/game.lua#gamepadEvent | [0..1] | lua xref
gestureSwipeEvent = res/game.lua#gestureSwipeEvent | [0..1] | lua xref
gesturePinchEvent = res/game.lua#gesturePinchEvent | [0..1] | lua xref
gestureTapEvent = res/game.lua#gestureTapEvent | [0..1] | lua xref
gestureLongTapevent = res/game.lua#gestureLongTapevent | [0..1] | lua xref
gestureDragEvent = res/game.lua#gestureDragEvent | [0..1] | lua xref
gestureDropEvent = res/game.lua#gestureDropEvent | [0..1] | lua xref
{ |  |

aliases |  |
{ |  |
alias_name = file_path | [0..*] | file path
} |  |

gamepads |  |
{ |  |
form = res/common/gamepad.form | [0..1] | xref
} |  |

ui |  |
{ |  |
theme = res/default.theme | [0..1] | xref
} |  |

## Scene

    // Load a scene from a .scene property file
    Scene* scene = Scene::load("res/common/game.scene");

scene scene_id | [0..1] | block
{ |  |
path = res/game.gpb | [0..1] | xref
ambientColor = x, y, z | [0..1] | 3 floats
activeCamera = node_id | [0..1] | string
node id {} | [0..*] | block
physics {} | [0..1] | block
animations | [0..1] | block
{ |  |
animation ani_id | [0..*] | block
{ |  |
url = res/walk.animation | required | xref
target = node_id | required | ref
} |  |
} |  |
} |  |

### Node

node node_id |  |
{ |  |
url = res/common/stuff.gpb#duck | [0..1] | xref
material = res/scene.material#wood | [0..1] | xref
collisionObject = res/obj.physics#box | [0..1] | xref
audio = res/game.audio#quack | [0..1] | xref
light = res/game.scene#spotlight | [0..1] | xref
camera = res/game.scene#first_person_camera | [0..1] | xref
// Drawable |  |
particle = res/game.particle#fog | [0..1] | xref
terrain = res/game.scene#lake | [0..1] | xref
sprite = res/game.sprite#indicator | [0..1] | xref
tileset = res/game.tileset#ground | [0..1] | xref
text = res/game.scene#name_tag | [0..1] | xref
translate = x, y, z | [0..1] | 3 floats
rotate = x, y, z, degrees | [0..1] | axis angle
scale = x, y, z | [0..1] | 3 floats
script = res/control.lua | [0..1] | lua xref
enabled = bool | [0..1] | bool
tags | [0..1] | block
{ |  |
tag_name1 | [0..*] | string
tag_name2 |  |
} |  |
// Each of these will be a child node |  |
node id {} | [0..*] | block
} |  |

### Camera

camera camera_id |  |
{ |  |
type = PERSPECTIVE | ORTHOGRAPHIC | required | enum
aspectRatio = float | [0..1] | float
nearPlane = 0.2 | [0..1] | float
farPlane = 100.0 | [0..1] | float
} |  |

camera camera_id |  |
{ |  |
type = PERSPECTIVE | required | enum
fieldOfView = 60.0 | [0..1] | float
} |  |

camera camera_id |  |
{ |  |
type = ORTHOGRAPHIC | required | enum
zoomX = float | [0..1] | float
zoomY = float | [0..1] | float
} |  |

### Light

light light_id |  |
{ |  |
type = DIRECTIONAL | POINT | SPOT | required | enum
color = r, g, b | required | 3 floats
} |  |

light light_id |  |
{ |  |
type = POINT | required | enum
range = float | required | float
} |  |

light light_id |  |
{ |  |
type = SPOT | required | enum
range = float | required | float
innerAngle = float | required | float
outerAngle = float | required | float
} |  |

## Materials

Notes:

- id is optional for material, technique and pass.
- Materials can inherit values from another material by optionally setting a parent_material_id.
- Vertex and fragment shader file extensions do not matter. The convention in gameplay is to use ".vert" and ".frag".
- scalar is float, int or bool.
- vector is a comma separated list of floats.

    // When the .material file contains one material
    Material* material = model->setMaterial("res/common/box.material");
    // When the .material file contains multiple materials
    Material* m = model->setMaterial("res/common/stuff.material#wood");

material material_id : parent_material_id |  |
{ |  |
uniform_name = scalar | vector | [0..*] | uniform
uniform_name = AUTO_BIND_ENUM | [0..*] | enum
sampler uniform_name {} | [0..*] | block
renderState {} | [0..1] | block
technique id {} | [0..*] | block
} |  |

technique technique_id |  |
{ |  |
uniform_name = scalar | vector | [0..*] | uniform
uniform_name = AUTO_BIND_ENUM | [0..*] | enum
sampler uniform_name {} | [0..*] | block
renderState {} | [0..1] | block
pass id {} | [0..*] | block
} |  |

pass pass_id |  |
{ |  |
vertexShader = res/colored.vert | required | file path
fragmentShader = res/colored.frag | required | file path
defines = semicolon separated list | [0..1] | string
uniform_name = scalar | vector | [0..*] | uniform
uniform_name = AUTO_BIND_ENUM | [0..*] | enum
sampler uniform_name {} | [0..*] | block
renderState {} | [0..1] | block
} |  |

sampler uniform_name |  |
{ |  |
path = res/wood.png | required | image path
mipmap = bool | [0..1] | bool
wrapS = REPEAT | CLAMP | [0..1] | enum
wrapT = REPEAT | CLAMP | [0..1] | enum
wrapR = REPEAT | CLAMP | [0..1] | enum
minFilter = TEXTURE_MIN_FILTER_ENUM | [0..1] | enum
magFilter = TEXTURE_MAG_FILTER_ENUM | [0..1] | enum
} |  |

renderState |  |
{ |  |
blend = false | [0..1] | bool
blendSrc = BLEND_ENUM | [0..1] | enum
blendDst = BLEND_ENUM | [0..1] | enum
cullFace = false | [0..1] | bool
cullFaceSide = CULL_FACE_SIDE_BACK | [0..1] | enum
frontFace = CW | CCW | [0..1] | enum
depthTest = false | [0..1] | bool
depthWrite = false | [0..1] | bool
depthFunc = FUNC_ENUM | [0..1] | enum
stencilTest = false | [0..1] | bool
stencilWrite = 4294967295 | [0..1] | uint
stencilFunc = FUNC_ENUM | [0..1] | enum
stencilFuncRef = 0 | [0..1] | int
stencilFuncMask = 4294967295 | [0..1] | uint
stencilOpSfail = STENCIL_OPERATION_ENUM | [0..1] | enum
stencilOpDpfail = STENCIL_OPERATION_ENUM | [0..1] | enum
stencilOpDppass = STENCIL_OPERATION_ENUM | [0..1] | enum
} |  |

#### Material Enums

AUTO_BIND_ENUM |
--- | ---
WORLD_MATRIX |
VIEW_MATRIX |
PROJECTION_MATRIX |
WORLD_VIEW_MATRIX |
VIEW_PROJECTION_MATRIX |
WORLD_VIEW_PROJECTION_MATRIX |
INVERSE_TRANSPOSE_WORLD_MATRIX |
INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX |
CAMERA_WORLD_POSITION |
CAMERA_VIEW_POSITION |
MATRIX_PALETTE | Used for vertex skinning
SCENE_AMBIENT_COLOR |
SCENE_LIGHT_COLOR |
SCENE_LIGHT_DIRECTION |

TEXTURE_MIN_FILTER_ENUM |
--- | ---
NEAREST | Lowest quality non-mipmapped
LINEAR | Better quality non-mipmapped
NEAREST_MIPMAP_NEAREST | Fast but low quality mipmapping
LINEAR_MIPMAP_NEAREST |
NEAREST_MIPMAP_LINEAR |
LINEAR_MIPMAP_LINEAR | Best quality mipmapping

TEXTURE_MAG_FILTER_ENUM |
--- | ---
NEAREST | Lowest quality
LINEAR | Better quality

BLEND_ENUM |
--- | ---
ZERO | ONE_MINUS_DST_ALPHA
ONE | CONSTANT_ALPHA
SRC_ALPHA | ONE_MINUS_CONSTANT_ALPHA
ONE_MINUS_SRC_ALPHA | SRC_ALPHA_SATURATE
DST_ALPHA |

CULL_FACE_SIDE_ENUM |
--- | ---
BACK | Cull back-facing polygons.
FRONT | Cull front-facing polygons.
FRONT_AND_BACK | Cull front and back-facing polygons.

FUNC_ENUM |
--- | ---
NEVER | ALWAYS
LESS | GREATER
EQUAL | NOTEQUAL
LEQUAL | GEQUAL

STENCIL_OPERATION_ENUM |
--- | ---
KEEP | REPLACE
ZERO | INVERT
INCR | DECR
INCR_WRAP | DECR_WRAP

## Physics

physics |  |
{ |  |
gravity = x, y, z | [0..1] | 3 floats
constraint {} | [0..*] | block
} |  |

Default gravity: 0.0, -9.8, 0.0

### Collision Objects

#### Physics Rigid Body

collisionObject id |  |
{ |  |
type = RIGID_BODY | required | enum
... same as physics shape |  |
mass = kilograms | [0..1] | float
friction = coefficient | [0..1] | float
restitution = coefficient | [0..1] | float
linearDamping = coefficient | [0..1] | float
angularDamping = coefficient | [0..1] | float
kinematic = bool | [0..1] | bool
anisotropicFriction = x, y, z | [0..1] | 3 floats
gravity = x, y, z | [0..1] | 3 floats
angularFactor = x, y, z | [0..1] | 3 floats
linearFactor = x, y, z | [0..1] | 3 floats
} |  |

#### Physics Ghost Object

collisionObject id |  |
{ |  |
type = GHOST_OBJECT | required | enum
... same as physics shape |  |
} |  |

#### Physics Character

collisionObject id |  |
{ |  |
type = CHARACTER | required | enum
... same as physics shape |  |
mass = kilograms | [0..1] | float
maxStepHeight = float | [0..1] | float
maxSlopeAngle = radians | [0..1] | float
} |  |

#### Physics Vehicle

collisionObject id |  |
{ |  |
type = VEHICLE | required | enum
... same as Rigid Body |  |
steeringGain = float | [0..1] | float
brakingForce = float | [0..1] | float
drivingForce = float | [0..1] | float
steerdownSpeed = float | [0..1] | float
steerdownGain = float | [0..1] | float
brakedownStart = float | [0..1] | float
brakedownFull = float | [0..1] | float
drivedownStart = float | [0..1] | float
drivedownFull = float | [0..1] | float
boostSpeed = float | [0..1] | float
boostGain = float | [0..1] | float
downforce = float | [0..1] | float
} |  |

#### Physics Vehicle Wheel

Note: Vehicle wheels are special, in that they will automatically connect themselves to the parent node's Vehicle physics. Vehicle must come before Vehicle Wheel in the scene graph.

collisionObject id |  |
{ |  |
type = VEHICLE_WHEEL | required | enum
steerable = false | [0..1] | bool
wheelDirection = x, y, z | [0..1] | 3 floats
wheelAxle = x, y, z | [0..1] | 3 floats
strutConnectionOffset = x, y, z | [0..1] | 3 floats
strutRestLength = float | [0..1] | float
strutTravelMax = float | [0..1] | float
strutStiffness = coefficient | [0..1] | float
strutDampingCompression = coefficient | [0..1] | float
strutDampingRelaxation = coefficient | [0..1] | float
strutForceMax = coefficient | [0..1] | float
frictionBreakout = float | [0..1] | float
wheelRadius = radius | [0..1] | float
rollInfluence = float | [0..1] | float
} |  |

#### Shapes

collisionObject id |  |
{ |  |
... |  |
shape = BOX | SPHERE | MESH | HEIGHTFIELD | CAPSULE | required | enum
// BOX properties |  |
extents = x, y, z | [0..1] | 3 floats
center = x, y, z | [0..1] | 3 floats
centerAbsolute = bool | [0..1] | bool
// SPHERE properties |  |
radius = float | [0..1] | float
center = x, y, z | [0..1] | 3 floats
centerAbsolute = bool | [0..1] | bool
// CAPSULE properties |  |
radius = float | [0..1] | float
height = float | [0..1] | float
center = x, y, z | [0..1] | 3 floats
centerAbsolute = bool | [0..1] | bool
// HEIGHTFIELD properties |  |
image = res/mountain_height.r16 | [0..1] | image path
width = uint | [0..1] | uint
height = uint | [0..1] | uint
minHeight = float | [0..1] | float
maxHeight = float | [0..1] | float
... |  |
} |  |

### Constraints

#### All Constraints

constraint id |  |
{ |  |
type = FIXED | GENERIC | HINGE | SOCKET | SPRING | required | enum
rigidBodyA = rigid_body_node_id | required | xref
rigidBodyB = rigid_body_node_id | [0..1] | xref
breakingImpulse = float | [0..1] | float
// All other constraint variables, or changes to these variables |  |
} |  |

#### Fixed Constraint

constraint id |  |
{ |  |
type = FIXED | required | enum
// FIXED has no other variables |  |
} |  |

#### Generic Constraint

constraint id |  |
{ |  |
type = GENERIC | required | enum
translationOffsetA = x, y, z | [0..1] | 3 floats
translationOffsetB = x, y, z | [0..1] | 3 floats
rotationOffsetA = x, y, z, degrees | [0..1] | axis angle
rotationOffsetB = x, y, z, degrees | [0..1] | axis angle
angularLowerLimit = x, y, z | [0..1] | 3 floats
angularUpperLimit = x, y, z | [0..1] | 3 floats
linearLowerLimit = x, y, z | [0..1] | 3 floats
linearUpperLimit = x, y, z | [0..1] | 3 floats
} |  |

#### Hinge Constraint

constraint id |  |
{ |  |
type = HINGE | required | enum
translationOffsetA = x, y, z | [0..1] | 3 floats
translationOffsetB = x, y, z | [0..1] | 3 floats
rotationOffsetA = x, y, z, degrees | [0..1] | axis angle
rotationOffsetB = x, y, z, degrees | [0..1] | axis angle
limits = lowerLimit, upperLimit, bounciness | [0..1] | 2 or 3 floats
} |  |

#### Socket Constraint

constraint id |  |
{ |  |
type = SOCKET | required | enum
translationOffsetA = x, y, z | [0..1] | 3 floats
translationOffsetB = x, y, z | [0..1] | 3 floats
} |  |

#### Spring Constraint

constraint id |  |
{ |  |
type = SPRING | required | enum
rigidBodyB = rigid_body_node_id | required | xref
translationOffsetA = x, y, z | [0..1] | 3 floats
translationOffsetB = x, y, z | [0..1] | 3 floats
rotationOffsetA = x, y, z, degrees | [0..1] | axis angle
rotationOffsetB = x, y, z, degrees | [0..1] | axis angle
angularLowerLimit = x, y, z | [0..1] | 3 floats
angularUpperLimit = x, y, z | [0..1] | 3 floats
linearLowerLimit = x, y, z | [0..1] | 3 floats
linearUpperLimit = x, y, z | [0..1] | 3 floats
angularDampingX = damping | [0..1] | float
angularDampingY = damping | [0..1] | float
angularDampingZ = damping | [0..1] | float
angularStrengthX = strength | [0..1] | float
angularStrengthY = strength | [0..1] | float
angularStrengthZ = strength | [0..1] | float
linearDampingX = damping | [0..1] | float
linearDampingY = damping | [0..1] | float
linearDampingZ = damping | [0..1] | float
linearStrengthX = strength | [0..1] | float
linearStrengthY = strength | [0..1] | float
linearStrengthZ = strength | [0..1] | float
} |  |

## Animation

    Animation* animation = node->createAnimation("animation", "res/common/boy.animation");

#### Animation

animation animation_id |  |
{ |  |
property = ANIMATION_PROPERTY | required | enum
keyCount = number_of_key_frames | required | uint
keyTimes = uint uint uint uint ... | required | uint(s)
keyValues = float float float float ... | required | float(s)
curve = INTERPOLATION_TYPE | required | enum
keyIn = float float float float ... | [0..1] | float(s)
keyOut = float float float float ... | [0..1] | float(s)
repeatCount = float | REPEAT_INDEFINITE | [0..1] | float | enum
frameCount = frame_count | required | int
clip clip_id {} | [0..*] | block
} |  |

Note: frameCount is required only if one or more clips exist

#### Animation Clip

clip clip_id |  |
{ |  |
begin = frame_index | [0..1] | int
end = frame_index | [0..1] | int
repeatCount = float | REPEAT_INDEFINITE | [0..1] | float | enum
speed = 1.0 | [0..1] | float
loopBlendTime = 0.0 | [0..1] | float
} |  |

#### Animation Enums

ANIMATION_PROPERTY
ANIMATE_SCALE | ANIMATE_TRANSLATE
ANIMATE_SCALE_X | ANIMATE_TRANSLATE_X
ANIMATE_SCALE_Y | ANIMATE_TRANSLATE_Y
ANIMATE_SCALE_Z | ANIMATE_TRANSLATE_Z
ANIMATE_ROTATE | ANIMATE_ROTATE_TRANSLATE
ANIMATE_UNIFORM | ANIMATE_SCALE_ROTATE_TRANSLATE

Some types have their own animation properties. They all start with ANIMATE_ and then state the property that will be changed.

INTERPOLATION_TYPE
BEZIER | QUARTIC_IN | CIRCULAR_IN
BSPLINE | QUARTIC_OUT | CIRCULAR_OUT
FLAT | QUARTIC_IN_OUT | CIRCULAR_IN_OUT
HERMITE | QUARTIC_OUT_IN | CIRCULAR_OUT_IN
LINEAR | QUINTIC_IN | ELASTIC_IN
SMOOTH | QUINTIC_OUT | ELASTIC_OUT
STEP | QUINTIC_IN_OUT | ELASTIC_IN_OUT
QUADRATIC_IN | QUINTIC_OUT_IN | ELASTIC_OUT_IN
QUADRATIC_OUT | SINE_IN | OVERSHOOT_IN
QUADRATIC_IN_OUT | SINE_OUT | OVERSHOOT_OUT
QUADRATIC_OUT_IN | SINE_IN_OUT | OVERSHOOT_IN_OUT
CUBIC_IN | SINE_OUT_IN | OVERSHOOT_OUT_IN
CUBIC_OUT | EXPONENTIAL_IN | BOUNCE_IN
CUBIC_IN_OUT | EXPONENTIAL_OUT | BOUNCE_OUT
CUBIC_OUT_IN | EXPONENTIAL_IN_OUT | BOUNCE_IN_OUT
| EXPONENTIAL_OUT_IN | BOUNCE_OUT_IN

## Audio

    // Load a sound from file
    AudioSource* source = AudioSource::create("res/game.audio#explode");

#### Audio Source

audio audio_id |  |
{ |  |
path = res/common/engine_loop.ogg | required | file path
streamed = false | [0..1] | bool
looped = false | [0..1] | bool
gain = volume_amplification (1.0) | [0..1] | float
pitch = pitch_value [0.5-2.0] | [0..1] | float
velocity = x, y, z | [0..1] | 3 floats
} |  |

## Drawables

Notes:

- Only one drawable can exist per-node.
- Model counts as a drawable, but is only loadable from a GPB file. This can be set via the URL property on Node

#### Terrain

terrain terrain_id |  |
{ |  |
// Use block for raw heightmap OR path for non-raw heightmap |  |
heightmap | required | block
{ |  |
path = res/mountain.raw | required | image path
size = raw_width, raw_height | required | 2 uints
} |  |
heightmap = res/mountain.png | required | image path
size = width, height, depth | [0..1] | 3 floats
patchSize = 32 | [0..1] | uint
detailLevels = 1 | [0..1] | uint
skirtScale = 0.0 | [0..1] | float
normalMap = res/mountain_normal.png | [0..1] | image path
material = res/mountain.material#ground | [0..1] | xref
layer layer_id {} | [0..*] | block
} |  |

layer layer_id |  |
{ |  |
texture | required | block
{ |  |
path = res/terrain/ground.png | required | image path
repeat = 1.0, 1.0 | [0..1] | 2 floats
} |  |
index = layer_index | [0..1] | int
row = layer_row | [0..1] | int
column = layer_column | [0..1] | int
blend | [0..1] | block
{ |  |
path = res/terrain/ground_blend.png | required | image path
channel = R | G | B | A | [0..1] | enum
} |  |
} |  |

#### Sprite

sprite sprite_id |  |
{ |  |
path = res/player.png | required | image path
width = sprite_width | image_width_scale (100.0%) | [0..1] | float
height = sprite_height | image_height_scale (100.0%) | [0..1] | float
source = frame_offset_x, frame_offset_y, frame_width, frame_height | [0..1] | 4 floats
frameCount = 1 | [0..1] | uint
anchor = 0.0, 0.0 | [0..1] | 2 floats
color = #RRGGBBAA | [0..1] | color
opacity = 1.0 | [0..1] | float
blendMode = BLEND_ALPHA | BLEND_ADDITIVE |BLEND_MULTIPLIED | BLEND_NONE | [0..1] | enum
flip = FLIP_VERTICAL | FLIP_HORIZONTAL |FLIP_VERTICAL_HORIZONTAL | FLIP_NONE | [0..1] | enum
offset = SPRITE_OFFSET_TYPE | [0..1] | enum
} |  |

##### Sprite Offset

SPRITE_OFFSET_TYPE
OFFSET_ANCHOR | Anchor position for offset
OFFSET_LEFT | Left
OFFSET_HCENTER | Horizontal center
OFFSET_RIGHT | Right
OFFSET_TOP | Top
OFFSET_VCENTER | Vertical center
OFFSET_BOTTOM | Bottom
OFFSET_TOP_LEFT | OFFSET_TOP | OFFSET_LEFT
OFFSET_VCENTER_LEFT | OFFSET_VCENTER | OFFSET_LEFT
OFFSET_BOTTOM_LEFT | OFFSET_BOTTOM | OFFSET_LEFT
OFFSET_TOP_HCENTER | OFFSET_TOP | OFFSET_HCENTER
OFFSET_VCENTER_HCENTER | OFFSET_VCENTER | OFFSET_HCENTER
OFFSET_BOTTOM_HCENTER | OFFSET_BOTTOM | OFFSET_HCENTER
OFFSET_TOP_RIGHT | OFFSET_TOP | OFFSET_RIGHT
OFFSET_VCENTER_RIGHT | OFFSET_VCENTER | OFFSET_RIGHT
OFFSET_BOTTOM_RIGHT | OFFSET_BOTTOM | OFFSET_RIGHT

#### TileSet

tileset tileset_id |  |
{ |  |
path = res/map.png | required | image path
rows = row_count | required | uint
columns = column_count | required | uint
tileWidth = tile_width | required | float
tileHeight = tile_height | required | float
color = #RRGGBBAA | [0..1] | color
opacity = 1.0 | [0..1] | float
tile | [0..*] | block
{ |  |
cell = tile_x, tile_y | required | 2 uints
source = image_offset_x, image_offset_y | required | 2 floats
} |  |
} |  |

#### Text

text text_id |  |
{ |  |
font = res/Arial.gpb | required | file path
text = Hello World | required | string
size = font_size | [0..1] | uint
color = #RRGGBBAA | [0..1] | color
} |  |

#### Particles

    // Load a particle emitter from a property file
    ParticleEmitter* p = ParticleEmitter::create("res/fire.particle");

particle particle_id |  |
{ |  |
sprite | required | block
{ |  |
path = res/common/smoke.png | required | image path
width = int | required | int
height = int | required | int
frameCount = count | required | uint
frameDuration = seconds | [0..1] | float
frameRandomOffset = offset | [0..1] | int
looped = false | [0..1] | bool
animated = false | [0..1] | bool
blendMode = BLEND_NONE | BLEND_ALPHA | BLEND_ADDITIVE | BLEND_MULTIPLIED | BLEND_OPAQUE | BLEND_TRANSPARENT | [0..1] | enum
} |  |
particleCountMax = 100 | [0..1] | uint
emissionRate = particles_per_second | [0..1] | uint
orbitPosition = false | [0..1] | bool
orbitVelocity = false | [0..1] | bool
orbitAcceleration = false | [0..1] | bool
ellipsoid = false | [0..1] | bool
sizeStartMin = 1.0 | [0..1] | float
sizeStartMax = 1.0 | [0..1] | float
sizeEndMin = 1.0 | [0..1] | float
sizeEndMax = 1.0 | [0..1] | float
energyMin = milliseconds | [0..1] | float
energyMax = milliseconds | [0..1] | float
rotationPerParticleSpeedMin = radians per second | [0..1] | float
rotationPerParticleSpeedMax = radians per second | [0..1] | float
colorStart = red, blue, green, alpha | [0..1] | 4 floats
colorStartVar = red, blue, green, alpha | [0..1] | 4 floats
colorEnd = red, blue, green, alpha | [0..1] | 4 floats
colorEndVar = red, blue, green, alpha | [0..1] | 4 floats
position = x, y, z | [0..1] | 3 floats
positionVar = x, y, z | [0..1] | 3 floats
velocity = x, y, z | [0..1] | 3 floats
velocityVar = x, y, z | [0..1] | 3 floats
acceleration = x, y, z | [0..1] | 3 floats
accelerationVar = x, y, z | [0..1] | 3 floats
} |  |

## UI Forms

    // Load a form from a property file
    Form* form = Form::create("res/editor.form");

Note:

- All Form elements are based off Control.
- It is possible to create custom controls and use them within a UI form by registering them with ControlFactory.

### Form

form form_id |  |
{ |  |
theme = res/editor.theme | [0..1] | xref
style = style_id | [0..1] | string
batchingEnabled = true | [0..1] | bool
... same as container |  |
} |  |

#### Container

container container_id |  |
{ |  |
// For specific layout options, use the blocks, otherwise use the property |  |
layout = LAYOUT_ENUM | [0..1] | enum
layout layout_id | [0..1] | block
{ |  |
type = LAYOUT_ENUM | [0..1] | enum
spacing = 0 | [0..1] | int
horizontalSpacing = 0 | [0..1] | int
verticalSpacing = 0 | [0..1] | int
} |  |
scroll = SCROLL_NONE | SCROLL_HORIZONTAL | SCROLL_VERTICAL | SCROLL_BOTH | [0..1] | enum
scrollBarsAutoHide = false | [0..1] | bool
scrollWheelRequiresFocus = false | [0..1] | bool
scrollingFriction = 1.0 | [0..1] | float
scrollWheelSpeed = 400.0 | [0..1] | float
activeControl = control_id | [0..1] | string
button button_id{} | [0..*] | block
checkBox checkBox_id{} | [0..*] | block
container container_id {} | [0..*] | block
image image_id{} | [0..*] | block
joystick joystick_id{} | [0..*] | block
label label_id{} | [0..*] | block
radioButton radioButton_id{} | [0..*] | block
slider slider_id{} | [0..*] | block
textBox textBox_id{} | [0..*] | block
// Any other user-registered controls |  |
} |  |

#### Label

label label_id |  |
{ |  |
text = Hello World | [0..1] | string
} |  |

#### Button

button button_id |  |
{ |  |
... same as label |  |
mapping = BUTTON_ENUM | [0..1] | enum
} |  |

#### CheckBox

checkBox checkBox_id |  |
{ |  |
... same as button |  |
checked = false | [0..1] | bool
} |  |

#### Image

image image_id |  |
{ |  |
path = res/image.png | [0..1] | image path
srcRegion = x, y, width, height | [0..1] | 4 floats
dstRegion = x, y, width, height | [0..1] | 4 floats
} |  |

#### Joystick

joystick joystick_id |  |
{ |  |
radius = joystick_radius | joystick_radius% | required | float
relative = false | [0..1] | bool
innerRegion = x, y | x, y% | x%, y | x%, y% | [0..1] | 2 floats
outerRegion = x, y | x, y% | x%, y | x%, y% | [0..1] | 2 floats
index = joystick_index | [0..1] | int
} |  |

#### RadioButton

radioButton radioButton_id |  |
{ |  |
... same as button |  |
selected = false | [0..1] | bool
group = group_id | [0..1] | string
} |  |

#### Slider

slider slider_id |  |
{ |  |
... same as label |  |
min = float | [0..1] | float
max = float | [0..1] | float
value = default_value | [0..1] | float
step = discrete_steps | [0..1] | float
valueTextVisible = false | [0..1] | bool
valueTextPrecision = 0 | [0..1] | int
valueTextAlignment = ALIGNMENT_ENUM | [0..1] | enum
} |  |

#### TextBox

textBox textBox_id |  |
{ |  |
... same as label |  |
inputMode = TEXT | PASSWORD | [0..1] | enum
} |  |

#### Control

Note: Control is not an actual UI element. It is the base class for all UI elements. All properties and blocks with Control are avaliable for all UI elements, including custom UI elements.

{ |  |
... |  |
style = style_id | [0..1] | string
alignment = ALIGNMENT_ENUM | [0..1] | enum
consumeInputEvents = true | [0..1] | bool
visible = true | [0..1] | bool
zIndex = z_index | [0..1] | int
canFocus = false | [0..1] | bool
focusIndex = focus_index | [0..1] | int
position = x, y | x, y% | x%, y | x%, y% | [0..1] | 2 floats
x = x | x% | [0..1] | float
y = y | y% | [0..1] | float
size = width, height | width, height% | width%, height | width%, height% | [0..1] | 2 floats
width = width | width% | [0..1] | float
height = width | width% | [0..1] | float
autoSize = AUTO_SIZE_WIDTH | AUTO_SIZE_HEIGHT | AUTO_SIZE_BOTH | [0..1] | enum
padding = 0.0 | [0..1] | float
margin = 0.0 | [0..1] | float
enabled = true | [0..1] | bool
script = res/ui.lua | [0..1] | xref
margin margin_id | [0..1] | block
{ |  |
top = 0.0 | [0..1] | float
bottom = 0.0 | [0..1] | float
left = 0.0 | [0..1] | float
right = 0.0 | [0..1] | float
} |  |
padding padding_id | [0..1] | block
{ |  |
top = 0.0 | [0..1] | float
bottom = 0.0 | [0..1] | float
left = 0.0 | [0..1] | float
right = 0.0 | [0..1] | float
} |  |
... to affect all states' theme, use theproperties of stateNormal |  |
... to affect a specific state's theme, usethe following blocks: |  |
stateNormal {} | [0..1] | block
stateFocus {} | [0..1] | block
stateActive {} | [0..1] | block
stateDisabled {} | [0..1] | block
stateHover {} | [0..1] | block
... |  |
} |  |

#### Form Enums

LAYOUT_ENUM |
LAYOUT_FLOW | Controls are placed next to one another horizontally until the right-most edge of the container is reached, at which point a new row is started.
LAYOUT_VERTICAL | Controls are placed next to one another vertically until the bottom-most edge of the container is reached.
LAYOUT_ABSOLUTE | Controls are not modified at all by this layout. They must be positioned and sized manually.

ALIGNMENT_ENUM |
ALIGN_LEFT | Left
ALIGN_HCENTER | Horizontal center
ALIGN_RIGHT | Right
ALIGN_TOP | Top
ALIGN_VCENTER | Vertical center
ALIGN_BOTTOM | Bottom
ALIGN_TOP_LEFT | ALIGN_TOP | ALIGN_LEFT
ALIGN_VCENTER_LEFT | ALIGN_VCENTER | ALIGN_LEFT
ALIGN_BOTTOM_LEFT | ALIGN_BOTTOM | ALIGN_LEFT
ALIGN_TOP_HCENTER | ALIGN_TOP | ALIGN_HCENTER
ALIGN_VCENTER_HCENTER | ALIGN_VCENTER | ALIGN_HCENTER
ALIGN_BOTTOM_HCENTER | ALIGN_BOTTOM | ALIGN_HCENTER
ALIGN_TOP_RIGHT | ALIGN_TOP | ALIGN_RIGHT
ALIGN_VCENTER_RIGHT | ALIGN_VCENTER | ALIGN_RIGHT
ALIGN_BOTTOM_RIGHT | ALIGN_BOTTOM | ALIGN_RIGHT

GAMEPAD_BUTTON_ENUM |
A | B
X | Y
L1 | R1
L2 | R2
L3 | R3
UP | DOWN
LEFT | RIGHT
MENU1 | MENU2
MENU3 |

### Theme

theme theme_id |  |
{ |  |
texture = image_path | required | image path
image image_id {} | [0..*] | block
imageList imageList_id {} | [0..*] | block
skin skin_id {} | [0..*] | block
style style_id {} | [0..*] | block
} |  |

image image_id |  |
{ |  |
region = x, y, width, height | [0..1] | 4 floats
color = #RRGGBBAA | [0..1] | color
} |  |

imageList imageList_id |  |
{ |  |
color = #RRGGBBAA | [0..1] | color
image image_id {} | [0..*] | block
} |  |

skin skin_id |  |
{ |  |
region = x, y, width, height | [0..1] | 4 floats
color = #RRGGBBAA | [0..1] | color
border | [0..1] | block
{ |  |
top = top | [0..1] | float
bottom = bottom | [0..1] | float
left = left | [0..1] | float
right = right | [0..1] | float
} |  |
} |  |

style style_id |  |
{ |  |
margin | [0..1] | block
{ |  |
top = top | [0..1] | int
bottom = bottom | [0..1] | int
left = left | [0..1] | int
right = right | [0..1] | int
} |  |
padding | [0..1] | block
{ |  |
top = top | [0..1] | int
bottom = bottom | [0..1] | int
left = left | [0..1] | int
right = right | [0..1] | int
} |  |
stateNormal {} | [0..1] | block
stateFocus {} | [0..1] | block
stateActive {} | [0..1] | block
stateDisabled {} | [0..1] | block
stateHover {} | [0..1] | block
} |  |

stateNormal |  |
{ |  |
skin = skin_id | [0..1] | string
imageList = imageList_id | [0..1] | string
cursor = image_id | [0..1] | string
font = res/common/arial40.gpb | [0..1] | file path
fontSize = fontSize | [0..1] | int
textColor = #RRGGBBAA | [0..1] | color
textAlignment = ALIGNMENT_ENUM | [0..1] | enum
rightToLeft = false | [0..1] | bool
opacity = float | [0..1] | float
} |  |

stateFocus |  |
{ |  |
... same as stateNormal |  |
} |  |

stateActive |  |
{ |  |
... same as stateNormal |  |
} |  |

stateDisabled |  |
{ |  |
... same as stateNormal |  |
} |  |

stateHover |  |
{ |  |
... same as stateNormal |  |
} |  |