fixed issues when resizing stairs in rooms
This commit is contained in:
+76
-66
@@ -588,6 +588,12 @@ impl DungeonApp {
|
|||||||
{
|
{
|
||||||
self.push_undo_snapshot();
|
self.push_undo_snapshot();
|
||||||
self.drag_state = Some(DragState::Staircase(stair_drag));
|
self.drag_state = Some(DragState::Staircase(stair_drag));
|
||||||
|
} else if response.drag_started()
|
||||||
|
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||||
|
&& let Some(corridor_drag) = self.corridor_drag_at_pointer(pointer_pos, geometry)
|
||||||
|
{
|
||||||
|
self.push_undo_snapshot();
|
||||||
|
self.drag_state = Some(DragState::Corridor(corridor_drag));
|
||||||
} else if response.drag_started()
|
} else if response.drag_started()
|
||||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||||
&& let Some((room_idx, offset_x, offset_y)) =
|
&& let Some((room_idx, offset_x, offset_y)) =
|
||||||
@@ -599,12 +605,6 @@ impl DungeonApp {
|
|||||||
offset_x,
|
offset_x,
|
||||||
offset_y,
|
offset_y,
|
||||||
}));
|
}));
|
||||||
} else if response.drag_started()
|
|
||||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
|
||||||
&& let Some(corridor_drag) = self.corridor_drag_at_pointer(pointer_pos, geometry)
|
|
||||||
{
|
|
||||||
self.push_undo_snapshot();
|
|
||||||
self.drag_state = Some(DragState::Corridor(corridor_drag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.dragged()
|
if response.dragged()
|
||||||
@@ -1225,6 +1225,13 @@ impl DungeonApp {
|
|||||||
|
|
||||||
// Update which room/corridor/door is currently hovered.
|
// Update which room/corridor/door is currently hovered.
|
||||||
fn update_hover_targets(&mut self, ctx: &egui::Context, geometry: &GridGeometry) {
|
fn update_hover_targets(&mut self, ctx: &egui::Context, geometry: &GridGeometry) {
|
||||||
|
if self.drag_state.is_some()
|
||||||
|
|| self.resize_state.is_some()
|
||||||
|
|| self.add_corridor_drag.is_some()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let Some(pointer_pos) = ctx.pointer_hover_pos() else {
|
let Some(pointer_pos) = ctx.pointer_hover_pos() else {
|
||||||
self.clear_hover_targets();
|
self.clear_hover_targets();
|
||||||
return;
|
return;
|
||||||
@@ -1560,12 +1567,6 @@ impl DungeonApp {
|
|||||||
self.resize_state = Some(ResizeState::Text(state));
|
self.resize_state = Some(ResizeState::Text(state));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if let Some(room_idx) = self.resize_room_at_pointer(pointer_pos, geometry) {
|
|
||||||
if let Some(state) = self.start_resize(room_idx, pointer_pos, geometry) {
|
|
||||||
self.push_undo_snapshot();
|
|
||||||
self.resize_state = Some(ResizeState::Room(state));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if let Some(stair_idx) = self.stair_at_pointer(pointer_pos, geometry) {
|
} else if let Some(stair_idx) = self.stair_at_pointer(pointer_pos, geometry) {
|
||||||
if let Some(state) =
|
if let Some(state) =
|
||||||
self.start_staircase_resize(stair_idx, pointer_pos, geometry)
|
self.start_staircase_resize(stair_idx, pointer_pos, geometry)
|
||||||
@@ -1574,6 +1575,12 @@ impl DungeonApp {
|
|||||||
self.resize_state = Some(ResizeState::Staircase(state));
|
self.resize_state = Some(ResizeState::Staircase(state));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if let Some(room_idx) = self.resize_room_at_pointer(pointer_pos, geometry) {
|
||||||
|
if let Some(state) = self.start_resize(room_idx, pointer_pos, geometry) {
|
||||||
|
self.push_undo_snapshot();
|
||||||
|
self.resize_state = Some(ResizeState::Room(state));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1822,22 +1829,8 @@ impl DungeonApp {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for collisions with other stairs or rooms on the current level.
|
// Check for collisions with other stairs on the current level.
|
||||||
let active_layout = &self.levels[self.settings.active_level_index];
|
let active_layout = &self.levels[self.settings.active_level_index];
|
||||||
if active_layout.rooms.iter().any(|room| {
|
|
||||||
rects_overlap(
|
|
||||||
new_stair_cell.0,
|
|
||||||
new_stair_cell.1,
|
|
||||||
new_stair_width,
|
|
||||||
new_stair_height,
|
|
||||||
room.x,
|
|
||||||
room.y,
|
|
||||||
room.width,
|
|
||||||
room.height,
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if active_layout.stairs.iter().enumerate().any(|(idx, stair)| {
|
if active_layout.stairs.iter().enumerate().any(|(idx, stair)| {
|
||||||
idx != state.stair_idx
|
idx != state.stair_idx
|
||||||
&& rects_overlap(
|
&& rects_overlap(
|
||||||
@@ -1903,15 +1896,36 @@ impl DungeonApp {
|
|||||||
}
|
}
|
||||||
let layout = &self.levels[self.settings.active_level_index];
|
let layout = &self.levels[self.settings.active_level_index];
|
||||||
|
|
||||||
if let Some(text_idx) = self
|
// 1. Check active ResizeState first to lock visual feedback to the being-resized object.
|
||||||
.resize_state
|
if let Some(state) = &self.resize_state {
|
||||||
.as_ref()
|
match state {
|
||||||
.and_then(|s| match s {
|
ResizeState::Text(state) => {
|
||||||
ResizeState::Text(state) => Some(state.text_idx),
|
if let Some(label) = layout.text_labels.get(state.text_idx) {
|
||||||
_ => None,
|
let rect = text_label_rect(geometry, label).expand(3.0);
|
||||||
})
|
painter.rect_stroke(
|
||||||
.or(self.hover_text_idx)
|
rect,
|
||||||
{
|
0.0,
|
||||||
|
Stroke::new(2.0, Color32::from_gray(180)),
|
||||||
|
egui::StrokeKind::Middle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResizeState::Room(state) => {
|
||||||
|
if let Some(room) = layout.rooms.get(state.room_idx) {
|
||||||
|
self.draw_room_resize_visuals(painter, geometry, room, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResizeState::Staircase(state) => {
|
||||||
|
if let Some(stair) = layout.stairs.get(state.stair_idx) {
|
||||||
|
self.draw_staircase_resize_visuals(painter, geometry, stair, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Fall back to hover state if not resizing.
|
||||||
|
if let Some(text_idx) = self.hover_text_idx {
|
||||||
if let Some(label) = layout.text_labels.get(text_idx) {
|
if let Some(label) = layout.text_labels.get(text_idx) {
|
||||||
let rect = text_label_rect(geometry, label).expand(3.0);
|
let rect = text_label_rect(geometry, label).expand(3.0);
|
||||||
painter.rect_stroke(
|
painter.rect_stroke(
|
||||||
@@ -1920,21 +1934,25 @@ impl DungeonApp {
|
|||||||
Stroke::new(2.0, Color32::from_gray(180)),
|
Stroke::new(2.0, Color32::from_gray(180)),
|
||||||
egui::StrokeKind::Middle,
|
egui::StrokeKind::Middle,
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
} else if let Some(room_idx) = self.hover_room_idx {
|
||||||
|
|
||||||
let room_idx = self
|
|
||||||
.resize_state
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|s| match s {
|
|
||||||
ResizeState::Room(state) => Some(state.room_idx),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.or(self.hover_room_idx);
|
|
||||||
|
|
||||||
if let Some(room_idx) = room_idx {
|
|
||||||
if let Some(room) = layout.rooms.get(room_idx) {
|
if let Some(room) = layout.rooms.get(room_idx) {
|
||||||
|
self.draw_room_resize_visuals(painter, geometry, room, false);
|
||||||
|
}
|
||||||
|
} else if let Some(stair_idx) = self.hover_stair_idx {
|
||||||
|
if let Some(stair) = layout.stairs.get(stair_idx) {
|
||||||
|
self.draw_staircase_resize_visuals(painter, geometry, stair, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_room_resize_visuals(
|
||||||
|
&self,
|
||||||
|
painter: &egui::Painter,
|
||||||
|
geometry: &GridGeometry,
|
||||||
|
room: &layout::Room,
|
||||||
|
show_handles: bool,
|
||||||
|
) {
|
||||||
let color = Color32::from_gray(170);
|
let color = Color32::from_gray(170);
|
||||||
let stroke = Stroke::new(1.5, color);
|
let stroke = Stroke::new(1.5, color);
|
||||||
|
|
||||||
@@ -1965,27 +1983,21 @@ impl DungeonApp {
|
|||||||
);
|
);
|
||||||
painter.text(center_left, egui::Align2::CENTER_CENTER, "^v", font, color);
|
painter.text(center_left, egui::Align2::CENTER_CENTER, "^v", font, color);
|
||||||
|
|
||||||
if matches!(self.resize_state, Some(ResizeState::Room(_))) {
|
if show_handles {
|
||||||
draw_resize_handle(painter, tl, ResizeCorner::TopLeft, color);
|
draw_resize_handle(painter, tl, ResizeCorner::TopLeft, color);
|
||||||
draw_resize_handle(painter, tr, ResizeCorner::TopRight, color);
|
draw_resize_handle(painter, tr, ResizeCorner::TopRight, color);
|
||||||
draw_resize_handle(painter, br, ResizeCorner::BottomRight, color);
|
draw_resize_handle(painter, br, ResizeCorner::BottomRight, color);
|
||||||
draw_resize_handle(painter, bl, ResizeCorner::BottomLeft, color);
|
draw_resize_handle(painter, bl, ResizeCorner::BottomLeft, color);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let stair_idx = self
|
fn draw_staircase_resize_visuals(
|
||||||
.resize_state
|
&self,
|
||||||
.as_ref()
|
painter: &egui::Painter,
|
||||||
.and_then(|s| match s {
|
geometry: &GridGeometry,
|
||||||
ResizeState::Staircase(state) => Some(state.stair_idx),
|
stair: &layout::Staircase,
|
||||||
_ => None,
|
show_handles: bool,
|
||||||
})
|
) {
|
||||||
.or(self.hover_stair_idx);
|
|
||||||
|
|
||||||
if let Some(stair_idx) = stair_idx {
|
|
||||||
if let Some(stair) = layout.stairs.get(stair_idx) {
|
|
||||||
let color = Color32::from_gray(170);
|
let color = Color32::from_gray(170);
|
||||||
let stroke = Stroke::new(1.5, color);
|
let stroke = Stroke::new(1.5, color);
|
||||||
|
|
||||||
@@ -2004,15 +2016,13 @@ impl DungeonApp {
|
|||||||
draw_dashed_line(painter, br, bl, stroke, 6.0, 6.0);
|
draw_dashed_line(painter, br, bl, stroke, 6.0, 6.0);
|
||||||
draw_dashed_line(painter, bl, tl, stroke, 6.0, 6.0);
|
draw_dashed_line(painter, bl, tl, stroke, 6.0, 6.0);
|
||||||
|
|
||||||
if matches!(self.resize_state, Some(ResizeState::Staircase(_))) {
|
if show_handles {
|
||||||
draw_resize_handle(painter, tl, ResizeCorner::TopLeft, color);
|
draw_resize_handle(painter, tl, ResizeCorner::TopLeft, color);
|
||||||
draw_resize_handle(painter, tr, ResizeCorner::TopRight, color);
|
draw_resize_handle(painter, tr, ResizeCorner::TopRight, color);
|
||||||
draw_resize_handle(painter, br, ResizeCorner::BottomRight, color);
|
draw_resize_handle(painter, br, ResizeCorner::BottomRight, color);
|
||||||
draw_resize_handle(painter, bl, ResizeCorner::BottomLeft, color);
|
draw_resize_handle(painter, bl, ResizeCorner::BottomLeft, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a dashed overlay along the hovered corridor path.
|
// Draw a dashed overlay along the hovered corridor path.
|
||||||
fn draw_corridor_hover_overlay(&self, painter: &egui::Painter, geometry: &GridGeometry) {
|
fn draw_corridor_hover_overlay(&self, painter: &egui::Painter, geometry: &GridGeometry) {
|
||||||
|
|||||||
Reference in New Issue
Block a user