Wip layers

This commit is contained in:
Ruben van de Ven 2025-10-17 15:04:00 +02:00
parent 905a3faa0c
commit fac5bda2f5
6 changed files with 214 additions and 90 deletions

View file

@ -133,7 +133,7 @@ fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
// false => trap::shapes::ARE_YOU_SURE, // false => trap::shapes::ARE_YOU_SURE,
// }; // };
let points = model.current_lines.clone(); let points = model.current_layers.clone();
let mut new_points = Vec::new(); let mut new_points = Vec::new();
for point in points.into_iter() { for point in points.into_iter() {

View file

@ -2,7 +2,6 @@
//! A clone of the `laser_frame_stream.rs` example that allows for configuring laser settings via a //! A clone of the `laser_frame_stream.rs` example that allows for configuring laser settings via a
//! UI. //! UI.
use bevy::scene::ron::Map;
// use bevy_nannou::prelude::DARK_GRAY; // use bevy_nannou::prelude::DARK_GRAY;
// use nannou::lyon::geom::euclid::Transform2D; // use nannou::lyon::geom::euclid::Transform2D;
use nannou::{geom::Rect, math::map_range as nannou_map_range}; use nannou::{geom::Rect, math::map_range as nannou_map_range};
@ -15,7 +14,7 @@ use nannou_laser::{self as laser};
use serde_json::Result; use serde_json::Result;
use laserspace::trap::filters::{MappedPoint, PointFilters}; use laserspace::trap::filters::{MappedPoint, PointFilters};
use laserspace::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX, Corner}; use laserspace::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX, Corner};
use laserspace::trap::tracks::CoordinateSpace; use laserspace::trap::tracks::{CoordinateSpace, RenderableLayers};
use laserspace::trap::utils::{closest_edge, split_on_blank}; use laserspace::trap::utils::{closest_edge, split_on_blank};
use laserspace::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}}; use laserspace::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
use zmq::Socket; use zmq::Socket;
@ -72,7 +71,7 @@ struct GuiModel {
egui: Egui, egui: Egui,
// socket for receiving points // socket for receiving points
zmq: Socket, zmq: Socket,
current_lines: RenderableLines, // a copy for the drawing renderer current_layers: RenderableLayers, // a copy for the drawing renderer
last_update: Instant, last_update: Instant,
// dimming_factor: f32, // dimming_factor: f32,
lost_alpha: f32, lost_alpha: f32,
@ -155,23 +154,23 @@ fn zmq_receive(model: &mut GuiModel) {
]; ];
let _nr = zmq::poll(&mut items, 0).unwrap(); let _nr = zmq::poll(&mut items, 0).unwrap();
let lines: RenderableLines; let layers: RenderableLayers;
if items[0].is_readable() { if items[0].is_readable() {
let json = subscriber.recv_string(0).unwrap().unwrap(); let json = subscriber.recv_string(0).unwrap().unwrap();
// dbg!(&json[4..]); // dbg!(&json[4..]);
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?"); // let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
let res: Result<RenderableLines> = serde_json::from_str(&json); let res: Result<RenderableLayers> = serde_json::from_str(&json);
model.lost_alpha = 1.; model.lost_alpha = 1.;
model.connected = true; model.connected = true;
lines = match res { layers = match res {
Ok(lines) => lines, // if Ok(255), set x to 255 Ok(layers) => layers, // if Ok(255), set x to 255
Err(_e) => { Err(_e) => {
println!("No valid json?"); println!("No valid json?");
println!("{}", _e); println!("{}", _e);
// empty if invalid // empty if invalid
RenderableLines::new() RenderableLayers::new()
}, // if Err("some message"), panic with error message "some message" }, // if Err("some message"), panic with error message "some message"
}; };
} else if model.last_update < Instant::now() - Duration::from_millis(100){ } else if model.last_update < Instant::now() - Duration::from_millis(100){
@ -180,14 +179,14 @@ fn zmq_receive(model: &mut GuiModel) {
if model.lost_alpha > 0.{ if model.lost_alpha > 0.{
println!("No input, clear lines!!"); println!("No input, clear layers!!");
model.lost_alpha *= 0.80; model.lost_alpha *= 0.80;
if model.lost_alpha < 0.1{ if model.lost_alpha < 0.1{
model.lost_alpha = 0.; model.lost_alpha = 0.;
} }
lines = model.current_lines.with_alpha(model.lost_alpha); layers = model.current_layers.with_alpha(model.lost_alpha);
} else { } else {
lines = RenderableLines::new() layers = RenderableLayers::new()
} }
} else { } else {
// No new lines, break // No new lines, break
@ -198,17 +197,17 @@ fn zmq_receive(model: &mut GuiModel) {
for (_dac, stream) in (&model.laser_streams).into_iter() { for (_dac, stream) in (&model.laser_streams).into_iter() {
// let lines = get_laser_lines(version); // let lines = get_laser_lines(version);
let lines_for_laser: RenderableLines = lines.clone(); let layers_for_laser: RenderableLayers = layers.clone();
let sending = stream.send(move |laser_model: &mut LaserModel| { let sending = stream.send(move |laser_model: &mut LaserModel| {
let laser_lines: RenderableLines = lines_for_laser; let laser_layers: RenderableLayers = layers_for_laser;
laser_model.current_lines = laser_lines; laser_model.current_layers = laser_layers;
}); });
if let Err(e) = sending { if let Err(e) = sending {
println!("Error sending to laser! {e:?}"); println!("Error sending to laser! {e:?}");
} }
} }
model.current_lines = lines; model.current_layers = layers;
model.last_update = Instant::now(); model.last_update = Instant::now();
} }
@ -393,7 +392,7 @@ fn model(app: &App) -> GuiModel {
let egui_ctx = egui.ctx(); let egui_ctx = egui.ctx();
egui_ctx.set_style(style()); egui_ctx.set_style(style());
let current_lines = RenderableLines::new(); //Vec::new(); let current_layers = RenderableLayers::new(); //Vec::new();
GuiModel { GuiModel {
laser_api, laser_api,
@ -403,7 +402,7 @@ fn model(app: &App) -> GuiModel {
dac_rx, dac_rx,
egui, egui,
zmq, zmq,
current_lines: current_lines, current_layers: current_layers,
last_update: Instant::now(), last_update: Instant::now(),
lost_alpha: 1., lost_alpha: 1.,
connected: true, connected: true,
@ -420,34 +419,35 @@ fn model(app: &App) -> GuiModel {
} }
} }
fn layers_to_points_for_config(current_layers: &RenderableLayers, config: &DacConfig ) -> Vec<Vec<laser::Point>> {
let mut new_laser_points: Vec<laser::Point> = Vec::new();
for (layer_nr, layer) in current_layers.0.iter() {
let mask = 1 << layer_nr;
if (mask & config.layers_enabled) != 0 {
let current_points: LaserPoints = layer.into();
// check which source should be used, and get points accordingly.
// potentially ignoring the points coming from the stream
let points = config.source.get_shape(current_points, config);
// let pointno = points.points.len();
let new_points = match points.space {
CoordinateSpace::RawLaser => points,
_ => config.filters.apply(&points)
};
// let new_laser_points = new_points.points;
new_laser_points.extend(new_points.points);
}
}
split_on_blank(new_laser_points)
}
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){ fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
let lines = layers_to_points_for_config(&model.current_layers, &model.config);
let current_points: LaserPoints = (&model.current_lines).into();
// let space = &model.current_lines.space;
// check which source should be used, and get points accordingly.
// potentially ignoring the points coming from the stream
let points = model.config.source.get_shape(current_points, &model.config);
// let pointno = points.points.len();
let new_points = match points.space {
CoordinateSpace::RawLaser => points,
_ => model.config.filters.apply(&points)
};
let new_laser_points = new_points.points;
// if new_laser_points.len() < pointno {
// println!("Cropped Points {} (was: {})", new_laser_points.len(), pointno);
// }
// split by blanked points
let lines = split_on_blank(new_laser_points);
for line in lines { for line in lines {
frame.add_lines(line); frame.add_lines(line);
} }
return; return;
} }
@ -542,7 +542,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
ref mut laser_settings, ref mut laser_settings,
ref mut per_laser_config, ref mut per_laser_config,
ref mut selected_stream, ref mut selected_stream,
ref mut current_lines, ref mut current_layers,
.. ..
} = *model; } = *model;
@ -566,9 +566,17 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
}); });
ui.separator(); ui.separator();
ui.columns(3, |cols| {
cols[0].label(format!("Layers {}", current_layers.0.len()));
cols[1].label(format!("Lines {}", current_layers.line_count()));
cols[2].label(format!("Points {}", current_layers.point_count()));
});
ui.add(egui::Label::new(format!("Lines {}", current_lines.lines.len()))); // ui.add(egui::Label::new(format!("Layers {}", current_layers.0.len())));
ui.add(egui::Label::new(format!("Points {}", current_lines.point_count()))); // ui.add(egui::Label::new(format!("Lines {}", current_layers.line_count())));
// ui.add(egui::Label::new(format!("Points {}", current_layers.point_count())));
ui.heading("General settings"); ui.heading("General settings");
@ -731,6 +739,40 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
} }
}); });
ui.horizontal_wrapped(|ui| {
for layer_nr in 1..=8 {
let mask = 1 << layer_nr;
let mut enabled_bool = mask & selected_config.layers_enabled != 0;
if ui
.add(egui::Checkbox::new(&mut enabled_bool,format!("{:?}", layer_nr)))
.changed()
{
selected_config.layers_enabled &= mask;
let layers_enabled = selected_config.layers_enabled;
if let Some(stream) = selected_laser_stream {
stream.send(move |laser_model: &mut LaserModel| {
laser_model.config.layers_enabled = layers_enabled;
}).unwrap();
}
}
}
});
// if ui
// .add_enabled(laser_settings.enable_optimisations,
// egui::Checkbox::new(&mut laser_settings.enable_draw_reorder,"Reorder paths")
// )
// // .checkbox(&mut laser_settings.enable_draw_reorder, "Reorder paths")
// .changed()
// {
// for (_dac_id, stream) in laser_streams.iter() {
// stream
// .enable_draw_reorder(laser_settings.enable_draw_reorder)
// .ok();
// }
// }
if ui if ui
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming")) .add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
@ -743,7 +785,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
}).unwrap(); }).unwrap();
} }
} }
if ui if ui
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming")) .add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
.changed() .changed()
@ -867,12 +909,9 @@ fn view_line_canvas(app: &App, model: &GuiModel, frame: Frame) {
// LaserPoints supports a mode that sends points directly into the laser // LaserPoints supports a mode that sends points directly into the laser
// if this mode is enabled by the sender, set background to blue // if this mode is enabled by the sender, set background to blue
// Red if nothing is sending / not for too long. // Red if nothing is sending / not for too long.
let bgcolor = match model.current_lines.space { let bgcolor = match model.connected{
CoordinateSpace::Laser => MEDIUMSLATEBLUE,
_ => match model.connected{
true => DARKGRAY, true => DARKGRAY,
false => LIGHTCORAL, false => LIGHTCORAL,
},
}; };
draw.background().color(bgcolor); draw.background().color(bgcolor);
@ -901,20 +940,23 @@ fn view_line_canvas(app: &App, model: &GuiModel, frame: Frame) {
// draw current laser lines // draw current laser lines
for line in &model.current_lines.lines{ for (_, layer) in model.current_layers.0.iter() {
let vertices = line.points.iter().map(|p| {
let color = srgba(p.color.red, p.color.green, p.color.blue, p.color.alpha);
let pos = [p.position[0] * scale + translate_x, p.position[1] * -scale + translate_y];
(pos, color)
});
draw.polyline() for line in &layer.lines{
let vertices = line.points.iter().map(|p| {
let color = srgba(p.color.red, p.color.green, p.color.blue, p.color.alpha);
let pos = [p.position[0] * scale + translate_x, p.position[1] * -scale + translate_y];
(pos, color)
});
draw.polyline()
.weight(thickness) .weight(thickness)
.join_round() .join_round()
.points_colored(vertices); .points_colored(vertices);
}
} }
// show each configured laser in the canvas. Highlight the selected. // show each configured laser in the canvas. Highlight the selected.
for (dac_id, config) in model.per_laser_config.iter() { for (dac_id, config) in model.per_laser_config.iter() {
let rect = shape_rect(LaserSpace::READY, 11); let rect = shape_rect(LaserSpace::READY, 11);
@ -1014,7 +1056,7 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
// let stream = model.laser_streams.get(&dac_id); //.expect("Selected stream not found in configs"); // let stream = model.laser_streams.get(&dac_id); //.expect("Selected stream not found in configs");
// 1. get config for laser // 1. get config for laser
let config = model.per_laser_config.get(&dac_id).expect("Selected stream not found in configs"); let config: &DacConfig = model.per_laser_config.get(&dac_id).expect("Selected stream not found in configs");
// 2. clipping mask + its anchor points // 2. clipping mask + its anchor points
@ -1039,28 +1081,13 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
// 3. current shape of the laser // 3. current shape of the laser
let lines = layers_to_points_for_config(&model.current_layers, &config);
let current_points: LaserPoints = (&model.current_lines).into();
// check which source should be used, and get points accordingly.
// potentially ignoring the points coming from the stream
let points = config.source.get_shape(current_points, config);
// let pointno = points.points.len();
let new_points = match points.space {
CoordinateSpace::RawLaser => points,
_ => config.filters.apply(&points)
};
let new_laser_points = new_points.points;
// draw as distinct lines (this is how it is send to post-processing) // draw as distinct lines (this is how it is send to post-processing)
// TODO: alternatively, if the optimisation becomes an actual filter // TODO: alternatively, if the optimisation becomes an actual filter
// this should be drawn as a single line, and we can have an option to // this should be drawn as a single line, and we can have an option to
// visualise the intermediate lines to make the draw order apparent // visualise the intermediate lines to make the draw order apparent
let lines = split_on_blank(new_laser_points);
for line in lines { for line in lines {
// similar to map code: // similar to map code:

View file

@ -47,6 +47,11 @@ pub struct ScaleFilter {
pub factor: f32 pub factor: f32
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct InterpolateFilter {
pub max_distance: f32
}
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PincushionFilter { pub struct PincushionFilter {
pub k_x: f32, pub k_x: f32,
@ -69,6 +74,7 @@ pub struct PincushionFilter {
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PointFilters{ pub struct PointFilters{
pub interpolate: InterpolateFilter,
pub dim: DimFilter, pub dim: DimFilter,
pub homography: HomographyFilter, pub homography: HomographyFilter,
pub scale: ScaleFilter, pub scale: ScaleFilter,
@ -91,9 +97,14 @@ pub struct PointFilters{
// } // }
// } // }
pub fn lerp(a: f32, b: f32, t: f32) -> f32{
return (1. - t) * a + t * b
}
impl PointFilters { impl PointFilters {
pub fn apply(&self, points: &LaserPoints) -> LaserPoints{ pub fn apply(&self, points: &LaserPoints) -> LaserPoints{
let mut p = self.dim.apply(points); let mut p = self.dim.apply(points);
// TODO: not implemented yet p = self.interpolate.apply(&p);
p = self.homography.apply(&p); p = self.homography.apply(&p);
p = self.scale.apply(&p); p = self.scale.apply(&p);
p = self.crop.apply(&p); p = self.crop.apply(&p);
@ -141,6 +152,7 @@ impl Default for PointFilters {
// let crop_filter = CropFilter{}; // let crop_filter = CropFilter{};
Self { Self {
homography: HomographyFilter::default(), homography: HomographyFilter::default(),
interpolate: InterpolateFilter{max_distance: 0.2},
dim: DimFilter{intensity: 0.5}, dim: DimFilter{intensity: 0.5},
scale: ScaleFilter { factor: 1. }, scale: ScaleFilter { factor: 1. },
pincushion: PincushionFilter{k_x: 0.,k_x2: 0., k_y: 0., k_y2: 0.}, pincushion: PincushionFilter{k_x: 0.,k_x2: 0., k_y: 0., k_y2: 0.},
@ -571,6 +583,57 @@ impl Filter for DimFilter {
} }
} }
impl Filter for InterpolateFilter {
fn apply(&self, points: &LaserPoints) -> LaserPoints {
// TODO: fix the code below
// let mut new_positions: Vec<[f32;2]> = Vec::new();
// // min distance between points before geometric filters
// let interpolated_edges = p.points.iter().zip(p.points.iter().skip(1)).map(|(p1, p2)|{
// let distance = f32::sqrt((p2.position[0] - p1.position[0]).powi(2) + (p2.position[1] - p1.position[1]).powi(2));
// let steps: i32 = (distance / required_distance).ceil() as i32;
// let mut interpolated_edge = Vec::new();
// for i in 0..steps {
// let t = (steps as f32) /(i as f32);
// interpolated_edge.push(
// laser::Point{
// position: [
// lerp(p1.position[0], p2.position[0], t),
// lerp(p1.position[1], p2.position[1], t)
// ],
// color: p1.color,
// weight: p1.weight,
// }
// );
// }
// interpolated_edge
// });
// let mut interpolated_points: Vec<laser::Point> = interpolated_edges.flatten().collect();
// if let Some(last) = p.points.last() {
// interpolated_points.push(last.clone()); // add last one so we don't lose it
// }
// LaserPoints{
// points: interpolated_points,
// space: points.space,
// }
LaserPoints::default()
}
fn reverse(&self, points: &LaserPoints) -> LaserPoints{
// cannot easily be undone
LaserPoints{
points: points.points.clone(),
space: points.space,
}
}
}
fn scale(points: &LaserPoints, factor: f32) -> LaserPoints{ fn scale(points: &LaserPoints, factor: f32) -> LaserPoints{
let new_points = points.points.iter().map(|point| { let new_points = points.points.iter().map(|point| {
let mut position = point.position.clone(); let mut position = point.position.clone();

View file

@ -2,7 +2,7 @@ use bevy::prelude::*;
use nannou_laser as laser; use nannou_laser as laser;
use std::time::Instant; use std::time::Instant;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::trap::{filters::{PointFilters}, tracks::CoordinateSpace}; use crate::trap::{filters::PointFilters, tracks::{CoordinateSpace, RenderableLayers}};
use super::tracks::{RenderableLines}; use super::tracks::{RenderableLines};
@ -74,7 +74,7 @@ pub fn apply_homography_matrix(h: Mat3, p: &[f32; 2]) -> [f32; 2]{
#[derive(Resource, Clone)] #[derive(Resource, Clone)]
pub struct LaserModel{ pub struct LaserModel{
pub t: Instant, // register start time, so that animations can be moving pub t: Instant, // register start time, so that animations can be moving
pub current_lines: RenderableLines, pub current_layers: RenderableLayers,
// pub dimming: f32, // pub dimming: f32,
pub config: DacConfig, // per dac configuration pub config: DacConfig, // per dac configuration
} }
@ -83,7 +83,7 @@ impl LaserModel{
pub fn new() -> Self{ pub fn new() -> Self{
Self{ Self{
t: Instant::now(), t: Instant::now(),
current_lines: RenderableLines::new(), current_layers: RenderableLayers::new(),
// dimming: 0.3, // dimming: 0.3,
config: DacConfig::default(), config: DacConfig::default(),
} }
@ -118,16 +118,18 @@ pub struct DacConfig{
// pub homography: Mat3, // pub homography: Mat3,
pub source: StreamSource, pub source: StreamSource,
pub filters: PointFilters, pub filters: PointFilters,
pub layers_enabled: u8,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum StreamSource { pub enum StreamSource {
Disabled, Disabled,
CurrentLines, CurrentLayers,
Rectangle, Rectangle,
GridY, // lines GridY, // lines
WorldGrid, // grid in world space WorldGrid, // grid in world space
Homography, // points for homography alignment Homography, // points for homography alignment
// Layers ( layers: )
// Circle, // segments // Circle, // segments
// Spiral, // Spiral,
} }
@ -135,7 +137,7 @@ pub enum StreamSource {
// usefull to create pull downs with an iterator // usefull to create pull downs with an iterator
pub const STREAM_SOURCES: [StreamSource; 6] = [ pub const STREAM_SOURCES: [StreamSource; 6] = [
StreamSource::Disabled, StreamSource::Disabled,
StreamSource::CurrentLines, StreamSource::CurrentLayers,
StreamSource::Rectangle, StreamSource::Rectangle,
StreamSource::GridY, StreamSource::GridY,
StreamSource::WorldGrid, StreamSource::WorldGrid,
@ -152,7 +154,7 @@ impl Default for DacConfig{
fn default() -> DacConfig{ fn default() -> DacConfig{
//DacConfig { name: "Unknown".into(), homography: Mat3::IDENTITY } //DacConfig { name: "Unknown".into(), homography: Mat3::IDENTITY }
// DacConfig { name: "Unknown".into(), homography: LASER_H_CM } // DacConfig { name: "Unknown".into(), homography: LASER_H_CM }
DacConfig { name: "Unknown".into(), source: StreamSource::CurrentLines, filters: PointFilters::default().with_homography(LASER_H) } DacConfig { name: "Unknown".into(), source: StreamSource::CurrentLayers, filters: PointFilters::default().with_homography(LASER_H), layers_enabled: 0b1111_1111 }
} }
} }
@ -214,7 +216,7 @@ impl StreamSource{
pub fn get_shape(&self, current_points: LaserPoints, config: &DacConfig) -> LaserPoints { pub fn get_shape(&self, current_points: LaserPoints, config: &DacConfig) -> LaserPoints {
match self { match self {
Self::CurrentLines => current_points, Self::CurrentLayers => current_points,
Self::Rectangle => { Self::Rectangle => {
shape_rect(LaserSpace::READY, 11) shape_rect(LaserSpace::READY, 11)
}, },

View file

@ -86,6 +86,36 @@ pub struct RenderableLines{
pub space: CoordinateSpace, // enum in python pub space: CoordinateSpace, // enum in python
} }
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct RenderableLayers(pub std::collections::HashMap<u8, RenderableLines>);
impl RenderableLayers{
pub fn new() -> Self{
Self (std::collections::HashMap::new())
}
pub fn with_alpha(&self, alpha: f32) -> Self {
if alpha == 1. {
return self.clone();
}
Self ( self.0.iter().map(|(layer, lines)| { (*layer, lines.with_alpha(alpha))}).collect() )
}
pub fn line_count(&self) -> usize {
let s = self.0.values().map(|l| l.lines.len()).sum();
s
}
pub fn point_count(&self) -> usize {
let s = self.0.values().map(|l| l.point_count()).sum();
s
}
}
impl RenderableLines{ impl RenderableLines{
pub fn new() -> Self{ pub fn new() -> Self{
RenderableLines { lines: Vec::new(), space: CoordinateSpace::World } RenderableLines { lines: Vec::new(), space: CoordinateSpace::World }

View file

@ -2,6 +2,8 @@ use zmq::Socket;
use serde_json::Result; use serde_json::Result;
use bevy::{ecs::system::SystemState, prelude::*, render::Render}; use bevy::{ecs::system::SystemState, prelude::*, render::Render};
use std::num::NonZero; use std::num::NonZero;
use crate::trap::tracks::RenderableLayers;
use super::{laser::{LaserApi, LaserTimer}, tracks::{Frame, RenderableLines, Track, TrackBundle}}; use super::{laser::{LaserApi, LaserTimer}, tracks::{Frame, RenderableLines, Track, TrackBundle}};
@ -60,10 +62,10 @@ fn receive_zmq_lines(
dbg!(&json); dbg!(&json);
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?"); // let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
let res: Result<RenderableLines> = serde_json::from_str(&json); let res: Result<RenderableLayers> = serde_json::from_str(&json);
let lines: RenderableLines = match res { let layers: RenderableLayers = match res {
Ok(lines) => lines, // if Ok(255), set x to 255 Ok(layers) => layers, // if Ok(255), set x to 255
Err(_e) => { Err(_e) => {
println!("No valid json? {json}"); println!("No valid json? {json}");
println!("{}", _e); println!("{}", _e);
@ -73,15 +75,15 @@ fn receive_zmq_lines(
}, // if Err("some message"), panic with error message "some message" }, // if Err("some message"), panic with error message "some message"
}; };
println!("receive {}", lines.lines.len()); println!("receive {} lines", layers.line_count());
for (laser_api, mut laser_timer) in lasers.iter_mut() { for (laser_api, mut laser_timer) in lasers.iter_mut() {
laser_timer.timer.tick(time.delta()); laser_timer.timer.tick(time.delta());
// let lines = get_laser_lines(version); // let lines = get_laser_lines(version);
let lines: RenderableLines = lines.clone(); let lines: RenderableLayers = layers.clone();
laser_api.laser_stream.send(|laser| { laser_api.laser_stream.send(|laser| {
let laser_lines: RenderableLines = lines; let current_layers: RenderableLayers = lines;
laser.current_lines = laser_lines; laser.current_layers = current_layers;
}).unwrap(); }).unwrap();
} }
} }