HISE Logo Forum
    • Categories
    • Register
    • Login

    Making a Rectangular Selection Tool

    Scheduled Pinned Locked Moved Scripting
    3 Posts 2 Posters 252 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • E
      ericchesek
      last edited by ericchesek

      Hello! I had an idea to make a rectangular or box selection tool so you can click and drag over multiple components and change their settings all at once in a HISE instrument.

      The snippet below includes a panel with my box-drawing script, and two buttons.
      The goal is as follows:
      While clicking and dragging - set the button value to 1 if the rectangle intersects with the button. Set the button value back to 0 if the rectangle no longer intersects with the button. This is basically collision detection.
      On mouse release - do nothing to the button states

      Maybe the box drawing can be optimized. I am interested to hear people's thoughts and solutions!

      HiseSnippet 1740.3ocsXstaaTDEd2jrArKEnBd.l1eTsoJI0tsDPJAHM2Zsn4B0oswBgJa1cr8nrdlUyNabrph3u7XwiBOB7F.myL683bgHp+gkmys4aNy4xb7ARgOMNVHsrab3jHpk8m4zcBWMbygdLtUmsrr+JmWS8Ud7AIgdxtzPXg0FSh7hioAV11y9BTP6FyYo+72+3FdgdbeZAIKq2JX9zWwFwTETOX8ehEFtiW.8P1nRR+r063K3aJBEI.nl0okUjm+IdCn64ghMiik87aGvTBYWkmhFaYO2FhfIcGJFyMx+VVL63PJtnsUWvPFx6HBCPDiTs1bHKL3frCerEXkCJbEyZbEesytr.VN8BWxWpYPJznr+vdlpva1JvqcY30pD7lBjrKAo4LP5dNc8krHUAGDO2woCWQk88.2dYnXj0Zl+3NNaJ.I3pkG4cBcGIrHWC2UZ0ZQB70Bq1DjJVDRW1Oj5IcABMe7iIaIHbghHS3DFmnFRIdIALA7KI0KnoNbY4.ZepbSuvvigaqXWkLglpNZSH7QE2zG+E4TOI4Uc1a620YqCeI46IsWsFiM2+U6+ZfQqyVYkczeLF5ETkd2eSGhuXTjfSqZzHdHnU1Ac.UsYlTtO.38fEJuQGq3stToQlWP71Wk3sQwMGWvon.WDIBhV.ulHQw3ThRPBjdiA5RS1THkLdHkS7CY9mv3CdLvdv.3GMArtbLUc.p+qMp61Og6qXBt6fEZ9glMZ1.1IVes6XjHIlRXwFKQCHiYpgoWTQdbZXyFfjt.s3kC7TdKmJ2BMa7AvPnkjz3Te6wIJkfCG4vDZLw02iSNFOL8ERRnPDs.pA5dPD9VTJWLtQSqccZFim5P.uXL5EhGJjfOjDqR52Gj.8tiYApgf6UiQv29Nbsq1FH6gT1fgpR7eolPg.LNScTFe8YTSoL6dWfcuL1GIogU3hDxX1qNydkXdjehrpl.gbMqyrWJSiaoalGWjvChIh9DnDAoOnHRsHHAuBhURpxeXpgoACn3ocWOHuSBRQcQDuXdR0hZ+4RZePtOB0pWUs5UUKiaVqVub03zAaOk8CNJ02u5pTeypphYyJElrKTXp1Qe7PlhBbGfAVlNBt4EHJo5VXhEpZrt6DjlTXjUMh7yIdP9EjO9Lh6H.TT3KlOTtZh1NXBh9x7GRikd3CM2el08fbkFPZGBELKFaH59KZIWTyeQ8ch96d+5hEk2zF+7ZP3oDf.MDSZy1109OrsY2Ho6rVwkxIdyfP6Uu.DpexWqDDHS+nmcQmd50xmgjqGCOY0q0Mr1MwMjihZdha.bPD8HxgPji+PHVfBwoXIJUhjWpZHjbxM0pA4ypRWKTUbJUm3NBJWBrigZVR58IO5wlcASKBECX9Goa3Q.+PTHz6cH9lDYYAvrlV0EfXrB5mtut36frBsKf9pTKm8qB+U0B0syN2mWz.wz7HIpYwMw8mZmhZIo5FKDEbQFG4Igtf5zz9vK5ddXnaqyZk9A2xyadN1bLss1t3Nl8Pgh9ZzSAin6sgXPupdipKfKyiGz.Kq+Edoy7BIPzC73HRjHloqGnu9PAzpRF5EEQ4wULZVSDyde1pWfYublSxYJo517tlyYIriwIF+FfN35BQD5mHGQ73Ajd4PqJHR6nLULzqLODBoVlSGWbPEkeTPpW.JyCU6NUGaq0prmppKJ0yVESlVfoGryHKUuO6B0vYE4mbA46sv069z3+MQW0UeqKwJPvVVTEj3tmPQ2m6Zd0z4MI0Y0u+T4gOzSJfRBxoxFGYQdUJ5xSFcLUtn4kT4BBuiu5vANW9vAkmcw27tyRBJ3c.W49PT7kMQiU5iUgAIlIEUfnJ8XDed5XDanKvYwfoEl2AqVXowKLM17YytYcS0s8Tz8Mc1BtzvQYRAC.vHpTwvyt8VzSg4BMC1zvYKZ7IJQDrO4Os1x9SL64cyF6AK6n2RGGndh0YEyMt25SJu.JvHFmOOhk8W3.ElHEDzOYIWg+52W27fjBSLYcqR3XtqyuUfj+LrLRBpXl4uNW3kXl0iVuJfs9sK.30V25hyKBSpJBfA2UUGeEmYOkAD1VYlQbtPNTRXR4Y5+eal1aJDumyAL3EuSGiyLELhQ4eDvX5+Dvcc1teenYeA.myYmi93L1ukYluAvamkLHdvYujQcgm95SgcmCw+XYC6YvLSy5V3ZzCzkxCzK9G3SJy13Z6TlsyXZMxyWJduuI0F+uF9TME.Sb8eyRCmcw0j7jZGmVK2xZDKf8dee73uDTyY557jagNO8VnyytE57M2BcV4Vny2dKz46tRcv+wommnDiLoC.gC1VWb01datGDYoiBs9WvRwf6t
      

      Here is the code. I now see things I would change immediately, like where I am setting the vars. 😄

      Content.makeFrontInterface(600, 600);
      Console.clear();
      
      // Do not run in the audio thread
      Synth.deferCallbacks(true);
      
      // Constants
      const var LINEWIDTH = 1;
      const var LINECOLOR = 0x66FFFFFF;
      
      // Get the UI components
      const var pnl = Content.getComponent("pnl");
      const var btn0 = Content.getComponent("btn0");
      const var btn1 = Content.getComponent("btn1");
      
      
      // Create a paint routine to draw a rectangle when clicking/dragging
      pnl.setPaintRoutine(function(g)
      {
      	
      	// if the mouse is clicked within the panel
      	if (this.data.clicked)
      	{	
      		// reset the button values (can be a for loop)	
      		btn0.setValue(0);
      		btn1.setValue(0);
      		
      		// Create vars to shorten stuff
      		var width = this.getWidth();
      		var height = this.getHeight();
      		var initX = this.data.initX;
      		var initY = this.data.initY;
      		var Xrel = this.data.Xrel;
      		var Yrel = this.data.Yrel;
      		var Xcur = this.data.Xcur;
      		var Ycur = this.data.Ycur;
      		
      		// Set the bounds of how far the rectangle can stretch
      		var edgeX = Math.range(Xrel,LINEWIDTH,width-initX);
      		var edgeY = Math.range(Yrel,LINEWIDTH,height-initY);
      		var negEdgeX = Math.range(Xcur,LINEWIDTH,width);
      		var negEdgeY = Math.range(Ycur,LINEWIDTH,height);
      		
      		// Make the rectangle white
      		g.setColour(LINECOLOR);
      		
      		// Draw the selection rectangle;
      		// Quadrant 4 (mathematically);
      		if (Xcur > initX && Ycur > initY)
      		{
      			g.drawRect([initX,initY,edgeX,edgeY], LINEWIDTH);
      		}
      		// Quadrant 3 
      		else if (Xcur < initX && Ycur > initY)
      		{
      			g.drawRect([negEdgeX,initY,initX-negEdgeX,edgeY], LINEWIDTH);
      		}
      		// Quadrant 1;
      		else if (Xcur > initX && Ycur < initY)
      		{ 
      			g.drawRect([initX,negEdgeY,edgeX,initY-negEdgeY], LINEWIDTH);
      		}
      		// Quadrant 2;
      		else if (Xcur < initX && Ycur < initY)
      		{
      			g.drawRect([negEdgeX,negEdgeY,initX-negEdgeX,initY-negEdgeY], LINEWIDTH);
      		}
      		
      		/* The challenge to turn the buttons on when 
      		dragging the rectangle over them begins here! */
      		
      		var logicX = 1; // placeholder
      		var logicY = 0; // placeholder 
      		
      		if (!btn0.getValue() && logicX && logicY)
      		{
      			btn0.setValue(1);
      		}
      	}
      	
      	// if mouse up
      	else if (!this.data.clicked)
      	{
      		// Make the panel transparent
      		g.fillAll(0x00000000);
      	}
      });
      
      pnl.setMouseCallback(function(event)
      {
      	if (event.clicked)
      	{	
      		this.data.clicked = 1;
      		// set the initial cursor position when the click happens
      		this.data.initX = event.x;
      		this.data.initY = event.y;
      		this.repaint();
      	}
      	if (event.drag)
      	{
      	// get current X and Y positions
      		this.data.Xcur = event.x;
      		this.data.Ycur = event.y;
      	// get new position of the mouse cursor relative to 
      	// the initial position when clicked
      		this.data.Xrel = (event.x - this.data.initX);
      		this.data.Yrel = (event.y - this.data.initY);
      		this.repaint();
      	}
      	if (event.mouseUp)
      	{	
      		this.data.clicked = 0;
      		this.repaint();
      	}
      });
      
      ustkU 2 Replies Last reply Reply Quote 0
      • ustkU
        ustk @ericchesek
        last edited by ustk

        @ericchesek The snippet isn't working here...

        A simpler way to do it is using a path and the getIntersection() method I added not long ago.
        Note that since you said "intersect with the button", this is only edge detection, meaning that if the buttons are inside the rectangle they will no longer intersect the path, so another method has to be used.

        HiseSnippet 1422.3ocsW0saaaCElJIpc1acXEaWsq3xECxXdN1ccYCKqXdwNo0X4Gi5zeFFJ5nkns4BMo.EURLJxiydO1izdC1NjTxRN0IovnUWHHd9iemCOmCOpuRFRSRjJjWkSlESQdeh+fYB8jNSHLApWWj2m6+TZnlHFmxIpATNr.s6rXRRBMB44s9iMB5UYCj84e+kcIbhHjVPBgdtjEROfMkoKn1u8uw378IQzSXSKI8Ca2KTJ5H4xT.Tq62DESBOkLldDwH1Z9Hu6rWDSKUCzDMMA4swtxnYClHOW3j+4rD1PN0rnEZ.XHG48k7HChMTQclv3Q8yc9DDXk9Egh0cghuv+PVDaN8hPxmYYfKznb7vasEg25K.uVkgWyRvaIPxqDj1vAo66OHTwh0EbL34i86IzT0HBD1KCEmrn096652QBRHzMlRNktuBVLWifsa1rNFdUampfTIRNsQHmRTA.gpasEtqDKjZrJUfYBrdBESRiXR3KEkDU0ltzHhNhp5P37gvoURfVkRyT2XSH8QmTMz7E9LhBePui16E85dxSvOB2ZmqvnywGb7SAFMuX6s2293LzioZ6t+rd3P4zXoftnQiEbPqbGcLU2IWpfMAdaVq7FMTKR.o+ikKNvs4l0pWsB7fwWqLs1r1q.rAFuQDQSZDWZ+Cgfil1mnmjGG6XofI3XHOBhmxTMSPwZINRQNGnqb0YbJ97ITANjyBOkIFuEvd7X3C6FkP08M5+Tm5AiREgZlTDLtV02TsxXi.tpmf4AS..UpVgMBGnmvRbXkk3pkA6VC7ywMLfvB2BYhqiKsv3+6JSEQIAsZzrV8hSQv9WZbxp4H7PYZBMOan.hzyfHiElFrXW0v5kzHCFJ1KHgQo6KMmPu4hexI3E0wyx9b1kycHGASDBrvaVvHk7PvNlLxcVfeXpRcK6QkETHtntXQxV3dD87AoCuRDL2QLVdITm8VlhCmomHCdKT9d1.4DeGze4tv0afPtLglGILbubwypolbimEW6FNqFQ3IzaOmMMFnR2MUqgxZ2oRUmMUTaMVPQhISXbLbdpH9J5ZxIGIU3fgldbllCYoSPc6ekB8LHPyuoDnJjnlgslJqW3TVTDTwJGYWMzZPnRNVQS.u03OLcBNVlvL6KXQtLjvyD7.vPCLwWSqnglBrGykCI79Yh+x.nLaIz+8fZ3uww3IT13Ifmt0Cd0NKw56Ihv3q254V4ErHyo0JsYrD6cIIYGelZsEaZTvF5AbEGu9hXst6rO6rrxPSyjmS3ozfqrKe0iJI4vFgSfFmznr7sKqdCOySAjhijZ5wB2oOnD9prFMZo7Ls3URNmpVJay7LpaRw.Q5zgTUc3hHvylKHbI+hSN3e8SNTdvlP2MNkDTJ5IX5iiohqabGT10TvTFqkgJPTscFiOMaFCWwAhAiRbGeyMhHKdKOXG5cU2VKQ2m0qKjhXlyICL..ioJMy36dcomACM5l5oheWZxoZYLrOyuAF4cW2ddu7YhHBJ2tk99v8PnKJuayJu.tXRd97gUPdeoeGysPI0wOQdFUg+Zb2rqbQmaJL.K58x0PnI1z+7UnRPYiaKzU.l+g2t.LsosKal6baQwqyLwsy.ZtS9msyAaNketM5smmDljUFAC1qWb7VyL8YLfL2ElozTEJfFCyJOy+6sYdeWg3886yzgSVNFWaIXzjn+A.iY+ov872azHnyTA.2ve+W9g42BPtI+FeHQqXP9f+QoSG.i6ERgcW.k.lNGd17S25ll0lHv.pHxt3+fmLlsLq8xX1JmIZJITIecnq517uHejkBfIg82vp3enYMddcsueyFMQvkgrWGFZb+uEZ6rbcdvJny2sB57vUPmueEzY6UPmeXEz4GuQcL+Q5ulpkSckC.g96Y6u54smf.YV1rPz+Silsop
        

        Can't help pressing F5 in the forum...

        1 Reply Last reply Reply Quote 1
        • ustkU
          ustk @ericchesek
          last edited by ustk

          @ericchesek I call b.changed() in the mouseCB making it fire at each drag movement which is bad. The button callback should be called when mouse is released, or using a check to see if the button state changed so the CB doesn't trigger constantly...

          pnl.setMouseCallback(function(event)
          {
          	if (event.clicked)
          		this.data.startPos = {x:event.x, y:event.y};
          	
          	if (event.drag)
          	{
          		this.data.isSelecting = true;
          		this.data.currPos = {x:event.x, y:event.y};
          		
          		this.data.p.clear();
          		this.data.p.startNewSubPath(this.data.startPos.x, this.data.startPos.y);
          		this.data.p.lineTo(this.data.currPos.x, this.data.startPos.y);
          		this.data.p.lineTo(this.data.currPos.x, this.data.currPos.y);
          		this.data.p.lineTo(this.data.startPos.x, this.data.currPos.y);
          		this.data.p.closeSubPath();
          	}
          	
          	if (this.data.isSelecting)
          		updateButtons(event.mouseUp);
          		
          	if (event.mouseUp)
          		this.data.isSelecting = false;
          	
          	this.repaint();
          });
          
          
          
          inline function updateButtons(isRelease)
          {
          	for (b in btns)
          	{
          		// just an imaginary line in the middle of the button representing its position
          		local buttonLineStart = [b.getGlobalPositionX(), b.getGlobalPositionY() + b.getHeight()/2];
          		local buttonLineEnd   = [b.getGlobalPositionX() + b.getWidth(), b.getGlobalPositionY() + b.getHeight()/2];
          		local isIntersecting  = this.data.p.getIntersection(buttonLineStart, buttonLineEnd, true);
          		
          		b.setValue(isIntersecting != false);
          		
          		if (isRelease)
          			b.changed();
          	}
          }
          

          Can't help pressing F5 in the forum...

          1 Reply Last reply Reply Quote 1
          • First post
            Last post

          23

          Online

          1.7k

          Users

          11.9k

          Topics

          103.6k

          Posts