kitgit

tirbofish/dropbear · commit

6c5410e6bfea89331b287677c91650d748354fc8

quitting + loading docks from files :)

Unverified

tk <4tkbytes@pm.me> · 2025-07-23 12:46

view full diff

diff --git a/.cargo/config.toml b/.cargo/config.toml
index 29937b0..f1863bb 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,5 +1,5 @@
 [build]
-jobs = 8 
+jobs = 8
 
 [profile.dev]
 opt-level = 0
diff --git a/eucalyptus/Cargo.toml b/eucalyptus/Cargo.toml
index d1f4c24..c561b4f 100644
--- a/eucalyptus/Cargo.toml
+++ b/eucalyptus/Cargo.toml
@@ -12,7 +12,9 @@ anyhow = "1.0.98"
 ron = "0.10.1"
 chrono = "0.4.41"
 egui-toast = { git = "https://github.com/creativcoder/egui-toast" }
-egui_dock = { git = "https://github.com/Adanos020/egui_dock" }
+egui_dock = { git = "https://github.com/Adanos020/egui_dock", features = [
+    "serde",
+] }
 once_cell = "1.21"
 
 [dependencies.rhai]
diff --git a/eucalyptus/src/editor.rs b/eucalyptus/src/editor.rs
index 1e6c4ae..d60ee34 100644
--- a/eucalyptus/src/editor.rs
+++ b/eucalyptus/src/editor.rs
@@ -1,4 +1,4 @@
-use std::{collections::HashSet, path::PathBuf, str::FromStr, sync::Arc};
+use std::{collections::HashSet, path::PathBuf, sync::Arc};
 
 use dropbear_engine::{
     async_trait::async_trait,
@@ -74,6 +74,21 @@ impl Editor {
         }
     }
 
