Editor.js 28 KB

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