sunrize 1.11.3 → 1.11.5

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.3",
4
+ "version": "1.11.5",
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.41",
92
92
  "capitalize": "^2.0.4",
93
93
  "console": "^0.7.2",
94
- "electron": "^38.4.0",
94
+ "electron": "^39.0.0",
95
95
  "electron-prompt": "^1.7.0",
96
96
  "electron-squirrel-startup": "^1.0.1",
97
97
  "electron-tabs": "^1.0.4",
@@ -100,7 +100,7 @@
100
100
  "jquery-ui-dist": "^1.13.3",
101
101
  "jstree": "^3.3.17",
102
102
  "material-icons": "^1.13.14",
103
- "material-symbols": "^0.38.0",
103
+ "material-symbols": "^0.39.1",
104
104
  "md5": "^2.3.0",
105
105
  "mime-types": "^3.0.1",
106
106
  "monaco-editor": "^0.54.0",
@@ -110,7 +110,7 @@
110
110
  "string-similarity": "^4.0.4",
111
111
  "tweakpane": "^3.1.10",
112
112
  "update-electron-app": "^3.1.1",
113
- "x_ite": "^12.1.3",
113
+ "x_ite": "^12.1.5",
114
114
  "x3d-traverse": "^1.0.22"
115
115
  }
116
116
  }
@@ -55,8 +55,9 @@ module .exports = class Document extends Interface
55
55
  */
56
56
  async initialize ()
57
57
  {
58
- $("html") .attr ("platform", process .platform);
59
- $("body") .addClass ("modal");
58
+ $("html")
59
+ .attr ("platform", process .platform)
60
+ .addClass ("read-only");
60
61
 
61
62
  // Actions
62
63
 
@@ -192,7 +193,7 @@ module .exports = class Document extends Interface
192
193
  await this .restoreFile ();
193
194
 
194
195
  if (!this .isInitialScene)
195
- $("body") .removeClass ("modal");
196
+ $("html") .removeClass ("read-only");
196
197
  }
197
198
 
198
199
  configure ()
@@ -11,23 +11,12 @@ const
11
11
  module .exports = class Console extends Interface
