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,
|
stair_drag_at_pointer, text_at_pointer,
|
||||||
};
|
};
|
||||||
use crate::app::DungeonApp;
|
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 crate::ui::AddTool;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::{Color32, Stroke};
|
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)
|
&& let Some((room_idx, offset_x, offset_y)) = room_at_pointer(app, pointer_pos, geometry)
|
||||||
{
|
{
|
||||||
app.push_undo_snapshot();
|
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 {
|
app.drag_state = Some(DragState::Room(RoomDragState {
|
||||||
room_idx,
|
room_idx,
|
||||||
offset_x,
|
offset_x,
|
||||||
offset_y,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.levels[app.settings.active_level_index].rooms[drag.room_idx].x = new_x;
|
let delta_x = new_x as isize - old_x as isize;
|
||||||
app.levels[app.settings.active_level_index].rooms[drag.room_idx].y = new_y;
|
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);
|
reroute_corridors_for_room(app, drag.room_idx);
|
||||||
|
for &idx in &drag.nested_rooms {
|
||||||
|
reroute_corridors_for_room(app, idx);
|
||||||
|
}
|
||||||
app.refresh_doors();
|
app.refresh_doors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ pub struct RoomDragState {
|
|||||||
pub room_idx: usize,
|
pub room_idx: usize,
|
||||||
pub offset_x: f32,
|
pub offset_x: f32,
|
||||||
pub offset_y: 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)]
|
#[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
|
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.
|
// Checks whether rects overlap.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn rects_overlap(
|
pub fn rects_overlap(
|
||||||
|
|||||||
Reference in New Issue
Block a user