sunrize 1.11.0 → 1.11.2

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.
@@ -14,8 +14,7 @@ const
14
14
 
15
15
  const
16
16
  _expanded = Symbol (),
17
- _fullExpanded = Symbol (),
18
- _changing = Symbol ();
17
+ _fullExpanded = Symbol ();
19
18
 
20
19
  module .exports = class OutlineView extends Interface
21
20
  {
@@ -281,9 +280,13 @@ module .exports = class OutlineView extends Interface
281
280
  .attr ("draggable", "true")
282
281
  .on ("dragstart", this .onDragStartNode .bind (this));
283
282
  }
283
+
284
+ child .find (".imported-node > .item")
285
+ .attr ("draggable", "true")
286
+ .on ("dragstart", this .onDragStartImportedNode .bind (this));
284
287
  }
285
288
 
286
- child .find (".externproto .name, .externproto .icon, .proto .name, .proto .icon, .node .name, .node .icon")
289
+ child .find (":is(.externproto, .proto, .node, .imported-node, .exported-node) :where(.name, .icon)")
287
290
  .on ("click", this .selectNode .bind (this))
288
291
  .on ("mouseenter", this .updateNodeTitle .bind (this));
289
292
 
@@ -501,7 +504,7 @@ module .exports = class OutlineView extends Interface
501
504
  let index = 0;
502
505
 
503
506
  for (const rootNode of scene .rootNodes)
504
- ul .append (this .createNodeElement ("node", parent, rootNode ? rootNode .getValue () : null, index ++));
507
+ ul .append (this .createNodeElement ("node", parent, rootNode ?.getValue (), index ++));
505
508
 
506
509
  // Added to prevent bug, that last route is not drawn right.
507
510
  $("<li></li>")
@@ -515,18 +518,8 @@ module .exports = class OutlineView extends Interface
515
518
 
516
519
  updateSceneRootNodes (parent, scene, type, func)