12
12
  {
13
13
  HISTORY_MAX = 100;
14
- CONSOLE_MAX = 1000;
15
-
16
- logLevels = [
17
- "debug",
18
- "log",
19
- "warn",
20
- "error",
21
- ];
22
-
23
- logClasses = ["", "", "filled", "filled"];
24
14
 
25
15
  constructor (element)
26
16
  {
27
17
  super (`Sunrize.Console.${element .attr ("id")}.`);
28
18
 
29
19
  this .suspendConsole = false;
30
- this .messageTime = 0;
31
20
  this .historyIndex = 0;
32
21
  this .history = [ ];
33
22
  this .addMessageCallback = this .addMessage .bind (this);
@@ -124,7 +113,7 @@ module .exports = class Console extends Interface
124
113
  // Input
125
114
 
126
115
  this .textarea = $("<textarea></textarea>")
127
- .attr ("placeholder", _("Evaluate X3D Script code here, e.g. type `Browser.name`."))
116
+ .attr ("placeholder", _("Evaluate Script node code here, e.g. type `Browser.name`."))
128
117
  .attr ("tabindex", 0)
129
118
  .on ("keydown", event => this .onkeydown (event))
130
119
  .on ("keyup", event => this .onkeyup (event))
@@ -175,6 +164,8 @@ module .exports = class Console extends Interface
175
164
  this .scriptNode .setup ();
176
165
  }
177
166
 
167
+ CONSOLE_MAX = 1000;
168
+
178
169
  // Add strings to exclude here:
179
170
  excludes = [
180
171
  "The vm module of Node.js is unsupported",
@@ -184,41 +175,31 @@ module .exports = class Console extends Interface
184
175
  // "Invalid asm.js: Invalid member of stdlib",
185
176
  ];
186
177
 
178
+ messageTime = 0;
179
+
180
+ logLevels = [
181
+ "debug",
182
+ "log",
183
+ "warn",
184
+ "error",
185
+ ];
186
+
187
187
  addMessage (event, level, sourceId, line, message)
188
188
  {
189
189
  if (this .excludes .some (exclude => message .includes (exclude)))
190
190
  return;
191
191
 
192
- const
193
- classes = [this .logLevels [level] ?? "log", this .logClasses [level]],
194
- title = sourceId ? `${sourceId}:${line}`: "";
195
-
196
- const text = $(message .split ("\n")
197
- .map (line => $("<p></p>")
198
- .addClass (classes)
199
- .attr ("title", title)
200
- .text (line)
201
- .get (0)));
192
+ const text = $("<p></p>")
193
+ .addClass (this .logLevels [level] ?? "log")
194
+ .attr ("title", sourceId ? `${sourceId}:${line}`: "")
195
+ .text (message);
202
196
 
203
- if (this .messageTime && performance .now () - this .messageTime > 1000)
197
+ if (performance .now () - this .messageTime > 1000)
204
198
  this .output .append ($("<p></p>") .addClass ("splitter"));
205
199
 
206
200
  this .messageTime = performance .now ();
207
201
 
208
- const
209
- children = this .output .children (),
210
- last = children .last ();
211
-
212
- if (last .hasClass (this .logLevels [level]))
213
- {
214
- last .css ("margin-bottom", "0");
215
- text .css ("margin-top", "0");
216
- last .css ("border-bottom", "none");
217
- text .css ("border-top", "none");
218
- }
219
-
220
- children .slice (0, Math .max (children .length - this .CONSOLE_MAX, 0)) .remove ();
221
-
202
+ this .output .children (`:not(:nth-last-child(-n+${this .CONSOLE_MAX}))`) .remove ();
222
203
  this .output .append (text);
223
204
  this .output .scrollTop (this .output .prop ("scrollHeight"));
224
205
 
@@ -368,6 +368,7 @@ module .exports = class OutlineView extends Interface
368
368
  expandSceneSubtreeComplete (specialElements, elements)
369
369
  {
370
370
  this .requestUpdateRouteGraph ();
371
+ this .updateQtips ();
371
372
 
372
373
  // Reopen externprotos, protos, imported, exported nodes.
373
374
 
@@ -846,7 +847,8 @@ module .exports = class OutlineView extends Interface
846
847
 
847
848
  expandNodeComplete (protos, scenes, elements)
848
849
  {
849
- this .requestUpdateRouteGraph ()
850
+ this .requestUpdateRouteGraph ();
851
+ this .updateQtips ();
850
852
 
851
853
  // Auto expand SFNodes
852
854
 
@@ -854,12 +856,12 @@ module .exports = class OutlineView extends Interface
854
856
  {
855
857
  const
856
858
  element = $(e),
857
- field = this .getField (element)
859
+ field = this .getField (element);
858
860
 
859
861
  if (field .getValue ())
860
862
  {
861
- element .data ("auto-expand", true)
862
- element .jstree ("open_node", element)
863
+ element .data ("auto-expand", true);
864
+ element .jstree ("open_node", element);
863
865
  }
864
866
  }
865
867
 
@@ -869,12 +871,12 @@ module .exports = class OutlineView extends Interface
869
871
  {
870
872
  const
871
873
  element = $(e),
872
- field = this .getField (element)
874
+ field = this .getField (element);
873
875
 
874
876
  if (field .length && field .length <= this .autoExpandMaxChildren)
875
877
  {
876
- element .data ("auto-expand", true)
877
- element .jstree ("open_node", element)
878
+ element .data ("auto-expand", true);
879
+ element .jstree ("open_node", element);
878
880
  }
879
881
  }
880
882
 
@@ -884,11 +886,11 @@ module .exports = class OutlineView extends Interface
884
886
  {
885
887
  const
886
888
  element = $(e),
887
- node = this .getNode (element)
889
+ node = this .getNode (element);
888
890
 
889
891
  if (node .getUserData (_expanded) && element .jstree ("is_closed", element))
890
892
  {
891
- element .jstree ("open_node", element)
893
+ element .jstree ("open_node", element);
892
894
  }
893
895
  }
894
896
 
@@ -898,12 +900,12 @@ module .exports = class OutlineView extends Interface
898
900
  {
899
901
  const
900
902
  element = $(e),
901
- scene = this .getNode (element)
903
+ scene = this .getNode (element);
902
904
 
903
905
  if (scene .getUserData (_expanded) && element .jstree ("is_closed", element))
904
906
  {
905
- element .data ("auto-expand", true)
906
- element .jstree ("open_node", element)
907
+ element .data ("auto-expand", true);
908
+ element .jstree ("open_node", element);
907
909
  }
908
910
  }
909
911
 
@@ -913,12 +915,12 @@ module .exports = class OutlineView extends Interface
913
915
  {
914
916
  const
915
917
  element = $(e),
916
- field = this .getField (element)
918
+ field = this .getField (element);
917
919
 
918
920
  if (field .getUserData (_expanded) && element .jstree ("is_closed", element))
919
921
  {
920
- element .data ("auto-expand", true)
921
- element .jstree ("open_node", element)
922
+ element .data ("auto-expand", true);
923
+ element .jstree ("open_node", element);
922
924
  }
923
925
  }
924
926
  }
@@ -1862,7 +1864,7 @@ module .exports = class OutlineView extends Interface
1862
1864
  {
1863
1865
  const
1864
1866
  name = $(event .currentTarget),
1865
- element = $(event .currentTarget) .closest (".externproto, .proto, .node, .special", this .sceneGraph),
1867
+ element = name .closest (".externproto, .proto, .node, .imported-node, .exported-node", this .sceneGraph),
1866
1868
  node = this .objects .get (parseInt (element .attr ("node-id")));
1867
1869
 
1868
1870
  // Handle NULL node element.
@@ -1878,7 +1880,7 @@ module .exports = class OutlineView extends Interface
1878
1880
  {
1879
1881
  const
1880
1882
  name = $(event .currentTarget),
1881
- element = $(event .currentTarget) .closest (".field, .special", this .sceneGraph),
1883
+ element = name .closest (".field, .special", this .sceneGraph),
1882
1884
  node = this .objects .get (parseInt (element .attr ("node-id"))),
1883
1885
  field = this .objects .get (parseInt (element .attr ("field-id"))),
1884
1886
  fieldElement = X3DUOM .find (`ConcreteNode[name="${node .getTypeName ()}"] field[name="${field .getName ()}"]`);
@@ -2218,6 +2220,7 @@ module .exports = class OutlineView extends Interface
2218
2220
  }
2219
2221
 
2220
2222
  this .requestUpdateRouteGraph ();
2223
+ this .updateQtips ();
2221
2224
  }
2222
2225
 
2223
2226
  expandSFNode (parent, node, field, type, full)
@@ -2299,6 +2302,7 @@ module .exports = class OutlineView extends Interface
2299
2302
  }
2300
2303
 
2301
2304
  this .requestUpdateRouteGraph ();
2305
+ this .updateQtips ();
2302
2306
  }
2303
2307
 
2304
2308
  nodeIcons = new Map ([
@@ -2390,7 +2394,9 @@ module .exports = class OutlineView extends Interface
2390
2394
  // Expand children.
2391
2395
 
2392
2396
  child .show ();
2397
+
2393
2398
  this .requestUpdateRouteGraph ();
2399
+ this .updateQtips ();
2394
2400
  }
2395
2401
 
2396
2402
  onkeydownField (input, event)
@@ -2495,8 +2501,10 @@ module .exports = class OutlineView extends Interface
2495
2501
 
2496
2502
  // Expand children.
2497
2503
 
2498
- child .show ()
2499
- this .requestUpdateRouteGraph ()
2504
+ child .show ();
2505
+
2506
+ this .requestUpdateRouteGraph ();
2507
+ this .updateQtips ();
2500
2508
  }
2501
2509
 
2502
2510
  onkeydownArrayField (textarea, event)
@@ -2905,6 +2913,7 @@ module .exports = class OutlineView extends Interface
2905
2913
  element .jstree ("open_node", element);
2906
2914
 
2907
2915
  this .requestUpdateRouteGraph ();
2916
+ this .updateQtips ();
2908
2917
  }
