rooms move other rooms and objects inside of them
This commit is contained in:
+129
-3
@@ -10,7 +10,10 @@ use super::{
|
||||
stair_drag_at_pointer, text_at_pointer,
|
||||
};
|
||||
use crate::app::DungeonApp;
|
||||
use crate::layout::{blocked_room_cells, shortest_path_cells};
|
||||
use crate::layout::{
|
||||
blocked_room_cells, is_cell_inside, is_marker_inside, is_room_inside, is_stair_inside,
|
||||
shortest_path_cells,
|
||||
};
|
||||
use crate::ui::AddTool;
|
||||
use eframe::egui;
|
||||
use egui::{Color32, Stroke};
|
||||
@@ -57,10 +60,70 @@ pub fn handle_drag(
|
||||
&& let Some((room_idx, offset_x, offset_y)) = room_at_pointer(app, pointer_pos, geometry)
|
||||
{
|
||||
app.push_undo_snapshot();
|
||||
let active_idx = app.settings.active_level_index;
|
||||
let layout = &app.levels[active_idx];
|
||||
let outer_room = &layout.rooms[room_idx];
|
||||
|
||||
let mut nested_rooms = Vec::new();
|
||||
for (i, room) in layout.rooms.iter().enumerate() {
|
||||
if i != room_idx && is_room_inside(room, outer_room) {
|
||||
nested_rooms.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_start_markers = Vec::new();
|
||||
for (i, marker) in layout.start_markers.iter().enumerate() {
|
||||
if is_marker_inside(marker, outer_room) {
|
||||
nested_start_markers.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_end_markers = Vec::new();
|
||||
for (i, marker) in layout.end_markers.iter().enumerate() {
|
||||
if is_marker_inside(marker, outer_room) {
|
||||
nested_end_markers.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_trap_markers = Vec::new();
|
||||
for (i, marker) in layout.trap_markers.iter().enumerate() {
|
||||
if is_marker_inside(marker, outer_room) {
|
||||
nested_trap_markers.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_monster_markers = Vec::new();
|
||||
for (i, marker) in layout.monster_markers.iter().enumerate() {
|
||||
if is_marker_inside(marker, outer_room) {
|
||||
nested_monster_markers.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_text_labels = Vec::new();
|
||||
for (i, label) in layout.text_labels.iter().enumerate() {
|
||||
if is_cell_inside(label.cell, outer_room) {
|
||||
nested_text_labels.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut nested_stairs = Vec::new();
|
||||
for (i, stair) in layout.stairs.iter().enumerate() {
|
||||
if is_stair_inside(stair, outer_room) {
|
||||
nested_stairs.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
app.drag_state = Some(DragState::Room(RoomDragState {
|
||||
room_idx,
|
||||
offset_x,
|
||||
offset_y,
|
||||
nested_rooms,
|
||||
nested_start_markers,
|
||||
nested_end_markers,
|
||||
nested_trap_markers,
|
||||
nested_monster_markers,
|
||||
nested_text_labels,
|
||||
nested_stairs,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -118,9 +181,72 @@ pub fn drag_room_to_pointer(
|
||||
return;
|
||||
}
|
||||
|
||||
app.levels[app.settings.active_level_index].rooms[drag.room_idx].x = new_x;
|
||||
app.levels[app.settings.active_level_index].rooms[drag.room_idx].y = new_y;
|
||||
let delta_x = new_x as isize - old_x as isize;
|
||||
let delta_y = new_y as isize - old_y as isize;
|
||||
|
||||
{
|
||||
let level = &mut app.levels[app.settings.active_level_index];
|
||||
level.rooms[drag.room_idx].x = new_x;
|
||||
level.rooms[drag.room_idx].y = new_y;
|
||||
|
||||
for &idx in &drag.nested_rooms {
|
||||
if idx < level.rooms.len() {
|
||||
level.rooms[idx].x = (level.rooms[idx].x as isize + delta_x) as usize;
|
||||
level.rooms[idx].y = (level.rooms[idx].y as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_start_markers {
|
||||
if idx < level.start_markers.len() {
|
||||
level.start_markers[idx].cell.0 =
|
||||
(level.start_markers[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.start_markers[idx].cell.1 =
|
||||
(level.start_markers[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_end_markers {
|
||||
if idx < level.end_markers.len() {
|
||||
level.end_markers[idx].cell.0 =
|
||||
(level.end_markers[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.end_markers[idx].cell.1 =
|
||||
(level.end_markers[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_trap_markers {
|
||||
if idx < level.trap_markers.len() {
|
||||
level.trap_markers[idx].cell.0 =
|
||||
(level.trap_markers[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.trap_markers[idx].cell.1 =
|
||||
(level.trap_markers[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_monster_markers {
|
||||
if idx < level.monster_markers.len() {
|
||||
level.monster_markers[idx].cell.0 =
|
||||
(level.monster_markers[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.monster_markers[idx].cell.1 =
|
||||
(level.monster_markers[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_text_labels {
|
||||
if idx < level.text_labels.len() {
|
||||
level.text_labels[idx].cell.0 =
|
||||
(level.text_labels[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.text_labels[idx].cell.1 =
|
||||
(level.text_labels[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
for &idx in &drag.nested_stairs {
|
||||
if idx < level.stairs.len() {
|
||||
level.stairs[idx].cell.0 = (level.stairs[idx].cell.0 as isize + delta_x) as usize;
|
||||
level.stairs[idx].cell.1 = (level.stairs[idx].cell.1 as isize + delta_y) as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reroute_corridors_for_room(app, drag.room_idx);
|
||||
for &idx in &drag.nested_rooms {
|
||||
reroute_corridors_for_room(app, idx);
|
||||
}
|
||||
app.refresh_doors();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@ pub struct RoomDragState {
|
||||
pub room_idx: usize,
|
||||
pub offset_x: f32,
|
||||
pub offset_y: f32,
|
||||
pub nested_rooms: Vec<usize>,
|
||||
pub nested_start_markers: Vec<usize>,
|
||||
pub nested_end_markers: Vec<usize>,
|
||||
pub nested_trap_markers: Vec<usize>,
|
||||
pub nested_monster_markers: Vec<usize>,
|
||||
pub nested_text_labels: Vec<usize>,
|
||||
pub nested_stairs: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
@@ -128,6 +128,38 @@ pub fn overlaps_with_padding(a: &Room, b: &Room, padding: usize) -> bool {
|
||||
a_left < b_right && a_right > b_left && a_top < b_bottom && a_bottom > b_top
|
||||
}
|
||||
|
||||
// Test whether one room is completely inside another.
|
||||
pub fn is_room_inside(inner: &Room, outer: &Room) -> bool {
|
||||
inner.x >= outer.x
|
||||
&& inner.x + inner.width <= outer.x + outer.width
|
||||
&& inner.y >= outer.y
|
||||
&& inner.y + inner.height <= outer.y + outer.height
|
||||
}
|
||||
|
||||
// Test whether a cell is inside a room.
|
||||
pub fn is_cell_inside(cell: (usize, usize), room: &Room) -> bool {
|
||||
cell.0 >= room.x
|
||||
&& cell.0 < room.x + room.width
|
||||
&& cell.1 >= room.y
|
||||
&& cell.1 < room.y + room.height
|
||||
}
|
||||
|
||||
// Test whether an area marker is completely inside a room.
|
||||
pub fn is_marker_inside(marker: &crate::layout::AreaMarker, room: &Room) -> bool {
|
||||
marker.cell.0 >= room.x
|
||||
&& marker.cell.0 + marker.size <= room.x + room.width
|
||||
&& marker.cell.1 >= room.y
|
||||
&& marker.cell.1 + marker.size <= room.y + room.height
|
||||
}
|
||||
|
||||
// Test whether a staircase is completely inside a room.
|
||||
pub fn is_stair_inside(stair: &crate::layout::Staircase, room: &Room) -> bool {
|
||||
stair.cell.0 >= room.x
|
||||
&& stair.cell.0 + stair.width <= room.x + room.width
|
||||
&& stair.cell.1 >= room.y
|
||||
&& stair.cell.1 + stair.height <= room.y + room.height
|
||||
}
|
||||
|
||||
// Checks whether rects overlap.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn rects_overlap(
|
||||
|
||||
Reference in New Issue
Block a user