diff --git a/src/controls/inputs.js b/src/controls/inputs.js index d216c61f..e9e83a3f 100644 --- a/src/controls/inputs.js +++ b/src/controls/inputs.js @@ -130,7 +130,6 @@ Crafty.extend({ * @see Crafty.multitouch */ mouseDispatch: function (e) { - if (!Crafty.mouseObjs) return; Crafty.lastEvent = e; @@ -592,7 +591,7 @@ Crafty.extend({ }); //initialize the input events onload -Crafty.bind("Load", function () { +Crafty._preBind("Load", function () { Crafty.addEvent(this, "keydown", Crafty.keyboardDispatch); Crafty.addEvent(this, "keyup", Crafty.keyboardDispatch); @@ -616,7 +615,7 @@ Crafty.bind("Load", function () { Crafty.addEvent(this, Crafty.stage.elem, "mousewheel", Crafty.mouseWheelDispatch); }); -Crafty.bind("CraftyStop", function () { +Crafty._preBind("CraftyStop", function () { Crafty.removeEvent(this, "keydown", Crafty.keyboardDispatch); Crafty.removeEvent(this, "keyup", Crafty.keyboardDispatch); diff --git a/src/core/core.js b/src/core/core.js index 59ce8ab0..81deea92 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -1136,6 +1136,16 @@ Crafty.extend({ * @see Crafty.stop, Crafty.viewport */ init: function (w, h, stage_elem) { + + // If necessary, attach any event handlers registered before Crafty started + if (!this._preBindDone) { + for(var i = 0; i < this._bindOnInit.length; i++) { + + var preBind = this._bindOnInit[i]; + Crafty.bind(preBind.event, preBind.handler); + } + } + Crafty.viewport.init(w, h, stage_elem); //call all arbitrary functions attached to onload @@ -1145,6 +1155,17 @@ Crafty.extend({ return this; }, + // There are some events that need to be bound to Crafty when it's started/restarted, so store them here + // Switching Crafty's internals to use the new system idiom should allow removing this hack + _bindOnInit: [], + _preBindDone: false, + _preBind: function(event, handler) { + this._bindOnInit.push({ + event: event, + handler: handler + }); + }, + /**@ * #Crafty.getVersion * @category Core @@ -1165,7 +1186,7 @@ Crafty.extend({ /**@ * #Crafty.stop * @category Core - * @trigger CraftyStop - when the game is stopped + * @trigger CraftyStop - when the game is stopped - {bool clearState} * @sign public this Crafty.stop([bool clearState]) * @param clearState - if true the stage and all game state is cleared. * @@ -1175,19 +1196,32 @@ Crafty.extend({ * @see Crafty.init */ stop: function (clearState) { + Crafty.trigger("CraftyStop", clearState); + this.timer.stop(); if (clearState) { + // Remove audio Crafty.audio.remove(); + + // Remove the stage element, and re-add a div with the same id if (Crafty.stage && Crafty.stage.elem.parentNode) { var newCrStage = document.createElement('div'); newCrStage.id = Crafty.stage.elem.id; Crafty.stage.elem.parentNode.replaceChild(newCrStage, Crafty.stage.elem); } - initState(); - } - Crafty.trigger("CraftyStop"); + // Reset references to the now destroyed graphics layers + delete Crafty.canvasLayer.context; + delete Crafty.domLayer._div; + delete Crafty.webgl.context; + // reset callbacks, and indicate that prebound functions need to be bound on init again + Crafty._unbindAll(); + Crafty._addCallbackMethods(Crafty); + this._preBindDone = false; + + initState(); + } return this; }, diff --git a/src/core/extensions.js b/src/core/extensions.js index 6e21e399..3482970f 100644 --- a/src/core/extensions.js +++ b/src/core/extensions.js @@ -177,22 +177,18 @@ module.exports = { //save anonymous function to be able to remove var afn = function (e) { - e = e || window.event; - - if (typeof callback === 'function') { - callback.call(ctx, e); - } + callback.call(ctx, e); }, id = ctx[0] || ""; - if (!this._events[id + obj + type + callback]) this._events[id + obj + type + callback] = afn; - else return; - - if (obj.attachEvent) { //IE - obj.attachEvent('on' + type, afn); - } else { //Everyone else - obj.addEventListener(type, afn, false); + if (!this._events[id + obj + type + callback]) + this._events[id + obj + type + callback] = afn; + else { + return; } + + obj.addEventListener(type, afn, false); + }, /**@ @@ -222,9 +218,7 @@ module.exports = { afn = this._events[id + obj + type + callback]; if (afn) { - if (obj.detachEvent) { - obj.detachEvent('on' + type, afn); - } else obj.removeEventListener(type, afn, false); + obj.removeEventListener(type, afn, false); delete this._events[id + obj + type + callback]; } }, diff --git a/src/graphics/canvas-layer.js b/src/graphics/canvas-layer.js index d415c619..c0be936b 100644 --- a/src/graphics/canvas-layer.js +++ b/src/graphics/canvas-layer.js @@ -66,6 +66,11 @@ Crafty.extend({ return; } + // set properties to initial values -- necessary on a restart + this._dirtyRects = []; + this._changedObjs = []; + this.layerCount = 0; + //create an empty canvas element var c; c = document.createElement("canvas"); diff --git a/src/graphics/dom-layer.js b/src/graphics/dom-layer.js index eaaf0703..76687a38 100644 --- a/src/graphics/dom-layer.js +++ b/src/graphics/dom-layer.js @@ -15,6 +15,10 @@ Crafty.extend({ _div: null, init: function () { + // Set properties to initial values -- necessary on a restart + this._changedObjs = []; + this._dirtyViewport = false; + // Create the div that will contain DOM elements var div = this._div = document.createElement("div"); diff --git a/src/graphics/viewport.js b/src/graphics/viewport.js index f0582cb5..0b6103b9 100644 --- a/src/graphics/viewport.js +++ b/src/graphics/viewport.js @@ -189,7 +189,7 @@ Crafty.extend({ Crafty.unbind("EnterFrame", enterFrame); } - Crafty.bind("StopCamera", stopPan); + Crafty._preBind("StopCamera", stopPan); return function (dx, dy, time, easingFn) { // Cancel any current camera control @@ -248,7 +248,7 @@ Crafty.extend({ } } - Crafty.bind("StopCamera", stopFollow); + Crafty._preBind("StopCamera", stopFollow); return function (target, offsetx, offsety) { if (!target || !target.has('2D')) @@ -320,7 +320,7 @@ Crafty.extend({ function stopZoom(){ Crafty.unbind("EnterFrame", enterFrame); } - Crafty.bind("StopCamera", stopZoom); + Crafty._preBind("StopCamera", stopZoom); var startingZoom, finalZoom, finalAmount, startingX, finalX, startingY, finalY, easing; @@ -528,11 +528,17 @@ Crafty.extend({ init: function (w, h, stage_elem) { // setters+getters for the viewport this._defineViewportProperties(); + + // Set initial values -- necessary on restart + this._x = 0; + this._y = 0; + this._scale = 1; + this.bounds = null; + // If no width or height is defined, the width and height is set to fullscreen this._width = w || window.innerWidth; this._height = h || window.innerHeight; - //check if stage exists if (typeof stage_elem === 'undefined') stage_elem = "cr-stage"; diff --git a/src/graphics/webgl.js b/src/graphics/webgl.js index 42bae28d..37105010 100644 --- a/src/graphics/webgl.js +++ b/src/graphics/webgl.js @@ -437,6 +437,9 @@ Crafty.extend({ return; } + // necessary on restart + this.changed_objects = []; + //create an empty canvas element var c; c = document.createElement("canvas");