super-three 0.136.1 → 0.137.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 (100) hide show
  1. package/README.md +1 -1
  2. package/build/three.cjs +37132 -0
  3. package/build/three.js +71 -53
  4. package/build/three.min.js +2 -2
  5. package/build/three.module.js +80 -47
  6. package/examples/js/animation/MMDAnimationHelper.js +3 -1
  7. package/examples/js/controls/experimental/CameraControls.js +6 -2
  8. package/examples/js/exporters/GLTFExporter.js +82 -39
  9. package/examples/js/geometries/TextGeometry.js +12 -10
  10. package/examples/js/interactive/HTMLMesh.js +14 -2
  11. package/examples/js/loaders/EXRLoader.js +20 -9
  12. package/examples/js/loaders/GLTFLoader.js +1 -1
  13. package/examples/js/loaders/LDrawLoader.js +541 -425
  14. package/examples/js/loaders/MD2Loader.js +5 -5
  15. package/examples/js/loaders/MTLLoader.js +10 -3
  16. package/examples/js/loaders/PCDLoader.js +2 -2
  17. package/examples/js/loaders/STLLoader.js +1 -1
  18. package/examples/js/loaders/SVGLoader.js +3 -2
  19. package/examples/js/modifiers/EdgeSplitModifier.js +0 -6
  20. package/examples/js/modifiers/SimplifyModifier.js +0 -10
  21. package/examples/js/objects/Lensflare.js +2 -2
  22. package/examples/js/postprocessing/OutlinePass.js +1 -5
  23. package/examples/js/renderers/CSS2DRenderer.js +25 -19
  24. package/examples/js/renderers/CSS3DRenderer.js +37 -32
  25. package/examples/js/utils/LDrawUtils.js +182 -0
  26. package/examples/jsm/exporters/GLTFExporter.js +80 -12
  27. package/examples/jsm/geometries/TextGeometry.js +13 -13
  28. package/examples/jsm/interactive/HTMLMesh.js +16 -2
  29. package/examples/jsm/libs/flow.module.js +930 -169
  30. package/examples/jsm/loaders/EXRLoader.js +19 -9
  31. package/examples/jsm/loaders/GLTFLoader.js +1 -1
  32. package/examples/jsm/loaders/LDrawLoader.js +534 -442
  33. package/examples/jsm/loaders/MD2Loader.js +5 -5
  34. package/examples/jsm/loaders/MTLLoader.js +11 -4
  35. package/examples/jsm/loaders/PCDLoader.js +2 -2
  36. package/examples/jsm/loaders/STLLoader.js +1 -1
  37. package/examples/jsm/loaders/SVGLoader.js +3 -1
  38. package/examples/jsm/loaders/VRMLLoader.js +0 -1
  39. package/examples/jsm/modifiers/EdgeSplitModifier.js +0 -6
  40. package/examples/jsm/modifiers/SimplifyModifier.js +0 -10
  41. package/examples/jsm/node-editor/NodeEditor.js +435 -181
  42. package/examples/jsm/node-editor/accessors/NormalEditor.js +8 -8
  43. package/examples/jsm/node-editor/accessors/PositionEditor.js +8 -8
  44. package/examples/jsm/node-editor/accessors/UVEditor.js +6 -7
  45. package/examples/jsm/node-editor/core/BaseNode.js +83 -0
  46. package/examples/jsm/node-editor/display/BlendEditor.js +7 -6
  47. package/examples/jsm/node-editor/examples/animate-uv.json +1 -1
  48. package/examples/jsm/node-editor/examples/fake-top-light.json +1 -1
  49. package/examples/jsm/node-editor/examples/oscillator-color.json +1 -1
  50. package/examples/jsm/node-editor/examples/rim.json +1 -1
  51. package/examples/jsm/node-editor/inputs/ColorEditor.js +14 -10
  52. package/examples/jsm/node-editor/inputs/FloatEditor.js +6 -7
  53. package/examples/jsm/node-editor/inputs/SliderEditor.js +4 -5
  54. package/examples/jsm/node-editor/inputs/Vector2Editor.js +6 -7
  55. package/examples/jsm/node-editor/inputs/Vector3Editor.js +8 -9
  56. package/examples/jsm/node-editor/inputs/Vector4Editor.js +9 -10
  57. package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +87 -0
  58. package/examples/jsm/node-editor/materials/PointsMaterialEditor.js +97 -0
  59. package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +20 -17
  60. package/examples/jsm/node-editor/math/AngleEditor.js +39 -0
  61. package/examples/jsm/node-editor/math/DotEditor.js +6 -7
  62. package/examples/jsm/node-editor/math/InvertEditor.js +4 -3
  63. package/examples/jsm/node-editor/math/LimiterEditor.js +11 -10
  64. package/examples/jsm/node-editor/math/NormalizeEditor.js +6 -5
  65. package/examples/jsm/node-editor/math/OperatorEditor.js +12 -11
  66. package/examples/jsm/node-editor/math/PowerEditor.js +6 -5
  67. package/examples/jsm/node-editor/math/TrigonometryEditor.js +12 -7
  68. package/examples/jsm/node-editor/procedural/CheckerEditor.js +4 -3
  69. package/examples/jsm/node-editor/scene/MeshEditor.js +99 -0
  70. package/examples/jsm/node-editor/scene/Object3DEditor.js +160 -0
  71. package/examples/jsm/node-editor/scene/PointsEditor.js +99 -0
  72. package/examples/jsm/node-editor/utils/JoinEditor.js +58 -0
  73. package/examples/jsm/node-editor/utils/OscillatorEditor.js +7 -6
  74. package/examples/jsm/node-editor/utils/SplitEditor.js +39 -0
  75. package/examples/jsm/node-editor/utils/TimerEditor.js +6 -5
  76. package/examples/jsm/postprocessing/OutlinePass.js +1 -4
  77. package/examples/jsm/renderers/CSS2DRenderer.js +24 -19
  78. package/examples/jsm/renderers/CSS3DRenderer.js +36 -30
  79. package/examples/jsm/renderers/nodes/accessors/UVNode.js +4 -4
  80. package/examples/jsm/renderers/nodes/core/NodeBuilder.js +2 -1
  81. package/examples/jsm/renderers/nodes/utils/SplitNode.js +19 -4
  82. package/examples/jsm/utils/LDrawUtils.js +18 -11
  83. package/package.json +16 -9
  84. package/src/constants.js +1 -3
  85. package/src/core/BufferGeometry.js +2 -2
  86. package/src/geometries/LatheGeometry.js +1 -1
  87. package/src/loaders/FileLoader.js +20 -3
  88. package/src/math/Box3.js +24 -10
  89. package/src/renderers/WebGLRenderTarget.js +4 -1
  90. package/src/renderers/WebGLRenderer.js +3 -3
  91. package/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js +1 -1
  92. package/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js +2 -2
  93. package/src/renderers/webgl/WebGLBackground.js +2 -2
  94. package/src/renderers/webgl/WebGLGeometries.js +2 -2
  95. package/src/renderers/webgl/WebGLPrograms.js +2 -2
  96. package/src/renderers/webgl/WebGLState.js +2 -2
  97. package/src/renderers/webgl/WebGLTextures.js +9 -6
  98. package/src/renderers/webgl/WebGLUtils.js +1 -3
  99. package/src/renderers/webxr/WebXRManager.js +2 -0
  100. package/src/utils.js +15 -1
