kitgit

tirbofish/dropbear · diff

ed57d91 · tk

worked on async and channels, with the dependency checking working perfectly :)

Unverified

diff --git a/Cargo.toml b/Cargo.toml
index b28240e..43311b3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -58,6 +58,7 @@ flate2 = "1.1"
 reqwest = { version = "0.11", features = ["stream"] }
 tar = "0.4"
 async-trait = "0.1"
+futures-util = "0.3"
 
 gltf = "1"
 thiserror = "2.0"
diff --git a/dropbear-engine/src/entity.rs b/dropbear-engine/src/entity.rs
index 171bef6..4af1406 100644
--- a/dropbear-engine/src/entity.rs
+++ b/dropbear-engine/src/entity.rs
@@ -68,7 +68,7 @@ pub struct LazyAdoptedEntity {
 impl LazyAdoptedEntity {
     /// Create a LazyAdoptedEntity from a file path (can be run on background thread)
     pub async fn from_file(path: &PathBuf, label: Option<&str>) -> anyhow::Result<Self> {
-        let buffer = std::fs::read(path)?;
+        let buffer = tokio::fs::read(path).await?;
         Self::from_memory(buffer, label).await
     }
 
diff --git a/dropbear-engine/src/lib.rs b/dropbear-engine/src/lib.rs
index 542a1d3..3c60f2b 100644
--- a/dropbear-engine/src/lib.rs
+++ b/dropbear-engine/src/lib.rs
@@ -407,14 +407,14 @@ impl App {
     /// - setup: A closure that can initialise the first scenes, such as a menu or the game itself.
     /// It takes an input of a scene manager and an input manager, and expects you to return back the changed
     /// managers.
-    pub fn run<F>(config: WindowConfiguration, app_name: &str, setup: F) -> anyhow::Result<()>
+    pub async fn run<F>(config: WindowConfiguration, app_name: &str, setup: F) -> anyhow::Result<()>
     where
         F: FnOnce(scene::Manager, input::Manager) -> (scene::Manager, input::Manager),
     {
         let log_dir = app_dirs2::app_root(AppDataType::UserData, &config.app_info)
             .expect("Failed to get app data directory")
             .join("logs");
-        std::fs::create_dir_all(&log_dir).expect("Failed to create log dir");
+        tokio::fs::create_dir_all(&log_dir).await.expect("Failed to create log dir");
 
         let datetime_str = Local::now().format("%Y-%m-%d_%H-%M-%S");
         let log_filename = format!("{}.{}.log", app_name, datetime_str);
diff --git a/dropbear-engine/src/model.rs b/dropbear-engine/src/model.rs
index fccda56..0557e56 100644
--- a/dropbear-engine/src/model.rs
+++ b/dropbear-engine/src/model.rs
@@ -299,7 +299,6 @@ impl Model {
         buffer: impl AsRef<[u8]>,
         label: Option<&str>
     ) -> anyhow::Result<Model> {
-        println!("========== Benchmarking speed of loading {:?} ==========", label);
         let start = Instant::now();
         let cache_key = label.unwrap_or("default").to_string();
 
@@ -307,7 +306,8 @@ impl Model {
             log::debug!("Model loaded from memory cache: {:?}", cache_key);
             return Ok(cached_model.clone());
         }
-
+        
+        println!("========== Benchmarking speed of loading {:?} ==========", label);
         log::debug!("Loading from memory");
         let res_ref = ResourceReference::from_bytes(buffer.as_ref());
 
@@ -481,7 +481,7 @@ impl Model {
             return Ok(cached_model.clone());
         }
 
-        let buffer = std::fs::read(path)?;
+        let buffer = tokio::fs::read(path).await?;
         let model = Self::load_from_memory(graphics, buffer, label).await?;
 
         MODEL_CACHE.lock().insert(path_str, model.clone());
diff --git a/eucalyptus-core/Cargo.toml b/eucalyptus-core/Cargo.toml
index 08affcd..93f73e1 100644
--- a/eucalyptus-core/Cargo.toml
+++ b/eucalyptus-core/Cargo.toml
@@ -32,6 +32,7 @@ flate2.workspace = true
 tar.workspace = true
 zip.workspace = true
 tokio.workspace = true
+futures-util.workspace = true
 
 [dev-dependencies]
 pollster = "*"
diff --git a/eucalyptus-core/src/scripting/build.rs b/eucalyptus-core/src/scripting/build.rs
index a11eae5..faf1983 100644
--- a/eucalyptus-core/src/scripting/build.rs
+++ b/eucalyptus-core/src/scripting/build.rs
@@ -3,6 +3,8 @@ use std::process::Command;
 use app_dirs2::{AppInfo, AppDataType, app_dir};
 use tokio::fs;
 use tokio::io::AsyncWriteExt;
+use tokio::sync::mpsc::UnboundedSender;
+use futures_util::StreamExt;
 
 const GLEAM_VERSION: &'static str = "1.12.0";
 const BUN_VERSION: &'static str = "1.2.22";
@@ -13,6 +15,17 @@ pub const APP_INFO: AppInfo = AppInfo {
     author: "4tkbytes",
 };
 
+pub enum InstallStatus {
+    NotStarted,
+    InProgress {
+        tool: String,
+        step: String,
+        progress: f32,
+    },
+    Success,
+    Failed(String),
+}
+
 /// Compiles a gleam project into WASM through a pipeline. 
 pub struct GleamScriptCompiler {
     #[allow(dead_code)]
@@ -26,29 +39,31 @@ impl GleamScriptCompiler {
         }
     }
 
-    pub async fn build(self) -> anyhow::Result<()> {
-        Self::ensure_dependencies().await?;
+    pub async fn build(self, sender: Option<UnboundedSender<InstallStatus>>) -> anyhow::Result<()> {
+        Self::ensure_dependencies(sender).await?;
         Ok(())
     }
 
-    pub async fn ensure_dependencies() -> anyhow::Result<()> {
+    pub async fn ensure_dependencies(sender: Option<UnboundedSender<InstallStatus>>) -> anyhow::Result<()> {
         println!("Checking dependencies...");
         
-        let gleam_available = Self::check_tool_in_path("gleam").await;
-        if gleam_available {
-            println!("Gleam already exists in path");
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                tool: "None".to_string(),
+                step: "Checking existing tools...".to_string(),
+                progress: 0.05,
+            });
         }
+
+        let gleam_available = Self::check_tool_in_path("gleam").await;
         let bun_available = Self::check_tool_in_path("bun").await;
-        if bun_available {
-            println!("Bun already exists in path");
-        }
         let javy_available = Self::check_tool_in_path("javy").await;
-        if javy_available {
-            println!("Javy already exists in path");
-        }
 
         if gleam_available && bun_available && javy_available {
             println!("All dependencies found in PATH");
+            if let Some(ref s) = sender {
+                let _ = s.send(InstallStatus::Success);
+            }
             return Ok(());
         }
 
@@ -59,18 +74,82 @@ impl GleamScriptCompiler {
         let app_dir = app_dir(AppDataType::UserData, &APP_INFO, "")
             .map_err(|e| anyhow::anyhow!("Failed to get app directory: {}", e))?;
 
+        let tools_to_install: Vec<(&str, bool)> = vec![
+            ("Gleam", gleam_available),
+            ("Bun", bun_available),
+            ("Javy", javy_available),
+        ];
+        let total_to_install = tools_to_install.iter().filter(|(_, avail)| !avail).count();
+        let mut installed_count = 0;
+
         if !gleam_available {
-            Self::download_gleam(&app_dir).await?;
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Gleam".to_string(),
+                    step: "Downloading Gleam...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_gleam(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Gleam".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
         }
 
         if !bun_available {
-            Self::download_bun(&app_dir).await?;
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Bun".to_string(),
+                    step: "Downloading Bun...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_bun(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Bun".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
         }
 
         if !javy_available {
-            Self::download_javy(&app_dir).await?;
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Javy".to_string(),
+                    step: "Downloading Javy...".to_string(),
+                    progress: 0.2 + (installed_count as f32 / total_to_install as f32) * 0.6,
+                });
+            }
+            Self::download_javy(&app_dir, sender.clone()).await?;
+            installed_count += 1;
+        } else {
+            if let Some(ref s) = sender.clone() {
+                let _ = s.send(InstallStatus::InProgress {
+                    tool: "Javy".to_string(),
+                    step: "Done!".to_string(),
+                    progress: 1.0,
+                });
+            }
+            installed_count += 1;
         }
 
+        if let Some(ref s) = sender.clone() {
+            let _ = s.send(InstallStatus::Success);
+        }
+
+        println!("All {} dependencies installed successfully", installed_count);
         Ok(())
     }
 
@@ -87,7 +166,7 @@ impl GleamScriptCompiler {
         }
     }
 
-    pub async fn download_gleam(app_dir: &PathBuf) -> anyhow::Result<()> {
+    pub async fn download_gleam(app_dir: &PathBuf, sender: Option<UnboundedSender<InstallStatus>>) -> anyhow::Result<()> {
         let gleam_dir = app_dir.join("dependencies").join("gleam").join(GLEAM_VERSION);
         
         if gleam_dir.exists() {
@@ -98,13 +177,13 @@ impl GleamScriptCompiler {
         println!("Downloading Gleam v{}...", GLEAM_VERSION);
         
         let gleam_link = Self::get_gleam_download_url()?;
-        Self::download_and_extract(&gleam_link, &gleam_dir, "gleam").await?;
+        Self::download_and_extract(&gleam_link, &gleam_dir, "gleam", sender).await?;
         
         println!("Gleam v{} downloaded successfully", GLEAM_VERSION);
         Ok(())
     }
 
-    pub async fn download_bun(app_dir: &PathBuf) -> anyhow::Result<()> {
+    pub async fn download_bun(app_dir: &PathBuf, sender: Option<UnboundedSender<InstallStatus>>) -> anyhow::Result<()> {
         let bun_dir = app_dir.join("dependencies").join("bun").join(BUN_VERSION);
         
         if bun_dir.exists() {
@@ -115,13 +194,13 @@ impl GleamScriptCompiler {
         println!("Downloading Bun v{}...", BUN_VERSION);
         
         let bun_link = Self::get_bun_download_url()?;
-        Self::download_and_extract(&bun_link, &bun_dir, "bun").await?;
+        Self::download_and_extract(&bun_link, &bun_dir, "bun", sender).await?;
         
         println!("Bun v{} downloaded successfully", BUN_VERSION);
         Ok(())
     }
 
-    pub async fn download_javy(app_dir: &PathBuf) -> anyhow::Result<()> {
+    pub async fn download_javy(app_dir: &PathBuf, sender: Option<UnboundedSender<InstallStatus>>) -> anyhow::Result<()> {
         let javy_dir = app_dir.join("dependencies").join("javy").join(JAVY_VERSION);
         
         if javy_dir.exists() {
@@ -132,24 +211,70 @@ impl GleamScriptCompiler {
         println!("Downloading Javy v{}...", JAVY_VERSION);
         
         let javy_link = Self::get_javy_download_url()?;
-        Self::download_and_extract(&javy_link, &javy_dir, "javy").await?;
+        Self::download_and_extract(&javy_link, &javy_dir, "javy", sender).await?;
         
         println!("Javy v{} downloaded successfully", JAVY_VERSION);
         Ok(())
     }
 
-    async fn download_and_extract(url: &str, target_dir: &PathBuf, tool_name: &str) -> anyhow::Result<()> {
+    async fn download_and_extract(
+        url: &str, 
+        target_dir: &PathBuf, 
+        tool_name: &str, 
+        sender: Option<UnboundedSender<InstallStatus>>
+    ) -> anyhow::Result<()> {
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Creating directories for {}...", tool_name),
+                progress: 0.0,
+                tool: tool_name.to_string(),
+            });
+        }
+
         fs::create_dir_all(target_dir).await?;
-        
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Downloading {}...", tool_name),
+                progress: 0.3,
+                tool: tool_name.to_string(),
+            });
+        }
+
         let response = reqwest::get(url).await?;
-        let bytes = response.bytes().await?;
-        
+        let total_size = response.content_length().unwrap_or(0);
+        let mut downloaded = 0;
+        let mut stream = response.bytes_stream();
+
         let temp_file = target_dir.join(format!("{}_download", tool_name));
         let mut file = fs::File::create(&temp_file).await?;
-        file.write_all(&bytes).await?;
+
+        while let Some(item) = stream.next().await {
+            let bytes = item?;
+            file.write_all(&bytes).await?;
+            downloaded += bytes.len() as u64;
+
+            if let Some(ref s) = sender {
+                let progress = 0.3 + (downloaded as f32 / total_size as f32) * 0.4;
+                let _ = s.send(InstallStatus::InProgress {
+                    step: format!("Downloading {}...", tool_name),
+                    progress,
+                    tool: tool_name.to_string(),
+                });
+            }
+        }
+
         file.sync_all().await?;
         drop(file);
 
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("Extracting {}...", tool_name),
+                progress: 0.7,
+                tool: tool_name.to_string(),
+            });
+        }
+
         if url.ends_with(".zip") {
             Self::extract_zip(&temp_file, target_dir).await?;
         } else if url.ends_with(".tar.gz") {
@@ -159,6 +284,15 @@ impl GleamScriptCompiler {
         }
 
         fs::remove_file(&temp_file).await?;
+
+        if let Some(ref s) = sender {
+            let _ = s.send(InstallStatus::InProgress {
+                step: format!("{} installation complete", tool_name),
+                progress: 0.9,
+                tool: tool_name.to_string(),
+            });
+        }
+
         Ok(())
     }
 
@@ -402,5 +536,5 @@ impl GleamScriptCompiler {
 
 #[tokio::test]
 async fn check_if_dependencies_install() {
-    GleamScriptCompiler::ensure_dependencies().await.unwrap();
+    GleamScriptCompiler::ensure_dependencies(None).await.unwrap();
 }
\ No newline at end of file
diff --git a/eucalyptus-editor/src/debug.rs b/eucalyptus-editor/src/debug.rs
index 023d66d..8249058 100644
--- a/eucalyptus-editor/src/debug.rs
+++ b/eucalyptus-editor/src/debug.rs
@@ -1,249 +1,180 @@
 //! Used to aid with debugging any issues with the editor.
 use crate::editor::Signal;
-use egui::{Ui, Window, ProgressBar};
-use eucalyptus_core::scripting::build::GleamScriptCompiler;
+use egui::Ui;
+use egui::ProgressBar;
+use egui::Window;
+use eucalyptus_core::scripting::build::{GleamScriptCompiler, InstallStatus};
 use tokio::sync::mpsc;
 
-#[derive(Debug, Clone)]
-pub enum DependencyProgress {
-    Starting,
-    CheckingPath(String),
-    Downloading(String),
-    Extracting(String),
-    Completed(String),
-    Error(String),
-    Finished,
-}
-
 pub struct DependencyInstaller {
-    pub progress_receiver: Option<mpsc::UnboundedReceiver<DependencyProgress>>,
-    pub current_progress: Vec<String>,
+    pub progress_receiver: Option<mpsc::UnboundedReceiver<InstallStatus>>,
     pub is_installing: bool,
-    pub progress_value: f32,
+
+    pub gleam_progress: f32,
+    pub bun_progress: f32,
+    pub javy_progress: f32,
+
+    pub gleam_status: String,
+    pub bun_status: String,
+    pub javy_status: String,
 }
 
 impl Default for DependencyInstaller {
     fn default() -> Self {
         Self {
             progress_receiver: None,
-            current_progress: Vec::new(),
             is_installing: false,
-            progress_value: 0.0,
+            gleam_progress: 0.0,
+            bun_progress: 0.0,
+            javy_progress: 0.0,
+            gleam_status: "Not started".to_string(),
+            bun_status: "Not started".to_string(),
+            javy_status: "Not started".to_string(),
         }
     }
 }
 
-/// Show a menu bar for debug. A new "Debug" menu button will show up on the editors menu bar.
-pub(crate) fn show_menu_bar(ui: &mut Ui, signal: &mut Signal, dependency_installer: &mut DependencyInstaller) {
-    ui.menu_button("Debug", |ui_debug| {
-        if ui_debug.button("Panic").clicked() {
-            log::warn!("Panic caused on purpose from Menu Button Click");
-            panic!("Testing out panicking with new panic module, this is a test")
-        }
-
-        if ui_debug.button("Show Entities Loaded").clicked() {
-            log::info!("Show Entities Loaded under Debug Menu is clicked");
-            *signal = Signal::LogEntities;
-        }
-
-        ui_debug.add_enabled_ui(!dependency_installer.is_installing, |ui| {
-            if ui.button("Ensure dependencies").clicked() {
-                log::info!("Clicked ensure dependencies from debug menu");
-                start_dependency_installation(dependency_installer);
-            }
-        });
-
-        if ui_debug.button("Evaluate script").clicked() {
-            log::info!("Evaluating script");
-        }
-    });
-}
-
-pub(crate) fn show_dependency_progress_window(
-    ctx: &egui::Context,
-    dependency_installer: &mut DependencyInstaller,
-) {
-    if let Some(receiver) = &mut dependency_installer.progress_receiver {
-        while let Ok(progress) = receiver.try_recv() {
-            match &progress {
-                DependencyProgress::Starting => {
-                    dependency_installer.current_progress.clear();
-                    dependency_installer.current_progress.push("Starting dependency check...".to_string());
-                    dependency_installer.progress_value = 0.0;
-                }
-                DependencyProgress::CheckingPath(tool) => {
-                    dependency_installer.current_progress.push(format!("Checking if {} is in PATH...", tool));
-                    dependency_installer.progress_value = 0.1;
-                }
-                DependencyProgress::Downloading(tool) => {
-                    dependency_installer.current_progress.push(format!("Downloading {}...", tool));
-                    dependency_installer.progress_value += 0.25;
-                }
-                DependencyProgress::Extracting(tool) => {
-                    dependency_installer.current_progress.push(format!("Extracting {}...", tool));
-                    dependency_installer.progress_value += 0.1;
-                }
-                DependencyProgress::Completed(tool) => {
-                    dependency_installer.current_progress.push(format!("✓ {} ready", tool));
-                    dependency_installer.progress_value += 0.1;
-                }
-                DependencyProgress::Error(error) => {
-                    dependency_installer.current_progress.push(format!("❌ Error: {}", error));
-                }
-                DependencyProgress::Finished => {
-                    dependency_installer.current_progress.push("✓ All dependencies ready!".to_string());
-                    dependency_installer.progress_value = 1.0;
-                    dependency_installer.is_installing = false;
-                    // dependency_installer.progress_receiver = None;
+impl DependencyInstaller {
+    pub fn update_progress(&mut self) {
+        let mut local_prog_rec = false;
+        let mut update_tool_status: (bool, String, f32, String) = Default::default();
+        if let Some(receiver) = &mut self.progress_receiver {
+            while let Ok(status) = receiver.try_recv() {
+                match status {
+                    InstallStatus::NotStarted => {
+                        self.is_installing = false;
+                    }
+                    InstallStatus::InProgress { tool, step, progress } => {
+                        self.is_installing = true;
+                        update_tool_status = (true, String::from(&tool), progress, String::from(&step));
+                    }
+                    InstallStatus::Success => {
+                        self.is_installing = false;
+                        local_prog_rec = true;
+                        self.gleam_status = "Complete".to_string();
+                        self.gleam_progress = 1.0;
+                        self.bun_status = "Complete".to_string();
+                        self.bun_progress = 1.0;
+                        self.javy_status = "Complete".to_string();
+                        self.javy_progress = 1.0;
+                    }
+                    InstallStatus::Failed(msg) => {
+                        self.is_installing = false;
+                        log::error!("Installation error: {}", msg);
+                        self.gleam_status = format!("Error: {}", msg);
+                        self.bun_status = format!("Error: {}", msg);
+                        self.javy_status = format!("Error: {}", msg);
+                    }
                 }
             }
         }
-    }
-
-    if dependency_installer.is_installing || !dependency_installer.current_progress.is_empty() {
-        Window::new("Dependency Installation")
-            .collapsible(false)
-            .resizable(false)
-            .show(ctx, |ui| {
-                ui.vertical(|ui| {
-                    ui.add(
-                        ProgressBar::new(dependency_installer.progress_value)
-                            .show_percentage()
-                            .animate(dependency_installer.is_installing)
-                    );
-                    
-                    ui.separator();
-                    
-                    egui::ScrollArea::vertical()
-                        .max_height(200.0)
-                        .show(ui, |ui| {
-                            for message in &dependency_installer.current_progress {
-                                ui.label(message);
-                            }
-                        });
-                    
-                    if !dependency_installer.is_installing && ui.button("Close").clicked() {
-                        dependency_installer.current_progress.clear();
-                    }
-                });
-            });
-    }
-}
-
-fn start_dependency_installation(dependency_installer: &mut DependencyInstaller) {
-    let (sender, receiver) = mpsc::unbounded_channel();
-    dependency_installer.progress_receiver = Some(receiver);
-    dependency_installer.is_installing = true;
-    dependency_installer.progress_value = 0.0;
-    
-    tokio::spawn(async move {
-        let _ = sender.send(DependencyProgress::Starting);
-        
-        match ensure_dependencies_with_progress(sender.clone()).await {
-            Ok(_) => {
-                let _ = sender.send(DependencyProgress::Finished);
-            }
-            Err(e) => {
-                let _ = sender.send(DependencyProgress::Error(e.to_string()));
-                let _ = sender.send(DependencyProgress::Finished);
-            }
+        if local_prog_rec {
+            self.progress_receiver = None;
         }
-    });
-}
-
-async fn ensure_dependencies_with_progress(
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let tools = vec![
-        ("gleam", "Gleam"),
-        ("bun", "Bun"), 
-        ("javy", "Javy"),
-    ];
-    
-    let mut tools_to_download = Vec::new();
-    
-    for (tool_cmd, tool_name) in &tools {
-        let _ = progress_sender.send(DependencyProgress::CheckingPath(tool_name.to_string()));
-        
-        let available = check_tool_in_path(tool_cmd).await;
-        if !available {
-            tools_to_download.push((*tool_cmd, *tool_name));
-        } else {
-            let _ = progress_sender.send(DependencyProgress::Completed(format!("{} (found in PATH)", tool_name)));
+        if update_tool_status.0 {
+            self.update_tool_status(update_tool_status.1.as_str(), update_tool_status.2, update_tool_status.3.as_str());
         }
     }
-    
-    if tools_to_download.is_empty() {
-        return Ok(());
-    }
-    
-    let app_dir = app_dirs2::app_dir(app_dirs2::AppDataType::UserData, &eucalyptus_core::scripting::build::APP_INFO, "")
-        .map_err(|e| anyhow::anyhow!("Failed to get app directory: {}", e))?;
-    
-    for (tool_cmd, tool_name) in tools_to_download {
-        let _ = progress_sender.send(DependencyProgress::Downloading(tool_name.to_string()));
-        
-        match tool_cmd {
+
+    fn update_tool_status(&mut self, tool: &str, progress: f32, status: &str) {
+        match tool.to_lowercase().as_str() {
             "gleam" => {
-                if let Err(e) = download_gleam_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Gleam: {}", e)));
-                    return Err(e);
-                }
+                self.gleam_progress = progress;
+                self.gleam_status = status.to_string();
             }
             "bun" => {
-                if let Err(e) = download_bun_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Bun: {}", e)));
-                    return Err(e);
-                }
+                self.bun_progress = progress;
+                self.bun_status = status.to_string();
             }
             "javy" => {
-                if let Err(e) = download_javy_with_progress(&app_dir, progress_sender.clone()).await {
-                    let _ = progress_sender.send(DependencyProgress::Error(format!("Failed to download Javy: {}", e)));
-                    return Err(e);
-                }
+                self.javy_progress = progress;
+                self.javy_status = status.to_string();
             }
             _ => {}
         }
-        
-        let _ = progress_sender.send(DependencyProgress::Completed(tool_name.to_string()));
     }
-    
-    Ok(())
-}
 
-async fn check_tool_in_path(tool: &str) -> bool {
-    let cmd = if cfg!(target_os = "windows") {
-        std::process::Command::new("where").arg(tool).output()
-    } else {
-        std::process::Command::new("which").arg(tool).output()
-    };
+    pub fn show_installation_window(&mut self, ctx: &egui::Context) {
+        Window::new("Installing Dependencies")
+            .resizable(true)
+            .collapsible(false)
+            .default_width(400.0)
+            .show(ctx, |ui| {
+                ui.heading("Installing Dependencies");
+
+                ui.separator();
+
+                ui.label("Gleam:");
+                ui.label(&self.gleam_status);
+                ui.add(ProgressBar::new(self.gleam_progress).show_percentage());
+                ui.separator();
+
+                ui.label("Bun:");
+                ui.label(&self.bun_status);
+                ui.add(ProgressBar::new(self.bun_progress).show_percentage());
+                ui.separator();
+
+                ui.label("Javy:");
+                ui.label(&self.javy_status);
+                ui.add(ProgressBar::new(self.javy_progress).show_percentage());
+                ui.separator();
 
-    match cmd {
-        Ok(output) => output.status.success(),
-        Err(_) => false,
+                let overall_progress = (self.gleam_progress + self.bun_progress + self.javy_progress) / 3.0;
+                ui.label("Overall Progress:");
+                ui.add(ProgressBar::new(overall_progress).show_percentage());
+
+                ui.separator();
+
+                if ui.button("Cancel").clicked() {
+                    self.is_installing = false;
+                    self.progress_receiver = None;
+                }
+            });
     }
 }
 
-async fn download_gleam_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Gleam".to_string()));
-    GleamScriptCompiler::download_gleam(app_dir).await
-}
+pub(crate) fn show_menu_bar(ui: &mut Ui, signal: &mut Signal, dependency_installer: &mut DependencyInstaller) {
+    ui.menu_button("Debug", |ui_debug| {
+        if ui_debug.button("Panic").clicked() {
+            log::warn!("Panic caused on purpose from Menu Button Click");
+            panic!("Testing out panicking with new panic module, this is a test")
+        }
 
-async fn download_bun_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Bun".to_string()));
-    GleamScriptCompiler::download_bun(app_dir).await
-}
+        if ui_debug.button("Show Entities Loaded").clicked() {
+            log::info!("Show Entities Loaded under Debug Menu is clicked");
+            *signal = Signal::LogEntities;
+        }
 
-async fn download_javy_with_progress(
-    app_dir: &std::path::PathBuf,
-    progress_sender: mpsc::UnboundedSender<DependencyProgress>,
-) -> anyhow::Result<()> {
-    let _ = progress_sender.send(DependencyProgress::Extracting("Javy".to_string()));
-    GleamScriptCompiler::download_javy(app_dir).await
+        ui_debug.add_enabled_ui(!dependency_installer.is_installing, |ui| {
+            if ui.button("Ensure dependencies").clicked() {
+                log::info!("Clicked ensure dependencies from debug menu");
+                
+                let (sender, receiver) = mpsc::unbounded_channel();
+                dependency_installer.progress_receiver = Some(receiver);
+                dependency_installer.is_installing = true;
+                
+                dependency_installer.gleam_progress = 0.0;
+                dependency_installer.bun_progress = 0.0;
+                dependency_installer.javy_progress = 0.0;
+                dependency_installer.gleam_status = "Starting...".to_string();
+                dependency_installer.bun_status = "Starting...".to_string();
+                dependency_installer.javy_status = "Starting...".to_string();
+
+                tokio::task::spawn(async move {
+                    match GleamScriptCompiler::ensure_dependencies(Some(sender.clone())).await {
+                        Ok(_) => {
+                            let _ = sender.send(InstallStatus::Success);
+                        }
+                        Err(e) => {
+                            let _ = sender.send(InstallStatus::Failed(e.to_string()));
+                        }
+                    }
+                });
+            }
+        });
+
+        if ui_debug.button("Evaluate script").clicked() {
+            log::info!("Evaluating script");
+        }
+    });
 }
\ No newline at end of file
diff --git a/eucalyptus-editor/src/editor/dock.rs b/eucalyptus-editor/src/editor/dock.rs
index bfa96cf..9aa740a 100644
--- a/eucalyptus-editor/src/editor/dock.rs
+++ b/eucalyptus-editor/src/editor/dock.rs
@@ -18,7 +18,7 @@ use log;
 use parking_lot::Mutex;
 use transform_gizmo_egui::{
     EnumSet, Gizmo, GizmoConfig, GizmoExt, GizmoMode,
-    math::{DMat4, DVec3},
+    math::DVec3,
 };
 
 pub struct EditorTabViewer<'a> {
@@ -360,30 +360,8 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                     {
                         if let Some((camera, _, _)) = q.get() {
                             self.gizmo.update_config(GizmoConfig {
-                                view_matrix: DMat4::look_at_lh(
-                                    DVec3::new(
-                                        camera.eye.x as f64,
-                                        camera.eye.y as f64,
-                                        camera.eye.z as f64,
-                                    ),
-                                    DVec3::new(
-                                        camera.target.x as f64,
-                                        camera.target.y as f64,
-                                        camera.target.z as f64,
-                                    ),
-                                    DVec3::new(
-                                        camera.up.x as f64,
-                                        camera.up.y as f64,
-                                        camera.up.z as f64,
-                                    ),
-                                )
-                                .into(),
-                                projection_matrix: DMat4::perspective_infinite_reverse_lh(
-                                    camera.fov_y as f64,
-                                    display_width as f64 / display_height as f64,
-                                    camera.znear as f64,
-                                )
-                                .into(),
+                                view_matrix: camera.view_mat.into(),
+                                projection_matrix: camera.proj_mat.into(),
                                 viewport: image_rect,
                                 modes: *self.gizmo_mode,
                                 orientation: transform_gizmo_egui::GizmoOrientation::Global,
diff --git a/eucalyptus-editor/src/editor/mod.rs b/eucalyptus-editor/src/editor/mod.rs
index 5cc8100..dd2b89d 100644
--- a/eucalyptus-editor/src/editor/mod.rs
+++ b/eucalyptus-editor/src/editor/mod.rs
@@ -326,7 +326,7 @@ impl Editor {
         Ok(())
     }
 
-    pub fn show_ui(&mut self, ctx: &Context) {
+    pub async 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| {
diff --git a/eucalyptus-editor/src/editor/scene.rs b/eucalyptus-editor/src/editor/scene.rs
index 1df6d3d..6ba8d3e 100644
--- a/eucalyptus-editor/src/editor/scene.rs
+++ b/eucalyptus-editor/src/editor/scene.rs
@@ -547,7 +547,7 @@ impl Scene for Editor {
                             script.path.display()
                         );
 
-                        let bytes = match std::fs::read(&script.path) {
+                        let bytes = match tokio::fs::read(&script.path).await {
                             Ok(val) => val,
                             Err(e) => {
                                 fatal!("Unable to read script {} to bytes because {}", &script.path.display(), e);
@@ -937,7 +937,8 @@ impl Scene for Editor {
                 }
             }
             Signal::LogEntities => {
-                log::info!("====================");
+                log::debug!("====================");
+                let mut counter = 0;
                 for entity in Arc::get_mut(&mut self.world).unwrap().iter() {
                     if let Some(entity) = entity.get::<&AdoptedEntity>() {
                         log::info!("Model: {:?}", entity.label());
@@ -946,8 +947,10 @@ impl Scene for Editor {
                     if let Some(entity) = entity.get::<&Light>() {
                         log::info!("Light: {:?}", entity.label());
                     }
+                    counter += 1;
                 }
-                log::info!("====================");
+                log::debug!("====================");
+                info!("Total entity count: {}", counter);
                 self.signal = Signal::None;
             },
             Signal::Spawn(entity_type) => {
@@ -1062,7 +1065,10 @@ impl Scene for Editor {
 
         self.light_manager.update(graphics.shared.clone(), &Arc::get_mut(&mut self.world).unwrap());
         
-        crate::debug::show_dependency_progress_window(&graphics.shared.get_egui_context(), &mut self.dep_installer);
+        if self.dep_installer.is_installing {
+            self.dep_installer.show_installation_window(&mut graphics.shared.get_egui_context());
+        }
+        self.dep_installer.update_progress();
     }
 
     async fn render<'a>(&mut self, graphics: &mut RenderContext<'a>) {
@@ -1077,7 +1083,7 @@ impl Scene for Editor {
         self.color = color.clone();
         self.size = graphics.shared.viewport_texture.size.clone();
         self.texture_id = Some(*graphics.shared.texture_id.clone());
-        self.show_ui(&graphics.shared.get_egui_context());
+        self.show_ui(&graphics.shared.get_egui_context()).await;
 
         self.window = Some(graphics.shared.window.clone());
         logging::render(&graphics.shared.get_egui_context());
diff --git a/eucalyptus-editor/src/main.rs b/eucalyptus-editor/src/main.rs
index a32a3a6..a8fa5c0 100644
--- a/eucalyptus-editor/src/main.rs
+++ b/eucalyptus-editor/src/main.rs
@@ -136,6 +136,7 @@ async fn main() -> anyhow::Result<()> {
 
                 (scene_manager, input_manager)
             })
+            .await
             .unwrap();
         }
         _ => unreachable!(),