sunrize 1.7.44 → 1.7.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/package.json +3 -3
  2. package/src/Application/Document.js +1 -9
  3. package/src/Components/Geometry2D/Arc2D.js +16 -0
  4. package/src/Components/Geometry2D/ArcClose2D.js +14 -0
  5. package/src/Components/Geometry2D/Circle2D.js +23 -0
  6. package/src/Components/Geometry2D/Disk2D.js +53 -0
  7. package/src/Components/Geometry2D/Polyline2D.js +16 -0
  8. package/src/Components/Geometry2D/Polypoint2D.js +20 -0
  9. package/src/Components/Geometry2D/Rectangle2D.js +27 -0
  10. package/src/Components/Geometry2D/TriangleSet2D.js +33 -0
  11. package/src/Components/Geometry3D/Box.js +27 -0
  12. package/src/Components/Geometry3D/Cone.js +79 -0
  13. package/src/Components/Geometry3D/Cylinder.js +81 -0
  14. package/src/Components/Geometry3D/ElevationGrid.js +23 -0
  15. package/src/Components/Geometry3D/Extrusion.js +194 -0
  16. package/src/Components/Geometry3D/IndexedFaceSet.js +112 -0
  17. package/src/Components/Geometry3D/Sphere.js +27 -0
  18. package/src/Components/NURBS/NurbsCurve.js +17 -0
  19. package/src/Components/NURBS/NurbsSweptSurface.js +24 -0
  20. package/src/Components/NURBS/NurbsSwungSurface.js +24 -0
  21. package/src/Components/NURBS/X3DNurbsSurfaceGeometryNode.js +19 -0
  22. package/src/Components/Rendering/IndexedLineSet.js +24 -0
  23. package/src/Components/Rendering/LineSet.js +34 -0
  24. package/src/Components/Rendering/X3DComposedGeometryNode.js +44 -0
  25. package/src/Components/Rendering/X3DGeometryNode.js +183 -0
  26. package/src/Components/Text/Text.js +17 -0
  27. package/src/Components.js +33 -0
  28. package/src/Editors/OutlineEditor.js +114 -21
  29. package/src/Editors/OutlineView.js +3 -3
  30. package/src/Tools/Geometry2D/Disk2DTool.js +16 -18
  31. package/src/Undo/Editor.js +198 -144
@@ -248,7 +248,11 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
248
248
  args: ["addUserDefinedField", element .attr ("id"), executionContext .getId (), node .getId ()],
249
249
  },
250
250
  { type: "separator" },
251
- {
251
+ ];
252
+
253
+ if (node .getType () .includes (X3D .X3DConstants .X3DChildNode))
254
+ {
255
+ menu .push ({
252
256
  label: _("Add Parent Group"),
253
257
  submenu: [
254
258
  {
@@ -358,8 +362,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
358
362
  enabled: parentNodeElement .hasClass ("node"),
359
363
  args: ["removeParent", element .attr ("id"), executionContext .getId (), node .getId ()],
360
364
  },
361
- { type: "separator" },
362
- ];
365
+ { type: "separator" });
366
+ }
363
367
 
364
368
  for (const type of node .getType () .toReversed ())
365
369
  {
@@ -386,6 +390,19 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
386
390
 
387
391
  continue;
388
392
  }
393
+ case X3D .X3DConstants .X3DGeometryNode:
394
+ {
395
+ if (!node .toPrimitive)
396
+ continue;
397
+
398
+ menu .push (
399
+ {
400
+ label: _("Convert Node to Next Lower Geometry Type"),
401
+ args: ["toPrimitive", element .attr ("id"), executionContext .getId (), node .getId ()],
402
+ });
403
+
404
+ continue;
405
+ }
389
406
  case X3D .X3DConstants .ImageTexture:
390
407
  {
391
408
  if (node .checkLoadState () === X3D .X3DConstants .COMPLETE_STATE)
@@ -432,6 +449,11 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
432
449
  }
433
450
  case X3D .X3DConstants .X3DPrototypeInstance:
434
451
  {
452
+ menu .push ({
453
+ label: _("Unwrap Inner Node"),
454
+ args: ["unwrapInnerNode", element .attr ("id"), executionContext .getId (), node .getId ()],
455
+ });
456
+
435
457
  if (!$.try (() => node .getInnerNode () .getType () .includes (X3D .X3DConstants .X3DChildNode)))
436
458
  continue;
437
459
 
@@ -1051,6 +1073,9 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1051
1073
  }
1052
1074
 
1053
1075
  UndoManager .shared .endUndo ();
1076
+
1077
+ if (element .hasClass ("selected"))
1078
+ require ("../Application/Selection") .add (primitive);
1054
1079
  }
