diff --git a/editor/src/main.rs b/editor/src/main.rs index f324367..498e1b6 100644 --- a/editor/src/main.rs +++ b/editor/src/main.rs @@ -7,6 +7,7 @@ use egui_winit::winit::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; +use legion::EntityStore; use std::sync::Arc; mod render; @@ -26,6 +27,7 @@ struct Application { viewport: ui::ViewportWidget, render_state: render::RenderState, file_receiver: crossbeam_channel::Receiver, + objects: Vec, } impl Application { @@ -92,6 +94,7 @@ impl Application { viewport: ui::ViewportWidget::new(viewport_texture), render_state, file_receiver, + objects: vec![], } } @@ -113,9 +116,36 @@ impl Application { } } } + + for object in self.objects.iter_mut() { + object.flush_dirty(|object| { + let translation = glam::Vec3::from_slice(&object.position); + let rotation = glam::Quat::from_euler( + glam::EulerRot::XYZ, + object.rotation[0], + object.rotation[1], + object.rotation[2], + ); + let scale = glam::Vec3::splat(object.scale); + let transform = + glam::Mat4::from_scale_rotation_translation(scale, rotation, translation); + self.render_state + .world + .entry_mut(object.entity) + .unwrap() + .get_component_mut::() + .unwrap() + .transform = transform; + }); + } } pub fn load_stl(&mut self, path: std::path::PathBuf) { + let root_name = path + .file_name() + .map(|v| v.to_string_lossy().to_string()) + .unwrap_or("".to_string()); + use cyborg::pass::{ mesh::{Index, MeshPass, Vertex}, RenderPassBox, @@ -172,14 +202,25 @@ impl Application { mesh.attributes.push(vertices); mesh.attributes.push(indices); - self.render_state.world.push(( + let entity = self.render_state.world.push(( cyborg::scene::Mesh { mesh: mesh_pass.get_mesh_pool().load(mesh).unwrap(), }, cyborg::scene::Transform { - transform: glam::Mat4::from_translation(glam::Vec3::new(0.0, -10.0, 0.0)), + transform: Default::default(), }, )); + + let object = ui::ObjectWidget { + name: root_name, + position: [0.0; 3], + rotation: [0.0; 3], + scale: 1.0, + entity, + dirty: false, + }; + + self.objects.push(object); } pub fn on_resize(&mut self, new_size: PhysicalSize) { @@ -201,8 +242,9 @@ impl Application { let output = { puffin::profile_scope!("Draw egui"); let raw_input = self.egui_state.take_egui_input(&self.window); - self.egui_ctx - .run(raw_input, |ctx| self.ui.run(ctx, &mut self.viewport)) + self.egui_ctx.run(raw_input, |ctx| { + self.ui.run(ctx, &mut self.viewport, &mut self.objects) + }) }; { diff --git a/editor/src/ui.rs b/editor/src/ui.rs index 46294fc..72f5963 100644 --- a/editor/src/ui.rs +++ b/editor/src/ui.rs @@ -22,7 +22,6 @@ pub struct UserInterface { quit: bool, show_about: bool, log_contents: String, - object: ObjectWidget, } impl UserInterface { @@ -34,7 +33,6 @@ impl UserInterface { quit: false, show_about: false, log_contents: "Hello logging!\n".to_string(), - object: ObjectWidget::new(), } } @@ -42,7 +40,12 @@ impl UserInterface { self.quit } - pub fn run(&mut self, ctx: &egui::Context, viewport: &mut ViewportWidget) { + pub fn run( + &mut self, + ctx: &egui::Context, + viewport: &mut ViewportWidget, + objects: &mut [ObjectWidget], + ) { egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| { egui::menu::bar(ui, |ui| { ui.menu_button("File", |ui| { @@ -148,7 +151,9 @@ impl UserInterface { egui::SidePanel::left("objects_panel") .resizable(true) .show(ctx, |ui| { - self.object.ui(ui); + for object in objects.iter_mut() { + object.ui(ui); + } }); egui::TopBottomPanel::bottom("info_panel") @@ -260,20 +265,11 @@ pub struct ObjectWidget { pub position: [f32; 3], pub rotation: [f32; 3], pub scale: f32, + pub entity: legion::Entity, pub dirty: bool, } impl ObjectWidget { - pub fn new() -> Self { - Self { - name: "Example Object".to_string(), - position: [0.0; 3], - rotation: [0.0; 3], - scale: 1.0, - dirty: true, - } - } - pub fn ui(&mut self, ui: &mut egui::Ui) { egui::CollapsingHeader::new(&self.name) .default_open(true)