sunrize 1.7.40 → 1.7.41

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.7.40",
4
+ "version": "1.7.41",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -109,7 +109,7 @@
109
109
  "string-similarity": "^4.0.4",
110
110
  "tweakpane": "^3.1.10",
111
111
  "update-electron-app": "^3.1.0",
112
- "x_ite": "^11.0.2",
113
- "x3d-traverse": "^1.0.8"
112
+ "x_ite": "^11.0.3",
113
+ "x3d-traverse": "^1.0.9"
114
114
  }
115
115
  }
@@ -6,7 +6,7 @@ const
6
6
  electron = require ("electron"),
7
7
  fs = require ("fs"),
8
8
  path = require ("path"),
9
- X3D = require ("../X3D"),
9
+ X3D = require ("x_ite"),
10
10
  Interface = require ("./Interface"),
11
11
  Splitter = require ("../Controls/Splitter"),
12
12
  Dashboard = require ("./Dashboard"),
@@ -133,10 +133,10 @@ module .exports = class Document extends Interface
133
133
 
134
134
  // Override replaceWorld and loadURL.
135
135
 
136
- this .#replaceWorld = X3D .X3DBrowser .prototype .replaceWorld;
136
+ this .#replaceWorld = this .browser .replaceWorld;
137
137
 
138
- X3D .X3DBrowser .prototype .loadURL = () => Promise .resolve ();
139
- X3D .X3DBrowser .prototype .replaceWorld = () => Promise .resolve ();
138
+ this .browser .loadURL = () => Promise .resolve ();
139
+ this .browser .replaceWorld = () => Promise .resolve ();
140
140
 
141
141
  // Connect browser options.
142
142
 
@@ -42,6 +42,9 @@ module .exports = new class Selection extends Interface
42
42
 
43
43
  has (node)
44
44
  {
45
+ if (!node)
46
+ return false;
47
+
45
48
  return this .nodes .includes (node .valueOf ());
46
49
  }
47
50
 
@@ -53,6 +56,9 @@ module .exports = new class Selection extends Interface
53
56
 
54
57
  set (node)
