kitgit

tirbofish/dropbear · diff

048f959 · tk

changed readme.md to update for linux build docs, fixed up the borked .eucp file where it copied to dir.

Unverified

diff --git a/README.md b/README.md
index 5fcbb4a..1386469 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,20 @@ If you might have not realised, all the crates/projects names are after Australi
 
 ## Build
 
-To build, clone the repository, then build it. It will build in debug mode, and use a lot of packages, so if your CPU is not fast enough for building you should brew a cup of coffee during the build time.
+To build, ensure build requirements, clone the repository, then build it. It will build in debug mode, and use a lot of packages, so if your CPU is not fast enough for building you should brew a cup of coffee during the build time.
+
+With Unix systems (macOS not tested), you will have to download a couple dependencies if building locally:
+<!-- If you have a macOS system, please create a PR and add your own implementation. I know you need to use brew, but I don't know what dependencies to install.  -->
+
+```bash
+# ubuntu, adapt to your own OS
+sudo apt install libudev-dev pkg-config libssl-dev clang
+
+# if on arm devices where russimp cannot compile
+sudo apt install assimp-utils
+```
+
+After downloading the requirements, you are free to build it using cargo.
 
 ```bash
 git clone git@github.com:4tkbytes/dropbear
diff --git a/dropbear-engine/src/camera.rs b/dropbear-engine/src/camera.rs
index 6454802..bdcb0c1 100644
--- a/dropbear-engine/src/camera.rs
+++ b/dropbear-engine/src/camera.rs
@@ -34,6 +34,9 @@ pub struct Camera {
 
     pub speed: f32,
     pub sensitivity: f32,
+
+    pub view_mat: Matrix4<f32>,
+    pub proj_mat: Matrix4<f32>,
 }
 
 impl Camera {
@@ -117,10 +120,13 @@ impl Camera {
         self.eye
     }
 
-    fn build_vp(&self) -> Matrix4<f32> {
+    fn build_vp(&mut self) -> Matrix4<f32> {
         let view = Matrix4::<f32>::look_at_rh(&self.eye, &self.target, &self.up);
         let proj = Perspective3::new(self.aspect, self.fov_y.to_radians(), self.znear, self.zfar);
-        return OPENGL_TO_WGPU_MATRIX * proj.to_homogeneous() * view;
+        self.view_mat = view.clone();
+        self.proj_mat = proj.clone().to_homogeneous();
+        let result = OPENGL_TO_WGPU_MATRIX * proj.to_homogeneous() * view;
+        result
     }
 
     pub fn create_bind_group_layout(&mut self, graphics: &Graphics, camera_buffer: Buffer) {
diff --git a/dropbear-engine/src/graphics.rs b/dropbear-engine/src/graphics.rs
index a9dbbcf..03cd678 100644
--- a/dropbear-engine/src/graphics.rs
+++ b/dropbear-engine/src/graphics.rs
@@ -18,7 +18,7 @@ use crate::{
 };
 
 pub struct Graphics<'a> {
-    pub state: &'a State,
+    pub state: &'a mut State,
     pub view: &'a TextureView,
     pub encoder: &'a mut CommandEncoder,
     pub screen_size: (f32, f32),
@@ -27,15 +27,24 @@ pub struct Graphics<'a> {
 pub const NO_TEXTURE: &'static [u8] = include_bytes!("no-texture.png");
 
 impl<'a> Graphics<'a> {
-    pub fn new(state: &'a State, view: &'a TextureView, encoder: &'a mut CommandEncoder) -> Self {
+    pub fn new(state: &'a mut State, view: &'a TextureView, encoder: &'a mut CommandEncoder) -> Self {
+        let screen_size = (state.config.width as f32, state.config.height as f32);
         Self {
             state,
             view,
             encoder,
-            screen_size: (state.config.width as f32, state.config.height as f32),
+            screen_size,
         }
     }
 
+    pub fn resize(&mut self, width: u32, height: u32) {
+        self.state.resize(width, height);
+    }
+
+    pub fn texture_bind_group(&mut self) -> &wgpu::BindGroupLayout {
+        &self.state.texture_bind_layout
+    }
+
     pub fn create_render_pipline(
         &mut self,
         shader: &Shader,
diff --git a/dropbear-engine/src/lib.rs b/dropbear-engine/src/lib.rs
index e360d80..0ffac09 100644
--- a/dropbear-engine/src/lib.rs
+++ b/dropbear-engine/src/lib.rs
@@ -224,7 +224,7 @@ Hardware:
                 label: Some("Render Encoder"),
             });
 
-        let viewport_view = { &self.viewport_texture.view };
+        let viewport_view = { &self.viewport_texture.view.clone() };
 
         self.egui_renderer.begin_frame(&self.window);
 
diff --git a/eucalyptus/src/editor/dock.rs b/eucalyptus/src/editor/dock.rs
index c9bbe75..3de8a98 100644
--- a/eucalyptus/src/editor/dock.rs
+++ b/eucalyptus/src/editor/dock.rs
@@ -14,6 +14,7 @@ use log;
 use egui_dock_fork::TabViewer;
 use egui_toast_fork::{Toast, ToastKind};
 use serde::{Deserialize, Serialize};
+use transform_gizmo_egui::{Gizmo, GizmoConfig};
 
 use crate::{
     APP_INFO,
@@ -28,10 +29,13 @@ pub enum EditorTab {
     Viewport,          // middle,
 }
 
-pub struct EditorTabViewer {
+pub struct EditorTabViewer<'a> {
     pub view: egui::TextureId,
     pub nodes: Vec<EntityNode>,
-    // pub world: hecs::World,
+    pub tex_size: Extent3d,
+    pub gizmo: &'a mut Gizmo,
+    pub camera: &'a mut Camera,
+    pub resize_signal: &'a mut (bool, u32, u32),
 }
 
 pub const SELECTED: LazyLock<Mutex<Option<hecs::Entity>>> = LazyLock::new(|| Mutex::new(None));
@@ -57,7 +61,7 @@ impl Default for INeedABetterNameForThisStruct {
 
 impl INeedABetterNameForThisStruct {}
 
-impl TabViewer for EditorTabViewer {
+impl<'a> TabViewer for EditorTabViewer<'a> {
     type Tab = EditorTab;
 
     fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
@@ -87,7 +91,28 @@ impl TabViewer for EditorTabViewer {
         match tab {
             EditorTab::Viewport => {
                 let size = ui.available_size();
-                ui.image((self.view, size));
+                let new_tex_width = size.x.max(1.0) as u32;
+                let new_tex_height = size.y.max(1.0) as u32;
+
+                if self.tex_size.width != new_tex_height || self.tex_size.height != new_tex_height {
+                    // log::debug!("Sending resize signal");
+                    *self.resize_signal = (true, new_tex_width, new_tex_height);
+
+                    self.tex_size.width = new_tex_width;
+                    self.tex_size.height = new_tex_height;
+
+                    let new_aspect = new_tex_width as f32 / new_tex_height as f32;
+                    self.camera.aspect = new_aspect;
+                }
+
+                ui.image((self.view, [self.tex_size.width as f32, self.tex_size.height as f32].into()));
+
+                // self.gizmo.update_config(GizmoConfig {
+                //     view_matrix: self.camera.view_mat.into(),
+                //     projection_matrix: self.camera.proj_mat.into(),
+                // });
+                // TODO: Figure out how to get the guizmos working because this is fucking annoying to deal with
+                // Note to self: fuck you >:(
             }
             EditorTab::ModelEntityList => {
                 ui.label("Model/Entity List");
diff --git a/eucalyptus/src/editor/input.rs b/eucalyptus/src/editor/input.rs
index 85fc1d7..0c6a174 100644
--- a/eucalyptus/src/editor/input.rs
+++ b/eucalyptus/src/editor/input.rs
@@ -15,17 +15,17 @@ impl Keyboard for Editor {
         match key {
             // KeyCode::Escape => event_loop.exit(),
             KeyCode::Escape => {
-                self.is_cursor_locked = !self.is_cursor_locked;
-                if !self.is_cursor_locked {
-                    if let Some((surface_idx, node_idx, _)) =
-                        self.dock_state.find_tab(&EditorTab::AssetViewer)
-                    {
-                        self.dock_state
-                            .set_focused_node_and_surface((surface_idx, node_idx));
-                    } else {
-                        self.dock_state.push_to_focused_leaf(EditorTab::AssetViewer);
-                    }
-                }
+                // self.is_cursor_locked = !self.is_cursor_locked;
+                // if !self.is_cursor_locked {
+                //     if let Some((surface_idx, node_idx, _)) =
+                //         self.dock_state.find_tab(&EditorTab::AssetViewer)
+                //     {
+                //         self.dock_state
+                //             .set_focused_node_and_surface((surface_idx, node_idx));
+                //     } else {
+                //         self.dock_state.push_to_focused_leaf(EditorTab::AssetViewer);
+                //     }
+                // }
             }
             KeyCode::KeyS => {
                 #[cfg(not(target_os = "macos"))]
diff --git a/eucalyptus/src/editor/mod.rs b/eucalyptus/src/editor/mod.rs
index 237e58d..3199494 100644
--- a/eucalyptus/src/editor/mod.rs
+++ b/eucalyptus/src/editor/mod.rs
@@ -11,12 +11,12 @@ use std::{
 };
 
 use dropbear_engine::{
-    camera::Camera,
-    scene::SceneCommand,
+    camera::Camera, scene::SceneCommand, 
 };
-use egui;
+use egui::{self, Context};
 use hecs::World;
 use log;
+use transform_gizmo_egui::Gizmo;
 use wgpu::{Color, Extent3d, RenderPipeline};
 use winit::{keyboard::KeyCode, window::Window};
 use egui_dock_fork::{DockArea, DockState, NodeIndex, Style};
@@ -53,6 +53,10 @@ pub struct Editor {
     project_name: String,
     project_path: Option<PathBuf>,
     pending_scene_switch: bool,
+
+    gizmo: Gizmo,
+
+    resize_signal: (bool, u32, u32),
 }
 
 impl Default for Editor {
@@ -90,6 +94,8 @@ impl Editor {
             project_name: String::new(),
             project_path: None,
             pending_scene_switch: false,
+            gizmo: Gizmo::default(),
+            resize_signal: (false, 1, 1)
         }
     }
 
@@ -109,7 +115,7 @@ impl Editor {
         Ok(())
     }
 
-    pub fn show_ui(&mut self, ctx: &egui::Context) {
+    pub fn show_ui(&mut self, ctx: &Context) {
         egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
             egui::MenuBar::new().ui(ui, |ui| {
                 ui.menu_button("File", |ui| {
@@ -206,7 +212,7 @@ impl Editor {
             });
         });
 
-        egui::CentralPanel::default().show(ctx, |ui| {
+        egui::CentralPanel::default().show(&ctx, |ui| {
             DockArea::new(&mut self.dock_state)
                 .style(Style::from_egui(ui.style().as_ref()))
                 .show_inside(
@@ -214,6 +220,10 @@ impl Editor {
                     &mut EditorTabViewer {
                         view: self.texture_id.unwrap(),
                         nodes: EntityNode::from_world(&self.world),
+                        gizmo: &mut self.gizmo,
+                        tex_size: self.size,
+                        camera: &mut self.camera,
+                        resize_signal: &mut self.resize_signal,
                     },
                 );
         });
diff --git a/eucalyptus/src/editor/scene.rs b/eucalyptus/src/editor/scene.rs
index ba1d8a3..fd042ac 100644
--- a/eucalyptus/src/editor/scene.rs
+++ b/eucalyptus/src/editor/scene.rs
@@ -70,12 +70,13 @@ impl Scene for Editor {
             0.125,
             0.002,
         );
+        let texture_bind_group = &graphics.texture_bind_group().clone();
 
         let model_layout = graphics.create_model_uniform_bind_group_layout();
         let pipeline = graphics.create_render_pipline(
             &shader,
             vec![
-                &graphics.state.texture_bind_layout,
+                texture_bind_group,
                 camera.layout(),
                 &model_layout,
             ],
@@ -111,6 +112,10 @@ impl Scene for Editor {
             }
         }
 
+        let new_size = graphics.state.viewport_texture.size;
+        let new_aspect = new_size.width as f32 / new_size.height as f32;
+        self.camera.aspect = new_aspect;
+
         self.camera.update(graphics);
 
         if !self.is_cursor_locked {
@@ -131,10 +136,15 @@ impl Scene for Editor {
             a: 1.0,
         };
         self.color = color.clone();
-        self.size = graphics.state.viewport_texture.size;
-        self.texture_id = Some(graphics.state.texture_id);
-        let ctx = graphics.get_egui_context();
-        self.show_ui(ctx);
+        self.size = graphics.state.viewport_texture.size.clone();
+        self.texture_id = Some(graphics.state.texture_id.clone());
+        self.show_ui(&graphics.get_egui_context());
+
+        if self.resize_signal.0.clone() {
+            // graphics.state.resize(self.resize_signal.1, self.resize_signal.2);
+            // self.resize_signal.0 = false;
+        }
+        
         self.window = Some(graphics.state.window.clone());
         if let Ok(mut toasts) = GLOBAL_TOASTS.lock() {
             toasts.show(graphics.get_egui_context());
diff --git a/eucalyptus/src/menu.rs b/eucalyptus/src/menu.rs
index 682a4dc..b53df6e 100644
--- a/eucalyptus/src/menu.rs
+++ b/eucalyptus/src/menu.rs
@@ -1,7 +1,5 @@
 use std::{
-    fs, io,
-    path::Path,
-    process::Command,
+    fs,
     sync::mpsc::{self, Receiver},
 };
 
@@ -12,7 +10,6 @@ use dropbear_engine::{
 };
 use log::{self, debug};
 use gilrs;
-use async_trait::async_trait;
 use egui::{self, FontId, Frame, RichText};
 use egui_toast_fork::{ToastOptions, Toasts};
 use git2::Repository;
@@ -57,49 +54,6 @@ impl MainMenu {
         }
     }
 
-    #[allow(dead_code)]
-    fn setup_poetry_project(project_path: &Path) -> anyhow::Result<()> {
-        if !Command::new("poetry").args(["--version"]).output().is_ok() {
-            return Err(anyhow!(
-                "Poetry is not installed. Please install it using pipx or the official poetry website"
-            ));
-        }
-
-        let status = Command::new("poetry")
-            .args(&["new", "scripts"])
-            .current_dir(project_path)
-            .status()
-            .expect("Failed to run poetry new");
-        if !status.success() {
-            return Err(anyhow!(io::Error::new(
-                io::ErrorKind::Other,
-                "Poetry project creation failed",
-            )));
-        }
-
-        let scripts_path = project_path.join("scripts");
-        if scripts_path.exists() && scripts_path.is_dir() {
-            for entry in fs::read_dir(&scripts_path)? {
-                let entry = entry?;
-                let path = entry.path();
-                let file_name = path.file_name().unwrap();
-                let dest = project_path.join(file_name);
-                fs::rename(&path, &dest)?;
-            }
-        }
-
-        if scripts_path.exists() {
-            fs::remove_dir_all(&scripts_path)?;
-        }
-
-        let tests_path = project_path.join("tests");
-        if tests_path.exists() {
-            fs::remove_dir_all(&tests_path)?;
-        }
-
-        Ok(())
-    }
-
     fn start_project_creation(&mut self) {
         let (tx, rx) = mpsc::channel();
         let project_name = self.project_name.clone();
@@ -153,7 +107,6 @@ impl MainMenu {
                     } else if folder == "src2" {
                         if let Some(path) = &project_path {
                             let mut config = ProjectConfig::new(project_name.clone(), &path);
-                            // let _ = config.write_to(&path);
                             let _ = config.write_to_all();
                             let mut global = PROJECT.write().unwrap();
                             *global = config;
@@ -162,29 +115,6 @@ impl MainMenu {
                             Err(anyhow!("Project path not found"))
                         }
                     }
-                    // else if folder == "scripts" || folder == "deps" {
-                    //     if folder == "scripts" {
-                    //         Self::setup_poetry_project(path)
-                    //     } else {
-                    //         let status = Command::new("poetry")
-                    //             .args(["add", "3d-to-image"])
-                    //             .current_dir(path)
-                    //             .status();
-                    //         match status {
-                    //             Ok(_) => Ok(()),
-                    //             Err(e) => Err(anyhow!(e)),
-                    //         }
-                    //     }
-                    // } else if folder == "scripts2" {
-                    //     if path.join("src/scripts").exists() {
-                    //         fs::write(
-                    //             &path.join("src/scripts/convert_model_to_image.py"),
-                    //             include_str!("scripts/convert_model_to_image.py"),
-                    //         )
-                    //         .map_err(|e| anyhow!(e))
-                    //     } else {
-                    //         Err(anyhow!("The src/scripts folder does not exist"))
-                    //     }
                     else {
                         if !full_path.exists() {
                             fs::create_dir_all(&full_path)
@@ -214,7 +144,6 @@ impl MainMenu {
     }
 }
 
-#[async_trait]
 impl Scene for MainMenu {
     fn load(&mut self, _graphics: &mut dropbear_engine::graphics::Graphics) {}
 
diff --git a/eucalyptus/src/states.rs b/eucalyptus/src/states.rs
index a0fbf1f..d87977a 100644
--- a/eucalyptus/src/states.rs
+++ b/eucalyptus/src/states.rs
@@ -36,7 +36,7 @@ pub static SOURCE: Lazy<RwLock<SourceConfig>> = Lazy::new(|| RwLock::new(SourceC
 #[derive(Debug, Deserialize, Serialize, Default)]
 pub struct ProjectConfig {
     pub project_name: String,
-    pub project_path: String,
+    pub project_path: PathBuf,
     pub date_created: String,
     pub date_last_accessed: String,
     #[serde(default)]
@@ -48,11 +48,10 @@ impl ProjectConfig {
     /// a new project, with it creating new defaults for everything.
     pub fn new(project_name: String, project_path: &PathBuf) -> Self {
         let date_created = format!("{}", Utc::now().format("%Y-%m-%d %H:%M:%S"));
-        let project_path_str = project_path.to_str().unwrap().to_string();
         let date_last_accessed = format!("{}", Utc::now().format("%Y-%m-%d %H:%M:%S"));
         let mut result = Self {
             project_name,
-            project_path: project_path_str,
+            project_path: project_path.to_path_buf(),
             date_created,
             date_last_accessed,
             dock_layout: None,
@@ -74,7 +73,7 @@ impl ProjectConfig {
         let ron_str = ron::ser::to_string_pretty(&self, PrettyConfig::default())
             .map_err(|e| anyhow::anyhow!("RON serialization error: {}", e))?;
         let config_path = path.join(format!("{}.eucp", self.project_name.clone().to_lowercase()));
-        self.project_path = path.clone().to_str().unwrap().to_string();
+        self.project_path = path.to_path_buf();
 
         fs::write(&config_path, ron_str).map_err(|e| anyhow::anyhow!(e.to_string()))?;
         Ok(())
@@ -88,11 +87,10 @@ impl ProjectConfig {
     pub fn read_from(path: &PathBuf) -> anyhow::Result<Self> {
         let ron_str = fs::read_to_string(path)?;
         let mut config: ProjectConfig = ron::de::from_str(&ron_str.as_str())?;
+        config.project_path = path.parent().unwrap().to_path_buf();
         log::info!("Loaded project!");
-        log::debug!("Loaded config info: {:#?}", config);
+        log::debug!("Loaded config info: {:?}", config);
         log::debug!("Updating with new content");
-        // config.write_to(&path.parent().unwrap().to_path_buf())?;
-        // config.assets = Assets::walk(&path.parent().unwrap().to_path_buf());
         config.load_config_to_memory()?;
         config.write_to_all()?;
         log::debug!("Successfully updated!");