sunrize 1.11.1 → 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.
@@ -9,6 +9,7 @@ const
9
9
  mime = require ("../Bits/MimeTypes"),
10
10
  X3D = require ("../X3D"),
11
11
  OutlineRouteGraph = require ("./OutlineRouteGraph"),
12
+ Traverse = require ("x3d-traverse") (X3D),
12
13
  Editor = require ("../Undo/Editor"),
13
14
  UndoManager = require ("../Undo/UndoManager"),
14
15
  _ = require ("../Application/GetText");
@@ -84,7 +85,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
84
85
  if (!element .is (".manually"))
85
86
  this .sceneGraph .find (".manually") .removeClass ("manually");
86
87
 
87
- if (element .is (".externproto, .proto, .proto-scene, .node, .field") && !element .is (".manually"))
88
+ if (element .is (":is(.externproto, .proto, .proto-scene, .node, .field, .imported-node, .exported-node):not(.manually)"))
88
89
  this .selectPrimaryElement (element);
89
90
 
90
91
  const
@@ -257,119 +258,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
257
258
  ];
258
259
 
259
260
  if (innerNode .getType () .includes (X3D .X3DConstants .X3DChildNode))
260
- {
261
- menu .push ({
262
- label: _("Add Parent Group"),
263
- submenu: [
264
- {
265
- label: "Transform",
266
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Transform", "children"],
267
- },
268
- {
269
- label: "Group",
270
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Group", "children"],
271
- },
272
- {
273
- label: "StaticGroup",
274
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "StaticGroup", "children"],
275
- },
276
- {
277
- label: "Switch",
278
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Switch", "children"],
279
- },
280
- { type: "separator" },
281
- {
282
- label: "Billboard",
283
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Billboard", "children"],
284
- },
285
- {
286
- label: "Collision",
287
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Collision", "children"],
288
- },
289
- {
290
- label: "LOD",
291
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "LOD", "children"],
292
- },
293
- {
294
- label: "ViewpointGroup",
295
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "ViewpointGroup", "children"],
296
- },
297
- { type: "separator" },
298
- {
299
- label: "Anchor",
300
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Anchor", "children"],
301
- },
302
- { type: "separator" },
303
- {
304
- label: "LayoutLayer",
305
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "LayoutLayer", "children"],
306
- },
307
- {
308
- label: "ScreenGroup",
309
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "ScreenGroup", "children"],
310
- },
311
- { type: "separator" },
312
- {
313
- label: "GeoTransform",
314
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoTransform", "children"],
315
- },
316
- {
317
- label: "GeoLocation",
318
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoLocation", "children"],
319
- },
320
- { type: "separator" },
321
- {
322
- label: "CADLayer",
323
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADLayer", "children"],
324
- },
325
- {
326
- label: "CADAssembly",
327
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADAssembly", "children"],
328
- },
329
- {
330
- label: "CADPart",
331
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADPart", "children"],
332
- },
333
- {
334
- label: "CADFace",
335
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADFace", "shape"],
336
- },
337
- { type: "separator" },
338
- {
339
- label: "LayerSet",
340
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "LayerSet", "layers"],
341
- },
342
- {
343
- label: "Layer",
344
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Layer", "children"],
345
- },
346
- {
347
- label: "Viewport",
348
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Viewport", "children"],
349
- },
350
- { type: "separator" },
351
- {
352
- label: "PickableGroup",
353
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Picking", "PickableGroup", "children"],
354
- },
355
- { type: "separator" },
356
- {
357
- label: "CollidableOffset",
358
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableOffset", "collidable"],
359
- },
360
- {
361
- label: "CollidableShape",
362
- args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableShape", "shape"],
363
- },
364
- ],
365
- },
366
- {
367
- label: _("Remove Parent"),
368
- enabled: parentNodeElement .hasClass ("node"),
369
- args: ["removeParent", element .attr ("id"), executionContext .getId (), node .getId ()],
370
- },
371
- { type: "separator" });
372
- }
261
+ this .addChildNodeMenu (menu, element, parentNodeElement, executionContext, node);
373
262
 
374
263
  for (const type of node .getType () .toReversed ())