55
58
  {
59
+ if (!node)
60
+ return;
61
+
56
62
  this .#clear (node);
57
63
  this .#add (node);
58
64
  this .processInterests ();
@@ -60,12 +66,18 @@ module .exports = new class Selection extends Interface
60
66
 
61
67
  add (node)
62
68
  {
69
+ if (!node)
70
+ return;
71
+
63
72
  this .#add (node);
64
73
  this .processInterests ();
65
74
  }
66
75
 
67
76
  remove (node)
68
77
  {
78
+ if (!node)
79
+ return;
80
+
69
81
  this .#remove (node);
70
82
  this .processInterests ();
71
83
  }
@@ -81,9 +81,6 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
81
81
  if (!(this .isEditable (element) || element .is (".exported-node")))
82
82
  return;
83
83
 
84
- if (element .attr ("node-id") === "NULL")
85
- return;
86
-
87
84
  if (!element .is (".manually"))
88
85
  this .sceneGraph .find (".manually") .removeClass ("manually");
89
86
 
@@ -206,297 +203,317 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
206
203
  parentFieldElement = element .closest (".field, .scene", this .sceneGraph),
207
204
  parentNodeElement = parentFieldElement .closest (".node, .proto, .scene", this .sceneGraph);
208
205
 
209
- var menu = [
210
- {
211
- label: _("Rename Node..."),
212
- args: ["renameNode", element .attr ("id"), executionContext .getId (), node .getId ()],
213
- },
214
- {
215
- label: _("Export Node..."),
216
- enabled: executionContext === this .executionContext,
217
- args: ["addExportedNode", element .attr ("id"), executionContext .getId (), node .getId ()],
218
- },
219
- {
220
- label: _("Add Node..."),
221
- args: ["openLibrary", element .attr ("id"), executionContext .getId (), node .getId ()],
222
- },
223
- { type: "separator" },
224
- {
225
- label: _("Cut"),
226
- args: ["cutNodes"],
227
- },
228
- {
229
- label: _("Copy"),
230
- args: ["copyNodes"],
231
- },
232
- {
233
- label: _("Paste"),
234
- args: ["pasteNodes", element .attr ("id"), executionContext .getId (), node .getId ()],
235
- },
236
- {
237
- label: _("Delete"),
238
- args: ["deleteNodes"],
239
- },
240
- {
241
- label: _("Unlink Clone"),
242
- enabled: node .getCloneCount () > 1,
243
- args: ["unlinkClone", element .attr ("id"), executionContext .getId (), node .getId ()],
244
- },
245
- { type: "separator" },
246
- {
247
- label: _("Add Field..."),
248
- visible: node .canUserDefinedFields (),
249
- args: ["addUserDefinedField", element .attr ("id"), executionContext .getId (), node .getId ()],
250
- },
251
- { type: "separator" },
252
- {
253
- label: _("Add Parent Group"),
254
- submenu: [
255
- {
256
- label: "Transform",
257
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Transform", "children"],
258
- },
259
- {
260
- label: "Group",
261
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Group", "children"],
262
- },
263
- {
264
- label: "StaticGroup",
265
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "StaticGroup", "children"],
266
- },
267
- {
268
- label: "Switch",
269
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Switch", "children"],
270
- },
271
- { type: "separator" },
272
- {
273
- label: "Billboard",
274
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Billboard", "children"],
275
- },
276
- {
277
- label: "Collision",
278
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Collision", "children"],
279
- },
280
- {
281
- label: "LOD",
282
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "LOD", "children"],
283
- },
284
- {
285
- label: "ViewpointGroup",
286
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "ViewpointGroup", "children"],
287
- },
288
- { type: "separator" },
289
- {
290
- label: "Anchor",
291
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Anchor", "children"],
292
- },
293
- { type: "separator" },
294
- {
295
- label: "LayoutLayer",
296
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "LayoutLayer", "children"],
297
- },
298
- {
299
- label: "ScreenGroup",
300
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "ScreenGroup", "children"],
301
- },
302
- { type: "separator" },
303
- {
304
- label: "GeoTransform",
305
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoTransform", "children"],
306
- },
307
- {
308
- label: "GeoLocation",
309
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoLocation", "children"],
310
- },
311
- { type: "separator" },
312
- {
313
- label: "CADLayer",
314
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADLayer", "children"],
315
- },
316
- {
317
- label: "CADAssembly",
318
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADAssembly", "children"],
319
- },
320
- {
321
- label: "CADPart",
322
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADPart", "children"],
323
- },
324
- {
325
- label: "CADFace",
326
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADFace", "shape"],
327
- },
328
- { type: "separator" },
329
- {
330
- label: "LayerSet",
331
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "LayerSet", "layers"],
332
- },
333
- {
334
- label: "Layer",
335
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Layer", "children"],
336
- },
337
- {
338
- label: "Viewport",
339
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Viewport", "children"],
340
- },
341
- { type: "separator" },
342
- {
343
- label: "PickableGroup",
344
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Picking", "PickableGroup", "children"],
345
- },
346
- { type: "separator" },
347
- {
348
- label: "CollidableOffset",
349
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableOffset", "collidable"],
350
- },
351
- {
352
- label: "CollidableShape",
353
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableShape", "shape"],
354
- },
355
- ],
356
- },
357
- {
358
- label: _("Remove Parent"),
359
- enabled: parentNodeElement .hasClass ("node"),
360
- args: ["removeParent", element .attr ("id"), executionContext .getId (), node .getId ()],
361
- },
362
- { type: "separator" },
363
- ];
364
-
365
- for (const type of node .getType () .toReversed ())
206
+ if (node)
366
207
  {
367
- switch (type)
208
+ var menu = [
209
+ {
210
+ label: _("Rename Node..."),
211
+ args: ["renameNode", element .attr ("id"), executionContext .getId (), node .getId ()],
212
+ },
213
+ {
214
+ label: _("Export Node..."),
215
+ enabled: executionContext === this .executionContext,
216
+ args: ["addExportedNode", element .attr ("id"), executionContext .getId (), node .getId ()],
217
+ },
218
+ {
219
+ label: _("Add Node..."),
220
+ args: ["openLibrary", element .attr ("id"), executionContext .getId (), node .getId ()],
221
+ },
222
+ { type: "separator" },
223
+ {
224
+ label: _("Cut"),
225
+ args: ["cutNodes"],
226
+ },
227
+ {
228
+ label: _("Copy"),
229
+ args: ["copyNodes"],
230
+ },
231
+ {
232
+ label: _("Paste"),
233
+ args: ["pasteNodes", element .attr ("id"), executionContext .getId (), node .getId ()],
234
+ },
235
+ {
236
+ label: _("Delete"),
237
+ args: ["deleteNodes"],
238
+ },
239
+ {
240
+ label: _("Unlink Clone"),
241
+ enabled: node .getCloneCount () > 1,
242
+ args: ["unlinkClone", element .attr ("id"), executionContext .getId (), node .getId ()],
243
+ },
244
+ { type: "separator" },
245
+ {
246
+ label: _("Add Field..."),
247
+ visible: node .canUserDefinedFields (),
248
+ args: ["addUserDefinedField", element .attr ("id"), executionContext .getId (), node .getId ()],
249
+ },
250
+ { type: "separator" },
251
+ {
252
+ label: _("Add Parent Group"),
253
+ submenu: [
254
+ {
255
+ label: "Transform",
256
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Transform", "children"],
257
+ },
258
+ {
259
+ label: "Group",
260
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Group", "children"],
261
+ },
262
+ {
263
+ label: "StaticGroup",
264
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "StaticGroup", "children"],
265
+ },
266
+ {
267
+ label: "Switch",
268
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Switch", "children"],
269
+ },
270
+ { type: "separator" },
271
+ {
272
+ label: "Billboard",
273
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Billboard", "children"],
274
+ },
275
+ {
276
+ label: "Collision",
277
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Collision", "children"],
278
+ },
279
+ {
280
+ label: "LOD",
281
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "LOD", "children"],
282
+ },
283
+ {
284
+ label: "ViewpointGroup",
285
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "ViewpointGroup", "children"],
286
+ },
287
+ { type: "separator" },
288
+ {
289
+ label: "Anchor",
290
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Anchor", "children"],
291
+ },
292
+ { type: "separator" },
293
+ {
294
+ label: "LayoutLayer",
295
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "LayoutLayer", "children"],
296
+ },
297
+ {
298
+ label: "ScreenGroup",
299
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "ScreenGroup", "children"],
300
+ },
301
+ { type: "separator" },
302
+ {
303
+ label: "GeoTransform",
304
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoTransform", "children"],
305
+ },
306
+ {
307
+ label: "GeoLocation",
308
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoLocation", "children"],
309
+ },
310
+ { type: "separator" },
311
+ {
312
+ label: "CADLayer",
313
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADLayer", "children"],
314
+ },
315
+ {
316
+ label: "CADAssembly",
317
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADAssembly", "children"],
318
+ },
319
+ {
320
+ label: "CADPart",
321
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADPart", "children"],
322
+ },
323
+ {
324
+ label: "CADFace",
325
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADFace", "shape"],
326
+ },
327
+ { type: "separator" },
328
+ {
329
+ label: "LayerSet",
330
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "LayerSet", "layers"],
331
+ },
332
+ {
333
+ label: "Layer",
334
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Layer", "children"],
335
+ },
336
+ {
337
+ label: "Viewport",
338
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Viewport", "children"],
339
+ },
340
+ { type: "separator" },
341
+ {
342
+ label: "PickableGroup",
343
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Picking", "PickableGroup", "children"],
344
+ },
345
+ { type: "separator" },
346
+ {
347
+ label: "CollidableOffset",
348
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableOffset", "collidable"],
349
+ },
350
+ {
351
+ label: "CollidableShape",
352
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableShape", "shape"],
353
+ },
354
+ ],
355
+ },
356
+ {
357
+ label: _("Remove Parent"),
358
+ enabled: parentNodeElement .hasClass ("node"),
359
+ args: ["removeParent", element .attr ("id"), executionContext .getId (), node .getId ()],
360
+ },
361
+ { type: "separator" },
362
+ ];
363
+
364
+ for (const type of node .getType () .toReversed ())
368
365
  {
369
- case X3D .X3DConstants .ElevationGrid:
370
- case X3D .X3DConstants .GeoElevationGrid:
371
- case X3D .X3DConstants .X3DComposedGeometryNode:
366
+ switch (type)
372
367
  {
373
- if (node ._normal .getValue ())
368
+ case X3D .X3DConstants .ElevationGrid:
369
+ case X3D .X3DConstants .GeoElevationGrid:
370
+ case X3D .X3DConstants .X3DComposedGeometryNode:
374
371
  {
375
- menu .push ({
376
- label: _("Remove Normals"),
377
- args: ["removeNormalsFromGeometry", element .attr ("id"), executionContext .getId (), node .getId ()],
378
- });
372
+ if (node ._normal .getValue ())
373
+ {
374
+ menu .push ({
375
+ label: _("Remove Normals"),
376
+ args: ["removeNormalsFromGeometry", element .attr ("id"), executionContext .getId (), node .getId ()],
377
+ });
378
+ }
379
+ else
380
+ {
381
+ menu .push ({
382
+ label: _("Add Normals"),
383
+ args: ["addNormalsToGeometry", element .attr ("id"), executionContext .getId (), node .getId ()],
384
+ });
385
+ }
386
+
387
+ continue;
379
388
  }
380
- else
389
+ case X3D .X3DConstants .ImageTexture:
381
390
  {
382
- menu .push ({
383
- label: _("Add Normals"),
384
- args: ["addNormalsToGeometry", element .attr ("id"), executionContext .getId (), node .getId ()],
385
- });
386
- }
391
+ if (node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE)
392
+ {
393
+ menu .push ({
394
+ label: _("Convert Node to PixelTexture"),
395
+ args: ["convertImageTextureToPixelTexture", element .attr ("id"), executionContext .getId (), node .getId ()],
396
+ });
397
+ }
387
398
 
388
- continue;
389
- }
390
- case X3D .X3DConstants .ImageTexture:
391
- {
392
- if (node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE)
399
+ continue;
400
+ }
401
+ case X3D .X3DConstants .Inline:
393
402
  {
394
403
  menu .push ({
395
- label: _("Convert Node to PixelTexture"),
396
- args: ["convertImageTextureToPixelTexture", element .attr ("id"), executionContext .getId (), node .getId ()],
404
+ label: _("Open Inline Scene in New Tab"),
405
+ enabled: node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE,
406
+ args: ["openFileInNewTab", node .getInternalScene () ?.worldURL],
407
+ },
408
+ {
409
+ label: _("Fold Inline Back into Scene"),
410
+ enabled: node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE,
411
+ args: ["foldInlineBackIntoScene", element .attr ("id"), executionContext .getId (), node .getId ()],
397
412
  });
398
- }
399
-
400
- continue;
401
- }
402
- case X3D .X3DConstants .Inline:
403
- {
404
- menu .push ({
405
- label: _("Open Inline Scene in New Tab"),
406
- enabled: node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE,
407
- args: ["openFileInNewTab", node .getInternalScene () ?.worldURL],
408
- },
409
- {
410
- label: _("Fold Inline Back into Scene"),
411
- enabled: node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE,
412
- args: ["foldInlineBackIntoScene", element .attr ("id"), executionContext .getId (), node .getId ()],
413
- });
414
413
 
415
- continue;
416
- }
417
- case X3D .X3DConstants .PixelTexture:
418
- {
419
- menu .push ({
420
- label: _("Update Image from File..."),
421
- args: ["updatePixelTextureFromFile", element .attr ("id"), executionContext .getId (), node .getId ()],
422
- });
423
-
424
- if (node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE)
414
+ continue;
415
+ }
416
+ case X3D .X3DConstants .PixelTexture:
425
417
  {
426
418
  menu .push ({
427
- label: _("Convert Node to ImageTexture"),
428
- args: ["convertPixelTextureToImageTexture", element .attr ("id"), executionContext .getId (), node .getId ()],
419
+ label: _("Update Image from File..."),
420
+ args: ["updatePixelTextureFromFile", element .attr ("id"), executionContext .getId (), node .getId ()],
429
421
  });
430
- }
431
-
432
- continue;
433
- }
434
- case X3D .X3DConstants .X3DPrototypeInstance:
435
- {
436
- if (!$.try (() => node .getInnerNode () .getType () .includes (X3D .X3DConstants .X3DChildNode)))
437
- continue;
438
422
 
439
- // Proceed with next case:
440
- }
441
- case X3D .X3DConstants .X3DChildNode:
442
- {
443
- menu .push ({
444
- label: _("Convert Node to Inline File..."),
445
- args: ["convertNodeToInlineFile", element .attr ("id"), executionContext .getId (), node .getId ()],
446
- });
423
+ if (node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE)
424
+ {
425
+ menu .push ({
426
+ label: _("Convert Node to ImageTexture"),
427
+ args: ["convertPixelTextureToImageTexture", element .attr ("id"), executionContext .getId (), node .getId ()],
428
+ });
429
+ }
447
430
 
448
- continue;
449
- }
450
- case X3D .X3DConstants .X3DBoundedObject:
451
- {
452
- menu .push ({
453
- label: _("Determine Bounding Box from Scratch"),
454
- args: ["determineBoundingBoxFromScratch", element .attr ("id"), executionContext .getId (), node .getId ()],
455
- });
431
+ continue;
432
+ }
433
+ case X3D .X3DConstants .X3DPrototypeInstance:
434
+ {
435
+ if (!$.try (() => node .getInnerNode () .getType () .includes (X3D .X3DConstants .X3DChildNode)))
436
+ continue;
456
437
 
457
- if (!node ._bboxSize .equals (new X3D .SFVec3f (-1, -1, -1)))
438
+ // Proceed with next case:
439
+ }
440
+ case X3D .X3DConstants .X3DChildNode:
458
441
  {
459
442
  menu .push ({
460
- label: _("Remove Custom Bounding Box"),
461
- args: ["removeCustomBoundingBox", element .attr ("id"), executionContext .getId (), node .getId ()],
443
+ label: _("Convert Node to Inline File..."),
444
+ args: ["convertNodeToInlineFile", element .attr ("id"), executionContext .getId (), node .getId ()],
462
445
  });
463
- }
464
446
 