1055
1080
 
1056
1081
  async addParentGroup (id, executionContextId, nodeId, component, typeName, fieldName)
@@ -1682,39 +1707,29 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1682
1707
  case X3D .X3DConstants .IndexedFaceSet:
1683
1708
  {
1684
1709
  const
1685
- polygons = node .triangulate (),
1686
1710
  coordIndex = node ._coordIndex,
1687
1711
  normalPerVertex = node ._normalPerVertex .getValue (),
1712
+ polygons = node .triangulate (),
1688
1713
  normals = node .createNormals (polygons),
1689
- normalIndex = new X3D .MFInt32 (),
1690
1714
  normalNode = executionContext .createNode ("Normal") .getValue (),
1691
1715
  vector = normalNode ._vector;
1692
1716
 
1693
1717
  if (normalPerVertex)
1694
1718
  {
1695
- for (let i = 0, length = coordIndex .length; i < length; ++ i)
1719
+ for (const [i, index] of coordIndex .entries ())
1696
1720
  {
1697
- const index = coordIndex [i];
1698
-
1699
1721
  if (index < 0)
1700
- {
1701
- normalIndex .push (-1);
1702
- }
1703
- else
1704
- {
1705
- normalIndex .push (vector .length);
1706
- vector .push (normals [i]);
1707
- }
1722
+ continue;
1723
+
1724
+ vector [index] = normals [i];
1708
1725
  }
1709
1726
  }
1710
1727
  else
1711
1728
  {
1712
1729
  let face = 0;
1713
1730
 
1714
- for (let i = 0, length = coordIndex .length; i < length; ++ i)
1731
+ for (const [i, index] of coordIndex .entries ())
1715
1732
  {
1716
- const index = coordIndex [i];
1717
-
1718
1733
  if (index < 0)
1719
1734
  {
1720
1735
  vector .length = ++ face;
@@ -1726,8 +1741,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1726
1741
  }
1727
1742
  }
1728
1743
 
1729
- Editor .setFieldValue (executionContext, node, node ._normalIndex, normalIndex);
1730
- Editor .setFieldValue (executionContext, node, node ._normal, normalNode);
1744
+ Editor .setFieldValue (executionContext, node, node ._normal, normalNode);
1731
1745
  break;
1732
1746
  }
1733
1747
  case X3D .X3DConstants .X3DComposedGeometryNode:
@@ -1809,6 +1823,85 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1809
1823
  UndoManager .shared .endUndo ();
1810
1824
  }
1811
1825
 