375
264
  {
@@ -584,20 +473,54 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
584
473
 
585
474
  else if (element .is (".imported-node"))
586
475
  {
587
- const importedNode = this .objects .get (parseInt (element .attr ("imported-node-id")));
476
+ const
477
+ parentFieldElement = element .closest (".field, .scene", this .sceneGraph),
478
+ parentNodeElement = parentFieldElement .closest (".node, .proto, .scene", this .sceneGraph),
479
+ node = this .objects .get (parseInt (element .attr ("node-id"))),
480
+ innerNode = $.try (() => node .getInnerNode ()) ?? node,
481
+ importedNode = this .objects .get (parseInt (element .attr ("imported-node-id"))),
482
+ local = importedNode .getExecutionContext () .getLocalScene () === this .executionContext;
588
483
 
589
484
  var menu = [
590
485
  {
591
486
  label: _("Edit Imported Node..."),
592
- visible: importedNode .getExecutionContext () .getLocalScene () === this .executionContext,
487
+ visible: local,
593
488
  args: ["editImportedNode", element .attr ("id")],
594
489
  },
595
490
  {
596
491
  label: _("Remove Imported Node"),
597
- visible: importedNode .getExecutionContext () .getLocalScene () === this .executionContext,
492
+ visible: local && !node .getCloneCount (),
598
493
  args: ["removeImportedNode", element .attr ("id")],
599
494
  },
495
+ {
496
+ label: _("Add Clone"),
497
+ visible: local,
498
+ args: ["addImportedNodeClone", element .attr ("id")],
499
+ },
500
+ { type: "separator" },
501
+ {
502
+ label: _("Cut"),
503
+ visible: local && element .hasClass ("proxy"),
504
+ accelerator: "CmdOrCtrl+X",
505
+ args: ["cutNodes"],
506
+ },
507
+ {
508
+ label: _("Copy"),
509
+ visible: local && element .hasClass ("proxy"),
510
+ accelerator: "CmdOrCtrl+C",
511
+ args: ["copyNodes"],
512
+ },
513
+ {
514
+ label: _("Delete"),
515
+ visible: local && element .hasClass ("proxy"),
516
+ accelerator: "CmdOrCtrl+Backspace",
517
+ args: ["deleteNodes"],
518
+ },
519
+ { type: "separator" },
600
520
  ];
521
+
522
+ if (local && element .hasClass ("proxy") && innerNode .getType () .includes (X3D .X3DConstants .X3DChildNode))
523
+ this .addChildNodeMenu (menu, element, parentNodeElement, executionContext, node);
601
524
  }
602
525
 
603
526
  else if (element .is (".externproto, .proto"))
@@ -679,7 +602,7 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
679
602
  {
680
603
  label: _("Paste"),
681
604
  accelerator: "CmdOrCtrl+V",
682
- args: ["pasteNodes", element .attr ("id"), executionContext .getId ()],
605
+ args: ["pasteNodes", element .attr ("id"), executionContext .getId (), undefined, undefined, true],
683
606
  },
684
607
  ];
685
608
  }
@@ -691,6 +614,121 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
691
614
  electron .ipcRenderer .send ("context-menu", "outline-editor", menu);
692
615
  }
693
616
 
617
+ addChildNodeMenu (menu, element, parentNodeElement, executionContext, node)
618
+ {
619
+ menu .push ({
620
+ label: _("Add Parent Group"),
621
+ submenu: [
622
+ {
623
+ label: "Transform",
624
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Transform", "children"],
625
+ },
626
+ {
627
+ label: "Group",
628
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Group", "children"],
629
+ },
630
+ {
631
+ label: "StaticGroup",
632
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "StaticGroup", "children"],
633
+ },
634
+ {
635
+ label: "Switch",
636
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Grouping", "Switch", "children"],
637
+ },
638
+ { type: "separator" },
639
+ {
640
+ label: "Billboard",
641
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Billboard", "children"],
642
+ },
643
+ {
644
+ label: "Collision",
645
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Collision", "children"],
646
+ },
647
+ {
648
+ label: "LOD",
649
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "LOD", "children"],
650
+ },
651
+ {
652
+ label: "ViewpointGroup",
653
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "ViewpointGroup", "children"],
654
+ },
655
+ { type: "separator" },
656
+ {
657
+ label: "Anchor",
658
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Navigation", "Anchor", "children"],
659
+ },
660
+ { type: "separator" },
661
+ {
662
+ label: "LayoutLayer",
663
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "LayoutLayer", "children"],
664
+ },
665
+ {
666
+ label: "ScreenGroup",
667
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layout", "ScreenGroup", "children"],
668
+ },
669
+ { type: "separator" },
670
+ {
671
+ label: "GeoTransform",
672
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoTransform", "children"],
673
+ },
674
+ {
675
+ label: "GeoLocation",
676
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Geospatial", "GeoLocation", "children"],
677
+ },
678
+ { type: "separator" },
679
+ {
680
+ label: "CADLayer",
681
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADLayer", "children"],
682
+ },
683
+ {
684
+ label: "CADAssembly",
685
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADAssembly", "children"],
686
+ },
687
+ {
688
+ label: "CADPart",
689
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADPart", "children"],
690
+ },
691
+ {
692
+ label: "CADFace",
693
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "CADGeometry", "CADFace", "shape"],
694
+ },
695
+ { type: "separator" },
696
+ {
697
+ label: "LayerSet",
698
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "LayerSet", "layers"],
699
+ },
700
+ {
701
+ label: "Layer",
702
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Layer", "children"],
703
+ },
704
+ {
705
+ label: "Viewport",
706
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Layering", "Viewport", "children"],
707
+ },
708
+ { type: "separator" },
709
+ {
710
+ label: "PickableGroup",
711
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "Picking", "PickableGroup", "children"],
712
+ },
713
+ { type: "separator" },
714
+ {
715
+ label: "CollidableOffset",
716
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableOffset", "collidable"],
717
+ },
718
+ {
719
+ label: "CollidableShape",
720
+ args: ["addParentGroup", element .attr ("id"), executionContext .getId (), node .getId (), "RigidBodyPhysics", "CollidableShape", "shape"],
721
+ },
722
+ ],
723
+ },
724
+ {
725
+ label: _("Remove Parent"),
726
+ enabled: parentNodeElement .hasClass ("node"),
727
+ args: ["removeParent", element .attr ("id"), executionContext .getId (), node .getId ()],
728
+ },
729
+ { type: "separator" });
730
+ }
731
+
694
732
  addUserDefinedField (id, executionContextId, nodeId, fieldId)