465
- continue;
466
- }
467
- case X3D .X3DConstants .X3DUrlObject:
468
- {
469
- if (node ._url .some (fileURL => !fileURL .match (/^\s*(?:data|ecmascript|javascript|vrmlscript):/s)))
447
+ continue;
448
+ }
449
+ case X3D .X3DConstants .X3DBoundedObject:
470
450
  {
471
451
  menu .push ({
472
- label: _("Embed External Resource as Data URL"),
473
- args: ["embedExternalResourceAsDataURL", element .attr ("id"), executionContext .getId (), node .getId ()],
452
+ label: _("Determine Bounding Box from Scratch"),
453
+ args: ["determineBoundingBoxFromScratch", element .attr ("id"), executionContext .getId (), node .getId ()],
474
454
  });
455
+
456
+ if (!node ._bboxSize .equals (new X3D .SFVec3f (-1, -1, -1)))
457
+ {
458
+ menu .push ({
459
+ label: _("Remove Custom Bounding Box"),
460
+ args: ["removeCustomBoundingBox", element .attr ("id"), executionContext .getId (), node .getId ()],
461
+ });
462
+ }
463
+
464
+ continue;
475
465
  }
466
+ case X3D .X3DConstants .X3DUrlObject:
467
+ {
468
+ if (node ._url .some (fileURL => !fileURL .match (/^\s*(?:data|ecmascript|javascript|vrmlscript):/s)))
469
+ {
470
+ menu .push ({
471
+ label: _("Embed External Resource as Data URL"),
472
+ args: ["embedExternalResourceAsDataURL", element .attr ("id"), executionContext .getId (), node .getId ()],
473
+ });
474
+ }
476
475
 
477
- if (node ._url .some (fileURL => fileURL .match (/^\s*(?:data|ecmascript|javascript|vrmlscript):/s)))
476
+ if (node ._url .some (fileURL => fileURL .match (/^\s*(?:data|ecmascript|javascript|vrmlscript):/s)))
477
+ {
478
+ menu .push ({
479
+ label: _("Save Data URL to File..."),
480
+ args: ["saveDataUrlToFile", element .attr ("id"), executionContext .getId (), node .getId ()],
481
+ });
482
+ }
483
+
484
+ continue;
485
+ }
486
+ case X3D .X3DConstants .X3DViewpointNode:
478
487
  {
479
488
  menu .push ({
480
- label: _("Save Data URL to File..."),
481
- args: ["saveDataUrlToFile", element .attr ("id"), executionContext .getId (), node .getId ()],
489
+ label: _("Move Viewpoint to User Position"),
490
+ args: ["moveViewpointToUserPosition", element .attr ("id"), executionContext .getId (), node .getId ()],
482
491
  });
483
- }
484
-
485
- continue;
486
- }
487
- case X3D .X3DConstants .X3DViewpointNode:
488
- {
489
- menu .push ({
490
- label: _("Move Viewpoint to User Position"),
491
- args: ["moveViewpointToUserPosition", element .attr ("id"), executionContext .getId (), node .getId ()],
492
- });
493
492
 
494
- continue;
493
+ continue;
494
+ }
495
+ default:
496
+ continue;
495
497
  }