@@ -1,11 +1,14 @@
1
- import { Canvas, CircleMenu, ButtonInput, ContextMenu, Loader } from '../libs/flow.module.js';
1
+ import { Styles, Canvas, CircleMenu, ButtonInput, ContextMenu, Tips, Search, Loader } from '../libs/flow.module.js';
2
+ import { BasicMaterialEditor } from './materials/BasicMaterialEditor.js';
2
3
  import { StandardMaterialEditor } from './materials/StandardMaterialEditor.js';
4
+ import { PointsMaterialEditor } from './materials/PointsMaterialEditor.js';
3
5
  import { OperatorEditor } from './math/OperatorEditor.js';
4
6
  import { NormalizeEditor } from './math/NormalizeEditor.js';
5
7
  import { InvertEditor } from './math/InvertEditor.js';
6
8
  import { LimiterEditor } from './math/LimiterEditor.js';
7
9
  import { DotEditor } from './math/DotEditor.js';
8
10
  import { PowerEditor } from './math/PowerEditor.js';
11
+ import { AngleEditor } from './math/AngleEditor.js';
9
12
  import { TrigonometryEditor } from './math/TrigonometryEditor.js';
10
13
  import { FloatEditor } from './inputs/FloatEditor.js';
11
14
  import { Vector2Editor } from './inputs/Vector2Editor.js';
