WIP: clip mask drawing
This commit is contained in:
parent
65acde713f
commit
9ef4c6745d
3 changed files with 136 additions and 48 deletions
|
@ -13,7 +13,7 @@ use nannou_laser::DacId;
|
|||
use nannou_laser::{self as laser};
|
||||
use serde_json::Result;
|
||||
use trap_rust::trap::filters::PointFilters;
|
||||
use trap_rust::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX};
|
||||
use trap_rust::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX, Corner};
|
||||
use trap_rust::trap::tracks::CoordinateSpace;
|
||||
use trap_rust::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
|
||||
use zmq::Socket;
|
||||
|
@ -50,28 +50,7 @@ pub struct StreamConfig{
|
|||
type StreamConfigMap = HashMap<DacId, StreamConfig>;
|
||||
type StreamMap = HashMap<DacId, laser::FrameStream<LaserModel>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Corner{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
}
|
||||
|
||||
impl Corner {
|
||||
pub fn in_laser_space() -> Vec<[f32; 2]>{
|
||||
vec!([-1.,1.], [1.,1.], [-1.,-1.], [1., -1.])
|
||||
}
|
||||
|
||||
fn index(&self) -> usize {
|
||||
match self {
|
||||
Self::TopLeft => 0,
|
||||
Self::TopRight => 1,
|
||||
Self::BottomLeft => 2,
|
||||
Self::BottomRight => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GuiModel {
|
||||
// A handle to the laser API used for spawning streams and detecting DACs.
|
||||
|
@ -98,6 +77,7 @@ struct GuiModel {
|
|||
canvas_scale: f32,
|
||||
canvas_translate: Vec2,
|
||||
canvas_dragging_corner: Option<Corner>,
|
||||
preview_dragging_point: Option<usize>,
|
||||
// canvas_transform: Translation2D<f32, ScreenSpace, ScreenSpace>,
|
||||
// dragging: bool,
|
||||
}
|
||||
|
@ -322,13 +302,15 @@ fn model(app: &App) -> GuiModel {
|
|||
.view(view_line_canvas)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
||||
let w_id_laserpreview = app
|
||||
.new_window()
|
||||
.size(1024, 1024)
|
||||
// .key_pressed(key_pressed)
|
||||
// .mouse_wheel(canvas_zoom)
|
||||
.mouse_pressed(laser_preview_mouse_pressed)
|
||||
.mouse_released(laser_mouse_released)
|
||||
.mouse_moved(laser_mouse_moved)
|
||||
.view(view_laser_preview)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
@ -413,6 +395,7 @@ fn model(app: &App) -> GuiModel {
|
|||
canvas_scale: 25.,
|
||||
canvas_translate: Vec2::new(-300.,100.),
|
||||
canvas_dragging_corner: None,
|
||||
preview_dragging_point: None,
|
||||
// canvas_transform: Transform2D
|
||||
// dimming_factor: 1.,
|
||||
}
|
||||
|
@ -935,6 +918,9 @@ fn view_line_canvas(app: &App, model: &GuiModel, frame: Frame) {
|
|||
draw.to_frame(app, &frame).unwrap();
|
||||
}
|
||||
|
||||
const LASER_PREVIEW_WIDTH: f32 = 1024.;
|
||||
const LASER_PREVIEW_HEIGHT: f32 = 1024.;
|
||||
|
||||
// preview the selected laser, to draw clip mask
|
||||
fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
||||
// get canvas to draw on
|
||||
|
@ -945,8 +931,8 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
|||
|
||||
let win = app.window_rect();
|
||||
|
||||
let w = 1024.;
|
||||
let h = 1024.;
|
||||
let w = LASER_PREVIEW_WIDTH;
|
||||
let h = LASER_PREVIEW_HEIGHT;
|
||||
let hh = h / 2.;
|
||||
let hw = w / 2.;
|
||||
|
||||
|
@ -963,9 +949,12 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
|||
},
|
||||
Some(dac_id) => {
|
||||
// let stream = model.laser_streams.get(&dac_id); //.expect("Selected stream not found in configs");
|
||||
|
||||
// 1. get config for laser
|
||||
let config = model.per_laser_config.get(&dac_id).expect("Selected stream not found in configs");
|
||||
|
||||
draw.text(&format!("{:?}", dac_id))
|
||||
// 2 draw identifier of laser
|
||||
draw.text(&format!("{} {:?}", config.name, dac_id))
|
||||
.h(win_rect.h())
|
||||
.font_size(10)
|
||||
.align_text_bottom()
|
||||
|
@ -973,6 +962,21 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
|||
.color(WHITE)
|
||||
.w(win_rect.w());
|
||||
|
||||
// 3. clipping mask + its anchor points
|
||||
let clip_points: Vec<[f32;2]> = Corner::in_laser_space().iter().map(|p| {
|
||||
[p[0] * hw, p[1] * hh]
|
||||
}).collect();
|
||||
|
||||
draw.polygon()
|
||||
.color(srgba(1.,1.,1.,0.))
|
||||
.stroke(PINK)
|
||||
.stroke_weight(thickness)
|
||||
.join_round()
|
||||
.points(clip_points);
|
||||
|
||||
|
||||
// 4. current shape of the laser
|
||||
|
||||
|
||||
let current_points: LaserPoints = (&model.current_lines).into();
|
||||
let space = &model.current_lines.space;
|
||||
|
@ -1001,34 +1005,59 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
|
||||
}
|
||||
|
||||
fn laser_preview_mouse_pressed(app: &App, _model: &mut GuiModel, button: MouseButton) {
|
||||
fn laser_preview_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseButton) {
|
||||
let dac_id = match &model.selected_stream {
|
||||
None => return,
|
||||
Some(d) => d,
|
||||
};
|
||||
|
||||
if button != MouseButton::Left {
|
||||
// ignore
|
||||
// TODO: right click remove point within Margin
|
||||
return;
|
||||
}
|
||||
|
||||
let half_w = (1024 / 2) as f32;
|
||||
let half_h = (1024 / 2) as f32;
|
||||
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
||||
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
||||
|
||||
let laser_x = app.mouse.x / half_w;
|
||||
let laser_y = app.mouse.y / half_h;
|
||||
|
||||
// if x > 1. || x < -1. || y > 1. || y < -1. {
|
||||
// println!("Click outside of canvas: {} {}", x, y);
|
||||
// return
|
||||
// }
|
||||
|
||||
// 1. check if empty. it not check if one point is close
|
||||
// 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
|
||||
// 2c. if no closest point is found (thus Vec is empty), create a point under cursor. Select that new point.
|
||||
|
||||
let x = app.mouse.x / half_w;
|
||||
let y = app.mouse.y / half_h;
|
||||
|
||||
if x > 1. || x < -1. || y > 1. || y < -1. {
|
||||
println!("Click outside of canvas: {} {}", x, y);
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn laser_mouse_moved(app: &App, model: &mut GuiModel, pos: Point2) {
|
||||
let half_w = LASER_PREVIEW_WIDTH / 2.;
|
||||
let half_h = LASER_PREVIEW_HEIGHT / 2.;
|
||||
|
||||
let laser_x = app.mouse.x / half_w;
|
||||
let laser_y = app.mouse.y / half_h;
|
||||
|
||||
// 1. Move selected point to laser_x, laser_y
|
||||
}
|
||||
|
||||
fn laser_mouse_released(_app: &App, model: &mut GuiModel, _button: MouseButton) {
|
||||
// deselect point
|
||||
model.preview_dragging_point = None;
|
||||
}
|
||||
|
||||
fn draw_grid(draw: &Draw, win: &Rect, step: f32, weight: f32) {
|
||||
let step_by = || (0..).map(|i| i as f32 * step);
|
||||
let r_iter = step_by().take_while(|&f| f < win.right());
|
||||
|
@ -1072,8 +1101,6 @@ fn style() -> egui::Style {
|
|||
style
|
||||
}
|
||||
|
||||
fn mouse_moved(_app: &App, _model: &mut GuiModel, _pos: Point2) {
|
||||
}
|
||||
|
||||
fn laser_corners_to_world(filters: &PointFilters) -> Vec<[f32;2]> {
|
||||
let corners_raw: Vec<[f32; 2]> = Corner::in_laser_space();
|
||||
|
@ -1169,8 +1196,8 @@ fn map_mouse_pressed(app: &App, model: &mut GuiModel, button: MouseButton) {
|
|||
match i {
|
||||
0 => selected = Some(Corner::TopLeft),
|
||||
1 => selected = Some(Corner::TopRight),
|
||||
2 => selected = Some(Corner::BottomLeft),
|
||||
3 => selected = Some(Corner::BottomRight),
|
||||
2 => selected = Some(Corner::BottomRight),
|
||||
3 => selected = Some(Corner::BottomLeft),
|
||||
_ => selected = None,
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use bevy::prelude::*; // for glam::f32::Mat3
|
||||
|
||||
use crate::trap::{laser::{apply_homography_matrix, LaserPoints}, tracks::CoordinateSpace};
|
||||
use crate::trap::{laser::{apply_homography_matrix, Corner, LaserPoints}, tracks::CoordinateSpace};
|
||||
|
||||
use nannou_laser::{self as laser, Point};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -22,6 +22,12 @@ pub struct CropFilter {
|
|||
pub enabled: bool
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct ClipFilter {
|
||||
pub enabled: bool,
|
||||
pub mask: Vec<[f32; 2]>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct DimFilter {
|
||||
pub intensity: f32
|
||||
|
@ -59,6 +65,7 @@ pub struct PointFilters{
|
|||
pub scale: ScaleFilter,
|
||||
pub pincushion: PincushionFilter,
|
||||
pub crop: CropFilter,
|
||||
pub clip: ClipFilter,
|
||||
}
|
||||
|
||||
// list of enums deprecated in favour of struct
|
||||
|
@ -128,6 +135,7 @@ impl Default for PointFilters {
|
|||
scale: ScaleFilter { factor: 1. },
|
||||
pincushion: PincushionFilter{k_x: 0.,k_x2: 0., k_y: 0., k_y2: 0.},
|
||||
crop: CropFilter{ enabled: true },
|
||||
clip: ClipFilter{ enabled: false, mask: Corner::in_laser_space() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +154,8 @@ impl Filter for HomographyFilter {
|
|||
|
||||
};
|
||||
// also converts from world space to laser space (origin in center)
|
||||
let s = 0xFFF as f32 / 2.;
|
||||
let normalised_pos: [f32;2] = [new_position[0]/s - 1., new_position[1]/s - 1.];
|
||||
// let s = 0xFFF as f32 / 2.;
|
||||
// let normalised_pos: [f32;2] = [new_position[0]/s - 1., new_position[1]/s - 1.];
|
||||
laser::Point {
|
||||
position: new_position,
|
||||
.. point.clone()
|
||||
|
@ -322,7 +330,7 @@ impl Filter for CropFilter {
|
|||
}
|
||||
|
||||
fn reverse(&self, points: &LaserPoints) -> LaserPoints{
|
||||
// we cannot really add points, can we
|
||||
// we cannot really conjure up points, can we
|
||||
return LaserPoints{
|
||||
points: points.points.clone(),
|
||||
space: points.space,
|
||||
|
@ -330,6 +338,36 @@ impl Filter for CropFilter {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Filter for ClipFilter {
|
||||
|
||||
fn apply(&self, points: &LaserPoints) -> LaserPoints {
|
||||
if !self.enabled {
|
||||
// don't modify if disabled
|
||||
return LaserPoints{
|
||||
points: points.points.clone(),
|
||||
space: points.space,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO
|
||||
return LaserPoints{
|
||||
points: points.points.clone(),
|
||||
space: points.space,
|
||||
};
|
||||
}
|
||||
|
||||
fn reverse(&self, points: &LaserPoints) -> LaserPoints{
|
||||
// we cannot really conjure up points, can we
|
||||
return LaserPoints{
|
||||
points: points.points.clone(),
|
||||
space: points.space,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn change_brightness(points: &LaserPoints, intensity: f32) -> LaserPoints{
|
||||
let new_points = points.points.iter().map(|point| {
|
||||
let mut color = point.color.clone();
|
||||
|
|
|
@ -307,4 +307,27 @@ impl StreamSource{
|
|||
_ => LaserPoints::default(), // empty set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Corner{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomRight,
|
||||
BottomLeft,
|
||||
}
|
||||
|
||||
impl Corner {
|
||||
pub fn in_laser_space() -> Vec<[f32; 2]>{
|
||||
vec!([-1.,1.], [1.,1.], [1., -1.], [-1.,-1.])
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
match self {
|
||||
Self::TopLeft => 0,
|
||||
Self::TopRight => 1,
|
||||
Self::BottomRight => 2,
|
||||
Self::BottomLeft => 3,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue