show solutions with no matching level under a 'missing levels' chapter

This commit is contained in:
Crispy 2025-04-13 01:11:17 +02:00
parent 522a027f7a
commit 563c819900
4 changed files with 49 additions and 4 deletions

View file

@ -3,6 +3,7 @@ Game store page: https://crispypin.itch.io/marble-machinations
## [unreleased] ## [unreleased]
### added ### added
- create "missing levels" section allowing access to solutions to levels that are no longer available
- click to collapse chapters in level list - click to collapse chapters in level list
### fixed ### 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. - 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.

View file

@ -21,7 +21,6 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble
- UI layout engine - UI layout engine
- global scale setting - global scale setting
#### unspecified #### unspecified
- show orphaned solutions
- comments - comments
- editing - editing
- add to all intro levels - add to all intro levels

View file

@ -49,6 +49,20 @@ impl IOData {
} }
impl Level { 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 { pub fn id(&self) -> &str {
&self.id &self.id
} }

View file

@ -10,7 +10,7 @@ use marble_machinations::*;
use config::Config; use config::Config;
use editor::{Editor, ExitState}; use editor::{Editor, ExitState};
use level::Chapter; use level::{Chapter, Level};
use solution::Solution; use solution::Solution;
use theme::*; use theme::*;
use ui::{simple_option_button, tex32_button, text_button, text_input, ShapedText, Tooltip}; use ui::{simple_option_button, tex32_button, text_button, text_input, ShapedText, Tooltip};
@ -46,8 +46,11 @@ fn main() {
impl Game { impl Game {
fn new(rl: &mut RaylibHandle, thread: &RaylibThread) -> Self { fn new(rl: &mut RaylibHandle, thread: &RaylibThread) -> Self {
let chapters = get_chapters(); let mut chapters = get_chapters();
let solutions = get_solutions(); let solutions = get_solutions();
if let Some(orphans) = find_orphans(&chapters, &solutions) {
chapters.push(orphans);
}
Self { Self {
chapters, chapters,
@ -407,9 +410,37 @@ fn get_solutions() -> HashMap<String, Vec<Solution>> {
} }
solutions.sort_unstable_by_key(Solution::id); solutions.sort_unstable_by_key(Solution::id);
} }
if !solutions.is_empty() {
by_level.insert(level_name, solutions); by_level.insert(level_name, solutions);
} }
} }
} }
}
by_level by_level
} }
fn find_orphans(
chapters: &[Chapter],
solutions: &HashMap<String, Vec<Solution>>,
) -> Option<Chapter> {
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,
})
}
}