sunrize 1.6.13 → 1.6.15

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.6.13",
4
+ "version": "1.6.15",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -68,6 +68,10 @@
68
68
  "url": "https://github.com/create3000"
69
69
  }
70
70
  ],
71
+ "funding": {
72
+ "type": "patreon",
73
+ "url": "https://patreon.com/X_ITE"
74
+ },
71
75
  "devDependencies": {
72
76
  "@electron-forge/cli": "^7.4.0",
73
77
  "@electron-forge/maker-deb": "^7.4.0",
@@ -81,16 +85,16 @@
81
85
  "dependencies": {
82
86
  "capitalize": "^2.0.4",
83
87
  "console": "^0.7.2",
84
- "electron": "^30.0.3",
88
+ "electron": "^30.0.8",
85
89
  "electron-prompt": "^1.7.0",
86
- "electron-squirrel-startup": "^1.0.0",
90
+ "electron-squirrel-startup": "^1.0.1",
87
91
  "electron-tabs": "^1.0.4",
88
92
  "fullname": "^5.0.0",
89
93
  "jquery": "^3.7.1",
90
94
  "jquery-ui-dist": "^1.13.2",
91
95
  "jstree": "^3.3.16",
92
96
  "material-icons": "^1.13.12",
93
- "material-symbols": "^0.17.4",
97
+ "material-symbols": "^0.18.0",
94
98
  "md5": "^2.3.0",
95
99
  "mime-types": "^2.1.35",
96
100
  "monaco-editor": "^0.48.0",
@@ -100,7 +104,7 @@
100
104
  "string-similarity": "^4.0.4",
101
105
  "tweakpane": "^3.1.10",
102
106
  "update-electron-app": "^3.0.0",
103
- "x_ite": "^9.6.1"
107
+ "x_ite": "^9.6.3"
104
108
  },
105
109
  "config": {
106
110
  "forge": {
@@ -886,6 +886,29 @@ module .exports = class Application
886
886
 
887
887
  async showOpenDialog ({ defaultPath, filters, properties = ["multiSelections"] })
888
888
  {
889
+ const defaultFilters = [
890
+ {
891
+ name: _("X3D"),
892
+ extensions: ["x3d", "x3dz", "x3dv", "x3dvz", "x3dj", "x3djz", "wrl", "wrz", "wrl.gz", "vrml"],
893
+ },
894
+ {
895
+ name: _("3D"),
896
+ extensions: ["gltf", "glb", "obj", "stl", "ply", "svg"],
897
+ },
898
+ {
899
+ name: _("Audio"),
900
+ extensions: ["mp3", "wav", "oga", "ogg"],
901
+ },
902
+ {
903
+ name: _("Images"),
904
+ extensions: ["png", "jpg", "jpeg", "gif", "webp", "ktx2"],
905
+ },
906
+ {
907
+ name: _("Video"),
908
+ extensions: ["mp4", "webm", "ogv"],
909
+ },
910
+ ];
911
+
889
912
  this .pushMenu (this .createDialogMenu ());
890
913
 
891
914
  const response = await electron .dialog .showOpenDialog ({
@@ -893,9 +916,10 @@ module .exports = class Application
893
916
  properties: ["openFile", ... properties],
894
917
  filters: filters ?? [
895
918
  {
896
- name: _("X3D Document"),
897
- extensions: ["x3d", "x3dz", "x3dv", "x3dvz", "x3dj", "x3djz", "wrl", "wrz", "wrl.gz", "vrml", "gltf", "glb", "obj", "stl", "ply", "svg"],
919
+ name: _("All Documents"),
920
+ extensions: defaultFilters .reduce ((p, c) => p .concat (c .extensions), [ ]),
898
921
  },
922
+ ... defaultFilters,
899
923
  ],
900
924
  });
901
925
 
@@ -15,6 +15,9 @@ const
15
15
  ActionKeys = require ("./ActionKeys"),
16
16
  Editor = require ("../Undo/Editor"),
17
17
  UndoManager = require ("../Undo/UndoManager"),
18
+ ImageParser = require ("../Parser/ImageParser"),
19
+ VideoParser = require ("../Parser/VideoParser"),
20
+ AudioParser = require ("../Parser/AudioParser"),
18
21
  _ = require ("./GetText");
19
22
 
20
23
  module .exports = class Document extends Interface
@@ -36,6 +39,10 @@ module .exports = class Document extends Interface
36
39
  this .secondaryToolbar = new Dashboard ($("#secondary-toolbar"));
37
40
  this .footer = new Footer ($("#footer"));
38
41
  this .sidebar = new Sidebar ($("#sidebar"));
42
+
43
+ // Additional Parsers
44
+
45
+ X3D .GoldenGate .addParsers (ImageParser, VideoParser, AudioParser);
39
46
  }
40
47
 
41
48
  /**
@@ -378,7 +385,7 @@ Viewpoint {
378
385
 
379
386
  if (this .filePath)
380
387
  {
381
- if (path .extname (this .filePath) .match (/\.(?:wrl|wrz|wrl\.gz|vrml|gltf|glb|obj|stl|ply|svg)$/i))
388
+ if (!path .extname (this .filePath) .match (/\.(?:x3dz?|x3dvz?|x3djz?|html)$/i))
382
389
  {
383
390
  if (!this .fileSaveFileTypeWarning)
384
391
  console .warn (`Couldn't save '${this .filePath}'. File type is not supported.`);
@@ -993,7 +993,7 @@ module .exports = class OutlineView extends Interface
993
993
 
994
994
  $("<span></span>")
995
995
  .addClass (["toggle-visibility", "button", "material-symbols-outlined"])
996
- .addClass (node .isHidden () ? "off" : "")
996
+ .addClass (node .isHidden () ? "off" : "on")
997
997
  .attr ("title", "Toggle visibility.")
998
998
  .text (node .isHidden () ? "visibility_off" : "visibility")
999
999
  .appendTo (name);
@@ -1005,7 +1005,7 @@ module .exports = class OutlineView extends Interface
1005
1005
 
1006
1006
  $("<span></span>")
1007
1007
  .addClass (["toggle-tool", "button", "material-symbols-outlined"])
1008
- .addClass (node .valueOf () === node ? "off" : "")
1008
+ .addClass (node .valueOf () === node ? "off" : "on")
1009
1009
  .attr ("title", _("Toggle display tool."))
1010
1010
  .text ("build_circle")
1011
1011
  .appendTo (name);
@@ -1036,7 +1036,7 @@ module .exports = class OutlineView extends Interface
1036
1036
 
1037
1037
  $("<span></span>")
1038
1038
  .addClass (["bind-node", "button", "material-symbols-outlined"])
1039
- .addClass (node ._isBound .getValue () ? "" : "off")
1039
+ .addClass (node ._isBound .getValue () ? "on" : "off")
1040
1040
  .attr ("title", _("Bind node."))
1041
1041
  .text (node ._isBound .getValue () ? "radio_button_checked" : "radio_button_unchecked")
1042
1042
  .appendTo (name);
@@ -1143,8 +1143,8 @@ module .exports = class OutlineView extends Interface
1143
1143
  this .sceneGraph
1144
1144
  .find (`.node[node-id=${node .getId ()}]`)
1145
1145
  .find ("> .item .bind-node")
1146
- .removeClass ("off")
1147
- .addClass (node ._isBound .getValue () ? "" : "off")
1146
+ .removeClass (["on", "off"])
1147
+ .addClass (node ._isBound .getValue () ? "on" : "off")
1148
1148
  .text (node ._isBound .getValue () ? "radio_button_checked" : "radio_button_unchecked");
1149
1149
  }
1150
1150
 
@@ -2936,8 +2936,8 @@ module .exports = class OutlineView extends Interface
2936
2936
 
2937
2937
  this .sceneGraph .find (`.node[node-id=${node .getId ()}]`)
2938
2938
  .find ("> .item .toggle-visibility")
2939
- .removeClass ("off")
2940
- .addClass (hidden ? "off" : "")
2939
+ .removeClass (["on", "off"])
2940
+ .addClass (hidden ? "off" : "on")
2941
2941
  .text (hidden ? "visibility_off" : "visibility");
2942
2942
  }
2943
2943
 
@@ -2965,8 +2965,8 @@ module .exports = class OutlineView extends Interface
2965
2965
  node .setUserData (_changing, true);
2966
2966
 
2967
2967
  this .sceneGraph .find (`.node[node-id=${node .getId ()}] > .item .toggle-tool`)
2968
- .removeClass ("off")
2969
- .addClass (tool ? "off" : "");
2968
+ .removeClass (["on", "off"])
2969
+ .addClass (tool ? "off" : "on");
2970
2970
  }
2971
2971
 
2972
2972
  activateLayer (event) { }
@@ -3013,8 +3013,8 @@ module .exports = class OutlineView extends Interface
3013
3013
 
3014
3014
  this .sceneGraph .find (`.node[node-id=${node .getId ()}]`)
3015
3015
  .find ("> .item .toggle-visibility")
3016
- .removeClass ("off")
3017
- .addClass (node .isHidden () ? "off" : "")
3016
+ .removeClass (["on", "off"])
3017
+ .addClass (node .isHidden () ? "off" : "on")
3018
3018
  .text (node .isHidden () ? "visibility_off" : "visibility")
3019
3019
  })
3020
3020
 
@@ -3035,6 +3035,7 @@ module .exports = class OutlineView extends Interface
3035
3035
  this .sceneGraph .find (`.node[node-id=${node .getId ()}]`)
3036
3036
  .find ("> .item .toggle-visibility")
3037
3037
  .removeClass ("off")
3038
+ .addClass ("on")
3038
3039
  .text ("visibility")
3039
3040
  })
3040
3041
  }
@@ -3053,6 +3054,7 @@ module .exports = class OutlineView extends Interface
3053
3054
  this .sceneGraph .find (`.node[node-id=${node .getId ()}]`)
3054
3055
  .find ("> .item .toggle-visibility")
3055
3056
  .removeClass ("off")
3057
+ .addClass ("on")
3056
3058
  .text ("visibility")
3057
3059
  })
3058
3060
  }
@@ -3069,6 +3071,7 @@ module .exports = class OutlineView extends Interface
3069
3071
  this .sceneGraph .find (`.node[node-id=${node .getId ()}]`)
3070
3072
  .find ("> .item .toggle-visibility")
3071
3073
  .removeClass ("off")
3074
+ .addClass ("on")
3072
3075
  .text ("visibility")
3073
3076
  })
3074
3077
  }
@@ -373,6 +373,7 @@ DEF Text Transform {
373
373
  }
374
374
  geometry Text {
375
375
  string "3D Text"
376
+ fontStyle FontStyle { }
376
377
  }
377
378
  }
378
379
  }
@@ -345,6 +345,7 @@ module .exports = class ScriptEditor extends Interface
345
345
  wordWrap: "on",
346
346
  wrappingIndent: "indent",
347
347
  minimap: { enabled: false },
348
+ bracketPairColorization: { enabled: true },
348
349
  });
349
350
 
350
351
  editor .onDidBlurEditorWidget (() => this .apply ());
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+
3
+ const
4
+ X3D = require ("../X3D"),
5
+ url = require ("url"),
6
+ path = require ("path");
7
+
8
+ class AudioParser extends X3D .X3DParser
9
+ {
10
+ constructor (scene)
11
+ {
12
+ super (scene);
13
+ }
14
+
15
+ getEncoding ()
16
+ {
17
+ return "ARRAY_BUFFER";
18
+ }
19
+
20
+ setInput (input)
21
+ { }
22
+
23
+ isValid ()
24
+ {
25
+ const worldURL = new URL (this .getScene () .worldURL);
26
+
27
+ if (!worldURL .pathname .match (/\.(?:mp3|wav|oga|ogg)$/i))
28
+ return;
29
+
30
+ return true;
31
+ }
32
+
33
+ parseIntoScene (resolve, reject)
34
+ {
35
+ this .audio ()
36
+ .then (resolve)
37
+ .catch (reject);
38
+ }
39
+
40
+ async audio ()
41
+ {
42
+ const
43
+ browser = this .getBrowser (),
44
+ scene = this .getScene ();
45
+
46
+ scene .setEncoding ("AUDIO");
47
+ scene .setProfile (browser .getProfile ("Interchange"));
48
+ scene .addComponent (browser .getComponent ("Sound", 1));
49
+
50
+ await this .loadComponents ();
51
+
52
+ // Rectangle
53
+
54
+ const
55
+ soundNode = scene .createNode ("Sound"),
56
+ audioClipNode = scene .createNode ("AudioClip");
57
+
58
+ audioClipNode .url = new X3D .MFString (this .getURL (scene .worldURL));
59
+ audioClipNode .loop = true;
60
+
61
+ soundNode .source = audioClipNode;
62
+
63
+ scene .rootNodes .push (soundNode);
64
+
65
+ // Name
66
+
67
+ const
68
+ worldURL = new URL (scene .worldURL),
69
+ name = worldURL .pathname .match (/([^\/]+)\.[^.]+$/);
70
+
71
+ if (name)
72
+ {
73
+ audioClipNode .description = decodeURIComponent (name [1]);
74
+
75
+ scene .addNamedNode (this .sanitizeName (decodeURIComponent (name [1])), soundNode);
76
+ }
77
+
78
+ return scene;
79
+ }
80
+
81
+ getURL (worldURL)
82
+ {
83
+ try
84
+ {
85
+ return encodeURIComponent (path .basename (url .fileURLToPath (worldURL)));
86
+ }
87
+ catch
88
+ {
89
+ return worldURL;
90
+ }
91
+ }
92
+ }
93
+
94
+ module .exports = AudioParser;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+
3
+ const
4
+ X3D = require ("../X3D"),
5
+ url = require ("url"),
6
+ path = require ("path");
7
+
8
+ class ImageParser extends X3D .X3DParser
9
+ {
10
+ constructor (scene)
11
+ {
12
+ super (scene);
13
+ }
14
+
15
+ getEncoding ()
16
+ {
17
+ return "ARRAY_BUFFER";
18
+ }
19
+
20
+ setInput (input)
21
+ { }
22
+
23
+ isValid ()
24
+ {
25
+ const worldURL = new URL (this .getScene () .worldURL);
26
+
27
+ if (!worldURL .pathname .match (/\.(?:png|jpg|jpeg|gif|webp|ktx2)$/i))
28
+ return;
29
+
30
+ return true;
31
+ }
32
+
33
+ parseIntoScene (resolve, reject)
34
+ {
35
+ this .image ()
36
+ .then (resolve)
37
+ .catch (reject);
38
+ }
39
+
40
+ async image ()
41
+ {
42
+ const
43
+ browser = this .getBrowser (),
44
+ scene = this .getScene ();
45
+
46
+ scene .setEncoding ("IMAGE");
47
+ scene .setProfile (browser .getProfile ("Interchange"));
48
+ scene .addComponent (browser .getComponent ("Geometry2D", 1));
49
+
50
+ await this .loadComponents ();
51
+
52
+ // Rectangle
53
+
54
+ const
55
+ transformNode = scene .createNode ("Transform"),
56
+ shapeNode = scene .createNode ("Shape"),
57
+ appearanceNode = scene .createNode ("Appearance"),
58
+ textureNode = scene .createNode ("ImageTexture"),
59
+ rectangleNode = scene .createNode ("Rectangle2D");
60
+
61
+ textureNode .url = new X3D .MFString (this .getURL (scene .worldURL));
62
+ textureNode .repeatS = false;
63
+ textureNode .repeatT = false;
64
+
65
+ await textureNode .getValue () .loading ();
66
+
67
+ appearanceNode .texture = textureNode;
68
+
69
+ rectangleNode .size .x = textureNode .getValue () .getWidth () / 72 * 0.0254;
70
+ rectangleNode .size .y = textureNode .getValue () .getHeight () / 72 * 0.0254;
71
+
72
+ shapeNode .appearance = appearanceNode;
73
+ shapeNode .geometry = rectangleNode;
74
+
75
+ transformNode .children .push (shapeNode);
76
+
77
+ scene .rootNodes .push (transformNode);
78
+
79
+ // Name
80
+
81
+ const
82
+ worldURL = new URL (scene .worldURL),
83
+ name = worldURL .pathname .match (/([^\/]+)\.[^.]+$/);
84
+
85
+ if (name)
86
+ {
87
+ textureNode .description = decodeURIComponent (name [1]);
88
+
89
+ scene .addNamedNode (this .sanitizeName (decodeURIComponent (name [1])), transformNode);
90
+ }
91
+
92
+ return scene;
93
+ }
94
+
95
+ getURL (worldURL)
96
+ {
97
+ try
98
+ {
99
+ return encodeURIComponent (path .basename (url .fileURLToPath (worldURL)));
100
+ }
101
+ catch
102
+ {
103
+ return worldURL;
104
+ }
105
+ }
106
+ }
107
+
108
+ module .exports = ImageParser;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ const
4
+ X3D = require ("../X3D"),
5
+ url = require ("url"),
6
+ path = require ("path");
7
+
8
+ class VideoParser extends X3D .X3DParser
9
+ {
10
+ constructor (scene)
11
+ {
12
+ super (scene);
13
+ }
14
+
15
+ getEncoding ()
16
+ {
17
+ return "ARRAY_BUFFER";
18
+ }
19
+
20
+ setInput (input)
21
+ { }
22
+
23
+ isValid ()
24
+ {
25
+ const worldURL = new URL (this .getScene () .worldURL);
26
+
27
+ if (!worldURL .pathname .match (/\.(?:mp4|webm|ogv)$/i))
28
+ return;
29
+
30
+ return true;
31
+ }
32
+
33
+ parseIntoScene (resolve, reject)
34
+ {
35
+ this .video ()
36
+ .then (resolve)
37
+ .catch (reject);
38
+ }
39
+
40
+ async video ()
41
+ {
42
+ const
43
+ browser = this .getBrowser (),
44
+ scene = this .getScene ();
45
+
46
+ scene .setEncoding ("VIDEO");
47
+ scene .setProfile (browser .getProfile ("Interchange"));
48
+ scene .addComponent (browser .getComponent ("Geometry2D", 1));
49
+ scene .addComponent (browser .getComponent ("Sound", 1));
50
+
51
+ await this .loadComponents ();
52
+
53
+ // Rectangle
54
+
55
+ const
56
+ transformNode = scene .createNode ("Transform"),
57
+ shapeNode = scene .createNode ("Shape"),
58
+ appearanceNode = scene .createNode ("Appearance"),
59
+ textureNode = scene .createNode ("MovieTexture"),
60
+ rectangleNode = scene .createNode ("Rectangle2D"),
61
+ soundNode = scene .createNode ("Sound");
62
+
63
+ textureNode .url = new X3D .MFString (this .getURL (scene .worldURL));
64
+ textureNode .loop = true;
65
+ textureNode .repeatS = false;
66
+ textureNode .repeatT = false;
67
+
68
+ await textureNode .getValue () .loading ();
69
+
70
+ appearanceNode .texture = textureNode;
71
+
72
+ rectangleNode .size .x = textureNode .getValue () .getWidth () / 72 * 0.0254;
73
+ rectangleNode .size .y = textureNode .getValue () .getHeight () / 72 * 0.0254;
74
+
75
+ shapeNode .appearance = appearanceNode;
76
+ shapeNode .geometry = rectangleNode;
77
+
78
+ soundNode .source = textureNode;
79
+
80
+ transformNode .children .push (shapeNode, soundNode);
81
+
82
+ scene .rootNodes .push (transformNode);
83
+
84
+ // Name
85
+
86
+ const
87
+ worldURL = new URL (scene .worldURL),
88
+ name = worldURL .pathname .match (/([^\/]+)\.[^.]+$/);
89
+
90
+ if (name)
91
+ {
92
+ textureNode .description = decodeURIComponent (name [1]);
93
+
94
+ scene .addNamedNode (this .sanitizeName (decodeURIComponent (name [1])), transformNode);
95
+ }
96
+
97
+ return scene;
98
+ }
99
+
100
+ getURL (worldURL)
101
+ {
102
+ try
103
+ {
104
+ return encodeURIComponent (path .basename (url .fileURLToPath (worldURL)));
105
+ }
106
+ catch
107
+ {
108
+ return worldURL;
109
+ }
110
+ }
111
+ }
112
+
113
+ module .exports = VideoParser;
@@ -549,9 +549,6 @@ tr.disabled ~ tr > td > div {
549
549
  background-color: var(--system-gray7);
550
550
  }
551
551
 
552
- #secondary-toolbar {
553
- }
554
-
555
552
  /* Dialog */
556
553
 
557
554
  .dialog ::selection {
@@ -1010,13 +1007,15 @@ body.dark .ui-widget .library-list .component {
1010
1007
 
1011
1008
  /* Outline Editor */
1012
1009
 
1013
- .outline-editor {
1014
- }
1015
-
1016
1010
  .scene-graph .material-symbols-outlined {
1017
1011
  font-size: var(--font-size);
1018
1012
  position: relative;
1019
1013
  top: 2.5px;
1014
+ color: var(--system-blue);
1015
+ }
1016
+
1017
+ .scene-graph .material-symbols-outlined:hover {
1018
+ color: var(--system-gray0);
1020
1019
  }
1021
1020
 
1022
1021
  .scene-graph .hidden {
@@ -1162,7 +1161,6 @@ body.dark .ui-widget .library-list .component {
1162
1161
  position: relative;
1163
1162
  top: 4px;
1164
1163
  margin-left: 10px;
1165
- color: black;
1166
1164
  font-variation-settings: 'GRAD' 200;
1167
1165
  }
1168
1166
 
@@ -1319,7 +1317,11 @@ body.dark .ui-widget .library-list .component {
1319
1317
  }
1320
1318
 
1321
1319
  .scene-graph .button.off {
1322
- color: var(--text-color);
1320
+ color: var(--system-gray1);
1321
+ }
1322
+
1323
+ .scene-graph .button.off:hover {
1324
+ color: var(--system-gray0);
1323
1325
  }
1324
1326
 
1325
1327
  /* Spectrum Color Picker */
@@ -549,9 +549,6 @@ tr.disabled ~ tr > td > div {
549
549
  background-color: var(--system-gray7);
550
550
  }
551
551
 
552
- #secondary-toolbar {
553
- }
554
-
555
552
  /* Dialog */
556
553
 
557
554
  .dialog ::selection {
@@ -1010,13 +1007,15 @@ body.dark .ui-widget .library-list .component {
1010
1007
 
1011
1008
  /* Outline Editor */
1012
1009
 
1013
- .outline-editor {
1014
- }
1015
-
1016
1010
  .scene-graph .material-symbols-outlined {
1017
1011
  font-size: var(--font-size);
1018
1012
  position: relative;
1019
1013
  top: 2.5px;
1014
+ color: var(--system-blue);
1015
+ }
1016
+
1017
+ .scene-graph .material-symbols-outlined:hover {
1018
+ color: var(--system-gray0);
1020
1019
  }
1021
1020
 
1022
1021
  .scene-graph .hidden {
@@ -1162,7 +1161,6 @@ body.dark .ui-widget .library-list .component {
1162
1161
  position: relative;
1163
1162
  top: 4px;
1164
1163
  margin-left: 10px;
1165
- color: black;
1166
1164
  font-variation-settings: 'GRAD' 200;
1167
1165
  }
1168
1166
 
@@ -1319,7 +1317,11 @@ body.dark .ui-widget .library-list .component {
1319
1317
  }
1320
1318
 
1321
1319
  .scene-graph .button.off {
1322
- color: var(--text-color);
1320
+ color: var(--system-gray1);
1321
+ }
1322
+
1323
+ .scene-graph .button.off:hover {
1324
+ color: var(--system-gray0);
1323
1325
  }
1324
1326
 
1325
1327
  /* Spectrum Color Picker */