spoint 0.1.0 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +134 -209
  2. package/SKILL.md +95 -0
  3. package/apps/environment/index.js +200 -1
  4. package/apps/environment/models/decorative/.gitkeep +0 -0
  5. package/apps/environment/models/hazards/.gitkeep +0 -0
  6. package/apps/environment/models/interactive/.gitkeep +0 -0
  7. package/apps/environment/models/structures/.gitkeep +0 -0
  8. package/apps/environment/smartObjects.js +114 -0
  9. package/apps/interactable/index.js +155 -0
  10. package/apps/physics-crate/index.js +15 -9
  11. package/apps/power-crate/index.js +18 -12
  12. package/apps/tps-game/$GDUPI.vrm +0 -0
  13. package/apps/tps-game/Cleetus.vrm +0 -0
  14. package/apps/tps-game/index.js +185 -27
  15. package/apps/world/index.js +68 -22
  16. package/bin/create-app.js +337 -0
  17. package/client/ARControls.js +301 -0
  18. package/client/LoadingManager.js +117 -0
  19. package/client/MobileControls.js +1122 -0
  20. package/client/anim-lib.glb +0 -0
  21. package/client/animation.js +306 -0
  22. package/client/app.js +1341 -65
  23. package/client/camera.js +191 -33
  24. package/client/createLoadingScreen.js +69 -0
  25. package/client/editor/bridge.js +113 -0
  26. package/client/editor/css/main.css +794 -0
  27. package/client/editor/images/rotate.svg +4 -0
  28. package/client/editor/images/scale.svg +4 -0
  29. package/client/editor/images/translate.svg +4 -0
  30. package/client/editor/index.html +103 -0
  31. package/client/editor/js/Command.js +41 -0
  32. package/client/editor/js/Config.js +81 -0
  33. package/client/editor/js/Editor.js +785 -0
  34. package/client/editor/js/EditorControls.js +438 -0
  35. package/client/editor/js/History.js +321 -0
  36. package/client/editor/js/Loader.js +987 -0
  37. package/client/editor/js/LoaderUtils.js +90 -0
  38. package/client/editor/js/Menubar.Add.js +510 -0
  39. package/client/editor/js/Menubar.Edit.js +145 -0
  40. package/client/editor/js/Menubar.File.js +466 -0
  41. package/client/editor/js/Menubar.Help.js +73 -0
  42. package/client/editor/js/Menubar.Status.js +51 -0
  43. package/client/editor/js/Menubar.View.js +183 -0
  44. package/client/editor/js/Menubar.js +27 -0
  45. package/client/editor/js/Player.js +53 -0
  46. package/client/editor/js/Resizer.js +58 -0
  47. package/client/editor/js/Script.js +503 -0
  48. package/client/editor/js/Selector.js +102 -0
  49. package/client/editor/js/Sidebar.Geometry.BoxGeometry.js +121 -0
  50. package/client/editor/js/Sidebar.Geometry.BufferGeometry.js +115 -0
  51. package/client/editor/js/Sidebar.Geometry.CapsuleGeometry.js +97 -0
  52. package/client/editor/js/Sidebar.Geometry.CircleGeometry.js +97 -0
  53. package/client/editor/js/Sidebar.Geometry.CylinderGeometry.js +121 -0
  54. package/client/editor/js/Sidebar.Geometry.DodecahedronGeometry.js +73 -0
  55. package/client/editor/js/Sidebar.Geometry.ExtrudeGeometry.js +196 -0
  56. package/client/editor/js/Sidebar.Geometry.IcosahedronGeometry.js +73 -0
  57. package/client/editor/js/Sidebar.Geometry.LatheGeometry.js +98 -0
  58. package/client/editor/js/Sidebar.Geometry.Modifiers.js +73 -0
  59. package/client/editor/js/Sidebar.Geometry.OctahedronGeometry.js +74 -0
  60. package/client/editor/js/Sidebar.Geometry.PlaneGeometry.js +97 -0
  61. package/client/editor/js/Sidebar.Geometry.RingGeometry.js +121 -0
  62. package/client/editor/js/Sidebar.Geometry.ShapeGeometry.js +76 -0
  63. package/client/editor/js/Sidebar.Geometry.SphereGeometry.js +133 -0
  64. package/client/editor/js/Sidebar.Geometry.TetrahedronGeometry.js +74 -0
  65. package/client/editor/js/Sidebar.Geometry.TorusGeometry.js +109 -0
  66. package/client/editor/js/Sidebar.Geometry.TorusKnotGeometry.js +121 -0
  67. package/client/editor/js/Sidebar.Geometry.TubeGeometry.js +135 -0
  68. package/client/editor/js/Sidebar.Geometry.js +332 -0
  69. package/client/editor/js/Sidebar.Material.BooleanProperty.js +60 -0
  70. package/client/editor/js/Sidebar.Material.ColorProperty.js +87 -0
  71. package/client/editor/js/Sidebar.Material.ConstantProperty.js +62 -0
  72. package/client/editor/js/Sidebar.Material.MapProperty.js +249 -0
  73. package/client/editor/js/Sidebar.Material.NumberProperty.js +60 -0
  74. package/client/editor/js/Sidebar.Material.Program.js +73 -0
  75. package/client/editor/js/Sidebar.Material.RangeValueProperty.js +63 -0
  76. package/client/editor/js/Sidebar.Material.js +751 -0
  77. package/client/editor/js/Sidebar.Object.Animation.js +102 -0
  78. package/client/editor/js/Sidebar.Object.js +898 -0
  79. package/client/editor/js/Sidebar.Project.App.js +165 -0
  80. package/client/editor/js/Sidebar.Project.Image.js +225 -0
  81. package/client/editor/js/Sidebar.Project.Materials.js +82 -0
  82. package/client/editor/js/Sidebar.Project.Renderer.js +144 -0
  83. package/client/editor/js/Sidebar.Project.Video.js +242 -0
  84. package/client/editor/js/Sidebar.Project.js +31 -0
  85. package/client/editor/js/Sidebar.Properties.js +73 -0
  86. package/client/editor/js/Sidebar.Scene.js +585 -0
  87. package/client/editor/js/Sidebar.Script.js +129 -0
  88. package/client/editor/js/Sidebar.Settings.History.js +146 -0
  89. package/client/editor/js/Sidebar.Settings.Shortcuts.js +175 -0
  90. package/client/editor/js/Sidebar.Settings.js +60 -0
  91. package/client/editor/js/Sidebar.js +41 -0
  92. package/client/editor/js/Storage.js +98 -0
  93. package/client/editor/js/Strings.js +2028 -0
  94. package/client/editor/js/Toolbar.js +84 -0
  95. package/client/editor/js/Viewport.Controls.js +92 -0
  96. package/client/editor/js/Viewport.Info.js +136 -0
  97. package/client/editor/js/Viewport.Pathtracer.js +91 -0
  98. package/client/editor/js/Viewport.ViewHelper.js +39 -0
  99. package/client/editor/js/Viewport.XR.js +222 -0
  100. package/client/editor/js/Viewport.js +900 -0
  101. package/client/editor/js/commands/AddObjectCommand.js +68 -0
  102. package/client/editor/js/commands/AddScriptCommand.js +75 -0
  103. package/client/editor/js/commands/Commands.js +23 -0
  104. package/client/editor/js/commands/MoveObjectCommand.js +111 -0
  105. package/client/editor/js/commands/MultiCmdsCommand.js +85 -0
  106. package/client/editor/js/commands/RemoveObjectCommand.js +88 -0
  107. package/client/editor/js/commands/RemoveScriptCommand.js +81 -0
  108. package/client/editor/js/commands/SetColorCommand.js +73 -0
  109. package/client/editor/js/commands/SetGeometryCommand.js +87 -0
  110. package/client/editor/js/commands/SetGeometryValueCommand.js +70 -0
  111. package/client/editor/js/commands/SetMaterialColorCommand.js +86 -0
  112. package/client/editor/js/commands/SetMaterialCommand.js +79 -0
  113. package/client/editor/js/commands/SetMaterialMapCommand.js +143 -0
  114. package/client/editor/js/commands/SetMaterialRangeCommand.js +91 -0
  115. package/client/editor/js/commands/SetMaterialValueCommand.js +90 -0
  116. package/client/editor/js/commands/SetMaterialVectorCommand.js +79 -0
  117. package/client/editor/js/commands/SetPositionCommand.js +84 -0
  118. package/client/editor/js/commands/SetRotationCommand.js +84 -0
  119. package/client/editor/js/commands/SetScaleCommand.js +84 -0
  120. package/client/editor/js/commands/SetSceneCommand.js +103 -0
  121. package/client/editor/js/commands/SetScriptValueCommand.js +80 -0
  122. package/client/editor/js/commands/SetShadowValueCommand.js +73 -0
  123. package/client/editor/js/commands/SetUuidCommand.js +70 -0
  124. package/client/editor/js/commands/SetValueCommand.js +75 -0
  125. package/client/editor/js/libs/acorn/acorn.js +3236 -0
  126. package/client/editor/js/libs/acorn/acorn_loose.js +1299 -0
  127. package/client/editor/js/libs/acorn/walk.js +344 -0
  128. package/client/editor/js/libs/app/index.html +57 -0
  129. package/client/editor/js/libs/app.js +251 -0
  130. package/client/editor/js/libs/codemirror/addon/dialog.css +32 -0
  131. package/client/editor/js/libs/codemirror/addon/dialog.js +163 -0
  132. package/client/editor/js/libs/codemirror/addon/show-hint.css +36 -0
  133. package/client/editor/js/libs/codemirror/addon/show-hint.js +529 -0
  134. package/client/editor/js/libs/codemirror/addon/tern.css +87 -0
  135. package/client/editor/js/libs/codemirror/addon/tern.js +750 -0
  136. package/client/editor/js/libs/codemirror/codemirror.css +344 -0
  137. package/client/editor/js/libs/codemirror/codemirror.js +9849 -0
  138. package/client/editor/js/libs/codemirror/mode/glsl.js +233 -0
  139. package/client/editor/js/libs/codemirror/mode/javascript.js +959 -0
  140. package/client/editor/js/libs/codemirror/theme/monokai.css +41 -0
  141. package/client/editor/js/libs/esprima.js +6401 -0
  142. package/client/editor/js/libs/jsonlint.js +453 -0
  143. package/client/editor/js/libs/signals.min.js +14 -0
  144. package/client/editor/js/libs/tern-threejs/threejs.js +5031 -0
  145. package/client/editor/js/libs/ternjs/comment.js +87 -0
  146. package/client/editor/js/libs/ternjs/def.js +588 -0
  147. package/client/editor/js/libs/ternjs/doc_comment.js +401 -0
  148. package/client/editor/js/libs/ternjs/infer.js +1635 -0
  149. package/client/editor/js/libs/ternjs/polyfill.js +80 -0
  150. package/client/editor/js/libs/ternjs/signal.js +26 -0
  151. package/client/editor/js/libs/ternjs/tern.js +993 -0
  152. package/client/editor/js/libs/ui.js +1346 -0
  153. package/client/editor/js/libs/ui.three.js +855 -0
  154. package/client/facial-animation.js +455 -0
  155. package/client/index.html +7 -4
  156. package/client/loading.css +147 -0
  157. package/client/loading.html +25 -0
  158. package/client/style.css +251 -0
  159. package/package.json +7 -3
  160. package/server.js +9 -1
  161. package/src/apps/AppContext.js +1 -1
  162. package/src/apps/AppLoader.js +50 -37
  163. package/src/apps/AppRuntime.js +32 -8
  164. package/src/client/InputHandler.js +233 -0
  165. package/src/client/JitterBuffer.js +207 -0
  166. package/src/client/KalmanFilter.js +125 -0
  167. package/src/client/MessageHandler.js +101 -0
  168. package/src/client/PhysicsNetworkClient.js +141 -68
  169. package/src/client/ReconnectManager.js +62 -0
  170. package/src/client/SmoothInterpolation.js +127 -0
  171. package/src/client/SnapshotProcessor.js +144 -0
  172. package/src/connection/ConnectionManager.js +21 -3
  173. package/src/connection/SessionStore.js +13 -3
  174. package/src/index.client.js +4 -6
  175. package/src/netcode/EventLog.js +29 -15
  176. package/src/netcode/LagCompensator.js +25 -26
  177. package/src/netcode/NetworkState.js +4 -1
  178. package/src/netcode/PhysicsIntegration.js +20 -6
  179. package/src/netcode/PlayerManager.js +10 -2
  180. package/src/netcode/SnapshotEncoder.js +66 -19
  181. package/src/netcode/TickSystem.js +13 -4
  182. package/src/physics/World.js +66 -13
  183. package/src/protocol/msgpack.js +90 -63
  184. package/src/sdk/ReloadHandlers.js +12 -2
  185. package/src/sdk/ReloadManager.js +5 -0
  186. package/src/sdk/ServerHandlers.js +50 -11
  187. package/src/sdk/StaticHandler.js +22 -6
  188. package/src/sdk/TickHandler.js +101 -34
  189. package/src/sdk/scaffold.js +31 -0
  190. package/src/sdk/server.js +59 -33
  191. package/src/shared/movement.js +2 -1
  192. package/src/spatial/Octree.js +5 -0
  193. package/apps/interactive-door/index.js +0 -33
  194. package/apps/patrol-npc/index.js +0 -37
  195. package/src/connection/QualityMonitor.js +0 -46
  196. package/src/debug/StateInspector.js +0 -42
  197. package/src/index.js +0 -1
  198. package/src/index.server.js +0 -27
  199. package/src/protocol/Codec.js +0 -60
  200. package/src/protocol/SequenceTracker.js +0 -71
  201. package/src/sdk/ClientMessageHandler.js +0 -80
  202. package/src/sdk/client.js +0 -122
  203. package/world/kaira.glb +0 -0
  204. package/world/schwust.glb +0 -0
