tirbofish/dropbear · diff
quitting + loading docks from files :)
Signature present but could not be verified.
Unverified
@@ -1,5 +1,5 @@ [build] -jobs = 8 +jobs = 8 [profile.dev] opt-level = 0 @@ -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] @@ -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"), @@ -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) {} @@ -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(()) }