sunrize 1.11.18 → 2.0.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sunrize",
3
3
  "productName": "Sunrize X3D Editor",
4
- "version": "1.11.18",
4
+ "version": "2.0.1",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -91,7 +91,7 @@
91
91
  "@vscode/codicons": "^0.0.44",
92
92
  "capitalize": "^2.0.4",
93
93
  "console": "^0.7.2",
94
- "electron": "^40.0.0",
94
+ "electron": "^40.1.0",
95
95
  "electron-prompt": "^1.7.0",
96
96
  "electron-squirrel-startup": "^1.0.1",
97
97
  "electron-tabs": "^1.0.4",
@@ -110,7 +110,7 @@
110
110
  "string-similarity": "^4.0.4",
111
111
  "tweakpane": "^3.1.10",
112
112
  "update-electron-app": "^3.1.2",
113
- "x_ite": "^12.2.6",
113
+ "x_ite": "^14.0.1",
114
114
  "x3d-traverse": "^1.0.22"
115
115
  }
116
116
  }
@@ -9,7 +9,7 @@ const
9
9
  require ("./Popover");
10
10
  require ("../Bits/Validate");
11
11
 
12
- $.fn.exportNodePopover = function (node, oldExportedName)
12
+ $.fn.exportNodePopover = function (node, oldExportedName, oldDescription = "")
13
13
  {
14
14
  // Create content.
15
15
 
@@ -18,7 +18,7 @@ $.fn.exportNodePopover = function (node, oldExportedName)
18
18
  const content = $("<div></div>");
19
19
 
20
20
  $("<span></span>")
21
- .text (_("Name"))
21
+ .text ("Exported Name")
22
22
  .appendTo (content);
23
23
 
24
24
  const nameInput = $("<input></input>")
@@ -26,19 +26,35 @@ $.fn.exportNodePopover = function (node, oldExportedName)
26
26
  .val (oldExportedName || scene .getUniqueExportName (node .getName ()))
27
27
  .appendTo (content);
28
28
 
29
+ $("<span></span>")
30
+ .text ("Description")
31
+ .appendTo (content);
32
+
33
+ const descriptionInput = $("<input></input>")
34
+ .attr ("placeholder", _("Enter description"))
35
+ .val (oldDescription)
36
+ .appendTo (content);
37
+
29
38
  // Create tooltip.
30
39
 
31
40
  const tooltip = this .popover ({
32
41
  content: content,
42
+ extension:
43
+ {
44
+ wide: true,
45
+ },
33
46
  events: {
34
47
  show: (event, api) =>
35
48
  {
36
- nameInput .off () .validate (Editor .Id, () =>
49
+ $(nameInput) .add (descriptionInput) .off ();
50
+
51
+ nameInput .validate (Editor .Id, () =>
37
52
  {
38
53
  electron .shell .beep ();
39
54
  nameInput .highlight ();
40
- })
41
- .on ("keydown.exportNodePopover", event =>
55
+ });
56
+
57
+ $(nameInput) .add (descriptionInput) .on ("keydown.exportNodePopover", event =>
42
58
  {
43
59
  if (event .key !== "Enter")
44
60
  return;
@@ -50,12 +66,13 @@ $.fn.exportNodePopover = function (node, oldExportedName)
50
66
  if (!nameInput .val ())
51
67
  return;
52
68
 
53
- if (oldExportedName && oldExportedName === nameInput .val ())
54
- return;
55
-
56
- const exportedName = scene .getUniqueExportName (nameInput .val ());
69
+ const
70
+ exportedName = nameInput .val () !== oldExportedName
71
+ ? scene .getUniqueExportName (nameInput .val ())
72
+ : oldExportedName,
73
+ description = descriptionInput .val ();
57
74
 
58
- Editor .updateExportedNode (scene, exportedName, oldExportedName, node);
75
+ Editor .updateExportedNode (scene, exportedName, oldExportedName, node, description);
59
76
  });
60
77
 
61
78
  setTimeout (() => nameInput .trigger ("select"), 1);
@@ -9,7 +9,7 @@ const
9
9
  require ("./Popover");
10
10
  require ("../Bits/Validate");
11
11
 
12
- $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName)
12
+ $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName, oldDescription = "")
13
13
  {
14
14
  // Create content.
15
15
 
@@ -18,7 +18,7 @@ $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName)
18
18
  const content = $("<div></div>");
19
19
 
20
20
  $("<span></span>")
21
- .text (_("Name"))
21
+ .text ("Imported Name")
22
22
  .appendTo (content);
23
23
 
24
24
  const nameInput = $("<input></input>")
@@ -26,19 +26,35 @@ $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName)
26
26
  .val (oldImportedName || executionContext .getUniqueImportName (exportedName))
27
27
  .appendTo (content);
28
28
 
29
+ $("<span></span>")
30
+ .text ("Description")
31
+ .appendTo (content);
32
+
33
+ const descriptionInput = $("<input></input>")
34
+ .attr ("placeholder", _("Enter description"))
35
+ .val (oldDescription)
36
+ .appendTo (content);
37
+
29
38
  // Create tooltip.
30
39
 
31
40
  const tooltip = this .popover ({
32
41
  content: content,
42
+ extension:
43
+ {
44
+ wide: true,
45
+ },
33
46
  events: {
34
47
  show: (event, api) =>
35
48
  {
49
+ $(nameInput) .add (descriptionInput) .off ();
50
+
36
51
  nameInput .off () .validate (Editor .Id, () =>
37
52
  {
38
53
  electron .shell .beep ();
39
54
  nameInput .highlight ();
40
- })
41
- .on ("keydown.importNodePopover", event =>
55
+ });
56
+
57
+ $(nameInput) .add (descriptionInput) .on ("keydown.importNodePopover", event =>
42
58
  {
43
59
  if (event .key !== "Enter")
44
60
  return;
@@ -50,12 +66,13 @@ $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName)
50
66
  if (!nameInput .val ())
51
67
  return;
52
68
 
53
- if (oldImportedName && oldImportedName === nameInput .val ())
54
- return;
55
-
56
- const importedName = executionContext .getUniqueImportName (nameInput .val ());
69
+ const
70
+ importedName = nameInput .val () !== oldImportedName
71
+ ? executionContext .getUniqueImportName (nameInput .val ())
72
+ : oldImportedName,
73
+ description = descriptionInput .val ();
57
74
 
58
- Editor .updateImportedNode (executionContext, inlineNode, exportedName, importedName, oldImportedName);
75
+ Editor .updateImportedNode (executionContext, inlineNode, exportedName, importedName, oldImportedName, description);
59
76
  });
60
77
 
61
78
  setTimeout (() => nameInput .trigger ("select"), 1);
@@ -18,10 +18,10 @@ $.fn.materialPreviewPopover = async function (node)
18
18
 
19
19
  const canvas = $("<x3d-canvas></x3d-canvas>")
20
20
  .css ({ width: "30vh", height: "30vh" })
21
- .attr ("cache", false)
22
- .attr ("splashScreen", false)
23
- .attr ("contextMenu", false)
24
- .attr ("notifications", false)
21
+ .attr ("cache", "false")
22
+ .attr ("splashScreen", "false")
23
+ .attr ("contextMenu", "false")
24
+ .attr ("notifications", "false")
25
25
  .attr ("colorSpace", node .getBrowser () .getBrowserOption ("ColorSpace"))
26
26
  .attr ("xrSessionMode", "NONE")
27
27
  .appendTo (preview);
@@ -42,10 +42,10 @@ $.fn.texturePreviewPopover = async function (node)
42
42
  const canvas = $("<x3d-canvas></x3d-canvas>")
43
43
  .css ("width","30vh")
44
44
  .css ("height", "30vh")
45
- .attr ("cache", false)
46
- .attr ("splashScreen", false)
47
- .attr ("contextMenu", false)
48
- .attr ("notifications", false)
45
+ .attr ("cache", "false")
46
+ .attr ("splashScreen", "false")
47
+ .attr ("contextMenu", "false")
48
+ .attr ("notifications", "false")
49
49
  .attr ("colorSpace", node .getBrowser () .getBrowserOption ("ColorSpace"))
50
50
  .attr ("xrSessionMode", "NONE")
51
51
  .appendTo (preview);
@@ -849,7 +849,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
849
849
  element = $(`#${id}`),
850
850
  exportedNode = this .objects .get (parseInt (element .attr ("exported-node-id")));
851
851
 
852
- element .find ("> .item") .exportNodePopover (exportedNode .getLocalNode (), exportedNode .getExportedName ());
852
+ element .find ("> .item") .exportNodePopover (exportedNode .getLocalNode (), exportedNode .getExportedName (), exportedNode .getDescription ());
853
853
  }
854
854
 
855
855
  removeExportedNode (id)
@@ -870,7 +870,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
870
870
  exportedNode = this .objects .get (parseInt (element .attr ("exported-node-id"))),
871
871
  inlineNode = this .getNode (element .closest (".node", this .sceneGraph));
872
872
 
873
- element .find ("> .item") .importNodePopover (inlineNode, exportedNode .getExportedName ());
873
+ element .find ("> .item") .importNodePopover (inlineNode, exportedNode .getExportedName (), "", exportedNode .getDescription ());
874
874
  }
875
875
 
876
876
  editImportedNode (id)
@@ -881,7 +881,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
881
881
  element = $(`#${id}`),
882
882
  importedNode = this .objects .get (parseInt (element .attr ("imported-node-id")));
883
883
 
884
- element .find ("> .item") .importNodePopover (importedNode .getInlineNode (), importedNode .getExportedName (), importedNode .getImportedName ());
884
+ element .find ("> .item") .importNodePopover (importedNode .getInlineNode (), importedNode .getExportedName (), importedNode .getImportedName (), importedNode .getDescription ());
885
885
  }
886
886
 
887
887
  removeImportedNode (id)
@@ -148,11 +148,12 @@ module .exports = class OutlineView extends Interface
148
148
  {
149
149
  this .onDemandToolNodes = new Set ([
150
150
  X3D .X3DConstants .DirectionalLight,
151
+ X3D .X3DConstants .EnvironmentLight,
151
152
  X3D .X3DConstants .ListenerPointSource,
152
153
  X3D .X3DConstants .PointLight,
153
- X3D .X3DConstants .SpotLight,
154
154
  X3D .X3DConstants .Sound,
155
155
  X3D .X3DConstants .SpatialSound,
156
+ X3D .X3DConstants .SpotLight,
156
157
  X3D .X3DConstants .ViewpointGroup,
157
158
  X3D .X3DConstants .X3DEnvironmentalSensorNode,
158
159
  X3D .X3DConstants .X3DTextureProjectorNode,
@@ -1438,7 +1439,8 @@ module .exports = class OutlineView extends Interface
1438
1439
  .addClass (classes)
1439
1440
  .attr ("node-id", node .getId ())
1440
1441
  .attr ("imported-node-id", importedNode .getId ())
1441
- .attr ("index", index);
1442
+ .attr ("index", index)
1443
+ .attr ("title", importedNode .getDescription ());
1442
1444
 
1443
1445
  // Icon
1444
1446
 
@@ -1529,7 +1531,8 @@ module .exports = class OutlineView extends Interface
1529
1531
  const child = $("<li></li>")
1530
1532
  .addClass (type)
1531
1533
  .attr ("exported-node-id", exportedNode .getId ())
1532
- .attr ("node-id", node .getId ());
1534
+ .attr ("node-id", node .getId ())
1535
+ .attr ("title", exportedNode .getDescription ());
1533
1536
 
1534
1537
  // Icon
1535
1538
 
@@ -1577,7 +1580,7 @@ module .exports = class OutlineView extends Interface
1577
1580
  }
1578
1581
 
1579
1582
  static connectorId = 0;
1580
- static urlFields = new Set (["url", "frontUrl", "backUrl", "leftUrl", "rightUrl", "topUrl", "bottomUrl", "family"]);
1583
+ static urlFields = new Set (["url", "frontUrl", "backUrl", "leftUrl", "rightUrl", "topUrl", "bottomUrl"]);
1581
1584
 
1582
1585
  #fieldSymbol = Symbol ();
1583
1586
  #fieldButtonSymbol = Symbol ();
@@ -45,7 +45,7 @@ class AudioParser extends X3D .X3DParser
45
45
 
46
46
  scene .setEncoding ("AUDIO");
47
47
  scene .setProfile (browser .getProfile ("Interchange"));
48
- scene .addComponent (browser .getComponent ("Sound", 1));
48
+ scene .updateComponent (browser .getComponent ("Sound", 1));
49
49
 
50
50
  await this .loadComponents ();
51
51
 
@@ -45,7 +45,7 @@ class ImageParser extends X3D .X3DParser
45
45
 
46
46
  scene .setEncoding ("IMAGE");
47
47
  scene .setProfile (browser .getProfile ("Interchange"));
48
- scene .addComponent (browser .getComponent ("Geometry2D", 1));
48
+ scene .updateComponent (browser .getComponent ("Geometry2D", 1));
49
49
 
50
50
  await this .loadComponents ();
51
51
 
@@ -45,8 +45,8 @@ class VideoParser extends X3D .X3DParser
45
45
 
46
46
  scene .setEncoding ("VIDEO");
47
47
  scene .setProfile (browser .getProfile ("Interchange"));
48
- scene .addComponent (browser .getComponent ("Geometry2D", 1));
49
- scene .addComponent (browser .getComponent ("Sound", 1));
48
+ scene .updateComponent (browser .getComponent ("Geometry2D", 1));
49
+ scene .updateComponent (browser .getComponent ("Sound", 1));
50
50
 
51
51
  await this .loadComponents ();
52
52
 
@@ -220,22 +220,22 @@ class X3DGridNodeTool extends X3DActiveLayerNodeTool
220
220
  index2 = (index0 + 2) % 3;
221
221
 
222
222
  const y = [
223
- absoluteMatrix .X_AXIS .copy (),
224
- absoluteMatrix .Y_AXIS .copy (),
225
- absoluteMatrix .Z_AXIS .copy (),
223
+ absoluteMatrix .xAxis .copy (),
224
+ absoluteMatrix .yAxis .copy (),
225
+ absoluteMatrix .zAxis .copy (),
226
226
  ]; // Rotation axis, equates to grid normal
227
227
 
228
228
  const z = [
229
- absoluteMatrix .Y_AXIS .copy (),
230
- absoluteMatrix .Z_AXIS .copy (),
231
- absoluteMatrix .Y_AXIS .copy (),
229
+ absoluteMatrix .yAxis .copy (),
230
+ absoluteMatrix .zAxis .copy (),
231
+ absoluteMatrix .yAxis .copy (),
232
232
  ]; // Axis which snaps, later transformed to grid space
233
233
 
234
234
  const gridMatrix = this .getGridMatrix ();
235
235
 
236
236
  const
237
237
  Y = y [index1] .copy () .cross (y [index2]) .normalize (), // Normal of rotation plane
238
- X = gridMatrix .Y_AXIS .copy () .cross (Y), // Intersection between both planes
238
+ X = gridMatrix .yAxis .copy () .cross (Y), // Intersection between both planes
239
239
  Z = X .copy () .cross (Y), // Front vector
240
240
  gridPlane = gridMatrix .submatrix .copy ();
241
241
 
@@ -245,7 +245,7 @@ class X3DGridNodeTool extends X3DActiveLayerNodeTool
245
245
 
246
246
  // If X or Z are near 0 then Y is collinear to the y-axis.
247
247
 
248
- if (1 - Math .abs (gridMatrix .Y_AXIS .normalize () .dot (Y)) < 1e-6)
248
+ if (1 - Math .abs (gridMatrix .yAxis .normalize () .dot (Y)) < 1e-6)
249
249
  {
250
250
  rotationPlane = new X3D .Matrix3 ();
251
251
  gridRotation = new X3D .Matrix3 ();
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ const X3DLightNodeTool = require ("./X3DLightNodeTool");
4
+
5
+ class EnvironmentLightTool extends X3DLightNodeTool
6
+ {
7
+ async initializeTool ()
8
+ {
9
+ await super .initializeTool ();
10
+
11
+ this .tool .getField ("location") .addReference (this .node ._origin);
12
+ this .tool .getField ("rotation") .addReference (this .node ._rotation);
13
+
14
+ this .tool .type = 3;
15
+ }
16
+
17
+ beginUndo ()
18
+ {
19
+ this .undoSaveInitialValues (["origin", "rotation"]);
20
+ }
21
+ }
22
+
23
+ module .exports = EnvironmentLightTool;
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 4.0//EN" "https://www.web3d.org/specifications/x3d-4.0.dtd">
3
- <X3D profile='Interchange' version='4.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-4.0.xsd'>
2
+ <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 4.1//EN" "https://www.web3d.org/specifications/x3d-4.1.dtd">
3
+ <X3D profile='Interchange' version='4.1' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-4.1.xsd'>
4
4
  <head>
5
5
  <component name='Layout' level='2'/>
6
6
  <component name='Scripting' level='1'/>
@@ -8,9 +8,9 @@
8
8
  <meta name='comment' content='Rise and Shine'/>
9
9
  <meta name='created' content='Fri, 01 Aug 2014 17:41:58 GMT'/>
10
10
  <meta name='creator' content='Holger Seelig'/>
11
- <meta name='generator' content='Sunrize X3D Editor V1.7.57, https://create3000.github.io/sunrize/'/>
11
+ <meta name='generator' content='Sunrize X3D Editor V2.0.0, https://create3000.github.io/sunrize/'/>
12
12
  <meta name='identifier' content='file:///Users/holger/Desktop/X_ITE/sunrize/src/sunrize/Tools/Lighting/X3DLightNodeTool.x3d'/>
13
- <meta name='modified' content='Mon, 10 Mar 2025 10:42:47 GMT'/>
13
+ <meta name='modified' content='Sat, 31 Jan 2026 23:04:56 GMT'/>
14
14
  </head>
15
15
  <Scene>
16
16
  <ExternProtoDeclare name='ToolShader' url='"../Shaders/ToolShader.x3d"'>
@@ -27,6 +27,7 @@
27
27
  <field accessType='inputOutput' type='SFColor' name='color' value='1 1 1'/>
28
28
  <field accessType='inputOutput' type='SFFloat' name='intensity' value='1'/>
29
29
  <field accessType='inputOutput' type='SFVec3f' name='location'/>
30
+ <field accessType='inputOutput' type='SFRotation' name='rotation'/>
30
31
  <field accessType='inputOutput' type='SFVec3f' name='direction' value='0 0 -1'/>
31
32
  <field accessType='inputOutput' type='SFFloat' name='beamWidth'/>
32
33
  <field accessType='inputOutput' type='SFFloat' name='cutOffAngle'/>
@@ -37,8 +38,7 @@
37
38
  <ProtoBody>
38
39
  <Collision
39
40
  enabled='false'>
40
- <Transform DEF='_1'
41
- rotation='0 1 0 3.14159265358979'>
41
+ <Transform DEF='_1'>
42
42
  <ScreenGroup>
43
43
  <Transform DEF='Lights'
44
44
  translation='0 0 1.26218e-29'
@@ -54,16 +54,16 @@
54
54
  <Transform DEF='Rays'>
55
55
  <Shape
56
56
  castShadow='false'>
57
- <Appearance DEF='_2'>
57
+ <Appearance DEF='_7'>
58
58
  <LineProperties
59
59
  linewidthScaleFactor='2'/>
60
- <Material DEF='_3'
60
+ <Material DEF='_8'
61
61
  ambientIntensity='0.1'
62
62
  diffuseColor='1 1 1'
63
63
  specularColor='0.8 0.8 0.8'
64
64
  emissiveColor='0.67 0.67 0.67'
65
65
  shininess='1'/>
66
- <ProtoInstance name='ToolShader' DEF='_4' containerField='shaders'/>
66
+ <ProtoInstance name='ToolShader' DEF='_9' containerField='shaders'/>
67
67
  </Appearance>
68
68
  <IndexedLineSet
69
69
  coordIndex='0, 1, -1, 2, 3, -1, 4, 5, -1, 6, 7, -1, 8, 9, -1, 10, 11, -1, 12, 13, -1, 14, 15, -1, 16, 17, -1'>
@@ -76,9 +76,9 @@
76
76
  scale='1 0.61803 0.1'>
77
77
  <Shape
78
78
  castShadow='false'>
79
- <Appearance DEF='_5'>
80
- <Material USE='_3'/>
81
- <ProtoInstance name='ToolShader' USE='_4' containerField='shaders'/>
79
+ <Appearance DEF='_10'>
80
+ <Material USE='_8'/>
81
+ <ProtoInstance name='ToolShader' USE='_9' containerField='shaders'/>
82
82
  </Appearance>
83
83
  <Box/>
84
84
  </Shape>
@@ -91,7 +91,7 @@
91
91
  scaleOrientation='0.999999999986306 2.43262999996669e-6 4.63356999993655e-6 0.785354'>
92
92
  <Shape DEF='_6'
93
93
  castShadow='false'>
94
- <Appearance USE='_5'/>
94
+ <Appearance USE='_10'/>
95
95
  <Cone
96
96
  height='3'/>
97
97
  </Shape>
@@ -155,11 +155,11 @@
155
155
  </Transform>
156
156
  </Transform>
157
157
  <Transform DEF='PointLight'>
158
- <Transform DEF='Rays_1'
158
+ <Transform DEF='Rays_3'
159
159
  scale='2 2 2'>
160
160
  <Shape
161
161
  castShadow='false'>
162
- <Appearance USE='_2'/>
162
+ <Appearance USE='_7'/>
163
163
  <IndexedLineSet
164
164
  coordIndex='0, 1, -1, 2, 3, -1, 4, 5, -1, 6, 7, -1, 8, 9, -1, 10, 11, -1, 12, 13, -1, 14, 15, -1, 16, 17, -1'>
165
165
  <Coordinate
@@ -167,10 +167,10 @@
167
167
  </IndexedLineSet>
168
168
  </Shape>
169
169
  </Transform>
170
- <Shape DEF='Sphere'
170
+ <Shape DEF='Sphere_2'
171
171
  castShadow='false'>
172
- <Appearance USE='_5'/>
173
- <Sphere/>
172
+ <Appearance USE='_10'/>
173
+ <Sphere DEF='_2'/>
174
174
  </Shape>
175
175
  </Transform>
176
176
  <Transform DEF='SpotLight'>
@@ -181,7 +181,7 @@
181
181
  scale='1.70236 1.70236 1.70236'>
182
182
  <Shape
183
183
  castShadow='false'>
184
- <Appearance USE='_2'/>
184
+ <Appearance USE='_7'/>
185
185
  <IndexedLineSet
186
186
  coordIndex='0, 1, 2, 0, -1, 2, 3, 0, -1, 3, 4, 0, -1, 4, 5, 0, -1, 5, 6, 0, -1, 6, 7, 0, -1, 7, 8, 0, -1, 8, 9, 0, -1, 9, 10, 0, -1, 10, 11, 0, -1, 11, 12, 0, -1, 12, 13, 0, -1, 13, 14, 0, -1, 14, 15, 0, -1, 15, 16, 0, -1, 16, 17, 0, -1, 17, 18, 0, -1, 18, 19, 0, -1, 19, 20, 0, -1, 20, 21, 0, -1, 21, 22, 0, -1, 22, 23, 0, -1, 23, 24, 0, -1, 24, 25, 0, -1, 25, 26, 0, -1, 26, 27, 0, -1, 27, 28, 0, -1, 28, 29, 0, -1, 29, 30, 0, -1, 30, 31, 0, -1, 31, 32, 0, -1, 32, 1, -1'>
187
187
  <Coordinate
@@ -194,14 +194,14 @@
194
194
  translation='0 0 1.46147'>
195
195
  <Shape DEF='Sphere_1'
196
196
  castShadow='false'>
197
- <Appearance USE='_5'/>
198
- <Sphere/>
197
+ <Appearance USE='_10'/>
198
+ <Sphere USE='_2'/>
199
199
  </Shape>
200
200
  <Transform DEF='Rays_2'
201
201
  scale='2 2 2'>
202
202
  <Shape
203
203
  castShadow='false'>
204
- <Appearance USE='_2'/>
204
+ <Appearance USE='_7'/>
205
205
  <IndexedLineSet
206
206
  coordIndex='0, 1, -1, 2, 3, -1, 4, 5, -1, 6, 7, -1, 8, 9, -1, 10, 11, -1, 12, 13, -1, 14, 15, -1, 16, 17, -1'>
207
207
  <Coordinate
@@ -211,14 +211,49 @@
211
211
  </Transform>
212
212
  </Transform>
213
213
  </Transform>
214
+ <Transform DEF='EnvironmentLight'
215
+ scale='2 2 2'>
216
+ <Transform DEF='Rays_1'
217
+ scale='2 2 2'>
218
+ <Shape
219
+ castShadow='false'>
220
+ <Appearance>
221
+ <LineProperties
222
+ linewidthScaleFactor='2'/>
223
+ <Material
224
+ ambientIntensity='0.1'
225
+ diffuseColor='1 1 1'
226
+ specularColor='0.8 0.8 0.8'
227
+ emissiveColor='0.67 0.67 0.67'
228
+ shininess='1'/>
229
+ <ProtoInstance name='ToolShader' containerField='shaders'/>
230
+ </Appearance>
231
+ <IndexedLineSet
232
+ coordIndex='0, 1, -1, 2, 3, -1, 4, 5, -1, 6, 7, -1, 8, 9, -1, 10, 11, -1, 12, 13, -1, 14, 15, -1, 16, 17, -1'>
233
+ <Coordinate
234
+ point='-1 0 0, 1 0 0, 0 -1 0, 0 1 0, 0 0 -1, 0 0 1, -0.5 0.7071068 -0.5, 0.5 -0.7071068 0.5, -0.5 -0.7071068 -0.5, 0.5 0.7071068 0.5, 0.7071068 0 -0.7071068, -0.7071068 0 0.7071068, -0.5 0.7071068 0.5, 0.5 -0.7071068 -0.5, -0.5 -0.7071068 0.5, 0.5 0.7071068 -0.5, -0.7071068 0 -0.7071068, 0.7071068 0 0.7071068'/>
235
+ </IndexedLineSet>
236
+ </Shape>
237
+ </Transform>
238
+ <Shape DEF='Sphere'
239
+ castShadow='false'>
240
+ <Appearance>
241
+ <PhysicalMaterial
242
+ roughness='0'/>
243
+ <TextureTransform
244
+ scale='-1 1'/>
245
+ </Appearance>
246
+ <Sphere USE='_2'/>
247
+ </Shape>
248
+ </Transform>
214
249
  </Switch>
215
250
  </Transform>
216
251
  </ScreenGroup>
217
252
  </Transform>
218
- <Transform DEF='TransformTool'
219
- rotation='0 1 0 3.14159265358979'>
253
+ <Transform DEF='TransformTool'>
220
254
  <IS>
221
255
  <connect nodeField='translation' protoField='location'/>
256
+ <connect nodeField='rotation' protoField='rotation'/>
222
257
  <connect nodeField='visible' protoField='selected'/>
223
258
  </IS>
224
259
  <ScreenGroup>
@@ -243,7 +278,7 @@
243
278
  <field accessType='inputOutput' type='SFFloat' name='intensity'/>
244
279
  <field accessType='inputOutput' type='SFVec3f' name='direction'/>
245
280
  <field accessType='initializeOnly' type='SFVec3f' name='upVector' value='0 1 0'/>
246
- <field accessType='inputOnly' type='SFRotation' name='set_rotation'/>
281
+ <field accessType='inputOutput' type='SFRotation' name='rotation'/>
247
282
  <field accessType='inputOutput' type='SFFloat' name='beamWidth'/>
248
283
  <field accessType='inputOutput' type='SFFloat' name='cutOffAngle'/>
249
284
  <field accessType='inputOutput' type='SFString' name='activeTool'/>
@@ -252,7 +287,7 @@
252
287
  <Transform USE='TransformTool'/>
253
288
  </field>
254
289
  <field accessType='initializeOnly' type='SFNode' name='material'>
255
- <Material USE='_3'/>
290
+ <Material USE='_8'/>
256
291
  </field>
257
292
  <field accessType='initializeOnly' type='SFNode' name='cone'>
258
293
  <Transform USE='Cone'/>
@@ -399,6 +434,8 @@ function set_angle ()
399
434
  <ROUTE fromNode='TransformTool' fromField='rotation_changed' toNode='Tool' toField='set_rotation'/>
400
435
  </ProtoBody>
401
436
  </ProtoDeclare>
402
- <ProtoInstance name='X3DLightNodeTool'/>
437
+ <ProtoInstance name='X3DLightNodeTool'>
438
+ <fieldValue name='type' value='3'/>
439
+ </ProtoInstance>
403
440
  </Scene>
404
441
  </X3D>
@@ -185,9 +185,9 @@ class SnapTarget extends X3DSnapNodeTool
185
185
  index2 = (index0 + 2) % 3;
186
186
 
187
187
  const axes = [
188
- absoluteMatrix .X_AXIS .copy (),
189
- absoluteMatrix .Y_AXIS .copy (),
190
- absoluteMatrix .Z_AXIS .copy (),
188
+ absoluteMatrix .xAxis .copy (),
189
+ absoluteMatrix .yAxis .copy (),
190
+ absoluteMatrix .zAxis .copy (),
191
191
  ]; // Rotation axis, equates to grid normal.
192
192
 
193
193
  const
@@ -196,7 +196,7 @@ module .exports = class Editor
196
196
  scene .setProfile (browser .getProfile ("Core"));
197
197
 
198
198
  for (const name of componentNames)
199
- scene .addComponent (browser .getComponent (name));
199
+ scene .updateComponent (browser .getComponent (name));
200
200
 
201
201
  // Add nodes.
202
202
 
@@ -378,7 +378,7 @@ module .exports = class Editor
378
378
  {
379
379
  for (const exportedNode of tempScene .exportedNodes)
380
380
  {
381
- this .updateExportedNode (executionContext, executionContext .getUniqueExportName (exportedNode .getExportedName ()), "", exportedNode .getLocalNode (), undoManager);
381
+ this .updateExportedNode (executionContext, executionContext .getUniqueExportName (exportedNode .getExportedName ()), "", exportedNode .getLocalNode (), exportedNode .getDescription (), undoManager);
382
382
  }
383
383
  }
384
384
 
@@ -538,7 +538,6 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
538
538
  }
539
539
 
540
540
  static absoluteURL = new RegExp ("^(?:[a-z]+:|//)", "i");
541
- static fontFamilies = new Set (["SERIF", "SANS", "TYPEWRITER"]);
542
541
 
543
542
  /**
544
543
  *
@@ -555,23 +554,17 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
555
554
  for (const object of Traverse .traverse (objects, Traverse .EXTERNPROTO_DECLARATIONS | Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES))
556
555
  {
557
556
  const
558
- node = object instanceof X3D .SFNode ? object .getValue () : object,
559
- urlObject = node .getType () .includes (X3D .X3DConstants .X3DUrlObject),
560
- fontStyleNode = node .getType () .includes (X3D .X3DConstants .X3DFontStyleNode);
557
+ node = object instanceof X3D .SFNode ? object .getValue () : object,
558
+ urlObject = node .getType () .includes (X3D .X3DConstants .X3DUrlObject);
561
559
 
562
- if (!(urlObject || fontStyleNode))
560
+ if (!urlObject)
563
561
  continue;
564
562
 
565
563
  const newURL = new X3D .MFString ();
566
564
 
567
565
  for (const fileURL of node ._url)
568
566
  {
569
- if (fontStyleNode && this .fontFamilies .has (fileURL))
570
- {
571
- newURL .push (fileURL);
572
- continue;
573
- }
574
- else if (this .absoluteURL .test (fileURL))
567
+ if (this .absoluteURL .test (fileURL))
575
568
  {
576
569
  try
577
570
  {
@@ -762,9 +755,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
762
755
  */
763
756
  static setComponents (scene, components, undoManager = UndoManager .shared)
764
757
  {
765
- const
766
- browser = scene .getBrowser (),
767
- oldComponents = Array .from (scene .getComponents ());
758
+ const oldComponents = Array .from (scene .getComponents ());
768
759
 
769
760
  undoManager .beginUndo (_("Set Components of Scene"));
770
761
 
@@ -800,7 +791,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
800
791
 
801
792
  undoManager .beginUndo (_("Add Component %s"), name);
802
793
 
803
- scene .addComponent (browser .getComponent (name));
794
+ scene .updateComponent (browser .getComponent (name));
804
795
 
805
796
  undoManager .registerUndo (() =>
806
797
  {
@@ -959,21 +950,30 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
959
950
  * @param {string} importedName
960
951
  * @param {UndoManager} undoManager
961
952
  */
962
- static updateImportedNode (executionContext, inlineNode, exportedName, importedName, oldImportedName, undoManager = UndoManager .shared)
953
+ static updateImportedNode (executionContext, inlineNode, exportedName, importedName, oldImportedName, description, undoManager = UndoManager .shared)
963
954
  {
964
955
  inlineNode = inlineNode .valueOf ();
965
956
 
957
+ const oldDescription = executionContext .getImportedNodes () .get (oldImportedName) ?.getDescription ();
958
+
966
959
  undoManager .beginUndo (_("Update Imported Node »%s«"), importedName);
967
960
 
968
961
  if (oldImportedName)
969
- executionContext .renameImportedNode (oldImportedName, importedName);
962
+ {
963
+ if (importedName !== oldImportedName)
964
+ executionContext .renameImportedNode (oldImportedName, importedName);
965
+
966
+ executionContext .getImportedNodes () .get (importedName) .setDescription (description);
967
+ }
970
968
  else
971
- executionContext .updateImportedNode (inlineNode .valueOf (), exportedName, importedName);
969
+ {
970
+ executionContext .updateImportedNode (inlineNode .valueOf (), exportedName, importedName, description);
971
+ }
972
972
 
973
973
  undoManager .registerUndo (() =>
974
974
  {
975
975
  if (oldImportedName)
976
- this .updateImportedNode (executionContext, inlineNode, exportedName, oldImportedName, importedName, undoManager);
976
+ this .updateImportedNode (executionContext, inlineNode, exportedName, oldImportedName, importedName, oldDescription, undoManager);
977
977
  else
978
978
  this .removeImportedNode (executionContext, importedName, undoManager);
979
979
  });
@@ -995,6 +995,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
995
995
  importedNode = executionContext .getImportedNodes () .get (importedName),
996
996
  inlineNode = importedNode .getInlineNode (),
997
997
  exportedName = importedNode .getExportedName (),
998
+ description = importedNode .getDescription (),
998
999
  exportedNode = importedNode .getExportedNode ();
999
1000
 
1000
1001
  const routes = executionContext .getRoutes () .filter (route =>
@@ -1059,7 +1060,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
1059
1060
 
1060
1061
  undoManager .registerUndo (() =>
1061
1062
  {
1062
- this .updateImportedNode (executionContext, inlineNode, exportedName, importedName, "", undoManager);
1063
+ this .updateImportedNode (executionContext, inlineNode, exportedName, importedName, "", description, undoManager);
1063
1064
 
1064
1065
  const newImportedNode = executionContext .getImportedNodes () .get (importedName);
1065
1066
 
@@ -1087,21 +1088,30 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
1087
1088
  * @param {X3DNode} node
1088
1089
  * @param {UndoManager} undoManager
1089
1090
  */
1090
- static updateExportedNode (scene, exportedName, oldExportedName, node, undoManager = UndoManager .shared)
1091
+ static updateExportedNode (scene, exportedName, oldExportedName, node, description, undoManager = UndoManager .shared)
1091
1092
  {
1092
1093
  node = node .valueOf ();
1093
1094
 
1094
1095
  undoManager .beginUndo (_("Update Exported Node »%s«"), exportedName);
1095
1096
 
1096
- if (oldExportedName)
1097
- scene .removeExportedNode (oldExportedName);
1097
+ const oldDescription = scene .getExportedNodes () .get (oldExportedName) ?.getDescription () ?? "";
1098
1098
 
1099
- scene .updateExportedNode (exportedName, node);
1099
+ if (exportedName === oldExportedName)
1100
+ {
1101
+ scene .getExportedNodes () .get (exportedName) ?.setDescription (description);
1102
+ }
1103
+ else
1104
+ {
1105
+ if (oldExportedName)
1106
+ scene .removeExportedNode (oldExportedName);
1107
+
1108
+ scene .updateExportedNode (exportedName, node, description);
1109
+ }
1100
1110
 
1101
1111
  undoManager .registerUndo (() =>
1102
1112
  {
1103
1113
  if (oldExportedName)
1104
- this .updateExportedNode (scene, oldExportedName, exportedName, node, undoManager);
1114
+ this .updateExportedNode (scene, oldExportedName, exportedName, node, oldDescription, undoManager);
1105
1115
  else
1106
1116
  this .removeExportedNode (scene, exportedName, undoManager);
1107
1117
  });
@@ -1121,7 +1131,8 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
1121
1131
  {
1122
1132
  const
1123
1133
  exportedNode = scene .getExportedNodes () .get (exportedName),
1124
- node = exportedNode .getLocalNode ();
1134
+ node = exportedNode .getLocalNode (),
1135
+ description = exportedNode .getDescription ();
1125
1136
 
1126
1137
  undoManager .beginUndo (_("Remove Exported Node »%s«"), exportedName);
1127
1138
 
@@ -1129,7 +1140,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
1129
1140
 
1130
1141
  undoManager .registerUndo (() =>
1131
1142
  {
1132
- this .updateExportedNode (scene, exportedName, "", node, undoManager);
1143
+ this .updateExportedNode (scene, exportedName, "", node, description, undoManager);
1133
1144
  });
1134
1145
 
1135
1146
  this .requestUpdateInstances (scene, undoManager);
@@ -2574,9 +2585,9 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
2574
2585
  {
2575
2586
  const
2576
2587
  bboxMatrix = subBBoxes [0] .matrix,
2577
- bboxXAxes = bboxMatrix .X_AXIS .norm () ? bboxMatrix .X_AXIS : X3D .Vector3 .X_AXIS,
2578
- bboxYAxes = bboxMatrix .Y_AXIS .norm () ? bboxMatrix .Y_AXIS : X3D .Vector3 .Y_AXIS,
2579
- bboxZAxes = bboxMatrix .Z_AXIS .norm () ? bboxMatrix .Z_AXIS : X3D .Vector3 .Z_AXIS;
2588
+ bboxXAxes = bboxMatrix .xAxis .norm () ? bboxMatrix .xAxis : X3D .Vector3 .X_AXIS,
2589
+ bboxYAxes = bboxMatrix .yAxis .norm () ? bboxMatrix .yAxis : X3D .Vector3 .Y_AXIS,
2590
+ bboxZAxes = bboxMatrix .zAxis .norm () ? bboxMatrix .zAxis : X3D .Vector3 .Z_AXIS;
2580
2591
 
2581
2592
  const axes = [
2582
2593
  bboxXAxes .copy (), // right