Simple Extension Template
The Simple Extension Template is a small working Stencyl extension containing one shared value, one getter block, and one setter block. Use it as the starting point for a new extension instead of rebuilding the folder structure and XML files from nothing.
1Understand the Extension Structure
The Simple Extension Template uses this complete folder structure:
Files used to build the extension
src/ contains the Haxe source code.
blocks.xml defines block wording, inputs, shape, return type, and generated Haxe.
stencyl-addons.xml places the blocks into the Stencyl palette.
Supporting files
include.xml and include.nmml tell the build system what the extension includes.
info.txt, icon.png, and README.md provide identifying information, an icon, and instructions.
2Write the Haxe Script
The Haxe file contains the actual data and functions used by the extension. The blocks do not contain the system itself; they generate calls into this class.
| Element | Purpose |
|---|---|
| src/scripts/Example.hx | The location of the Haxe source file inside the extension. |
| package scripts; | Matches the scripts package folder inside src. |
| class Example | Defines the class. The class name must match the filename Example.hx. |
| public static var | Creates shared data that can be accessed without first creating an instance of the class. |
| public static function | Creates a function that blocks.xml can call directly. |
| (e:String) | Defines a function parameter. This setter accepts one String value named e. |
| :String | Declares that the getter returns text. |
| :Void | Declares that the setter performs an action and returns no value. |
package scripts;
class Example
{
public static var example:String = "HelloWorld!";
public static function exampleGetter():String
{
return example;
}
public static function exampleSetter(e:String):Void
{
example = e;
}
}
3Set Up blocks.xml
Every custom block is defined in blocks.xml. The file begins with the XML declaration, then places every block inside one <palette> element.
<block tag="prefix-action-name"
spec="Do Something with %0"
help="Explains what the block does."
code="scripts.ClassName.functionName(~);"
type="action" color="cyan" returns="void">
<fields>
<string order="0"/>
</fields>
</block>
Block attributes
| Element | Purpose |
|---|---|
| <block> | Contains the complete definition for one Stencyl block. |
| tag | The permanent internal ID. Use a unique prefix and lowercase hyphenated wording, such as example-setter. |
| spec | The words shown directly on the block. Inputs appear as %0, %1, and so on. |
| help | The tooltip shown in Stencyl. State what the block changes or returns. |
| code | The Haxe generated by the block. Each ~ is replaced by one field value. |
| type | action creates a command block. normal creates a value or boolean block. |
| color | Sets the block's Stencyl color, such as cyan. |
| returns | Declares what Stencyl receives: void, string, number, or boolean. |
The fields section
| Element | Purpose |
|---|---|
| <fields> | Contains every input shown on the block. A block with no inputs can use <fields></fields>. |
| <string>, <number>, etc. | The field element chooses the type of input Stencyl displays and passes into the generated Haxe. |
| order="0" | Identifies the first field. order="1" identifies the second field, and so on. |
| %0 in spec | Controls where field 0 appears visually in the block sentence. |
| ~ in code | The first ~ receives field 0, the second receives field 1, and so on. |
| ; | Action blocks generate complete statements and end with a semicolon. Getter and boolean blocks are inserted into other expressions and do not. |
Available field types
| Field | Example | Purpose |
|---|---|---|
| Number | <number order="0"/> | Provides a numeric input. Common Haxe types are Float and Int. |
| String | <string order="0"/> | Provides a String input for names, labels, and other text. |
| Text | <text order="0"/> | Provides another text-entry field and is passed to Haxe as a String. |
| Actor | <actor order="0"/> | Accepts a Stencyl actor value. The Haxe parameter normally uses Actor. |
| Image | <image order="0"/> | Accepts a Stencyl image. Rendering code commonly receives it as BitmapData. |
| Color | <color order="0"/> | Displays Stencyl's color picker and supplies a packed integer color value. |
| Code Block | <CODE_BLOCK order="0"/> | Accepts nested blocks inside an advanced wrapper block. |
Dropdown fields
<dropdown order="0">
<choices>
<c text="Centered" code=""Centered""/>
<c text="Smooth Centered" code=""Smooth Centered""/>
</choices>
</dropdown>
The visible label is stored in text. The generated value is stored in code. String quotes are written as " because they are inside XML.
<dropdown order="0">
<choices>
<c text="On" code="true"/>
<c text="Off" code="false"/>
</choices>
</dropdown>
Boolean and numeric dropdown values are emitted without String quotes. This dropdown sends the Haxe values true or false.
4Getter Block Example
<block tag="example-getter"
spec="Get Value of Example"
help="Returns the current Example text."
code="scripts.Example.exampleGetter()"
type="normal" color="cyan" returns="string">
<fields></fields>
</block>
What makes it a getter
- It uses type="normal".
- It uses returns="string".
- The Haxe function returns String.
- The function call includes ().
- The generated code does not end with a semicolon.
- It has no fields because the function has no parameters.
Without parentheses, the generated code references the function instead of calling it.
5Setter Block Example
<block tag="example-setter"
spec="Set Example to %0"
help="Sets the current Example text."
code="scripts.Example.exampleSetter(~);"
type="action" color="cyan" returns="void">
<fields>
<string order="0"/>
</fields>
</block>
What makes it a setter
- It uses type="action".
- It uses returns="void".
- The Haxe function returns Void.
- The generated function call ends with a semicolon.
- The block includes one String input with order="0".
- %0 and the first ~ both refer to that field.
6Complete blocks.xml
Both block definitions live inside the same <palette> element.
<?xml version="1.0" encoding="UTF-8"?>
<palette>
<block tag="example-getter"
spec="Get Value of Example"
help="Returns the current Example text."
code="scripts.Example.exampleGetter()"
type="normal" color="cyan" returns="string">
<fields></fields>
</block>
<block tag="example-setter"
spec="Set Example to %0"
help="Sets the current Example text."
code="scripts.Example.exampleSetter(~);"
type="action" color="cyan" returns="void">
<fields>
<string order="0"/>
</fields>
</block>
</palette>
7How to Organize the Blocks in the Palette
stencyl-addons.xml does not define what a block does. It controls where defined blocks appear in Stencyl and the order in which they are shown.
<?xml version="1.0" encoding="UTF-8"?>
<stencyl-addons>
<palette-addon target="stencyl-behavior-palette">
<category title="Simple Extension Template" color="cyan">
<section title="Example">
<header title="Values" />
<block tag="example-getter" />
<block tag="example-setter" />
</section>
</category>
</palette-addon>
</stencyl-addons>
| Element | Purpose |
|---|---|
| <category> | Creates the top-level extension category in the Stencyl palette. |
| <section> | Groups blocks by a major feature or responsibility. |
| <header> | Adds a smaller labeled divider inside a section. |
| <block tag="..." /> | Places a block already defined in blocks.xml. |
8Test and Reload the Extension
Haxe script changes
Changes inside files under src/ can be saved and tested during the current Stencyl session as long as the function names and block-facing function signatures do not change.
Edit the Haxe, save it, and test the game again.
XML changes
Changes to blocks.xml, stencyl-addons.xml, or the other extension XML files require a full restart of Stencyl.
If the block definition changed, remove the old placed block and drag in a fresh copy after restarting.
Expected test
The copy button below copies the actual Stencyl block XML.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<copy format="1">
<vars/>
<group eventID="-1" id="-1">
<print comment="false" x="0" y="0">
<example-getter comment="false" id="0" x="0" y="0"/>
</print>
<example-setter comment="false" x="0" y="0">
<int id="0" val="OOGA BOOGA"/>
</example-setter>
<print comment="false" x="0" y="0">
<example-getter comment="false" id="0" x="0" y="0"/>
</print>
</group>
</copy>
First output
HelloWorld!
Second output
OOGA BOOGA
9Debug the Generated Code
| Symptom | Cause | Fix |
|---|---|---|
| Missing semicolon error | An action block's generated code does not end with ;. | Add the semicolon inside the block's code attribute. |
| Prints exampleGetter | The function was referenced instead of called, or Stencyl is using an old placed block. | Use exampleGetter(), restart if XML changed, and replace the placed block. |
| Return type error | The Haxe return type and XML returns value disagree. | Match String with returns="string", and so on. |
| Block missing from the palette | The tag is missing or misspelled in stencyl-addons.xml. | Copy the exact tag from blocks.xml, then restart Stencyl. |
| Arguments arrive in the wrong order | The field orders and ~ positions do not match the Haxe function parameters. | Trace field 0, field 1, and each placeholder through the generated function call. |