2909
2918
 
2910
2919
  removeSubtree (element)
@@ -3716,6 +3725,7 @@ module .exports = class OutlineView extends Interface
3716
3725
  onresize ()
3717
3726
  {
3718
3727
  this .requestUpdateRouteGraph ();
3728
+ this .updateQtips ();
3719
3729
  }
3720
3730
 
3721
3731
  addFieldButtons (parent, child, node)
@@ -3819,6 +3829,11 @@ module .exports = class OutlineView extends Interface
3819
3829
  // Update route graph.
3820
3830
  }
3821
3831
 
3832
+ updateQtips ()
3833
+ {
3834
+ this .sceneGraph .find ("[data-hasqtip]") .qtip ?.("reposition");
3835
+ }
3836
+
3822
3837
  onDragStartExternProto () { }
3823
3838
 
3824
3839
  onDragStartProto () { }
@@ -2,6 +2,7 @@
2
2
 
3
3
  const
4
4
  $ = require ("jquery"),
5
+ electron = require ("electron"),
5
6
  capitalize = require ("capitalize"),
6
7
  Dialog = require ("../Controls/Dialog"),
7
8
  Tabs = require ("../Controls/Tabs"),
@@ -10,7 +11,6 @@ const
10
11
  Editor = require ("../Undo/Editor"),
