sunrize 1.7.4 → 1.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sunrize",
3
3
  "productName": "Sunrize X3D Editor",
4
- "version": "1.7.4",
4
+ "version": "1.7.6",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "start": "electron .",
16
16
  "development": "SUNRISE_ENVIRONMENT=DEVELOPMENT electron .",
17
17
  "release": "node build/release.js",
18
- "x3duom": "sh build/x3duom.sh",
18
+ "X3DUOM": "sh build/X3DUOM.sh",
19
19
  "download": "node build/download.js",
20
20
  "premake": "npm i -D electron",
21
21
  "make": "env PATH=\"$(pwd)/build/wine-proxy:$PATH\" electron-forge make",
@@ -109,7 +109,7 @@
109
109
  "string-similarity": "^4.0.4",
110
110
  "tweakpane": "^3.1.10",
111
111
  "update-electron-app": "^3.0.0",
112
- "x_ite": "^10.0.2"
112
+ "x_ite": "^10.0.4"
113
113
  },
114
114
  "config": {
115
115
  "forge": {
@@ -154,6 +154,13 @@ module .exports = class Document extends Interface
154
154
  .on ("mousedown", event => this .onmousedown (event))
155
155
  .on ("mouseup", event => this .onmouseup (event));
156
156
 
157
+ // Load components.
158
+
159
+ await this .browser .loadComponents (this .browser .getProfile ("Full"),
160
+ this .browser .getComponent ("X_ITE"));
161
+
162
+ this .browser .updateConcreteNode (require ("../Components/Grouping/StaticGroup"));
163
+
157
164
  // Restore
158
165
 
159
166
  await this .restoreFile ();
@@ -313,10 +320,6 @@ module .exports = class Document extends Interface
313
320
 
314
321
  async restoreFile ()
315
322
  {
316
- await this .browser .loadComponents (this .browser .getComponent ("Grouping"));
317
-
318
- this .browser .updateConcreteNode (require ("../Components/Grouping/StaticGroup"));
319
-
320
323
  if (this .fileId)
321
324
  {
322
325
  const contents = this .config .global .addNameSpace ("unsaved.") [this .fileId];
@@ -566,7 +569,7 @@ Viewpoint {
566
569
  if (this .activeElementIsInputOrOutput ())
567
570
  return;
568
571
 
569
- this .sidebar .outlineEditor .copyNodes ();
572
+ this .sidebar .outlineEditor .copyNodes (true);
570
573
  return false;
571
574
  }
572
575
 
@@ -1,11 +1,12 @@
1
1
  const
2
2
  $ = require ("jquery"),
3
3
  fs = require ("fs"),
4
- path = require ("path");
4
+ path = require ("path"),
5
+ X3D = require ("../X3D");
5
6
 
6
7
  const
7
- X3DUOM = $($.parseXML (fs .readFileSync (path .join (__dirname, "..", "assets", "x3duom.xml"), "utf-8"))),
8
- X_ITE = $($.parseXML (fs .readFileSync (path .join (__dirname, "..", "assets", "x3duom-x_ite.xml"), "utf-8")));
8
+ X3DUOM = $($.parseXML (fs .readFileSync (path .join (__dirname, "..", "assets", "X3DUOM.xml"), "utf-8"))),
9
+ X_ITE = $($.parseXML (fs .readFileSync (X3D .X3DUOM_PATH, "utf-8")));
9
10
 
10
11
  X3DUOM .find ("ConcreteNodes") .append (X_ITE .find ("ConcreteNode"));
11
12
 
@@ -95,6 +95,7 @@ module .exports = new class BrowserFrame extends Dialog
95
95
 
96
96
  this .connect (Editor .getWorldInfo (this .browser .currentScene));
97
97
  this .updateInputs ();
98
+ this .onresize ();
98
99
  }
99
100
 
100
101
  connect (worldInfoNode)
@@ -2,13 +2,12 @@
2
2
 
3
3
  const
4
4
  $ = require ("jquery"),
5
+ StringSimilarity = require ("string-similarity"),
5
6
  X3D = require ("../X3D"),
6
7
  Dialog = require ("../Controls/Dialog"),
7
8
  Editor = require ("../Undo/Editor"),
8
9
  UndoManager = require ("../Undo/UndoManager"),
9
- Primitives = require ("./Primitives"),
10
- StringSimilarity = require ("string-similarity"),
11
- Traverse = require("../Application/Traverse"),
10
+ Traverse = require ("../Application/Traverse"),
12
11
  _ = require ("../Application/GetText");
13
12
 
14
13
  module .exports = new class Library extends Dialog
@@ -17,6 +16,12 @@ module .exports = new class Library extends Dialog
17
16
  {
18
17
  super ("Sunrize.Library.");
19
18
 
19
+ this .panes = [
20
+ new (require ("./NodesLibrary")) (this),
21
+ new (require ("./PrimitivesLibrary")) (this),
22
+ new (require ("./MaterialsLibrary")) (this),
23
+ ];
24
+
20
25
  this .setup ();
21
26
  }
22
27
 
@@ -27,7 +32,7 @@ module .exports = new class Library extends Dialog
27
32
  // Set default config values.
28
33
 
29
34
  this .config .file .setDefaultValues ({
30
- type: "NODES",
35
+ type: this .panes [0] .id,
31
36
  });
32
37
 
33
38
  // Add class.
@@ -41,7 +46,7 @@ module .exports = new class Library extends Dialog
41
46
  .addClass ("library-input")
42
47
  .attr ("placeholder", _("Search a node"))
43
48
  .on ("keydown", event => this .enter (event))
44
- .on ("keyup", () => this .update ());
49
+ .on ("keyup", () => this .filter ());
45
50
 
46
51
  // Buttons
47
52
 
@@ -49,19 +54,15 @@ module .exports = new class Library extends Dialog
49
54
  .appendTo (this .element)
50
55
  .addClass ("library-buttons");
51
56
 
52
- this .nodesButton = $("<span></span>")
53
- .appendTo (this .buttons)
54
- .addClass ("library-button")
55
- .data ("type", "NODES")
56
- .text (_("Nodes"))
57
- .on ("click", () => this .button (this .nodesButton));
58
-
59
- this .primitivesButton = $("<span></span>")
60
- .appendTo (this .buttons)
61
- .addClass ("library-button")
62
- .data ("type", "PRIMITIVES")
63
- .text (_("Primitives"))
64
- .on ("click", () => this .button (this .primitivesButton));
57
+ for (const pane of this .panes)
58
+ {
59
+ const button = $("<span></span>")
60
+ .appendTo (this .buttons)
61
+ .addClass ("library-button")
62
+ .data ("type", pane .id)
63
+ .text (_(pane .description))
64
+ .on ("click", () => this .button (button));
65
+ }
65
66
 
66
67
  // Output
67
68
 
@@ -69,33 +70,23 @@ module .exports = new class Library extends Dialog
69
70
  .appendTo (this .element)
70
71
  .addClass ("library-output");
71
72
 
72
- this .list = $("<ul></ul>")
73
- .appendTo (this .output)
74
- .addClass ("library-list");
75
-
76
73
  // Configure list type.
77
74
 
78
- switch (this .config .file .type)
79
- {
80
- case "NODES":
81
- this .button (this .nodesButton);
82
- break;
83
- case "PRIMITIVES":
84
- this .button (this .primitivesButton);
85
- break;
86
- }
75
+ const button = [... this .buttons .children ()]
76
+ .find (button => $(button) .data ("type") === this .config .file .type);
77
+
78
+ if (button)
79
+ this .button ($(button));
87
80
  }
88
81
 
89
82
  async open (executionContext, node, field)
90
83
  {
91
- await this .browser .loadComponents (this .browser .getProfile ("Full"),
92
- this .browser .getComponent ("X_ITE"));
93
-
94
84
  this .executionContext = executionContext;
95
85
  this .node = node;
96
86
  this .field = field;
97
87
 
98
88
  super .open ();
89
+ this .panes .forEach (pane => pane .open ());
99
90
  this .update ();
100
91
  this .input .trigger ("focus");
101
92
  }
@@ -109,265 +100,94 @@ module .exports = new class Library extends Dialog
109
100
  button .addClass ("active");
110
101
 
111
102
  this .update ();
103
+ this .filter ();
112
104
  }
113
105
 
114
- enter (event)
115
- {
116
- if (event .key !== "Enter")
117
- return;
118
-
119
- const nodes = Array .from (this .list .find (".node"), element => $(element));
120
-
121
- if (!nodes .length)
122
- return;
123
-
124
- try
125
- {
126
- const
127
- input = this .config .file .type === "NODES" ? this .input .val () .toUpperCase () .trim () : "",
128
- ConcreteNode = this .browser .getConcreteNode (X3D .HTMLSupport .getNodeTypeName (input));
129
-
130
- this .createNode (ConcreteNode .typeName, ConcreteNode .componentInfo .name);
131
- }
132
- catch
133
- {
134
- nodes .sort ((a, b) => a .attr ("similarity") - b .attr ("similarity"))
135
- .pop ()
136
- .trigger ("dblclick");
137
- }
138
- }
139
-
140
- update ()
141
- {
142
- switch (this .config .file .type)
143
- {
144
- case "NODES":
145
- this .updateNodes ();
146
- break;
147
- case "PRIMITIVES":
148
- this .updatePrimitives ();
149
- break;
150
- }
151
- }
152
-
153
- getProtos (executionContext = this .executionContext, protos = new Map (), outerNode)
154
- {
155
- if (!executionContext)
156
- return protos;
157
-
158
- for (const proto of executionContext .protos)
159
- {
160
- if (proto === outerNode)
161
- break;
162
-
163
- if (protos .has (proto .name))
164
- continue;
165
-
166
- protos .set (proto .name, proto);
167
- }
168
-
169
- for (const proto of executionContext .externprotos)
170
- {
171
- if (proto === outerNode)
172
- break;
173
-
174
- if (protos .has (proto .name))
175
- continue;
176
-
177
- protos .set (proto .name, proto);
178
- }
179
-
180
- if (!(executionContext instanceof X3D .X3DScene))
181
- this .getProtos (executionContext .getExecutionContext (), protos, executionContext .getOuterNode ());
182
-
183
- return protos;
184
- }
185
-
186
- updateNodes ()
106
+ filter ()
187
107
  {
188
- const cmp = (a, b) => (a > b) - (a < b);
189
-
190
- // Clear list.
191
-
192
- this .list .empty ();
193
-
194
108
  const input = this .input .val () .toLowerCase () .trim ();
195
109
 
196
- // Get protos.
197
-
198
- const protoFilter = input
199
- ? proto => StringSimilarity .compareTwoStrings (proto .name .toLowerCase (), input) > 0.4
200
- : () => true;
201
-
202
- const protos = Array .from (this .getProtos () .values ())
203
- .filter (protoFilter)
204
- .sort ((a, b) => cmp (a .name, b .name));
205
-
206
- // Get supported nodes.
110
+ if (input)
111
+ {
112
+ const elements = Array .from (this .output .find (".node, .component"), e => $(e));
207
113
 
208
- const nodeFilter = input
209
- ? ConcreteNode => StringSimilarity .compareTwoStrings (ConcreteNode .typeName .toLowerCase (), input) > 0.4
210
- : () => true;
114
+ // Hide nodes.
211
115
 
212
- const nodes = [... this .browser .getConcreteNodes ()]
213
- .filter (nodeFilter)
214
- .sort ((a, b) => cmp (a .typeName, b .typeName))
215
- .sort ((a, b) => cmp (a .componentInfo .name, b .componentInfo .name));
116
+ for (const node of elements)
117
+ {
118
+ if (!node .hasClass ("node"))
119
+ continue;
216
120
 
217
- // Create list for proto elements
121
+ const similarity = StringSimilarity .compareTwoStrings (node .text () .toLowerCase (), input);
218
122
 
219
- if (protos .length)
220
- {
221
- $("<li></li>")
222
- .addClass ("component")
223
- .attr ("name", "prototypes")
224
- .text ("Prototypes")
225
- .appendTo (this .list);
123
+ node .data ("similarity", similarity);
226
124
 
227
- for (const proto of protos)
228
- {
229
- $("<li></li>")
230
- .addClass ("node")
231
- .text (proto .name)
232
- .attr ("similarity", StringSimilarity .compareTwoStrings (proto .name .toLowerCase (), input))
233
- .appendTo (this .list)
234
- .on ("dblclick", () => this .createProto (proto));
125
+ if (similarity > 0.4)
126
+ node .removeClass ("hidden");
127
+ else
128
+ node .addClass ("hidden");
235
129
  }
236
- }
237
130
 
238
- // Create list for nodes elements.
131
+ // Hide components with only hidden nodes.
239
132
 
240
- let componentName = "";
133
+ let
134
+ nodes = 0,
135
+ hidden = 0;
241
136
 
242
- for (const node of nodes)
243
- {
244
- if (node .componentInfo .name !== componentName)
137
+ for (const element of elements .reverse ())
245
138
  {
246
- componentName = node .componentInfo .name;
139
+ if (element .hasClass ("component"))
140
+ {
141
+ if (hidden === nodes)
142
+ element .addClass ("hidden")
143
+ else
144
+ element .removeClass ("hidden");
247
145
 
248
- $("<li></li>")
249
- .addClass ("component")
250
- .attr ("name", node .componentInfo .name)
251
- .text (this .browser .getSupportedComponents () .get (node .componentInfo .name) .title)
252
- .appendTo (this .list);
146
+ nodes = 0,
147
+ hidden = 0;
148
+ }
149
+ else if (element .hasClass ("node"))
150
+ {
151
+ nodes += 1;
152
+ hidden += element .hasClass ("hidden");
153
+ }
253
154
  }
254
-
255
- $("<li></li>")
256
- .addClass ("node")
257
- .text (node .typeName)
258
- .attr ("componentName", node .componentInfo .name)
259
- .attr ("similarity", StringSimilarity .compareTwoStrings (node .typeName .toLowerCase (), input))
260
- .appendTo (this .list)
261
- .on ("dblclick", () => this .createNode (node .typeName, node .componentInfo .name));
262
155
  }
263
- }
264
-
265
- async createNode (typeName, componentName)
266
- {
267
- UndoManager .shared .beginUndo (_("Create Node %s"), typeName);
268
-
269
- await Editor .addComponent (this .executionContext, componentName);
270
-
271
- const node = this .executionContext .createNode (typeName);
272
-
273
- this .addNode (node);
274
-
275
- UndoManager .shared .endUndo ();
276
- }
277
-
278
- async createProto (proto)
279
- {
280
- UndoManager .shared .beginUndo (_("Create Proto Instance %s"), proto .name);
281
-
282
- const node = proto .createInstance (this .executionContext);
283
-
284
- this .addNode (node);
285
-
286
- UndoManager .shared .endUndo ();
287
- }
288
-
289
- addNode (node)
290
- {
291
- const field = this .field ?? $.try (() => this .node ?.getField (node .getValue () .getContainerField ()));
292
-
293
- switch (field ?.getType ())
156
+ else
294
157
  {
295
- case X3D .X3DConstants .SFNode:
296
- {
297
- Editor .setFieldValue (this .executionContext, this .node, field, node);
298
- break;
299
- }
300
- case X3D .X3DConstants .MFNode:
301
- {
302
- Editor .insertValueIntoArray (this .executionContext, this .node, field, field .length, node);
303
- break;
304
- }
305
- default:
306
- {
307
- Editor .insertValueIntoArray (this .executionContext, this .executionContext, this .executionContext .rootNodes, this .executionContext .rootNodes .length, node);
308
- break;
309
- }
158
+ this .output .find (".node, .component") .removeClass ("hidden");
310
159
  }
311
-
312
- node = node .getValue ();
313
-
314
- requestAnimationFrame (() =>
315
- {
316
- const outlineEditor = require ("../Application/Window") .sidebar .outlineEditor;
317
-
318
- outlineEditor .expandTo (node);
319
- outlineEditor .selectNodeElement ($(`.node[node-id=${node .getId ()}]`));
320
- });
321
160
  }
322
161
 
323
- updatePrimitives ()
162
+ enter (event)
324
163
  {
325
- const cmp = (a, b) => (a > b) - (a < b);
326
-
327
- // Clear list.
328
-
329
- this .list .empty ();
330
-
331
- // Make filter.
164
+ if (event .key !== "Enter")
165
+ return;
332
166
 
333
- const input = this .input .val () .toLowerCase () .trim ();
167
+ const input = this .input .val () .trim () .toLowerCase ();
334
168
 
335
- if (input)
336
- var filter = (object) => StringSimilarity .compareTwoStrings (object .typeName .toLowerCase (), input) > 0.4;
337
- else
338
- var filter = () => true;
169
+ if (!input)
170
+ return;
339
171
 
340
- // Get primitives.
172
+ const nodes = Array .from (this .output .find (".node:not(.hidden)"), element => $(element));
341
173
 
342
- const nodes = Primitives
343
- .filter (filter)
344
- .sort ((a, b) => cmp (a .typeName, b .typeName))
345
- .sort ((a, b) => cmp (a .componentInfo .name, b .componentInfo .name));
174
+ if (!nodes .length)
175
+ return;
346
176
 
347
- // Create list elements.
177
+ const node = nodes .find (node => node .text () .toLowerCase () === input)
178
+ ?? nodes .sort ((a, b) => a .data ("similarity") - b .data ("similarity")) .at (-1);
348
179
 
349
- let componentName = "";
180
+ node .trigger ("dblclick");
181
+ }
350
182
 
351
- for (const node of nodes)
352
- {
353
- if (node .componentInfo .name !== componentName)
354
- {
355
- componentName = node .componentInfo .name;
183
+ update ()
184
+ {
185
+ this .output .children () .detach ();
356
186
 
357
- $("<li></li>")
358
- .addClass ("component")
359
- .text (node .componentInfo .name)
360
- .appendTo (this .list);
361
- }
187
+ const pane = this .panes
188
+ .find (pane => pane .id === this .config .file .type);
362
189
 
363
- $("<li></li>")
364
- .addClass ("node")
365
- .text (node .typeName)
366
- .attr ("x3dSyntax", node .x3dSyntax)
367
- .attr ("similarity", StringSimilarity .compareTwoStrings (node .typeName .toLowerCase (), input))
368
- .appendTo (this .list)
369
- .on ("dblclick", () => this .importX3D (node .typeName, node .x3dSyntax));
370
- }
190
+ pane .update ();
371
191
  }
372
192
 
373
193
  async importX3D (typeName, x3dSyntax)
@@ -420,12 +240,16 @@ module .exports = new class Library extends Dialog
420
240
 
421
241
  UndoManager .shared .endUndo ();
422
242
 
423
- requestAnimationFrame (() =>
424
- {
425
- const outlineEditor = require ("../Application/Window") .sidebar .outlineEditor;
243
+ await this .expandToAndSelectNode (node);
244
+ }
426
245
 
427
- outlineEditor .expandTo (node);
428
- outlineEditor .selectNodeElement ($(`.node[node-id=${node .getId ()}]`));
429
- });
246
+ async expandToAndSelectNode (node)
247
+ {
248
+ await this .browser .nextFrame ();
249
+
250
+ const outlineEditor = require ("../Application/Window") .sidebar .outlineEditor;
251
+
252
+ outlineEditor .expandTo (node);
253
+ outlineEditor .selectNodeElement ($(`.node[node-id=${node .getId ()}]`));
430
254
  }
431
255
  }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ module .exports = class LibraryPanel
4
+ {
5
+ #library;
6
+
7
+ constructor (library)
8
+ {
9
+ this .#library = library;
10
+ }
11
+
12
+ get browser ()
13
+ {
14
+ return this .#library .browser;
15
+ }
16
+
17
+ get executionContext ()
18
+ {
19
+ return this .#library .executionContext;
20
+ }
21
+
22
+ get node ()
23
+ {
24
+ return this .#library .node;
25
+ }
26
+
27
+ get field ()
28
+ {
29
+ return this .#library .field;
30
+ }
31
+
32
+ get element ()
33
+ {
34
+ return this .#library .element;
35
+ }
36
+
37
+ get output ()
38
+ {
39
+ return this .#library .output;
40
+ }
41
+
42
+ get importX3D ()
43
+ {
44
+ return this .#library .importX3D;
45
+ }
46
+
47
+ get expandToAndSelectNode ()
48
+ {
49
+ return this .#library .expandToAndSelectNode;
50
+ }
51
+
52
+ open () { }
53
+ };