lexgui 0.1.30 → 0.1.32

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.
@@ -352,6 +352,11 @@ class GraphEditor {
352
352
  node.position = new LX.vec2( 0, 0 );
353
353
  node.color = null;
354
354
 
355
+ if( baseClass.name == 'NodeFunction' )
356
+ {
357
+ node.gid = baseClass.gid;
358
+ }
359
+
355
360
  // Extra options
356
361
  if ( options ) {
357
362
  for (var i in options) {
@@ -450,7 +455,17 @@ class GraphEditor {
450
455
  let graph = new Graph();
451
456
  graph.editor = this;
452
457
 
453
- if( o ) graph.configure( o );
458
+ if( o )
459
+ {
460
+ // Load functions first if any..
461
+
462
+ for( let fn of o.functions ?? [] )
463
+ {
464
+ this.addGraphFunction( fn );
465
+ }
466
+
467
+ graph.configure( o );
468
+ }
454
469
 
455
470
  this.setGraph( graph );
456
471
 
@@ -471,7 +486,17 @@ class GraphEditor {
471
486
  let func = new GraphFunction();
472
487
  func.editor = this;
473
488
 
474
- if( o ) func.configure( o );
489
+ if( o )
490
+ {
491
+ // Load other inner functions first if any..
492
+
493
+ for( let fn of o.functions ?? [] )
494
+ {
495
+ this.addGraphFunction( fn );
496
+ }
497
+
498
+ func.configure( o );
499
+ }
475
500
 
476
501
  this.setGraph( func );
477
502
 
@@ -492,6 +517,7 @@ class GraphEditor {
492
517
  }
493
518
 
494
519
  NodeFunction.func = func;
520
+ NodeFunction.gid = func.id;
495
521
  GraphEditor.registerCustomNode( "function/" + func.name, NodeFunction );
496
522
 
497
523
  this._sidebar.add( func.name, { icon: "fa fa-florin-sign", className: func.id, callback: (e) => { this.setGraph( func ) } } );
@@ -642,13 +668,16 @@ class GraphEditor {
642
668
  LX.addContextMenu(null, e, m => {
643
669
 
644
670
  m.add( "Copy", () => {
645
- this._clipboardData = node.id;
671
+ this._clipboardData = {
672
+ id: node.id,
673
+ gid: this.currentGraph.id
674
+ };
646
675
  } );
647
676
 
648
- m.add( "Paste", () => {
649
- // TODO
650
- // ...
651
- } );
677
+ // TODO
678
+ // m.add( "Paste", () => {
679
+
680
+ // } );
652
681
 
653
682
  m.add( "" );
654
683
 
@@ -1315,6 +1344,28 @@ class GraphEditor {
1315
1344
  this.currentGraph.groups.splice( idx, 1 );
1316
1345
  }
1317
1346
 
1347
+ _cloneNode( nodeId, graphId, position ) {
1348
+
1349
+ const graph = this.graphs[ graphId ?? this.currentGraph.id ];
1350
+
1351
+ const nodeData = graph.getNodeById( nodeId );
1352
+
1353
+ if( !nodeData )
1354
+ return;
1355
+
1356
+ const el = this._getNodeDOMElement( nodeId );
1357
+ const newNode = GraphEditor.addNode( nodeData.type );
1358
+ newNode.properties = LX.deepCopy( nodeData.properties );
1359
+
1360
+ const newDom = this._createNodeDOM( newNode );
1361
+
1362
+ this._translateNode( newDom, position ?? this._getNodePosition( el ) );
1363
+
1364
+ this._selectNode( newDom, true );
1365
+
1366
+ this.currentGraph.nodes.push( newNode );
1367
+ }
1368
+
1318
1369
  _cloneNodes() {
1319
1370
 
1320
1371
  // Clone all selected nodes
@@ -1324,20 +1375,7 @@ class GraphEditor {
1324
1375
 
1325
1376
  for( let nodeId of selectedIds )
1326
1377
  {
1327
- const nodeInfo = this.nodes[ nodeId ];
1328
- if( !nodeInfo )
1329
- return;
1330
-
1331
- const el = this._getNodeDOMElement( nodeId );
1332
- const data = nodeInfo.data;
1333
- const newNode = GraphEditor.addNode( data.type );
1334
- const newDom = this._createNodeDOM( newNode );
1335
-
1336
- this._translateNode( newDom, this._getNodePosition( el ) );
1337
-
1338
- this._selectNode( newDom, true );
1339
-
1340
- this.currentGraph.nodes.push( newNode );
1378
+ this._cloneNode( nodeId );
1341
1379
  }
1342
1380
  }
1343
1381
 
@@ -1706,80 +1744,86 @@ class GraphEditor {
1706
1744
 
1707
1745
  _processContextMenu( e, autoConnect ) {
1708
1746
 
1709
- if( this._clipboardData )
1710
- {
1711
- LX.addContextMenu(null, e, m => {
1712
- m.add( "Paste", () => {
1713
- // TODO: paste node data
1714
- // ...
1715
- } );
1716
- });
1717
- }
1718
- else
1719
- {
1720
- LX.addContextMenu( "ADD NODE", e, m => {
1721
-
1722
- for( let type in GraphEditor.NODE_TYPES )
1723
- {
1724
- const baseClass = GraphEditor.NODE_TYPES[ type ];
1747
+ LX.addContextMenu( null, e, m => {
1725
1748
 
1726
- if( baseClass.blockAdd )
1727
- continue;
1749
+ var eventPosition = null;
1728
1750
 
1729
- m.add( type, () => {
1751
+ if( e )
1752
+ {
1753
+ const rect = this.root.getBoundingClientRect();
1730
1754
 
1731
- const newNode = GraphEditor.addNode( type );
1755
+ const localPosition = new LX.vec2( e.clientX - rect.x, e.clientY - rect.y );
1732
1756
 
1733
- const dom = this._createNodeDOM( newNode );
1757
+ eventPosition = this._getPatternPosition( localPosition );
1758
+ }
1734
1759
 
1735
- if( this._snapToGrid )
1736
- {
1737
- dom.mustSnap = true;
1738
- }
1760
+ if( this._clipboardData )
1761
+ {
1762
+ m.add( "Paste", () => {
1739
1763
 
1740
- if( e )
1741
- {
1742
- const rect = this.root.getBoundingClientRect();
1764
+ const nodeId = this._clipboardData.id;
1765
+ const graphId = this._clipboardData.gid;
1743
1766
 
1744
- let position = new LX.vec2( e.clientX - rect.x, e.clientY - rect.y );
1767
+ this._cloneNode( nodeId, graphId, eventPosition );
1745
1768
 
1746
- position = this._getPatternPosition( position );
1769
+ } );
1770
+ m.add( "" );
1771
+ }
1747
1772
 
1748
- this._translateNode( dom, position );
1749
- }
1773
+ for( let type in GraphEditor.NODE_TYPES )
1774
+ {
1775
+ const baseClass = GraphEditor.NODE_TYPES[ type ];
1750
1776
 
1751
- this.currentGraph.nodes.push( newNode );
1777
+ if( baseClass.blockAdd )
1778
+ continue;
1752
1779
 
1753
- if( autoConnect && newNode.inputs.length )
1754
- {
1755
- const srcId = autoConnect.domEl.dataset[ 'id' ];
1756
- const srcType = autoConnect.io.childNodes[ autoConnect.index ].dataset[ 'type' ];
1757
- const srcIsInput = autoConnect.ioType == GraphEditor.NODE_IO_INPUT;
1780
+ m.add( type, () => {
1758
1781
 
1759
- const newLink = {
1760
- inputNode: srcIsInput ? srcId : newNode.id,
1761
- inputIdx: srcIsInput ? autoConnect.index : 0,
1762
- inputType: srcIsInput ? srcType : newNode.inputs[ 0 ].type,
1763
- outputNode: srcIsInput ? newNode.id : srcId,
1764
- outputIdx: srcIsInput ? 0 : autoConnect.index,
1765
- outputType: srcIsInput ? newNode.inputs[ 0 ].type : srcType,
1766
- }
1782
+ const newNode = GraphEditor.addNode( type );
1767
1783
 
1768
- // Store link
1784
+ const dom = this._createNodeDOM( newNode );
1769
1785
 
1770
- const pathId = newLink.outputNode + '@' + newLink.inputNode;
1786
+ if( this._snapToGrid )
1787
+ {
1788
+ dom.mustSnap = true;
1789
+ }
1771
1790
 
1772
- if( !this.currentGraph.links[ pathId ] ) this.currentGraph.links[ pathId ] = [];
1791
+ if( eventPosition )
1792
+ {
1793
+ this._translateNode( dom, eventPosition );
1794
+ }
1773
1795
 
1774
- this.currentGraph.links[ pathId ].push( newLink );
1796
+ this.currentGraph.nodes.push( newNode );
1775
1797
 
1776
- this._createLink( newLink );
1798
+ if( autoConnect && newNode.inputs.length )
1799
+ {
1800
+ const srcId = autoConnect.domEl.dataset[ 'id' ];
1801
+ const srcType = autoConnect.io.childNodes[ autoConnect.index ].dataset[ 'type' ];
1802
+ const srcIsInput = autoConnect.ioType == GraphEditor.NODE_IO_INPUT;
1803
+
1804
+ const newLink = {
1805
+ inputNode: srcIsInput ? srcId : newNode.id,
1806
+ inputIdx: srcIsInput ? autoConnect.index : 0,
1807
+ inputType: srcIsInput ? srcType : newNode.inputs[ 0 ].type,
1808
+ outputNode: srcIsInput ? newNode.id : srcId,
1809
+ outputIdx: srcIsInput ? 0 : autoConnect.index,
1810
+ outputType: srcIsInput ? newNode.inputs[ 0 ].type : srcType,
1777
1811
  }
1778
1812
 
1779
- } );
1780
- }
1781
- });
1782
- }
1813
+ // Store link
1814
+
1815
+ const pathId = newLink.outputNode + '@' + newLink.inputNode;
1816
+
1817
+ if( !this.currentGraph.links[ pathId ] ) this.currentGraph.links[ pathId ] = [];
1818
+
1819
+ this.currentGraph.links[ pathId ].push( newLink );
1820
+
1821
+ this._createLink( newLink );
1822
+ }
1823
+
1824
+ } );
1825
+ }
1826
+ });
1783
1827
  }
1784
1828
 
1785
1829
  /**
@@ -2683,21 +2727,47 @@ class GraphEditor {
2683
2727
 
2684
2728
  _showRenameGraphDialog() {
2685
2729
 
2686
- new LX.Dialog( this.currentGraph.constructor.name, p => {
2687
- p.addText( "Name", this.currentGraph.name, v => this._updateGraphName(v) );
2730
+ const dialog = new LX.Dialog( this.currentGraph.constructor.name, p => {
2731
+ p.addText( "Name", this.currentGraph.name, v => {
2732
+ this._updateGraphName( v );
2733
+ dialog.close();
2734
+ } );
2688
2735
  }, { modal: true, size: [ "350px", null ] } );
2689
2736
  }
2690
2737
 
2691
2738
  _updateGraphName( name ) {
2692
2739
 
2693
- this.currentGraph.name = name;
2740
+ const newNameKey = name.replace( /\s/g, '' ).replaceAll( '.', '' );
2694
2741
 
2742
+ // Change graph name button
2695
2743
  const nameDom = LX.root.querySelector( '.graph-title button' );
2696
2744
  console.assert( nameDom );
2697
2745
  nameDom.innerText = name;
2698
2746
 
2699
- // TODO:
2700
- // Update name in sidebar and all references in current nodes..
2747
+ // Change name in sidebar
2748
+ const graphNameKey = this.currentGraph.name.replace( /\s/g, '' ).replaceAll( '.', '' );
2749
+ const sidebarItem = this._sidebar.items.find( v => v.name === graphNameKey );
2750
+ if( sidebarItem )
2751
+ {
2752
+ sidebarItem.name = newNameKey;
2753
+ sidebarItem.domEl.id = newNameKey;
2754
+ sidebarItem.domEl.querySelector(".lexsidebarentrydesc").innerText = name;
2755
+ }
2756
+
2757
+ // Change registered nodes function
2758
+ const oldType = 'function/' + this.currentGraph.name;
2759
+ const nodeClass = GraphEditor.NODE_TYPES[ oldType ];
2760
+
2761
+ if( nodeClass )
2762
+ {
2763
+ delete GraphEditor.NODE_TYPES[ oldType ];
2764
+
2765
+ nodeClass.title = name;
2766
+
2767
+ GraphEditor.registerCustomNode( "function/" + name, nodeClass );
2768
+ }
2769
+
2770
+ this.currentGraph.name = name;
2701
2771
  }
2702
2772
 
2703
2773
  _addGlobalActions() {
@@ -2762,6 +2832,18 @@ class Graph {
2762
2832
  // zoom/translation ??
2763
2833
  }
2764
2834
 
2835
+ /**
2836
+ * @method getNodeById
2837
+ */
2838
+
2839
+ getNodeById( id ) {
2840
+
2841
+ for( let node of this.nodes )
2842
+ {
2843
+ if( node.id == id ) return node;
2844
+ }
2845
+ }
2846
+
2765
2847
  /**
2766
2848
  * @method _runStep
2767
2849
  */
@@ -2828,12 +2910,12 @@ class Graph {
2828
2910
  }
2829
2911
 
2830
2912
  /**
2831
- * @method export
2913
+ * @method serialize
2832
2914
  * @param {Boolean} prettify
2833
2915
  * @returns JSON data from the serialized graph
2834
2916
  */
2835
2917
 
2836
- export( prettify = true ) {
2918
+ serialize( prettify = true ) {
2837
2919
 
2838
2920
  var o = { };
2839
2921
 
@@ -2841,13 +2923,21 @@ class Graph {
2841
2923
  o.name = this.name;
2842
2924
  o.type = this.type;
2843
2925
 
2844
- o.nodes = [ ];
2845
- o.groups = [ ];
2846
- o.links = { };
2926
+ o.nodes = [ ];
2927
+ o.groups = [ ];
2928
+ o.functions = [ ];
2929
+ o.links = { };
2847
2930
 
2848
2931
  for( let node of this.nodes )
2849
2932
  {
2850
2933
  o.nodes.push( node.serialize() );
2934
+
2935
+ const fnOrigin = this.editor.graphs[ node.gid ];
2936
+
2937
+ if( fnOrigin )
2938
+ {
2939
+ o.functions.push( JSON.parse( fnOrigin.serialize() ) );
2940
+ }
2851
2941
  }
2852
2942
 
2853
2943
  for( let linkId in this.links )
@@ -2880,10 +2970,19 @@ class Graph {
2880
2970
  console.error( `Can't export GraphNode [${ this.title }] of type [${ this.type }].` );
2881
2971
  }
2882
2972
 
2883
- LX.downloadFile( this.name + ".json", o );
2884
-
2885
2973
  return o;
2886
2974
  }
2975
+
2976
+ /**
2977
+ * @method export
2978
+ */
2979
+
2980
+ export() {
2981
+
2982
+ const o = this.serialize();
2983
+
2984
+ LX.downloadFile( this.name + ".json", o );
2985
+ }
2887
2986
  }
2888
2987
 
2889
2988
  LX.Graph = Graph;