diff --git a/support/client/lib/vwf.js b/support/client/lib/vwf.js
index 36e3e758a..f6b369ee0 100644
--- a/support/client/lib/vwf.js
+++ b/support/client/lib/vwf.js
@@ -194,18 +194,6 @@
this.moniker_ = undefined;
- /// Nodes that are receiving ticks.
- ///
- /// @name module:vwf.tickable
- ///
- /// @private
-
- this.tickable = {
- // models: [],
- // views: [],
- nodeIDs: [],
- };
-
// == Private variables ====================================================================
/// @name module:vwf.private
@@ -405,6 +393,7 @@
{ library: "vwf/view/cesium", active: false },
{ library: "vwf/view/kineticjs", active: false },
{ library: "vwf/view/mil-sym", active: false },
+ { library: "vwf/view/jiglib", active: false },
{ library: "vwf/view/audio", active: false },
{ library: "vwf/kernel/utility", active: true },
{ library: "vwf/utility", active: true },
@@ -461,6 +450,7 @@
{ library: "vwf/view/kineticjs", active: false },
{ library: "vwf/view/mil-sym", active: false },
{ library: "vwf/view/audio", active: false },
+ { library: "vwf/view/jiglib", active: false },
{ library: "vwf/view/webrtc", active: false}
]
};
@@ -948,10 +938,11 @@
fields.origin = "reflector";
- // Update the queue. Messages in the queue are ordered by time, then by order of arrival.
- // Time is only advanced if the message has no action, meaning it is a tick.
+ // Update the queue. Insert the message (unless it is only a time tick), and
+ // advance the queue's record of the current time. Messages in the queue are
+ // ordered by time, then by order of arrival.
- queue.insert( fields, !fields.action ); // may invoke dispatch(), so call last before returning to the host
+ queue.insert( fields, true ); // may invoke dispatch(), so call last before returning to the host
// Each message from the server allows us to move time forward. Parse the
// timestamp from the message and call dispatch() to execute all queued
@@ -1224,34 +1215,20 @@
// Advance time to the message time.
- if ( this.now != fields.time ) {
- this.sequence_ = undefined; // clear after the previous action
- this.client_ = undefined; // clear after the previous action
+ if ( this.now !== fields.time ) {
this.now = fields.time;
this.tock();
}
- // Perform the action.
+ // Set the per-action kernel globals.
- if ( fields.action ) { // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes)
- this.sequence_ = fields.sequence; // note the message's queue sequence number for the duration of the action
- this.client_ = fields.client; // ... and note the originating client
- this.receive( fields.node, fields.action, fields.member, fields.parameters, fields.respond, fields.origin );
- }
- else {
- this.tick();
- }
+ this.sequence_ = fields.sequence; // note the message's queue sequence number for the duration of the action
+ this.client_ = fields.client; // ... and note the originating client
- }
+ // Perform the action.
- // Advance time to the most recent time received from the server. Tick if the time
- // changed.
+ this.receive( fields.node, fields.action, fields.member, fields.parameters, fields.respond, fields.origin );
- if ( queue.ready() && this.now != queue.time ) {
- this.sequence_ = undefined; // clear after the previous action
- this.client_ = undefined; // clear after the previous action
- this.now = queue.time;
- this.tock();
}
};
@@ -1279,24 +1256,12 @@
this.tick = function() {
- // Call ticking() on each model.
-
- this.models.forEach( function( model ) {
- model.ticking && model.ticking( this.now ); // TODO: maintain a list of tickable models and only call those
- }, this );
-
// Call ticked() on each view.
this.views.forEach( function( view ) {
view.ticked && view.ticked( this.now ); // TODO: maintain a list of tickable views and only call those
}, this );
- // Call tick() on each tickable node.
-
- this.tickable.nodeIDs.forEach( function( nodeID ) {
- this.callMethod( nodeID, "tick", [ this.now ] );
- }, this );
-
};
// -- tock ---------------------------------------------------------------------------------
@@ -2708,13 +2673,8 @@ if ( ! childComponent.source ) {
vwf.setProperty( childID, propertyName, deferredInitializations[propertyName] );
} );
- // TODO: Adding the node to the tickable list here if it contains a tick() function in JavaScript at initialization time. Replace with better control of ticks on/off and the interval by the node.
-
- if ( vwf.execute( childID, "Boolean( this.tick )" ) ) {
- vwf.tickable.nodeIDs.push( childID );
- }
-
// Restore kernel reentry.
+
replicating && vwf.models.kernel.enable();
}, function() {
@@ -5400,7 +5360,7 @@ if ( ! childComponent.source ) {
// reinserted.
return object.filter( function( fields ) {
- return ! ( fields.origin === "reflector" && fields.sequence > vwf.sequence_ ) && fields.action; // TODO: fields.action is here to filter out tick messages // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes)
+ return ! ( fields.origin === "reflector" && fields.sequence > vwf.sequence_ );
} ).sort( function( fieldsA, fieldsB ) {
return fieldsA.sequence - fieldsB.sequence;
} );
@@ -5408,8 +5368,8 @@ if ( ! childComponent.source ) {
} else if ( depth == 1 ) {
// Remove the sequence fields since they're just local annotations used to keep
- // messages ordered by insertion order and aren't directly meaniful outside of this
- // client.
+ // messages ordered by insertion order. They aren't directly meaningful outside of
+ // this client.
var filtered = {};
@@ -6832,12 +6792,10 @@ if ( ! childComponent.source ) {
messages.forEach( function( fields ) {
- // if ( fields.action ) { // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes)
-
+ if ( fields.action ) {
fields.sequence = ++this.sequence; // track the insertion order for use as a sort key
this.queue.push( fields );
-
- // }
+ }
if ( chronic ) {
this.time = Math.max( this.time, fields.time ); // save the latest allowed time for suspend/resume
@@ -6868,6 +6826,21 @@ if ( ! childComponent.source ) {
} );
+ // Tick the views on each idle message.
+
+ if ( chronic && ! fields.action ) {
+
+ // Clear the per-action kernel globals. `tick` isn't an action.
+
+ vwf.sequence_ = undefined;
+ vwf.client_ = undefined;
+
+ // Tick the views.
+
+ vwf.tick();
+
+ }
+
// Execute the simulation through the new time.
// To prevent actions from executing out of order, callers should immediately return
diff --git a/support/client/lib/vwf/model/blockly.js b/support/client/lib/vwf/model/blockly.js
index 5bdea9eac..7e1a2026b 100644
--- a/support/client/lib/vwf/model/blockly.js
+++ b/support/client/lib/vwf/model/blockly.js
@@ -23,7 +23,9 @@ define( [ "module", "vwf/model", "vwf/utility",
],
function( module, model, utility, acorn, Blockly ) {
- var self;
+ var modelDriver;
+ var updateTime = -0.05;
+ var startUpdate = false;
return model.load( module, {
@@ -33,13 +35,13 @@ define( [ "module", "vwf/model", "vwf/utility",
initialize: function( options ) {
- self = this;
+ modelDriver = this;
this.arguments = Array.prototype.slice.call( arguments );
- if ( options === undefined ) {
- options = {};
- }
+ this.options = options || {};
+
+ updateTime = this.options.updateTime || -0.05;
this.state = {
"nodes": {},
@@ -138,6 +140,13 @@ define( [ "module", "vwf/model", "vwf/utility",
this.logger.infox( "initializingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
}
+ var appID = this.kernel.application();
+ if ( childID === appID ) {
+ if ( !startUpdate ) {
+ this.kernel.callMethod( appID, "update", [], updateTime );
+ startUpdate = true;
+ }
+ }
},
@@ -308,13 +317,14 @@ define( [ "module", "vwf/model", "vwf/utility",
// -- callingMethod --------------------------------------------------------------------------
callingMethod: function( nodeID, methodName /* [, parameter1, parameter2, ... ] */ ) { // TODO: parameters
+ var appID = this.kernel.application();
var node = this.state.nodes[ nodeID ];
if ( this.debug.methods ) {
this.logger.infox( " M === callingMethod ", nodeID, methodName );
}
- if ( nodeID == this.kernel.application() ) {
+ if ( nodeID == appID ) {
switch ( methodName ) {
@@ -333,6 +343,11 @@ define( [ "module", "vwf/model", "vwf/utility",
}
break;
+ case "update":
+ executeBlocks();
+ this.kernel.callMethod( appID, "update", [], updateTime );
+ break;
+
}
} else if ( node !== undefined ) {
@@ -346,7 +361,7 @@ define( [ "module", "vwf/model", "vwf/utility",
break;
}
}
- },
+ }
// TODO: creatingEvent, deltetingEvent, firingEvent
@@ -357,45 +372,6 @@ define( [ "module", "vwf/model", "vwf/utility",
// return undefined;
//},
- // == ticking =============================================================================
-
- ticking: function( vwfTime ) {
-
- if ( this.state.executingBlocks !== undefined ) {
- var blocklyNode = undefined;
-
- for ( var nodeID in this.state.executingBlocks ) {
-
- blocklyNode = this.state.executingBlocks[ nodeID ];
- var executeNextLine = false;
-
- if ( blocklyNode.interpreter === undefined ||
- blocklyNode.interpreterStatus === "completed" ) {
- blocklyNode.interpreter = createInterpreter( acorn, blocklyNode.code );
- blocklyNode.interpreterStatus = "created";
- blocklyNode.lastLineExeTime = vwfTime;
- executeNextLine = true;
- } else {
- var elaspedTime = vwfTime - blocklyNode.lastLineExeTime;
- if ( elaspedTime >= blocklyNode.timeBetweenLines ) {
- executeNextLine = true;
- blocklyNode.lastLineExeTime = vwfTime;
- }
- }
-
- if ( executeNextLine ) {
-
- self.state.executionHalted = false;
-
- nextStep( blocklyNode );
-
- this.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] );
- }
- }
- }
-
- }
-
} );
function getPrototypes( extendsID ) {
@@ -404,14 +380,14 @@ define( [ "module", "vwf/model", "vwf/utility",
while ( id !== undefined ) {
prototypes.push( id );
- id = self.kernel.prototype( id );
+ id = modelDriver.kernel.prototype( id );
}
return prototypes;
}
function isBlockly3Node( nodeID ) {
- return self.kernel.test( nodeID,
+ return modelDriver.kernel.test( nodeID,
"self::element(*,'http://vwf.example.com/blockly/controller.vwf')",
nodeID );
}
@@ -426,6 +402,43 @@ define( [ "module", "vwf/model", "vwf/utility",
return found;
}
+ function executeBlocks() {
+
+ if ( modelDriver.state.executingBlocks !== undefined ) {
+ var blocklyNode = undefined;
+
+ for ( var nodeID in modelDriver.state.executingBlocks ) {
+
+ blocklyNode = modelDriver.state.executingBlocks[ nodeID ];
+ var executeNextLine = false;
+
+ if ( blocklyNode.interpreter === undefined ||
+ blocklyNode.interpreterStatus === "completed" ) {
+ blocklyNode.interpreter = createInterpreter( acorn, blocklyNode.code );
+ blocklyNode.interpreterStatus = "created";
+ blocklyNode.lastLineExeTime = vwfTime;
+ executeNextLine = true;
+ } else {
+ var elaspedTime = vwfTime - blocklyNode.lastLineExeTime;
+ if ( elaspedTime >= blocklyNode.timeBetweenLines ) {
+ executeNextLine = true;
+ blocklyNode.lastLineExeTime = vwfTime;
+ }
+ }
+
+ if ( executeNextLine ) {
+
+ modelDriver.state.executionHalted = false;
+
+ nextStep( blocklyNode );
+
+ modelDriver.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] );
+ }
+ }
+ }
+
+ }
+
function getJavaScript( node ) {
var xml = Blockly.Xml.workspaceToDom( Blockly.getMainWorkspace() );
@@ -459,10 +472,10 @@ define( [ "module", "vwf/model", "vwf/utility",
if ( node.interpreter !== undefined ) {
var stepType = node.interpreter.step();
- while ( stepType && !self.state.executionHalted ) {
+ while ( stepType && !modelDriver.state.executionHalted ) {
if ( stepType === "stepProgram" ) {
if ( node.interpreterStatus === "created" ) {
- self.kernel.fireEvent( node.ID, "blocklyStarted", [ true ] );
+ modelDriver.kernel.fireEvent( node.ID, "blocklyStarted", [ true ] );
node.interpreterStatus = "started";
}
}
@@ -470,8 +483,8 @@ define( [ "module", "vwf/model", "vwf/utility",
}
if ( stepType === false ) {
if ( node.interpreterStatus === "started" ) {
- self.kernel.setProperty( node.ID, "blockly_executing", false );
- self.kernel.fireEvent( node.ID, "blocklyStopped", [ true ] );
+ modelDriver.kernel.setProperty( node.ID, "blockly_executing", false );
+ modelDriver.kernel.fireEvent( node.ID, "blocklyStopped", [ true ] );
node.interpreterStatus = "completed";
}
}
@@ -495,7 +508,7 @@ define( [ "module", "vwf/model", "vwf/utility",
for ( var j = 0; j < arguments.length; j++) {
parms.push( arguments[ j ].toString() );
}
- self.state.executionHalted = true;
+ modelDriver.state.executionHalted = true;
return interpreter.createPrimitive( nativeFunc.apply( vwf, parms ) );
};
} )( vwf[ vwfKernelFunctions[ i ] ] );
@@ -516,7 +529,7 @@ define( [ "module", "vwf/model", "vwf/utility",
parms.push( arguments[ j ].toString() );
}
}
- self.state.executionHalted = true;
+ modelDriver.state.executionHalted = true;
return interpreter.createPrimitive( nativeFunc.apply( vwf, parms ) );
};
} )( vwf[ vwfKernelFunctions[ i ] ] );
diff --git a/support/client/lib/vwf/model/buzz.js b/support/client/lib/vwf/model/buzz.js
index c0c010feb..ae175b85b 100644
--- a/support/client/lib/vwf/model/buzz.js
+++ b/support/client/lib/vwf/model/buzz.js
@@ -394,7 +394,7 @@ define( [
}
- },
+ }
// TODO: creatingEvent, deltetingEvent, firingEvent
@@ -405,13 +405,6 @@ define( [
// return undefined;
// },
- // == ticking =============================================================================
-
- // ticking: function( vwfTime ) {
-
- // }
-
-
} );
diff --git a/support/client/lib/vwf/model/cesium.js b/support/client/lib/vwf/model/cesium.js
index d47a142dd..7b912cd53 100644
--- a/support/client/lib/vwf/model/cesium.js
+++ b/support/client/lib/vwf/model/cesium.js
@@ -1966,7 +1966,7 @@ define( [ "module",
}
return value;
- },
+ }
// TODO: deletingMethod
@@ -1986,8 +1986,6 @@ define( [ "module",
// return undefined;
//},
- // == ticking =============================================================================
-
} );
// == PRIVATE ========================================================================================
diff --git a/support/client/lib/vwf/model/glge.js b/support/client/lib/vwf/model/glge.js
index 137175fa0..d6c1550d6 100644
--- a/support/client/lib/vwf/model/glge.js
+++ b/support/client/lib/vwf/model/glge.js
@@ -802,7 +802,7 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili
return value;
- },
+ }
// TODO: deletingMethod
@@ -822,10 +822,6 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili
// return undefined;
// },
- // == ticking =============================================================================
-
-// ticking: function( vwfTime ) {
-// },
} );
diff --git a/support/client/lib/vwf/model/jiglib.js b/support/client/lib/vwf/model/jiglib.js
index d6c85dedf..b8290642c 100644
--- a/support/client/lib/vwf/model/jiglib.js
+++ b/support/client/lib/vwf/model/jiglib.js
@@ -16,7 +16,9 @@
/// @module vwf/model/jiglib
/// @requires vwf/model
-define( [ "module", "vwf/model" ], function( module, model ) {
+define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utility ) {
+
+ var modelDriver;
return model.load( module, {
@@ -26,13 +28,29 @@ define( [ "module", "vwf/model" ], function( module, model ) {
initialize: function() {
- this.nodes = {}; // maps id => { property: value, ... }
- this.scenes = {};
- this.active = {};
- this.enabled = false;
- this.lastTime = 0;
- this.delayedProperties = {};
- this.updating = false;
+ modelDriver = this;
+
+ this.state = {
+ "nodes": {},
+ "scenes": {},
+ "active": {},
+ "enabled": false,
+ "delayedProperties": {},
+ "updating": false
+ }
+
+ // turns on logger debugger console messages
+ this.debug = {
+ "creation": false,
+ "initializing": false,
+ "parenting": false,
+ "deleting": false,
+ "properties": false,
+ "setting": false,
+ "getting": false,
+ "prototypes": false,
+ "loading": false
+ };
},
@@ -44,40 +62,41 @@ define( [ "module", "vwf/model" ], function( module, model ) {
childSource, childType, childIndex, childName, callback /* ( ready ) */) {
var kernel = this.kernel;
- //this.logger.enable = true;
- //this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs,
- // childSource, childType, childIndex, childName );
- //this.logger.enabled = false;
+
+ if ( this.debug.creation ) {
+ this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
+ }
if ( childExtendsID && this.kernel.test( childExtendsID,
"self::element(*,'http://vwf.example.com/scene.vwf')", childExtendsID ) ) {
- this.scenes[ childID ] = {};
- this.scenes[ childID ].ID = childID;
- this.scenes[ childID ].extendsID = childExtendsID;
- this.scenes[ childID ].implementsIDs = childImplementsIDs;
- this.scenes[ childID ].source = childSource;
- this.scenes[ childID ].type = childType;
- this.scenes[ childID ].system = jigLib.PhysicsSystem.getInstance();
- this.scenes[ childID ].initialized = false;
- this.scenes[ childID ].propertyMap = {};
-
+ this.state.scenes[ childID ] = {
+ "ID": childID,
+ "extendsID": childExtendsID,
+ "implementsIDs": childImplementsIDs,
+ "source": childSource,
+ "type": childType,
+ "system": jigLib.PhysicsSystem.getInstance(),
+ "initialized": false,
+ "propertyMap": {}
+ };
} else {
- switch ( childExtendsID && this.kernel.uri( childExtendsID ) ) {
+ switch ( childExtendsID && this.kernel.uri( childExtendsID ) ) {
case "http://vwf.example.com/physics3.vwf":
case "http://vwf.example.com/node3.vwf":
case "http://vwf.example.com/mesh.vwf":
- this.nodes[ childID ] = {};
- this.nodes[ childID ].sceneID = this.kernel.application();
- this.nodes[ childID ].name = childName;
- this.nodes[ childID ].ID = childID;
- this.nodes[ childID ].parentID = nodeID;
- this.nodes[ childID ].extendsID = childExtendsID;
- this.nodes[ childID ].implementsIDs = childImplementsIDs;
- this.nodes[ childID ].source = childSource;
- this.nodes[ childID ].type = childType;
-
+ this.state.nodes[ childID ] = {
+ "sceneID": this.kernel.application(),
+ "name": childName,
+ "ID": childID,
+ "parentID": nodeID,
+ "extendsID": childExtendsID,
+ "implementsIDs": childImplementsIDs,
+ "source": childSource,
+ "type": childType
+ };
+
break;
}
}
@@ -90,14 +109,18 @@ define( [ "module", "vwf/model" ], function( module, model ) {
initializingNode: function( nodeID, childID ) {
- var scene = this.scenes[ childID ];
- var node = this.nodes[ childID ];
+ var scene = this.state.scenes[ childID ];
+ var node = this.state.nodes[ childID ];
+
+ if ( this.debug.initializing ) {
+ this.logger.infox( "initializingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
+ }
if ( scene && scene.system ) {
if ( !scene.initialized ) {
initializeScene.call( this, scene );
}
- this.enabled = true;
+ this.state.enabled = true;
} else if ( node ) {
if ( node.jigLibObj && node.jigLibInternals ) {
@@ -129,13 +152,17 @@ define( [ "module", "vwf/model" ], function( module, model ) {
deletingNode: function( nodeID ) {
- if ( this.active[ nodeID ] ) {
- delete this.active[ nodeID ];
+ if ( this.debug.deleting ) {
+ this.logger.infox( "deletingNode", nodeID );
+ }
+
+ if ( this.state.active[ nodeID ] ) {
+ delete this.state.active[ nodeID ];
}
- if ( this.nodes[ nodeID ] ) {
- var node = this.nodes[ nodeID ];
- var scene = this.scenes[ node.sceneID ];
+ if ( this.state.nodes[ nodeID ] ) {
+ var node = this.state.nodes[ nodeID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( node.jigLibObj ) {
if ( node.jigLibObj ) {
if ( scene ) scene.system.removeBody( node.jigLibObj );
@@ -148,7 +175,7 @@ define( [ "module", "vwf/model" ], function( module, model ) {
}
node.jigLibMeshes = undefined;
}
- delete this.nodes[ nodeID ];
+ delete this.state.nodes[ nodeID ];
}
},
@@ -171,6 +198,9 @@ define( [ "module", "vwf/model" ], function( module, model ) {
// -- creatingProperty ---------------------------------------------------------------------
creatingProperty: function( nodeID, propertyName, propertyValue ) {
+ if ( this.debug.properties ) {
+ this.logger.infox( "C === creatingProperty ", nodeID, propertyName, propertyValue );
+ }
return this.initializingProperty( nodeID, propertyName, propertyValue );
},
@@ -179,14 +209,15 @@ define( [ "module", "vwf/model" ], function( module, model ) {
initializingProperty: function( nodeID, propertyName, propertyValue ) {
var value = undefined;
- //this.logger.enabled = true;
- //this.logger.infox( "creatingProperty", nodeID, propertyName, propertyValue );
- //this.logger.enabled = false;
+
+ if ( this.debug.properties ) {
+ this.logger.infox( " I === initializingProperty ", nodeID, propertyName, propertyValue );
+ }
if ( !( propertyValue === undefined ) ) {
- var node = this.nodes[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
if ( node ) {
- var scene = this.scenes[ node.sceneID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( scene && !scene.initialized ) {
var pm;
if ( !scene.propertyMap[ nodeID ] ) {
@@ -204,25 +235,25 @@ define( [ "module", "vwf/model" ], function( module, model ) {
} else {
if ( propertyName == "physics" ) {
this.settingProperty( nodeID, propertyName, propertyValue );
- if ( this.delayedProperties[ nodeID ] ) {
+ if ( this.state.delayedProperties[ nodeID ] ) {
var propValue;
- for ( propName in this.delayedProperties[ nodeID ] ) {
- propValue = this.delayedProperties[ nodeID ][ propName ];
+ for ( propName in this.state.delayedProperties[ nodeID ] ) {
+ propValue = this.state.delayedProperties[ nodeID ][ propName ];
this.settingProperty( nodeID, propName, propValue );
}
- delete this.delayedProperties[ nodeID ];
+ delete this.state.delayedProperties[ nodeID ];
}
} else {
- if ( !this.delayedProperties[ nodeID ] ) {
- this.delayedProperties[ nodeID ] = {};
+ if ( !this.state.delayedProperties[ nodeID ] ) {
+ this.state.delayedProperties[ nodeID ] = {};
}
- this.delayedProperties[ nodeID ][ propertyName ] = propertyValue;
+ this.state.delayedProperties[ nodeID ][ propertyName ] = propertyValue;
}
}
}
} else {
- var scene = this.scenes[ nodeID ];
+ var scene = this.state.scenes[ nodeID ];
if ( scene ) {
this.settingProperty( nodeID, propertyName, propertyValue );
}
@@ -240,10 +271,14 @@ define( [ "module", "vwf/model" ], function( module, model ) {
var value = undefined;
- if ( propertyValue === undefined )
+ if ( ( this.debug.properties || this.debug.setting ) && ( propertyName !== "transform" ) ) {
+ this.logger.infox( " S === settingProperty ", nodeID, propertyName, propertyValue );
+ }
+
+ if ( !utility.validObject( propertyValue ) )
return value;
- if ( this.updating ) {
+ if ( this.state.updating ) {
switch ( propertyName ) {
case "transform":
return;
@@ -251,13 +286,13 @@ define( [ "module", "vwf/model" ], function( module, model ) {
}
}
- var activeNode = this.active[ nodeID ];
- var node = this.nodes[ nodeID ];
- var scene = this.scenes[ nodeID ];
+ var activeNode = this.state.active[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
+ var scene = this.state.scenes[ nodeID ];
if ( node && node.jigLibObj ) {
- scene = this.scenes[ node.sceneID ];
+ scene = this.state.scenes[ node.sceneID ];
switch ( propertyName ) {
case "transform":
if ( activeNode && activeNode.jlObj ) {
@@ -308,7 +343,7 @@ define( [ "module", "vwf/model" ], function( module, model ) {
break;
}
} else if ( node && !scene ) {
- scene = this.scenes[ node.sceneID ];
+ scene = this.state.scenes[ node.sceneID ];
if ( propertyName == "physics" ) {
if ( scene && scene.system && propertyValue ) {
var type = ( propertyValue.constructor == Array ) ? propertyValue[0] : propertyValue;
@@ -331,21 +366,21 @@ define( [ "module", "vwf/model" ], function( module, model ) {
}
}
- if ( this.delayedProperties[nodeID] ) {
- var props = this.delayedProperties[nodeID];
+ if ( this.state.delayedProperties[nodeID] ) {
+ var props = this.state.delayedProperties[nodeID];
for ( var propName in props ) {
this.settingProperty( nodeID, propName, props[propName] );
}
- delete this.delayedProperties[nodeID];
+ delete this.state.delayedProperties[nodeID];
}
} else {
if ( node ) {
var propArray;
- if ( !this.delayedProperties[nodeID] ) {
- this.delayedProperties[nodeID] = {};
+ if ( !this.state.delayedProperties[nodeID] ) {
+ this.state.delayedProperties[nodeID] = {};
}
- propArray = this.delayedProperties[nodeID];
+ propArray = this.state.delayedProperties[nodeID];
propArray[ propertyName ] = propertyValue;
}
@@ -383,8 +418,12 @@ define( [ "module", "vwf/model" ], function( module, model ) {
propertyValue = undefined;
- if ( this.nodes[ nodeID ] ) {
- var node = this.nodes[ nodeID ];
+ if ( this.debug.properties || this.debug.getting ) {
+ this.logger.infox( " G === gettingProperty ", nodeID, propertyName );
+ }
+
+ if ( this.state.nodes[ nodeID ] ) {
+ var node = this.state.nodes[ nodeID ];
if ( node && node.jigLibObj ) {
switch ( propertyName ) {
case "physics":
@@ -436,8 +475,8 @@ define( [ "module", "vwf/model" ], function( module, model ) {
break;
}
}
- } else if ( this.scenes[ nodeID ] ) {
- var sceneNode = this.scenes[ nodeID ];
+ } else if ( this.state.scenes[ nodeID ] ) {
+ var sceneNode = this.state.scenes[ nodeID ];
if ( sceneNode && sceneNode.system ) {
switch ( propertyName ) {
case "gravity":
@@ -462,8 +501,20 @@ define( [ "module", "vwf/model" ], function( module, model ) {
// -- callingMethod ------------------------------------------------------------------------
- //callingMethod: function( nodeID, methodName, methodParameters ) {
- //},
+ callingMethod: function( nodeID, methodName, methodParameters ) {
+
+ var sceneID = this.kernel.application();
+ if ( nodeID === sceneID ) {
+ switch ( methodName ) {
+
+ case "update":
+ updateScene( 0.05 );
+ this.kernel.callMethod( sceneID, "update", [], -0.05 );
+ break;
+
+ }
+ }
+ }
// -- creatingEvent ------------------------------------------------------------------------
@@ -482,35 +533,6 @@ define( [ "module", "vwf/model" ], function( module, model ) {
// return undefined;
//},
- // == ticking =============================================================================
-
- ticking: function( vwfTime ) {
-
- var elaspedTime = vwfTime - this.lastTime;
- this.lastTime = vwfTime;
-
- if ( this.enabled ) {
- if ( elaspedTime > 0 ) {
- if (elaspedTime > 0.05) elaspedTime = 0.05;
- var activeObj, posRotProp, pos, rot, posRot;
- var sceneNode = this.scenes[this.kernel.application()];
-
- if ( sceneNode && sceneNode.system ) {
- sceneNode.system.integrate( elaspedTime );
- this.updating = true;
- for ( var nodeID in this.active ) {
- activeObj = this.active[nodeID];
- if ( activeObj && activeObj.jlObj ) {
- var trans = activeObj.jlObj.get_Transform();
- this.kernel.setProperty( nodeID, "transform", trans );
- }
- }
- this.updating = false;
- }
- }
- }
- },
-
} );
// == Private functions ==================================================================
@@ -537,9 +559,9 @@ define( [ "module", "vwf/model" ], function( module, model ) {
function createJBox( nodeID, scale, def ) {
- var node = this.nodes[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
if ( node ) {
- var scene = this.scenes[ node.sceneID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( scene ) {
var v1, v2;
var width = 1;
@@ -569,9 +591,9 @@ define( [ "module", "vwf/model" ], function( module, model ) {
if ( node.jigLibObj ) {
scene.system.addBody( node.jigLibObj );
if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] );
- this.active[ nodeID ] = {};
- this.active[ nodeID ].jlObj = node.jigLibObj;
- this.active[ nodeID ].offset = offset;
+ this.state.active[ nodeID ] = {};
+ this.state.active[ nodeID ].jlObj = node.jigLibObj;
+ this.state.active[ nodeID ].offset = offset;
}
}
}
@@ -582,9 +604,9 @@ define( [ "module", "vwf/model" ], function( module, model ) {
function createJSphere( nodeID, scale, def ) {
- var node = this.nodes[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
if ( node ) {
- var scene = this.scenes[ node.sceneID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( scene ) {
var v1, v2;
var verts = this.kernel.getProperty( nodeID, "vertices" );
@@ -619,10 +641,10 @@ define( [ "module", "vwf/model" ], function( module, model ) {
node.jigLibObj = new jigLib.JSphere( null, raduis );
if ( node.jigLibObj ) {
scene.system.addBody( node.jigLibObj );
- if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] );
- this.active[ nodeID ] = {};
- this.active[ nodeID ].jlObj = node.jigLibObj;
- this.active[ nodeID ].offset = this.kernel.getProperty( nodeID, "centerOffset" ) || [ 0, 0, 0 ];
+ if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] );
+ this.state.active[ nodeID ] = {};
+ this.state.active[ nodeID ].jlObj = node.jigLibObj;
+ this.state.active[ nodeID ].offset = this.kernel.getProperty( nodeID, "centerOffset" ) || [ 0, 0, 0 ];
}
}
}
@@ -634,9 +656,9 @@ define( [ "module", "vwf/model" ], function( module, model ) {
function createJMesh( nodeID, scale ) {
- var node = this.nodes[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
if ( node ) {
- var scene = this.scenes[ node.sceneID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( scene ) {
if ( node.jigLibMeshes ) {
for ( var j = 0; j < node.jigLibMeshes.length; j++ ) {
@@ -678,13 +700,13 @@ define( [ "module", "vwf/model" ], function( module, model ) {
function createJPlane( nodeID, physicsDef ) {
- var node = this.nodes[ nodeID ];
+ var node = this.state.nodes[ nodeID ];
if ( node ) {
- var scene = this.scenes[ node.sceneID ];
+ var scene = this.state.scenes[ node.sceneID ];
if ( scene ) {
var normal = [0, 0, 1, 0];
-
- var pos = this.kernel.getProperty( nodeID, "translation" )|| [ 0, 0, 0 ];
+
+ var pos = this.kernel.getProperty( nodeID, "translation" )|| [ 0, 0, 0 ];
if ( physicsDef.constructor == Array ) {
switch ( physicsDef.length ) {
case 2:
@@ -709,7 +731,7 @@ define( [ "module", "vwf/model" ], function( module, model ) {
node.jigLibObj = new jigLib.JPlane( null, normal );
scene.system.addBody( node.jigLibObj );
- if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] );
+ if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] );
}
}
}
@@ -747,6 +769,7 @@ define( [ "module", "vwf/model" ], function( module, model ) {
}
scene.propertyMap = {};
scene.initialized = true;
+ this.kernel.callMethod( this.kernel.application(), "update", [], -0.05 )
}
// == initializeObject ===================================================================
@@ -812,4 +835,35 @@ define( [ "module", "vwf/model" ], function( module, model ) {
}
}
+ // == updateScene ===================================================================
+
+ function updateScene( elaspedTime ) {
+
+ if ( modelDriver.state.enabled ) {
+
+ var activeObj, trans;
+ var sceneNode = modelDriver.state.scenes[ modelDriver.kernel.application() ];
+
+ if ( sceneNode && sceneNode.system ) {
+ sceneNode.system.integrate( elaspedTime );
+
+ var activeKeys = Object.keys( modelDriver.state.active );
+ if ( activeKeys !== undefined ) {
+ modelDriver.state.updating = true;
+ for ( var i = 0; i < activeKeys.length; i++ ) {
+ activeObj = modelDriver.state.active[ activeKeys[ i ] ];
+ if ( activeObj && activeObj.jlObj ) {
+ trans = activeObj.jlObj.get_Transform();
+ modelDriver.kernel.setProperty( activeKeys[ i ], "transform", trans );
+ }
+ }
+ modelDriver.state.updating = false;
+ }
+
+ }
+
+ }
+ }
+
+
} );
diff --git a/support/client/lib/vwf/model/kineticjs.js b/support/client/lib/vwf/model/kineticjs.js
index dd7f3bdaf..d08eedaad 100644
--- a/support/client/lib/vwf/model/kineticjs.js
+++ b/support/client/lib/vwf/model/kineticjs.js
@@ -2062,18 +2062,18 @@ define( [ "module",
}
return value;
- },
+ }
// TODO: deletingMethod
// -- callingMethod --------------------------------------------------------------------------
- callingMethod: function( nodeID, methodName, methodParameters, methodValue ) {
- if ( this.debug.methods ) {
- this.logger.infox( " M === callingMethod ", nodeID, methodName );
- }
- },
+ // callingMethod: function( nodeID, methodName, methodParameters, methodValue ) {
+ // if ( this.debug.methods ) {
+ // this.logger.infox( " M === callingMethod ", nodeID, methodName );
+ // }
+ // },
// -- executing ------------------------------------------------------------------------------
@@ -2081,9 +2081,6 @@ define( [ "module",
// return undefined;
// },
- // ticking: function( vwfTime ) {
- // }
-
} );
// == PRIVATE ========================================================================================
diff --git a/support/client/lib/vwf/model/mil-sym.js b/support/client/lib/vwf/model/mil-sym.js
index f30941d0e..4566ea477 100644
--- a/support/client/lib/vwf/model/mil-sym.js
+++ b/support/client/lib/vwf/model/mil-sym.js
@@ -403,7 +403,7 @@ define( [ "module",
}
return value;
- },
+ }
// TODO: creatingEvent, deltetingEvent, firingEvent
@@ -414,14 +414,6 @@ define( [ "module",
// return undefined;
// },
- // == ticking =============================================================================
-
- // ticking: function( vwfTime ) {
-
- // }
-
-
-
} );
function getPrototypes( extendsID ) {
diff --git a/support/client/lib/vwf/model/threejs.js b/support/client/lib/vwf/model/threejs.js
index 2c16019b8..d50b5fc4b 100644
--- a/support/client/lib/vwf/model/threejs.js
+++ b/support/client/lib/vwf/model/threejs.js
@@ -59,7 +59,6 @@ define( [ "module",
var self;
var checkLights = true;
- var sceneCreated = false;
return model.load( module, {
@@ -73,8 +72,9 @@ define( [ "module",
checkCompatibility.call(this);
- this.state.scenes = {}; // id => { glgeDocument: new GLGE.Document(), glgeRenderer: new GLGE.Renderer(), glgeScene: new GLGE.Scene() }
- this.state.nodes = {}; // id => { name: string, glgeObject: GLGE.Object, GLGE.Collada, GLGE.Light, or other...? }
+ this.state.scenes = {};
+ this.state.nodes = {};
+ this.state.animatedNodes = {};
this.state.prototypes = {};
this.state.kernel = this.kernel.kernel.kernel;
this.state.lights = {};
@@ -110,7 +110,8 @@ define( [ "module",
"properties": false,
"setting": false,
"getting": false,
- "prototypes": false
+ "prototypes": false,
+ "loading": false
};
},
@@ -180,13 +181,13 @@ define( [ "module",
var kernel = this.kernel.kernel.kernel;
var protos = getPrototypes.call( this, kernel, childExtendsID );
- if ( isSceneDefinition.call(this, protos) && childID == this.kernel.application() )
+ if ( isSceneDefinition.call(this, protos) && childID == appID )
{
var sceneNode = CreateThreeJSSceneNode( nodeID, childID, childExtendsID );
this.state.scenes[ childID ] = sceneNode;
this.state.cameraInUse = sceneNode.camera.defaultCamera;
- sceneCreated = true;
+ createDefaultLighting.call( this, sceneLights.call( this ) );
if ( childImplementsIDs && childImplementsIDs.length > 0 ) {
for ( var i = 0; i < childImplementsIDs.length; i++ ) {
@@ -2704,29 +2705,16 @@ define( [ "module",
}
return undefined;
- },
+ }
// TODO: creatingEvent, deltetingEvent, firingEvent
// -- executing ------------------------------------------------------------------------------
- executing: function( nodeID, scriptText, scriptType ) {
- return undefined;
- },
-
- // == ticking =============================================================================
-
- ticking: function( vwfTime ) {
-
- if ( checkLights && this.state.appInitialized && sceneCreated ) {
-
- var lightsInScene = sceneLights.call( this );
-
- createDefaultLighting.call( this, lightsInScene );
- checkLights = false;
- }
- }
+ // executing: function( nodeID, scriptText, scriptType ) {
+ // return undefined;
+ // }
} );
@@ -2735,7 +2723,7 @@ define( [ "module",
function checkCompatibility() {
this.compatibilityStatus = { compatible:true, errors:{} }
var contextNames = ["webgl","experimental-webgl","moz-webgl","webkit-3d"];
- for(var i = 0; i < contextNames.length; i++){
+ for( var i = 0; i < contextNames.length; i++){
try{
var canvas = document.createElement('canvas');
var gl = canvas.getContext(contextNames[i]);
@@ -3547,7 +3535,10 @@ define( [ "module",
var threeModel = this;
var sceneNode = this.state.scenes[ this.kernel.application() ];
var parentObject3 = parentNode.threeObject ? parentNode.threeObject : parentNode.threeScene;
- //console.info( "---- loadAsset( "+parentNode.name+", "+node.name+", "+childType+" )" );
+
+ if ( this.debug.loading ) {
+ this.logger.infox( "loadAsset", parentNode.ID, node.ID, childType );
+ }
node.assetLoaded = function( geometry , materials) {
//console.info( "++++ assetLoaded( "+parentNode.name+", "+node.name+", "+childType+" )" );
diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js
index ff60f2c51..bf6ce1867 100644
--- a/support/client/lib/vwf/view/threejs.js
+++ b/support/client/lib/vwf/view/threejs.js
@@ -146,7 +146,7 @@ define( [ "module",
raycaster = new THREE.Raycaster();
window._dView = this;
- this.nodes = {};
+
this.interpolateTransforms = true;
this.tickTime = 0;
this.realTickDif = 50;
@@ -163,8 +163,8 @@ define( [ "module",
//how/when does the model set the state object?
if ( this.state.scenes[ childID ] )
{
- this.canvasQuery = $(this.rootSelector).append(""
- ).children(":last");
+ var canvasDef = ""
+ this.canvasQuery = $(this.rootSelector).append( canvasDef ).children(":last");
initScene.call(this,this.state.scenes[childID]);
}
@@ -175,9 +175,6 @@ define( [ "module",
}
}
- if(this.state.nodes[childID] && this.state.nodes[childID].threeObject instanceof THREE.Object3D) {
- this.nodes[childID] = {id:childID,extends:childExtendsID};
- }
},
initializedNode: function( nodeID, childID ) {
@@ -240,7 +237,9 @@ define( [ "module",
deletedNode: function(childID)
{
- delete this.nodes[childID];
+ if ( this.state.animatedNodes[ childID ] !== undefined ) {
+ delete this.state.animatedNodes[ childID ];
+ }
},
// -- addedChild -------------------------------------------------------------------------------
@@ -251,16 +250,18 @@ define( [ "module",
//removedChild: function( nodeID, childID ) { },
- // -- createdProperty --------------------------------------------------------------------------
-
- //createdProperty: function (nodeID, propertyName, propertyValue) { },
-
// -- initializedProperty ----------------------------------------------------------------------
initializedProperty: function ( nodeID, propertyName, propertyValue ) {
this.satProperty(nodeID, propertyName, propertyValue);
},
+ // -- createdProperty --------------------------------------------------------------------------
+
+ createdProperty: function (nodeID, propertyName, propertyValue) {
+ this.satProperty(nodeID, propertyName, propertyValue);
+ },
+
// TODO: deletedProperty
// -- satProperty ------------------------------------------------------------------------------
@@ -307,7 +308,8 @@ define( [ "module",
if ( node ) {
nodeLookAt( node );
}
- }
+
+ }
},
// -- gotProperty ------------------------------------------------------------------------------
@@ -422,7 +424,23 @@ define( [ "module",
// -- calledMethod -----------------------------------------------------------------------------
calledMethod: function( nodeID, methodName, methodParameters, methodValue ) {
- switch(methodName) {
+
+ switch( methodName ) {
+
+ case "animationPlay":
+ if ( navObject === undefined || navObject.ID !== nodeID ) {
+ if ( this.state.animatedNodes[ nodeID ] === undefined ) {
+ this.state.animatedNodes[ nodeID ] = {
+ "id": nodeID,
+ "lastAnimationFrame": getAnimationFrame( nodeID ),
+ "thisAnimationFrame": getAnimationFrame( nodeID ),
+ "thisTickTransform": getTransform( nodeID ),
+ "lastTickTransform": getTransform( nodeID )
+ }
+ }
+ }
+ break;
+
case "translateBy":
case "translateTo":
// No need for rotateBy or rotateTo because they call the quaternion methods
@@ -434,9 +452,16 @@ define( [ "module",
case "transformTo":
case "worldTransformTo":
// If the duration of the transform is 0, set the transforms to their final value so it doesn't interpolate
- if(methodParameters.length < 2 || methodParameters[1] == 0) {
- this.nodes[nodeID].lastTickTransform = getTransform(nodeID);
- this.nodes[nodeID].selfTickTransform = goog.vec.Mat4.clone(this.nodes[nodeID].lastTickTransform);
+ if ( ( methodParameters.length >= 2 ) && ( methodParameters[ 1 ] !== 0 && methodParameters[ 1 ] !== undefined ) ) {
+ if ( navObject === undefined || navObject.ID !== nodeID ) {
+ this.state.animatedNodes[ nodeID ] = {
+ "id": nodeID,
+ "thisTickTransform": getTransform( nodeID ),
+ "lastTickTransform": getTransform( nodeID )
+ }
+ }
+ } else if ( this.state.animatedNodes[ nodeID ] !== undefined ) {
+ delete this.state.animatedNodes[ nodeID ];
}
break;
}
@@ -489,7 +514,7 @@ define( [ "module",
// -- firedEvent -----------------------------------------------------------------------------
- firedEvent: function( nodeID, eventName ) {
+ firedEvent: function( nodeID, eventName, eventParameters ) {
if ( eventName == "changingTransformFromView" ) {
var clientThatSatProperty = self.kernel.client();
var me = self.kernel.moniker();
@@ -504,7 +529,11 @@ define( [ "module",
if(this.state.scenes[nodeID]) {
this.state.scenes[nodeID].renderer.setViewport(0,0,window.innerWidth,window.innerHeight);
}
- }
+ } else if ( eventName === "animationStopped" ) {
+ if ( this.state.animatedNodes[ nodeID ] !== undefined ) {
+ delete this.state.animatedNodes[ nodeID ];
+ }
+ }
},
// -- ticked -----------------------------------------------------------------------------------
@@ -522,7 +551,7 @@ define( [ "module",
findNavObject();
}
- lerpTick();
+
},
// -- render -----------------------------------------------------------------------------------
@@ -889,22 +918,7 @@ define( [ "module",
var navObject = undefined;
var cameraNode = undefined;
- function lerpTick () {
- var now = performance.now();
- self.realTickDif = now - self.lastRealTick;
-
- self.lastRealTick = now;
-
- //reset - loading can cause us to get behind and always but up against the max prediction value
- self.tickTime = 0;
-
- for ( var nodeID in self.nodes ) {
- if ( self.state.nodes[nodeID] ) {
- self.nodes[nodeID].lastTickTransform = self.nodes[nodeID].selfTickTransform;
- self.nodes[nodeID].selfTickTransform = getTransform(nodeID);
- }
- }
- }
+
function lerp(a,b,l,c) {
if(c) l = Math.min(1,Math.max(l,0));
return (b*l) + a*(1.0-l);
@@ -948,7 +962,19 @@ define( [ "module",
}
}
- function matrixLerp( a, b, l ) {
+ function matset(newv, old) {
+ if (!old) {
+ newv = old;
+ return;
+ }
+ if (!newv)
+ newv = [];
+ for (var i = 0; i < old.length; i++)
+ newv[i] = old[i];
+ return newv;
+ }
+
+ function matrixLerp( a, b, l,n ) {
// If either of the matrices is not left-handed or not orthogonal, interpolation won't work
// Just return the second matrix
@@ -956,7 +982,7 @@ define( [ "module",
return b;
}
- var n = goog.vec.Mat4.clone(a);
+ if (!n) n = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
n[12] = lerp(a[12],b[12],l);
n[13] = lerp(a[13],b[13],l);
n[14] = lerp(a[14],b[14],l);
@@ -1016,45 +1042,122 @@ define( [ "module",
return nqm;
}
- function getTransform(id) {
- var interp = goog.vec.Mat4.clone(self.state.nodes[id].threeObject.matrix.elements);
+ function getAnimationFrame( id ) {
+ var interp = vwf.getProperty( id, 'animationFrame' );
return interp;
}
- function setTransform(id,interp) {
- interp = goog.vec.Mat4.clone(interp)
- self.state.nodes[id].threeObject.matrix.elements = interp;
- self.state.nodes[id].threeObject.updateMatrixWorld(true);
+ function setAnimationFrame( id, val ) {
+ //NOTE: this can cause state errors. Need a layer in VWF to abstract the set of this
+ //property from the VWF model state.
+ vwf.setProperty( id, 'animationFrame', val );
+ }
+ function getTransform( id ) {
+ var interp = goog.vec.Mat4.clone( self.state.nodes[ id ].threeObject.matrix.elements );
+ return interp;
+ }
+ function setTransform( id, interp ) {
+ interp = goog.vec.Mat4.clone( interp )
+ self.state.nodes[ id ].threeObject.matrix.elements = interp;
+ self.state.nodes[ id ].threeObject.updateMatrixWorld( true );
}
function setInterpolatedTransforms(deltaTime) {
- var step = (self.tickTime) / (self.realTickDif);
- step = Math.min(step,1);
- deltaTime = Math.min(deltaTime, self.realTickDif)
- self.tickTime += deltaTime || 0;
- for(var nodeID in self.nodes) {
- var last = self.nodes[nodeID].lastTickTransform;
- var now = self.nodes[nodeID].selfTickTransform;
- if(last && now && !matCmp(last,now,.0001) ) {
- var interp = matrixLerp(last, now, step || 0);
+ //smooth over local time
+ self.tickTime += deltaTime || 0;
+ var hit = 0;
+
+ //how many ticks has it been?
+ while (self.tickTime > 50) {
+ hit++;
+ self.tickTime -= 50;
+ }
+ var step = (self.tickTime) / (50);
+ var keys, id, j, nd;
+ //if the tick is exactly one, we reset
+ if (hit === 1) {
+
+ //NOTE: we use this construct because V8 will not optimize a function with a for in loop
+ keys = Object.keys( self.state.animatedNodes );
+ for ( j = 0; j < keys.length; j++) {
+ id = keys[ j ];
+ nd = self.state.animatedNodes[ id ];
- var objectIsControlledByUser = ( ( navmode !== "none" ) &&
- ( ( navObject && ( nodeID === navObject.ID ) ) ||
- ( cameraNode && ( nodeID === cameraNode.ID ) ) ) );
- if ( !objectIsControlledByUser ) {
- setTransform(nodeID, interp);
- self.nodes[nodeID].needTransformRestore = true;
+ if ( self.state.nodes[ id ] ) {
+ if ( nd.lastTickTransform !== undefined && nd.thisTickTransform !== undefined ) {
+ nd.lastTickTransform = matset( nd.lastTickTransform, nd.thisTickTransform );
+ nd.thisTickTransform = matset( nd.thisTickTransform, getTransform( id ) );
+ }
+
+ if ( nd.lastAnimationFrame !== undefined && nd.thisAnimationFrame !== undefined ) {
+ nd.lastAnimationFrame = nd.thisAnimationFrame;
+ nd.thisAnimationFrame = getAnimationFrame( id );
+ }
}
}
+
+ }
+
+ //this is where we trade off between responsive and smooth. This is sort of a magic number picked
+ //empirically.
+ //try the duck example with this set to 1, and then again set to .01
+ var LERPFACTOR = .15;
+ var lerpStep = Math.min(1, LERPFACTOR * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20
+ keys = Object.keys( self.state.animatedNodes );
+ //reuse local variables where possible, especially if they are arrays
+ var interp = null;
+ var last, now;
+ for ( j = 0; j < keys.length; j++) {
+ id = keys[j];
+ nd = self.state.animatedNodes[ id ];
+ last = nd.lastTickTransform;
+ now = nd.thisTickTransform;
+ if (last && now) {
+ //use matset to keep data in temp variables
+ interp = matset(interp, last);
+ interp = matrixLerp(last, now, step, interp);
+
+ nd.currentTickTransform = matset( nd.currentTickTransform, getTransform( id ) );
+
+ if ( nd.lastFrameInterp )
+ interp = matrixLerp( nd.lastFrameInterp, now, lerpStep, interp );
+ setTransform( id, interp );
+ nd.lastFrameInterp = matset( nd.lastFrameInterp || [], interp );
+ }
+
+ last = nd.lastAnimationFrame;
+ now = nd.thisAnimationFrame;
+ //If the delta in animation frames is greater than 3, treat is as discontinuous
+ if ( last && now && Math.abs(now - last) < 3) {
+ var interpA = 0;
+ interpA = lerp(last, now, step);
+ nd.currentAnimationFrame = getAnimationFrame(id);
+
+ if (self.state.nodes[id].lastAnimationInterp)
+ interpA = lerp(self.state.nodes[id].lastAnimationInterp, now, lerpStep);
+ setAnimationFrame(id,interpA);
+ self.state.nodes[id].lastAnimationInterp = interpA || 0;
+
+ } else if (self.state.nodes[id]) {
+ self.state.nodes[id].lastAnimationInterp = null;
+ }
+
}
}
function restoreTransforms() {
- for(var nodeID in self.nodes) {
- var now = self.nodes[nodeID].selfTickTransform;
-
- if(self.node != navObject && now && self.nodes[nodeID].needTransformRestore) {
- self.state.nodes[nodeID].threeObject.matrix.elements = goog.vec.Mat4.clone(now);
- self.state.nodes[nodeID].threeObject.updateMatrixWorld(true);
- self.nodes[nodeID].needTransformRestore = false;
+ var keys, id, j, now, nd;
+ keys = Object.keys( self.state.animatedNodes );
+ for ( j = 0; j < keys.length; j++) {
+ id = keys[j];
+ nd = self.state.animatedNodes[ id ];
+ if ( nd.currentTickTransform != null ) {
+ now = nd.currentTickTransform;
+ nd.currentTickTransform = null;
+ setTransform( id, now );
+ }
+ if ( nd.currentAnimationFrame != null ) {
+ now = nd.currentAnimationFrame;
+ nd.currentAnimationFrame = null;
+ setAnimationFrame( id, now );
}
}
}
diff --git a/support/proxy/vwf.example.com/node3.vwf.yaml b/support/proxy/vwf.example.com/node3.vwf.yaml
index 574d7844d..fac18eaa5 100644
--- a/support/proxy/vwf.example.com/node3.vwf.yaml
+++ b/support/proxy/vwf.example.com/node3.vwf.yaml
@@ -274,45 +274,6 @@ properties:
## @name node3.vwf#vertices
## @property
- vertices:
- set: |
- this.logger.info( "WARNING: node3 vertices cannot be set" )
-
- ## Vertex indices of 3D node
- ##
- ## @name node3.vwf#vertexIndices
- ## @property
-
- vertexIndices:
- set: |
- this.logger.info( "WARNING: node3 vertexIndices cannot be set" )
-
- ## Speed value
- ##
- ## @name node3.vwf#speed
- ## @property
-
- speed: 1
-
- ## Playing value
- ##
- ## @name node3.vwf#playing
- ## @property
-
- playing: false
-
- ## Looping value
- ##
- ## @name node3.vwf#looping
- ## @property
-
- looping: false
-
- ## Look at value
- ##
- ## @name lookAt
- ## @property
-
lookAt: ""
## Visible value
diff --git a/support/proxy/vwf.example.com/node3/animation.vwf.yaml b/support/proxy/vwf.example.com/node3/animation.vwf.yaml
index 57504dd43..4492ed099 100644
--- a/support/proxy/vwf.example.com/node3/animation.vwf.yaml
+++ b/support/proxy/vwf.example.com/node3/animation.vwf.yaml
@@ -416,5 +416,5 @@ methods:
}
this.transformTo( stopTransform, duration ); //@ sourceURL=node3.animation.worldTransformTo.vwf
-event:
+events:
changingTransformFromView: