Menubar.File.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. Menubar.File = function ( editor ) {
  5. var NUMBER_PRECISION = 6;
  6. function parseNumber( key, value ) {
  7. return typeof value === 'number' ? parseFloat( value.toFixed( NUMBER_PRECISION ) ) : value;
  8. }
  9. //
  10. var container = new UI.Panel();
  11. container.setClass( 'menu' );
  12. var title = new UI.Panel();
  13. title.setClass( 'title' );
  14. title.setTextContent( 'File' );
  15. container.add( title );
  16. var options = new UI.Panel();
  17. options.setClass( 'options' );
  18. container.add( options );
  19. // New
  20. var option = new UI.Row();
  21. option.setClass( 'option' );
  22. option.setTextContent( 'New' );
  23. option.onClick( function () {
  24. if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {
  25. editor.clear();
  26. }
  27. } );
  28. options.add( option );
  29. //
  30. options.add( new UI.HorizontalRule() );
  31. // Import
  32. var fileInput = document.createElement( 'input' );
  33. fileInput.type = 'file';
  34. fileInput.addEventListener( 'change', function ( event ) {
  35. editor.loader.loadFile( fileInput.files[ 0 ] );
  36. } );
  37. var option = new UI.Row();
  38. option.setClass( 'option' );
  39. option.setTextContent( 'Import' );
  40. option.onClick( function () {
  41. fileInput.click();
  42. } );
  43. options.add( option );
  44. //
  45. options.add( new UI.HorizontalRule() );
  46. // Export Geometry
  47. var option = new UI.Row();
  48. option.setClass( 'option' );
  49. option.setTextContent( 'Export Geometry' );
  50. option.onClick( function () {
  51. var object = editor.selected;
  52. if ( object === null ) {
  53. alert( 'No object selected.' );
  54. return;
  55. }
  56. var geometry = object.geometry;
  57. if ( geometry === undefined ) {
  58. alert( 'The selected object doesn\'t have geometry.' );
  59. return;
  60. }
  61. var output = geometry.toJSON();
  62. try {
  63. output = JSON.stringify( output, parseNumber, '\t' );
  64. output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
  65. } catch ( e ) {
  66. output = JSON.stringify( output );
  67. }
  68. saveString( output, 'geometry.json' );
  69. } );
  70. options.add( option );
  71. // Export Object
  72. var option = new UI.Row();
  73. option.setClass( 'option' );
  74. option.setTextContent( 'Export Object' );
  75. option.onClick( function () {
  76. var object = editor.selected;
  77. if ( object === null ) {
  78. alert( 'No object selected' );
  79. return;
  80. }
  81. var output = object.toJSON();
  82. try {
  83. output = JSON.stringify( output, parseNumber, '\t' );
  84. output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
  85. } catch ( e ) {
  86. output = JSON.stringify( output );
  87. }
  88. saveString( output, 'model.json' );
  89. } );
  90. options.add( option );
  91. // Export Scene
  92. var option = new UI.Row();
  93. option.setClass( 'option' );
  94. option.setTextContent( 'Export Scene' );
  95. option.onClick( function () {
  96. var output = editor.scene.toJSON();
  97. try {
  98. output = JSON.stringify( output, parseNumber, '\t' );
  99. output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
  100. } catch ( e ) {
  101. output = JSON.stringify( output );
  102. }
  103. saveString( output, 'scene.json' );
  104. } );
  105. options.add( option );
  106. //
  107. options.add( new UI.HorizontalRule() );
  108. // Export GLTF
  109. var option = new UI.Row();
  110. option.setClass( 'option' );
  111. option.setTextContent( 'Export GLTF' );
  112. option.onClick( function () {
  113. var exporter = new THREE.GLTFExporter();
  114. exporter.parse( editor.scene, function ( result ) {
  115. saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' );
  116. } );
  117. } );
  118. options.add( option );
  119. // Export OBJ
  120. var option = new UI.Row();
  121. option.setClass( 'option' );
  122. option.setTextContent( 'Export OBJ' );
  123. option.onClick( function () {
  124. var object = editor.selected;
  125. if ( object === null ) {
  126. alert( 'No object selected.' );
  127. return;
  128. }
  129. var exporter = new THREE.OBJExporter();
  130. saveString( exporter.parse( object ), 'model.obj' );
  131. } );
  132. options.add( option );
  133. // Export STL
  134. var option = new UI.Row();
  135. option.setClass( 'option' );
  136. option.setTextContent( 'Export STL' );
  137. option.onClick( function () {
  138. var exporter = new THREE.STLExporter();
  139. saveString( exporter.parse( editor.scene ), 'model.stl' );
  140. } );
  141. options.add( option );
  142. //
  143. options.add( new UI.HorizontalRule() );
  144. // Publish
  145. var option = new UI.Row();
  146. option.setClass( 'option' );
  147. option.setTextContent( 'Publish' );
  148. option.onClick( function () {
  149. var zip = new JSZip();
  150. //
  151. var output = editor.toJSON();
  152. output.metadata.type = 'App';
  153. delete output.history;
  154. var vr = output.project.vr;
  155. output = JSON.stringify( output, parseNumber, '\t' );
  156. output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
  157. zip.file( 'app.json', output );
  158. //
  159. var manager = new THREE.LoadingManager( function () {
  160. save( zip.generate( { type: 'blob' } ), 'download.zip' );
  161. } );
  162. var loader = new THREE.FileLoader( manager );
  163. loader.load( 'js/libs/app/index.html', function ( content ) {
  164. var includes = [];
  165. if ( vr ) {
  166. includes.push( '<script src="js/WebVR.js"></script>' );
  167. }
  168. content = content.replace( '<!-- includes -->', includes.join( '\n\t\t' ) );
  169. zip.file( 'index.html', content );
  170. } );
  171. loader.load( 'js/libs/app.js', function ( content ) {
  172. zip.file( 'js/app.js', content );
  173. } );
  174. loader.load( '../build/three.min.js', function ( content ) {
  175. zip.file( 'js/three.min.js', content );
  176. } );
  177. if ( vr ) {
  178. loader.load( '../examples/js/vr/WebVR.js', function ( content ) {
  179. zip.file( 'js/WebVR.js', content );
  180. } );
  181. }
  182. } );
  183. options.add( option );
  184. /*
  185. // Publish (Dropbox)
  186. var option = new UI.Row();
  187. option.setClass( 'option' );
  188. option.setTextContent( 'Publish (Dropbox)' );
  189. option.onClick( function () {
  190. var parameters = {
  191. files: [
  192. { 'url': 'data:text/plain;base64,' + window.btoa( "Hello, World" ), 'filename': 'app/test.txt' }
  193. ]
  194. };
  195. Dropbox.save( parameters );
  196. } );
  197. options.add( option );
  198. */
  199. //
  200. var link = document.createElement( 'a' );
  201. link.style.display = 'none';
  202. document.body.appendChild( link ); // Firefox workaround, see #6594
  203. function save( blob, filename ) {
  204. link.href = URL.createObjectURL( blob );
  205. link.download = filename || 'data.json';
  206. link.click();
  207. // URL.revokeObjectURL( url ); breaks Firefox...
  208. }
  209. function saveString( text, filename ) {
  210. save( new Blob( [ text ], { type: 'text/plain' } ), filename );
  211. }
  212. return container;
  213. };