1826
+ toPrimitive (id, executionContextId, nodeId)
1827
+ {
1828
+ const
1829
+ element = $(`#${id}`),
1830
+ executionContext = this .objects .get (executionContextId),
1831
+ parentFieldElement = element .closest (".field, .scene", this .sceneGraph),
1832
+ parentNodeElement = parentFieldElement .closest (".node, .proto, .scene", this .sceneGraph),
1833
+ parentNode = this .getNode (parentNodeElement),
1834
+ parentField = parentFieldElement .hasClass ("scene") ? parentNode .rootNodes : this .getField (parentFieldElement),
1835
+ node = this .objects .get (nodeId),
1836
+ primitive = node .toPrimitive (executionContext),
1837
+ index = parseInt (element .attr ("index"));
1838
+
1839
+ UndoManager .shared .beginUndo (_("Convert Node to Next Lower Primitive"));
1840
+
1841
+ if (node .getName ())
1842
+ Editor .updateNamedNode (executionContext, executionContext .getUniqueName (node .getName ()), primitive);
1843
+
1844
+ switch (parentField .getType ())
1845
+ {
1846
+ case X3D .X3DConstants .SFNode:
1847
+ {
1848
+ Editor .setFieldValue (executionContext, parentNode, parentField, primitive);
1849
+ break;
1850
+ }
1851
+ case X3D .X3DConstants .MFNode:
1852
+ {
1853
+ Editor .removeValueFromArray (executionContext, parentNode, parentField, index);
1854
+ Editor .insertValueIntoArray (executionContext, parentNode, parentField, index, primitive);
1855
+ break;
1856
+ }
1857
+ }
1858
+
1859
+ UndoManager .shared .endUndo ();
1860
+
1861
+ if (element .hasClass ("selected"))
1862
+ require ("../Application/Selection") .add (primitive);
1863
+ }
1864
+
1865
+ async unwrapInnerNode (id, executionContextId, nodeId)
1866
+ {
1867
+ const
1868
+ element = $(`#${id}`),
1869
+ executionContext = this .objects .get (executionContextId),
1870
+ parentFieldElement = element .closest (".field, .scene", this .sceneGraph),
1871
+ parentNodeElement = parentFieldElement .closest (".node, .proto, .scene", this .sceneGraph),
1872
+ parentNode = this .getNode (parentNodeElement),
1873
+ parentField = parentFieldElement .hasClass ("scene") ? parentNode .rootNodes : this .getField (parentFieldElement),
1874
+ node = this .objects .get (nodeId),
1875
+ x3dSyntax = await Editor .exportX3D (this .executionContext, [node]),
1876
+ importedNodes = await Editor .importX3D (this .executionContext, x3dSyntax),
1877
+ innerNode = importedNodes [0],
1878
+ index = parseInt (element .attr ("index"));
1879
+
1880
+ this .executionContext .rootNodes .length -= importedNodes .length;
1881
+
1882
+ UndoManager .shared .beginUndo (_("Convert Node to Next Lower Primitive"));
1883
+
1884
+ switch (parentField .getType ())
1885
+ {
1886
+ case X3D .X3DConstants .SFNode:
1887
+ {
1888
+ Editor .setFieldValue (executionContext, parentNode, parentField, innerNode);
1889
+ break;
1890
+ }
1891
+ case X3D .X3DConstants .MFNode:
1892
+ {
1893
+ Editor .removeValueFromArray (executionContext, parentNode, parentField, index);
1894
+ Editor .insertValueIntoArray (executionContext, parentNode, parentField, index, innerNode);
1895
+ break;
1896
+ }
1897
+ }
1898
+
1899
+ UndoManager .shared .endUndo ();
1900
+
1901
+ if (element .hasClass ("selected"))
1902
+ require ("../Application/Selection") .add (innerNode);
1903
+ }
1904
+
1812
1905
  addPrototype (id, executionContextId)
1813
1906
  {
1814
1907
  require ("../Controls/AddPrototypePopover");
@@ -2926,7 +2926,7 @@ module .exports = class OutlineView extends Interface
2926
2926
  }
2927
2927
  });
2928
2928
 
