WIP: clipping mask drawing (with glitch)
This commit is contained in:
parent
9ef4c6745d
commit
e3fe78ec5c
1 changed files with 96 additions and 3 deletions
|
@ -20,6 +20,7 @@ use zmq::Socket;
|
||||||
use std::sync::{mpsc, Arc};
|
use std::sync::{mpsc, Arc};
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::cmp::{Ordering, min};
|
||||||
use serde::{Serialize,Deserialize};
|
use serde::{Serialize,Deserialize};
|
||||||
|
|
||||||
use nannou::winit::dpi::PhysicalPosition;
|
use nannou::winit::dpi::PhysicalPosition;
|
||||||
|
@ -963,10 +964,19 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
||||||
.w(win_rect.w());
|
.w(win_rect.w());
|
||||||
|
|
||||||
// 3. clipping mask + its anchor points
|
// 3. clipping mask + its anchor points
|
||||||
let clip_points: Vec<[f32;2]> = Corner::in_laser_space().iter().map(|p| {
|
|
||||||
|
let clip_points: Vec<[f32;2]> = config.filters.clip.mask.iter().map(|p| {
|
||||||
[p[0] * hw, p[1] * hh]
|
[p[0] * hw, p[1] * hh]
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
for point in clip_points.iter() {
|
||||||
|
// TODO: does not work?
|
||||||
|
draw.ellipse()
|
||||||
|
.x_y(point[0], point[1])
|
||||||
|
.radius(1.)
|
||||||
|
.color(BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
draw.polygon()
|
draw.polygon()
|
||||||
.color(srgba(1.,1.,1.,0.))
|
.color(srgba(1.,1.,1.,0.))
|
||||||
.stroke(PINK)
|
.stroke(PINK)
|
||||||
|
@ -1021,6 +1031,8 @@ fn laser_preview_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseBut
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let config = model.per_laser_config.get_mut(&dac_id).expect("Dac config unavailable");
|
||||||
|
|
||||||
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
||||||
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
||||||
|
|
||||||
|
@ -1032,7 +1044,63 @@ fn laser_preview_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseBut
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// 1. check if empty. it not check if one point is close
|
// 1. Always min. 4 points. We need closest two. So sort first
|
||||||
|
let mask_points = &config.filters.clip.mask;
|
||||||
|
let point_distances: Vec<(usize, f32, [f32;2])> = mask_points
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, &p)| {
|
||||||
|
(i, (laser_x - p[0]).powi(2) + (laser_y - p[1]).powi(2), p)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// dbg!(&half_w, &half_h, &laser_x, &laser_y, &point_distances);
|
||||||
|
let (idx, dist_sq, closest_point) = point_distances.iter().min_by(|a,b| a.1.partial_cmp(&b.1).unwrap()).expect("No clipping points existing?");
|
||||||
|
|
||||||
|
// = point_distances;
|
||||||
|
// let (idx2, _, _) = point_distances.get(1).expect("No clipping points existing?");
|
||||||
|
|
||||||
|
// match_distance is in pixelspace. Convert to laser-space
|
||||||
|
if dist_sq.sqrt() <= (MATCH_DISTANCE / half_w) {
|
||||||
|
// 2a. if closest is within MATCH_DISTANCE. Select point for dragging
|
||||||
|
model.preview_dragging_point = Some(idx.clone());
|
||||||
|
// println!("Closest point {:?} is within distance: {}", closest_point, dist_sq.sqrt());
|
||||||
|
} else {
|
||||||
|
// 2b. if not, if close point is found, if point has neighbours (i.e. len of vec > 1), and find which of neighbours is closest. Insert point between these. Select new point
|
||||||
|
let prev_point = point_distances.get((idx + point_distances.len() -1) % point_distances.len()).expect("No prev neighbour?");
|
||||||
|
let next_point = point_distances.get((idx+1) % point_distances.len()).expect("No next neighbour");
|
||||||
|
|
||||||
|
// select closest of prev/next
|
||||||
|
let (idx2, _, _closest_point2) = if prev_point.1 < next_point.1 {
|
||||||
|
prev_point
|
||||||
|
} else {
|
||||||
|
next_point
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// insert point
|
||||||
|
let instert_at = *min(idx, idx2);
|
||||||
|
|
||||||
|
let new_point = [laser_x, laser_y];
|
||||||
|
|
||||||
|
config.filters.clip.mask.insert(instert_at, new_point);
|
||||||
|
model.preview_dragging_point = Some(instert_at);
|
||||||
|
|
||||||
|
// println!("Closest point {:?} is too far: {}", closest_point, dist_sq.sqrt());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (app.mouse.x - c[0]).abs() < MATCH_DISTANCE && (app.mouse.y - c[1]).abs() < MATCH_DISTANCE {
|
||||||
|
// dbg!("close to corner! {:?}", &c);
|
||||||
|
// match i {
|
||||||
|
// 0 => selected = Some(Corner::TopLeft),
|
||||||
|
// 1 => selected = Some(Corner::TopRight),
|
||||||
|
// 2 => selected = Some(Corner::BottomRight),
|
||||||
|
// 3 => selected = Some(Corner::BottomLeft),
|
||||||
|
// _ => selected = None,
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
// 2a. if closest point is within selection margin, select that item.
|
// 2a. if closest point is within selection margin, select that item.
|
||||||
// 2b. if not, if close point is found, if point has neighbours (i.e. len of vec > 1), and find which of neighbours is closest. Insert point between these. Select new point
|
// 2b. if not, if close point is found, if point has neighbours (i.e. len of vec > 1), and find which of neighbours is closest. Insert point between these. Select new point
|
||||||
// 2c. if no closest point is found (thus Vec is empty), create a point under cursor. Select that new point.
|
// 2c. if no closest point is found (thus Vec is empty), create a point under cursor. Select that new point.
|
||||||
|
@ -1044,13 +1112,36 @@ fn laser_preview_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseBut
|
||||||
|
|
||||||
|
|
||||||
fn laser_mouse_moved(app: &App, model: &mut GuiModel, pos: Point2) {
|
fn laser_mouse_moved(app: &App, model: &mut GuiModel, pos: Point2) {
|
||||||
|
let dac_id = match &model.selected_stream {
|
||||||
|
None => return,
|
||||||
|
Some(d) => d,
|
||||||
|
};
|
||||||
|
|
||||||
|
let point_idx = match &model.preview_dragging_point {
|
||||||
|
None => return,
|
||||||
|
Some(d) => d,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
||||||
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
||||||
|
|
||||||
let laser_x = app.mouse.x / half_w;
|
let laser_x = app.mouse.x / half_w;
|
||||||
let laser_y = app.mouse.y / half_h;
|
let laser_y = app.mouse.y / half_h;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 0. Get config
|
||||||
|
let config = model.per_laser_config.get_mut(&dac_id).expect("Dac config unavailable");
|
||||||
|
|
||||||
// 1. Move selected point to laser_x, laser_y
|
// 1. Move selected point to laser_x, laser_y
|
||||||
|
// config.filters.clip.
|
||||||
|
let point = config.filters.clip.mask.get_mut(*point_idx).unwrap();
|
||||||
|
|
||||||
|
*point = [laser_x, laser_y];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn laser_mouse_released(_app: &App, model: &mut GuiModel, _button: MouseButton) {
|
fn laser_mouse_released(_app: &App, model: &mut GuiModel, _button: MouseButton) {
|
||||||
|
@ -1166,6 +1257,8 @@ fn map_mouse_moved(_app: &App, model: &mut GuiModel, pos: Point2) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MATCH_DISTANCE: f32 = 30.; // screen pixels
|
||||||
|
|
||||||
fn map_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseButton) {
|
fn map_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseButton) {
|
||||||
if button != MouseButton::Left {
|
if button != MouseButton::Left {
|
||||||
// ignore
|
// ignore
|
||||||
|
@ -1173,7 +1266,7 @@ fn map_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseButton) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dac_id) = &model.selected_stream {
|
if let Some(dac_id) = &model.selected_stream {
|
||||||
const MATCH_DISTANCE: f32 = 30.; // screen pixels
|
|
||||||
|
|
||||||
let config = model.per_laser_config.get(&dac_id).expect("Dac config unavailable");
|
let config = model.per_laser_config.get(&dac_id).expect("Dac config unavailable");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue