model.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/model.js is the common implementation of all Virtual World Framework models. Each model
  15. /// is part of a federation with other models attached to the simulation that implements part of
  16. /// the greater model. Taken together, the models create the entire model system for the
  17. /// simulation.
  18. ///
  19. /// Models are inside of, and directly part of the simulation. They may control the simulation
  20. /// and cause immediate change, but they cannot accept external input. The model configuration is
  21. /// identical for all participants in a shared world.
  22. ///
  23. /// A given model might be responsible for a certain subset of nodes in the the simulation, such
  24. /// as those representing Flash objects. Or it might implement part of the functionality of any
  25. /// node, such as translating 3-D transforms and material properties back and forth to a scene
  26. /// manager. Or it might implement functionality that is only active for a short period, such as
  27. /// importing a document.
  28. ///
  29. /// vwf/model and all deriving models are loaded as RequireJS (http://requirejs.org) modules.
  30. ///
  31. /// @module vwf/model
  32. /// @requires logger
  33. /// @requires vwf/api/kernel
  34. /// @requires vwf/api/model
  35. define( [ "module", "logger", "vwf/api/kernel", "vwf/api/model" ], function( module, logger, kernel_api, model_api ) {
  36. // TODO: most of this is the same between vwf/model.js and vwf/view.js. Find a way to share.
  37. var label = module.id.replace( /\//g, "." );
  38. logger.for( label ).debug( "loading" );
  39. var exports = {
  40. module: module,
  41. logger: logger.for( label ),
  42. load: function( module, initializer, modelGenerator, kernelGenerator ) {
  43. var instance = Object.create( this );
  44. instance.module = module;
  45. instance.logger = logger.for( instance.module.id.replace( /\//g, "." ), instance );
  46. instance.logger.debug( "loading" );
  47. if ( typeof initializer == "function" || initializer instanceof Function ) {
  48. initializer = initializer();
  49. }
  50. for ( var key in initializer ) {
  51. instance[key] = initializer[key];
  52. }
  53. modelGenerator && Object.keys( model_api ).forEach( function( modelFunctionName ) {
  54. if ( ! instance.hasOwnProperty( modelFunctionName ) ) {
  55. instance[modelFunctionName] = modelGenerator.call( instance, modelFunctionName );
  56. instance[modelFunctionName] || delete instance[modelFunctionName];
  57. }
  58. } );
  59. kernelGenerator && Object.keys( kernel_api ).forEach( function( kernelFunctionName ) {
  60. if ( ! instance.hasOwnProperty( kernelFunctionName ) ) {
  61. instance[kernelFunctionName] = kernelGenerator.call( instance, kernelFunctionName );
  62. instance[kernelFunctionName] || delete instance[kernelFunctionName];
  63. }
  64. } );
  65. return instance;
  66. },
  67. create: function( kernel, model, stages, state, parameters ) {
  68. this.logger.debug( "creating" );
  69. // Interpret create( kernel, stages, ... ) as create( kernel, undefined, stages, ... )
  70. if ( model && model.length !== undefined ) { // is an array?
  71. parameters = state;
  72. state = stages;
  73. stages = model;
  74. model = undefined;
  75. }
  76. // Append this driver's stages to the pipeline to be placed in front of this driver.
  77. if ( ! model ) {
  78. stages = Array.prototype.concat.apply( [], ( this.pipeline || [] ).map( function( stage ) {
  79. return ( stages || [] ).concat( stage );
  80. } ) ).concat( stages || [] );
  81. } else {
  82. stages = ( stages || [] ).concat( this.pipeline || [] );
  83. }
  84. // Create the driver stage using its module as its prototype.
  85. var instance = Object.create( this );
  86. // Attach the reference to the stage to the right through the model API.
  87. modelize.call( instance, model, model_api );
  88. // Create the pipeline to the left and attach the reference to the stage to the left
  89. // through the kernel API.
  90. kernelize.call( instance,
  91. stages.length ?
  92. stages.pop().create( kernel, instance, stages ) :
  93. kernel,
  94. kernel_api );
  95. // Attach the shared state object.
  96. instance.state = state || {};
  97. // Call the driver's initialize().
  98. initialize.apply( instance, parameters );
  99. // Call modelize() on the driver.
  100. function modelize( model, model_api ) {
  101. Object.getPrototypeOf( this ) && modelize.call( Object.getPrototypeOf( this ), model, model_api ); // depth-first recursion through the prototypes
  102. this.hasOwnProperty( "modelize" ) && this.modelize.call( instance, model, model_api ); // modelize() from the bottom up
  103. }
  104. // Call kernelize() on the driver.
  105. function kernelize( kernel, kernel_api ) {
  106. Object.getPrototypeOf( this ) && kernelize.call( Object.getPrototypeOf( this ), kernel, kernel_api ); // depth-first recursion through the prototypes
  107. this.hasOwnProperty( "kernelize" ) && this.kernelize.call( instance, kernel, kernel_api ); // kernelize() from the bottom up
  108. }
  109. // Call initialize() on the driver.
  110. function initialize( /* parameters */ ) {
  111. Object.getPrototypeOf( this ) && initialize.apply( Object.getPrototypeOf( this ), arguments ); // depth-first recursion through the prototypes
  112. this.hasOwnProperty( "initialize" ) && this.initialize.apply( instance, arguments ); // initialize() from the bottom up
  113. }
  114. // Return the driver stage. For the actual driver, return the leftmost stage in the
  115. // pipeline.
  116. if ( ! model ) {
  117. while ( instance.kernel !== kernel ) {
  118. instance = instance.kernel;
  119. }
  120. }
  121. return instance;
  122. },
  123. kernelize: function( kernel, kernel_api ) {
  124. this.kernel = kernel;
  125. },
  126. };
  127. return exports;
  128. } );