sunrize 1.0.17 → 1.0.18

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sunrize",
3
3
  "productName": "Sunrize X3D Editor",
4
- "version": "1.0.17",
4
+ "version": "1.0.18",
5
5
  "description": "A Multi Platform X3D Editor",
6
6
  "homepage": "https://create3000.github.io/sunrize/",
7
7
  "author": "Holger Seelig",
@@ -39,7 +39,7 @@
39
39
  "@electron-forge/maker-rpm": "^6.1.1",
40
40
  "@electron-forge/maker-squirrel": "^6.1.1",
41
41
  "@electron-forge/maker-zip": "^6.1.1",
42
- "electron": "^24.1.0"
42
+ "electron": "^24.1.2"
43
43
  },
44
44
  "dependencies": {
45
45
  "capitalize": "^2.0.4",
@@ -58,7 +58,7 @@
58
58
  "qtip2": "^3.0.3",
59
59
  "spectrum-colorpicker2": "^2.0.10",
60
60
  "string-similarity": "^4.0.4",
61
- "x_ite": "^8.6.17"
61
+ "x_ite": "^8.6.18"
62
62
  },
63
63
  "main": "src/main.js",
64
64
  "bin": {
@@ -35,7 +35,7 @@ module .exports = class Dashboard extends Interface
35
35
  .on ("click", () => this .arrow ())
36
36
 
37
37
  this .playButton = $("<span></span>")
38
- .addClass (["material-icons", "active"])
38
+ .addClass (["material-icons"])
39
39
  .attr ("title", _ ("Toggle browser update."))
40
40
  .css ({ position: "relative", left: "-1px", "font-weight": "bold" })
41
41
  .text ("play_arrow")
@@ -63,7 +63,7 @@ module .exports = class Dashboard extends Interface
63
63
  {
64
64
  this .config .file .addDefaultValues ({
65
65
  pointer: "hand",
66
- play: true,
66
+ play: false,
67
67
  })
68
68
 
69
69
  this [this .config .file .pointer] ()
@@ -98,29 +98,14 @@ module .exports = new class Document extends Interface
98
98
 
99
99
  onfocus ()
100
100
  {
101
- if (this .activeElement)
102
- this .activeElement .off ("keyup.Document, change.Document")
101
+ this .activeElement ?.off ("keyup.Document, change.Document")
103
102
 
104
103
  this .activeElement = document .activeElement ? $(document .activeElement) : null
105
104
 
106
- if (this .activeElementIsInputOrOutput (false))
107
- {
108
- this .activeElement .on ("keyup.Document, change.Document", () => this .onchange ())
109
-
110
- this .onchange ()
111
- }
112
- else
113
- {
114
- this .autosave ()
115
- }
116
- }
105
+ if (this .activeElementIsInputOrOutput ())
106
+ this .activeElement .on ("keyup.Document, change.Document", () => this .undoManager ())
117
107
 
118
- onchange ()
119
- {
120
- electron .ipcRenderer .send ("change-menu", {
121
- undoLabel: document .queryCommandEnabled ("undo") ? _ ("Undo ") : _ ("Undo"),
122
- redoLabel: document .queryCommandEnabled ("redo") ? _ ("Redo ") : _ ("Redo"),
123
- })
108
+ this .undoManager ()
124
109
  }
125
110
 
126
111
  async restoreFile ()
@@ -174,8 +159,7 @@ module .exports = new class Document extends Interface
174
159
  */
175
160
  saveFile (force = false)
176
161
  {
177
- if (this .footer .scriptEditor)
178
- this .footer .scriptEditor .apply ()
162
+ this .footer .scriptEditor ?.apply ()
179
163
 
180
164
  if (!UndoManager .shared .saveNeeded && !force)
181
165
  return
@@ -289,7 +273,7 @@ module .exports = new class Document extends Interface
289
273
 
290
274
  undo ()
291
275
  {
292
- if (this .activeElementIsInputOrOutput (false))
276
+ if (this .activeElementIsInputOrOutput ())
293
277
  {
294
278
  if (this .activeElement .closest (".script-editor-monaco") .length)
295
279
  this .scriptEditor .monaco .getModel () .undo ()
@@ -297,12 +281,14 @@ module .exports = new class Document extends Interface
297
281
  document .execCommand ("undo")
298
282
  }
299
283
  else
284
+ {
300
285
  UndoManager .shared .undo ()
286
+ }
301
287
  }
302
288
 
303
289
  redo ()
304
290
  {
305
- if (this .activeElementIsInputOrOutput (false))
291
+ if (this .activeElementIsInputOrOutput ())
306
292
  {
307
293
  if (this .activeElement .closest (".script-editor-monaco") .length)
308
294
  this .scriptEditor .monaco .getModel () .redo ()
@@ -310,21 +296,33 @@ module .exports = new class Document extends Interface
310
296
  document .execCommand ("redo")
311
297
  }
312
298
  else
299
+ {
313
300
  UndoManager .shared .redo ()
301
+ }
314
302
  }
315
303
 
316
304
  undoManager ()
317
305
  {
318
- electron .ipcRenderer .send ("change-menu",
306
+ if (this .activeElementIsInputOrOutput ())
319
307
  {
320
- undoLabel: UndoManager .shared .undoLabel,
321
- redoLabel: UndoManager .shared .redoLabel,
322
- })
308
+ electron .ipcRenderer .send ("change-menu", {
309
+ undoLabel: document .queryCommandEnabled ("undo") ? _ ("Undo ") : _ ("Undo"),
310
+ redoLabel: document .queryCommandEnabled ("redo") ? _ ("Redo ") : _ ("Redo"),
311
+ })
312
+ }
313
+ else
314
+ {
315
+ electron .ipcRenderer .send ("change-menu",
316
+ {
317
+ undoLabel: UndoManager .shared .undoLabel,
318
+ redoLabel: UndoManager .shared .redoLabel,
319
+ })
323
320
 
324
- electron .ipcRenderer .sendToHost ("saved", !UndoManager .shared .saveNeeded)
321
+ electron .ipcRenderer .sendToHost ("saved", !UndoManager .shared .saveNeeded)
325
322
 
326
- if (UndoManager .shared .saveNeeded)
327
- this .autosave ()
323
+ if (UndoManager .shared .saveNeeded)
324
+ this .autosave ()
325
+ }
328
326
  }
329
327
 
330
328
  cut ()
@@ -317,7 +317,7 @@ module .exports = class Traverse
317
317
 
318
318
  for (let t = type .length - 1; t >= 0; -- t)
319
319
  {
320
- switch (type)
320
+ switch (type [t])
321
321
  {
322
322
  case X3D .X3DConstants .X3DExternProtoDeclaration:
323
323
  {
@@ -81,22 +81,25 @@ module .exports = class Console extends Interface
81
81
 
82
82
  async setBrowserEvent (event)
83
83
  {
84
- try
85
- {
86
- super .setBrowserEvent (event)
84
+ super .setBrowserEvent (event)
87
85
 
88
- if (event !== X3D .X3DConstants .INITIALIZED_EVENT)
89
- return
86
+ if (event !== X3D .X3DConstants .INITIALIZED_EVENT)
87
+ return
90
88
 
91
- this .scriptNode = this .browser .currentScene .createNode ("Script", { warn: false })
92
- this .scriptNode .url = new X3D .MFString ("ecmascript:")
93
- }
94
- catch (error)
95
- { }
96
- }
89
+ const Script = this .browser .getSupportedNode ("Script")
90
+
91
+ if (!Script)
92
+ return
93
+
94
+ this .scriptNode = new Script (this .browser .currentScene)
95
+ this .scriptNode ._url = new X3D .MFString ("ecmascript:")
96
+
97
+ this .scriptNode .setup ()
98
+ }
97
99
 
98
100
  excludes = new Set ([
99
101
  "The vm module of Node.js is deprecated in the renderer process and will be removed.",
102
+ "Invalid asm.js: Invalid member of stdlib",
100
103
  ])
101
104
 
102
105
  addMessage (event, level, sourceId, line, message)
@@ -227,7 +230,7 @@ module .exports = class Console extends Interface
227
230
 
228
231
  try
229
232
  {
230
- console .debug ("" + this .scriptNode .getValue () .evaluate (text))
233
+ console .debug ("" + this .scriptNode .evaluate (text))
231
234
  }
232
235
  catch (error)
233
236
  {
@@ -110,7 +110,9 @@ module .exports = new class Library extends Dialog
110
110
  if (event .key !== "Enter")
111
111
  return
112
112
 
113
- const first = this .list .find (".node") .first ()
113
+ const
114
+ first = this .list .find (".node") .first (),
115
+ component = this .list .find (".component") .first ()
114
116
 
115
117
  if (!first .length)
116
118
  return
@@ -122,9 +124,9 @@ module .exports = new class Library extends Dialog
122
124
  Type = SupportedNodes .getType (HTMLSupport .getNodeTypeName (input))
123
125
 
124
126
  if (Type)
125
- this .createNode (Type .prototype .getTypeName ())
127
+ this .createNode (Type .prototype .getTypeName (), Type .prototype .getComponentName ())
126
128
  else
127
- this .createNode (first .text ())
129
+ this .createNode (first .text (), component .attr ("name"))
128
130
  }
129
131
 
130
132
  update ()
@@ -177,6 +179,7 @@ module .exports = new class Library extends Dialog
177
179
 
178
180
  $("<li></li>")
179
181
  .addClass ("component")
182
+ .attr ("name", node .component)
180
183
  .text (this .browser .getSupportedComponents () .get (node .component) .title)
181
184
  .appendTo (this .list)
182
185
  }
@@ -185,16 +188,18 @@ module .exports = new class Library extends Dialog
185
188
  .addClass ("node")
186
189
  .text (node .typeName)
187
190
  .appendTo (this .list)
188
- .on ("dblclick", () => this .createNode (node .typeName))
191
+ .on ("dblclick", () => this .createNode (node .typeName, node .component))
189
192
  }
190
193
  }
191
194
 
192
- createNode (typeName)
195
+ createNode (typeName, component)
193
196
  {
194
- const node = this .executionContext .createNode (typeName, { warn: false })
195
-
196
197
  UndoManager .shared .beginUndo (_ ("Create Node %s"), typeName)
197
198
 
199
+ Editor .addComponent (this .executionContext, component)
200
+
201
+ const node = this .executionContext .createNode (typeName)
202
+
198
203
  Editor .insertValueIntoArray (this .executionContext, this .executionContext, this .executionContext .rootNodes, this .executionContext .rootNodes .length, node)
199
204
 
200
205
  UndoManager .shared .endUndo ()
@@ -200,103 +200,103 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
200
200
  submenu: [
201
201
  {
202
202
  label: "Transform",
203
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Transform", "children"],
203
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Transform", "children"],
204
204
  },
205
205
  {
206
206
  label: "Group",
207
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Group", "children"],
207
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Group", "children"],
208
208
  },
209
209
  {
210
210
  label: "StaticGroup",
211
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "StaticGroup", "children"],
211
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "StaticGroup", "children"],
212
212
  },
213
213
  {
214
214
  label: "Switch",
215
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Switch", "children"],
215
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Switch", "children"],
216
216
  },
217
217
  { type: "separator" },
218
218
  {
219
219
  label: "Billboard",
220
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Billboard", "children"],
220
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Billboard", "children"],
221
221
  },
222
222
  {
223
223
  label: "Collision",
224
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Collision", "children"],
224
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Collision", "children"],
225
225
  },
226
226
  {
227
227
  label: "LOD",
228
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "LOD", "children"],
228
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "LOD", "children"],
229
229
  },