695
733
  {
696
734
  require ("../Controls/EditUserDefinedFieldPopover");
@@ -855,11 +893,25 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
855
893
  Editor .removeImportedNode (importedNode .getExecutionContext (), importedNode .getImportedName ());
856
894
  }
857
895
 
896
+ addImportedNodeClone (id)
897
+ {
898
+ const
899
+ element = $(`#${id}`),
900
+ importedNode = this .objects .get (parseInt (element .attr ("imported-node-id"))),
901
+ executionContext = importedNode .getExecutionContext ();
902
+
903
+ UndoManager .shared .beginUndo (_("Add Clone of Imported Node »%s«"), importedNode .getImportedName ());
904
+
905
+ Editor .appendValueToArray (executionContext, executionContext, executionContext .rootNodes, importedNode .getExportedNode ());
906
+
907
+ UndoManager .shared .endUndo ();
908
+ }
909
+
858
910
  async cutNodes ()
859
911
  {
860
912
  const
861
- primary = $(".node.primary, .proto.primary, .externproto.primary"),
862
- selected = this .sceneGraph .find (".node.manually, .proto.manually, .externproto.manually"),
913
+ primary = $(":is(.node, .proto, .externproto).primary"),
914
+ selected = this .sceneGraph .find (":is(.node, .proto, .externproto).manually"),
863
915
  selection = selected .filter (primary) .length ? selected : primary,
864
916
  ids = selection .map (function () { return this .id }) .get (),
865
917
  elements = ids .map (id => $(`#${id}`)),
@@ -867,17 +919,17 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
867
919
 
868
920
  UndoManager .shared .beginUndo (nodes .length === 1 ? _("Cut %d Node") : _("Cut %d Nodes"), nodes .length);
869
921
 
870
- await this .copyNodes ();
922
+ await this .copyNodes (false);
871
923
  await this .deleteNodes ();
872
924
 
873
925
  UndoManager .shared .endUndo ();
874
926
  }
875
927
 
876
- async copyNodes (deselect)
928
+ async copyNodes ()
877
929
  {
878
930
  const
879
- primary = $(".node.primary, .proto.primary, .externproto.primary"),
880
- selected = this .sceneGraph .find (".node.manually, .proto.manually, .externproto.manually"),
931
+ primary = $(":is(.node, .proto, .externproto, .imported-node.proxy).primary"),
932
+ selected = this .sceneGraph .find (":is(.node, .proto, .externproto, .imported-node.proxy).manually"),
881
933
  selection = selected .filter (primary) .length ? selected : primary,
882
934
  ids = selection .map (function () { return this .id }) .get (),
883
935
  elements = ids .map (id => $(`#${id}`)),
@@ -905,9 +957,6 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
905
957
  navigator .clipboard .writeText (x3dSyntax);
906
958
 
907
959
  undoManager .undo ();
908
-
909
- if (deselect)
910
- this .deselectAll ();
911
960
  }
912
961
 
913
962
  async copyExternPrototype ()
@@ -938,21 +987,21 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
938
987
  scene .dispose ();
939
988
  }
940
989
 
