/**
* Copyright robertsonchisholm ( http://wonderfl.net/user/robertsonchisholm )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5moJ
*/
package {
//import com.blake.utils.*;
//import com.blake.BCT; // main class for the BCT RSL
import flash.display.*;
import flash.net.*;
import flash.system.*;
import flash.events.*;
import flash.media.SoundMixer;
import flash.utils.getDefinitionByName;
import flash.media.*;
import com.adobe.serialization.json.*;
import flash.text.*;
/**
* Blake Content Tools (BCT) Base Activity/Superclass
*
* @langversion ActionScript 3
* @playerversion Flash 9.0.0
*
* @since 30.03.2011
*/
public class BaseActivity extends Sprite{
/** @private */
public var appDom:ApplicationDomain;
/** Holder for the instance of the main RSL interface. Usage: <code>bct.findAudio("thisAudio");</code> @see com.blake.BCT*/
public var bct:Object;
/** @private*/
public var id:String;
/** Override this in your document class to load an RSL from a different location. ie: a local copy to avoid sandbox-security violation issues. @default "http://assets.readingeggsassets.com/content_tools/rsl/0.4.0/BlakeRSL.swf"*/
public var rslUrl:String = "http://assets.readingeggsassets.com/content_tools/rsl/0.4.0/BlakeRSL.swf";
/** @private*/
public var RSLLoader:Loader;
/** @private*/
public var JSONString:String;
public var standalone:Boolean;
public var thisMovieName:String;
public var thisMoviePath:String;
/** @private*/
public var verboseMode:Boolean=true;
/** @private*/
public var findMovieCallbacks:Object = {onProgress: new Object(), onInit: new Object(), onComplete: new Object()};
/** These are all the asset types to be preloaded from the JSON data. Override this array in the document class to change. @default ["images", "audio", "movies", "variables"]*/
public var preloadAssetTypes:Array = ["images", "audio", "movies", "variables"];
/** @private*/
public var loadAssetsCalled:Boolean = false;
/** @private*/
public var initialAssetsLoadDone:Boolean = false;
/** Holder for the instance of the Blake Sounds utility class. The Sounds utility class contains functions for finding and playing audio. Usage: <code>sounds.playSound("thisSound");</code> @see com.blake.utils.Sounds*/
//public var sounds:Sounds = new Sounds(this);
/** Holder for the instance of the Blake Grafix utility class. The Grafix utility class contains functions for finding and using graphics/Sprites/MovieClips. Usage: <code>grafix.placeMC("thisMC");</code> @see com.blake.utils.Grafix*/
//public var grafix:Grafix = new Grafix(this);
/** Holder for the instance of the ReadingEggsUtils utility class. The ReadingEggsUtils utility class contains functions specific to Reading Eggs, such as creating title and closing screens. Usage: <code>reu.makeClosingScreen();</code> @see com.blake.utils.ReadingEggsUtils*/
//public var reu:ReadingEggsUtils = new ReadingEggsUtils(this);
/** A hash of information about the student. */
protected var student:Object;
/** If true, shows the loading bar and any other content during loading */
protected var showLoadingScreen:Boolean = true;
/** @private*/
public var sndChannel:SoundChannel;
/** Boolean flag to toggle whether traces are shown from this class or not. */
public var verbose:Boolean = true;
/**
* Constructor
*
* @private
* @return
*/
public function BaseActivity(){
//trace(">> BaseActivity Instantiated!");
initBCT();
}
/**
* Initializes BaseActivity and sets and loads RSL
*
* @private
* @see #getMovieInfo()
* @see #loadRSL()
*/
final public function initBCT():void {
getMovieInfo();
Security.allowDomain('*');
// Load the runtime shared library (RSL) first to import our classes
if (standalone) rslUrl = "../../lib/BlakeRSL.swf"; // this is necessary to avoid security-sandbox violations when testing in standalone mode.
loadRSL(rslUrl);
id = LoaderInfo(this.root.loaderInfo).parameters.swf_id;
}
public function _trace(msg:String):void{
var tf:TextField = new TextField();
tf.text = msg;
addChild(tf);
}
/**
* Gets information about current runtime environment.
* This includes the SWF's file name, it's path and whether it's running in standalone or in a browser.
*
* @private
*/
final public function getMovieInfo():void {
var myFileName:String = decodeURI(this.loaderInfo.url);
var myFileNameArray:Array = myFileName.split("/");
var sfn:String = (myFileNameArray[myFileNameArray.length-1]);
thisMoviePath = myFileName.substring(0, myFileName.length-sfn.length);
thisMovieName = sfn.substring(0, sfn.length-4);
standalone = (Capabilities.playerType == "External") || (Capabilities.playerType == "StandAlone");
}
/**
* Loads the runtime shared library
*
* @private
* @param rUrl String
*/
final public function loadRSL(rUrl:String):void {
if (verbose) trace("Loading "+rUrl);
RSLLoader = new Loader();
// Create a listener for the INIT event so we know when the RSL is loaded and can then instantiate our classes
RSLLoader.contentLoaderInfo.addEventListener(Event.INIT,RSLInitListener);
RSLLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,RSLErrorListener);
RSLLoader.load(new URLRequest(rUrl), new LoaderContext(false, ApplicationDomain.currentDomain, standalone ? null : SecurityDomain.currentDomain));
}
/**
* Reports errors upon loading attempts of RSL
*
* @private
* @param event IOErrorEvent
*/
final public function RSLErrorListener(event:IOErrorEvent):void {
trace("WARNING: "+rslUrl+" wasn't able to be loaded!\nERROR: "+(event.text.split("."))[0]);
}
/**
* Initializes the RSL after it's loaded.
* Intializes the BCT RSL and stores it in the variable <strong><code>bct</code></strong>.
*
* @private
* @param e Event
* @see #bct
* @see #init()
*/
final public function RSLInitListener(e:Event):void {
RSLLoader.contentLoaderInfo.removeEventListener(Event.INIT,RSLInitListener);
RSLLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,RSLErrorListener);
// The application domain and getDefinition stuff is to allow for dynamic changing of the RSL SWF without needing to change the associated local SWC (unless classes are added to the RSL)
appDom = LoaderInfo(e.target).applicationDomain;
_trace("standalone = "+standalone);
bct = new (Class(appDom.getDefinition("com.blake.BCT")))(this, thisMovieName);
if (verbose) trace("RSL: " + rslUrl);
init();
}
/**
* Default initialization function.
* Called from RSLInitListener() after the RSL has been loaded and initialized.
* Does these things:
* <ul>
* <li>Sends init() call to the RSL</li>
* <li>Sets up a listener for JS_DATA events</li>
* <li>Sends a ready signal to JavaScript/browser</li>
* <li>Makes the loading screen</li>
* <li>If standalone, begins loading the JSON data</li>
* </ul>
* Override this in your class and call super.
*
* @see com.blake.BCT#init()
* @see com.blake.BCT#listenForJSData()
* @see #signalReady()
* @see com.blake.utils.Grafix#makeScreen()
* @see com.blake.BCT#loadFromDisk()
*/
public function init():void {
// Initialize the BCT and set up JScommunication listeners for start, stop and loadResources
bct.init();
// Set up a general event listener for data sent from Javascript
bct.listenForJSData("receivedJSData");
// Send the READY message to Javascript
signalReady();
//if (showLoadingScreen) grafix.makeScreen("load");
// If standalone, load the JSON file locally
if (standalone) bct.loadFromDisk();
}
/**
* Is this even needed anymore now that we just use Flashbug and FireFlashBug?
*
* @private
* @param msg *
* @param swf Object
*/
public function mtrace(msg:*, swf:Object = null):void {
trace(String(msg));
if (!standalone) {
bct.signalDebug(msg, swf);
}
}
/**
* This method should be called by all SWFs once they load and are ready to receive direction and commands from the javascript-library(1).
* This signal will be interpreted in one of two ways. It will either be a green light for the browser to trigger SWF playback, or to trigger content
* preloading if content preloading is required.
* When called this method will result in the javascript-library(1) readyEvent() being triggered.
*
* @see com.blake.BCT#signalReady()
*/
final public function signalReady():void {
if (standalone){
if (verbose) trace("signalReady(id) signal would be sent to Javascript now") ;
} else {
bct.signalReady(id);
}
}
//////////////////////////////////////////////////////////////////////////////////////
// Methods involved with loading content/assets
//////////////////////////////////////////////////////////////////////////////////////
/**
* An AS3 method which is automatically invoked by the flash runtime shared library in response to the invocation of the triggerContent() javascript-library(1) method.
* Internally this method calls to the contentRequestEvent() method which provides a JSON encoded string as a return value.
* The returned JSON is decoded, parsed by the runtime shared library and assets preloaded. Once this process is complete the signalContentReady AS3 method is called.
* The reason for this round trip is due to a shortcoming in Adobe's External Interface protocol. No function arguments can be passed into SWFs from JavaScript, so instead
* we get the SWF to request the content from JavaScript on demand.
*
* @param e Event
* @see com.blake.BCT#requestJSONData()
*/
final public function signalContentRequest(e:Event):void {
if (!loadAssetsCalled) {
// Ask request JSON data from Javascript
bct.requestJSONData(id);
loadAssetsCalled = true;
}
}
/**
* Event signalling the loading progress of entire load batch
*
* @param e Event
* @see com.blake.Grafix#updateLoaderBar()
*/
public function allProgressEvent(e:Event):void{
//grafix.updateLoaderBar(int(e.target.loadingQueue.progress*100));
}
/**
* Event signalling the loading progress of individual asset
*
* @param e Event
*/
public function individualProgressEvent(e:Event):void {
}
/**
* Event signalling the completion of loading of a single object.
* Also checks for any callbacks for when a MovieClip is loaded.
*
* @param e Event
*/
public function individualLoadedEvent(e:Event):void {
if (standalone){
if (verbose) trace("signalDebug(\""+e.target.curLoader.name+" load is completed.\",id) signal would be sent to Javascript now");
} else {
bct.signalDebug(e.target.curLoader.name+" load is completed.", id);
}
// Check for any callbacks to be called
for (var i:String in findMovieCallbacks.onComplete){
// Check if the callback is for the loaded movie and the function isn't null/undefined
if ((i==e.target.curLoader.name)&&(findMovieCallbacks.onInit[i]!=undefined)&&(findMovieCallbacks.onComplete[i]!=null)){
var t:String = findMovieCallbacks.onComplete[i];
// Run the specified function on the loaded content
this[t](e.target.curLoader.content);
}
}
}
/**
* Event signalling the initialization of loading of a single object.
* Also checks for any callbacks for when a MovieClip is loaded.
*
* @param e Event
*/
public function individualInitEvent(e:Event):void {
if (standalone){
if (verbose) trace("signalDebug(\""+e.target.curLoader.name+" load init.\",id) signal would be sent to Javascript now");
} else {
bct.signalDebug(e.target.curLoader.name+" load is initialized.", id);
}
// Check for any callbacks to be called
for (var i:String in findMovieCallbacks.onInit){
// Check if the callback is for the loaded movie and the function isn't null/undefined
if ((i==e.target.curLoader.name)&&(findMovieCallbacks.onInit[i]!=undefined)&&(findMovieCallbacks.onInit[i]!=null)){
// Run the specified function on the loaded content
this[findMovieCallbacks.onInit[i]](e.target.curLoader.content);
}
}
}
/**
* Handler that runs when all the JSON content is loaded.
* If running in standalone, it makes the title screen automatically.
* If running in a browser, it sends a "contentReady" signal to JavaScript/browser.
* It also find and stores the loaded "student" variable.
*
* @param e Event
* @see #makeScreen()
* @see com.blake.BCT#signalContentReady()
* @see com.blake.BCT#findVariable()
*/
public function signalContentReady(e:Event):void {
if (!initialAssetsLoadDone){
initialAssetsLoadDone = true;
standalone ? makeScreen("title") : bct.signalContentReady(id);
}
student = bct.findVariable("student");
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Methods involved with running main body of code
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* An AS3 function which is invoked when the embedded SWF is prompted to begin playback.
* The SWF should not commence any playback, video or audio before this event is received.
* The runtime shared library will call this function when the javascript-library(1) method triggerStart() is invoked.
* After being called, it makes the title screen.
*
* @param e Event
* @see #makeScreen()
*/
public function startEvent(e:Event):void {
makeScreen("title");
}
/**
* An AS3 function which is invoked when the embedded SWF is prompted to stop playback.
* The implementation of this method should halt all SWF playback including audio and video.
* The function is called when the javascript-library(1) method triggerStop() is invoked.
* After being called, it stops all currently playing sounds.
*
* @param e Event
*/
public function stopEvent(e:Event):void {
SoundMixer.stopAll();
}
/**
* This method should be called by SWFs when the bct end game 'Next' button is clicked by a user at the end of the flash experience.
* When called this method will result in the javascript-library(1) nextEvent() being triggered.
* After being called, it sends a "next" signal to JavaScript/browser
*
* @see com.blake.BCT#signalNext()
*/
final public function signalNext():void {
if (standalone){
if (verbose) trace("signalNext(id) signal would be sent to Javascript now");
} else {
bct.signalNext(id);
}
}
/**
* This method should be called by SWFs when the bct 'Restart / Replay' button is clicked by a user at the end of the flash experience.
* When called this method will result in the javascript-library(1) restartEvent() being triggered.
* After being called, it sends a "next" signal to JavaScript/browser, stops all currently playing sounds and returns to the title screen.
*
* @see com.blake.BCT#signalNext()
* @see #makeScreen()
*/
final public function signalRestart():void {
if (standalone){
if (verbose) trace("signalRestart(id) signal would be sent to Javascript now");
} else {
bct.signalRestart(id);
}
SoundMixer.stopAll();
makeScreen("title");
}
/**
* This method should be used to signal a generic in SWF click event by the user. A bct use case will be to capture and signal clicks within a SWF which will then be used by the browser to discern routing options.
* The context argument is a string which needs to describe the nature of the click event. It should be minimal in length, preferably one word long, all in lowercase. Where multiple words are required please use hyphens.
* When called this method will result in the javascript-library(1) clickEvent() being triggered.
* After being called, it sends a "click" signal to JavaScript/browser along with the context in which the click happened.
*
* @param context String
* @see com.blake.BCT#signalClick()
*/
final public function signalClick(context:String):void {
if (standalone){
if (verbose) trace("signalClick(" + context + ", id) signal would be sent to Javascript now");
} else {
bct.signalClick(context, id);
}
}
/**
* Sends a message to Javascript via JScommunication.
* After being called, it sends a message to JavaScript/browser
*
* @param context *
* @param id String
* @see com.blake.BCT#signalMessage()
*/
final public function signalMessage(context:*):void {
if (standalone){
if (verbose) trace("signalMessage(" + context + ", id) signal would be sent to Javascript now");
} else {
bct.signalMessage(context, id);
}
}
/**
* Sends an object to Javascript via JScommunication.
* After being called, it sends an "object" to JavaScript/browser
*
* @param context *
* @param id String
* @see com.blake.BCT#signalObject()
*/
final public function signalObject(context:*):void {
if (standalone){
if (verbose) trace("signalObject(" + JSON.encode(context) + ", id) signal would be sent to Javascript now");
} else {
bct.signalObject(context, id);
}
}
/**
* Finds and returns a movie while setting up callbacks for different loading events.
*
* @param n String
* @param flags String
* @param functionOnInit String
* @param functionOnComplete String
* @param functionOnProgress String
* @return Object
* @see #findMovieCallbacks()
* @see com.blake.BCT#findMovie()
*/
final public function findMovie(n:String, flags:String="g", functionOnInit:String=null, functionOnComplete:String=null, functionOnProgress:String=null):Object{
if (verbose) trace("findMovie("+n+", "+functionOnInit+", "+functionOnComplete+", "+functionOnProgress+") called");
findMovieCallbacks.onComplete[n] = functionOnComplete;
findMovieCallbacks.onInit[n] = functionOnInit;
findMovieCallbacks.onProgress[n] = functionOnProgress;
return(bct.findMovie(n));
}
/**
* Looks in the FLA/SWC library for a symbol with the same linkage name.
*
* @param exportName String
* @return Object
* @private
*/
final public function getLibrarySymbol(exportName:String):Object{
var c:Class = null
try{
c = getDefinitionByName(exportName) as Class;
var librarySymbol:Object = new c();
librarySymbol.name = exportName;
} catch (e:*) {
//bct.signalDebug(e, id);
if (verbose) trace(e+"\nNo such symbol in the library: "+exportName);
}
return (c!=null ? librarySymbol : null);
}
/**
* Default mouse event handler.
*
* @param evt MouseEvent
*/
public function mouseHandler( evt:MouseEvent ):void {
if (verbose) trace("BaseActivity:mouseHandler called: "+evt.target.name+", "+evt.type);
var mc:MovieClip = evt.currentTarget as MovieClip;
switch (evt.target.name) {
case "Click Back":
bct.signalMessage("clicked_back", id);
break;
case "Close":
break;
case "restart":
trace("baseActivity:signalRestart()");
signalRestart();
break;
case "next":
signalNext();
break;
case "playButton":
//sounds.playSound("clickSFX");
makeScreen("game");
break;
default :
switch (evt.type) {
case MouseEvent.CLICK:
case MouseEvent.MOUSE_UP:
signalClick(evt.target.name);
break;
case MouseEvent.MOUSE_OVER:
break;
case MouseEvent.MOUSE_OUT:
break;
case MouseEvent.MOUSE_DOWN:
break;
}
break;
}
}
/**
* Default event handler for keyboard events.
* Override in sub/doc class if needed.
*
* @param evt KeyboardEvent
*/
public function keyboardHandler(evt:KeyboardEvent):void {
if (verbose) trace("keycode: "+evt.keyCode+", event: "+evt.type+", ctrl: "+evt.ctrlKey+", shiftKey: "+evt.shiftKey+", altKey: "+evt.altKey+", keyLocation: "+evt.keyLocation);
switch (evt.type) {
case KeyboardEvent.KEY_DOWN:
break;
case KeyboardEvent.KEY_UP:
break;
}
}
/**
* Stub for makeScreen function in document class.
* Used to allow override in subclass.
*
* @param s String
*/
public function makeScreen(s:String):void{
}
/**
* Default event handler for when a sound complete.
* Checks what the current sound (sounds.curSound) is that is playing and does associated actions.
* Override in child classes if needed.
*
* @param e Event
* @see com.blake.utils.Sounds#curSound
* @see com.blake.utils.Sounds#playSound()
*/
public function soundComplete(e:Event):void {
/*switch(sounds.curSound ){
case "titleSound":
sounds.playSound("voice");
break;
default:
}*/
}
/**
* Handles incoming dataEvents from javascript.
* Override in child classes if needed.
*
* @param event Object
*/
public function receivedJSData(event:Object):void {
if (verbose) trace("Received data: " + event.data);
}
}
}