Merge branch 'FyroxEngine:master' into tiles

This commit is contained in:
b-guild
2024-12-15 12:05:27 -08:00
committed by GitHub
125 changed files with 3721 additions and 1934 deletions
+1
View File
@@ -43,6 +43,7 @@
<sourceFolder url="file://$MODULE_DIR$/project-manager/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/template-core/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/fyrox-graphics/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/fyrox-build-tools/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/wasm/target" />
</content>
+16 -5
View File
@@ -7,16 +7,19 @@ members = [
"fyrox-resource",
"fyrox-scripts",
"fyrox-animation",
"editor",
"editor",
"editor-standalone",
"template-core",
"template",
"template-core",
"template",
"fyrox-graph",
"fyrox-math",
"fyrox-dylib",
"fyrox",
"fyrox-impl"
, "project-manager", "fyrox-graphics"]
"fyrox-impl",
"project-manager",
"fyrox-graphics",
"fyrox-build-tools"
]
resolver = "2"
[profile.dev]
@@ -26,6 +29,14 @@ opt-level = 0
opt-level = 3
debug = true
[profile.project-manager]
inherits = "release"
opt-level = "z"
debug = false
strip = true
panic = "abort"
lto = true
[profile.github-ci]
inherits = "dev"
strip = "symbols"
+2 -1
View File
@@ -14,6 +14,7 @@ include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md", "/resources/**/
[dependencies]
fyrox = { version = "0.34.1", path = "../fyrox", default-features = false }
fyrox-build-tools = { version = "0.1.0", path = "../fyrox-build-tools" }
lazy_static = "1.4.0"
ron = "0.8.0"
serde = "^1.0.0"
@@ -22,7 +23,7 @@ strum = "0.26.1"
strum_macros = "0.26.1"
open = "5"
rust-fuzzy-search = "0.1.1"
cargo_metadata = "0.18.1"
cargo_metadata = "0.19"
serde_json = "1.0.113"
image = { version = "0.25.1", default-features = false, features = ["gif", "jpeg", "png", "tga", "tiff", "bmp"] }
imageproc = "0.25.0"
+15 -14
View File
@@ -23,19 +23,18 @@ use crate::{
fyrox::{
asset::{manager::ResourceManager, untyped::UntypedResource, Resource, TypedResourceData},
core::{
algebra::Vector2, color::Color, futures::executor::block_on, make_relative_path,
pool::Handle, reflect::prelude::*, type_traits::prelude::*, uuid_provider,
visitor::prelude::*,
algebra::Vector2, futures::executor::block_on, make_relative_path, pool::Handle,
reflect::prelude::*, type_traits::prelude::*, uuid_provider, visitor::prelude::*,
},
gui::{
border::BorderBuilder,
brush::Brush,
define_constructor,
draw::{CommandTexture, Draw, DrawingContext},
formatted_text::WrapMode,
grid::{Column, GridBuilder, Row},
image::{ImageBuilder, ImageMessage},
message::{MessageDirection, UiMessage},
style::{resource::StyleResourceExt, Style},
text::TextBuilder,
widget::{Widget, WidgetBuilder, WidgetMessage},
BuildContext, Control, HorizontalAlignment, RcUiNodeHandle, Thickness, UiNode,
@@ -47,8 +46,6 @@ use crate::{
message::MessageSender,
Message,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::{
ops::{Deref, DerefMut},
path::{Path, PathBuf},
@@ -84,6 +81,10 @@ pub struct AssetItem {
}
impl AssetItem {
pub const SELECTED_FOREGROUND: &'static str = "AssetItem.SelectedForeground";
pub const SELECTED_BACKGROUND: &'static str = "AssetItem.SelectedBackground";
pub const DESELECTED_BRUSH: &'static str = "AssetItem.DeselectedBrush";
pub fn relative_path(&self) -> Result<PathBuf, std::io::Error> {
let Some(resource_manager) = self.resource_manager.as_ref() else {
return Err(std::io::Error::new(
@@ -211,18 +212,18 @@ impl Control for AssetItem {
self.handle(),
MessageDirection::ToWidget,
if *select {
Brush::Solid(Color::opaque(200, 220, 240))
ui.style.property(Self::SELECTED_FOREGROUND)
} else {
Brush::Solid(Color::TRANSPARENT)
ui.style.property(Self::DESELECTED_BRUSH)
},
));
ui.send_message(WidgetMessage::background(
self.handle(),
MessageDirection::ToWidget,
if *select {
Brush::Solid(Color::opaque(100, 100, 100))
ui.style.property(Self::SELECTED_BACKGROUND)
} else {
Brush::Solid(Color::TRANSPARENT)
ui.style.property(Self::DESELECTED_BRUSH)
},
));
}
@@ -256,14 +257,14 @@ fn make_tooltip(ctx: &mut BuildContext, text: &str) -> RcUiNodeHandle {
let handle = BorderBuilder::new(
WidgetBuilder::new()
.with_visibility(false)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKEST))
.with_background(Brush::Solid(Color::opaque(230, 230, 230)))
.with_foreground(ctx.style.property(Style::BRUSH_DARKEST))
.with_background(ctx.style.property(Style::BRUSH_TEXT))
.with_max_size(Vector2::new(300.0, f32::INFINITY))
.with_child(
TextBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(2.0))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKER)),
.with_foreground(ctx.style.property(Style::BRUSH_DARKER)),
)
.with_wrap(WrapMode::Letter)
.with_text(text)
@@ -315,7 +316,7 @@ impl AssetItemBuilder {
.widget_builder
.with_margin(Thickness::uniform(1.0))
.with_allow_drag(true)
.with_foreground(Brush::Solid(Color::opaque(50, 50, 50)))
.with_foreground(ctx.style.property(Style::BRUSH_PRIMARY))
.with_tooltip(make_tooltip(ctx, &format!("{path:?}")))
.with_child(
GridBuilder::new(
+4 -5
View File
@@ -35,14 +35,13 @@ use crate::{
untyped::{ResourceHeader, ResourceKind, UntypedResource},
},
core::{
color::Color, futures::executor::block_on, log::Log, make_relative_path,
futures::executor::block_on, log::Log, make_relative_path,
parking_lot::lock_api::Mutex, pool::Handle, TypeUuidProvider, Uuid,
},
engine::Engine,
graph::BaseSceneGraph,
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
copypasta::ClipboardProvider,
file_browser::{FileBrowserBuilder, FileBrowserMessage, Filter},
@@ -67,7 +66,6 @@ use crate::{
scene::sound::SoundBuffer,
walkdir,
},
gui::{make_dropdown_list_option, make_image_button_with_tooltip},
load_image,
message::MessageSender,
preview::PreviewPanel,
@@ -76,6 +74,7 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::{make_dropdown_list_option, make_image_button_with_tooltip};
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::fs::File;
use std::io::Write;
@@ -661,7 +660,7 @@ impl AssetBrowser {
.with_child(
BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_DARK))
.with_background(ctx.style.property(Style::BRUSH_DARK))
.with_child({
folder_browser = FileBrowserBuilder::new(
WidgetBuilder::new()
@@ -712,7 +711,7 @@ impl AssetBrowser {
BorderBuilder::new(
WidgetBuilder::new()
.on_column(2)
.with_foreground(Brush::Solid(Color::opaque(80, 80, 80)))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHTER))
.with_child(
GridBuilder::new(
WidgetBuilder::new()
+1 -1
View File
@@ -658,7 +658,7 @@ impl AssetPreviewGenerator for FontPreview {
WidgetBuilder::new().with_child(
TextBuilder::new(WidgetBuilder::new())
.with_font(font)
.with_font_size(16.0)
.with_font_size(16.0.into())
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_horizontal_text_alignment(HorizontalAlignment::Center)
.with_wrap(WrapMode::Letter)
+2 -2
View File
@@ -39,9 +39,9 @@ use crate::fyrox::{
},
scene::sound::{AudioBus, AudioBusGraph},
};
use crate::gui::make_dropdown_list_option;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_dropdown_list_option;
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone, PartialEq)]
@@ -139,7 +139,7 @@ fn make_items(buses: &[(Handle<AudioBus>, String)], ctx: &mut BuildContext) -> V
fn make_effect_names(names: &[String], ctx: &mut BuildContext) -> Vec<Handle<UiNode>> {
if names.is_empty() {
vec![TextBuilder::new(
WidgetBuilder::new().with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHTER)),
WidgetBuilder::new().with_foreground(ctx.style.property(Style::BRUSH_LIGHTER)),
)
.with_text("No Effects")
.with_horizontal_text_alignment(HorizontalAlignment::Center)
+1 -1
View File
@@ -41,7 +41,6 @@ use crate::{
},
scene::sound::{AudioBus, AudioBusGraph, DistanceModel, HrirSphereResourceData, Renderer},
},
gui::make_dropdown_list_option,
message::MessageSender,
scene::{
commands::{
@@ -57,6 +56,7 @@ use crate::{
ChangeSelectionCommand, Command, GameScene, GridBuilder, MessageDirection, Mode, Selection,
UserInterface,
};
use fyrox::gui::utils::make_dropdown_list_option;
use std::cmp::Ordering;
use strum::VariantNames;
+1 -1
View File
@@ -79,7 +79,7 @@ impl BuildWindow {
WidgetBuilder::new()
.on_row(1)
.with_margin(Thickness::uniform(2.0))
.with_background(ctx.style.get_or_default(Style::BRUSH_DARKEST))
.with_background(ctx.style.property(Style::BRUSH_DARKEST))
.with_child({
scroll_viewer =
ScrollViewerBuilder::new(WidgetBuilder::new())
+8 -7
View File
@@ -19,9 +19,8 @@
// SOFTWARE.
use crate::fyrox::{
core::{color::Color, pool::Handle},
core::pool::Handle,
gui::{
brush::Brush,
button::ButtonMessage,
grid::{Column, GridBuilder, Row},
list_view::{ListViewBuilder, ListViewMessage},
@@ -35,9 +34,11 @@ use crate::fyrox::{
},
};
use crate::{
gui::make_image_button_with_tooltip, load_image, message::MessageSender, send_sync_message,
utils::window_content, Message, Mode,
load_image, message::MessageSender, send_sync_message, utils::window_content, Message, Mode,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_image_button_with_tooltip;
pub struct CommandStackViewer {
pub window: Handle<UiNode>,
@@ -154,12 +155,12 @@ impl CommandStackViewer {
.map(|(i, name)| {
let brush = if let Some(top) = top {
if (0..=top).contains(&i) {
Brush::Solid(Color::opaque(255, 255, 255))
ui.style.property(Style::BRUSH_TEXT)
} else {
Brush::Solid(Color::opaque(100, 100, 100))
ui.style.property(Style::BRUSH_LIGHTEST)
}
} else {
Brush::Solid(Color::opaque(100, 100, 100))
ui.style.property(Style::BRUSH_LIGHTEST)
};
TextBuilder::new(
+16 -18
View File
@@ -21,15 +21,14 @@
use crate::{
fyrox::{
core::{
color::Color,
log::{Log, LogMessage, MessageKind},
pool::Handle,
reflect::prelude::*,
},
graph::BaseSceneGraph,
graph::SceneGraph,
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
decorator::DecoratorBuilder,
dropdown_list::{DropdownListBuilder, DropdownListMessage},
@@ -43,6 +42,8 @@ use crate::{
message::{MessageDirection, UiMessage},
scroll_viewer::{ScrollViewerBuilder, ScrollViewerMessage},
stack_panel::StackPanelBuilder,
style::resource::StyleResourceExt,
style::Style,
text::TextBuilder,
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
@@ -51,14 +52,11 @@ use crate::{
VerticalAlignment,
},
},
gui::make_dropdown_list_option,
message::MessageSender,
Message,
};
use cargo_metadata::{camino::Utf8Path, Metadata};
use fyrox::graph::SceneGraph;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_dropdown_list_option;
use std::{
ffi::OsStr,
fmt::{Display, Formatter},
@@ -186,7 +184,7 @@ fn make_command(program: &str) -> std::process::Command {
}
fn read_metadata() -> Result<Metadata, String> {
return match make_command("cargo")
match make_command("cargo")
.arg("metadata")
.stdout(Stdio::piped())
.spawn()
@@ -201,7 +199,7 @@ fn read_metadata() -> Result<Metadata, String> {
Err(err) => Err(format!("Unable to fetch project metadata. Reason {err:?}")),
},
Err(err) => Err(format!("Unable to fetch project metadata. Reason {err:?}")),
};
}
}
fn prepare_build_dir(path: &Path) -> Result<(), String> {
@@ -722,15 +720,16 @@ fn make_title_text(text: &str, row: usize, ctx: &mut BuildContext) -> Handle<UiN
TextBuilder::new(
WidgetBuilder::new()
.on_row(row)
.with_foreground(Brush::Solid(Color::CORN_SILK))
.with_foreground(ctx.style.property(ExportWindow::TITLE_BRUSH))
.with_margin(Thickness::uniform(2.0)),
)
.with_font_size(14.0)
.with_text(text)
.build(ctx)
}
impl ExportWindow {
pub const TITLE_BRUSH: &'static str = "ExportWindow.TitleBrush";
pub fn new(ctx: &mut BuildContext) -> Self {
let instructions =
"Select the target directory in which you want to export the current project. You can \
@@ -778,7 +777,6 @@ impl ExportWindow {
HorizontalAlignment::Center,
)
.with_text(p)
.with_font_size(14.0)
.build(ctx),
),
))
@@ -828,7 +826,7 @@ impl ExportWindow {
WidgetBuilder::new()
.on_row(3)
.with_margin(Thickness::uniform(2.0))
.with_background(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_background(ctx.style.property(Style::BRUSH_LIGHT))
.with_child(
ScrollViewerBuilder::new(
WidgetBuilder::new().with_margin(Thickness::uniform(2.0)),
@@ -864,7 +862,7 @@ impl ExportWindow {
BorderBuilder::new(
WidgetBuilder::new()
.on_row(1)
.with_background(ctx.style.get_or_default(Style::BRUSH_DARKER))
.with_background(ctx.style.property(Style::BRUSH_DARKER))
.with_margin(Thickness::uniform(2.0))
.with_child({
log_scroll_viewer = ScrollViewerBuilder::new(
@@ -1113,15 +1111,15 @@ impl ExportWindow {
if let Some(log_message_receiver) = self.log_message_receiver.as_mut() {
while let Ok(message) = log_message_receiver.try_recv() {
let ctx = &mut ui.build_ctx();
let color = match message.kind {
MessageKind::Information => Color::ANTIQUE_WHITE,
MessageKind::Warning => Color::ORANGE,
MessageKind::Error => Color::RED,
let foreground = match message.kind {
MessageKind::Information => ctx.style.property(Style::BRUSH_INFORMATION),
MessageKind::Warning => ctx.style.property(Style::BRUSH_WARNING),
MessageKind::Error => ctx.style.property(Style::BRUSH_ERROR),
};
let entry = TextBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.with_foreground(Brush::Solid(color)),
.with_foreground(foreground),
)
.with_wrap(WrapMode::Letter)
.with_text(format!("> {}", message.content))
-121
View File
@@ -1,121 +0,0 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::fyrox::{
asset::untyped::UntypedResource,
core::{color::Color, parking_lot::Mutex, pool::Handle},
gui::{
border::BorderBuilder, brush::Brush, button::ButtonBuilder, decorator::DecoratorBuilder,
image::ImageBuilder, text::TextBuilder, utils::make_simple_tooltip, widget::WidgetBuilder,
BuildContext, HorizontalAlignment, Thickness, UiNode, VerticalAlignment,
},
};
use std::sync::Arc;
pub fn make_dropdown_list_option_universal<T: Send + 'static>(
ctx: &mut BuildContext,
name: &str,
height: f32,
user_data: T,
) -> Handle<UiNode> {
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new()
.with_height(height)
.with_user_data(Arc::new(Mutex::new(user_data)))
.with_child(
TextBuilder::new(WidgetBuilder::new())
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_horizontal_text_alignment(HorizontalAlignment::Center)
.with_text(name)
.build(ctx),
),
)
.with_corner_radius(4.0)
.with_pad_by_corner_radius(false),
)
.build(ctx)
}
pub fn make_dropdown_list_option(ctx: &mut BuildContext, name: &str) -> Handle<UiNode> {
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_child(
TextBuilder::new(WidgetBuilder::new())
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_horizontal_text_alignment(HorizontalAlignment::Center)
.with_text(name)
.build(ctx),
),
)
.with_corner_radius(4.0)
.with_pad_by_corner_radius(false),
)
.build(ctx)
}
pub fn make_dropdown_list_option_with_height(
ctx: &mut BuildContext,
name: &str,
height: f32,
) -> Handle<UiNode> {
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_height(height).with_child(
TextBuilder::new(WidgetBuilder::new())
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_horizontal_text_alignment(HorizontalAlignment::Center)
.with_text(name)
.build(ctx),
),
)
.with_corner_radius(4.0)
.with_pad_by_corner_radius(false),
)
.build(ctx)
}
pub fn make_image_button_with_tooltip(
ctx: &mut BuildContext,
width: f32,
height: f32,
image: Option<UntypedResource>,
tooltip: &str,
tab_index: Option<usize>,
) -> Handle<UiNode> {
ButtonBuilder::new(
WidgetBuilder::new()
.with_tab_index(tab_index)
.with_tooltip(make_simple_tooltip(ctx, tooltip))
.with_margin(Thickness::uniform(1.0)),
)
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_background(Brush::Solid(Color::opaque(180, 180, 180)))
.with_margin(Thickness::uniform(2.0))
.with_width(width)
.with_height(height),
)
.with_opt_texture(image)
.build(ctx),
)
.build(ctx)
}
+8 -10
View File
@@ -22,14 +22,12 @@ use crate::{
fyrox::{
core::{
algebra::{Vector2, Vector3},
color::Color,
pool::Handle,
uuid::Uuid,
TypeUuidProvider,
},
gui::{
border::BorderBuilder,
brush::Brush,
button::ButtonBuilder,
decorator::DecoratorBuilder,
image::ImageBuilder,
@@ -213,23 +211,23 @@ pub fn make_interaction_mode_button(
.with_back(
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKER)),
WidgetBuilder::new().with_foreground(ctx.style.property(Style::BRUSH_DARKER)),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(4.0)
.with_stroke_thickness(Thickness::uniform(1.0)),
.with_corner_radius(4.0f32.into())
.with_stroke_thickness(Thickness::uniform(1.0).into()),
)
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_selected_brush(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.property(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.property(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.property(Style::BRUSH_LIGHTEST))
.with_selected_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.with_selected(selected)
.build(ctx),
)
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_background(Brush::Solid(Color::opaque(220, 220, 220)))
.with_background(ctx.style.property(Style::BRUSH_TEXT))
.with_margin(Thickness::uniform(2.0))
.with_width(23.0)
.with_height(23.0),
+2 -2
View File
@@ -616,7 +616,7 @@ impl InteractionMode for EditNavmeshMode {
let scene = &mut engine.scenes[game_scene.scene];
if let Some(selection) = fetch_selection(editor_selection) {
return match key {
match key {
KeyCode::Delete => {
if scene
.graph
@@ -672,7 +672,7 @@ impl InteractionMode for EditNavmeshMode {
true
}
_ => false,
};
}
} else {
false
}
+142 -86
View File
@@ -37,11 +37,9 @@ pub mod camera;
pub mod command;
pub mod configurator;
pub mod export;
pub mod gui;
pub mod highlight;
pub mod interaction;
pub mod light;
pub mod log;
pub mod menu;
pub mod mesh;
pub mod message;
@@ -60,7 +58,8 @@ pub mod world;
pub use fyrox;
use crate::plugins::path_fixer::PathFixerPlugin;
use crate::asset::item::AssetItem;
use crate::plugins::absm::AbsmEditor;
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},
@@ -117,12 +121,12 @@ use crate::{
},
plugin::{dylib::DyLibDynamicPlugin, DynamicPlugin, Plugin, PluginContainer},
resource::texture::{
CompressionOptions, TextureImportOptions, TextureKind, TextureMinificationFilter,
TextureResource, TextureResourceExtension,
CompressionOptions, TextureImportOptions, TextureMinificationFilter, TextureResource,
TextureResourceExtension,
},
scene::{graph::GraphUpdateSwitches, mesh::Mesh, Scene, SceneLoader},
utils::{translate_cursor_icon, translate_event},
window::{Icon, WindowAttributes},
window::WindowAttributes,
},
highlight::HighlightRenderPass,
interaction::{
@@ -134,7 +138,6 @@ use crate::{
terrain::TerrainInteractionMode,
},
light::LightPanel,
log::LogPanel,
menu::{Menu, MenuContext, Panels},
mesh::{MeshControlPanel, SurfaceDataViewer},
message::MessageSender,
@@ -143,8 +146,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 +160,7 @@ use crate::{
GameScene, Selection,
},
scene_viewer::SceneViewer,
settings::build::BuildCommand,
settings::Settings,
settings::{general::EditorStyle, Settings},
stats::{StatisticsWindow, StatisticsWindowAction},
ui_scene::{
commands::graph::PasteWidgetCommand, menu::WidgetContextMenu,
@@ -166,15 +169,16 @@ use crate::{
utils::doc::DocWindow,
world::{graph::menu::SceneNodeContextMenu, graph::EditorSceneWrapper, WorldViewer},
};
use fyrox::gui::constructor::new_widget_constructor_container;
use fyrox::gui::log::LogPanel;
use fyrox_build_tools::CommandDescriptor;
pub use message::Message;
use plugins::inspector::InspectorPlugin;
use std::process::Stdio;
use std::{
cell::RefCell,
collections::VecDeque,
io::{BufRead, BufReader},
path::{Path, PathBuf},
process::Stdio,
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
@@ -299,7 +303,7 @@ pub fn make_save_file_selector(
pub enum Mode {
Edit,
Build {
queue: VecDeque<BuildCommand>,
queue: VecDeque<CommandDescriptor>,
process: Option<std::process::Child>,
},
Play {
@@ -557,6 +561,7 @@ pub struct Editor {
pub statistics_window: Option<StatisticsWindow>,
pub surface_data_viewer: Option<SurfaceDataViewer>,
pub processed_ui_messages: usize,
pub styles: FxHashMap<EditorStyle, StyleResource>,
}
impl Editor {
@@ -565,6 +570,71 @@ impl Editor {
Log::add_listener(log_message_sender);
let mut dark_style = Style::dark_style();
dark_style
.set(
WorldViewer::INSTANCE_BRUSH,
Brush::Solid(Color::opaque(160, 160, 200)),
)
.set(
AssetItem::SELECTED_FOREGROUND,
Brush::Solid(Color::opaque(200, 220, 240)),
)
.set(
AssetItem::SELECTED_BACKGROUND,
Brush::Solid(Color::opaque(100, 100, 100)),
)
.set(
AssetItem::DESELECTED_BRUSH,
Brush::Solid(Color::TRANSPARENT),
)
.set(ExportWindow::TITLE_BRUSH, Brush::Solid(Color::CORN_SILK))
.set(
AbsmEditor::NORMAL_ROOT_COLOR,
Brush::Solid(Color::opaque(40, 80, 0)),
)
.set(
AbsmEditor::SELECTED_ROOT_COLOR,
Brush::Solid(Color::opaque(60, 100, 0)),
);
let dark_style = StyleResource::new_ok(ResourceKind::Embedded, dark_style);
let mut light_style = Style::light_style();
light_style
.set(
WorldViewer::INSTANCE_BRUSH,
Brush::Solid(Color::opaque(160, 160, 200)),
)
.set(
AssetItem::SELECTED_FOREGROUND,
Brush::Solid(Color::opaque(200, 220, 240)),
)
.set(
AssetItem::SELECTED_BACKGROUND,
Brush::Solid(Color::opaque(100, 100, 100)),
)
.set(
AssetItem::DESELECTED_BRUSH,
Brush::Solid(Color::TRANSPARENT),
)
.set(ExportWindow::TITLE_BRUSH, Brush::Solid(Color::CORN_SILK))
.set(
AbsmEditor::NORMAL_ROOT_COLOR,
Brush::Solid(Color::opaque(40, 80, 0)),
)
.set(
AbsmEditor::SELECTED_ROOT_COLOR,
Brush::Solid(Color::opaque(60, 100, 0)),
);
let light_style = StyleResource::new_ok(ResourceKind::Embedded, light_style);
let styles = [
(EditorStyle::Dark, dark_style),
(EditorStyle::Light, light_style),
]
.into_iter()
.collect::<FxHashMap<_, _>>();
let mut settings = Settings::default();
match Settings::load() {
@@ -623,10 +693,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);
@@ -646,7 +718,12 @@ impl Editor {
)));
let world_outliner = WorldViewer::new(ctx, message_sender.clone(), &settings);
let command_stack_viewer = CommandStackViewer::new(ctx, message_sender.clone());
let log = LogPanel::new(ctx, log_message_receiver);
let log = LogPanel::new(
ctx,
log_message_receiver,
load_image!("../resources/clear.png"),
true,
);
let inspector_plugin = InspectorPlugin::new(ctx, message_sender.clone());
let particle_system_control_panel =
ParticleSystemPreviewControlPanel::new(scene_viewer.frame(), ctx);
@@ -888,6 +965,7 @@ impl Editor {
statistics_window: None,
surface_data_viewer: None,
processed_ui_messages: 0,
styles,
};
if let Some(data) = startup_data {
@@ -1215,12 +1293,18 @@ impl Editor {
self.surface_data_viewer = surface_data_viewer.handle_ui_message(message, engine);
}
self.build_window.handle_ui_message(
message,
&self.message_sender,
engine.user_interfaces.first(),
);
self.log.handle_ui_message(message, engine);
let ui = engine.user_interfaces.first_mut();
self.build_window
.handle_ui_message(message, &self.message_sender, ui);
if let Some(export_window) = self.export_window.as_mut() {
export_window.handle_ui_message(message, ui, &self.message_sender);
}
if let Some(stats) = self.statistics_window.as_ref() {
if let StatisticsWindowAction::Remove = stats.handle_ui_message(message, ui) {
self.statistics_window.take();
}
}
self.log.handle_ui_message(message, ui);
self.asset_browser
.handle_ui_message(message, engine, self.message_sender.clone());
self.command_stack_viewer.handle_ui_message(message);
@@ -1231,20 +1315,6 @@ impl Editor {
&mut self.settings,
&self.mode,
);
if let Some(export_window) = self.export_window.as_mut() {
export_window.handle_ui_message(
message,
engine.user_interfaces.first_mut(),
&self.message_sender,
);
}
if let Some(stats) = self.statistics_window.as_ref() {
if let StatisticsWindowAction::Remove =
stats.handle_ui_message(message, engine.user_interfaces.first())
{
self.statistics_window.take();
}
}
let current_scene_entry = self.scenes.current_scene_entry_mut();
@@ -1424,22 +1494,15 @@ impl Editor {
build_profile.run_command
));
let mut process = std::process::Command::new(&build_profile.run_command.command);
let mut command = build_profile.run_command.make_command();
process
command
.stdout(Stdio::piped())
.args(build_profile.run_command.args.iter())
.envs(
build_profile
.run_command
.environment_variables
.iter()
.map(|v| (&v.name, &v.value)),
);
.arg("--")
.arg("--override-scene")
.arg(path);
process.arg("--").arg("--override-scene").arg(path);
match process.spawn() {
match command.spawn() {
Ok(mut process) => {
let active = Arc::new(AtomicBool::new(true));
@@ -2066,21 +2129,10 @@ impl Editor {
ref mut queue,
} => {
if process.is_none() {
if let Some(command) = queue.pop_front() {
Log::info(format!("Trying to run build command: {command}"));
if let Some(build_command) = queue.pop_front() {
Log::info(format!("Trying to run build command: {build_command}"));
let mut new_process = std::process::Command::new(&command.command);
new_process
.stderr(Stdio::piped())
.args(command.args.iter())
.envs(
command
.environment_variables
.iter()
.map(|v| (&v.name, &v.value)),
);
match new_process.spawn() {
match build_command.make_command().stderr(Stdio::piped()).spawn() {
Ok(mut new_process) => {
self.build_window.listen(
new_process.stderr.take().unwrap(),
@@ -2137,12 +2189,22 @@ impl Editor {
self.handle_modes();
self.log.update(&self.settings, &mut self.engine);
let ui = self.engine.user_interfaces.first_mut();
if let Some(active_tooltip) = ui.active_tooltip() {
if !active_tooltip.shown {
// Keep the editor running until the current tooltip is not shown.
self.update_loop_state.request_update_in_next_frame();
}
}
self.log.update(self.settings.general.max_log_entries, ui);
if let Some(export_window) = self.export_window.as_mut() {
export_window.update(ui);
}
self.asset_browser
.update(&mut self.engine, &self.message_sender);
if let Some(export_window) = self.export_window.as_mut() {
export_window.update(self.engine.user_interfaces.first_mut());
}
if let Some(surface_data_viewer) = self.surface_data_viewer.as_mut() {
surface_data_viewer.update(&mut self.engine);
}
@@ -2397,7 +2459,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) {
@@ -2496,20 +2565,7 @@ impl Editor {
let graphics_context = engine.graphics_context.as_initialized_mut();
if let Ok(icon_img) = TextureResource::load_from_memory(
"../resources/icon.png".into(),
include_bytes!("../resources/icon.png"),
TextureImportOptions::default()
.with_compression(CompressionOptions::NoCompression)
.with_minification_filter(TextureMinificationFilter::Linear),
) {
let data = icon_img.data_ref();
if let TextureKind::Rectangle { width, height } = data.kind() {
if let Ok(img) = Icon::from_rgba(data.data().to_vec(), width, height) {
graphics_context.window.set_window_icon(Some(img));
}
}
}
graphics_context.set_window_icon_from_memory(include_bytes!("../resources/icon.png"));
// High-DPI screen support
Log::info(format!(
-325
View File
@@ -1,325 +0,0 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// 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::{
gui::{make_dropdown_list_option, make_image_button_with_tooltip},
load_image, Brush, Color, DropdownListBuilder, Engine,
};
use fyrox::gui::menu::ContextMenuBuilder;
use std::sync::mpsc::Receiver;
struct ContextMenu {
menu: RcUiNodeHandle,
copy: Handle<UiNode>,
placement_target: Handle<UiNode>,
}
impl ContextMenu {
pub fn new(ctx: &mut BuildContext) -> Self {
let copy;
let menu = ContextMenuBuilder::new(
PopupBuilder::new(WidgetBuilder::new()).with_content(
StackPanelBuilder::new(WidgetBuilder::new().with_child({
copy = MenuItemBuilder::new(WidgetBuilder::new())
.with_content(MenuItemContent::text("Copy"))
.build(ctx);
copy
}))
.build(ctx),
),
)
.build(ctx);
let menu = RcUiNodeHandle::new(menu, ctx.sender());
Self {
menu,
copy,
placement_target: Default::default(),
}
}
pub fn handle_ui_message(&mut self, message: &UiMessage, engine: &mut Engine) {
if let Some(PopupMessage::Placement(Placement::Cursor(target))) = message.data() {
if message.destination() == self.menu.handle() {
self.placement_target = *target;
}
} else if let Some(MenuItemMessage::Click) = message.data() {
if message.destination() == self.copy {
if let Some(field) = engine
.user_interfaces
.first_mut()
.try_get(self.placement_target)
.and_then(|n| n.query_component::<Text>())
{
let text = field.text();
if let Some(mut clipboard) = engine.user_interfaces.first_mut().clipboard_mut()
{
let _ = clipboard.set_contents(text);
}
}
}
}
}
}
pub struct LogPanel {
pub window: Handle<UiNode>,
messages: Handle<UiNode>,
clear: Handle<UiNode>,
receiver: Receiver<LogMessage>,
severity: MessageKind,
severity_list: Handle<UiNode>,
context_menu: ContextMenu,
}
impl LogPanel {
pub fn new(ctx: &mut BuildContext, message_receiver: Receiver<LogMessage>) -> Self {
let messages;
let clear;
let severity_list;
let window = WindowBuilder::new(WidgetBuilder::new().with_name("LogPanel"))
.can_minimize(false)
.with_title(WindowTitle::text("Message Log"))
.with_content(
GridBuilder::new(
WidgetBuilder::new()
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Left)
.on_row(0)
.on_column(0)
.with_child({
clear = make_image_button_with_tooltip(
ctx,
24.0,
24.0,
load_image!("../resources/clear.png"),
"Clear the log.",
Some(0),
);
clear
})
.with_child({
severity_list = DropdownListBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(1))
.with_width(120.0)
.with_margin(Thickness::uniform(1.0)),
)
.with_items(vec![
make_dropdown_list_option(ctx, "Info+"),
make_dropdown_list_option(ctx, "Warnings+"),
make_dropdown_list_option(ctx, "Errors"),
])
// Warnings+
.with_selected(1)
.build(ctx);
severity_list
}),
)
.with_orientation(Orientation::Horizontal)
.build(ctx),
)
.with_child({
messages = ListViewBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.on_row(1)
.on_column(0),
)
.with_scroll_viewer(
ScrollViewerBuilder::new(
WidgetBuilder::new().with_margin(Thickness::uniform(3.0)),
)
.with_horizontal_scroll_allowed(true)
.with_vertical_scroll_allowed(true)
.build(ctx),
)
.build(ctx);
messages
}),
)
.add_row(Row::strict(26.0))
.add_row(Row::stretch())
.add_column(Column::stretch())
.build(ctx),
)
.build(ctx);
let context_menu = ContextMenu::new(ctx);
Self {
window,
messages,
clear,
receiver: message_receiver,
severity: MessageKind::Warning,
severity_list,
context_menu,
}
}
pub fn handle_ui_message(&mut self, message: &UiMessage, engine: &mut Engine) {
if let Some(ButtonMessage::Click) = message.data::<ButtonMessage>() {
if message.destination() == self.clear {
engine
.user_interfaces
.first_mut()
.send_message(ListViewMessage::items(
self.messages,
MessageDirection::ToWidget,
vec![],
));
}
} else if let Some(DropdownListMessage::SelectionChanged(Some(idx))) =
message.data::<DropdownListMessage>()
{
if message.destination() == self.severity_list
&& message.direction() == MessageDirection::FromWidget
{
match idx {
0 => self.severity = MessageKind::Information,
1 => self.severity = MessageKind::Warning,
2 => self.severity = MessageKind::Error,
_ => (),
};
}
}
self.context_menu.handle_ui_message(message, engine);
}
pub fn update(&mut self, settings: &Settings, engine: &mut Engine) {
let ui = engine.user_interfaces.first();
let existing_items = ui
.node(self.messages)
.cast::<ListView>()
.map(|v| v.items())
.unwrap();
let mut count = existing_items.len();
if count > settings.general.max_log_entries {
let delta = count - settings.general.max_log_entries;
// Remove every item in the head of the list of entries to keep the amount of entries
// in the limits.
//
// TODO: This is suboptimal, because it creates a message per each excessive entry, which
// might be slow to process in case of large amount of messages.
for item in existing_items.iter().take(delta) {
ui.send_message(ListViewMessage::remove_item(
self.messages,
MessageDirection::ToWidget,
*item,
));
}
count -= delta;
}
let mut item_to_bring_into_view = Handle::NONE;
while let Ok(msg) = self.receiver.try_recv() {
if msg.kind < self.severity {
continue;
}
let text = format!("[{:.2}s] {}", msg.time.as_secs_f32(), msg.content);
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)
} else {
Color::opaque(40, 40, 40)
}))
.with_child(
TextBuilder::new(
WidgetBuilder::new()
.with_context_menu(self.context_menu.menu.clone())
.with_margin(Thickness::uniform(1.0))
.with_foreground(Brush::Solid(match msg.kind {
MessageKind::Information => Color::ANTIQUE_WHITE,
MessageKind::Warning => Color::GOLD,
MessageKind::Error => Color::RED,
})),
)
.with_text(text)
.with_wrap(WrapMode::Word)
.build(ctx),
),
)
.build(ctx);
engine
.user_interfaces
.first_mut()
.send_message(ListViewMessage::add_item(
self.messages,
MessageDirection::ToWidget,
item,
));
item_to_bring_into_view = item;
count += 1;
}
if item_to_bring_into_view.is_some() {
engine
.user_interfaces
.first_mut()
.send_message(ListViewMessage::bring_item_into_view(
self.messages,
MessageDirection::ToWidget,
item_to_bring_into_view,
));
}
}
}
+4 -4
View File
@@ -172,8 +172,8 @@ fn make_points<P: Iterator<Item = Vector2<f32>>>(
BlendSpaceFieldPointBuilder::new(
WidgetBuilder::new()
.with_context_menu(context_menu.clone())
.with_background(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_foreground(Brush::Solid(Color::WHITE))
.with_background(ctx.style.property(Style::BRUSH_LIGHTEST))
.with_foreground(ctx.style.property(Style::BRUSH_TEXT))
.with_desired_position(p),
i,
)
@@ -658,8 +658,8 @@ impl BlendSpaceEditor {
.on_row(0)
.on_column(1)
.with_margin(Thickness::uniform(15.0))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_background(ctx.style.get_or_default(Style::BRUSH_DARK)),
.with_foreground(ctx.style.property(Style::BRUSH_LIGHTEST))
.with_background(ctx.style.property(Style::BRUSH_DARK)),
)
.build(ctx);
+3 -3
View File
@@ -91,14 +91,14 @@ impl Control for Connection {
ui.send_message(WidgetMessage::foreground(
self.handle(),
MessageDirection::ToWidget,
PICKED_BRUSH.clone(),
PICKED_BRUSH.clone().into(),
));
}
WidgetMessage::MouseLeave => {
ui.send_message(WidgetMessage::foreground(
self.handle(),
MessageDirection::ToWidget,
NORMAL_BRUSH.clone(),
NORMAL_BRUSH.clone().into(),
));
}
_ => (),
@@ -152,7 +152,7 @@ impl ConnectionBuilder {
let connection = Connection {
widget: self
.widget_builder
.with_foreground(NORMAL_BRUSH)
.with_foreground(NORMAL_BRUSH.into())
.with_clip_to_bounds(false)
.build(ctx),
segment: Segment {
+4 -7
View File
@@ -19,7 +19,7 @@
// SOFTWARE.
use crate::fyrox::{
core::{color::Color, pool::ErasedHandle, pool::Handle, variable::InheritableVariable},
core::{pool::ErasedHandle, pool::Handle, variable::InheritableVariable},
fxhash::FxHashSet,
generic_animation::{
machine::{
@@ -75,12 +75,6 @@ mod state_viewer;
mod toolbar;
mod transition;
const NORMAL_BACKGROUND: Color = Color::opaque(60, 60, 60);
const SELECTED_BACKGROUND: Color = Color::opaque(80, 80, 80);
const BORDER_COLOR: Color = Color::opaque(70, 70, 70);
const NORMAL_ROOT_COLOR: Color = Color::opaque(40, 80, 0);
const SELECTED_ROOT_COLOR: Color = Color::opaque(60, 100, 0);
struct PreviewModeData<N: 'static> {
machine: Machine<Handle<N>>,
nodes: Vec<(Handle<N>, N)>,
@@ -203,6 +197,9 @@ pub struct AbsmEditor {
impl AbsmEditor {
const WINDOW_NAME: &'static str = "AsbmEditor";
pub const NORMAL_ROOT_COLOR: &'static str = "AsbmEditor.NormalRootColor";
pub const SELECTED_ROOT_COLOR: &'static str = "AsbmEditor.SelectedRootColor";
pub fn new(ctx: &mut BuildContext, sender: MessageSender) -> Self {
let state_graph_viewer = StateGraphViewer::new(ctx);
let state_viewer = StateViewer::new(ctx);
+57 -44
View File
@@ -38,10 +38,9 @@ use crate::fyrox::{
VerticalAlignment,
},
};
use crate::plugins::absm::{
selectable::{Selectable, SelectableMessage},
BORDER_COLOR, NORMAL_BACKGROUND, SELECTED_BACKGROUND,
};
use crate::plugins::absm::selectable::{Selectable, SelectableMessage};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::{Style, StyledProperty};
use std::{
fmt::{Debug, Formatter},
ops::{Deref, DerefMut},
@@ -68,8 +67,8 @@ where
pub base: AbsmBaseNode,
pub add_input: Handle<UiNode>,
input_sockets_panel: Handle<UiNode>,
normal_color: Color,
selected_color: Color,
normal_brush: StyledProperty<Brush>,
selected_brush: StyledProperty<Brush>,
name: Handle<UiNode>,
edit: Handle<UiNode>,
}
@@ -94,8 +93,8 @@ where
base: self.base.clone(),
add_input: self.add_input,
input_sockets_panel: self.input_sockets_panel,
normal_color: self.normal_color,
selected_color: self.selected_color,
normal_brush: self.normal_brush.clone(),
selected_brush: self.selected_brush.clone(),
name: self.name,
edit: self.edit,
}
@@ -130,23 +129,23 @@ where
ui.send_message(WidgetMessage::background(
self.background,
MessageDirection::ToWidget,
Brush::Solid(if self.selectable.selected {
self.selected_color
if self.selectable.selected {
self.selected_brush.clone()
} else {
self.normal_color
}),
self.normal_brush.clone()
},
));
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq)]
pub enum AbsmNodeMessage {
Name(String),
Enter,
AddInput,
InputSockets(Vec<Handle<UiNode>>),
NormalColor(Color),
SelectedColor(Color),
NormalBrush(StyledProperty<Brush>),
SelectedBrush(StyledProperty<Brush>),
SetActive(bool),
Edit,
}
@@ -156,8 +155,8 @@ impl AbsmNodeMessage {
define_constructor!(AbsmNodeMessage:Enter => fn enter(), layout: false);
define_constructor!(AbsmNodeMessage:AddInput => fn add_input(), layout: false);
define_constructor!(AbsmNodeMessage:InputSockets => fn input_sockets(Vec<Handle<UiNode>>), layout: false);
define_constructor!(AbsmNodeMessage:NormalColor => fn normal_color(Color), layout: false);
define_constructor!(AbsmNodeMessage:SelectedColor => fn selected_color(Color), layout: false);
define_constructor!(AbsmNodeMessage:NormalBrush => fn normal_color(StyledProperty<Brush>), layout: false);
define_constructor!(AbsmNodeMessage:SelectedBrush => fn selected_color(StyledProperty<Brush>), layout: false);
define_constructor!(AbsmNodeMessage:SetActive => fn set_active(bool), layout: false);
define_constructor!(AbsmNodeMessage:Edit => fn edit(), layout: false);
}
@@ -233,15 +232,15 @@ where
self.base.input_sockets.clone_from(input_sockets);
}
}
AbsmNodeMessage::NormalColor(color) => {
if &self.normal_color != color {
self.normal_color = *color;
AbsmNodeMessage::NormalBrush(color) => {
if &self.normal_brush != color {
self.normal_brush = color.clone();
self.update_colors(ui);
}
}
AbsmNodeMessage::SelectedColor(color) => {
if &self.selected_color != color {
self.selected_color = *color;
AbsmNodeMessage::SelectedBrush(color) => {
if &self.selected_brush != color {
self.selected_brush = color.clone();
self.update_colors(ui);
}
}
@@ -257,21 +256,27 @@ where
}
}
AbsmNodeMessage::SetActive(active) => {
let (thickness, color) = if *active {
(Thickness::uniform(3.0), Color::opaque(120, 80, 60))
let (thickness, brush) = if *active {
(
Thickness::uniform(3.0),
Brush::Solid(Color::opaque(120, 80, 60)).into(),
)
} else {
(Thickness::uniform(1.0), BORDER_COLOR)
(
Thickness::uniform(1.0),
ui.style.property(Style::BRUSH_LIGHT),
)
};
ui.send_message(BorderMessage::stroke_thickness(
self.background,
MessageDirection::ToWidget,
thickness,
thickness.into(),
));
ui.send_message(WidgetMessage::foreground(
self.background,
MessageDirection::ToWidget,
Brush::Solid(color),
brush,
));
}
_ => (),
@@ -292,8 +297,8 @@ where
output_socket: Handle<UiNode>,
can_add_sockets: bool,
title: Option<String>,
normal_color: Color,
selected_color: Color,
normal_brush: Option<StyledProperty<Brush>>,
selected_brush: Option<StyledProperty<Brush>>,
editable: bool,
}
@@ -310,8 +315,8 @@ where
output_socket: Default::default(),
can_add_sockets: false,
title: None,
normal_color: NORMAL_BACKGROUND,
selected_color: SELECTED_BACKGROUND,
normal_brush: None,
selected_brush: None,
editable: false,
}
}
@@ -346,13 +351,13 @@ where
self
}
pub fn with_normal_color(mut self, color: Color) -> Self {
self.normal_color = color;
pub fn with_normal_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.normal_brush = Some(brush);
self
}
pub fn with_selected_color(mut self, color: Color) -> Self {
self.selected_color = color;
pub fn with_selected_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.selected_brush = Some(brush);
self
}
@@ -457,7 +462,7 @@ where
BorderBuilder::new(
WidgetBuilder::new()
.with_height(24.0)
.with_background(Brush::Solid(Color::opaque(30, 30, 30)))
.with_background(ctx.style.property(Style::BRUSH_DARKER))
.with_child(
TextBuilder::new(
WidgetBuilder::new()
@@ -472,8 +477,8 @@ where
),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(12.0)
.with_stroke_thickness(Thickness::zero())
.with_corner_radius(12.0f32.into())
.with_stroke_thickness(Thickness::zero().into())
.build(ctx)
})
.unwrap_or_default(),
@@ -485,14 +490,22 @@ where
.add_column(Column::stretch())
.build(ctx);
let normal_brush = self
.normal_brush
.unwrap_or_else(|| ctx.style.property(Style::BRUSH_LIGHTER_PRIMARY));
let selected_brush = self
.selected_brush
.unwrap_or_else(|| ctx.style.property(Style::BRUSH_LIGHTER));
let background = BorderBuilder::new(
WidgetBuilder::new()
.with_foreground(Brush::Solid(BORDER_COLOR))
.with_background(Brush::Solid(self.normal_color))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHT))
.with_background(normal_brush.clone())
.with_child(grid2),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(12.0)
.with_corner_radius(12.0f32.into())
.build(ctx);
let node = AbsmNode {
@@ -507,8 +520,8 @@ where
},
add_input,
input_sockets_panel,
normal_color: self.normal_color,
selected_color: self.selected_color,
normal_brush,
selected_brush,
name,
edit,
};
+6 -8
View File
@@ -21,11 +21,10 @@
use crate::fyrox::core::pool::ErasedHandle;
use crate::fyrox::{
core::{
algebra::Vector2, color::Color, pool::Handle, reflect::prelude::*, type_traits::prelude::*,
algebra::Vector2, pool::Handle, reflect::prelude::*, type_traits::prelude::*,
uuid_provider, visitor::prelude::*,
},
gui::{
brush::Brush,
define_constructor, define_widget_deref,
grid::{Column, GridBuilder, Row},
message::{MessageDirection, MouseButton, UiMessage},
@@ -36,11 +35,10 @@ use crate::fyrox::{
BuildContext, Control, Orientation, Thickness, UiNode, UserInterface, VerticalAlignment,
},
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::ops::{Deref, DerefMut};
const PICKED_BRUSH: Brush = Brush::Solid(Color::opaque(170, 170, 170));
const NORMAL_BRUSH: Brush = Brush::Solid(Color::opaque(120, 120, 120));
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SocketMessage {
// Occurs when user clicks on socket and starts dragging it.
@@ -116,14 +114,14 @@ impl Control for Socket {
ui.send_message(WidgetMessage::foreground(
self.pin,
MessageDirection::ToWidget,
NORMAL_BRUSH,
ui.style.property(Style::BRUSH_BRIGHT),
));
}
WidgetMessage::MouseEnter => {
ui.send_message(WidgetMessage::foreground(
self.pin,
MessageDirection::ToWidget,
PICKED_BRUSH,
ui.style.property(Style::BRUSH_BRIGHTEST),
));
}
_ => (),
@@ -195,7 +193,7 @@ impl SocketBuilder {
WidgetBuilder::new()
.on_row(0)
.on_column(0)
.with_foreground(NORMAL_BRUSH),
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHT)),
)
.with_primitives(vec![Primitive::Circle {
center: Vector2::new(RADIUS, RADIUS),
+13 -11
View File
@@ -39,7 +39,7 @@ use crate::plugins::absm::{
selection::{AbsmSelection, SelectedEntity},
state_graph::context::{CanvasContextMenu, NodeContextMenu, TransitionContextMenu},
transition::{TransitionBuilder, TransitionMessage, TransitionView},
NORMAL_BACKGROUND, NORMAL_ROOT_COLOR, SELECTED_BACKGROUND, SELECTED_ROOT_COLOR,
AbsmEditor,
};
use crate::{
command::{Command, CommandGroup},
@@ -47,6 +47,8 @@ use crate::{
scene::{commands::ChangeSelectionCommand, Selection},
send_sync_message,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::cmp::Ordering;
mod context;
@@ -359,15 +361,15 @@ impl StateGraphViewer {
.with_context_menu(self.node_context_menu.menu.clone())
.with_desired_position(state.position),
)
.with_normal_color(if state_handle == machine_layer.entry_state() {
NORMAL_ROOT_COLOR
.with_normal_brush(if state_handle == machine_layer.entry_state() {
ui.style.property(AbsmEditor::NORMAL_ROOT_COLOR)
} else {
NORMAL_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER_PRIMARY)
})
.with_selected_color(if state_handle == machine_layer.entry_state() {
SELECTED_ROOT_COLOR
.with_selected_brush(if state_handle == machine_layer.entry_state() {
ui.style.property(AbsmEditor::SELECTED_ROOT_COLOR)
} else {
SELECTED_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER)
})
.with_model_handle(state_handle)
.with_name(state.name.clone())
@@ -454,9 +456,9 @@ impl StateGraphViewer {
*state,
MessageDirection::ToWidget,
if state_model_handle == machine_layer.entry_state() {
NORMAL_ROOT_COLOR
ui.style.property(AbsmEditor::NORMAL_ROOT_COLOR)
} else {
NORMAL_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER_PRIMARY)
},
),
);
@@ -466,9 +468,9 @@ impl StateGraphViewer {
*state,
MessageDirection::ToWidget,
if state_model_handle == machine_layer.entry_state() {
SELECTED_ROOT_COLOR
ui.style.property(AbsmEditor::SELECTED_ROOT_COLOR)
} else {
SELECTED_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER)
},
),
);
+13 -11
View File
@@ -53,12 +53,14 @@ use crate::plugins::absm::{
selection::{AbsmSelection, SelectedEntity},
socket::{Socket, SocketBuilder, SocketDirection},
state_viewer::context::{CanvasContextMenu, ConnectionContextMenu, NodeContextMenu},
NORMAL_BACKGROUND, NORMAL_ROOT_COLOR, SELECTED_BACKGROUND, SELECTED_ROOT_COLOR,
AbsmEditor,
};
use crate::{
scene::{commands::ChangeSelectionCommand, Selection},
send_sync_message,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::cmp::Ordering;
mod context;
@@ -533,15 +535,15 @@ impl StateViewer {
pose_definition,
ui,
))
.with_normal_color(if pose_definition == parent_state_ref.root {
NORMAL_ROOT_COLOR
.with_normal_brush(if pose_definition == parent_state_ref.root {
ui.style.property(AbsmEditor::NORMAL_ROOT_COLOR)
} else {
NORMAL_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER_PRIMARY)
})
.with_selected_color(if pose_definition == parent_state_ref.root {
SELECTED_ROOT_COLOR
.with_selected_brush(if pose_definition == parent_state_ref.root {
ui.style.property(AbsmEditor::SELECTED_ROOT_COLOR)
} else {
SELECTED_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER)
})
.with_editable(editable)
.with_model_handle(pose_definition)
@@ -642,9 +644,9 @@ impl StateViewer {
view,
MessageDirection::ToWidget,
if model_handle == parent_state_ref.root {
NORMAL_ROOT_COLOR
ui.style.property(AbsmEditor::NORMAL_ROOT_COLOR)
} else {
NORMAL_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER_PRIMARY)
},
),
);
@@ -654,9 +656,9 @@ impl StateViewer {
view,
MessageDirection::ToWidget,
if model_handle == parent_state_ref.root {
SELECTED_ROOT_COLOR
ui.style.property(AbsmEditor::SELECTED_ROOT_COLOR)
} else {
SELECTED_BACKGROUND
ui.style.property(Style::BRUSH_LIGHTER)
},
),
);
+2 -2
View File
@@ -46,7 +46,6 @@ use crate::plugins::absm::{
};
use crate::{
command::{Command, CommandGroup},
gui::make_dropdown_list_option,
load_image,
message::MessageSender,
scene::{
@@ -58,6 +57,7 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_dropdown_list_option;
pub struct Toolbar {
pub panel: Handle<UiNode>,
@@ -157,7 +157,7 @@ impl Toolbar {
.with_width(18.0)
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHT)),
.with_background(ctx.style.property(Style::BRUSH_BRIGHT)),
)
.with_opt_texture(load_image!("../../../resources/filter.png"))
.build(ctx),
+10 -16
View File
@@ -44,16 +44,10 @@ use crate::plugins::absm::{
selectable::{Selectable, SelectableMessage},
};
use crate::utils::fetch_node_center;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::ops::{Deref, DerefMut};
const PICKED_COLOR: Color = Color::opaque(100, 100, 100);
const NORMAL_COLOR: Color = Color::opaque(80, 80, 80);
const SELECTED_COLOR: Color = Color::opaque(120, 120, 120);
const PICKED_BRUSH: Brush = Brush::Solid(PICKED_COLOR);
const NORMAL_BRUSH: Brush = Brush::Solid(NORMAL_COLOR);
const SELECTED_BRUSH: Brush = Brush::Solid(SELECTED_COLOR);
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TransitionMessage {
Activate,
@@ -79,9 +73,9 @@ impl TransitionView {
self.handle(),
MessageDirection::ToWidget,
if self.selectable.selected {
SELECTED_BRUSH.clone()
ui.style.property(Style::BRUSH_BRIGHT)
} else {
NORMAL_BRUSH.clone()
ui.style.property(Style::BRUSH_LIGHTER)
},
));
}
@@ -117,16 +111,16 @@ uuid_provider!(TransitionView = "01798aee-8fe5-4480-a69d-8e5b95c3cc96");
impl Control for TransitionView {
fn draw(&self, drawing_context: &mut DrawingContext) {
let color = if let Brush::Solid(color) = self.foreground() {
color
let brush = if let Brush::Solid(color) = self.foreground() {
Brush::Solid(color + Color::from(Hsv::new(180.0, 100.0, 50.0 * self.activity_factor)))
} else {
NORMAL_COLOR
drawing_context.style.get_or_default(Style::BRUSH_LIGHTER)
};
draw_transition(
drawing_context,
self.clip_bounds(),
Brush::Solid(color + Color::from(Hsv::new(180.0, 100.0, 50.0 * self.activity_factor))),
brush,
self.segment.source_pos,
self.segment.dest_pos,
);
@@ -144,7 +138,7 @@ impl Control for TransitionView {
ui.send_message(WidgetMessage::foreground(
self.handle(),
MessageDirection::ToWidget,
PICKED_BRUSH.clone(),
ui.style.property(Style::BRUSH_LIGHTEST),
));
}
WidgetMessage::MouseLeave => {
@@ -198,7 +192,7 @@ impl TransitionBuilder {
let transition = TransitionView {
widget: self
.widget_builder
.with_foreground(NORMAL_BRUSH.clone())
.with_foreground(ctx.style.property(Style::BRUSH_LIGHTEST))
.with_clip_to_bounds(false)
.with_need_update(true)
.build(ctx),
+1 -1
View File
@@ -235,7 +235,7 @@ impl AnimationEditor {
curve_editor = CurveEditorBuilder::new(
WidgetBuilder::new()
.with_background(
ctx.style.get_or_default(Style::BRUSH_DARK),
ctx.style.property(Style::BRUSH_DARK),
)
.on_row(1),
)
+2 -2
View File
@@ -460,8 +460,8 @@ impl RulerBuilder {
.widget_builder
.with_preview_messages(true)
.with_context_menu(context_menu.menu.clone())
.with_background(ctx.style.get_or_default(Style::BRUSH_DARKER))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHTER))
.with_background(ctx.style.property(Style::BRUSH_DARKER))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHTER))
.build(ctx),
transform: Default::default(),
text: RefCell::new(FormattedTextBuilder::new(ctx.default_font()).build()),
+1 -1
View File
@@ -143,7 +143,7 @@ impl ThumbBuilder {
widget: self
.widget_builder
.with_hit_test_visibility(false)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHT))
.build(ctx),
transform: CurveTransformCell::default(),
position: 0.0,
+15 -17
View File
@@ -60,7 +60,6 @@ use crate::plugins::animation::{
};
use crate::{
command::{Command, CommandGroup},
gui::make_dropdown_list_option_universal,
load_image,
message::MessageSender,
scene::{
@@ -72,6 +71,7 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_dropdown_list_option_universal;
use std::path::Path;
enum ImportMode {
@@ -426,7 +426,7 @@ impl Toolbar {
let panel = BorderBuilder::new(
WidgetBuilder::new()
.on_row(0)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHT))
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new()
@@ -478,7 +478,7 @@ impl Toolbar {
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
ctx.style.property(Style::BRUSH_BRIGHT),
),
)
.with_opt_texture(load_image!("../../../resources/import.png"))
@@ -508,7 +508,7 @@ impl Toolbar {
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
ctx.style.property(Style::BRUSH_BRIGHT),
),
)
.with_opt_texture(load_image!(
@@ -539,7 +539,7 @@ impl Toolbar {
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
ctx.style.property(Style::BRUSH_BRIGHT),
),
)
.with_opt_texture(load_image!("../../../resources/rename.png"))
@@ -594,7 +594,7 @@ impl Toolbar {
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
ctx.style.property(Style::BRUSH_BRIGHT),
),
)
.with_opt_texture(load_image!("../../../resources/copy.png"))
@@ -649,9 +649,7 @@ impl Toolbar {
.with_width(18.0)
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
),
.with_background(ctx.style.property(Style::BRUSH_BRIGHT)),
)
.with_opt_texture(load_image!("../../../resources/speed.png"))
.build(ctx),
@@ -677,9 +675,7 @@ impl Toolbar {
.with_width(18.0)
.with_height(18.0)
.with_margin(Thickness::uniform(1.0))
.with_background(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
),
.with_background(ctx.style.property(Style::BRUSH_BRIGHT)),
)
.with_opt_texture(load_image!("../../../resources/time.png"))
.build(ctx),
@@ -763,7 +759,7 @@ impl Toolbar {
VectorImageBuilder::new(
WidgetBuilder::new()
.with_foreground(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
ctx.style.property(Style::BRUSH_BRIGHT),
)
.with_tooltip(make_simple_tooltip(ctx, "Play/Pause")),
)
@@ -795,9 +791,11 @@ impl Toolbar {
.with_tooltip(make_simple_tooltip(ctx, "Stop Playback")),
)
.with_content(
VectorImageBuilder::new(WidgetBuilder::new().with_foreground(
ctx.style.get_or_default(Style::BRUSH_BRIGHT),
))
VectorImageBuilder::new(
WidgetBuilder::new().with_foreground(
ctx.style.property(Style::BRUSH_BRIGHT),
),
)
.with_primitives(vec![Primitive::RectangleFilled {
rect: Rect::new(0.0, 0.0, 16.0, 16.0),
}])
@@ -811,7 +809,7 @@ impl Toolbar {
.build(ctx),
),
)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx);
let node_selector = NodeSelectorWindowBuilder::new(
+12 -10
View File
@@ -76,7 +76,6 @@ use crate::{
},
resource::texture::TextureBytes,
},
gui::make_image_button_with_tooltip,
load_image,
menu::create_menu_item,
message::MessageSender,
@@ -94,6 +93,7 @@ use crate::{
use fyrox::generic_animation::track::TrackBinding;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_image_button_with_tooltip;
use fyrox::renderer::framework::DrawParameters;
use fyrox::scene::mesh::buffer::{TriangleBuffer, VertexBuffer};
use fyrox::scene::sound::Samples;
@@ -372,9 +372,9 @@ impl Control for TrackView {
self.name_text,
MessageDirection::ToWidget,
if result.is_ok() {
ui.style.get_or_default(Style::BRUSH_TEXT)
ui.style.property(Style::BRUSH_TEXT)
} else {
Brush::Solid(Color::RED)
ui.style.property(Style::BRUSH_ERROR)
},
));
@@ -550,7 +550,7 @@ impl Toolbar {
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
.with_background(ctx.style.property(Style::BRUSH_BRIGHT))
.with_width(16.0)
.with_height(16.0),
)
@@ -570,7 +570,7 @@ impl Toolbar {
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
.with_background(ctx.style.property(Style::BRUSH_BRIGHT))
.with_width(16.0)
.with_height(16.0),
)
@@ -1445,13 +1445,15 @@ impl TrackList {
BorderBuilder::new(
WidgetBuilder::new()
.on_column(0)
.with_foreground(Brush::Solid(
Color::TRANSPARENT,
))
.with_background(Brush::Solid(colors[i])),
.with_foreground(
Brush::Solid(Color::TRANSPARENT).into(),
)
.with_background(
Brush::Solid(colors[i]).into(),
),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(2.0)
.with_corner_radius(2.0f32.into())
.build(ctx),
)
.with_child(
+5 -4
View File
@@ -23,13 +23,12 @@ use crate::{
fyrox::{
asset::{untyped::ResourceKind, Resource},
core::{
color::Color, futures::executor::block_on, math::curve::Curve, pool::Handle,
type_traits::prelude::*, visitor::prelude::*,
futures::executor::block_on, math::curve::Curve, pool::Handle, type_traits::prelude::*,
visitor::prelude::*,
},
engine::Engine,
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
curve::{CurveEditorBuilder, CurveEditorMessage},
file_browser::{FileBrowserMode, FileSelectorMessage},
@@ -51,6 +50,8 @@ use crate::{
Editor, MessageBoxButtons, MessageBoxMessage, MSG_SYNC_FLAG,
};
use fyrox::core::some_or_return;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::{fmt::Debug, path::PathBuf};
#[derive(Debug, ComponentProvider)]
@@ -232,7 +233,7 @@ impl CurveEditorWindow {
WidgetBuilder::new()
.on_row(1)
.on_column(0)
.with_background(Brush::Solid(Color::opaque(20, 20, 20)))
.with_background(ctx.style.property(Style::BRUSH_DARKEST))
.with_child({
curve_editor = CurveEditorBuilder::new(
WidgetBuilder::new().with_enabled(false),
@@ -39,7 +39,8 @@ use crate::fyrox::{
},
};
use crate::plugins::inspector::EditorEnvironment;
use crate::{gui::make_dropdown_list_option_universal, Message};
use crate::Message;
use fyrox::gui::utils::make_dropdown_list_option_universal;
use std::{
any::TypeId,
fmt::{Debug, Formatter},
@@ -172,9 +172,9 @@ impl Control for HandlePropertyEditor {
));
let color = if self.value.is_none() {
Brush::Solid(Color::ORANGE)
ui.style.property(Style::BRUSH_WARNING)
} else {
ui.style.get_or_default(Style::BRUSH_FOREGROUND)
ui.style.property(Style::BRUSH_FOREGROUND)
};
ui.send_message(WidgetMessage::foreground(
self.text,
@@ -191,7 +191,7 @@ impl Control for HandlePropertyEditor {
ui.send_message(WidgetMessage::foreground(
self.text,
MessageDirection::ToWidget,
Brush::Solid(Color::RED),
ui.style.property(Style::BRUSH_ERROR),
));
};
}
@@ -292,7 +292,7 @@ fn make_icon(data: &[u8], color: Color, ctx: &mut BuildContext) -> Handle<UiNode
.with_width(16.0)
.with_height(16.0)
.with_margin(Thickness::uniform(1.0))
.with_background(Brush::Solid(color)),
.with_background(Brush::Solid(color).into()),
)
.with_opt_texture(load_image_internal(data))
.build(ctx)
@@ -50,11 +50,11 @@ use crate::fyrox::{
};
use crate::plugins::inspector::EditorEnvironment;
use crate::{
gui::make_dropdown_list_option,
send_sync_message,
settings::{general::ScriptEditor, SettingsData},
DropdownListBuilder, MSG_SYNC_FLAG,
};
use fyrox::gui::utils::make_dropdown_list_option;
use std::{
any::TypeId,
cell::Cell,
@@ -172,6 +172,7 @@ impl Control for ScriptPropertyEditor {
}
ScriptEditor::XCode => Some("xcode"),
ScriptEditor::Emacs => Some("emacs"),
ScriptEditor::Zed => Some("zed"),
ScriptEditor::SystemDefault => None,
};
@@ -21,12 +21,11 @@
use crate::fyrox::graph::BaseSceneGraph;
use crate::fyrox::{
core::{
algebra::Vector2, color::Color, parking_lot::Mutex, pool::Handle, reflect::prelude::*,
algebra::Vector2, parking_lot::Mutex, pool::Handle, reflect::prelude::*,
type_traits::prelude::*, uuid_provider, visitor::prelude::*,
},
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
check_box::{CheckBoxBuilder, CheckBoxMessage},
draw::DrawingContext,
@@ -45,6 +44,8 @@ use crate::fyrox::{
scene::animation::spritesheet::prelude::*,
};
use crate::plugins::inspector::editors::spritesheet::SpriteSheetFramesPropertyEditorMessage;
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::{
ops::{Deref, DerefMut},
sync::{mpsc::Sender, Arc},
@@ -218,7 +219,7 @@ fn make_grid(
let grid = GridBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.with_foreground(Brush::Solid(Color::opaque(127, 127, 127)))
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHT))
.with_children(cells.clone()),
)
.add_columns((0..container.size().x).map(|_| Column::stretch()).collect())
+5 -4
View File
@@ -24,7 +24,6 @@ use crate::{
fyrox::{
asset::manager::ResourceManager,
core::{
color::Color,
log::{Log, MessageKind},
pool::{ErasedHandle, Handle},
reflect::prelude::*,
@@ -47,7 +46,6 @@ use crate::{
},
scene::SceneContainer,
},
gui::make_image_button_with_tooltip,
load_image,
message::MessageSender,
plugin::EditorPlugin,
@@ -55,8 +53,11 @@ use crate::{
send_sync_message,
ui_scene::UiScene,
utils::window_content,
Brush, Editor, Message, WidgetMessage, WrapMode, MSG_SYNC_FLAG,
Editor, Message, WidgetMessage, WrapMode, MSG_SYNC_FLAG,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_image_button_with_tooltip;
use std::{any::Any, sync::Arc};
pub mod editors;
@@ -179,7 +180,7 @@ impl InspectorPlugin {
WidgetBuilder::new()
.with_visibility(false)
.with_margin(Thickness::left(4.0))
.with_foreground(Brush::Solid(Color::RED))
.with_foreground(ctx.style.property(Style::BRUSH_ERROR))
.on_row(0),
)
.with_wrap(WrapMode::Word)
+8 -5
View File
@@ -25,14 +25,13 @@ use crate::{
fyrox::{
asset::{manager::ResourceManager, untyped::ResourceKind, untyped::UntypedResource},
core::{
color::Color, futures::executor::block_on, pool::Handle, replace_slashes,
some_or_return, visitor::Visitor,
futures::executor::block_on, pool::Handle, replace_slashes, some_or_return,
visitor::Visitor,
},
engine::SerializationContext,
graph::{BaseSceneGraph, SceneGraph},
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
decorator::DecoratorBuilder,
file_browser::{FileSelectorBuilder, FileSelectorMessage},
@@ -55,6 +54,8 @@ use crate::{
plugin::EditorPlugin,
Editor, Message,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use std::{
path::{Path, PathBuf},
sync::Arc,
@@ -264,7 +265,7 @@ impl PathFixer {
ui.send_message(WidgetMessage::foreground(
item_text,
MessageDirection::ToWidget,
Brush::Solid(Color::GREEN),
ui.style.property(Style::BRUSH_OK),
));
ui.send_message(TextMessage::text(
item_text,
@@ -338,7 +339,9 @@ impl PathFixer {
TextBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.with_foreground(Brush::Solid(Color::RED)),
.with_foreground(
ctx.style.property(Style::BRUSH_ERROR),
),
)
.with_vertical_text_alignment(
VerticalAlignment::Center,
+6 -3
View File
@@ -20,6 +20,8 @@
//! Settings window plugin.
use crate::settings::build::BuildSettings;
use crate::settings::general::EditorStyle;
use crate::{
fyrox::{
core::{log::Log, pool::Handle, some_or_return},
@@ -51,7 +53,6 @@ use crate::{
message::MessageSender,
plugin::EditorPlugin,
settings::{
build::{BuildCommand, BuildProfile, BuildSettings, EnvironmentVariable},
camera::CameraSettings,
debugging::DebuggingSettings,
general::{GeneralSettings, ScriptEditor},
@@ -66,6 +67,7 @@ use crate::{
},
Editor, MSG_SYNC_FLAG,
};
use fyrox_build_tools::{BuildProfile, CommandDescriptor, EnvironmentVariable};
use std::sync::Arc;
fn make_property_editors_container(
@@ -78,6 +80,7 @@ fn make_property_editors_container(
container.insert(InspectablePropertyEditorDefinition::<SelectionSettings>::new());
container.insert(EnumPropertyEditorDefinition::<ShadowMapPrecision>::new());
container.insert(EnumPropertyEditorDefinition::<ScriptEditor>::new());
container.insert(EnumPropertyEditorDefinition::<EditorStyle>::new());
container.insert(InspectablePropertyEditorDefinition::<DebuggingSettings>::new());
container.insert(InspectablePropertyEditorDefinition::<CsmSettings>::new());
container.insert(InspectablePropertyEditorDefinition::<QualitySettings>::new());
@@ -97,8 +100,8 @@ fn make_property_editors_container(
container.insert(InspectablePropertyEditorDefinition::<EnvironmentVariable>::new());
container.insert(VecCollectionPropertyEditorDefinition::<BuildProfile>::new());
container.insert(InspectablePropertyEditorDefinition::<BuildProfile>::new());
container.insert(VecCollectionPropertyEditorDefinition::<BuildCommand>::new());
container.insert(InspectablePropertyEditorDefinition::<BuildCommand>::new());
container.insert(VecCollectionPropertyEditorDefinition::<CommandDescriptor>::new());
container.insert(InspectablePropertyEditorDefinition::<CommandDescriptor>::new());
container.insert(HotKeyPropertyEditorDefinition);
Arc::new(container)
}
+1 -1
View File
@@ -587,7 +587,7 @@ impl Control for BrushTileView {
drawing_context.push_rect(&self.bounding_rect(), 1.0);
drawing_context.commit(
self.clip_bounds(),
(*self.foreground).clone(),
self.foreground.property.clone(),
CommandTexture::None,
None,
);
+9 -11
View File
@@ -23,13 +23,11 @@ use crate::{
command::{Command, CommandGroup, SetPropertyCommand},
fyrox::{
asset::untyped::UntypedResource,
core::color::Color,
core::{pool::Handle, TypeUuidProvider, Uuid},
fxhash::FxHashSet,
graph::{BaseSceneGraph, SceneGraph, SceneGraphNode},
gui::{
border::BorderBuilder,
brush::Brush,
button::{Button, ButtonBuilder, ButtonMessage},
decorator::{DecoratorBuilder, DecoratorMessage},
dropdown_list::{DropdownListBuilder, DropdownListMessage},
@@ -52,7 +50,6 @@ use crate::{
},
},
},
gui::make_dropdown_list_option,
load_image,
message::MessageSender,
plugins::tilemap::{
@@ -71,6 +68,7 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_dropdown_list_option;
pub struct TileMapPanel {
pub window: Handle<UiNode>,
@@ -140,22 +138,22 @@ fn make_drawing_mode_button(
.with_back(
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKER)),
WidgetBuilder::new().with_foreground(ctx.style.property(Style::BRUSH_DARKER)),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(4.0)
.with_stroke_thickness(Thickness::uniform(1.0)),
.with_corner_radius(4.0f32.into())
.with_stroke_thickness(Thickness::uniform(1.0).into()),
)
.with_selected_brush(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_selected_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.property(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.property(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.property(Style::BRUSH_LIGHTEST))
.build(ctx),
)
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_background(Brush::Solid(Color::opaque(180, 180, 180)))
.with_background(ctx.style.property(Style::BRUSH_BRIGHTEST))
.with_margin(Thickness::uniform(2.0))
.with_width(width)
.with_height(height),
+1 -1
View File
@@ -546,7 +546,7 @@ impl TileSetTileViewBuilder {
let decorator =
DecoratorBuilder::new(BorderBuilder::new(WidgetBuilder::new().with_child(image)))
.with_selected_brush(Brush::Solid(Color::RED))
.with_selected_brush(Brush::Solid(Color::RED).into())
.build(ctx);
ctx.add_node(UiNode::new(TileSetTileView {
+1 -1
View File
@@ -473,7 +473,7 @@ impl PropertySelectorBuilder {
.with_child(
BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_DARK))
.with_background(ctx.style.property(Style::BRUSH_DARK))
.on_row(1)
.on_column(0)
.with_child(scroll_viewer),
+1 -1
View File
@@ -359,7 +359,7 @@ impl NodeSelectorBuilder {
.with_child(
BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_DARK))
.with_background(ctx.style.property(Style::BRUSH_DARK))
.on_row(1)
.on_column(0)
.with_child({
+23 -19
View File
@@ -54,10 +54,6 @@ use crate::{
resource::texture::TextureResource,
scene::camera::Projection,
},
gui::{
make_dropdown_list_option, make_dropdown_list_option_universal,
make_dropdown_list_option_with_height, make_image_button_with_tooltip,
},
load_image,
message::MessageSender,
scene::container::EditorSceneEntry,
@@ -70,6 +66,10 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::{
make_dropdown_list_option, make_dropdown_list_option_universal,
make_dropdown_list_option_with_height, make_image_button_with_tooltip,
};
use std::{
ops::Deref,
sync::mpsc::{self, Receiver},
@@ -217,7 +217,7 @@ impl GridSnappingMenu {
ui.send_message(DecoratorMessage::selected_brush(
*button.decorator,
MessageDirection::ToWidget,
ui.style.get_or_default(Style::BRUSH_BRIGHT_BLUE),
ui.style.property(Style::BRUSH_BRIGHT_BLUE),
));
ui.send_message(DecoratorMessage::select(
@@ -418,9 +418,9 @@ impl SceneViewer {
.with_width(16.0)
.with_height(16.0)
.with_margin(Thickness::uniform(4.0))
.with_background(Brush::Solid(Color::opaque(
0, 200, 0,
))),
.with_background(
Brush::Solid(Color::opaque(0, 200, 0)).into(),
),
)
.with_opt_texture(load_image!("../../resources/play.png"))
.build(ctx),
@@ -441,9 +441,9 @@ impl SceneViewer {
.with_width(16.0)
.with_height(16.0)
.with_margin(Thickness::uniform(4.0))
.with_background(Brush::Solid(Color::opaque(
200, 0, 0,
))),
.with_background(
Brush::Solid(Color::opaque(200, 0, 0)).into(),
),
)
.with_opt_texture(load_image!("../../resources/stop.png"))
.build(ctx),
@@ -466,7 +466,7 @@ impl SceneViewer {
let no_scene_reminder = TextBuilder::new(
WidgetBuilder::new()
.with_hit_test_visibility(false)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKEST)),
.with_foreground(ctx.style.property(Style::BRUSH_DARKEST)),
)
.with_text("No scene loaded. Create a new scene (File -> New Scene) or load existing (File -> Load Scene)")
.with_vertical_text_alignment(VerticalAlignment::Center)
@@ -520,14 +520,18 @@ impl SceneViewer {
selection_frame = BorderBuilder::new(
WidgetBuilder::new()
.with_visibility(false)
.with_background(Brush::Solid(
Color::from_rgba(255, 255, 255, 40),
))
.with_foreground(Brush::Solid(Color::opaque(
0, 255, 0,
))),
.with_background(
Brush::Solid(Color::from_rgba(
255, 255, 255, 40,
))
.into(),
)
.with_foreground(
Brush::Solid(Color::opaque(0, 255, 0))
.into(),
),
)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx);
selection_frame
}))
+5 -149
View File
@@ -19,64 +19,8 @@
// SOFTWARE.
use crate::fyrox::core::reflect::prelude::*;
use fyrox::core::type_traits::prelude::*;
use fyrox_build_tools::BuildProfile;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "55e7651e-8840-4c81-aa93-3f01348855e6")]
pub struct EnvironmentVariable {
pub name: String,
pub value: String,
}
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "67b93136-17fe-4776-b5f0-f4a9ef3d8972")]
pub struct BuildCommand {
pub command: String,
pub args: Vec<String>,
pub environment_variables: Vec<EnvironmentVariable>,
}
impl Display for BuildCommand {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for var in self.environment_variables.iter() {
write!(f, "{}=\"{}\" ", var.name, var.value)?;
}
write!(f, "{}", self.command)?;
for arg in self.args.iter() {
write!(f, " {arg}")?;
}
Ok(())
}
}
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "1a9443df-bf75-42fb-93d3-860a0249168a")]
pub struct BuildProfile {
pub name: String,
#[reflect(description = "A set of commands that will be used to build your game.")]
pub build_commands: Vec<BuildCommand>,
#[reflect(description = "A set of commands that will be used to run your game. \
This set of commands will be executed right after build commands (if the \
build was successful)")]
pub run_command: BuildCommand,
}
impl BuildProfile {
fn add_arg(&mut self, arg: &str) {
for command in self
.build_commands
.iter_mut()
.chain([&mut self.run_command])
{
command.args.push(arg.to_string());
}
}
}
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Reflect)]
pub struct BuildSettings {
@@ -87,98 +31,10 @@ pub struct BuildSettings {
impl Default for BuildSettings {
fn default() -> Self {
let debug = BuildProfile {
name: "Debug".to_string(),
build_commands: vec![BuildCommand {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"executor".to_string(),
],
environment_variables: vec![],
}],
run_command: BuildCommand {
command: "cargo".to_string(),
args: vec![
"run".to_string(),
"--package".to_string(),
"executor".to_string(),
],
environment_variables: vec![],
},
};
let mut release = debug.clone();
release.name = "Release".to_string();
release.add_arg("--release");
let debug_hot_reloading = BuildProfile {
name: "Debug (HR)".to_string(),
build_commands: vec![
// Build the game plugin DLL first.
BuildCommand {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"game_dylib".to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib-engine".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
},
// Build the executor.
BuildCommand {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"executor".to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
},
],
run_command:
// Run only executor, it will load the game plugin DLL.
BuildCommand {
command: "cargo".to_string(),
args: vec![
"run".to_string(),
"--package".to_string(),
"executor".to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
},
};
let mut release_hot_reloading = release.clone();
release_hot_reloading.name = "Release (HR)".to_string();
release_hot_reloading.add_arg("--release");
let debug = BuildProfile::debug();
let release = BuildProfile::release();
let debug_hot_reloading = BuildProfile::debug_hot_reloading();
let release_hot_reloading = BuildProfile::release_hot_reloading();
Self {
selected_profile: 0,
profiles: vec![debug, debug_hot_reloading, release, release_hot_reloading],
+33 -1
View File
@@ -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 {
@@ -104,6 +134,7 @@ pub enum ScriptEditor {
VSCode,
Emacs,
XCode,
Zed,
}
uuid_provider!(ScriptEditor = "d0c942e8-24e4-40f2-ad2e-1b9f189d3ca2");
@@ -117,6 +148,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,
}
}
}
+9 -5
View File
@@ -18,13 +18,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::settings::build::BuildSettings;
use crate::{
fyrox::core::{log::Log, reflect::prelude::*},
settings::{
build::BuildSettings, camera::CameraSettings, debugging::DebuggingSettings,
general::GeneralSettings, graphics::GraphicsSettings, keys::KeyBindings,
model::ModelSettings, move_mode::MoveInteractionModeSettings, navmesh::NavmeshSettings,
recent::RecentFiles, rotate_mode::RotateInteractionModeSettings, scene::SceneSettings,
camera::CameraSettings, debugging::DebuggingSettings, general::GeneralSettings,
graphics::GraphicsSettings, keys::KeyBindings, model::ModelSettings,
move_mode::MoveInteractionModeSettings, navmesh::NavmeshSettings, recent::RecentFiles,
rotate_mode::RotateInteractionModeSettings, scene::SceneSettings,
selection::SelectionSettings, windows::WindowsSettings,
},
};
@@ -122,10 +123,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
}
}
}
+1 -1
View File
@@ -55,7 +55,7 @@ pub struct UiSceneWorldViewerDataProvider<'a> {
pub resource_manager: &'a ResourceManager,
}
impl<'a> WorldViewerDataProvider for UiSceneWorldViewerDataProvider<'a> {
impl WorldViewerDataProvider for UiSceneWorldViewerDataProvider<'_> {
fn root_node(&self) -> ErasedHandle {
self.ui.root().into()
}
+4 -4
View File
@@ -43,7 +43,7 @@ use crate::fyrox::{
};
use crate::{load_image, message::MessageSender, utils::make_node_name, Message};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::style::{Style, StyledProperty};
use std::{
fmt::{Debug, Formatter},
ops::{Deref, DerefMut},
@@ -270,7 +270,7 @@ pub struct SceneItemBuilder {
entity_handle: ErasedHandle,
name: String,
icon: Option<UntypedResource>,
text_brush: Option<Brush>,
text_brush: Option<StyledProperty<Brush>>,
}
impl SceneItemBuilder {
@@ -299,7 +299,7 @@ impl SceneItemBuilder {
self
}
pub fn with_text_brush(mut self, brush: Brush) -> Self {
pub fn with_text_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.text_brush = Some(brush);
self
}
@@ -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.property(Style::BRUSH_TEXT)),
)
.with_margin(Thickness::left(1.0))
.on_column(1)
+1 -1
View File
@@ -64,7 +64,7 @@ pub struct EditorSceneWrapper<'a> {
pub instantiation_scale: Vector3<f32>,
}
impl<'a> WorldViewerDataProvider for EditorSceneWrapper<'a> {
impl WorldViewerDataProvider for EditorSceneWrapper<'_> {
fn root_node(&self) -> ErasedHandle {
self.game_scene.scene_content_root.into()
}
+14 -17
View File
@@ -22,14 +22,10 @@ use crate::{
asset::item::AssetItem,
fyrox::{
asset::untyped::UntypedResource,
core::{
color::Color,
pool::{ErasedHandle, Handle},
},
core::pool::{ErasedHandle, Handle},
graph::{BaseSceneGraph, SceneGraph},
gui::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
check_box::{CheckBoxBuilder, CheckBoxMessage},
decorator::{Decorator, DecoratorBuilder, DecoratorMessage},
@@ -50,7 +46,6 @@ use crate::{
VerticalAlignment,
},
},
gui::make_image_button_with_tooltip,
load_image,
message::MessageSender,
send_sync_message,
@@ -60,6 +55,7 @@ use crate::{
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::make_image_button_with_tooltip;
use rust_fuzzy_search::fuzzy_compare;
use std::{
borrow::Cow,
@@ -156,9 +152,9 @@ fn make_graph_node_item(
.with_expanded(is_expanded),
)
.with_text_brush(if is_instance {
Brush::Solid(Color::opaque(160, 160, 200))
ctx.style.property(WorldViewer::INSTANCE_BRUSH)
} else {
ctx.style.get_or_default(Style::BRUSH_FOREGROUND)
ctx.style.property(Style::BRUSH_TEXT)
})
.with_name(name.deref().to_owned())
.with_entity_handle(handle)
@@ -178,11 +174,11 @@ fn colorize(handle: Handle<UiNode>, ui: &UserInterface, index: &mut usize) {
if let Some(decorator) = node.cast::<Decorator>() {
if node.parent().is_some() {
let new_brush = Brush::Solid(if *index % 2 == 0 {
Color::opaque(50, 50, 50)
let new_brush = if *index % 2 == 0 {
ui.style.property(Style::BRUSH_PRIMARY)
} else {
Color::opaque(60, 60, 60)
});
ui.style.property(Style::BRUSH_LIGHTER_PRIMARY)
};
if *decorator.normal_brush != new_brush {
ui.send_message(DecoratorMessage::normal_brush(
@@ -215,6 +211,8 @@ fn fetch_expanded_state(
}
impl WorldViewer {
pub const INSTANCE_BRUSH: &'static str = "WorldViewer.InstanceBrush";
pub fn new(ctx: &mut BuildContext, sender: MessageSender, settings: &Settings) -> Self {
let tree_root;
let node_path;
@@ -372,11 +370,10 @@ impl WorldViewer {
let element = ButtonBuilder::new(WidgetBuilder::new().with_height(16.0))
.with_back(
DecoratorBuilder::new(BorderBuilder::new(
WidgetBuilder::new()
.with_foreground(ctx.style.get_or_default(Style::BRUSH_PRIMARY)),
WidgetBuilder::new().with_foreground(ctx.style.property(Style::BRUSH_PRIMARY)),
))
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_PRIMARY))
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.property(Style::BRUSH_PRIMARY))
.with_hover_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.build(ctx),
)
.with_content(
@@ -387,7 +384,7 @@ impl WorldViewer {
} else {
format!("{name} >")
})
.with_font_size(11.0)
.with_font_size(11.0.into())
.build(ctx),
)
.build(ctx);
@@ -227,7 +227,7 @@ pub struct PointsMut<'a, T: EntityId> {
blend_space: &'a mut BlendSpace<T>,
}
impl<'a, T: EntityId> Deref for PointsMut<'a, T> {
impl<T: EntityId> Deref for PointsMut<'_, T> {
type Target = Vec<BlendSpacePoint<T>>;
fn deref(&self) -> &Self::Target {
@@ -235,13 +235,13 @@ impl<'a, T: EntityId> Deref for PointsMut<'a, T> {
}
}
impl<'a, T: EntityId> DerefMut for PointsMut<'a, T> {
impl<T: EntityId> DerefMut for PointsMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.blend_space.points
}
}
impl<'a, T: EntityId> Drop for PointsMut<'a, T> {
impl<T: EntityId> Drop for PointsMut<'_, T> {
fn drop(&mut self) {
self.blend_space.triangulate();
}
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "fyrox-build-tools"
version = "0.1.0"
edition = "2021"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.28.1" }
serde = { version = "1.0.215", features = ["derive"] }
+254
View File
@@ -0,0 +1,254 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use fyrox_core::{reflect::prelude::*, type_traits::prelude::*};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::fmt::{Display, Formatter};
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "55e7651e-8840-4c81-aa93-3f01348855e6")]
pub struct EnvironmentVariable {
pub name: String,
pub value: String,
}
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "67b93136-17fe-4776-b5f0-f4a9ef3d8972")]
pub struct CommandDescriptor {
pub command: String,
pub args: Vec<String>,
pub environment_variables: Vec<EnvironmentVariable>,
}
impl CommandDescriptor {
pub fn make_command(&self) -> std::process::Command {
let mut command = std::process::Command::new(&self.command);
command.args(self.args.iter()).envs(
self.environment_variables
.iter()
.map(|v| (&v.name, &v.value)),
);
command
}
}
impl Display for CommandDescriptor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for var in self.environment_variables.iter() {
write!(f, "{}=\"{}\" ", var.name, var.value)?;
}
write!(f, "{}", self.command)?;
for arg in self.args.iter() {
write!(f, " {arg}")?;
}
Ok(())
}
}
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Default, Reflect, TypeUuidProvider)]
#[type_uuid(id = "1a9443df-bf75-42fb-93d3-860a0249168a")]
pub struct BuildProfile {
pub name: String,
#[reflect(description = "A set of commands that will be used to build your game.")]
pub build_commands: Vec<CommandDescriptor>,
#[reflect(description = "A set of commands that will be used to run your game. \
This set of commands will be executed right after build commands (if the \
build was successful)")]
pub run_command: CommandDescriptor,
}
impl BuildProfile {
fn add_arg(&mut self, arg: &str) {
for command in self
.build_commands
.iter_mut()
.chain([&mut self.run_command])
{
command.args.push(arg.to_string());
}
}
pub fn build_and_run_queue(&self) -> VecDeque<CommandDescriptor> {
let mut queue = self.build_commands.iter().cloned().collect::<VecDeque<_>>();
queue.push_back(self.run_command.clone());
queue
}
pub fn debug() -> Self {
BuildProfile {
name: "Debug".to_string(),
build_commands: vec![CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"executor".to_string(),
],
environment_variables: vec![],
}],
run_command: CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"run".to_string(),
"--package".to_string(),
"executor".to_string(),
],
environment_variables: vec![],
},
}
}
pub fn release() -> Self {
let mut release = Self::debug();
release.name = "Release".to_string();
release.add_arg("--release");
release
}
pub fn debug_hot_reloading() -> Self {
BuildProfile {
name: "Debug (HR)".to_string(),
build_commands: vec![
Self::build_game(), // Build the executor.
CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"executor".to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
},
],
// Run only executor, it will load the game plugin DLL.
run_command: Self::run_hot_reload("executor"),
}
}
pub fn release_hot_reloading() -> Self {
let mut release_hot_reloading = Self::release();
release_hot_reloading.name = "Release (HR)".to_string();
release_hot_reloading.add_arg("--release");
release_hot_reloading
}
fn build_game() -> CommandDescriptor {
// Build the game plugin DLL first.
CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"game_dylib".to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib-engine".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
}
}
fn run_hot_reload(package_name: &str) -> CommandDescriptor {
CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"run".to_string(),
"--package".to_string(),
package_name.to_string(),
"--no-default-features".to_string(),
"--features".to_string(),
"dylib".to_string(),
"--profile".to_string(),
"dev-hot-reload".to_string(),
],
environment_variables: vec![EnvironmentVariable {
name: "RUSTFLAGS".to_string(),
value: "-C prefer-dynamic=yes".to_string(),
}],
}
}
pub fn debug_editor_hot_reloading() -> Self {
BuildProfile {
name: "Debug Editor (HR)".to_string(),
build_commands: vec![Self::build_game()],
run_command: Self::run_hot_reload("editor"),
}
}
pub fn release_editor_hot_reloading() -> Self {
let mut release_hot_reloading = Self::debug_editor_hot_reloading();
release_hot_reloading.name = "Release Editor (HR)".to_string();
release_hot_reloading.add_arg("--release");
release_hot_reloading
}
pub fn debug_editor() -> Self {
BuildProfile {
name: "Debug Editor".to_string(),
build_commands: vec![CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"build".to_string(),
"--package".to_string(),
"editor".to_string(),
],
environment_variables: vec![],
}],
run_command: CommandDescriptor {
command: "cargo".to_string(),
args: vec![
"run".to_string(),
"--package".to_string(),
"editor".to_string(),
],
environment_variables: vec![],
},
}
}
pub fn release_editor() -> Self {
let mut release = Self::debug_editor();
release.name = "Release Editor".to_string();
release.add_arg("--release");
release
}
//run --package editor --no-default-features --features dylib --profile dev-hot-reload
}
+1 -1
View File
@@ -49,7 +49,7 @@ pub struct Property<'a> {
pub field: &'a args::FieldArgs,
}
impl<'a> Property<'a> {
impl Property<'_> {
pub fn quote(&self) -> TokenStream2 {
let Property { ident, value, .. } = self;
+8 -8
View File
@@ -39,7 +39,7 @@ where
phantom: PhantomData<&'b ()>,
}
impl<'a, 'b, T> Debug for Ref<'a, 'b, T>
impl<T> Debug for Ref<'_, '_, T>
where
T: ?Sized + Debug,
{
@@ -48,7 +48,7 @@ where
}
}
impl<'a, 'b, T> Deref for Ref<'a, 'b, T>
impl<T> Deref for Ref<'_, '_, T>
where
T: ?Sized,
{
@@ -59,7 +59,7 @@ where
}
}
impl<'a, 'b, T> Drop for Ref<'a, 'b, T>
impl<T> Drop for Ref<'_, '_, T>
where
T: ?Sized,
{
@@ -77,7 +77,7 @@ where
phantom: PhantomData<&'b ()>,
}
impl<'a, 'b, T> Debug for RefMut<'a, 'b, T>
impl<T> Debug for RefMut<'_, '_, T>
where
T: ?Sized + Debug,
{
@@ -86,7 +86,7 @@ where
}
}
impl<'a, 'b, T> Deref for RefMut<'a, 'b, T>
impl<T> Deref for RefMut<'_, '_, T>
where
T: ?Sized,
{
@@ -97,7 +97,7 @@ where
}
}
impl<'a, 'b, T> DerefMut for RefMut<'a, 'b, T>
impl<T> DerefMut for RefMut<'_, '_, T>
where
T: ?Sized,
{
@@ -106,7 +106,7 @@ where
}
}
impl<'a, 'b, T> Drop for RefMut<'a, 'b, T>
impl<T> Drop for RefMut<'_, '_, T>
where
T: ?Sized,
{
@@ -186,7 +186,7 @@ impl<T> Display for MultiBorrowError<T> {
}
}
impl<'a, T, P> Drop for MultiBorrowContext<'a, T, P>
impl<T, P> Drop for MultiBorrowContext<'_, T, P>
where
T: Sized,
P: PayloadContainer<Element = T> + 'static,
+4 -4
View File
@@ -112,7 +112,7 @@ pub struct FieldInfo<'a, 'b> {
pub precision: Option<usize>,
}
impl<'a, 'b> FieldInfo<'a, 'b> {
impl FieldInfo<'_, '_> {
/// Tries to cast a value to a given type.
pub fn cast_value<T: 'static>(&self) -> Result<&T, CastError> {
match self.value.as_any().downcast_ref::<T>() {
@@ -126,7 +126,7 @@ impl<'a, 'b> FieldInfo<'a, 'b> {
}
}
impl<'a, 'b> fmt::Debug for FieldInfo<'a, 'b> {
impl fmt::Debug for FieldInfo<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PropertyInfo")
.field("owner_type_id", &self.owner_type_id)
@@ -143,7 +143,7 @@ impl<'a, 'b> fmt::Debug for FieldInfo<'a, 'b> {
}
}
impl<'a, 'b> PartialEq<Self> for FieldInfo<'a, 'b> {
impl PartialEq<Self> for FieldInfo<'_, '_> {
fn eq(&self, other: &Self) -> bool {
let value_ptr_a = self.value as *const _ as *const ();
let value_ptr_b = other.value as *const _ as *const ();
@@ -407,7 +407,7 @@ pub enum ReflectPathError<'a> {
NotAnArray,
}
impl<'a> Display for ReflectPathError<'a> {
impl Display for ReflectPathError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ReflectPathError::UnclosedBrackets { s } => {
+5 -5
View File
@@ -233,7 +233,7 @@ impl<'a, T: Pod> PodVecView<'a, T> {
}
}
impl<'a, T: Pod> Visit for PodVecView<'a, T> {
impl<T: Pod> Visit for PodVecView<'_, T> {
#[allow(clippy::uninit_vec)]
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
if visitor.reading {
@@ -538,7 +538,7 @@ impl_field_data!(Vector2<u64>, FieldKind::Vector2U64);
impl_field_data!(Vector3<u64>, FieldKind::Vector3U64);
impl_field_data!(Vector4<u64>, FieldKind::Vector4U64);
impl<'a, T> Visit for BinaryBlob<'a, T>
impl<T> Visit for BinaryBlob<'_, T>
where
T: Copy,
{
@@ -1162,7 +1162,7 @@ impl Default for VisitorNode {
#[must_use = "the guard must be used"]
pub struct RegionGuard<'a>(&'a mut Visitor);
impl<'a> Deref for RegionGuard<'a> {
impl Deref for RegionGuard<'_> {
type Target = Visitor;
fn deref(&self) -> &Self::Target {
@@ -1170,13 +1170,13 @@ impl<'a> Deref for RegionGuard<'a> {
}
}
impl<'a> DerefMut for RegionGuard<'a> {
impl DerefMut for RegionGuard<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl<'a> Drop for RegionGuard<'a> {
impl Drop for RegionGuard<'_> {
fn drop(&mut self) {
// If we acquired RegionGuard instance, then it is safe to assert that
// `leave_region` was successful.
-1
View File
@@ -104,7 +104,6 @@ where
/// Maps each handle in the slice to a handle of its origin, or sets it to [Handle::NONE] if there is no such node.
/// It should be used when you are sure that respective origin exists.
#[inline]
pub fn map_slice<T>(&self, handles: &mut [T]) -> &Self
where
+1 -1
View File
@@ -75,7 +75,7 @@ pub enum ResourceBinding<'a> {
},
}
impl<'a> ResourceBinding<'a> {
impl ResourceBinding<'_> {
pub fn texture(
texture: &Rc<RefCell<dyn GpuTexture>>,
shader_location: &UniformLocation,
+7 -3
View File
@@ -1106,10 +1106,14 @@ impl GraphicsServer for GlGraphicsServer {
fn invalidate_resource_bindings_cache(&self) {
let mut state = self.state.borrow_mut();
for unit in state.texture_units_storage.units.iter() {
for binding in unit.bindings.iter() {
unsafe { self.gl.bind_texture(binding.target, None) };
unsafe {
for (unit_index, unit) in state.texture_units_storage.units.iter().enumerate() {
self.gl.active_texture(glow::TEXTURE0 + unit_index as u32);
for binding in unit.bindings.iter() {
self.gl.bind_texture(binding.target, None)
}
}
self.gl.active_texture(glow::TEXTURE0);
}
state.texture_units_storage = Default::default();
+32
View File
@@ -29,6 +29,10 @@ pub mod task;
mod hotreload;
use crate::resource::texture::{
CompressionOptions, TextureImportOptions, TextureMinificationFilter, TextureResource,
TextureResourceExtension,
};
use crate::{
asset::{
event::ResourceEvent,
@@ -117,6 +121,7 @@ use std::{
},
time::Duration,
};
use winit::window::Icon;
use winit::{
dpi::{Position, Size},
event_loop::EventLoopWindowTarget,
@@ -182,6 +187,33 @@ pub struct InitializedGraphicsContext {
params: GraphicsContextParams,
}
impl InitializedGraphicsContext {
/// Tries to set a new icon for the window from the given data source. The data source must contain
/// some of the supported texture types data (png, bmp, jpg images). You can call this method
/// with [`include_bytes`] macro to pass file's data directly.
pub fn set_window_icon_from_memory(&mut self, data: &[u8]) {
if let Ok(texture) = TextureResource::load_from_memory(
ResourceKind::Embedded,
data,
TextureImportOptions::default()
.with_compression(CompressionOptions::NoCompression)
.with_minification_filter(TextureMinificationFilter::Linear),
) {
self.set_window_icon_from_texture(&texture);
}
}
/// Tries to set a new icon for the window using the given texture.
pub fn set_window_icon_from_texture(&mut self, texture: &TextureResource) {
let data = texture.data_ref();
if let TextureKind::Rectangle { width, height } = data.kind() {
if let Ok(img) = Icon::from_rgba(data.data().to_vec(), width, height) {
self.window.set_window_icon(Some(img));
}
}
}
}
/// Graphics context of the engine, it could be in two main states:
///
/// - [`GraphicsContext::Initialized`] - active graphics context, that is fully initialized and ready for use.
+1 -1
View File
@@ -121,7 +121,7 @@ pub struct RenderContext<'a> {
pub render_pass_name: &'a ImmutableString,
}
impl<'a> RenderContext<'a> {
impl RenderContext<'_> {
/// Calculates sorting index using of the given point by transforming it in the view space and
/// using Z coordinate. This index could be used for back-to-front sorting to prevent blending
/// issues.
+5 -4
View File
@@ -1760,13 +1760,13 @@ pub struct TextureDataRefMut<'a> {
texture: &'a mut Texture,
}
impl<'a> Drop for TextureDataRefMut<'a> {
impl Drop for TextureDataRefMut<'_> {
fn drop(&mut self) {
self.texture.modifications_counter += 1;
}
}
impl<'a> Deref for TextureDataRefMut<'a> {
impl Deref for TextureDataRefMut<'_> {
type Target = Texture;
fn deref(&self) -> &Self::Target {
@@ -1774,13 +1774,13 @@ impl<'a> Deref for TextureDataRefMut<'a> {
}
}
impl<'a> DerefMut for TextureDataRefMut<'a> {
impl DerefMut for TextureDataRefMut<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.texture
}
}
impl<'a> TextureDataRefMut<'a> {
impl TextureDataRefMut<'_> {
/// Returns mutable reference to the data of the texture.
pub fn data_mut(&mut self) -> &mut [u8] {
&mut self.texture.bytes
@@ -1803,6 +1803,7 @@ impl<'a> TextureDataRefMut<'a> {
}
#[cfg(test)]
#[allow(missing_docs)]
pub mod test {
use crate::resource::texture::{
TextureKind, TexturePixelKind, TextureResource, TextureResourceExtension,
-1
View File
@@ -216,7 +216,6 @@ impl BoundValueCollectionExt for BoundValueCollection {
///
/// // Create a track that will animate the node using the curve above.
/// let mut track = Track::new(frames_container, ValueBinding::Position);
/// // Finally create an animation and set its time slice and turn it on.
/// let mut animation = Animation::default();
/// animation.add_track_with_binding(TrackBinding::new(animated_node),track);
-1
View File
@@ -481,7 +481,6 @@ pub struct Base {
/// A set of custom properties that can hold almost any data. It can be used to set additional
/// properties to scene nodes.
#[reflect(setter = "set_properties")]
pub properties: InheritableVariable<Vec<Property>>,
+15 -15
View File
@@ -414,13 +414,13 @@ pub struct VertexBufferRefMut<'a> {
vertex_buffer: &'a mut VertexBuffer,
}
impl<'a> Drop for VertexBufferRefMut<'a> {
impl Drop for VertexBufferRefMut<'_> {
fn drop(&mut self) {
self.vertex_buffer.modifications_counter += 1;
}
}
impl<'a> Deref for VertexBufferRefMut<'a> {
impl Deref for VertexBufferRefMut<'_> {
type Target = VertexBuffer;
fn deref(&self) -> &Self::Target {
@@ -428,13 +428,13 @@ impl<'a> Deref for VertexBufferRefMut<'a> {
}
}
impl<'a> DerefMut for VertexBufferRefMut<'a> {
impl DerefMut for VertexBufferRefMut<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.vertex_buffer
}
}
impl<'a> VertexBufferRefMut<'a> {
impl VertexBufferRefMut<'_> {
/// Tries to append a vertex to the buffer.
///
/// # Safety and validation
@@ -1163,7 +1163,7 @@ pub struct VertexViewRef<'a> {
sparse_layout: &'a [Option<VertexAttribute>],
}
impl<'a> PartialEq for VertexViewRef<'a> {
impl PartialEq for VertexViewRef<'_> {
fn eq(&self, other: &Self) -> bool {
self.vertex_data == other.vertex_data
}
@@ -1176,7 +1176,7 @@ pub struct VertexViewMut<'a> {
sparse_layout: &'a [Option<VertexAttribute>],
}
impl<'a> PartialEq for VertexViewMut<'a> {
impl PartialEq for VertexViewMut<'_> {
fn eq(&self, other: &Self) -> bool {
self.vertex_data == other.vertex_data
}
@@ -1305,7 +1305,7 @@ pub trait VertexReadTrait {
}
}
impl<'a> VertexReadTrait for VertexViewRef<'a> {
impl VertexReadTrait for VertexViewRef<'_> {
fn data_layout_ref(&self) -> (&[u8], &[Option<VertexAttribute>]) {
(self.vertex_data, self.sparse_layout)
}
@@ -1370,13 +1370,13 @@ pub trait VertexWriteTrait: VertexReadTrait {
) -> Result<(), VertexFetchError>;
}
impl<'a> VertexReadTrait for VertexViewMut<'a> {
impl VertexReadTrait for VertexViewMut<'_> {
fn data_layout_ref(&self) -> (&[u8], &[Option<VertexAttribute>]) {
(self.vertex_data, self.sparse_layout)
}
}
impl<'a> VertexWriteTrait for VertexViewMut<'a> {
impl VertexWriteTrait for VertexViewMut<'_> {
#[inline(always)]
fn data_layout_mut(&mut self) -> (&mut [u8], &[Option<VertexAttribute>]) {
(self.vertex_data, self.sparse_layout)
@@ -1531,7 +1531,7 @@ pub struct TriangleBufferRefMut<'a> {
triangle_buffer: &'a mut TriangleBuffer,
}
impl<'a> Deref for TriangleBufferRefMut<'a> {
impl Deref for TriangleBufferRefMut<'_> {
type Target = TriangleBuffer;
fn deref(&self) -> &Self::Target {
@@ -1539,19 +1539,19 @@ impl<'a> Deref for TriangleBufferRefMut<'a> {
}
}
impl<'a> DerefMut for TriangleBufferRefMut<'a> {
impl DerefMut for TriangleBufferRefMut<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.triangle_buffer
}
}
impl<'a> Drop for TriangleBufferRefMut<'a> {
impl Drop for TriangleBufferRefMut<'_> {
fn drop(&mut self) {
self.triangle_buffer.modifications_counter += 1;
}
}
impl<'a> TriangleBufferRefMut<'a> {
impl TriangleBufferRefMut<'_> {
/// Returns mutable iterator.
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TriangleDefinition> {
self.triangles.iter_mut()
@@ -1595,7 +1595,7 @@ impl<'a> TriangleBufferRefMut<'a> {
}
}
impl<'a> Index<usize> for TriangleBufferRefMut<'a> {
impl Index<usize> for TriangleBufferRefMut<'_> {
type Output = TriangleDefinition;
fn index(&self, index: usize) -> &Self::Output {
@@ -1603,7 +1603,7 @@ impl<'a> Index<usize> for TriangleBufferRefMut<'a> {
}
}
impl<'a> IndexMut<usize> for TriangleBufferRefMut<'a> {
impl IndexMut<usize> for TriangleBufferRefMut<'_> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.triangle_buffer.triangles[index]
}
+1 -1
View File
@@ -49,7 +49,7 @@ pub struct SoundContextGuard<'a> {
guard: MutexGuard<'a, fyrox_sound::context::State>,
}
impl<'a> SoundContextGuard<'a> {
impl SoundContextGuard<'_> {
/// Returns a reference to the audio bus graph.
pub fn bus_graph_ref(&self) -> &AudioBusGraph {
self.guard.bus_graph_ref()
+5 -5
View File
@@ -129,7 +129,7 @@ pub struct ChunkHeightData<'a>(pub ResourceDataRef<'a, Texture>);
/// (0,0) is the actual origin of the chunk, while (-1,-1) is the in the margin of the chunk.
pub struct ChunkHeightMutData<'a>(pub TextureDataRefMut<'a>);
impl<'a> ChunkHeightData<'a> {
impl ChunkHeightData<'_> {
/// The size of the hight map, excluding the margins
pub fn size(&self) -> Vector2<u32> {
match self.0.kind() {
@@ -159,7 +159,7 @@ impl<'a> ChunkHeightData<'a> {
}
}
impl<'a> ChunkHeightMutData<'a> {
impl ChunkHeightMutData<'_> {
/// The size of the hight map, excluding the margins
pub fn size(&self) -> Vector2<u32> {
match self.0.kind() {
@@ -197,7 +197,7 @@ impl<'a> ChunkHeightMutData<'a> {
}
}
impl<'a> std::ops::Index<Vector2<i32>> for ChunkHeightData<'a> {
impl std::ops::Index<Vector2<i32>> for ChunkHeightData<'_> {
type Output = f32;
fn index(&self, position: Vector2<i32>) -> &Self::Output {
@@ -211,7 +211,7 @@ impl<'a> std::ops::Index<Vector2<i32>> for ChunkHeightData<'a> {
}
}
}
impl<'a> std::ops::Index<Vector2<i32>> for ChunkHeightMutData<'a> {
impl std::ops::Index<Vector2<i32>> for ChunkHeightMutData<'_> {
type Output = f32;
fn index(&self, position: Vector2<i32>) -> &Self::Output {
@@ -222,7 +222,7 @@ impl<'a> std::ops::Index<Vector2<i32>> for ChunkHeightMutData<'a> {
&self.0.data_of_type::<f32>().unwrap()[y * row_size + x]
}
}
impl<'a> std::ops::IndexMut<Vector2<i32>> for ChunkHeightMutData<'a> {
impl std::ops::IndexMut<Vector2<i32>> for ChunkHeightMutData<'_> {
fn index_mut(&mut self, position: Vector2<i32>) -> &mut Self::Output {
assert!(self.is_valid_index(position));
let row_size = self.row_size();
+6 -6
View File
@@ -260,7 +260,7 @@ where
/// a plugin of certain type. See [`PluginsRefMut::of_type_ref`] and [`PluginsRefMut::of_type_mut`].
pub struct PluginsRefMut<'a>(pub &'a mut [PluginContainer]);
impl<'a> Deref for PluginsRefMut<'a> {
impl Deref for PluginsRefMut<'_> {
type Target = [PluginContainer];
fn deref(&self) -> &Self::Target {
@@ -268,13 +268,13 @@ impl<'a> Deref for PluginsRefMut<'a> {
}
}
impl<'a> DerefMut for PluginsRefMut<'a> {
impl DerefMut for PluginsRefMut<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl<'a> PluginsRefMut<'a> {
impl PluginsRefMut<'_> {
/// Searches for a plugin of the given type `T`.
#[inline]
pub fn of_type_ref<T>(&self) -> Option<&T>
@@ -400,7 +400,7 @@ pub struct ScriptContext<'a, 'b, 'c> {
pub script_index: usize,
}
impl<'a, 'b, 'c> UniversalScriptContext for ScriptContext<'a, 'b, 'c> {
impl UniversalScriptContext for ScriptContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
self.scene.graph.try_get_mut(self.handle)
}
@@ -476,7 +476,7 @@ pub struct ScriptMessageContext<'a, 'b, 'c> {
pub script_index: usize,
}
impl<'a, 'b, 'c> UniversalScriptContext for ScriptMessageContext<'a, 'b, 'c> {
impl UniversalScriptContext for ScriptMessageContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
self.scene.graph.try_get_mut(self.handle)
}
@@ -543,7 +543,7 @@ pub struct ScriptDeinitContext<'a, 'b, 'c> {
pub script_index: usize,
}
impl<'a, 'b, 'c> UniversalScriptContext for ScriptDeinitContext<'a, 'b, 'c> {
impl UniversalScriptContext for ScriptDeinitContext<'_, '_, '_> {
fn node(&mut self) -> Option<&mut Node> {
self.scene.graph.try_get_mut(self.node_handle)
}
-1
View File
@@ -428,7 +428,6 @@ impl<T: VertexDataProvider> Graph<T> {
/// This implementation is fast and allows for multiple searches in parallel, but does not attempt to find the optimal route
///
/// **See `Graph<T>.max_search_iterations`** to change the maximum amount of search iterations
pub fn build_indexed_path(
&self,
from: usize,
+5 -5
View File
@@ -320,7 +320,7 @@ mod test {
#[derive(Debug, PartialEq, Default, Visit, Clone)]
struct WalkAction;
impl<'a> Behavior<'a> for WalkAction {
impl Behavior<'_> for WalkAction {
type Context = Environment;
fn tick(&mut self, context: &mut Self::Context) -> Status {
@@ -340,7 +340,7 @@ mod test {
#[derive(Debug, PartialEq, Default, Visit, Clone)]
struct OpenDoorAction;
impl<'a> Behavior<'a> for OpenDoorAction {
impl Behavior<'_> for OpenDoorAction {
type Context = Environment;
fn tick(&mut self, context: &mut Self::Context) -> Status {
@@ -355,7 +355,7 @@ mod test {
#[derive(Debug, PartialEq, Default, Visit, Clone)]
struct StepThroughAction;
impl<'a> Behavior<'a> for StepThroughAction {
impl Behavior<'_> for StepThroughAction {
type Context = Environment;
fn tick(&mut self, context: &mut Self::Context) -> Status {
@@ -375,7 +375,7 @@ mod test {
#[derive(Debug, PartialEq, Default, Visit, Clone)]
struct CloseDoorAction;
impl<'a> Behavior<'a> for CloseDoorAction {
impl Behavior<'_> for CloseDoorAction {
type Context = Environment;
fn tick(&mut self, context: &mut Self::Context) -> Status {
@@ -412,7 +412,7 @@ mod test {
done: bool,
}
impl<'a> Behavior<'a> for BotBehavior {
impl Behavior<'_> for BotBehavior {
type Context = Environment;
fn tick(&mut self, context: &mut Self::Context) -> Status {
+1 -1
View File
@@ -544,7 +544,7 @@ impl Lightmap {
data.geometry_buffer.iter().map(|t| t.0),
uv_spacing,
)
.ok_or_else(|| LightmapGenerationError::InvalidIndex)?;
.ok_or(LightmapGenerationError::InvalidIndex)?;
patch.data_id = data.content_hash();
apply_surface_data_patch(data, &patch);
+2 -2
View File
@@ -229,14 +229,14 @@ pub struct NavmeshModificationContext<'a> {
navmesh: &'a mut Navmesh,
}
impl<'a> Drop for NavmeshModificationContext<'a> {
impl Drop for NavmeshModificationContext<'_> {
fn drop(&mut self) {
let graph = make_graph(&self.navmesh.triangles, &self.navmesh.vertices);
self.navmesh.graph = graph;
}
}
impl<'a> NavmeshModificationContext<'a> {
impl NavmeshModificationContext<'_> {
/// Adds the triangle to the navigational mesh and returns its index in the internal array. Vertex indices in
/// the triangle must be valid!
pub fn add_triangle(&mut self, triangle: TriangleDefinition) -> u32 {
+5 -5
View File
@@ -124,7 +124,7 @@ where
phantom: PhantomData<T>,
}
impl<'a, T> ResourceHeaderGuard<'a, T>
impl<T> ResourceHeaderGuard<'_, T>
where
T: TypedResourceData,
{
@@ -427,7 +427,7 @@ where
phantom: PhantomData<T>,
}
impl<'a, T> ResourceDataRef<'a, T>
impl<T> ResourceDataRef<'_, T>
where
T: TypedResourceData,
{
@@ -448,7 +448,7 @@ where
}
}
impl<'a, T> Debug for ResourceDataRef<'a, T>
impl<T> Debug for ResourceDataRef<'_, T>
where
T: TypedResourceData,
{
@@ -473,7 +473,7 @@ where
}
}
impl<'a, T> Deref for ResourceDataRef<'a, T>
impl<T> Deref for ResourceDataRef<'_, T>
where
T: TypedResourceData,
{
@@ -500,7 +500,7 @@ where
}
}
impl<'a, T> DerefMut for ResourceDataRef<'a, T>
impl<T> DerefMut for ResourceDataRef<'_, T>
where
T: TypedResourceData,
{
+27 -28
View File
@@ -23,8 +23,6 @@
//! The Border widget provides a stylized, static border around its child widget. See [`Border`] docs for more info and
//! usage examples.
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::{
core::{
algebra::Vector2, math::Rect, pool::Handle, reflect::prelude::*, type_traits::prelude::*,
@@ -33,6 +31,7 @@ use crate::{
define_constructor,
draw::{CommandTexture, Draw, DrawingContext},
message::UiMessage,
style::{resource::StyleResourceExt, Style, StyledProperty},
widget::{Widget, WidgetBuilder},
BuildContext, Control, MessageDirection, Thickness, UiNode, UserInterface,
};
@@ -61,7 +60,7 @@ use std::ops::{Deref, DerefMut};
/// )
/// )
/// //You can also use Thickness::uniform(1.0)
/// .with_stroke_thickness(Thickness {left: 1.0, right: 1.0, top: 1.0, bottom: 1.0})
/// .with_stroke_thickness(Thickness {left: 1.0, right: 1.0, top: 1.0, bottom: 1.0}.into())
/// .build(&mut ui.build_ctx());
/// }
/// ```
@@ -90,15 +89,15 @@ use std::ops::{Deref, DerefMut};
///
/// BorderBuilder::new(
/// WidgetBuilder::new()
/// .with_foreground(Brush::Solid(Color::opaque(0, 0, 200)))
/// .with_background(Brush::Solid(Color::opaque(200, 0, 0)))
/// .with_foreground(Brush::Solid(Color::opaque(0, 0, 200)).into())
/// .with_background(Brush::Solid(Color::opaque(200, 0, 0)).into())
/// .with_child(
/// TextBuilder::new(WidgetBuilder::new())
/// .with_text("I'm boxed in Blue and backed in Red!")
/// .build(&mut ui.build_ctx())
/// )
/// )
/// .with_stroke_thickness(Thickness {left: 2.0, right: 2.0, top: 2.0, bottom: 2.0})
/// .with_stroke_thickness(Thickness {left: 2.0, right: 2.0, top: 2.0, bottom: 2.0}.into())
/// .build(&mut ui.build_ctx());
/// ```
#[derive(Default, Clone, Visit, Reflect, Debug, TypeUuidProvider, ComponentProvider)]
@@ -107,10 +106,10 @@ pub struct Border {
/// Base widget of the border. See [`Widget`] docs for more info.
pub widget: Widget,
/// Stroke thickness for each side of the border.
pub stroke_thickness: InheritableVariable<Thickness>,
pub stroke_thickness: InheritableVariable<StyledProperty<Thickness>>,
/// Corner radius.
#[visit(optional)]
pub corner_radius: InheritableVariable<f32>,
pub corner_radius: InheritableVariable<StyledProperty<f32>>,
/// Enables or disables padding the children nodes by corner radius. If disabled, then the
/// children nodes layout won't be affected by the corner radius.
#[visit(optional)]
@@ -135,9 +134,9 @@ crate::define_widget_deref!(Border);
#[derive(Debug, Clone, PartialEq)]
pub enum BorderMessage {
/// Allows you to set stroke thickness at runtime. See [`Self::stroke_thickness`] docs for more.
StrokeThickness(Thickness),
StrokeThickness(StyledProperty<Thickness>),
/// Allows you to set corner radius at runtime. See [`Self::corner_radius`] docs for more.
CornerRadius(f32),
CornerRadius(StyledProperty<f32>),
/// Allows you to enable or disable padding the children nodes by corner radius. See
/// [`Self::pad_by_corner_radius`] docs for more.
PadByCornerRadius(bool),
@@ -146,12 +145,11 @@ pub enum BorderMessage {
impl BorderMessage {
define_constructor!(
/// Creates a new [Self::StrokeThickness] message.
BorderMessage:StrokeThickness => fn stroke_thickness(Thickness), layout: false
BorderMessage:StrokeThickness => fn stroke_thickness(StyledProperty<Thickness>), layout: false
);
define_constructor!(
/// Creates a new [Self::CornerRadius] message.
BorderMessage:CornerRadius => fn corner_radius(f32), layout: false
BorderMessage:CornerRadius => fn corner_radius(StyledProperty<f32>), layout: false
);
define_constructor!(
/// Creates a new [Self::PadByCornerRadius] message.
@@ -166,7 +164,7 @@ fn corner_offset(radius: f32) -> f32 {
impl Control for Border {
fn measure_override(&self, ui: &UserInterface, available_size: Vector2<f32>) -> Vector2<f32> {
let corner_offset = if *self.pad_by_corner_radius {
corner_offset(*self.corner_radius)
corner_offset(**self.corner_radius)
} else {
0.0
};
@@ -200,7 +198,7 @@ impl Control for Border {
fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
let corner_offset = if *self.pad_by_corner_radius {
corner_offset(*self.corner_radius)
corner_offset(**self.corner_radius)
} else {
0.0
};
@@ -225,7 +223,7 @@ impl Control for Border {
fn draw(&self, drawing_context: &mut DrawingContext) {
let bounds = self.widget.bounding_rect();
if (*self.corner_radius).eq(&0.0) {
if (**self.corner_radius).eq(&0.0) {
DrawingContext::push_rect_filled(drawing_context, &bounds, None);
drawing_context.commit(
self.clip_bounds(),
@@ -234,7 +232,7 @@ impl Control for Border {
None,
);
drawing_context.push_rect_vary(&bounds, *self.stroke_thickness);
drawing_context.push_rect_vary(&bounds, **self.stroke_thickness);
drawing_context.commit(
self.clip_bounds(),
self.widget.foreground(),
@@ -245,7 +243,7 @@ impl Control for Border {
DrawingContext::push_rounded_rect_filled(
drawing_context,
&bounds,
*self.corner_radius,
**self.corner_radius,
16,
);
drawing_context.commit(
@@ -258,7 +256,7 @@ impl Control for Border {
drawing_context.push_rounded_rect(
&bounds,
self.stroke_thickness.left,
*self.corner_radius,
**self.corner_radius,
16,
);
drawing_context.commit(
@@ -281,14 +279,15 @@ impl Control for Border {
BorderMessage::StrokeThickness(thickness) => {
if *thickness != *self.stroke_thickness {
self.stroke_thickness
.set_value_and_mark_modified(*thickness);
.set_value_and_mark_modified(thickness.clone());
ui.send_message(message.reverse());
self.invalidate_layout();
}
}
BorderMessage::CornerRadius(radius) => {
if *radius != *self.corner_radius {
self.corner_radius.set_value_and_mark_modified(*radius);
self.corner_radius
.set_value_and_mark_modified(radius.clone());
ui.send_message(message.reverse());
self.invalidate_layout();
}
@@ -311,9 +310,9 @@ pub struct BorderBuilder {
/// Widget builder that will be used to build the base of the widget.
pub widget_builder: WidgetBuilder,
/// Stroke thickness for each side of the border. Default is 1px wide border for each side.
pub stroke_thickness: Thickness,
pub stroke_thickness: StyledProperty<Thickness>,
/// Radius at each of four corners of the border. Default is zero.
pub corner_radius: f32,
pub corner_radius: StyledProperty<f32>,
/// Enables or disables padding the children nodes by corner radius. If disabled, then the
/// children nodes layout won't be affected by the corner radius. Default is `true`.
pub pad_by_corner_radius: bool,
@@ -324,20 +323,20 @@ impl BorderBuilder {
pub fn new(widget_builder: WidgetBuilder) -> Self {
Self {
widget_builder,
stroke_thickness: Thickness::uniform(1.0),
corner_radius: 0.0,
stroke_thickness: Thickness::uniform(1.0).into(),
corner_radius: 0.0.into(),
pad_by_corner_radius: true,
}
}
/// Sets the desired stroke thickness for each side of the border.
pub fn with_stroke_thickness(mut self, stroke_thickness: Thickness) -> Self {
pub fn with_stroke_thickness(mut self, stroke_thickness: StyledProperty<Thickness>) -> Self {
self.stroke_thickness = stroke_thickness;
self
}
/// Sets the desired corner radius.
pub fn with_corner_radius(mut self, corner_radius: f32) -> Self {
pub fn with_corner_radius(mut self, corner_radius: StyledProperty<f32>) -> Self {
self.corner_radius = corner_radius;
self
}
@@ -351,7 +350,7 @@ impl BorderBuilder {
/// Creates a [`Border`] widget, but does not add it to the user interface. Also see [`Self::build`] docs.
pub fn build_border(mut self, ctx: &BuildContext) -> Border {
if self.widget_builder.foreground.is_none() {
self.widget_builder.foreground = Some(ctx.style.get_or_default(Style::BRUSH_PRIMARY));
self.widget_builder.foreground = Some(ctx.style.property(Style::BRUSH_PRIMARY));
}
Border {
widget: self.widget_builder.build(ctx),
+3 -3
View File
@@ -91,7 +91,7 @@ pub struct BuildContext<'a> {
pub style: StyleResource,
}
impl<'a> Index<Handle<UiNode>> for BuildContext<'a> {
impl Index<Handle<UiNode>> for BuildContext<'_> {
type Output = UiNode;
fn index(&self, index: Handle<UiNode>) -> &Self::Output {
@@ -99,7 +99,7 @@ impl<'a> Index<Handle<UiNode>> for BuildContext<'a> {
}
}
impl<'a> IndexMut<Handle<UiNode>> for BuildContext<'a> {
impl IndexMut<Handle<UiNode>> for BuildContext<'_> {
fn index_mut(&mut self, index: Handle<UiNode>) -> &mut Self::Output {
&mut self.ui.nodes[index]
}
@@ -114,7 +114,7 @@ impl<'a> From<&'a mut UserInterface> for BuildContext<'a> {
}
}
impl<'a> BuildContext<'a> {
impl BuildContext<'_> {
/// Returns default font instance used by the UI.
pub fn default_font(&self) -> FontResource {
self.ui.default_font.clone()
+34 -33
View File
@@ -22,7 +22,7 @@
#![warn(missing_docs)]
use crate::border::BorderMessage;
use crate::style::StyledProperty;
use crate::{
border::BorderBuilder,
core::{
@@ -141,6 +141,13 @@ impl Button {
pub const CORNER_RADIUS: &'static str = "Button.CornerRadius";
/// A name of style property, that defines border thickness of a button.
pub const BORDER_THICKNESS: &'static str = "Button.BorderThickness";
/// Returns a style of the widget. This style contains only widget-specific properties.
pub fn style() -> Style {
Style::default()
.with(Self::CORNER_RADIUS, 4.0f32)
.with(Self::BORDER_THICKNESS, Thickness::uniform(1.0))
}
}
impl ConstructorProvider<UiNode, UserInterface> for Button {
@@ -217,21 +224,6 @@ 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),
));
}
}
} else if let Some(msg) = message.data::<ButtonMessage>() {
if message.destination() == self.handle() {
match msg {
@@ -285,8 +277,8 @@ pub enum ButtonContent {
text: String,
/// Optional font of the button. If [`None`], the default font will be used.
font: Option<FontResource>,
/// Font size of the text. Default is 14.0
size: f32,
/// Font size of the text. Default is 14.0 (defined by default style of the crate).
size: Option<StyledProperty<f32>>,
},
/// Arbitrary widget handle. It could be any widget handle, for example a handle of [`crate::image::Image`]
/// widget.
@@ -299,7 +291,7 @@ impl ButtonContent {
Self::Text {
text: s.as_ref().to_owned(),
font: None,
size: 14.0,
size: None,
}
}
@@ -308,16 +300,20 @@ impl ButtonContent {
Self::Text {
text: s.as_ref().to_owned(),
font: Some(font),
size: 14.0,
size: None,
}
}
/// Creates [`ButtonContent::Text`] with custom font and size.
pub fn text_with_font_size<S: AsRef<str>>(s: S, font: FontResource, size: f32) -> Self {
pub fn text_with_font_size<S: AsRef<str>>(
s: S,
font: FontResource,
size: StyledProperty<f32>,
) -> Self {
Self::Text {
text: s.as_ref().to_owned(),
font: Some(font),
size,
size: Some(size),
}
}
@@ -333,7 +329,10 @@ impl ButtonContent {
.with_horizontal_text_alignment(HorizontalAlignment::Center)
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_font(font.clone().unwrap_or_else(|| ctx.default_font()))
.with_font_size(*size)
.with_font_size(
size.clone()
.unwrap_or_else(|| ctx.style.property(Style::FONT_SIZE)),
)
.build(ctx),
Self::Node(node) => *node,
}
@@ -374,7 +373,12 @@ impl ButtonBuilder {
}
/// Sets the content of the button to be [`ButtonContent::Text`] (text with a custom font and size).
pub fn with_text_and_font_size(mut self, text: &str, font: FontResource, size: f32) -> Self {
pub fn with_text_and_font_size(
mut self,
text: &str,
font: FontResource,
size: StyledProperty<f32>,
) -> Self {
self.content = Some(ButtonContent::text_with_font_size(text, font, size));
self
}
@@ -413,19 +417,16 @@ impl ButtonBuilder {
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new()
.with_foreground(ctx.style.get_or_default(Style::BRUSH_DARKER))
.with_foreground(ctx.style.property(Style::BRUSH_DARKER))
.with_child(content),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(ctx.style.get_or(Button::CORNER_RADIUS, 4.0f32))
.with_stroke_thickness(
ctx.style
.get_or(Button::BORDER_THICKNESS, Thickness::uniform(1.0)),
),
.with_corner_radius(ctx.style.property(Button::CORNER_RADIUS))
.with_stroke_thickness(ctx.style.property(Button::BORDER_THICKNESS)),
)
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_normal_brush(ctx.style.property(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.property(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.property(Style::BRUSH_LIGHTEST))
.build(ctx)
});
+34 -18
View File
@@ -24,8 +24,6 @@
#![warn(missing_docs)]
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::{
border::BorderBuilder,
brush::Brush,
@@ -36,6 +34,7 @@ use crate::{
define_constructor,
grid::{Column, GridBuilder, Row},
message::{KeyCode, MessageDirection, UiMessage},
style::{resource::StyleResourceExt, Style},
vector_image::{Primitive, VectorImageBuilder},
widget::{Widget, WidgetBuilder, WidgetMessage},
BuildContext, Control, HorizontalAlignment, MouseButton, Thickness, UiNode, UserInterface,
@@ -165,6 +164,23 @@ pub struct CheckBox {
pub undefined_mark: InheritableVariable<Handle<UiNode>>,
}
impl CheckBox {
/// A name of style property, that defines corner radius of a checkbox.
pub const CORNER_RADIUS: &'static str = "CheckBox.CornerRadius";
/// A name of style property, that defines border thickness of a checkbox.
pub const BORDER_THICKNESS: &'static str = "CheckBox.BorderThickness";
/// A name of style property, that defines border thickness of a checkbox.
pub const CHECK_MARK_SIZE: &'static str = "CheckBox.CheckMarkSize";
/// Returns a style of the widget. This style contains only widget-specific properties.
pub fn style() -> Style {
Style::default()
.with(Self::CORNER_RADIUS, 4.0f32)
.with(Self::BORDER_THICKNESS, Thickness::uniform(1.0))
.with(Self::CHECK_MARK_SIZE, 7.0f32)
}
}
impl ConstructorProvider<UiNode, UserInterface> for CheckBox {
fn constructor() -> GraphNodeConstructor<UiNode, UserInterface> {
GraphNodeConstructor::new::<Self>()
@@ -346,12 +362,12 @@ impl CheckBoxBuilder {
/// Finishes check box building and adds it to the user interface.
pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
let check_mark = self.check_mark.unwrap_or_else(|| {
let size = 7.0;
let size = *ctx.style.property(CheckBox::CHECK_MARK_SIZE);
let half_size = size * 0.5;
BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_background(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.with_child(
VectorImageBuilder::new(
WidgetBuilder::new()
@@ -360,7 +376,7 @@ impl CheckBoxBuilder {
// Give some padding to ensure primitives don't get too cut off
.with_width(size + 1.0)
.with_height(size + 1.0)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_TEXT)),
.with_foreground(ctx.style.property(Style::BRUSH_TEXT)),
)
.with_primitives({
vec![
@@ -380,8 +396,8 @@ impl CheckBoxBuilder {
),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(3.0)
.with_stroke_thickness(Thickness::uniform(0.0))
.with_corner_radius(ctx.style.property(CheckBox::CORNER_RADIUS))
.with_stroke_thickness(Thickness::uniform(0.0).into())
.build(ctx)
});
ctx[check_mark].set_visibility(self.checked.unwrap_or(false));
@@ -392,12 +408,12 @@ impl CheckBoxBuilder {
.with_margin(Thickness::uniform(3.0))
.with_width(10.0)
.with_height(9.0)
.with_background(Brush::Solid(Color::TRANSPARENT))
.with_foreground(Brush::Solid(Color::TRANSPARENT)),
.with_background(Brush::Solid(Color::TRANSPARENT).into())
.with_foreground(Brush::Solid(Color::TRANSPARENT).into()),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(3.0)
.with_stroke_thickness(Thickness::uniform(0.0))
.with_corner_radius(ctx.style.property(CheckBox::CORNER_RADIUS))
.with_stroke_thickness(Thickness::uniform(0.0).into())
.build(ctx)
});
ctx[uncheck_mark].set_visibility(!self.checked.unwrap_or(true));
@@ -406,11 +422,11 @@ impl CheckBoxBuilder {
BorderBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(4.0))
.with_background(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
.with_foreground(Brush::Solid(Color::TRANSPARENT)),
.with_background(ctx.style.property(Style::BRUSH_BRIGHT))
.with_foreground(Brush::Solid(Color::TRANSPARENT).into()),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(3.0)
.with_corner_radius(ctx.style.property(CheckBox::CORNER_RADIUS))
.build(ctx)
});
ctx[undefined_mark].set_visibility(self.checked.is_none());
@@ -423,12 +439,12 @@ impl CheckBoxBuilder {
BorderBuilder::new(
WidgetBuilder::new()
.with_vertical_alignment(VerticalAlignment::Center)
.with_background(ctx.style.get_or_default(Style::BRUSH_DARKEST))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHT)),
.with_background(ctx.style.property(Style::BRUSH_DARKEST))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHT)),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(3.0)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_corner_radius(ctx.style.property(CheckBox::CORNER_RADIUS))
.with_stroke_thickness(ctx.style.property(CheckBox::BORDER_THICKNESS))
.build(ctx)
});
+2 -2
View File
@@ -383,7 +383,7 @@ fn create_color_points(
.with_context_menu(point_context_menu.clone())
.with_cursor(Some(CursorIcon::EwResize))
.with_width(6.0)
.with_foreground(Brush::Solid(pt.color())),
.with_foreground(Brush::Solid(pt.color()).into()),
)
.with_location(pt.location())
.build(ctx)
@@ -613,7 +613,7 @@ impl Control for ColorPoint {
impl ColorPoint {
fn color(&self) -> Color {
if let Brush::Solid(color) = *self.foreground {
if let Brush::Solid(color) = self.foreground.property {
color
} else {
unreachable!()
+1 -1
View File
@@ -859,7 +859,7 @@ impl ColorPicker {
ui.send_message(mark_handled(WidgetMessage::background(
self.color_mark,
MessageDirection::ToWidget,
Brush::Solid(color),
Brush::Solid(color).into(),
)));
}
}
+1 -1
View File
@@ -1946,7 +1946,7 @@ impl CurveEditorBuilder {
let context_menu = RcUiNodeHandle::new(context_menu, ctx.sender());
if self.widget_builder.foreground.is_none() {
self.widget_builder.foreground = Some(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
self.widget_builder.foreground = Some(ctx.style.property(Style::BRUSH_BRIGHT))
}
let editor = CurveEditor {
+39 -30
View File
@@ -24,7 +24,7 @@
#![warn(missing_docs)]
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::style::{Style, StyledProperty};
use crate::widget::WidgetBuilder;
use crate::{
border::{Border, BorderBuilder},
@@ -50,13 +50,13 @@ pub enum DecoratorMessage {
/// This message is used to switch a decorator in a `Selected` state or not.
Select(bool),
/// Sets a new brush for `Hovered` state.
HoverBrush(Brush),
HoverBrush(StyledProperty<Brush>),
/// Sets a new brush for `Normal` state.
NormalBrush(Brush),
NormalBrush(StyledProperty<Brush>),
/// Sets a new brush for `Pressed` state.
PressedBrush(Brush),
PressedBrush(StyledProperty<Brush>),
/// Sets a new brush for `Selected` state.
SelectedBrush(Brush),
SelectedBrush(StyledProperty<Brush>),
}
impl DecoratorMessage {
@@ -66,19 +66,19 @@ impl DecoratorMessage {
);
define_constructor!(
/// Creates a [`DecoratorMessage::HoverBrush`] message.
DecoratorMessage:HoverBrush => fn hover_brush(Brush), layout: false
DecoratorMessage:HoverBrush => fn hover_brush(StyledProperty<Brush>), layout: false
);
define_constructor!(
/// Creates a [`DecoratorMessage::NormalBrush`] message.
DecoratorMessage:NormalBrush => fn normal_brush(Brush), layout: false
DecoratorMessage:NormalBrush => fn normal_brush(StyledProperty<Brush>), layout: false
);
define_constructor!(
/// Creates a [`DecoratorMessage::PressedBrush`] message.
DecoratorMessage:PressedBrush => fn pressed_brush(Brush), layout: false
DecoratorMessage:PressedBrush => fn pressed_brush(StyledProperty<Brush>), layout: false
);
define_constructor!(
/// Creates a [`DecoratorMessage::SelectedBrush`] message.
DecoratorMessage:SelectedBrush => fn selected_brush(Brush), layout: false
DecoratorMessage:SelectedBrush => fn selected_brush(StyledProperty<Brush>), layout: false
);
}
@@ -107,7 +107,7 @@ impl DecoratorMessage {
/// # };
/// fn create_decorator(ctx: &mut BuildContext) -> Handle<UiNode> {
/// DecoratorBuilder::new(BorderBuilder::new(WidgetBuilder::new()))
/// .with_hover_brush(Brush::Solid(Color::opaque(0, 255, 0)))
/// .with_hover_brush(Brush::Solid(Color::opaque(0, 255, 0)).into())
/// .build(ctx)
/// }
/// ```
@@ -117,13 +117,13 @@ pub struct Decorator {
#[component(include)]
pub border: Border,
/// Current brush used for `Normal` state.
pub normal_brush: InheritableVariable<Brush>,
pub normal_brush: InheritableVariable<StyledProperty<Brush>>,
/// Current brush used for `Hovered` state.
pub hover_brush: InheritableVariable<Brush>,
pub hover_brush: InheritableVariable<StyledProperty<Brush>>,
/// Current brush used for `Pressed` state.
pub pressed_brush: InheritableVariable<Brush>,
pub pressed_brush: InheritableVariable<StyledProperty<Brush>>,
/// Current brush used for `Selected` state.
pub selected_brush: InheritableVariable<Brush>,
pub selected_brush: InheritableVariable<StyledProperty<Brush>>,
/// Whether the decorator is in `Selected` state or not.
pub is_selected: InheritableVariable<bool>,
/// Whether the decorator should react to mouse clicks and switch its state to `Pressed` or not.
@@ -285,6 +285,15 @@ impl Control for Decorator {
_ => {}
}
}
if message.destination() == self.handle() {
if let WidgetMessage::Style(style) = msg {
self.normal_brush.update(style);
self.hover_brush.update(style);
self.pressed_brush.update(style);
self.selected_brush.update(style);
}
}
}
}
}
@@ -292,10 +301,10 @@ impl Control for Decorator {
/// Creates [`Decorator`] widget instances and adds them to the user interface.
pub struct DecoratorBuilder {
border_builder: BorderBuilder,
normal_brush: Option<Brush>,
hover_brush: Option<Brush>,
pressed_brush: Option<Brush>,
selected_brush: Option<Brush>,
normal_brush: Option<StyledProperty<Brush>>,
hover_brush: Option<StyledProperty<Brush>>,
pressed_brush: Option<StyledProperty<Brush>>,
selected_brush: Option<StyledProperty<Brush>>,
pressable: bool,
selected: bool,
}
@@ -315,25 +324,25 @@ impl DecoratorBuilder {
}
/// Sets a desired brush for `Normal` state.
pub fn with_normal_brush(mut self, brush: Brush) -> Self {
pub fn with_normal_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.normal_brush = Some(brush);
self
}
/// Sets a desired brush for `Hovered` state.
pub fn with_hover_brush(mut self, brush: Brush) -> Self {
pub fn with_hover_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.hover_brush = Some(brush);
self
}
/// Sets a desired brush for `Pressed` state.
pub fn with_pressed_brush(mut self, brush: Brush) -> Self {
pub fn with_pressed_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.pressed_brush = Some(brush);
self
}
/// Sets a desired brush for `Selected` state.
pub fn with_selected_brush(mut self, brush: Brush) -> Self {
pub fn with_selected_brush(mut self, brush: StyledProperty<Brush>) -> Self {
self.selected_brush = Some(brush);
self
}
@@ -354,28 +363,28 @@ impl DecoratorBuilder {
pub fn build(mut self, ctx: &mut BuildContext) -> Handle<UiNode> {
let normal_brush = self
.normal_brush
.unwrap_or_else(|| ctx.style.get_or_default::<Brush>(Style::BRUSH_LIGHT));
.unwrap_or_else(|| ctx.style.property::<Brush>(Style::BRUSH_LIGHT));
let hover_brush = self
.hover_brush
.unwrap_or_else(|| ctx.style.get_or_default::<Brush>(Style::BRUSH_LIGHTER));
.unwrap_or_else(|| ctx.style.property::<Brush>(Style::BRUSH_LIGHTER));
let pressed_brush = self
.pressed_brush
.unwrap_or_else(|| ctx.style.get_or_default::<Brush>(Style::BRUSH_LIGHTEST));
.unwrap_or_else(|| ctx.style.property::<Brush>(Style::BRUSH_LIGHTEST));
let selected_brush = self
.selected_brush
.unwrap_or_else(|| ctx.style.get_or_default::<Brush>(Style::BRUSH_BRIGHT));
.unwrap_or_else(|| ctx.style.property::<Brush>(Style::BRUSH_BRIGHT));
if self.border_builder.widget_builder.foreground.is_none() {
let brush = ctx.style.get(Style::BRUSH_DARKER);
self.border_builder.widget_builder.foreground = brush;
let brush = ctx.style.property(Style::BRUSH_DARKER);
self.border_builder.widget_builder.foreground = Some(brush);
}
let mut border = self.border_builder.build_border(ctx);
if self.selected {
border.set_background(selected_brush.clone());
*border.background = selected_brush.clone();
} else {
border.set_background(normal_brush.clone());
*border.background = normal_brush.clone();
}
let node = UiNode::new(Decorator {
+3 -3
View File
@@ -109,7 +109,7 @@ fn send_background(ui: &UserInterface, destination: Handle<UiNode>, color: Color
ui.send_message(WidgetMessage::background(
destination,
MessageDirection::ToWidget,
Brush::Solid(color),
Brush::Solid(color).into(),
));
}
@@ -834,7 +834,7 @@ pub fn make_default_anchor(ctx: &mut BuildContext, row: usize, column: usize) ->
.on_row(row)
.on_column(column)
.with_draw_on_top(true)
.with_background(Brush::Solid(DEFAULT_ANCHOR_COLOR)),
.with_background(Brush::Solid(DEFAULT_ANCHOR_COLOR).into()),
)
.build(ctx)
}
@@ -905,7 +905,7 @@ impl TileBuilder {
_ => None,
}),
)
.with_stroke_thickness(Thickness::uniform(0.0))
.with_stroke_thickness(Thickness::uniform(0.0).into())
.build(ctx);
if let TileContent::Window(window) = self.content {
+2 -2
View File
@@ -953,7 +953,7 @@ impl DrawingContext {
CommandTexture::Font {
font: font.clone(),
page_index: current_page_index,
height: formatted_text.font_size().into(),
height: FontHeight::from(**formatted_text.font_size()),
},
None,
);
@@ -980,7 +980,7 @@ impl DrawingContext {
CommandTexture::Font {
font: font.clone(),
page_index: current_page_index,
height: formatted_text.font_size().into(),
height: FontHeight::from(**formatted_text.font_size()),
},
None,
);
+16 -7
View File
@@ -24,8 +24,6 @@
#![warn(missing_docs)]
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::{
border::BorderBuilder,
core::{
@@ -37,12 +35,15 @@ use crate::{
list_view::{ListViewBuilder, ListViewMessage},
message::{KeyCode, MessageDirection, UiMessage},
popup::{Placement, PopupBuilder, PopupMessage},
style::{resource::StyleResourceExt, Style},
utils::{make_arrow_non_uniform_size, ArrowDirection},
widget::{Widget, WidgetBuilder, WidgetMessage},
BuildContext, Control, Thickness, UiNode, UserInterface,
};
use fyrox_graph::constructor::{ConstructorProvider, GraphNodeConstructor};
use fyrox_graph::BaseSceneGraph;
use fyrox_graph::{
constructor::{ConstructorProvider, GraphNodeConstructor},
BaseSceneGraph,
};
use std::{
ops::{Deref, DerefMut},
sync::mpsc::Sender,
@@ -383,6 +384,14 @@ impl Control for DropdownList {
}
impl DropdownList {
/// A name of style property, that defines corner radius of a dropdown list.
pub const CORNER_RADIUS: &'static str = "DropdownList.CornerRadius";
/// Returns a style of the widget. This style contains only widget-specific properties.
pub fn style() -> Style {
Style::default().with(Self::CORNER_RADIUS, 4.0f32)
}
fn sync_selected_item_preview(&mut self, ui: &mut UserInterface) {
// Copy node from current selection in list view. This is not
// always suitable because if an item has some visual behaviour
@@ -497,12 +506,12 @@ impl DropdownListBuilder {
let border = BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_DARKER))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_background(ctx.style.property(Style::BRUSH_DARKER))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHT))
.with_child(main_grid),
)
.with_pad_by_corner_radius(false)
.with_corner_radius(4.0)
.with_corner_radius(ctx.style.property(DropdownList::CORNER_RADIUS))
.build(ctx);
let dropdown_list = UiNode::new(DropdownList {
+1 -3
View File
@@ -90,9 +90,7 @@ impl Atlas {
let border = 2;
match self.char_map.get(&unicode) {
Some(glyph_index) => {
return self.glyphs.get(*glyph_index);
}
Some(glyph_index) => self.glyphs.get(*glyph_index),
None => {
// Char might be missing, because it wasn't requested earlier. Try to find
// it in the inner font and render/pack it.
+21 -18
View File
@@ -20,12 +20,14 @@
use crate::{
brush::Brush,
core::{algebra::Vector2, color::Color, math::Rect, reflect::prelude::*, visitor::prelude::*},
core::{
algebra::Vector2, color::Color, math::Rect, reflect::prelude::*, uuid_provider,
variable::InheritableVariable, visitor::prelude::*,
},
font::{Font, FontGlyph, FontResource},
style::StyledProperty,
HorizontalAlignment, VerticalAlignment,
};
use fyrox_core::uuid_provider;
use fyrox_core::variable::InheritableVariable;
use std::ops::Range;
use strum_macros::{AsRefStr, EnumString, VariantNames};
@@ -125,7 +127,7 @@ struct GlyphMetrics<'a> {
size: f32,
}
impl<'a> GlyphMetrics<'a> {
impl GlyphMetrics<'_> {
fn ascender(&self) -> f32 {
self.font.ascender(self.size)
}
@@ -183,7 +185,7 @@ struct WrapSink<'a> {
max_width: f32,
}
impl<'a> LineSink for WrapSink<'a> {
impl LineSink for WrapSink<'_> {
fn push_line(&mut self, range: Range<usize>, width: f32) {
let mut line = TextLine::new();
line.begin = range.start;
@@ -220,7 +222,7 @@ pub struct FormattedText {
wrap: InheritableVariable<WrapMode>,
mask_char: InheritableVariable<Option<char>>,
#[visit(rename = "Height")]
font_size: InheritableVariable<f32>,
font_size: InheritableVariable<StyledProperty<f32>>,
pub shadow: InheritableVariable<bool>,
pub shadow_brush: InheritableVariable<Brush>,
pub shadow_dilation: InheritableVariable<f32>,
@@ -372,7 +374,7 @@ impl FormattedText {
};
let mut metrics = GlyphMetrics {
font,
size: *self.font_size,
size: **self.font_size,
};
let mut caret_pos = Vector2::default();
let position = self.nearest_valid_position(position);
@@ -394,6 +396,7 @@ impl FormattedText {
}
pub fn local_to_position(&self, point: Vector2<f32>) -> Position {
let font_size = **self.font_size();
let font = self.get_font();
let mut state = font.state();
let Some(font) = state.data() else {
@@ -401,7 +404,7 @@ impl FormattedText {
};
let mut metrics = GlyphMetrics {
font,
size: self.font_size(),
size: font_size,
};
let y = point.y;
@@ -425,7 +428,7 @@ impl FormattedText {
if let Some(advance) = raw_text.get(char_index).map(|c| metrics.advance(*c)) {
glyph_x += advance;
} else {
glyph_x += self.font_size();
glyph_x += font_size;
}
let dist = (x - glyph_x).abs();
if dist < min_dist {
@@ -452,11 +455,11 @@ impl FormattedText {
self
}
pub fn font_size(&self) -> f32 {
*self.font_size
pub fn font_size(&self) -> &StyledProperty<f32> {
&self.font_size
}
pub fn set_font_size(&mut self, font_size: f32) -> &mut Self {
pub fn set_font_size(&mut self, font_size: StyledProperty<f32>) -> &mut Self {
self.font_size.set_value_and_mark_modified(font_size);
self
}
@@ -519,7 +522,7 @@ impl FormattedText {
if let Some(font) = self.font.state().data() {
let mut metrics = GlyphMetrics {
font,
size: self.font_size(),
size: **self.font_size(),
};
for index in range {
// We can't trust the range values, check to prevent panic.
@@ -601,7 +604,7 @@ impl FormattedText {
};
let mut metrics = GlyphMetrics {
font,
size: self.font_size(),
size: **self.font_size(),
};
let line_height: f32 = metrics.ascender();
@@ -618,7 +621,7 @@ impl FormattedText {
LetterWrap::new(sink),
self.text.len(),
mask,
*self.font_size,
**self.font_size,
),
WrapMode::Word => wrap_mask(WordWrap::new(sink), self.text.len(), mask, advance),
}
@@ -743,7 +746,7 @@ pub struct FormattedTextBuilder {
shadow_brush: Brush,
shadow_dilation: f32,
shadow_offset: Vector2<f32>,
font_size: f32,
font_size: StyledProperty<f32>,
}
impl FormattedTextBuilder {
@@ -762,7 +765,7 @@ impl FormattedTextBuilder {
shadow_brush: Brush::Solid(Color::BLACK),
shadow_dilation: 1.0,
shadow_offset: Vector2::new(1.0, 1.0),
font_size: 14.0,
font_size: 14.0f32.into(),
}
}
@@ -786,7 +789,7 @@ impl FormattedTextBuilder {
self
}
pub fn with_font_size(mut self, font_size: f32) -> Self {
pub fn with_font_size(mut self, font_size: StyledProperty<f32>) -> Self {
self.font_size = font_size;
self
}
+1 -1
View File
@@ -345,7 +345,7 @@ impl ImageBuilder {
/// Builds the [`Image`] widget, but does not add it to the UI.
pub fn build_node(mut self, ctx: &BuildContext) -> UiNode {
if self.widget_builder.background.is_none() {
self.widget_builder.background = Some(Brush::Solid(Color::WHITE))
self.widget_builder.background = Some(Brush::Solid(Color::WHITE).into())
}
let image = Image {
@@ -431,7 +431,7 @@ where
.build(ctx.build_context),
),
)
.with_corner_radius(4.0)
.with_corner_radius(4.0f32.into())
.with_pad_by_corner_radius(false),
)
.build(ctx.build_context)
+1 -1
View File
@@ -682,7 +682,7 @@ fn make_expander_check_box(
.with_vertical_alignment(VerticalAlignment::Center)
.with_min_size(Vector2::new(4.0, 4.0)),
)
.with_stroke_thickness(Thickness::zero())
.with_stroke_thickness(Thickness::zero().into())
.build(ctx),
)
.with_content(
+94 -38
View File
@@ -233,6 +233,7 @@ pub mod inspector;
pub mod key;
pub mod list_view;
pub mod loader;
pub mod log;
pub mod matrix;
pub mod menu;
pub mod message;
@@ -557,32 +558,29 @@ pub struct RestrictionEntry {
}
#[derive(Clone, Debug)]
struct TooltipEntry {
tooltip: RcUiNodeHandle,
pub struct TooltipEntry {
pub tooltip: RcUiNodeHandle,
pub appear_timer: f32,
pub shown: bool,
/// Time remaining until this entry should disappear (in seconds).
time: f32,
pub disappear_timer: f32,
/// Maximum time that it should be kept for
/// This is stored here as well, because when hovering
/// over the tooltip, we don't know the time it should stay for and
/// so we use this to refresh the timer.
max_time: f32,
pub max_time: f32,
}
impl TooltipEntry {
fn new(tooltip: RcUiNodeHandle, time: f32) -> TooltipEntry {
fn new(tooltip: RcUiNodeHandle, appear_timeout: f32, disappear_timeout: f32) -> TooltipEntry {
Self {
tooltip,
time,
max_time: time,
appear_timer: appear_timeout,
shown: false,
disappear_timer: disappear_timeout,
max_time: disappear_timeout,
}
}
fn decrease(&mut self, amount: f32) {
self.time -= amount;
}
fn should_display(&self) -> bool {
self.time > 0.0
}
}
#[derive(Debug)]
@@ -695,6 +693,7 @@ pub struct UserInterface {
#[reflect(hidden)]
double_click_entries: FxHashMap<MouseButton, DoubleClickEntry>,
pub double_click_time_slice: f32,
pub tooltip_appear_delay: f32,
}
impl Visit for UserInterface {
@@ -725,6 +724,9 @@ impl Visit for UserInterface {
self.cursor_icon.visit("CursorIcon", &mut region)?;
self.double_click_time_slice
.visit("DoubleClickTimeSlice", &mut region)?;
let _ = self
.tooltip_appear_delay
.visit("TooltipAppearDelay", &mut region);
if region.is_reading() {
for node in self.nodes.iter() {
@@ -758,7 +760,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(),
@@ -778,6 +780,7 @@ impl Clone for UserInterface {
default_font: self.default_font.clone(),
double_click_entries: self.double_click_entries.clone(),
double_click_time_slice: self.double_click_time_slice,
tooltip_appear_delay: self.tooltip_appear_delay,
}
}
}
@@ -1045,7 +1048,7 @@ impl UserInterface {
screen_size: Vector2<f32>,
) -> 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,
@@ -1077,6 +1080,7 @@ impl UserInterface {
default_font: BUILT_IN_FONT.resource(),
double_click_entries: Default::default(),
double_click_time_slice: 0.5, // 500 ms is standard in most operating systems.
tooltip_appear_delay: 0.55,
};
let root_node = UiNode::new(Canvas {
widget: WidgetBuilder::new().build(&ui.build_ctx()),
@@ -1086,6 +1090,18 @@ impl UserInterface {
ui
}
pub fn set_tooltip_appear_delay(&mut self, appear_delay: f32) {
self.tooltip_appear_delay = appear_delay;
}
pub fn tooltip_appear_delay(&self) -> f32 {
self.tooltip_appear_delay
}
pub fn active_tooltip(&self) -> Option<&TooltipEntry> {
self.active_tooltip.as_ref()
}
pub fn keyboard_modifiers(&self) -> KeyboardModifiers {
self.keyboard_modifiers
}
@@ -1314,6 +1330,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<UiNode>, 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
}
@@ -2069,16 +2109,20 @@ impl UserInterface {
));
}
fn replace_or_update_tooltip(&mut self, tooltip: RcUiNodeHandle, time: f32) {
fn replace_or_update_tooltip(&mut self, tooltip: RcUiNodeHandle, disappear_timeout: f32) {
if let Some(entry) = self.active_tooltip.as_mut() {
if entry.tooltip == tooltip {
// Keep current visible.
entry.time = time;
if entry.shown {
// Keep current visible.
entry.disappear_timer = disappear_timeout;
}
} else {
let old_tooltip = entry.tooltip.clone();
entry.shown = false;
entry.appear_timer = self.tooltip_appear_delay;
entry.disappear_timer = disappear_timeout;
entry.tooltip = tooltip.clone();
self.show_tooltip(tooltip);
// Hide previous.
self.send_message(WidgetMessage::visibility(
@@ -2088,8 +2132,11 @@ impl UserInterface {
));
}
} else {
self.show_tooltip(tooltip.clone());
self.active_tooltip = Some(TooltipEntry::new(tooltip, time));
self.active_tooltip = Some(TooltipEntry::new(
tooltip,
self.tooltip_appear_delay,
disappear_timeout,
));
}
}
@@ -2098,19 +2145,28 @@ impl UserInterface {
fn update_tooltips(&mut self, dt: f32) {
let sender = &self.sender;
if let Some(entry) = self.active_tooltip.as_mut() {
entry.decrease(dt);
if !entry.should_display() {
// This uses sender directly since we're currently mutably borrowing
// visible_tooltips
sender
.send(WidgetMessage::visibility(
entry.tooltip.handle(),
MessageDirection::ToWidget,
false,
))
.unwrap();
if entry.shown {
entry.disappear_timer -= dt;
if entry.disappear_timer <= 0.0 {
// This uses sender directly since we're currently mutably borrowing
// visible_tooltips
sender
.send(WidgetMessage::visibility(
entry.tooltip.handle(),
MessageDirection::ToWidget,
false,
))
.unwrap();
self.active_tooltip = None;
self.active_tooltip = None;
}
} else {
entry.appear_timer -= dt;
if entry.appear_timer <= 0.0 {
entry.shown = true;
let tooltip = entry.tooltip.clone();
self.show_tooltip(tooltip);
}
}
}
@@ -2123,14 +2179,14 @@ impl UserInterface {
if let Some(tooltip) = node.tooltip() {
// They have a tooltip, we stop here and use that.
let tooltip_time = node.tooltip_time();
self.replace_or_update_tooltip(tooltip, tooltip_time);
let disappear_timeout = node.tooltip_time();
self.replace_or_update_tooltip(tooltip, disappear_timeout);
break;
} else if let Some(entry) = self.active_tooltip.as_mut() {
if entry.tooltip.handle() == handle {
// The current node was a tooltip.
// We refresh the timer back to the stored max time.
entry.time = entry.max_time;
entry.disappear_timer = entry.max_time;
break;
}
}
+3 -3
View File
@@ -592,10 +592,10 @@ impl ListViewBuilder {
let style = &ctx.style;
let back = BorderBuilder::new(
WidgetBuilder::new()
.with_background(style.get_or_default(Style::BRUSH_DARK))
.with_foreground(style.get_or_default(Style::BRUSH_LIGHT)),
.with_background(style.property(Style::BRUSH_DARK))
.with_foreground(style.property(Style::BRUSH_LIGHT)),
)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx);
let scroll_viewer = self.scroll_viewer.unwrap_or_else(|| {
+358
View File
@@ -0,0 +1,358 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::{
border::BorderBuilder,
button::ButtonMessage,
copypasta::ClipboardProvider,
dropdown_list::{DropdownListBuilder, 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},
utils::{make_dropdown_list_option, make_image_button_with_tooltip},
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
BuildContext, HorizontalAlignment, Orientation, RcUiNodeHandle, Thickness, UiNode,
UserInterface,
};
use fyrox_core::{
log::{LogMessage, MessageKind},
pool::Handle,
};
use fyrox_graph::BaseSceneGraph;
use fyrox_resource::untyped::UntypedResource;
use std::sync::mpsc::Receiver;
struct ContextMenu {
menu: RcUiNodeHandle,
copy: Handle<UiNode>,
placement_target: Handle<UiNode>,
}
impl ContextMenu {
pub fn new(ctx: &mut BuildContext) -> Self {
let copy;
let menu = ContextMenuBuilder::new(
PopupBuilder::new(WidgetBuilder::new()).with_content(
StackPanelBuilder::new(WidgetBuilder::new().with_child({
copy = MenuItemBuilder::new(WidgetBuilder::new())
.with_content(MenuItemContent::text("Copy"))
.build(ctx);
copy
}))
.build(ctx),
),
)
.build(ctx);
let menu = RcUiNodeHandle::new(menu, ctx.sender());
Self {
menu,
copy,
placement_target: Default::default(),
}
}
pub fn handle_ui_message(&mut self, message: &UiMessage, ui: &mut UserInterface) {
if let Some(PopupMessage::Placement(Placement::Cursor(target))) = message.data() {
if message.destination() == self.menu.handle() {
self.placement_target = *target;
}
} else if let Some(MenuItemMessage::Click) = message.data() {
if message.destination() == self.copy {
if let Some(field) = ui
.try_get(self.placement_target)
.and_then(|n| n.query_component::<Text>())
{
let text = field.text();
if let Some(mut clipboard) = ui.clipboard_mut() {
let _ = clipboard.set_contents(text);
}
}
}
}
}
}
pub struct LogPanel {
pub window: Handle<UiNode>,
messages: Handle<UiNode>,
clear: Handle<UiNode>,
receiver: Receiver<LogMessage>,
severity: MessageKind,
severity_list: Handle<UiNode>,
context_menu: ContextMenu,
pub message_count: usize,
}
impl LogPanel {
pub fn new(
ctx: &mut BuildContext,
message_receiver: Receiver<LogMessage>,
clear_icon: Option<UntypedResource>,
open: bool,
) -> Self {
let messages;
let clear;
let severity_list;
let window = WindowBuilder::new(
WidgetBuilder::new()
.with_width(400.0)
.with_height(200.0)
.with_name("LogPanel"),
)
.can_minimize(false)
.open(open)
.with_title(WindowTitle::text("Message Log"))
.with_content(
GridBuilder::new(
WidgetBuilder::new()
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Left)
.on_row(0)
.on_column(0)
.with_child({
clear = make_image_button_with_tooltip(
ctx,
24.0,
24.0,
clear_icon,
"Clear the log.",
Some(0),
);
clear
})
.with_child({
severity_list = DropdownListBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(1))
.with_width(120.0)
.with_margin(Thickness::uniform(1.0)),
)
.with_items(vec![
make_dropdown_list_option(ctx, "Info+"),
make_dropdown_list_option(ctx, "Warnings+"),
make_dropdown_list_option(ctx, "Errors"),
])
// Warnings+
.with_selected(1)
.build(ctx);
severity_list
}),
)
.with_orientation(Orientation::Horizontal)
.build(ctx),
)
.with_child({
messages = ListViewBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.on_row(1)
.on_column(0),
)
.with_scroll_viewer(
ScrollViewerBuilder::new(
WidgetBuilder::new().with_margin(Thickness::uniform(3.0)),
)
.with_horizontal_scroll_allowed(true)
.with_vertical_scroll_allowed(true)
.build(ctx),
)
.build(ctx);
messages
}),
)
.add_row(Row::strict(26.0))
.add_row(Row::stretch())
.add_column(Column::stretch())
.build(ctx),
)
.build(ctx);
let context_menu = ContextMenu::new(ctx);
Self {
window,
messages,
clear,
receiver: message_receiver,
severity: MessageKind::Warning,
severity_list,
context_menu,
message_count: 0,
}
}
pub fn destroy(self, ui: &UserInterface) {
ui.send_message(WidgetMessage::remove(
self.context_menu.menu.handle(),
MessageDirection::ToWidget,
));
ui.send_message(WidgetMessage::remove(
self.window,
MessageDirection::ToWidget,
));
}
pub fn open(&self, ui: &UserInterface) {
ui.send_message(WindowMessage::open(
self.window,
MessageDirection::ToWidget,
true,
true,
));
}
pub fn close(&self, ui: &UserInterface) {
ui.send_message(WindowMessage::close(
self.window,
MessageDirection::ToWidget,
));
}
pub fn handle_ui_message(&mut self, message: &UiMessage, ui: &mut UserInterface) {
if let Some(ButtonMessage::Click) = message.data::<ButtonMessage>() {
if message.destination() == self.clear {
ui.send_message(ListViewMessage::items(
self.messages,
MessageDirection::ToWidget,
vec![],
));
}
} else if let Some(DropdownListMessage::SelectionChanged(Some(idx))) =
message.data::<DropdownListMessage>()
{
if message.destination() == self.severity_list
&& message.direction() == MessageDirection::FromWidget
{
match idx {
0 => self.severity = MessageKind::Information,
1 => self.severity = MessageKind::Warning,
2 => self.severity = MessageKind::Error,
_ => (),
};
}
}
self.context_menu.handle_ui_message(message, ui);
}
pub fn update(&mut self, max_log_entries: usize, ui: &mut UserInterface) -> bool {
let existing_items = ui
.node(self.messages)
.cast::<ListView>()
.map(|v| v.items())
.unwrap();
let mut count = existing_items.len();
if count > max_log_entries {
let delta = count - max_log_entries;
// Remove every item in the head of the list of entries to keep the amount of entries
// in the limits.
//
// TODO: This is suboptimal, because it creates a message per each excessive entry, which
// might be slow to process in case of large amount of messages.
for item in existing_items.iter().take(delta) {
ui.send_message(ListViewMessage::remove_item(
self.messages,
MessageDirection::ToWidget,
*item,
));
}
count -= delta;
}
let mut item_to_bring_into_view = Handle::NONE;
let mut received_anything = false;
while let Ok(msg) = self.receiver.try_recv() {
if msg.kind < self.severity {
continue;
}
self.message_count += 1;
received_anything = true;
let text = format!("[{:.2}s] {}", msg.time.as_secs_f32(), msg.content);
let ctx = &mut ui.build_ctx();
let item = BorderBuilder::new(
WidgetBuilder::new()
.with_background(if count % 2 == 0 {
ctx.style.property(Style::BRUSH_LIGHT)
} else {
ctx.style.property(Style::BRUSH_DARK)
})
.with_child(
TextBuilder::new(
WidgetBuilder::new()
.with_context_menu(self.context_menu.menu.clone())
.with_margin(Thickness::uniform(1.0))
.with_foreground(match msg.kind {
MessageKind::Information => {
ctx.style.property(Style::BRUSH_INFORMATION)
}
MessageKind::Warning => {
ctx.style.property(Style::BRUSH_WARNING)
}
MessageKind::Error => ctx.style.property(Style::BRUSH_ERROR),
}),
)
.with_text(text)
.with_wrap(WrapMode::Word)
.build(ctx),
),
)
.build(ctx);
ui.send_message(ListViewMessage::add_item(
self.messages,
MessageDirection::ToWidget,
item,
));
item_to_bring_into_view = item;
count += 1;
}
if item_to_bring_into_view.is_some() {
ui.send_message(ListViewMessage::bring_item_into_view(
self.messages,
MessageDirection::ToWidget,
item_to_bring_into_view,
));
}
received_anything
}
}
+7 -7
View File
@@ -915,7 +915,7 @@ impl MenuBuilder {
let back = BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_PRIMARY))
.with_background(ctx.style.property(Style::BRUSH_PRIMARY))
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new().with_children(self.items.iter().cloned()),
@@ -1111,7 +1111,7 @@ impl MenuItemBuilder {
.on_column(3)
.with_width(8.0)
.with_height(8.0)
.with_foreground(ctx.style.get_or_default(Style::BRUSH_BRIGHT))
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHT))
.with_horizontal_alignment(HorizontalAlignment::Center)
.with_vertical_alignment(VerticalAlignment::Center),
)
@@ -1145,12 +1145,12 @@ impl MenuItemBuilder {
let decorator = self.back.unwrap_or_else(|| {
DecoratorBuilder::new(
BorderBuilder::new(WidgetBuilder::new())
.with_stroke_thickness(Thickness::uniform(0.0)),
.with_stroke_thickness(Thickness::uniform(0.0).into()),
)
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_selected_brush(ctx.style.get_or_default(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_PRIMARY))
.with_pressed_brush(Brush::Solid(Color::TRANSPARENT))
.with_hover_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.with_selected_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.with_normal_brush(ctx.style.property(Style::BRUSH_PRIMARY))
.with_pressed_brush(Brush::Solid(Color::TRANSPARENT).into())
.with_pressable(false)
.build(ctx)
});
+1 -1
View File
@@ -424,7 +424,7 @@ impl NinePatchBuilder {
}
pub fn build(mut self, ctx: &mut BuildContext) -> Handle<UiNode> {
if self.widget_builder.background.is_none() {
self.widget_builder.background = Some(Brush::Solid(Color::WHITE))
self.widget_builder.background = Some(Brush::Solid(Color::WHITE).into())
}
// if one of the margins hasn't been set just mirror the opposite one.
+9 -11
View File
@@ -26,10 +26,8 @@ use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::{
border::BorderBuilder,
brush::Brush,
button::{ButtonBuilder, ButtonMessage},
core::{
color::Color,
num_traits::{clamp, Bounded, NumAssign, NumCast, NumOps},
pool::Handle,
reflect::{prelude::*, Reflect},
@@ -644,14 +642,14 @@ fn make_button(
.with_back(
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_foreground(Brush::Solid(Color::opaque(90, 90, 90))),
WidgetBuilder::new().with_foreground(ctx.style.property(Style::BRUSH_LIGHTER)),
)
.with_corner_radius(2.0)
.with_corner_radius(2.0f32.into())
.with_pad_by_corner_radius(false),
)
.with_normal_brush(Brush::Solid(Color::opaque(60, 60, 60)))
.with_hover_brush(Brush::Solid(Color::opaque(80, 80, 80)))
.with_pressed_brush(Brush::Solid(Color::opaque(80, 118, 178)))
.with_normal_brush(ctx.style.property(Style::BRUSH_PRIMARY))
.with_hover_brush(ctx.style.property(Style::BRUSH_LIGHT))
.with_pressed_brush(ctx.style.property(Style::BRUSH_BRIGHT_BLUE))
.build(ctx),
)
.with_content(make_arrow(ctx, arrow, 6.0))
@@ -737,12 +735,12 @@ impl<T: NumericType> NumericUpDownBuilder<T> {
let field;
let back = BorderBuilder::new(
WidgetBuilder::new()
.with_background(ctx.style.get_or_default(Style::BRUSH_DARK))
.with_foreground(ctx.style.get_or_default(Style::BRUSH_LIGHT)),
.with_background(ctx.style.property(Style::BRUSH_DARK))
.with_foreground(ctx.style.property(Style::BRUSH_LIGHT)),
)
.with_corner_radius(4.0)
.with_corner_radius(4.0f32.into())
.with_pad_by_corner_radius(false)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx);
let text = format!("{:.1$}", self.value, self.precision);
+3 -3
View File
@@ -607,11 +607,11 @@ impl PopupBuilder {
let body = BorderBuilder::new(
WidgetBuilder::new()
.with_background(style.get_or_default(Style::BRUSH_PRIMARY))
.with_foreground(style.get_or_default(Style::BRUSH_DARKEST))
.with_background(style.property(Style::BRUSH_PRIMARY))
.with_foreground(style.property(Style::BRUSH_DARKEST))
.with_child(self.content),
)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx);
Popup {
+4 -3
View File
@@ -23,12 +23,13 @@
#![warn(missing_docs)]
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::{
border::BorderBuilder,
brush::Brush,
canvas::CanvasBuilder,
core::{
algebra::Vector2, color::Color, pool::Handle, reflect::prelude::*, type_traits::prelude::*,
algebra::Vector2, pool::Handle, reflect::prelude::*, type_traits::prelude::*,
visitor::prelude::*,
},
define_constructor,
@@ -206,7 +207,7 @@ impl ProgressBarBuilder {
let indicator = self.indicator.unwrap_or_else(|| {
BorderBuilder::new(
WidgetBuilder::new().with_background(Brush::Solid(Color::opaque(180, 180, 180))),
WidgetBuilder::new().with_background(ctx.style.property(Style::BRUSH_BRIGHTEST)),
)
.build(ctx)
});
+17 -14
View File
@@ -25,7 +25,7 @@
use crate::font::FontResource;
use crate::style::resource::StyleResourceExt;
use crate::style::Style;
use crate::style::{Style, StyledProperty};
use crate::{
border::BorderBuilder,
brush::Brush,
@@ -480,7 +480,7 @@ pub struct ScrollBarBuilder {
show_value: bool,
value_precision: usize,
font: Option<FontResource>,
font_size: f32,
font_size: Option<StyledProperty<f32>>,
}
impl ScrollBarBuilder {
@@ -500,7 +500,7 @@ impl ScrollBarBuilder {
show_value: false,
value_precision: 3,
font: None,
font_size: 14.0,
font_size: None,
}
}
@@ -577,8 +577,8 @@ impl ScrollBarBuilder {
}
/// Sets the desired font size.
pub fn with_font_size(mut self, size: f32) -> Self {
self.font_size = size;
pub fn with_font_size(mut self, size: StyledProperty<f32>) -> Self {
self.font_size = Some(size);
self
}
@@ -625,15 +625,15 @@ impl ScrollBarBuilder {
let indicator = self.indicator.unwrap_or_else(|| {
DecoratorBuilder::new(
BorderBuilder::new(
WidgetBuilder::new().with_foreground(Brush::Solid(Color::TRANSPARENT)),
WidgetBuilder::new().with_foreground(Brush::Solid(Color::TRANSPARENT).into()),
)
.with_corner_radius(8.0)
.with_corner_radius(8.0f32.into())
.with_pad_by_corner_radius(false)
.with_stroke_thickness(Thickness::uniform(1.0)),
.with_stroke_thickness(Thickness::uniform(1.0).into()),
)
.with_normal_brush(ctx.style.get_or_default(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.get_or_default(Style::BRUSH_LIGHTEST))
.with_normal_brush(ctx.style.property(Style::BRUSH_LIGHT))
.with_hover_brush(ctx.style.property(Style::BRUSH_LIGHTER))
.with_pressed_brush(ctx.style.property(Style::BRUSH_LIGHTEST))
.build(ctx)
});
@@ -668,7 +668,10 @@ impl ScrollBarBuilder {
}),
)
.with_font(self.font.unwrap_or_else(|| ctx.default_font()))
.with_font_size(self.font_size)
.with_font_size(
self.font_size
.unwrap_or_else(|| ctx.style.property(Style::FONT_SIZE)),
)
.with_text(format!("{:.1$}", value, self.value_precision))
.build(ctx);
@@ -711,9 +714,9 @@ impl ScrollBarBuilder {
let body = self.body.unwrap_or_else(|| {
BorderBuilder::new(
WidgetBuilder::new().with_background(ctx.style.get_or_default(Style::BRUSH_DARK)),
WidgetBuilder::new().with_background(ctx.style.property(Style::BRUSH_DARK)),
)
.with_stroke_thickness(Thickness::uniform(1.0))
.with_stroke_thickness(Thickness::uniform(1.0).into())
.build(ctx)
});
ctx.link(grid, body);

Some files were not shown because too many files have changed in this diff Show More