diff --git a/core/Commands.js b/core/Commands.js index 2ca50e02..00031f85 100644 --- a/core/Commands.js +++ b/core/Commands.js @@ -65,6 +65,7 @@ var Commands = { ALLOW_DEFAULT: 34, PREVENT_DEFAULT: 35, UNSUBSCRIBE: 36, + REMOVE_SCENE: 37, prettyPrint: function (buffer, start, count) { var callback; start = start ? start : 0; @@ -85,7 +86,7 @@ var commandPrinters = []; commandPrinters[Commands.INIT_DOM] = function init_dom (buffer, data) { data.result += data.i + '. INIT_DOM\n tagName: ' + buffer[++data.i] + '\n\n'; -}; +}; commandPrinters[Commands.DOM_RENDER_SIZE] = function dom_render_size (buffer, data) { data.result += data.i + '. DOM_RENDER_SIZE\n selector: ' + buffer[++data.i] + '\n\n'; @@ -210,4 +211,3 @@ commandPrinters[Commands.NEED_SIZE_FOR] = function need_size_for (buffer, data) }; module.exports = Commands; - diff --git a/core/FamousEngine.js b/core/FamousEngine.js index 82766e7c..2e27e289 100644 --- a/core/FamousEngine.js +++ b/core/FamousEngine.js @@ -369,8 +369,11 @@ FamousEngine.prototype.createScene = function createScene (selector) { selector = selector || 'body'; if (this._scenes[selector]) this._scenes[selector].dismount(); - this._scenes[selector] = new Scene(selector, this); - return this._scenes[selector]; + + var scene = new Scene(); + this._scenes[selector] = scene; + scene.mount(selector); + return scene; }; /** @@ -383,11 +386,11 @@ FamousEngine.prototype.createScene = function createScene (selector) { * @return {FamousEngine} this */ FamousEngine.prototype.addScene = function addScene (scene) { - var selector = scene._selector; + var selector = scene._id; var current = this._scenes[selector]; if (current && current !== scene) current.dismount(); - if (!scene.isMounted()) scene.mount(scene.getSelector()); + if (!scene.isMounted()) scene.mount(scene._id); this._scenes[selector] = scene; return this; }; @@ -402,12 +405,13 @@ FamousEngine.prototype.addScene = function addScene (scene) { * @return {FamousEngine} this */ FamousEngine.prototype.removeScene = function removeScene (scene) { - var selector = scene._selector; + var selector = scene._id; var current = this._scenes[selector]; if (current && current === scene) { if (scene.isMounted()) scene.dismount(); delete this._scenes[selector]; + this._messages.push(Commands.WITH, selector, Commands.REMOVE_SCENE); } return this; }; diff --git a/core/Node.js b/core/Node.js index eed38ad0..77bd607d 100644 --- a/core/Node.js +++ b/core/Node.js @@ -179,6 +179,15 @@ Node.prototype._setUpdater = function _setUpdater (updater) { if (this._requestingUpdate) this._updater.requestUpdate(this); }; +/** + * Scene getUpdater function returns the previously set updater. + * + * @return {Object} the updater of this Node + */ +Node.prototype.getUpdater = function getUpdater () { + return this._updater; +}; + /** * Determine the node's location in the scene graph hierarchy. * A location of `body/0/1` can be interpreted as the following scene graph diff --git a/core/Scene.js b/core/Scene.js index 5e7061a7..610ab877 100644 --- a/core/Scene.js +++ b/core/Scene.js @@ -22,8 +22,6 @@ * THE SOFTWARE. */ -/*jshint -W079 */ - 'use strict'; var Node = require('./Node'); @@ -39,60 +37,23 @@ var SizeSystem = require('./SizeSystem'); * @class Scene * @constructor * @extends Node - * - * @param {String} selector a string which is a dom selector - * signifying which dom element the context - * should be set upon - * @param {Famous} updater a class which conforms to Famous' interface - * it needs to be able to send methods to - * the renderers and update nodes in the scene graph */ -function Scene (selector, updater) { - if (!selector) throw new Error('Scene needs to be created with a DOM selector'); - if (!updater) throw new Error('Scene needs to be created with a class like Famous'); - - Node.call(this); // Scene inherits from node - - this._globalUpdater = updater; // The updater that will both - // send messages to the renderers - // and update dirty nodes - - this._selector = selector; // reference to the DOM selector - // that represents the element - // in the dom that this context - // inhabits - - this.mount(selector); // Mount the context to itself - // (it is its own parent) - - this._globalUpdater // message a request for the dom - .message(Commands.NEED_SIZE_FOR) // size of the context so that - .message(selector); // the scene graph has a total size - - this.show(); // the context begins shown (it's already present in the dom) +function Scene () { + Node.call(this); } -// Scene inherits from node Scene.prototype = Object.create(Node.prototype); Scene.prototype.constructor = Scene; -Scene.NO_DEFAULT_COMPONENTS = true; - -/** - * Scene getUpdater function returns the passed in updater - * - * @return {Famous} the updater for this Scene - */ -Scene.prototype.getUpdater = function getUpdater () { - return this._updater; -}; /** * Returns the selector that the context was instantiated with * * @return {String} dom selector + * @deprecated */ Scene.prototype.getSelector = function getSelector () { - return this._selector; + console.warn('Scene#getSelector is deprecated, use Scene#getLocation or Scene#getId instead'); + return this._id; }; /** @@ -134,7 +95,7 @@ Scene.prototype.onReceive = function onReceive (event, payload) { payload[1], payload[2] ? payload[2] : 0); - this._updater.message(Commands.WITH).message(this._selector).message(Commands.READY); + this._updater.message(Commands.WITH).message(this._id).message(Commands.READY); } }; @@ -142,12 +103,21 @@ Scene.prototype.onReceive = function onReceive (event, payload) { Scene.prototype.mount = function mount (path) { if (this.isMounted()) throw new Error('Scene is already mounted at: ' + this.getLocation()); + Dispatch.mount(path, this); + + this._updater // message a request for the dom + .message(Commands.NEED_SIZE_FOR) // size of the context so that + .message(path); // the scene graph has a total size + this._id = path; this._mounted = true; this._parent = this; TransformSystem.registerTransformAtPath(path); SizeSystem.registerSizeAtPath(path); + + // the context begins shown (it's already present in the dom) + this.show(); }; module.exports = Scene; diff --git a/renderers/Compositor.js b/renderers/Compositor.js index 386c00de..7090d02e 100644 --- a/renderers/Compositor.js +++ b/renderers/Compositor.js @@ -158,6 +158,21 @@ Compositor.prototype.getOrSetContext = function getOrSetContext(selector) { } }; +/** + * Removes the context from the internal registry. + * + * @method + * + * @param {String} selector Selector used for accessing the regisered + * context. + * @return {undefined} undefined + */ +Compositor.prototype.removeContext = function removeContext (selector) { + var context = this._contexts[selector]; + delete this._contexts[selector]; + context.cleanup(); +}; + /** * Retrieves a context object registered under the passed in selector. * diff --git a/renderers/Context.js b/renderers/Context.js index e59df0db..5c618f85 100644 --- a/renderers/Context.js +++ b/renderers/Context.js @@ -153,6 +153,12 @@ Context.prototype._initDOMRenderer = function _initDOMRenderer() { ); }; +Context.prototype.cleanup = function cleanup () { + this._rootEl.removeChild(this._domRendererRootEl); + if (this._webGLRendererRootEl) + this._rootEl.removeChild(this._webGLRendererRootEl); +}; + Context.prototype.initCommandCallbacks = function initCommandCallbacks () { this._commandCallbacks[Commands.INIT_DOM] = initDOM; this._commandCallbacks[Commands.DOM_RENDER_SIZE] = domRenderSize; @@ -182,6 +188,7 @@ Context.prototype.initCommandCallbacks = function initCommandCallbacks () { this._commandCallbacks[Commands.PREVENT_DEFAULT] = preventDefault; this._commandCallbacks[Commands.ALLOW_DEFAULT] = allowDefault; this._commandCallbacks[Commands.READY] = ready; + this._commandCallbacks[Commands.REMOVE_SCENE] = removeScene; }; /** @@ -540,4 +547,9 @@ function changeViewTransform (context, path, commands, iterator) { return iterator; } +function removeScene (context, path, commands, iterator) { + context._compositor.removeContext(path); + return commands.length - 1; +} + module.exports = Context; diff --git a/webgl-renderers/WebGLRenderer.js b/webgl-renderers/WebGLRenderer.js index 8c175579..efa1dc7d 100644 --- a/webgl-renderers/WebGLRenderer.js +++ b/webgl-renderers/WebGLRenderer.js @@ -825,9 +825,9 @@ WebGLRenderer.prototype.handleOptions = function handleOptions(options, mesh) { switch (options.side) { case 'double': - this.gl.cullFace(this.gl.FRONT); + gl.cullFace(gl.FRONT); this.drawBuffers(this.bufferRegistry.registry[mesh.geometry], mesh.drawType, mesh.geometry); - this.gl.cullFace(this.gl.BACK); + gl.cullFace(gl.BACK); break; case 'back': gl.cullFace(gl.FRONT);