From 234a450c26743e77b93a68c8f8f1cd436c692664 Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Wed, 14 Feb 2024 17:49:17 -0600 Subject: [PATCH 1/7] configurable-sizing --- crates/editor_ui/src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/editor_ui/src/lib.rs b/crates/editor_ui/src/lib.rs index 0a021b76..b5fbaa2b 100644 --- a/crates/editor_ui/src/lib.rs +++ b/crates/editor_ui/src/lib.rs @@ -68,6 +68,7 @@ use bevy_mod_picking::{ use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin, PanOrbitCameraSystemSet}; use camera_view::CameraViewTabPlugin; use egui_dock::DockArea; +use sizing::IconSize; use space_editor_core::prelude::*; use bevy::{ @@ -184,6 +185,8 @@ pub struct EditorSetsPlugin; impl Plugin for EditorSetsPlugin { fn build(&self, app: &mut App) { + app.init_resource::<IconSize>() + .register_type::<IconSize>(); app.configure_sets(PostUpdate, UndoSet::Global.in_set(EditorSet::Editor)); app.configure_sets( @@ -403,3 +406,28 @@ pub mod colors { pub const SELECTED_ITEM_COLOR: Color32 = Color32::from_rgb(76, 93, 235); pub const TEXT_COLOR: Color32 = Color32::WHITE; } + +pub mod sizing { + use bevy::prelude::*; + + #[derive(Resource, Clone, Default, PartialEq, Eq, Reflect)] + #[reflect(Resource, Default)] + pub enum IconSize { + Small, + Gizmos, + #[default] + Medium, + Large, + } + + impl IconSize { + pub fn to_size(&self) -> f32 { + match self { + Self::Small => 16., + Self::Gizmos => 20., + Self::Medium => 24., + Self::Large => 32., + } + } + } +} \ No newline at end of file From e39e39c63ee5b520ddec29eac440f864100797ed Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Sat, 17 Feb 2024 20:42:25 -0600 Subject: [PATCH 2/7] Add a bunch of extra features --- Cargo.toml | 16 +++++------ crates/editor_ui/src/inspector/mod.rs | 11 +++++++- crates/editor_ui/src/lib.rs | 7 +++-- crates/editor_ui/src/menu_toolbars.rs | 38 +++++++++++++++++++++++++++ crates/editor_ui/src/settings.rs | 7 +++++ 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1c3498a1..9dec7dde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ homepage = "https://github.com/rewin123/space_editor" repository = "https://github.com/rewin123/space_editor" [workspace.package] -version = "0.3.1" +version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" authors = ["rewin <rewin1996@gmail.com>", "Julia Naomi <jnboeira@outlook.com>"] @@ -26,12 +26,12 @@ homepage = "https://github.com/rewin123/space_editor" bevy = "0.12" # Editor Crates -space_prefab = { version = "0.3.1", path = "crates/prefab" } -space_shared = { version = "0.3.1", path = "crates/shared" } -space_undo = { version = "0.3.1", path = "crates/undo" } -space_persistence = { version = "0.3.1", path = "crates/persistence"} -space_editor_core = { version = "0.3.1", path = "crates/editor_core", features = ["persistence_editor"] } -space_editor_ui = { version = "0.3.1", path = "crates/editor_ui", features = ["persistence_editor"] } +space_prefab = { version = "0.4.0", path = "crates/prefab" } +space_shared = { version = "0.4.0", path = "crates/shared" } +space_undo = { version = "0.4.0", path = "crates/undo" } +space_persistence = { version = "0.4.0", path = "crates/persistence"} +space_editor_core = { version = "0.4.0", path = "crates/editor_core", features = ["persistence_editor"] } +space_editor_ui = { version = "0.4.0", path = "crates/editor_ui", features = ["persistence_editor"] } # Crates inner libraries anyhow = "1.0" @@ -61,7 +61,7 @@ resvg = "0.37" serde = "1" # Community Modules -space_bevy_xpbd_plugin = { version = "0.3.1", path = "modules/bevy_xpbd_plugin"} +space_bevy_xpbd_plugin = { version = "0.4.0", path = "modules/bevy_xpbd_plugin"} [patch.crates-io] egui-gizmo = { git = "https://github.com/naomijub/egui-gizmo.git" } diff --git a/crates/editor_ui/src/inspector/mod.rs b/crates/editor_ui/src/inspector/mod.rs index f1d5cb56..95802c9e 100644 --- a/crates/editor_ui/src/inspector/mod.rs +++ b/crates/editor_ui/src/inspector/mod.rs @@ -276,11 +276,20 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM } }); + let width = ui.available_width(); + let add_component_str = "Add component"; + let pixel_count = add_component_str.len() as f32 * 8.; + let x_padding = (width - pixel_count - 16. - 16.) / 2.; + //Open context window by button ui.vertical_centered(|ui| { ui.spacing(); + ui.style_mut().spacing.button_padding = egui::Vec2 { + x: x_padding, + y: 2., + }; if ui - .add(add_component_icon(16., 16., "Add component")) + .add(add_component_icon(16., 16., add_component_str)) .clicked() { state.show_add_component_window = true; diff --git a/crates/editor_ui/src/lib.rs b/crates/editor_ui/src/lib.rs index b5fbaa2b..23ffccfc 100644 --- a/crates/editor_ui/src/lib.rs +++ b/crates/editor_ui/src/lib.rs @@ -185,8 +185,7 @@ pub struct EditorSetsPlugin; impl Plugin for EditorSetsPlugin { fn build(&self, app: &mut App) { - app.init_resource::<IconSize>() - .register_type::<IconSize>(); + app.init_resource::<IconSize>().register_type::<IconSize>(); app.configure_sets(PostUpdate, UndoSet::Global.in_set(EditorSet::Editor)); app.configure_sets( @@ -421,7 +420,7 @@ pub mod sizing { } impl IconSize { - pub fn to_size(&self) -> f32 { + pub const fn to_size(&self) -> f32 { match self { Self::Small => 16., Self::Gizmos => 20., @@ -430,4 +429,4 @@ pub mod sizing { } } } -} \ No newline at end of file +} diff --git a/crates/editor_ui/src/menu_toolbars.rs b/crates/editor_ui/src/menu_toolbars.rs index ab4bde8e..2b8e6c1a 100644 --- a/crates/editor_ui/src/menu_toolbars.rs +++ b/crates/editor_ui/src/menu_toolbars.rs @@ -46,8 +46,19 @@ pub struct MenuLoadEvent { pub path: String, } +pub struct FrameSpeedMultiplier { + pub ratio: f32, +} + +impl Default for FrameSpeedMultiplier { + fn default() -> Self { + Self { ratio: 1.0 } + } +} + fn in_game_menu( mut smoothed_dt: Local<f32>, + mut frame_speed_mult: Local<FrameSpeedMultiplier>, mut ctxs: EguiContexts, mut state: ResMut<NextState<EditorState>>, mut time: ResMut<Time<Virtual>>, @@ -55,6 +66,7 @@ fn in_game_menu( egui::TopBottomPanel::top("top_gameplay_panel") .exact_height(28.) .show(ctxs.ctx_mut(), |ui| { + let frame_duration = time.delta(); if !time.is_paused() { *smoothed_dt = (*smoothed_dt).mul_add(0.98, time.delta_seconds() * 0.02); } @@ -64,6 +76,9 @@ fn in_game_menu( let distance = ui.available_width() / 2. - 64.; ui.add_space(distance); let button = if time.is_paused() { "▶" } else { "⏸" }; + if ui.button("⏮").clicked() { + time.advance_by(frame_duration.mul_f32(-1.)); + } if ui.button(button).clicked() { if time.is_paused() { time.unpause(); @@ -74,6 +89,29 @@ fn in_game_menu( if ui.button("⏹").clicked() { state.set(EditorState::Editor); } + if ui.button("⏭").clicked() { + time.advance_by(frame_duration); + } + + ui.add_space(60.); + if egui::DragValue::new(&mut frame_speed_mult.ratio) + .suffix(" x") + .clamp_range((0.)..=5.) + .speed(1. / 60.) + .fixed_decimals(2) + .ui(ui) + .changed() + { + time.set_relative_speed(frame_speed_mult.ratio); + }; + + if ui + .button("⟲") + .on_hover_text("Reset frame speed multiplier to 1.0 ") + .clicked() + { + frame_speed_mult.ratio = 1.; + } }); }); } diff --git a/crates/editor_ui/src/settings.rs b/crates/editor_ui/src/settings.rs index 90ba061c..ce0d435d 100644 --- a/crates/editor_ui/src/settings.rs +++ b/crates/editor_ui/src/settings.rs @@ -4,11 +4,14 @@ use bevy::{ }; use bevy_egui_next::*; use space_editor_core::hotkeys::AllHotkeys; +use space_shared::ext::bevy_inspector_egui::bevy_inspector; use space_undo::ChangeChainSettings; #[cfg(feature = "persistence_editor")] use space_persistence::*; +use crate::sizing::IconSize; + use super::{ editor_tab::{EditorTab, EditorTabName}, EditorUiAppExt, @@ -207,6 +210,10 @@ impl EditorTab for SettingsWindow { let new_window_settings = &mut world.resource_mut::<NewWindowSettings>(); new_window_settings.ui(ui); + ui.spacing(); + ui.heading("Default Sizing"); + bevy_inspector::ui_for_resource::<IconSize>(world, ui); + ui.spacing(); ui.heading("Hotkeys in Game view tab"); if world.contains_resource::<AllHotkeys>() { From faea0ea1d77e704eeaded8857846e441099cc6fd Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Sat, 17 Feb 2024 21:35:17 -0600 Subject: [PATCH 3/7] attempt-to-configure-size --- crates/editor_ui/src/inspector/mod.rs | 11 ++++++++--- crates/editor_ui/src/lib.rs | 26 +++++++++++++++++++++++--- crates/editor_ui/src/menu_toolbars.rs | 21 +++++++++++++++++---- crates/editor_ui/src/settings.rs | 4 ++-- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/crates/editor_ui/src/inspector/mod.rs b/crates/editor_ui/src/inspector/mod.rs index 95802c9e..eb85e7a7 100644 --- a/crates/editor_ui/src/inspector/mod.rs +++ b/crates/editor_ui/src/inspector/mod.rs @@ -22,7 +22,7 @@ use space_shared::ext::bevy_inspector_egui::{ self, inspector_egui_impls::InspectorEguiImpl, reflect_inspector::InspectorUi, }; -use crate::{colors::DEFAULT_BG_COLOR, icons::add_component_icon}; +use crate::{colors::DEFAULT_BG_COLOR, icons::add_component_icon, sizing::Sizing}; use self::{ components_order::{ComponentsOrder, ComponentsPriority}, @@ -141,6 +141,7 @@ fn execute_inspect_command( /// System to show inspector panel pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashMap<String, bool>) { + let sizing = world.resource::<Sizing>().clone(); let selected_entity = world .query_filtered::<Entity, With<Selected>>() .get_single(world); @@ -279,7 +280,7 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM let width = ui.available_width(); let add_component_str = "Add component"; let pixel_count = add_component_str.len() as f32 * 8.; - let x_padding = (width - pixel_count - 16. - 16.) / 2.; + let x_padding = (width - pixel_count - 16. - sizing.icon.to_size()) / 2.; //Open context window by button ui.vertical_centered(|ui| { @@ -289,7 +290,11 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM y: 2., }; if ui - .add(add_component_icon(16., 16., add_component_str)) + .add(add_component_icon( + sizing.icon.to_size(), + sizing.icon.to_size(), + add_component_str, + )) .clicked() { state.show_add_component_window = true; diff --git a/crates/editor_ui/src/lib.rs b/crates/editor_ui/src/lib.rs index 23ffccfc..e122a414 100644 --- a/crates/editor_ui/src/lib.rs +++ b/crates/editor_ui/src/lib.rs @@ -68,7 +68,7 @@ use bevy_mod_picking::{ use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin, PanOrbitCameraSystemSet}; use camera_view::CameraViewTabPlugin; use egui_dock::DockArea; -use sizing::IconSize; +use sizing::{IconSize, Sizing}; use space_editor_core::prelude::*; use bevy::{ @@ -185,7 +185,9 @@ pub struct EditorSetsPlugin; impl Plugin for EditorSetsPlugin { fn build(&self, app: &mut App) { - app.init_resource::<IconSize>().register_type::<IconSize>(); + app.init_resource::<Sizing>() + .register_type::<Sizing>() + .register_type::<IconSize>(); app.configure_sets(PostUpdate, UndoSet::Global.in_set(EditorSet::Editor)); app.configure_sets( @@ -409,8 +411,26 @@ pub mod colors { pub mod sizing { use bevy::prelude::*; - #[derive(Resource, Clone, Default, PartialEq, Eq, Reflect)] + #[derive(Resource, Clone, PartialEq, Reflect)] #[reflect(Resource, Default)] + pub struct Sizing { + pub icon: IconSize, + pub gizmos: IconSize, + pub text: f32, + } + + impl Default for Sizing { + fn default() -> Self { + Self { + icon: IconSize::Medium, + gizmos: IconSize::Gizmos, + text: 18., + } + } + } + + #[derive(Clone, Default, PartialEq, Eq, Reflect)] + #[reflect(Default)] pub enum IconSize { Small, Gizmos, diff --git a/crates/editor_ui/src/menu_toolbars.rs b/crates/editor_ui/src/menu_toolbars.rs index 2b8e6c1a..3c13ff28 100644 --- a/crates/editor_ui/src/menu_toolbars.rs +++ b/crates/editor_ui/src/menu_toolbars.rs @@ -14,6 +14,7 @@ use crate::{ colors::*, hierarchy::{HierarchyQueryIter, HierarchyTabState}, icons::{add_bundle_icon, add_entity_icon, delete_entity_icon, prefab_icon}, + sizing::Sizing, ui_registration::{BundleReg, EditorBundleUntyped}, }; @@ -134,6 +135,7 @@ pub fn bottom_menu( mut state: ResMut<HierarchyTabState>, ui_reg: Res<BundleReg>, menu_state: Res<MenuToolbarState>, + sizing: Res<Sizing>, ) { let ctx = ctxs.ctx_mut(); egui::TopBottomPanel::bottom("bottom_menu").show(ctx, |ui| { @@ -142,7 +144,10 @@ pub fn bottom_menu( stl.spacing.button_padding = egui::Vec2::new(8., 2.); if ui - .add(delete_entity_icon(16., 16., "").stroke(stroke_default_color())) + .add( + delete_entity_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") + .stroke(stroke_default_color()), + ) .on_hover_text("Clear all entities") .clicked() { @@ -155,7 +160,10 @@ pub fn bottom_menu( } } if ui - .add(add_entity_icon(16., 16., "").stroke(stroke_default_color())) + .add( + add_entity_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") + .stroke(stroke_default_color()), + ) .on_hover_text("Add new entity") .clicked() { @@ -164,7 +172,9 @@ pub fn bottom_menu( change: Arc::new(AddedEntity { entity: id }), }); } - let spawnable_button = add_bundle_icon(16., 16., "").stroke(stroke_default_color()); + let spawnable_button = + add_bundle_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") + .stroke(stroke_default_color()); let spawnables = ui.add(if state.show_spawnable_bundles { spawnable_button.fill(SELECTED_ITEM_COLOR) @@ -239,6 +249,7 @@ pub fn top_menu( mut menu_state: ResMut<MenuToolbarState>, mut editor_events: EventWriter<EditorEvent>, background_tasks: Res<BackgroundTaskStorage>, + sizing: Res<Sizing>, ) { let ctx = ctxs.ctx_mut(); egui::TopBottomPanel::top("top_menu_bar") @@ -384,7 +395,9 @@ pub fn top_menu( // END Load Scene // Open GLTF - let open_gltf_button = prefab_icon(16., 16., "").stroke(stroke_default_color()); + let open_gltf_button = + prefab_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") + .stroke(stroke_default_color()); if ui .add(open_gltf_button) .on_hover_text("Open GLTF/GLB as prefab") diff --git a/crates/editor_ui/src/settings.rs b/crates/editor_ui/src/settings.rs index ce0d435d..b8401ee5 100644 --- a/crates/editor_ui/src/settings.rs +++ b/crates/editor_ui/src/settings.rs @@ -10,7 +10,7 @@ use space_undo::ChangeChainSettings; #[cfg(feature = "persistence_editor")] use space_persistence::*; -use crate::sizing::IconSize; +use crate::sizing::Sizing; use super::{ editor_tab::{EditorTab, EditorTabName}, @@ -212,7 +212,7 @@ impl EditorTab for SettingsWindow { ui.spacing(); ui.heading("Default Sizing"); - bevy_inspector::ui_for_resource::<IconSize>(world, ui); + bevy_inspector::ui_for_resource::<Sizing>(world, ui); ui.spacing(); ui.heading("Hotkeys in Game view tab"); From 6aaecb679ff3d0ce778857c77a7663f0002cee32 Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Thu, 22 Feb 2024 16:44:14 -0600 Subject: [PATCH 4/7] Add icon accessibility --- crates/editor_ui/Cargo.toml | 1 + crates/editor_ui/src/icons.rs | 64 +++---- crates/editor_ui/src/inspector/mod.rs | 6 +- crates/editor_ui/src/lib.rs | 29 +++- crates/editor_ui/src/menu_toolbars.rs | 229 ++++++++++++++------------ crates/editor_ui/src/settings.rs | 28 ++-- crates/editor_ui/src/tools/gizmo.rs | 16 +- modules/bevy_xpbd_plugin/src/lib.rs | 4 + 8 files changed, 201 insertions(+), 176 deletions(-) diff --git a/crates/editor_ui/Cargo.toml b/crates/editor_ui/Cargo.toml index c549be84..29108261 100644 --- a/crates/editor_ui/Cargo.toml +++ b/crates/editor_ui/Cargo.toml @@ -28,6 +28,7 @@ bevy_egui_next.workspace = true egui-gizmo.workspace = true egui_dock.workspace = true bevy_debug_grid.workspace = true +bevy-inspector-egui.workspace = true bevy_mod_picking.workspace = true bevy_asset_loader.workspace = true bevy_panorbit_camera.workspace = true diff --git a/crates/editor_ui/src/icons.rs b/crates/editor_ui/src/icons.rs index 04b90018..8a320ed9 100644 --- a/crates/editor_ui/src/icons.rs +++ b/crates/editor_ui/src/icons.rs @@ -17,9 +17,9 @@ pub const MESH: &str = "<svg fill=\"#F0f0f0\" height=\"200px\" width=\"200px\" v pub const SCENE: &str = "<svg fill=\"#ffffff\" version=\"1.1\" id=\"Capa_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 54.57 54.57\" xml:space=\"preserve\"><g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g><g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g><g id=\"SVGRepo_iconCarrier\"> <g> <path d=\"M52.186,4.632c-0.346,0.345-0.82,0.558-1.348,0.558c-0.525,0-1.003-0.213-1.348-0.558c-0.584-0.585-0.83-1.347-1.168-1.347 c-0.336,0-0.607,1.266-0.607,2.828s-1.343,2.829-3,2.829H9.857c-1.657,0-3-1.266-3-2.829c0-1.562-0.447-2.828-0.999-2.828 c-0.553,0-0.974,0.763-1.558,1.347C3.955,4.977,3.479,5.19,2.952,5.19c-0.526,0-1.002-0.213-1.347-0.558 c-0.582-0.584-0.79-1.347-1.081-1.347c-0.29,0-0.524,1.343-0.524,3v42c0,1.657,0.356,3,0.797,3c0.44,0,0.548-0.234,0.393-0.611 c-0.092-0.223-0.142-0.466-0.142-0.721c0-1.052,0.853-1.904,1.904-1.904c1.053,0,1.905,0.853,1.905,1.904 c0,0.255-0.05,0.498-0.142,0.721c-0.154,0.377,0.165,0.611,0.868,0.611c0.703,0,1.272-1.215,1.272-2.714s1.343-2.714,3-2.714 h34.858c1.657,0,3,1.215,3,2.714s0.395,2.714,0.882,2.714s0.632-0.234,0.478-0.611c-0.092-0.223-0.142-0.466-0.142-0.721 c0-1.052,0.853-1.904,1.905-1.904c1.052,0,1.904,0.853,1.904,1.904c0,0.255-0.051,0.498-0.143,0.721 c-0.154,0.377,0.129,0.611,0.784,0.611c0.656,0,1.188-1.343,1.188-3v-42c0-1.657-0.41-3-0.916-3 C53.15,3.285,52.77,4.048,52.186,4.632z M2.953,45.191c-1.052,0-1.904-0.854-1.904-1.905s0.853-1.905,1.904-1.905 c1.053,0,1.905,0.854,1.905,1.905C4.858,44.34,4.006,45.191,2.953,45.191z M2.953,38.524c-1.052,0-1.904-0.854-1.904-1.905 c0-1.053,0.853-1.904,1.904-1.904c1.053,0,1.905,0.853,1.905,1.904C4.858,37.672,4.006,38.524,2.953,38.524z M2.953,31.858 c-1.052,0-1.904-0.854-1.904-1.905c0-1.053,0.853-1.904,1.904-1.904c1.053,0,1.905,0.853,1.905,1.904S4.006,31.858,2.953,31.858z M2.953,25.191c-1.052,0-1.904-0.854-1.904-1.905s0.853-1.905,1.904-1.905c1.053,0,1.905,0.853,1.905,1.905 S4.006,25.191,2.953,25.191z M2.953,18.524c-1.052,0-1.904-0.854-1.904-1.905s0.853-1.905,1.904-1.905 c1.053,0,1.905,0.853,1.905,1.905S4.006,18.524,2.953,18.524z M2.953,11.857c-1.052,0-1.904-0.854-1.904-1.905 c0-1.053,0.853-1.905,1.904-1.905c1.053,0,1.905,0.853,1.905,1.905S4.006,11.857,2.953,11.857z M45.645,37.952 c0,1.894-1.535,3.429-3.43,3.429H12.357c-1.893,0-3.429-1.535-3.429-3.429V16.951c0-1.893,1.535-3.428,3.429-3.428h29.858 c1.893,0,3.43,1.535,3.43,3.428V37.952z M50.838,45.191c-1.053,0-1.904-0.854-1.904-1.905s0.852-1.905,1.904-1.905 c1.052,0,1.904,0.854,1.904,1.905C52.742,44.34,51.89,45.191,50.838,45.191z M50.838,38.524c-1.053,0-1.904-0.854-1.904-1.905 c0-1.053,0.852-1.904,1.904-1.904c1.052,0,1.904,0.853,1.904,1.904C52.742,37.672,51.89,38.524,50.838,38.524z M50.838,31.858 c-1.053,0-1.904-0.854-1.904-1.905c0-1.053,0.852-1.904,1.904-1.904c1.052,0,1.904,0.853,1.904,1.904S51.89,31.858,50.838,31.858z M50.838,25.191c-1.053,0-1.904-0.854-1.904-1.905s0.852-1.905,1.904-1.905c1.052,0,1.904,0.853,1.904,1.905 S51.89,25.191,50.838,25.191z M50.838,18.524c-1.053,0-1.904-0.854-1.904-1.905s0.852-1.905,1.904-1.905 c1.052,0,1.904,0.853,1.904,1.905S51.89,18.524,50.838,18.524z M50.838,11.857c-1.053,0-1.904-0.854-1.904-1.905 c0-1.053,0.852-1.905,1.904-1.905c1.052,0,1.904,0.853,1.904,1.905S51.89,11.857,50.838,11.857z\"></path> </g> </g></svg>"; pub const PREFAB: &str = "<svg fill=\"#ffffff\" viewBox=\"0 0 32 32\" id=\"icon\" xmlns=\"http://www.w3.org/2000/svg\"><g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g><g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g><g id=\"SVGRepo_iconCarrier\"> <defs> <style> .cls-1 { fill: none; } </style> </defs> <path d=\"M28.4473,16.1055,23,13.3818V7a1,1,0,0,0-.5527-.8945l-6-3a1.0008,1.0008,0,0,0-.8946,0l-6,3A1,1,0,0,0,9,7v6.3818L3.5527,16.1055A1,1,0,0,0,3,17v7a1,1,0,0,0,.5527.8945l6,3a1.001,1.001,0,0,0,.8946,0L16,25.1182l5.5527,2.7763a1.001,1.001,0,0,0,.8946,0l6-3A1,1,0,0,0,29,24V17A1,1,0,0,0,28.4473,16.1055ZM21,13.3818l-4,2V10.6182l4-2ZM16,5.1182,19.7637,7,16,8.8818,12.2363,7Zm-5,3.5,4,2v4.7636l-4-2ZM9,25.3818l-4-2V18.6182l4,2Zm1-6.5L6.2363,17,10,15.1182,13.7637,17Zm1,1.7364,4-2v4.7636l-4,2Zm10,4.7636-4-2V18.6182l4,2Zm1-6.5L18.2363,17,22,15.1182,25.7637,17Zm5,4.5-4,2V20.6182l4-2Z\"></path> <rect id=\"_Transparent_Rectangle_\" data-name=\"Transparent Rectangle\" class=\"cls-1\" width=\"32\" height=\"32\"></rect> </g></svg>"; -pub fn prefab_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn prefab_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("prefab.svg", crate::icons::PREFAB.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -27,9 +27,9 @@ pub fn prefab_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn scene_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn scene_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("scene.svg", crate::icons::SCENE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -37,9 +37,9 @@ pub fn scene_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn rotation_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn rotation_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("rotatio.svg", crate::icons::ROTATION.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -47,9 +47,9 @@ pub fn rotation_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<' } } -pub fn scale_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn scale_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("scale.svg", crate::icons::SCALE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -57,9 +57,9 @@ pub fn scale_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn entity_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn entity_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("entity.svg", crate::icons::ENTITY.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -67,9 +67,9 @@ pub fn entity_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn component_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn component_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("component.svg", crate::icons::COMPONENT.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -77,9 +77,9 @@ pub fn component_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button< } } -pub fn delete_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn delete_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("delete.svg", crate::icons::DELETE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -87,9 +87,9 @@ pub fn delete_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn light_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn light_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("light.svg", crate::icons::LIGHT.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -97,9 +97,9 @@ pub fn light_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn camera_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn camera_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("camera.svg", crate::icons::CAMERA.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -107,9 +107,9 @@ pub fn camera_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn mesh_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn mesh_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("mesh.svg", crate::icons::MESH.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -117,9 +117,9 @@ pub fn mesh_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { } } -pub fn bundle_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn bundle_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("bundle.svg", crate::icons::BUNDLE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -127,9 +127,9 @@ pub fn bundle_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> } } -pub fn translate_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn translate_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("translate.svg", crate::icons::TRANSLATE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -137,9 +137,9 @@ pub fn translate_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button< } } -pub fn add_bundle_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn add_bundle_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("add_bundle.svg", crate::icons::ADD_BUNDLE.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -147,9 +147,9 @@ pub fn add_bundle_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button } } -pub fn add_entity_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn add_entity_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("add_entity.svg", crate::icons::ADD_ENTITY.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -157,10 +157,10 @@ pub fn add_entity_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button } } -pub fn add_component_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn add_component_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("add_component.svg", crate::icons::ADD_COMPONENT.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { @@ -168,10 +168,10 @@ pub fn add_component_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::But } } -pub fn delete_entity_icon<'a>(x_size: f32, y_size: f32, text: &str) -> egui::Button<'a> { +pub fn delete_entity_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { let image = egui::Image::from_bytes("delete_entity.svg", crate::icons::DELETE_ENTITY.as_bytes()) - .max_size(bevy_egui_next::egui::vec2(x_size, y_size)); + .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); if text.is_empty() { egui::Button::image(image) } else { diff --git a/crates/editor_ui/src/inspector/mod.rs b/crates/editor_ui/src/inspector/mod.rs index eb85e7a7..f1195f2b 100644 --- a/crates/editor_ui/src/inspector/mod.rs +++ b/crates/editor_ui/src/inspector/mod.rs @@ -290,11 +290,7 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM y: 2., }; if ui - .add(add_component_icon( - sizing.icon.to_size(), - sizing.icon.to_size(), - add_component_str, - )) + .add(add_component_icon(sizing.icon.to_size(), add_component_str)) .clicked() { state.show_add_component_window = true; diff --git a/crates/editor_ui/src/lib.rs b/crates/editor_ui/src/lib.rs index e122a414..01a7db83 100644 --- a/crates/editor_ui/src/lib.rs +++ b/crates/editor_ui/src/lib.rs @@ -68,7 +68,6 @@ use bevy_mod_picking::{ use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin, PanOrbitCameraSystemSet}; use camera_view::CameraViewTabPlugin; use egui_dock::DockArea; -use sizing::{IconSize, Sizing}; use space_editor_core::prelude::*; use bevy::{ @@ -185,9 +184,6 @@ pub struct EditorSetsPlugin; impl Plugin for EditorSetsPlugin { fn build(&self, app: &mut App) { - app.init_resource::<Sizing>() - .register_type::<Sizing>() - .register_type::<IconSize>(); app.configure_sets(PostUpdate, UndoSet::Global.in_set(EditorSet::Editor)); app.configure_sets( @@ -410,12 +406,15 @@ pub mod colors { pub mod sizing { use bevy::prelude::*; + use bevy_inspector_egui::prelude::*; + use egui_dock::egui::RichText; - #[derive(Resource, Clone, PartialEq, Reflect)] - #[reflect(Resource, Default)] + #[derive(Resource, Clone, PartialEq, Reflect, InspectorOptions)] + #[reflect(Resource, Default, InspectorOptions)] pub struct Sizing { pub icon: IconSize, pub gizmos: IconSize, + #[inspector(min = 16.0, max = 24.0)] pub text: f32, } @@ -432,21 +431,37 @@ pub mod sizing { #[derive(Clone, Default, PartialEq, Eq, Reflect)] #[reflect(Default)] pub enum IconSize { + XSmall, Small, + SmallPlus, Gizmos, #[default] + Regular, Medium, Large, + XLarge, } impl IconSize { pub const fn to_size(&self) -> f32 { match self { + Self::XSmall => 12., Self::Small => 16., + Self::SmallPlus => 18., Self::Gizmos => 20., + Self::Regular => 20., Self::Medium => 24., - Self::Large => 32., + Self::Large => 28., + Self::XLarge => 32., } } } + + pub fn to_richtext(text: &str, size: &IconSize) -> RichText { + RichText::new(text).size(size.to_size()) + } + + pub fn to_label(text: &str, size: f32) -> RichText { + RichText::new(text).size(size) + } } diff --git a/crates/editor_ui/src/menu_toolbars.rs b/crates/editor_ui/src/menu_toolbars.rs index 3c13ff28..c361c1e0 100644 --- a/crates/editor_ui/src/menu_toolbars.rs +++ b/crates/editor_ui/src/menu_toolbars.rs @@ -14,7 +14,7 @@ use crate::{ colors::*, hierarchy::{HierarchyQueryIter, HierarchyTabState}, icons::{add_bundle_icon, add_entity_icon, delete_entity_icon, prefab_icon}, - sizing::Sizing, + sizing::{to_label, to_richtext, Sizing}, ui_registration::{BundleReg, EditorBundleUntyped}, }; @@ -63,9 +63,10 @@ fn in_game_menu( mut ctxs: EguiContexts, mut state: ResMut<NextState<EditorState>>, mut time: ResMut<Time<Virtual>>, + sizing: Res<Sizing>, ) { egui::TopBottomPanel::top("top_gameplay_panel") - .exact_height(28.) + .exact_height(&sizing.icon.to_size() + 4.) .show(ctxs.ctx_mut(), |ui| { let frame_duration = time.delta(); if !time.is_paused() { @@ -76,8 +77,12 @@ fn in_game_menu( ui.label(format!("FPS: {:04.0}", 1.0 / *smoothed_dt)); let distance = ui.available_width() / 2. - 64.; ui.add_space(distance); - let button = if time.is_paused() { "▶" } else { "⏸" }; - if ui.button("⏮").clicked() { + let button = if time.is_paused() { + to_richtext("▶", &sizing.icon) + } else { + to_richtext("⏸", &sizing.icon) + }; + if ui.button(to_richtext("⏮", &sizing.icon)).clicked() { time.advance_by(frame_duration.mul_f32(-1.)); } if ui.button(button).clicked() { @@ -87,10 +92,10 @@ fn in_game_menu( time.pause(); } } - if ui.button("⏹").clicked() { + if ui.button(to_richtext("⏹", &sizing.icon)).clicked() { state.set(EditorState::Editor); } - if ui.button("⏭").clicked() { + if ui.button(to_richtext("⏭", &sizing.icon)).clicked() { time.advance_by(frame_duration); } @@ -107,7 +112,7 @@ fn in_game_menu( }; if ui - .button("⟲") + .button(to_richtext("⟲", &sizing.icon)) .on_hover_text("Reset frame speed multiplier to 1.0 ") .clicked() { @@ -138,108 +143,116 @@ pub fn bottom_menu( sizing: Res<Sizing>, ) { let ctx = ctxs.ctx_mut(); - egui::TopBottomPanel::bottom("bottom_menu").show(ctx, |ui| { - egui::menu::bar(ui, |ui| { - let stl = ui.style_mut(); - stl.spacing.button_padding = egui::Vec2::new(8., 2.); - - if ui - .add( - delete_entity_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") - .stroke(stroke_default_color()), - ) - .on_hover_text("Clear all entities") - .clicked() - { - for (entity, _, _, _parent) in query.iter() { - commands.entity(entity).despawn_recursive(); + egui::TopBottomPanel::bottom("bottom_menu") + .exact_height(&sizing.icon.to_size().max(sizing.text) + 4.) + .show(ctx, |ui| { + ui.style_mut().spacing.menu_margin = Margin::symmetric(16., 4.); + egui::menu::bar(ui, |ui| { + let stl = ui.style_mut(); + stl.spacing.button_padding = egui::Vec2::new(8., 2.); + + if ui + .add( + delete_entity_icon(sizing.icon.to_size(), "") + .stroke(stroke_default_color()), + ) + .on_hover_text("Clear all entities") + .clicked() + { + for (entity, _, _, _parent) in query.iter() { + commands.entity(entity).despawn_recursive(); + changes.send(NewChange { + change: Arc::new(RemovedEntity { entity }), + }); + } + } + if ui + .add(add_entity_icon(sizing.icon.to_size(), "").stroke(stroke_default_color())) + .on_hover_text("Add new entity") + .clicked() + { + let id = commands.spawn_empty().insert(PrefabMarker).id(); changes.send(NewChange { - change: Arc::new(RemovedEntity { entity }), + change: Arc::new(AddedEntity { entity: id }), }); } - } - if ui - .add( - add_entity_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") - .stroke(stroke_default_color()), - ) - .on_hover_text("Add new entity") - .clicked() - { - let id = commands.spawn_empty().insert(PrefabMarker).id(); - changes.send(NewChange { - change: Arc::new(AddedEntity { entity: id }), - }); - } - let spawnable_button = - add_bundle_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") - .stroke(stroke_default_color()); + let spawnable_button = + add_bundle_icon(sizing.icon.to_size(), "").stroke(stroke_default_color()); - let spawnables = ui.add(if state.show_spawnable_bundles { - spawnable_button.fill(SELECTED_ITEM_COLOR) - } else { - spawnable_button - }); - let spawnable_pos = Pos2 { - x: 16., - y: spawnables.rect.right_top().y - 4., - }; - if spawnables - .on_hover_text("Spawnable preset bundles") - .clicked() - { - state.show_spawnable_bundles = !state.show_spawnable_bundles; - } + let spawnables = ui.add(if state.show_spawnable_bundles { + spawnable_button.fill(SELECTED_ITEM_COLOR) + } else { + spawnable_button + }); + let spawnable_pos = Pos2 { + x: 16., + y: spawnables.rect.right_top().y - 4., + }; + if spawnables + .on_hover_text("Spawnable preset bundles") + .clicked() + { + state.show_spawnable_bundles = !state.show_spawnable_bundles; + } - if state.show_spawnable_bundles { - egui::Window::new("Bundles") - .frame( - egui::Frame::none() - .inner_margin(Margin::symmetric(8., 4.)) - .rounding(3.) - .stroke(stroke_default_color()) - .fill(SPECIAL_BG_COLOR), - ) - .collapsible(false) - .pivot(Align2::LEFT_BOTTOM) - .default_pos(spawnable_pos) - .default_size(egui::Vec2::new(80., 80.)) - .title_bar(false) - .show(ctx, |ui| { - egui::menu::bar(ui, |ui| { - ui.spacing(); - for (category_name, category_bundle) in ui_reg.bundles.iter() { - ui.menu_button(category_name, |ui| { - let mut categories_vec: Vec<(&String, &EditorBundleUntyped)> = - category_bundle.iter().collect(); - categories_vec.sort_by(|a, b| a.0.cmp(b.0)); - - for (name, dyn_bundle) in categories_vec { - let button = egui::Button::new(name).ui(ui); - if button.clicked() { - let entity = dyn_bundle.spawn(&mut commands); - changes.send(NewChange { - change: Arc::new(AddedEntity { entity }), - }); + if state.show_spawnable_bundles { + egui::Window::new("Bundles") + .frame( + egui::Frame::none() + .inner_margin(Margin::symmetric(8., 4.)) + .rounding(3.) + .stroke(stroke_default_color()) + .fill(SPECIAL_BG_COLOR), + ) + .collapsible(false) + .pivot(Align2::LEFT_BOTTOM) + .default_pos(spawnable_pos) + .default_size(egui::Vec2::new(80., 80.)) + .title_bar(false) + .show(ctx, |ui| { + egui::menu::bar(ui, |ui| { + ui.spacing(); + for (category_name, category_bundle) in ui_reg.bundles.iter() { + ui.menu_button(category_name, |ui| { + let mut categories_vec: Vec<( + &String, + &EditorBundleUntyped, + )> = category_bundle.iter().collect(); + categories_vec.sort_by(|a, b| a.0.cmp(b.0)); + + for (name, dyn_bundle) in categories_vec { + let button = egui::Button::new(name).ui(ui); + if button.clicked() { + let entity = dyn_bundle.spawn(&mut commands); + changes.send(NewChange { + change: Arc::new(AddedEntity { entity }), + }); + } } - } - }); - ui.add_space(32.); - } - if ui.button("🗙").clicked() { - state.show_spawnable_bundles = !state.show_spawnable_bundles; - } + }); + ui.add_space(32.); + } + if ui.button("🗙").clicked() { + state.show_spawnable_bundles = !state.show_spawnable_bundles; + } + }); }); - }); - } - ui.spacing(); - ui.checkbox(&mut state.show_editor_entities, "Show editor entities"); - let distance = ui.available_width() * 0.66; - ui.add_space(distance); - ui.label(format!("Current Scene: {}", menu_state.path)); + } + ui.spacing(); + ui.style_mut().spacing.icon_width = sizing.text - 4.; + ui.checkbox( + &mut state.show_editor_entities, + to_label("Show editor entities", sizing.text), + ); + let distance = ui.available_width() * 0.66 * 12. / sizing.text; + ui.add_space(distance); + ui.label(to_label( + &format!("Current Scene: {}", menu_state.path), + sizing.text, + )); + }); }); - }); } pub fn top_menu( @@ -253,7 +266,7 @@ pub fn top_menu( ) { let ctx = ctxs.ctx_mut(); egui::TopBottomPanel::top("top_menu_bar") - .exact_height(28.) + .exact_height(&sizing.icon.to_size() + 4.) .show(ctx, |ui| { ui.style_mut().spacing.menu_margin = Margin::symmetric(16., 4.); egui::menu::bar(ui, |ui| { @@ -261,7 +274,8 @@ pub fn top_menu( stl.spacing.button_padding = egui::Vec2::new(8., 4.); // Open Assets Folder - let open_button = egui::Button::new("📂").stroke(stroke_default_color()); + let open_button = egui::Button::new(to_richtext("📂", &sizing.icon)) + .stroke(stroke_default_color()); if ui.add(open_button).clicked() { let mut dialog = egui_file::FileDialog::open_file(Some("assets/".into())) .show_files_filter(Box::new(|path| { @@ -304,7 +318,8 @@ pub fn top_menu( // END Open Assets Folder // Save file - let file_button = egui::Button::new("💾").stroke(stroke_default_color()); + let file_button = egui::Button::new(to_richtext("💾", &sizing.icon)) + .stroke(stroke_default_color()); if ui .add(file_button) .on_hover_text("Save current scene") @@ -348,7 +363,8 @@ pub fn top_menu( // End Save File // Load Scene - let load_button = egui::Button::new("📤").stroke(stroke_default_color()); + let load_button = egui::Button::new(to_richtext("📤", &sizing.icon)) + .stroke(stroke_default_color()); if ui .add(load_button) .on_hover_text("Load scene file") @@ -396,8 +412,7 @@ pub fn top_menu( // Open GLTF let open_gltf_button = - prefab_icon(sizing.icon.to_size(), sizing.icon.to_size(), "") - .stroke(stroke_default_color()); + prefab_icon(sizing.icon.to_size(), "").stroke(stroke_default_color()); if ui .add(open_gltf_button) .on_hover_text("Open GLTF/GLB as prefab") @@ -442,7 +457,7 @@ pub fn top_menu( let distance = ui.available_width() / 2. - 40.; ui.add_space(distance); - let play_button = egui::Button::new("▶") + let play_button = egui::Button::new(to_richtext("▶", &sizing.icon)) .fill(SPECIAL_BG_COLOR) .stroke(Stroke { width: 1., diff --git a/crates/editor_ui/src/settings.rs b/crates/editor_ui/src/settings.rs index b8401ee5..96b97234 100644 --- a/crates/editor_ui/src/settings.rs +++ b/crates/editor_ui/src/settings.rs @@ -10,7 +10,7 @@ use space_undo::ChangeChainSettings; #[cfg(feature = "persistence_editor")] use space_persistence::*; -use crate::sizing::Sizing; +use crate::sizing::{IconSize, Sizing}; use super::{ editor_tab::{EditorTab, EditorTabName}, @@ -31,27 +31,19 @@ impl Plugin for SettingsWindowPlugin { fn build(&self, app: &mut App) { app.editor_tab_by_trait(EditorTabName::Settings, SettingsWindow::default()); app.register_type::<GameMode>() - .init_resource::<GameModeSettings>(); + .init_resource::<GameModeSettings>() + .init_resource::<Sizing>() + .register_type::<Sizing>() + .register_type::<IconSize>() + .register_type::<NewTabBehaviour>() + .init_resource::<NewWindowSettings>(); #[cfg(feature = "persistence_editor")] { app.persistence_resource::<NewWindowSettings>() - .register_type::<NewTabBehaviour>() - .init_resource::<NewWindowSettings>(); - app.persistence_resource::<ChangeChainSettings>(); - app.persistence_resource::<GameModeSettings>(); + .persistence_resource::<Sizing>() + .persistence_resource::<ChangeChainSettings>() + .persistence_resource::<GameModeSettings>(); } - - // #[cfg(feature = "bevy_xpbd_3d")] - // { - // #[cfg(feature = "persistence_editor")] - // { - // app.persistence_resource::<bevy_xpbd_3d::prelude::PhysicsDebugConfig>(); - // app.register_type::<Option<Vec3>>(); - // app.register_type::<Option<Color>>(); - // app.register_type::<Option<[f32; 4]>>(); - // app.register_type::<[f32; 4]>(); - // } - // } } } diff --git a/crates/editor_ui/src/tools/gizmo.rs b/crates/editor_ui/src/tools/gizmo.rs index 830a922d..96a848ff 100644 --- a/crates/editor_ui/src/tools/gizmo.rs +++ b/crates/editor_ui/src/tools/gizmo.rs @@ -9,6 +9,7 @@ use crate::{ game_view::GameViewTab, icons::{rotation_icon, scale_icon, translate_icon}, prelude::{CloneEvent, EditorTool}, + sizing::Sizing, tool::ToolExt, }; pub struct GizmoToolPlugin; @@ -81,6 +82,7 @@ impl EditorTool for GizmoTool { (GizmoMode::Rotate, "Rotate"), (GizmoMode::Scale, "Scale"), ]; + let sizing = world.resource::<Sizing>(); ui.spacing(); ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { @@ -89,12 +91,12 @@ impl EditorTool for GizmoTool { stl.spacing.item_spacing = egui::Vec2::new(1., 0.); for (mode, hint) in mode2name { if self.gizmo_mode == mode { - ui.add(mode.to_button().fill(SELECTED_ITEM_COLOR)) + ui.add(mode.to_button(sizing).fill(SELECTED_ITEM_COLOR)) .on_disabled_hover_text(hint) .on_hover_text(hint) .clicked(); } else if ui - .add(mode.to_button()) + .add(mode.to_button(sizing)) .on_disabled_hover_text(hint) .on_hover_text(hint) .clicked() @@ -357,15 +359,15 @@ impl EditorTool for GizmoTool { } trait ToButton { - fn to_button(&self) -> egui::Button; + fn to_button(&self, size: &Sizing) -> egui::Button; } impl ToButton for GizmoMode { - fn to_button(&self) -> egui::Button { + fn to_button(&self, size: &Sizing) -> egui::Button { match self { - Self::Rotate => rotation_icon(18., 18., ""), - Self::Translate => translate_icon(18., 18., ""), - Self::Scale => scale_icon(18., 18., ""), + Self::Rotate => rotation_icon(size.gizmos.to_size(), ""), + Self::Translate => translate_icon(size.gizmos.to_size(), ""), + Self::Scale => scale_icon(size.gizmos.to_size(), ""), } } } diff --git a/modules/bevy_xpbd_plugin/src/lib.rs b/modules/bevy_xpbd_plugin/src/lib.rs index f180f96b..6ddfe94b 100644 --- a/modules/bevy_xpbd_plugin/src/lib.rs +++ b/modules/bevy_xpbd_plugin/src/lib.rs @@ -14,6 +14,10 @@ impl Plugin for XpbdPlugin { { info!("Add bevy_xpbd_3d plugin to editor"); app.add_plugins(registry::BevyXpbdPlugin); + app.register_type::<Option<Vec3>>(); + app.register_type::<Option<Color>>(); + app.register_type::<Option<[f32; 4]>>(); + app.register_type::<[f32; 4]>(); } } } From 76e1d24af5392df643f7834f7653c3f766182762 Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Thu, 22 Feb 2024 17:20:08 -0600 Subject: [PATCH 5/7] text-accessability --- crates/editor_ui/src/editor_tab.rs | 15 +++++++++++---- crates/editor_ui/src/lib.rs | 8 +++++--- crates/editor_ui/src/settings.rs | 7 +++---- crates/editor_ui/src/ui_plugin.rs | 10 ++++++++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/crates/editor_ui/src/editor_tab.rs b/crates/editor_ui/src/editor_tab.rs index e029df86..5e1f5854 100644 --- a/crates/editor_ui/src/editor_tab.rs +++ b/crates/editor_ui/src/editor_tab.rs @@ -4,7 +4,10 @@ use bevy::{prelude::*, utils::HashMap}; use bevy_egui_next::egui::{self, WidgetText}; use convert_case::{Case, Casing}; -use crate::colors::ERROR_COLOR; +use crate::{ + colors::ERROR_COLOR, + sizing::{to_label, Sizing}, +}; use super::{EditorUiRef, EditorUiReg}; @@ -76,7 +79,8 @@ impl<'a, 'w, 's> egui_dock::TabViewer for EditorTabViewer<'a, 'w, 's> { } fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText { - if let Some(reg) = self.registry.get_mut(tab) { + let sizing = self.world.resource::<Sizing>().clone(); + if let Some(reg) = self.registry.get(tab) { match reg { EditorUiReg::ResourceBased { show_command: _, @@ -87,10 +91,13 @@ impl<'a, 'w, 's> egui_dock::TabViewer for EditorTabViewer<'a, 'w, 's> { .resource_mut::<ScheduleEditorTabStorage>() .0 .get(tab) - .map_or_else(|| format!("{tab:?}").into(), |tab| tab.title.clone()), + .map_or_else( + || to_label(&format!("{tab:?}"), sizing.text).into(), + |tab| to_label(tab.title.text(), sizing.text).into(), + ), } } else { - format!("{tab:?}").into() + to_label(&format!("{tab:?}"), sizing.text).into() } } diff --git a/crates/editor_ui/src/lib.rs b/crates/editor_ui/src/lib.rs index 01a7db83..723858c4 100644 --- a/crates/editor_ui/src/lib.rs +++ b/crates/editor_ui/src/lib.rs @@ -414,7 +414,7 @@ pub mod sizing { pub struct Sizing { pub icon: IconSize, pub gizmos: IconSize, - #[inspector(min = 16.0, max = 24.0)] + #[inspector(min = 12.0, max = 24.0)] pub text: f32, } @@ -423,7 +423,7 @@ pub mod sizing { Self { icon: IconSize::Medium, gizmos: IconSize::Gizmos, - text: 18., + text: 14., } } } @@ -462,6 +462,8 @@ pub mod sizing { } pub fn to_label(text: &str, size: f32) -> RichText { - RichText::new(text).size(size) + RichText::new(text) + .size(size) + .family(egui_dock::egui::FontFamily::Proportional) } } diff --git a/crates/editor_ui/src/settings.rs b/crates/editor_ui/src/settings.rs index 96b97234..0ba8d48a 100644 --- a/crates/editor_ui/src/settings.rs +++ b/crates/editor_ui/src/settings.rs @@ -187,7 +187,6 @@ impl EditorTab for SettingsWindow { fn ui(&mut self, ui: &mut egui::Ui, commands: &mut Commands, world: &mut World) { let game_mode_setting = &mut world.resource_mut::<GameModeSettings>(); game_mode_setting.ui(ui); - ui.spacing(); ui.heading("Undo"); world.resource_scope::<ChangeChainSettings, _>(|_world, mut settings| { @@ -197,16 +196,16 @@ impl EditorTab for SettingsWindow { ); }); - ui.spacing(); + ui.add_space(12.); ui.heading("New Tab Behaviour"); let new_window_settings = &mut world.resource_mut::<NewWindowSettings>(); new_window_settings.ui(ui); - ui.spacing(); + ui.add_space(12.); ui.heading("Default Sizing"); bevy_inspector::ui_for_resource::<Sizing>(world, ui); - ui.spacing(); + ui.add_space(12.); ui.heading("Hotkeys in Game view tab"); if world.contains_resource::<AllHotkeys>() { egui::Grid::new("hotkeys_grid") diff --git a/crates/editor_ui/src/ui_plugin.rs b/crates/editor_ui/src/ui_plugin.rs index 46480043..e6dc2bb5 100644 --- a/crates/editor_ui/src/ui_plugin.rs +++ b/crates/editor_ui/src/ui_plugin.rs @@ -7,7 +7,10 @@ use bevy_egui_next::egui::{ use camera_plugin::draw_camera_gizmo; use meshless_visualizer::draw_light_gizmo; -use self::colors::*; +use self::{ + colors::*, + sizing::{to_label, Sizing}, +}; /// All systems for editor ui wil be placed in UiSystemSet #[derive(SystemSet, Hash, PartialEq, Eq, Debug, Clone, Copy)] @@ -371,7 +374,10 @@ impl EditorUiAppExt for App { ); let reg = EditorUiReg::ResourceBased { show_command: show_fn, - title_command: Box::new(|world| world.resource_mut::<T>().title()), + title_command: Box::new(|world| { + let sizing = world.resource::<Sizing>().clone(); + to_label(world.resource_mut::<T>().title().text(), sizing.text).into() + }), }; self.world From ad9a819b35105a78baf4e6d503c80086b199ee4e Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Thu, 22 Feb 2024 17:37:20 -0600 Subject: [PATCH 6/7] sub-buttons --- crates/editor_ui/src/icons.rs | 4 +++- crates/editor_ui/src/inspector/mod.rs | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/editor_ui/src/icons.rs b/crates/editor_ui/src/icons.rs index 8a320ed9..6d84dc38 100644 --- a/crates/editor_ui/src/icons.rs +++ b/crates/editor_ui/src/icons.rs @@ -1,4 +1,5 @@ use bevy_egui_next::egui; +use egui_dock::egui::WidgetText; pub const TRANSLATE: &str = "<svg fill=\"#ffffff\" viewBox=\"0 0 1024 1024\" xmlns=\"http://www.w3.org/2000/svg\" stroke=\"#ffffff\"><g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g><g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g><g id=\"SVGRepo_iconCarrier\"><path d=\"M1016.4 496.64l-8.48-8.08c-.16-.16-.335-.224-.528-.367L877.648 369.76c-9.344-8.945-24.448-8.945-33.824 0l-5.488 8.064c-9.344 8.945-6.304 23.408 3.04 32.336l76.464 69.344H546.496V106.16l69.343 76.464c8.945 9.344 23.409 12.384 32.336 3.023l8.065-5.471c8.944-9.376 8.944-24.481 0-33.841L543.072 22.368a31.874 31.874 0 0 0-12.32-13.296l-1.423-1.488C524.897 2.912 518.993.576 513.105.608c-5.904-.032-11.776 2.304-16.288 6.976l-8.096 8.463c-.16.16-.176.369-.336.544L372.881 144.335c-8.927 9.329-8.927 24.449 0 33.825l8.065 5.471c8.928 9.344 23.424 6.32 32.368-3.024l69.152-77.105v375.984H106.162l76.464-69.343c9.344-8.945 12.384-23.409 3.04-32.336l-5.471-8.065c-9.36-8.944-24.497-8.944-33.84 0L22.37 482.926a31.957 31.957 0 0 0-13.28 12.29l-1.489 1.423C2.914 501.087.593 506.992.626 512.88c-.016 5.905 2.288 11.777 6.976 16.288l8.464 8.096c.16.16.368.176.528.336l127.744 115.504c9.344 8.928 24.464 8.928 33.84 0l5.472-8.064c9.344-8.945 6.304-23.44-3.04-32.369l-77.12-69.152h379.008v376.96l-69.153-77.103c-8.944-9.344-23.44-12.369-32.368-3.025l-8.064 5.472c-8.928 9.376-8.928 24.496 0 33.824l115.504 127.744c.16.176.192.368.336.528l8.095 8.48c4.512 4.673 10.384 7.009 16.288 6.976 5.873.033 11.777-2.303 16.225-6.975l8.096-8.48c.16-.16.224-.337.368-.529l118.432-129.744c8.944-9.344 8.944-24.464 0-33.824l-8.065-5.488c-8.944-9.344-23.408-6.304-32.335 3.04l-69.344 76.464V543.502H920.48l-77.105 69.152c-9.343 8.944-12.368 23.44-3.024 32.368l5.472 8.064c9.376 8.928 24.496 8.928 33.824 0l127.744-115.504c.176-.175.368-.19.528-.334l8.48-8.096c4.672-4.496 7.008-10.368 6.976-16.288.032-5.857-2.304-11.777-6.975-16.225z\"></path></g></svg>"; pub const ROTATION: &str = "<svg viewBox=\"0 0 24 24\" id=\"Layer_1\" data-name=\"Layer 1\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"#000000\" stroke=\"#000000\"><g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g><g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g><g id=\"SVGRepo_iconCarrier\"><defs><style>.cls-1{fill:none;stroke:#ffffff;stroke-miterlimit:10;stroke-width:1.95px;}</style></defs><path class=\"cls-1\" d=\"M14.37,20.55c-.66,1.38-1.48,2.2-2.37,2.2-1.69,0-3.13-2.95-3.66-7.09A25,25,0,0,1,8.09,12a25,25,0,0,1,.25-3.66c.53-4.14,2-7.09,3.66-7.09s3.13,3,3.66,7.09A22.48,22.48,0,0,1,15.89,11\"></path><path class=\"cls-1\" d=\"M13.9,15.85l-.92,0-1,0-1,0a22.48,22.48,0,0,1-2.68-.23c-4.14-.53-7.09-2-7.09-3.66s3-3.13,7.09-3.66A25,25,0,0,1,12,8.09a26.79,26.79,0,0,1,3.17.18l.49.07c4.14.53,7.09,2,7.09,3.66,0,.89-.82,1.71-2.2,2.37\"></path><polyline class=\"cls-1\" points=\"12 12.98 14.93 15.91 12 18.84\"></polyline></g></svg>"; @@ -157,7 +158,8 @@ pub fn add_entity_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { } } -pub fn add_component_icon<'a>(size: f32, text: &str) -> egui::Button<'a> { +pub fn add_component_icon<'a>(size: f32, text: impl Into<WidgetText>) -> egui::Button<'a> { + let text = text.into(); let image = egui::Image::from_bytes("add_component.svg", crate::icons::ADD_COMPONENT.as_bytes()) .fit_to_exact_size(bevy_egui_next::egui::vec2(size, size)); diff --git a/crates/editor_ui/src/inspector/mod.rs b/crates/editor_ui/src/inspector/mod.rs index f1195f2b..6664bd80 100644 --- a/crates/editor_ui/src/inspector/mod.rs +++ b/crates/editor_ui/src/inspector/mod.rs @@ -22,7 +22,11 @@ use space_shared::ext::bevy_inspector_egui::{ self, inspector_egui_impls::InspectorEguiImpl, reflect_inspector::InspectorUi, }; -use crate::{colors::DEFAULT_BG_COLOR, icons::add_component_icon, sizing::Sizing}; +use crate::{ + colors::DEFAULT_BG_COLOR, + icons::add_component_icon, + sizing::{to_label, Sizing}, +}; use self::{ components_order::{ComponentsOrder, ComponentsPriority}, @@ -278,8 +282,8 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM }); let width = ui.available_width(); - let add_component_str = "Add component"; - let pixel_count = add_component_str.len() as f32 * 8.; + let add_component_str = to_label("Add component", sizing.text); + let pixel_count = add_component_str.text().len() as f32 * 8. * sizing.text / 12.; let x_padding = (width - pixel_count - 16. - sizing.icon.to_size()) / 2.; //Open context window by button From 82f9e995f4f4e0adc48030a6d78cb235063facb2 Mon Sep 17 00:00:00 2001 From: Julia Naomi <jnboeira@outlook.com> Date: Thu, 22 Feb 2024 18:03:17 -0600 Subject: [PATCH 7/7] add-filter-bar --- crates/editor_ui/src/hierarchy.rs | 14 +++- crates/editor_ui/src/inspector/mod.rs | 111 ++++++++++++++------------ 2 files changed, 71 insertions(+), 54 deletions(-) diff --git a/crates/editor_ui/src/hierarchy.rs b/crates/editor_ui/src/hierarchy.rs index 1f884567..9877cb52 100644 --- a/crates/editor_ui/src/hierarchy.rs +++ b/crates/editor_ui/src/hierarchy.rs @@ -46,6 +46,7 @@ impl Plugin for SpaceHierarchyPlugin { pub struct HierarchyTabState { pub show_editor_entities: bool, pub show_spawnable_bundles: bool, + pub entity_filter: String, } pub type HierarchyQueryIter<'a> = ( @@ -64,7 +65,7 @@ pub fn show_hierarchy( mut clone_events: EventWriter<CloneEvent>, mut ui: NonSendMut<EditorUiRef>, mut changes: EventWriter<NewChange>, - state: Res<HierarchyTabState>, + mut state: ResMut<HierarchyTabState>, ) { let mut all: Vec<_> = if state.show_editor_entities { all_entites.iter().collect() @@ -72,10 +73,17 @@ pub fn show_hierarchy( query.iter().collect() }; all.sort_by_key(|a| a.0); - let ui = &mut ui.0; + ui.text_edit_singleline(&mut state.entity_filter); + ui.spacing(); + let lower_filter = state.entity_filter.to_lowercase(); + egui::ScrollArea::vertical().show(ui, |ui| { - for (entity, _name, _children, parent) in all.iter() { + for (entity, _name, _children, parent) in all.iter().filter(|(_, name, _, _)| { + name.map(|n| n.to_lowercase()) + .unwrap_or_else(|| "entity".to_string()) + .contains(&lower_filter) + }) { if parent.is_none() { if state.show_editor_entities { draw_entity::<()>( diff --git a/crates/editor_ui/src/inspector/mod.rs b/crates/editor_ui/src/inspector/mod.rs index 6664bd80..950fa68c 100644 --- a/crates/editor_ui/src/inspector/mod.rs +++ b/crates/editor_ui/src/inspector/mod.rs @@ -213,64 +213,73 @@ pub fn inspect(ui: &mut egui::Ui, world: &mut World, open_components: &mut HashM name = format!("{:?}", e.id()); } ui.heading(&name); - ui.label("Components:"); + let mut state = unsafe { cell.get_resource_mut::<FilterComponentState>().unwrap() }; + ui.text_edit_singleline(&mut state.component_add_filter); + let lower_filter = state.component_add_filter.to_lowercase(); let e_id = e.id().index(); + ui.label("Components:"); egui::Grid::new(format!("{e_id}")).show(ui, |ui| { for (c_id, t_id, name, _) in &components_id { - if let Some(data) = unsafe { e.get_mut_by_id(*c_id) } { - let registration = registry.get(*t_id).unwrap(); - if let Some(reflect_from_ptr) = registration.data::<ReflectFromPtr>() { - let (ptr, mut set_changed) = mut_untyped_split(data); - - let value = unsafe { reflect_from_ptr.from_ptr_mut()(ptr) }; - - if !editor_registry.silent.contains(®istration.type_id()) { - ui.push_id(format!("{:?}-{}", &e.id(), &name), |ui| { - let header = egui::CollapsingHeader::new(name) - .default_open(*open_components.get(name).unwrap_or(&false)) - .show(ui, |ui| { - ui.push_id( - format!("content-{:?}-{}", &e.id(), &name), + if name.to_lowercase().contains(&lower_filter) { + if let Some(data) = unsafe { e.get_mut_by_id(*c_id) } { + let registration = registry.get(*t_id).unwrap(); + if let Some(reflect_from_ptr) = registration.data::<ReflectFromPtr>() { + let (ptr, mut set_changed) = mut_untyped_split(data); + + let value = unsafe { reflect_from_ptr.from_ptr_mut()(ptr) }; + + if !editor_registry.silent.contains(®istration.type_id()) { + ui.push_id(format!("{:?}-{}", &e.id(), &name), |ui| { + let header = egui::CollapsingHeader::new(name) + .default_open( + *open_components.get(name).unwrap_or(&false), + ) + .show(ui, |ui| { + ui.push_id( + format!("content-{:?}-{}", &e.id(), &name), + |ui| { + if env.ui_for_reflect_with_options( + value, + ui, + ui.id(), + &(), + ) { + set_changed(); + } + }, + ); + }); + if header.header_response.clicked() { + let open_name = + open_components.entry(name.clone()).or_default(); + //At click header not opened simultaneously so its need to check percent of opened + *open_name = header.openness < 0.5; + } + }); + + ui.push_id( + format!("del component {:?}-{}", &e.id(), &name), + |ui| { + //must be on top + ui.with_layout( + egui::Layout::top_down(egui::Align::Min), |ui| { - if env.ui_for_reflect_with_options( - value, - ui, - ui.id(), - &(), - ) { - set_changed(); + let button = egui::Button::new("🗙") + .fill(DEFAULT_BG_COLOR); + if ui.add(button).clicked() { + commands.push( + InspectCommand::RemoveComponent( + e.id(), + *t_id, + ), + ); } }, ); - }); - if header.header_response.clicked() { - let open_name = - open_components.entry(name.clone()).or_default(); - //At click header not opened simultaneously so its need to check percent of opened - *open_name = header.openness < 0.5; - } - }); - - ui.push_id( - format!("del component {:?}-{}", &e.id(), &name), - |ui| { - //must be on top - ui.with_layout( - egui::Layout::top_down(egui::Align::Min), - |ui| { - let button = - egui::Button::new("🗙").fill(DEFAULT_BG_COLOR); - if ui.add(button).clicked() { - commands.push(InspectCommand::RemoveComponent( - e.id(), - *t_id, - )); - } - }, - ); - }, - ); - ui.end_row(); + }, + ); + ui.end_row(); + } } } }