mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
Merge branch 'FyroxEngine:master' into tiles
This commit is contained in:
Generated
+1
@@ -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
@@ -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
@@ -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
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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!(
|
||||
|
||||
@@ -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,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
}))
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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"] }
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 } => {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>>,
|
||||
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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),
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
});
|
||||
|
||||
|
||||
@@ -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!()
|
||||
|
||||
@@ -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(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(|| {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
});
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user