ability to draw lines on tile maps

This commit is contained in:
Dmitry Stepanov
2024-07-30 23:36:49 +03:00
parent 7b25f44d96
commit b2de1b7a14
4 changed files with 95 additions and 8 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

+50
View File
@@ -84,6 +84,9 @@ pub enum DrawingMode {
NineSlice {
click_grid_position: Option<Vector2<i32>>,
},
Line {
click_grid_position: Option<Vector2<i32>>,
},
}
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::<f32>().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,
);
}
}
}
}
}
+25 -6
View File
@@ -63,6 +63,7 @@ pub struct TileMapPanel {
pick_button: Handle<UiNode>,
rect_fill_button: Handle<UiNode>,
nine_slice_button: Handle<UiNode>,
line_button: Handle<UiNode>,
}
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);
}
}
}
}
+20 -2
View File
@@ -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<i32>,
to: Vector2<i32>,
@@ -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<i32>,
to: Vector2<i32>,
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);
}
}