@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,982 @@
1
+ import * as THREE from 'three';
2
+
3
+ import { TransformControls } from 'three/addons/controls/TransformControls.js';
4
+
5
+ import { UIPanel } from './libs/ui.js';
6
+
7
+ import { EditorControls } from './EditorControls.js';
8
+
9
+ import { ViewportControls } from './Viewport.Controls.js';
10
+ import { ViewportInfo } from './Viewport.Info.js';
11
+
12
+ import { ViewHelper } from './Viewport.ViewHelper.js';
13
+ import { XR } from './Viewport.XR.js';
14
+
15
+ import { SetPositionCommand } from './commands/SetPositionCommand.js';
16
+ import { SetRotationCommand } from './commands/SetRotationCommand.js';
17
+ import { SetScaleCommand } from './commands/SetScaleCommand.js';
18
+
19
+ import { ColorEnvironment } from 'three/addons/environments/ColorEnvironment.js';
20
+ import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
21
+ import { ViewportPathtracer } from './Viewport.Pathtracer.js';
22
+
23
+ function Viewport( editor ) {
24
+
25
+ const selector = editor.selector;
26
+ const signals = editor.signals;
27
+
28
+ const container = new UIPanel();
29
+ container.setId( 'viewport' );
30
+ container.setPosition( 'absolute' );
31
+
32
+ container.add( new ViewportControls( editor ) );
33
+ container.add( new ViewportInfo( editor ) );
34
+
35
+ //
36
+
37
+ let renderer = null;
38
+ let pmremGenerator = null;
39
+ let pathtracer = null;
40
+
41
+ let camera = editor.camera;
42
+ const scene = editor.scene;
43
+ const sceneHelpers = editor.sceneHelpers;
44
+
45
+ // helpers
46
+
47
+ const GRID_COLORS_LIGHT = [ 0x999999, 0x777777 ];
48
+ const GRID_COLORS_DARK = [ 0x555555, 0x888888 ];
49
+
50
+ const grid = new THREE.Group();
51
+
52
+ const grid1 = new THREE.GridHelper( 30, 30 );
53
+ grid1.material.color.setHex( GRID_COLORS_LIGHT[ 0 ] );
54
+ grid1.material.vertexColors = false;
55
+ grid.add( grid1 );
56
+
57
+ const grid2 = new THREE.GridHelper( 30, 6 );
58
+ grid2.material.color.setHex( GRID_COLORS_LIGHT[ 1 ] );
59
+ grid2.material.vertexColors = false;
60
+ grid.add( grid2 );
61
+
62
+ const viewHelper = new ViewHelper( camera, container );
63
+
64
+ //
65
+
66
+ const box = new THREE.Box3();
67
+
68
+ const selectionBox = new THREE.Box3Helper( box );
69
+ selectionBox.material.depthTest = false;
70
+ selectionBox.material.transparent = true;
71
+ selectionBox.visible = false;
72
+ sceneHelpers.add( selectionBox );
73
+
74
+ let objectPositionOnDown = null;
75
+ let objectRotationOnDown = null;
76
+ let objectScaleOnDown = null;
77
+
78
+ const transformControls = new TransformControls( camera );
79
+ transformControls.addEventListener( 'axis-changed', function () {
80
+
81
+ if ( editor.viewportShading !== 'realistic' ) render();
82
+
83
+ } );
84
+ transformControls.addEventListener( 'objectChange', function () {
85
+
86
+ signals.objectChanged.dispatch( transformControls.object );
87
+
88
+ } );
89
+ transformControls.addEventListener( 'mouseDown', function () {
90
+
91
+ const object = transformControls.object;
92
+
93
+ objectPositionOnDown = object.position.clone();
94
+ objectRotationOnDown = object.rotation.clone();
95
+ objectScaleOnDown = object.scale.clone();
96
+
97
+ controls.enabled = false;
98
+
99
+ } );
100
+ transformControls.addEventListener( 'mouseUp', function () {
101
+
102
+ const object = transformControls.object;
103
+
104
+ if ( object !== undefined ) {
105
+
106
+ switch ( transformControls.getMode() ) {
107
+
108
+ case 'translate':
109
+
110
+ if ( ! objectPositionOnDown.equals( object.position ) ) {
111
+
112
+ editor.execute( new SetPositionCommand( editor, object, object.position, objectPositionOnDown ) );
113
+
114
+ }
115
+
116
+ break;
117
+
118
+ case 'rotate':
119
+
120
+ if ( ! objectRotationOnDown.equals( object.rotation ) ) {
121
+
122
+ editor.execute( new SetRotationCommand( editor, object, object.rotation, objectRotationOnDown ) );
123
+
124
+ }
125
+
126
+ break;
127
+
128
+ case 'scale':
129
+
130
+ if ( ! objectScaleOnDown.equals( object.scale ) ) {
131
+
132
+ editor.execute( new SetScaleCommand( editor, object, object.scale, objectScaleOnDown ) );
133
+
134
+ }
135
+
136
+ break;
137
+
138
+ }
139
+
140
+ }
141
+
142
+ controls.enabled = true;
143
+
144
+ } );
145
+
146
+ sceneHelpers.add( transformControls.getHelper() );
147
+
148
+ //
149
+
150
+ const xr = new XR( editor, transformControls ); // eslint-disable-line no-unused-vars
151
+
152
+ // events
153
+
154
+ function updateAspectRatio() {
155
+
156
+ for ( const uuid in editor.cameras ) {
157
+
158
+ const camera = editor.cameras[ uuid ];
159
+
160
+ const aspect = container.dom.offsetWidth / container.dom.offsetHeight;
161
+
162
+ if ( camera.isPerspectiveCamera ) {
163
+
164
+ camera.aspect = aspect;
165
+
166
+ } else {
167
+
168
+ const frustumHeight = camera.top - camera.bottom;
169
+
170
+ camera.left = - frustumHeight * aspect / 2;
171
+ camera.right = frustumHeight * aspect / 2;
172
+
173
+ }
174
+
175
+ camera.updateProjectionMatrix();
176
+
177
+ const cameraHelper = editor.helpers[ camera.id ];
178
+ if ( cameraHelper ) cameraHelper.update();
179
+
180
+ }
181
+
182
+ }
183
+
184
+ const onDownPosition = new THREE.Vector2();
185
+ const onUpPosition = new THREE.Vector2();
186
+ const onDoubleClickPosition = new THREE.Vector2();
187
+
188
+ function getMousePosition( dom, x, y ) {
189
+
190
+ const rect = dom.getBoundingClientRect();
191
+ return [ ( x - rect.left ) / rect.width, ( y - rect.top ) / rect.height ];
192
+
193
+ }
194
+
195
+ function handleClick() {
196
+
197
+ if ( onDownPosition.distanceTo( onUpPosition ) === 0 ) {
198
+
199
+ const intersects = selector.getPointerIntersects( onUpPosition, camera );
200
+ signals.intersectionsDetected.dispatch( intersects );
201
+
202
+ render();
203
+
204
+ }
205
+
206
+ }
207
+
208
+ function onMouseDown( event ) {
209
+
210
+ // event.preventDefault();
211
+
212
+ if ( event.target !== renderer.domElement ) return;
213
+
214
+ const array = getMousePosition( container.dom, event.clientX, event.clientY );
215
+ onDownPosition.fromArray( array );
216
+
217
+ document.addEventListener( 'mouseup', onMouseUp );
218
+
219
+ }
220
+
221
+ function onMouseUp( event ) {
222
+
223
+ const array = getMousePosition( container.dom, event.clientX, event.clientY );
224
+ onUpPosition.fromArray( array );
225
+
226
+ handleClick();
227
+
228
+ document.removeEventListener( 'mouseup', onMouseUp );
229
+
230
+ }
231
+
232
+ function onTouchStart( event ) {
233
+
234
+ const touch = event.changedTouches[ 0 ];
235
+
236
+ const array = getMousePosition( container.dom, touch.clientX, touch.clientY );
237
+ onDownPosition.fromArray( array );
238
+
239
+ document.addEventListener( 'touchend', onTouchEnd );
240
+
241
+ }
242
+
243
+ function onTouchEnd( event ) {
244
+
245
+ const touch = event.changedTouches[ 0 ];
246
+
247
+ const array = getMousePosition( container.dom, touch.clientX, touch.clientY );
248
+ onUpPosition.fromArray( array );
249
+
250
+ handleClick();
251
+
252
+ document.removeEventListener( 'touchend', onTouchEnd );
253
+
254
+ }
255
+
256
+ function onDoubleClick( event ) {
257
+
258
+ const array = getMousePosition( container.dom, event.clientX, event.clientY );
259
+ onDoubleClickPosition.fromArray( array );
260
+
261
+ const intersects = selector.getPointerIntersects( onDoubleClickPosition, camera );
262
+
263
+ if ( intersects.length > 0 ) {
264
+
265
+ const intersect = intersects[ 0 ];
266
+
267
+ signals.objectFocused.dispatch( intersect.object );
268
+
269
+ }
270
+
271
+ }
272
+
273
+ container.dom.addEventListener( 'mousedown', onMouseDown );
274
+ container.dom.addEventListener( 'touchstart', onTouchStart, { passive: false } );
275
+ container.dom.addEventListener( 'dblclick', onDoubleClick );
276
+
277
+ // controls need to be added *after* main logic,
278
+ // otherwise controls.enabled doesn't work.
279
+
280
+ const controls = new EditorControls( camera );
281
+ controls.addEventListener( 'change', function () {
282
+
283
+ signals.cameraChanged.dispatch( camera );
284
+ signals.refreshSidebarObject3D.dispatch( camera );
285
+
286
+ } );
287
+ viewHelper.center = controls.center;
288
+
289
+ editor.controls = controls;
290
+
291
+ // signals
292
+
293
+ signals.editorCleared.add( function () {
294
+
295
+ controls.center.set( 0, 0, 0 );
296
+ if ( pathtracer ) pathtracer.reset();
297
+
298
+ initPT();
299
+
300
+ signals.sceneEnvironmentChanged.dispatch( editor.environmentType );
301
+
302
+ } );
303
+
304
+ signals.transformModeChanged.add( function ( mode ) {
305
+
306
+ transformControls.setMode( mode );
307
+
308
+ render();
309
+
310
+ } );
311
+
312
+ signals.snapChanged.add( function ( dist ) {
313
+
314
+ transformControls.setTranslationSnap( dist );
315
+
316
+ } );
317
+
318
+ signals.spaceChanged.add( function ( space ) {
319
+
320
+ transformControls.setSpace( space );
321
+
322
+ render();
323
+
324
+ } );
325
+
326
+ signals.rendererUpdated.add( function () {
327
+
328
+ scene.traverse( function ( child ) {
329
+
330
+ if ( child.material !== undefined ) {
331
+
332
+ child.material.needsUpdate = true;
333
+
334
+ }
335
+
336
+ } );
337
+
338
+ render();
339
+
340
+ } );
341
+
342
+ signals.rendererCreated.add( function ( newRenderer ) {
343
+
344
+ if ( renderer !== null ) {
345
+
346
+ renderer.setAnimationLoop( null );
347
+
348
+ try {
349
+
350
+ pmremGenerator.dispose();
351
+
352
+ } catch ( e ) {
353
+
354
+ console.warn( 'PMREMGenerator dispose error:', e );
355
+
356
+ }
357
+
358
+ renderer.dispose();
359
+
360
+ container.dom.removeChild( renderer.domElement );
361
+
362
+ }
363
+
364
+ controls.connect( newRenderer.domElement );
365
+ transformControls.connect( newRenderer.domElement );
366
+
367
+ renderer = newRenderer;
368
+
369
+ renderer.setAnimationLoop( animate );
370
+ renderer.setClearColor( 0xaaaaaa );
371
+
372
+ if ( window.matchMedia ) {
373
+
374
+ const mediaQuery = window.matchMedia( '(prefers-color-scheme: dark)' );
375
+ mediaQuery.addEventListener( 'change', function ( event ) {
376
+
377
+ renderer.setClearColor( event.matches ? 0x333333 : 0xaaaaaa );
378
+ updateGridColors( grid1, grid2, event.matches ? GRID_COLORS_DARK : GRID_COLORS_LIGHT );
379
+
380
+ render();
381
+
382
+ } );
383
+
384
+ renderer.setClearColor( mediaQuery.matches ? 0x333333 : 0xaaaaaa );
385
+ updateGridColors( grid1, grid2, mediaQuery.matches ? GRID_COLORS_DARK : GRID_COLORS_LIGHT );
386
+
387
+ }
388
+
389
+ renderer.getClearColor( editor.viewportColor );
390
+
391
+ renderer.setPixelRatio( window.devicePixelRatio );
392
+ renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
393
+
394
+ if ( renderer.isWebGLRenderer ) {
395
+
396
+ pmremGenerator = new THREE.PMREMGenerator( renderer );
397
+ pmremGenerator.compileEquirectangularShader();
398
+
399
+ pathtracer = new ViewportPathtracer( renderer );
400
+
401
+ } else {
402
+
403
+ pmremGenerator = new THREE.PMREMGenerator( renderer );
404
+
405
+ pathtracer = null;
406
+
407
+ }
408
+
409
+ container.dom.appendChild( renderer.domElement );
410
+
411
+ signals.sceneEnvironmentChanged.dispatch( editor.environmentType );
412
+
413
+ render();
414
+
415
+ } );
416
+
417
+ signals.rendererDetectKTX2Support.add( function ( ktx2Loader ) {
418
+
419
+ ktx2Loader.detectSupport( renderer );
420
+
421
+ } );
422
+
423
+ signals.sceneGraphChanged.add( function () {
424
+
425
+ initPT();
426
+ render();
427
+
428
+ } );
429
+
430
+ signals.cameraChanged.add( function () {
431
+
432
+ if ( pathtracer ) pathtracer.reset();
433
+
434
+ render();
435
+
436
+ } );
437
+
438
+ signals.objectSelected.add( function ( object ) {
439
+
440
+ selectionBox.visible = false;
441
+ transformControls.detach();
442
+
443
+ if ( object !== null && object !== scene && object !== camera ) {
444
+
445
+ box.setFromObject( object, true );
446
+
447
+ if ( box.isEmpty() === false ) {
448
+
449
+ selectionBox.visible = true;
450
+
451
+ }
452
+
453
+ transformControls.attach( object );
454
+
455
+ }
456
+
457
+ render();
458
+
459
+ } );
460
+
461
+ signals.objectFocused.add( function ( object ) {
462
+
463
+ controls.focus( object );
464
+
465
+ } );
466
+
467
+ signals.geometryChanged.add( function ( object ) {
468
+
469
+ if ( object !== undefined ) {
470
+
471
+ box.setFromObject( object, true );
472
+
473
+ }
474
+
475
+ initPT();
476
+ render();
477
+
478
+ } );
479
+
480
+ signals.objectChanged.add( function ( object ) {
481
+
482
+ if ( editor.selected === object ) {
483
+
484
+ box.setFromObject( object, true );
485
+
486
+ }
487
+
488
+ if ( object.isPerspectiveCamera ) {
489
+
490
+ object.updateProjectionMatrix();
491
+
492
+ }
493
+
494
+ const helper = editor.helpers[ object.id ];
495
+
496
+ if ( helper !== undefined && helper.isSkeletonHelper !== true ) {
497
+
498
+ helper.update();
499
+
500
+ }
501
+
502
+ // update light helper when light target is changed
503
+
504
+ for ( const id in editor.helpers ) {
505
+
506
+ const helper = editor.helpers[ id ];
507
+
508
+ if ( helper.light && helper.light.target === object ) {
509
+
510
+ helper.update();
511
+
512
+ }
513
+
514
+ }
515
+
516
+ initPT();
517
+ render();
518
+
519
+ } );
520
+
521
+ signals.objectRemoved.add( function ( object ) {
522
+
523
+ controls.enabled = true; // see #14180
524
+
525
+ if ( object === transformControls.object ) {
526
+
527
+ transformControls.detach();
528
+
529
+ }
530
+
531
+ } );
532
+
533
+ signals.materialChanged.add( function () {
534
+
535
+ updatePTMaterials();
536
+ render();
537
+
538
+ } );
539
+
540
+ // background
541
+
542
+ signals.sceneBackgroundChanged.add( function ( backgroundType, backgroundColor, backgroundTexture, backgroundEquirectangularTexture, backgroundColorSpace, backgroundBlurriness, backgroundIntensity, backgroundRotation ) {
543
+
544
+ editor.backgroundType = backgroundType;
545
+
546
+ scene.background = null;
547
+
548
+ switch ( backgroundType ) {
549
+
550
+ case 'Color':
551
+
552
+ scene.background = new THREE.Color( backgroundColor );
553
+
554
+ break;
555
+
556
+ case 'Texture':
557
+
558
+ if ( backgroundTexture ) {
559
+
560
+ backgroundTexture.colorSpace = backgroundColorSpace;
561
+ backgroundTexture.needsUpdate = true;
562
+
563
+ scene.background = backgroundTexture;
564
+
565
+ }
566
+
567
+ break;
568
+
569
+ case 'Equirectangular':
570
+
571
+ if ( backgroundEquirectangularTexture ) {
572
+
573
+ backgroundEquirectangularTexture.mapping = THREE.EquirectangularReflectionMapping;
574
+ backgroundEquirectangularTexture.colorSpace = backgroundColorSpace;
575
+ backgroundEquirectangularTexture.needsUpdate = true;
576
+
577
+ scene.background = backgroundEquirectangularTexture;
578
+ scene.backgroundBlurriness = backgroundBlurriness;
579
+ scene.backgroundIntensity = backgroundIntensity;
580
+ scene.backgroundRotation.y = backgroundRotation * THREE.MathUtils.DEG2RAD;
581
+
582
+ }
583
+
584
+ break;
585
+
586
+ }
587
+
588
+ if ( useBackgroundAsEnvironment ) {
589
+
590
+ signals.sceneEnvironmentChanged.dispatch( editor.environmentType );
591
+
592
+ }
593
+
594
+ updatePTBackground();
595
+ render();
596
+
597
+ } );
598
+
599
+ // environment
600
+
601
+ let useBackgroundAsEnvironment = false;
602
+
603
+ signals.sceneEnvironmentChanged.add( function ( environmentType, environmentEquirectangularTexture ) {
604
+
605
+ editor.environmentType = environmentType;
606
+
607
+ scene.environment = null;
608
+
609
+ useBackgroundAsEnvironment = false;
610
+
611
+ switch ( environmentType ) {
612
+
613
+ case 'Equirectangular':
614
+
615
+ if ( environmentEquirectangularTexture ) {
616
+
617
+ scene.environment = environmentEquirectangularTexture;
618
+ scene.environment.mapping = THREE.EquirectangularReflectionMapping;
619
+
620
+ }
621
+
622
+ break;
623
+
624
+ case 'Default':
625
+
626
+ useBackgroundAsEnvironment = true;
627
+
628
+ if ( scene.background !== null ) {
629
+
630
+ if ( scene.background.isColor ) {
631
+
632
+ scene.environment = pmremGenerator.fromScene( new ColorEnvironment( scene.background ), 0.04 ).texture;
633
+
634
+ } else if ( scene.background.isTexture ) {
635
+
636
+ scene.environment = scene.background;
637
+ scene.environment.mapping = THREE.EquirectangularReflectionMapping;
638
+ scene.environmentRotation.y = scene.backgroundRotation.y;
639
+
640
+ }
641
+
642
+ } else {
643
+
644
+ scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture;
645
+
646
+ }
647
+
648
+ break;
649
+
650
+ }
651
+
652
+ updatePTEnvironment();
653
+ render();
654
+
655
+ } );
656
+
657
+ // fog
658
+
659
+ signals.sceneFogChanged.add( function ( fogType, fogColor, fogNear, fogFar, fogDensity ) {
660
+
661
+ switch ( fogType ) {
662
+
663
+ case 'None':
664
+ scene.fog = null;
665
+ break;
666
+ case 'Fog':
667
+ scene.fog = new THREE.Fog( fogColor, fogNear, fogFar );
668
+ break;
669
+ case 'FogExp2':
670
+ scene.fog = new THREE.FogExp2( fogColor, fogDensity );
671
+ break;
672
+
673
+ }
674
+
675
+ render();
676
+
677
+ } );
678
+
679
+ signals.sceneFogSettingsChanged.add( function ( fogType, fogColor, fogNear, fogFar, fogDensity ) {
680
+
681
+ switch ( fogType ) {
682
+
683
+ case 'Fog':
684
+ scene.fog.color.setHex( fogColor );
685
+ scene.fog.near = fogNear;
686
+ scene.fog.far = fogFar;
687
+ break;
688
+ case 'FogExp2':
689
+ scene.fog.color.setHex( fogColor );
690
+ scene.fog.density = fogDensity;
691
+ break;
692
+
693
+ }
694
+
695
+ render();
696
+
697
+ } );
698
+
699
+ signals.viewportCameraChanged.add( function () {
700
+
701
+ const viewportCamera = editor.viewportCamera;
702
+
703
+ if ( viewportCamera.isPerspectiveCamera || viewportCamera.isOrthographicCamera ) {
704
+
705
+ updateAspectRatio();
706
+
707
+ }
708
+
709
+ // disable EditorControls when setting a user camera
710
+
711
+ controls.enabled = ( viewportCamera === editor.camera );
712
+
713
+ initPT();
714
+ render();
715
+
716
+ } );
717
+
718
+ signals.viewportShadingChanged.add( function () {
719
+
720
+ const viewportShading = editor.viewportShading;
721
+
722
+ switch ( viewportShading ) {
723
+
724
+ case 'realistic':
725
+ if ( pathtracer ) pathtracer.init( scene, editor.viewportCamera );
726
+ break;
727
+
728
+ case 'solid':
729
+ scene.overrideMaterial = null;
730
+ break;
731
+
732
+ case 'normals':
733
+ scene.overrideMaterial = new THREE.MeshNormalMaterial();
734
+ break;
735
+
736
+ case 'wireframe':
737
+ scene.overrideMaterial = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true } );
738
+ break;
739
+
740
+ }
741
+
742
+ render();
743
+
744
+ } );
745
+
746
+ //
747
+
748
+ signals.windowResize.add( function () {
749
+
750
+ updateAspectRatio();
751
+
752
+ if ( renderer === null ) return;
753
+
754
+ renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
755
+ if ( pathtracer ) pathtracer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
756
+
757
+ render();
758
+
759
+ } );
760
+
761
+ signals.showHelpersChanged.add( function ( appearanceStates ) {
762
+
763
+ grid.visible = appearanceStates.gridHelper;
764
+
765
+ sceneHelpers.traverse( function ( object ) {
766
+
767
+ switch ( object.type ) {
768
+
769
+ case 'CameraHelper':
770
+
771
+ {
772
+
773
+ object.visible = appearanceStates.cameraHelpers;
774
+ break;
775
+
776
+ }
777
+
778
+ case 'PointLightHelper':
779
+ case 'DirectionalLightHelper':
780
+ case 'SpotLightHelper':
781
+ case 'HemisphereLightHelper':
782
+
783
+ {
784
+
785
+ object.visible = appearanceStates.lightHelpers;
786
+ break;
787
+
788
+ }
789
+
790
+ case 'SkeletonHelper':
791
+
792
+ {
793
+
794
+ object.visible = appearanceStates.skeletonHelpers;
795
+ break;
796
+
797
+ }
798
+
799
+ default:
800
+
801
+ {
802
+
803
+ // not a helper, skip.
804
+
805
+ }
806
+
807
+ }
808
+
809
+ } );
810
+
811
+
812
+ render();
813
+
814
+ } );
815
+
816
+ signals.cameraResetted.add( function () {
817
+
818
+ if ( camera !== editor.camera ) {
819
+
820
+ camera = editor.camera;
821
+
822
+ controls.setCamera( camera );
823
+ transformControls.camera = camera;
824
+ viewHelper.camera = camera;
825
+
826
+ }
827
+
828
+ updateAspectRatio();
829
+ render();
830
+
831
+ } );
832
+
833
+ // animations
834
+
835
+ let prevActionsInUse = 0;
836
+
837
+ const timer = new THREE.Timer(); // only used for animations
838
+
839
+ function animate() {
840
+
841
+ timer.update();
842
+
843
+ const mixer = editor.mixer;
844
+ const delta = timer.getDelta();
845
+
846
+ let needsUpdate = false;
847
+
848
+ // Animations
849
+
850
+ const actions = mixer.stats.actions;
851
+
852
+ if ( actions.inUse > 0 || prevActionsInUse > 0 ) {
853
+
854
+ prevActionsInUse = actions.inUse;
855
+
856
+ mixer.update( delta );
857
+ needsUpdate = true;
858
+
859
+ if ( editor.selected !== null ) {
860
+
861
+ editor.selected.updateWorldMatrix( false, true ); // avoid frame late effect for certain skinned meshes (e.g. Michelle.glb)
862
+ selectionBox.box.setFromObject( editor.selected, true ); // selection box should reflect current animation state
863
+
864
+ }
865
+
866
+ signals.morphTargetsUpdated.dispatch();
867
+
868
+ }
869
+
870
+ // View Helper
871
+
872
+ if ( viewHelper.animating === true ) {
873
+
874
+ viewHelper.update( delta );
875
+ needsUpdate = true;
876
+
877
+ }
878
+
879
+ if ( renderer.xr.isPresenting === true ) {
880
+
881
+ needsUpdate = true;
882
+
883
+ }
884
+
885
+ if ( needsUpdate === true ) render();
886
+
887
+ updatePT();
888
+
889
+ }
890
+
891
+ function initPT() {
892
+
893
+ if ( pathtracer && editor.viewportShading === 'realistic' ) {
894
+
895
+ pathtracer.init( scene, editor.viewportCamera );
896
+
897
+ }
898
+
899
+ }
900
+
901
+ function updatePTBackground() {
902
+
903
+ if ( pathtracer && editor.viewportShading === 'realistic' ) {
904
+
905
+ pathtracer.setBackground( scene.background, scene.backgroundBlurriness );
906
+
907
+ }
908
+
909
+ }
910
+
911
+ function updatePTEnvironment() {
912
+
913
+ if ( pathtracer && editor.viewportShading === 'realistic' ) {
914
+
915
+ pathtracer.setEnvironment( scene.environment );
916
+
917
+ }
918
+
919
+ }
920
+
921
+ function updatePTMaterials() {
922
+
923
+ if ( pathtracer && editor.viewportShading === 'realistic' ) {
924
+
925
+ pathtracer.updateMaterials();
926
+
927
+ }
928
+
929
+ }
930
+
931
+ function updatePT() {
932
+
933
+ if ( pathtracer && editor.viewportShading === 'realistic' ) {
934
+
935
+ pathtracer.update();
936
+ editor.signals.pathTracerUpdated.dispatch( pathtracer.getSamples() );
937
+
938
+ }
939
+
940
+ }
941
+
942
+ //
943
+
944
+ let startTime = 0;
945
+ let endTime = 0;
946
+
947
+ function render() {
948
+
949
+ if ( renderer === null ) return;
950
+
951
+ startTime = performance.now();
952
+
953
+ renderer.setViewport( 0, 0, container.dom.offsetWidth, container.dom.offsetHeight );
954
+ renderer.render( scene, editor.viewportCamera );
955
+
956
+ if ( camera === editor.viewportCamera ) {
957
+
958
+ renderer.autoClear = false;
959
+ if ( grid.visible === true ) renderer.render( grid, camera );
960
+ if ( sceneHelpers.visible === true ) renderer.render( sceneHelpers, camera );
961
+ if ( renderer.xr.isPresenting !== true ) viewHelper.render( renderer );
962
+ renderer.autoClear = true;
963
+
964
+ }
965
+
966
+ endTime = performance.now();
967
+ editor.signals.sceneRendered.dispatch( endTime - startTime );
968
+
969
+ }
970
+
971
+ return container;
972
+
973
+ }
974
+
975
+ function updateGridColors( grid1, grid2, colors ) {
976
+
977
+ grid1.material.color.setHex( colors[ 0 ] );
978
+ grid2.material.color.setHex( colors[ 1 ] );
979
+
980
+ }
981
+
982
+ export { Viewport };