496
- default:
497
- continue;
498
498
  }
499
499
  }
500
+ else
501
+ {
502
+ var menu = [
503
+ {
504
+ label: _("Cut"),
505
+ args: ["cutNodes"],
506
+ },
507
+ {
508
+ label: _("Copy"),
509
+ args: ["copyNodes"],
510
+ },
511
+ {
512
+ label: _("Delete"),
513
+ args: ["deleteNodes"],
514
+ },
515
+ ];
516
+ }
500
517
  }
501
518
 
502
519
  else if (element .is (".exported-node"))
@@ -796,7 +813,15 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
796
813
 
797
814
  async cutNodes ()
798
815
  {
799
- UndoManager .shared .beginUndo (_("Cut Nodes"));
816
+ const
817
+ primary = $(".node.primary, .proto.primary, .externproto.primary"),
818
+ selected = this .sceneGraph .find (".node.manually, .proto.manually, .externproto.manually"),
819
+ selection = selected .filter (primary) .length ? selected : primary,
820
+ ids = selection .map (function () { return this .id }) .get (),
821
+ elements = ids .map (id => $(`#${id}`)),
822
+ nodes = elements .map (element => this .getNode ($(element)));
823
+
824
+ UndoManager .shared .beginUndo (nodes .length === 1 ? _("Cut %d Node") : _("Cut %d Nodes"), nodes .length);
800
825
 
801
826
  await this .copyNodes ();
802
827
  await this .deleteNodes ();
@@ -821,7 +846,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
821
846
  {
822
847
  const node = this .getNode ($(element));
823
848
 
824
- if (!node .getType () .some (type => this .transformLikeNodes .has (type)))
849
+ if (!node ?.getType () .some (type => this .transformLikeNodes .has (type)))
825
850
  continue;
826
851
 
827
852
  Editor .setMatrixWithCenter (node, this .getModelMatrix (element), undefined, undoManager);
@@ -871,7 +896,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
871
896
 
872
897
  async pasteNodes (id, executionContextId, nodeId, fieldId)
873
898
  {
874
- try
899
+ // try
875
900
  {
876
901
  // if there is a selected field or node, update nodeId and fieldId.
877
902
 
@@ -892,7 +917,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
892
917
  for (const node of nodes)
893
918
  {
894
919
  const
895
- containerField = $.try (() => node .getInnerNode () .getContainerField ()) ?? node .getContainerField (),
920
+ containerField = $.try (() => node .getInnerNode () .getContainerField ()) ?? node ?.getContainerField (),
896
921
  field = targetField ?? $.try (() => targetNode ?.getField (containerField));
897
922
 
898
923
  if (!field)
@@ -900,7 +925,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
900
925
 
901
926
  // Adjust matrix.
902
927
 
903
- if (node .getType () .some (type => this .transformLikeNodes .has (type)))
928
+ if (node ?.getType () .some (type => this .transformLikeNodes .has (type)))
904
929
  {
905
930
  const
906
931
  sourceModelMatrix = node .getMatrix (),
@@ -935,11 +960,11 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
935
960
  for (const node of nodes)
936
961
  this .expandTo (node);
937
962
  }
938
- catch (error)
939
- {
940
- // Catch "Document is not focused." from navigator.clipboard.readText.
941
- console .error (`Paste failed: ${error .message}`);
942
- }
963
+ // catch (error)
964
+ // {
965
+ // // Catch "Document is not focused." from navigator.clipboard.readText.
966
+ // console .error (`Paste failed: ${error .message}`);
967
+ // }
943
968
  }
944
969
 
945
970
  deleteNodes ()
@@ -953,7 +978,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
953
978
  if (ids .length > 1)
954
979
  UndoManager .shared .beginUndo (_("Delete %s Nodes"), ids .length);
955
980
  else if (ids .length === 1)
956
- UndoManager .shared .beginUndo (_("Delete Node %s"), this .getNode ($(`#${ids [0]}`)) .getTypeName ());
981
+ UndoManager .shared .beginUndo (_("Delete Node %s"), this .getNode ($(`#${ids [0]}`)) ?.getTypeName () ?? "NULL");
957
982
  else
958
983
  return;
959
984
 
@@ -3067,9 +3092,16 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3067
3092
  {
3068
3093
  const
3069
3094
  sourceElement = $("#" + sourceElementsIds [0]),
3070
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement);
3095
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement);
3071
3096
 
3072
- UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), sourceNode .getTypeName (), sourceNode .getDisplayName ());
3097
+ if (sourceNode)
3098
+ {
3099
+ UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), sourceNode .getTypeName (), sourceNode .getDisplayName ());
3100
+ }
3101
+ else
3102
+ {
3103
+ UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), "NULL");
3104
+ }
3073
3105
  }
