Custom Nodes

A node is a piece of functionality that exists within a Node Map. If you have an idea for a custom node, you can make one yourself and share it online as a .bbnode file with JSON formatting.

As of release 3.4.1 you can now create a custom node (or group of nodes) and right click > export! This .bbnode or .bbgroup file can then be dragged into any node map to be reused, no code required. Nodes that are exported this way cannot be edited in a text editor.

To create a custom node, you need a basic understanding of JSON formatting and a text editor of your choice. To modify a pre-existing node, see Customizing Nodes.

Writing your own Custom Node

Let’s look at a simple example – the “Set Color” node. Here’s the full .bbnode file:

{
	"name" : "Set Color",
	"attributes": [
		{
			"name" : "Set",
			"type" : "Boolean",
			"connection" : "Input",
			"editable" : false		
		},
		{
			"name" : "Done",
			"type" : "Boolean",
			"connection" : "Output",
			"editable" : false		
		},
		{
			"name" : "Color",
                        "type" : "Color",
			"connection" : "None",
			"editable" : true
		}

	],
	"script":"
        function init(){
        }


        function update(dt){
        }


        function signal(name, value) {
            //Check the incoming signals
            if (name == 'Set' && value) {
                //get the node attributes
                let col = this.attribute('Color');
                
                //set the entity color
                this.entity().setColor(col.r, col.g, col.b, col.a);
                
                //Emit signal to indicate the node finished
                this.emitSignal('Done', true);
            }
        }
    "

}

This results in the following node and attributes:

Now let’s look at it line by line.


name

"name" : "Set Color",

This defines what name this node will have.


attributes

"attributes": []

This array defines what attributes the node will have in the attributes sidebar. It also details any input or output connections the node will have. Please note that the Fields and Possible Values here are all cAsE sEnSiTiVe!

Field Description Possible Values
name Required. The name of the attribute or connection. Any string
*do not give two attributes in the same node the same name!
type Required. What data type the attribute contains. Asset
Animation
Boolean
Color
Dropdown
Mesh
Number
Slider
Text
Vector2D
Vector3D
connection Required. Whether this attribute is an input or output connection. Input
Output
None
editable Required.
Attribute: Whether this attribute is visible & editable in the attribute sidebar.
Connection: Whether the name of this connection can be altered.
true
false
essential Optional (defaults to false). If this field is set to true, then this attribute will be displayed on the Entity’s attribute sidebar when clicked in the asset window. You are marking this attribute as important enough to be accessible from the world view instead of just the entity’s mind map. true
false
hasVariance Optional (for number or vector attributes only). If this field is set to true, then this attribute will display a variance field next to its value. (see Wave node documentation for an example) true
false
self Optional. If you’d like your node to be able to be referenced by other nodes without using signals, set this to true to make the purple connection circle visible. (See requested() for more information) “self”: { “visible” : true }
“self”: { “visible” : false }
value Optional field used to define a default value for the attribute. For instance, your Number type attribute could have a default value of 100 with “value”: 100.
Value is required for a Dropdown type attribute because all possible values are pre-defined.
Dropdown Example from Advanced Move node:

"value": {
    "default": "kReplace",
    "options": {
        "Replace": "kReplace",
        "Add": "kAdd",
        "Multiply": "kMultiply"
    }
}

Example for a Vector3D attribute (leaving the X and Z values blank with null):
“value”: [null, 20, null]

sliderMin
sliderMax
sliderStepSize
sliderDefaultValue
Required fields for a Slider type attribute. sliderMin and sliderMax define the range of the slider, sliderStepSize defines the increment of the slider, and sliderDefaultValue defines the initial value of the slider. Example of a Slider attribute:

{
    "name": "My Slider",
    "type": "Slider",
    "connection": "None",
    "editable": true,
    "sliderMin": 0,
    "sliderMax": 10,
    "sliderStepSize": 2,
    "sliderDefaultValue": 2
}

script

"script":"

Anything you put in this string will be inserted into the Script section of the Node. Since it’s all defined within a string, make sure to use single quotes (‘) instead of double quotes (“) to avoid terminating the string early.

If you save your .bbnode file as a .json file and use a program that has syntax highlighting (such as Visual Studio Code), this section will highlight with errors. This is because normal JSON doesn’t allow multiline strings; this is an area where the .bbnode format differs from JSON.

Here’s another script example, this time from the Jump node. This code snippet is entirely contained within the “script”: ” … ” section of the Jump.bbnode file.

    //Input Signal variables
    let _enabled = true;

    //Node attribute variables
    let _jumpLimit;
    let _jumpForce;

    //working variables
    let _physics;
    let _jumpCount = 0;

    function init(){
        //get the node attributes
        _jumpForce = this.attribute('Jump Force');
        _jumpLimit = this.attribute('Jump Limit');
    
        //Get and check the Physics status of this entity
        _physics = this.entity().physics();
        if(_physics && _physics.type() != 'kDynamic'){
            warning('Jump Node only works with [Dynamic] bodies. Enabling by default');

            _physics.setType('kDynamic');
        }
    }

    function start(){

    }

    function update(dt){

    }

    function signal(name, value){
        //Check the incoming signals
        if(name == 'Jump' && value){
            //check we have dynamic physics on the entity
            if(_physics){
                //check here if the signal to jump again is valid
                //we need to check we are with the jump limit
                if(_jumpLimit == 0 || _jumpCount < _jumpLimit){
                    //calculate the jump force to be applied
                    let vel = _physics.linearVelocity();
                    if(_jumpForce.x != null){
                        vel.x = _jumpForce.x;
                    }
                    if(_jumpForce.y != null){
                        vel.y = _jumpForce.y;
                    }
                    if(_jumpForce.z != null){
                        vel.z = _jumpForce.z;
                    }
                    
                    //apply the jump velocity
                    _physics.setLinearVelocity( vel.x, vel.y, vel.z );

                    //track the jump count
                    _jumpCount++;
                }
            }
        }
        else if(name == 'Reset' && value){
            //Signal to reset the jump so we just reset the 
            //jumpcount variable
            _jumpCount = 0;
        }
    }

Import a Node

To import a node into BuildBox, drag it from your file explorer into the mind map of the Entity you’d like to add it to. Voilà!

Troubleshooting

If you drag your .bbnode into the mind map and nothing happens, that probably means there’s a typo somewhere.

– Make sure that each attribute includes all the required fields.
– Make sure that you have no trailing commas.
– A JSON Validator will give you errors based on the Script section, because as noted above, JSON doesn’t normally allow multiline strings. You can try pasting your .bbnode contents into a JSON Validator and then deleting the script section to look for errors elsewhere.

Did you find this page useful?

Please give it a rating:

Please provide some feedback!

This is very helpful to us.

Tell us how we can improve this post?