11
12
  UndoManager = require ("../Undo/UndoManager"),
12
13
  _ = require ("../Application/GetText");
13
- const { height } = require("../Bits/X3DUOM");
14
14
 
15
15
  require ("../Fields");
16
16
 
@@ -472,6 +472,7 @@ module .exports = new class SceneProperties extends Dialog
472
472
  .attr ("placeholder", _("Insert meta key here."))
473
473
  .val (key) .on ("change", (event) => this .changeMetaData (event, key))))
474
474
  .append ($("<td></td>")
475
+ .addClass ("meta-value")
475
476
  .append ($("<input></input>")
476
477
  .attr ("index", 1)
477
478
  .attr ("placeholder", _("Insert meta value here."))
@@ -485,6 +486,27 @@ module .exports = new class SceneProperties extends Dialog
485
486
  .text ("delete_forever")
486
487
  .on ("click", (event) => this .removeMetaData (event, key))));
487
488
 
489
+ // Add Open Link in Browser button if it matches a link somewhere in value.
490
+ {
491
+ const
492
+ http = /(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))/,
493
+ match = value .match (http);
494
+
495
+ if (match)
496
+ {
497
+ const column = row .find ("input[index=1]") .parent ();
498
+
499
+ $("<span></span>")
500
+ .addClass ("open-link")
501
+ .attr ("title", _("Open link in web browser."))
502
+ .css ("font-size", "120%")
503
+ .addClass (["material-icons", "button"])
504
+ .text ("open_in_new")
505
+ .appendTo (column)
506
+ .on ("click", () => electron .shell .openExternal (match [1]));
507
+ }
508
+ }
509
+
488
510
  rows .push (row);
489
511
  }
490
512
 
@@ -139,6 +139,7 @@ module .exports = class ScriptEditor extends Interface
139
139
 
140
140
  // Setup.
141
141
 
142
+ this .addLanguages ();
142
143
  this .setup ();
143
144
  }
144
145
 
@@ -157,6 +158,178 @@ module .exports = class ScriptEditor extends Interface
157
158
  monaco .editor .setTheme (shouldUseDarkColors ? "vs-dark" : "vs-light");
158
159
  }
159
160
 
