organized add menu and added ability to add stairs and monsters

This commit is contained in:
grimsace
2026-04-27 15:00:59 -05:00
parent 5c02e37166
commit 4157f6b721
2 changed files with 127 additions and 47 deletions
+48 -1
View File
@@ -947,6 +947,16 @@ impl DungeonApp {
} }
} }
} }
AddTool::Staircase => {
self.add_corridor_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)
{
let cell = (grid_x.floor() as usize, grid_y.floor() as usize);
self.add_staircase_at_cell(cell);
}
}
AddTool::Archway | AddTool::Door | AddTool::LockedDoor | AddTool::SecretDoor => { AddTool::Archway | AddTool::Door | AddTool::LockedDoor | AddTool::SecretDoor => {
self.add_corridor_drag = None; self.add_corridor_drag = None;
if response.clicked() if response.clicked()
@@ -972,7 +982,10 @@ impl DungeonApp {
self.add_text_at_cell(cell); self.add_text_at_cell(cell);
} }
} }
AddTool::StartMarker | AddTool::EndMarker | AddTool::TrapMarker => { AddTool::StartMarker
| AddTool::EndMarker
| AddTool::TrapMarker
| AddTool::MonsterMarker => {
self.add_corridor_drag = None; self.add_corridor_drag = None;
if response.clicked() if response.clicked()
&& let Some(pointer_pos) = response.interact_pointer_pos() && let Some(pointer_pos) = response.interact_pointer_pos()
@@ -983,6 +996,7 @@ impl DungeonApp {
AddTool::StartMarker => MarkerKind::Start, AddTool::StartMarker => MarkerKind::Start,
AddTool::EndMarker => MarkerKind::End, AddTool::EndMarker => MarkerKind::End,
AddTool::TrapMarker => MarkerKind::Trap, AddTool::TrapMarker => MarkerKind::Trap,
AddTool::MonsterMarker => MarkerKind::Monster,
_ => unreachable!(), _ => unreachable!(),
}; };
self.add_marker_at_cell(cell, kind); self.add_marker_at_cell(cell, kind);
@@ -1155,6 +1169,39 @@ impl DungeonApp {
} }
} }
fn add_staircase_at_cell(&mut self, cell: (usize, usize)) {
self.push_undo_snapshot();
if self.settings.active_level_index >= self.levels.len() {
return;
}
if cell.0 >= self.settings.cols || cell.1 >= self.settings.rows {
return;
}
let size = self.settings.manual_stair_size.max(1);
let max_x = self.settings.cols.saturating_sub(size);
let max_y = self.settings.rows.saturating_sub(size);
let origin_x = cell.0.min(max_x);
let origin_y = cell.1.min(max_y);
let stair = layout::Staircase {
cell: (origin_x, origin_y),
size,
};
if self.settings.sync_stairs_across_levels {
// Add stairs to ALL levels at the same position.
for layout in &mut self.levels {
layout.stairs.push(stair.clone());
}
} else {
// Add stairs only to the active level.
let layout = &mut self.levels[self.settings.active_level_index];
layout.stairs.push(stair);
}
}
// 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) {
let Some(pointer_pos) = ctx.pointer_hover_pos() else { let Some(pointer_pos) = ctx.pointer_hover_pos() else {
+79 -46
View File
@@ -158,70 +158,71 @@ pub struct UiSettings {
pub min_stairs_per_level: usize, pub min_stairs_per_level: usize,
pub max_stairs_per_level: usize, pub max_stairs_per_level: usize,
pub sync_stairs_across_levels: bool, pub sync_stairs_across_levels: bool,
pub manual_stair_size: usize,
active_tab: Tab, active_tab: Tab,
} }
impl Default for UiSettings { impl Default for UiSettings {
// Provide initial UI settings for a fresh session.
fn default() -> Self { fn default() -> Self {
Self { UiSettings {
seed: 1, seed: 0,
cols: 24, cols: 32,
rows: 18, rows: 32,
room_count: 8, room_count: 8,
min_room_size: 2, min_room_size: 3,
max_room_size: 6, max_room_size: 8,
square_rooms_only: false, square_rooms_only: true,
min_corridor_width: 1, min_corridor_width: 1,
max_corridor_width: 2, max_corridor_width: 3,
corridor_randomness: 0, corridor_randomness: 50,
dead_end_rooms_percent: 0, dead_end_rooms_percent: 20,
pack_rooms_without_corridors: false, pack_rooms_without_corridors: false,
door_frequency_percent: 30, door_frequency_percent: 50,
room_hallway_door_percent: 70, room_hallway_door_percent: 20,
locked_door_percent: 25, locked_door_percent: 10,
secret_door_percent: 10, secret_door_percent: 5,
allow_middle_corridor_doors: false, allow_middle_corridor_doors: false,
windows_enabled: false, windows_enabled: false,
min_window_width: 1, min_window_width: 2,
max_window_width: 2, max_window_width: 4,
window_frequency_percent: 30, window_frequency_percent: 30,
room_hallway_window_percent: 40, room_hallway_window_percent: 10,
allow_internal_windows: false, allow_internal_windows: false,
colorblind_mode: false, colorblind_mode: false,
export_format: ExportFormat::Png, export_format: ExportFormat::Png,
mask_format: MaskFormat::Png, mask_format: MaskFormat::Png,
export_width: 1920, export_width: 0,
export_height: 1080, export_height: 0,
allow_export_aspect_change: false, allow_export_aspect_change: true,
export_show_grid: true, export_show_grid: false,
last_export_path: None, last_export_path: None,
add_tool: AddTool::None, add_tool: AddTool::None,
add_text_value: "Text".to_string(), add_text_value: String::from("Text"),
min_start_marker_size: 1, min_start_marker_size: 1,
max_start_marker_size: 1, max_start_marker_size: 3,
min_end_marker_size: 1, min_end_marker_size: 1,
max_end_marker_size: 1, max_end_marker_size: 3,
min_start_marker_count: 1, min_start_marker_count: 1,
max_start_marker_count: 1, max_start_marker_count: 3,
min_end_marker_count: 1, min_end_marker_count: 1,
max_end_marker_count: 1, max_end_marker_count: 3,
min_levels: 1, min_levels: 1,
max_levels: 1, max_levels: 1,
active_level_index: 0, active_level_index: 0,
trap_frequency_percent: 20, trap_frequency_percent: 30,
min_traps_per_area: 1, min_traps_per_area: 1,
max_traps_per_area: 3, max_traps_per_area: 3,
monster_frequency_percent: 15, monster_frequency_percent: 30,
min_monsters_per_area: 1, min_monsters_per_area: 1,
max_monsters_per_area: 2, max_monsters_per_area: 3,
min_stair_width: 1, min_stair_width: 2,
max_stair_width: 2, max_stair_width: 3,
min_stair_height: 2, min_stair_height: 2,
max_stair_height: 3, max_stair_height: 3,
min_stairs_per_level: 1, min_stairs_per_level: 1,
max_stairs_per_level: 1, max_stairs_per_level: 2,
sync_stairs_across_levels: true, sync_stairs_across_levels: false,
manual_stair_size: 2,
active_tab: Tab::Generate, active_tab: Tab::Generate,
} }
} }
@@ -240,6 +241,8 @@ pub enum AddTool {
StartMarker, StartMarker,
EndMarker, EndMarker,
TrapMarker, TrapMarker,
MonsterMarker,
Staircase,
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
@@ -938,14 +941,30 @@ fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut SideP
ui.label(RichText::new("Add Tools").strong()); ui.label(RichText::new("Add Tools").strong());
ui.add_space(8.0); ui.add_space(8.0);
ui.label(RichText::new("Layout").strong());
ui.add_space(4.0);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Room, "Add Room"); ui.selectable_value(&mut settings.add_tool, AddTool::Room, "Add Room");
ui.selectable_value(&mut settings.add_tool, AddTool::Corridor, "Add Corridor"); ui.selectable_value(&mut settings.add_tool, AddTool::Corridor, "Add Corridor");
}); });
ui.add_space(2.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Staircase, "Add Stairs");
});
ui.add_space(4.0);
if ui.button("Add New Level").clicked() {
result.new_level_clicked = true;
}
ui.add_space(8.0);
ui.label(RichText::new("Doors").strong());
ui.add_space(4.0); ui.add_space(4.0);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Archway, "Add Archway"); ui.selectable_value(&mut settings.add_tool, AddTool::Archway, "Add Archway");
ui.selectable_value(&mut settings.add_tool, AddTool::Door, "Add Door"); ui.selectable_value(&mut settings.add_tool, AddTool::Door, "Add Door");
});
ui.add_space(2.0);
ui.horizontal(|ui| {
ui.selectable_value( ui.selectable_value(
&mut settings.add_tool, &mut settings.add_tool,
AddTool::LockedDoor, AddTool::LockedDoor,
@@ -957,25 +976,38 @@ fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut SideP
"Add Secret Door", "Add Secret Door",
); );
}); });
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Text, "Add Text");
ui.selectable_value(&mut settings.add_tool, AddTool::StartMarker, "Place Start");
ui.selectable_value(&mut settings.add_tool, AddTool::EndMarker, "Place End");
ui.selectable_value(&mut settings.add_tool, AddTool::TrapMarker, "Place Trap");
});
ui.add_space(4.0);
ui.label("Left click to place, Right click/Escape to cancel");
ui.add_space(8.0); ui.add_space(8.0);
if ui.button("Add New Level").clicked() { ui.label(RichText::new("Features").strong());
result.new_level_clicked = true; ui.add_space(4.0);
} ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::StartMarker, "Place Start");
ui.selectable_value(&mut settings.add_tool, AddTool::EndMarker, "Place End");
});
ui.add_space(2.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::TrapMarker, "Place Trap");
ui.selectable_value(
&mut settings.add_tool,
AddTool::MonsterMarker,
"Place Monster",
);
});
ui.add_space(2.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Text, "Add Text");
});
ui.add_space(8.0);
ui.label("Left click to place, Right click/Escape to cancel");
ui.add_space(6.0); ui.add_space(6.0);
match settings.add_tool { match settings.add_tool {
AddTool::Room => ui.label("Click to place a room at the grid cell."), AddTool::Room => ui.label("Click to place a room at the grid cell."),
AddTool::Corridor => ui.label("Click-drag to place a corridor between two cells."), AddTool::Corridor => ui.label("Click-drag to place a corridor between two cells."),
AddTool::Staircase => {
ui.label("Click the grid to place stairs (visible on current and adjacent levels).")
}
AddTool::Archway => ui.label("Click a valid room or corridor edge to place an archway."), AddTool::Archway => ui.label("Click a valid room or corridor edge to place an archway."),
AddTool::Door => ui.label("Click a room/corridor edge to place a door."), AddTool::Door => ui.label("Click a room/corridor edge to place a door."),
AddTool::LockedDoor => ui.label("Click a room/corridor edge to place a locked door."), AddTool::LockedDoor => ui.label("Click a room/corridor edge to place a locked door."),
@@ -992,6 +1024,7 @@ fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut SideP
AddTool::StartMarker => ui.label("Click the grid to place the start marker."), AddTool::StartMarker => ui.label("Click the grid to place the start marker."),
AddTool::EndMarker => ui.label("Click the grid to place the end marker."), AddTool::EndMarker => ui.label("Click the grid to place the end marker."),
AddTool::TrapMarker => ui.label("Click the grid to place a trap marker."), AddTool::TrapMarker => ui.label("Click the grid to place a trap marker."),
AddTool::MonsterMarker => ui.label("Click the grid to place a monster marker."),
AddTool::None => ui.label("Select a tool to add rooms or corridors."), AddTool::None => ui.label("Select a tool to add rooms or corridors."),
}; };
} }