added click and drag for door objects
This commit is contained in:
+6
-1
@@ -9,7 +9,9 @@ use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
use crate::exporter;
|
||||
use crate::interact::{AddCorridorDrag, DragState, HoverMarker, ResizeState, draw_grid};
|
||||
use crate::interact::{
|
||||
AddCorridorDrag, AddDoorDrag, DragState, HoverMarker, ResizeState, draw_grid,
|
||||
};
|
||||
use crate::layout::{
|
||||
self, DoorSettings, DungeonLayout, WindowSettings, populate_random_markers, populate_stairs,
|
||||
};
|
||||
@@ -45,6 +47,7 @@ pub struct DungeonApp {
|
||||
pub export_progress: Option<exporter::ExportProgress>,
|
||||
pub pending_delete: bool,
|
||||
pub add_corridor_drag: Option<AddCorridorDrag>,
|
||||
pub add_door_drag: Option<AddDoorDrag>,
|
||||
pub resize_state: Option<ResizeState>,
|
||||
pub hover_room_idx: Option<usize>,
|
||||
pub hover_corridor_idx: Option<usize>,
|
||||
@@ -70,6 +73,7 @@ impl Default for DungeonApp {
|
||||
export_progress: None,
|
||||
pending_delete: false,
|
||||
add_corridor_drag: None,
|
||||
add_door_drag: None,
|
||||
resize_state: None,
|
||||
hover_room_idx: None,
|
||||
hover_corridor_idx: None,
|
||||
@@ -398,6 +402,7 @@ impl DungeonApp {
|
||||
pub fn reset_transient_state(&mut self) {
|
||||
self.drag_state = None;
|
||||
self.add_corridor_drag = None;
|
||||
self.add_door_drag = None;
|
||||
self.resize_state = None;
|
||||
self.clear_hover_targets();
|
||||
self.pending_delete = false;
|
||||
|
||||
+97
-28
@@ -5,9 +5,10 @@
|
||||
*/
|
||||
|
||||
use super::{
|
||||
AddCorridorDrag, GridGeometry, HoverMarker, MarkerKind, cell_center, centered_marker_origin,
|
||||
corridor_drag_at_pointer, door_edge_at_pointer, door_edges_for, marker_at_pointer, marker_rect,
|
||||
normalized_edge, pointer_to_grid, room_at_pointer, stair_at_pointer, text_at_pointer,
|
||||
AddCorridorDrag, AddDoorDrag, GridGeometry, HoverMarker, MarkerKind, cell_center,
|
||||
centered_marker_origin, corridor_drag_at_pointer, door_edge_at_pointer, door_edges_for,
|
||||
marker_at_pointer, marker_rect, normalized_edge, pointer_to_grid, room_at_pointer,
|
||||
stair_at_pointer, text_at_pointer,
|
||||
};
|
||||
use crate::app::{DungeonApp, ManualDoorKind};
|
||||
use crate::layout::{
|
||||
@@ -23,12 +24,14 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
if app.settings.add_tool != AddTool::None && response.secondary_clicked() {
|
||||
app.settings.add_tool = AddTool::None;
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
return;
|
||||
}
|
||||
|
||||
match app.settings.add_tool {
|
||||
AddTool::Room => {
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
if response.clicked()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
&& let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry)
|
||||
@@ -38,6 +41,7 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
}
|
||||
}
|
||||
AddTool::Corridor => {
|
||||
app.add_door_drag = None;
|
||||
if response.drag_started()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
&& let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry)
|
||||
@@ -65,6 +69,7 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
}
|
||||
AddTool::Staircase => {
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
if response.clicked()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
&& let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry)
|
||||
@@ -75,21 +80,11 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
}
|
||||
AddTool::Archway | AddTool::Door | AddTool::LockedDoor | AddTool::SecretDoor => {
|
||||
app.add_corridor_drag = None;
|
||||
if response.clicked()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
{
|
||||
let kind = match app.settings.add_tool {
|
||||
AddTool::Archway => ManualDoorKind::Archway,
|
||||
AddTool::Door => ManualDoorKind::Regular,
|
||||
AddTool::LockedDoor => ManualDoorKind::Locked,
|
||||
AddTool::SecretDoor => ManualDoorKind::Secret,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
add_door_at_pointer(app, pointer_pos, geometry, kind);
|
||||
}
|
||||
handle_add_door_tool(app, response, geometry);
|
||||
}
|
||||
AddTool::Text => {
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
if response.clicked()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
&& let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry)
|
||||
@@ -103,6 +98,7 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
| AddTool::TrapMarker
|
||||
| AddTool::MonsterMarker => {
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
if response.clicked()
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
&& let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry)
|
||||
@@ -120,10 +116,88 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry
|
||||
}
|
||||
AddTool::None => {
|
||||
app.add_corridor_drag = None;
|
||||
app.add_door_drag = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles click-and-drag painting for manual door tools.
|
||||
pub fn handle_add_door_tool(
|
||||
app: &mut DungeonApp,
|
||||
response: &egui::Response,
|
||||
geometry: &GridGeometry,
|
||||
) {
|
||||
let Some(kind) = manual_door_kind_from_tool(app.settings.add_tool) else {
|
||||
app.add_door_drag = None;
|
||||
return;
|
||||
};
|
||||
|
||||
if response.drag_started() {
|
||||
app.add_door_drag = Some(AddDoorDrag {
|
||||
painted_edges: Default::default(),
|
||||
snapshot_taken: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (response.drag_started() || response.dragged() || response.clicked())
|
||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||
{
|
||||
paint_door_at_pointer(app, pointer_pos, geometry, kind);
|
||||
}
|
||||
|
||||
if response.drag_stopped() {
|
||||
app.add_door_drag = None;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts the active add tool into a manual door kind.
|
||||
pub fn manual_door_kind_from_tool(tool: AddTool) -> Option<ManualDoorKind> {
|
||||
match tool {
|
||||
AddTool::Archway => Some(ManualDoorKind::Archway),
|
||||
AddTool::Door => Some(ManualDoorKind::Regular),
|
||||
AddTool::LockedDoor => Some(ManualDoorKind::Locked),
|
||||
AddTool::SecretDoor => Some(ManualDoorKind::Secret),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Paints one door edge during a manual door drag.
|
||||
pub fn paint_door_at_pointer(
|
||||
app: &mut DungeonApp,
|
||||
pointer_pos: egui::Pos2,
|
||||
geometry: &GridGeometry,
|
||||
kind: ManualDoorKind,
|
||||
) {
|
||||
let Some(edge) = door_edge_at_pointer(app, pointer_pos, geometry) else {
|
||||
return;
|
||||
};
|
||||
let target = normalized_edge(edge.0, edge.1);
|
||||
|
||||
if let Some(drag) = &app.add_door_drag
|
||||
&& drag.painted_edges.contains(&target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let needs_snapshot = app
|
||||
.add_door_drag
|
||||
.as_ref()
|
||||
.map(|drag| !drag.snapshot_taken)
|
||||
.unwrap_or(true);
|
||||
if needs_snapshot {
|
||||
app.push_undo_snapshot();
|
||||
if let Some(drag) = &mut app.add_door_drag {
|
||||
drag.snapshot_taken = true;
|
||||
}
|
||||
}
|
||||
|
||||
if add_door_at_edge(app, edge, kind)
|
||||
&& let Some(drag) = &mut app.add_door_drag
|
||||
{
|
||||
drag.painted_edges.insert(target);
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes at pointer.
|
||||
pub fn delete_at_pointer(app: &mut DungeonApp, pointer_pos: egui::Pos2, geometry: &GridGeometry) {
|
||||
if app.settings.active_level_index >= app.levels.len() {
|
||||
@@ -450,22 +524,16 @@ pub fn delete_room(app: &mut DungeonApp, room_idx: usize) {
|
||||
app.refresh_doors();
|
||||
}
|
||||
|
||||
// Adds door at pointer.
|
||||
pub fn add_door_at_pointer(
|
||||
// Adds or updates a manual door on a specific cell edge.
|
||||
pub fn add_door_at_edge(
|
||||
app: &mut DungeonApp,
|
||||
pointer_pos: egui::Pos2,
|
||||
geometry: &GridGeometry,
|
||||
edge: ((usize, usize), (usize, usize)),
|
||||
kind: ManualDoorKind,
|
||||
) {
|
||||
) -> bool {
|
||||
if app.settings.active_level_index >= app.levels.len() {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(edge) = door_edge_at_pointer(app, pointer_pos, geometry) else {
|
||||
return;
|
||||
};
|
||||
|
||||
app.push_undo_snapshot();
|
||||
let layout = &mut app.levels[app.settings.active_level_index];
|
||||
|
||||
let target = normalized_edge(edge.0, edge.1);
|
||||
@@ -509,7 +577,7 @@ pub fn add_door_at_pointer(
|
||||
app.suppressed_auto_door_edges.remove(&edge);
|
||||
}
|
||||
layout.doors.extend(spawned);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
let corridor_cells = corridor_cells(layout, app.settings.cols, app.settings.rows);
|
||||
@@ -519,7 +587,7 @@ pub fn add_door_at_pointer(
|
||||
let b_in_corridor = corridor_cells.contains(&edge.1);
|
||||
|
||||
if !manual_door_edge_allowed(a_room, b_room, a_in_corridor, b_in_corridor) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
layout.doors.push(layout::Door {
|
||||
@@ -533,6 +601,7 @@ pub fn add_door_at_pointer(
|
||||
manual: true,
|
||||
});
|
||||
app.suppressed_auto_door_edges.remove(&target);
|
||||
true
|
||||
}
|
||||
|
||||
// Checks whether manual door edge allowed.
|
||||
|
||||
@@ -11,7 +11,11 @@ use eframe::egui;
|
||||
|
||||
// Handles update hover targets.
|
||||
pub fn update_hover_targets(app: &mut DungeonApp, ctx: &egui::Context, geometry: &GridGeometry) {
|
||||
if app.drag_state.is_some() || app.resize_state.is_some() || app.add_corridor_drag.is_some() {
|
||||
if app.drag_state.is_some()
|
||||
|| app.resize_state.is_some()
|
||||
|| app.add_corridor_drag.is_some()
|
||||
|| app.add_door_drag.is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
use crate::layout;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RoomDragState {
|
||||
@@ -38,6 +39,12 @@ pub struct AddCorridorDrag {
|
||||
pub current_cell: (usize, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AddDoorDrag {
|
||||
pub painted_edges: HashSet<((usize, usize), (usize, usize))>,
|
||||
pub snapshot_taken: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ResizeCorner {
|
||||
TopLeft,
|
||||
|
||||
Reference in New Issue
Block a user