Custom exporter
Custom Exporters have saved me dozens of hours. I can't function without PhysicsEditor. Richard Jarell
PhysicsEditor comes with many different data output formats - both generic formats like JSON and XML, as well as platform-specific formats like Cocos2D, Box2D, and others.
However, sometimes these built-in formats aren't sufficient - either because your game framework requires its own specific format, or because the existing formats don't meet your particular needs.
The solution is to create your own custom format. This process is easier than you might think - just follow the instructions below to get started.
How to add custom output formats to PhysicsEditor:
Creating a new exporter
An exporter consists of 2 files:
- exporter.xml - the description of the exporter itself
- template.txt - a template file containing the file layout
Modifying an existing exporter
Many of the exporters are available in the PhysicsEditor folder:
- Windows users look under C:/Program Files/CodeAndWeb/PhysicsEditor/resources/exporters
- Mac users go to /Applications/PhysicsEditor.app/Contents/Resources/exporters
The plain exporter may be a good starting point. Make sure to duplicate the exporter folder to somewhere outside PhysicsEditor's installation path and rename the folder and the exporter contents as shown below!
Preparations before creating your own exporter
Setting up your custom exporter directory
First, create a directory - it's the Exporter Directory that will contain all your custom exporters - e.g. my-PE-Exporters.
Now create a new subdirectory inside that directory - name it like the exporter you want to create - e.g. myexporter.
Your folder structure should look like this:
my-PE-Exporters/
└── myexporter/
├── exporter.xml
└── template.txt
The exporters shipped with PhysicsEditor are located inside the application's folder in a folder called exporters.
To add your own exporter, point PhysicsEditor's preferences to your custom exporter directory location. After setting the path, you'll need to restart PhysicsEditor for it to recognize the new exporters.

exporter.xml
Let's first have a look at the exporter.xml. This file describes the basic information about the exporter itself.
PhysicsEditor scans the exporter directories with each start. If you change the directory location in the preferences or make some changes in the exporter.xml you need to restart PhysicsEditor. If you change the contents' template file there is no need for restarting - it is read with each export.
The exporter.xml is - as the name already says - an xml file.
It has 4 main blocks:
- Global exporter settings - settings for the exporter itself
- Global parameters - settings for all bodies - e.g. gravity
- Body parameters - settings for one body - e.g. body name, type, ...
- Fixture parameters - settings for a single fixture - e.g. bounce rate of the head
Example:
<?xml version="1.0"?>
<exporter>
<!-- exporter settings -->
<name>cocos2d-x</name>
<displayName>Cocos2d-x</displayName>
<description>Exporter for Cocos2d-x</description>
<version>1.0</version>
<yAxisDirection>up</yAxisDirection>
<physicsEngine>chipmunk</physicsEngine>
<template>cocos2d-x.plist</template>
<fileExtension>plist</fileExtension>
<anchorPoint>
<enabled>yes</enabled>
<relX>0.5</relX>
<relY>0.5</relY>
</anchorPoint>
<origin>
<type>fixed</type>
<relX>0.5</relX>
<relY>0.5</relY>
</origin>
<global>
<!-- global parameters -->
</global>
<body>
<!-- body parameters -->
<parameter>
<name>is_dynamic</name>
<displayName>Dynamic body</displayName>
<description>A non-dynamic body is immovable such as a wall or the ground.</description>
<type>bool</type>
<default>true</default>
</parameter>
...
</body>
<fixture>
<!-- fixture parameters -->
<parameter>
<name>density</name>
<displayName>Density</displayName>
<description>Density of the physics shape.</description>
<type>float</type>
<default>1.0</default>
</parameter>
...
</fixture>
</exporter>
Global exporter parameters
Element | Type | Info |
---|---|---|
<name> | string | Identifier for the exporter, must be unique. Otherwise the lastest exporter found for that name will overwrite the others. |
<displayName> | string | This is how the exporter's name is displayed in the combo box in the GUI |
<description> | string | Some information about the exporter |
<version> | string | Exporter version - should be build from digits separated with dots - e.g. 1.0 or 1.0.1 |
<yAxisDirection> | "up " | "down " | Direction of the yAxis |
<physicsEngine> | "box2d " | "chipmunk " | "generic " | Name of the physics engine used. This currently set the polygon orientation. |
<template> | string | Name of the template file - relative to the exporter.xml |
<fileExtension> | string | File extension used when exporting the data file |
Anchor Points