941
- async pasteNodes (id, executionContextId, nodeId, fieldId)
990
+ async pasteNodes (id, executionContextId, nodeId, fieldId, deselect)
942
991
  {
943
992
  // try
944
993
  {
945
994
  // if there is a selected field or node, update nodeId and fieldId.
946
995
 
947
996
  const
948
- primary = $(".primary"),
997
+ primary = deselect ? $("") : $(".node.primary"),
949
998
  executionContextElement = primary .closest (".scene", this .sceneGraph),
950
999
  executionContext = this .objects .get (executionContextId) ?? this .getNode (executionContextElement) ?? this .executionContext,
951
1000
  targetNode = this .objects .get (nodeId) ?? this .getNode (primary),
952
1001
  targetField = this .objects .get (fieldId) ?? this .getField (primary),
953
1002
  numRootNodes = executionContext .rootNodes .length,
954
1003
  x3dSyntax = await navigator .clipboard .readText (),
955
- destinationModelMatrix = nodeId !== undefined ? this .getModelMatrix ($(`.node[node-id=${nodeId}]`)) : new X3D .Matrix4 ();
1004
+ destinationModelMatrix = this .getModelMatrix ($(`.node[node-id=${targetNode ?.getId ()}]`));
956
1005
 
957
1006
  UndoManager .shared .beginUndo (_("Paste Nodes"));
958
1007
 
@@ -999,10 +1048,17 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
999
1048
 
1000
1049
  UndoManager .shared .endUndo ();
1001
1050
 
1051
+ // Expand to pasted nodes and select them.
1052
+
1002
1053
  await this .browser .nextFrame ();
1003
1054
 
1055
+ this .deselectAll ();
1056
+
1004
1057
  for (const node of nodes)
1058
+ {
1005
1059
  this .expandTo (node);
1060
+ this .selectNodeElement ($(`.node[node-id="${node .getId ()}"]`), { add: true });
1061
+ }
1006
1062
  }
1007
1063
  // catch (error)
1008
1064
  // {
@@ -1014,8 +1070,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1014
1070
  deleteNodes ()
1015
1071
  {
1016
1072
  const
1017
- primary = $(".node.primary"),
1018
- selected = this .sceneGraph .find (".node.manually"),
1073
+ primary = $(".node.primary, .imported-node.proxy.primary"),
1074
+ selected = this .sceneGraph .find (".node.manually, .imported-node.proxy.manually"),
1019
1075
  selection = !primary .length || selected .filter (primary) .length ? selected : primary,
1020
1076
  ids = selection .map (function () { return this .id }) .get ();
1021
1077
 
@@ -1026,8 +1082,6 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1026
1082
  else
1027
1083
  return;
1028
1084
 
1029
- const nodes = [ ];
1030
-
1031
1085
  for (const id of ids .reverse ())
1032
1086
  {
1033
1087
  const
@@ -1050,12 +1104,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1050
1104
  Editor .removeValueFromArray (executionContext, parentNode, parentField, index);
1051
1105
  break;
1052
1106
  }
1053
-
1054
- nodes .push (node);
1055
1107
  }
1056
1108
 
1057
- Editor .removeNodesFromExecutionContextIfNecessary (this .executionContext, nodes);
1058
-
1059
1109
  UndoManager .shared .endUndo ();
1060
1110
  }
1061
1111
 
@@ -1154,8 +1204,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
1154
1204
  if (field .getType () === X3D .X3DConstants .MFNode)
1155
1205
  {
1156
1206
  const
1157
- selectedNodes = Array .from (this .sceneGraph .find (".node.manually,.node.primary"), e => this .getNode ($(e))),
1158
- selectedElements = Array .from (this .sceneGraph .find (".node.manually"), e => $(e)),
1207
+ selectedNodes = Array .from (this .sceneGraph .find (":is(.node, .imported-node.proxy):is(.manually,.primary)"), e => this .getNode ($(e))),
1208
+ selectedElements = Array .from (this .sceneGraph .find (":is(.node, .imported-node.proxy).manually"), e => $(e)),
1159
1209
  destinationModelMatrix = this .getModelMatrix (parentNodeElement);
1160
1210
 
1161
1211
  // Add other selected nodes.
@@ -2829,31 +2879,51 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2829
2879
  const
2830
2880
  element = $(event .target) .closest (".field", this .sceneGraph),
2831
2881
  node = this .getNode (element),
2832
- field = this .getField (element)
2882
+ field = this .getField (element);
2833
2883
 
2834
2884
  if (node .canUserDefinedFields () && node .getUserDefinedFields () .has (field .getName ()))
2835
2885
  {
2836
- this .selectPrimaryElement (element)
2886
+ this .selectPrimaryElement (element);
2837
2887
 
2838
- event .originalEvent .dataTransfer .setData ("sunrize/field", element .attr ("id"))
2888
+ event .originalEvent .dataTransfer .setData ("sunrize/field", element .attr ("id"));
2839
2889
  }
2840
2890
  else
2841
2891
  {
2842
- event .preventDefault ()
2892
+ event .preventDefault ();
2893
+ }
2894
+ }
2895
+
2896
+ onDragStartImportedNode (event)
2897
+ {
2898
+ const
2899
+ element = $(event .target) .closest (".imported-node", this .sceneGraph),
2900
+ selected = this .sceneGraph .find (".imported-node.manually"),
2901
+ selection = selected .filter (element) .length ? selected : element,
2902
+ ids = selection .map (function () { return this .id }) .get ();
2903
+
2904
+ if (element .closest (".imported-nodes") .length)
2905
+ {
2906
+ event .preventDefault ();
2907
+ }
2908
+ else
2909
+ {
2910
+ this .selectPrimaryElement (element);
2911
+
2912
+ event .originalEvent .dataTransfer .setData ("sunrize/imported-node", ids .join (","));
2843
2913
  }
2844
2914
  }
