diff --git a/editor/resources/line.png b/editor/resources/line.png new file mode 100644 index 000000000..9f1b634ae Binary files /dev/null and b/editor/resources/line.png differ diff --git a/editor/src/plugins/tilemap/mod.rs b/editor/src/plugins/tilemap/mod.rs index 6df0b503a..d165fc154 100644 --- a/editor/src/plugins/tilemap/mod.rs +++ b/editor/src/plugins/tilemap/mod.rs @@ -84,6 +84,9 @@ pub enum DrawingMode { NineSlice { click_grid_position: Option>, }, + Line { + click_grid_position: Option>, + }, } struct InteractionContext { @@ -176,6 +179,9 @@ impl InteractionMode for TileMapInteractionMode { } | DrawingMode::NineSlice { ref mut click_grid_position, + } + | DrawingMode::Line { + ref mut click_grid_position, } => { *click_grid_position = Some(grid_coord); } @@ -253,6 +259,17 @@ impl InteractionMode for TileMapInteractionMode { ) } } + DrawingMode::Line { + click_grid_position, + } => { + if let Some(click_grid_position) = click_grid_position { + tile_map.tiles.draw_line_with_brush( + self.brush_position, + click_grid_position, + &brush, + ); + } + } _ => (), } } @@ -373,6 +390,26 @@ impl InteractionMode for TileMapInteractionMode { Color::RED, ); } + DrawingMode::Line { + click_grid_position, + } => { + if self.interaction_context.is_some() { + if let Some(click_grid_position) = click_grid_position { + for point in [click_grid_position, self.brush_position] { + scene.drawing_context.draw_rectangle( + 0.5, + 0.5, + transform + * Matrix4::new_translation( + &(point.cast::().to_homogeneous() + + Vector3::new(0.5, 0.5, 0.0)), + ), + Color::RED, + ); + } + } + } + } DrawingMode::Pick { click_grid_position, } @@ -448,6 +485,19 @@ impl InteractionMode for TileMapInteractionMode { } } } + DrawingMode::Line { + click_grid_position, + } => { + if self.interaction_context.is_some() { + if let Some(click_grid_position) = click_grid_position { + tile_map.overlay_tiles.draw_line_with_brush( + self.brush_position, + click_grid_position, + &brush, + ); + } + } + } } } diff --git a/editor/src/plugins/tilemap/panel.rs b/editor/src/plugins/tilemap/panel.rs index f70e612b4..716335af6 100644 --- a/editor/src/plugins/tilemap/panel.rs +++ b/editor/src/plugins/tilemap/panel.rs @@ -63,6 +63,7 @@ pub struct TileMapPanel { pick_button: Handle, rect_fill_button: Handle, nine_slice_button: Handle, + line_button: Handle, } fn generate_tiles( @@ -183,7 +184,7 @@ impl TileMapPanel { height, load_image(include_bytes!("../../../resources/eraser.png")), "Erase with active brush.", - Some(0), + Some(1), ); let flood_fill_button = make_drawing_mode_button( ctx, @@ -191,7 +192,7 @@ impl TileMapPanel { height, load_image(include_bytes!("../../../resources/fill.png")), "Flood fill with random tiles from current brush.", - Some(0), + Some(2), ); let pick_button = make_drawing_mode_button( ctx, @@ -199,7 +200,7 @@ impl TileMapPanel { height, load_image(include_bytes!("../../../resources/pipette.png")), "Pick tiles for drawing from the tile map.", - Some(0), + Some(3), ); let rect_fill_button = make_drawing_mode_button( ctx, @@ -207,7 +208,7 @@ impl TileMapPanel { height, load_image(include_bytes!("../../../resources/rect_fill.png")), "Fill the rectangle using the current brush.", - Some(0), + Some(4), ); let nine_slice_button = make_drawing_mode_button( ctx, @@ -215,7 +216,15 @@ impl TileMapPanel { height, load_image(include_bytes!("../../../resources/nine_slice.png")), "Draw rectangles with fixed corners, but stretchable sides.", - Some(0), + Some(5), + ); + let line_button = make_drawing_mode_button( + ctx, + width, + height, + load_image(include_bytes!("../../../resources/line.png")), + "Draw a line using random tiles from the given brush.", + Some(6), ); let drawing_modes_panel = WrapPanelBuilder::new( @@ -226,7 +235,8 @@ impl TileMapPanel { .with_child(flood_fill_button) .with_child(pick_button) .with_child(rect_fill_button) - .with_child(nine_slice_button), + .with_child(nine_slice_button) + .with_child(line_button), ) .with_orientation(Orientation::Horizontal) .build(ctx); @@ -280,6 +290,7 @@ impl TileMapPanel { pick_button, rect_fill_button, nine_slice_button, + line_button, } } @@ -451,6 +462,10 @@ impl TileMapPanel { sender.send(Message::SetInteractionMode( TileMapInteractionMode::type_uuid(), )); + } else if message.destination() == self.line_button { + interaction_mode.drawing_mode = DrawingMode::Line { + click_grid_position: Default::default(), + }; } } } @@ -493,6 +508,7 @@ impl TileMapPanel { self.flood_fill_button, self.rect_fill_button, self.nine_slice_button, + self.line_button, ]; match interaction_mode.drawing_mode { @@ -514,6 +530,9 @@ impl TileMapPanel { DrawingMode::NineSlice { .. } => { highlight_all_except(self.nine_slice_button, &buttons, true, ui); } + DrawingMode::Line { .. } => { + highlight_all_except(self.line_button, &buttons, true, ui); + } } } } diff --git a/fyrox-impl/src/scene/tilemap/mod.rs b/fyrox-impl/src/scene/tilemap/mod.rs index 47a2e7f13..cf4be159a 100644 --- a/fyrox-impl/src/scene/tilemap/mod.rs +++ b/fyrox-impl/src/scene/tilemap/mod.rs @@ -286,7 +286,7 @@ impl Tiles { /// Draw a line from a point to point. #[inline] - pub fn line( + pub fn draw_line( &mut self, from: Vector2, to: Vector2, @@ -300,6 +300,24 @@ impl Tiles { } } + /// Draw a line from a point to point using random tiles from the given brush. + #[inline] + pub fn draw_line_with_brush( + &mut self, + from: Vector2, + to: Vector2, + brush: &TileMapBrush, + ) { + for position in BresenhamLineIter::new(from, to) { + if let Some(random_tile) = brush.tiles.iter().choose(&mut thread_rng()) { + self.insert(Tile { + position, + definition_handle: random_tile.definition_handle, + }); + } + } + } + /// Fills in a rectangle using special brush with 3x3 tiles. It puts /// corner tiles in the respective corners of the target rectangle and draws lines between each /// corner using middle tiles. @@ -368,7 +386,7 @@ impl Tiles { .iter() .find(|tile| tile.local_position - brush_rect.position == brush_tile_position) { - self.line(begin, end, tile.definition_handle); + self.draw_line(begin, end, tile.definition_handle); } }