@@ -46,6 +46,16 @@ export class Editor {
4646
4747 readonly scene :ThreeScene ;
4848
49+ /**
50+ * Start of a box selection. In canva's coordinate.
51+ */
52+ private boxSelectionStart ?:Vector2Like ;
53+
54+ /**
55+ * Nodes selected...
56+ */
57+ private selectedNodes :Node [ ] = [ ]
58+
4959 /**
5060 * An object that will intercept and handle the mouse events.
5161 */
@@ -141,6 +151,12 @@ export class Editor {
141151 const mousePos = this . getMousePos ( event ) ;
142152 const canvasPos = this . getCanvasMousePosition ( mousePos ) ;
143153
154+ // if( this.boxSelectionStart )
155+ // {
156+ // this.selectNodesInsideBoxSelection(this.boxSelectionStart, canvasPos);
157+ // return;
158+ // }
159+
144160 let sx = ( mousePos . x - this . mouse . x ) ;
145161 let sy = ( mousePos . y - this . mouse . y ) ;
146162
@@ -161,8 +177,21 @@ export class Editor {
161177 }
162178 else if ( this . focusedChild )
163179 {
164- this . focusedChild . x += sx ;
165- this . focusedChild . y += sy ;
180+ //this.focusedChild.x += sx;
181+ //this.focusedChild.y += sy;
182+
183+ // move the selection
184+ this . selectedNodes . forEach ( node => {
185+ node . x += sx ;
186+ node . y += sy ;
187+ } )
188+ }
189+ else if ( this . boxSelectionStart )
190+ {
191+ //
192+ // update box selection
193+ //
194+ this . selectNodesInsideBoxSelection ( this . boxSelectionStart , canvasPos ) ;
166195 }
167196 else
168197 {
@@ -189,11 +218,12 @@ export class Editor {
189218 // main mouse button to move stuff arround...
190219 else if ( ev . button == 0 )
191220 {
192- const cursor = this . getCanvasMousePosition ( this . mouse ) ;
193-
221+ const cursor = this . getCanvasMousePosition ( this . mouse ) ;
194222
195223 if ( this . overlay )
196224 {
225+ this . clearBoxSelection ( ) ;
226+
197227 if ( this . clickElementAt ( this . mouse , this . overlay . overlayBody ) )
198228 {
199229 return ;
@@ -248,7 +278,10 @@ export class Editor {
248278
249279 } ) ;
250280
251- if ( this . selectedOutlet ) continue ;
281+ if ( this . selectedOutlet ) {
282+ this . clearBoxSelection ( ) ;
283+ break ;
284+ }
252285 //#endregion
253286
254287 //#region Click on element...
@@ -268,14 +301,17 @@ export class Editor {
268301 // default: mouse down on the node window.
269302 //
270303 if ( cursor . x > obj . x && cursor . x < obj . x + obj . width ( this . ctx ) && cursor . y > obj . y && cursor . y < obj . y + obj . height ( this . ctx ) )
271- {
304+ {
272305 // default... will make the object move...
273306 this . focusedChild = obj ;
274307 this . bingToTop ( obj ) ;
308+
309+
310+
275311 break ; //<-- to avoid processing childrens under us....
276- }
312+ }
277313
278- } ;
314+ } ;
279315
280316 //
281317 // if we clicked an outlet, we need to know which of the available outlets are valid to be connected to...
@@ -295,6 +331,31 @@ export class Editor {
295331 } ) ;
296332 }
297333
334+ //
335+ // if we selected a child...
336+ //
337+ else
338+ {
339+ if ( this . focusedChild )
340+ {
341+ if ( ! this . selectedNodes . includes ( this . focusedChild ) )
342+ {
343+ this . clearBoxSelection ( )
344+ this . selectedNodes . push ( this . focusedChild ) ;
345+ }
346+
347+ return ;
348+ }
349+ else
350+ {
351+ this . clearBoxSelection ( ) ;
352+ }
353+
354+ this . boxSelectionStart = cursor ;
355+
356+ console . log ( "START SELECTION" )
357+ }
358+
298359 }
299360 } ) ;
300361 //#endregion
@@ -304,6 +365,8 @@ export class Editor {
304365
305366 const cursor = this . getCanvasMousePosition ( this . mouse ) ;
306367
368+ this . boxSelectionStart = undefined ;
369+
307370 if ( this . eventsHandler )
308371 {
309372 this . eventsHandler . onMouseUp ( ) ;
@@ -686,6 +749,64 @@ export class Editor {
686749
687750 }
688751
752+ protected drawBoxSelection ( ctx :CanvasRenderingContext2D ) {
753+ if ( ! this . boxSelectionStart ) return ;
754+
755+ const cursor = this . getCanvasMousePosition ( this . mouse ) ;
756+
757+ ctx . save ( ) ;
758+ ctx . beginPath ( )
759+
760+ ctx . rect ( this . boxSelectionStart . x , this . boxSelectionStart . y ,
761+ cursor . x - this . boxSelectionStart . x ,
762+ cursor . y - this . boxSelectionStart . y
763+ ) ;
764+
765+ ctx . lineWidth = 2
766+ ctx . setLineDash ( [ 3 , 3 ] ) ;
767+ ctx . strokeStyle = Theme . config . selectionBoxColor ;
768+ ctx . stroke ( ) ;
769+ ctx . restore ( )
770+ }
771+
772+ protected clearBoxSelection ( ) {
773+ this . selectedNodes . length = 0 ;
774+ }
775+
776+ /**
777+ * Select the nodes inside the box...
778+ * @param poin1 In canva's coordinate
779+ * @param point2 In canva's coordinate
780+ */
781+ protected selectNodesInsideBoxSelection ( point1 :Vector2Like , point2 :Vector2Like )
782+ {
783+ // reset
784+ this . selectedNodes . length = 0 ;
785+
786+ const left = Math . min ( point1 . x , point2 . x ) ;
787+ const right = Math . max ( point1 . x , point2 . x ) ;
788+ const top = Math . min ( point1 . y , point2 . y ) ;
789+ const bottom = Math . max ( point1 . y , point2 . y ) ;
790+
791+ const ctx = this . _ctx ;
792+
793+ this . objs . forEach ( node => {
794+
795+ const objLeft = node . x ;
796+ const objRight = node . x + node . width ( ctx ) ;
797+ const objTop = node . y ;
798+ const objBottom = node . y + node . height ( ctx ) ;
799+
800+ const overlaps = ( left <= objRight &&
801+ right >= objLeft &&
802+ top <= objBottom &&
803+ bottom >= objTop ) ;
804+
805+ if ( overlaps ) this . selectedNodes . push ( node ) ;
806+
807+ } ) ;
808+ }
809+
689810 start ( ) {
690811
691812 this . scene . render ( )
@@ -704,13 +825,15 @@ export class Editor {
704825
705826 ctx . save ( ) ;
706827
828+ obj . selected = this . selectedNodes . includes ( obj )
707829 obj . draw ( ctx ) ;
708830
709831 ctx . restore ( ) ;
710832
711833 } ) ;
712834
713- this . drawAvailableConnectionPipes ( ctx ) ;
835+ this . drawAvailableConnectionPipes ( ctx ) ;
836+ this . drawBoxSelection ( ctx ) ;
714837
715838 ctx . save ( )
716839 this . overlay ?. renderOverlay ( ctx ) ;
0 commit comments