@awayjs/scene
Version:
AwayJS scene classes
387 lines (386 loc) • 16.9 kB
JavaScript
var FrameScriptManager = /** @class */ (function () {
function FrameScriptManager() {
}
FrameScriptManager.setInterval = function (fun, time, isTimeout) {
if (isTimeout === void 0) { isTimeout = false; }
this._intervalID++;
// make sure we have at least 1ms intervals
if (time < 1) {
time = 1;
}
this._active_intervals.push({ 'id': this._intervalID, 'f': fun, 't': time, 'dt': 0, 'isTimeout': isTimeout, 'isActive': true });
return this._intervalID;
};
FrameScriptManager.setTimeOut = function (fun, time) {
return this.setInterval(fun, time, true);
};
FrameScriptManager.clearInterval = function (id) {
var i = this._active_intervals.length;
while (i--) {
if (this._active_intervals[i].id == id) {
this._active_intervals[i].isActive = false;
this._active_intervals.splice(i, 1);
if (this._index > i) {
//edge case when in the middle of execute_intervals
this._index--;
}
break;
}
}
};
FrameScriptManager.clearTimeout = function (id) {
this.clearInterval(id);
};
FrameScriptManager.execute_intervals = function (dt) {
if (dt === void 0) { dt = 0; }
var interval;
this._index = this._active_intervals.length;
while (this._index--) {
interval = this._active_intervals[this._index];
interval.dt += dt;
// keep executing the setInterval for as many times as the dt allows
// a setInterval can delete itself, so we need to check if it still exists
while (interval.isActive && interval.dt >= interval.t) {
if (interval.isTimeout) {
interval.isActive = false;
this._active_intervals.splice(this._index, 1);
}
interval.dt -= interval.t;
interval.f();
}
}
};
FrameScriptManager.add_child_to_dispose = function (child) {
this._queued_dispose.push(child);
};
FrameScriptManager.get_queue = function () {
if (!FrameScriptManager._queue) {
FrameScriptManager._queue = {
queued_mcs: [],
queued_scripts: [],
queued_mcs_pass2: [],
queued_scripts_pass2: [],
constructors: [],
};
}
return FrameScriptManager._queue;
};
FrameScriptManager.add_script_to_queue = function (mc, script) {
//console.log("add_script_to_queue", mc.name);
var queue = FrameScriptManager.get_queue();
// whenever we queue scripts of new objects, we first inject the lists of pass2
var len = queue.queued_mcs_pass2.length;
var i = 0;
for (i = 0; i < len; i++) {
queue.queued_mcs.push(queue.queued_mcs_pass2[i]);
queue.queued_scripts.push(queue.queued_scripts_pass2[i]);
}
queue.queued_mcs_pass2.length = 0;
queue.queued_scripts_pass2.length = 0;
mc.adapter.allowScript = true;
queue.queued_mcs.push(mc);
queue.queued_scripts.push(script);
};
FrameScriptManager.add_loaded_action_to_queue = function (mc) {
//console.log("add_loaded_action_to_queue", mc.name);
var queue = FrameScriptManager.get_queue();
queue.queued_mcs.push(mc);
queue.queued_scripts.push(null);
};
FrameScriptManager.add_script_to_queue_pass2 = function (mc, script) {
//console.log("add_script_to_queue_pass2", mc.name);
var queue = FrameScriptManager.get_queue();
mc.adapter.allowScript = true;
queue.queued_mcs_pass2.push(mc);
queue.queued_scripts_pass2.push(script);
};
FrameScriptManager.execute_as3_constructors_finish_scene = function (mc) {
/**
* this gets executed after a timeline-navigation
* first execute_as3_constructors_recursiv is called for the mc that was navigated
* after that execute_as3_constructors_finish_scene is called for the scene-mc
* so that we can continue with the next top-level child that has not yet been processed
*/
for (var i = 0, l = mc.numChildren; i < l; i++) {
var child = mc.getChildAt(i);
if (child.parent && child.adapter.executeConstructor)
FrameScriptManager.execute_as3_constructors_recursiv(child);
}
};
FrameScriptManager.execute_as3_constructors_enterFrame = function (mc) {
if (!FrameScriptManager.invalidAS3Constructors)
return;
FrameScriptManager.execute_as3_constructors_recursiv(mc);
FrameScriptManager.invalidAS3Constructors = false;
};
FrameScriptManager.execute_as3_constructors_recursiv = function (mc) {
/**
* when called from advanceFrame, this should iterate all childs and execute constructors
*
* when called after a navigation command,
* this should iterate the navigated object first,
* than it should continue with unprocessed top-level children
*
* this scenegraph:
* scene
* - mc1
* - child1
* - mc2
* - child2
* - mc3
* - child3
*
* should normally be executed in the same order.
* the constructors of childs will be executed from within the super-calls in the parent-constructors
* this happens after the parent constructor has initialized the parent properties,
* but before the parents custom constructor code has run
* so when putting traces in the constructors, the order in which the traces appear is this:
* - child1 - start constructor
* - child1 - end constructor
* - mc1 - start constructor
* - mc1 - end constructor
* - chidl2 - start constructor
* - chidl2 - end constructor
* - mc2 - start constructor
* - mc2 - end constructor
* - child3 - start constructor
* - child3 - end constructor
* - mc3 - start constructor
* - mc3 - end constructor
*
* now when we have a timeline navigation called from for example constructor of mc1
*
* after the timeline navigation, it will first process new constructors
* added for the new frame we navigated too
* it will than continue to work of top-level childs that have not been processed yet
* so the order should look like this:
* - child1 - start constructor
* - child1 - end constructor
* - mc1 - start constructor (calls timeline navigation on itself - gotoAndStop(2))
* - child1.2 (on frame 2) - start constructor
* - child1.2 (on frame 2) - end constructor
* - chidl2 - start constructor
* - chidl2 - end constructor
* - mc2 - start constructor
* - mc2 - end constructor
* - child3 - start constructor
* - child3 - end constructor
* - mc3 - start constructor
* - mc3 - end constructor
* - mc1 - end constructor
*
*/
var mcadapter = mc.adapter;
var constructorFunc = mcadapter.executeConstructor;
if (constructorFunc) {
// constructor has not run yet. will run constructors of all childs aswell
mcadapter.executeConstructor = null;
constructorFunc();
}
else {
// constructor already has run. we need to still do recursion on childs
for (var i = 0, l = mc.numChildren; i < l; i++) {
var child = mc.getChildAt(i);
// because we iterate over mc, it already is parent
//if (child.parent) {
FrameScriptManager.execute_as3_constructors_recursiv(child);
//}
}
}
// if mc was created by timeline, instanceID != ""
if (mc.just_added_to_timeline
&& mc._sessionID >= 0
&& mcadapter
&& mcadapter.dispatchStaticEvent) {
mc.just_added_to_timeline = false;
mcadapter.dispatchStaticEvent('added', mcadapter);
mc.hasDispatchedAddedToStage = mc.isOnDisplayList();
if (mc.hasDispatchedAddedToStage)
mcadapter.dispatchStaticEvent('addedToStage', mcadapter);
// todo: this does not dispatch ADDED and ADDED_TO_STAGE on SHAPE,
// because in awayjs timeline Shape are Sprite without any as3-adapter
}
};
// todo: better / faster way to check if a obj is currently on stage
FrameScriptManager.isOnStage = function (mc) {
var parent = mc;
while (parent && !parent.isAVMScene) {
parent = parent.parent;
}
if (parent && parent.isAVMScene)
return true;
return false;
};
FrameScriptManager.execute_avm1_constructors = function () {
var queue = FrameScriptManager.get_queue();
if (queue.queued_mcs.length == 0 && queue.queued_mcs_pass2.length == 0)
return;
var i = queue.queued_mcs_pass2.length;
while (i > 0) {
i--;
queue.queued_mcs.push(queue.queued_mcs_pass2[i]);
queue.queued_scripts.push(queue.queued_scripts_pass2[i]);
}
queue.queued_mcs_pass2.length = 0;
queue.queued_scripts_pass2.length = 0;
var queues_tmp = queue.queued_mcs;
var mc;
if (FrameScriptManager.useAVM1) {
i = queues_tmp.length;
while (i > 0) {
i--;
mc = queues_tmp[i];
if (!FrameScriptManager.isOnStage(mc))
continue;
if (mc.onInitialize) {
var myFunc = mc.onInitialize;
mc.onInitialize = null;
myFunc();
}
}
for (i = 0; i < queues_tmp.length; i++) {
mc = queues_tmp[i];
if (!FrameScriptManager.isOnStage(mc))
continue;
// onClipEvent (construct) comes before class-constructor
if (mc.onConstruct) {
var myFunc = mc.onConstruct;
mc.onConstruct = null;
myFunc();
}
// class-constructor
var constructorFunc = mc.adapter.executeConstructor;
if (constructorFunc) {
mc.adapter.executeConstructor = null;
//console.log(randomVal, "call constructor for ", mc.parent.name, mc.name);
constructorFunc();
}
}
}
};
FrameScriptManager.execute_queue = function () {
var queue = FrameScriptManager.get_queue();
if (queue.queued_mcs.length == 0 && queue.queued_mcs_pass2.length == 0)
return;
var queues_tmp = queue.queued_mcs.concat();
var queues_scripts_tmp = queue.queued_scripts.concat();
queue.queued_mcs.length = 0;
queue.queued_scripts.length = 0;
var len = queue.queued_mcs_pass2.length;
var i = 0;
for (i = 0; i < len; i++) {
queues_tmp.push(queue.queued_mcs_pass2[i]);
queues_scripts_tmp.push(queue.queued_scripts_pass2[i]);
}
queue.queued_mcs_pass2.length = 0;
queue.queued_scripts_pass2.length = 0;
var mc;
if (FrameScriptManager.useAVM1) {
// first we need to execute all onclipEvent(initialize)
for (i = 0; i < queues_tmp.length; i++) {
mc = queues_tmp[i];
// ignore objects that are not on stage
if (!FrameScriptManager.isOnStage(mc))
continue;
if (mc.onInitialize) {
var myFunc = mc.onInitialize;
mc.onInitialize = null;
myFunc();
}
}
// second we execute onClipEvent (construct) and class-constructors
for (i = 0; i < queues_tmp.length; i++) {
mc = queues_tmp[i];
// ignore objects that are not on stage
if (!FrameScriptManager.isOnStage(mc))
continue;
if (mc.onConstruct) {
var myFunc = mc.onConstruct;
mc.onConstruct = null;
myFunc();
}
var constructorFunc = mc.adapter.executeConstructor;
if (constructorFunc) {
mc.adapter.executeConstructor = null;
//console.log(randomVal, "call constructor for ", mc.parent.name, mc.name);
constructorFunc();
}
}
}
//console.log("execute scripts")
for (i = 0; i < queues_tmp.length; i++) {
mc = queues_tmp[i];
//console.log("scriptqueue", mc.name);
if (FrameScriptManager.useAVM1) {
// ignore objects that are not on stage
if (!FrameScriptManager.isOnStage(mc))
continue;
// execute onclipEvent(loaded)
if (mc.onLoaded) {
var myFunc = mc.onLoaded;
mc.onLoaded = null;
myFunc();
}
// execute onLoad defined as class-property
if (!mc.adapter.hasOnLoadExecuted) {
// i wanted to delete the onLoad property after it has been executed
// but its a prototype-method, and not sure how to savly delete it
// thats why i am working with the "hasOnLoadExecuted" for now
mc.adapter.hasOnLoadExecuted = true;
var func = mc.adapter.alGet('onLoad');
if (func) {
func.alCall(mc.adapter);
}
}
}
if (queues_scripts_tmp[i] != null) {
mc = queues_tmp[i];
// only execute scripts for mcs that already had constructors run
// other framescripts get send back into the queue for being executed in next call to execute_queue
// in FP10 and above there should always come a execute_queue after processing constructors
// so after all constructors have been run, all objects should pass this test
// we cant check for if a executeConstructor exists here, because we only consider a constructor run,
// once it has processed the super-constructors. not when we actually call the constructor-function
// (this is because child-constructor do execute from within the super-constructor)
// for avm1 (<any>mc.adapter).constructorHasRun should always be true
if (mc && mc.adapter && !mc.adapter.constructorHasRun) {
//console.log("mc with contructor - queue script", mc.name)
queue.queued_mcs.push(mc);
queue.queued_scripts.push(queues_scripts_tmp[i]);
}
else if (mc && mc.adapter && mc.adapter.executeScript) {
//console.log("mc script", mc.name);
mc.adapter.executeScript(queues_scripts_tmp[i]);
}
else {
//console.log("mc ignored", mc.name)
}
}
else {
//console.log("script is null", mc.name)
}
}
};
FrameScriptManager.execute_dispose = function () {
var len = this._queued_dispose.length;
for (var i = 0; i < len; i++)
this._queued_dispose[i].dispose();
this._queued_dispose.length = 0;
};
FrameScriptManager.invalidAS3Constructors = false;
// FrameScript debugging:
// the first line of a FrameScript should be a comment that represents the functions unique name
// the exporter creates a js file, containing a object that has the framescripts
// functions set as properties according to the unique names
// this object can be set as "frameScriptDebug" in order to enable debug mode
FrameScriptManager.frameScriptDebug = undefined;
FrameScriptManager.useAVM1 = false;
//queue of objects for disposal
FrameScriptManager._queued_dispose = [];
FrameScriptManager._active_intervals = [];
FrameScriptManager._index = 0;
FrameScriptManager._intervalID = 0;
return FrameScriptManager;
}());
export { FrameScriptManager };
export default FrameScriptManager;