From 563c819900510c47c1c4a55c981f1c7fc0977737 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sun, 13 Apr 2025 01:11:17 +0200 Subject: [PATCH] show solutions with no matching level under a 'missing levels' chapter --- CHANGELOG.md | 1 + README.md | 1 - src/level.rs | 14 ++++++++++++++ src/main.rs | 37 ++++++++++++++++++++++++++++++++++--- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75eb77f..b6e086f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Game store page: https://crispypin.itch.io/marble-machinations ## [unreleased] ### added +- create "missing levels" section allowing access to solutions to levels that are no longer available - click to collapse chapters in level list ### fixed - When two input bindings had the same trigger but one has a strict subset of the others modifiers, both would activate when the one with more modifiers was pressed. For example (Ctrl+S -> Save) would also trigger (S -> Wire Tool). Now, Shift+S will still trigger Wire Tool, unless Shift+S (or eg. Shift+Ctrl+S) is bound to something else. diff --git a/README.md b/README.md index d93ce2c..ecedb81 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble - UI layout engine - global scale setting #### unspecified -- show orphaned solutions - comments - editing - add to all intro levels diff --git a/src/level.rs b/src/level.rs index 0a60a84..b8d37f7 100644 --- a/src/level.rs +++ b/src/level.rs @@ -49,6 +49,20 @@ impl IOData { } impl Level { + pub fn new_orphan(id: &str) -> Self { + Self { + id: id.to_owned(), + name: id.to_owned(), + description: String::from( + "No level with this id was found, but there are saved solutions pointing to it.\n +Because input values and expected output is not available, this functions as a sandbox.\n +This allows you to recover any machines you have built here.", + ), + init_board: None, + stages: Vec::new(), + } + } + pub fn id(&self) -> &str { &self.id } diff --git a/src/main.rs b/src/main.rs index 86e4830..5db9b89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use marble_machinations::*; use config::Config; use editor::{Editor, ExitState}; -use level::Chapter; +use level::{Chapter, Level}; use solution::Solution; use theme::*; use ui::{simple_option_button, tex32_button, text_button, text_input, ShapedText, Tooltip}; @@ -46,8 +46,11 @@ fn main() { impl Game { fn new(rl: &mut RaylibHandle, thread: &RaylibThread) -> Self { - let chapters = get_chapters(); + let mut chapters = get_chapters(); let solutions = get_solutions(); + if let Some(orphans) = find_orphans(&chapters, &solutions) { + chapters.push(orphans); + } Self { chapters, @@ -407,9 +410,37 @@ fn get_solutions() -> HashMap> { } solutions.sort_unstable_by_key(Solution::id); } - by_level.insert(level_name, solutions); + if !solutions.is_empty() { + by_level.insert(level_name, solutions); + } } } } by_level } + +fn find_orphans( + chapters: &[Chapter], + solutions: &HashMap>, +) -> Option { + let mut orphan_levels = Vec::new(); + 'outer: for id in solutions.keys() { + for c in chapters { + for l in &c.levels { + if l.id() == id { + continue 'outer; + } + } + } + orphan_levels.push(Level::new_orphan(id)) + } + if orphan_levels.is_empty() { + None + } else { + Some(Chapter { + title: "Missing levels".into(), + levels: orphan_levels, + visible: false, + }) + } +}