added generation of start/end and settings for that, along with stuff for place, move, and remove

This commit is contained in:
grimsace
2026-04-14 11:03:58 -05:00
parent 8a8dedd775
commit 0b7696031b
4 changed files with 469 additions and 117 deletions
+4 -4
View File
@@ -276,10 +276,10 @@ fn render_pixmap(layout: &DungeonLayout, settings: &UiSettings) -> Result<Pixmap
draw_window(&mut pixmap, &g, window, door_w, WINDOW, style);
}
if let Some(marker) = layout.start_marker.as_ref() {
for marker in &layout.start_markers {
draw_area_marker(&mut pixmap, &g, marker, "S", START_MARKER, settings.colorblind_mode);
}
if let Some(marker) = layout.end_marker.as_ref() {
for marker in &layout.end_markers {
draw_area_marker(&mut pixmap, &g, marker, "E", END_MARKER, settings.colorblind_mode);
}
@@ -677,10 +677,10 @@ fn build_svg(layout: &DungeonLayout, settings: &UiSettings) -> String {
}
}
if let Some(marker) = layout.start_marker.as_ref() {
for marker in &layout.start_markers {
append_svg_area_marker(&mut s, &g, marker, "S", START_MARKER, settings.colorblind_mode);
}
if let Some(marker) = layout.end_marker.as_ref() {
for marker in &layout.end_markers {
append_svg_area_marker(&mut s, &g, marker, "E", END_MARKER, settings.colorblind_mode);
}
+14 -14
View File
@@ -94,8 +94,8 @@ pub struct DungeonLayout {
pub doors: Vec<Door>,
pub windows: Vec<Window>,
pub text_labels: Vec<TextLabel>,
pub start_marker: Option<AreaMarker>,
pub end_marker: Option<AreaMarker>,
pub start_markers: Vec<AreaMarker>,
pub end_markers: Vec<AreaMarker>,
pub packed_rooms: bool,
}
@@ -107,8 +107,8 @@ impl Default for DungeonLayout {
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: false,
}
}
@@ -176,8 +176,8 @@ pub fn generate_layout(
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: pack_rooms_without_corridors,
};
}
@@ -201,8 +201,8 @@ pub fn generate_layout(
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: pack_rooms_without_corridors,
};
}
@@ -231,8 +231,8 @@ pub fn generate_layout(
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: true,
};
apply_doors(&mut layout, seed, door_settings, cols, rows);
@@ -290,8 +290,8 @@ pub fn generate_layout(
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: false,
};
}
@@ -346,8 +346,8 @@ pub fn generate_layout(
doors: Vec::new(),
windows: Vec::new(),
text_labels: Vec::new(),
start_marker: None,
end_marker: None,
start_markers: Vec::new(),
end_markers: Vec::new(),
packed_rooms: false,
};
apply_doors(&mut layout, seed, door_settings, cols, rows);
+311 -34
View File
@@ -57,7 +57,7 @@ struct DungeonApp {
hover_corridor_idx: Option<usize>,
hover_door_idx: Option<usize>,
hover_text_idx: Option<usize>,
hover_marker_kind: Option<MarkerKind>,
hover_marker: Option<HoverMarker>,
}
impl Default for DungeonApp {
@@ -80,6 +80,7 @@ impl Default for DungeonApp {
door_settings_from_ui(&settings),
window_settings_from_ui(&settings),
);
let layout = populate_random_markers(layout, &settings);
Self {
settings,
layout,
@@ -95,7 +96,7 @@ impl Default for DungeonApp {
hover_corridor_idx: None,
hover_door_idx: None,
hover_text_idx: None,
hover_marker_kind: None,
hover_marker: None,
}
}
}
@@ -131,6 +132,18 @@ impl eframe::App for DungeonApp {
if self.settings.min_window_width > self.settings.max_window_width {
self.settings.max_window_width = self.settings.min_window_width;
}
if self.settings.min_start_marker_size > self.settings.max_start_marker_size {
self.settings.max_start_marker_size = self.settings.min_start_marker_size;
}
if self.settings.min_end_marker_size > self.settings.max_end_marker_size {
self.settings.max_end_marker_size = self.settings.min_end_marker_size;
}
if self.settings.min_start_marker_count > self.settings.max_start_marker_count {
self.settings.max_start_marker_count = self.settings.min_start_marker_count;
}
if self.settings.min_end_marker_count > self.settings.max_end_marker_count {
self.settings.max_end_marker_count = self.settings.min_end_marker_count;
}
if undo_requested {
self.undo();
@@ -255,7 +268,7 @@ impl eframe::App for DungeonApp {
&self.layout,
self.settings.colorblind_mode,
self.hover_text_idx,
self.hover_marker_kind,
self.hover_marker,
);
self.draw_add_overlay(&painter, &geometry);
self.draw_resize_overlay(&painter, &geometry);
@@ -297,7 +310,7 @@ impl DungeonApp {
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_text_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
self.pending_delete = false;
}
@@ -331,7 +344,7 @@ impl DungeonApp {
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_text_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
self.pending_delete = false;
}
@@ -339,7 +352,7 @@ impl DungeonApp {
fn regenerate_layout(&mut self) {
self.drag_state = None;
self.suppressed_auto_door_edges.clear();
self.layout = layout::generate_layout(
let layout = layout::generate_layout(
self.settings.cols,
self.settings.rows,
self.settings.room_count,
@@ -355,6 +368,7 @@ impl DungeonApp {
door_settings_from_ui(&self.settings),
window_settings_from_ui(&self.settings),
);
self.layout = populate_random_markers(layout, &self.settings);
}
// Handle dragging rooms or corridors with the primary mouse button.
@@ -376,6 +390,12 @@ impl DungeonApp {
{
self.push_undo_snapshot();
self.drag_state = Some(DragState::Text(TextDragState { text_idx }));
} else if response.drag_started()
&& let Some(pointer_pos) = response.interact_pointer_pos()
&& let Some(marker_drag) = self.marker_drag_at_pointer(pointer_pos, geometry)
{
self.push_undo_snapshot();
self.drag_state = Some(DragState::Marker(marker_drag));
} else if response.drag_started()
&& let Some(pointer_pos) = response.interact_pointer_pos()
&& let Some((room_idx, offset_x, offset_y)) =
@@ -402,6 +422,7 @@ impl DungeonApp {
match drag_state {
DragState::Room(drag) => self.drag_room_to_pointer(drag, pointer_pos, geometry),
DragState::Text(drag) => self.drag_text_to_pointer(drag, pointer_pos, geometry),
DragState::Marker(drag) => self.drag_marker_to_pointer(drag, pointer_pos, geometry),
DragState::Corridor(drag) => {
self.drag_corridor_to_pointer(drag, pointer_pos, geometry)
}
@@ -827,18 +848,14 @@ impl DungeonApp {
return;
}
let size = match kind {
MarkerKind::Start => self.settings.start_marker_size,
MarkerKind::End => self.settings.end_marker_size,
}
.clamp(1, 10);
let size = manual_marker_size(&self.settings, kind);
let origin = centered_marker_origin(cell, size, self.settings.cols, self.settings.rows);
let marker = layout::AreaMarker { cell: origin, size };
self.push_undo_snapshot();
match kind {
MarkerKind::Start => self.layout.start_marker = Some(marker),
MarkerKind::End => self.layout.end_marker = Some(marker),
MarkerKind::Start => self.layout.start_markers.push(marker),
MarkerKind::End => self.layout.end_markers.push(marker),
}
}
@@ -849,7 +866,7 @@ impl DungeonApp {
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_text_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
return;
};
if let Some(edge) = self.door_edge_at_pointer(pointer_pos, geometry) {
@@ -863,7 +880,7 @@ impl DungeonApp {
self.hover_room_idx = None;
self.hover_corridor_idx = None;
self.hover_text_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
return;
}
}
@@ -873,12 +890,12 @@ impl DungeonApp {
self.hover_room_idx = None;
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
return;
}
self.hover_marker_kind = self.marker_at_pointer(pointer_pos, geometry);
if self.hover_marker_kind.is_some() {
self.hover_marker = self.marker_at_pointer(pointer_pos, geometry);
if self.hover_marker.is_some() {
self.hover_room_idx = None;
self.hover_corridor_idx = None;
self.hover_door_idx = None;
@@ -889,17 +906,17 @@ impl DungeonApp {
self.hover_room_idx = Some(room_idx);
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
} else {
self.hover_room_idx = None;
if let Some(corridor_drag) = self.corridor_drag_at_pointer(pointer_pos, geometry) {
self.hover_corridor_idx = Some(corridor_drag.corridor_index);
self.hover_door_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
} else {
self.hover_corridor_idx = None;
self.hover_door_idx = None;
self.hover_marker_kind = None;
self.hover_marker = None;
}
}
}
@@ -917,16 +934,79 @@ impl DungeonApp {
&self,
pointer_pos: egui::Pos2,
geometry: &GridGeometry,
) -> Option<MarkerKind> {
) -> Option<HoverMarker> {
let (grid_x, grid_y) = pointer_to_grid(pointer_pos, geometry)?;
let clicked = (grid_x.floor() as usize, grid_y.floor() as usize);
marker_contains_cell(self.layout.start_marker.as_ref(), clicked)
.then_some(MarkerKind::Start)
self.layout
.start_markers
.iter()
.enumerate()
.find(|(_, marker)| marker_contains_cell(Some(marker), clicked))
.map(|(idx, _)| HoverMarker::Start(idx))
.or_else(|| {
marker_contains_cell(self.layout.end_marker.as_ref(), clicked).then_some(MarkerKind::End)
self.layout
.end_markers
.iter()
.enumerate()
.find(|(_, marker)| marker_contains_cell(Some(marker), clicked))
.map(|(idx, _)| HoverMarker::End(idx))
})
}
fn marker_drag_at_pointer(
&self,
pointer_pos: egui::Pos2,
geometry: &GridGeometry,
) -> Option<MarkerDragState> {
let (grid_x, grid_y) = pointer_to_grid(pointer_pos, geometry)?;
match self.marker_at_pointer(pointer_pos, geometry)? {
HoverMarker::Start(marker_idx) => {
let marker = self.layout.start_markers.get(marker_idx)?;
Some(MarkerDragState {
kind: MarkerKind::Start,
marker_idx,
offset_x: grid_x - marker.cell.0 as f32,
offset_y: grid_y - marker.cell.1 as f32,
})
}
HoverMarker::End(marker_idx) => {
let marker = self.layout.end_markers.get(marker_idx)?;
Some(MarkerDragState {
kind: MarkerKind::End,
marker_idx,
offset_x: grid_x - marker.cell.0 as f32,
offset_y: grid_y - marker.cell.1 as f32,
})
}
}
}
fn drag_marker_to_pointer(
&mut self,
drag: MarkerDragState,
pointer_pos: egui::Pos2,
geometry: &GridGeometry,
) {
let Some((grid_x, grid_y)) = pointer_to_grid(pointer_pos, geometry) else {
return;
};
let markers = match drag.kind {
MarkerKind::Start => &mut self.layout.start_markers,
MarkerKind::End => &mut self.layout.end_markers,
};
let Some(marker) = markers.get_mut(drag.marker_idx) else {
self.drag_state = None;
return;
};
let max_x = self.settings.cols.saturating_sub(marker.size);
let max_y = self.settings.rows.saturating_sub(marker.size);
let target_x = (grid_x - drag.offset_x).floor().max(0.0) as usize;
let target_y = (grid_y - drag.offset_y).floor().max(0.0) as usize;
marker.cell = (target_x.min(max_x), target_y.min(max_y));
}
// Handle right-click resizing of rooms and return whether resizing is active.
fn handle_resize(
&mut self,
@@ -1241,11 +1321,19 @@ impl DungeonApp {
return;
}
if let Some(kind) = self.marker_at_pointer(pointer_pos, geometry) {
if let Some(marker) = self.marker_at_pointer(pointer_pos, geometry) {
self.push_undo_snapshot();
match kind {
MarkerKind::Start => self.layout.start_marker = None,
MarkerKind::End => self.layout.end_marker = None,
match marker {
HoverMarker::Start(idx) => {
if idx < self.layout.start_markers.len() {
self.layout.start_markers.remove(idx);
}
}
HoverMarker::End(idx) => {
if idx < self.layout.end_markers.len() {
self.layout.end_markers.remove(idx);
}
}
}
return;
}
@@ -1461,6 +1549,14 @@ struct TextDragState {
text_idx: usize,
}
#[derive(Debug, Clone)]
struct MarkerDragState {
kind: MarkerKind,
marker_idx: usize,
offset_x: f32,
offset_y: f32,
}
#[derive(Debug, Clone)]
struct CorridorDragState {
corridor_index: usize,
@@ -1488,6 +1584,12 @@ enum MarkerKind {
End,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum HoverMarker {
Start(usize),
End(usize),
}
#[derive(Debug, Clone)]
struct RoomResizeState {
room_idx: usize,
@@ -1499,6 +1601,7 @@ struct RoomResizeState {
enum DragState {
Room(RoomDragState),
Text(TextDragState),
Marker(MarkerDragState),
Corridor(CorridorDragState),
}
@@ -1579,7 +1682,7 @@ fn draw_layout(
layout: &DungeonLayout,
colorblind_mode: bool,
hover_text_idx: Option<usize>,
hover_marker_kind: Option<MarkerKind>,
hover_marker: Option<HoverMarker>,
) {
let wall_width_px = (geometry.cell_size / 5.0).max(1.0);
let door_width_px = (geometry.cell_size / 10.0).max(1.0);
@@ -1832,7 +1935,7 @@ fn draw_layout(
);
}
if let Some(marker) = layout.start_marker.as_ref() {
for (idx, marker) in layout.start_markers.iter().enumerate() {
draw_area_marker(
painter,
geometry,
@@ -1840,10 +1943,10 @@ fn draw_layout(
"S",
Color32::from_rgb(60, 220, 200),
colorblind_mode,
hover_marker_kind == Some(MarkerKind::Start),
hover_marker == Some(HoverMarker::Start(idx)),
);
}
if let Some(marker) = layout.end_marker.as_ref() {
for (idx, marker) in layout.end_markers.iter().enumerate() {
draw_area_marker(
painter,
geometry,
@@ -1851,7 +1954,7 @@ fn draw_layout(
"E",
Color32::from_rgb(240, 90, 90),
colorblind_mode,
hover_marker_kind == Some(MarkerKind::End),
hover_marker == Some(HoverMarker::End(idx)),
);
}
}
@@ -1901,6 +2004,180 @@ fn centered_marker_origin(
(cell.0.saturating_sub(half).min(max_x), cell.1.saturating_sub(half).min(max_y))
}
fn populate_random_markers(
mut layout: DungeonLayout,
settings: &UiSettings,
) -> DungeonLayout {
layout.start_markers.clear();
layout.end_markers.clear();
if layout.rooms.is_empty() {
return layout;
}
let start_count = random_range_inclusive(
settings.min_start_marker_count,
settings.max_start_marker_count,
seed::derive_seed(settings.seed, 10_001),
);
let end_count = random_range_inclusive(
settings.min_end_marker_count,
settings.max_end_marker_count,
seed::derive_seed(settings.seed, 10_002),
);
let pair_count = start_count.min(end_count);
let mut available_start_rooms: Vec<usize> = (0..layout.rooms.len()).collect();
let mut available_end_rooms: Vec<usize> = (0..layout.rooms.len()).collect();
for pair_idx in 0..pair_count {
let (start_room_idx, end_room_idx) =
farthest_room_pair(&layout.rooms, &available_start_rooms, &available_end_rooms);
let start_room = &layout.rooms[start_room_idx];
let end_room = &layout.rooms[end_room_idx];
layout.start_markers.push(marker_in_room(
start_room,
settings.min_start_marker_size,
settings.max_start_marker_size,
seed::derive_seed(settings.seed, 11_000 + pair_idx as u64),
));
layout.end_markers.push(marker_in_room(
end_room,
settings.min_end_marker_size,
settings.max_end_marker_size,
seed::derive_seed(settings.seed, 12_000 + pair_idx as u64),
));
consume_room(&mut available_start_rooms, start_room_idx);
consume_room(&mut available_end_rooms, end_room_idx);
}
for idx in pair_count..start_count {
let room_idx = pick_room_index(
&available_start_rooms,
layout.rooms.len(),
seed::derive_seed(settings.seed, 13_000 + idx as u64),
);
let room = &layout.rooms[room_idx];
layout.start_markers.push(marker_in_room(
room,
settings.min_start_marker_size,
settings.max_start_marker_size,
seed::derive_seed(settings.seed, 14_000 + idx as u64),
));
consume_room(&mut available_start_rooms, room_idx);
}
for idx in pair_count..end_count {
let room_idx = pick_room_index(
&available_end_rooms,
layout.rooms.len(),
seed::derive_seed(settings.seed, 15_000 + idx as u64),
);
let room = &layout.rooms[room_idx];
layout.end_markers.push(marker_in_room(
room,
settings.min_end_marker_size,
settings.max_end_marker_size,
seed::derive_seed(settings.seed, 16_000 + idx as u64),
));
consume_room(&mut available_end_rooms, room_idx);
}
layout
}
fn random_range_inclusive(min: usize, max: usize, seed_value: u64) -> usize {
let min = min.max(1);
let max = max.max(min);
let span = max - min + 1;
min + (seed_value as usize % span)
}
fn manual_marker_size(settings: &UiSettings, kind: MarkerKind) -> usize {
match kind {
MarkerKind::Start => settings.min_start_marker_size.min(settings.max_start_marker_size),
MarkerKind::End => settings.min_end_marker_size.min(settings.max_end_marker_size),
}
.clamp(1, 10)
}
fn marker_in_room(room: &layout::Room, min_size: usize, max_size: usize, seed_value: u64) -> layout::AreaMarker {
let room_limit = room.width.min(room.height).max(1);
let min_size = min_size.clamp(1, 10).min(room_limit);
let max_size = max_size.clamp(min_size, 10).min(room_limit);
let size = random_range_inclusive(min_size, max_size, seed_value.rotate_left(7));
let x_span = room.width.saturating_sub(size);
let y_span = room.height.saturating_sub(size);
let x = room.x
+ if x_span == 0 {
0
} else {
(seed_value as usize) % (x_span + 1)
};
let y = room.y
+ if y_span == 0 {
0
} else {
(seed_value.rotate_left(19) as usize) % (y_span + 1)
};
layout::AreaMarker { cell: (x, y), size }
}
fn farthest_room_pair(
rooms: &[layout::Room],
available_start_rooms: &[usize],
available_end_rooms: &[usize],
) -> (usize, usize) {
let start_rooms = if available_start_rooms.is_empty() {
(0..rooms.len()).collect::<Vec<_>>()
} else {
available_start_rooms.to_vec()
};
let end_rooms = if available_end_rooms.is_empty() {
(0..rooms.len()).collect::<Vec<_>>()
} else {
available_end_rooms.to_vec()
};
let mut best = (start_rooms[0], end_rooms[0]);
let mut best_dist = 0usize;
for &start_idx in &start_rooms {
for &end_idx in &end_rooms {
if rooms.len() > 1 && start_idx == end_idx {
continue;
}
let dist = room_distance_sq(&rooms[start_idx], &rooms[end_idx]);
if dist > best_dist {
best = (start_idx, end_idx);
best_dist = dist;
}
}
}
best
}
fn room_distance_sq(a: &layout::Room, b: &layout::Room) -> usize {
let ac = a.center_cell();
let bc = b.center_cell();
let dx = ac.0.abs_diff(bc.0);
let dy = ac.1.abs_diff(bc.1);
dx * dx + dy * dy
}
fn consume_room(available_rooms: &mut Vec<usize>, room_idx: usize) {
if let Some(pos) = available_rooms.iter().position(|&idx| idx == room_idx) {
available_rooms.remove(pos);
}
}
fn pick_room_index(available_rooms: &[usize], room_count: usize, seed_value: u64) -> usize {
if !available_rooms.is_empty() {
available_rooms[seed_value as usize % available_rooms.len()]
} else {
seed_value as usize % room_count.max(1)
}
}
fn draw_area_marker(
painter: &egui::Painter,
geometry: &GridGeometry,
+140 -65
View File
@@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize};
enum Tab {
Generate,
Layout,
StartAndEnd,
Add,
MonstersAndTraps,
}
impl Default for Tab {
@@ -132,8 +132,14 @@ pub struct UiSettings {
pub export_show_grid: bool,
pub add_tool: AddTool,
pub add_text_value: String,
pub start_marker_size: usize,
pub end_marker_size: usize,
pub min_start_marker_size: usize,
pub max_start_marker_size: usize,
pub min_end_marker_size: usize,
pub max_end_marker_size: usize,
pub min_start_marker_count: usize,
pub max_start_marker_count: usize,
pub min_end_marker_count: usize,
pub max_end_marker_count: usize,
active_tab: Tab,
}
@@ -173,8 +179,14 @@ impl Default for UiSettings {
export_show_grid: true,
add_tool: AddTool::None,
add_text_value: "Text".to_string(),
start_marker_size: 1,
end_marker_size: 1,
min_start_marker_size: 1,
max_start_marker_size: 1,
min_end_marker_size: 1,
max_end_marker_size: 1,
min_start_marker_count: 1,
max_start_marker_count: 1,
min_end_marker_count: 1,
max_end_marker_count: 1,
active_tab: Tab::Generate,
}
}
@@ -219,8 +231,8 @@ pub fn draw_side_panel(
ui.horizontal(|ui| {
let is_generate = settings.active_tab == Tab::Generate;
let is_layout = settings.active_tab == Tab::Layout;
let is_start_and_end = settings.active_tab == Tab::StartAndEnd;
let is_add = settings.active_tab == Tab::Add;
let is_monsters_and_traps = settings.active_tab == Tab::MonstersAndTraps;
if ui.selectable_label(is_generate, "Generate").clicked() {
settings.active_tab = Tab::Generate;
@@ -228,23 +240,20 @@ pub fn draw_side_panel(
if ui.selectable_label(is_layout, "Layout").clicked() {
settings.active_tab = Tab::Layout;
}
if ui.selectable_label(is_start_and_end, "Start & End").clicked() {
settings.active_tab = Tab::StartAndEnd;
}
if ui.selectable_label(is_add, "Add").clicked() {
settings.active_tab = Tab::Add;
}
if ui
.selectable_label(is_monsters_and_traps, "Monsters & Traps")
.clicked()
{
settings.active_tab = Tab::MonstersAndTraps;
}
});
ui.separator();
match settings.active_tab {
Tab::Generate => draw_generate_tab(ui, settings, &mut result, export_in_progress),
Tab::Layout => draw_layout_tab(ui, settings, &mut result),
Tab::StartAndEnd => draw_start_and_end_tab(ui, settings, &mut result),
Tab::Add => draw_add_tab(ui, settings),
Tab::MonstersAndTraps => draw_monsters_and_traps_tab(ui, settings),
}
});
@@ -740,6 +749,8 @@ fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings) {
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.add_space(6.0);
@@ -759,72 +770,136 @@ fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings) {
ui.label("Note: Left click on the canvas to place the text.");
response
}
AddTool::StartMarker | AddTool::EndMarker => {
ui.label("Use the Monsters & Traps tab to place start and end markers.")
}
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::None => ui.label("Select a tool to add rooms or corridors."),
};
}
fn draw_monsters_and_traps_tab(ui: &mut egui::Ui, settings: &mut UiSettings) {
ui.label(RichText::new("Start / End Markers").strong());
fn draw_start_and_end_tab(
ui: &mut egui::Ui,
settings: &mut UiSettings,
result: &mut SidePanelResult,
) {
ui.label(RichText::new("Start Markers").strong());
ui.add_space(8.0);
ui.label("Start Marker Size");
ui.label("Min Start Marker Size");
ui.horizontal(|ui| {
ui.add(egui::Slider::new(&mut settings.start_marker_size, 1..=10).show_value(false));
ui.add(
egui::DragValue::new(&mut settings.start_marker_size)
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_start_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_start_marker_size)
.speed(1.0)
.range(1..=10),
);
)
.changed();
});
ui.add_space(4.0);
if ui
.selectable_label(settings.add_tool == AddTool::StartMarker, "Place Start Marker")
.clicked()
{
settings.add_tool = if settings.add_tool == AddTool::StartMarker {
AddTool::None
} else {
AddTool::StartMarker
};
}
ui.add_space(10.0);
ui.label("End Marker Size");
ui.add_space(6.0);
ui.label("Max Start Marker Size");
ui.horizontal(|ui| {
ui.add(egui::Slider::new(&mut settings.end_marker_size, 1..=10).show_value(false));
ui.add(
egui::DragValue::new(&mut settings.end_marker_size)
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_start_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_start_marker_size)
.speed(1.0)
.range(1..=10),
);
)
.changed();
});
ui.add_space(6.0);
ui.label("Min Start Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_start_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_start_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max Start Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_start_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_start_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(4.0);
if ui
.selectable_label(settings.add_tool == AddTool::EndMarker, "Place End Marker")
.clicked()
{
settings.add_tool = if settings.add_tool == AddTool::EndMarker {
AddTool::None
} else {
AddTool::EndMarker
};
}
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("End Markers").strong());
ui.add_space(8.0);
ui.label("Min End Marker Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_end_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_end_marker_size)
.speed(1.0)
.range(1..=10),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max End Marker Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_end_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_end_marker_size)
.speed(1.0)
.range(1..=10),
)
.changed();
});
ui.add_space(6.0);
ui.label("Min End Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_end_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_end_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max End Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_end_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_end_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(8.0);
match settings.add_tool {
AddTool::StartMarker => {
ui.label("Click the grid to place the start marker. It is centered on the clicked cell.");
}
AddTool::EndMarker => {
ui.label("Click the grid to place the end marker. It is centered on the clicked cell.");
}
_ => {
ui.label("Monsters, traps, and bosses will live here next. For now, place start and end markers.");
}
}
ui.label("Markers are generated inside rooms. Matching start/end indices are paired as far apart as possible.");
}