161
+ async addLanguages ()
162
+ {
163
+ const monaco = await this .getMonaco ();
164
+
165
+ const conf = {
166
+ comments: {
167
+ lineComment: '//',
168
+ blockComment: ['/*', '*/']
169
+ },
170
+ brackets: [
171
+ ['{', '}'],
172
+ ['[', ']'],
173
+ ['(', ')']
174
+ ],
175
+ autoClosingPairs: [
176
+ { open: '[', close: ']' },
177
+ { open: '{', close: '}' },
178
+ { open: '(', close: ')' },
179
+ { open: "'", close: "'", notIn: ['string', 'comment'] },
180
+ { open: '"', close: '"', notIn: ['string'] }
181
+ ],
182
+ surroundingPairs: [
183
+ { open: '{', close: '}' },
184
+ { open: '[', close: ']' },
185
+ { open: '(', close: ')' },
186
+ { open: '"', close: '"' },
187
+ { open: "'", close: "'" }
188
+ ]
189
+ };
190
+
191
+ const keywords = [
192
+ 'const', 'uniform', 'break', 'continue',
193
+ 'do', 'for', 'while', 'if', 'else', 'switch', 'case', 'in', 'out', 'inout', 'true', 'false',
194
+ 'invariant', 'discard', 'return', 'sampler2D', 'samplerCube', 'sampler3D', 'struct',
195
+ 'radians', 'degrees', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'pow', 'sinh', 'cosh', 'tanh', 'asinh', 'acosh', 'atanh',
196
+ 'exp', 'log', 'exp2', 'log2', 'sqrt', 'inversesqrt', 'abs', 'sign', 'floor', 'ceil', 'round', 'roundEven', 'trunc', 'fract', 'mod', 'modf',
197
+ 'min', 'max', 'clamp', 'mix', 'step', 'smoothstep', 'length', 'distance', 'dot', 'cross ',
198
+ 'determinant', 'inverse', 'normalize', 'faceforward', 'reflect', 'refract', 'matrixCompMult', 'outerProduct', 'transpose', 'lessThan ',
199
+ 'lessThanEqual', 'greaterThan', 'greaterThanEqual', 'equal', 'notEqual', 'any', 'all', 'not', 'packUnorm2x16', 'unpackUnorm2x16', 'packSnorm2x16', 'unpackSnorm2x16', 'packHalf2x16', 'unpackHalf2x16',
200
+ 'dFdx', 'dFdy', 'fwidth', 'textureSize', 'texture', 'textureProj', 'textureLod', 'textureGrad', 'texelFetch', 'texelFetchOffset',
201
+ 'textureProjLod', 'textureLodOffset', 'textureGradOffset', 'textureProjLodOffset', 'textureProjGrad', 'intBitsToFloat', 'uintBitsToFloat', 'floatBitsToInt', 'floatBitsToUint', 'isnan', 'isinf',
202
+ 'vec2', 'vec3', 'vec4', 'ivec2', 'ivec3', 'ivec4', 'uvec2', 'uvec3', 'uvec4', 'bvec2', 'bvec3', 'bvec4',
203
+ 'mat2', 'mat3', 'mat2x2', 'mat2x3', 'mat2x4', 'mat3x2', 'mat3x3', 'mat3x4', 'mat4x2', 'mat4x3', 'mat4x4', 'mat4',
204
+ 'float', 'int', 'uint', 'void', 'bool',
205
+ ];
206
+
207
+ const language = {
208
+ tokenPostfix: '.glsl',
209
+ // Set defaultToken to invalid to see what you do not tokenize yet
210
+ defaultToken: 'invalid',
211
+ keywords,
212
+ operators: [
213
+ '=',
214
+ '>',
215
+ '<',
216
+ '!',
217
+ '~',
218
+ '?',
219
+ ':',
220
+ '==',
221
+ '<=',
222
+ '>=',
223
+ '!=',
224
+ '&&',
225
+ '||',
226
+ '++',
227
+ '--',
228
+ '+',
229
+ '-',
230
+ '*',
231
+ '/',
232
+ '&',
233
+ '|',
234
+ '^',
235
+ '%',
236
+ '<<',
237
+ '>>',
238
+ '>>>',
239
+ '+=',
240
+ '-=',
241
+ '*=',
242
+ '/=',
243
+ '&=',
244
+ '|=',
245
+ '^=',
246
+ '%=',
247
+ '<<=',
248
+ '>>=',
249
+ '>>>='
250
+ ],
251
+ symbols: /[=><!~?:&|+\-*\/\^%]+/,
252
+ escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
253
+ integersuffix: /([uU](ll|LL|l|L)|(ll|LL|l|L)?[uU]?)/,
254
+ floatsuffix: /[fFlL]?/,
255
+ encoding: /u|u8|U|L/,
256
+
257
+ tokenizer: {
258
+ root: [
259
+ // identifiers and keywords
260
+ [
261
+ /[a-zA-Z_]\w*/,
262
+ {
263
+ cases: {
264
+ '@keywords': { token: 'keyword.$0' },
265
+ '@default': 'identifier'
266
+ }
267
+ }
268
+ ],
269
+
270
+ // Preprocessor directive (#define)
271
+ [/^\s*#\s*\w+/, 'keyword.directive'],
272
+
273
+ // Version
274
+ [/#version\s+\d+\s+es/, 'keyword.directive'],
275
+
276
+ // whitespace
277
+ { include: '@whitespace' },
278
+
279
+ // delimiters and operators
280
+ [/[{}()\[\]]/, '@brackets'],
281
+ [/@symbols/, {
282
+ cases: {
283
+ '@operators': 'operator',
284
+ '@default': ''
285
+ }
286
+ }],
287
+
288
+ // numbers
289
+ [/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
290
+ [/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'],
291
+ [/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'],
292
+ [/0[0-7']*[0-7](@integersuffix)/, 'number.octal'],
293
+ [/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'],
294
+ [/\d[\d']*\d(@integersuffix)/, 'number'],
295
+ [/\d(@integersuffix)/, 'number'],
296
+
297
+ // delimiter: after number because of .\d floats
298
+ [/[;,.]/, 'delimiter']
299
+ ],
300
+
301
+ comment: [
302
+ [/[^\/*]+/, 'comment'],
303
+ [/\/\*/, 'comment', '@push'],
304
+ ['\\*/', 'comment', '@pop'],
305
+ [/[\/*]/, 'comment']
306
+ ],
307
+
308
+ // Does it have strings?
309
+ string: [
310
+ [/[^\\"]+/, 'string'],
311
+ [/@escapes/, 'string.escape'],
312
+ [/\\./, 'string.escape.invalid'],
313
+ [/"/, {
314
+ token: 'string.quote',
315
+ bracket: '@close',
316
+ next: '@pop'
317
+ }]
318
+ ],
319
+
320
+ whitespace: [
321
+ [/[ \t\r\n]+/, 'white'],
322
+ [/\/\*/, 'comment', '@comment'],
323
+ [/\/\/.*$/, 'comment']
324
+ ]
325
+ }
326
+ };
327
+
328
+ monaco .languages .register ({ id: "glsl" });
329
+ monaco .languages .setMonarchTokensProvider ("glsl", language);
330
+ monaco .languages .setLanguageConfiguration ("glsl", conf);
331
+ }
332
+
160
333
  async setNode (node)
161
334
  {
162
335
  this .directOutputButton .hide ();
@@ -169,7 +342,7 @@ module .exports = class ScriptEditor extends Interface
169
342
  this .node ._loadState .removeFieldCallback (this);
170
343
 
171
344
  for (const field of this .node .getUserDefinedFields ())
172
- field .removeInterest ("setDeclarations", this);
345
+ field .removeInterest ("updateDeclarations", this);
173
346
 
174
347
  switch (this .node .getTypeName ())
175
348
  {
@@ -258,7 +431,7 @@ module .exports = class ScriptEditor extends Interface
258
431
 
259
432
  #declarations;
260
433
 
261
- setDeclarations (monaco)
434
+ updateDeclarations (monaco)
262
435
  {
263
436
  if (!this .node .getType () .includes (X3D .X3DConstants .Script))
264
437
  return;
@@ -362,6 +535,7 @@ module .exports = class ScriptEditor extends Interface
362
535
  declare const X3DField: typeof X3D. X3DField;
363
536
  declare const X3DArrayField: typeof X3D. X3DArrayField;
364
537
  ${Array .from (this .browser .fieldTypes)
538
+ .filter (type => !this .#internalTypes .has (type .type))
365
539
  .map (type => `declare const ${type .typeName}: typeof X3D .${type .typeName};`)
366
540
  .join ("\n")}
367
541
  declare const TRUE: true;
@@ -369,15 +543,15 @@ module .exports = class ScriptEditor extends Interface
369
543
  declare const NULL: null;
370
544
  declare function print (... args: any []): void;
371
545
  ${fields .join ("\n")};
372
- `},
373
- ]);
546
+ `,
547
+ }]);
374
548
  }
375
549
 
376
550
  editors = new Map ();
377
551
 
378
552
  languages = {
379
553
  "Script": "javascript",
380
- "ShaderPart": "c",
554
+ "ShaderPart": "glsl",
381
555
  };
382
556
 
383
557
  async getEditor (node)
@@ -407,11 +581,11 @@ module .exports = class ScriptEditor extends Interface
407
581
 
408
582
  editor .viewState = editor .saveViewState ();
409
583
 
410
- editor .onDidFocusEditorWidget (() => this .setDeclarations (monaco));
584
+ editor .onDidFocusEditorWidget (() => this .updateDeclarations (monaco));
411
585
  editor .onDidBlurEditorWidget (() => this .apply ());
412
586
  editor .onKeyDown (event => this .onKeyDown (event));
413
587
 
414
- element .on ("mouseenter", () => this .setDeclarations (monaco));
588
+ element .on ("mouseenter", () => this .updateDeclarations (monaco));
415
589
  element .on ("contextmenu", () => this .showContextMenu ());
416
590
 
417
591
  // this .debugFindActions (editor)
@@ -795,13 +969,13 @@ main ()
795
969
  case X3D .X3DConstants .SFNode:
796
970
  case X3D .X3DConstants .MFNode:
797
971
  {
798
- field .addInterest ("setDeclarations", this, monaco);
972
+ field .addInterest ("updateDeclarations", this, monaco);
799
973
  break;
800
974
  }
801
975
  }
802
976
  }
803
977
 
804
- this .setDeclarations (monaco);
978
+ this .updateDeclarations (monaco);
805
979
  }
806
980
 
807
981
  toggleDirectOutput ()
@@ -93,7 +93,7 @@ input[type=checkbox] {
93
93
  color: var(--system-yellow);
94
94
  }
95
95
 
96
- .modal {
96
+ .read-only :is(x3d-canvas, .toolbar, .dialog, .outline-editor) {
97
97
  pointer-events: none;
98
98
  }
99
99
 
@@ -150,6 +150,7 @@ tbody th th {
150
150
  thead tr,
151
151
  tfoot tr {
152
152
  background: var(--tint-color2);
153
+ backdrop-filter: var(--tool-backdrop-filter);
153
154
  }
154
155
 
155
156
  tbody tr:nth-child(odd) {
@@ -786,6 +787,14 @@ body.dark .dialog ::placeholder {
786
787
  color: var(--system-gray2);
787
788
  }
788
789
 
790
+ .scene-properties td.meta-value {
791
+ display: flex;
792
+ }
793
+
794
+ .scene-properties .open-link {
795
+ padding-left: 4px;
796
+ }
797
+
789
798
  /* Library */
790
799
 
791
800
  .ui-widget .library-input {
@@ -1023,7 +1032,7 @@ body.dark .ui-widget .library-list .component {
1023
1032
  overflow: hidden;
1024
1033
  position: absolute;
1025
1034
  box-sizing: border-box;
1026
- left: 0;
1035
+ left: 0px;
1027
1036
  right: var(--toolbar-width);
1028
1037
  height: 100%;
1029
1038
  }
@@ -1032,7 +1041,7 @@ body.dark .ui-widget .library-list .component {
1032
1041
  position: absolute;
1033
1042
  box-sizing: border-box;
1034
1043
  overflow-y: scroll;
1035
- top: 0;
1044
+ top: 0px;
1036
1045
  border-right: 1px solid var(--border-color);
1037
1046
  border-bottom: 1px solid var(--border-color);
1038
1047
  padding: 5px;
@@ -1046,13 +1055,27 @@ body.dark .ui-widget .library-list .component {
1046
1055
  }
1047
1056
 
1048
1057
  .console-output p {
1058
+ box-sizing: border-box;
1059
+ position: relative;
1060
+ z-index: 0;
1049
1061
  margin: 0;
1062
+ padding: 1px 2px;
1063
+ white-space: pre-wrap;
1064
+ overflow-wrap: break-word;
1065
+ font-family: monospace;
1066
+ font-size: 8pt;
1050
1067
  }
1051
1068
 
1052
- .console-output p.splitter {
1053
- margin-top: 5px;
1054
- border-top: 1px solid var(--system-gray3);
1055
- margin-bottom: 5px;
1069
+ .console-output p:where(.warn, .error):before {
1070
+ content: "";
1071
+ box-sizing: border-box;
1072
+ position: absolute;
1073
+ display: block;
1074
+ z-index: -1;
1075
+ top: 0px;
1076
+ left: 0px;
1077
+ width: 100%;
1078
+ height: 100%;
1056
1079
  }
1057
1080
 
1058
1081
  .console-output p.debug {
@@ -1075,40 +1098,49 @@ body.dark .ui-widget .library-list .component {
1075
1098
  color: var(--system-red);
1076
1099
  }
1077
1100
 
1078
- .console-output p.filled {
1079
- position: relative;
1080
- z-index: 0;
1081
- margin-top: 5px;
1082
- margin-bottom: 5px;
1101
+ .console-output p.warn {
1102
+ border-top: 1px solid var(--system-yellow);
1103
+ border-bottom: 1px solid var(--system-yellow);
1083
1104
  color: black;
1084
1105
  }
1085
1106
 
1086
- .console-output p.filled:before {
1087
- content: "";
1088
- position: absolute;
1089
- display: block;
1090
- z-index: -1;
1091
- width: 100%;
1092
- height: 100%;
1093
- filter: brightness(2) opacity(60%);
1107
+ .console-output p.warn:before {
1108
+ background-color: color-mix(in srgb, color-mix(in srgb, var(--system-yellow), white 50%), transparent 30%);
1094
1109
  }
1095
1110
 
1096
- .console-output p.warn.filled {
1097
- border-top: 1px solid var(--system-yellow);
1098
- border-bottom: 1px solid var(--system-yellow);
1111
+ .console-output p.error {
1112
+ border-top: 1px solid var(--system-red);
1113
+ border-bottom: 1px solid var(--system-red);
1114
+ color: black;
1099
1115
  }
1100
1116
 
1101
- .console-output p.warn.filled:before {
1102
- background-color: var(--system-yellow);
1117
+ .console-output p.error:before {
1118
+ background-color: color-mix(in srgb, color-mix(in srgb, var(--system-red), white 50%), transparent 30%);
1103
1119
  }
1104
1120
 
1105
- .console-output p.error.filled {
1106
- border-top: 1px solid var(--system-red);
1107
- border-bottom: 1px solid var(--system-red);
1121
+ .console-output p.warn:has(+ p.warn),
1122
+ .console-output p.error:has(+ p.error) {
1123
+ border-bottom: none;
1124
+ }
1125
+
1126
+ .console-output p.warn + p.warn,
1127
+ .console-output p.error + p.error {
1128
+ border-top: none;
1129
+ }
1130
+
1131
+ .console-output p.warn:not(:has(+ p.warn)),
1132
+ .console-output p.error:not(:has(+ p.error)) {
1133
+ margin-bottom: 2px;
1108
1134
  }
1109
1135
 
1110
- .console-output p.error.filled:before {
1111
- background-color: var(--system-red);
1136
+ .console-output p.splitter {
1137
+ margin: 5px 0px;
1138
+ border-top: 1px solid var(--system-gray3);
1139
+ padding: 0px;
1140
+ }
1141
+
1142
+ .console-output p.splitter:first-child {
1143
+ display: none;
1112
1144
  }
1113
1145
 
1114
1146
  .console-input {