diff --git a/lib/nodejs/serve.js b/lib/nodejs/serve.js
index 5413ac069..9a1b56767 100755
--- a/lib/nodejs/serve.js
+++ b/lib/nodejs/serve.js
@@ -98,7 +98,8 @@ function ServeYAML( filename, response, URL ) {
try {
var deYAML = JSON.stringify( YAML.load( file ) );
} catch ( e ) {
- global.log( "error parsing YAML " + filename );
+ global.log( "error parsing YAML " + filename);
+ global.log("" + e);
_404( response );
return;
}
diff --git a/support/client/lib/vwf.js b/support/client/lib/vwf.js
index 36e3e758a..fa239e70c 100644
--- a/support/client/lib/vwf.js
+++ b/support/client/lib/vwf.js
@@ -323,6 +323,9 @@
"vwf/model/blockly/msg/js/en": {
deps: [ "vwf/model/blockly/blockly_compressed" ]
},
+ "vwf/model/hud/hud": {
+ exports: "HUD"
+ }
}
};
@@ -363,6 +366,8 @@
active: false
},
{ library: "vwf/model/graphtool", active: false },
+ { library: "vwf/model/hud", active: false },
+ { library: "vwf/model/eventManager", active: false },
{ library: "vwf/model/sound", active: false },
{ library: "vwf/model/object", active: true },
{ library: "vwf/model/stage/log", active: true },
@@ -400,11 +405,13 @@
active: false
},
{ library: "vwf/view/blockly", active: false },
+ { library: "vwf/view/hud", active: false },
{ library: "vwf/view/sound", active: false },
{ library: "vwf/view/touch", active: false },
{ library: "vwf/view/cesium", active: false },
{ library: "vwf/view/kineticjs", active: false },
{ library: "vwf/view/mil-sym", active: false },
+ { library: "vwf/view/jPlayer", linkedLibraries: ["vwf/model/jPlayer.2.7.1/jquery.jplayer.min"], active: false },
{ library: "vwf/view/audio", active: false },
{ library: "vwf/kernel/utility", active: true },
{ library: "vwf/utility", active: true },
@@ -439,6 +446,8 @@
{ library: "vwf/model/cesium", active: false },
{ library: "vwf/model/blockly", active: false },
{ library: "vwf/model/graphtool", active: false },
+ { library: "vwf/model/hud", active: false },
+ { library: "vwf/model/eventManager", active: false },
{ library: "vwf/model/sound", active: false },
{ library: "vwf/model/kineticjs", active: false },
{ library: "vwf/model/mil-sym", active: false },
@@ -456,10 +465,12 @@
{ library: "vwf/view/google-earth", active: false },
{ library: "vwf/view/cesium", active: false },
{ library: "vwf/view/blockly", active: false },
+ { library: "vwf/view/hud", active: false },
{ library: "vwf/view/sound", active: false },
{ library: "vwf/view/touch", active: false },
{ library: "vwf/view/kineticjs", active: false },
{ library: "vwf/view/mil-sym", active: false },
+ { library: "vwf/view/jPlayer", active: false },
{ library: "vwf/view/audio", active: false },
{ library: "vwf/view/webrtc", active: false}
]
@@ -697,7 +708,7 @@
var model = require( modelName ).create(
this.models.kernel, // model's kernel access
- [ require( "vwf/model/stage/log" ) ], // stages between the kernel and model
+ [], // stages between the kernel and model
{}, // state shared with a paired view
[].concat( modelArguments || [] ) // arguments for initialize()
);
@@ -716,11 +727,16 @@
while ( this.models.object.model ) this.models.object = this.models.object.model;
}
- if(model.model.compatibilityStatus) {
+ if(model.model && model.model.compatibilityStatus) {
if(!model.model.compatibilityStatus.compatible) {
compatibilityStatus.compatible = false;
jQuery.extend(compatibilityStatus.errors, model.model.compatibilityStatus.errors);
}
+ } else if(model.compatibilityStatus) {
+ if(!model.compatibilityStatus.compatible) {
+ compatibilityStatus.compatible = false;
+ jQuery.extend(compatibilityStatus.errors, model.compatibilityStatus.errors);
+ }
}
}
@@ -3177,73 +3193,87 @@ if ( ! childComponent.source ) {
var delegated = false, assigned = false;
- // Call settingProperty() on each model. The first model to return a non-undefined value
- // has performed the set and dictates the return value. The property is considered set
- // after all models have run.
+ if ( propertyName[ propertyName.length - 1 ] !== "$" ) {
- this.models.some( function( model, index ) {
+ // Call settingProperty() on each model. The first model to return a non-undefined value
+ // has performed the set and dictates the return value. The property is considered set
+ // after all models have run.
- // Skip initial models that an outer call has already invoked for this node and
- // property (if any). If an inner call completed for this node and property, skip
- // the remaining models.
+ this.models.some( function( model, index ) {
- if ( ( ! reentered || index > entry.index ) && ! reentry.completed ) {
+ // Skip initial models that an outer call has already invoked for this node and
+ // property (if any). If an inner call completed for this node and property, skip
+ // the remaining models.
- // Record the active model number.
-
- reentry.index = index;
+ if ( ( ! reentered || index > entry.index ) && ! reentry.completed ) {
- // Record the number of assignments made since the outermost call. When
- // `entrants.assignments` increases, a driver has called `setProperty` to make
- // an assignment elsewhere.
+ // Record the active model number.
- var assignments = entrants.assignments;
+ reentry.index = index;
- // Make the call.
+ // Record the number of assignments made since the outermost call. When
+ // `entrants.assignments` increases, a driver has called `setProperty` to make
+ // an assignment elsewhere.
- if ( ! delegated && ! assigned ) {
- var value = model[settingPropertyEtc] && model[settingPropertyEtc]( nodeID, propertyName, propertyValue );
- } else {
- model[settingPropertyEtc] && model[settingPropertyEtc]( nodeID, propertyName, undefined );
- }
+ var assignments = entrants.assignments;
- // Ignore the result if reentry is disabled and the driver attempted to call
- // back into the kernel. Kernel reentry is disabled during replication to
- // prevent coloring from accessor scripts.
+ // Make the call.
- if ( this.models.kernel.blocked() ) { // TODO: this might be better handled wholly in vwf/kernel/model by converting to a stage and clearing blocked results on the return
- value = undefined;
- }
+ if ( ! delegated && ! assigned ) {
+ var value = model[settingPropertyEtc] && model[settingPropertyEtc]( nodeID, propertyName, propertyValue );
+ } else {
+ model[settingPropertyEtc] && model[settingPropertyEtc]( nodeID, propertyName, undefined );
+ }
- // The property was delegated if the call made any assignments.
+ // Ignore the result if reentry is disabled and the driver attempted to call
+ // back into the kernel. Kernel reentry is disabled during replication to
+ // prevent coloring from accessor scripts.
- if ( entrants.assignments !== assignments ) {
- delegated = true;
- }
+ if ( this.models.kernel.blocked() ) { // TODO: this might be better handled wholly in vwf/kernel/model by converting to a stage and clearing blocked results on the return
+ value = undefined;
+ }
- // Otherwise if the call returned a value, the property was assigned here.
+ // The property was delegated if the call made any assignments.
- else if ( value !== undefined ) {
- entrants.assignments++;
- assigned = true;
- }
+ if ( entrants.assignments !== assignments ) {
+ delegated = true;
+ }
- // Record the value actually assigned. This may differ from the incoming value
- // if it was range limited, quantized, etc. by the model. This is the value
- // passed to the views.
+ // Otherwise if the call returned a value, the property was assigned here.
- if ( value !== undefined ) {
- propertyValue = value;
+ else if ( value !== undefined ) {
+ entrants.assignments++;
+ assigned = true;
+ }
+
+ // Record the value actually assigned. This may differ from the incoming value
+ // if it was range limited, quantized, etc. by the model. This is the value
+ // passed to the views.
+
+ if ( value !== undefined ) {
+ propertyValue = value;
+ }
+
+ // If we are setting, exit from the this.models.some() iterator once the value
+ // has been set. Don't exit early if we are creating or initializing since every
+ // model needs the opportunity to register the property.
+
+ return settingPropertyEtc == "settingProperty" && ( delegated || assigned );
}
- // If we are setting, exit from the this.models.some() iterator once the value
- // has been set. Don't exit early if we are creating or initializing since every
- // model needs the opportunity to register the property.
+ }, this );
- return settingPropertyEtc == "settingProperty" && ( delegated || assigned );
+ } else {
+
+ var value = this.models.object[settingPropertyEtc]( nodeID, propertyName, propertyValue );
+
+ if ( value !== undefined ) {
+ entrants.assignments++;
+ assigned = true;
+ propertyValue = value;
}
- }, this );
+ }
// Record the change if the property was assigned here.
@@ -3258,7 +3288,7 @@ if ( ! childComponent.source ) {
// ephemeral, and views on late-joining clients would never see it, it's best to never
// send those notifications.
- if ( assigned ) {
+ if ( assigned && propertyName[ propertyName.length - 1 ] !== "$" ) {
this.views.forEach( function( view ) {
view[satPropertyEtc] && view[satPropertyEtc]( nodeID, propertyName, propertyValue );
} );
@@ -3350,65 +3380,78 @@ if ( ! childComponent.source ) {
var delegated = false, retrieved = false;
- // Call gettingProperty() on each model. The first model to return a non-undefined value
- // dictates the return value.
+ if ( propertyName[ propertyName.length - 1 ] !== "$" ) {
- this.models.some( function( model, index ) {
+ // Call gettingProperty() on each model. The first model to return a non-undefined value
+ // dictates the return value.
- // Skip initial models that an outer call has already invoked for this node and
- // property (if any). If an inner call completed for this node and property, skip
- // the remaining models.
+ this.models.some( function( model, index ) {
- if ( ( ! reentered || index > entry.index ) && ! reentry.completed ) {
+ // Skip initial models that an outer call has already invoked for this node and
+ // property (if any). If an inner call completed for this node and property, skip
+ // the remaining models.
- // Record the active model number.
-
- reentry.index = index;
+ if ( ( ! reentered || index > entry.index ) && ! reentry.completed ) {
- // Record the number of retrievals made since the outermost call. When
- // `entrants.retrievals` increases, a driver has called `getProperty` to make
- // a retrieval elsewhere.
+ // Record the active model number.
- var retrievals = entrants.retrievals;
+ reentry.index = index;
- // Make the call.
+ // Record the number of retrievals made since the outermost call. When
+ // `entrants.retrievals` increases, a driver has called `getProperty` to make
+ // a retrieval elsewhere.
- var value = model.gettingProperty &&
- model.gettingProperty( nodeID, propertyName, propertyValue ); // TODO: probably don't need propertyValue here
+ var retrievals = entrants.retrievals;
- // Ignore the result if reentry is disabled and the driver attempted to call
- // back into the kernel. Kernel reentry is disabled during replication to
- // prevent coloring from accessor scripts.
+ // Make the call.
- if ( this.models.kernel.blocked() ) { // TODO: this might be better handled wholly in vwf/kernel/model by converting to a stage and clearing blocked results on the return
- value = undefined;
- }
+ var value = model.gettingProperty &&
+ model.gettingProperty( nodeID, propertyName, propertyValue ); // TODO: probably don't need propertyValue here
- // The property was delegated if the call made any retrievals.
+ // Ignore the result if reentry is disabled and the driver attempted to call
+ // back into the kernel. Kernel reentry is disabled during replication to
+ // prevent coloring from accessor scripts.
- if ( entrants.retrievals !== retrievals ) {
- delegated = true;
- }
+ if ( this.models.kernel.blocked() ) { // TODO: this might be better handled wholly in vwf/kernel/model by converting to a stage and clearing blocked results on the return
+ value = undefined;
+ }
- // Otherwise if the call returned a value, the property was retrieved here.
+ // The property was delegated if the call made any retrievals.
- else if ( value !== undefined ) {
- entrants.retrievals++;
- retrieved = true;
- }
+ if ( entrants.retrievals !== retrievals ) {
+ delegated = true;
+ }
+
+ // Otherwise if the call returned a value, the property was retrieved here.
+
+ else if ( value !== undefined ) {
+ entrants.retrievals++;
+ retrieved = true;
+ }
+
+ // Record the value retrieved.
+
+ if ( value !== undefined ) {
+ propertyValue = value;
+ }
- // Record the value retrieved.
+ // Exit from the this.models.some() iterator once we have a return value.
- if ( value !== undefined ) {
- propertyValue = value;
+ return delegated || retrieved;
}
- // Exit from the this.models.some() iterator once we have a return value.
+ }, this );
+
+ } else {
+
+ var value = this.models.object.gettingProperty( nodeID, propertyName, propertyValue ); // TODO: probably don't need propertyValue here
- return delegated || retrieved;
+ if ( value !== undefined ) {
+ entrants.retrievals++;
+ propertyValue = value;
}
- }, this );
+ }
if ( reentered ) {
@@ -3447,9 +3490,11 @@ if ( ! childComponent.source ) {
// Call gotProperty() on each view.
- this.views.forEach( function( view ) {
- view.gotProperty && view.gotProperty( nodeID, propertyName, propertyValue ); // TODO: be sure this is the value actually gotten and not an intermediate value from above
- } );
+ if ( propertyName[ propertyName.length - 1 ] !== "$" ) {
+ this.views.forEach( function( view ) {
+ view.gotProperty && view.gotProperty( nodeID, propertyName, propertyValue ); // TODO: be sure this is the value actually gotten and not an intermediate value from above
+ } );
+ }
}
@@ -4319,8 +4364,12 @@ if ( ! childComponent.source ) {
///
/// @see {@link module:vwf/api/kernel.application}
+this.applicationID = undefined;
+
this.application = function( initializedOnly ) {
+if ( this.applicationID ) return this.applicationID;
+
var applicationID;
Object.keys( nodes.globals ).forEach( function( globalID ) {
@@ -4330,6 +4379,8 @@ if ( ! childComponent.source ) {
}
}, this );
+this.applicationID = applicationID;
+
return applicationID;
};
diff --git a/support/client/lib/vwf/model/blockly.js b/support/client/lib/vwf/model/blockly.js
index 5bdea9eac..27ead98a0 100644
--- a/support/client/lib/vwf/model/blockly.js
+++ b/support/client/lib/vwf/model/blockly.js
@@ -63,7 +63,8 @@ define( [ "module", "vwf/model", "vwf/utility",
"defaultXml": undefined,
"code": undefined,
"lastLineExeTime": undefined,
- "timeBetweenLines": 1,
+ "timeBetweenLines": 0.5,
+ "baseExecutionSpeed": 1,
"interpreter": undefined,
"interpreterStatus": ""
};
@@ -226,9 +227,30 @@ define( [ "module", "vwf/model", "vwf/utility",
case "blockly_code":
value = node.code = propertyValue;
break;
-
+
+ case "new_xml":
+ node.blocks = propertyValue;
+ value = propertyValue;
+ break;
+
case "blockly_xml":
- value = node.blocks = propertyValue;
+ node.blocks = propertyValue;
+ value = propertyValue;
+ break;
+
+ case "blockly_timeBetweenLines":
+ this.state.blockly.node.timeBetweenLines = propertyValue;
+ break;
+
+ case "blockly_baseExecutionSpeed":
+
+ if ( propertyValue > 0 && propertyValue <= 10 ) {
+ this.state.blockly.node.baseExecutionSpeed = propertyValue;
+ } else {
+ this.logger.errorx("baseExecutionSpeed", "Blockly node with", nodeID,
+ "must be in the range (0,10).");
+ }
+
break;
case "blockly_executing":
@@ -307,7 +329,7 @@ define( [ "module", "vwf/model", "vwf/utility",
// -- callingMethod --------------------------------------------------------------------------
- callingMethod: function( nodeID, methodName /* [, parameter1, parameter2, ... ] */ ) { // TODO: parameters
+ callingMethod: function( nodeID, methodName, methodParameters ) {
var node = this.state.nodes[ nodeID ];
if ( this.debug.methods ) {
@@ -317,7 +339,7 @@ define( [ "module", "vwf/model", "vwf/utility",
if ( nodeID == this.kernel.application() ) {
switch ( methodName ) {
-
+
case "stopAllExecution":
for ( var id in this.state.executingBlocks ) {
this.state.executingBlocks[ id ].interpreterStatus = "completed";
@@ -332,8 +354,6 @@ define( [ "module", "vwf/model", "vwf/utility",
this.kernel.fireEvent( id, "blocklyStarted", [ true ] );
}
break;
-
-
}
} else if ( node !== undefined ) {
switch ( methodName ) {
@@ -344,6 +364,17 @@ define( [ "module", "vwf/model", "vwf/utility",
this.kernel.setProperty( nodeID, "blockly_xml", '' );
}
break;
+ case "stopExecution":
+ var currBlockly3Node = this.state.executingBlocks[ nodeID ];
+ if ( currBlockly3Node ) {
+ currBlockly3Node.interpreterStatus = "completed";
+ this.kernel.setProperty( nodeID, 'blockly_executing', false );
+ this.kernel.fireEvent( nodeID, "blocklyStopped", [ true ] );
+ } else {
+ this.logger.errorx("stopExecutionForNode", "Node with", nodeID,
+ "is not currently executing Blockly!");
+ }
+ break;
}
}
},
@@ -367,8 +398,9 @@ define( [ "module", "vwf/model", "vwf/utility",
for ( var nodeID in this.state.executingBlocks ) {
blocklyNode = this.state.executingBlocks[ nodeID ];
- var executeNextLine = false;
+ var executeNextLine = false;
+
if ( blocklyNode.interpreter === undefined ||
blocklyNode.interpreterStatus === "completed" ) {
blocklyNode.interpreter = createInterpreter( acorn, blocklyNode.code );
@@ -377,7 +409,7 @@ define( [ "module", "vwf/model", "vwf/utility",
executeNextLine = true;
} else {
var elaspedTime = vwfTime - blocklyNode.lastLineExeTime;
- if ( elaspedTime >= blocklyNode.timeBetweenLines ) {
+ if ( elaspedTime >= ( blocklyNode.timeBetweenLines * blocklyNode.baseExecutionSpeed ) ) {
executeNextLine = true;
blocklyNode.lastLineExeTime = vwfTime;
}
@@ -386,10 +418,11 @@ define( [ "module", "vwf/model", "vwf/utility",
if ( executeNextLine ) {
self.state.executionHalted = false;
-
nextStep( blocklyNode );
- this.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] );
+ // Does this serve any real purpose? It's not handled in any application.
+ // Certain blocks, such as repeat blocks, break with the recursive node reference changes.
+ // this.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] );
}
}
}
@@ -398,18 +431,6 @@ define( [ "module", "vwf/model", "vwf/utility",
} );
- function getPrototypes( extendsID ) {
- var prototypes = [];
- var id = extendsID;
-
- while ( id !== undefined ) {
- prototypes.push( id );
- id = self.kernel.prototype( id );
- }
-
- return prototypes;
- }
-
function isBlockly3Node( nodeID ) {
return self.kernel.test( nodeID,
"self::element(*,'http://vwf.example.com/blockly/controller.vwf')",
diff --git a/support/client/lib/vwf/model/blockly/blockly_compressed.js b/support/client/lib/vwf/model/blockly/blockly_compressed.js
index 9a0ab7c43..8b6d0159c 100644
--- a/support/client/lib/vwf/model/blockly/blockly_compressed.js
+++ b/support/client/lib/vwf/model/blockly/blockly_compressed.js
@@ -1,233 +1,366 @@
// Do not edit this file; automatically generated by build.py.
"use strict";
-var COMPILED=!0,goog=goog||{};goog.global=this;goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c=c[d]?c[d]:c[d]={}:c[d]=b};goog.define=function(a,b){var c=b;COMPILED||goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]);goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE="en";goog.TRUSTED_SITE=!0;
-goog.provide=function(a){if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a];for(var b=a;(b=b.substring(0,b.lastIndexOf(".")))&&!goog.getObjectByName(b);)goog.implicitNamespaces_[b]=!0}goog.exportPath_(a)};goog.setTestOnly=function(a){if(COMPILED&&!goog.DEBUG)throw a=a||"",Error("Importing test-only code into non-debug environment"+a?": "+a:".");};
-COMPILED||(goog.isProvided_=function(a){return!goog.implicitNamespaces_[a]&&!!goog.getObjectByName(a)},goog.implicitNamespaces_={});goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]};
-goog.addDependency=function(a,b,c){if(goog.DEPENDENCIES_ENABLED){var d;a=a.replace(/\\/g,"/");for(var e=goog.dependencies_,f=0;d=b[f];f++)e.nameToPath[d]=a,a in e.pathToNames||(e.pathToNames[a]={}),e.pathToNames[a][d]=!0;for(d=0;b=c[d];d++)a in e.requires||(e.requires[a]={}),e.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0;
-goog.require=function(a){if(!COMPILED&&!goog.isProvided_(a)){if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b){goog.included_[b]=!0;goog.writeScripts_();return}}a="goog.require could not find: "+a;goog.global.console&&goog.global.console.error(a);throw Error(a);}};goog.basePath="";goog.nullFunction=function(){};goog.identityFunction=function(a,b){return a};goog.abstractMethod=function(){throw Error("unimplemented abstract method");};
-goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER;
-goog.DEPENDENCIES_ENABLED&&(goog.included_={},goog.dependencies_={pathToNames:{},nameToPath:{},requires:{},visited:{},written:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return"undefined"!=typeof a&&"write"in a},goog.findBasePath_=function(){if(goog.global.CLOSURE_BASE_PATH)goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("script"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length:
-d;if("base.js"==c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a){var b=goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_;!goog.dependencies_.written[a]&&b(a)&&(goog.dependencies_.written[a]=!0)},goog.writeScriptTag_=function(a){if(goog.inHtmlDocument_()){var b=goog.global.document;if("complete"==b.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}b.write('