@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,532 @@
1
+ import { UIElement, UIPanel, UIText } from './libs/ui.js';
2
+
3
+ import { SetScriptValueCommand } from './commands/SetScriptValueCommand.js';
4
+ import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
5
+
6
+ import buildThreeDefs from './libs/tern-threejs/build-defs.js';
7
+
8
+ function Script( editor ) {
9
+
10
+ const signals = editor.signals;
11
+ const strings = editor.strings;
12
+
13
+ const container = new UIPanel();
14
+ container.setId( 'script' );
15
+ container.setPosition( 'absolute' );
16
+ container.setBackgroundColor( '#272822' );
17
+ container.setDisplay( 'none' );
18
+
19
+ const header = new UIPanel();
20
+ header.setPadding( '10px' );
21
+ container.add( header );
22
+
23
+ const title = new UIText().setColor( '#fff' );
24
+ header.add( title );
25
+
26
+ const buttonSVG = ( function () {
27
+
28
+ const svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
29
+ svg.setAttribute( 'width', 32 );
30
+ svg.setAttribute( 'height', 32 );
31
+ const path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
32
+ path.setAttribute( 'd', 'M 12,12 L 22,22 M 22,12 12,22' );
33
+ path.setAttribute( 'stroke', '#fff' );
34
+ svg.appendChild( path );
35
+ return svg;
36
+
37
+ } )();
38
+
39
+ const close = new UIElement( buttonSVG );
40
+ close.setPosition( 'absolute' );
41
+ close.setTop( '3px' );
42
+ close.setRight( '1px' );
43
+ close.setCursor( 'pointer' );
44
+ close.onClick( function () {
45
+
46
+ container.setDisplay( 'none' );
47
+
48
+ } );
49
+ header.add( close );
50
+
51
+
52
+ let renderer;
53
+
54
+ signals.rendererCreated.add( function ( newRenderer ) {
55
+
56
+ renderer = newRenderer;
57
+
58
+ } );
59
+
60
+
61
+ let delay;
62
+ let currentMode;
63
+ let currentScript;
64
+ let currentObject;
65
+
66
+ const codemirror = CodeMirror( container.dom, {
67
+ value: '',
68
+ lineNumbers: true,
69
+ matchBrackets: true,
70
+ indentWithTabs: true,
71
+ tabSize: 4,
72
+ indentUnit: 4,
73
+ hintOptions: {
74
+ completeSingle: false
75
+ }
76
+ } );
77
+ codemirror.setOption( 'theme', 'monokai' );
78
+ codemirror.on( 'change', function () {
79
+
80
+ if ( codemirror.state.focused === false ) return;
81
+
82
+ clearTimeout( delay );
83
+ delay = setTimeout( function () {
84
+
85
+ const value = codemirror.getValue();
86
+
87
+ if ( ! validate( value ) ) return;
88
+
89
+ if ( typeof ( currentScript ) === 'object' ) {
90
+
91
+ if ( value !== currentScript.source ) {
92
+
93
+ editor.execute( new SetScriptValueCommand( editor, currentObject, currentScript, 'source', value ) );
94
+
95
+ }
96
+
97
+ return;
98
+
99
+ }
100
+
101
+ if ( currentScript !== 'programInfo' ) return;
102
+
103
+ const json = JSON.parse( value );
104
+
105
+ if ( JSON.stringify( currentObject.material.defines ) !== JSON.stringify( json.defines ) ) {
106
+
107
+ const cmd = new SetMaterialValueCommand( editor, currentObject, 'defines', json.defines );
108
+ cmd.updatable = false;
109
+ editor.execute( cmd );
110
+
111
+ }
112
+
113
+ if ( JSON.stringify( currentObject.material.uniforms ) !== JSON.stringify( json.uniforms ) ) {
114
+
115
+ const cmd = new SetMaterialValueCommand( editor, currentObject, 'uniforms', json.uniforms );
116
+ cmd.updatable = false;
117
+ editor.execute( cmd );
118
+
119
+ }
120
+
121
+ if ( JSON.stringify( currentObject.material.attributes ) !== JSON.stringify( json.attributes ) ) {
122
+
123
+ const cmd = new SetMaterialValueCommand( editor, currentObject, 'attributes', json.attributes );
124
+ cmd.updatable = false;
125
+ editor.execute( cmd );
126
+
127
+ }
128
+
129
+ }, 300 );
130
+
131
+ } );
132
+
133
+ // prevent backspace from deleting objects
134
+ const wrapper = codemirror.getWrapperElement();
135
+ wrapper.addEventListener( 'keydown', function ( event ) {
136
+
137
+ event.stopPropagation();
138
+
139
+ } );
140
+
141
+ // validate
142
+
143
+ const errorLines = [];
144
+ const widgets = [];
145
+
146
+ const validate = function ( string ) {
147
+
148
+ let valid;
149
+ let errors = [];
150
+
151
+ return codemirror.operation( function () {
152
+
153
+ while ( errorLines.length > 0 ) {
154
+
155
+ codemirror.removeLineClass( errorLines.shift(), 'background', 'errorLine' );
156
+
157
+ }
158
+
159
+ while ( widgets.length > 0 ) {
160
+
161
+ codemirror.removeLineWidget( widgets.shift() );
162
+
163
+ }
164
+
165
+ //
166
+
167
+ switch ( currentMode ) {
168
+
169
+ case 'javascript':
170
+
171
+ try {
172
+
173
+ const syntax = esprima.parse( string, { tolerant: true } );
174
+ errors = syntax.errors;
175
+
176
+ } catch ( error ) {
177
+
178
+ errors.push( {
179
+
180
+ lineNumber: error.lineNumber - 1,
181
+ message: error.message
182
+
183
+ } );
184
+
185
+ }
186
+
187
+ for ( let i = 0; i < errors.length; i ++ ) {
188
+
189
+ const error = errors[ i ];
190
+ error.message = error.message.replace( /Line [0-9]+: /, '' );
191
+
192
+ }
193
+
194
+ break;
195
+
196
+ case 'json':
197
+
198
+ errors = [];
199
+
200
+ jsonlint.parseError = function ( message, info ) {
201
+
202
+ message = message.split( '\n' )[ 3 ];
203
+
204
+ errors.push( {
205
+
206
+ lineNumber: info.loc.first_line - 1,
207
+ message: message
208
+
209
+ } );
210
+
211
+ };
212
+
213
+ try {
214
+
215
+ jsonlint.parse( string );
216
+
217
+ } catch ( error ) {
218
+
219
+ // ignore failed error recovery
220
+
221
+ }
222
+
223
+ break;
224
+
225
+ case 'glsl':
226
+
227
+ currentObject.material[ currentScript ] = string;
228
+ currentObject.material.needsUpdate = true;
229
+ signals.materialChanged.dispatch( currentObject, 0 ); // TODO: Add multi-material support
230
+
231
+ const programs = renderer.info.programs;
232
+
233
+ valid = true;
234
+ const parseMessage = /^(?:ERROR|WARNING): \d+:(\d+): (.*)/g;
235
+
236
+ for ( let i = 0, n = programs.length; i !== n; ++ i ) {
237
+
238
+ const diagnostics = programs[ i ].diagnostics;
239
+
240
+ if ( diagnostics === undefined ||
241
+ diagnostics.material !== currentObject.material ) continue;
242
+
243
+ if ( ! diagnostics.runnable ) valid = false;
244
+
245
+ const shaderInfo = diagnostics[ currentScript ];
246
+ const lineOffset = shaderInfo.prefix.split( /\r\n|\r|\n/ ).length;
247
+
248
+ while ( true ) {
249
+
250
+ const parseResult = parseMessage.exec( shaderInfo.log );
251
+ if ( parseResult === null ) break;
252
+
253
+ errors.push( {
254
+
255
+ lineNumber: parseResult[ 1 ] - lineOffset,
256
+ message: parseResult[ 2 ]
257
+
258
+ } );
259
+
260
+ } // messages
261
+
262
+ break;
263
+
264
+ } // programs
265
+
266
+ } // mode switch
267
+
268
+ for ( let i = 0; i < errors.length; i ++ ) {
269
+
270
+ const error = errors[ i ];
271
+
272
+ const message = document.createElement( 'div' );
273
+ message.className = 'esprima-error';
274
+ message.textContent = error.message;
275
+
276
+ const lineNumber = Math.max( error.lineNumber, 0 );
277
+ errorLines.push( lineNumber );
278
+
279
+ codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
280
+
281
+ const widget = codemirror.addLineWidget( lineNumber, message );
282
+
283
+ widgets.push( widget );
284
+
285
+ }
286
+
287
+ return valid !== undefined ? valid : errors.length === 0;
288
+
289
+ } );
290
+
291
+ };
292
+
293
+ // tern js autocomplete
294
+
295
+ const server = new CodeMirror.TernServer( {
296
+ caseInsensitive: true
297
+ } );
298
+
299
+ // The three.js API definitions are built lazily from the JSDoc in the library
300
+ // build the first time the script editor is opened.
301
+
302
+ let threeDefsRequested = false;
303
+
304
+ async function loadThreeDefs() {
305
+
306
+ if ( threeDefsRequested ) return;
307
+ threeDefsRequested = true;
308
+
309
+ try {
310
+
311
+ const url = new URL( '../build/three.core.js', document.baseURI ).href;
312
+ const source = await ( await fetch( url ) ).text();
313
+
314
+ server.server.defs.push( buildThreeDefs( source ) );
315
+ server.server.reset();
316
+
317
+ } catch ( error ) {
318
+
319
+ console.warn( 'Script: Failed to build three.js autocomplete defs.', error );
320
+
321
+ }
322
+
323
+ }
324
+
325
+ codemirror.setOption( 'extraKeys', {
326
+ 'Ctrl-Space': function ( cm ) {
327
+
328
+ server.complete( cm );
329
+
330
+ },
331
+ 'Ctrl-I': function ( cm ) {
332
+
333
+ server.showType( cm );
334
+
335
+ },
336
+ 'Ctrl-O': function ( cm ) {
337
+
338
+ server.showDocs( cm );
339
+
340
+ },
341
+ 'Alt-.': function ( cm ) {
342
+
343
+ server.jumpToDef( cm );
344
+
345
+ },
346
+ 'Alt-,': function ( cm ) {
347
+
348
+ server.jumpBack( cm );
349
+
350
+ },
351
+ 'Ctrl-Q': function ( cm ) {
352
+
353
+ server.rename( cm );
354
+
355
+ },
356
+ 'Ctrl-.': function ( cm ) {
357
+
358
+ server.selectName( cm );
359
+
360
+ }
361
+ } );
362
+
363
+ codemirror.on( 'cursorActivity', function ( cm ) {
364
+
365
+ if ( currentMode !== 'javascript' ) return;
366
+ server.updateArgHints( cm );
367
+
368
+ } );
369
+
370
+ codemirror.on( 'keypress', function ( cm, kb ) {
371
+
372
+ if ( currentMode !== 'javascript' ) return;
373
+ if ( /[\w\.]/.exec( kb.key ) ) {
374
+
375
+ server.complete( cm );
376
+
377
+ }
378
+
379
+ } );
380
+
381
+
382
+ //
383
+
384
+ signals.editorCleared.add( function () {
385
+
386
+ container.setDisplay( 'none' );
387
+
388
+ } );
389
+
390
+ function setTitle( object, script ) {
391
+
392
+ if ( typeof script === 'object' ) {
393
+
394
+ title.setValue( object.name + ' / ' + script.name );
395
+
396
+ } else {
397
+
398
+ switch ( script ) {
399
+
400
+ case 'vertexShader':
401
+
402
+ title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/vertexShader' ) );
403
+ break;
404
+
405
+ case 'fragmentShader':
406
+
407
+ title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/fragmentShader' ) );
408
+ break;
409
+
410
+ case 'programInfo':
411
+
412
+ title.setValue( object.material.name + ' / ' + strings.getKey( 'script/title/programInfo' ) );
413
+ break;
414
+
415
+ default:
416
+
417
+ throw new Error( 'setTitle: Unknown script' );
418
+
419
+ }
420
+
421
+ }
422
+
423
+ }
424
+
425
+ signals.editScript.add( function ( object, script ) {
426
+
427
+ let mode, source;
428
+
429
+ if ( typeof ( script ) === 'object' ) {
430
+
431
+ mode = 'javascript';
432
+ source = script.source;
433
+
434
+ } else {
435
+
436
+ switch ( script ) {
437
+
438
+ case 'vertexShader':
439
+
440
+ mode = 'glsl';
441
+ source = object.material.vertexShader || '';
442
+
443
+ break;
444
+
445
+ case 'fragmentShader':
446
+
447
+ mode = 'glsl';
448
+ source = object.material.fragmentShader || '';
449
+
450
+ break;
451
+
452
+ case 'programInfo':
453
+
454
+ mode = 'json';
455
+ const json = {
456
+ defines: object.material.defines,
457
+ uniforms: object.material.uniforms,
458
+ attributes: object.material.attributes
459
+ };
460
+ source = JSON.stringify( json, null, '\t' );
461
+
462
+ break;
463
+
464
+ default:
465
+
466
+ throw new Error( 'editScript: Unknown script' );
467
+
468
+ }
469
+
470
+ }
471
+
472
+ setTitle( object, script );
473
+
474
+ currentMode = mode;
475
+ currentScript = script;
476
+ currentObject = object;
477
+
478
+ if ( mode === 'javascript' ) loadThreeDefs();
479
+
480
+ container.setDisplay( '' );
481
+ codemirror.setValue( source );
482
+ codemirror.clearHistory();
483
+ if ( mode === 'json' ) mode = { name: 'javascript', json: true };
484
+ codemirror.setOption( 'mode', mode );
485
+
486
+ } );
487
+
488
+ signals.scriptRemoved.add( function ( script ) {
489
+
490
+ if ( currentScript === script ) {
491
+
492
+ container.setDisplay( 'none' );
493
+
494
+ }
495
+
496
+ } );
497
+
498
+ signals.objectChanged.add( function ( object ) {
499
+
500
+ if ( object !== currentObject ) return;
501
+
502
+ if ( [ 'programInfo', 'vertexShader', 'fragmentShader' ].includes( currentScript ) ) return;
503
+
504
+ setTitle( currentObject, currentScript );
505
+
506
+ } );
507
+
508
+ signals.scriptChanged.add( function ( script ) {
509
+
510
+ if ( script === currentScript ) {
511
+
512
+ setTitle( currentObject, currentScript );
513
+
514
+ }
515
+
516
+ } );
517
+
518
+ signals.materialChanged.add( function ( object/*, slot */ ) {
519
+
520
+ if ( object !== currentObject ) return;
521
+
522
+ // TODO: Adds multi-material support
523
+
524
+ setTitle( currentObject, currentScript );
525
+
526
+ } );
527
+
528
+ return container;
529
+
530
+ }
531
+
532
+ export { Script };
@@ -0,0 +1,129 @@
1
+ import * as THREE from 'three';
2
+
3
+ const mouse = new THREE.Vector2();
4
+ const raycaster = new THREE.Raycaster();
5
+
6
+ class Selector {
7
+
8
+ constructor( editor ) {
9
+
10
+ const signals = editor.signals;
11
+
12
+ this.editor = editor;
13
+ this.signals = signals;
14
+
15
+ // signals
16
+
17
+ signals.intersectionsDetected.add( ( intersects ) => {
18
+
19
+ if ( intersects.length > 0 ) {
20
+
21
+ // Resolve helpers to their actual objects
22
+
23
+ const objects = [];
24
+
25
+ for ( let i = 0; i < intersects.length; i ++ ) {
26
+
27
+ let object = intersects[ i ].object;
28
+
29
+ if ( object.userData.object !== undefined ) {
30
+
31
+ object = object.userData.object;
32
+
33
+ }
34
+
35
+ if ( objects.indexOf( object ) === - 1 ) {
36
+
37
+ objects.push( object );
38
+
39
+ }
40
+
41
+ }
42
+
43
+ // Cycle through objects if the first one is already selected
44
+
45
+ const index = objects.indexOf( editor.selected );
46
+
47
+ if ( index !== - 1 && index < objects.length - 1 ) {
48
+
49
+ this.select( objects[ index + 1 ] );
50
+
51
+ } else {
52
+
53
+ this.select( objects[ 0 ] );
54
+
55
+ }
56
+
57
+ } else {
58
+
59
+ this.select( null );
60
+
61
+ }
62
+
63
+ } );
64
+
65
+ }
66
+
67
+ getIntersects( raycaster ) {
68
+
69
+ const objects = [];
70
+
71
+ this.editor.scene.traverseVisible( function ( child ) {
72
+
73
+ objects.push( child );
74
+
75
+ } );
76
+
77
+ this.editor.sceneHelpers.traverseVisible( function ( child ) {
78
+
79
+ if ( child.name === 'picker' ) objects.push( child );
80
+
81
+ } );
82
+
83
+ return raycaster.intersectObjects( objects, false );
84
+
85
+ }
86
+
87
+ getPointerIntersects( point, camera ) {
88
+
89
+ mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
90
+
91
+ raycaster.setFromCamera( mouse, camera );
92
+
93
+ return this.getIntersects( raycaster );
94
+
95
+ }
96
+
97
+ select( object ) {
98
+
99
+ if ( this.editor.selected === object ) return;
100
+
101
+ let uuid = null;
102
+
103
+ if ( object !== null ) {
104
+
105
+ uuid = object.uuid;
106
+
107
+ }
108
+
109
+ this.editor.selected = object;
110
+ this.editor.config.setKey( 'selected', uuid );
111
+
112
+ // single-select clears any multi-selection (Spline-like)
113
+ if ( object !== null ) this.editor.selectedObjects = [ object ];
114
+ else this.editor.selectedObjects = [];
115
+
116
+ this.signals.objectSelected.dispatch( object );
117
+ this.signals.objectMultiSelected.dispatch( this.editor.selectedObjects );
118
+
119
+ }
120
+
121
+ deselect() {
122
+
123
+ this.select( null );
124
+
125
+ }
126
+
127
+ }
128
+
129
+ export { Selector };