Back to Content

Creating a scripted action using JavaScript


The easiest thing to extend CopperCube with is to create an extension script action. Basically, this is an action which behaves like the built-in ones, but was created by you or a user, in JavaScript. To start, create a new file in the extension directory (Documents\CopperCube\extensions on Windows, or ~/Documents/CopperCube/extensions on Mac OS X) and name it "action_MovePosition.js". Open it with a text editor, and fill the content with this:

/*  <action jsname="action_MovePosition" description="Move Position">
      <property name="MoveBy" type="vect3d" default="0.0, 5.0, 0.0" />
    </action>
*/

action_MovePosition = function()
{
};

// called when the action is executed 
action_MovePosition.prototype.execute = function(currentNode)
{
  var oldPos = ccbGetSceneNodeProperty(currentNode, "Position");	
  var newPos = oldPos.add(this.MoveBy);	
  ccbSetSceneNodeProperty(currentNode, "Position", newPos);
}		

If you restart CopperCube, a new Action named "Move Position" will be available. Note that if you make changes to this file, you no longer need to restart CopperCube, this is only necessary for new actions, or ones which have a changed XML manifest.

Now in the default scene of CopperCube, click on the 3D cube 'cubeMesh1', select the 'Behavior Tab', click '+' to add a new behavior, select "Behaviors triggered by events -> When clicked on this do something", and in the 'Action' property click the '...' button to add a new action. In the now opening action dialog, you will see our new action under 'Scripted Actions' (probably beside other existing actions):





If you now start the app for example as Windows .exe or Mac OS X .app, and click on the cube, this action will be executed, and the cube the action is attached to will move by the vector specified in the 'MoveBy' property. Your first own action worked!

The following will describe how this works and how it can be extended.


Specifying parameters

Maybe you've noticed, that "MovePosition" action we created above had one parameter, named 'MoveBy'. It is a 3D vector specifying the length and direction how the node should be moved:



And if you take a closer look at the JavaScript source code again, it included a small XML part in the header, defining that property 'MoveBy' (marked in red):
/*  <action jsname="action_MovePosition" description="Move Position">
      <property name="MoveBy" type="vect3d" default="0.0, 5.0, 0.0" />
    </action>
*/
This whole XML part in this JavaScript code is inside a JavaScript comment (/* and */) so that it doesn't interfere with the JavaScript. But it is read by CopperCube in order to show the parameters in the editor, so that users can edit them easily. The 'MoveBy' parameter has the type 'vect3d', as you can see, meaning this is a 3D vector. There are several other supported parameter types, like for choosing colors, scene nodes, and others:

Name Description Example
int an integer value <property name="SomeIntValue" type="int" default="500" />
float a floating point value <property name="SomeNumber" type="float" default="1.2" />
string a text <property name="SomeText" type="string" default="Hello World" />
bool a true/false value <property name="TrueOrFalse" type="bool" default="true" />
color a color <property name="MyColor" type="color" default="ff0000ff" />
vect3d a 3D vector or position <property name="MyPos" type="vect3d" default="0.1, 34.0, 0.0" />
scenenode A reference to a
3D scene node in
the scene
<property name="ToHide" type="scenenode" />
texture a texture <property name="Floor" type="texture" default="C:\test.png" />
action one or more actions.
Can be started with
the call ccbInvokeAction
<property name="DoWhat" type="action" />

To try this out, we add some properties to the MoveAction: We extend the MoveAction with a color, a string and a scene node reference. Also, we add some code to use the selected scene node reference instead of the current node (the 'currentNode' parameter usage was replaced by 'this.MoveWhat' in the JavaScript code below). Edit and save the content of the action_MovePosition.js file to look like this:
/* <action jsname="action_MovePosition" description="Move Position">
    <property name="MoveBy" type="vect3d" default="0.0, 5.0, 0.0" />
    <property name="MoveWhat" type="scenenode" />
    <property name="TestColor" type="color" default="ff00ff00" />
    <property name="TestText" type="string" default="Hello World!" />
 </action>
*/

action_MovePosition = function()
{
};

// called when the action is executed 
action_MovePosition.prototype.execute = function(currentNode)
{
  var oldPos = ccbGetSceneNodeProperty(this.MoveWhat, "Position");	
  var newPos = oldPos.add(this.MoveBy);	
  ccbSetSceneNodeProperty(this.MoveWhat, "Position", newPos);
}
Changes in the JavaScript code will be automatically detected by CopperCube, but changes to the XML header won't, so that existing actions won't get destroyed. To make the change appear in CopperCube, either restart CopperCube or select "Edit -> Plugins -> Reload an Verify Extensions". After that, delete and recreate your action in the 'click' behavior of the cube. Otherwise you will only see the original parameters. Once you create a new 'Move Position' action, it will look like this, reflecting all the parameters we added above:



Because we changed the JavaScript code to use the 'MoveWhat' property for changing the position of a scene node, you now need to select the scene node in the editor at the 'MoveWhat' property which should be influenced. Otherwise you will probably get an error when the action runs.

These properties in the scripting system of CopperCube work like this: At runtime, CopperCube will set the properties of the action class instance to the properties selected by the user in the editor. If you created a parameter named 'TestColor' above, there will be a property in the Javascript class, named 'TestColor' with the value of the color the user selected. You can access it with the code 'this.TestColor'.


The Code

Now take a closer look at the other properties of the XML on top of the extension action:

<action jsname="action_MovePosition" description="Move Position">
...

The top line with the tag 'action' specifies the name of the action, and adds a description which will be shown in the editor. Note that the name of the action, "action_MovePosition" in this case, must be the same as the file name, and the same as the javascript class you are creating in this file. Otherwise, the action won't work.

Now take a look at the first two lines of the JavaScript code:

action_MovePosition = function()
{
};

This bascially only defines our javascript class, named 'action_MovePosition'. In the function, you can add some code to initialize members of your class if you like, but since this is an action, and basically only created and, executed once, and then removed again, it is not necessary in most cases.
But the next part is the most important one. The code which gets executed when the action is invoked by CopperCube:

// called when the action is executed 
action_MovePosition.prototype.execute = function(currentNode)
{
  var oldPos = ccbGetSceneNodeProperty(this.MoveWhat, "Position");	
  var newPos = oldPos.add(this.MoveBy);	
  ccbSetSceneNodeProperty(this.MoveWhat, "Position", newPos);
}

This code creates a function in the 'action_MovePosition' class named 'execute'. Execute() is called by CopperCube when the action is executed. The only parameter is a reference to the scene node which is the 'current' one. For example if this action is called by a "when clicked do something" behavior, this is then the scene node onto which the user clicked. In our example, this parameter is not used, we are using the this.MoveWhat property of the action set by the user.

The code works like this: the function ccbGetSceneNodeProperty() returns the 3D position of the scene node as vector3d. Then we add a vector specified by the user and stored in the this.MoveBy property of the action.

Finally, the new position is set again in the scene node by ccbSetSceneNodeProperty(). And that's it.


Now you should be able to write your own actions in CopperCube. If you want to create a behavior instead, read the next tutorial: Creating a scripted behavior using JavaScript.