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('