517
520
  {
518
- for (const node of scene .rootNodes)
519
- {
520
- if (!node ?.getNodeUserData (_changing))
521
- continue;
522
-
523
- const nodes = Array .from (scene .rootNodes);
524
-
525
- this .browser .nextFrame ()
526
- .then (() => nodes .forEach (node => node ?.setNodeUserData (_changing, false)));
527
-
521
+ if (this .#changing)
528
522
  return;
529
- }
530
523
 
531
524
  this .updateSceneSubtree (parent, scene, type, func);
532
525
  }
@@ -554,8 +547,8 @@ module .exports = class OutlineView extends Interface
554
547
  .text ("Imported Nodes")
555
548
  .appendTo (ul);
556
549
 
557
- for (const importedNode of importedNodes)
558
- ul .append (this .createImportedNodeElement ("imported-node", parent, scene, importedNode));
550
+ for (const [index, importedNode] of importedNodes .entries ())
551
+ ul .append (this .createImportedNodeElement (["imported-node"], parent, scene, importedNode .getExportedNode (), index));
559
552
 
560
553
  // Added to prevent bug, that last route is not drawn right.
561
554
  $("<li></li>")
@@ -972,6 +965,9 @@ module .exports = class OutlineView extends Interface
972
965
 
973
966
  createNodeElement (type, parent, node, index)
974
967
  {
968
+ if (node instanceof X3D .X3DImportedNodeProxy)
969
+ return this .createImportedNodeElement (["imported-node", "proxy"], parent, node .getExecutionContext (), node, index);
970
+
975
971
  if (node)
976
972
  {
977
973
  if (!node .isInitialized ())
@@ -996,8 +992,6 @@ module .exports = class OutlineView extends Interface
996
992
 
997
993
  this .objects .set (node .getId (), node .valueOf ());
998
994
 
999
- node .setUserData (_changing, false);
1000
-
1001
995
  // These fields are observed and must never be disconnected, because clones would also lose connection.
1002
996
 
1003
997
  node .typeName_changed .addFieldCallback (this .#nodeSymbol, this .updateNodeTypeName .bind (this, node));
@@ -1306,12 +1300,12 @@ module .exports = class OutlineView extends Interface
1306
1300
 
1307
1301
  updateCloneCount (node)
1308
1302
  {
1309
- const cloneCount = node .getCloneCount ?.() ?? 0
1303
+ const cloneCount = node .getCloneCount ?.() ?? 0;
1310
1304
 
1311
1305
  this .sceneGraph
1312
- .find (`.node[node-id=${node .getId ()}]`)
1306
+ .find (`:is(.node, .imported-node)[node-id="${node .getId ()}"]`)
1313
1307
  .find ("> .item .clone-count")
1314
- .text (cloneCount > 1 ? `[${cloneCount}]` : "")
1308
+ .text (cloneCount > 1 ? `[${cloneCount}]` : "");
1315
1309
  }
1316
1310
 
1317
1311
  updateActiveLayer ()
@@ -1404,105 +1398,113 @@ module .exports = class OutlineView extends Interface
1404
1398
 
1405
1399
  #importedNodeSymbol = Symbol ();
1406
1400
 
1407
- createImportedNodeElement (type, parent, scene, importedNode)
1401
+ createImportedNodeElement (type, parent, scene, node, index)
1408
1402
  {
1409
- importedNode .getInlineNode () .getLoadState () .addFieldCallback (this .#importedNodeSymbol, this .updateScene .bind (this, parent, scene));
1403
+ const importedNode = node .getImportedNode ();
1410
1404
 
1411
- try
1412
- {
1413
- this .objects .set (importedNode .getId (), importedNode);
1414
- this .objects .set (importedNode .getExportedNode () .getId (), importedNode .getExportedNode ());
1405
+ if (!importedNode)
1406
+ return this .createNodeElement ("node", parent, null, index);
1415
1407
 
1416
- // Node
1408
+ // These fields are observed and must never be disconnected, because clones would also lose connection.
1417
1409
 
1418
- const child = $("<li></li>")
1419
- .addClass (type)
1420
- .attr ("imported-node-id", importedNode .getId ())
1421
- .attr ("node-id", importedNode .getExportedNode () .getId ());
1410
+ node .name_changed .addFieldCallback (this .#importedNodeSymbol, this .updateImportedNodeName .bind (this, importedNode));
1411
+ node .parents_changed .addFieldCallback (this .#nodeSymbol, this .updateCloneCount .bind (this, node));
1422
1412
 
1423
- // Icon
1413
+ importedNode .getInlineNode () .getLoadState () .addFieldCallback (this .#importedNodeSymbol, this .updateScene .bind (this, parent .closest (".scene"), scene));
1424
1414
 
1425
- const icon = $("<img></img>")
1426
- .addClass ("icon")
1427
- .attr ("src", `../images/OutlineEditor/Node/${this .nodeIcons .get (type)}.svg`)
1428
- .appendTo (child);
1415
+ this .objects .set (node .getId (), node);
1416
+ this .objects .set (importedNode .getId (), importedNode);
1429
1417
 
1430
- // Name
1418
+ // Node
1431
1419
 
1432
- const name = $("<div></div>")
1433
- .addClass ("name")
1434
- .appendTo (child);
1420
+ const classes = type;
1435
1421
 
1436
- $("<span></span>")
1437
- .addClass ("node-type-name")
1438
- .text (importedNode .getExportedNode () .getTypeName ())
1439
- .appendTo (name);
1422
+ if (importedNode .getExportedNode () .getSharedNode ())
1423
+ {
1424
+ const selection = require ("../Application/Selection");
1440
1425
 
1441
- name .append (document .createTextNode (" "));
1426
+ if (selection .has (node))
1427
+ classes .push ("selected");
1428
+ }
1429
+ else
1430
+ {
1431
+ classes .push ("no-expand");
1432
+ }
1442
1433
 
1443
- $("<span></span>")
1444
- .addClass ("node-name")
1445
- .text (importedNode .getExportedName ())
1446
- .appendTo (name);
1434
+ const child = $("<li></li>")
1435
+ .addClass (classes)
1436
+ .attr ("node-id", node .getId ())
1437
+ .attr ("imported-node-id", importedNode .getId ())
1438
+ .attr ("index", index);
1447
1439
 
1448
- if (importedNode .getExportedName () !== importedNode .getImportedName ())
1449
- {
1450
- name
1451
- .append (document .createTextNode (" "))
1452
- .append ($("<span></span>") .addClass ("as") .text ("AS"))
1453
- .append (document .createTextNode (" "))
1454
- .append ($("<span></span>") .addClass ("as-name") .text (importedNode .getImportedName ()));
1455
- }
1440
+ // Icon
1456
1441
 
1457
- // Add buttons to name.
1442
+ const icon = $("<img></img>")
1443
+ .addClass ("icon")
1444
+ .attr ("src", `../images/OutlineEditor/Node/${this .nodeIcons .get (type [0])}.svg`)
1445
+ .appendTo (child);
1458
1446
 
1459
- this .addNodeButtons (this .getNode (parent), importedNode .getExportedNode (), name);
1447
+ // Name
1460
1448
 
1461
- // Append empty tree to enable expander.
1449
+ const name = $("<div></div>")
1450
+ .addClass ("name")
1451
+ .appendTo (child);
1462
1452
 
1463
- $("<ul><li></li></ul>") .appendTo (child);
1453
+ $("<span></span>")
1454
+ .addClass ("node-type-name")
1455
+ .text (node .getTypeName ())
1456
+ .appendTo (name);
1464
1457
 
1465
- return child;
1466
- }
1467
- catch
1468
- {
1469
- this .objects .set (importedNode .getId (), importedNode);
1458
+ name .append (document .createTextNode (" "));
1470
1459
 
1471
- // Node
1460
+ $("<span></span>")
1461
+ .addClass ("node-name")
1462
+ .text (importedNode .getExportedName ())
1463
+ .appendTo (name);
1472
1464
 
1473
- const child = $("<li></li>")
1474
- .addClass ([type, "no-expand"])
1475
- .attr ("imported-node-id", importedNode .getId ());
1465
+ const nodeAsName = $("<span></span>")
1466
+ .addClass ("node-as-name")
1467
+ .append (document .createTextNode (" "))
1468
+ .append ($("<span></span>") .addClass ("as") .text ("AS"))
1469
+ .append (document .createTextNode (" "))
1470
+ .append ($("<span></span>") .addClass ("as-name") .text (importedNode .getImportedName ()))
1471
+ .appendTo (name);
1476
1472
 
1477
- // Icon
1473
+ if (importedNode .getExportedName () === importedNode .getImportedName ())
1474
+ nodeAsName .hide ();
1478
1475
 
1479
- const icon = $("<img></img>")
1480
- .addClass ("icon")
1481
- .attr ("src", `../images/OutlineEditor/Node/${this .nodeIcons .get (type)}.svg`)
1482
- .appendTo (child);
1476
+ name .append (document .createTextNode (" "));
1483
1477
 
1484
- // Name
1478
+ const cloneCount = node .getCloneCount ?.() ?? 0
1485
1479
 
1486
- const name = $("<div></div>")
1487
- .addClass ("name")
1488
- .appendTo (child);
1480
+ $("<span></span>")
1481
+ .addClass ("clone-count")
1482
+ .text (cloneCount > 1 ? `[${cloneCount}]` : "")
1483
+ .appendTo (name);
1489
1484
 
1490
- $("<span></span>")
1491
- .addClass ("node-name")
1492
- .text (importedNode .getExportedName ())
1493
- .appendTo (name);
1485
+ // Add buttons to name.
1494
1486
 
1495
- if (importedNode .getExportedName () !== importedNode .getImportedName ())
1496
- {
1497
- name
1498
- .append (document .createTextNode (" "))
1499
- .append ($("<span></span>") .addClass ("as") .text ("AS"))
1500
- .append (document .createTextNode (" "))
1501
- .append ($("<span></span>") .addClass ("as-name") .text (importedNode .getImportedName ()));
1502
- }
1487
+ this .addNodeButtons (this .getNode (parent), node, name);
1503
1488
 
1504
- return child;
1505
- }
1489
+ // Append empty tree to enable expander.
1490
+
1491
+ $("<ul><li></li></ul>") .appendTo (child);
1492
+
1493
+ return child;
1494
+ }
1495
+
1496
+ updateImportedNodeName (importedNode)
1497
+ {
1498
+ const nodeAsName = this .sceneGraph
1499
+ .find (`.imported-node[imported-node-id="${importedNode .getId ()}"]`)
1500
+ .find ("> .item .node-as-name");
1501
+
1502
+ nodeAsName .find (".as-name") .text (importedNode .getImportedName ());
1503
+
1504
+ if (importedNode .getExportedName () === importedNode .getImportedName ())
1505
+ nodeAsName .hide ();
1506
+ else
1507
+ nodeAsName .show ();
1506
1508
  }
1507
1509
 
1508
1510
  #exportedNodeSymbol = Symbol ();
@@ -1514,6 +1516,8 @@ module .exports = class OutlineView extends Interface
1514
1516
  this .objects .set (exportedNode .getId (), exportedNode);
1515
1517
  this .objects .set (node .getId (), node .valueOf ());
1516
1518
 
1519
+ // These fields are observed and must never be disconnected, because clones would also lose connection.
1520
+
1517
1521
  node .typeName_changed .addFieldCallback (this .#exportedNodeSymbol, this .updateNodeTypeName .bind (this, node));
1518
1522
  node .name_changed .addFieldCallback (this .#exportedNodeSymbol, this .updateExportedNodeName .bind (this, exportedNode));
1519
1523
 
@@ -2034,36 +2038,8 @@ module .exports = class OutlineView extends Interface
2034
2038
  if (!parent .prop ("isConnected"))
2035
2039
  return;
2036
2040
 
2037
- switch (field .getType ())
2038
- {
2039
- case X3D .X3DConstants .SFNode:
2040
- {
2041
- if (!field .getValue () || !field .getNodeUserData (_changing))
2042
- break;
2043
-
2044
- this .browser .nextFrame ()
2045
- .then (() => field .setNodeUserData (_changing, false));
2046
-
2047
- return;
2048
- }
2049
- case X3D .X3DConstants .MFNode:
2050
- {
2051
- for (const node of field)
2052
- {
2053
- if (!node ?.getNodeUserData (_changing))
2054
- continue;
2055
-
2056
- const nodes = Array .from (field);
2057
-
2058
- this .browser .nextFrame ()
2059
- .then (() => nodes .forEach (node => node ?.setNodeUserData (_changing, false)));
2060
-
2061
- return;
2062
- }
2063
-
2064
- break;
2065
- }
2066
- }
2041
+ if (this .#changing)
2042
+ return;
2067
2043
 
2068
2044
  this .saveScrollPositions ();
2069
2045
 
@@ -2176,7 +2152,7 @@ module .exports = class OutlineView extends Interface
2176
2152
  let index = 0;
2177
2153
 
2178
2154
  for (const node of field)
2179
- ul .append (this .createNodeElement ("node", parent, node ?.getValue (), index ++));
2155
+ ul .append (this .createNodeElement ("node", parent, node .getValue (), index ++));
2180
2156
 
2181
2157
  // Make jsTree.
2182
2158
 
@@ -3014,18 +2990,12 @@ module .exports = class OutlineView extends Interface
3014
2990
  return;
3015
2991
 
3016
2992
  // If node is somewhere else, don't disconnect.
3017
- if (Array .from (this .sceneGraph .find (`.node[node-id="${node .getId ()}"],
3018
- .imported-node[node-id="${node .getId ()}"],
3019
- .exported-node[node-id="${node .getId ()}"]`))
2993
+ if (Array .from (this .sceneGraph .find (`:is(.node, .imported-node, .exported-node)[node-id="${node .getId ()}"]`))
3020
2994
  .some (s => !$(s) .closest (element) .length))
3021
2995
  {
3022
2996
  return;
3023
2997
  }
3024
2998
 
3025
- node .typeName_changed .removeFieldCallback (this .#nodeSymbol);
3026
- node .name_changed .removeFieldCallback (this .#nodeSymbol);
3027
- node .parents_changed .removeFieldCallback (this .#nodeSymbol);
3028
-
3029
2999
  for (const type of node .getType ())
3030
3000
  {
3031
3001
  switch (type)
@@ -3052,16 +3022,6 @@ module .exports = class OutlineView extends Interface
3052
3022
  }
3053
3023
  });
3054
3024
 
3055
- element .find (".exported-node") .each ((i, e) =>
3056
- {
3057
- const
3058
- child = $(e),
3059
- node = this .getNode (child);
3060
-
3061
- node .typeName_changed .removeFieldCallback (this .#exportedNodeSymbol);
3062
- node .name_changed .removeFieldCallback (this .#exportedNodeSymbol);
3063
- });
3064
-
3065
3025
  element .find (".field, .special") .each ((i, e) =>
3066
3026
  {
3067
3027
  const
@@ -3109,7 +3069,7 @@ module .exports = class OutlineView extends Interface
3109
3069
  this .selectNodeElement ($(element), { add: true });
3110
3070
  }
3111
3071
 
3112
- deselectAll ()
3072
+ deselectAll ({ target = true } = { })
3113
3073
  {
3114
3074
  const
3115
3075
  selection = require ("../Application/Selection"),
@@ -3119,7 +3079,15 @@ module .exports = class OutlineView extends Interface
3119
3079
  nodes .removeClass (["primary", "manually", "selected"]);
3120
3080
 
3121
3081
  selection .clear ();
3122
- hierarchy .clear ();
3082
+
3083
+ if (target)
3084
+ hierarchy .clear ();
3085
+
3086
+ // Prevent update tree view.
3087
+
3088
+ this .#changing = true;
3089
+
3090
+ this .browser .nextFrame () .then (() => this .#changing = false);
3123
3091
  }
3124
3092
 
3125
3093
  showPreview (event)
@@ -3135,7 +3103,7 @@ module .exports = class OutlineView extends Interface
3135
3103
  event .stopImmediatePropagation ();
3136
3104
 
3137
3105
  $("[data-hasqtip]") .qtip ?.("hide") .qtip ("destroy", true);
3138
- $(".show-preview.on") .removeClass ("on") .addClass ("off");
3106
+ $("[action=show-preview].on") .removeClass ("on") .addClass ("off");
3139
3107
 
3140
3108
  if (on)
3141
3109
  return;
@@ -3233,14 +3201,18 @@ module .exports = class OutlineView extends Interface
3233
3201
  node .getTool () .setSelected (element .hasClass ("selected"));
3234
3202
  }
3235
3203
 
3236
- node .setUserData (_changing, true);
3237
-
3238
3204
  this .sceneGraph .find (`.node[node-id=${node .getId ()}],
3239
3205
  .imported-node[node-id=${node .getId ()}],
3240
3206
  .exported-node[node-id=${node .getId ()}]`)
3241
3207
  .find ("> .item [action=toggle-tool]")
3242
3208
  .removeClass (["on", "off"])
3243
3209
  .addClass (tool ? "off" : "on");
3210
+
3211
+ // Prevent update tree view.
3212
+
3213
+ this .#changing = true;
3214
+
3215
+ this .browser .nextFrame () .then (() => this .#changing = false);
3244
3216
  }
3245
3217
 
3246
3218
  proxyDisplay (event)
@@ -3461,19 +3433,21 @@ module .exports = class OutlineView extends Interface
3461
3433
  this .clearConnectors ();
3462
3434
 
3463
3435
  const
3464
- element = $(event .currentTarget) .closest (".node, .externproto, .proto"),
3436
+ element = $(event .currentTarget) .closest (".node, .externproto, .proto, .imported-node, .exported-node"),
3465
3437
  add = event .shiftKey || event .metaKey;
3466
3438
 
3467
- if (element .hasClass ("node"))
3439
+ if (element .is (".node"))
3468
3440
  this .selectNodeElement (element, { add, target: true });
3469
3441
 
3470
- else if (element .is (".externproto, .proto"))
3471
- this .selectPrimaryElement (element, add);
3442
+ else if (element .is (".externproto, .proto, .imported-node, .exported-node"))
3443
+ this .selectPrimaryElement (element, { add, target: true });
3472
3444
  }
3473
3445
 
3446
+ #changing = false;
3447
+
3474
3448
  selectNodeElement (element, { add = false, target = false } = { })
3475
3449
  {
3476
- if (!element .hasClass ("node"))
3450
+ if (!element .is (".node"))
3477
3451
  return;
3478
3452
 
3479
3453
  if (!this .isEditable (element))
@@ -3485,11 +3459,7 @@ module .exports = class OutlineView extends Interface
3485
3459
  selected = element .hasClass ("manually"),
3486
3460
  selectedElements = this .sceneGraph .find (".primary, .selected"),
3487
3461
  node = this .getNode (element),
3488
- elements = $(`.node[node-id=${node ?.getId ()}]`),
3489
- changed = new Map (selection .nodes .map (node => [node, node .getTool ()]));
3490
-
3491
- if (node)
3492
- changed .set (node .valueOf (), node .getTool ());
3462
+ elements = $(`.node[node-id='${node ?.getId ()}']`);
3493
3463
 
3494
3464
  selectedElements .removeClass ("primary");
3495
3465
 
@@ -3541,24 +3511,33 @@ module .exports = class OutlineView extends Interface
3541
3511
  hierarchy .set (node);
3542
3512
  }
3543
3513
 
3544
- for (const [node, tool] of changed)
3545
- {
3546
- if (node .getTool () !== tool)
3547
- node .setUserData (_changing, true);
3548
- }
3514
+ // Prevent update tree view.
3515
+
3516
+ this .#changing = true;
3517
+
3518
+ this .browser .nextFrame () .then (() => this .#changing = false);
3549
3519
  }
3550
3520
 
3551
- selectPrimaryElement (element, add = false)
3521
+ selectPrimaryElement (element, { add = false, target = false } = { })
3552
3522
  {
3553
3523
  if (!this .isEditable (element))
3554
3524
  return;
3555
3525
 
3526
+ const
3527
+ hierarchy = require ("../Application/Hierarchy"),
3528
+ node = this .getNode (element);
3529
+
3556
3530
  if (!add)
3557
3531
  this .sceneGraph .find (".manually") .removeClass ("manually");
3558
3532
 
3559
3533
  this .sceneGraph .find (".primary") .removeClass ("primary");
3560
3534
 
3561
3535
  element .addClass (["primary", "manually"]);
3536
+
3537
+ if (target)
3538
+ hierarchy .target (node);
3539
+
3540
+ hierarchy .add (node);
3562
3541
  }
3563
3542
 
3564
3543
  selectField (event)
@@ -3848,6 +3827,8 @@ module .exports = class OutlineView extends Interface
3848
3827
 
3849
3828
  onDragStartField (event) { }
3850
3829
 
3830
+ onDragStartImportedNode (event) { }
3831
+
3851
3832
  onDragEnter (event) { }
3852
3833
 
3853
3834
  onDragLeave (event) { }
@@ -3891,13 +3872,6 @@ module .exports = class OutlineView extends Interface
3891
3872
  }
3892
3873
  }
3893
3874
 
3894
- static objectClasses = {
3895
- "X3DExternProtoDeclaration": "externproto",
3896
- "X3DProtoDeclaration": "proto",
3897
- "X3DScene": "scene",
3898
- "X3DExecutionContext": "scene",
3899
- };
3900
-
3901
3875
  expandHierarchy (hierarchy, parent, parentObject)
3902
3876
  {
3903
3877
  let object = hierarchy .shift ();
@@ -3947,9 +3921,10 @@ module .exports = class OutlineView extends Interface
3947
3921
  }
3948
3922
  default: // X3DBaseNode
3949
3923
  {
3950
- const
3951
- objectClass = OutlineView .objectClasses [object .getTypeName ()] || "node",
3952
- element = parent .find (`.${objectClass}[node-id=${object .getId ()}]`);
3924
+ const element = parent .find (`:is(.node, .imported-node.proxy, .externproto, .proto, .scene)[node-id="${object .getId ()}"]`);
3925
+
3926
+ if (!element .length)
3927
+ break;
3953
3928
 
3954
3929
  element .jstree ("open_node", element);
3955
3930
 
@@ -316,7 +316,7 @@ module .exports = new class Panel extends Interface
316
316
 
317
317
  const
318
318
  fieldElement = concreteNode .find (`field[name="${field .getName ()}"]`),
319
- options = { };
319
+ options = { format: value => this .format (field, value) };
320
320
 
321
321
  switch (field .getType ())
322
322
  {
@@ -377,12 +377,28 @@ module .exports = new class Panel extends Interface
377
377
  min = fieldElement .attr ("minInclusive") ?? fieldElement .attr ("minExclusive"),
378
378
  max = fieldElement .attr ("maxInclusive") ?? fieldElement .attr ("maxExclusive");
379
379
 
380
+ for (const key in field)
381
+ options [key] ??= { };
382
+
383
+ for (const key in field)
384
+ options [key] .format = options .format;
385
+
380
386
  if (min !== undefined)
387
+ {
381
388
  options .min = scene .toUnit (category, parseFloat (min));
382
389
 
390
+ for (const key in field)
391
+ options [key] .min = options .min;
392
+ }
393
+
383
394
  if (max !== undefined)
395
+ {
384
396
  options .max = scene .toUnit (category, parseFloat (max));
385
397
 
398
+ for (const key in field)
399
+ options [key] .max = options .max;
400
+ }
401
+
386
402
  this .refresh (parameter, node, field);
387
403
 
388
404
  const input = $.try (() => folder .addInput (parameter, field .getName (), options));
@@ -467,6 +483,44 @@ module .exports = new class Panel extends Interface
467
483
  }
468
484
  }
469
485
 
486
+ #float = new X3D .SFFloat ();
487
+ #double = new X3D .SFDouble ();
488
+
489
+ format (field, value)
490
+ {
491
+ switch (field .getType ())
492
+ {
493
+ case X3D .X3DConstants .SFColor:
494
+ case X3D .X3DConstants .SFColorRGBA:
495
+ case X3D .X3DConstants .SFFloat:
496
+ case X3D .X3DConstants .SFMatrix3f:
497
+ case X3D .X3DConstants .SFMatrix4f:
498
+ case X3D .X3DConstants .SFVec2f:
499
+ case X3D .X3DConstants .SFVec3f:
500
+ case X3D .X3DConstants .SFVec4f:
501
+ {
502
+ this .#float .setValue (value);
503
+
504
+ return this .#float .toString ();
505
+ }
506
+ case X3D .X3DConstants .SFDouble:
507
+ case X3D .X3DConstants .SFMatrix3d:
508
+ case X3D .X3DConstants .SFMatrix4d:
509
+ case X3D .X3DConstants .SFRotation:
510
+ case X3D .X3DConstants .SFTime:
511
+ case X3D .X3DConstants .SFVec2d:
512
+ case X3D .X3DConstants .SFVec3d:
513
+ case X3D .X3DConstants .SFVec4d:
514
+ {
515
+ this .#double .setValue (value);
516
+
517
+ return this .#double .toString ();
518
+ }
519
+ default:
520
+ return value;
521
+ }
522
+ }
523
+
470
524
  refresh (parameter, node, field)
471
525
  {
472
526
  const