123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- "use strict";
- // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
- // Secretary of Defense (Personnel & Readiness).
- //
- // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- // in compliance with the License. You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software distributed under the License
- // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- // or implied. See the License for the specific language governing permissions and limitations under
- // the License.
- /// vwf/model.js is the common implementation of all Virtual World Framework models. Each model
- /// is part of a federation with other models attached to the simulation that implements part of
- /// the greater model. Taken together, the models create the entire model system for the
- /// simulation.
- ///
- /// Models are inside of, and directly part of the simulation. They may control the simulation
- /// and cause immediate change, but they cannot accept external input. The model configuration is
- /// identical for all participants in a shared world.
- ///
- /// A given model might be responsible for a certain subset of nodes in the the simulation, such
- /// as those representing Flash objects. Or it might implement part of the functionality of any
- /// node, such as translating 3-D transforms and material properties back and forth to a scene
- /// manager. Or it might implement functionality that is only active for a short period, such as
- /// importing a document.
- ///
- /// vwf/model and all deriving models are loaded as RequireJS (http://requirejs.org) modules.
- ///
- /// @module vwf/model
- /// @requires logger
- /// @requires vwf/api/kernel
- /// @requires vwf/api/model
- define( [ "module", "logger", "vwf/api/kernel", "vwf/api/model" ], function( module, logger, kernel_api, model_api ) {
- // TODO: most of this is the same between vwf/model.js and vwf/view.js. Find a way to share.
- var label = module.id.replace( /\//g, "." );
- logger.for( label ).debug( "loading" );
- var exports = {
- module: module,
- logger: logger.for( label ),
- load: function( module, initializer, modelGenerator, kernelGenerator ) {
- var instance = Object.create( this );
- instance.module = module;
- instance.logger = logger.for( instance.module.id.replace( /\//g, "." ), instance );
-
- instance.logger.debug( "loading" );
- if ( typeof initializer == "function" || initializer instanceof Function ) {
- initializer = initializer();
- }
- for ( var key in initializer ) {
- instance[key] = initializer[key];
- }
- modelGenerator && Object.keys( model_api ).forEach( function( modelFunctionName ) {
- if ( ! instance.hasOwnProperty( modelFunctionName ) ) {
- instance[modelFunctionName] = modelGenerator.call( instance, modelFunctionName );
- instance[modelFunctionName] || delete instance[modelFunctionName];
- }
- } );
- kernelGenerator && Object.keys( kernel_api ).forEach( function( kernelFunctionName ) {
- if ( ! instance.hasOwnProperty( kernelFunctionName ) ) {
- instance[kernelFunctionName] = kernelGenerator.call( instance, kernelFunctionName );
- instance[kernelFunctionName] || delete instance[kernelFunctionName];
- }
- } );
- return instance;
- },
- create: function( kernel, model, stages, state, parameters ) {
- this.logger.debug( "creating" );
- // Interpret create( kernel, stages, ... ) as create( kernel, undefined, stages, ... )
- if ( model && model.length !== undefined ) { // is an array?
- parameters = state;
- state = stages;
- stages = model;
- model = undefined;
- }
- // Append this driver's stages to the pipeline to be placed in front of this driver.
- if ( ! model ) {
- stages = Array.prototype.concat.apply( [], ( this.pipeline || [] ).map( function( stage ) {
- return ( stages || [] ).concat( stage );
- } ) ).concat( stages || [] );
- } else {
- stages = ( stages || [] ).concat( this.pipeline || [] );
- }
- // Create the driver stage using its module as its prototype.
- var instance = Object.create( this );
- // Attach the reference to the stage to the right through the model API.
- modelize.call( instance, model, model_api );
- // Create the pipeline to the left and attach the reference to the stage to the left
- // through the kernel API.
- kernelize.call( instance,
- stages.length ?
- stages.pop().create( kernel, instance, stages ) :
- kernel,
- kernel_api );
- // Attach the shared state object.
- instance.state = state || {};
- // Call the driver's initialize().
- initialize.apply( instance, parameters );
- // Call modelize() on the driver.
- function modelize( model, model_api ) {
- Object.getPrototypeOf( this ) && modelize.call( Object.getPrototypeOf( this ), model, model_api ); // depth-first recursion through the prototypes
- this.hasOwnProperty( "modelize" ) && this.modelize.call( instance, model, model_api ); // modelize() from the bottom up
- }
- // Call kernelize() on the driver.
- function kernelize( kernel, kernel_api ) {
- Object.getPrototypeOf( this ) && kernelize.call( Object.getPrototypeOf( this ), kernel, kernel_api ); // depth-first recursion through the prototypes
- this.hasOwnProperty( "kernelize" ) && this.kernelize.call( instance, kernel, kernel_api ); // kernelize() from the bottom up
- }
- // Call initialize() on the driver.
- function initialize( /* parameters */ ) {
- Object.getPrototypeOf( this ) && initialize.apply( Object.getPrototypeOf( this ), arguments ); // depth-first recursion through the prototypes
- this.hasOwnProperty( "initialize" ) && this.initialize.apply( instance, arguments ); // initialize() from the bottom up
- }
- // Return the driver stage. For the actual driver, return the leftmost stage in the
- // pipeline.
- if ( ! model ) {
- while ( instance.kernel !== kernel ) {
- instance = instance.kernel;
- }
- }
- return instance;
- },
- kernelize: function( kernel, kernel_api ) {
- this.kernel = kernel;
- },
-
- };
- return exports;
- } );
|