3074
3106
  else
3075
3107
  {
@@ -3084,7 +3116,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3084
3116
  {
3085
3117
  const
3086
3118
  sourceElement = $("#" + sourceElementId),
3087
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement),
3119
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement),
3088
3120
  sourceExecutionContextElement = sourceElement .closest (".scene", this .sceneGraph),
3089
3121
  sourceExecutionContext = this .getNode (sourceExecutionContextElement);
3090
3122
 
@@ -3117,7 +3149,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3117
3149
  sourceExecutionContext = this .getNode (sourceExecutionContextElement);
3118
3150
 
3119
3151
  let
3120
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement),
3152
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement),
3121
3153
  sourceIndex = parseInt (sourceElement .attr ("index"));
3122
3154
 
3123
3155
  if (destinationElement .attr ("node-id") !== "NULL")
@@ -3128,7 +3160,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3128
3160
  continue;
3129
3161
 
3130
3162
  const containerField = $.try (() => sourceNode .getInnerNode () .getContainerField ())
3131
- ?? sourceNode .getContainerField ();
3163
+ ?? sourceNode ?.getContainerField ();
3132
3164
 
3133
3165
  if (containerField)
3134
3166
  destinationParentField = $.try (() => destinationParentNode .getField (containerField));
@@ -3204,7 +3236,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3204
3236
 