AnchorPoints can be used as the center of a sprite - e.g. for rotation or move operations.
When setting the origin
to anchorPoint
it is also possible to center.
Additional global parameters are anchor points:
Element | Type | Info |
---|---|---|
<enabled> | "yes " | "no " | Display and use anchor points for this exporter |
<relX> | float | Relative position of the anchor points x position |
<relY> | float | Relative position of the anchor points y position |
Origin
Origin - the 0/0 location of the sprite. This might be set to a fixed position or to the anchor point.
Element | Type | Info |
---|---|---|
<type> | "fixed" | "anchorPoint" | Fixed sets a fixed relative position to the sprite's size, anchorPoint uses the AnchorPoint as sprite's center |
<relX> | float | Relative position of the origin x position |
<relY> | float | Relative position of the origin y position |
Parameter blocks
There are 3 parameter blocks which can be used to define properties and values on file base, per body and per fixture.
Element | Type | Info |
---|---|---|
<global> | <parameter> [] | The global parameters used for the complete file - e.g. gravity |
<body> | <parameter> [] | Parameters used for an individual body |
<fixture> | <parameter> [] | Parameters used on an individual fixture. Might be multiple sub-fixtures in case the fixture is decomposed into convex parts. |
Parameter definitions
In each of the elements <global>
, <body>
; and <fixture>
;
zero or more parameters can be defined.
Values for all parameters
These elements must be present for all parameters and define their appearance in the GUI.
Element | Type | Info |
---|---|---|
<name> | string | Name of the value (used in the template) |
<displayName> | string | Human readable name of the value (used in the user interface) |
<description> | string | Description of the element used in the tooltip when hovering over the element for some time |
<shortDescription> | string | Short description of the element used in the status bar when hovering over the element |
<type> | " | Type of the parameter - which adds additional fields |
<bitfield> | "yes ", "no " | Connects a value to an existing bit field |
bool
Element | Type | Info |
---|---|---|
<type> | bool | Defines a bool input field / Checkbox |
<default> | "false " | "true " | The default value |

<parameter>
<name>isSensor</name>
<displayName>Is Sensor</displayName>
<description>The object only detects collisions without colliding</description>
<shortDescription>Turns the fixture into a sensor</shortDescription>
<type>bool</type>
<default>false</default>
</parameter>
string
Element | Type | Info |
---|---|---|
<type> | string | Defines a string input field |
<default> | string | The default value which is used if nothing else is entered |

<parameter>
<name>fixture_id</name>
<displayName>Identifier</displayName>
<description>Identify a fixture during collision detection</description>
<shortDescription>Identifier for the fixture</shortDescription>
<type><code>string</code></type>
<default>fixture123</default>
</parameter>
float
Element | Type | Info |
---|---|---|
<type> | float | Defines a float input field |
<default> | float | The default value |
<min> | float | Minimum value |
<max> | float | Maximum value |

<parameter>
<name>density</name>
<displayName>Density</displayName>
<description>
Density of the fixture, results in the mass if multiplied with the fixture's area
</description>
<shortDescription>Density of the fixture</shortDescription>
<type>float</type>
<min>-1000</min>
<max>1000</max>
<default>2.0</default>
</parameter>
int / uint16
Element | Type | Info |
---|---|---|
<type> | int | Defines a int input field |
<default> | int | The default value |

<parameter>
<name>filter_groupIndex</name>
<displayName>Group</displayName>
<description>
Collision group - objects which have collision enabled need to be in the same collision group
</description>
<shortDescription>The collision group</shortDescription>
<type>int</type>
<default>0</default>
</parameter>
BitField
The bit field is a more complicated structure and might get a better XML representation some day.
It works quite simple for now. First you need to define a bitfield parameter which holds the other values.
The values themselves get an additional field <bitfield>yes</bitfield>
which connects them to the bit field.
Make sure to match the size of the values to the <size>
value in the bitfield definition.
Element | Type | Info |
---|---|---|
<type> | "bitfield" | Defines a bitfield input |
<size> | int | The number of bits usually 16 or 32 |