2845
2915
 
2846
2916
  onDragEnter (event)
2847
2917
  {
2848
- event .preventDefault ()
2849
- event .stopPropagation ()
2918
+ event .preventDefault ();
2919
+ event .stopPropagation ();
2850
2920
 
2851
- event .originalEvent .dataTransfer .dropEffect = "none"
2921
+ event .originalEvent .dataTransfer .dropEffect = "none";
2852
2922
 
2853
2923
  // Show drop indicator.
2854
2924
 
2855
2925
  const destinationElement = $(event .target) .closest ("li, .scene", this .sceneGraph)
2856
- .removeClass (["drag-before", "drag-into", "drag-after"])
2926
+ .removeClass (["drag-before", "drag-into", "drag-after"]);
2857
2927
 
2858
2928
  if (this .isEditable (destinationElement))
2859
2929
  {
@@ -2864,44 +2934,54 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2864
2934
  sourceExecutionContextElement = sourceElement .closest (".scene", this .sceneGraph),
2865
2935
  destinationExecutionContextElement = destinationElement .closest (".scene", this .sceneGraph),
2866
2936
  sourceExecutionContext = this .getNode (sourceExecutionContextElement),
2867
- destinationExecutionContext = this .getNode (destinationExecutionContextElement)
2937
+ destinationExecutionContext = this .getNode (destinationExecutionContextElement);
2868
2938
 
2869
2939
  if (sourceExecutionContext === destinationExecutionContext)
2870
2940
  {
2871
2941
  if (event .altKey)
2872
- event .originalEvent .dataTransfer .dropEffect = "copy"
2942
+ event .originalEvent .dataTransfer .dropEffect = "copy";
2873
2943
  else
2874
- event .originalEvent .dataTransfer .dropEffect = "move"
2944
+ event .originalEvent .dataTransfer .dropEffect = "move";
2875
2945
  }
2876
2946
  else
2877
2947
  {
2878
- event .originalEvent .dataTransfer .dropEffect = "copy"
2948
+ event .originalEvent .dataTransfer .dropEffect = "copy";
2879
2949
  }
2880
2950
 
2881
2951
  if (destinationElement .is (".scene-graph"))
2882
- destinationElement .addClass ("drag-after")
2952
+ {
2953
+ destinationElement .addClass ("drag-after");
2954
+ }
2883
2955
  else if (destinationElement .is (".scene, .externprotos"))
2884
- destinationElement .addClass ("drag-into")
2956
+ {
2957
+ destinationElement .addClass ("drag-into");
2958
+ }
2885
2959
  else if (destinationElement .is (".externproto"))
2886
2960
  {
2887
2961
  const
2888
2962
  item = destinationElement .find ("> .item"),
2889
- y = event .pageY - destinationElement .offset () .top
2963
+ y = event .pageY - destinationElement .offset () .top;
2890
2964
 
2891
2965
  if (y < item .height () * 0.5)
2892
- destinationElement .data ("drag-type", "drag-before")
2966
+ {
2967
+ destinationElement .data ("drag-type", "drag-before");
2968
+ }
2893
2969
  else if (y > destinationElement .height () - item .height () * 0.5)
2894
- destinationElement .data ("drag-type", "drag-after")
2970
+ {
2971
+ destinationElement .data ("drag-type", "drag-after");
2972
+ }
2895
2973
  else
2896
2974
  {
2897
- destinationElement .data ("drag-type", "")
2898
- event .originalEvent .dataTransfer .dropEffect = "none"
2975
+ destinationElement .data ("drag-type", "");
2976
+ event .originalEvent .dataTransfer .dropEffect = "none";
2899
2977
  }
2900
2978
 
2901
- item .addClass (destinationElement .data ("drag-type"))
2979
+ item .addClass (destinationElement .data ("drag-type"));
2902
2980
  }
2903
2981
  else
2904
- event .originalEvent .dataTransfer .dropEffect = "none"
2982
+ {
2983
+ event .originalEvent .dataTransfer .dropEffect = "none";
2984
+ }
2905
2985
  }
2906
2986
  else if (event .originalEvent .dataTransfer .types .includes ("sunrize/proto"))
2907
2987
  {
@@ -2910,13 +2990,13 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2910
2990
  sourceExecutionContextElement = sourceElement .closest (".scene", this .sceneGraph),
2911
2991
  destinationExecutionContextElement = destinationElement .closest (".scene", this .sceneGraph),
2912
2992
  sourceExecutionContext = this .getNode (sourceExecutionContextElement),
2913
- destinationExecutionContext = this .getNode (destinationExecutionContextElement)
2993
+ destinationExecutionContext = this .getNode (destinationExecutionContextElement);
2914
2994
 
2915
2995
  if (sourceExecutionContext === destinationExecutionContext)
2916
2996
  {
2917
2997
  if (event .altKey)
2918
2998
  {
2919
- event .originalEvent .dataTransfer .dropEffect = "copy"
2999
+ event .originalEvent .dataTransfer .dropEffect = "copy";
2920
3000
  }
2921
3001
  else
2922
3002
  {
@@ -2924,9 +3004,9 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2924
3004
  sourceIndex = parseInt (sourceElement .attr ("index")),
2925
3005
  destinationIndex = destinationElement .hasClass ("proto") ? parseInt (destinationElement .attr ("index")) : destinationExecutionContext .protos .length,
2926
3006
  sourceProto = this .getNode (sourceElement),
2927
- destinationProtos = destinationExecutionContext .protos
3007
+ destinationProtos = destinationExecutionContext .protos;
2928
3008
 
2929
- event .originalEvent .dataTransfer .dropEffect = "move"
3009
+ event .originalEvent .dataTransfer .dropEffect = "move";
2930
3010
 
2931
3011
  if (sourceIndex == destinationIndex || sourceIndex + 1 == destinationIndex)
2932
3012
  { }
@@ -2936,8 +3016,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2936
3016
  {
2937
3017
  if (Editor .protoIsUsedInProto (sourceProto, destinationProtos [i]))
2938
3018
  {
2939
- event .originalEvent .dataTransfer .dropEffect = "none"
2940
- break
3019
+ event .originalEvent .dataTransfer .dropEffect = "none";
3020
+ break;
2941
3021
  }
2942
3022
  }
2943
3023
  }
@@ -2947,8 +3027,8 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2947
3027
  {
2948
3028
  if (Editor .protoIsUsedInProto (destinationProtos [i], sourceProto))
2949
3029
  {
2950
- event .originalEvent .dataTransfer .dropEffect = "none"
2951
- break
3030
+ event .originalEvent .dataTransfer .dropEffect = "none";
3031
+ break;
2952
3032
  }
2953
3033
  }
2954
3034
  }
@@ -2956,74 +3036,106 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
2956
3036
  }
2957
3037
  else
2958
3038
  {
2959
- event .originalEvent .dataTransfer .dropEffect = "copy"
3039
+ event .originalEvent .dataTransfer .dropEffect = "copy";
2960
3040
  }
2961
3041
 
2962
3042
  if (event .originalEvent .dataTransfer .dropEffect !== "none")
2963
3043
  {
2964
3044
  if (destinationElement .is (".scene-graph"))
2965
- destinationElement .addClass ("drag-after")
3045
+ {
3046
+ destinationElement .addClass ("drag-after");
3047
+ }
2966
3048
  else if (destinationElement .is (".scene, .protos"))
2967
- destinationElement .addClass ("drag-into")
3049
+ {
3050
+ destinationElement .addClass ("drag-into");
3051
+ }
2968
3052
  else if (destinationElement .is (".proto"))
2969
3053
  {
2970
3054
  const
2971
3055
  item = destinationElement .find ("> .item"),
2972
- y = event .pageY - destinationElement .offset () .top
3056
+ y = event .pageY - destinationElement .offset () .top;
2973
3057
 
2974
3058
  if (y < item .height () * 0.5)
2975
- destinationElement .data ("drag-type", "drag-before")
3059
+ {
3060
+ destinationElement .data ("drag-type", "drag-before");
3061
+ }
2976
3062
  else if (y > destinationElement .height () - item .height () * 0.5)
2977
- destinationElement .data ("drag-type", "drag-after")
3063
+ {
3064
+ destinationElement .data ("drag-type", "drag-after");
3065
+ }
2978
3066
  else
2979
3067
  {
2980
- destinationElement .data ("drag-type", "")
2981
- event .originalEvent .dataTransfer .dropEffect = "none"
3068
+ destinationElement .data ("drag-type", "");
3069
+ event .originalEvent .dataTransfer .dropEffect = "none";
2982
3070
  }
2983
3071
 
2984
- item .addClass (destinationElement .data ("drag-type"))
3072
+ item .addClass (destinationElement .data ("drag-type"));
2985
3073
  }
2986
3074
  else
2987
- event .originalEvent .dataTransfer .dropEffect = "none"
3075
+ {
3076
+ event .originalEvent .dataTransfer .dropEffect = "none";
3077
+ }
2988
3078
  }
2989
3079
  }
