/** * System takes care of updating all the entities (based on their component data) * @param apiSystem R3.API.System * @constructor */ R3.System.Animation = function( apiSystem ) { R3.System.call( this, apiSystem ); this.animations = []; // this.textures = []; // this.textureIds = []; // this.latest = {}; this.textures = {}; this.textureIds = []; // this.animationMeshAddedSubscription = null; // this.animationMeshRemovedSubscription = null; this.instanceCreatedSubscription = null; this.removeComponentSubscription = null; this.textureAnimatedSubscription = null; /** * Sometimes we want to animate texture instances directly, without the overhead of a R3.Texture */ this.animateTextureInstanceSubscription = null; }; R3.System.Animation.prototype = Object.create(R3.System.prototype); R3.System.Animation.prototype.constructor = R3.System.Animation; R3.System.Animation.prototype.start = function() { R3.System.prototype.start.call(this); this.beforeRenderSubscription = R3.Event.Subscribe( R3.Event.BEFORE_RENDER, this.beforeRender.bind(this) ); this.animations = R3.EntityManager.Instance.queryComponents(R3.Component.ANIMATION); // // animations.map(function(animation){ // animation.meshes.map( // function(mesh) { // this.attachAnimation(animation, mesh); // }.bind(this) // ); // this.animations[animation.id] = animation; // }.bind(this)); // this.animationMeshAddedSubscription = R3.Event.Subscribe( // R3.Event.ANIMATION_MESH_ADDED, // function(data) { // this.attachAnimation(data.animation, data.mesh); // }.bind(this) // ); // // this.animationMeshRemovedSubscription = R3.Event.Subscribe( // R3.Event.ANIMATION_MESH_REMOVED, // function(data) { // this.detachAnimation(data.mesh); // }.bind(this) // ); this.instanceCreatedSubscription = R3.Event.Subscribe( R3.Event.INSTANCE_CREATED, this.instanceCreated.bind(this) ); this.removeComponentSubscription = R3.Event.Subscribe( R3.Event.REMOVE_COMPONENT, this.removeComponent.bind(this) ); this.textureAnimatedSubscription = R3.Event.Subscribe( R3.Event.TEXTURE_ANIMATED_CHANGE, this.textureAnimatedChange.bind(this) ); this.animateTextureInstanceSubscription = R3.Event.Subscribe( R3.Event.ANIMATE_TEXTURE_INSTANCE, this.animateTextureInstance.bind(this) ) }; R3.System.Animation.prototype.instanceCreated = function(data) { if ( data.component instanceof R3.D3.Texture && data.component.animated ) { if (data.component.repeat.x > 1 || data.component.repeat.x < 0) { console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0'); data.component.animated = false; return; } if (data.component.repeat.y > 1 || data.component.repeat.y < 0) { console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0'); data.component.animated = false; return; } this.textures[data.component.id] = data.component; this.textureIds = Object.keys(this.textures); } if (data.component instanceof R3.D3.Animation) { R3.Utils.PushUnique(this.animations, data.component); // // this.animations[data.component.id] = data.component; // data.component.meshes.map( // function(mesh){ // this.attachAnimation(data.component, mesh) // }.bind(this) // ); } }; R3.System.Animation.prototype.removeComponent = function(data) { if ( data.component instanceof R3.D3.Texture && data.component.animated ) { if (R3.Utils.UndefinedOrNull(this.textures[data.component.id])) { console.warn('tried to remove an animated texture, which should have been in the list but isnt: ' + data.component.name); } else { delete this.textures[data.component.id]; this.textureIds = Object.keys(this.textures); } } if (data.component instanceof R3.D3.Animation) { var index = this.animations.indexOf(data.component); if (index === -1) { console.warn('animation index out of sync'); } else { this.animations.splice(index, 1); } } if (data.component instanceof R3.D3.Mesh) { this.animations.map( function(animation) { var index = animation.meshes.indexOf(data.component); if (index !== -1) { animation.meshes.splice(index, 1); animation.updateInstance('meshes'); } } ) } }; R3.System.Animation.prototype.textureAnimatedChange = function(data) { if (data.texture.animated) { if (data.texture.repeat.x > 1 || data.texture.repeat.x < 0) { console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0'); data.texture.animated = false; return; } if (data.texture.repeat.y > 1 || data.texture.repeat.y < 0) { console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0'); data.texture.animated = false; return; } this.textures[data.texture.id] = data.texture; this.textureIds = Object.keys(this.textures); } else { if (R3.Utils.UndefinedOrNull(this.textures[data.texture.id])) { console.warn('tried to remove an animated texture, which should have been in the list but isnt: ' + data.texture.name); } else { delete this.textures[data.texture.id]; this.textureIds = Object.keys(this.textures); } } }; /** * This adds a texture instance directly on our textures to be animated - to bypass our R3 component and linking * system, which adds too much overhead for managing textures * @param data */ R3.System.Animation.prototype.animateTextureInstance = function(data) { if (data.texture.repeat.x > 1 || data.texture.repeat.x < 0) { console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0'); data.texture.userData.animated = false; return; } if (data.texture.repeat.y > 1 || data.texture.repeat.y < 0) { console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0'); data.texture.userData.animated = false; return; } data.texture.userData.animated = true; this.textures[data.texture.id] = data.texture; this.textureIds = Object.keys(this.textures); }; /** * Performs a slight change on object[property][subProperty] from instance towards object * @param object * @param property * @param subProperty * @param increment * @returns {boolean} */ R3.System.Animation.prototype.slightChange = function(object, property, subProperty, increment) { var current = object.instance[property][subProperty]; var target = object[property][subProperty]; if (Math.abs(target - current) < increment) { object.instance[property][subProperty] = object[property][subProperty]; return false; } else if (current > target) { object.instance[property][subProperty] -= increment; } else { object.instance[property][subProperty] += increment; } return true; }; R3.System.Animation.prototype.beforeRender = function(data) { if (this.paused) { return; } var increment = 0; this.animations.map( function(animation) { animation.meshes.map( function(mesh) { if (animation.rotationSpeed) { /** * Apply slight rotation to mesh */ increment = animation.rotationSpeed * data.delta; this.slightChange(mesh, 'rotation', 'x', increment); this.slightChange(mesh, 'rotation', 'y', increment); this.slightChange(mesh, 'rotation', 'z', increment); } if (animation.translationSpeed) { /** * Apply slight translation to mesh */ increment = animation.translationSpeed * data.delta; this.slightChange(mesh, 'position', 'x', increment); this.slightChange(mesh, 'position', 'y', increment); this.slightChange(mesh, 'position', 'z', increment); } if (animation.scaleSpeed) { /** * Apply slight scale to mesh */ increment = animation.scaleSpeed * data.delta; this.slightChange(mesh, 'scale', 'x', increment); this.slightChange(mesh, 'scale', 'y', increment); this.slightChange(mesh, 'scale', 'z', increment); } }.bind(this) ) }.bind(this) ); this.textureIds.map( function(textureId) { var texture = this.textures[textureId]; if (texture.reverseAnimation || (texture.userData && texture.userData.reverseAnimation)) { if (texture.forward === true || (texture.userData && texture.userData.forward === true)) { texture.offset.x += texture.repeat.x; if (texture.offset.x >= (1 - texture.repeat.x)) { if (texture.offset.y >= (1 - texture.repeat.y)) { texture.offset.x = (1 - texture.repeat.x); texture.offset.y = (1 - texture.repeat.y); if (texture.userData) { texture.userData.forward = false; } else { texture.forward = false; } } else { texture.offset.x = 0; texture.offset.y += texture.repeat.y; } } } if (texture.forward === false || (texture.userData && texture.userData.forward === false)) { texture.offset.x -= texture.repeat.x; if (texture.offset.x <= 0) { texture.offset.x = 0; if (texture.offset.y < texture.repeat.y) { texture.offset.x = texture.repeat.x; texture.offset.y = 0; if (texture.userData) { texture.userData.forward = true; } else { texture.forward = true; } } else { texture.offset.x = (1 - texture.repeat.x); texture.offset.y -= texture.repeat.y; } } } } else { texture.offset.x += texture.repeat.x; if (texture.offset.x >= (1 - texture.repeat.x)) { if (texture.offset.y >= (1 - texture.repeat.y)) { texture.offset.x = 0; texture.offset.y = 0; } else { texture.offset.x = 0; texture.offset.y += texture.repeat.y; } } } if (!texture.userData) { texture.updateInstance('offset'); } }.bind(this) ) }; /** * Stop Animation System */ R3.System.Animation.prototype.stop = function() { R3.System.prototype.stop.call(this); this.beforeRenderSubscription.remove(); // this.animationMeshAddedSubscription.remove(); // // this.animationMeshRemovedSubscription.remove(); // this.animations = []; this.instanceCreatedSubscription.remove(); this.removeComponentSubscription.remove(); this.textureAnimatedSubscription.remove(); this.animateTextureInstanceSubscription.remove(); }; /* R3.System.Animation.prototype.detachAnimation = function(mesh) { var detached = false; if (mesh.backupQuaternionAngleDescriptor) { Object.defineProperty( mesh.quaternion, 'angle', mesh.backupQuaternionAngleDescriptor ); delete mesh.backupQuaternionAngleDescriptor; detached = true; } if (mesh.backupQuaternionAxisXDescriptor) { Object.defineProperty( mesh.quaternion.axis, 'x', mesh.backupQuaternionAxisXDescriptor ); delete mesh.backupQuaternionAxisXDescriptor; detached = true; } if (mesh.backupQuaternionAxisYDescriptor) { Object.defineProperty( mesh.quaternion.axis, 'y', mesh.backupQuaternionAxisYDescriptor ); delete mesh.backupQuaternionAxisYDescriptor; detached = true; } if (mesh.backupQuaternionAxisZDescriptor) { Object.defineProperty( mesh.quaternion.axis, 'z', mesh.backupQuaternionAxisZDescriptor ); delete mesh.backupQuaternionAxisXDescriptor; detached = true; } if (mesh.backupRotationXDescriptor) { Object.defineProperty( mesh.rotation, 'x', mesh.backupRotationXDescriptor ); delete mesh.backupRotationXDescriptor; detached = true; } if (mesh.backupRotationYDescriptor) { Object.defineProperty( mesh.rotation, 'y', mesh.backupRotationYDescriptor ); delete mesh.backupRotationYDescriptor; detached = true; } if (mesh.backupRotationZDescriptor) { Object.defineProperty( mesh.rotation, 'z', mesh.backupRotationZDescriptor ); delete mesh.backupRotationZDescriptor; detached = true; } if (mesh.backupPositionXDescriptor) { Object.defineProperty( mesh.position, 'x', mesh.backupPositionXDescriptor ); delete mesh.backupPositionXDescriptor; detached = true; } if (mesh.backupPositionYDescriptor) { Object.defineProperty( mesh.position, 'y', mesh.backupPositionYDescriptor ); delete mesh.backupPositionYDescriptor; detached = true; } if (mesh.backupPositionZDescriptor) { Object.defineProperty( mesh.position, 'z', mesh.backupPositionZDescriptor ); delete mesh.backupPositionZDescriptor; detached = true; } if (mesh.backupScaleXDescriptor) { Object.defineProperty( mesh.scale, 'x', mesh.backupScaleXDescriptor ); delete mesh.backupScaleXDescriptor; detached = true; } if (mesh.backupScaleYDescriptor) { Object.defineProperty( mesh.scale, 'y', mesh.backupScaleYDescriptor ); delete mesh.backupScaleYDescriptor; detached = true; } if (mesh.backupScaleZDescriptor) { Object.defineProperty( mesh.scale, 'z', mesh.backupScaleZDescriptor ); delete mesh.backupScaleZDescriptor; detached = true; } if (this.latest[mesh.id]) { mesh.rotation.x = this.latest[mesh.id].rotation.x; mesh.rotation.y = this.latest[mesh.id].rotation.y; mesh.rotation.z = this.latest[mesh.id].rotation.z; mesh.position.x = this.latest[mesh.id].position.x; mesh.position.y = this.latest[mesh.id].position.y; mesh.position.z = this.latest[mesh.id].position.z; mesh.scale.x = this.latest[mesh.id].scale.x; mesh.scale.y = this.latest[mesh.id].scale.y; mesh.scale.z = this.latest[mesh.id].scale.z; mesh.quaternion.axis.x = this.latest[mesh.id].quaternion.axis.x; mesh.quaternion.axis.y = this.latest[mesh.id].quaternion.axis.y; mesh.quaternion.axis.z = this.latest[mesh.id].quaternion.axis.z; mesh.quaternion.angle = this.latest[mesh.id].quaternion.angle; delete this.latest[mesh.id]; detached = true; } if (this.animations[mesh.id]) { delete this.animations[mesh.id]; detached = true; } if (detached) { mesh.updateInstance('position'); mesh.updateInstance('rotation'); mesh.updateInstance('scale'); } }; */ //R3.System.Animation.prototype.attachAnimation = function(animation, mesh) { /** * Initialize the property with the original mesh z value */ /* this.latest[mesh.id] = { rotation : { x : mesh.rotation.x, y : mesh.rotation.y, z : mesh.rotation.z }, position : { x : mesh.position.x, y : mesh.position.y, z : mesh.position.z }, scale : { x : mesh.scale.x, y : mesh.scale.y, z : mesh.scale.z }, quaternion : { axis : { x : mesh.quaternion.axis.x, y : mesh.quaternion.axis.y, z : mesh.quaternion.axis.z }, angle : mesh.quaternion.angle } }; this.animations[mesh.id] = []; if (mesh.backupRotationXDescriptor) { throw new Error('already a backed up x descriptor'); } mesh.backupQuaternionAngleDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion, 'angle'); mesh.backupQuaternionAxisXDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'x'); mesh.backupQuaternionAxisYDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'y'); mesh.backupQuaternionAxisZDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'z'); mesh.backupRotationXDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'x'); mesh.backupRotationYDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'y'); mesh.backupRotationZDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'z'); mesh.backupPositionXDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'x'); mesh.backupPositionYDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'y'); mesh.backupPositionZDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'z'); mesh.backupScaleXDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'x'); mesh.backupScaleYDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'y'); mesh.backupScaleZDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'z'); Object.defineProperty( mesh.quaternion, 'angle', { 'get': this.getProperty(mesh, 'angle', 'quaternion'), 'set': this.setProperty(mesh, animation, 'angle', 'quaternion'), 'configurable': true } ); Object.defineProperty( mesh.quaternion.axis, 'x', { 'get': this.getSubProperty(mesh, 'x', 'quaternion', 'axis'), 'set': this.setSubProperty(mesh, animation, 'x', 'quaternion', 'axis'), 'configurable': true } ); Object.defineProperty( mesh.quaternion.axis, 'y', { 'get': this.getSubProperty(mesh, 'y', 'quaternion', 'axis'), 'set': this.setSubProperty(mesh, animation, 'y', 'quaternion', 'axis'), 'configurable': true } ); Object.defineProperty( mesh.quaternion.axis, 'z', { 'get': this.getSubProperty(mesh, 'z', 'quaternion', 'axis'), 'set': this.setSubProperty(mesh, animation, 'z', 'quaternion', 'axis'), 'configurable': true } ); Object.defineProperty( mesh.rotation, 'x', { 'get': this.getProperty(mesh, 'x', 'rotation'), 'set': this.setProperty(mesh, animation, 'x', 'rotation'), 'configurable': true } ); Object.defineProperty( mesh.rotation, 'y', { 'get': this.getProperty(mesh, 'y', 'rotation'), 'set': this.setProperty(mesh, animation, 'y', 'rotation'), 'configurable': true } ); Object.defineProperty( mesh.rotation, 'z', { 'get': this.getProperty(mesh, 'z', 'rotation'), 'set': this.setProperty(mesh, animation, 'z', 'rotation'), 'configurable': true } ); Object.defineProperty( mesh.scale, 'x', { 'get': this.getProperty(mesh, 'x', 'scale'), 'set': this.setProperty(mesh, animation, 'x', 'scale'), 'configurable': true } ); Object.defineProperty( mesh.scale, 'y', { 'get': this.getProperty(mesh, 'y', 'scale'), 'set': this.setProperty(mesh, animation, 'y', 'scale'), 'configurable': true } ); Object.defineProperty( mesh.scale, 'z', { 'get': this.getProperty(mesh, 'z', 'scale'), 'set': this.setProperty(mesh, animation, 'z', 'scale'), 'configurable': true } ); Object.defineProperty( mesh.position, 'x', { 'get': this.getProperty(mesh, 'x', 'position'), 'set': this.setProperty(mesh, animation, 'x', 'position'), 'configurable': true } ); Object.defineProperty( mesh.position, 'y', { 'get': this.getProperty(mesh, 'y', 'position'), 'set': this.setProperty(mesh, animation, 'y', 'position'), 'configurable': true } ); Object.defineProperty( mesh.position, 'z', { 'get': this.getProperty(mesh, 'z', 'position'), 'set': this.setProperty(mesh, animation, 'z', 'position'), 'configurable': true } ); }; */ // R3.System.Animation.prototype.getQuaternionAngle = function(mesh, animation) { // // return function() { // return; // /** // * TODO: fix this shit.. // * Back up the current property descriptor // */ // mesh.animationObject = { // backupAngleDescriptor: Object.getOwnPropertyDescriptor(mesh.quaternion, 'angle'), // targetAngle: mesh.quaternion.angle, // angleIncrement: true, // intermediateAngle: mesh.quaternion.angle, // subscription: null, // inProcess: false, // blocking: animation.blocking//, // // callbacks : [], // // storedValues : [] // }; // // var getIntermediateAngle = function() { // return mesh.animationObject.intermediateAngle; // }; // // var getTargetAngle = function() { // // // if (mesh.animationObject.storedValues.length > 0) { // // return mesh.animationObject.storedValues[mesh.animationObject.storedValues.length - 1]; // // } // // return mesh.animationObject.targetAngle; // }; // // var animateRotation = function(value) { // // mesh.animationObject.intermediateAngle += value; // // var done = false; // // if (mesh.animationObject.angleIncrement) { // /** // * We are rotating upwards // */ // if (mesh.animationObject.intermediateAngle >= mesh.animationObject.targetAngle) { // /** // * We need to stop // */ // done = true; // } // } else { // /** // * We are rotating downwards // */ // if (mesh.animationObject.intermediateAngle <= mesh.animationObject.targetAngle) { // /** // * We need to stop // */ // done = true; // } // } // // if (done) { // // /** // * We clamp to our target angle // */ // mesh.animationObject.intermediateAngle = mesh.animationObject.targetAngle; // // /** // * We limit our intermediate angle between values of -pi and pi // */ // while (mesh.animationObject.intermediateAngle > Math.PI) { // mesh.animationObject.intermediateAngle -= (Math.PI * 2); // } // // while (mesh.animationObject.intermediateAngle < -(Math.PI)) { // mesh.animationObject.intermediateAngle += (Math.PI * 2); // } // // /** // * We apply our new intermediate angle to our target // */ // mesh.animationObject.targetAngle = mesh.animationObject.intermediateAngle; // } // // /** // * Apply the actual rotation to the mesh // */ // mesh.updateInstanceRotationFromAxisAngle(mesh.quaternion.axis, mesh.animationObject.intermediateAngle); // // /** // * Check again if we are done, we need to do some additional work - // */ // if (done) { // // if (!mesh.animationObject.subscription) { // var message = 'mesh animation object subscription went missing for '; // message += mesh.name + ': '; // message += animation.name; // console.warn(message); // throw new Error(message); // } // // /** // * Stop subscribing to before render events // */ // mesh.animationObject.subscription.remove(); // // /** // * @type {null} // */ // mesh.animationObject.subscription = null; // // /** // * For some meshes, when we are done with the animation, we want to apply // * the current state of the mesh to the object data itself (i.e. update // * its vertices etc) // */ // if (animation.applyToMeshWhenDone) { // /** // * Now we say that our intermediate angle is zero, because we will apply our rotation // * and this will prevent us from re-registering a new 'animationRender' event // */ // mesh.animationObject.targetAngle = 0; // mesh.animationObject.intermediateAngle = 0; // // /** // * Apply our position, rotation and scale to the mesh // */ // mesh.applyPositionRotationScale(); // } // // /** // * Tell our animation component that it is no longer in process... // * @type {boolean} // */ // mesh.animationObject.inProcess = false; // // // if (mesh.animationObject.callbacks.length > 0) { // // var callback = mesh.animationObject.callbacks[0]; // // mesh.animationObject.callbacks.splice(0,1); // // callback(); // // } // // // mesh.animationObject.storedValues = []; // } // }; // } // }; // // R3.System.Animation.prototype.setQuaternionAngle = function(mesh, animation) { // // return function(value) { // return; // /** // * TODO: update this shit // */ // /** // * Check if we have work to do // */ // if (mesh.animationObject.intermediateAngle === value) { // // mesh.animationObject.inProcess = false; // // /** // * Nothing to do // */ // return; // } // // /** // * Check if we have another animation in process // */ // if (mesh.animationObject.inProcess && mesh.animationObject.blocking) { // // console.log('another animation is already in process'); // // // setTargetAngle(value); // // // R3.Utils.PushUnique(mesh.animationObject.storedValues, value); // // // // mesh.animationObject.callbacks.push( // // function(__value) { // // return function(){ // // mesh.quaternion.angle = __value; // // } // // }(value) // // ); // // /** // * Respond that our angle is actually our target angle (it will be that soon) // */ // return; // } // // /** // * We indicate that we now have an animation in process // * @type {boolean} // */ // mesh.animationObject.inProcess = true; // // /** // * Ok - all good - lets start the animation // */ // if (mesh.animationObject.intermediateAngle > value) { // /** // * We will rotate towards by decrementing // */ // mesh.animationObject.angleIncrement = false; // } else { // /** // * We will rotate towards by incrementing // */ // mesh.animationObject.angleIncrement = true; // } // // /** // * We say what our target angle is - when we reach our target angle, we want // * to stop our animation // */ // mesh.animationObject.targetAngle = value; // // /** // * Now we subscribe to 'before render' events, and slowly increment the value // * @type {{fn, remove}} // */ // mesh.animationObject.subscription = R3.Event.Subscribe( // R3.Event.BEFORE_RENDER, // function(data) { // // var increment = Math.abs(animation.rotationSpeed); // // if (!mesh.animationObject.angleIncrement) { // increment *= -1; // } // // animateRotation(data.delta * increment); // } // ); // } // }; // // R3.System.Animation.prototype.getQuaternionAxisX = function(mesh, animation) { // return function() { // return this.latest[mesh.id].quaternion.axis.x; // }.bind(this); // }; // // R3.System.Animation.prototype.setQuaternionAxisX = function(mesh, animation) { // return function(value) { // this.latest[mesh.id].quaternion.axis.x = value; // }.bind(this); // }; // // R3.System.Animation.prototype.getQuaternionAxisY = function(mesh, animation) { // return function() { // return this.latest[mesh.id].quaternion.axis.y; // }.bind(this); // }; // // R3.System.Animation.prototype.setQuaternionAxisY = function(mesh, animation) { // return function(value) { // this.latest[mesh.id].quaternion.axis.y = value; // }.bind(this); // }; // // R3.System.Animation.prototype.getQuaternionAxisZ = function(mesh, animation) { // return function() { // return this.latest[mesh.id].quaternion.axis.z; // }.bind(this); // }; // // R3.System.Animation.prototype.setQuaternionAxisZ = function(mesh, animation) { // return function(value) { // this.latest[mesh.id].quaternion.axis.z = value; // }.bind(this); // }; // // R3.System.Animation.prototype.getSubProperty = function(mesh, axis, property, subProperty) { // return function() { // return this.latest[mesh.id][property][subProperty][axis]; // }.bind(this); // }; // R3.System.Animation.prototype.setSubProperty = function(mesh, animation, axis, property, subProperty) { // return function(value) { // // var from = Number(this.latest[mesh.id][property][subProperty][axis]); // // this.latest[mesh.id][property][subProperty][axis] = value; // // if (property === 'position') { // /** // * Look for other position animations // * TODO:check when not super exausted // */ // // var positionAnimationObject = this.animations[mesh.id].reduce( // // function(result, animationObject) { // // // // if (animationObject.type === 'position') { // // result = animationObject; // // } // // // // return result; // // }, // // null // // ); // // /** // * We found another position animation - just update the 'to' property // */ // // if (positionAnimationObject) { // // positionAnimationObject.to = value; // // return; // // } // } // // this.animations[mesh.id].push( // { // type : property, // axis : axis, // from : from, // to : value, // animation : animation, // mesh : mesh // } // ); // // }.bind(this) // }; // R3.System.Animation.prototype.getProperty = function(mesh, axis, property) { // return function() { // return this.latest[mesh.id][property][axis]; // }.bind(this); // }; // // R3.System.Animation.prototype.setProperty = function(mesh, animation, axis, property) { // return function(value) { // // var from = Number(this.latest[mesh.id][property][axis]); // // this.latest[mesh.id][property][axis] = value; // // if (property === 'position') { // /** // * Look for other position animations // * TODO:check when not super exausted // */ // // var positionAnimationObject = this.animations[mesh.id].reduce( // // function(result, animationObject) { // // // // if (animationObject.type === 'position') { // // result = animationObject; // // } // // // // return result; // // }, // // null // // ); // // /** // * We found another position animation - just update the 'to' property // */ // // if (positionAnimationObject) { // // positionAnimationObject.to = value; // // return; // // } // } // // this.animations[mesh.id].push( // { // type : property, // axis : axis, // from : from, // to : value, // animation : animation, // mesh : mesh // } // ); // // }.bind(this) // };