230
230
  {
231
231
  label: "ViewpointGroup",
232
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "ViewpointGroup", "children"],
232
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "ViewpointGroup", "children"],
233
233
  },
234
234
  { type: "separator" },
235
235
  {
236
236
  label: "Anchor",
237
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Anchor", "children"],
237
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Anchor", "children"],
238
238
  },
239
239
  { type: "separator" },
240
240
  {
241
241
  label: "LayoutLayer",
242
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "LayoutLayer", "children"],
242
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "LayoutLayer", "children"],
243
243
  },
244
244
  {
245
245
  label: "ScreenGroup",
246
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "ScreenGroup", "children"],
246
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "ScreenGroup", "children"],
247
247
  },
248
248
  { type: "separator" },
249
249
  {
250
250
  label: "GeoTransform",
251
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "GeoTransform", "children"],
251
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoTransform", "children"],
252
252
  },
253
253
  {
254
254
  label: "GeoLocation",
255
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "GeoLocation", "children"],
255
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoLocation", "children"],
256
256
  },
257
257
  { type: "separator" },
258
258
  {
259
259
  label: "CADAssembly",
260
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADAssembly", "children"],
260
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADAssembly", "children"],
261
261
  },
262
262
  {
263
263
  label: "CADFace",
264
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADFace", "shape"],
264
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADFace", "shape"],
265
265
  },