2990
- else if (event .originalEvent .dataTransfer .types .includes ("sunrize/nodes"))
3080
+ else if (event .originalEvent .dataTransfer .types .includes ("sunrize/nodes") ||
3081
+ event .originalEvent .dataTransfer .types .includes ("sunrize/imported-node"))
2991
3082
  {
2992
- if (event .altKey)
2993
- event .originalEvent .dataTransfer .dropEffect = "copy"
2994
- else if (event .ctrlKey)
2995
- event .originalEvent .dataTransfer .dropEffect = "link"
2996
- else
2997
- event .originalEvent .dataTransfer .dropEffect = "move"
3083
+ const
3084
+ isImportedNode = event .originalEvent .dataTransfer .types .includes ("sunrize/imported-node"),
3085
+ sourceElement = this .sceneGraph .find (".primary"),
3086
+ sourceExecutionContextElement = sourceElement .closest (".scene", this .sceneGraph),
3087
+ destinationExecutionContextElement = destinationElement .closest (".scene", this .sceneGraph),
3088
+ sourceExecutionContext = this .getNode (sourceExecutionContextElement),
3089
+ destinationExecutionContext = this .getNode (destinationExecutionContextElement);
2998
3090
 
2999
- if (destinationElement .is (".scene-graph"))
3000
- destinationElement .addClass ("drag-after")
3001
- else if (destinationElement .is (".scene, .root-nodes, .field[type-name*=Node]"))
3002
- destinationElement .addClass ("drag-into")
3003
- else if (destinationElement .is (".node"))
3091
+ if (isImportedNode && sourceExecutionContext !== destinationExecutionContext)
3004
3092
  {
3005
- const
3006
- item = destinationElement .find ("> .item"),
3007
- y = event .pageY - destinationElement .offset () .top
3093
+ event .originalEvent .dataTransfer .dropEffect = "none";
3094
+ }
3095
+ else
3096
+ {
3097
+ if (event .altKey)
3098
+ event .originalEvent .dataTransfer .dropEffect = isImportedNode ? "link" : "copy";
3099
+ else if (event .ctrlKey)
3100
+ event .originalEvent .dataTransfer .dropEffect = "link";
3101
+ else
3102
+ event .originalEvent .dataTransfer .dropEffect = "move";
3008
3103
 
3009
- if (y < item .height () * 0.25)
3104
+ if (destinationElement .is (".scene-graph"))
3010
3105
  {
3011
- destinationElement .data ("drag-type", "drag-before")
3012
- destinationElement .addClass ("drag-before")
3106
+ destinationElement .addClass ("drag-after");
3013
3107
  }
3014
- else if (y > destinationElement .height () - item .height () * 0.25)
3108
+ else if (destinationElement .is (".scene, .root-nodes, .field[type-name*=Node]"))
3015
3109
  {
3016
- destinationElement .data ("drag-type", "drag-after")
3017
- destinationElement .addClass ("drag-after")
3110
+ destinationElement .addClass ("drag-into");
3111
+ }
3112
+ else if (destinationElement .is (".node, .imported-node.proxy"))
3113
+ {
3114
+ const
3115
+ item = destinationElement .find ("> .item"),
3116
+ y = event .pageY - destinationElement .offset () .top;
3117
+
3118
+ if (y < item .height () * 0.25)
3119
+ {
3120
+ destinationElement .data ("drag-type", "drag-before");
3121
+ destinationElement .addClass ("drag-before");
3122
+ }
3123
+ else if (y > destinationElement .height () - item .height () * 0.25)
3124
+ {
3125
+ destinationElement .data ("drag-type", "drag-after");
3126
+ destinationElement .addClass ("drag-after");
3127
+ }
3128
+ else
3129
+ {
3130
+ destinationElement .data ("drag-type", "drag-into");
3131
+ destinationElement .addClass ("drag-into");
3132
+ }
3018
3133
  }
3019
3134
  else
3020
3135
  {
3021
- destinationElement .data ("drag-type", "drag-into")
3022
- destinationElement .addClass ("drag-into")
3136
+ event .originalEvent .dataTransfer .dropEffect = "none";
3023
3137
  }
3024
3138
  }
3025
- else
3026
- event .originalEvent .dataTransfer .dropEffect = "none"
3027
3139
  }
