Live object editing!

This commit is contained in:
mars 2022-05-16 18:59:04 -06:00
parent e6cdb5ebe8
commit afb3dca4ce
2 changed files with 56 additions and 18 deletions

View File

@ -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<ui::FileEvent>,
objects: Vec<ui::ObjectWidget>,
}
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::<cyborg::scene::Transform>()
.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("<unnamed>".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<u32>) {
@ -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)
})
};
{

View File

@ -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)