266
266
  {
267
267
  label: "CADLayer",
268
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADLayer", "children"],
268
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADLayer", "children"],
269
269
  },
270
270
  {
271
271
  label: "CADPart",
272
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADPart", "children"],
272
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADPart", "children"],
273
273
  },
274
274
  { type: "separator" },
275
275
  {
276
276
  label: "LayerSet",
277
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "LayerSet", "layers"],
277
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "LayerSet", "layers"],
278
278
  },
279
279
  {
280
280
  label: "Layer",
281
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layer", "children"],
281
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Layer", "children"],
282
282
  },
283
283
  {
284
284
  label: "Viewport",
285
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Viewport", "children"],
285
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Viewport", "children"],
286
286
  },
287
287
  { type: "separator" },
288
288
  {
289
289
  label: "PickableGroup",
290
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "PickableGroup", "children"],
290
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Picking", "PickableGroup", "children"],
291
291
  },
292
292
  { type: "separator" },
293
293
  {
294
294
  label: "CollidableShape",
295
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CollidableShape", "shape"],
295
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableShape", "shape"],
296
296
  },
297
297
  {
298
298
  label: "CollidableOffset",
299
- args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CollidableOffset", "collidable"],
299
+ args:[ "addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableOffset", "collidable"],
300
300
  },
