NodeMaterialLoader.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import {
  2. Loader,
  3. FileLoader
  4. } from '../../../build/three.module.js';
  5. import * as Nodes from '../nodes/Nodes.js';
  6. class NodeMaterialLoader extends Loader {
  7. constructor( manager, library = {} ) {
  8. super( manager );
  9. this.nodes = {};
  10. this.materials = {};
  11. this.passes = {};
  12. this.names = {};
  13. this.library = library;
  14. }
  15. load( url, onLoad, onProgress, onError ) {
  16. const scope = this;
  17. const loader = new FileLoader( scope.manager );
  18. loader.setPath( scope.path );
  19. loader.load( url, function ( text ) {
  20. onLoad( scope.parse( JSON.parse( text ) ) );
  21. }, onProgress, onError );
  22. return this;
  23. }
  24. getObjectByName( uuid ) {
  25. return this.names[ uuid ];
  26. }
  27. getObjectById( uuid ) {
  28. return this.library[ uuid ] ||
  29. this.nodes[ uuid ] ||
  30. this.materials[ uuid ] ||
  31. this.passes[ uuid ] ||
  32. this.names[ uuid ];
  33. }
  34. getNode( uuid ) {
  35. const object = this.getObjectById( uuid );
  36. if ( ! object ) {
  37. console.warn( 'Node "' + uuid + '" not found.' );
  38. }
  39. return object;
  40. }
  41. resolve( json ) {
  42. switch ( typeof json ) {
  43. case 'boolean':
  44. case 'number':
  45. return json;
  46. case 'string':
  47. if ( /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/i.test( json ) || this.library[ json ] ) {
  48. return this.getNode( json );
  49. }
  50. return json;
  51. default:
  52. if ( Array.isArray( json ) ) {
  53. for ( let i = 0; i < json.length; i ++ ) {
  54. json[ i ] = this.resolve( json[ i ] );
  55. }
  56. } else {
  57. for ( const prop in json ) {
  58. if ( prop === 'uuid' ) continue;
  59. json[ prop ] = this.resolve( json[ prop ] );
  60. }
  61. }
  62. }
  63. return json;
  64. }
  65. declare( json ) {
  66. let uuid, node, object;
  67. for ( uuid in json.nodes ) {
  68. node = json.nodes[ uuid ];
  69. object = new Nodes[ node.nodeType + 'Node' ]();
  70. if ( node.name ) {
  71. object.name = node.name;
  72. this.names[ object.name ] = object;
  73. }
  74. this.nodes[ uuid ] = object;
  75. }
  76. for ( uuid in json.materials ) {
  77. node = json.materials[ uuid ];
  78. object = new Nodes[ node.type ]();
  79. if ( node.name ) {
  80. object.name = node.name;
  81. this.names[ object.name ] = object;
  82. }
  83. this.materials[ uuid ] = object;
  84. }
  85. for ( uuid in json.passes ) {
  86. node = json.passes[ uuid ];
  87. object = new Nodes[ node.type ]();
  88. if ( node.name ) {
  89. object.name = node.name;
  90. this.names[ object.name ] = object;
  91. }
  92. this.passes[ uuid ] = object;
  93. }
  94. if ( json.material ) this.material = this.materials[ json.material ];
  95. if ( json.pass ) this.pass = this.passes[ json.pass ];
  96. return json;
  97. }
  98. parse( json ) {
  99. let uuid;
  100. json = this.resolve( this.declare( json ) );
  101. for ( uuid in json.nodes ) {
  102. this.nodes[ uuid ].copy( json.nodes[ uuid ] );
  103. }
  104. for ( uuid in json.materials ) {
  105. this.materials[ uuid ].copy( json.materials[ uuid ] );
  106. }
  107. for ( uuid in json.passes ) {
  108. this.passes[ uuid ].copy( json.passes[ uuid ] );
  109. }
  110. return this.material || this.pass || this;
  111. }
  112. }
  113. class NodeMaterialLoaderUtils {
  114. static replaceUUIDObject( object, uuid, value, recursive ) {
  115. recursive = recursive !== undefined ? recursive : true;
  116. if ( typeof uuid === 'object' ) uuid = uuid.uuid;
  117. if ( typeof object === 'object' ) {
  118. const keys = Object.keys( object );
  119. for ( let i = 0; i < keys.length; i ++ ) {
  120. const key = keys[ i ];
  121. if ( recursive ) {
  122. object[ key ] = this.replaceUUIDObject( object[ key ], uuid, value );
  123. }
  124. if ( key === uuid ) {
  125. object[ uuid ] = object[ key ];
  126. delete object[ key ];
  127. }
  128. }
  129. }
  130. return object === uuid ? value : object;
  131. }
  132. static replaceUUID( json, uuid, value ) {
  133. this.replaceUUIDObject( json, uuid, value, false );
  134. this.replaceUUIDObject( json.nodes, uuid, value );
  135. this.replaceUUIDObject( json.materials, uuid, value );
  136. this.replaceUUIDObject( json.passes, uuid, value );
  137. this.replaceUUIDObject( json.library, uuid, value, false );
  138. return json;
  139. }
  140. }
  141. export { NodeMaterialLoader, NodeMaterialLoaderUtils };