From 2720735a58668d1e2f8e4b747d757e81d7043a45 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sun, 13 Oct 2024 01:23:56 +0200 Subject: [PATCH] add button to clone solutions --- README.md | 4 ++-- src/editor.rs | 15 +++------------ src/main.rs | 25 ++++++++++++++++--------- src/solution.rs | 19 +++++++++++++------ src/util.rs | 8 ++++++++ 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 08d475b..14ae1f1 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ blueprint rotation? ```json { "level_id": "00_zeroes", - "solution_id": "solution_0", + "solution_id": 0, "name": "unnamed 1", "board": "oo\nP*\n|-", "score": { @@ -71,7 +71,7 @@ blueprint rotation? `blueprints/blueprint_0.json` ```json { - "id": "blueprint_0", + "id": 0, "name": "zero_printer", "board": "o -B I\n> * < \n" } diff --git a/src/editor.rs b/src/editor.rs index 00e522d..209eb16 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -8,7 +8,7 @@ use raylib::prelude::*; use crate::{ blueprint::Blueprint, - draw_scaled_texture, draw_usize, + draw_scaled_texture, draw_usize, get_free_id, get_scroll, level::Level, marble_engine::{ board::Board, @@ -18,7 +18,7 @@ use crate::{ }, simple_button, simple_option_button, slider, solution::{Score, Solution}, - text_input, texture_option_button, get_scroll, userdata_dir, Scroll, Textures, + text_input, texture_option_button, userdata_dir, Scroll, Textures, }; const HEADER_HEIGHT: i32 = 40; @@ -254,16 +254,7 @@ impl Editor { } } board.trim_size(0); - let mut id = 0; - 'outer: loop { - for b in &self.blueprints { - if b.id() == id { - id += 1; - continue 'outer; - } - } - break; - } + let id = get_free_id(&self.blueprints, Blueprint::id); let mut blueprint = Blueprint::new(&board, id); if !self.new_blueprint_name.is_empty() { blueprint.name = self.new_blueprint_name.clone(); diff --git a/src/main.rs b/src/main.rs index 05f9485..4ae388c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -203,10 +203,10 @@ impl Game { solution_y += solution_entry_height + 10; } + let next_id = get_free_id(solutions, Solution::id); if simple_button(d, level_list_width + 10, solution_y, entry_width, 30) { - let n = solutions.len(); self.selected_solution = solutions.len(); - solutions.push(Solution::new(level, n)); + solutions.push(Solution::new(level, next_id)); } d.draw_text( "new solution", @@ -227,14 +227,23 @@ impl Game { 24, true, ); - d.draw_text(solution.id(), column_x, y + 35, 10, Color::GRAY); + let id_text = format!("{}", solution.id()); + d.draw_text(&id_text, column_x, y + 35, 10, Color::GRAY); if simple_button(d, column_x, y + 50, 220, 30) { + let cloned = solution.new_copy(next_id); + self.selected_solution = solutions.len(); + solutions.push(cloned); + return; + } + d.draw_text("clone", column_x + 5, y + 55, 20, Color::WHITE); + + if simple_button(d, column_x, y + 85, 220, 30) { let mut editor = Editor::new(solution.clone(), level.clone()); editor.center_view(d); self.open_editor = Some(editor); } - d.draw_text("edit", column_x + 5, y + 55, 20, Color::WHITE); + d.draw_text("edit", column_x + 5, y + 90, 20, Color::WHITE); } } else { self.solutions.insert(level.id().to_owned(), Vec::new()); @@ -263,7 +272,7 @@ fn get_levels() -> Vec { add_level(d.path()); } } - levels.sort_by_key(Level::sort_order); + levels.sort_unstable_by_key(Level::sort_order); levels } @@ -275,7 +284,6 @@ fn get_solutions() -> HashMap> { if dir.path().is_dir() { let level_name = dir.file_name().to_string_lossy().to_string(); let mut solutions = Vec::new(); - if let Ok(files) = read_dir(dir.path()) { for file in files.flatten() { let s = read_to_string(file.path()) @@ -286,12 +294,11 @@ fn get_solutions() -> HashMap> { solutions.push(solution) } } - - by_level.insert(level_name, solutions); + solutions.sort_unstable_by_key(Solution::id); } + by_level.insert(level_name, solutions); } } } - by_level } diff --git a/src/solution.rs b/src/solution.rs index 12809d6..ffc9b89 100644 --- a/src/solution.rs +++ b/src/solution.rs @@ -9,7 +9,7 @@ use crate::{level::Level, userdata_dir}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Solution { - solution_id: String, + solution_id: usize, level_id: String, pub name: String, pub board: String, @@ -25,18 +25,25 @@ pub struct Score { } impl Solution { - pub fn new(level: &Level, number: usize) -> Self { + pub fn new(level: &Level, id: usize) -> Self { Self { - solution_id: format!("solution_{number}"), + solution_id: id, level_id: level.id().to_owned(), - name: format!("Unnamed {number}"), + name: format!("Unnamed {id}"), board: level.init_board().unwrap_or(String::from(" ")), score: None, } } - pub fn id(&self) -> &str { - &self.solution_id + pub fn new_copy(&self, id: usize) -> Self { + let mut new = self.clone(); + new.solution_id = id; + new.score = None; + new + } + + pub fn id(&self) -> usize { + self.solution_id } pub fn save(&self) { diff --git a/src/util.rs b/src/util.rs index efdd070..732aae3 100644 --- a/src/util.rs +++ b/src/util.rs @@ -307,3 +307,11 @@ pub fn get_scroll(rl: &RaylibHandle) -> Option { None } } + +pub fn get_free_id(items: &[T], id_fn: fn(&T) -> usize) -> usize { + let mut id = 0; + while items.iter().any(|i| id_fn(i) == id) { + id += 1; + } + id +}