Skip to content

Commit

Permalink
use brush resource in tile map editor + moved brush to engine
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Jul 9, 2024
1 parent a619639 commit 7aabb65
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 63 deletions.
17 changes: 17 additions & 0 deletions editor/src/inspector/editors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ use crate::{
},
message::MessageSender,
};
use fyrox::scene::tilemap::brush::{TileMapBrush, TileMapBrushResource};
use std::{path::Path, sync::Arc};

pub mod animation;
Expand Down Expand Up @@ -341,6 +342,22 @@ pub fn make_property_editors_container(sender: MessageSender) -> PropertyEditorD
container.insert(InheritablePropertyEditorDefinition::<Option<ShaderResource>>::new());
container.register_inheritable_vec_collection::<Option<ShaderResource>>();

container.insert(ResourceFieldPropertyEditorDefinition::<TileMapBrush>::new(
Arc::new(Mutex::new(
|resource_manager: &ResourceManager, path: &Path| {
resource_manager
.try_request::<TileMapBrush>(path)
.map(block_on)
},
)),
sender.clone(),
));
container.insert(InheritablePropertyEditorDefinition::<
Option<TileMapBrushResource>,
>::new());
container.register_inheritable_vec_collection::<Option<TileMapBrushResource>>();
container.register_inheritable_inspectable::<TileMapBrush>();

container.register_inheritable_inspectable::<ColorGradingLut>();
container.register_inheritable_inspectable::<InteractionGroups>();

Expand Down
53 changes: 34 additions & 19 deletions editor/src/plugins/tilemap/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod brush;
pub mod palette;
pub mod panel;
pub mod tile_set_import;
Expand All @@ -25,18 +24,13 @@ use crate::{
scene::{
debug::Line,
node::Node,
tilemap::{Tile, TileMap, Tiles},
tilemap::{brush::TileMapBrush, Tile, TileMap, Tiles},
},
},
interaction::{make_interaction_mode_button, InteractionMode},
message::MessageSender,
plugin::EditorPlugin,
plugins::tilemap::{
brush::{TileMapBrush, TileMapBrushLoader},
palette::PaletteMessage,
panel::TileMapPanel,
tileset::TileSetEditor,
},
plugins::tilemap::{palette::PaletteMessage, panel::TileMapPanel, tileset::TileSetEditor},
scene::{commands::GameSceneContext, controller::SceneController, GameScene, Selection},
settings::Settings,
Editor, Message,
Expand Down Expand Up @@ -256,17 +250,37 @@ pub struct TileMapEditorPlugin {
}

