moved resourcecreator into a separate mod

This commit is contained in:
Dmitry Stepanov
2025-05-03 15:05:43 +03:00
parent a28ca35766
commit b987915ce7
2 changed files with 278 additions and 239 deletions
+272
View File
@@ -0,0 +1,272 @@
// 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::{
manager::ResourceManager,
untyped::{ResourceKind, UntypedResource},
},
core::{log::Log, pool::Handle, Uuid},
engine::Engine,
gui::{
button::{ButtonBuilder, ButtonMessage},
grid::{Column, GridBuilder, Row},
list_view::{ListViewBuilder, ListViewMessage},
message::{MessageDirection, UiMessage},
stack_panel::StackPanelBuilder,
text::TextMessage,
text_box::TextBoxBuilder,
utils::make_dropdown_list_option,
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
BuildContext, HorizontalAlignment, Orientation, Thickness, UiNode, UserInterface,
},
},
message::MessageSender,
Message,
};
use std::path::{Path, PathBuf};
pub struct ResourceCreator {
pub window: Handle<UiNode>,
resource_constructors_list: Handle<UiNode>,
ok: Handle<UiNode>,
cancel: Handle<UiNode>,
name: Handle<UiNode>,
selected: Option<usize>,
supported_resource_data_uuids: Vec<Uuid>,
name_str: String,
}
impl ResourceCreator {
pub fn new(ctx: &mut BuildContext, resource_manager: &ResourceManager) -> Self {
let rm_state = resource_manager.state();
let mut constructors = rm_state.constructors_container.map.lock();
let mut items = Vec::new();
let mut supported_resource_data_uuids = Vec::new();
for (uuid, constructor) in constructors.iter_mut() {
let instance = (constructor.callback)();
if instance.can_be_saved() {
supported_resource_data_uuids.push(*uuid);
items.push(make_dropdown_list_option(ctx, &constructor.type_name))
}
}
let name_str = String::from("unnamed_resource");
let name;
let ok;
let cancel;
let resource_constructors_list;
let window = WindowBuilder::new(WidgetBuilder::new().with_width(300.0).with_height(400.0))
.with_title(WindowTitle::text("Resource Creator"))
.open(false)
.with_content(
GridBuilder::new(
WidgetBuilder::new()
.with_child({
name = TextBoxBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(0))
.on_row(0)
.with_height(22.0)
.with_margin(Thickness::uniform(1.0)),
)
.with_text(&name_str)
.build(ctx);
name
})
.with_child({
resource_constructors_list = ListViewBuilder::new(
WidgetBuilder::new().with_tab_index(Some(1)).on_row(1),
)
.with_items(items)
.build(ctx);
resource_constructors_list
})
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Right)
.on_row(2)
.with_child({
ok = ButtonBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(2))
.with_enabled(false)
.with_width(100.0)
.with_height(22.0),
)
.with_text("OK")
.build(ctx);
ok
})
.with_child({
cancel = ButtonBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(3))
.with_width(100.0)
.with_height(22.0),
)
.with_text("Cancel")
.build(ctx);
cancel
}),
)
.with_orientation(Orientation::Horizontal)
.build(ctx),
),
)
.add_row(Row::auto())
.add_row(Row::stretch())
.add_row(Row::auto())
.add_column(Column::stretch())
.build(ctx),
)
.build(ctx);
Self {
window,
resource_constructors_list,
ok,
cancel,
name,
selected: None,
name_str,
supported_resource_data_uuids,
}
}
pub fn open(&self, ui: &UserInterface) {
ui.send_message(WindowMessage::open_modal(
self.window,
MessageDirection::ToWidget,
true,
true,
));
}
#[must_use]
pub fn handle_ui_message(
&mut self,
message: &UiMessage,
engine: &mut Engine,
sender: MessageSender,
base_path: &Path,
) -> bool {
let mut asset_added = false;
if let Some(ListViewMessage::SelectionChanged(selection)) = message.data() {
if message.destination() == self.resource_constructors_list
&& message.direction() == MessageDirection::FromWidget
{
self.selected = selection.first().cloned();
engine
.user_interfaces
.first_mut()
.send_message(WidgetMessage::enabled(
self.ok,
MessageDirection::ToWidget,
true,
));
// Propose extension for the resource.
let resource_manager_state = engine.resource_manager.state();
if let Some(data_type_uuid) = self
.supported_resource_data_uuids
.get(self.selected.unwrap_or_default())
{
let loaders = resource_manager_state.loaders.lock();
if let Some(loader) = loaders
.iter()
.find(|loader| &loader.data_type_uuid() == data_type_uuid)
{
if let Some(first) = loader.extensions().first() {
let mut path = PathBuf::from(&self.name_str);
path.set_extension(first);
self.name_str = path.to_string_lossy().to_string();
engine
.user_interfaces
.first_mut()
.send_message(TextMessage::text(
self.name,
MessageDirection::ToWidget,
self.name_str.clone(),
));
}
};
}
}
} else if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.ok {
let resource_manager_state = engine.resource_manager.state();
let mut constructors = resource_manager_state.constructors_container.map.lock();
if let Some(mut instance) = self
.supported_resource_data_uuids
.get(self.selected.unwrap_or_default())
.and_then(|uuid| constructors.get_mut(uuid))
.map(|c| c.create_instance())
{
let path = base_path.join(&self.name_str);
match instance.save(&path) {
Ok(_) => {
let resource = UntypedResource::new_ok_untyped(
Uuid::new_v4(),
ResourceKind::External,
instance,
);
drop(constructors);
drop(resource_manager_state);
Log::verify(engine.resource_manager.register(resource, path));
sender.send(Message::ForceSync);
asset_added = true;
}
Err(e) => Log::err(format!("Unable to create a resource. Reason: {e:?}")),
}
}
}
if message.destination() == self.ok || message.destination() == self.cancel {
engine
.user_interfaces
.first_mut()
.send_message(WindowMessage::close(
self.window,
MessageDirection::ToWidget,
));
}
} else if let Some(TextMessage::Text(text)) = message.data() {
if message.destination() == self.name
&& message.direction() == MessageDirection::FromWidget
{
self.name_str.clone_from(text);
}
}
asset_added
}
}
+6 -239
View File
@@ -20,6 +20,7 @@
use crate::{
asset::{
creator::ResourceCreator,
dependency::DependencyViewer,
inspector::AssetInspector,
item::{AssetItem, AssetItemBuilder, AssetItemMessage},
@@ -29,11 +30,8 @@ use crate::{
},
},
fyrox::{
asset::{
manager::ResourceManager,
untyped::{ResourceKind, UntypedResource},
},
core::{futures::executor::block_on, log::Log, make_relative_path, pool::Handle, Uuid},
asset::manager::ResourceManager,
core::{futures::executor::block_on, log::Log, make_relative_path, pool::Handle},
engine::Engine,
graph::BaseSceneGraph,
gui::{
@@ -42,18 +40,13 @@ use crate::{
dock::{DockingManagerBuilder, TileBuilder, TileContent},
file_browser::{FileBrowserBuilder, FileBrowserMessage, Filter},
grid::{Column, GridBuilder, Row},
list_view::{ListViewBuilder, ListViewMessage},
menu::{ContextMenuBuilder, MenuItemBuilder, MenuItemContent, MenuItemMessage},
message::{MessageDirection, UiMessage},
popup::{Placement, PopupBuilder, PopupMessage},
scroll_viewer::{ScrollViewerBuilder, ScrollViewerMessage},
searchbar::{SearchBarBuilder, SearchBarMessage},
stack_panel::StackPanelBuilder,
text::TextMessage,
text_box::TextBoxBuilder,
utils::{
make_dropdown_list_option, make_image_button_with_tooltip, make_simple_tooltip,
},
utils::{make_image_button_with_tooltip, make_simple_tooltip},
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
wrap_panel::WrapPanelBuilder,
@@ -66,10 +59,9 @@ use crate::{
message::MessageSender,
preview::PreviewPanel,
utils::window_content,
Message, Mode,
Mode,
};
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::{
ffi::OsStr,
fs::File,
@@ -82,6 +74,7 @@ use std::{
},
};
mod creator;
mod dependency;
mod inspector;
pub mod item;
@@ -307,232 +300,6 @@ impl ContextMenu {
}
}
struct ResourceCreator {
window: Handle<UiNode>,
resource_constructors_list: Handle<UiNode>,
ok: Handle<UiNode>,
cancel: Handle<UiNode>,
name: Handle<UiNode>,
selected: Option<usize>,
supported_resource_data_uuids: Vec<Uuid>,
name_str: String,
}
impl ResourceCreator {
pub fn new(ctx: &mut BuildContext, resource_manager: &ResourceManager) -> Self {
let rm_state = resource_manager.state();
let mut constructors = rm_state.constructors_container.map.lock();
let mut items = Vec::new();
let mut supported_resource_data_uuids = Vec::new();
for (uuid, constructor) in constructors.iter_mut() {
let instance = (constructor.callback)();
if instance.can_be_saved() {
supported_resource_data_uuids.push(*uuid);
items.push(make_dropdown_list_option(ctx, &constructor.type_name))
}
}
let name_str = String::from("unnamed_resource");
let name;
let ok;
let cancel;
let resource_constructors_list;
let window = WindowBuilder::new(WidgetBuilder::new().with_width(300.0).with_height(400.0))
.with_title(WindowTitle::text("Resource Creator"))
.open(false)
.with_content(
GridBuilder::new(
WidgetBuilder::new()
.with_child({
name = TextBoxBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(0))
.on_row(0)
.with_height(22.0)
.with_margin(Thickness::uniform(1.0)),
)
.with_text(&name_str)
.build(ctx);
name
})
.with_child({
resource_constructors_list = ListViewBuilder::new(
WidgetBuilder::new().with_tab_index(Some(1)).on_row(1),
)
.with_items(items)
.build(ctx);
resource_constructors_list
})
.with_child(
StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Right)
.on_row(2)
.with_child({
ok = ButtonBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(2))
.with_enabled(false)
.with_width(100.0)
.with_height(22.0),
)
.with_text("OK")
.build(ctx);
ok
})
.with_child({
cancel = ButtonBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(3))
.with_width(100.0)
.with_height(22.0),
)
.with_text("Cancel")
.build(ctx);
cancel
}),
)
.with_orientation(Orientation::Horizontal)
.build(ctx),
),
)
.add_row(Row::auto())
.add_row(Row::stretch())
.add_row(Row::auto())
.add_column(Column::stretch())
.build(ctx),
)
.build(ctx);
Self {
window,
resource_constructors_list,
ok,
cancel,
name,
selected: None,
name_str,
supported_resource_data_uuids,
}
}
fn open(&self, ui: &UserInterface) {
ui.send_message(WindowMessage::open_modal(
self.window,
MessageDirection::ToWidget,
true,
true,
));
}
#[must_use]
fn handle_ui_message(
&mut self,
message: &UiMessage,
engine: &mut Engine,
sender: MessageSender,
base_path: &Path,
) -> bool {
let mut asset_added = false;
if let Some(ListViewMessage::SelectionChanged(selection)) = message.data() {
if message.destination() == self.resource_constructors_list
&& message.direction() == MessageDirection::FromWidget
{
self.selected = selection.first().cloned();
engine
.user_interfaces
.first_mut()
.send_message(WidgetMessage::enabled(
self.ok,
MessageDirection::ToWidget,
true,
));
// Propose extension for the resource.
let resource_manager_state = engine.resource_manager.state();
if let Some(data_type_uuid) = self
.supported_resource_data_uuids
.get(self.selected.unwrap_or_default())
{
let loaders = resource_manager_state.loaders.lock();
if let Some(loader) = loaders
.iter()
.find(|loader| &loader.data_type_uuid() == data_type_uuid)
{
if let Some(first) = loader.extensions().first() {
let mut path = PathBuf::from(&self.name_str);
path.set_extension(first);
self.name_str = path.to_string_lossy().to_string();
engine
.user_interfaces
.first_mut()
.send_message(TextMessage::text(
self.name,
MessageDirection::ToWidget,
self.name_str.clone(),
));
}
};
}
}
} else if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.ok {
let resource_manager_state = engine.resource_manager.state();
let mut constructors = resource_manager_state.constructors_container.map.lock();
if let Some(mut instance) = self
.supported_resource_data_uuids
.get(self.selected.unwrap_or_default())
.and_then(|uuid| constructors.get_mut(uuid))
.map(|c| c.create_instance())
{
let path = base_path.join(&self.name_str);
match instance.save(&path) {
Ok(_) => {
let resource = UntypedResource::new_ok_untyped(
Uuid::new_v4(),
ResourceKind::External,
instance,
);
drop(constructors);
drop(resource_manager_state);
Log::verify(engine.resource_manager.register(resource, path));
sender.send(Message::ForceSync);
asset_added = true;
}
Err(e) => Log::err(format!("Unable to create a resource. Reason: {e:?}")),
}
}
}
if message.destination() == self.ok || message.destination() == self.cancel {
engine
.user_interfaces
.first_mut()
.send_message(WindowMessage::close(
self.window,
MessageDirection::ToWidget,
));
}
} else if let Some(TextMessage::Text(text)) = message.data() {
if message.destination() == self.name
&& message.direction() == MessageDirection::FromWidget
{
self.name_str.clone_from(text);
}
}
asset_added
}
}
pub struct AssetBrowser {
pub window: Handle<UiNode>,
pub docking_manager: Handle<UiNode>,