@@ -0,0 +1,145 @@
1
+ import { Box3, Vector3 } from 'three';
2
+
3
+ import { UIPanel, UIRow, UIHorizontalRule, UIText } from './libs/ui.js';
4
+
5
+ import { AddObjectCommand } from './commands/AddObjectCommand.js';
6
+ import { RemoveObjectCommand } from './commands/RemoveObjectCommand.js';
7
+ import { SetPositionCommand } from './commands/SetPositionCommand.js';
8
+ import { clone } from 'three/addons/utils/SkeletonUtils.js';
9
+
10
+ function MenubarEdit( editor ) {
11
+
12
+ const strings = editor.strings;
13
+
14
+ const container = new UIPanel();
15
+ container.setClass( 'menu' );
16
+
17
+ const title = new UIPanel();
18
+ title.setClass( 'title' );
19
+ title.setTextContent( strings.getKey( 'menubar/edit' ) );
20
+ container.add( title );
21
+
22
+ const options = new UIPanel();
23
+ options.setClass( 'options' );
24
+ container.add( options );
25
+
26
+ // Undo
27
+
28
+ const undo = new UIRow();
29
+ undo.setClass( 'option' );
30
+ undo.setTextContent( strings.getKey( 'menubar/edit/undo' ) );
31
+ undo.add( new UIText( 'CTRL+Z' ).setClass( 'key' ) );
32
+ undo.onClick( function () {
33
+
34
+ editor.undo();
35
+
36
+ } );
37
+ options.add( undo );
38
+
39
+ // Redo
40
+
41
+ const redo = new UIRow();
42
+ redo.setClass( 'option' );
43
+ redo.setTextContent( strings.getKey( 'menubar/edit/redo' ) );
44
+ redo.add( new UIText( 'CTRL+SHIFT+Z' ).setClass( 'key' ) );
45
+ redo.onClick( function () {
46
+
47
+ editor.redo();
48
+
49
+ } );
50
+ options.add( redo );
51
+
52
+ function onHistoryChanged() {
53
+
54
+ const history = editor.history;
55
+
56
+ undo.setClass( 'option' );
57
+ redo.setClass( 'option' );
58
+
59
+ if ( history.undos.length == 0 ) {
60
+
61
+ undo.setClass( 'inactive' );
62
+
63
+ }
64
+
65
+ if ( history.redos.length == 0 ) {
66
+
67
+ redo.setClass( 'inactive' );
68
+
69
+ }
70
+
71
+ }
72
+
73
+ editor.signals.historyChanged.add( onHistoryChanged );
74
+ onHistoryChanged();
75
+
76
+ // ---
77
+
78
+ options.add( new UIHorizontalRule() );
79
+
80
+ // Center
81
+
82
+ let option = new UIRow();
83
+ option.setClass( 'option' );
84
+ option.setTextContent( strings.getKey( 'menubar/edit/center' ) );
85
+ option.onClick( function () {
86
+
87
+ const object = editor.selected;
88
+
89
+ if ( object === null || object.parent === null ) return; // avoid centering the camera or scene
90
+
91
+ const aabb = new Box3().setFromObject( object );
92
+ const center = aabb.getCenter( new Vector3() );
93
+ const newPosition = new Vector3();
94
+
95
+ newPosition.x = object.position.x - center.x;
96
+ newPosition.y = object.position.y - center.y;
97
+ newPosition.z = object.position.z - center.z;
98
+
99
+ editor.execute( new SetPositionCommand( editor, object, newPosition ) );
100
+
101
+ } );
102
+ options.add( option );
103
+
104
+ // Clone
105
+
106
+ option = new UIRow();
107
+ option.setClass( 'option' );
108
+ option.setTextContent( strings.getKey( 'menubar/edit/clone' ) );
109
+ option.onClick( function () {
110
+
111
+ let object = editor.selected;
112
+
113
+ if ( object === null || object.parent === null ) return; // avoid cloning the camera or scene
114
+
115
+ object = clone( object );
116
+
117
+ editor.execute( new AddObjectCommand( editor, object ) );
118
+
119
+ } );
120
+ options.add( option );
121
+
122
+ // Delete
123
+
124
+ option = new UIRow();
125
+ option.setClass( 'option' );
126
+ option.setTextContent( strings.getKey( 'menubar/edit/delete' ) );
127
+ option.add( new UIText( 'DEL' ).setClass( 'key' ) );
128
+ option.onClick( function () {
129
+
130
+ const object = editor.selected;
131
+
132
+ if ( object !== null && object.parent !== null ) {
133
+
134
+ editor.execute( new RemoveObjectCommand( editor, object ) );
135
+
136
+ }
137
+
138
+ } );
139
+ options.add( option );
140
+
141
+ return container;
142
+
143
+ }
144
+
145
+ export { MenubarEdit };
@@ -0,0 +1,466 @@
1
+ import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';
2
+
3
+ function MenubarFile( editor ) {
4
+
5
+ const strings = editor.strings;
6
+
7
+ const saveArrayBuffer = editor.utils.saveArrayBuffer;
8
+ const saveString = editor.utils.saveString;
9
+
10
+ const container = new UIPanel();
11
+ container.setClass( 'menu' );
12
+
13
+ const title = new UIPanel();
14
+ title.setClass( 'title' );
15
+ title.setTextContent( strings.getKey( 'menubar/file' ) );
16
+ container.add( title );
17
+
18
+ const options = new UIPanel();
19
+ options.setClass( 'options' );
20
+ container.add( options );
21
+
22
+ // New Project
23
+
24
+ const newProjectSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/file/new' ) ).addClass( 'option' ).addClass( 'submenu-title' );
25
+ newProjectSubmenuTitle.onMouseOver( function () {
26
+
27
+ const { top, right } = this.dom.getBoundingClientRect();
28
+ const { paddingTop } = getComputedStyle( this.dom );
29
+ newProjectSubmenu.setLeft( right + 'px' );
30
+ newProjectSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
31
+ newProjectSubmenu.setDisplay( 'block' );
32
+
33
+ } );
34
+ newProjectSubmenuTitle.onMouseOut( function () {
35
+
36
+ newProjectSubmenu.setDisplay( 'none' );
37
+
38
+ } );
39
+ options.add( newProjectSubmenuTitle );
40
+
41
+ const newProjectSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
42
+ newProjectSubmenuTitle.add( newProjectSubmenu );
43
+
44
+ // New Project / Empty
45
+
46
+ let option = new UIRow().setTextContent( strings.getKey( 'menubar/file/new/empty' ) ).setClass( 'option' );
47
+ option.onClick( function () {
48
+
49
+ if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
50
+
51
+ editor.clear();
52
+
53
+ }
54
+
55
+ } );
56
+ newProjectSubmenu.add( option );
57
+
58
+ //
59
+
60
+ newProjectSubmenu.add( new UIHorizontalRule() );
61
+
62
+ // New Project / ...
63
+
64
+ const examples = [
65
+ { title: 'menubar/file/new/Arkanoid', file: 'arkanoid.app.json' },
66
+ { title: 'menubar/file/new/Camera', file: 'camera.app.json' },
67
+ { title: 'menubar/file/new/Particles', file: 'particles.app.json' },
68
+ { title: 'menubar/file/new/Pong', file: 'pong.app.json' },
69
+ { title: 'menubar/file/new/Shaders', file: 'shaders.app.json' }
70
+ ];
71
+
72
+ const loader = new THREE.FileLoader();
73
+
74
+ for ( let i = 0; i < examples.length; i ++ ) {
75
+
76
+ ( function ( i ) {
77
+
78
+ const example = examples[ i ];
79
+
80
+ const option = new UIRow();
81
+ option.setClass( 'option' );
82
+ option.setTextContent( strings.getKey( example.title ) );
83
+ option.onClick( function () {
84
+
85
+ if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
86
+
87
+ loader.load( 'examples/' + example.file, function ( text ) {
88
+
89
+ editor.clear();
90
+ editor.fromJSON( JSON.parse( text ) );
91
+
92
+ } );
93
+
94
+ }
95
+
96
+ } );
97
+ newProjectSubmenu.add( option );
98
+
99
+ } )( i );
100
+
101
+ }
102
+
103
+ // Open
104
+
105
+ const openProjectForm = document.createElement( 'form' );
106
+ openProjectForm.style.display = 'none';
107
+ document.body.appendChild( openProjectForm );
108
+
109
+ const openProjectInput = document.createElement( 'input' );
110
+ openProjectInput.multiple = false;
111
+ openProjectInput.type = 'file';
112
+ openProjectInput.accept = '.json';
113
+ openProjectInput.addEventListener( 'change', async function () {
114
+
115
+ const file = openProjectInput.files[ 0 ];
116
+
117
+ if ( file === undefined ) return;
118
+
119
+ try {
120
+
121
+ const json = JSON.parse( await file.text() );
122
+
123
+ async function onEditorCleared() {
124
+
125
+ await editor.fromJSON( json );
126
+
127
+ editor.signals.editorCleared.remove( onEditorCleared );
128
+
129
+ }
130
+
131
+ editor.signals.editorCleared.add( onEditorCleared );
132
+
133
+ editor.clear();
134
+
135
+ } catch ( e ) {
136
+
137
+ alert( strings.getKey( 'prompt/file/failedToOpenProject' ) );
138
+ console.error( e );
139
+
140
+ } finally {
141
+
142
+ form.reset();
143
+
144
+ }
145
+
146
+ } );
147
+
148
+ openProjectForm.appendChild( openProjectInput );
149
+
150
+ option = new UIRow()
151
+ .addClass( 'option' )
152
+ .setTextContent( strings.getKey( 'menubar/file/open' ) )
153
+ .onClick( function () {
154
+
155
+ if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
156
+
157
+ openProjectInput.click();
158
+
159
+ }
160
+
161
+ } );
162
+
163
+ options.add( option );
164
+
165
+ // Save
166
+
167
+ option = new UIRow()
168
+ .addClass( 'option' )
169
+ .setTextContent( strings.getKey( 'menubar/file/save' ) )
170
+ .onClick( function () {
171
+
172
+ const json = editor.toJSON();
173
+ const blob = new Blob( [ JSON.stringify( json ) ], { type: 'application/json' } );
174
+ editor.utils.save( blob, 'project.json' );
175
+
176
+ } );
177
+
178
+ options.add( option );
179
+
180
+ //
181
+
182
+ options.add( new UIHorizontalRule() );
183
+
184
+ // Import
185
+
186
+ const form = document.createElement( 'form' );
187
+ form.style.display = 'none';
188
+ document.body.appendChild( form );
189
+
190
+ const fileInput = document.createElement( 'input' );
191
+ fileInput.multiple = true;
192
+ fileInput.type = 'file';
193
+ fileInput.addEventListener( 'change', function () {
194
+
195
+ editor.loader.loadFiles( fileInput.files );
196
+ form.reset();
197
+
198
+ } );
199
+ form.appendChild( fileInput );
200
+
201
+ option = new UIRow();
202
+ option.setClass( 'option' );
203
+ option.setTextContent( strings.getKey( 'menubar/file/import' ) );
204
+ option.onClick( function () {
205
+
206
+ fileInput.click();
207
+
208
+ } );
209
+ options.add( option );
210
+
211
+ // Export
212
+
213
+ const fileExportSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/file/export' ) ).addClass( 'option' ).addClass( 'submenu-title' );
214
+ fileExportSubmenuTitle.onMouseOver( function () {
215
+
216
+ const { top, right } = this.dom.getBoundingClientRect();
217
+ const { paddingTop } = getComputedStyle( this.dom );
218
+ fileExportSubmenu.setLeft( right + 'px' );
219
+ fileExportSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
220
+ fileExportSubmenu.setDisplay( 'block' );
221
+
222
+ } );
223
+ fileExportSubmenuTitle.onMouseOut( function () {
224
+
225
+ fileExportSubmenu.setDisplay( 'none' );
226
+
227
+ } );
228
+ options.add( fileExportSubmenuTitle );
229
+
230
+ const fileExportSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
231
+ fileExportSubmenuTitle.add( fileExportSubmenu );
232
+
233
+ // Export DRC
234
+
235
+ option = new UIRow();
236
+ option.setClass( 'option' );
237
+ option.setTextContent( 'DRC' );
238
+ option.onClick( async function () {
239
+
240
+ const object = editor.selected;
241
+
242
+ if ( object === null || object.isMesh === undefined ) {
243
+
244
+ alert( strings.getKey( 'prompt/file/export/noMeshSelected' ) );
245
+ return;
246
+
247
+ }
248
+
249
+ const { DRACOExporter } = await import( 'three/addons/exporters/DRACOExporter.js' );
250
+
251
+ const exporter = new DRACOExporter();
252
+
253
+ const options = {
254
+ decodeSpeed: 5,
255
+ encodeSpeed: 5,
256
+ encoderMethod: DRACOExporter.MESH_EDGEBREAKER_ENCODING,
257
+ quantization: [ 16, 8, 8, 8, 8 ],
258
+ exportUvs: true,
259
+ exportNormals: true,
260
+ exportColor: object.geometry.hasAttribute( 'color' )
261
+ };
262
+
263
+ // TODO: Change to DRACOExporter's parse( geometry, onParse )?
264
+ const result = exporter.parse( object, options );
265
+ saveArrayBuffer( result, 'model.drc' );
266
+
267
+ } );
268
+ fileExportSubmenu.add( option );
269
+
270
+ // Export GLB
271
+
272
+ option = new UIRow();
273
+ option.setClass( 'option' );
274
+ option.setTextContent( 'GLB' );
275
+ option.onClick( async function () {
276
+
277
+ const scene = editor.scene;
278
+ const animations = getAnimations( scene );
279
+
280
+ const optimizedAnimations = [];
281
+
282
+ for ( const animation of animations ) {
283
+
284
+ optimizedAnimations.push( animation.clone().optimize() );
285
+
286
+ }
287
+
288
+ const { GLTFExporter } = await import( 'three/addons/exporters/GLTFExporter.js' );
289
+
290
+ const exporter = new GLTFExporter();
291
+
292
+ exporter.parse( scene, function ( result ) {
293
+
294
+ saveArrayBuffer( result, 'scene.glb' );
295
+
296
+ }, undefined, { binary: true, animations: optimizedAnimations } );
297
+
298
+ } );
299
+ fileExportSubmenu.add( option );
300
+
301
+ // Export GLTF
302
+
303
+ option = new UIRow();
304
+ option.setClass( 'option' );
305
+ option.setTextContent( 'GLTF' );
306
+ option.onClick( async function () {
307
+
308
+ const scene = editor.scene;
309
+ const animations = getAnimations( scene );
310
+
311
+ const optimizedAnimations = [];
312
+
313
+ for ( const animation of animations ) {
314
+
315
+ optimizedAnimations.push( animation.clone().optimize() );
316
+
317
+ }
318
+
319
+ const { GLTFExporter } = await import( 'three/addons/exporters/GLTFExporter.js' );
320
+
321
+ const exporter = new GLTFExporter();
322
+
323
+ exporter.parse( scene, function ( result ) {
324
+
325
+ saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' );
326
+
327
+ }, undefined, { animations: optimizedAnimations } );
328
+
329
+
330
+ } );
331
+ fileExportSubmenu.add( option );
332
+
333
+ // Export OBJ
334
+
335
+ option = new UIRow();
336
+ option.setClass( 'option' );
337
+ option.setTextContent( 'OBJ' );
338
+ option.onClick( async function () {
339
+
340
+ const object = editor.selected;
341
+
342
+ if ( object === null ) {
343
+
344
+ alert( strings.getKey( 'prompt/file/export/noObjectSelected' ) );
345
+ return;
346
+
347
+ }
348
+
349
+ const { OBJExporter } = await import( 'three/addons/exporters/OBJExporter.js' );
350
+
351
+ const exporter = new OBJExporter();
352
+
353
+ saveString( exporter.parse( object ), 'model.obj' );
354
+
355
+ } );
356
+ fileExportSubmenu.add( option );
357
+
358
+ // Export PLY (ASCII)
359
+
360
+ option = new UIRow();
361
+ option.setClass( 'option' );
362
+ option.setTextContent( 'PLY' );
363
+ option.onClick( async function () {
364
+
365
+ const { PLYExporter } = await import( 'three/addons/exporters/PLYExporter.js' );
366
+
367
+ const exporter = new PLYExporter();
368
+
369
+ exporter.parse( editor.scene, function ( result ) {
370
+
371
+ saveArrayBuffer( result, 'model.ply' );
372
+
373
+ } );
374
+
375
+ } );
376
+ fileExportSubmenu.add( option );
377
+
378
+ // Export PLY (BINARY)
379
+
380
+ option = new UIRow();
381
+ option.setClass( 'option' );
382
+ option.setTextContent( 'PLY (BINARY)' );
383
+ option.onClick( async function () {
384
+
385
+ const { PLYExporter } = await import( 'three/addons/exporters/PLYExporter.js' );
386
+
387
+ const exporter = new PLYExporter();
388
+
389
+ exporter.parse( editor.scene, function ( result ) {
390
+
391
+ saveArrayBuffer( result, 'model-binary.ply' );
392
+
393
+ }, { binary: true } );
394
+
395
+ } );
396
+ fileExportSubmenu.add( option );
397
+
398
+ // Export STL (ASCII)
399
+
400
+ option = new UIRow();
401
+ option.setClass( 'option' );
402
+ option.setTextContent( 'STL' );
403
+ option.onClick( async function () {
404
+
405
+ const { STLExporter } = await import( 'three/addons/exporters/STLExporter.js' );
406
+
407
+ const exporter = new STLExporter();
408
+
409
+ saveString( exporter.parse( editor.scene ), 'model.stl' );
410
+
411
+ } );
412
+ fileExportSubmenu.add( option );
413
+
414
+ // Export STL (BINARY)
415
+
416
+ option = new UIRow();
417
+ option.setClass( 'option' );
418
+ option.setTextContent( 'STL (BINARY)' );
419
+ option.onClick( async function () {
420
+
421
+ const { STLExporter } = await import( 'three/addons/exporters/STLExporter.js' );
422
+
423
+ const exporter = new STLExporter();
424
+
425
+ saveArrayBuffer( exporter.parse( editor.scene, { binary: true } ), 'model-binary.stl' );
426
+
427
+ } );
428
+ fileExportSubmenu.add( option );
429
+
430
+ // Export USDZ
431
+
432
+ option = new UIRow();
433
+ option.setClass( 'option' );
434
+ option.setTextContent( 'USDZ' );
435
+ option.onClick( async function () {
436
+
437
+ const { USDZExporter } = await import( 'three/addons/exporters/USDZExporter.js' );
438
+
439
+ const exporter = new USDZExporter();
440
+
441
+ saveArrayBuffer( await exporter.parseAsync( editor.scene ), 'model.usdz' );
442
+
443
+ } );
444
+ fileExportSubmenu.add( option );
445
+
446
+ //
447
+
448
+ function getAnimations( scene ) {
449
+
450
+ const animations = [];
451
+
452
+ scene.traverse( function ( object ) {
453
+
454
+ animations.push( ... object.animations );
455
+
456
+ } );
457
+
458
+ return animations;
459
+
460
+ }
461
+
462
+ return container;
463
+
464
+ }
465
+
466
+ export { MenubarFile };
@@ -0,0 +1,73 @@
1
+ import { UIPanel, UIRow } from './libs/ui.js';
2
+
3
+ function MenubarHelp( editor ) {
4
+
5
+ const strings = editor.strings;
6
+
7
+ const container = new UIPanel();
8
+ container.setClass( 'menu' );
9
+
10
+ const title = new UIPanel();
11
+ title.setClass( 'title' );
12
+ title.setTextContent( strings.getKey( 'menubar/help' ) );
13
+ container.add( title );
14
+
15
+ const options = new UIPanel();
16
+ options.setClass( 'options' );
17
+ container.add( options );
18
+
19
+ // Source code
20
+
21
+ let option = new UIRow();
22
+ option.setClass( 'option' );
23
+ option.setTextContent( strings.getKey( 'menubar/help/source_code' ) );
24
+ option.onClick( function () {
25
+
26
+ window.open( 'https://github.com/mrdoob/three.js/tree/master/editor', '_blank' );
27
+
28
+ } );
29
+ options.add( option );
30
+
31
+ /*
32
+ // Icon
33
+
34
+ let option = new UIRow();
35
+ option.setClass( 'option' );
36
+ option.setTextContent( strings.getKey( 'menubar/help/icons' ) );
37
+ option.onClick( function () {
38
+
39
+ window.open( 'https://www.flaticon.com/packs/interface-44', '_blank' );
40
+
41
+ } );
42
+ options.add( option );
43
+ */
44
+
45
+ // About
46
+
47
+ option = new UIRow();
48
+ option.setClass( 'option' );
49
+ option.setTextContent( strings.getKey( 'menubar/help/about' ) );
50
+ option.onClick( function () {
51
+
52
+ window.open( 'https://threejs.org', '_blank' );
53
+
54
+ } );
55
+ options.add( option );
56
+
57
+ // Manual
58
+
59
+ option = new UIRow();
60
+ option.setClass( 'option' );
61
+ option.setTextContent( strings.getKey( 'menubar/help/manual' ) );
62
+ option.onClick( function () {
63
+
64
+ window.open( 'https://github.com/mrdoob/three.js/wiki/Editor-Manual', '_blank' );
65
+
66
+ } );
67
+ options.add( option );
68
+
69
+ return container;
70
+
71
+ }
72
+
73
+ export { MenubarHelp };