From 2928d73b1418bc819acccbcde24bfa7d53488858 Mon Sep 17 00:00:00 2001 From: Dmitry Stepanov Date: Fri, 29 Nov 2024 10:29:16 +0300 Subject: [PATCH 01/37] added support for styles for the editor + light style draft --- editor/src/gui.rs | 4 ++- editor/src/interaction/mod.rs | 2 +- editor/src/lib.rs | 47 +++++++++++++++++------- editor/src/log.rs | 65 +++++++++++++++++----------------- editor/src/plugins/settings.rs | 2 ++ editor/src/settings/general.rs | 33 ++++++++++++++++- editor/src/settings/mod.rs | 5 ++- editor/src/world/graph/item.rs | 2 +- editor/src/world/mod.rs | 2 +- fyrox-ui/src/button.rs | 27 ++++++++------ fyrox-ui/src/lib.rs | 28 +++++++++++++-- fyrox-ui/src/searchbar.rs | 2 +- fyrox-ui/src/style/mod.rs | 60 +++++++++++++++++++++++-------- fyrox-ui/src/text.rs | 4 ++- 14 files changed, 205 insertions(+), 78 deletions(-) diff --git a/editor/src/gui.rs b/editor/src/gui.rs index 41e1ea4ec..f71c658a4 100644 --- a/editor/src/gui.rs +++ b/editor/src/gui.rs @@ -27,6 +27,8 @@ use crate::fyrox::{ BuildContext, HorizontalAlignment, Thickness, UiNode, VerticalAlignment, }, }; +use fyrox::gui::style::resource::StyleResourceExt; +use fyrox::gui::style::Style; use std::sync::Arc; pub fn make_dropdown_list_option_universal( @@ -109,7 +111,7 @@ pub fn make_image_button_with_tooltip( .with_content( ImageBuilder::new( WidgetBuilder::new() - .with_background(Brush::Solid(Color::opaque(180, 180, 180))) + .with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHTEST)) .with_margin(Thickness::uniform(2.0)) .with_width(width) .with_height(height), diff --git a/editor/src/interaction/mod.rs b/editor/src/interaction/mod.rs index 73a998905..a1129e0fa 100644 --- a/editor/src/interaction/mod.rs +++ b/editor/src/interaction/mod.rs @@ -229,7 +229,7 @@ pub fn make_interaction_mode_button( .with_content( ImageBuilder::new( WidgetBuilder::new() - .with_background(Brush::Solid(Color::opaque(220, 220, 220))) + .with_background(ctx.style.get_or_default(Style::BRUSH_TEXT)) .with_margin(Thickness::uniform(2.0)) .with_width(23.0) .with_height(23.0), diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 3db62a423..f86a96ae8 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -60,7 +60,6 @@ pub mod world; pub use fyrox; -use crate::plugins::path_fixer::PathFixerPlugin; use crate::{ asset::AssetBrowser, audio::{preview::AudioPreviewPanel, AudioPanel}, @@ -70,7 +69,10 @@ use crate::{ configurator::Configurator, export::ExportWindow, fyrox::{ - asset::{io::FsResourceIo, manager::ResourceManager, untyped::UntypedResource}, + asset::{ + io::FsResourceIo, manager::ResourceManager, untyped::ResourceKind, + untyped::UntypedResource, + }, core::{ algebra::{Matrix3, Vector2}, color::Color, @@ -92,6 +94,7 @@ use crate::{ gui::{ brush::Brush, button::ButtonBuilder, + constructor::new_widget_constructor_container, dock::{ DockingManager, DockingManagerBuilder, DockingManagerMessage, TileBuilder, TileContent, @@ -106,6 +109,7 @@ use crate::{ messagebox::{ MessageBoxBuilder, MessageBoxButtons, MessageBoxMessage, MessageBoxResult, }, + style::{resource::StyleResource, Style}, text::TextBuilder, widget::{WidgetBuilder, WidgetMessage}, window::{WindowBuilder, WindowMessage, WindowTitle}, @@ -143,8 +147,9 @@ use crate::{ plugin::{EditorPlugin, EditorPluginsContainer}, plugins::{ absm::AbsmEditorPlugin, animation::AnimationEditorPlugin, collider::ColliderPlugin, - curve_editor::CurveEditorPlugin, material::MaterialPlugin, ragdoll::RagdollPlugin, - settings::SettingsPlugin, stats::UiStatisticsPlugin, tilemap::TileMapEditorPlugin, + curve_editor::CurveEditorPlugin, material::MaterialPlugin, path_fixer::PathFixerPlugin, + ragdoll::RagdollPlugin, settings::SettingsPlugin, stats::UiStatisticsPlugin, + tilemap::TileMapEditorPlugin, }, scene::{ commands::{ @@ -156,8 +161,7 @@ use crate::{ GameScene, Selection, }, scene_viewer::SceneViewer, - settings::build::BuildCommand, - settings::Settings, + settings::{build::BuildCommand, general::EditorStyle, Settings}, stats::{StatisticsWindow, StatisticsWindowAction}, ui_scene::{ commands::graph::PasteWidgetCommand, menu::WidgetContextMenu, @@ -166,7 +170,6 @@ use crate::{ utils::doc::DocWindow, world::{graph::menu::SceneNodeContextMenu, graph::EditorSceneWrapper, WorldViewer}, }; -use fyrox::gui::constructor::new_widget_constructor_container; pub use message::Message; use plugins::inspector::InspectorPlugin; use std::{ @@ -557,6 +560,7 @@ pub struct Editor { pub statistics_window: Option, pub surface_data_viewer: Option, pub processed_ui_messages: usize, + pub styles: FxHashMap, } impl Editor { @@ -565,6 +569,15 @@ impl Editor { Log::add_listener(log_message_sender); + let dark_style = StyleResource::new_ok(ResourceKind::Embedded, Style::dark_style()); + let light_style = StyleResource::new_ok(ResourceKind::Embedded, Style::light_style()); + let styles = [ + (EditorStyle::Dark, dark_style), + (EditorStyle::Light, light_style), + ] + .into_iter() + .collect::>(); + let mut settings = Settings::default(); match Settings::load() { @@ -623,10 +636,12 @@ impl Editor { .unwrap(); } - let configurator = Configurator::new( - message_sender.clone(), - &mut engine.user_interfaces.first_mut().build_ctx(), - ); + let ui = engine.user_interfaces.first_mut(); + if let Some(style) = styles.get(&settings.general.style) { + ui.set_style(style.clone()); + } + + let configurator = Configurator::new(message_sender.clone(), &mut ui.build_ctx()); let scene_viewer = SceneViewer::new(&mut engine, message_sender.clone(), &mut settings); let asset_browser = AssetBrowser::new(&mut engine); @@ -888,6 +903,7 @@ impl Editor { statistics_window: None, surface_data_viewer: None, processed_ui_messages: 0, + styles, }; if let Some(data) = startup_data { @@ -2397,7 +2413,14 @@ impl Editor { } } - self.settings.update(); + if self.settings.try_save() { + let ui = self.engine.user_interfaces.first_mut(); + if let Some(style) = self.styles.get(&self.settings.general.style) { + if style != ui.style() { + ui.set_style(style.clone()); + } + } + } } fn save_layout(&mut self) { diff --git a/editor/src/log.rs b/editor/src/log.rs index 144bb4ffa..b14059a8e 100644 --- a/editor/src/log.rs +++ b/editor/src/log.rs @@ -18,37 +18,38 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -use crate::fyrox::graph::BaseSceneGraph; -use crate::fyrox::{ - core::{ - log::{LogMessage, MessageKind}, - pool::Handle, - }, - gui::{ - border::BorderBuilder, - button::ButtonMessage, - copypasta::ClipboardProvider, - dropdown_list::DropdownListMessage, - formatted_text::WrapMode, - grid::{Column, GridBuilder, Row}, - list_view::{ListView, ListViewBuilder, ListViewMessage}, - menu::{MenuItemBuilder, MenuItemContent, MenuItemMessage}, - message::{MessageDirection, UiMessage}, - popup::{Placement, PopupBuilder, PopupMessage}, - scroll_viewer::ScrollViewerBuilder, - stack_panel::StackPanelBuilder, - text::{Text, TextBuilder}, - widget::WidgetBuilder, - window::{WindowBuilder, WindowTitle}, - BuildContext, HorizontalAlignment, Orientation, RcUiNodeHandle, Thickness, UiNode, - }, -}; -use crate::settings::Settings; use crate::{ + fyrox::{ + core::{ + log::{LogMessage, MessageKind}, + pool::Handle, + }, + graph::BaseSceneGraph, + gui::{ + border::BorderBuilder, + button::ButtonMessage, + copypasta::ClipboardProvider, + dropdown_list::DropdownListMessage, + formatted_text::WrapMode, + grid::{Column, GridBuilder, Row}, + list_view::{ListView, ListViewBuilder, ListViewMessage}, + menu::{ContextMenuBuilder, MenuItemBuilder, MenuItemContent, MenuItemMessage}, + message::{MessageDirection, UiMessage}, + popup::{Placement, PopupBuilder, PopupMessage}, + scroll_viewer::ScrollViewerBuilder, + stack_panel::StackPanelBuilder, + style::{resource::StyleResourceExt, Style}, + text::{Text, TextBuilder}, + widget::WidgetBuilder, + window::{WindowBuilder, WindowTitle}, + BuildContext, HorizontalAlignment, Orientation, RcUiNodeHandle, Thickness, UiNode, + }, + }, gui::{make_dropdown_list_option, make_image_button_with_tooltip}, - load_image, Brush, Color, DropdownListBuilder, Engine, + load_image, + settings::Settings, + Brush, Color, DropdownListBuilder, Engine, }; -use fyrox::gui::menu::ContextMenuBuilder; use std::sync::mpsc::Receiver; struct ContextMenu { @@ -274,11 +275,11 @@ impl LogPanel { let ctx = &mut engine.user_interfaces.first_mut().build_ctx(); let item = BorderBuilder::new( WidgetBuilder::new() - .with_background(Brush::Solid(if count % 2 == 0 { - Color::opaque(70, 70, 70) + .with_background(if count % 2 == 0 { + ctx.style.get_or_default(Style::BRUSH_LIGHT) } else { - Color::opaque(40, 40, 40) - })) + ctx.style.get_or_default(Style::BRUSH_DARK) + }) .with_child( TextBuilder::new( WidgetBuilder::new() diff --git a/editor/src/plugins/settings.rs b/editor/src/plugins/settings.rs index a1e5ded50..dfcf7bde3 100644 --- a/editor/src/plugins/settings.rs +++ b/editor/src/plugins/settings.rs @@ -20,6 +20,7 @@ //! Settings window plugin. +use crate::settings::general::EditorStyle; use crate::{ fyrox::{ core::{log::Log, pool::Handle, some_or_return}, @@ -78,6 +79,7 @@ fn make_property_editors_container( container.insert(InspectablePropertyEditorDefinition::::new()); container.insert(EnumPropertyEditorDefinition::::new()); container.insert(EnumPropertyEditorDefinition::::new()); + container.insert(EnumPropertyEditorDefinition::::new()); container.insert(InspectablePropertyEditorDefinition::::new()); container.insert(InspectablePropertyEditorDefinition::::new()); container.insert(InspectablePropertyEditorDefinition::::new()); diff --git a/editor/src/settings/general.rs b/editor/src/settings/general.rs index 1da3ab657..52a296c94 100644 --- a/editor/src/settings/general.rs +++ b/editor/src/settings/general.rs @@ -18,10 +18,33 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -use crate::fyrox::core::{reflect::prelude::*, uuid_provider}; +use crate::fyrox::core::{reflect::prelude::*, type_traits::prelude::*, uuid_provider}; use serde::{Deserialize, Serialize}; use strum_macros::{AsRefStr, EnumString, VariantNames}; +#[derive( + Copy, + Clone, + Hash, + PartialOrd, + PartialEq, + Eq, + Ord, + Debug, + Serialize, + Deserialize, + Reflect, + AsRefStr, + EnumString, + VariantNames, + TypeUuidProvider, +)] +#[type_uuid(id = "35e8d30d-1213-4d87-905e-19d48550e6d5")] +pub enum EditorStyle { + Dark, + Light, +} + #[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Reflect)] pub struct GeneralSettings { #[reflect( @@ -61,6 +84,13 @@ pub struct GeneralSettings { )] #[serde(default = "default_max_log_entries")] pub max_log_entries: usize, + + #[serde(default = "default_style")] + pub style: EditorStyle, +} + +fn default_style() -> EditorStyle { + EditorStyle::Dark } fn default_max_log_entries() -> usize { @@ -117,6 +147,7 @@ impl Default for GeneralSettings { max_history_entries: default_max_history_entries(), generate_previews: default_generate_previews(), max_log_entries: default_max_log_entries(), + style: EditorStyle::Dark, } } } diff --git a/editor/src/settings/mod.rs b/editor/src/settings/mod.rs index bbb11cff5..73aadefde 100644 --- a/editor/src/settings/mod.rs +++ b/editor/src/settings/mod.rs @@ -122,10 +122,13 @@ impl Settings { Log::verify(self.settings.save()); } - pub fn update(&mut self) { + pub fn try_save(&mut self) -> bool { if self.need_save { self.need_save = false; Log::verify(self.settings.save()); + true + } else { + false } } } diff --git a/editor/src/world/graph/item.rs b/editor/src/world/graph/item.rs index ea844f49d..409302888 100644 --- a/editor/src/world/graph/item.rs +++ b/editor/src/world/graph/item.rs @@ -325,7 +325,7 @@ impl SceneItemBuilder { WidgetBuilder::new() .with_foreground( self.text_brush - .unwrap_or(ctx.style.get_or_default(Style::BRUSH_FOREGROUND)), + .unwrap_or(ctx.style.get_or_default(Style::BRUSH_TEXT)), ) .with_margin(Thickness::left(1.0)) .on_column(1) diff --git a/editor/src/world/mod.rs b/editor/src/world/mod.rs index 40a39ea60..8e3c8b111 100644 --- a/editor/src/world/mod.rs +++ b/editor/src/world/mod.rs @@ -158,7 +158,7 @@ fn make_graph_node_item( .with_text_brush(if is_instance { Brush::Solid(Color::opaque(160, 160, 200)) } else { - ctx.style.get_or_default(Style::BRUSH_FOREGROUND) + ctx.style.get_or_default(Style::BRUSH_TEXT) }) .with_name(name.deref().to_owned()) .with_entity_handle(handle) diff --git a/fyrox-ui/src/button.rs b/fyrox-ui/src/button.rs index 8c33fc065..888eb6582 100644 --- a/fyrox-ui/src/button.rs +++ b/fyrox-ui/src/button.rs @@ -23,6 +23,7 @@ #![warn(missing_docs)] use crate::border::BorderMessage; +use crate::style::resource::StyleResource; use crate::{ border::BorderBuilder, core::{ @@ -162,6 +163,21 @@ impl ConstructorProvider for Button { crate::define_widget_deref!(Button); +impl Button { + fn apply_style(&self, style: &StyleResource, ui: &UserInterface) { + ui.send_message(BorderMessage::stroke_thickness( + *self.decorator, + MessageDirection::ToWidget, + style.get_or(Self::BORDER_THICKNESS, Thickness::uniform(1.0)), + )); + ui.send_message(BorderMessage::corner_radius( + *self.decorator, + MessageDirection::ToWidget, + style.get_or(Self::CORNER_RADIUS, 4.0f32), + )); + } +} + impl Control for Button { fn update(&mut self, dt: f32, ui: &mut UserInterface) { let mut repeat_timer = self.repeat_timer.borrow_mut(); @@ -220,16 +236,7 @@ impl Control for Button { if message.destination() == self.handle() { if let WidgetMessage::Style(style) = msg { - ui.send_message(BorderMessage::stroke_thickness( - *self.decorator, - MessageDirection::ToWidget, - style.get_or(Self::BORDER_THICKNESS, Thickness::uniform(1.0)), - )); - ui.send_message(BorderMessage::corner_radius( - *self.decorator, - MessageDirection::ToWidget, - style.get_or(Self::CORNER_RADIUS, 4.0f32), - )); + self.apply_style(style, ui); } } } else if let Some(msg) = message.data::() { diff --git a/fyrox-ui/src/lib.rs b/fyrox-ui/src/lib.rs index 2c646f643..cc201fdc0 100644 --- a/fyrox-ui/src/lib.rs +++ b/fyrox-ui/src/lib.rs @@ -758,7 +758,7 @@ impl Clone for UserInterface { captured_node: self.captured_node, keyboard_focus_node: self.keyboard_focus_node, cursor_position: self.cursor_position, - style: StyleResource::new_ok(ResourceKind::Embedded, Style::default_style()), + style: StyleResource::new_ok(ResourceKind::Embedded, Style::dark_style()), receiver, sender, stack: self.stack.clone(), @@ -1045,7 +1045,7 @@ impl UserInterface { screen_size: Vector2, ) -> UserInterface { let (layout_events_sender, layout_events_receiver) = mpsc::channel(); - let style = StyleResource::new_ok(ResourceKind::Embedded, Style::default_style()); + let style = StyleResource::new_ok(ResourceKind::Embedded, Style::dark_style()); let mut ui = UserInterface { screen_size, sender, @@ -1314,6 +1314,30 @@ impl UserInterface { } } + pub fn style(&self) -> &StyleResource { + &self.style + } + + pub fn set_style(&mut self, style: StyleResource) { + self.style = style; + + fn notify_depth_first(node: Handle, ui: &UserInterface) { + if let Some(node_ref) = ui.try_get(node) { + for child in node_ref.children.iter() { + notify_depth_first(*child, ui); + } + + ui.send_message(WidgetMessage::style( + node, + MessageDirection::ToWidget, + ui.style.clone(), + )); + } + } + + notify_depth_first(self.root_canvas, self); + } + pub fn cursor(&self) -> CursorIcon { self.cursor_icon } diff --git a/fyrox-ui/src/searchbar.rs b/fyrox-ui/src/searchbar.rs index 391f1c2ba..497eb007b 100644 --- a/fyrox-ui/src/searchbar.rs +++ b/fyrox-ui/src/searchbar.rs @@ -203,7 +203,7 @@ impl SearchBarBuilder { .with_height(12.0) .with_vertical_alignment(VerticalAlignment::Center) .with_foreground( - ctx.style.get_or_default(Style::BRUSH_LIGHTEST), + ctx.style.get_or_default(Style::BRUSH_BRIGHT), ) .with_margin(Thickness { left: 2.0, diff --git a/fyrox-ui/src/style/mod.rs b/fyrox-ui/src/style/mod.rs index b4255212b..9515215e1 100644 --- a/fyrox-ui/src/style/mod.rs +++ b/fyrox-ui/src/style/mod.rs @@ -80,7 +80,7 @@ impl_casts!(Brush => Brush); lazy_static! { pub static ref DEFAULT_STYLE: BuiltInResource