3028
3140
  else if (event .originalEvent .dataTransfer .types .includes ("sunrize/field"))
3029
3141
  {
@@ -3031,41 +3143,41 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3031
3143
  {
3032
3144
  const
3033
3145
  sourceElement = this .sceneGraph .find (".primary"),
3034
- sourceNode = this .getNode (sourceElement)
3146
+ sourceNode = this .getNode (sourceElement);
3035
3147
 
3036
3148
  const
3037
3149
  destinationNode = this .getNode (destinationElement),
3038
3150
  destinationField = this .getField (destinationElement),
3039
- userDefined = destinationNode .getUserDefinedFields () .has (destinationField .getName ())
3151
+ userDefined = destinationNode .getUserDefinedFields () .has (destinationField .getName ());
3040
3152
 
3041
3153
  if (destinationNode === sourceNode && userDefined)
3042
3154
  {
3043
- event .originalEvent .dataTransfer .dropEffect = "move"
3155
+ event .originalEvent .dataTransfer .dropEffect = "move";
3044
3156
 
3045
3157
  const
3046
3158
  item = destinationElement .find ("> .item"),
3047
- y = event .pageY - destinationElement .offset () .top
3159
+ y = event .pageY - destinationElement .offset () .top;
3048
3160
 
3049
3161
  if (y < item .height () * 0.5)
3050
3162
  {
3051
- destinationElement .data ("drag-type", "drag-before")
3052
- destinationElement .addClass ("drag-before")
3163
+ destinationElement .data ("drag-type", "drag-before");
3164
+ destinationElement .addClass ("drag-before");
3053
3165
  }
3054
3166
  else if (y > destinationElement .height () - item .height () * 0.5)
3055
3167
  {
3056
- destinationElement .data ("drag-type", "drag-after")
3057
- destinationElement .addClass ("drag-after")
3168
+ destinationElement .data ("drag-type", "drag-after");
3169
+ destinationElement .addClass ("drag-after");
3058
3170
  }
3059
3171
  else
3060
3172
  {
3061
- event .originalEvent .dataTransfer .dropEffect = "none"
3173
+ event .originalEvent .dataTransfer .dropEffect = "none";
3062
3174
  }
3063
3175
  }
3064
3176
  }
3065
3177
  }
