Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Scripting Coppercube with ActionScript 3

4.20/5 (2 votes)
1 Sep 2009CPOL4 min read 18.5K  
Learn how to control a Coppercube SWF application using ActionScript
Image 1

Introduction

Coppercube is a tool that can be used to create interactive 3D applications, either for Windows or for the web. While Coppercube includes a number of behaviors, customized or complex actions still require custom code. The SWF files produced by Coppercube can be scripted using ActionScript. This tutorial shows you how. 

Background

The code presented here is used as the basis for a number of Coppercube tutorials that you can view here.

Using the Code

Coppercube applications can be scripted through the SimpleAPI, which is a set of functions that expose the inner properties of the elements in the scene. We will make use of this to create a light that changes color.

First the Coppercube application needs to be compiled. The sample project is included in the downloads, or can create your own using the steps described on this web page (you will need to add an additional light called Light2 if following these instructions).

Coppercube supports two scripting languages: ActionScript (Flash or Flex) and Squirrel. ActionScript is used to script the Flash applications, while Squirrel is used to script the Windows applications. This means your target audience (web or Windows) will define what language you use. This will be a web application, so we will use ActionScript.

Scripting Flash Coppercube applications basically involves loading the SWF file created by Coppercube into a new SWF created by your ActionScript compiler. We will use the Flex compiler to create the final scripted application. The SWF you create then modifies the elements inside the Coppercube SWF file.

To keep things simple, you can embed the Coppercube SWF inside the final SWF file. The process is described here. We use this same formula for our class called CoppercubeSprite.

CoppercubeSprite.as
C#
package  
{
  import flash.display.*;
  import flash.events.Event;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;
  import flash.utils.ByteArray;
  
  import gs.TweenMax;
  
  [SWF(width="600", height="400", frameRate="100", backgroundColor="000000")]
  public class CoppercubeSprite extends Sprite 
  {
    // The CopperCube generated SWF file. Embedded into this file here 
    // so we get only one single SWF
    [Embed(source="../resources/scripting.swf", mimeType="application/octet-stream")]
    public static var EmbeddedCopperCubeSWFDataFile:Class;  
    
    private var loader:Loader;
      
    private var simpleAPI:Object;
    private var loadingFinished:Boolean;
    
    private var applicationStarted:Boolean = false;
    private var light:CCLight = null;
    
    public function CoppercubeSprite()
    {  
      addEventListener(Event.ENTER_FRAME, onGraphicsFrame);
      
      // load the coppercube scene from the other swf
      var copperCubeData:ByteArray = new EmbeddedCopperCubeSWFDataFile() as ByteArray;
      
      loader = new Loader();    
      addChild(loader);
      
      loader.loadBytes(copperCubeData);
      loader.contentLoaderInfo.addEventListener(Event.INIT, onCoppercubeLoaded); 
    }      
    
    // called when the coppercube .swf file has been loaded and initialized
    private function onCoppercubeLoaded(e:Event):void 
    {     
      loadingFinished = true;    
      simpleAPI = (loader.content as DisplayObject)['simpleAPI'];
    }    
    
    // called every frame
    public function onGraphicsFrame(event:Event):void
    {    
      if (loadingFinished)
      {            
        if (simpleAPI && simpleAPI.isLoaded() && !applicationStarted)
        {
          	applicationStarted = true;
          	startCCApplication();
        }
        
        if (applicationStarted)
        {
        	enterFrame(event);
        }
      }
    }
    
    public function startCCApplication():void
    {
    	this.light = new CCLight
			(this.simpleAPI, simpleAPI.getSceneNodeByName("Light2"));
    	this.light.Color = 0xFFFF00;
    	TweenMax.to(this.light, 1, {hexColors:{Color:0x00FFFF}, yoyo:0});
    }
    
    public function enterFrame(event:Event):void
    {
    	
    }    
  }
} 

First the Coppercube SWF file is embedded. You can use the Embed keyword to add resources into a SWF file, giving you one file to distribute, and also negating the need to load resources from external sources (along with its inherent unreliability).

[Embed(source="../resources/scripting.swf", mimeType="application/octet-stream")]

We set up a function to be called every frame. It is in this function that we can modify the Coppercube scene.

C#
addEventListener(Event.ENTER_FRAME, onGraphicsFrame);

The embedded SWF file is then loaded, with the onCoppercubeLoaded function set to be called when the loading is finished.

C#
// load the coppercube scene from the other swf
var copperCubeData:ByteArray = new EmbeddedCopperCubeSWFDataFile() as ByteArray;
      
loader = new Loader();    
addChild(loader);
      
