spoint 0.1.0 → 0.1.10

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 +28 -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,90 @@
1
+ const LoaderUtils = {
2
+
3
+ createFilesMap: function ( files ) {
4
+
5
+ const map = {};
6
+
7
+ for ( let i = 0; i < files.length; i ++ ) {
8
+
9
+ const file = files[ i ];
10
+ map[ file.name ] = file;
11
+
12
+ }
13
+
14
+ return map;
15
+
16
+ },
17
+
18
+ getFilesFromItemList: function ( items, onDone ) {
19
+
20
+ // TOFIX: setURLModifier() breaks when the file being loaded is not in root
21
+
22
+ let itemsCount = 0;
23
+ let itemsTotal = 0;
24
+
25
+ const files = [];
26
+ const filesMap = {};
27
+
28
+ function onEntryHandled() {
29
+
30
+ itemsCount ++;
31
+
32
+ if ( itemsCount === itemsTotal ) {
33
+
34
+ onDone( files, filesMap );
35
+
36
+ }
37
+
38
+ }
39
+
40
+ function handleEntry( entry ) {
41
+
42
+ if ( entry.isDirectory ) {
43
+
44
+ const reader = entry.createReader();
45
+ reader.readEntries( function ( entries ) {
46
+
47
+ for ( let i = 0; i < entries.length; i ++ ) {
48
+
49
+ handleEntry( entries[ i ] );
50
+
51
+ }
52
+
53
+ onEntryHandled();
54
+
55
+ } );
56
+
57
+ } else if ( entry.isFile ) {
58
+
59
+ entry.file( function ( file ) {
60
+
61
+ files.push( file );
62
+
63
+ filesMap[ entry.fullPath.slice( 1 ) ] = file;
64
+ onEntryHandled();
65
+
66
+ } );
67
+
68
+ }
69
+
70
+ itemsTotal ++;
71
+
72
+ }
73
+
74
+ for ( let i = 0; i < items.length; i ++ ) {
75
+
76
+ const item = items[ i ];
77
+
78
+ if ( item.kind === 'file' ) {
79
+
80
+ handleEntry( item.webkitGetAsEntry() );
81
+
82
+ }
83
+
84
+ }
85
+
86
+ }
87
+
88
+ };
89
+
90
+ export { LoaderUtils };
@@ -0,0 +1,510 @@
1
+ import * as THREE from 'three';
2
+
3
+ import { UIPanel, UIRow } from './libs/ui.js';
4
+
5
+ import { AddObjectCommand } from './commands/AddObjectCommand.js';
6
+
7
+ function MenubarAdd( editor ) {
8
+
9
+ const strings = editor.strings;
10
+
11
+ const container = new UIPanel();
12
+ container.setClass( 'menu' );
13
+
14
+ const title = new UIPanel();
15
+ title.setClass( 'title' );
16
+ title.setTextContent( strings.getKey( 'menubar/add' ) );
17
+ container.add( title );
18
+
19
+ const options = new UIPanel();
20
+ options.setClass( 'options' );
21
+ container.add( options );
22
+
23
+ // Group
24
+
25
+ let option = new UIRow();
26
+ option.setClass( 'option' );
27
+ option.setTextContent( strings.getKey( 'menubar/add/group' ) );
28
+ option.onClick( function () {
29
+
30
+ const mesh = new THREE.Group();
31
+ mesh.name = 'Group';
32
+
33
+ editor.execute( new AddObjectCommand( editor, mesh ) );
34
+
35
+ } );
36
+ options.add( option );
37
+
38
+ // Mesh
39
+
40
+ const meshSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/mesh' ) ).addClass( 'option' ).addClass( 'submenu-title' );
41
+ meshSubmenuTitle.onMouseOver( function () {
42
+
43
+ const { top, right } = meshSubmenuTitle.dom.getBoundingClientRect();
44
+ const { paddingTop } = getComputedStyle( this.dom );
45
+ meshSubmenu.setLeft( right + 'px' );
46
+ meshSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
47
+ meshSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
48
+ meshSubmenu.setDisplay( 'block' );
49
+
50
+ } );
51
+ meshSubmenuTitle.onMouseOut( function () {
52
+
53
+ meshSubmenu.setDisplay( 'none' );
54
+
55
+ } );
56
+ options.add( meshSubmenuTitle );
57
+
58
+ const meshSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
59
+ meshSubmenuTitle.add( meshSubmenu );
60
+
61
+ // Mesh / Box
62
+
63
+ option = new UIRow();
64
+ option.setClass( 'option' );
65
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/box' ) );
66
+ option.onClick( function () {
67
+
68
+ const geometry = new THREE.BoxGeometry( 1, 1, 1, 1, 1, 1 );
69
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
70
+ mesh.name = 'Box';
71
+
72
+ editor.execute( new AddObjectCommand( editor, mesh ) );
73
+
74
+ } );
75
+ meshSubmenu.add( option );
76
+
77
+ // Mesh / Capsule
78
+
79
+ option = new UIRow();
80
+ option.setClass( 'option' );
81
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/capsule' ) );
82
+ option.onClick( function () {
83
+
84
+ const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8 );
85
+ const material = new THREE.MeshStandardMaterial();
86
+ const mesh = new THREE.Mesh( geometry, material );
87
+ mesh.name = 'Capsule';
88
+
89
+ editor.execute( new AddObjectCommand( editor, mesh ) );
90
+
91
+ } );
92
+ meshSubmenu.add( option );
93
+
94
+ // Mesh / Circle
95
+
96
+ option = new UIRow();
97
+ option.setClass( 'option' );
98
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/circle' ) );
99
+ option.onClick( function () {
100
+
101
+ const geometry = new THREE.CircleGeometry( 1, 32, 0, Math.PI * 2 );
102
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
103
+ mesh.name = 'Circle';
104
+
105
+ editor.execute( new AddObjectCommand( editor, mesh ) );
106
+
107
+ } );
108
+ meshSubmenu.add( option );
109
+
110
+ // Mesh / Cylinder
111
+
112
+ option = new UIRow();
113
+ option.setClass( 'option' );
114
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/cylinder' ) );
115
+ option.onClick( function () {
116
+
117
+ const geometry = new THREE.CylinderGeometry( 1, 1, 1, 32, 1, false, 0, Math.PI * 2 );
118
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
119
+ mesh.name = 'Cylinder';
120
+
121
+ editor.execute( new AddObjectCommand( editor, mesh ) );
122
+
123
+ } );
124
+ meshSubmenu.add( option );
125
+
126
+ // Mesh / Dodecahedron
127
+
128
+ option = new UIRow();
129
+ option.setClass( 'option' );
130
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/dodecahedron' ) );
131
+ option.onClick( function () {
132
+
133
+ const geometry = new THREE.DodecahedronGeometry( 1, 0 );
134
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
135
+ mesh.name = 'Dodecahedron';
136
+
137
+ editor.execute( new AddObjectCommand( editor, mesh ) );
138
+
139
+ } );
140
+ meshSubmenu.add( option );
141
+
142
+ // Mesh / Icosahedron
143
+
144
+ option = new UIRow();
145
+ option.setClass( 'option' );
146
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/icosahedron' ) );
147
+ option.onClick( function () {
148
+
149
+ const geometry = new THREE.IcosahedronGeometry( 1, 0 );
150
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
151
+ mesh.name = 'Icosahedron';
152
+
153
+ editor.execute( new AddObjectCommand( editor, mesh ) );
154
+
155
+ } );
156
+ meshSubmenu.add( option );
157
+
158
+ // Mesh / Lathe
159
+
160
+ option = new UIRow();
161
+ option.setClass( 'option' );
162
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/lathe' ) );
163
+ option.onClick( function () {
164
+
165
+ const geometry = new THREE.LatheGeometry();
166
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial( { side: THREE.DoubleSide } ) );
167
+ mesh.name = 'Lathe';
168
+
169
+ editor.execute( new AddObjectCommand( editor, mesh ) );
170
+
171
+ } );
172
+ meshSubmenu.add( option );
173
+
174
+ // Mesh / Octahedron
175
+
176
+ option = new UIRow();
177
+ option.setClass( 'option' );
178
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/octahedron' ) );
179
+ option.onClick( function () {
180
+
181
+ const geometry = new THREE.OctahedronGeometry( 1, 0 );
182
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
183
+ mesh.name = 'Octahedron';
184
+
185
+ editor.execute( new AddObjectCommand( editor, mesh ) );
186
+
187
+ } );
188
+ meshSubmenu.add( option );
189
+
190
+ // Mesh / Plane
191
+
192
+ option = new UIRow();
193
+ option.setClass( 'option' );
194
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/plane' ) );
195
+ option.onClick( function () {
196
+
197
+ const geometry = new THREE.PlaneGeometry( 1, 1, 1, 1 );
198
+ const material = new THREE.MeshStandardMaterial();
199
+ const mesh = new THREE.Mesh( geometry, material );
200
+ mesh.name = 'Plane';
201
+
202
+ editor.execute( new AddObjectCommand( editor, mesh ) );
203
+
204
+ } );
205
+ meshSubmenu.add( option );
206
+
207
+ // Mesh / Ring
208
+
209
+ option = new UIRow();
210
+ option.setClass( 'option' );
211
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/ring' ) );
212
+ option.onClick( function () {
213
+
214
+ const geometry = new THREE.RingGeometry( 0.5, 1, 32, 1, 0, Math.PI * 2 );
215
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
216
+ mesh.name = 'Ring';
217
+
218
+ editor.execute( new AddObjectCommand( editor, mesh ) );
219
+
220
+ } );
221
+ meshSubmenu.add( option );
222
+
223
+ // Mesh / Sphere
224
+
225
+ option = new UIRow();
226
+ option.setClass( 'option' );
227
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/sphere' ) );
228
+ option.onClick( function () {
229
+
230
+ const geometry = new THREE.SphereGeometry( 1, 32, 16, 0, Math.PI * 2, 0, Math.PI );
231
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
232
+ mesh.name = 'Sphere';
233
+
234
+ editor.execute( new AddObjectCommand( editor, mesh ) );
235
+
236
+ } );
237
+ meshSubmenu.add( option );
238
+
239
+ // Mesh / Sprite
240
+
241
+ option = new UIRow();
242
+ option.setClass( 'option' );
243
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/sprite' ) );
244
+ option.onClick( function () {
245
+
246
+ const sprite = new THREE.Sprite( new THREE.SpriteMaterial() );
247
+ sprite.name = 'Sprite';
248
+
249
+ editor.execute( new AddObjectCommand( editor, sprite ) );
250
+
251
+ } );
252
+ meshSubmenu.add( option );
253
+
254
+ // Mesh / Tetrahedron
255
+
256
+ option = new UIRow();
257
+ option.setClass( 'option' );
258
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/tetrahedron' ) );
259
+ option.onClick( function () {
260
+
261
+ const geometry = new THREE.TetrahedronGeometry( 1, 0 );
262
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
263
+ mesh.name = 'Tetrahedron';
264
+
265
+ editor.execute( new AddObjectCommand( editor, mesh ) );
266
+
267
+ } );
268
+ meshSubmenu.add( option );
269
+
270
+ // Mesh / Torus
271
+
272
+ option = new UIRow();
273
+ option.setClass( 'option' );
274
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/torus' ) );
275
+ option.onClick( function () {
276
+
277
+ const geometry = new THREE.TorusGeometry( 1, 0.4, 12, 48, Math.PI * 2 );
278
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
279
+ mesh.name = 'Torus';
280
+
281
+ editor.execute( new AddObjectCommand( editor, mesh ) );
282
+
283
+ } );
284
+ meshSubmenu.add( option );
285
+
286
+ // Mesh / TorusKnot
287
+
288
+ option = new UIRow();
289
+ option.setClass( 'option' );
290
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/torusknot' ) );
291
+ option.onClick( function () {
292
+
293
+ const geometry = new THREE.TorusKnotGeometry( 1, 0.4, 64, 8, 2, 3 );
294
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
295
+ mesh.name = 'TorusKnot';
296
+
297
+ editor.execute( new AddObjectCommand( editor, mesh ) );
298
+
299
+ } );
300
+ meshSubmenu.add( option );
301
+
302
+ // Mesh / Tube
303
+
304
+ option = new UIRow();
305
+ option.setClass( 'option' );
306
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/tube' ) );
307
+ option.onClick( function () {
308
+
309
+ const path = new THREE.CatmullRomCurve3( [
310
+ new THREE.Vector3( 2, 2, - 2 ),
311
+ new THREE.Vector3( 2, - 2, - 0.6666666666666667 ),
312
+ new THREE.Vector3( - 2, - 2, 0.6666666666666667 ),
313
+ new THREE.Vector3( - 2, 2, 2 )
314
+ ] );
315
+
316
+ const geometry = new THREE.TubeGeometry( path, 64, 1, 8, false );
317
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
318
+ mesh.name = 'Tube';
319
+
320
+ editor.execute( new AddObjectCommand( editor, mesh ) );
321
+
322
+ } );
323
+ meshSubmenu.add( option );
324
+
325
+ // Light
326
+
327
+ const lightSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/light' ) ).addClass( 'option' ).addClass( 'submenu-title' );
328
+ lightSubmenuTitle.onMouseOver( function () {
329
+
330
+ const { top, right } = lightSubmenuTitle.dom.getBoundingClientRect();
331
+ const { paddingTop } = getComputedStyle( this.dom );
332
+
333
+ lightSubmenu.setLeft( right + 'px' );
334
+ lightSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
335
+ lightSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
336
+ lightSubmenu.setDisplay( 'block' );
337
+
338
+ } );
339
+ lightSubmenuTitle.onMouseOut( function () {
340
+
341
+ lightSubmenu.setDisplay( 'none' );
342
+
343
+ } );
344
+ options.add( lightSubmenuTitle );
345
+
346
+ const lightSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
347
+ lightSubmenuTitle.add( lightSubmenu );
348
+
349
+ // Light / Ambient
350
+
351
+ option = new UIRow();
352
+ option.setClass( 'option' );
353
+ option.setTextContent( strings.getKey( 'menubar/add/light/ambient' ) );
354
+ option.onClick( function () {
355
+
356
+ const color = 0x222222;
357
+
358
+ const light = new THREE.AmbientLight( color );
359
+ light.name = 'AmbientLight';
360
+
361
+ editor.execute( new AddObjectCommand( editor, light ) );
362
+
363
+ } );
364
+ lightSubmenu.add( option );
365
+
366
+ // Light / Directional
367
+
368
+ option = new UIRow();
369
+ option.setClass( 'option' );
370
+ option.setTextContent( strings.getKey( 'menubar/add/light/directional' ) );
371
+ option.onClick( function () {
372
+
373
+ const color = 0xffffff;
374
+ const intensity = 1;
375
+
376
+ const light = new THREE.DirectionalLight( color, intensity );
377
+ light.name = 'DirectionalLight';
378
+ light.target.name = 'DirectionalLight Target';
379
+
380
+ light.position.set( 5, 10, 7.5 );
381
+
382
+ editor.execute( new AddObjectCommand( editor, light ) );
383
+
384
+ } );
385
+ lightSubmenu.add( option );
386
+
387
+ // Light / Hemisphere
388
+
389
+ option = new UIRow();
390
+ option.setClass( 'option' );
391
+ option.setTextContent( strings.getKey( 'menubar/add/light/hemisphere' ) );
392
+ option.onClick( function () {
393
+
394
+ const skyColor = 0x00aaff;
395
+ const groundColor = 0xffaa00;
396
+ const intensity = 1;
397
+
398
+ const light = new THREE.HemisphereLight( skyColor, groundColor, intensity );
399
+ light.name = 'HemisphereLight';
400
+
401
+ light.position.set( 0, 10, 0 );
402
+
403
+ editor.execute( new AddObjectCommand( editor, light ) );
404
+
405
+ } );
406
+ lightSubmenu.add( option );
407
+
408
+ // Light / Point
409
+
410
+ option = new UIRow();
411
+ option.setClass( 'option' );
412
+ option.setTextContent( strings.getKey( 'menubar/add/light/point' ) );
413
+ option.onClick( function () {
414
+
415
+ const color = 0xffffff;
416
+ const intensity = 1;
417
+ const distance = 0;
418
+
419
+ const light = new THREE.PointLight( color, intensity, distance );
420
+ light.name = 'PointLight';
421
+
422
+ editor.execute( new AddObjectCommand( editor, light ) );
423
+
424
+ } );
425
+ lightSubmenu.add( option );
426
+
427
+ // Light / Spot
428
+
429
+ option = new UIRow();
430
+ option.setClass( 'option' );
431
+ option.setTextContent( strings.getKey( 'menubar/add/light/spot' ) );
432
+ option.onClick( function () {
433
+
434
+ const color = 0xffffff;
435
+ const intensity = 1;
436
+ const distance = 0;
437
+ const angle = Math.PI * 0.1;
438
+ const penumbra = 0;
439
+
440
+ const light = new THREE.SpotLight( color, intensity, distance, angle, penumbra );
441
+ light.name = 'SpotLight';
442
+ light.target.name = 'SpotLight Target';
443
+
444
+ light.position.set( 5, 10, 7.5 );
445
+
446
+ editor.execute( new AddObjectCommand( editor, light ) );
447
+
448
+ } );
449
+ lightSubmenu.add( option );
450
+
451
+ // Camera
452
+
453
+ const cameraSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/camera' ) ).addClass( 'option' ).addClass( 'submenu-title' );
454
+ cameraSubmenuTitle.onMouseOver( function () {
455
+
456
+ const { top, right } = cameraSubmenuTitle.dom.getBoundingClientRect();
457
+ const { paddingTop } = getComputedStyle( this.dom );
458
+
459
+ cameraSubmenu.setLeft( right + 'px' );
460
+ cameraSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
461
+ cameraSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
462
+ cameraSubmenu.setDisplay( 'block' );
463
+
464
+ } );
465
+ cameraSubmenuTitle.onMouseOut( function () {
466
+
467
+ cameraSubmenu.setDisplay( 'none' );
468
+
469
+ } );
470
+ options.add( cameraSubmenuTitle );
471
+
472
+ const cameraSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
473
+ cameraSubmenuTitle.add( cameraSubmenu );
474
+
475
+ // Camera / Orthographic
476
+
477
+ option = new UIRow();
478
+ option.setClass( 'option' );
479
+ option.setTextContent( strings.getKey( 'menubar/add/camera/orthographic' ) );
480
+ option.onClick( function () {
481
+
482
+ const aspect = editor.camera.aspect;
483
+ const camera = new THREE.OrthographicCamera( - aspect, aspect );
484
+ camera.name = 'OrthographicCamera';
485
+
486
+ editor.execute( new AddObjectCommand( editor, camera ) );
487
+
488
+ } );
489
+ cameraSubmenu.add( option );
490
+
491
+ // Camera / Perspective
492
+
493
+ option = new UIRow();
494
+ option.setClass( 'option' );
495
+ option.setTextContent( strings.getKey( 'menubar/add/camera/perspective' ) );
496
+ option.onClick( function () {
497
+
498
+ const camera = new THREE.PerspectiveCamera();
499
+ camera.name = 'PerspectiveCamera';
500
+
501
+ editor.execute( new AddObjectCommand( editor, camera ) );
502
+
503
+ } );
504
+ cameraSubmenu.add( option );
505
+
506
+ return container;
507
+
508
+ }
509
+
510
+ export { MenubarAdd };