301
301
  ],
302
302
  },
@@ -629,7 +629,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
629
629
  UndoManager .shared .endUndo ()
630
630
  }
631
631
 
632
- addParentGroup (id, executionContextId, nodeId, typeName, fieldName)
632
+ addParentGroup (id, executionContextId, nodeId, component, typeName, fieldName)
633
633
  {
634
634
  const
635
635
  element = $(`#${id}`),
@@ -639,12 +639,16 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
639
639
  parentFieldElement = element .closest (".field, .scene", this .sceneGraph),
640
640
  parentNodeElement = parentFieldElement .closest (".node, .proto, .scene", this .sceneGraph),
641
641
  parentNode = this .getNode (parentNodeElement),
642
- parentField = parentFieldElement .hasClass ("scene") ? parentNode .rootNodes : this .getField (parentFieldElement),
643
- node = executionContext .createNode (typeName, { warn: false }) .getValue (),
644
- field = node .getField (fieldName)
642
+ parentField = parentFieldElement .hasClass ("scene") ? parentNode .rootNodes : this .getField (parentFieldElement)
645
643
 
646
644
  UndoManager .shared .beginUndo (_ ("Add Parent Group %s to Node %s"), typeName, childNode .getTypeName ())
647
645
 
646
+ Editor .addComponent (executionContext, component)
647
+
648
+ const
649
+ node = executionContext .createNode (typeName) .getValue (),
650
+ field = node .getField (fieldName)
651
+
648
652
  if (field instanceof X3D .X3DArrayField)
649
653
  Editor .insertValueIntoArray (executionContext, node, field, 0, childNode)
650
654
  else
@@ -772,7 +776,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
772
776
  {
773
777
  const externproto = this .objects .get (protoNodeId)
774
778
 
775
- externproto .loadNow ()
779
+ externproto .loadNow () .catch (Function .prototype)
776
780
  }
777
781
 
778
782
  async turnIntoExternPrototype (id, executionContextId, protoNodeId)
@@ -166,18 +166,30 @@ module .exports = class OutlineView extends Interface
166
166
  parent .data ("full-expanded", false)
167
167
 
168
168
  if (scene .getOuterNode () instanceof X3D .X3DProtoDeclaration)
169
- Traverse .traverse (scene, Traverse .ROOT_NODES, node => node .setup ())
169
+ {
170
+ Traverse .traverse (scene, Traverse .ROOT_NODES, node =>
171
+ {
172
+ if (node .isInitialized ())
173
+ return
174
+
175
+ if (node .getType () .includes (X3D .X3DConstants .X3DUrlObject))
176
+ node .requestImmediateLoad = () => Promise .resolve ()
177
+
178
+ node .setup ()
179
+ })
180
+ }
170
181
 
171
182
  if (scene .isScene ())
172
183
  scene ._units_changed .addInterest ("updateScene", this, parent, scene)
173
184
 
174
185
  // Generate subtrees.
175
186
 
176
- const externprotos = this .expandSceneExternProtoDeclarations (parent, scene)
177
- const protos = this .expandSceneProtoDeclarations (parent, scene)
178
- const rootNodes = this .expandSceneRootNodes (parent, scene)
179
- const importedNodes = this .expandSceneImportedNodes (parent, scene)
180
- const exportedNodes = this .expandSceneExportedNodes (parent, scene)
187
+ const
188
+ externprotos = this .expandSceneExternProtoDeclarations (parent, scene),
189
+ protos = this .expandSceneProtoDeclarations (parent, scene),
190
+ rootNodes = this .expandSceneRootNodes (parent, scene),
191
+ importedNodes = this .expandSceneImportedNodes (parent, scene),
192
+ exportedNodes = this .expandSceneExportedNodes (parent, scene)
181
193
 
182
194
  if (!externprotos .is (":empty") || !protos .is (":empty") || !rootNodes .is (":empty") || !importedNodes .is (":empty") || !exportedNodes .is (":empty"))
183
195
  {
@@ -472,7 +484,7 @@ module .exports = class OutlineView extends Interface
472
484
  expandSceneExportedNodes (parent, scene)
473
485
  {
474
486
  if (!scene .isScene ())
475
- return $("")
487
+ return $("<div></div>")
476
488
 
477
489
  const child = $("<div></div>")
478
490
  .addClass (["exported-nodes", "subtree"])
@@ -584,6 +596,8 @@ module .exports = class OutlineView extends Interface
584
596
 
585
597
  if (node .canUserDefinedFields ())
586
598
  {
599
+ // Move user-defined fields on top.
600
+
587
601
  const userDefinedFields = node .getUserDefinedFields ()
588
602
 
589
603
  fields .sort ((a, b) =>
@@ -595,6 +609,8 @@ module .exports = class OutlineView extends Interface
595
609
  return ub - ua
596
610
  })
597
611
 
612
+ // Move metadata field on top.
613
+
598
614
  fields .sort ((a, b) =>
599
615
  {
600
616
  const
@@ -604,7 +620,9 @@ module .exports = class OutlineView extends Interface
604
620
  return mb - ma
605
621
  })
606
622
 
607
- // Proto fields, instance fields, user-defined fields.
623
+ // Proto fields, user-defined fields.
624
+ // Instances are updated, because they completely change.
625
+
608
626
  node ._fields_changed .addInterest ("updateNode", this, parent, node, full)
609
627
  }
610
628
 
@@ -39,8 +39,6 @@ module .exports = class ScriptEditor extends Interface
39
39
 
40
40
  this .vSplitter = new Splitter (this .verticalSplitter, "vertical")
41
41
 
42
- this .vSplitter .splitter .on ("dblclick", () => this .closeLeftBar ())
43
-
44
42
  this .toolbar = $("<div></div>")
45
43
  .addClass (["toolbar", "vertical-toolbar", "script-editor-toolbar"])
46
44
  .appendTo (this .scriptEditor)
@@ -143,7 +141,7 @@ module .exports = class ScriptEditor extends Interface
143
141
  }
144
142
  }