+    pub fn save_project_config(&self) -> anyhow::Result<()> {
+        let mut config = PROJECT.write().unwrap();
+        config.dock_layout = Some(self.dock_state.clone());
+        let project_path = config.project_path.clone();
+        config.write_to(&PathBuf::from(project_path))
+    }
+
+    pub fn load_project_config(&mut self) -> anyhow::Result<()> {
+        let config = PROJECT.read().unwrap();
+        if let Some(layout) = &config.dock_layout {
+            self.dock_state = layout.clone();
+        }
+        Ok(())
+    }
+
     pub fn show_ui(&mut self, ctx: &egui::Context) {
         egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
             egui::MenuBar::new().ui(ui, |ui| {
@@ -81,12 +96,7 @@ impl Editor {
                     ui.label("New");
                     ui.label("Open");
                     if ui.button("Save").clicked() {
-                        let project_path = {
-                            let config = PROJECT.read().unwrap();
-                            config.project_path.clone()
-                        };
-                        let mut config = PROJECT.write().unwrap();
-                        match config.write_to(&PathBuf::from_str(&project_path).unwrap()) {
+                        match self.save_project_config() {
                             Ok(_) => {}
                             Err(e) => {
                                 log::error!("Error saving project: {}", e);
@@ -119,12 +129,7 @@ impl Editor {
                         ui.label("Eucalyptus Editor");
                     });
                     if ui.button("Quit").clicked() {
-                        let project_path = {
-                            let config = PROJECT.read().unwrap();
-                            config.project_path.clone()
-                        };
-                        let mut config = PROJECT.write().unwrap();
-                        match config.write_to(&PathBuf::from_str(&project_path).unwrap()) {
+                        match self.save_project_config() {
                             Ok(_) => {}
                             Err(e) => {
                                 log::error!("Error saving project: {}", e);
@@ -139,6 +144,15 @@ impl Editor {
                             }
                         }
                         log::info!("Successfully saved project");
+                        self.toasts.add(egui_toast::Toast {
+                            kind: egui_toast::ToastKind::Success,
+                            text: format!("Successfully saved project").into(),
+                            options: ToastOptions::default()
+                                .duration_in_seconds(5.0)
+                                .show_progress(true),
+                            ..Default::default()
+                        });
+                        self.scene_command = SceneCommand::Quit;
                     }
                 });
                 ui.menu_button("Edit", |ui| {
@@ -203,6 +217,8 @@ impl TabViewer for EditorTabViewer {
 #[async_trait]
 impl Scene for Editor {
     async fn load(&mut self, graphics: &mut Graphics) {
+        let _ = self.load_project_config();
+
         let shader = Shader::new(
             graphics,
             include_str!("../../dropbear-engine/resources/shaders/shader.wgsl"),
diff --git a/eucalyptus/src/menu.rs b/eucalyptus/src/menu.rs
index aacd4a1..4de968f 100644
--- a/eucalyptus/src/menu.rs
+++ b/eucalyptus/src/menu.rs
@@ -9,6 +9,7 @@ use dropbear_engine::{
     log::{self, debug},
     scene::{Scene, SceneCommand},
 };
+use egui_toast::{ToastOptions, Toasts};
 use git2::Repository;
 
 use crate::states::{PROJECT, ProjectConfig};
@@ -25,12 +26,16 @@ pub struct MainMenu {
     show_progress: bool,
     progress: f32,
     progress_message: String,
+    toast: Toasts,
 }
 
 impl MainMenu {
     pub fn new() -> Self {
         Self {
             show_progress: false,
+            toast: egui_toast::Toasts::new()
+                .anchor(egui::Align2::RIGHT_BOTTOM, (-10.0, -10.0))
+                .direction(egui::Direction::BottomUp),
             ..Default::default()
         }
     }
@@ -143,15 +148,29 @@ impl Scene for MainMenu {
                     {
                         log::debug!("Opening project");
                         if let Some(path) = rfd::FileDialog::new()
-                            .add_filter("Eucalyptus Configuration Files", &["euc"])
+                            .add_filter("Eucalyptus Configuration Files", &["eucp"])
                             .pick_file()
                         {
-                            let config = ProjectConfig::read_from(&path).unwrap();
-                            log::info!("Loaded project!");
-                            let mut global = PROJECT.write().unwrap();
-                            *global = config;
-                            println!("Loaded config info: {:#?}", global);
-                            self.scene_command = SceneCommand::SwitchScene(String::from("editor"));
+                            match ProjectConfig::read_from(&path) {
+                                Ok(config) => {
+                                    log::info!("Loaded project!");
+                                    let mut global = PROJECT.write().unwrap();
+                                    *global = config;
+                                    println!("Loaded config info: {:#?}", global);
+                                    self.scene_command =
+                                        SceneCommand::SwitchScene(String::from("editor"));
+                                }
+                                Err(e) => if e.to_string().contains("missing field") {
+                                    self.toast.add(egui_toast::Toast {
+                                        kind: egui_toast::ToastKind::Error,
+                                        text: format!("Your project version is not up to date with the current project version. To fix this, // TODO: create a way to backup").into(),
+                                        options: ToastOptions::default()
+                                            .duration_in_seconds(5.0)
+                                            .show_progress(true),
+                                        ..Default::default()
+                                    });
+                                }
+                            };
                         } else {
                             log::error!("File dialog returned \"None\"");
                         }
@@ -242,6 +261,8 @@ impl Scene for MainMenu {
                     }
                 });
         }
+
+        self.toast.show(graphics.get_egui_context());
     }
 
     async fn exit(&mut self, _event_loop: &dropbear_engine::winit::event_loop::ActiveEventLoop) {}
diff --git a/eucalyptus/src/states.rs b/eucalyptus/src/states.rs
index 81bae3c..b2a49a8 100644
--- a/eucalyptus/src/states.rs
+++ b/eucalyptus/src/states.rs
@@ -1,5 +1,5 @@
 //! In this module, it will describe all the different types for
-//! storing configuration files (.euc).
+//! storing configuration files (.eucp for project and .eucc for config files for subdirectories).
 //!
 //! There is a singleton that is used for other crates to access,
 //! as well as public structs related to that config and docs (hopefully).
@@ -8,23 +8,27 @@ use std::{fs, path::PathBuf, sync::RwLock};
 
 use chrono::Utc;
 use dropbear_engine::log;
+use egui_dock::DockState;
 use once_cell::sync::Lazy;
 use ron::ser::PrettyConfig;
 use serde::{Deserialize, Serialize};
 
+use crate::editor::EditorTab;
+
 pub static PROJECT: Lazy<RwLock<ProjectConfig>> =
     Lazy::new(|| RwLock::new(ProjectConfig::default()));
 
 /// The root config file, responsible for building and other metadata.
 ///
 /// # Location
-/// This file is {project_name}.euc and is located at {project_dir}/
+/// This file is {project_name}.eucp and is located at {project_dir}/
 #[derive(Debug, Deserialize, Serialize, Default)]
 pub struct ProjectConfig {
     pub project_name: String,
     pub project_path: String,
     pub date_created: String,
     pub date_last_accessed: String,
+    pub dock_layout: Option<DockState<EditorTab>>,
 }
 
 impl ProjectConfig {
@@ -39,6 +43,7 @@ impl ProjectConfig {
             project_path,
             date_created,
             date_last_accessed,
+            dock_layout: None,
         }
     }
 
@@ -51,7 +56,7 @@ impl ProjectConfig {
         self.date_last_accessed = format!("{}", Utc::now().format("%Y-%m-%d %H:%M:%S"));
         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!("{}.euc", self.project_name.clone().to_lowercase()));
+        let config_path = path.join(format!("{}.eucp", self.project_name.clone().to_lowercase()));
         fs::write(&config_path, ron_str).map_err(|e| anyhow::anyhow!(e.to_string()))?;
         Ok(())
     }