sunrize 1.7.63 → 1.8.1

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 (43) hide show
  1. package/package.json +4 -4
  2. package/src/Application/ActionKeys.js +3 -3
  3. package/src/Application/Application.js +5 -1
  4. package/src/Application/Dashboard.js +87 -6
  5. package/src/Application/Document.js +167 -24
  6. package/src/Application/Hierarchy.js +268 -0
  7. package/src/Application/Selection.js +6 -6
  8. package/src/Application/Tabs.js +1 -0
  9. package/src/Components/Grouping/StaticGroup.js +1 -1
  10. package/src/Components/Grouping/Switch.js +34 -0
  11. package/src/Components/Navigation/Collision.js +70 -0
  12. package/src/Components/Navigation/LOD.js +34 -0
  13. package/src/Editors/Library.js +1 -1
  14. package/src/Editors/OutlineEditor.js +6 -2
  15. package/src/Editors/OutlineRouteGraph.js +4 -4
  16. package/src/Editors/OutlineView.js +210 -63
  17. package/src/Tools/Core/X3DNodeTool.js +2 -0
  18. package/src/Tools/EnvironmentalSensor/X3DEnvironmentalSensorNodeTool.x3d +1 -0
  19. package/src/Tools/Geometry2D/Arc2DTool.js +1 -0
  20. package/src/Tools/Geometry2D/ArcClose2DTool.js +1 -0
  21. package/src/Tools/Geometry2D/Circle2DTool.js +1 -0
  22. package/src/Tools/Geometry2D/Disk2DTool.js +2 -0
  23. package/src/Tools/Geometry2D/Rectangle2DTool.js +1 -0
  24. package/src/Tools/Geometry3D/BoxTool.js +1 -0
  25. package/src/Tools/Geometry3D/ConeTool.js +1 -0
  26. package/src/Tools/Geometry3D/CylinderTool.js +1 -0
  27. package/src/Tools/Geometry3D/SphereTool.js +1 -0
  28. package/src/Tools/Grouping/X3DBoundedObjectTool.x3d +28 -12
  29. package/src/Tools/Grouping/X3DTransformNodeTool.x3d +30 -12
  30. package/src/Tools/Lighting/X3DLightNodeTool.x3d +1 -0
  31. package/src/Tools/Navigation/X3DViewpointNodeTool.x3d +1 -0
  32. package/src/Tools/SnapTool/SnapSource.js +4 -2
  33. package/src/Tools/SnapTool/SnapTool.x3d +1 -1
  34. package/src/Tools/SnapTool/X3DSnapNodeTool.js +8 -6
  35. package/src/Tools/Sound/ListenerPointSourceTool.x3d +1 -0
  36. package/src/Tools/Sound/SoundTool.x3d +5 -0
  37. package/src/Tools/Sound/SpatialSoundTool.x3d +2 -1
  38. package/src/Tools/TextureProjection/X3DTextureProjectorNodeTool.x3d +1 -0
  39. package/src/Undo/Editor.js +1 -1
  40. package/src/Undo/UndoManager.js +4 -4
  41. package/src/X3D.js +1 -1
  42. package/src/assets/themes/default-template.css +6 -0
  43. package/src/assets/themes/default.css +6 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sunrize",
3
3
  "productName": "Sunrize X3D Editor",
4
- "version": "1.7.63",
4
+ "version": "1.8.1",
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": "^35.1.2",
93
+ "electron": "^35.1.4",
94
94
  "electron-prompt": "^1.7.0",
95
95
  "electron-squirrel-startup": "^1.0.1",
96
96
  "electron-tabs": "^1.0.4",
@@ -99,7 +99,7 @@
99
99
  "jquery-ui-dist": "^1.13.3",
100
100
  "jstree": "^3.3.17",
101
101
  "material-icons": "^1.13.14",
102
- "material-symbols": "^0.29.2",
102
+ "material-symbols": "^0.29.3",
103
103
  "md5": "^2.3.0",
104
104
  "mime-types": "^3.0.1",
105
105
  "monaco-editor": "^0.50.0",
@@ -109,7 +109,7 @@
109
109
  "string-similarity": "^4.0.4",
110
110
  "tweakpane": "^3.1.10",
111
111
  "update-electron-app": "^3.1.1",
112
- "x_ite": "^11.5.0",
112
+ "x_ite": "^11.5.2",
113
113
  "x3d-traverse": "^1.0.11"
114
114
  }
115
115
  }
