From e6131c1db334dc3d76d550e89fd171485c2d329a Mon Sep 17 00:00:00 2001 From: Arnleif Mydland Date: Tue, 26 Jan 2016 13:20:24 +0100 Subject: [PATCH 1/4] * Optimized famous to run a bit better in 'idle'. * Fixed a bug in famous where transform would report changed when it was not and vise versa. * Fixed a bug in famous engine where only every even child would get removed because a loop was iterating the list while it was being truncated in each step. * Note: I've made an assumption that worldtransforms does not need to be updated every frame. this.calculatingWorldMatrix = true has been commented out in Transform.prototype.setBreakPoint. I don't know if this is correct, nor do I know what those breakpoints are, but I think everything was flagged as breakpoints, so just commenting out that line helped me. There is probably some more correct fix for this. --- core/Dispatch.js | 23 +++++-- core/Size.js | 27 +++++--- core/SizeSystem.js | 37 ++++++---- core/Transform.js | 84 ++++++++++++++--------- core/TransformSystem.js | 54 +++++++++------ dom-renderers/Math.js | 32 ++++----- render-loops/RequestAnimationFrameLoop.js | 4 +- 7 files changed, 168 insertions(+), 93 deletions(-) diff --git a/core/Dispatch.js b/core/Dispatch.js index 2352f82d..c6bc8b5f 100644 --- a/core/Dispatch.js +++ b/core/Dispatch.js @@ -158,13 +158,26 @@ Dispatch.prototype.dismount = function dismount (path) { if (node.isMounted()) { if (node.onDismount) node.onDismount(path); - for (i = 0, len = children.length ; i < len ; i++) - if (children[i] && children[i].dismount) children[i].dismount(); - else if (children[i]) this.dismount(path + '/' + i); + // NOTE! Traverse the list backwards as the child will be removed from the list and the list is shrunk in the back per dismount. This avoids a bug where only half the elements would get removed! + for (i = children.length - 1 ; i >= 0 ; i--) + { + if (children[i] && children[i].dismount) + { + children[i].dismount(); + } + else if (children[i]) + { + this.dismount(path + '/' + i); + } + } for (i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onDismount) - components[i].onDismount(); + { + if (components[i] && components[i].onDismount) + { + components[i].onDismount(); + } + } node._setMounted(false); node._setParent(null); diff --git a/core/Size.js b/core/Size.js index 9a6071af..731f67ad 100644 --- a/core/Size.js +++ b/core/Size.js @@ -54,6 +54,8 @@ function Size (parent) { this.renderSizeChanged = false; this.parent = parent != null ? parent : null; + + this.refresh = false; } // an enumeration of the different types of size modes @@ -170,8 +172,9 @@ Size.prototype.setSizeMode = function setSizeMode (x, y, z) { if (x != null) x = resolveSizeMode(x); if (y != null) y = resolveSizeMode(y); if (z != null) z = resolveSizeMode(z); - this.sizeModeChanged = setVec(this.sizeMode, x, y, z); - return this; + var ch = setVec(this.sizeMode, x, y, z); + this.sizeModeChanged = ch; + this.refresh |= ch; }; /** @@ -197,8 +200,10 @@ Size.prototype.getSizeMode = function getSizeMode () { * @return {Size} this */ Size.prototype.setAbsolute = function setAbsolute (x, y, z) { - this.absoluteSizeChanged = setVec(this.absoluteSize, x, y, z); - return this; + var ch = setVec(this.absoluteSize, x, y, z); + this.absoluteSizeChanged = ch; + this.refresh |= ch; + return this; }; /** @@ -224,8 +229,10 @@ Size.prototype.getAbsolute = function getAbsolute () { * @return {Size} this */ Size.prototype.setProportional = function setProportional (x, y, z) { - this.proportionalSizeChanged = setVec(this.proportionalSize, x, y, z); - return this; + var ch = setVec(this.proportionalSize, x, y, z); + this.proportionalSizeChanged = ch; + this.refresh |= ch; + return this; }; /** @@ -251,7 +258,9 @@ Size.prototype.getProportional = function getProportional () { * @return {Size} this */ Size.prototype.setDifferential = function setDifferential (x, y, z) { - this.differentialSizeChanged = setVec(this.differentialSize, x, y, z); + var ch = setVec(this.differentialSize, x, y, z); + this.differentialSizeChanged = ch; + this.refresh |= ch; return this; }; @@ -324,7 +333,9 @@ Size.prototype.fromComponents = function fromComponents (components) { } changed = changed || prev !== target[i]; } - this.sizeChanged = changed; + var ch = changed; + this.sizeChanged = ch; + this.refresh |= ch; return changed; }; diff --git a/core/SizeSystem.js b/core/SizeSystem.js index d8f2fb88..aa94f598 100644 --- a/core/SizeSystem.js +++ b/core/SizeSystem.js @@ -99,7 +99,10 @@ SizeSystem.prototype.get = function get (path) { * * @return {undefined} undefined */ -SizeSystem.prototype.update = function update () { +SizeSystem.prototype.update = function update() +{ + if (stats) stats.ProfileStart("ssUp") + var sizes = this.pathStore.getItems(); var paths = this.pathStore.getPaths(); var node; @@ -108,18 +111,28 @@ SizeSystem.prototype.update = function update () { var len; var components; - for (i = 0, len = sizes.length ; i < len ; i++) { - node = Dispatch.getNode(paths[i]); - components = node.getComponents(); - if (!node) continue; - size = sizes[i]; - if (size.sizeModeChanged) sizeModeChanged(node, components, size); - if (size.absoluteSizeChanged) absoluteSizeChanged(node, components, size); - if (size.proportionalSizeChanged) proportionalSizeChanged(node, components, size); - if (size.differentialSizeChanged) differentialSizeChanged(node, components, size); - if (size.renderSizeChanged) renderSizeChanged(node, components, size); - if (size.fromComponents(components)) sizeChanged(node, components, size); + for (i = 0, len = sizes.length ; i < len ; i++) + { + size = sizes[i]; + if (size.refresh) + { + size.refresh = false; + + node = Dispatch.getNode(paths[i]); + if (node) + { + components = node.getComponents(); + if (size.sizeModeChanged) sizeModeChanged(node, components, size); + if (size.absoluteSizeChanged) absoluteSizeChanged(node, components, size); + if (size.proportionalSizeChanged) proportionalSizeChanged(node, components, size); + if (size.differentialSizeChanged) differentialSizeChanged(node, components, size); + if (size.renderSizeChanged) renderSizeChanged(node, components, size); + if (size.fromComponents(components)) sizeChanged(node, components, size); + } + } } + + if (stats) stats.ProfileEnd("ssUp") }; // private methods diff --git a/core/Transform.js b/core/Transform.js index 53146fc0..f95eb4fa 100644 --- a/core/Transform.js +++ b/core/Transform.js @@ -59,6 +59,7 @@ function Transform (parent) { this.parent = parent ? parent : null; this.breakPoint = false; this.calculatingWorldMatrix = false; + this.refresh = false; // The idea is that this changes to true if anything in the component needs to update. This allows us to early out in the update loop instead of trashng cache to check each sub objects changed state. } Transform.IDENT = [ 1, 0, 0, 0, @@ -118,7 +119,7 @@ Transform.prototype.getParent = function getParent () { */ Transform.prototype.setBreakPoint = function setBreakPoint () { this.breakPoint = true; - this.calculatingWorldMatrix = true; +// this.calculatingWorldMatrix = true; // NOTE: COMMENTED OUT AS IT HAD NO EFFECT IN MY USAGE OF THE ENGINE. THIS AVOIDS US RECALCULATING ALL WORLD MATRIX EVERY FRAME! }; /** @@ -253,7 +254,9 @@ Transform.prototype.getPosition = function getPosition () { * @return {undefined} undefined */ Transform.prototype.setPosition = function setPosition (x, y, z) { - this.vectors.positionChanged = setVec(this.vectors.position, x, y, z); + var ch = setVec(this.vectors.position, x, y, z); + this.vectors.positionChanged = ch; + this.refresh |= ch; }; /** @@ -344,7 +347,9 @@ Transform.prototype.setRotation = function setRotation (x, y, z, w) { this._lastEulerVals[2] = z; } - this.vectors.rotationChanged = setVec(quat, qx, qy, qz, qw); + var ch = setVec(quat, qx, qy, qz, qw); + this.vectors.rotationChanged = ch; + this.refresh |= ch; }; /** @@ -370,7 +375,9 @@ Transform.prototype.getScale = function getScale () { * @return {undefined} undefined */ Transform.prototype.setScale = function setScale (x, y, z) { - this.vectors.scaleChanged = setVec(this.vectors.scale, x, y, z); + var ch = setVec(this.vectors.scale, x, y, z); + this.vectors.scaleChanged = ch; + this.refresh |= ch; }; /** @@ -396,7 +403,9 @@ Transform.prototype.getAlign = function getAlign () { * @return {undefined} undefined */ Transform.prototype.setAlign = function setAlign (x, y, z) { - this.offsets.alignChanged = setVec(this.offsets.align, x, y, z != null ? z - 0.5 : z); + var ch = setVec(this.offsets.align, x, y, z != null ? z - 0.5 : z); + this.offsets.alignChanged = ch; + this.refresh |= ch; }; /** @@ -422,7 +431,9 @@ Transform.prototype.getMountPoint = function getMountPoint () { * @return {undefined} undefined */ Transform.prototype.setMountPoint = function setMountPoint (x, y, z) { - this.offsets.mountPointChanged = setVec(this.offsets.mountPoint, x, y, z != null ? z - 0.5 : z); + var ch = setVec(this.offsets.mountPoint, x, y, z != null ? z - 0.5 : z); + this.offsets.mountPointChanged = ch; + this.refresh |= ch; }; /** @@ -448,7 +459,9 @@ Transform.prototype.getOrigin = function getOrigin () { * @return {undefined} undefined */ Transform.prototype.setOrigin = function setOrigin (x, y, z) { - this.offsets.originChanged = setVec(this.offsets.origin, x, y, z != null ? z - 0.5 : z); + var ch = setVec(this.offsets.origin, x, y, z != null ? z - 0.5 : z); + this.offsets.originChanged = ch; + this.refresh |= ch; }; /** @@ -717,64 +730,64 @@ function multiply (out, a, b) { // Cache only the current line of the second matrix var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[0] === res; + res = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + changed = changed ? changed : (out[0] !== res && !nearlyEqual(out[0], res)); out[0] = res; - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[1] === res; + res = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + changed = changed ? changed : (out[1] !== res && !nearlyEqual(out[1], res)); out[1] = res; - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[2] === res; + res = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + changed = changed ? changed : (out[2] !== res && !nearlyEqual(out[2], res)); out[2] = res; out[3] = 0; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[4] === res; + res = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + changed = changed ? changed : (out[4] !== res && !nearlyEqual(out[4], res)); out[4] = res; - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[5] === res; + res = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + changed = changed ? changed : (out[5] !== res && !nearlyEqual(out[5], res)); out[5] = res; - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[6] === res; + res = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + changed = changed ? changed : (out[6] !== res && !nearlyEqual(out[6], res)); out[6] = res; out[7] = 0; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[8] === res; + res = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + changed = changed ? changed : (out[8] !== res && !nearlyEqual(out[8], res)); out[8] = res; - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[9] === res; + res = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + changed = changed ? changed : (out[9] !== res && !nearlyEqual(out[9], res)); out[9] = res; - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[10] === res; + res = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + changed = changed ? changed : (out[10] !== res && !nearlyEqual(out[10], res)); out[10] = res; out[11] = 0; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; - res = b0*a00 + b1*a10 + b2*a20 + b3*a30; - changed = changed ? changed : out[12] === res; + res = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + changed = changed ? changed : (out[12] !== res && !nearlyEqual(out[12], res)); out[12] = res; - res = b0*a01 + b1*a11 + b2*a21 + b3*a31; - changed = changed ? changed : out[13] === res; + res = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + changed = changed ? changed : (out[13] !== res && !nearlyEqual(out[13], res)); out[13] = res; - res = b0*a02 + b1*a12 + b2*a22 + b3*a32; - changed = changed ? changed : out[14] === res; + res = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + changed = changed ? changed : (out[14] !== res && !nearlyEqual(out[14], res)); out[14] = res; out[15] = 1; @@ -782,4 +795,13 @@ function multiply (out, a, b) { return changed; } +function nearlyEqual(a, b) +{ + var diff = Math.abs(a - b); + + // Note: Should be good enough for the needs here. + return diff < 0.01; +} + + module.exports = Transform; diff --git a/core/TransformSystem.js b/core/TransformSystem.js index f74daa6d..e795ce60 100644 --- a/core/TransformSystem.js +++ b/core/TransformSystem.js @@ -134,8 +134,11 @@ TransformSystem.prototype.get = function get (path) { * * @return {undefined} undefined */ -TransformSystem.prototype.update = function update () { - var transforms = this.pathStore.getItems(); +TransformSystem.prototype.update = function update() +{ + if (stats) stats.ProfileStart("trUp") + + var transforms = this.pathStore.getItems(); var paths = this.pathStore.getPaths(); var transform; var changed; @@ -144,25 +147,36 @@ TransformSystem.prototype.update = function update () { var offsets; var components; - for (var i = 0, len = transforms.length ; i < len ; i++) { - node = Dispatch.getNode(paths[i]); - if (!node) continue; - components = node.getComponents(); - transform = transforms[i]; - vectors = transform.vectors; - offsets = transform.offsets; - if (offsets.alignChanged) alignChanged(node, components, offsets); - if (offsets.mountPointChanged) mountPointChanged(node, components, offsets); - if (offsets.originChanged) originChanged(node, components, offsets); - if (vectors.positionChanged) positionChanged(node, components, vectors); - if (vectors.rotationChanged) rotationChanged(node, components, vectors); - if (vectors.scaleChanged) scaleChanged(node, components, vectors); - if ((changed = transform.calculate(node))) { - transformChanged(node, components, transform); - if (changed & Transform.LOCAL_CHANGED) localTransformChanged(node, components, transform.getLocalTransform()); - if (changed & Transform.WORLD_CHANGED) worldTransformChanged(node, components, transform.getWorldTransform()); - } + for (var i = 0, len = transforms.length ; i < len ; i++) + { + transform = transforms[i]; + if (transform.refresh) + { + transform.refresh = false; + + node = Dispatch.getNode(paths[i]); + if (node) + { + components = node.getComponents(); + transform = transforms[i]; + vectors = transform.vectors; + offsets = transform.offsets; + if (offsets.alignChanged) alignChanged(node, components, offsets); + if (offsets.mountPointChanged) mountPointChanged(node, components, offsets); + if (offsets.originChanged) originChanged(node, components, offsets); + if (vectors.positionChanged) positionChanged(node, components, vectors); + if (vectors.rotationChanged) rotationChanged(node, components, vectors); + if (vectors.scaleChanged) scaleChanged(node, components, vectors); + if ((changed = transform.calculate(node))) { + transformChanged(node, components, transform); + if (changed & Transform.LOCAL_CHANGED) localTransformChanged(node, components, transform.getLocalTransform()); + if (changed & Transform.WORLD_CHANGED) worldTransformChanged(node, components, transform.getWorldTransform()); + } + } + } } + + if(stats) stats.ProfileEnd("trUp") }; // private methods diff --git a/dom-renderers/Math.js b/dom-renderers/Math.js index 9b2dc09b..d30e86f5 100644 --- a/dom-renderers/Math.js +++ b/dom-renderers/Math.js @@ -114,10 +114,10 @@ function multiply (out, a, b) { out3 = b0*a03 + b1*a13 + b2*a23 + b3*a33; changed = changed ? - changed : out0 === out[0] || - out1 === out[1] || - out2 === out[2] || - out3 === out[3]; + changed : out0 !== out[0] || + out1 !== out[1] || + out2 !== out[2] || + out3 !== out[3]; out[0] = out0; out[1] = out1; @@ -131,10 +131,10 @@ function multiply (out, a, b) { out3 = b0*a03 + b1*a13 + b2*a23 + b3*a33; changed = changed ? - changed : out0 === out[4] || - out1 === out[5] || - out2 === out[6] || - out3 === out[7]; + changed : out0 !== out[4] || + out1 !== out[5] || + out2 !== out[6] || + out3 !== out[7]; out[4] = out0; out[5] = out1; @@ -148,10 +148,10 @@ function multiply (out, a, b) { out3 = b0*a03 + b1*a13 + b2*a23 + b3*a33; changed = changed ? - changed : out0 === out[8] || - out1 === out[9] || - out2 === out[10] || - out3 === out[11]; + changed : out0 !== out[8] || + out1 !== out[9] || + out2 !== out[10] || + out3 !== out[11]; out[8] = out0; out[9] = out1; @@ -165,10 +165,10 @@ function multiply (out, a, b) { out3 = b0*a03 + b1*a13 + b2*a23 + b3*a33; changed = changed ? - changed : out0 === out[12] || - out1 === out[13] || - out2 === out[14] || - out3 === out[15]; + changed : out0 !== out[12] || + out1 !== out[13] || + out2 !== out[14] || + out3 !== out[15]; out[12] = out0; out[13] = out1; diff --git a/render-loops/RequestAnimationFrameLoop.js b/render-loops/RequestAnimationFrameLoop.js index e2b1fd37..80cf5210 100644 --- a/render-loops/RequestAnimationFrameLoop.js +++ b/render-loops/RequestAnimationFrameLoop.js @@ -76,7 +76,9 @@ function RequestAnimationFrameLoop() { this._updates = []; this._looper = function(time) { - _this.loop(time); + if( stats ) stats.ProfileStart("gui") + _this.loop(time); + if (stats) stats.ProfileEnd("gui") }; this._time = 0; this._stoppedAt = 0; From 5f192937c260dcdc95dcaea85264eb20a5716d8b Mon Sep 17 00:00:00 2001 From: Arnleif Mydland Date: Wed, 27 Jan 2016 10:55:52 +0100 Subject: [PATCH 2/4] Hackish fix for performance loss in certain situation. The problem, massive amount of drawcommands being sent each frame, happens if DomElement.OnDismount is called and this.setCutoutState(false); happens. This call seem to be to turn off this cutout thing, but in my case it was never turned on. Anyway, it causes som webgl content to be created, just so it can set that flag to off. And in turn that causes the barrage of drawcommands. So this fix is hackish in the sense that it stops context._initWebGLRenderer(); from happening, and does not adress the real problem, whatever that is.. --- render-loops/RequestAnimationFrameLoop.js | 4 ++-- renderers/Context.js | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/render-loops/RequestAnimationFrameLoop.js b/render-loops/RequestAnimationFrameLoop.js index 80cf5210..09417e76 100644 --- a/render-loops/RequestAnimationFrameLoop.js +++ b/render-loops/RequestAnimationFrameLoop.js @@ -76,9 +76,9 @@ function RequestAnimationFrameLoop() { this._updates = []; this._looper = function(time) { - if( stats ) stats.ProfileStart("gui") + if (stats) stats.ProfileStart("gui"); _this.loop(time); - if (stats) stats.ProfileEnd("gui") + if (stats) stats.ProfileEnd("gui"); }; this._time = 0; this._stoppedAt = 0; diff --git a/renderers/Context.js b/renderers/Context.js index e59df0db..372856ee 100644 --- a/renderers/Context.js +++ b/renderers/Context.js @@ -484,9 +484,13 @@ function glBufferData (context, path, commands, iterator) { } function glCutoutState (context, path, commands, iterator) { - if (!context._webGLRenderer) context._initWebGLRenderer(); - context._webGLRenderer.setCutoutState(path, commands[++iterator]); - return iterator; + var state = commands[++iterator]; + if (!context._webGLRenderer && state) context._initWebGLRenderer(); + if (context._webGLRenderer) + { + context._webGLRenderer.setCutoutState(path, state); + } + return iterator; } function glMeshVisibility (context, path, commands, iterator) { From 71e652b08616953b4856ead2162aae3e713544b1 Mon Sep 17 00:00:00 2001 From: Arnleif Mydland Date: Fri, 29 Jan 2016 10:01:49 +0100 Subject: [PATCH 3/4] Opacity system to not do so much updating every frame. Should now only do it's things when some changes has happened. This save 12 ms on ipad2 when you have 1000 elements to go through. --- core/FamousEngine.js | 2 ++ core/Opacity.js | 48 ++++++++++++++++++++++++++++++++++++++++--- core/OpacitySystem.js | 36 +++++++++++++++++++++----------- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/core/FamousEngine.js b/core/FamousEngine.js index e75cfa88..f9f90782 100644 --- a/core/FamousEngine.js +++ b/core/FamousEngine.js @@ -159,7 +159,9 @@ FamousEngine.prototype._update = function _update () { SizeSystem.update(); TransformSystem.update(); + if (stats) stats.ProfileStart("osUp") OpacitySystem.update(); + if (stats) stats.ProfileEnd("osUp") while (nextQueue.length) queue.unshift(nextQueue.pop()); diff --git a/core/Opacity.js b/core/Opacity.js index 83fb1bcf..7cf9134b 100644 --- a/core/Opacity.js +++ b/core/Opacity.js @@ -31,6 +31,8 @@ function Opacity (parent) { this.parent = parent ? parent : null; this.breakPoint = false; this.calculatingWorldOpacity = false; + this.refresh = false; + this.childs = []; } Opacity.WORLD_CHANGED = 1; @@ -41,8 +43,26 @@ Opacity.prototype.reset = function reset () { this.breakPoint = false; }; -Opacity.prototype.setParent = function setParent (parent) { - this.parent = parent; +Opacity.prototype.setParent = function setParent(parent) +{ + if (this.parent) + { + // Remove as child. + var index = this.parent.childs.indexOf(this, 0); + if (index != undefined) + { + this.parent.childs.splice(index, 1); + } + } + + this.parent = parent; + + if (parent) + { + parent.childs.push(this); + this._refresh(); + } + }; Opacity.prototype.getParent = function getParent () { @@ -52,6 +72,7 @@ Opacity.prototype.getParent = function getParent () { Opacity.prototype.setBreakPoint = function setBreakPoint () { this.breakPoint = true; this.calculatingWorldOpacity = true; + this._refresh(); }; /** @@ -89,8 +110,29 @@ Opacity.prototype.getOpacity = function getOpacity () { return this.opacity; }; +Opacity.prototype._refresh = function _refresh(opacity) +{ + this.refresh = true; + + // Tell all it's children. + for (var i = 0, len = this.childs.length ; i < len ; i++) + { + if (!this.childs[i].refresh) + { + this.childs[i]._refresh(); + } + } +} + Opacity.prototype.setOpacity = function setOpacity (opacity) { - this.opacity = opacity; + var changed = this.opacity !== opacity; + this.opacity = opacity; + + if (changed) + { + this._refresh(); + } + }; Opacity.prototype.calculateWorldOpacity = function calculateWorldOpacity () { diff --git a/core/OpacitySystem.js b/core/OpacitySystem.js index 219fed04..5e062e1c 100644 --- a/core/OpacitySystem.js +++ b/core/OpacitySystem.js @@ -71,7 +71,11 @@ OpacitySystem.prototype.registerOpacityAtPath = function registerOpacityAtPath ( * * @param {String} path at which to register the opacity */ -OpacitySystem.prototype.deregisterOpacityAtPath = function deregisterOpacityAtPath (path) { +OpacitySystem.prototype.deregisterOpacityAtPath = function deregisterOpacityAtPath(path) +{ + var op = this.pathStore.get(path); + op.setParent(null); + this.pathStore.remove(path); }; @@ -140,17 +144,25 @@ OpacitySystem.prototype.update = function update () { var node; var components; - for (var i = 0, len = opacities.length ; i < len ; i++) { - node = Dispatch.getNode(paths[i]); - if (!node) continue; - components = node.getComponents(); - opacity = opacities[i]; - - if ((changed = opacity.calculate())) { - opacityChanged(node, components, opacity); - if (changed & Opacity.LOCAL_CHANGED) localOpacityChanged(node, components, opacity.getLocalOpacity()); - if (changed & Opacity.WORLD_CHANGED) worldOpacityChanged(node, components, opacity.getWorldOpacity()); - } + for (var i = 0, len = opacities.length ; i < len ; i++) + { + opacity = opacities[i]; + if (opacity.refresh) + { + opacity.refresh = false; + + node = Dispatch.getNode(paths[i]); + if (node) + { + if ((changed = opacity.calculate())) + { + components = node.getComponents(); + opacityChanged(node, components, opacity); + if (changed & Opacity.LOCAL_CHANGED) localOpacityChanged(node, components, opacity.getLocalOpacity()); + if (changed & Opacity.WORLD_CHANGED) worldOpacityChanged(node, components, opacity.getWorldOpacity()); + } + } + } } }; From 8fbffb9bd73b9bb456e6a18cc4acbaf90ac5532b Mon Sep 17 00:00:00 2001 From: Arnleif Mydland Date: Thu, 4 Feb 2016 14:47:30 +0100 Subject: [PATCH 4/4] My previous transform optimizing had a redraw problem. Fixed it by refreshing all child transforms when a node is refreshed. Similar to what I did for the opacity system. --- core/Opacity.js | 15 +- core/Transform.js | 122 ++++++--- core/TransformSystem.js | 540 ++++++++++++++++++++-------------------- 3 files changed, 372 insertions(+), 305 deletions(-) diff --git a/core/Opacity.js b/core/Opacity.js index 7cf9134b..a333d7e4 100644 --- a/core/Opacity.js +++ b/core/Opacity.js @@ -112,14 +112,17 @@ Opacity.prototype.getOpacity = function getOpacity () { Opacity.prototype._refresh = function _refresh(opacity) { - this.refresh = true; - - // Tell all it's children. - for (var i = 0, len = this.childs.length ; i < len ; i++) + if (!this.refresh) { - if (!this.childs[i].refresh) + this.refresh = true; + + // Tell all it's children. + for (var i = 0, len = this.childs.length ; i < len ; i++) { - this.childs[i]._refresh(); + if (!this.childs[i].refresh) + { + this.childs[i]._refresh(); + } } } } diff --git a/core/Transform.js b/core/Transform.js index f95eb4fa..abda5cb3 100644 --- a/core/Transform.js +++ b/core/Transform.js @@ -35,31 +35,34 @@ var ONES = [1, 1, 1]; * * @param {Transform} parent the parent Transform */ -function Transform (parent) { - this.local = new Float32Array(Transform.IDENT); - this.global = new Float32Array(Transform.IDENT); - this.offsets = { - align: new Float32Array(3), - alignChanged: false, - mountPoint: new Float32Array(3), - mountPointChanged: false, - origin: new Float32Array(3), - originChanged: false - }; - this.vectors = { - position: new Float32Array(3), - positionChanged: false, - rotation: new Float32Array(QUAT), - rotationChanged: false, - scale: new Float32Array(ONES), - scaleChanged: false - }; - this._lastEulerVals = [0, 0, 0]; - this._lastEuler = false; - this.parent = parent ? parent : null; - this.breakPoint = false; - this.calculatingWorldMatrix = false; - this.refresh = false; // The idea is that this changes to true if anything in the component needs to update. This allows us to early out in the update loop instead of trashng cache to check each sub objects changed state. +function Transform(parent) +{ + this.local = new Float32Array(Transform.IDENT); + this.global = new Float32Array(Transform.IDENT); + this.offsets = { + align: new Float32Array(3), + alignChanged: false, + mountPoint: new Float32Array(3), + mountPointChanged: false, + origin: new Float32Array(3), + originChanged: false + }; + this.vectors = { + position: new Float32Array(3), + positionChanged: false, + rotation: new Float32Array(QUAT), + rotationChanged: false, + scale: new Float32Array(ONES), + scaleChanged: false + }; + this._lastEulerVals = [0, 0, 0]; + this._lastEuler = false; + this.parent = parent ? parent : null; + this.breakPoint = false; + this.calculatingWorldMatrix = false; + + this.refresh = false; // The idea is that this changes to true if anything in the component needs to update. This allows us to early out in the update loop instead of trashng cache to check each sub objects changed state. + this.childs = []; } Transform.IDENT = [ 1, 0, 0, 0, @@ -93,10 +96,45 @@ Transform.prototype.reset = function reset () { * * @return {undefined} undefined */ -Transform.prototype.setParent = function setParent (parent) { - this.parent = parent; +Transform.prototype.setParent = function setParent(parent) +{ + if (this.parent) + { + // Remove as child. + var index = this.parent.childs.indexOf(this, 0); + if (index != undefined) + { + this.parent.childs.splice(index, 1); + } + } + + this.parent = parent; + + if (parent) + { + parent.childs.push(this); + this._refresh(); + } }; +Transform.prototype._refresh = function _refresh() +{ + // Refresh all if needed. + if (!this.refresh) + { + this.refresh = true; + + // Tell all it's children. + for (var i = 0, len = this.childs.length ; i < len ; i++) + { + if (!this.childs[i].refresh) + { + this.childs[i]._refresh(); + } + } + } +} + /** * returns the parent of this transform * @@ -256,7 +294,10 @@ Transform.prototype.getPosition = function getPosition () { Transform.prototype.setPosition = function setPosition (x, y, z) { var ch = setVec(this.vectors.position, x, y, z); this.vectors.positionChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** @@ -349,7 +390,10 @@ Transform.prototype.setRotation = function setRotation (x, y, z, w) { var ch = setVec(quat, qx, qy, qz, qw); this.vectors.rotationChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** @@ -377,7 +421,10 @@ Transform.prototype.getScale = function getScale () { Transform.prototype.setScale = function setScale (x, y, z) { var ch = setVec(this.vectors.scale, x, y, z); this.vectors.scaleChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** @@ -405,7 +452,10 @@ Transform.prototype.getAlign = function getAlign () { Transform.prototype.setAlign = function setAlign (x, y, z) { var ch = setVec(this.offsets.align, x, y, z != null ? z - 0.5 : z); this.offsets.alignChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** @@ -433,7 +483,10 @@ Transform.prototype.getMountPoint = function getMountPoint () { Transform.prototype.setMountPoint = function setMountPoint (x, y, z) { var ch = setVec(this.offsets.mountPoint, x, y, z != null ? z - 0.5 : z); this.offsets.mountPointChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** @@ -461,7 +514,10 @@ Transform.prototype.getOrigin = function getOrigin () { Transform.prototype.setOrigin = function setOrigin (x, y, z) { var ch = setVec(this.offsets.origin, x, y, z != null ? z - 0.5 : z); this.offsets.originChanged = ch; - this.refresh |= ch; + if (ch) + { + this._refresh(); + } }; /** diff --git a/core/TransformSystem.js b/core/TransformSystem.js index e795ce60..d8b4ef2f 100644 --- a/core/TransformSystem.js +++ b/core/TransformSystem.js @@ -36,7 +36,7 @@ var PathStore = require('./PathStore'); * @constructor {TransformSystem} */ function TransformSystem () { - this.pathStore = new PathStore(); + this.pathStore = new PathStore(); } /** @@ -49,341 +49,349 @@ function TransformSystem () { * @param {String} path for the transform to be registered to. * @param {Transform | undefined} transform optional transform to register. */ -TransformSystem.prototype.registerTransformAtPath = function registerTransformAtPath (path, transform) { - if (!PathUtils.depth(path)) - return this.pathStore.insert(path, transform ? transform : new Transform()); +TransformSystem.prototype.registerTransformAtPath = function registerTransformAtPath(path, transform) +{ + if (!PathUtils.depth(path)) + return this.pathStore.insert(path, transform ? transform : new Transform()); - var parent = this.pathStore.get(PathUtils.parent(path)); + var parent = this.pathStore.get(PathUtils.parent(path)); - if (!parent) throw new Error( + if (!parent) throw new Error( 'No parent transform registered at expected path: ' + PathUtils.parent(path) ); - if (transform) transform.setParent(parent); + if (transform) transform.setParent(parent); - this.pathStore.insert(path, transform ? transform : new Transform(parent)); + this.pathStore.insert(path, transform ? transform : new Transform(parent)); }; /** - * deregisters a transform registered at the given path. - * - * @method deregisterTransformAtPath - * @return {void} - * - * @param {String} path at which to register the transform - */ -TransformSystem.prototype.deregisterTransformAtPath = function deregisterTransformAtPath (path) { - this.pathStore.remove(path); + * deregisters a transform registered at the given path. + * + * @method deregisterTransformAtPath + * @return {void} + * + * @param {String} path at which to register the transform + */ +TransformSystem.prototype.deregisterTransformAtPath = function deregisterTransformAtPath(path) +{ + var transform = this.pathStore.get(path); + if (transform) + { + // Just to be sure. + transform.node = null; + } + + this.pathStore.remove(path); }; /** - * Method which will make the transform currently stored at the given path a breakpoint. - * A transform being a breakpoint means that both a local and world transform will be calculated - * for that point. The local transform being the concatinated transform of all ancestor transforms up - * until the nearest breakpoint, and the world being the concatinated transform of all ancestor transforms. - * This method throws if no transform is at the provided path. - * - * @method - * - * @param {String} path The path at which to turn the transform into a breakpoint - * - * @return {undefined} undefined - */ + * Method which will make the transform currently stored at the given path a breakpoint. + * A transform being a breakpoint means that both a local and world transform will be calculated + * for that point. The local transform being the concatinated transform of all ancestor transforms up + * until the nearest breakpoint, and the world being the concatinated transform of all ancestor transforms. + * This method throws if no transform is at the provided path. + * + * @method + * + * @param {String} path The path at which to turn the transform into a breakpoint + * + * @return {undefined} undefined + */ TransformSystem.prototype.makeBreakPointAt = function makeBreakPointAt (path) { - var transform = this.pathStore.get(path); - if (!transform) throw new Error('No transform Registered at path: ' + path); - transform.setBreakPoint(); + var transform = this.pathStore.get(path); + if (!transform) throw new Error('No transform Registered at path: ' + path); + transform.setBreakPoint(); }; /** - * Method that will make the transform at this location calculate a world matrix. - * - * @method - * - * @param {String} path The path at which to make the transform calculate a world matrix - * - * @return {undefined} undefined - */ + * Method that will make the transform at this location calculate a world matrix. + * + * @method + * + * @param {String} path The path at which to make the transform calculate a world matrix + * + * @return {undefined} undefined + */ TransformSystem.prototype.makeCalculateWorldMatrixAt = function makeCalculateWorldMatrixAt (path) { - var transform = this.pathStore.get(path); - if (!transform) throw new Error('No transform Registered at path: ' + path); - transform.setCalculateWorldMatrix(); + var transform = this.pathStore.get(path); + if (!transform) throw new Error('No transform Registered at path: ' + path); + transform.setCalculateWorldMatrix(); }; /** - * Returns the instance of the transform class associated with the given path, - * or undefined if no transform is associated. - * - * @method - * - * @param {String} path The path to lookup - * - * @return {Transform | undefined} the transform at that path is available, else undefined. - */ + * Returns the instance of the transform class associated with the given path, + * or undefined if no transform is associated. + * + * @method + * + * @param {String} path The path to lookup + * + * @return {Transform | undefined} the transform at that path is available, else undefined. + */ TransformSystem.prototype.get = function get (path) { - return this.pathStore.get(path); + return this.pathStore.get(path); }; /** - * update is called when the transform system requires an update. - * It traverses the transform array and evaluates the necessary transforms - * in the scene graph with the information from the corresponding node - * in the scene graph - * - * @method update - * - * @return {undefined} undefined - */ + * update is called when the transform system requires an update. + * It traverses the transform array and evaluates the necessary transforms + * in the scene graph with the information from the corresponding node + * in the scene graph + * + * @method update + * + * @return {undefined} undefined + */ TransformSystem.prototype.update = function update() { if (stats) stats.ProfileStart("trUp") var transforms = this.pathStore.getItems(); - var paths = this.pathStore.getPaths(); - var transform; - var changed; - var node; - var vectors; - var offsets; - var components; + var paths = this.pathStore.getPaths(); + var transform; + var changed; + var node; + var vectors; + var offsets; + var components; - for (var i = 0, len = transforms.length ; i < len ; i++) - { - transform = transforms[i]; - if (transform.refresh) - { - transform.refresh = false; + for (var i = 0, len = transforms.length ; i < len ; i++) + { + transform = transforms[i]; + if (transform.refresh) + { + transform.refresh = false; - node = Dispatch.getNode(paths[i]); - if (node) - { - components = node.getComponents(); - transform = transforms[i]; - vectors = transform.vectors; - offsets = transform.offsets; - if (offsets.alignChanged) alignChanged(node, components, offsets); - if (offsets.mountPointChanged) mountPointChanged(node, components, offsets); - if (offsets.originChanged) originChanged(node, components, offsets); - if (vectors.positionChanged) positionChanged(node, components, vectors); - if (vectors.rotationChanged) rotationChanged(node, components, vectors); - if (vectors.scaleChanged) scaleChanged(node, components, vectors); - if ((changed = transform.calculate(node))) { - transformChanged(node, components, transform); - if (changed & Transform.LOCAL_CHANGED) localTransformChanged(node, components, transform.getLocalTransform()); - if (changed & Transform.WORLD_CHANGED) worldTransformChanged(node, components, transform.getWorldTransform()); - } - } - } - } + node = Dispatch.getNode(paths[i]); + if (node) + { + components = node.getComponents(); + vectors = transform.vectors; + offsets = transform.offsets; + if (offsets.alignChanged) alignChanged(node, components, offsets); + if (offsets.mountPointChanged) mountPointChanged(node, components, offsets); + if (offsets.originChanged) originChanged(node, components, offsets); + if (vectors.positionChanged) positionChanged(node, components, vectors); + if (vectors.rotationChanged) rotationChanged(node, components, vectors); + if (vectors.scaleChanged) scaleChanged(node, components, vectors); + if ((changed = transform.calculate(node))) { + transformChanged(node, components, transform); + if (changed & Transform.LOCAL_CHANGED) localTransformChanged(node, components, transform.getLocalTransform()); + if (changed & Transform.WORLD_CHANGED) worldTransformChanged(node, components, transform.getWorldTransform()); + } + } + } + } - if(stats) stats.ProfileEnd("trUp") + if(stats) stats.ProfileEnd("trUp") }; // private methods /** - * Private method to call when align changes. Triggers 'onAlignChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to call onAlignChange if necessary - * @param {Array} components the components on which to call onAlignChange if necessary - * @param {Object} offsets the set of offsets from the transform - * - * @return {undefined} undefined - */ + * Private method to call when align changes. Triggers 'onAlignChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to call onAlignChange if necessary + * @param {Array} components the components on which to call onAlignChange if necessary + * @param {Object} offsets the set of offsets from the transform + * + * @return {undefined} undefined + */ function alignChanged (node, components, offsets) { - var x = offsets.align[0]; - var y = offsets.align[1]; - var z = offsets.align[2]; - if (node.onAlignChange) node.onAlignChange(x, y, z); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onAlignChange) - components[i].onAlignChange(x, y, z); - offsets.alignChanged = false; + var x = offsets.align[0]; + var y = offsets.align[1]; + var z = offsets.align[2]; + if (node.onAlignChange) node.onAlignChange(x, y, z); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onAlignChange) + components[i].onAlignChange(x, y, z); + offsets.alignChanged = false; } /** - * Private method to call when MountPoint changes. Triggers 'onMountPointChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Object} offsets the set of offsets from the transform - * - * @return {undefined} undefined - */ + * Private method to call when MountPoint changes. Triggers 'onMountPointChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Object} offsets the set of offsets from the transform + * + * @return {undefined} undefined + */ function mountPointChanged (node, components, offsets) { - var x = offsets.mountPoint[0]; - var y = offsets.mountPoint[1]; - var z = offsets.mountPoint[2]; - if (node.onMountPointChange) node.onMountPointChange(x, y, z); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onMountPointChange) - components[i].onMountPointChange(x, y, z); - offsets.mountPointChanged = false; + var x = offsets.mountPoint[0]; + var y = offsets.mountPoint[1]; + var z = offsets.mountPoint[2]; + if (node.onMountPointChange) node.onMountPointChange(x, y, z); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onMountPointChange) + components[i].onMountPointChange(x, y, z); + offsets.mountPointChanged = false; } /** - * Private method to call when Origin changes. Triggers 'onOriginChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Object} offsets the set of offsets from the transform - * - * @return {undefined} undefined - */ + * Private method to call when Origin changes. Triggers 'onOriginChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Object} offsets the set of offsets from the transform + * + * @return {undefined} undefined + */ function originChanged (node, components, offsets) { - var x = offsets.origin[0]; - var y = offsets.origin[1]; - var z = offsets.origin[2]; - if (node.onOriginChange) node.onOriginChange(x, y, z); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onOriginChange) - components[i].onOriginChange(x, y, z); - offsets.originChanged = false; + var x = offsets.origin[0]; + var y = offsets.origin[1]; + var z = offsets.origin[2]; + if (node.onOriginChange) node.onOriginChange(x, y, z); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onOriginChange) + components[i].onOriginChange(x, y, z); + offsets.originChanged = false; } /** - * Private method to call when Position changes. Triggers 'onPositionChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Object} vectors the set of vectors from the transform - * - * @return {undefined} undefined - */ + * Private method to call when Position changes. Triggers 'onPositionChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Object} vectors the set of vectors from the transform + * + * @return {undefined} undefined + */ function positionChanged (node, components, vectors) { - var x = vectors.position[0]; - var y = vectors.position[1]; - var z = vectors.position[2]; - if (node.onPositionChange) node.onPositionChange(x, y, z); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onPositionChange) - components[i].onPositionChange(x, y, z); - vectors.positionChanged = false; + var x = vectors.position[0]; + var y = vectors.position[1]; + var z = vectors.position[2]; + if (node.onPositionChange) node.onPositionChange(x, y, z); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onPositionChange) + components[i].onPositionChange(x, y, z); + vectors.positionChanged = false; } /** - * Private method to call when Rotation changes. Triggers 'onRotationChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Object} vectors the set of vectors from the transform - * - * @return {undefined} undefined - */ + * Private method to call when Rotation changes. Triggers 'onRotationChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Object} vectors the set of vectors from the transform + * + * @return {undefined} undefined + */ function rotationChanged (node, components, vectors) { - var x = vectors.rotation[0]; - var y = vectors.rotation[1]; - var z = vectors.rotation[2]; - var w = vectors.rotation[3]; - if (node.onRotationChange) node.onRotationChange(x, y, z, w); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onRotationChange) - components[i].onRotationChange(x, y, z, w); - vectors.rotationChanged = false; + var x = vectors.rotation[0]; + var y = vectors.rotation[1]; + var z = vectors.rotation[2]; + var w = vectors.rotation[3]; + if (node.onRotationChange) node.onRotationChange(x, y, z, w); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onRotationChange) + components[i].onRotationChange(x, y, z, w); + vectors.rotationChanged = false; } /** - * Private method to call when Scale changes. Triggers 'onScaleChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Object} vectors the set of vectors from the transform - * - * @return {undefined} undefined - */ + * Private method to call when Scale changes. Triggers 'onScaleChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Object} vectors the set of vectors from the transform + * + * @return {undefined} undefined + */ function scaleChanged (node, components, vectors) { - var x = vectors.scale[0]; - var y = vectors.scale[1]; - var z = vectors.scale[2]; - if (node.onScaleChange) node.onScaleChange(x, y, z); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onScaleChange) - components[i].onScaleChange(x, y, z); - vectors.scaleChanged = false; + var x = vectors.scale[0]; + var y = vectors.scale[1]; + var z = vectors.scale[2]; + if (node.onScaleChange) node.onScaleChange(x, y, z); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onScaleChange) + components[i].onScaleChange(x, y, z); + vectors.scaleChanged = false; } /** - * Private method to call when either the Local or World Transform changes. - * Triggers 'onTransformChange' methods on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Transform} transform the transform class that changed - * - * @return {undefined} undefined - */ + * Private method to call when either the Local or World Transform changes. + * Triggers 'onTransformChange' methods on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Transform} transform the transform class that changed + * + * @return {undefined} undefined + */ function transformChanged (node, components, transform) { - if (node.onTransformChange) node.onTransformChange(transform); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onTransformChange) - components[i].onTransformChange(transform); + if (node.onTransformChange) node.onTransformChange(transform); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onTransformChange) + components[i].onTransformChange(transform); } /** - * Private method to call when the local transform changes. Triggers 'onLocalTransformChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Array} transform the local transform - * - * @return {undefined} undefined - */ + * Private method to call when the local transform changes. Triggers 'onLocalTransformChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Array} transform the local transform + * + * @return {undefined} undefined + */ function localTransformChanged (node, components, transform) { - if (node.onLocalTransformChange) node.onLocalTransformChange(transform); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onLocalTransformChange) - components[i].onLocalTransformChange(transform); + if (node.onLocalTransformChange) node.onLocalTransformChange(transform); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onLocalTransformChange) + components[i].onLocalTransformChange(transform); } /** - * Private method to call when the world transform changes. Triggers 'onWorldTransformChange' methods - * on the node and all of the node's components - * - * @method - * @private - * - * @param {Node} node the node on which to trigger a change event if necessary - * @param {Array} components the components on which to trigger a change event if necessary - * @param {Array} transform the world transform - * - * @return {undefined} undefined - */ + * Private method to call when the world transform changes. Triggers 'onWorldTransformChange' methods + * on the node and all of the node's components + * + * @method + * @private + * + * @param {Node} node the node on which to trigger a change event if necessary + * @param {Array} components the components on which to trigger a change event if necessary + * @param {Array} transform the world transform + * + * @return {undefined} undefined + */ function worldTransformChanged (node, components, transform) { - if (node.onWorldTransformChange) node.onWorldTransformChange(transform); - for (var i = 0, len = components.length ; i < len ; i++) - if (components[i] && components[i].onWorldTransformChange) - components[i].onWorldTransformChange(transform); + if (node.onWorldTransformChange) node.onWorldTransformChange(transform); + for (var i = 0, len = components.length ; i < len ; i++) + if (components[i] && components[i].onWorldTransformChange) + components[i].onWorldTransformChange(transform); } module.exports = new TransformSystem();