3066
3178
  }
3067
3179
 
3068
- destinationElement .data ("dropEffect", event .originalEvent .dataTransfer .dropEffect)
3180
+ destinationElement .data ("dropEffect", event .originalEvent .dataTransfer .dropEffect);
3069
3181
  }
3070
3182
 
3071
3183
  onDragLeave (event)
@@ -3234,9 +3346,12 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3234
3346
  }
3235
3347
  }
3236
3348
  }
3237
- else if (event .originalEvent .dataTransfer .types .includes ("sunrize/nodes"))
3349
+ else if (event .originalEvent .dataTransfer .types .includes ("sunrize/nodes") ||
3350
+ event .originalEvent .dataTransfer .types .includes ("sunrize/imported-node"))
3238
3351
  {
3239
- const sourceElementsIds = event .originalEvent .dataTransfer .getData ("sunrize/nodes") .split (",");
3352
+ const sourceElementsIds = event .originalEvent .dataTransfer .types .includes ("sunrize/imported-node")
3353
+ ? event .originalEvent .dataTransfer .getData ("sunrize/imported-node") .split (",")
3354
+ : event .originalEvent .dataTransfer .getData ("sunrize/nodes") .split (",");
3240
3355
 
3241
3356
  const
3242
3357
  destinationElement = $(event .target) .closest ("li, .scene", this .sceneGraph),
@@ -3411,14 +3526,17 @@ module .exports = class OutlineEditor extends OutlineRouteGraph
3411
3526
 
3412
3527
  if (destinationElement .data ("dropEffect") ?.match (/copy|move/))
3413
3528
  {
3414
- if (sourceNode ?.getType () .some (type => this .transformLikeNodes .has (type)))
3529
+ if (!(sourceNode instanceof X3D .X3DImportedNodeProxy))
3415
3530
  {
3416
- const
3417
- sourceModelMatrix = this .getModelMatrix (sourceElement),
3418
- destinationModelMatrix = this .getModelMatrix (destinationParentNodeElement);
3531
+ if (sourceNode ?.getType () .some (type => this .transformLikeNodes .has (type)))
3532
+ {
3533
+ const
3534
+ sourceModelMatrix = this .getModelMatrix (sourceElement),
3535
+ destinationModelMatrix = this .getModelMatrix (destinationParentNodeElement);
3419
3536
 
3420
- destinationModelMatrix .inverse () .multLeft (sourceModelMatrix);
3421
- Editor .setMatrixWithCenter (sourceNode, destinationModelMatrix);
3537
+ destinationModelMatrix .inverse () .multLeft (sourceModelMatrix);
3538
+ Editor .setMatrixWithCenter (sourceNode, destinationModelMatrix);
3539
+ }
3422
3540
  }
3423
3541
  }
3424
3542