impl EditorPlugin for TileMapEditorPlugin {
fn on_start(&mut self, editor: &mut Editor) {
let mut resource_manager = editor.engine.resource_manager.state();
resource_manager
.constructors_container
.add::<TileMapBrush>();
resource_manager.loaders.set(TileMapBrushLoader {});
}

fn on_sync_to_model(&mut self, editor: &mut Editor) {
let ui = editor.engine.user_interfaces.first_mut();

if let Some(tile_set_editor) = self.tile_set_editor.as_mut() {
tile_set_editor.sync_to_model(editor.engine.user_interfaces.first_mut());
tile_set_editor.sync_to_model(ui);
}

let Some(entry) = editor.scenes.current_scene_entry_mut() else {
return;
};

let Some(selection) = entry.selection.as_graph() else {
return;
};

let Some(game_scene) = entry.controller.downcast_mut::<GameScene>() else {
return;
};

let scene = &mut editor.engine.scenes[game_scene.scene];

for node_handle in selection.nodes().iter() {
if let Some(tile_map_node) = scene.graph.try_get(*node_handle) {
let Some(tile_map) = tile_map_node.component_ref::<TileMap>() else {
continue;
};

if let Some(panel) = self.panel.as_mut() {
panel.sync_to_model(ui, tile_map);
}
}
}
}

Expand All @@ -283,7 +297,7 @@ impl EditorPlugin for TileMapEditorPlugin {
}

if let Some(panel) = self.panel.take() {
if let Some(PaletteMessage::Brush(brush)) = message.data() {
if let Some(PaletteMessage::ActiveBrush(brush)) = message.data() {
if message.destination() == panel.palette {
*self.brush.lock() = brush.clone();
}
Expand Down Expand Up @@ -347,7 +361,8 @@ impl EditorPlugin for TileMapEditorPlugin {
self.panel = Some(TileMapPanel::new(
&mut ui.build_ctx(),
editor.scene_viewer.frame(),
tile_map.tile_set().cloned(),
editor.engine.resource_manager.clone(),
tile_map,
));

break;
Expand Down
165 changes: 151 additions & 14 deletions editor/src/plugins/tilemap/palette.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::{
absm::selectable::{Selectable, SelectableMessage},
asset::item::AssetItem,
fyrox::{
asset::manager::ResourceManager,
core::{
algebra::{Matrix3, Point2, Vector2},
color::Color,
math::Rect,
math::{OptionRect, Rect},
pool::Handle,
reflect::prelude::*,
type_traits::prelude::*,
Expand All @@ -19,20 +21,27 @@ use crate::{
widget::{Widget, WidgetBuilder, WidgetMessage},
BuildContext, Control, UiNode, UserInterface,
},
scene::tilemap::tileset::TileSetResource,
scene::tilemap::{
brush::{BrushTile, TileMapBrush, TileMapBrushResource},
tileset::TileSetResource,
},
},
plugins::tilemap::brush::{BrushTile, TileMapBrush},
};
use fyrox::core::math::OptionRect;
use fyrox::core::log::Log;
use fyrox::scene::tilemap::tileset::TileSet;
use std::ops::{Deref, DerefMut};

#[derive(Debug, PartialEq, Clone)]
pub enum PaletteMessage {
Brush(TileMapBrush),
ActiveBrush(TileMapBrush),
BrushResource(Option<TileMapBrushResource>),
TileSet(Option<TileSetResource>),
}

impl PaletteMessage {
define_constructor!(PaletteMessage:Brush => fn brush(TileMapBrush), layout: false);
define_constructor!(PaletteMessage:ActiveBrush => fn active_brush(TileMapBrush), layout: false);
define_constructor!(PaletteMessage:BrushResource => fn brush_resource(Option<TileMapBrushResource>), layout: false);
define_constructor!(PaletteMessage:TileSet => fn tile_set(Option<TileSetResource>), layout: false);
}

#[derive(Debug, Clone, PartialEq, Visit, Reflect, Default)]
Expand Down Expand Up @@ -70,6 +79,11 @@ pub struct PaletteWidget {
tile_size: Vector2<f32>,
selection: Vec<Handle<UiNode>>,
mode: Mode,
tile_set: Option<TileSetResource>,
brush_resource: Option<TileMapBrushResource>,
#[visit(skip)]
#[reflect(hidden)]
resource_manager: ResourceManager,
}

define_widget_deref!(PaletteWidget);
Expand Down Expand Up @@ -160,7 +174,7 @@ impl PaletteWidget {

self.selection = new_selection.to_vec();

ui.send_message(PaletteMessage::brush(
ui.send_message(PaletteMessage::active_brush(
self.handle(),
MessageDirection::FromWidget,
self.selected_tiles_to_brush(ui),
Expand All @@ -179,6 +193,50 @@ impl PaletteWidget {
(pos.y / self.tile_size.y) as i32,
)
}

fn recreate_tiles(&mut self, ui: &mut UserInterface) {
for &tile in self.children() {
ui.send_message(WidgetMessage::remove(tile, MessageDirection::ToWidget));
}

if let Some(tile_set) = self.tile_set.as_ref() {
if let Some(brush_resource) = self.brush_resource.as_ref() {
let brush = brush_resource.data_ref();
self.tiles = generate_tiles(tile_set.clone(), &brush, &mut ui.build_ctx());

for &tile in &self.tiles {
ui.send_message(WidgetMessage::link(
tile,
MessageDirection::ToWidget,
self.handle,
));
}
}
}
}

fn save_brush(&self) {
if let Some(active_brush) = self.brush_resource.as_ref() {
Log::verify(active_brush.save_back())
}
}
}

fn generate_tiles(
tile_set_resource: TileSetResource,
tile_map_brush: &TileMapBrush,
ctx: &mut BuildContext,
) -> Vec<Handle<UiNode>> {
tile_map_brush
.tiles
.iter()
.map(|tile| {
TileViewBuilder::new(tile_set_resource.clone(), WidgetBuilder::new())
.with_definition_index(tile.definition_index)
.with_position(tile.local_position)
.build(ctx)
})
.collect::<Vec<_>>()
}

impl Control for PaletteWidget {
Expand Down Expand Up @@ -377,41 +435,120 @@ impl Control for PaletteWidget {
{
self.selection.remove(position);
}
} else if let Some(WidgetMessage::Drop(dropped)) = message.data() {
if message.destination() == self.handle {
if let Some(item) = ui.node(*dropped).cast::<AssetItem>() {
if let Some(brush) = item.resource::<TileMapBrush>(&self.resource_manager) {
ui.send_message(PaletteMessage::brush_resource(
self.handle,
MessageDirection::ToWidget,
Some(brush),
));
} else if let Some(tile_set) = item.resource::<TileSet>(&self.resource_manager)
{
if let Some(active_brush) = self.brush_resource.as_ref() {
let tile_set = tile_set.data_ref();
let tiles = tile_set
.tiles
.iter()
.enumerate()
.map(|(index, _tile)| {
let side_size = 11;

BrushTile {
definition_index: index,
local_position: Vector2::new(
index as i32 % side_size,
index as i32 / side_size,
),
}
})
.collect::<Vec<_>>();
active_brush.data_ref().tiles = tiles;
self.save_brush();
self.recreate_tiles(ui);
}
}
}
}
} else if let Some(msg) = message.data::<PaletteMessage>() {
if message.destination() == self.handle {
match msg {
PaletteMessage::BrushResource(brush_resource) => {
if &self.brush_resource != brush_resource {
self.brush_resource.clone_from(brush_resource);
self.recreate_tiles(ui);
}
}
PaletteMessage::ActiveBrush(_) => {
// Nothing to do.
}
PaletteMessage::TileSet(tile_set) => {
if &self.tile_set != tile_set {
self.tile_set.clone_from(tile_set);
self.recreate_tiles(ui);
}
}
}
}
}
}
}

pub struct PaletteWidgetBuilder {
widget_builder: WidgetBuilder,
tiles: Vec<Handle<UiNode>>,
brush: Option<TileMapBrushResource>,
tile_set: Option<TileSetResource>,
}

impl PaletteWidgetBuilder {
pub fn new(widget_builder: WidgetBuilder) -> Self {
Self {
widget_builder,
tiles: Default::default(),
brush: None,
tile_set: None,
}
}

pub fn with_tiles(mut self, tiles: Vec<Handle<UiNode>>) -> Self {
self.tiles = tiles;
pub fn with_brush(mut self, brush: Option<TileMapBrushResource>) -> Self {
self.brush = brush;
self
}

pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
pub fn with_tile_set(mut self, tile_set_resource: Option<TileSetResource>) -> Self {
self.tile_set = tile_set_resource;
self
}

pub fn build(
self,
resource_manager: ResourceManager,
ctx: &mut BuildContext,
) -> Handle<UiNode> {
let mut tiles = Vec::default();
if let Some(brush) = self.brush.as_ref() {
let brush = brush.data_ref();
if let Some(tile_set_resource) = self.tile_set.as_ref() {
tiles = generate_tiles(tile_set_resource.clone(), &brush, ctx);
}
}

ctx.add_node(UiNode::new(PaletteWidget {
widget: self
.widget_builder
.with_allow_drop(true)
.with_clip_to_bounds(false)
.with_children(self.tiles.iter().cloned())
.with_children(tiles.iter().cloned())
.build(),
tiles: self.tiles,
tiles,
view_position: Default::default(),
zoom: 1.0,
tile_size: Vector2::repeat(32.0),
selection: Default::default(),
mode: Mode::None,
tile_set: self.tile_set,
brush_resource: self.brush,
resource_manager,
}))
}
}
Expand Down
Loading

0 comments on commit 7aabb65

Please sign in to comment.