Skip to content

Commit

Permalink
ability to add tiles into tile set resource by drag'n'droping an asset
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Jun 30, 2024
1 parent 2f2fd72 commit cb1e659
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 20 deletions.
14 changes: 12 additions & 2 deletions editor/src/plugins/tilemap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,18 @@ pub struct TileMapEditorPlugin {
impl EditorPlugin for TileMapEditorPlugin {
fn on_ui_message(&mut self, message: &mut UiMessage, editor: &mut Editor) {
if let Some(tile_set_editor) = self.tile_set_editor.take() {
self.tile_set_editor =
tile_set_editor.handle_ui_message(message, editor.engine.user_interfaces.first());
self.tile_set_editor = tile_set_editor.handle_ui_message(
message,
editor.engine.user_interfaces.first(),
&editor.engine.resource_manager,
&editor.message_sender,
);
}
}

fn on_sync_to_model(&mut self, editor: &mut Editor) {
if let Some(tile_set_editor) = self.tile_set_editor.as_mut() {
tile_set_editor.sync_to_model(editor.engine.user_interfaces.first_mut());
}
}

Expand Down
191 changes: 173 additions & 18 deletions editor/src/plugins/tilemap/tileset.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
use crate::fyrox::{
core::pool::Handle,
gui::{
button::ButtonBuilder,
grid::{Column, GridBuilder, Row},
list_view::ListViewBuilder,
message::{MessageDirection, UiMessage},
stack_panel::StackPanelBuilder,
utils::make_simple_tooltip,
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
wrap_panel::WrapPanelBuilder,
BuildContext, Orientation, Thickness, UiNode, UserInterface,
use crate::{
asset::item::AssetItem,
command::{CommandContext, CommandTrait},
fyrox::{
asset::{manager::ResourceManager, untyped::ResourceKind},
core::{futures::executor::block_on, make_relative_path, math::Rect, pool::Handle, Uuid},
graph::{BaseSceneGraph, SceneGraphNode},
gui::{
button::ButtonBuilder,
grid::{Column, GridBuilder, Row},
image::ImageBuilder,
list_view::{ListView, ListViewBuilder, ListViewMessage},
message::{MessageDirection, UiMessage},
stack_panel::StackPanelBuilder,
utils::make_simple_tooltip,
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
wrap_panel::WrapPanelBuilder,
BuildContext, Orientation, Thickness, UiNode, UserInterface,
},
material::{Material, MaterialResource},
resource::texture::Texture,
scene::tilemap::tileset::{TileDefinition, TileSetResource},
},
scene::tilemap::tileset::TileSetResource,
message::MessageSender,
};
use fyrox::material::PropertyValue;

#[allow(dead_code)]
pub struct TileSetEditor {
Expand Down Expand Up @@ -46,7 +57,8 @@ impl TileSetEditor {
let tiles = ListViewBuilder::new(
WidgetBuilder::new()
.on_row(1)
.with_margin(Thickness::uniform(1.0)),
.with_margin(Thickness::uniform(1.0))
.with_allow_drop(true),
)
.with_items_panel(
WrapPanelBuilder::new(WidgetBuilder::new())
Expand Down Expand Up @@ -76,11 +88,15 @@ impl TileSetEditor {
))
.unwrap();

Self {
let mut editor = Self {
window,
tiles,
tile_set,
}
};

editor.sync_to_model(ctx.inner_mut());

editor
}

fn destroy(self, ui: &UserInterface) {
Expand All @@ -90,16 +106,155 @@ impl TileSetEditor {
));
}

pub fn handle_ui_message(self, message: &UiMessage, ui: &UserInterface) -> Option<Self> {
pub fn sync_to_model(&mut self, ui: &mut UserInterface) {
let tile_set = self.tile_set.data_ref();
let tile_views = ui
.node(self.tiles)
.component_ref::<ListView>()
.unwrap()
.items
.clone();

for tile_view in tile_views.iter() {
if tile_set
.tiles
.iter()
.all(|tile| tile.id != ui.node(*tile_view).id)
{
ui.send_message(ListViewMessage::remove_item(
self.tiles,
MessageDirection::ToWidget,
*tile_view,
));
}
}

for tile in tile_set.tiles.iter() {
if tile_views
.iter()
.all(|tile_view| ui.node(*tile_view).id != tile.id)
{
let texture =
tile.material
.data_ref()
.properties()
.iter()
.find_map(|(name, value)| {
if name.as_str() == "diffuseTexture" {
if let PropertyValue::Sampler { value, .. } = value {
return value.clone();
}
}
None
});

let tile_view = ImageBuilder::new(
WidgetBuilder::new()
.with_width(32.0)
.with_height(32.0)
.with_id(tile.id),
)
.with_opt_texture(texture.map(|t| t.into()))
.build(&mut ui.build_ctx());

ui.send_message(ListViewMessage::add_item(
self.tiles,
MessageDirection::ToWidget,
tile_view,
));
}
}
}

pub fn handle_ui_message(
self,
message: &UiMessage,
ui: &UserInterface,
resource_manager: &ResourceManager,
sender: &MessageSender,
) -> Option<Self> {
if let Some(WindowMessage::Close) = message.data() {
if message.destination() == self.window
&& message.direction() == MessageDirection::FromWidget
{
self.destroy(ui);
return None;
}
} else if let Some(WidgetMessage::Drop(dropped)) = message.data() {
if message.destination() == self.tiles {
if let Some(item) = ui.node(*dropped).cast::<AssetItem>() {
let path = if resource_manager
.state()
.built_in_resources
.contains_key(&item.path)
{
Ok(item.path.clone())
} else {
make_relative_path(&item.path)
};

if let Ok(path) = path {
if let Some(material) = resource_manager.try_request::<Material>(&path) {
if let Ok(material) = block_on(material) {
sender.do_command(AddTileCommand {
tile_set: self.tile_set.clone(),
tile: TileDefinition {
material,
uv_rect: Rect::new(0.0, 0.0, 1.0, 1.0),
collider: Default::default(),
color: Default::default(),
id: Uuid::new_v4(),
},
});
}
} else if let Some(texture) = resource_manager.try_request::<Texture>(&path)
{
if let Ok(texture) = block_on(texture) {
let mut material = Material::standard_2d();
material
.set_texture(&"diffuseTexture".into(), Some(texture))
.unwrap();

let material =
MaterialResource::new_ok(ResourceKind::Embedded, material);

sender.do_command(AddTileCommand {
tile_set: self.tile_set.clone(),
tile: TileDefinition {
material,
uv_rect: Rect::new(0.0, 0.0, 1.0, 1.0),
collider: Default::default(),
color: Default::default(),
id: Uuid::new_v4(),
},
});
}
}
}
}
}
}

Some(self)
}
}

#[derive(Debug)]
pub struct AddTileCommand {
tile_set: TileSetResource,
tile: TileDefinition,
}

impl CommandTrait for AddTileCommand {
fn name(&mut self, _context: &dyn CommandContext) -> String {
"Add Tile".into()
}

fn execute(&mut self, _context: &mut dyn CommandContext) {
self.tile_set.data_ref().tiles.push(self.tile.clone());
}

fn revert(&mut self, _context: &mut dyn CommandContext) {
self.tile = self.tile_set.data_ref().tiles.pop().unwrap();
}
}
1 change: 1 addition & 0 deletions fyrox-impl/src/scene/tilemap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl TileMapBuilder {
uv_rect: Rect::new(0.0, 0.0, 1.0, 1.0),
collider: Default::default(),
color: Default::default(),
id: Uuid::new_v4(),
}],
};

Expand Down
1 change: 1 addition & 0 deletions fyrox-impl/src/scene/tilemap/tileset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub struct TileDefinition {
pub uv_rect: Rect<f32>,
pub collider: TileCollider,
pub color: Color,
pub id: Uuid,
}

#[derive(Clone, Default, Debug, Reflect, Visit, TypeUuidProvider, ComponentProvider)]
Expand Down

0 comments on commit cb1e659

Please sign in to comment.