Editor.js 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. var Editor = function ( scene ) {
  2. this.geometries = {};
  3. this.materials = {};
  4. this.textures = {};
  5. this.objects = {};
  6. this.geometriesCount = 0;
  7. this.materialsCount = 0;
  8. this.texturesCount = 0;
  9. this.objectsCount = 0;
  10. this.selected = {};
  11. this.helpers = {};
  12. this.scene = new THREE.Scene();
  13. this.scene.name = ( scene && scene.name ) ? scene.name : 'Scene';
  14. this.addObject( this.scene );
  15. this.sceneHelpers = new THREE.Scene();
  16. this.defaultMaterial = new THREE.MeshPhongMaterial();
  17. this.defaultMaterial.name = 'Default Material';
  18. this.addMaterial( this.defaultMaterial );
  19. }
  20. Editor.prototype = {
  21. // Assets
  22. setScene: function( scene ) {
  23. this.deleteAll(); // WARNING! deletes everything
  24. if ( scene ) {
  25. this.scene.name = scene.name ? scene.name : 'Scene';
  26. this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );
  27. if ( scene.children.length ) this.addObject( scene.children );
  28. }
  29. signals.sceneChanged.dispatch( this.scene );
  30. return this.scene
  31. },
  32. createObject: function( type, parameters, material ) {
  33. this.objectsCount ++;
  34. type = type ? type.toLowerCase() : null;
  35. var object;
  36. var geometry;
  37. material = material ? material : this.defaultMaterial;
  38. parameters = parameters ? parameters : {};
  39. var color = parameters.color ? parameters.color : null;
  40. var groundColor = parameters.groundColor ? parameters.groundColor : null;
  41. var intensity = parameters.intensity ? parameters.intensity : null;
  42. var distance = parameters.distance ? parameters.distance : null;
  43. var angle = parameters.angle ? parameters.angle : null;
  44. var exponent = parameters.exponent ? parameters.exponent : null;
  45. if ( !type ) {
  46. object = new THREE.Object3D();
  47. object.name = parameters.name ? parameters.name : 'Group ' + this.objectsCount;
  48. } else if ( type == 'plane' ) {
  49. geometry = this.createGeometry( type, parameters );
  50. object = new THREE.Mesh( geometry, this.defaultMaterial );
  51. object.name = name ? name : type + this.objectsCount;
  52. object.rotation.x = - Math.PI/2;
  53. } else if ( type == 'cube' ) {
  54. geometry = this.createGeometry( type, parameters );
  55. object = new THREE.Mesh( geometry, this.defaultMaterial );
  56. object.name = name ? name : type + this.objectsCount;
  57. } else if ( type == 'cylinder' ) {
  58. geometry = this.createGeometry( type, parameters );
  59. object = new THREE.Mesh( geometry, this.defaultMaterial );
  60. object.name = name ? name : type + this.objectsCount;
  61. } else if ( type == 'sphere' ) {
  62. geometry = this.createGeometry( type, parameters );
  63. object = new THREE.Mesh( geometry, this.defaultMaterial );
  64. object.name = name ? name : type + this.objectsCount;
  65. } else if ( type == 'icosahedron' ) {
  66. geometry = this.createGeometry( type, parameters );
  67. object = new THREE.Mesh( geometry, this.defaultMaterial );
  68. object.name = name ? name : type + this.objectsCount;
  69. } else if ( type == 'torus' ) {
  70. geometry = this.createGeometry( type, parameters );
  71. object = new THREE.Mesh( geometry, this.defaultMaterial );
  72. object.name = name ? name : type + this.objectsCount;
  73. } else if ( type == 'torusknot' ) {
  74. geometry = this.createGeometry( type, parameters );
  75. object = new THREE.Mesh( geometry, this.defaultMaterial );
  76. object.name = name ? name : type + this.objectsCount;
  77. } else if ( type == 'pointlight' ) {
  78. color = color ? color : 0xffffff;
  79. intensity = intensity ? intensity : 1;
  80. distance = distance ? distance : 0;
  81. var object = new THREE.PointLight( color, intensity, distance );
  82. object.name = name ? name : 'PointLight ' + this.objectsCount;
  83. } else if ( type == 'spotlight' ) {
  84. color = color ? color : 0xffffff;
  85. intensity = intensity ? intensity : 1;
  86. distance = distance ? distance : 0;
  87. angle = angle ? angle : Math.PI * 0.1;
  88. exponent = exponent ? exponent : 10;
  89. var object = new THREE.SpotLight( color, intensity, distance, angle, exponent );
  90. object.name = name ? name : 'SpotLight ' + this.objectsCount;
  91. object.target.name = object.name + ' Target';
  92. object.position.set( 0, 1, 0 ).multiplyScalar( 200 );
  93. } else if ( type == 'directionallight' ) {
  94. color = color ? color : 0xffffff;
  95. intensity = intensity ? intensity : 1;
  96. var object = new THREE.DirectionalLight( color, intensity );
  97. object.name = name ? name : 'DirectionalLight ' + this.objectsCount;
  98. object.target.name = object.name + ' Target';
  99. object.position.set( 1, 1, 1 ).multiplyScalar( 200 );
  100. } else if ( type == 'hemispherelight' ) {
  101. color = color ? color : 0x00aaff;
  102. groundColor = groundColor ? groundColor : 0xffaa00;
  103. intensity = intensity ? intensity : 1;
  104. var object = new THREE.HemisphereLight( color, groundColor, intensity );
  105. object.name = name ? name : 'HemisphereLight ' + this.objectsCount;
  106. object.position.set( 1, 1, 1 ).multiplyScalar( 200 );
  107. } else if ( type == 'ambientlight' ) {
  108. color = color ? color : 0x222222;
  109. var object = new THREE.AmbientLight( color );
  110. object.name = name ? name : 'AmbientLight ' + this.objectsCount;
  111. }
  112. if ( object ) this.addObject( object );
  113. return object;
  114. },
  115. createGeometry: function( type, parameters ) {
  116. this.geometriesCount ++;
  117. type = type ? type : null;
  118. parameters = parameters ? parameters : {};
  119. var name = parameters.name ? parameters.name : type + 'Geometry ' + this.geometriesCount;
  120. var width = parameters.width ? parameters.width : null;
  121. var height = parameters.height ? parameters.height : null;
  122. var depth = parameters.depth ? parameters.depth : null;
  123. var widthSegments = parameters.widthSegments ? parameters.widthSegments : null;
  124. var heightSegments = parameters.heightSegments ? parameters.heightSegments : null;
  125. var depthSegments = parameters.depthSegments ? parameters.depthSegments : null;
  126. var radialSegments = parameters.radialSegments ? parameters.radialSegments : null;
  127. var tubularSegments = parameters.tubularSegments ? parameters.tubularSegments : null;
  128. var radius = parameters.radius ? parameters.radius : null;
  129. var radiusTop = parameters.radiusTop ? parameters.radiusTop : null;
  130. var radiusBottom = parameters.radiusBottom ? parameters.radiusBottom : null;
  131. var phiStart = parameters.phiStart ? parameters.phiStart : null;
  132. var phiLength = parameters.phiLength ? parameters.phiLength : null;
  133. var thetaStart = parameters.thetaStart ? parameters.thetaStart : null;
  134. var thetaLength = parameters.thetaLength ? parameters.thetaLength : null;
  135. var tube = parameters.tube ? parameters.tube : null;
  136. var arc = parameters.arc ? parameters.arc : null;
  137. var detail = parameters.detail ? parameters.detail : null;
  138. var p = parameters.p ? parameters.p : null;
  139. var q = parameters.q ? parameters.q : null;
  140. var heightScale = parameters.heightScale ? parameters.heightScale : null;
  141. var openEnded = parameters.openEnded ? parameters.openEnded : false;
  142. var geometry;
  143. if ( !type ) {
  144. geometry = new THREE.Geometry();
  145. } else if ( type == 'plane' ) {
  146. width = width ? width : 200;
  147. height = height ? height : 200;
  148. widthSegments = widthSegments ? widthSegments : 1;
  149. heightSegments = heightSegments ? heightSegments : 1;
  150. geometry = new THREE.PlaneGeometry( width, height, widthSegments, heightSegments );
  151. } else if ( type == 'cube' ) {
  152. width = width ? width : 100;
  153. height = height ? height : 100;
  154. depth = depth ? depth : 100;
  155. widthSegments = widthSegments ? widthSegments : 1;
  156. heightSegments = heightSegments ? heightSegments : 1;
  157. depthSegments = depthSegments ? depthSegments : 1;
  158. geometry = new THREE.CubeGeometry( width, height, depth, widthSegments, heightSegments, depthSegments );
  159. } else if ( type == 'cylinder' ) {
  160. radiusTop = radiusTop ? radiusTop : 20;
  161. radiusBottom = radiusBottom ? radiusBottom : 20;
  162. height = height ? height : 100;
  163. radialSegments = radialSegments ? radialSegments : 8;
  164. heightSegments = heightSegments ? heightSegments : 1;
  165. openEnded = openEnded ? openEnded : false;
  166. geometry = new THREE.CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded );
  167. } else if ( type == 'sphere' ) {
  168. radius = radius ? radius : 75;
  169. widthSegments = widthSegments ? widthSegments : 32;
  170. heightSegments = heightSegments ? heightSegments : 16;
  171. widthSegments = widthSegments ? widthSegments : 32;
  172. heightSegments = heightSegments ? heightSegments : 16;
  173. phiStart = phiStart ? phiStart : 0;
  174. phiLength = phiLength ? phiLength : Math.PI * 2;
  175. thetaStart = thetaStart ? thetaStart : 0;
  176. thetaLength = thetaLength ? thetaLength : Math.PI;
  177. geometry = new THREE.SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength );
  178. } else if ( type == 'icosahedron' ) {
  179. radius = radius ? radius : 75;
  180. detail = detail ? detail : 2;
  181. geometry = new THREE.IcosahedronGeometry ( radius, detail );
  182. } else if ( type == 'torus' ) {
  183. radius = radius ? radius : 100;
  184. tube = tube ? tube : 40;
  185. radialSegments = radialSegments ? radialSegments : 8;
  186. tubularSegments = tubularSegments ? tubularSegments : 6;
  187. arc = arc ? arc : Math.PI * 2;
  188. geometry = new THREE.TorusGeometry( radius, tube, radialSegments, tubularSegments, arc );
  189. } else if ( type == 'torusknot' ) {
  190. radius = radius ? radius : 100;
  191. tube = tube ? tube : 40;
  192. radialSegments = radialSegments ? radialSegments : 64;
  193. tubularSegments = tubularSegments ? tubularSegments : 8;
  194. p = p ? p : 2;
  195. q = q ? q : 3;
  196. heightScale = heightScale ? heightScale : 1;
  197. geometry = new THREE.TorusKnotGeometry( radius, tube, radialSegments, tubularSegments, p, q, heightScale );
  198. }
  199. geometry.name = name;
  200. geometry.computeBoundingSphere();
  201. return geometry;
  202. },
  203. createMaterial: function( type, parameters ) {
  204. this.materialsCount ++;
  205. type = type ? type.toLowerCase() : 'phong';
  206. parameters = parameters ? parameters : {};
  207. var material;
  208. var name = parameters.name ? parameters.name : null;
  209. if ( type == 'phong' ) {
  210. material = new THREE.MeshPhongMaterial( parameters );
  211. material.name = name ? name : 'Phong Material ' + this.materialsCount;
  212. } else if ( type == 'lambert' ) {
  213. material = new THREE.MeshLambertMaterial( parameters );
  214. material.name = name ? name : 'Lambert Material ' + this.materialsCount;
  215. } else if ( type == 'normal' ) {
  216. material = new THREE.MeshNormalMaterial( parameters );
  217. material.name = name ? name : 'Normal Material ' + this.materialsCount;
  218. } else if ( type == 'basic' ) {
  219. material = new THREE.MeshBasicMaterial( parameters );
  220. material.name = name ? name : 'Basic Material ' + this.materialsCount;
  221. }
  222. if ( material ) this.addMaterial( material );
  223. return material;
  224. },
  225. createTexture: function( image, parameters ) {
  226. this.texturesCount ++;
  227. image = image ? image : '../examples/textures/ash_uvgrid01.jpg';
  228. parameters = parameters ? parameters : {};
  229. // TODO: implement parameters
  230. var texture = THREE.ImageUtils.loadTexture( image );
  231. texture.name = parameters.name ? parameters.name : 'Texture ' + this.texturesCount;
  232. this.addTexture( texture );
  233. return texture;
  234. },
  235. addObject: function( list, parent ) {
  236. list = ( list instanceof Array ) ? [].concat( list ) : [ list ];
  237. parent = parent ? parent : this.scene;
  238. for ( var i in list ) {
  239. if ( !list[ i ].uuid ) list[ i ].uuid = this.uuid();
  240. this.objects[ list[ i ].uuid ] = list[ i ];
  241. this.addHelper( list[ i ] );
  242. if ( list[ i ].target ) {
  243. if ( !list[ i ].target.uuid ) list[ i ].target.uuid = this.uuid();
  244. this.objects[ list[ i ].target.uuid ] = list[ i ].target;
  245. }
  246. if ( list[ i ].material ) this.addMaterial( list[ i ].material );
  247. if ( list[ i ].geometry ) this.addGeometry( list[ i ].geometry );
  248. if ( parent != list[ i ] ) {
  249. // Add object to the scene
  250. parent.add( list[ i ] );
  251. if ( list[ i ] instanceof THREE.Light ) this.updateMaterials();
  252. signals.objectAdded.dispatch( list[ i ] );
  253. // Continue adding children
  254. if ( list[ i ].children && list[ i ].children.length ) {
  255. this.addObject( list[ i ].children, list[ i ] );
  256. }
  257. }
  258. }
  259. signals.sceneChanged.dispatch( this.scene );
  260. },
  261. addHelper: function( object ) {
  262. if ( object instanceof THREE.PointLight ) {
  263. this.helpers[ object.uuid ] = new THREE.PointLightHelper( object, 10 );
  264. this.sceneHelpers.add( this.helpers[ object.uuid ] );
  265. this.helpers[ object.uuid ].lightSphere.uuid = object.uuid;
  266. } else if ( object instanceof THREE.DirectionalLight ) {
  267. this.helpers[ object.uuid ] = new THREE.DirectionalLightHelper( object, 10 );
  268. this.sceneHelpers.add( this.helpers[ object.uuid ] );
  269. this.helpers[ object.uuid ].lightSphere.uuid = object.uuid;
  270. } else if ( object instanceof THREE.SpotLight ) {
  271. this.helpers[ object.uuid ] = new THREE.SpotLightHelper( object, 10 );
  272. this.sceneHelpers.add( this.helpers[ object.uuid ] );
  273. this.helpers[ object.uuid ].lightSphere.uuid = object.uuid;
  274. } else if ( object instanceof THREE.HemisphereLight ) {
  275. this.helpers[ object.uuid ] = new THREE.HemisphereLightHelper( object, 10 );
  276. this.sceneHelpers.add( this.helpers[ object.uuid ] );
  277. this.helpers[ object.uuid ].lightSphere.uuid = object.uuid;
  278. }
  279. },
  280. deleteHelper: function( object ) {
  281. if ( this.helpers[ object.uuid ] ) {
  282. this.helpers[ object.uuid ].parent.remove( this.helpers[ object.uuid ] );
  283. delete this.helpers[ object.uuid ];
  284. }
  285. },
  286. addGeometry: function( geometry ) {
  287. if (!geometry.uuid) geometry.uuid = this.uuid();
  288. this.geometries[ geometry.uuid ] = geometry;
  289. signals.geometryAdded.dispatch( geometry );
  290. },
  291. addMaterial: function( material ) {
  292. if ( material.name == 'Default Material' ) {
  293. this.delete( this.defaultMaterial );
  294. this.defaultMaterial = material;
  295. }
  296. if (!material.uuid) material.uuid = this.uuid();
  297. this.materials[ material.uuid ] = material;
  298. signals.materialAdded.dispatch( material );
  299. },
  300. addTexture: function( texture ) {
  301. if (!texture.uuid) texture.uuid = this.uuid();
  302. this.textures[ texture.uuid ] = texture;
  303. signals.textureAdded.dispatch( texture );
  304. },
  305. // Selection
  306. select: function( list, additive ) {
  307. //TODO toggle
  308. list = ( list instanceof Array ) ? list : [ list ];
  309. if ( !additive ) this.selected = {};
  310. for ( var i in list ) {
  311. this.selected[ list[ i ].uuid ] = list[ i ];
  312. }
  313. signals.selected.dispatch( this.selected );
  314. },
  315. selectByUuid: function( uuid, additive ) {
  316. var list = this.list();
  317. if ( !additive ) this.selected = {};
  318. for ( var i in list ) {
  319. if ( list[ i ].uuid == uuid ) this.select( list[ i ], true );
  320. }
  321. },
  322. selectByName: function( name, type, additive ) {
  323. type = type ? type : "all";
  324. this.select( this.listByName( name, type ), additive );
  325. },
  326. selectAll: function( type, additive ) {
  327. type = type ? type : "all";
  328. this.select( this.listByName( '*', type ), additive );
  329. },
  330. deselect: function( list ) {
  331. list = ( list instanceof Array ) ? list : [ list ];
  332. for ( var i in list ) {
  333. if ( this.selected[ list[ i ].uuid ] ) delete this.selected[ list[ i ].uuid ];
  334. }
  335. signals.selected.dispatch( this.selected );
  336. },
  337. deselectByUuid: function( uuid ) {
  338. if ( this.selected[ uuid ] ) delete this.selected[ uuid ];
  339. },
  340. deselectByName: function( name, type ) {
  341. type = type ? type : "all";
  342. this.deselect( this.listByName( name, type ) );
  343. },
  344. deselectAll: function( type ) {
  345. type = type ? type : "all";
  346. this.deselect( this.list( "all" ) );
  347. },
  348. pickWalk: function( direction ) {
  349. direction = direction.toLowerCase();
  350. var selection = this.listSelected();
  351. var newSelection = [];
  352. if ( direction === 'up' ) {
  353. for ( var i in selection ) {
  354. if ( selection[ i ].parent )
  355. newSelection.push( selection[ i ].parent );
  356. else newSelection.push( selection[ i ] );
  357. }
  358. } else if ( direction === 'down' ) {
  359. for ( var i in selection ) {
  360. if ( selection[ i ].children && selection[ i ].children.length )
  361. newSelection.push( selection[ i ].children[0] );
  362. else newSelection.push( selection[ i ] );
  363. }
  364. } else if ( direction === 'left' || direction === 'right' ) {
  365. for ( var i in selection ) {
  366. var siblings = null;
  367. var index = null;
  368. var newIndex = null;
  369. if ( selection[ i ].parent ) {
  370. siblings = selection[ i ].parent.children;
  371. index = selection[ i ].parent.children.indexOf( selection[ i ] );
  372. newIndex = index;
  373. if ( siblings.length > 1 && direction === 'left' )
  374. newIndex = ( index + siblings.length + 1 ) % siblings.length;
  375. else if ( siblings.length > 1 && direction === 'right' )
  376. newIndex = ( index + siblings.length - 1 ) % siblings.length;
  377. newSelection.push( siblings[ newIndex ] );
  378. } else {
  379. newSelection.push( selection[ i ] );
  380. }
  381. }
  382. }
  383. if ( newSelection.length ) this.select( newSelection );
  384. },
  385. // List
  386. list: function( type ) {
  387. type = type ? type : "all";
  388. var list = this.listByName( '*', type );
  389. return list;
  390. },
  391. listSelected: function( type ) {
  392. var list = this.listByName( '*', 'selected' );
  393. if ( type ) {
  394. var typeList = this.listByName( '*', type );
  395. var list = list.filter(function(n) {
  396. if(typeList.indexOf(n) == -1) return false;
  397. return true;
  398. });
  399. }
  400. return list;
  401. },
  402. listByName: function( name, type ) {
  403. type = type ? type.toLowerCase() : "all";
  404. var scope = this;
  405. var list = [];
  406. function listFromMap( map, name ) {
  407. for ( var uuid in map ) {
  408. if ( scope.regexMatch( map[ uuid ].name, name ) ) {
  409. list.push( map[ uuid ] );
  410. }
  411. }
  412. }
  413. if ( type == 'all' || type == 'object' ) {
  414. listFromMap( this.objects, name );
  415. }
  416. if ( type == 'all' || type == 'geometry' ) {
  417. listFromMap( this.geometries, name );
  418. }
  419. if ( type == 'all' || type == 'material' ) {
  420. listFromMap( this.materials, name );
  421. }
  422. if ( type == 'all' || type == 'texture' ) {
  423. listFromMap( this.textures, name );
  424. }
  425. if ( type == 'all' || type == 'selected' ) {
  426. listFromMap( this.selected, name );
  427. }
  428. return list;
  429. },
  430. // Delete
  431. delete: function( list ) {
  432. list = list ? list : this.list( 'selected' );
  433. list = ( list instanceof Array ) ? list : [ list ];
  434. this.deselect( list );
  435. var deletedObjects = {};
  436. for ( var i in list ) {
  437. if ( this.objects[ list[ i ].uuid ] && list[ i ] != this.scene ) {
  438. delete this.objects[ list[ i ].uuid ];
  439. this.deleteHelper( list[ i ] );
  440. deletedObjects[ list[ i ].uuid ] = list[ i ];
  441. if ( list[ i ] instanceof THREE.Light ) this.updateMaterials();
  442. signals.objectDeleted.dispatch();
  443. if ( list[ i ].children.length ) this.delete( list[ i ].children );
  444. }
  445. if ( this.geometries[ list[ i ].uuid ] ) {
  446. delete this.geometries[ list[ i ].uuid ];
  447. signals.objectDeleted.dispatch();
  448. }
  449. if ( this.materials[ list[ i ].uuid ] ) {
  450. delete this.materials[ list[ i ].uuid ];
  451. signals.materialDeleted.dispatch();
  452. }
  453. if ( this.textures[ list[ i ].uuid ] ) {
  454. delete this.textures[ list[ i ].uuid ];
  455. signals.textureDeleted.dispatch();
  456. }
  457. }
  458. for ( var i in deletedObjects ) {
  459. if ( deletedObjects[ i ].parent ) {
  460. deletedObjects[ i ].parent.remove( deletedObjects[ i ] );
  461. }
  462. }
  463. delete deletedObjects;
  464. signals.sceneChanged.dispatch( this.scene );
  465. },
  466. deleteByName: function( name, type ) {
  467. type = type ? type : "all";
  468. this.delete( this.listByName( name, type ) );
  469. },
  470. deleteAll: function( type ) {
  471. type = type ? type : 'all';
  472. this.delete( this.listByName( '*', type ) );
  473. },
  474. deleteUnused: function( type ) {
  475. // TODO: test with textures
  476. type = type ? type.toLowerCase() : 'all';
  477. var used = {};
  478. this.scene.traverse( function( object ) {
  479. used[ object.uuid ] = object;
  480. if ( object.geometry ) used[ object.geometry.uuid ] = object.geometry;
  481. if ( object.material ) {
  482. used[ object.material.uuid ] = object.material;
  483. for ( var i in object.material ){
  484. if ( object.material[ i ] instanceof THREE.Texture ) {
  485. used[ object.material[ i ].uuid ] = object.material[ i ];
  486. }
  487. }
  488. }
  489. } );
  490. if ( !type || type == 'object' ) {
  491. for ( var uuid in this.objects ) {
  492. if ( !used[ uuid ] ) this.delete( this.objects[ uuid ] );
  493. }
  494. }
  495. if ( !type || type == 'geometry' ) {
  496. for ( var uuid in this.geometries ) {
  497. if ( !used[ uuid ] ) this.delete( this.geometries[ uuid ] );
  498. }
  499. }
  500. if ( !type || type == 'material' ) {
  501. for ( var uuid in this.materials ) {
  502. if ( !used[ uuid ] ) this.delete( this.materials[ uuid ] );
  503. }
  504. }
  505. if ( !type || type == 'texture' ) {
  506. for ( var uuid in this.textures ) {
  507. if ( !used[ uuid ] ) this.delete( this.textures[ uuid ] );
  508. }
  509. }
  510. delete used;
  511. },
  512. // Hierarchy
  513. clone: function( assets, recursive, deep ) {
  514. // TODO: consider using list
  515. // TODO: Implement non-recursive and deep
  516. var assets = assets ? assets : this.selected;
  517. // recursive = recursive ? recursive : true;
  518. // deep = deep ? deep : false;
  519. var clones = {};
  520. for ( var i in assets ){
  521. if ( this.objects[ i ] ) {
  522. var clonedObject = this.objects[assets[ i ].uuid ].clone();
  523. clonedObject.traverse( function( child ) {
  524. child.name += ' Clone';
  525. } );
  526. this.addObject( clonedObject, assets[ i ].parent );
  527. clones[ clonedObject.uuid ] = clonedObject;
  528. }
  529. }
  530. return clones;
  531. },
  532. parent: function( list, parent, locked ) {
  533. //TODO: implement locked
  534. list = list ? list : this.list( 'selected' );
  535. list = ( list instanceof Array ) ? list : [ list ];
  536. parent = parent ? parent : this.scene;
  537. for ( var i in list ) {
  538. if ( list[ i ] !== parent && list[ i ] !== this.scene ) {
  539. parent.add( list[ i ] );
  540. signals.objectChanged.dispatch( list[ i ] );
  541. }
  542. }
  543. signals.sceneChanged.dispatch( this.scene );
  544. },
  545. unparent: function( list ) {
  546. this.parent( list, this.scene );
  547. },
  548. group: function( list ) {
  549. list = list ? list : this.listSelected( 'objects' );
  550. list = ( list instanceof Array ) ? list : [ list ];
  551. var parent = ( list.length && list[0].parent ) ? list[0].parent : this.scene;
  552. var group = this.createObject();
  553. this.parent( group, parent );
  554. console.log(group);
  555. this.parent( list, group );
  556. },
  557. // Utils
  558. updateObject: function( object, parameters ) {
  559. parameters = parameters ? parameters : {};
  560. if ( parameters.parent && object.parent && object.parent != parameters.parent)
  561. editor.parent( object, parameters.parent );
  562. if ( parameters.geometry && object.geometry && object.geometry != parameters.geometry) {
  563. object.geometry = parameters.geometry;
  564. this.updateGeometry( object.geometry );
  565. }
  566. if ( parameters.material && object.material && object.material != parameters.material)
  567. object.material = parameters.material;
  568. if ( parameters.name !== undefined ) object.name = parameters.name;
  569. if ( parameters.position !== undefined ) object.position = parameters.position;
  570. if ( parameters.rotation !== undefined ) object.rotation = parameters.rotation;
  571. if ( parameters.scale !== undefined ) object.scale = parameters.scale;
  572. if ( object.fov !== undefined && parameters.fov !== undefined ) object.fov = parameters.fov;
  573. if ( object.near !== undefined && parameters.near !== undefined ) object.near = parameters.near;
  574. if ( object.far !== undefined && parameters.far !== undefined ) object.far = parameters.far;
  575. if ( object.intensity !== undefined && parameters.intensity !== undefined ) object.intensity = parameters.intensity;
  576. if ( object.color && parameters.color !== undefined ) object.color.setHex( parameters.color );
  577. if ( object.groundColor && parameters.groundColor !== undefined ) object.groundColor.setHex( parameters.groundColor );
  578. if ( object.distance !== undefined && parameters.distance !== undefined ) object.distance = parameters.distance;
  579. if ( object.angle !== undefined && parameters.angle !== undefined ) object.angle = parameters.angle;
  580. if ( object.exponent !== undefined && parameters.exponent !== undefined ) object.exponent = parameters.exponent;
  581. if ( object.visible !== undefined && parameters.visible !== undefined ) object.visible = parameters.visible;
  582. if ( parameters.userData !== undefined ) {
  583. try {
  584. object.userData = JSON.parse( parameters.userData );
  585. } catch ( error ) {
  586. console.log( error );
  587. }
  588. };
  589. if ( object.updateProjectionMatrix ) object.updateProjectionMatrix();
  590. signals.objectChanged.dispatch( object );
  591. },
  592. updateMaterials: function( list ) {
  593. list = list ? list : this.list( 'material' );
  594. list = ( list instanceof Array ) ? list : [ list ];
  595. for ( var i in list ) {
  596. list[ i ].needsUpdate = true;
  597. if ( list[ i ] instanceof THREE.MeshFaceMaterial ) {
  598. for ( var j in list[ i ].materials ) {
  599. list[ i ].materials[ j ].needsUpdate = true;
  600. }
  601. }
  602. }
  603. },
  604. updateGeometry: function( geometry, parameters ) {
  605. parameters = parameters ? parameters : {};
  606. var uuid = geometry.uuid;
  607. var name = geometry.name;
  608. if ( geometry instanceof THREE.PlaneGeometry )
  609. geometry = this.createGeometry( 'plane', parameters );
  610. if ( geometry instanceof THREE.CubeGeometry )
  611. geometry = this.createGeometry( 'cube', parameters );
  612. if ( geometry instanceof THREE.CylinderGeometry )
  613. geometry = this.createGeometry( 'cylinder', parameters );
  614. if ( geometry instanceof THREE.SphereGeometry )
  615. geometry = this.createGeometry( 'sphere', parameters );
  616. if ( geometry instanceof THREE.IcosahedronGeometry )
  617. geometry = this.createGeometry( 'icosahedron', parameters );
  618. if ( geometry instanceof THREE.TorusGeometry )
  619. geometry = this.createGeometry( 'torus', parameters );
  620. if ( geometry instanceof THREE.TorusKnotGeometry )
  621. geometry = this.createGeometry( 'torusknot', parameters );
  622. geometry.computeBoundingSphere();
  623. geometry.uuid = uuid;
  624. geometry.name = name;
  625. for ( var i in editor.objects ) {
  626. var object = editor.objects[i];
  627. if ( object.geometry && object.geometry.uuid == uuid ) {
  628. delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
  629. object.geometry.dispose();
  630. object.geometry = geometry;
  631. signals.objectChanged.dispatch( object );
  632. }
  633. }
  634. },
  635. setFog: function( parameters ) {
  636. var fogType = parameters.fogType ? parameters.fogType : null;
  637. var near = parameters.near ? parameters.near : null;
  638. var far = parameters.far ? parameters.far : null;
  639. var density = parameters.density ? parameters.density : null;
  640. var color = parameters.color ? parameters.color : null;
  641. if ( fogType ) {
  642. if ( fogType === "None" ) this.scene.fog = null;
  643. else if ( fogType === "Fog" ) this.scene.fog = new THREE.Fog();
  644. else if ( fogType === "FogExp2" ) this.scene.fog = new THREE.FogExp2();
  645. }
  646. if ( this.scene.fog ) {
  647. if ( fogType ) this.scene.fog.fogType = fogType;
  648. if ( near ) this.scene.fog.near = near;
  649. if ( far ) this.scene.fog.far = far;
  650. if ( density ) this.scene.fog.density = density;
  651. if ( color ) this.scene.fog.color.setHex( color );
  652. }
  653. this.updateMaterials();
  654. signals.fogChanged.dispatch( this.scene.fog );
  655. },
  656. regexMatch: function( name, filter ) {
  657. name = name.toLowerCase();
  658. filter = '^' + filter.toLowerCase().replace(/\*/g, '.*').replace(/\?/g, '.') + '$';
  659. var regex = new RegExp(filter);
  660. return regex.test( name );
  661. },
  662. uuid: function() {
  663. // http://note19.com/2007/05/27/javascript-guid-generator/
  664. function s4() {
  665. return Math.floor( ( 1 + Math.random() ) * 0x10000 ).toString( 16 ).substring( 1 );
  666. };
  667. return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
  668. }
  669. }