How to Make a Stencyl Extension
Using the Simple Extension Template

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.

Download Template

1Understand the Extension Structure

The Simple Extension Template uses this complete folder structure:

Simple Extension Template/ ├── src/ │ └── scripts/ │ └── Example.hx ├── blocks.xml ├── icon.png ├── include.nmml ├── include.xml ├── info.txt ├── README.md └── stencyl-addons.xml

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.

Most extension work happens in three places: src/scripts/Example.hx, blocks.xml, and stencyl-addons.xml.

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.
src/scripts/Example.hx
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;
    }
}
The full function path used by a block is scripts.Example.exampleGetter(): package, class, function, and function call.

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.

Basic block template
<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.
Field 0 connects three places: %0 in the visible block wording, order="0" in the field definition, and the first ~ in the generated Haxe.

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 that supplies Strings
<dropdown order="0">
    <choices>
        <c text="Centered" code="&quot;Centered&quot;"/>
        <c text="Smooth Centered" code="&quot;Smooth Centered&quot;"/>
    </choices>
</dropdown>

The visible label is stored in text. The generated value is stored in code. String quotes are written as &quot; because they are inside XML.

Dropdown that supplies booleans
<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

Getter definition
<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.
Incorrect: scripts.Example.exampleGetter
Without parentheses, the generated code references the function instead of calling it.

5Setter Block Example

Setter definition
<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.

blocks.xml
<?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.

stencyl-addons.xml
<?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>
ElementPurpose
<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.
The tag must match exactly in both files. A block defined as tag="example-getter" is placed with <block tag="example-getter" />.

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.

Changing a Haxe function name or its parameters also requires updating the matching code in blocks.xml. Because the XML changed, restart Stencyl afterward.

Expected test

The copy button below copies the actual Stencyl block XML.

Expected test blocks
Print Get Value of Example
Set Example to OOGA BOOGA
Print Get Value of Example
<?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

SymptomCauseFix
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.
When Stencyl reports an error in generated scene code, inspect the generated Haxe line. That line shows exactly what the XML produced.