mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
searching for entity creator
This commit is contained in:
+100
-22
@@ -21,20 +21,24 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
command::{Command, CommandGroup},
|
command::{Command, CommandGroup},
|
||||||
fyrox::{
|
fyrox::{
|
||||||
core::{algebra::Vector3, pool::Handle},
|
core::{algebra::Vector3, pool::Handle, ImmutableString},
|
||||||
engine::Engine,
|
engine::Engine,
|
||||||
fxhash::FxHashMap,
|
fxhash::FxHashMap,
|
||||||
graph::constructor::{ConstructorVariantId, GraphNodeConstructorContainer, VariantResult},
|
graph::{
|
||||||
|
constructor::{ConstructorVariantId, GraphNodeConstructorContainer, VariantResult},
|
||||||
|
SceneGraph,
|
||||||
|
},
|
||||||
gui::{
|
gui::{
|
||||||
button::{Button, ButtonBuilder, ButtonMessage},
|
button::{Button, ButtonBuilder, ButtonMessage},
|
||||||
grid::{Column, GridBuilder, Row},
|
grid::{Column, GridBuilder, Row},
|
||||||
list_view::{ListView, ListViewBuilder},
|
list_view::{ListView, ListViewBuilder},
|
||||||
message::UiMessage,
|
message::UiMessage,
|
||||||
scroll_viewer::ScrollViewerBuilder,
|
scroll_viewer::{ScrollViewer, ScrollViewerBuilder, ScrollViewerMessage},
|
||||||
|
searchbar::{SearchBar, SearchBarBuilder, SearchBarMessage},
|
||||||
stack_panel::StackPanelBuilder,
|
stack_panel::StackPanelBuilder,
|
||||||
text::TextBuilder,
|
text::TextBuilder,
|
||||||
tree::{Tree, TreeBuilder, TreeMessage, TreeRoot, TreeRootBuilder, TreeRootMessage},
|
tree::{Tree, TreeBuilder, TreeMessage, TreeRoot, TreeRootBuilder, TreeRootMessage},
|
||||||
widget::WidgetBuilder,
|
widget::{UserData, WidgetBuilder, WidgetMessage},
|
||||||
window::{Window, WindowAlignment, WindowBuilder, WindowMessage, WindowTitle},
|
window::{Window, WindowAlignment, WindowBuilder, WindowMessage, WindowTitle},
|
||||||
BuildContext, HorizontalAlignment, Orientation, Thickness, UiNode, UserInterface,
|
BuildContext, HorizontalAlignment, Orientation, Thickness, UiNode, UserInterface,
|
||||||
},
|
},
|
||||||
@@ -47,7 +51,6 @@ use crate::{
|
|||||||
scene::{GameScene, Selection},
|
scene::{GameScene, Selection},
|
||||||
ui_scene::{commands::graph::AddWidgetCommand, UiScene},
|
ui_scene::{commands::graph::AddWidgetCommand, UiScene},
|
||||||
};
|
};
|
||||||
use fyrox::gui::widget::WidgetMessage;
|
|
||||||
|
|
||||||
#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)]
|
#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
pub enum EntityCreatorMode {
|
pub enum EntityCreatorMode {
|
||||||
@@ -59,6 +62,7 @@ pub enum EntityCreatorMode {
|
|||||||
|
|
||||||
pub struct EntityCreator {
|
pub struct EntityCreator {
|
||||||
window: Handle<Window>,
|
window: Handle<Window>,
|
||||||
|
#[allow(unused)] // TODO
|
||||||
recent_list: Handle<ListView>,
|
recent_list: Handle<ListView>,
|
||||||
groups_tree: Handle<TreeRoot>,
|
groups_tree: Handle<TreeRoot>,
|
||||||
items_map: FxHashMap<Handle<Tree>, ConstructorVariantId>,
|
items_map: FxHashMap<Handle<Tree>, ConstructorVariantId>,
|
||||||
@@ -66,11 +70,22 @@ pub struct EntityCreator {
|
|||||||
cancel: Handle<Button>,
|
cancel: Handle<Button>,
|
||||||
selection: Option<ConstructorVariantId>,
|
selection: Option<ConstructorVariantId>,
|
||||||
mode: EntityCreatorMode,
|
mode: EntityCreatorMode,
|
||||||
|
search_bar: Handle<SearchBar>,
|
||||||
|
groups_scroll_viewer: Handle<ScrollViewer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_tree_item(ui: &mut UserInterface, text: &str) -> Handle<Tree> {
|
#[derive(Clone)]
|
||||||
|
struct TreeData {
|
||||||
|
variant_name: ImmutableString,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_tree_item(
|
||||||
|
ui: &mut UserInterface,
|
||||||
|
variant_name: ImmutableString,
|
||||||
|
text: &str,
|
||||||
|
) -> Handle<Tree> {
|
||||||
let ctx = &mut ui.build_ctx();
|
let ctx = &mut ui.build_ctx();
|
||||||
TreeBuilder::new(WidgetBuilder::new())
|
TreeBuilder::new(WidgetBuilder::new().with_user_data(UserData::new(TreeData { variant_name })))
|
||||||
.with_content(
|
.with_content(
|
||||||
TextBuilder::new(WidgetBuilder::new())
|
TextBuilder::new(WidgetBuilder::new())
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
@@ -79,8 +94,35 @@ fn make_tree_item(ui: &mut UserInterface, text: &str) -> Handle<Tree> {
|
|||||||
.build(ctx)
|
.build(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apply_filter_recursive(node: Handle<UiNode>, filter: &str, ui: &UserInterface) -> bool {
|
||||||
|
let node_ref = ui.node(node);
|
||||||
|
|
||||||
|
let mut is_any_match = false;
|
||||||
|
for &child in node_ref.children() {
|
||||||
|
is_any_match |= apply_filter_recursive(child, filter, ui)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(data) = node_ref
|
||||||
|
.self_or_field_ref::<Tree>()
|
||||||
|
.and_then(|n| n.user_data_cloned::<TreeData>())
|
||||||
|
{
|
||||||
|
is_any_match |= data.variant_name.to_lowercase().contains(filter);
|
||||||
|
|
||||||
|
ui.send(node, WidgetMessage::Visibility(is_any_match));
|
||||||
|
}
|
||||||
|
|
||||||
|
is_any_match
|
||||||
|
}
|
||||||
|
|
||||||
impl EntityCreator {
|
impl EntityCreator {
|
||||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||||
|
let search_bar = SearchBarBuilder::new(
|
||||||
|
WidgetBuilder::new()
|
||||||
|
.on_row(0)
|
||||||
|
.with_margin(Thickness::uniform(2.0)),
|
||||||
|
)
|
||||||
|
.build(ctx);
|
||||||
|
|
||||||
let recent_list = ListViewBuilder::new(WidgetBuilder::new().on_column(0)).build(ctx);
|
let recent_list = ListViewBuilder::new(WidgetBuilder::new().on_column(0)).build(ctx);
|
||||||
|
|
||||||
let groups_tree = TreeRootBuilder::new(WidgetBuilder::new()).build(ctx);
|
let groups_tree = TreeRootBuilder::new(WidgetBuilder::new()).build(ctx);
|
||||||
@@ -109,7 +151,7 @@ impl EntityCreator {
|
|||||||
WidgetBuilder::new()
|
WidgetBuilder::new()
|
||||||
.with_height(28.0)
|
.with_height(28.0)
|
||||||
.with_horizontal_alignment(HorizontalAlignment::Right)
|
.with_horizontal_alignment(HorizontalAlignment::Right)
|
||||||
.on_row(1)
|
.on_row(2)
|
||||||
.with_child(create)
|
.with_child(create)
|
||||||
.with_child(cancel),
|
.with_child(cancel),
|
||||||
)
|
)
|
||||||
@@ -118,6 +160,7 @@ impl EntityCreator {
|
|||||||
|
|
||||||
let grid = GridBuilder::new(
|
let grid = GridBuilder::new(
|
||||||
WidgetBuilder::new()
|
WidgetBuilder::new()
|
||||||
|
.on_row(1)
|
||||||
.with_margin(Thickness::uniform(2.0))
|
.with_margin(Thickness::uniform(2.0))
|
||||||
.with_child(recent_list)
|
.with_child(recent_list)
|
||||||
.with_child(groups_scroll_viewer),
|
.with_child(groups_scroll_viewer),
|
||||||
@@ -127,11 +170,17 @@ impl EntityCreator {
|
|||||||
.add_row(Row::stretch())
|
.add_row(Row::stretch())
|
||||||
.build(ctx);
|
.build(ctx);
|
||||||
|
|
||||||
let content = GridBuilder::new(WidgetBuilder::new().with_child(grid).with_child(buttons))
|
let content = GridBuilder::new(
|
||||||
.add_column(Column::stretch())
|
WidgetBuilder::new()
|
||||||
.add_row(Row::stretch())
|
.with_child(search_bar)
|
||||||
.add_row(Row::auto())
|
.with_child(grid)
|
||||||
.build(ctx);
|
.with_child(buttons),
|
||||||
|
)
|
||||||
|
.add_column(Column::stretch())
|
||||||
|
.add_row(Row::auto())
|
||||||
|
.add_row(Row::stretch())
|
||||||
|
.add_row(Row::auto())
|
||||||
|
.build(ctx);
|
||||||
|
|
||||||
let window = WindowBuilder::new(WidgetBuilder::new().with_width(500.0).with_height(600.0))
|
let window = WindowBuilder::new(WidgetBuilder::new().with_width(500.0).with_height(600.0))
|
||||||
.with_content(content)
|
.with_content(content)
|
||||||
@@ -148,6 +197,8 @@ impl EntityCreator {
|
|||||||
cancel,
|
cancel,
|
||||||
selection: None,
|
selection: None,
|
||||||
mode: EntityCreatorMode::default(),
|
mode: EntityCreatorMode::default(),
|
||||||
|
search_bar,
|
||||||
|
groups_scroll_viewer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,14 +227,18 @@ impl EntityCreator {
|
|||||||
let mut groups = FxHashMap::default();
|
let mut groups = FxHashMap::default();
|
||||||
for (type_uuid, constructor) in constructors.iter() {
|
for (type_uuid, constructor) in constructors.iter() {
|
||||||
for (variant_index, variant) in constructor.variants.iter().enumerate() {
|
for (variant_index, variant) in constructor.variants.iter().enumerate() {
|
||||||
let item = make_tree_item(ui, &variant.name);
|
let item = make_tree_item(ui, variant.name.clone(), &variant.name);
|
||||||
self.items_map
|
self.items_map
|
||||||
.insert(item, ConstructorVariantId::new(type_uuid, variant_index));
|
.insert(item, ConstructorVariantId::new(type_uuid, variant_index));
|
||||||
if constructor.group.is_empty() {
|
if constructor.group.is_empty() {
|
||||||
ui.send(self.groups_tree, TreeRootMessage::AddItem(item));
|
ui.send(self.groups_tree, TreeRootMessage::AddItem(item));
|
||||||
} else {
|
} else {
|
||||||
let group = *groups.entry(constructor.group).or_insert_with(|| {
|
let group = *groups.entry(constructor.group).or_insert_with(|| {
|
||||||
let group = make_tree_item(ui, constructor.group);
|
let group = make_tree_item(
|
||||||
|
ui,
|
||||||
|
ImmutableString::new(constructor.group),
|
||||||
|
constructor.group,
|
||||||
|
);
|
||||||
ui.send(self.groups_tree, TreeRootMessage::AddItem(group));
|
ui.send(self.groups_tree, TreeRootMessage::AddItem(group));
|
||||||
group
|
group
|
||||||
});
|
});
|
||||||
@@ -216,6 +271,19 @@ impl EntityCreator {
|
|||||||
}
|
}
|
||||||
} else if let Some(ButtonMessage::Click) = message.data_from(self.cancel) {
|
} else if let Some(ButtonMessage::Click) = message.data_from(self.cancel) {
|
||||||
ui.send(self.window, WindowMessage::Close);
|
ui.send(self.window, WindowMessage::Close);
|
||||||
|
} else if let Some(SearchBarMessage::Text(filter_text)) = message.data_from(self.search_bar)
|
||||||
|
{
|
||||||
|
apply_filter_recursive(self.groups_tree.to_base(), &filter_text.to_lowercase(), ui);
|
||||||
|
|
||||||
|
// Bring first item of current selection in the view when clearing the filter.
|
||||||
|
if filter_text.is_empty() {
|
||||||
|
if let Some(first) = ui[self.groups_tree].selected.first() {
|
||||||
|
ui.send(
|
||||||
|
self.groups_scroll_viewer,
|
||||||
|
ScrollViewerMessage::BringIntoView(first.to_base()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -315,13 +383,23 @@ impl EntityCreator {
|
|||||||
&mut ui_scene.ui,
|
&mut ui_scene.ui,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let sub_graph = ui_scene.ui.take_reserve_sub_graph(ui_node_handle);
|
match self.mode {
|
||||||
let parent = if let Some(selection) = editor_selection.as_ui() {
|
EntityCreatorMode::CreateChild => {
|
||||||
selection.widgets.first().cloned().unwrap_or_default()
|
let sub_graph = ui_scene.ui.take_reserve_sub_graph(ui_node_handle);
|
||||||
} else {
|
let parent = if let Some(selection) = editor_selection.as_ui() {
|
||||||
Handle::NONE
|
selection.widgets.first().cloned().unwrap_or_default()
|
||||||
};
|
} else {
|
||||||
sender.do_command(AddWidgetCommand::new(sub_graph, parent, true));
|
Handle::NONE
|
||||||
|
};
|
||||||
|
sender.do_command(AddWidgetCommand::new(sub_graph, parent, true));
|
||||||
|
}
|
||||||
|
EntityCreatorMode::CreateParent => {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
EntityCreatorMode::CreateReplacement => {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use fyrox_core::uuid::Uuid;
|
|||||||
use fyrox_core::{
|
use fyrox_core::{
|
||||||
parking_lot::{Mutex, MutexGuard},
|
parking_lot::{Mutex, MutexGuard},
|
||||||
reflect::prelude::*,
|
reflect::prelude::*,
|
||||||
SafeLock,
|
ImmutableString, SafeLock,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ pub type VariantConstructor<Node, Ctx> = Arc<dyn Fn(&mut Ctx) -> VariantResult<N
|
|||||||
/// Constructor variant.
|
/// Constructor variant.
|
||||||
pub struct Variant<Node, Ctx> {
|
pub struct Variant<Node, Ctx> {
|
||||||
/// Name of the variant.
|
/// Name of the variant.
|
||||||
pub name: String,
|
pub name: ImmutableString,
|
||||||
/// Boxed type constructor.
|
/// Boxed type constructor.
|
||||||
pub constructor: VariantConstructor<Node, Ctx>,
|
pub constructor: VariantConstructor<Node, Ctx>,
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ impl<Node, Ctx> GraphNodeConstructor<Node, Ctx> {
|
|||||||
F: Fn(&mut Ctx) -> VariantResult<Node> + Send + Sync + 'static,
|
F: Fn(&mut Ctx) -> VariantResult<Node> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.variants.push(Variant {
|
self.variants.push(Variant {
|
||||||
name: name.as_ref().to_string(),
|
name: ImmutableString::new(name),
|
||||||
constructor: Arc::new(variant),
|
constructor: Arc::new(variant),
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
|
|||||||
Reference in New Issue
Block a user