@@ -58,7 +58,7 @@ module .exports = new class ActionKeys
58
58
  if (this .value === value)
59
59
  return;
60
60
 
61
- this .processInterests ();
61
+ this .#processInterests ();
62
62
  }
63
63
 
64
64
  onkeyup (event)
@@ -94,7 +94,7 @@ module .exports = new class ActionKeys
94
94
  if (this .value === value)
95
95
  return;
96
96
 
97
- this .processInterests ();
97
+ this .#processInterests ();
98
98
  }
99
99
 
100
100
  #interests = new Map ();
@@ -109,7 +109,7 @@ module .exports = new class ActionKeys
109
109
  this .#interests .delete (key);
110
110
  }
111
111
 
112
- processInterests ()
112
+ #processInterests ()
113
113
  {
114
114
  for (const callback of this .#interests .values ())
115
115
  callback (this .value);
@@ -288,7 +288,7 @@ module .exports = class Application
288
288
  },
289
289
  { type: "separator" },
290
290
  {
291
- label: _("Default Play Button State"),
291
+ label: _("Enable Browser Update on Load"),
292
292
  type: "checkbox",
293
293
  checked: this .config .browserUpdate,
294
294
  click: () =>
@@ -789,6 +789,10 @@ module .exports = class Application
789
789
  label: _("Center Snap Target in Selection"),
790
790
  click: () => this .mainWindow .webContents .send ("center-snap-target-in-selection"),
791
791
  },
792
+ {
793
+ label: _("Center Snap Source in Selection"),
794
+ click: () => this .mainWindow .webContents .send ("center-snap-source-in-selection"),
795
+ },
792
796
  {
793
797
  label: _("Move Selection to Snap Target"),
794
798
  accelerator: "CmdOrCtrl+M",
@@ -9,11 +9,12 @@ const
9
9
 
10
10
  module .exports = class Dashboard extends Interface
11
11
  {
12
- constructor (element)
12
+ constructor (element, document)
13
13
  {
14
14
  super ("Sunrize.Dashboard.");
15
15
 
16
- this .toolbar = element;
16
+ this .document = document;
17
+ this .toolbar = element;
17
18
 
18
19
  this .setup ();
19
20
  }
@@ -44,12 +45,41 @@ module .exports = class Dashboard extends Interface
44
45
 
45
46
  $("<span></span>") .addClass ("separator") .appendTo (this .toolbar);
46
47
 
47
- this .viewAllButton = $("<span></span>")
48
+ const hierarchy = require ("./Hierarchy");
49
+
50
+ this .upButton = $("<span></span>")
51
+ .addClass (["material-icons", "disabled"])
52
+ .attr ("title", _("Select parent node(s)."))
53
+ .css ({ transform: "rotate(-90deg) scaleX(0.8)", "margin-top": "-6px", "margin-bottom": "-7px" })
54
+ .text ("play_arrow")
55
+ .appendTo (this .toolbar)
56
+ .on ("click", () => this .selectParent ());
57
+
58
+ this .downButton = $("<span></span>")
59
+ .addClass (["material-icons", "disabled"])
60
+ .attr ("title", _("Select child node(s)."))
61
+ .css ({ transform: "rotate(90deg) scaleX(0.8)", "margin-top": "-7px", "margin-bottom": "-6px" })
62
+ .text ("play_arrow")
63
+ .appendTo (this .toolbar)
64
+ .on ("click", () => this .selectChild ());
65
+
66
+ hierarchy .addInterest (this, () => this .onHierarchy ());
67
+
68
+ $("<span></span>") .addClass ("separator") .appendTo (this .toolbar);
69
+
70
+ this .viewSelectedButton = $("<span></span>")
48
71
  .addClass (["material-symbols-outlined"])
49
72
  .attr ("title", _("Look at selected objects."))
50
73
  .text ("center_focus_strong")
51
74
  .appendTo (this .toolbar)
52
- .on ("click", () => this .viewAll ());
75
+ .on ("click", () => this .viewAll (true));
76
+
77
+ this .viewAllButton = $("<span></span>")
78
+ .addClass (["material-symbols-outlined"])
79
+ .attr ("title", _("Look at all objects in active layer."))
80
+ .text ("zoom_out_map")
81
+ .appendTo (this .toolbar)
82
+ .on ("click", () => this .viewAll (false));
53
83
 
54
84
  this .straightenButton = $("<span></span>")
55
85
  .addClass (["material-symbols-outlined", "active"])
@@ -130,13 +160,64 @@ module .exports = class Dashboard extends Interface
130
160
  this .playButton .removeClass ("active");
131
161
  }
132
162
 
133
- viewAll ()
163
+ selectParent ()
164
+ {
165
+ this .selectHierarchy ("up");
166
+ }
167
+
168
+ selectChild ()
169
+ {
170
+ this .selectHierarchy ("down");
171
+ }
172
+
173
+ selectHierarchy (direction)
174
+ {
175
+ const
176
+ hierarchy = require ("./Hierarchy"),
177
+ outlineEditor = this .document .sidebar .outlineEditor,
178
+ nodes = hierarchy [direction] ();
179
+
180
+ for (const node of nodes)
181
+ outlineEditor .expandTo (node, { expandObject: true, expandAll: true });
182
+
183
+ const elements = nodes .map (node => outlineEditor .sceneGraph .find (`.node[node-id=${node .getId ()}]`));
184
+
185
+ for (const [i, element] of elements .entries ())
186
+ outlineEditor .selectNodeElement (element, { add: i > 0 });
187
+
188
+ // Scroll element into view.
189
+ // Hide scrollbars during scroll to prevent overlay issue.
190
+
191
+ outlineEditor .treeView .css ("overflow", "hidden");
192
+
193
+ elements [0] ?.[0] ?.scrollIntoView ({ block: "center", inline: "start", behavior: "smooth" });
194
+ $(window) .scrollTop (0);
195
+
196
+ setTimeout (() => outlineEditor .treeView .css ("overflow", ""), 1000);
197
+ }
198
+
199
+ onHierarchy ()
200
+ {
201
+ const hierarchy = require ("./Hierarchy");
202
+
203
+ if (hierarchy .canUp ())
204
+ this .upButton .removeClass ("disabled");
205
+ else
206
+ this .upButton .addClass ("disabled");
207
+
208
+ if (hierarchy .canDown ())
209
+ this .downButton .removeClass ("disabled");
210
+ else
211
+ this .downButton .addClass ("disabled");
212
+ }
213
+
214
+ viewAll (selected)
134
215
  {
135
216
  const
136
217
  selection = require ("./Selection"),
137
218
  nodes = selection .nodes;
138
219
 
139
- if (nodes .length)
220
+ if (selected && nodes .length)
140
221
  {
141
222
  const
142
223
  executionContext = this .browser .currentScene,
@@ -28,9 +28,6 @@ module .exports = class Document extends Interface
28
28
  {
29
29
  super ("Sunrize.Document.");
30
30
 
31
- // Add X3D to window to provide access in Script nodes.
32
- window .X3D = X3D;
33
-
34
31
  // Globals
35
32
 
36
33
  this .config .global .setDefaultValues ({
@@ -41,7 +38,7 @@ module .exports = class Document extends Interface
41
38
 
42
39
  this .verticalSplitter = new Splitter ($("#vertical-splitter"), "vertical");
43
40
  this .horizontalSplitter = new Splitter ($("#horizontal-splitter"), "horizontal");
44
- this .secondaryToolbar = new Dashboard ($("#secondary-toolbar"));
41
+ this .secondaryToolbar = new Dashboard ($("#secondary-toolbar"), this);
45
42
  this .footer = new Footer ($("#footer"));
46
43
  this .sidebar = new Sidebar ($("#sidebar"));
47
44
 
@@ -120,6 +117,7 @@ module .exports = class Document extends Interface
120
117
  electron .ipcRenderer .on ("activate-snap-target", (event, visible) => this .activateSnapTarget (visible));
121
118
  electron .ipcRenderer .on ("activate-snap-source", (event, visible) => this .activateSnapSource (visible));
122
119
  electron .ipcRenderer .on ("center-snap-target-in-selection", () => this .centerSnapTargetInSelection ());
120
+ electron .ipcRenderer .on ("center-snap-source-in-selection", () => this .centerSnapSourceInSelection ());
123
121
  electron .ipcRenderer .on ("move-selection-to-snap-target", () => this .moveSelectionToSnapTarget ());
124
122
  electron .ipcRenderer .on ("move-selection-center-to-snap-target", () => this .moveSelectionCenterToSnapTarget ());
125
123
 
@@ -166,9 +164,10 @@ module .exports = class Document extends Interface
166
164
 
167
165
  // Connect for Snap Target and Snap Source.
168
166
 
169
- $(this .browser .element .shadowRoot) .find ("canvas")
167
+ $(this .browser .element)
170
168
  .on ("mousedown", event => this .onmousedown (event))
171
- .on ("mouseup", event => this .onmouseup (event));
169
+ .on ("mouseup", event => this .onsnaptool (event))
170
+ .on ("mouseup", event => this .onselect (event));
172
171
 
173
172
  // Load components.
174
173
 
@@ -178,6 +177,9 @@ module .exports = class Document extends Interface
178
177
  // Modify nodes.
179
178
 
180
179
  this .browser .updateConcreteNode (require ("../Components/Grouping/StaticGroup"));
180
+ this .browser .updateConcreteNode (require ("../Components/Grouping/Switch"));
181
+ this .browser .updateConcreteNode (require ("../Components/Navigation/Collision"));
182
+ this .browser .updateConcreteNode (require ("../Components/Navigation/LOD"));
181
183
 
182
184
  require ("../Components");
183
185
 
@@ -939,48 +941,79 @@ Viewpoint {
939
941
  }
940
942
  }
941
943
 
944
+ #select = false;
945
+ #pointer = new X3D .Vector2 ();
942
946
  #snapTarget = null;
943
947
  #snapSource = null;
944
948
 
945
949
  async onmousedown (event)
946
950
  {
947
- if (event .button !== 2)
951
+ this .#select = false;
952
+
953
+ if (!this .secondaryToolbar .arrowButton .hasClass ("active"))
948
954
  return;
949
955
 
950
- switch (ActionKeys .value)
956
+ switch (event .button)
951
957
  {
952
- case ActionKeys .None:
958
+ case 0:
953
959
  {
954
- if (this .#snapTarget ?._visible .getValue ())
955
- break;
960
+ if (event .shiftKey && (event .ctrlKey || event .metaKey))
961
+ return;
956
962
 
957
- this .activateSnapTarget (true);
963
+ this .#pointer .assign (this .browser .getPointerFromEvent (event));
958
964
 
959
- await this .#snapTarget .getToolInstance ();
965
+ if (this .browser .touch (... this .#pointer))
966
+ {
967
+ if (this .browser .getHit () .sensors .size)
968
+ return;
969
+
970
+ this .#select = true;
971
+ }
972
+ else
973
+ {
974
+ this .#select = true;
975
+ }
960
976
 
961
- this .#snapTarget .onmousedown (event, true);
962
977
  break;
963
978
  }
964
- case ActionKeys .Option:
979
+ case 2:
965
980
  {
966
- if (this .#snapSource ?._visible .getValue ())
967
- break;
981
+ switch (ActionKeys .value)
982
+ {
983
+ case ActionKeys .None:
984
+ {
985
+ if (this .#snapTarget ?._visible .getValue ())
986
+ break;
987
+
988
+ this .activateSnapTarget (true);
989
+
990
+ await this .#snapTarget .getToolInstance ();
991
+
992
+ this .#snapTarget .onmousedown (event, true);
993
+ break;
994
+ }
995
+ case ActionKeys .Option:
996
+ {
997
+ if (this .#snapSource ?._visible .getValue ())
998
+ break;
999
+
1000
+ this .activateSnapSource (true);
968
1001
 
969
- this .activateSnapSource (true);
1002
+ await this .#snapSource .getToolInstance ();
970
1003
 
971
- await this .#snapSource .getToolInstance ();
1004
+ this .#snapSource .onmousedown (event, true);
1005
+ break;
1006
+ }
1007
+ }
972
1008
 
973
- this .#snapSource .onmousedown (event, true);
974
1009
  break;
975
1010
  }
976
1011
  }
1012
+
977
1013
  }
978
1014
 
979
- async onmouseup (event)
1015
+ async onsnaptool (event)
980
1016
  {
981
- if (ActionKeys .value & ActionKeys .Control)
982
- event .button = 2;
983
-
984
1017
  if (event .button !== 2)
985
1018
  return;
986
1019
 
@@ -991,6 +1024,94 @@ Viewpoint {
991
1024
  this .#snapTarget ?.onmouseup (event);
992
1025
  }
993
1026
 
1027
+ onselect (event)
1028
+ {
1029
+ if (!this .secondaryToolbar .arrowButton .hasClass ("active"))
1030
+ return;
1031
+
1032
+ if (event .button !== 0)
1033
+ return;
1034
+
1035
+ if (!this .#select)
1036
+ return;
1037
+
1038
+ const pointer = this .browser .getPointerFromEvent (event);
1039
+
1040
+ if (this .#pointer .distance (pointer) > this .browser .getRenderingProperty ("ContentScale"))
1041
+ return;
1042
+
1043
+ // Stop event propagation.
1044
+
1045
+ event .preventDefault ();
1046
+
1047
+ // Select or deselect.
1048
+
1049
+ const outlineEditor = this .sidebar .outlineEditor;
1050
+
1051
+ if (!this .browser .touch (... pointer))
1052
+ {
1053
+ outlineEditor .deselectAll ();
1054
+ return;
1055
+ }
1056
+
1057
+ // Select.
1058
+
1059
+ const
1060
+ shapeNode = this .browser .getHit () .shapeNode,
1061
+ geometryTool = shapeNode .getGeometry () ?.getTool (),
1062
+ tool = geometryTool ?? shapeNode .getExecutionContext () .getOuterNode () ?.getTool (),
1063
+ node = tool ?? shapeNode;
1064
+
1065
+ outlineEditor .expandTo (node, { expandObject: true, expandAll: true });
1066
+
1067
+ let elements = outlineEditor .sceneGraph .find (`.node[node-id=${node .getId ()}]`);
1068
+
1069
+ if (!elements .length)
1070
+ return;
1071
+
1072
+ if (outlineEditor .isEditable (elements))
1073
+ {
1074
+ if (tool)
1075
+ {
1076
+ elements = Array .from (elements);
1077
+ }
1078
+ else
1079
+ {
1080
+ const parentElements = Array .from (elements) .flatMap (element =>
1081
+ {
1082
+ const parentElements = Array .from ($(element) .parent () .closest (".node", outlineEditor .sceneGraph));
1083
+
1084
+ return parentElements .length ? parentElements : element;
1085
+ });
1086
+
1087
+ elements = parentElements .map ((element, i) => outlineEditor .getNode ($(element)) .getType () .includes (X3D .X3DConstants .X3DGroupingNode) ? parentElements [i] : elements [i]);
1088
+ }
1089
+ }
1090
+ else
1091
+ {
1092
+ while (!outlineEditor .isEditable (elements))
1093
+ {
1094
+ elements .jstree ("close_node", elements);
1095
+ elements = elements .parent () .closest (".node, .scene", outlineEditor .sceneGraph);
1096
+ }
1097
+
1098
+ elements = Array .from (elements);
1099
+ }
1100
+
1101
+ for (const [i, element] of elements .entries ())
1102
+ outlineEditor .selectNodeElement ($(element), { add: (event .shiftKey || event .metaKey) || i > 0, target: true });
1103
+
1104
+ // Scroll element into view.
1105
+ // Hide scrollbars during scroll to prevent overlay issue.
1106
+
1107
+ outlineEditor .treeView .css ("overflow", "hidden");
1108
+
1109
+ elements [0] ?.scrollIntoView ({ block: "center", inline: "start", behavior: "smooth" });
1110
+ $(window) .scrollTop (0);
1111
+
1112
+ setTimeout (() => outlineEditor .treeView .css ("overflow", ""), 1000);
1113
+ }
1114
+
994
1115
  activateSnapTarget (visible)
995
1116
  {
996
1117
  const SnapTarget = require ("../Tools/SnapTool/SnapTarget");
@@ -1035,6 +1156,28 @@ Viewpoint {
1035
1156
  UndoManager .shared .endUndo ();
1036
1157
  }
1037
1158
 
1159
+ async centerSnapSourceInSelection ()
1160
+ {
1161
+ this .activateSnapSource (true);
1162
+
1163
+ const
1164
+ selection = require ("./Selection"),
1165
+ source = await this .#snapSource .getToolInstance (),
1166
+ executionContext = this .browser .currentScene,
1167
+ layerNode = this .browser .getActiveLayer (),
1168
+ nodes = selection .nodes,
1169
+ [values, bbox] = Editor .getModelMatricesAndBBoxes (executionContext, layerNode, nodes);
1170
+
1171
+ if (!bbox .size .magnitude ())
1172
+ return;
1173
+
1174
+ UndoManager .shared .beginUndo (_("Center SnapSource in Selection"));
1175
+
1176
+ Editor .setFieldValue (executionContext, source .getValue (), source .position, bbox .center);
1177
+
1178
+ UndoManager .shared .endUndo ();
1179
+ }
1180
+
1038
1181
  async moveSelectionToSnapTarget ()
1039
1182
  {
1040
1183
  const