@@ -19,43 +22,248 @@ import { PositionEditor } from './accessors/PositionEditor.js';
19
22
  import { NormalEditor } from './accessors/NormalEditor.js';
20
23
  import { TimerEditor } from './utils/TimerEditor.js';
21
24
  import { OscillatorEditor } from './utils/OscillatorEditor.js';
25
+ import { SplitEditor } from './utils/SplitEditor.js';
26
+ import { JoinEditor } from './utils/JoinEditor.js';
22
27
  import { CheckerEditor } from './procedural/CheckerEditor.js';
28
+ import { PointsEditor } from './scene/PointsEditor.js';
29
+ import { MeshEditor } from './scene/MeshEditor.js';
23
30
  import { EventDispatcher } from 'three';
24
31
 
32
+ Styles.icons.unlink = 'ti ti-unlink';
33
+
34
+ export const NodeList = [
35
+ {
36
+ name: 'Inputs',
37
+ icon: 'forms',
38
+ children: [
39
+ {
40
+ name: 'Slider',
41
+ icon: 'adjustments-horizontal',
42
+ nodeClass: SliderEditor
43
+ },
44
+ {
45
+ name: 'Float',
46
+ icon: 'box-multiple-1',
47
+ nodeClass: FloatEditor
48
+ },
49
+ {
50
+ name: 'Vector 2',
51
+ icon: 'box-multiple-2',
52
+ nodeClass: Vector2Editor
53
+ },
54
+ {
55
+ name: 'Vector 3',
56
+ icon: 'box-multiple-3',
57
+ nodeClass: Vector3Editor
58
+ },
59
+ {
60
+ name: 'Vector 4',
61
+ icon: 'box-multiple-4',
62
+ nodeClass: Vector4Editor
63
+ },
64
+ {
65
+ name: 'Color',
66
+ icon: 'palette',
67
+ nodeClass: ColorEditor
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ name: 'Accessors',
73
+ icon: 'vector-triangle',
74
+ children: [
75
+ {
76
+ name: 'UV',
77
+ icon: 'details',
78
+ nodeClass: UVEditor
79
+ },
80
+ {
81
+ name: 'Position',
82
+ icon: 'hierarchy',
83
+ nodeClass: PositionEditor
84
+ },
85
+ {
86
+ name: 'Normal',
87
+ icon: 'fold-up',
88
+ nodeClass: NormalEditor
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ name: 'Display',
94
+ icon: 'brightness',
95
+ children: [
96
+ {
97
+ name: 'Blend',
98
+ icon: 'layers-subtract',
99
+ nodeClass: BlendEditor
100
+ }
101
+ ]
102
+ },
103
+ {
104
+ name: 'Math',
105
+ icon: 'calculator',
106
+ children: [
107
+ {
108
+ name: 'Operator',
109
+ icon: 'math-symbols',
110
+ nodeClass: OperatorEditor
111
+ },
112
+ {
113
+ name: 'Invert',
114
+ icon: 'flip-vertical',
115
+ tip: 'Negate',
116
+ nodeClass: OperatorEditor
117
+ },
118
+ {
119
+ name: 'Limiter',
120
+ icon: 'arrow-bar-to-up',
121
+ tip: 'Min / Max',
122
+ nodeClass: LimiterEditor
123
+ },
124
+ {
125
+ name: 'Dot Product',
126
+ icon: 'arrows-up-left',
127
+ nodeClass: DotEditor
128
+ },
129
+ {
130
+ name: 'Power',
131
+ icon: 'arrow-up-right',
132
+ nodeClass: PowerEditor
133
+ },
134
+ {
135
+ name: 'Trigonometry',
136
+ icon: 'wave-sine',
137
+ tip: 'Sin / Cos / Tan / ...',
138
+ nodeClass: TrigonometryEditor
139
+ },
140
+ {
141
+ name: 'Angle',
142
+ icon: 'angle',
143
+ tip: 'Degress / Radians',
144
+ nodeClass: AngleEditor
145
+ },
146
+ {
147
+ name: 'Normalize',
148
+ icon: 'fold',
149
+ nodeClass: NormalizeEditor
150
+ }
151
+ ]
152
+ },
153
+ {
154
+ name: 'Procedural',
155
+ icon: 'infinity',
156
+ children: [
157
+ {
158
+ name: 'Checker',
159
+ icon: 'border-outer',
160
+ nodeClass: CheckerEditor
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ name: 'Utils',
166
+ icon: 'apps',
167
+ children: [
168
+ {
169
+ name: 'Timer',
170
+ icon: 'clock',
171
+ nodeClass: TimerEditor
172
+ },
173
+ {
174
+ name: 'Oscillator',
175
+ icon: 'wave-sine',
176
+ nodeClass: OscillatorEditor
177
+ },
178
+ {
179
+ name: 'Split',
180
+ icon: 'arrows-split-2',
181
+ nodeClass: SplitEditor
182
+ },
183
+ {
184
+ name: 'Join',
185
+ icon: 'arrows-join-2',
186
+ nodeClass: JoinEditor
187
+ }
188
+ ]
189
+ },
190
+ /*{
191
+ name: 'Scene',
192
+ icon: '3d-cube-sphere',
193
+ children: [
194
+ {
195
+ name: 'Mesh',
196
+ icon: '3d-cube-sphere',
197
+ nodeClass: MeshEditor
198
+ }
199
+ ]
200
+ },*/
201
+ {
202
+ name: 'Material',
203
+ icon: 'circles',
204
+ children: [
205
+ {
206
+ name: 'Basic Material',
207
+ icon: 'circle',
208
+ nodeClass: BasicMaterialEditor
209
+ },
210
+ {
211
+ name: 'Standard Material',
212
+ icon: 'circle',
213
+ nodeClass: StandardMaterialEditor
214
+ },
215
+ {
216
+ name: 'Points Material',
217
+ icon: 'circle-dotted',
218
+ nodeClass: PointsMaterialEditor
219
+ }
220
+ ]
221
+ }
222
+ ];
223
+
25
224
  export const ClassLib = {
26
- 'StandardMaterialEditor': StandardMaterialEditor,
27
- 'OperatorEditor': OperatorEditor,
28
- 'NormalizeEditor': NormalizeEditor,
29
- 'InvertEditor': InvertEditor,
30
- 'LimiterEditor': LimiterEditor,
31
- 'DotEditor': DotEditor,
32
- 'PowerEditor': PowerEditor,
33
- 'TrigonometryEditor': TrigonometryEditor,
34
- 'FloatEditor': FloatEditor,
35
- 'Vector2Editor': Vector2Editor,
36
- 'Vector3Editor': Vector3Editor,
37
- 'Vector4Editor': Vector4Editor,
38
- 'SliderEditor': SliderEditor,
39
- 'ColorEditor': ColorEditor,
40
- 'BlendEditor': BlendEditor,
41
- 'UVEditor': UVEditor,
42
- 'PositionEditor': PositionEditor,
43
- 'NormalEditor': NormalEditor,
44
- 'TimerEditor': TimerEditor,
45
- 'OscillatorEditor': OscillatorEditor,
46
- 'CheckerEditor': CheckerEditor
225
+ BasicMaterialEditor,
226
+ StandardMaterialEditor,
227
+ PointsMaterialEditor,
228
+ PointsEditor,
229
+ MeshEditor,
230
+ OperatorEditor,
231
+ NormalizeEditor,
232
+ InvertEditor,
233
+ LimiterEditor,
234
+ DotEditor,
235
+ PowerEditor,
236
+ AngleEditor,
237
+ TrigonometryEditor,
238
+ FloatEditor,
239
+ Vector2Editor,
240
+ Vector3Editor,
241
+ Vector4Editor,
242
+ SliderEditor,
243
+ ColorEditor,
244
+ BlendEditor,
245
+ UVEditor,
246
+ PositionEditor,
247
+ NormalEditor,
248
+ TimerEditor,
249
+ OscillatorEditor,
250
+ SplitEditor,
251
+ JoinEditor,
252
+ CheckerEditor
47
253
  };
48
254
 
49
255
  export class NodeEditor extends EventDispatcher {
50
256
 
51
- constructor() {
257
+ constructor( scene = null ) {
52
258
 
53
259
  super();
54
260
 
55
261
  const domElement = document.createElement( 'flow' );
56
262
  const canvas = new Canvas();
57
263
 
58
- domElement.appendChild( canvas.dom );
264
+ domElement.append( canvas.dom );
265
+
266
+ this.scene = scene;
59
267
 
60
268
  this.canvas = canvas;
61
269
  this.domElement = domElement;
@@ -63,16 +271,48 @@ export class NodeEditor extends EventDispatcher {
63
271
  this.nodesContext = null;
64
272
  this.examplesContext = null;
65
273
 
274
+ this._initTips();
66
275
  this._initMenu();
276
+ this._initSearch();
67
277
  this._initNodesContext();
68
278
  this._initExamplesContext();
69
279
 
70
280
  }
71
281
 
282
+ centralizeNode( node ) {
283
+
284
+ const canvas = this.canvas;
285
+ const canvasRect = canvas.rect;
286
+
287
+ const nodeRect = node.dom.getBoundingClientRect();
288
+
289
+ const defaultOffsetX = nodeRect.width;
290
+ const defaultOffsetY = nodeRect.height;
291
+
292
+ node.setPosition(
293
+ ( canvas.relativeX + ( canvasRect.width / 2 ) ) - defaultOffsetX,
294
+ ( canvas.relativeY + ( canvasRect.height / 2 ) ) - defaultOffsetY
295
+ );
296
+
297
+ }
298
+
72
299
  add( node ) {
73
300
 
301
+ const onRemove = () => {
302
+
303
+ node.removeEventListener( 'remove', onRemove );
304
+
305
+ node.setEditor( null );
306
+
307
+ };
308
+
309
+ node.setEditor( this );
310
+ node.addEventListener( 'remove', onRemove );
311
+
74
312
  this.canvas.add( node );
75
313
 
314
+ this.dispatchEvent( { type: 'add', node } );
315
+
76
316
  return this;
77
317
 
78
318
  }
@@ -97,51 +337,49 @@ export class NodeEditor extends EventDispatcher {
97
337
 
98
338
  this.canvas.deserialize( json );
99
339
 
340
+ for ( const node of this.canvas.nodes ) {
341
+
342
+ this.add( node );
343
+
344
+ }
345
+
100
346
  this.dispatchEvent( { type: 'load' } );
101
347
 
102
348
  }
103
349
 
350
+ _initTips() {
351
+
352
+ this.tips = new Tips();
353
+
354
+ this.domElement.append( this.tips.dom );
355
+
356
+ }
357
+
104
358
  _initMenu() {
105
359
 
106
360
  const menu = new CircleMenu();
107
361
 
108
- const menuButton = new ButtonInput().setIcon( 'ti ti-menu-2' );
362
+ const menuButton = new ButtonInput().setIcon( 'ti ti-apps' ).setToolTip( 'Add' );
109
363
  const examplesButton = new ButtonInput().setIcon( 'ti ti-file-symlink' ).setToolTip( 'Examples' );
110
364
  const newButton = new ButtonInput().setIcon( 'ti ti-file' ).setToolTip( 'New' );
111
365
  const openButton = new ButtonInput().setIcon( 'ti ti-upload' ).setToolTip( 'Open' );
112
366
  const saveButton = new ButtonInput().setIcon( 'ti ti-download' ).setToolTip( 'Save' );
113
367
 
114
- const hideContext = () => {
115
-
116
- this.examplesContext.hide();
117
- this.nodesContext.hide();
118
-
119
- };
120
-
121
- menuButton.onClick( () => {
122
-
123
- this.nodesContext.show( 60, 50 );
124
-
125
- } );
126
-
127
- examplesButton.onClick( () => {
128
-
129
- this.examplesContext.show( 60, 175 );
130
-
131
- } );
368
+ menuButton.onClick( () => this.nodesContext.open() );
369
+ examplesButton.onClick( () => this.examplesContext.open() );
132
370
 
133
371
  newButton.onClick( () => {
134
372
 
135
- hideContext();
373
+ if ( confirm( 'Are you sure?' ) === true ) {
136
374
 
137
- this.newProject();
375
+ this.newProject();
376
+
377
+ }
138
378
 
139
379
  } );
140
380
 
141
381
  openButton.onClick( () => {
142
382
 
143
- hideContext();
144
-
145
383
  const input = document.createElement( 'input' );
146
384
  input.type = 'file';
147
385
 
@@ -169,8 +407,6 @@ export class NodeEditor extends EventDispatcher {
169
407
 
170
408
  saveButton.onClick( () => {
171
409
 
172
- hideContext();
173
-
174
410
  const json = JSON.stringify( this.canvas.toJSON() );
175
411
 
176
412
  const a = document.createElement( 'a' );
@@ -182,13 +418,13 @@ export class NodeEditor extends EventDispatcher {
182
418
 
183
419
  } );
184
420
 
185
- menu.add( menuButton )
421
+ menu.add( examplesButton )
422
+ .add( menuButton )
186
423
  .add( newButton )
187
- .add( examplesButton )
188
424
  .add( openButton )
189
425
  .add( saveButton );
190
426
 
191
- this.domElement.appendChild( menu.dom );
427
+ this.domElement.append( menu.dom );
192
428
 
193
429
  this.menu = menu;
194
430
 
@@ -247,12 +483,133 @@ export class NodeEditor extends EventDispatcher {
247
483
  context.add( new ButtonInput( 'Basic' ), basicContext );
248
484
  context.add( new ButtonInput( 'Advanced' ), advancedContext );
249
485
 
250
- this.domElement.appendChild( context.dom );
251
-
252
486
  this.examplesContext = context;
253
487
 
254
488
  }
255
489
 
490
+ _initSearch() {
491
+
492
+ const traverseNodeEditors = ( item ) => {
493
+
494
+ if ( item.nodeClass ) {
495
+
496
+ const button = new ButtonInput( item.name );
497
+ button.setIcon( `ti ti-${item.icon}` );
498
+ button.addEventListener( 'complete', () => {
499
+
500
+ const node = new item.nodeClass();
501
+
502
+ this.add( node );
503
+
504
+ this.centralizeNode( node );
505
+
506
+ } );
507
+
508
+ search.add( button );
509
+
510
+ }
511
+
512
+ if ( item.children ) {
513
+
514
+ for ( const subItem of item.children ) {
515
+
516
+ traverseNodeEditors( subItem );
517
+
518
+ }
519
+
520
+ }
521
+
522
+ };
523
+
524
+ const search = new Search();
525
+ search.forceAutoComplete = true;
526
+
527
+ search.onFilter( () => {
528
+
529
+ search.clear();
530
+
531
+ for ( const item of NodeList ) {
532
+
533
+ traverseNodeEditors( item );
534
+
535
+ }
536
+
537
+ const object3d = this.scene;
538
+
539
+ if ( object3d !== null ) {
540
+
541
+ object3d.traverse( ( obj3d ) => {
542
+
543
+ if ( obj3d.isMesh === true || obj3d.isPoints === true ) {
544
+
545
+ let prefix = null;
546
+ let icon = null;
547
+ let editorClass = null;
548
+
549
+ if ( obj3d.isMesh === true ) {
550
+
551
+ prefix = 'Mesh';
552
+ icon = 'ti ti-3d-cube-sphere';
553
+ editorClass = MeshEditor;
554
+
555
+ } else if ( obj3d.isPoints === true ) {
556
+
557
+ prefix = 'Points';
558
+ icon = 'ti ti-border-none';
559
+ editorClass = PointsEditor;
560
+
561
+ }
562
+
563
+ const button = new ButtonInput( `${prefix} - ${obj3d.name}` );
564
+ button.setIcon( icon );
565
+ button.addEventListener( 'complete', () => {
566
+
567
+ for ( const node of this.canvas.nodes ) {
568
+
569
+ if ( node.value === obj3d ) {
570
+
571
+ // prevent duplicated node
572
+
573
+ this.canvas.select( node );
574
+
575
+ return;
576
+
577
+ }
578
+
579
+ }
580
+
581
+ const node = new editorClass( obj3d );
582
+
583
+ this.add( node );
584
+
585
+ this.centralizeNode( node );
586
+
587
+ } );
588
+
589
+ search.add( button );
590
+
591
+ }
592
+
593
+ } );
594
+
595
+ }
596
+
597
+ } );
598
+
599
+ search.onSubmit( () => {
600
+
601
+ if ( search.currentFiltered !== null ) {
602
+
603
+ search.currentFiltered.button.dispatchEvent( new Event( 'complete' ) );
604
+
605
+ }
606
+
607
+ } );
608
+
609
+ this.domElement.append( search.dom );
610
+
611
+ }
612
+
256
613
  _initNodesContext() {
257
614
 
258
615
  const context = new ContextMenu( this.domElement );
@@ -262,9 +619,6 @@ export class NodeEditor extends EventDispatcher {
262
619
 
263
620
  const add = ( node ) => {
264
621
 
265
- const canvas = this.canvas;
266
- const canvasRect = canvas.rect;
267
-
268
622
  if ( isContext ) {
269
623
 
270
624
  node.setPosition(
@@ -274,13 +628,7 @@ export class NodeEditor extends EventDispatcher {
274
628
 
275
629
  } else {
276
630
 
277
- const defaultOffsetX = 350 / 2;
278
- const defaultOffsetY = 20;
279
-
280
- node.setPosition(
281
- ( canvas.relativeX + ( canvasRect.width / 2 ) ) - defaultOffsetX,
282
- ( canvas.relativeY + ( canvasRect.height / 2 ) ) - defaultOffsetY
283
- );
631
+ this.centralizeNode( node );
284
632
 
285
633
  }
286
634
 
@@ -309,144 +657,50 @@ export class NodeEditor extends EventDispatcher {
309
657
  // INPUTS
310
658
  //**************//
311
659
 
312
- const inputsContext = new ContextMenu();
313
-
314
- const sliderInput = new ButtonInput( 'Slider' ).setIcon( 'ti ti-adjustments-horizontal' )
315
- .onClick( () => add( new SliderEditor() ) );
316
-
317
- const floatInput = new ButtonInput( 'Float' ).setIcon( 'ti ti-box-multiple-1' )
318
- .onClick( () => add( new FloatEditor() ) );
319
-
320
- const vector2Input = new ButtonInput( 'Vector 2' ).setIcon( 'ti ti-box-multiple-2' )
321
- .onClick( () => add( new Vector2Editor() ) );
322
-
323
- const vector3Input = new ButtonInput( 'Vector 3' ).setIcon( 'ti ti-box-multiple-3' )
324
- .onClick( () => add( new Vector3Editor() ) );
325
-
326
- const vector4Input = new ButtonInput( 'Vector 4' ).setIcon( 'ti ti-box-multiple-4' )
327
- .onClick( () => add( new Vector4Editor() ) );
328
-
329
- const colorInput = new ButtonInput( 'Color' ).setIcon( 'ti ti-palette' )
330
- .onClick( () => add( new ColorEditor() ) );
331
-
332
- //const mapInput = new ButtonInput( 'Map' ).setIcon( 'ti ti-photo' );
333
- //const cubeMapInput = new ButtonInput( 'Cube Map' ).setIcon( 'ti ti-box' );
334
- //const integerInput = new ButtonInput( 'Integer' ).setIcon( 'ti ti-list-numbers' );
335
-
336
- inputsContext
337
- .add( sliderInput )
338
- .add( floatInput )
339
- .add( vector2Input )
340
- .add( vector3Input )
341
- .add( vector4Input )
342
- .add( colorInput );
343
-
344
- //**************//
345
- // MATH
346
- //**************//
347
-
348
- const mathContext = new ContextMenu();
349
-
350
- const operatorsNode = new ButtonInput( 'Operator' ).setIcon( 'ti ti-math-symbols' )
351
- .onClick( () => add( new OperatorEditor() ) );
352
-
353
- const normalizeNode = new ButtonInput( 'Normalize' ).setIcon( 'ti ti-fold' )
354
- .onClick( () => add( new NormalizeEditor() ) );
355
-
356
- const invertNode = new ButtonInput( 'Invert' ).setToolTip( 'Negate' ).setIcon( 'ti ti-flip-vertical' )
357
- .onClick( () => add( new InvertEditor() ) );
358
-
359
- const limiterNode = new ButtonInput( 'Limiter' ).setToolTip( 'Min / Max' ).setIcon( 'ti ti-arrow-bar-to-up' )
360
- .onClick( () => add( new LimiterEditor() ) );
660
+ const createButtonMenu = ( item ) => {
361
661
 
362
- const dotNode = new ButtonInput( 'Dot Product' ).setIcon( 'ti ti-arrows-up-left' )
363
- .onClick( () => add( new DotEditor() ) );
662
+ const button = new ButtonInput( item.name );
663
+ button.setIcon( `ti ti-${item.icon}` );
364
664
 
365
- const powNode = new ButtonInput( 'Power' ).setIcon( 'ti ti-arrow-up-right' )
366
- .onClick( () => add( new PowerEditor() ) );
665
+ let context = null;
367
666
 
368
- const triNode = new ButtonInput( 'Trigonometry' ).setToolTip( 'Sin / Cos / Tan' ).setIcon( 'ti ti-wave-sine' )
369
- .onClick( () => add( new TrigonometryEditor() ) );
667
+ if ( item.nodeClass ) {
370
668
 
371
- mathContext
372
- .add( operatorsNode )
373
- .add( invertNode )
374
- .add( limiterNode )
375
- .add( dotNode )
376
- .add( powNode )
377
- .add( triNode )
378
- .add( normalizeNode );
669
+ button.onClick( () => add( new item.nodeClass() ) );
379
670
 
380
- //**************//
381
- // ACCESSORS
382
- //**************//
383
-
384
- const accessorsContext = new ContextMenu();
385
-
386
- const uvNode = new ButtonInput( 'UV' ).setIcon( 'ti ti-details' )
387
- .onClick( () => add( new UVEditor() ) );
671
+ }
388
672
 
389
- const positionNode = new ButtonInput( 'Position' ).setIcon( 'ti ti-hierarchy' )
390
- .onClick( () => add( new PositionEditor() ) );
673
+ if ( item.tip ) {
391
674
 
392
- const normalNode = new ButtonInput( 'Normal' ).setIcon( 'ti ti-fold-up' )
393
- .onClick( () => add( new NormalEditor() ) );
675
+ button.setToolTip( item.tip );
394
676
 
395
- accessorsContext
396
- .add( uvNode )
397
- .add( positionNode )
398
- .add( normalNode );
677
+ }
399
678
 
400
- //**************//
401
- // PROCEDURAL
402
- //**************//
679
+ if ( item.children ) {
403
680
 
404
- const proceduralContext = new ContextMenu();
681
+ context = new ContextMenu();
405
682
 
406
- const checkerNode = new ButtonInput( 'Checker' ).setIcon( 'ti ti-border-outer' )
407
- .onClick( () => add( new CheckerEditor() ) );
683
+ for ( const subItem of item.children ) {
408
684
 
409
- proceduralContext
410
- .add( checkerNode );
685
+ const buttonMenu = createButtonMenu( subItem );
411
686
 
412
- //**************//
413
- // DISPLAY
414
- //**************//
687
+ context.add( buttonMenu.button, buttonMenu.context );
415
688
 
416
- const displayContext = new ContextMenu();
689
+ }
417
690
 
418
- const blendNode = new ButtonInput( 'Blend' ).setIcon( 'ti ti-layers-subtract' )
419
- .onClick( () => add( new BlendEditor() ) );
420
-
421
- displayContext
422
- .add( blendNode );
423
-
424
- //**************//
425
- // UTILS
426
- //**************//
691
+ }
427
692
 
428
- const utilsContext = new ContextMenu();
693
+ return { button, context };
429
694
 
430
- const timerNode = new ButtonInput( 'Timer' ).setIcon( 'ti ti-clock' )
431
- .onClick( () => add( new TimerEditor() ) );
695
+ };
432
696
 
433
- const oscNode = new ButtonInput( 'Oscillator' ).setIcon( 'ti ti-wave-sine' )
434
- .onClick( () => add( new OscillatorEditor() ) );
697
+ for ( const item of NodeList ) {
435
698
 
436
- utilsContext
437
- .add( timerNode )
438
- .add( oscNode );
699
+ const buttonMenu = createButtonMenu( item );
439
700
 
440
- //**************//
441
- // MAIN
442
- //**************//
701
+ context.add( buttonMenu.button, buttonMenu.context );
443
702
 
444
- context.add( new ButtonInput( 'Inputs' ).setIcon( 'ti ti-forms' ), inputsContext );
445
- context.add( new ButtonInput( 'Accessors' ).setIcon( 'ti ti-vector-triangle' ), accessorsContext );
446
- context.add( new ButtonInput( 'Display' ).setIcon( 'ti ti-brightness' ), displayContext );
447
- context.add( new ButtonInput( 'Math' ).setIcon( 'ti ti-calculator' ), mathContext );
448
- context.add( new ButtonInput( 'Procedural' ).setIcon( 'ti ti-infinity' ), proceduralContext );
449
- context.add( new ButtonInput( 'Utils' ).setIcon( 'ti ti-apps' ), utilsContext );
703
+ }
450
704
 
451
705
  this.nodesContext = context;
452
706