@@ -10294,6 +10294,96 @@ LGraphNode.prototype.executeAction = function(action)
1029410294 canvas . graph . add ( group ) ;
1029510295 } ;
1029610296
10297+ /**
10298+ * Determines the furthest nodes in each direction
10299+ * @param nodes {LGraphNode[]} the nodes to from which boundary nodes will be extracted
10300+ * @return {{left: LGraphNode, top: LGraphNode, right: LGraphNode, bottom: LGraphNode} }
10301+ */
10302+ LGraphCanvas . getBoundaryNodes = function ( nodes ) {
10303+ let top = null ;
10304+ let right = null ;
10305+ let bottom = null ;
10306+ let left = null ;
10307+ for ( const nID in nodes ) {
10308+ const node = nodes [ nID ] ;
10309+ const [ x , y ] = node . pos ;
10310+ const [ width , height ] = node . size ;
10311+
10312+ if ( top === null || y < top . pos [ 1 ] ) {
10313+ top = node ;
10314+ }
10315+ if ( right === null || x + width > right . pos [ 0 ] + right . size [ 0 ] ) {
10316+ right = node ;
10317+ }
10318+ if ( bottom === null || y + height > bottom . pos [ 1 ] + bottom . size [ 1 ] ) {
10319+ bottom = node ;
10320+ }
10321+ if ( left === null || x < left . pos [ 0 ] ) {
10322+ left = node ;
10323+ }
10324+ }
10325+
10326+ return {
10327+ "top" : top ,
10328+ "right" : right ,
10329+ "bottom" : bottom ,
10330+ "left" : left
10331+ } ;
10332+ }
10333+ /**
10334+ * Determines the furthest nodes in each direction for the currently selected nodes
10335+ * @return {{left: LGraphNode, top: LGraphNode, right: LGraphNode, bottom: LGraphNode} }
10336+ */
10337+ LGraphCanvas . prototype . boundaryNodesForSelection = function ( ) {
10338+ return LGraphCanvas . getBoundaryNodes ( Object . values ( this . selected_nodes ) ) ;
10339+ }
10340+
10341+ /**
10342+ *
10343+ * @param {LGraphNode[] } nodes a list of nodes
10344+ * @param {"top"|"bottom"|"left"|"right" } direction Direction to align the nodes
10345+ */
10346+ LGraphCanvas . alignNodes = function ( nodes , direction ) {
10347+ if ( ! nodes ) {
10348+ return ;
10349+ }
10350+
10351+ const canvas = LGraphCanvas . active_canvas ;
10352+ const boundaryNodes = LGraphCanvas . getBoundaryNodes ( nodes )
10353+
10354+ for ( const [ _ , node ] of Object . entries ( canvas . selected_nodes ) ) {
10355+ switch ( direction ) {
10356+ case "right" :
10357+ node . pos [ 0 ] = boundaryNodes [ "right" ] . pos [ 0 ] + boundaryNodes [ "right" ] . size [ 0 ] - node . size [ 0 ] ;
10358+ break ;
10359+ case "left" :
10360+ node . pos [ 0 ] = boundaryNodes [ "left" ] . pos [ 0 ] ;
10361+ break ;
10362+ case "top" :
10363+ node . pos [ 1 ] = boundaryNodes [ "top" ] . pos [ 1 ] ;
10364+ break ;
10365+ case "bottom" :
10366+ node . pos [ 1 ] = boundaryNodes [ "bottom" ] . pos [ 1 ] + boundaryNodes [ "bottom" ] . size [ 1 ] - node . size [ 1 ] ;
10367+ break ;
10368+ }
10369+ }
10370+
10371+ canvas . dirty_canvas = true ;
10372+ canvas . dirty_bgcanvas = true ;
10373+ } ;
10374+
10375+ LGraphCanvas . onGroupAlign = function ( value , options , event , prev_menu ) {
10376+ new LiteGraph . ContextMenu ( [ "Top" , "Bottom" , "Left" , "Right" ] , {
10377+ event : event ,
10378+ callback : inner_clicked ,
10379+ parentMenu : prev_menu ,
10380+ } ) ;
10381+
10382+ function inner_clicked ( value ) {
10383+ LGraphCanvas . alignNodes ( LGraphCanvas . active_canvas . selected_nodes , value . toLowerCase ( ) ) ;
10384+ }
10385+ }
10386+
1029710387 LGraphCanvas . onMenuAdd = function ( node , options , e , prev_menu , callback ) {
1029810388
1029910389 var canvas = LGraphCanvas . active_canvas ;
@@ -12887,6 +12977,7 @@ LGraphNode.prototype.executeAction = function(action)
1288712977 callback : LGraphCanvas . onMenuAdd
1288812978 } ,
1288912979 { content : "Add Group" , callback : LGraphCanvas . onGroupAdd } ,
12980+ { content : "Align" , has_submenu : true , callback : LGraphCanvas . onGroupAlign } ,
1289012981 //{ content: "Arrange", callback: that.graph.arrange },
1289112982 //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll }
1289212983 ] ;
0 commit comments