From a6f115eb55388005a7893d0d891660440ce8f27c Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Wed, 11 Sep 2024 20:55:12 -0700 Subject: [PATCH] Preventing editing while dialogs are open --- Cargo.lock | 22 +++++++-------- Cargo.toml | 6 ++-- src/funnybones.rs | 70 +++++++++++++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5874dd6..6a07c77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,14 +108,14 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" [[package]] name = "appit" version = "0.3.2" -source = "git+https://github.com/khonsulabs/appit#6c59e6942fdeecf8405f0b0ee1098aeb4bef9e60" +source = "git+https://github.com/khonsulabs/appit#93479b81112dfeef2b1646c5050c9fbd305c3288" dependencies = [ "winit", ] @@ -844,7 +844,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "cushy" version = "0.4.0" -source = "git+https://github.com/khonsulabs/cushy#8eaf0f414f3c50e7f7fdee5ea1add39968ab7ac8" +source = "git+https://github.com/khonsulabs/cushy#8d082ab77f462a9798739fe0ddc39476b79231e2" dependencies = [ "ahash", "alot", @@ -872,7 +872,7 @@ dependencies = [ [[package]] name = "cushy-macros" version = "0.4.0" -source = "git+https://github.com/khonsulabs/cushy#8eaf0f414f3c50e7f7fdee5ea1add39968ab7ac8" +source = "git+https://github.com/khonsulabs/cushy#8d082ab77f462a9798739fe0ddc39476b79231e2" dependencies = [ "attribute-derive", "manyhow", @@ -1644,7 +1644,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kludgine" version = "0.10.0" -source = "git+https://github.com/khonsulabs/kludgine#7d2d0dae63ba14142cb5355f10cfff074659ae27" +source = "git+https://github.com/khonsulabs/kludgine#04013453b631609cacb0edf79f08aa00715f7621" dependencies = [ "ahash", "alot", @@ -2407,7 +2407,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.4", "smallvec", "windows-targets 0.52.6", ] @@ -2816,9 +2816,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -2929,9 +2929,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.36" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", diff --git a/Cargo.toml b/Cargo.toml index bb9299e..edb4efc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,14 +20,14 @@ required-features = ["editor"] [dependencies] serde = { version = "1.0.208", optional = true, features = ["derive"] } easing-function = "0.1.0" -rsn = { version = "0.1", optional = true } -tempfile = { version = "3.12.0", optional = true } -rfd = { version = "0.14.1", optional = true } # Editor dependencies cushy = { git = "https://github.com/khonsulabs/cushy", optional = true, features = [ "serde", ] } +rsn = { version = "0.1", optional = true } +tempfile = { version = "3.12.0", optional = true } +rfd = { version = "0.14.1", optional = true } [dev-dependencies] pot = "3.0.0" diff --git a/src/funnybones.rs b/src/funnybones.rs index d1df7bf..8d94229 100644 --- a/src/funnybones.rs +++ b/src/funnybones.rs @@ -13,8 +13,8 @@ use cushy::{ kludgine::app::winit::keyboard::ModifiersState, value::{Destination, Dynamic, DynamicRead, Source, Switchable, Watcher}, widget::{MakeWidget, SharedCallback, WidgetList, HANDLED}, - widgets::{checkbox::Checkable, input::InputValue, slider::Slidable, Space}, - window::{MakeWindow, PendingWindow, Window}, + widgets::{checkbox::Checkable, input::InputValue, layers::Modal, slider::Slidable, Space}, + window::{MakeWindow, PendingWindow, Window, WindowHandle}, App, Application, ModifiersStateExt, Open, PendingApp, WithClone, }; use funnybones::{ @@ -31,6 +31,7 @@ fn main() -> cushy::Result { } fn skeleton_window(path: Option) -> Window { + let modals = Modal::new(); let editing_skeleton = if let Some(path) = path.as_ref() { match EditingSkeleton::read_from(path) { Ok(skeleton) => skeleton, @@ -85,14 +86,18 @@ fn skeleton_window(path: Option) -> Window { }); bones_editor + .vertical_scroll() .expand() .and(canvas.expand().and(zoom).into_rows().expand()) .into_columns() + .expand() + .and(modals.clone()) + .into_layers() .with_shortcut("s", ModifiersState::PRIMARY, { - (&path, &editing_skeleton, &on_error).with_clone( - |(path, editing_skeleton, on_error)| { + (&path, &editing_skeleton, &on_error, &modals).with_clone( + |(path, editing_skeleton, on_error, modals)| { move |_| { - if let Err(err) = save(&path, &editing_skeleton, &on_error) { + if let Err(err) = save(&path, &editing_skeleton, &on_error, &modals) { on_error.invoke(err); } HANDLED @@ -102,7 +107,7 @@ fn skeleton_window(path: Option) -> Window { }) .with_shortcut("s", ModifiersState::PRIMARY | ModifiersState::SHIFT, { move |_| { - save_as(&path, &editing_skeleton, &on_error); + save_as(&path, &editing_skeleton, &on_error, &modals); HANDLED } }) @@ -113,12 +118,13 @@ fn save( path: &Dynamic>, skeleton: &EditingSkeleton, on_error: &SharedCallback, + modals: &Modal, ) -> Result<(), SaveError> { let current_path = path.read(); if let Some(path) = &*current_path { skeleton.write_to(path) } else { - save_as(path, skeleton, on_error); + save_as(path, skeleton, on_error, modals); Ok(()) } } @@ -127,13 +133,16 @@ fn save_as( path: &Dynamic>, skeleton: &EditingSkeleton, on_error: &SharedCallback, + modals: &Modal, ) { - (path, skeleton, on_error).with_clone(|(path, skeleton, on_error)| { + (path, skeleton, on_error, modals).with_clone(|(path, skeleton, on_error, modals)| { std::thread::spawn(move || { - if let Some(new_path) = rfd::FileDialog::new() + modals.present("Please dismiss the save file dialog to continue editing."); + let new_path = rfd::FileDialog::new() .add_filter("FunnyBones Skeleton (.fbs)", &["fbs"]) - .save_file() - { + .save_file(); + modals.dismiss(); + if let Some(new_path) = new_path { match skeleton.write_to(&new_path) { Ok(()) => { path.set(Some(new_path)); @@ -148,6 +157,7 @@ fn save_as( fn main_menu_window(app: &impl Application) -> Window { let window = PendingWindow::default(); let handle = window.handle(); + let visible = Dynamic::new(true); window .with_root( @@ -164,9 +174,11 @@ fn main_menu_window(app: &impl Application) -> Window { .and("New Animation".into_button()) .and("Open Existing...".into_button().on_click({ let mut app = app.as_app(); + let handle = handle.clone(); + let visible = visible.clone(); move |_| { - open_file(&mut app); - handle.request_close(); + visible.set(false); + open_file(&mut app, &handle, true); } })) .into_rows() @@ -174,6 +186,7 @@ fn main_menu_window(app: &impl Application) -> Window { ) .resize_to_fit(true) .resizable(false) + .visible(visible) } fn add_bones_to_skeleton( @@ -668,15 +681,26 @@ fn bone_property_editor(bone: SkeletalBone, watcher: &Watcher, is_root: bool) -> .into_rows() } -fn open_file(app: &mut App) { - if let Some(file) = rfd::FileDialog::new() - .add_filter("FunnyBones Skeleton (.fbs)", &["fbs"]) - .pick_file() - { - if file.extension().map_or(false, |ext| ext == "fbs") { - let _ = skeleton_window(Some(file)).open(app); - } else { - todo!("unknown file type"); +fn open_file(app: &mut App, parent_window: &WindowHandle, close: bool) { + parent_window.execute({ + let mut app = app.clone(); + let parent_window = parent_window.clone(); + move |context| { + let dialog = rfd::FileDialog::new() + .add_filter("FunnyBones Skeleton (.fbs)", &["fbs"]) + .set_parent(context.winit().expect("running on winit")); + std::thread::spawn(move || { + if let Some(file) = dialog.pick_file() { + if file.extension().map_or(false, |ext| ext == "fbs") { + let _ = skeleton_window(Some(file)).open(&mut app); + } else { + todo!("unknown file type"); + } + } + if close { + parent_window.request_close(); + } + }); } - } + }); }