Menubar.File.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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. // Export OBJ
  107. var option = new UI.Row();
  108. option.setClass( 'option' );
  109. option.setTextContent( 'Export OBJ' );
  110. option.onClick( function () {
  111. var object = editor.selected;
  112. if ( object === null ) {
  113. alert( 'No object selected.' );
  114. return;
  115. }
  116. var exporter = new THREE.OBJExporter();
  117. saveString( exporter.parse( object ), 'model.obj' );
  118. } );
  119. options.add( option );
  120. // Export STL
  121. var option = new UI.Row();
  122. option.setClass( 'option' );
  123. option.setTextContent( 'Export STL' );
  124. option.onClick( function () {
  125. var exporter = new THREE.STLExporter();
  126. saveString( exporter.parse( editor.scene ), 'model.stl' );
  127. } );
  128. options.add( option );
  129. //
  130. options.add( new UI.HorizontalRule() );
  131. // Publish
  132. var option = new UI.Row();
  133. option.setClass( 'option' );
  134. option.setTextContent( 'Publish' );
  135. option.onClick( function () {
  136. var zip = new JSZip();
  137. //
  138. var output = editor.toJSON();
  139. output.metadata.type = 'App';
  140. delete output.history;
  141. var vr = output.project.vr;
  142. output = JSON.stringify( output, parseNumber, '\t' );
  143. output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
  144. zip.file( 'app.json', output );
  145. //
  146. var manager = new THREE.LoadingManager( function () {
  147. save( zip.generate( { type: 'blob' } ), 'download.zip' );
  148. } );
  149. var loader = new THREE.FileLoader( manager );
  150. loader.load( 'js/libs/app/index.html', function ( content ) {
  151. var includes = [];
  152. if ( vr ) {
  153. includes.push( '<script src="js/VRControls.js"></script>' );
  154. includes.push( '<script src="js/VREffect.js"></script>' );
  155. includes.push( '<script src="js/WebVR.js"></script>' );
  156. }
  157. content = content.replace( '<!-- includes -->', includes.join( '\n\t\t' ) );
  158. zip.file( 'index.html', content );
  159. } );
  160. loader.load( 'js/libs/app.js', function ( content ) {
  161. zip.file( 'js/app.js', content );
  162. } );
  163. loader.load( '../build/three.min.js', function ( content ) {
  164. zip.file( 'js/three.min.js', content );
  165. } );
  166. if ( vr ) {
  167. loader.load( '../examples/js/controls/VRControls.js', function ( content ) {
  168. zip.file( 'js/VRControls.js', content );
  169. } );
  170. loader.load( '../examples/js/effects/VREffect.js', function ( content ) {
  171. zip.file( 'js/VREffect.js', content );
  172. } );
  173. loader.load( '../examples/js/WebVR.js', function ( content ) {
  174. zip.file( 'js/WebVR.js', content );
  175. } );
  176. }
  177. } );
  178. options.add( option );
  179. /*
  180. // Publish (Dropbox)
  181. var option = new UI.Row();
  182. option.setClass( 'option' );
  183. option.setTextContent( 'Publish (Dropbox)' );
  184. option.onClick( function () {
  185. var parameters = {
  186. files: [
  187. { 'url': 'data:text/plain;base64,' + window.btoa( "Hello, World" ), 'filename': 'app/test.txt' }
  188. ]
  189. };
  190. Dropbox.save( parameters );
  191. } );
  192. options.add( option );
  193. */
  194. //
  195. var link = document.createElement( 'a' );
  196. link.style.display = 'none';
  197. document.body.appendChild( link ); // Firefox workaround, see #6594
  198. function save( blob, filename ) {
  199. link.href = URL.createObjectURL( blob );
  200. link.download = filename || 'data.json';
  201. link.click();
  202. // URL.revokeObjectURL( url ); breaks Firefox...
  203. }
  204. function saveString( text, filename ) {
  205. save( new Blob( [ text ], { type: 'text/plain' } ), filename );
  206. }
  207. return container;
  208. };