@thanhthbm/scene-editor 0.1.0

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 (136) hide show
  1. package/README.md +169 -0
  2. package/dist/index.css +921 -0
  3. package/dist/index.js +14076 -0
  4. package/package.json +49 -0
  5. package/src/editor/css/main.css +1030 -0
  6. package/src/editor/js/Animation.js +618 -0
  7. package/src/editor/js/AnimationResizer.js +73 -0
  8. package/src/editor/js/Command.js +40 -0
  9. package/src/editor/js/Config.js +86 -0
  10. package/src/editor/js/Editor.js +1006 -0
  11. package/src/editor/js/EditorControls.js +489 -0
  12. package/src/editor/js/GLTFImportDialog.js +112 -0
  13. package/src/editor/js/History.js +321 -0
  14. package/src/editor/js/Loader.js +1162 -0
  15. package/src/editor/js/LoaderUtils.js +90 -0
  16. package/src/editor/js/Menubar.Add.js +559 -0
  17. package/src/editor/js/Menubar.Edit.js +155 -0
  18. package/src/editor/js/Menubar.File.js +585 -0
  19. package/src/editor/js/Menubar.Help.js +73 -0
  20. package/src/editor/js/Menubar.Render.js +858 -0
  21. package/src/editor/js/Menubar.Status.js +51 -0
  22. package/src/editor/js/Menubar.View.js +193 -0
  23. package/src/editor/js/Menubar.js +29 -0
  24. package/src/editor/js/Player.js +53 -0
  25. package/src/editor/js/Resizer.js +65 -0
  26. package/src/editor/js/Script.js +532 -0
  27. package/src/editor/js/Selector.js +129 -0
  28. package/src/editor/js/Sidebar.Geometry.BoxGeometry.js +121 -0
  29. package/src/editor/js/Sidebar.Geometry.BufferGeometry.js +124 -0
  30. package/src/editor/js/Sidebar.Geometry.CapsuleGeometry.js +109 -0
  31. package/src/editor/js/Sidebar.Geometry.CircleGeometry.js +97 -0
  32. package/src/editor/js/Sidebar.Geometry.CylinderGeometry.js +121 -0
  33. package/src/editor/js/Sidebar.Geometry.DodecahedronGeometry.js +73 -0
  34. package/src/editor/js/Sidebar.Geometry.ExtrudeGeometry.js +196 -0
  35. package/src/editor/js/Sidebar.Geometry.IcosahedronGeometry.js +73 -0
  36. package/src/editor/js/Sidebar.Geometry.LatheGeometry.js +98 -0
  37. package/src/editor/js/Sidebar.Geometry.Modifiers.js +73 -0
  38. package/src/editor/js/Sidebar.Geometry.OctahedronGeometry.js +74 -0
  39. package/src/editor/js/Sidebar.Geometry.PlaneGeometry.js +97 -0
  40. package/src/editor/js/Sidebar.Geometry.RingGeometry.js +121 -0
  41. package/src/editor/js/Sidebar.Geometry.ShapeGeometry.js +76 -0
  42. package/src/editor/js/Sidebar.Geometry.SphereGeometry.js +133 -0
  43. package/src/editor/js/Sidebar.Geometry.TetrahedronGeometry.js +74 -0
  44. package/src/editor/js/Sidebar.Geometry.TextGeometry.js +136 -0
  45. package/src/editor/js/Sidebar.Geometry.TorusGeometry.js +109 -0
  46. package/src/editor/js/Sidebar.Geometry.TorusKnotGeometry.js +121 -0
  47. package/src/editor/js/Sidebar.Geometry.TubeGeometry.js +135 -0
  48. package/src/editor/js/Sidebar.Geometry.js +471 -0
  49. package/src/editor/js/Sidebar.Material.BooleanProperty.js +60 -0
  50. package/src/editor/js/Sidebar.Material.ColorProperty.js +87 -0
  51. package/src/editor/js/Sidebar.Material.ConstantProperty.js +62 -0
  52. package/src/editor/js/Sidebar.Material.MapProperty.js +277 -0
  53. package/src/editor/js/Sidebar.Material.NumberProperty.js +60 -0
  54. package/src/editor/js/Sidebar.Material.Program.js +73 -0
  55. package/src/editor/js/Sidebar.Material.RangeValueProperty.js +63 -0
  56. package/src/editor/js/Sidebar.Material.js +751 -0
  57. package/src/editor/js/Sidebar.Object.js +892 -0
  58. package/src/editor/js/Sidebar.Project.App.js +218 -0
  59. package/src/editor/js/Sidebar.Project.Materials.js +82 -0
  60. package/src/editor/js/Sidebar.Project.Renderer.js +193 -0
  61. package/src/editor/js/Sidebar.Project.Resources.js +242 -0
  62. package/src/editor/js/Sidebar.Project.js +21 -0
  63. package/src/editor/js/Sidebar.Properties.js +73 -0
  64. package/src/editor/js/Sidebar.Scene.js +643 -0
  65. package/src/editor/js/Sidebar.Script.js +129 -0
  66. package/src/editor/js/Sidebar.Settings.History.js +146 -0
  67. package/src/editor/js/Sidebar.Settings.Shortcuts.js +198 -0
  68. package/src/editor/js/Sidebar.Settings.js +58 -0
  69. package/src/editor/js/Sidebar.js +41 -0
  70. package/src/editor/js/Storage.js +98 -0
  71. package/src/editor/js/Strings.js +2718 -0
  72. package/src/editor/js/TextureParametersDialog.js +293 -0
  73. package/src/editor/js/Toolbar.js +75 -0
  74. package/src/editor/js/Viewport.Controls.js +98 -0
  75. package/src/editor/js/Viewport.Info.js +144 -0
  76. package/src/editor/js/Viewport.Pathtracer.js +27 -0
  77. package/src/editor/js/Viewport.ViewHelper.js +41 -0
  78. package/src/editor/js/Viewport.XR.js +7 -0
  79. package/src/editor/js/Viewport.js +982 -0
  80. package/src/editor/js/commands/AddObjectCommand.js +68 -0
  81. package/src/editor/js/commands/AddScriptCommand.js +75 -0
  82. package/src/editor/js/commands/Commands.js +24 -0
  83. package/src/editor/js/commands/MoveObjectCommand.js +117 -0
  84. package/src/editor/js/commands/MultiCmdsCommand.js +85 -0
  85. package/src/editor/js/commands/RemoveObjectCommand.js +88 -0
  86. package/src/editor/js/commands/RemoveScriptCommand.js +81 -0
  87. package/src/editor/js/commands/SetColorCommand.js +73 -0
  88. package/src/editor/js/commands/SetGeometryCommand.js +86 -0
  89. package/src/editor/js/commands/SetGeometryValueCommand.js +70 -0
  90. package/src/editor/js/commands/SetMaterialColorCommand.js +87 -0
  91. package/src/editor/js/commands/SetMaterialCommand.js +80 -0
  92. package/src/editor/js/commands/SetMaterialMapCommand.js +144 -0
  93. package/src/editor/js/commands/SetMaterialRangeCommand.js +92 -0
  94. package/src/editor/js/commands/SetMaterialValueCommand.js +91 -0
  95. package/src/editor/js/commands/SetMaterialVectorCommand.js +88 -0
  96. package/src/editor/js/commands/SetPositionCommand.js +84 -0
  97. package/src/editor/js/commands/SetRotationCommand.js +84 -0
  98. package/src/editor/js/commands/SetScaleCommand.js +84 -0
  99. package/src/editor/js/commands/SetSceneCommand.js +104 -0
  100. package/src/editor/js/commands/SetScriptValueCommand.js +80 -0
  101. package/src/editor/js/commands/SetShadowValueCommand.js +73 -0
  102. package/src/editor/js/commands/SetTextureParametersCommand.js +143 -0
  103. package/src/editor/js/commands/SetUuidCommand.js +70 -0
  104. package/src/editor/js/commands/SetValueCommand.js +75 -0
  105. package/src/editor/js/libs/acorn/acorn.js +3236 -0
  106. package/src/editor/js/libs/acorn/acorn_loose.js +1299 -0
  107. package/src/editor/js/libs/acorn/walk.js +344 -0
  108. package/src/editor/js/libs/app/index.html +51 -0
  109. package/src/editor/js/libs/app.js +14 -0
  110. package/src/editor/js/libs/codemirror/addon/dialog.css +32 -0
  111. package/src/editor/js/libs/codemirror/addon/dialog.js +163 -0
  112. package/src/editor/js/libs/codemirror/addon/show-hint.css +36 -0
  113. package/src/editor/js/libs/codemirror/addon/show-hint.js +529 -0
  114. package/src/editor/js/libs/codemirror/addon/tern.css +87 -0
  115. package/src/editor/js/libs/codemirror/addon/tern.js +750 -0
  116. package/src/editor/js/libs/codemirror/codemirror.css +344 -0
  117. package/src/editor/js/libs/codemirror/codemirror.js +9849 -0
  118. package/src/editor/js/libs/codemirror/mode/glsl.js +233 -0
  119. package/src/editor/js/libs/codemirror/mode/javascript.js +959 -0
  120. package/src/editor/js/libs/codemirror/theme/monokai.css +41 -0
  121. package/src/editor/js/libs/esprima.js +6401 -0
  122. package/src/editor/js/libs/jsonlint.js +453 -0
  123. package/src/editor/js/libs/signals.min.js +14 -0
  124. package/src/editor/js/libs/tern-threejs/build-defs.js +233 -0
  125. package/src/editor/js/libs/ternjs/comment.js +87 -0
  126. package/src/editor/js/libs/ternjs/def.js +588 -0
  127. package/src/editor/js/libs/ternjs/doc_comment.js +401 -0
  128. package/src/editor/js/libs/ternjs/infer.js +1635 -0
  129. package/src/editor/js/libs/ternjs/polyfill.js +80 -0
  130. package/src/editor/js/libs/ternjs/signal.js +26 -0
  131. package/src/editor/js/libs/ternjs/tern.js +993 -0
  132. package/src/editor/js/libs/ui.js +1305 -0
  133. package/src/editor/js/libs/ui.three.js +946 -0
  134. package/src/events.js +273 -0
  135. package/src/index.js +284 -0
  136. package/src/presets/machines.js +239 -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,559 @@
1
+ import * as THREE from 'three';
2
+
3
+ import { UIPanel, UIRow } from './libs/ui.js';
4
+
5
+ import { AddObjectCommand } from './commands/AddObjectCommand.js';
6
+ import { MultiCmdsCommand } from './commands/MultiCmdsCommand.js';
7
+
8
+ import { FontLoader } from 'three/addons/loaders/FontLoader.js';
9
+ import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
10
+
11
+ function MenubarAdd( editor ) {
12
+
13
+ const strings = editor.strings;
14
+
15
+ const container = new UIPanel();
16
+ container.setClass( 'menu' );
17
+
18
+ const title = new UIPanel();
19
+ title.setClass( 'title' );
20
+ title.setTextContent( strings.getKey( 'menubar/add' ) );
21
+ container.add( title );
22
+
23
+ const options = new UIPanel();
24
+ options.setClass( 'options' );
25
+ container.add( options );
26
+
27
+ // Group
28
+
29
+ let option = new UIRow();
30
+ option.setClass( 'option' );
31
+ option.setTextContent( strings.getKey( 'menubar/add/group' ) );
32
+ option.onClick( function () {
33
+
34
+ const mesh = new THREE.Group();
35
+ mesh.name = 'Group';
36
+
37
+ editor.execute( new AddObjectCommand( editor, mesh ) );
38
+
39
+ } );
40
+ options.add( option );
41
+
42
+ // Mesh
43
+
44
+ const meshSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/mesh' ) ).addClass( 'option' ).addClass( 'submenu-title' );
45
+ meshSubmenuTitle.onMouseOver( function () {
46
+
47
+ const { top, right } = meshSubmenuTitle.dom.getBoundingClientRect();
48
+ const { paddingTop } = getComputedStyle( this.dom );
49
+ meshSubmenu.setLeft( right + 'px' );
50
+ meshSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
51
+ meshSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
52
+ meshSubmenu.setDisplay( 'block' );
53
+
54
+ } );
55
+ meshSubmenuTitle.onMouseOut( function () {
56
+
57
+ meshSubmenu.setDisplay( 'none' );
58
+
59
+ } );
60
+ options.add( meshSubmenuTitle );
61
+
62
+ const meshSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
63
+ meshSubmenuTitle.add( meshSubmenu );
64
+
65
+ // Mesh / Box
66
+
67
+ option = new UIRow();
68
+ option.setClass( 'option' );
69
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/box' ) );
70
+ option.onClick( function () {
71
+
72
+ const geometry = new THREE.BoxGeometry( 1, 1, 1, 1, 1, 1 );
73
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
74
+ mesh.name = 'Box';
75
+
76
+ editor.execute( new AddObjectCommand( editor, mesh ) );
77
+
78
+ } );
79
+ meshSubmenu.add( option );
80
+
81
+ // Mesh / Capsule
82
+
83
+ option = new UIRow();
84
+ option.setClass( 'option' );
85
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/capsule' ) );
86
+ option.onClick( function () {
87
+
88
+ const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8, 1 );
89
+ const material = new THREE.MeshStandardMaterial();
90
+ const mesh = new THREE.Mesh( geometry, material );
91
+ mesh.name = 'Capsule';
92
+
93
+ editor.execute( new AddObjectCommand( editor, mesh ) );
94
+
95
+ } );
96
+ meshSubmenu.add( option );
97
+
98
+ // Mesh / Circle
99
+
100
+ option = new UIRow();
101
+ option.setClass( 'option' );
102
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/circle' ) );
103
+ option.onClick( function () {
104
+
105
+ const geometry = new THREE.CircleGeometry( 1, 32, 0, Math.PI * 2 );
106
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
107
+ mesh.name = 'Circle';
108
+
109
+ editor.execute( new AddObjectCommand( editor, mesh ) );
110
+
111
+ } );
112
+ meshSubmenu.add( option );
113
+
114
+ // Mesh / Cylinder
115
+
116
+ option = new UIRow();
117
+ option.setClass( 'option' );
118
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/cylinder' ) );
119
+ option.onClick( function () {
120
+
121
+ const geometry = new THREE.CylinderGeometry( 1, 1, 1, 32, 1, false, 0, Math.PI * 2 );
122
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
123
+ mesh.name = 'Cylinder';
124
+
125
+ editor.execute( new AddObjectCommand( editor, mesh ) );
126
+
127
+ } );
128
+ meshSubmenu.add( option );
129
+
130
+ // Mesh / Dodecahedron
131
+
132
+ option = new UIRow();
133
+ option.setClass( 'option' );
134
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/dodecahedron' ) );
135
+ option.onClick( function () {
136
+
137
+ const geometry = new THREE.DodecahedronGeometry( 1, 0 );
138
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
139
+ mesh.name = 'Dodecahedron';
140
+
141
+ editor.execute( new AddObjectCommand( editor, mesh ) );
142
+
143
+ } );
144
+ meshSubmenu.add( option );
145
+
146
+ // Mesh / Icosahedron
147
+
148
+ option = new UIRow();
149
+ option.setClass( 'option' );
150
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/icosahedron' ) );
151
+ option.onClick( function () {
152
+
153
+ const geometry = new THREE.IcosahedronGeometry( 1, 0 );
154
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
155
+ mesh.name = 'Icosahedron';
156
+
157
+ editor.execute( new AddObjectCommand( editor, mesh ) );
158
+
159
+ } );
160
+ meshSubmenu.add( option );
161
+
162
+ // Mesh / Lathe
163
+
164
+ option = new UIRow();
165
+ option.setClass( 'option' );
166
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/lathe' ) );
167
+ option.onClick( function () {
168
+
169
+ const geometry = new THREE.LatheGeometry();
170
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial( { side: THREE.DoubleSide } ) );
171
+ mesh.name = 'Lathe';
172
+
173
+ editor.execute( new AddObjectCommand( editor, mesh ) );
174
+
175
+ } );
176
+ meshSubmenu.add( option );
177
+
178
+ // Mesh / Octahedron
179
+
180
+ option = new UIRow();
181
+ option.setClass( 'option' );
182
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/octahedron' ) );
183
+ option.onClick( function () {
184
+
185
+ const geometry = new THREE.OctahedronGeometry( 1, 0 );
186
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
187
+ mesh.name = 'Octahedron';
188
+
189
+ editor.execute( new AddObjectCommand( editor, mesh ) );
190
+
191
+ } );
192
+ meshSubmenu.add( option );
193
+
194
+ // Mesh / Plane
195
+
196
+ option = new UIRow();
197
+ option.setClass( 'option' );
198
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/plane' ) );
199
+ option.onClick( function () {
200
+
201
+ const geometry = new THREE.PlaneGeometry( 1, 1, 1, 1 );
202
+ const material = new THREE.MeshStandardMaterial();
203
+ const mesh = new THREE.Mesh( geometry, material );
204
+ mesh.name = 'Plane';
205
+
206
+ editor.execute( new AddObjectCommand( editor, mesh ) );
207
+
208
+ } );
209
+ meshSubmenu.add( option );
210
+
211
+ // Mesh / Ring
212
+
213
+ option = new UIRow();
214
+ option.setClass( 'option' );
215
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/ring' ) );
216
+ option.onClick( function () {
217
+
218
+ const geometry = new THREE.RingGeometry( 0.5, 1, 32, 1, 0, Math.PI * 2 );
219
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
220
+ mesh.name = 'Ring';
221
+
222
+ editor.execute( new AddObjectCommand( editor, mesh ) );
223
+
224
+ } );
225
+ meshSubmenu.add( option );
226
+
227
+ // Mesh / Sphere
228
+
229
+ option = new UIRow();
230
+ option.setClass( 'option' );
231
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/sphere' ) );
232
+ option.onClick( function () {
233
+
234
+ const geometry = new THREE.SphereGeometry( 1, 32, 16, 0, Math.PI * 2, 0, Math.PI );
235
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
236
+ mesh.name = 'Sphere';
237
+
238
+ editor.execute( new AddObjectCommand( editor, mesh ) );
239
+
240
+ } );
241
+ meshSubmenu.add( option );
242
+
243
+ // Mesh / Sprite
244
+
245
+ option = new UIRow();
246
+ option.setClass( 'option' );
247
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/sprite' ) );
248
+ option.onClick( function () {
249
+
250
+ const sprite = new THREE.Sprite( new THREE.SpriteMaterial() );
251
+ sprite.name = 'Sprite';
252
+
253
+ editor.execute( new AddObjectCommand( editor, sprite ) );
254
+
255
+ } );
256
+ meshSubmenu.add( option );
257
+
258
+ // Mesh / Tetrahedron
259
+
260
+ option = new UIRow();
261
+ option.setClass( 'option' );
262
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/tetrahedron' ) );
263
+ option.onClick( function () {
264
+
265
+ const geometry = new THREE.TetrahedronGeometry( 1, 0 );
266
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
267
+ mesh.name = 'Tetrahedron';
268
+
269
+ editor.execute( new AddObjectCommand( editor, mesh ) );
270
+
271
+ } );
272
+ meshSubmenu.add( option );
273
+
274
+ // Mesh / Text
275
+
276
+ option = new UIRow();
277
+ option.setClass( 'option' );
278
+ option.setTextContent( strings.getKey( 'menubar/add/text' ) );
279
+ option.onClick( function () {
280
+
281
+ const loader = new FontLoader();
282
+ loader.load( '../examples/fonts/helvetiker_bold.typeface.json', function ( font ) {
283
+
284
+ const text = 'THREE.JS';
285
+
286
+ const geometry = new TextGeometry( text, {
287
+ text: text,
288
+ font,
289
+ size: 1,
290
+ depth: 0.5,
291
+ curveSegments: 4,
292
+
293
+ bevelEnabled: false,
294
+ bevelThickness: 0.1,
295
+ bevelSize: 0.01,
296
+ bevelOffset: 0,
297
+ bevelSegments: 3
298
+
299
+ } );
300
+
301
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
302
+ mesh.name = 'Text';
303
+
304
+ editor.execute( new AddObjectCommand( editor, mesh ) );
305
+
306
+ } );
307
+
308
+ } );
309
+ meshSubmenu.add( option );
310
+
311
+ // Mesh / Torus
312
+
313
+ option = new UIRow();
314
+ option.setClass( 'option' );
315
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/torus' ) );
316
+ option.onClick( function () {
317
+
318
+ const geometry = new THREE.TorusGeometry( 1, 0.4, 12, 48, Math.PI * 2 );
319
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
320
+ mesh.name = 'Torus';
321
+
322
+ editor.execute( new AddObjectCommand( editor, mesh ) );
323
+
324
+ } );
325
+ meshSubmenu.add( option );
326
+
327
+ // Mesh / TorusKnot
328
+
329
+ option = new UIRow();
330
+ option.setClass( 'option' );
331
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/torusknot' ) );
332
+ option.onClick( function () {
333
+
334
+ const geometry = new THREE.TorusKnotGeometry( 1, 0.4, 64, 8, 2, 3 );
335
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
336
+ mesh.name = 'TorusKnot';
337
+
338
+ editor.execute( new AddObjectCommand( editor, mesh ) );
339
+
340
+ } );
341
+ meshSubmenu.add( option );
342
+
343
+ // Mesh / Tube
344
+
345
+ option = new UIRow();
346
+ option.setClass( 'option' );
347
+ option.setTextContent( strings.getKey( 'menubar/add/mesh/tube' ) );
348
+ option.onClick( function () {
349
+
350
+ const path = new THREE.CatmullRomCurve3( [
351
+ new THREE.Vector3( 2, 2, - 2 ),
352
+ new THREE.Vector3( 2, - 2, - 0.6666666666666667 ),
353
+ new THREE.Vector3( - 2, - 2, 0.6666666666666667 ),
354
+ new THREE.Vector3( - 2, 2, 2 )
355
+ ] );
356
+
357
+ const geometry = new THREE.TubeGeometry( path, 64, 1, 8, false );
358
+ const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
359
+ mesh.name = 'Tube';
360
+
361
+ editor.execute( new AddObjectCommand( editor, mesh ) );
362
+
363
+ } );
364
+ meshSubmenu.add( option );
365
+
366
+ // Light
367
+
368
+ const lightSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/light' ) ).addClass( 'option' ).addClass( 'submenu-title' );
369
+ lightSubmenuTitle.onMouseOver( function () {
370
+
371
+ const { top, right } = lightSubmenuTitle.dom.getBoundingClientRect();
372
+ const { paddingTop } = getComputedStyle( this.dom );
373
+
374
+ lightSubmenu.setLeft( right + 'px' );
375
+ lightSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
376
+ lightSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
377
+ lightSubmenu.setDisplay( 'block' );
378
+
379
+ } );
380
+ lightSubmenuTitle.onMouseOut( function () {
381
+
382
+ lightSubmenu.setDisplay( 'none' );
383
+
384
+ } );
385
+ options.add( lightSubmenuTitle );
386
+
387
+ const lightSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
388
+ lightSubmenuTitle.add( lightSubmenu );
389
+
390
+ // Light / Ambient
391
+
392
+ option = new UIRow();
393
+ option.setClass( 'option' );
394
+ option.setTextContent( strings.getKey( 'menubar/add/light/ambient' ) );
395
+ option.onClick( function () {
396
+
397
+ const color = 0x222222;
398
+
399
+ const light = new THREE.AmbientLight( color );
400
+ light.name = 'AmbientLight';
401
+
402
+ editor.execute( new AddObjectCommand( editor, light ) );
403
+
404
+ } );
405
+ lightSubmenu.add( option );
406
+
407
+ // Light / Directional
408
+
409
+ option = new UIRow();
410
+ option.setClass( 'option' );
411
+ option.setTextContent( strings.getKey( 'menubar/add/light/directional' ) );
412
+ option.onClick( function () {
413
+
414
+ const color = 0xffffff;
415
+ const intensity = 1;
416
+
417
+ const light = new THREE.DirectionalLight( color, intensity );
418
+ light.name = 'DirectionalLight';
419
+ light.target.name = 'DirectionalLight Target';
420
+
421
+ light.position.set( 5, 10, 7.5 );
422
+
423
+ editor.execute( new MultiCmdsCommand( editor, [
424
+ new AddObjectCommand( editor, light.target ),
425
+ new AddObjectCommand( editor, light )
426
+ ] ) );
427
+
428
+ } );
429
+ lightSubmenu.add( option );
430
+
431
+ // Light / Hemisphere
432
+
433
+ option = new UIRow();
434
+ option.setClass( 'option' );
435
+ option.setTextContent( strings.getKey( 'menubar/add/light/hemisphere' ) );
436
+ option.onClick( function () {
437
+
438
+ const skyColor = 0x00aaff;
439
+ const groundColor = 0xffaa00;
440
+ const intensity = 1;
441
+
442
+ const light = new THREE.HemisphereLight( skyColor, groundColor, intensity );
443
+ light.name = 'HemisphereLight';
444
+
445
+ light.position.set( 0, 10, 0 );
446
+
447
+ editor.execute( new AddObjectCommand( editor, light ) );
448
+
449
+ } );
450
+ lightSubmenu.add( option );
451
+
452
+ // Light / Point
453
+
454
+ option = new UIRow();
455
+ option.setClass( 'option' );
456
+ option.setTextContent( strings.getKey( 'menubar/add/light/point' ) );
457
+ option.onClick( function () {
458
+
459
+ const color = 0xffffff;
460
+ const intensity = 1;
461
+ const distance = 0;
462
+
463
+ const light = new THREE.PointLight( color, intensity, distance );
464
+ light.name = 'PointLight';
465
+
466
+ editor.execute( new AddObjectCommand( editor, light ) );
467
+
468
+ } );
469
+ lightSubmenu.add( option );
470
+
471
+ // Light / Spot
472
+
473
+ option = new UIRow();
474
+ option.setClass( 'option' );
475
+ option.setTextContent( strings.getKey( 'menubar/add/light/spot' ) );
476
+ option.onClick( function () {
477
+
478
+ const color = 0xffffff;
479
+ const intensity = 1;
480
+ const distance = 0;
481
+ const angle = Math.PI * 0.1;
482
+ const penumbra = 0;
483
+
484
+ const light = new THREE.SpotLight( color, intensity, distance, angle, penumbra );
485
+ light.name = 'SpotLight';
486
+ light.target.name = 'SpotLight Target';
487
+
488
+ light.position.set( 5, 10, 7.5 );
489
+
490
+ editor.execute( new MultiCmdsCommand( editor, [
491
+ new AddObjectCommand( editor, light.target ),
492
+ new AddObjectCommand( editor, light )
493
+ ] ) );
494
+
495
+ } );
496
+ lightSubmenu.add( option );
497
+
498
+ // Camera
499
+
500
+ const cameraSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/add/camera' ) ).addClass( 'option' ).addClass( 'submenu-title' );
501
+ cameraSubmenuTitle.onMouseOver( function () {
502
+
503
+ const { top, right } = cameraSubmenuTitle.dom.getBoundingClientRect();
504
+ const { paddingTop } = getComputedStyle( this.dom );
505
+
506
+ cameraSubmenu.setLeft( right + 'px' );
507
+ cameraSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
508
+ cameraSubmenu.setStyle( 'max-height', [ `calc( 100vh - ${top}px )` ] );
509
+ cameraSubmenu.setDisplay( 'block' );
510
+
511
+ } );
512
+ cameraSubmenuTitle.onMouseOut( function () {
513
+
514
+ cameraSubmenu.setDisplay( 'none' );
515
+
516
+ } );
517
+ options.add( cameraSubmenuTitle );
518
+
519
+ const cameraSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
520
+ cameraSubmenuTitle.add( cameraSubmenu );
521
+
522
+ // Camera / Orthographic
523
+
524
+ option = new UIRow();
525
+ option.setClass( 'option' );
526
+ option.setTextContent( strings.getKey( 'menubar/add/camera/orthographic' ) );
527
+ option.onClick( function () {
528
+
529
+ const aspect = editor.camera.isPerspectiveCamera
530
+ ? editor.camera.aspect
531
+ : ( editor.camera.right - editor.camera.left ) / ( editor.camera.top - editor.camera.bottom );
532
+ const camera = new THREE.OrthographicCamera( - aspect, aspect );
533
+ camera.name = 'OrthographicCamera';
534
+
535
+ editor.execute( new AddObjectCommand( editor, camera ) );
536
+
537
+ } );
538
+ cameraSubmenu.add( option );
539
+
540
+ // Camera / Perspective
541
+
542
+ option = new UIRow();
543
+ option.setClass( 'option' );
544
+ option.setTextContent( strings.getKey( 'menubar/add/camera/perspective' ) );
545
+ option.onClick( function () {
546
+
547
+ const camera = new THREE.PerspectiveCamera();
548
+ camera.name = 'PerspectiveCamera';
549
+
550
+ editor.execute( new AddObjectCommand( editor, camera ) );
551
+
552
+ } );
553
+ cameraSubmenu.add( option );
554
+
555
+ return container;
556
+
557
+ }
558
+
559
+ export { MenubarAdd };