2929
- element .find (".node:not([node-id=NULL])") .each ((i, e) =>
2929
+ element .find (".node:not([node-id=NULL]), .imported-node, .exported-node") .each ((i, e) =>
2930
2930
  {
2931
2931
  const
2932
2932
  child = $(e),
@@ -2975,7 +2975,7 @@ module .exports = class OutlineView extends Interface
2975
2975
  {
2976
2976
  const
2977
2977
  child = $(e),
2978
- node = this .getNode (child);
2978
+ node = this .getNode (child);
2979
2979
 
2980
2980
  node .typeName_changed .removeFieldCallback (this .#exportedNodeSymbol);
2981
2981
  node .name_changed .removeFieldCallback (this .#exportedNodeSymbol);
@@ -2985,7 +2985,7 @@ module .exports = class OutlineView extends Interface
2985
2985
  {
2986
2986
  const
2987
2987
  child = $(e),
2988
- field = this .getField (child);
2988
+ field = this .getField (child);
2989
2989
 
2990
2990
  field .removeReferencesCallback (this .#fieldSymbol);
2991
2991
  field .removeRouteCallback (this .#fieldSymbol);
@@ -19,58 +19,56 @@ class Disk2DTool extends X3DGeometryNodeTool
19
19
 
20
20
  const toolChildren = new X3D .MFNode ();
21
21
 
22
- // Transform Tool innerRadius
22
+ // Transform Tool outerRadius
23
23
  {
24
24
  const
25
25
  groupNode = this .getToolScene () .createNode ("Group"),
26
26
  transformNode = this .getToolScene () .createNode ("Transform"),
27
27
  transformTool = await transformNode .getValue () .addTool () .getToolInstance ();
28
28
 
29
- this .#innerRadiusTransformNode = transformNode;
29
+ this .#outerRadiusTransformNode = transformNode;
30
30
 
31
- transformNode .scale .addInterest ("set_innerRadiusScale", this);
31
+ transformNode .scale .addInterest ("set_outerRadiusScale", this);
32
32
  transformTool .getField ("isActive") .addInterest ("handleUndo", this);
33
- transformTool .getField ("isActive") .addInterest ("set_innerRadiusActive", this);
33
+ transformTool .getField ("isActive") .addInterest ("set_outerRadiusActive", this);
34
34
 
35
35
  groupNode .bboxSize = new X3D .Vector3 (2, 2, 0);
36
36
  transformNode .children = [groupNode];
37
- transformTool .group = `${this .getTypeName ()}.innerRadius`;
37
+ transformTool .group = `${this .getTypeName ()}.outerRadius`;
38
38
  transformTool .undo = false;
39
39
  transformTool .tools = ["SCALE"];
40
40
  transformTool .keys = [ ];
41
41
  transformTool .connectedAxes = ["XY", "YX", "ZX"];
42
42
  transformTool .centerDisplay = false;
43
43
  transformTool .centerTool = false;
44
- transformTool .xAxisDisplay = false;
45
- transformTool .yAxisDisplay = false;
46
44
  transformTool .zAxisDisplay = false;
47
45
  transformTool .bboxColor = ToolColors .BLUE;
48
46
 
49
47
  toolChildren .push (transformNode);
50
48
 
51
- // Connections innerRadius
49
+ // Connections outerRadius
52
50
 
53
- this .node ._innerRadius .addInterest ("set_innerRadius", this);
51
+ this .node ._outerRadius .addInterest ("set_outerRadius", this);
54
52
 
55
- this .set_innerRadius (this .node ._innerRadius);
53
+ this .set_outerRadius (this .node ._outerRadius);
56
54
  }
57
55
 
58
- // Transform Tool outerRadius
56
+ // Transform Tool innerRadius
59
57
  {
60
58
  const
61
59
  groupNode = this .getToolScene () .createNode ("Group"),
62
60
  transformNode = this .getToolScene () .createNode ("Transform"),
63
61
  transformTool = await transformNode .getValue () .addTool () .getToolInstance ();
64
62
 
65
- this .#outerRadiusTransformNode = transformNode;
63
+ this .#innerRadiusTransformNode = transformNode;
66
64
 
67
- transformNode .scale .addInterest ("set_outerRadiusScale", this);
65
+ transformNode .scale .addInterest ("set_innerRadiusScale", this);
68
66
  transformTool .getField ("isActive") .addInterest ("handleUndo", this);
69
- transformTool .getField ("isActive") .addInterest ("set_outerRadiusActive", this);
67
+ transformTool .getField ("isActive") .addInterest ("set_innerRadiusActive", this);
70
68
 
71
69
  groupNode .bboxSize = new X3D .Vector3 (2, 2, 0);
72
70
  transformNode .children = [groupNode];
73
- transformTool .group = `${this .getTypeName ()}.outerRadius`;
71
+ transformTool .group = `${this .getTypeName ()}.innerRadius`;
74
72
  transformTool .undo = false;
75
73
  transformTool .tools = ["SCALE"];
76
74
  transformTool .keys = [ ];
@@ -82,11 +80,11 @@ class Disk2DTool extends X3DGeometryNodeTool
82
80
 
83
81
  toolChildren .push (transformNode);
84
82
 
85
- // Connections outerRadius
83
+ // Connections innerRadius
86
84
 
87
- this .node ._outerRadius .addInterest ("set_outerRadius", this);
85
+ this .node ._innerRadius .addInterest ("set_innerRadius", this);
88
86
 
89
- this .set_outerRadius (this .node ._outerRadius);
87
+ this .set_innerRadius (this .node ._innerRadius);
90
88
  }
91
89
 
92
90
  this .tool .undo = true;
@@ -607,150 +607,6 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
607
607
  return executionContext === parentContext
608
608
  }
609
609
 
610
- static nodesToRemove = new Map ()
611
-
612
- /**
613
- *
614
- * @param {X3DExecutionContext} executionContext
615
- * @param {Array<X3DNode|SFNode>|MFNode} nodes
616
- * @param {UndoManager} undoManager
617
- */
618
- static removeNodesFromExecutionContextIfNecessary (executionContext, nodes, undoManager = UndoManager .shared)
619
- {
620
- if (!nodes .length)
621
- return;
622
-
623
- if (!this .nodesToRemove .has (executionContext))
624
- this .nodesToRemove .set (executionContext, [ ]);
625
-
626
- const nodesToRemove = this .nodesToRemove .get (executionContext);
627
-
628
- for (const node of nodes)
629
- nodesToRemove .push (node);
630
-
631
- if (undoManager .defer ("removeNodesFromExecutionContextIfNecessary"))
632
- return;
633
-
634
- undoManager .defer ("removeNodesFromExecutionContextIfNecessary", () =>
635
- {
636
- for (const [executionContext, nodesToRemove] of this .nodesToRemove)
637
- {
638
- // Add nodes and child nodes.
639
-
640
- const children = new Set ();
641
-
642
- Array .from (Traverse .traverse (nodesToRemove, Traverse .ROOT_NODES | Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY))
643
- .filter (object => object instanceof X3D .SFNode)
644
- .forEach (node => children .add (node .getValue () .valueOf ()));
645
-
646
- // Remove nodes still in scene graph.
647
-
648
- Array .from (Traverse .traverse (executionContext, Traverse .ROOT_NODES | Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY))
649
- .filter (object => object instanceof X3D .SFNode)
650
- .forEach (node => children .delete (node .getValue () .valueOf ()));
651
-
652
- if (children .size === 0)
653
- continue;
654
-
655
- undoManager .beginUndo (_("Remove %s Nodes from Execution Context"), children .size);
656
-
657
- for (const node of children)
658
- {
659
- // Rebind X3DBindableNode nodes.
660
-
661
- if (node .getType () .includes (X3D .X3DConstants .X3DBindableNode))
662
- {
663
- if (node ._isBound .getValue ())
664
- {
665
- undoManager .registerUndo (() =>
666
- {
667
- this .setFieldValue (executionContext, node, node ._set_bind, true, undoManager);
668
- });
669
- }
670
- }
671
-
672
- // Remove named nodes.
673
-
674
- if (node .getName ())
675
- this .removeNamedNode (executionContext, node, undoManager);
676
-
677
- // Remove routes.
678
-
679
- this .deleteRoutes (executionContext, node, undoManager);
680
-
681
- // Remove imported nodes if node is an Inline node.
682
-
683
- for (const importedNode of Array .from (executionContext .getImportedNodes ()))
684
- {
685
- if (importedNode .getInlineNode () .valueOf () === node)
686
- this .removeImportedNode (executionContext, importedNode .getImportedName (), undoManager);
687
- }
688
-
689
- // Remove exported nodes.
690
-
691
- if (executionContext instanceof X3D .X3DScene)
692
- {
693
- for (const exportedNode of Array .from (executionContext .getExportedNodes ()))
694
- {
695
- if (exportedNode .getLocalNode () .valueOf () === node)
696
- this .removeExportedNode (executionContext, exportedNode .getExportedName (), undoManager);
697
- }
698
- }
699
-
700
- // Clear fields, to get right clone count.
701
-
702
- for (const field of node .getFields ())
703
- {
704
- switch (field .getType ())
705
- {
706
- case X3D .X3DConstants .SFNode:
707
- {
708
- this .setFieldValue (executionContext, node, field, null, undoManager);
709
- break;
710
- }
711
- case X3D .X3DConstants .MFNode:
712
- {
713
- this .setFieldValue (executionContext, node, field, new X3D .MFNode (), undoManager);
714
- break;
715
- }
716
- }
717
- }
718
-
719
- this .#setLive (node, false, undoManager);
720
- }
721
-
722
- this .requestUpdateInstances (executionContext, undoManager);
723
-
724
- undoManager .endUndo ();
725
- }
726
-
727
- this .nodesToRemove .clear ();
728
- });
729
- }
730
-
731
- /**
732
- *
733
- * @param {X3DBaseNode} node
734
- * @param {boolean} value
735
- */
736
- static #setLive (node, value, undoManager = UndoManager .shared)
737
- {
738
- node = node .valueOf ();
739
-
740
- const oldValue = node .isLive ();
741
-
742
- undoManager .beginUndo (_("Set live state to »%s«"), value);
743
-
744
- node .setLive (value);
745
-
746
- undoManager .registerUndo (() =>
747
- {
748
- this .#setLive (node, oldValue, undoManager);
749
- });
750
-
751
- undoManager .endUndo ();
752
- }
753
-
754
610
  /**
755
611
  *
756
612
  * @param {X3DScene} scene
@@ -3542,6 +3398,204 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
3542
3398
  });
3543
3399
  }
3544
3400
 
3401
+ static #nodesToRemove = new Map ();
3402
+
3403
+ /**
3404
+ *
3405
+ * @param {X3DExecutionContext} executionContext
3406
+ * @param {Array<X3DNode|SFNode>|MFNode} nodes
3407
+ * @param {UndoManager} undoManager
3408
+ */
3409
+ static removeNodesFromExecutionContextIfNecessary (executionContext, nodes, undoManager = UndoManager .shared)
3410
+ {
3411
+ if (!nodes .length)
3412
+ return;
3413
+
3414
+ if (!this .#nodesToRemove .has (executionContext))
3415
+ this .#nodesToRemove .set (executionContext, [ ]);
3416
+
3417
+ const nodesToRemove = this .#nodesToRemove .get (executionContext);
3418
+
3419
+ for (const node of nodes)
3420
+ nodesToRemove .push (node .valueOf ());
3421
+
3422
+ if (undoManager .defer ("removeNodesFromExecutionContextIfNecessary"))
3423
+ return;
3424
+
3425
+ undoManager .defer ("removeNodesFromExecutionContextIfNecessary", () =>
3426
+ {
3427
+ for (const [executionContext, nodesToRemove] of this .#nodesToRemove)
3428
+ {
3429
+ // Add nodes and child nodes.
3430
+
3431
+ const children = new Set ();
3432
+
3433
+ Array .from (Traverse .traverse (nodesToRemove, Traverse .ROOT_NODES | Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY))
3434
+ .filter (object => object instanceof X3D .SFNode)
3435
+ .forEach (node => children .add (node .getValue () .valueOf ()));
3436
+
3437
+ // Remove nodes still in scene graph.
3438
+
3439
+ Array .from (Traverse .traverse (executionContext, Traverse .ROOT_NODES | Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY))
3440
+ .filter (object => object instanceof X3D .SFNode)
3441
+ .forEach (node => children .delete (node .getValue () .valueOf ()));
3442
+
3443
+ if (children .size === 0)
3444
+ continue;
3445
+
3446
+ undoManager .beginUndo (_("Remove %s Nodes from Execution Context"), children .size);
3447
+
3448
+ for (const node of children)
3449
+ {
3450
+ // Rebind X3DBindableNode nodes.
3451
+
3452
+ if (node .getType () .includes (X3D .X3DConstants .X3DBindableNode))
3453
+ {
3454
+ if (node ._isBound .getValue ())
3455
+ {
3456
+ undoManager .registerUndo (() =>
3457
+ {
3458
+ this .setFieldValue (executionContext, node, node ._set_bind, true, undoManager);
3459
+ });
3460
+ }
3461
+ }
3462
+
3463
+ // Remove named nodes.
3464
+
3465
+ if (node .getName ())
3466
+ this .removeNamedNode (executionContext, node, undoManager);
3467
+
3468
+ // Remove routes.
3469
+
3470
+ this .deleteRoutes (executionContext, node, undoManager);
3471
+
3472
+ // Remove imported nodes if node is an Inline node.
3473
+
3474
+ for (const importedNode of Array .from (executionContext .getImportedNodes ()))
3475
+ {
3476
+ if (importedNode .getInlineNode () .valueOf () === node)
3477
+ this .removeImportedNode (executionContext, importedNode .getImportedName (), undoManager);
3478
+ }
3479
+
3480
+ // Remove exported nodes.
3481
+
3482
+ if (executionContext instanceof X3D .X3DScene)
3483
+ {
3484
+ for (const exportedNode of Array .from (executionContext .getExportedNodes ()))
3485
+ {
3486
+ if (exportedNode .getLocalNode () .valueOf () === node)
3487
+ this .removeExportedNode (executionContext, exportedNode .getExportedName (), undoManager);
3488
+ }
3489
+ }
3490
+
3491
+ // Clear fields, to get right clone count.
3492
+
3493
+ for (const field of node .getFields ())
3494
+ {
3495
+ switch (field .getType ())
3496
+ {
3497
+ case X3D .X3DConstants .SFNode:
3498
+ {
3499
+ this .setFieldValue (executionContext, node, field, null, undoManager);
3500
+ break;
3501
+ }
3502
+ case X3D .X3DConstants .MFNode:
3503
+ {
3504
+ this .setFieldValue (executionContext, node, field, new X3D .MFNode (), undoManager);
3505
+ break;
3506
+ }
3507
+ }
3508
+ }
3509
+
3510
+ this .#setLive (node, false, undoManager);
3511
+ this .#removeSelection (node, undoManager);
3512
+ }
3513
+
3514
+ this .requestUpdateInstances (executionContext, undoManager);
3515
+
3516
+ undoManager .endUndo ();
3517
+ }
3518
+
3519
+ this .#nodesToRemove .clear ();
3520
+ });
3521
+ }
3522
+
3523
+ /**
3524
+ *
3525
+ * @param {X3DBaseNode} node
3526
+ * @param {boolean} value
3527
+ * @param {UndoManager} undoManager
3528
+ */
3529
+ static #setLive (node, value, undoManager = UndoManager .shared)
3530
+ {
3531
+ node = node .valueOf ();
3532
+
3533
+ const oldValue = node .isLive ();
3534
+
3535
+ undoManager .beginUndo (_("Set live state to »%s«"), value);
3536
+
3537
+ node .setLive (value);
3538
+
3539
+ undoManager .registerUndo (() =>
3540
+ {
3541
+ this .#setLive (node, oldValue, undoManager);
3542
+ });
3543
+
3544
+ undoManager .endUndo ();
3545
+ }
3546
+
3547
+ /**
3548
+ *
3549
+ * @param {X3DBaseNode} node
3550
+ * @param {UndoManager} undoManager
3551
+ */
3552
+ static #addSelection (node, undoManager = UndoManager .shared)
3553
+ {
3554
+ node = node .valueOf ();
3555
+
3556
+ const selection = require ("../Application/Selection");
3557
+
3558
+ if (selection .has (node))
3559
+ return;
3560
+
3561
+ undoManager .beginUndo (_("Select node"));
3562
+
3563
+ selection .add (node);
3564
+
3565
+ undoManager .registerUndo (() =>
3566
+ {
3567
+ this .#removeSelection (node, undoManager);
3568
+ });
3569
+
3570
+ undoManager .endUndo ();
3571
+ }
3572
+
3573
+ /**
3574
+ *
3575
+ * @param {X3DBaseNode} node
3576
+ * @param {UndoManager} undoManager
3577
+ */
3578
+ static #removeSelection (node, undoManager = UndoManager .shared)
3579
+ {
3580
+ node = node .valueOf ();
3581
+
3582
+ const selection = require ("../Application/Selection");
3583
+
3584
+ if (!selection .has (node))
3585
+ return;
3586
+
3587
+ undoManager .beginUndo (_("Deselect node"));
3588
+
3589
+ selection .remove (node);
3590
+
3591
+ undoManager .registerUndo (() =>
3592
+ {
3593
+ this .#addSelection (node, undoManager);
3594
+ });
3595
+
3596
+ undoManager .endUndo ();
3597
+ }
3598
+
3545
3599
  /**
3546
3600
  *
3547
3601
  * @param {function} callback