loader.loadBytes(copperCubeData);
loader.contentLoaderInfo.addEventListener(Event.INIT, onCoppercubeLoaded); 

Once the embedded SWF file is loaded, we set loadingFinished to true to indicate that the Coppercube scene is ready to be modified, and get a reference to the SimpleAPI interface.

C#
// called when the coppercube .swf file has been loaded and initialized
private function onCoppercubeLoaded(e:Event):void 
{     
  loadingFinished = true;    
  simpleAPI = (loader.content as DisplayObject)['simpleAPI'];
}

The onGraphicsFrame function won’t do anything until loadingFinished has been set to true. Once we know that the Coppercube SWF file has been loaded and a reference to the SimpleAPI interface has been obtained, we then check to see if the SimpleAPI has loaded. Once it has, the startCCApplication function is called, and the applicationStarted flag is set to true so we don’t call this function again.

C#
if (simpleAPI && simpleAPI.isLoaded() && !applicationStarted)
{
    applicationStarted = true;
    startCCApplication();
}

Once the application has been started, we then call the enterFrame function.

C#
if (applicationStarted)
{
    enterFrame(event);
}

It is in the startCCApplication function that we perform any initialization required. In this case, we create a new instance of the CCLight class, and use the TweenMax class to modify the colour of the light.

C#
this.light = new CCLight(this.simpleAPI, simpleAPI.getSceneNodeByName("Light2"));
this.light.Color = 0xFFFF00;
TweenMax.to(this.light, 1, {hexColors:{Color:0x00FFFF}, yoyo:0});

Tweening is the process of changing the properties of an object smoothly over time, and TweenMax is just one of many tweening libraries available for ActionScript. I like TweenMax because it can tween colours, and the yoyo property means that properties can by cycled back and forth.

The enterFrame function is left empty; the TweenMax class will modify the colour of the light every frame for us.

C#
public function enterFrame(event:Event):void
{
    	
}
CCLight.as
C#
package
{
	import mx.messaging.management.ObjectInstance;
	
	public class CCLight
	{
		protected var ccObject:Object = null;
		protected var simpleAPI:Object = null;
		protected var color:int = 0x000000;
		
		public function get Color():int
		{
			return this.color;
		}
		
		public function set Color(color:int):void
		{
			this.color = color;
			simpleAPI.setLightColor(ccObject, color);
		}
		
		public function CCLight(simpleAPI:Object, ccObject:Object)
		{
			this.simpleAPI = simpleAPI;
			this.ccObject = ccObject;
		}
	}
}

CCLight is a very simple class designed to expose the colour property of a Coppercube light as a pair of get/set functions. This is because TweenMax expects to be able to modify a property rather than supply a parameter to a function, which is how the SimpleAPI works. So the CCLight class simply keeps a reference to the SimpleAPI interface and the light that it is to modify, and class the SimpleAPI setLightColor function from within a standard set function. This makes modifying a Coppercube object from TweenMax simple.

SpriteUIComponent.as
C#
package
{
	import flash.display.Sprite;
	
	import mx.core.UIComponent;
	
	public class SpriteUIComponent extends UIComponent
	{
		public function SpriteUIComponent(sprite:Sprite)
		{
		    super ();
		
		    explicitHeight = sprite.height;
		    explicitWidth = sprite.width;
		
		    addChild (sprite);
		}
	}
}

Because we are using Flex to create the application, we need a way to add a Sprite to the application defined in the MXML file. Sprites can not be added directly to a Flex Application object, so as a very simple workaround we use the SpriteUIComponent class as an intermediate step. SpriteUIComponent extends the UIComponent class, which means it can be added to a Flex Application object, and then simply adds the supplied Sprite as a child of itself.

LightScripting.mxml
XML
<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute" 
	xmlns:ns1="*" 
	width="600"
	height="400"
	creationComplete="creationComplete()">
	<mx:Script>
		<![CDATA[
			public function creationComplete():void
			{
				this.addChild (new SpriteUIComponent
						(new CoppercubeSprite()));
			}
		]]>
	</mx:Script>
	
</mx:Application>

The MXML file is the entry point of the application. Once the application is ready, the creationComplete function is called, at which point a new CoppercubeSprite object is added to the Flex Application object as a child of a new SpriteUIComponent object.

When you run the application, you will see that the light that is sitting above the model will slowly fade between yellow and cyan. Almost any aspect of the Coppercube scene can be modified using the same methods, and we also have available to us the full power of ActionScript (such as tweening).

Check out the live demo here, and download the source code here.

History

  • 1st September, 2009 - Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)