This block creates the basic bit field:
<parameter>
<name>filter_bitfield</name>
<type>bitfield</type>
<size>16</size>
</parameter>
This block adds a variable for the collision category and attaches it to the bit field.
<parameter>
<name>filter_categoryBits</name>
<displayName>Cat.</displayName>
<description>Collision category</description>
<shortDescription>Collision category</shortDescription>
<type>uint16</type>
<default>1</default>
<bitfield>yes</bitfield>
</parameter>
This block adds another variable for the collision mask:
<parameter>
<name>filter_maskBits</name>
<displayName>Mask</displayName>
<description>Collision mask</description>
<shortDescription>Collision mask</shortDescription>
<type>uint16</type>
<default>65535</default>
<bitfield>yes</bitfield>
</parameter>
The Template
PhysicsEditor uses the Grantlee template engine - which is similar to Django templates.
This is a short overview over the most important language elements. The template syntax is described in detail at the end of this document.
Referencing values
You can access 2 types of values
- Build in values
- Values that are added through parameters in exporter.xml
Values are surrounded by {{
and }}
Sub values are separated by .
.
You might use |
after the value itself to use filters for changing the value itself.
Template | Output | Remark |
---|---|---|
g={{global.gravity}}; | g=9.800000; | This uses the |
g={{global.gravity|floatformat:3}}; | g=9.800; | Same as above with shortening the float value to 3 digits. |
Control structures
Control-Structure: if
{% if condition %} ... {% else %} ... {% endif %}
Renders the first block if the condition is true, the second if it's false.
Example:
dynamic = {% if body.is_dynamic %}true{% else %}false{% endif %};
Control-Structure: for
{% for object in objectList %} ... {% endfor %}
Loops over a list of elements in the data structure.
The variable forloop.first
is true
if the loop is in the first cycle.
Example:
{% for body in bodies %}
{{body.name}}
{% endfor %}
Mixed example
This example prints a list of coordinates, separating each block with a ,
but not adding a comma before the first element of the list:
{% for point in fixture.hull %}
{% if not forloop.first %}, {% endif %}({{point.x}}, {{point.y}})
{% endfor %}
Data structure
Top level objects
Value | Type | Description |
---|---|---|
global |
| Contains all generic parameters defined in |
bodies | Body | Contains all bodies as |
Body
A body
object holds all the bodies defined in PhysicsEditor.
Here's a table of the built-in values.
Values defined in the <body>
section of the exporter.xml are added to the object.
Value | Type | Description |
---|---|---|
anchorPointRel | Point | Anchorpoint's coordinates relative to the sprite's size. |
anchorPointAbs | Point | Anchorpoint's coordinate in pixels. |
size | Size | The body's size in pixels. Same as sprite width. |
fixtures |
| List of body's |
Fixture
A fixture
object holds all the fixtures defined in a body.
Values defined in the <fixture>
section of the exporter.xml are added to the object.
Circle-Fixture
These additional values are available inside circle fixtures.
Value | Type | Description |
---|---|---|
type | " | Type of the fixture |
isCircle | true | Convenience function to check if the fixture is a circle |
radius | float | The radius of the shape in pixels |
center | Point | Circle's center coordinate |
Polygon-Fixture
These additional values are available inside polygon fixtures.
Value | Description | |
---|---|---|
type | " | Type of the fixture |
isCircle | false | Convenience function to check if the fixture is a circle |
hull | Polygon | All points as a single |
polygons |
| List of convex |
Polygon
A polygon is a list of Point
objects.
Point
Value | Description |
---|---|
x | x coordinate of a vertex in pixels |
y | y coordinate of a vertex in pixels |
Size
Value | Description |
---|---|
width | width of the object in pixels |
height | height of the object in pixels |
Enhancing Exporters with JavaScript
While templates are powerful, sometimes you need more advanced functionality - such as complex calculations or data transformations. In these cases, you can enhance your exporter with JavaScript, just like in TexturePacker.
Setting Up JavaScript Support
To add JavaScript capabilities to your exporter:
- Create two nested directories inside your exporter folder:
- First create a grantlee directory
- Then create a 0.2 directory inside it
Your folder structure should look like this:
my-exporters/
└── myexporter/
├── exporter.xml
├── template.txt
└── grantlee/
└── 0.2/
└── myfilter.qs
- Place your JavaScript file(s) in the grantlee/0.2 directory
- Use the .qs extension for your JavaScript files
Creating JavaScript Filters
In your JavaScript file, you can create filters - functions that process template values. A filter:
- Receives a value from the template
- Processes or transforms that value
- Returns the result, which is then included in the output
Here's an example of a filter that converts a value to radians:
// Define the filter function
var ToRadiansFilter = function(input) {
// Convert the input to a regular JavaScript string
var input = input.rawString();
// Process the string (convert degrees to radians)
return String(parseFloat(input) * 3.14159 / 180);
};
// Set the filter name (this is how it will be referenced in templates)
ToRadiansFilter.filterName = "toradians";
// Register the filter with the template system
Library.addFilter("ToRadiansFilter");
Important Notes:
- Converting Input: Always convert the input parameter to a regular JavaScript string using
.rawString()
before using JavaScript string methods. - Return Type: Filters must return a string value.
- Conditional Filters: To create a filter that evaluates a condition, return an empty string
""
for false or any non-empty string for true.
Using JavaScript Filters in Templates
To use a JavaScript filter in your template, you first need to load it:
{% load toradians %}
Important: The value in the load
tag must match the JavaScript file name (without the .qs
extension).
Once loaded, you can apply the filter to any value in your template:
{{ fixture.rotation|toradians }}
Syntax of the Templates
The syntax of templates contains four types of tokens:
- Plain text
- Comments
- Variables
- Control tags
A simple template might look like this:
{# A simple template example #}
Hello {{ person.name }},
{% if person.hasBirthday %}
Happy Birthday!
{% else %}
Have a nice day!
{% endif %}
Bye,
{{ myname }}
- Content inside
{# #}
are comments and are not part of the output. - Content inside
{{ }}
are variables which are substituted when the template is rendered. - Content inside
{% %}
are control tags which can affect the rendering of the template.
PhysicsEditor supports commonly used tags such as if
, for
, cycle
and a
host of others (see https://docs.djangoproject.com/en/dev/ref/templates/builtins/). It is also
possible to define your own custom tags.
Loops
The type of a variable determines how it can be used in templates. For example, treatment of items in an iterable context works as follows:
Lists work as expected:
{% for item in mylist %}
- {{ item }}
{% endfor %}
Truthiness
Truthiness of a variable is evaluated in a similar way to Python. That is:
- An empty string is
false
0
isfalse
- An empty list is
false
- Boolean
false
isfalse
Everything else is true
.
{% if mylist %}
List items:
{% for item in mylist %}
- {{ item }}
{% endfor %}
{% else %}
The list is empty.
{% endif %}
Variable Lookups
So far we've mostly used simple variable lookups in variable
tags,
but the template system is capable of a lot more. Complex structures can be evaluated using the dot (.
) character.
The dot can be used for list index lookup (note that list lookup is 0
-indexed):
The first item is {{ mylist.0 }}, and the fifth item is {{ mylist.4 }}.
It can also be used for key lookups:
The hash value is {{ myhash.mykey }}.
And it can retrieve properties from object instances:
The object property is {{ myobj.myprop }}.
Filters
Filters can further affect the result of including a variable in a template. Filters are separated by the pipe (|
) character.
Name is {{ name }}, and name in uppercase is {{ name|upper }}.
Which is rendered as:
Name is Alice, and name in uppercase is ALICE.
Note that filters may be combined with dot-lookup. For example, if people
is a list of Person
objects,
and Person
objects have name
properties:
First person's name: {{ people.0.name|upper }}.
Rendered as:
First person's name: BOB.
Filters may also be chained. Here, 'Claire' is first uppercased, then lowercased:
Name is {{ name|upper|lower }}
Rendered as:
Name is claire.
Filters may take one string argument, which is delimited by a colon (:
).
If peoplestring
contains "Dave and Ellen and Frank"
, we can cut the string and
:
The people are {{ peoplestring|cut:"and " }}
Rendered as:
The people are Dave Ellen Frank.
Internal filters include:
upper
- Converts text to uppercaselower
- Converts text to lowercaseslice
- Returns a slice of the listtruncate
- Truncates a stringjoin
- Joins a list with a stringsplit
- Splits a string into a list
For more filters, see the Django template built-in filters documentation.
Auto-Escaping in Templates
When creating HTML output, it's necessary to consider escaping data inserted into the template. HTML escaping involves replacing characters like <
with <
and &
with &
to prevent them from being interpreted as HTML markup. The template engine automatically escapes string input before adding it to the output.
This is relevant when writing a variable from the context into the template.
If the context object companies
is a list containing (Burger King
, Ben & Jerries
, Ford
),
and it is used in a template such as:
{% for company in companies %}
- {{ company }}
{% endfor %}
The output would be:
- Burger King
- Ben & Jerries
- Ford
Notice that the &
has been replaced with &
, as is appropriate for HTML output.
Use the |safe
filter to get the unescaped content of the string:
{% for company in companies %}
- {{ company|safe }}
{% endfor %}
It is also possible to turn this auto-escaping feature off for a block in a template:
{% autoescape off %}
...
{% endautoescape %}
This would not escape the content between the autoescape
and endautoescape
tags. This should only be used for content which is actually already safe.
For more information, see the Django template auto-escaping documentation.