diff --git a/nih_plug_vizia/src/widgets/resize_handle.rs b/nih_plug_vizia/src/widgets/resize_handle.rs index bffd84a1..fd5123ec 100644 --- a/nih_plug_vizia/src/widgets/resize_handle.rs +++ b/nih_plug_vizia/src/widgets/resize_handle.rs @@ -39,15 +39,26 @@ impl View for ResizeHandle { if let Some(window_event) = event.message.downcast() { match *window_event { WindowEvent::MouseDown(MouseButton::Left) => { - cx.capture(); - cx.current.set_active(cx, true); + // The handle is a triangle, so we should also interac twith it as if it was a + // triangle + if intersects_triangle( + cx.cache.get_bounds(cx.current), + (cx.mouse.cursorx, cx.mouse.cursory), + ) { + cx.capture(); + cx.current.set_active(cx, true); - self.drag_active = true; - self.start_scale_factor = cx.user_scale_factor; - self.start_physical_coordinates = ( - cx.mouse.cursorx * cx.style.dpi_factor as f32, - cx.mouse.cursory * cx.style.dpi_factor as f32, - ); + self.drag_active = true; + self.start_scale_factor = cx.user_scale_factor; + self.start_physical_coordinates = ( + cx.mouse.cursorx * cx.style.dpi_factor as f32, + cx.mouse.cursory * cx.style.dpi_factor as f32, + ); + + event.consume(); + } else { + // TODO: The click should be forwarded to the element behind the triangle + } } WindowEvent::MouseUp(MouseButton::Left) => { if self.drag_active { @@ -58,7 +69,12 @@ impl View for ResizeHandle { } } WindowEvent::MouseMove(x, y) => { - // TODO: Filter the hover color and dragging to the actual triangle + if !intersects_triangle(cx.cache.get_bounds(cx.current), (x, y)) { + cx.current.set_hover(cx, false); + } else { + cx.current.set_hover(cx, true); + } + if self.drag_active { // We need to convert our measurements into physical pixels relative to the // initial drag to be able to keep a consistent ratio. This 'relative to the @@ -188,3 +204,25 @@ impl View for ResizeHandle { canvas.fill_path(&mut path, paint); } } + +/// Test whether a point intersects with the triangle of this resize handle. +fn intersects_triangle(bounds: BoundingBox, (x, y): (f32, f32)) -> bool { + // We could also compute Barycentric coordinates, but this is simple and I like not having to + // think. Just check if (going clockwise), the point is on the right of each of all of the + // triangle's edges. We can compute this using the determinant of the 2x2 matrix formed by two + // column ve vectors, aka the perp dot product, aka the wedge product. + // NOTE: Since this element is positioned in the bottom right corner we would technically only + // have to calculate this for `v1`, checking the other two vectors is redundant but for + // now we'll do it anyways + let (p1x, p1y) = bounds.bottom_left(); + let (p2x, p2y) = bounds.top_right(); + let (p3x, p3y) = bounds.bottom_right(); + + let (v1x, v1y) = (p2x - p1x, p2y - p1y); + let (v2x, v2y) = (p3x - p2x, p3y - p2y); + let (v3x, v3y) = (p1x - p3x, p1y - p3y); + + ((x - p1x) * v1y) - ((y - p1y) * v1x) <= 0.0 + && ((x - p2x) * v2y) - ((y - p2y) * v2x) <= 0.0 + && ((x - p3x) * v3y) - ((y - p3y) * v3x) <= 0.0 +}