3205
3237
  if (destinationElement .data ("dropEffect") ?.match (/copy|move/))
3206
3238
  {
3207
- if (sourceNode .getType () .some (type => this .transformLikeNodes .has (type)))
3239
+ if (sourceNode ?.getType () .some (type => this .transformLikeNodes .has (type)))
3208
3240
  {
3209
3241
  const
3210
3242
  sourceModelMatrix = this .getModelMatrix (sourceElement),
@@ -3291,7 +3323,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3291
3323
  }
3292
3324
  else
3293
3325
  {
3294
- if (node .getDisplayName ())
3326
+ if (node ?.getDisplayName ())
3295
3327
  {
3296
3328
  switch (dropEffect)
3297
3329
  {
@@ -274,7 +274,7 @@ module .exports = class OutlineView extends Interface
274
274
  .attr ("draggable", "true")
275
275
  .on ("dragstart", this .onDragStartProto .bind (this));
276
276
 
277
- child .find (".node:not([node-id=NULL]) > .item")
277
+ child .find (".node > .item")
278
278
  .attr ("draggable", "true")
279
279
  .on ("dragstart", this .onDragStartNode .bind (this));
280
280
  }
@@ -3314,10 +3314,8 @@ module .exports = class OutlineView extends Interface
3314
3314
  elements = $(`.node[node-id=${node ?.getId ()}]`),
3315
3315
  changed = new Map (selection .nodes .map (node => [node, node .getTool ()]));
3316
3316
 
3317
- if (!node)
3318
- return; // NULL node
3319
-
3320
- changed .set (node .valueOf (), node .getTool ());
3317
+ if (node)
3318
+ changed .set (node .valueOf (), node .getTool ());
3321
3319
 
3322
3320
  selectedElements .removeClass ("primary");
3323
3321
 
@@ -80,7 +80,7 @@ module .exports = class Editor
80
80
  const
81
81
  externprotos = new Set (),
82
82
  protos = new Set (),
83
- nodes = new X3D .MFNode (... objects .filter (o => o .getType () .includes (X3D .X3DConstants .X3DNode)));
83
+ nodes = new X3D .MFNode (... objects .filter (o => o ?.getType () .includes (X3D .X3DConstants .X3DNode) ?? true));
84
84
 
85
85
  const
86
86
  browser = executionContext .getBrowser (),
@@ -298,7 +298,7 @@ module .exports = class Editor
298
298
  // Remove protos that already exists in context.
299
299
 
300
300
  const
301
- nodes = [... executionContext .rootNodes] .slice (rootNodes .length) .map (n => n .getValue ()),
301
+ nodes = [... executionContext .rootNodes] .slice (rootNodes .length) .map (n => n ?.getValue ()),
302
302
  newExternProtos = [... executionContext .externprotos] .slice (externprotos .size),
303
303
  newProtos = [... executionContext .protos] .slice (protos .size),
304
304
  updatedExternProtos = new Map (),
package/src/X3D.js CHANGED
@@ -1,17 +1,8 @@
1
1
  "use strict";
2
2
 
3
- const path = require ("path");
3
+ const X3D = require ("x_ite");
4
4
 
5
- const X3D = process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT"
6
- ? require ("../x_ite/x_ite.js")
7
- : require ("x_ite");
8
-
9
- X3D .TYPE_SCRIPT_PATH = process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT"
10
- ? path .resolve (__dirname, "../x_ite/x_ite.d.ts")
11
- : require .resolve ("x_ite/x_ite.d.ts");
12
-
13
- X3D .X3DUOM_PATH = process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT"
14
- ? path .resolve (__dirname, "../x_ite/X3DUOM.xml")
15
- : require .resolve ("x_ite/X3DUOM.xml");
5
+ X3D .TYPE_SCRIPT_PATH = require .resolve ("x_ite/x_ite.d.ts");
6
+ X3D .X3DUOM_PATH = require .resolve ("x_ite/X3DUOM.xml");
16
7
 
17
8
  module .exports = X3D;
@@ -2,7 +2,7 @@
2
2
  <!-- X3D Unified Object Model (X3DUOM) X3dUnifiedObjectModel-4.0.xml -->
3
3
  <!-- Online at https://www.web3d.org/specifications/X3dUnifiedObjectModel-4.0.xml -->
4
4
  <!-- This file contains a listing of all abstract and concrete nodes in version 4.0 of X3D -->
5
- <!-- Generated 2024-12-10-08:00 12:33:23.8336395-08:00 -->
5
+ <!-- Generated 2024-12-31-08:00 13:12:27.809051-08:00 -->
6
6
  <X3dUnifiedObjectModel xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
7
7
  version="4.0"
8
8
  xsd:noNamespaceSchemaLocation="X3dUnifiedObjectModel.xsd">
@@ -33510,6 +33510,7 @@
33510
33510
  <field name="name"
33511
33511
  type="SFString"
33512
33512
  accessType="inputOutput"
33513
+ use="required"
33513
33514
  baseType="xs:NMTOKEN"
33514
33515
  description="name of the prototype node being instanced."/>
33515
33516
  <field name="DEF"
@@ -38531,7 +38532,7 @@
38531
38532
  accessType="inputOutput"
38532
38533
  default="0 1 0"
38533
38534
  inheritedFrom="X3DTextureProjectorNode"
38534
- description="upVector describes the roll of the camera by saying which direction is up for the camera's orientation."/>
38535
+ description="upVector describes the roll of the camera by defining which direction is up for camera orientation."/>
38535
38536
  <field name="DEF"
38536
38537
  type="SFString"
38537
38538
  accessType="inputOutput"
@@ -38694,7 +38695,7 @@
38694
38695
  accessType="inputOutput"
38695
38696
  default="0 1 0"
38696
38697
  inheritedFrom="X3DTextureProjectorNode"
38697
- description="upVector describes the roll of the camera by saying which direction is up for the camera's orientation."/>
38698
+ description="upVector describes the roll of the camera by defining which direction is up for camera orientation."/>
38698
38699
  <field name="DEF"
38699
38700
  type="SFString"
38700
38701
  accessType="inputOutput"