145
143
 
146
- this .monaco .viewState = this .monaco .saveViewState ()
144
+ this .monaco .viewState = this .monaco ?.saveViewState ()
147
145
  }
148
146
 
149
147
  this .node = node
@@ -394,6 +392,8 @@ main ()
394
392
  {
395
393
  UndoManager .shared .beginUndo (_ ("Create New Script"))
396
394
 
395
+ Editor .addComponent (this .browser .currentScene, "Scripting")
396
+
397
397
  const nodes = Editor .importX3D (this .browser .currentScene, `
398
398
  DEF NewScript Script {
399
399
  url "ecmascript:
@@ -420,8 +420,11 @@ function set_field (value, time)
420
420
  {
421
421
  UndoManager .shared .beginUndo (_ ("Create New Shader"))
422
422
 
423
+ Editor .addComponent (this .browser .currentScene, "Shaders")
424
+
423
425
  const nodes = Editor .importX3D (this .browser .currentScene, `
424
426
  DEF NewShader ComposedShader {
427
+ language "GLSL"
425
428
  parts [
426
429
  DEF VertexShader ShaderPart {
427
430
  type "VERTEX"
@@ -503,16 +503,21 @@ module .exports = class Editor
503
503
  /**
504
504
  *
505
505
  * @param {X3DScene} scene
506
- * @returns {Array<ComponentInfo}
506
+ * @returns {Array<ComponentInfo>}
507
507
  */
508
508
  static getUsedComponents (scene)
509
509
  {
510
510
  const components = new Set ()
511
511
 
512
- Traverse .traverse (scene, Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES, (node) =>
512
+ Traverse .traverse (scene, Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES | Traverse .PROTOTYPE_INSTANCES, (node) =>
513
513
  {
514
- if (node .getType () .includes (X3D .X3DConstants .X3DNode))
515
- components .add (node .getComponentName ())
514
+ if (!node .getType () .includes (X3D .X3DConstants .X3DNode))
515
+ return
516
+
517
+ if (node .getScene () !== scene)
518
+ return
519
+
520
+ components .add (node .getComponentName ())
516
521
  })
517
522
 
518
523
  return components
@@ -585,8 +590,8 @@ module .exports = class Editor
585
590
 
586
591
  undoManager .beginUndo (_ ("Set Components of Scene"))
587
592
 
588
- for (const component of oldComponents)
589
- scene .removeComponent (component)
593
+ for (const { name } of oldComponents)
594
+ scene .removeComponent (name)
590
595
 
591
596
  for (const component of components)
592
597
  scene .addComponent (component)
@@ -599,6 +604,42 @@ module .exports = class Editor
599
604
  undoManager .endUndo ()
600
605
  }
601
606
 
607
+ static addComponent (executionContext, name, undoManager = UndoManager .shared)
608
+ {
609
+ if (executionContext .hasComponent (name))
610
+ return
611
+
612
+ const browser = executionContext .getBrowser ()
613
+
614
+ undoManager .beginUndo (_ ("Add Component %s"), name)
615
+
616
+ executionContext .addComponent (browser .getComponent (name))
617
+
618
+ undoManager .registerUndo (() =>
619
+ {
620
+ this .removeComponent (executionContext, name, undoManager)
621
+ })
622
+
623
+ undoManager .endUndo ()
624
+ }
625
+
626
+ static removeComponent (executionContext, name, undoManager = UndoManager .shared)
627
+ {
628
+ if (!executionContext .hasComponent (name))
629
+ return
630
+
631
+ undoManager .beginUndo (_ ("Remove Component %s"), name)
632
+
633
+ executionContext .removeComponent (name)
634
+
635
+ undoManager .registerUndo (() =>
636
+ {
637
+ this .addComponent (executionContext, name, undoManager)
638
+ })
639
+
640
+ undoManager .endUndo ()
641
+ }
642
+
602
643
  /**
603
644
  *
604
645
  * @param {X3DScene} scene