Ambiera Forum

Discussions, Help and Support.

Ambiera Forum > CopperCube > Programming and Scripting
Guest's scripts and plugins

Guest
Guest
Quote
2022-08-08 19:55:09

I decided to reinstall my CopperCube app to remove some excess scripts and plugins from my exploration of the program. This has given me the idea to create a thread here to document my journey of rebuilding my tools. Everything I post here is given freely to the CC community for their projects, both personal and commercial, no credit required.

It's traditional to begin with a "Hello, World!" program, so that is where we will start.


// CopperCube action that prints a message to the console

/* <action jsname="action_PrintToConsole" description="Print to console">
<property name="Message" type="string" default="Hello, World!" />
</action>
*/

action_PrintToConsole = function () { }

action_PrintToConsole.prototype.execute = function () {
print(this.Message);
}

Copy the code above, paste it into a text file, save it as "action_PrintToConsole.js", and place it inside CC's extension folder (located in your Documents\CopperCube folder). When you start you CC app, the new action should be available. If your CC app is already running, go to Edit > Plugins > Reload and Verify Extensions and Plugins, then it should appear.

This action script will print a message (default: "Hello, World!") to CC's debug console. What good does this do for us? Plenty. This code gives us a quick means to "sanity check" our game's logic. Logic is conditional. That is, it's either true or false. Consider behavior scripts to be the conditional loops (logic) of CC; consider action scripts to be the ordered (they fire sequentially, top to bottom) instructions after the condition of the behavior loop is true. Generally speaking, if it repeats, it's a behavior; if it doesn't, it's an action. So what does all this have to do with a "Hello, World!" action script? Simple. Call this action to test if the condition of your behavior is true or not.

Example: Open your CC app, attach a "When clicked on this do something" behavior to your default cube, attach the "Print to console" action to this behavior, then test your app. When you click on the cube, it will print "Hello, World!" to the debug console. Thus we now know our logic is sound, and that our app is "sane."


Guest
Guest
Quote
2022-08-08 20:28:46

After a bit of thinking, I think "Print to console" can be simplified to "Print message". Let's make the change.

// CopperCube action that prints a message to the console

/* <action jsname="action_PrintMessage" description="Print message">
<property name="Message" type="string" default="Hello, World!" />
</action>
*/

action_PrintMessage = function () { }

action_PrintMessage.prototype.execute = function () {
print(this.Message);
}

Save this as "action_PrintMessage.js" and place it in your CC extensions folder like was stated in the previous post. Delete the "action_PrintToConsole.js" and then restart your CC app to see "Print to console" has been changed to "Print message". Can you spot where I changed the code to make this happen? Be prepared for changes like this in the future; it's an unfortunate part of the evolution of code. Our next script will be an action that prints the value of a variable to the console. These two scripts are the workhorses of the CC developer.


Guest
Guest
Quote
2022-08-08 22:49:31

So this time let's begin with the code:

// CopperCube action that prints the value of a variable to the console

/* <action jsname="action_PrintVariable" description="Print variable">
<property name="VariableName" type="string" default="" />
<property name="isJSVar" type="bool" default="false" />
<property name="isToString" type="bool" default="false" />
<property name="isTypeOf" type="bool" default="false" />
</action>
*/

action_PrintVariable = function () { }

action_PrintVariable.prototype.execute = function () {
var value = ccbGetCopperCubeVariable(this.VariableName);

if (this.isJSVar) {
value = eval(this.VariableName);
}

if (this.isToString) {
var newValue = value.toString();

if (this.isTypeOf) {
print(typeof newValue);
} else {
print(newValue);
}
} else if (this.isTypeOf) {
print(typeof value);
} else {
print(value);
}
}

Save this action script as "action_PrintVariable.js" and follow the rest of the directions as mentioned already. In CC, you should see a new action: "Print variable."

This action does a bit more than simply print the value of a CC variable. It also prints pure JavaScript variables. It prints their value types, and it also converts them to strings if need be. Why do we need all this? Generally, normal CC variables come in two types: strings and numbers via the action "Set or Change a Variable." Those print with no problems in the debug console; however, what if we want to use a boolean or object such as an array? If you print an object in CC, you get a return of "0.0,0.0,0.0." That's where this action script comes into play.

Example: Open CC if you have not, add a "Before first drawing do something" behavior to the root scene node ("New 3D Scene1"), add two actions to that behavior: "Execute Java Script" and "Print variable."

In the "Execute Java Script" behavior type: "var a = ["a", "b", "c"];" This defines an array, and in the "Print variable" action input "a" as the variable name (exclude quotation marks).

Now test the app. You should see the result of "0" in the debug console. Why? This array is a JS variable, not a CC variable. So let's check the "isJSVar" option in the "Print variable" action and test the app again. "0.0, 0.0, 0.0" is your result.

We know our array is an object, but let's prove it. In the "Print variable" action, check "isTypeOf" and test the app again. Result: "object." Now uncheck the "isTypeOf" option in the "Print variable" action and choose "isToString." Test the app again. Result: "a,b,c."

One final thing: let's get the result of one of the array's indices. Uncheck "isToString" in the "Print variable" action. Type "a[0]' as the variable name. Check "isJSVar." Uncheck all the rest. Test the app. Result: "a", the first index of our array.

All in all, this action is useful for displaying not only CC variables during runtime, but also JS variables, which is handy to have. These two actions (or some form of them) should be in everyone's toolkit, imo.


Guest
Guest
Quote
2022-08-09 02:02:51

This next script is a behavior that prints key codes to the console. We will need this script for a custom key event behavior later. Here's the code:


// CopperCube behavior that prints key codes to the console

/* <behavior jsname="behavior_PrintKeyCodes" description="Print key codes">
<property name="isPrintToConsole" type="bool" default="true" />
</behavior>
*/

behavior_PrintKeyCodes = function () { }

behavior_PrintKeyCodes.prototype.onAnimate = function () { }

behavior_PrintKeyCodes.prototype.onKeyEvent = function (key, pressed) {
if (this.isPrintToConsole) {
if (!this.Pressed) {
if (pressed) {
print(key);

this.Pressed = pressed;
}
}

if (!pressed) {
this.Pressed = !this.Pressed;
}
}
}


Save this as "behavior_PrintKeyCodes.js" and follow the rest of the instructions as already mentioned for adding new scripts to CC.

The only property for this behavior is "isPrintToConsole" which simply toggles on and off printing the key codes to the console. I typically leave this behavior attached to a folder node in the scene graph and just turn it off when I don't need it. The next script is going to be a behavior that utilizes the output from this behavior.


Guest
Guest
Quote
2022-08-09 02:46:46

This is a custom key event behavior that uses the key codes from my "Print key codes" behavior. The default key code is the A key, just like CC's key event behavior. Unlike CC's key behavior, this one allows you to use any key (including function keys) so long as you know its key code. Also, this custom key behavior doesn't repeat the key event unless you toggle the "isDefaultKeyRepeat" property.


// This is a CopperCube behavior for declaring a key event

/*
<behavior jsname="behavior_DeclareKeyEvent" description="Declare key event">
<property name="KeyCode" type="int" default="65" />
<property name="isDefaultKeyRepeat" type="bool" default="false" />
<property name="Action" type="action" />
<property name="Action" type="action" />
</behavior>
*/

behavior_DeclareKeyEvent = function () { };

behavior_DeclareKeyEvent.prototype.onAnimate = function () { };

behavior_DeclareKeyEvent.prototype.onKeyEvent = function (key, pressed) {
if (key == this.KeyCode) {
if (!this.isDefaultKeyRepeat) {
if (!this.Pressed) {
if (pressed) {
ccbInvokeAction(this.Action);

this.Pressed = pressed;
}
}

if (!pressed) {
ccbInvokeAction(this.Action);

this.Pressed = !this.Pressed;
}
} else {
if (pressed) {
ccbInvokeAction(this.Action);
} else {
ccbInvokeAction(this.Action);
}
}
}
}

Next will be the behavior for the mouse.


andgameplay
Registered User
Quote
2022-08-09 02:55:26

Very good! It will help me to learn and understand javascript in the Coppercube, thanks!


Guest
Guest
Quote
2022-08-09 02:58:09

Here's the behavior for the mouse.

// This is a CopperCube behavior for declaring mouse events

/*
<behavior jsname="behavior_DeclareMouseEvents" description="Declare mouse events">
<property name="ActionOnLMBDown" type="action" />
<property name="ActionOnLMBUp" type="action" />
<property name="ActionOnRMBDown" type="action" />
<property name="ActionOnRMBUp" type="action" />
</behavior>
*/

behavior_DeclareMouseEvents = function () { }

behavior_DeclareMouseEvents.prototype.onAnimate = function () { }

behavior_DeclareMouseEvents.prototype.onMouseEvent = function (button) {
if (button) {
if (button == 2) {
ccbInvokeAction(this.ActionOnLMBUp);
}

if (button == 3) {
ccbInvokeAction(this.ActionOnLMBDown);
}

if (button == 4) {
ccbInvokeAction(this.ActionOnRMBUp);
}

if (button == 5) {
ccbInvokeAction(this.ActionOnRMBDown);
}
}
}


The mouse wheel might be a behavior I do in the future, but as of right now, I don't have much use for it.


Guest
Guest
Quote
2022-08-09 03:01:41

@andgameplay

You're welcome!


Guest
Guest
Quote
2022-08-09 03:14:43

Here's a version of my mouse behavior that uses a switch instead of if statements. Looks cleaner, imo.

// This is a CopperCube behavior for declaring mouse events

/*
<behavior jsname="behavior_DeclareMouseEvents" description="Declare mouse events">
<property name="ActionOnLMBDown" type="action" />
<property name="ActionOnLMBUp" type="action" />
<property name="ActionOnRMBDown" type="action" />
<property name="ActionOnRMBUp" type="action" />
</behavior>
*/

behavior_DeclareMouseEvents = function () { }

behavior_DeclareMouseEvents.prototype.onAnimate = function () { }

behavior_DeclareMouseEvents.prototype.onMouseEvent = function (button) {
switch (button) {
case 2:
ccbInvokeAction(this.ActionOnLMBUp);
break;
case 3:
ccbInvokeAction(this.ActionOnLMBDown);
break;
case 4:
ccbInvokeAction(this.ActionOnRMBUp);
break;
case 5:
ccbInvokeAction(this.ActionOnRMBDown);
break;
default:
// Do nothing
break;
}
}



Create reply:


Posted by: (you are not logged in)


Enter the missing letter in: "Internatio?al" (you are not logged in)


Text:

 

  

Possible Codes


Feature Code
Link [url] www.example.com [/url]
Bold [b]bold text[/b]
Image [img]http://www.example.com/image.jpg[/img]
Quote [quote]quoted text[/quote]
Code [code]source code[/code]

Emoticons


   






Copyright© Ambiera e.U. all rights reserved.
Privacy Policy | Terms and Conditions | Imprint | Contact