@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(); } }