From 3c988af08d169439a346f76d2e0ffa120ba9f67e Mon Sep 17 00:00:00 2001 From: Dmitry Stepanov Date: Fri, 5 Jul 2024 10:32:34 +0300 Subject: [PATCH] draw grid in tile map edit mode + basic brush support --- editor/src/plugins/tilemap/brush.rs | 55 +++++++++++++++++++ editor/src/plugins/tilemap/mod.rs | 85 +++++++++++++++++++++++++---- 2 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 editor/src/plugins/tilemap/brush.rs diff --git a/editor/src/plugins/tilemap/brush.rs b/editor/src/plugins/tilemap/brush.rs new file mode 100644 index 000000000..0eef3d9ca --- /dev/null +++ b/editor/src/plugins/tilemap/brush.rs @@ -0,0 +1,55 @@ +use crate::fyrox::{ + core::{ + algebra::{Matrix4, Vector2, Vector3}, + color::Color, + }, + scene::{debug::SceneDrawingContext, tilemap::tileset::TileDefinition}, +}; + +#[allow(dead_code)] // TODO +#[derive(Default)] +pub struct BrushTile { + definition: TileDefinition, + local_position: Vector2, +} + +impl BrushTile { + pub fn draw_outline( + &self, + ctx: &mut SceneDrawingContext, + position: Vector2, + world_transform: &Matrix4, + color: Color, + ) { + ctx.draw_rectangle( + 0.5, + 0.5, + Matrix4::new_translation( + &((self.local_position + position) + .cast::() + .to_homogeneous() + + Vector3::new(0.5, 0.5, 0.0)), + ) * world_transform, + color, + ); + } +} + +#[derive(Default)] +pub struct Brush { + tiles: Vec, +} + +impl Brush { + pub fn draw_outline( + &self, + ctx: &mut SceneDrawingContext, + position: Vector2, + world_transform: &Matrix4, + color: Color, + ) { + for tile in self.tiles.iter() { + tile.draw_outline(ctx, position, world_transform, color); + } + } +} diff --git a/editor/src/plugins/tilemap/mod.rs b/editor/src/plugins/tilemap/mod.rs index d0a2f8db7..e517c8282 100644 --- a/editor/src/plugins/tilemap/mod.rs +++ b/editor/src/plugins/tilemap/mod.rs @@ -1,24 +1,34 @@ +pub mod brush; mod tile_set_import; pub mod tileset; use crate::{ fyrox::{ - core::{algebra::Vector2, pool::Handle, type_traits::prelude::*, Uuid}, + core::{ + algebra::{Vector2, Vector3}, + color::Color, + math::plane::Plane, + parking_lot::Mutex, + pool::Handle, + type_traits::prelude::*, + Uuid, + }, engine::Engine, graph::{BaseSceneGraph, SceneGraphNode}, gui::{ button::ButtonBuilder, message::UiMessage, utils::make_simple_tooltip, widget::WidgetBuilder, BuildContext, Thickness, UiNode, }, - scene::{node::Node, tilemap::TileMap}, + scene::{debug::Line, node::Node, tilemap::TileMap}, }, interaction::{make_interaction_mode_button, InteractionMode}, plugin::EditorPlugin, - plugins::tilemap::tileset::TileSetEditor, + plugins::tilemap::{brush::Brush, tileset::TileSetEditor}, scene::{controller::SceneController, GameScene, Selection}, settings::Settings, Editor, Message, }; +use std::sync::Arc; fn make_button( title: &str, @@ -43,6 +53,8 @@ fn make_button( pub struct TileMapInteractionMode { #[allow(dead_code)] tile_map: Handle, + brush: Arc>, + brush_position: Vector2, } impl InteractionMode for TileMapInteractionMode { @@ -73,14 +85,30 @@ impl InteractionMode for TileMapInteractionMode { fn on_mouse_move( &mut self, _mouse_offset: Vector2, - _mouse_position: Vector2, + mouse_position: Vector2, _editor_selection: &Selection, - _controller: &mut dyn SceneController, - _engine: &mut Engine, - _frame_size: Vector2, + controller: &mut dyn SceneController, + engine: &mut Engine, + frame_size: Vector2, _settings: &Settings, ) { - // TODO + let Some(game_scene) = controller.downcast_mut::() else { + return; + }; + + let scene = &mut engine.scenes[game_scene.scene]; + + let camera = scene.graph[game_scene.camera_controller.camera].as_camera(); + let ray = camera.make_ray(mouse_position, frame_size); + + // TODO: This does not take global transform of the tile map into account! + let plane = Plane::from_normal_and_point(&Vector3::new(0.0, 0.0, 1.0), &Default::default()) + .unwrap_or_default(); + + if let Some(intersection) = ray.plane_intersection_point(&plane) { + let grid_coord = Vector2::new(intersection.x as i32, intersection.y as i32); + self.brush_position = grid_coord; + } } fn update( @@ -94,7 +122,39 @@ impl InteractionMode for TileMapInteractionMode { return; }; - let _scene = &mut engine.scenes[game_scene.scene]; + let scene = &mut engine.scenes[game_scene.scene]; + + let Some(tile_map) = scene.graph.try_get(self.tile_map) else { + return; + }; + + let transform = tile_map.global_transform(); + + let mut draw_line = |begin: Vector2, end: Vector2, color: Color| { + scene.drawing_context.add_line(Line { + begin: transform + .transform_point(&Vector3::new(begin.x as f32, begin.y as f32, 0.0).into()) + .coords, + end: transform + .transform_point(&Vector3::new(end.x as f32, end.y as f32, 0.0).into()) + .coords, + color, + }); + }; + + let size = 1000i32; + for y in -size..size { + draw_line(Vector2::new(-size, y), Vector2::new(size, y), Color::WHITE); + } + for x in -size..size { + draw_line(Vector2::new(x, -size), Vector2::new(x, size), Color::WHITE); + } + self.brush.lock().draw_outline( + &mut scene.drawing_context, + self.brush_position, + &transform, + Color::RED, + ); } fn deactivate(&mut self, _controller: &dyn SceneController, _engine: &mut Engine) { @@ -118,6 +178,7 @@ impl InteractionMode for TileMapInteractionMode { #[derive(Default)] pub struct TileMapEditorPlugin { tile_set_editor: Option, + brush: Arc>, } impl EditorPlugin for TileMapEditorPlugin { @@ -171,13 +232,15 @@ impl EditorPlugin for TileMapEditorPlugin { .remove_typed::(); for node_handle in selection.nodes().iter() { - if let Some(collider) = scene.graph.try_get(*node_handle) { - if collider.component_ref::().is_none() { + if let Some(tile_map) = scene.graph.try_get(*node_handle) { + if tile_map.component_ref::().is_none() { continue; } entry.interaction_modes.add(TileMapInteractionMode { tile_map: *node_handle, + brush: self.brush.clone(), + brush_position: Default::default(), }); break;