sunrize 1.7.40 → 1.7.42

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.42",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -90,7 +90,7 @@
90
90
  "dependencies": {
91
91
  "capitalize": "^2.0.4",
92
92
  "console": "^0.7.2",
93
- "electron": "^33.2.1",
93
+ "electron": "^33.3.1",
94
94
  "electron-prompt": "^1.7.0",
95
95
  "electron-squirrel-startup": "^1.0.1",
96
96
  "electron-tabs": "^1.0.4",
@@ -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.4",
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
422
 
432
- continue;
433
- }
434
- case X3D .X3DConstants .X3DPrototypeInstance:
435
- {
436
- if (!$.try (() => node .getInnerNode () .getType () .includes (X3D .X3DConstants .X3DChildNode)))
437
- continue;
438
-
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
492
 
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
-
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
 
@@ -1917,9 +1942,9 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1917
1942
  }
1918
1943
  else
1919
1944
  {
1920
- node ._isEvenLive = true;
1921
-
1922
1945
  Editor .setFieldValue (this .browser .currentScene, node, node ._startTime, Date .now () / 1000);
1946
+
1947
+ node ._isEvenLive = true;
1923
1948
  }
1924
1949
  }
1925
1950
 
@@ -1947,6 +1972,9 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1947
1972
  event .stopImmediatePropagation ();
1948
1973
 
1949
1974
  Editor .setFieldValue (this .browser .currentScene, node, node ._loop, !node ._loop .getValue ());
1975
+
1976
+ if (node ._loop .getValue () && node ._startTime .getValue () >= node ._stopTime .getValue ())
1977
+ node ._isEvenLive = true;
1950
1978
  }
1951
1979
 
1952
1980
  addBooleanField (button)
@@ -3067,9 +3095,16 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3067
3095
  {
3068
3096
  const
3069
3097
  sourceElement = $("#" + sourceElementsIds [0]),
3070
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement);
3098
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement);
3071
3099
 
3072
- UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), sourceNode .getTypeName (), sourceNode .getDisplayName ());
3100
+ if (sourceNode)
3101
+ {
3102
+ UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), sourceNode .getTypeName (), sourceNode .getDisplayName ());
3103
+ }
3104
+ else
3105
+ {
3106
+ UndoManager .shared .beginUndo (this .getUndoDescriptionForNode (destinationElement .data ("dropEffect"), sourceNode), "NULL");
3107
+ }
3073
3108
  }
3074
3109
  else
3075
3110
  {
@@ -3084,7 +3119,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3084
3119
  {
3085
3120
  const
3086
3121
  sourceElement = $("#" + sourceElementId),
3087
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement),
3122
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement),
3088
3123
  sourceExecutionContextElement = sourceElement .closest (".scene", this .sceneGraph),
3089
3124
  sourceExecutionContext = this .getNode (sourceExecutionContextElement);
3090
3125
 
@@ -3117,7 +3152,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3117
3152
  sourceExecutionContext = this .getNode (sourceExecutionContextElement);
3118
3153
 
3119
3154
  let
3120
- sourceNode = this .getNode (sourceElement) .getTool () ?? this .getNode (sourceElement),
3155
+ sourceNode = this .getNode (sourceElement) ?.getTool () ?? this .getNode (sourceElement),
3121
3156
  sourceIndex = parseInt (sourceElement .attr ("index"));
3122
3157
 
3123
3158
  if (destinationElement .attr ("node-id") !== "NULL")
@@ -3128,7 +3163,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3128
3163
  continue;
3129
3164
 
3130
3165
  const containerField = $.try (() => sourceNode .getInnerNode () .getContainerField ())
3131
- ?? sourceNode .getContainerField ();
3166
+ ?? sourceNode ?.getContainerField ();
3132
3167
 
3133
3168
  if (containerField)
3134
3169
  destinationParentField = $.try (() => destinationParentNode .getField (containerField));
@@ -3204,7 +3239,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3204
3239
 
3205
3240
  if (destinationElement .data ("dropEffect") ?.match (/copy|move/))
3206
3241
  {
3207
- if (sourceNode .getType () .some (type => this .transformLikeNodes .has (type)))
3242
+ if (sourceNode ?.getType () .some (type => this .transformLikeNodes .has (type)))
3208
3243
  {
3209
3244
  const
3210
3245
  sourceModelMatrix = this .getModelMatrix (sourceElement),
@@ -3291,7 +3326,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3291
3326
  }
3292
3327
  else
3293
3328
  {
3294
- if (node .getDisplayName ())
3329
+ if (node ?.getDisplayName ())
3295
3330
  {
3296
3331
  switch (dropEffect)
3297
3332
  {
@@ -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"