From acc2dfd74a11dc988755d37dbaba4e6da7cfdebe Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Sun, 24 Nov 2024 10:17:58 -0700 Subject: [PATCH] Add serde serialisation --- Cargo.toml | 2 +- src/app.rs | 16 +- src/panes.rs | 592 +++++++----------------------------- src/point_cloud_renderer.rs | 215 ++++++++----- 4 files changed, 260 insertions(+), 565 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d2f896..a23f596 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ eframe = { version = "0.29.1", features = [ "persistence",]} egui = { version = "0.29.1", features = ["callstack", "default", "log"] } -erased-serde = "0.4.5" glam = "0.29.2" rand = "0.8.5" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" +typetag = "0.2.18" diff --git a/src/app.rs b/src/app.rs index 99fbaa1..fd8becf 100644 --- a/src/app.rs +++ b/src/app.rs @@ -27,18 +27,18 @@ impl App { // } Some(Self { - pane_manager: PaneManager::new(Some(cc)), + pane_manager: PaneManager::new(cc), }) } } -impl Default for App { - fn default() -> Self { - Self { - pane_manager: PaneManager::new(None), - } - } -} +// impl Default for App { +// fn default() -> Self { +// Self { +// pane_manager: PaneManager::new(None), +// } +// } +// } impl eframe::App for App { /// Called each time the UI needs repainting, which may be many times per second. diff --git a/src/panes.rs b/src/panes.rs index cae7c60..5868257 100644 --- a/src/panes.rs +++ b/src/panes.rs @@ -1,4 +1,6 @@ use egui::{Ui, Color32, Stroke}; +use eframe::egui_glow::glow; +use std::sync::Arc; // use erased_serde::serialize_trait_object; #[derive(serde::Deserialize, serde::Serialize, PartialEq)] @@ -11,14 +13,20 @@ pub enum PaneMode { Center, } +#[typetag::serde(tag = "type")] pub trait Pane { - fn new(cc: &eframe::CreationContext<'_>) -> PaneState where Self: Sized; + fn new() -> PaneState where Self: Sized; + fn init(&mut self, pcc: &PsudoCreationContext); fn name(&mut self) -> &str; fn render(&mut self, ui: &mut Ui); fn context_menu(&mut self, ui: &mut Ui); } -// #[derive(serde::Deserialize, serde::Serialize)] +// impl Deserializer for Pane { + +// } + +#[derive(serde::Deserialize, serde::Serialize)] pub struct PaneState { // #[serde(skip)] pub pane: Box, @@ -27,12 +35,30 @@ pub struct PaneState { // pub window_location: Pos2, } -// pub struct NoPane {} -// impl Pane for NoPane { -// fn name(&mut self) -> &str {"ERROR"} -// fn render(&mut self, _ui: &mut Ui){} -// fn context_menu(&mut self, _ui: &mut Ui) {} -// } + +#[derive(serde::Serialize, serde::Deserialize)] +pub struct NoPane {} +#[typetag::serde] +impl Pane for NoPane { + fn new() -> PaneState where Self: Sized { + let mut s = Self {}; + PaneState { + id: s.name().to_string(), + mode: PaneMode::Left, + pane: Box::new(s), + } + } + fn init(&mut self, _pcc: &PsudoCreationContext) {} + fn name(&mut self) -> &str {"ERROR"} + fn render(&mut self, _ui: &mut Ui){} + fn context_menu(&mut self, _ui: &mut Ui) {} +} + +impl PaneState { + pub fn render(&mut self, ui: &mut Ui) { + self.pane.render(ui); + } +} // impl Default for dyn Pane { @@ -41,28 +67,19 @@ pub struct PaneState { // } // } -impl PaneState { - pub fn render(&mut self, ui: &mut Ui) { - self.pane.render(ui); - } -} - // pub struct PaneGroup { // pub direction: TileDirection, // pub panes: Vec, // } // #[derive(serde::Deserialize, serde::Serialize)] -pub struct PaneManager { - pub panes: Vec, -} - - +// #[derive(serde::Deserialize, serde::Serialize)] +#[derive(serde::Serialize, serde::Deserialize)] pub struct BluePane {} +#[typetag::serde] impl Pane for BluePane { - fn new(cc: &eframe::CreationContext<'_>) -> PaneState where Self: Sized { - + fn new() -> PaneState where Self: Sized { let mut s = Self {}; PaneState { id: s.name().to_string(), @@ -70,6 +87,7 @@ impl Pane for BluePane { pane: Box::new(s), } } + fn init(&mut self, _pcc: &PsudoCreationContext){} fn name(&mut self) -> &str {"BLUE"} fn render(&mut self, ui: &mut Ui){ ui.painter().rect(ui.max_rect(), 0., Color32::BLUE, Stroke::NONE); @@ -77,9 +95,12 @@ impl Pane for BluePane { fn context_menu(&mut self, _ui: &mut Ui) {} } + +#[derive(serde::Serialize, serde::Deserialize)] pub struct GreenPane {} +#[typetag::serde] impl Pane for GreenPane { - fn new(cc: &eframe::CreationContext<'_>) -> PaneState where Self: Sized { + fn new() -> PaneState where Self: Sized { let mut s = Self {}; PaneState { id: s.name().to_string(), @@ -87,6 +108,7 @@ impl Pane for GreenPane { pane: Box::new(s), } } + fn init(&mut self, _cc: &PsudoCreationContext){} fn name(&mut self) -> &str {"Green"} fn render(&mut self, ui: &mut Ui){ ui.painter().rect(ui.max_rect(), 0., Color32::GREEN, Stroke::NONE); @@ -94,26 +116,40 @@ impl Pane for GreenPane { fn context_menu(&mut self, _ui: &mut Ui) {} } +pub struct PsudoCreationContext { + pub gl: Option>, +} + +pub struct PaneManager { + pcc: PsudoCreationContext, + pub panes: Vec, +} + + impl PaneManager { - pub fn new(cc: Option<&eframe::CreationContext<'_>>) -> Self { - if let Some(cc) = cc { - Self { - panes: vec![ - BluePane::new(cc), - GreenPane::new(cc), - // PaneState {pane: Box::new(BluePane{}), id: "iqnhjqnbekjq".to_string(), mode: PaneMode::Windowed}, - // PaneState {pane: Box::new(GreenPane{}), id: "kjwkjwqfd".to_string(), mode: PaneMode::Right}, - crate::point_cloud_renderer::PointRendererPane::new(cc), - ], - } - } else { - Self { - panes: vec![] - } + pub fn new(cc: &eframe::CreationContext<'_>) -> Self { + // if let Some(cc) = cc { + + let mut panes = vec![ + BluePane::new(), + GreenPane::new(), + crate::point_cloud_renderer::PointRendererPane::new(), + ]; + + let pcc = PsudoCreationContext { + gl: cc.gl.clone(), + }; + + for pane in &mut panes { + pane.pane.init(&pcc); + } + + Self { + pcc, + panes } } - pub fn render(&mut self, ui: &mut Ui){ let len = self.panes.len(); @@ -125,6 +161,8 @@ impl PaneManager { egui::widgets::global_theme_preference_switch(ui); ui.menu_button("File", |ui| { + if ui.button("Save Layout").clicked() {self.save_layout();} + if ui.button("Load Layout").clicked() {self.load_layout();} if ui.button("Quit").clicked() { ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); } @@ -162,9 +200,16 @@ impl PaneManager { } }); - ui.separator(); - // self. + + for i in 0..len { + ui.menu_button(self.panes[i].id.clone(), |ui| { + let pane: &mut PaneState = &mut self.panes[i]; + if pane.mode != PaneMode::Hidden { + pane.pane.context_menu(ui); + } + }); + } }); }); @@ -211,452 +256,23 @@ impl PaneManager { } } } + + fn save_layout(&self) { + if let Ok(json) = serde_json::to_string_pretty(&self.panes) { + let _ = std::fs::write("pane_layout.json", json); + } + } + + fn load_layout(&mut self) { + if let Ok(panes) = std::fs::read_to_string("pane_layout.json") { + if let Ok(panes) = serde_json::from_str(&panes) { + + self.panes = panes; + + for (mut pane) in &mut self.panes { + pane.pane.init(&self.pcc); + } + } + } + } } - -// impl - - - - - - - - -// use eframe::egui; -// use egui::Stroke; -// use serde::{Deserialize, Serialize}; -// use std::collections::HashMap; -// use std::fs; -// use egui::Color32; - -// #[derive(Serialize, Deserialize, Clone, PartialEq)] -// enum PaneMode { -// Hidden, -// Tiled, -// Windowed, -// } - -// #[derive(Serialize, Deserialize, Clone, PartialEq)] -// enum SplitDirection { -// Horizontal, -// Vertical, -// } - -// #[derive(Serialize, Deserialize, Clone)] -// struct GroupNode { -// direction: SplitDirection, -// children: Vec, -// sizes: Vec, // Stores the relative sizes of children -// } - -// #[derive(Serialize, Deserialize, Clone)] -// enum LayoutNode { -// Pane(String), // Stores pane identifier -// Group(GroupNode), -// } - -// #[derive(Serialize, Deserialize, Clone)] -// struct LayoutConfig { -// root: Option, -// windowed_panes: HashMap, -// } - -// #[derive(Serialize, Deserialize, Clone)] -// struct WindowedPaneConfig { -// position: [f32; 2], -// size: [f32; 2], -// } - -// pub trait Pane { -// fn name(&self) -> &str; -// fn show(&mut self, ui: &mut egui::Ui); -// fn default_size(&self) -> egui::Vec2; -// } - -// // Example panes implementation -// struct ConsolePane { -// content: String, -// } - -// impl Pane for ConsolePane { -// fn name(&self) -> &str { "Console" } -// fn show(&mut self, ui: &mut egui::Ui) { -// ui.painter().rect(ui.max_rect(), 0., Color32::RED, Stroke::NONE); -// ui.text_edit_multiline(&mut self.content); -// } -// fn default_size(&self) -> egui::Vec2 { egui::vec2(300.0, 200.0) } -// } - -// struct PropertiesPane { -// value: f32, -// } - -// impl Pane for PropertiesPane { -// fn name(&self) -> &str { "Properties" } -// fn show(&mut self, ui: &mut egui::Ui) { -// ui.painter().rect(ui.max_rect(), 0., Color32::BLUE, Stroke::NONE); -// ui.add(egui::Slider::new(&mut self.value, 0.0..=100.0)); -// } -// fn default_size(&self) -> egui::Vec2 { egui::vec2(200.0, 300.0) } -// } - -// struct DragState { -// dragged_pane: String, -// original_group_path: Vec, -// drag_started: bool, -// drop_target: Option, -// } - -// #[derive(Clone)] -// struct DropTarget { -// target_pane: String, -// group_path: Vec, -// position: DropPosition, -// } - -// #[derive(Clone, PartialEq)] -// enum DropPosition { -// Above, -// Below, -// Left, -// Right, -// Center, -// } - -// pub struct PaneManager { -// panes: HashMap>, -// layout: LayoutConfig, -// drag_state: Option, -// } - -// impl PaneManager { -// pub fn new() -> Self { -// let mut panes: HashMap> = HashMap::new(); -// panes.insert("properties".to_string(), Box::new(PropertiesPane { value: 50.0 })); -// panes.insert("console".to_string(), Box::new(ConsolePane { content: String::new() })); - -// // Create initial layout -// let initial_group = GroupNode { -// direction: SplitDirection::Vertical, -// children: vec![ -// LayoutNode::Pane("console".to_string()), -// LayoutNode::Pane("properties".to_string()), -// ], -// sizes: vec![0.5, 0.5], -// }; - -// let layout = LayoutConfig { -// root: Some(LayoutNode::Group(initial_group)), -// windowed_panes: HashMap::new(), -// }; - -// Self { -// panes, -// layout, -// drag_state: None, -// } -// } - -// fn save_layout(&self) { -// if let Ok(json) = serde_json::to_string_pretty(&self.layout) { -// let _ = fs::write("layout.json", json); -// } -// } - -// fn load_layout(&mut self) { -// if let Ok(contents) = fs::read_to_string("layout.json") { -// if let Ok(layout) = serde_json::from_str(&contents) { -// self.layout = layout; -// } -// } -// } - -// fn handle_drop(&mut self) { -// if let Some(drag_state) = &self.drag_state { -// if let Some(drop_target) = &drag_state.drop_target { -// let mut new_layout = self.layout.clone(); - -// // Remove dragged pane from original location -// self.remove_pane_from_path(&mut new_layout.root, &drag_state.original_group_path, &drag_state.dragged_pane); - -// // Insert at new location based on drop position -// self.insert_pane_at_target( -// &mut new_layout.root, -// &drop_target.group_path, -// &drop_target.target_pane, -// &drag_state.dragged_pane, -// &drop_target.position, -// ); - -// self.layout = new_layout; -// } -// } -// self.drag_state = None; -// } - -// fn remove_pane_from_path( -// &self, -// node: &mut Option, -// path: &[usize], -// pane_id: &str, -// ) -> bool { -// if path.is_empty() { -// return false; -// } - -// if let Some(LayoutNode::Group(group)) = node { -// if path.len() == 1 { -// if let Some(idx) = group.children.iter().position(|child| { -// matches!(child, LayoutNode::Pane(id) if id == pane_id) -// }) { -// group.children.remove(idx); -// group.sizes.remove(idx); -// return true; -// } -// } else if path[0] < group.children.len() { -// return self.remove_pane_from_path( -// &mut Some(group.children[path[0]].clone()), -// &path[1..], -// pane_id, -// ); -// } -// } -// false -// } - -// fn insert_pane_at_target( -// &self, -// node: &mut Option, -// path: &[usize], -// target_pane: &str, -// dragged_pane: &str, -// position: &DropPosition, -// ) { -// if let Some(LayoutNode::Group(group)) = node { -// if path.len() == 1 { -// let target_idx = group.children.iter().position(|child| { -// matches!(child, LayoutNode::Pane(id) if id == target_pane) -// }).unwrap(); -// // if target_idx.is_none(){ return; } -// // target_idx = target_idx.unwrap(); -// // target_idx = target_idx.unwrap(); - -// match (position, &group.direction) { -// (DropPosition::Above | DropPosition::Below, SplitDirection::Vertical) -// | (DropPosition::Left | DropPosition::Right, SplitDirection::Horizontal) => { -// // Insert in same group -// let insert_idx = if matches!(position, DropPosition::Below | DropPosition::Right) { -// target_idx + 1 -// } else { -// target_idx -// }; -// group.children.insert(insert_idx, LayoutNode::Pane(dragged_pane.to_string())); -// group.sizes.insert(insert_idx, 1.0 / (group.sizes.len() + 1) as f32); -// // Normalize sizes -// let total: f32 = group.sizes.iter().sum(); -// for size in &mut group.sizes { -// *size /= total; -// } -// } -// _ => { -// // Create new group -// let new_direction = if matches!(position, DropPosition::Above | DropPosition::Below) { -// SplitDirection::Vertical -// } else { -// SplitDirection::Horizontal -// }; - -// let mut new_group = GroupNode { -// direction: new_direction, -// children: vec![], -// sizes: vec![], -// }; - -// if matches!(position, DropPosition::Above | DropPosition::Left) { -// new_group.children.push(LayoutNode::Pane(dragged_pane.to_string())); -// new_group.children.push(LayoutNode::Pane(target_pane.to_string())); -// } else { -// new_group.children.push(LayoutNode::Pane(target_pane.to_string())); -// new_group.children.push(LayoutNode::Pane(dragged_pane.to_string())); -// } -// new_group.sizes = vec![0.5, 0.5]; - -// group.children[target_idx] = LayoutNode::Group(new_group); -// } -// } -// } else if path[0] < group.children.len() { -// self.insert_pane_at_target( -// &mut Some(group.children[path[0]].clone()), -// &path[1..], -// target_pane, -// dragged_pane, -// position, -// ); -// } -// } -// } - -// fn show_group( -// &mut self, -// ui: &mut egui::Ui, -// group: &GroupNode, -// path: &mut Vec, -// rect: egui::Rect, -// ) { -// let mut current_offset = if group.direction == SplitDirection::Horizontal { -// rect.left() -// } else { -// rect.top() -// }; - -// for (idx, (child, &size)) in group.children.iter().zip(group.sizes.iter()).enumerate() { -// path.push(idx); - -// let child_size = if group.direction == SplitDirection::Horizontal { -// size * rect.width() -// } else { -// size * rect.height() -// }; - -// let child_rect = if group.direction == SplitDirection::Horizontal { -// egui::Rect::from_min_size( -// egui::pos2(current_offset, rect.top()), -// egui::vec2(child_size, rect.height()), -// ) -// } else { -// egui::Rect::from_min_size( -// egui::pos2(rect.left(), current_offset), -// egui::vec2(rect.width(), child_size), -// ) -// }; - -// match child { -// LayoutNode::Pane(id) => { -// // let pane = self.panes.get_mut(id).unwrap(); -// // if !pane.is_none(){ -// self.show_pane(ui, id, child_rect, path.clone()); -// // } -// } -// LayoutNode::Group(child_group) => { -// self.show_group(ui, child_group, path, child_rect); -// } -// } - -// current_offset += child_size; -// path.pop(); -// } -// } - -// fn show_pane( -// &mut self, -// ui: &mut egui::Ui, -// id: &String, -// // pane: &mut Box, -// rect: egui::Rect, -// path: Vec, -// ) { -// let pane = self.panes.get_mut(id).unwrap(); -// let response = ui.allocate_rect(rect, egui::Sense::drag()); - -// if response.dragged() { -// if self.drag_state.is_none() { -// self.drag_state = Some(DragState { -// dragged_pane: pane.name().to_string(), -// original_group_path: path.clone(), -// drag_started: true, -// drop_target: None, -// }); -// } -// } - -// // Handle drop targeting -// if let Some(drag_state) = &mut self.drag_state { -// if drag_state.dragged_pane != pane.name() { -// let hover_pos: Option = ui.input(|i| {i.pointer.hover_pos().clone()}); -// if let Some(pos) = hover_pos { -// if rect.contains(pos) { -// let relative_pos = (pos - rect.min) / rect.size(); -// let position = if relative_pos.y < 0.25 { -// DropPosition::Above -// } else if relative_pos.y > 0.75 { -// DropPosition::Below -// } else if relative_pos.x < 0.25 { -// DropPosition::Left -// } else if relative_pos.x > 0.75 { -// DropPosition::Right -// } else { -// DropPosition::Center -// }; - -// drag_state.drop_target = Some(DropTarget { -// target_pane: pane.name().to_string(), -// group_path: path, -// position, -// }); -// } -// } -// } -// } - -// // Show the actual pane content -// let frame = egui::Frame::none() -// .fill(ui.style().visuals.window_fill) -// .stroke(ui.style().visuals.window_stroke) -// .inner_margin(egui::Margin::same(4.0)); - -// frame.show(ui, |ui| { -// ui.set_min_size(rect.size()); -// pane.show(ui); -// }); -// } - -// // fn is_valid_group -// } - -// impl eframe::App for PaneManager { -// fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { -// egui::TopBottomPanel::top("toolbar").show(ctx, |ui| { -// ui.horizontal(|ui| { -// ui.menu_button("File", |ui| { -// if ui.button("Save Layout").clicked() { -// self.save_layout(); -// ui.close_menu(); -// } -// if ui.button("Load Layout").clicked() { -// self.load_layout(); -// ui.close_menu(); -// } -// }); -// }); -// }); - -// let any_down = ctx.input(|i| {i.pointer.any_down().clone()}); -// if !any_down {// && drag_state.drag_started { -// self.handle_drop(); -// } - -// egui::CentralPanel::default().show(ctx, |ui| { - -// let mut root_group = if let LayoutNode::Group(c) = as Clone>::clone(&self.layout.root).unwrap() {c} else { unreachable!() }; - -// // if let Some(LayoutNode::Group(root_group)) = &self.layout.root { - - - -// // // let root = LayoutNode::Group(&mut self.layout.root.unwrap()); - -// // // if LayoutNode::Group(root_group).unwrap() - - - -// let mut path = Vec::new(); -// self.show_group(ui, &root_group, &mut path, ui.available_rect_before_wrap()); - -// }); - -// // Handle drag end -// // if let Some(drag_state) = &self.drag_state { - -// // } -// } -// } diff --git a/src/point_cloud_renderer.rs b/src/point_cloud_renderer.rs index f40c496..2171e8e 100644 --- a/src/point_cloud_renderer.rs +++ b/src/point_cloud_renderer.rs @@ -14,6 +14,7 @@ use egui::Align2; use std::time::Instant; use egui::Stroke; use egui::Ui; +use crate::panes; // Shader sources updated for 3D rendering with fixed-point positions const VERTEX_SHADER: &str = r#" @@ -56,11 +57,13 @@ const FRAGMENT_SHADER: &str = r#" "#; // Camera controller for 3D navigation +#[derive(Clone)] pub struct Camera { position: Vec3, pub orientation: Quat, distance: f32, pub point_size_scale: f32, + // last_pos: Option, } @@ -71,6 +74,7 @@ impl Camera { orientation: Quat::IDENTITY, distance: 5.0, point_size_scale: 0.1, + // last_pos: None, } } @@ -83,12 +87,9 @@ impl Camera { // } pub fn update(&mut self, i: InputState) { - // let response = { - // Mouse controls let mut changed = false; - // Right mouse button for rotation - if i.pointer.secondary_down() { + if i.pointer.secondary_down() && !i.modifiers.shift { let delta = i.pointer.delta(); let rotation_speed = 0.01; @@ -103,9 +104,31 @@ impl Camera { self.orientation = self.orientation.normalize(); changed = true; - } - - // Scroll for zoom\ + } // else if i.pointer.secondary_down() && i.modifiers.shift { + // let cur_pos = i.pointer.latest_pos(); + + // if let Some(last_pos) = self.last_pos { + // let last_angle = f32::atan2(last_pos.y, last_pos.x); + // if let Some(cur_pos) = cur_pos { + // let cur_angle = f32::atan2(cur_pos.y, cur_pos.x); + + // println!("{}",cur_angle - last_angle); + + // let pitch_rotation = Quat::from_axis_angle(Vec3::X, 0.); + // let yaw_rotation = Quat::from_axis_angle(Vec3::Y, 0.); + // let roll_rotation = Quat::from_axis_angle(Vec3::Z,cur_angle-last_angle); + + // self.orientation = self.orientation * pitch_rotation * yaw_rotation * roll_rotation; + // self.orientation = self.orientation.normalize(); + + // changed = true; + + // } + // } + + // self.last_pos = cur_pos; + // } + let zoom_delta = i.smooth_scroll_delta.x + i.smooth_scroll_delta.y; if zoom_delta != 0. { if i.modifiers.shift { @@ -119,7 +142,6 @@ impl Camera { changed = true; } - // Middle mouse button for camera-plane panning if i.pointer.primary_down() { let delta = i.pointer.delta(); let pan_speed = self.distance * 0.001; @@ -135,7 +157,6 @@ impl Camera { changed = true; } - @@ -194,18 +215,35 @@ struct PlyHeader { // color: Color32, // } + +#[derive(Default)] pub struct PointRenderer { - gl: Arc, - program: glow::Program, - vao: glow::VertexArray, - vbo: glow::Buffer, - points: Vec, + pub gl: Option>, + program: Option, + vao: Option, + vbo: Option, + points: Option>, // capacity: usize, - pub camera: Camera, + pub camera: Option, } +// impl Defalt for PointRenderer { +// fn default() -> Self { +// Self { +// gl: Option>, +// program: Option, +// vao: Option, +// vbo: Option, +// points: Option>, +// // capacity: usize, +// camera: Option, +// } +// } +// } +// } + impl PointRenderer { - pub fn new(gl: Option>, initial_capacity: usize) -> Self { + pub fn init(&mut self, gl: Option>, initial_capacity: usize) { use glow::HasContext; let gl = gl.unwrap(); @@ -258,24 +296,22 @@ impl PointRenderer { vbo }; - PointRenderer { - gl, - program, - vao, - vbo, - points: Vec::with_capacity(initial_capacity * 7), + self.gl = Some(gl); + self.program = Some(program); + self.vao = Some(vao); + self.vbo = Some(vbo); + self.points = Some(Vec::with_capacity(initial_capacity * 7)); // capacity: initial_capacity, - camera: Camera::new(), - } + self.camera = Some(Camera::new()); } pub fn add_point(&mut self, x: i32, y: i32, z: i32, color: Color32) { let [r, g, b, a] = color.to_array(); - self.points.extend_from_slice(&[x, y, z, r as i32, g as i32, b as i32, a as i32]); + self.points.as_mut().as_mut().expect("Not Initialised").extend_from_slice(&[x, y, z, r as i32, g as i32, b as i32, a as i32]); } pub fn clear(&mut self) { - self.points.clear(); + self.points.as_mut().as_mut().expect("Not Initialised").clear(); } pub fn render(&mut self, rect: Rect, input_state: Option) { @@ -283,55 +319,55 @@ impl PointRenderer { // Update camera if let Some(i) = input_state{ - self.camera.update(i); + self.camera.as_mut().expect("Not Initialised").update(i); } unsafe { - self.gl.use_program(Some(self.program)); + self.gl.as_mut().expect("Not Initialised").use_program(self.program); // Set up view-projection matrix let aspect = rect.width() / rect.height(); let projection = Mat4::perspective_rh(45.0f32.to_radians(), aspect, 0.1, 1000.0); - let view = self.camera.get_view_matrix(); + let view = self.camera.as_mut().expect("Not Initialised").get_view_matrix(); let view_projection = projection * view; - let location = self.gl.get_uniform_location(self.program, "u_view_projection") + let location = self.gl.as_mut().expect("Not Initialised").get_uniform_location(*self.program.as_mut().expect("Not Initialised"), "u_view_projection") .expect("Cannot get uniform location"); - self.gl.uniform_matrix_4_f32_slice(Some(&location), false, &view_projection.to_cols_array()); + self.gl.as_mut().expect("Not Initialised").uniform_matrix_4_f32_slice(Some(&location), false, &view_projection.to_cols_array()); // Set position scale factor (converts uint positions to world space) - let scale_location = self.gl.get_uniform_location(self.program, "u_position_scale") + let scale_location = self.gl.as_mut().expect("Not Initialised").get_uniform_location(*self.program.as_mut().expect("Not Initialised"), "u_position_scale") .expect("Cannot get scale uniform location"); - self.gl.uniform_1_f32(Some(&scale_location), 0.001); // Adjust this value to scale your point cloud + self.gl.as_mut().expect("Not Initialised").uniform_1_f32(Some(&scale_location), 0.001); // Adjust this value to scale your point cloud - let point_size_location = self.gl.get_uniform_location(self.program, "u_point_size_scale") + let point_size_location = self.gl.as_mut().expect("Not Initialised").get_uniform_location(*self.program.as_mut().expect("Not Initialised"), "u_point_size_scale") .expect("Cannot get point size scale location"); - self.gl.uniform_1_f32(Some(&point_size_location), self.camera.point_size_scale); + self.gl.as_mut().expect("Not Initialised").uniform_1_f32(Some(&point_size_location), self.camera.as_mut().expect("Not Initialised").point_size_scale); - self.gl.bind_vertex_array(Some(self.vao)); - self.gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vbo)); + self.gl.as_mut().expect("Not Initialised").bind_vertex_array(self.vao); + self.gl.as_mut().expect("Not Initialised").bind_buffer(glow::ARRAY_BUFFER, Some(*self.vbo.as_mut().expect("Not Initialised"))); - self.gl.buffer_sub_data_u8_slice( + self.gl.as_mut().expect("Not Initialised").buffer_sub_data_u8_slice( glow::ARRAY_BUFFER, 0, - bytemuck::cast_slice(&self.points), + bytemuck::cast_slice(&self.points.as_mut().expect("Not Initialised")), ); - self.gl.enable(glow::PROGRAM_POINT_SIZE); - self.gl.enable(glow::DEPTH_TEST); + self.gl.as_mut().expect("Not Initialised").enable(glow::PROGRAM_POINT_SIZE); + self.gl.as_mut().expect("Not Initialised").enable(glow::DEPTH_TEST); - self.gl.clear_depth_f32(1.0); - self.gl.depth_func(glow::LESS); - self.gl.depth_mask(true); + self.gl.as_mut().expect("Not Initialised").clear_depth_f32(1.0); + self.gl.as_mut().expect("Not Initialised").depth_func(glow::LESS); + self.gl.as_mut().expect("Not Initialised").depth_mask(true); // self.gl.clear_color(0.3, 0.3, 0.3, 1.0); - self.gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); + self.gl.as_mut().expect("Not Initialised").clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); - self.gl.draw_arrays(glow::POINTS, 0, (self.points.len() / 7) as i32); + self.gl.as_mut().expect("Not Initialised").draw_arrays(glow::POINTS, 0, (self.points.as_mut().as_mut().expect("Not Initialised").len() / 7) as i32); - self.gl.disable(glow::DEPTH_TEST); - self.gl.disable(glow::PROGRAM_POINT_SIZE); + self.gl.as_mut().expect("Not Initialised").disable(glow::DEPTH_TEST); + self.gl.as_mut().expect("Not Initialised").disable(glow::PROGRAM_POINT_SIZE); } } @@ -358,7 +394,7 @@ impl PointRenderer { self.clear(); // Reserve capacity - self.points.reserve(header.vertex_count * 7); + self.points.as_mut().as_mut().expect("Not Initialised").reserve(header.vertex_count * 7); // Parse vertices based on format if header.is_binary { @@ -457,17 +493,48 @@ impl Drop for PointRenderer { } } + + + + + + + + + + + + + + + + + + +#[derive(serde::Serialize, serde::Deserialize)] pub struct PointRendererPane { + #[serde(skip)] renderer: Arc>, + #[serde(skip)] points: Vec<(i32, i32, i32, Color32)>, + #[serde(skip)] file_dialog_open: bool, + #[serde(skip)] cur_path: String, } +// impl Default for PointRenderer { +// fn default() -> Self { +// Self {} +// } +// } + +#[typetag::serde] impl Pane for PointRendererPane { - fn new(cc: &eframe::CreationContext<'_>) -> PaneState where Self: Sized { + fn new() -> PaneState where Self: Sized { + let mut renderer = PointRenderer::default(); let mut s = Self { - renderer: Arc::new(Mutex::new(PointRenderer::new(cc.gl.clone(), 1_000_000))), + renderer: Arc::new(Mutex::new(renderer)), points: Vec::new(), file_dialog_open: false, cur_path: "./".to_string(), @@ -478,14 +545,21 @@ impl Pane for PointRendererPane { pane: Box::new(s), } } + fn init(&mut self, pcc: &panes::PsudoCreationContext){ + self.renderer.lock().expect("Renderer Not Initialized").init(pcc.gl.clone(), 1_000_000); + } fn name(&mut self) -> &str {"Point Cloud"} fn render(&mut self, ui: &mut Ui){ + let max_rect = ui.max_rect(); let renderer = self.renderer.clone(); + if renderer.lock().expect("Renderer Not Initialized").gl.is_none() { + return; + // renderer.lock().expect("Renderer Not Initialized").init(ui.ctx()., 1_000_000); + } renderer.lock().expect("Renderer Not Initialized").clear(); - if self.file_dialog_open { egui::Window::new("Load PLY File") .show(ui.ctx(), |ui| { @@ -557,7 +631,7 @@ impl Pane for PointRendererPane { renderer.lock().expect("Renderer Not Initialized").add_point(x, y, z, color); } - let o = renderer.lock().expect("Renderer Not Initialized").camera.orientation.clone(); + let o = as Clone>::clone(&renderer.lock().expect("Renderer Not Initialized").camera).unwrap().orientation.clone(); let cb = egui_glow::CallbackFn::new(move |_info, _painter| { renderer.lock().expect("Renderer Not Initialized").render(max_rect, input_state.clone()); @@ -570,28 +644,33 @@ impl Pane for PointRendererPane { ui.painter().add(callback); - let pos1 = o.inverse()*glam::Vec3::X; - let pos2 = o.inverse()*glam::Vec3::Y; - let pos3 = o.inverse()*glam::Vec3::Z; let line_length:f32 = 20.; - ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos1.x, y: -line_length*pos1.y,}], Stroke { - width: 1.5, - color: Color32::RED, - }); + // if let Some(input_state) = input_state { + // if input_state.pointer.any_down() { + + let pos1 = o.inverse()*glam::Vec3::X; + let pos2 = o.inverse()*glam::Vec3::Y; + let pos3 = o.inverse()*glam::Vec3::Z; + + ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos1.x, y: -line_length*pos1.y,}], Stroke { + width: 1.5, + color: Color32::RED, + }); - ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos2.x, y: -line_length*pos2.y,}], Stroke { - width: 1.5, - color: Color32::BLUE, - }); + ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos2.x, y: -line_length*pos2.y,}], Stroke { + width: 1.5, + color: Color32::BLUE, + }); - ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos3.x, y: -line_length*pos3.y,}], Stroke { - width: 1.5, - color: Color32::GREEN, - }); + ui.painter().line_segment([rect.center(), rect.center() + egui::Vec2{ x: line_length*pos3.x, y: -line_length*pos3.y,}], Stroke { + width: 1.5, + color: Color32::GREEN, + }); + // }} let end_time = Instant::now();