added generation of start/end and settings for that, along with stuff for place, move, and remove
This commit is contained in:
+4
-4
@@ -276,10 +276,10 @@ fn render_pixmap(layout: &DungeonLayout, settings: &UiSettings) -> Result<Pixmap
|
|||||||
draw_window(&mut pixmap, &g, window, door_w, WINDOW, style);
|
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);
|
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);
|
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);
|
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);
|
append_svg_area_marker(&mut s, &g, marker, "E", END_MARKER, settings.colorblind_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -94,8 +94,8 @@ pub struct DungeonLayout {
|
|||||||
pub doors: Vec<Door>,
|
pub doors: Vec<Door>,
|
||||||
pub windows: Vec<Window>,
|
pub windows: Vec<Window>,
|
||||||
pub text_labels: Vec<TextLabel>,
|
pub text_labels: Vec<TextLabel>,
|
||||||
pub start_marker: Option<AreaMarker>,
|
pub start_markers: Vec<AreaMarker>,
|
||||||
pub end_marker: Option<AreaMarker>,
|
pub end_markers: Vec<AreaMarker>,
|
||||||
pub packed_rooms: bool,
|
pub packed_rooms: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +107,8 @@ impl Default for DungeonLayout {
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: false,
|
packed_rooms: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,8 +176,8 @@ pub fn generate_layout(
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: pack_rooms_without_corridors,
|
packed_rooms: pack_rooms_without_corridors,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -201,8 +201,8 @@ pub fn generate_layout(
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: pack_rooms_without_corridors,
|
packed_rooms: pack_rooms_without_corridors,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -231,8 +231,8 @@ pub fn generate_layout(
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: true,
|
packed_rooms: true,
|
||||||
};
|
};
|
||||||
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
||||||
@@ -290,8 +290,8 @@ pub fn generate_layout(
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: false,
|
packed_rooms: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -346,8 +346,8 @@ pub fn generate_layout(
|
|||||||
doors: Vec::new(),
|
doors: Vec::new(),
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
text_labels: Vec::new(),
|
text_labels: Vec::new(),
|
||||||
start_marker: None,
|
start_markers: Vec::new(),
|
||||||
end_marker: None,
|
end_markers: Vec::new(),
|
||||||
packed_rooms: false,
|
packed_rooms: false,
|
||||||
};
|
};
|
||||||
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
||||||
|
|||||||
+311
-34
@@ -57,7 +57,7 @@ struct DungeonApp {
|
|||||||
hover_corridor_idx: Option<usize>,
|
hover_corridor_idx: Option<usize>,
|
||||||
hover_door_idx: Option<usize>,
|
hover_door_idx: Option<usize>,
|
||||||
hover_text_idx: Option<usize>,
|
hover_text_idx: Option<usize>,
|
||||||
hover_marker_kind: Option<MarkerKind>,
|
hover_marker: Option<HoverMarker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DungeonApp {
|
impl Default for DungeonApp {
|
||||||
@@ -80,6 +80,7 @@ impl Default for DungeonApp {
|
|||||||
door_settings_from_ui(&settings),
|
door_settings_from_ui(&settings),
|
||||||
window_settings_from_ui(&settings),
|
window_settings_from_ui(&settings),
|
||||||
);
|
);
|
||||||
|
let layout = populate_random_markers(layout, &settings);
|
||||||
Self {
|
Self {
|
||||||
settings,
|
settings,
|
||||||
layout,
|
layout,
|
||||||
@@ -95,7 +96,7 @@ impl Default for DungeonApp {
|
|||||||
hover_corridor_idx: None,
|
hover_corridor_idx: None,
|
||||||
hover_door_idx: None,
|
hover_door_idx: None,
|
||||||
hover_text_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 {
|
if self.settings.min_window_width > self.settings.max_window_width {
|
||||||
self.settings.max_window_width = self.settings.min_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 {
|
if undo_requested {
|
||||||
self.undo();
|
self.undo();
|
||||||
@@ -255,7 +268,7 @@ impl eframe::App for DungeonApp {
|
|||||||
&self.layout,
|
&self.layout,
|
||||||
self.settings.colorblind_mode,
|
self.settings.colorblind_mode,
|
||||||
self.hover_text_idx,
|
self.hover_text_idx,
|
||||||
self.hover_marker_kind,
|
self.hover_marker,
|
||||||
);
|
);
|
||||||
self.draw_add_overlay(&painter, &geometry);
|
self.draw_add_overlay(&painter, &geometry);
|
||||||
self.draw_resize_overlay(&painter, &geometry);
|
self.draw_resize_overlay(&painter, &geometry);
|
||||||
@@ -297,7 +310,7 @@ impl DungeonApp {
|
|||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_text_idx = None;
|
self.hover_text_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
self.pending_delete = false;
|
self.pending_delete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +344,7 @@ impl DungeonApp {
|
|||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_text_idx = None;
|
self.hover_text_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
self.pending_delete = false;
|
self.pending_delete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +352,7 @@ impl DungeonApp {
|
|||||||
fn regenerate_layout(&mut self) {
|
fn regenerate_layout(&mut self) {
|
||||||
self.drag_state = None;
|
self.drag_state = None;
|
||||||
self.suppressed_auto_door_edges.clear();
|
self.suppressed_auto_door_edges.clear();
|
||||||
self.layout = layout::generate_layout(
|
let layout = layout::generate_layout(
|
||||||
self.settings.cols,
|
self.settings.cols,
|
||||||
self.settings.rows,
|
self.settings.rows,
|
||||||
self.settings.room_count,
|
self.settings.room_count,
|
||||||
@@ -355,6 +368,7 @@ impl DungeonApp {
|
|||||||
door_settings_from_ui(&self.settings),
|
door_settings_from_ui(&self.settings),
|
||||||
window_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.
|
// Handle dragging rooms or corridors with the primary mouse button.
|
||||||
@@ -376,6 +390,12 @@ impl DungeonApp {
|
|||||||
{
|
{
|
||||||
self.push_undo_snapshot();
|
self.push_undo_snapshot();
|
||||||
self.drag_state = Some(DragState::Text(TextDragState { text_idx }));
|
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()
|
} else if response.drag_started()
|
||||||
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
&& let Some(pointer_pos) = response.interact_pointer_pos()
|
||||||
&& let Some((room_idx, offset_x, offset_y)) =
|
&& let Some((room_idx, offset_x, offset_y)) =
|
||||||
@@ -402,6 +422,7 @@ impl DungeonApp {
|
|||||||
match drag_state {
|
match drag_state {
|
||||||
DragState::Room(drag) => self.drag_room_to_pointer(drag, pointer_pos, geometry),
|
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::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) => {
|
DragState::Corridor(drag) => {
|
||||||
self.drag_corridor_to_pointer(drag, pointer_pos, geometry)
|
self.drag_corridor_to_pointer(drag, pointer_pos, geometry)
|
||||||
}
|
}
|
||||||
@@ -827,18 +848,14 @@ impl DungeonApp {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = match kind {
|
let size = manual_marker_size(&self.settings, kind);
|
||||||
MarkerKind::Start => self.settings.start_marker_size,
|
|
||||||
MarkerKind::End => self.settings.end_marker_size,
|
|
||||||
}
|
|
||||||
.clamp(1, 10);
|
|
||||||
let origin = centered_marker_origin(cell, size, self.settings.cols, self.settings.rows);
|
let origin = centered_marker_origin(cell, size, self.settings.cols, self.settings.rows);
|
||||||
let marker = layout::AreaMarker { cell: origin, size };
|
let marker = layout::AreaMarker { cell: origin, size };
|
||||||
|
|
||||||
self.push_undo_snapshot();
|
self.push_undo_snapshot();
|
||||||
match kind {
|
match kind {
|
||||||
MarkerKind::Start => self.layout.start_marker = Some(marker),
|
MarkerKind::Start => self.layout.start_markers.push(marker),
|
||||||
MarkerKind::End => self.layout.end_marker = Some(marker),
|
MarkerKind::End => self.layout.end_markers.push(marker),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,7 +866,7 @@ impl DungeonApp {
|
|||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_text_idx = None;
|
self.hover_text_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let Some(edge) = self.door_edge_at_pointer(pointer_pos, geometry) {
|
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_room_idx = None;
|
||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_text_idx = None;
|
self.hover_text_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -873,12 +890,12 @@ impl DungeonApp {
|
|||||||
self.hover_room_idx = None;
|
self.hover_room_idx = None;
|
||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.hover_marker_kind = self.marker_at_pointer(pointer_pos, geometry);
|
self.hover_marker = self.marker_at_pointer(pointer_pos, geometry);
|
||||||
if self.hover_marker_kind.is_some() {
|
if self.hover_marker.is_some() {
|
||||||
self.hover_room_idx = None;
|
self.hover_room_idx = None;
|
||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
@@ -889,17 +906,17 @@ impl DungeonApp {
|
|||||||
self.hover_room_idx = Some(room_idx);
|
self.hover_room_idx = Some(room_idx);
|
||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
} else {
|
} else {
|
||||||
self.hover_room_idx = None;
|
self.hover_room_idx = None;
|
||||||
if let Some(corridor_drag) = self.corridor_drag_at_pointer(pointer_pos, geometry) {
|
if let Some(corridor_drag) = self.corridor_drag_at_pointer(pointer_pos, geometry) {
|
||||||
self.hover_corridor_idx = Some(corridor_drag.corridor_index);
|
self.hover_corridor_idx = Some(corridor_drag.corridor_index);
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
} else {
|
} else {
|
||||||
self.hover_corridor_idx = None;
|
self.hover_corridor_idx = None;
|
||||||
self.hover_door_idx = None;
|
self.hover_door_idx = None;
|
||||||
self.hover_marker_kind = None;
|
self.hover_marker = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -917,16 +934,79 @@ impl DungeonApp {
|
|||||||
&self,
|
&self,
|
||||||
pointer_pos: egui::Pos2,
|
pointer_pos: egui::Pos2,
|
||||||
geometry: &GridGeometry,
|
geometry: &GridGeometry,
|
||||||
) -> Option<MarkerKind> {
|
) -> Option<HoverMarker> {
|
||||||
let (grid_x, grid_y) = pointer_to_grid(pointer_pos, geometry)?;
|
let (grid_x, grid_y) = pointer_to_grid(pointer_pos, geometry)?;
|
||||||
let clicked = (grid_x.floor() as usize, grid_y.floor() as usize);
|
let clicked = (grid_x.floor() as usize, grid_y.floor() as usize);
|
||||||
marker_contains_cell(self.layout.start_marker.as_ref(), clicked)
|
self.layout
|
||||||
.then_some(MarkerKind::Start)
|
.start_markers
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, marker)| marker_contains_cell(Some(marker), clicked))
|
||||||
|
.map(|(idx, _)| HoverMarker::Start(idx))
|
||||||
.or_else(|| {
|
.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.
|
// Handle right-click resizing of rooms and return whether resizing is active.
|
||||||
fn handle_resize(
|
fn handle_resize(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -1241,11 +1321,19 @@ impl DungeonApp {
|
|||||||
return;
|
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();
|
self.push_undo_snapshot();
|
||||||
match kind {
|
match marker {
|
||||||
MarkerKind::Start => self.layout.start_marker = None,
|
HoverMarker::Start(idx) => {
|
||||||
MarkerKind::End => self.layout.end_marker = None,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1461,6 +1549,14 @@ struct TextDragState {
|
|||||||
text_idx: usize,
|
text_idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct MarkerDragState {
|
||||||
|
kind: MarkerKind,
|
||||||
|
marker_idx: usize,
|
||||||
|
offset_x: f32,
|
||||||
|
offset_y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct CorridorDragState {
|
struct CorridorDragState {
|
||||||
corridor_index: usize,
|
corridor_index: usize,
|
||||||
@@ -1488,6 +1584,12 @@ enum MarkerKind {
|
|||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum HoverMarker {
|
||||||
|
Start(usize),
|
||||||
|
End(usize),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct RoomResizeState {
|
struct RoomResizeState {
|
||||||
room_idx: usize,
|
room_idx: usize,
|
||||||
@@ -1499,6 +1601,7 @@ struct RoomResizeState {
|
|||||||
enum DragState {
|
enum DragState {
|
||||||
Room(RoomDragState),
|
Room(RoomDragState),
|
||||||
Text(TextDragState),
|
Text(TextDragState),
|
||||||
|
Marker(MarkerDragState),
|
||||||
Corridor(CorridorDragState),
|
Corridor(CorridorDragState),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1579,7 +1682,7 @@ fn draw_layout(
|
|||||||
layout: &DungeonLayout,
|
layout: &DungeonLayout,
|
||||||
colorblind_mode: bool,
|
colorblind_mode: bool,
|
||||||
hover_text_idx: Option<usize>,
|
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 wall_width_px = (geometry.cell_size / 5.0).max(1.0);
|
||||||
let door_width_px = (geometry.cell_size / 10.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(
|
draw_area_marker(
|
||||||
painter,
|
painter,
|
||||||
geometry,
|
geometry,
|
||||||
@@ -1840,10 +1943,10 @@ fn draw_layout(
|
|||||||
"S",
|
"S",
|
||||||
Color32::from_rgb(60, 220, 200),
|
Color32::from_rgb(60, 220, 200),
|
||||||
colorblind_mode,
|
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(
|
draw_area_marker(
|
||||||
painter,
|
painter,
|
||||||
geometry,
|
geometry,
|
||||||
@@ -1851,7 +1954,7 @@ fn draw_layout(
|
|||||||
"E",
|
"E",
|
||||||
Color32::from_rgb(240, 90, 90),
|
Color32::from_rgb(240, 90, 90),
|
||||||
colorblind_mode,
|
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))
|
(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(
|
fn draw_area_marker(
|
||||||
painter: &egui::Painter,
|
painter: &egui::Painter,
|
||||||
geometry: &GridGeometry,
|
geometry: &GridGeometry,
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
enum Tab {
|
enum Tab {
|
||||||
Generate,
|
Generate,
|
||||||
Layout,
|
Layout,
|
||||||
|
StartAndEnd,
|
||||||
Add,
|
Add,
|
||||||
MonstersAndTraps,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Tab {
|
impl Default for Tab {
|
||||||
@@ -132,8 +132,14 @@ pub struct UiSettings {
|
|||||||
pub export_show_grid: bool,
|
pub export_show_grid: bool,
|
||||||
pub add_tool: AddTool,
|
pub add_tool: AddTool,
|
||||||
pub add_text_value: String,
|
pub add_text_value: String,
|
||||||
pub start_marker_size: usize,
|
pub min_start_marker_size: usize,
|
||||||
pub end_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,
|
active_tab: Tab,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,8 +179,14 @@ impl Default for UiSettings {
|
|||||||
export_show_grid: true,
|
export_show_grid: true,
|
||||||
add_tool: AddTool::None,
|
add_tool: AddTool::None,
|
||||||
add_text_value: "Text".to_string(),
|
add_text_value: "Text".to_string(),
|
||||||
start_marker_size: 1,
|
min_start_marker_size: 1,
|
||||||
end_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,
|
active_tab: Tab::Generate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,8 +231,8 @@ pub fn draw_side_panel(
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let is_generate = settings.active_tab == Tab::Generate;
|
let is_generate = settings.active_tab == Tab::Generate;
|
||||||
let is_layout = settings.active_tab == Tab::Layout;
|
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_add = settings.active_tab == Tab::Add;
|
||||||
let is_monsters_and_traps = settings.active_tab == Tab::MonstersAndTraps;
|
|
||||||
|
|
||||||
if ui.selectable_label(is_generate, "Generate").clicked() {
|
if ui.selectable_label(is_generate, "Generate").clicked() {
|
||||||
settings.active_tab = Tab::Generate;
|
settings.active_tab = Tab::Generate;
|
||||||
@@ -228,23 +240,20 @@ pub fn draw_side_panel(
|
|||||||
if ui.selectable_label(is_layout, "Layout").clicked() {
|
if ui.selectable_label(is_layout, "Layout").clicked() {
|
||||||
settings.active_tab = Tab::Layout;
|
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() {
|
if ui.selectable_label(is_add, "Add").clicked() {
|
||||||
settings.active_tab = Tab::Add;
|
settings.active_tab = Tab::Add;
|
||||||
}
|
}
|
||||||
if ui
|
|
||||||
.selectable_label(is_monsters_and_traps, "Monsters & Traps")
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
settings.active_tab = Tab::MonstersAndTraps;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
match settings.active_tab {
|
match settings.active_tab {
|
||||||
Tab::Generate => draw_generate_tab(ui, settings, &mut result, export_in_progress),
|
Tab::Generate => draw_generate_tab(ui, settings, &mut result, export_in_progress),
|
||||||
Tab::Layout => draw_layout_tab(ui, settings, &mut result),
|
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::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.add_space(4.0);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.selectable_value(&mut settings.add_tool, AddTool::Text, "Add Text");
|
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);
|
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.");
|
ui.label("Note: Left click on the canvas to place the text.");
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
AddTool::StartMarker | AddTool::EndMarker => {
|
AddTool::StartMarker => ui.label("Click the grid to place the start marker."),
|
||||||
ui.label("Use the Monsters & Traps tab to place start and end markers.")
|
AddTool::EndMarker => ui.label("Click the grid to place the end 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."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_monsters_and_traps_tab(ui: &mut egui::Ui, settings: &mut UiSettings) {
|
fn draw_start_and_end_tab(
|
||||||
ui.label(RichText::new("Start / End Markers").strong());
|
ui: &mut egui::Ui,
|
||||||
|
settings: &mut UiSettings,
|
||||||
|
result: &mut SidePanelResult,
|
||||||
|
) {
|
||||||
|
ui.label(RichText::new("Start Markers").strong());
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
ui.label("Min Start Marker Size");
|
||||||
ui.label("Start Marker Size");
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(egui::Slider::new(&mut settings.start_marker_size, 1..=10).show_value(false));
|
result.settings_changed |= ui
|
||||||
ui.add(
|
.add(egui::Slider::new(&mut settings.min_start_marker_size, 1..=10).show_value(false))
|
||||||
egui::DragValue::new(&mut settings.start_marker_size)
|
.changed();
|
||||||
|
result.settings_changed |= ui
|
||||||
|
.add(
|
||||||
|
egui::DragValue::new(&mut settings.min_start_marker_size)
|
||||||
.speed(1.0)
|
.speed(1.0)
|
||||||
.range(1..=10),
|
.range(1..=10),
|
||||||
);
|
)
|
||||||
|
.changed();
|
||||||
});
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
ui.add_space(4.0);
|
ui.label("Max Start Marker Size");
|
||||||
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.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(egui::Slider::new(&mut settings.end_marker_size, 1..=10).show_value(false));
|
result.settings_changed |= ui
|
||||||
ui.add(
|
.add(egui::Slider::new(&mut settings.max_start_marker_size, 1..=10).show_value(false))
|
||||||
egui::DragValue::new(&mut settings.end_marker_size)
|
.changed();
|
||||||
|
result.settings_changed |= ui
|
||||||
|
.add(
|
||||||
|
egui::DragValue::new(&mut settings.max_start_marker_size)
|
||||||
.speed(1.0)
|
.speed(1.0)
|
||||||
.range(1..=10),
|
.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);
|
ui.add_space(12.0);
|
||||||
if ui
|
ui.separator();
|
||||||
.selectable_label(settings.add_tool == AddTool::EndMarker, "Place End Marker")
|
ui.add_space(8.0);
|
||||||
.clicked()
|
ui.label(RichText::new("End Markers").strong());
|
||||||
{
|
ui.add_space(8.0);
|
||||||
settings.add_tool = if settings.add_tool == AddTool::EndMarker {
|
ui.label("Min End Marker Size");
|
||||||
AddTool::None
|
ui.horizontal(|ui| {
|
||||||
} else {
|
result.settings_changed |= ui
|
||||||
AddTool::EndMarker
|
.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);
|
ui.add_space(8.0);
|
||||||
match settings.add_tool {
|
ui.label("Markers are generated inside rooms. Matching start/end indices are paired as far apart as possible.");
|
||||||
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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user