diff --git a/src/bmfont_renderer.rs b/src/bmfont_renderer.rs index a227cc0..8f04ab9 100644 --- a/src/bmfont_renderer.rs +++ b/src/bmfont_renderer.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::path::PathBuf; use crate::bmfont::BMFont; @@ -65,13 +65,14 @@ impl BMFontRenderer { pub fn text_width_with_rects + Clone>( &self, iter: I, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], constants: &EngineConstants, ) -> f32 { let mut width = self.text_width(iter.clone(), constants); for chr in iter { - if let Some(rect) = rect_map.get(&chr) { + let rect_map_entry = rect_map.iter().find(|(c, _)| *c == chr); + if let Some((_, rect)) = rect_map_entry { if let Some(glyph) = self.font.chars.get(&chr) { width += rect.width() as f32; width -= glyph.xadvance as f32 * constants.font_scale; @@ -101,7 +102,7 @@ impl BMFontRenderer { y: f32, constants: &EngineConstants, texture_set: &mut TextureSet, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], sprite_batch_name: Option<&str>, ctx: &mut Context, ) -> GameResult { @@ -138,7 +139,7 @@ impl BMFontRenderer { y: f32, constants: &EngineConstants, texture_set: &mut TextureSet, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], sprite_batch_name: Option<&str>, ctx: &mut Context, ) -> GameResult { @@ -199,7 +200,7 @@ impl BMFontRenderer { color: (u8, u8, u8, u8), constants: &EngineConstants, texture_set: &mut TextureSet, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], sprite_batch_name: Option<&str>, ctx: &mut Context, ) -> GameResult { @@ -240,9 +241,7 @@ impl BMFontRenderer { texture_set: &mut TextureSet, ctx: &mut Context, ) -> GameResult { - let rect_map: HashMap> = HashMap::new(); - - self.draw_colored_text_with_rects_scaled(iter, x, y, scale, color, constants, texture_set, &rect_map, None, ctx) + self.draw_colored_text_with_rects_scaled(iter, x, y, scale, color, constants, texture_set, &[], None, ctx) } pub fn draw_colored_text_with_rects_scaled>( @@ -254,7 +253,7 @@ impl BMFontRenderer { color: (u8, u8, u8, u8), constants: &EngineConstants, texture_set: &mut TextureSet, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], sprite_batch_name: Option<&str>, ctx: &mut Context, ) -> GameResult { @@ -266,7 +265,9 @@ impl BMFontRenderer { for chr in iter { if let Some(glyph) = self.font.chars.get(&chr) { - if let Some(rect) = rect_map.get(&chr) { + let rect_map_entry = rect_map.iter().find(|(c, _)| *c == chr); + + if let Some((_, rect)) = rect_map_entry { sprite_rects.push(( offset_x, y + self.line_height(constants) / 2.0 - rect.height() as f32 / 2.0, @@ -311,7 +312,9 @@ impl BMFontRenderer { let mut offset_x = x; for (chr, glyph) in chars.iter() { - if let Some(rect) = rect_map.get(&chr) { + let rect_map_entry = rect_map.iter().find(|(c, _)| *c == *chr); + + if let Some((_, rect)) = rect_map_entry { sprite_rects.push(( offset_x, y + self.line_height(constants) / 2.0 - rect.height() as f32 / 2.0, @@ -379,7 +382,7 @@ impl BMFontRenderer { color: (u8, u8, u8, u8), constants: &EngineConstants, texture_set: &mut TextureSet, - rect_map: &HashMap>, + rect_map: &[(char, Rect)], sprite_batch_name: Option<&str>, ctx: &mut Context, ) -> GameResult { diff --git a/src/i18n.rs b/src/i18n.rs index d43b403..21f3f19 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -53,7 +53,7 @@ impl Locale { self.strings.get(key).unwrap_or(&key.to_owned()).to_owned() } - pub fn tt(&self, key: &str, args: HashMap) -> String { + pub fn tt(&self, key: &str, args: &[(&str, &str)]) -> String { let mut string = self.t(key); for (key, value) in args.iter() { diff --git a/src/menu/controls_menu.rs b/src/menu/controls_menu.rs index bfd89b6..a8c25d8 100644 --- a/src/menu/controls_menu.rs +++ b/src/menu/controls_menu.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use crate::framework::context::Context; use crate::framework::error::GameResult; use crate::framework::gamepad::{self, Axis, AxisDirection, Button, PlayerControllerInputType}; @@ -455,7 +453,7 @@ impl ControlsMenu { 0, MenuEntry::DisabledWhite(state.tt( "menus.controls_menu.rebind_confirm_menu.title", - HashMap::from([("control".to_string(), control.to_string(state))]), + &[("control", control.to_string(state).as_str())], )), ); self.confirm_rebind diff --git a/src/menu/settings_menu.rs b/src/menu/settings_menu.rs index 046f335..9dcd654 100644 --- a/src/menu/settings_menu.rs +++ b/src/menu/settings_menu.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use itertools::Itertools; use crate::framework::context::Context; @@ -320,9 +318,13 @@ impl SettingsMenu { self.links.push_entry(LinksMenuEntry::Link(DISCORD_LINK), MenuEntry::Active("doukutsu-rs Discord".to_owned())); self.links.push_entry(LinksMenuEntry::Link(GITHUB_LINK), MenuEntry::Active("doukutsu-rs GitHub".to_owned())); self.links.push_entry(LinksMenuEntry::Link(DOCS_LINK), MenuEntry::Active("doukutsu-rs Docs".to_owned())); - self.links.push_entry(LinksMenuEntry::Link(TRIBUTE_LINK), MenuEntry::Active("Cave Story Tribute Website".to_owned())); + self.links + .push_entry(LinksMenuEntry::Link(TRIBUTE_LINK), MenuEntry::Active("Cave Story Tribute Website".to_owned())); self.links.push_entry(LinksMenuEntry::Link(GENERAL_LINK), MenuEntry::Active("Cave Story Discord".to_owned())); - self.links.push_entry(LinksMenuEntry::Link(MODDING_LINK),MenuEntry::Active("Cave Story Modding Community".to_owned())); + self.links.push_entry( + LinksMenuEntry::Link(MODDING_LINK), + MenuEntry::Active("Cave Story Modding Community".to_owned()), + ); self.links.push_entry(LinksMenuEntry::Link(GETPLUS_LINK), MenuEntry::Active("Get Cave Story+".to_owned())); self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.t("common.back"))); @@ -359,10 +361,12 @@ impl SettingsMenu { ); self.sound.push_entry( SoundMenuEntry::Soundtrack, - MenuEntry::Active(state.tt( - "menus.options_menu.sound_menu.soundtrack", - HashMap::from([("soundtrack".to_owned(), state.settings.soundtrack.to_owned())]), - )), + MenuEntry::Active( + state.tt( + "menus.options_menu.sound_menu.soundtrack", + &[("soundtrack", state.settings.soundtrack.as_str())], + ), + ), ); self.sound.push_entry(SoundMenuEntry::Back, MenuEntry::Active(state.t("common.back"))); @@ -670,7 +674,7 @@ impl SettingsMenu { let _ = state.settings.save(ctx); } } - MenuSelectionResult::Selected(SoundMenuEntry::BGMInterpolation, toggle) + MenuSelectionResult::Selected(SoundMenuEntry::BGMInterpolation, toggle) | MenuSelectionResult::Right(SoundMenuEntry::BGMInterpolation, toggle, _) => { if let MenuEntry::DescriptiveOptions(_, value, _, _) = toggle { let (new_mode, new_value) = match *value { @@ -680,7 +684,7 @@ impl SettingsMenu { 3 => (InterpolationMode::Polyphase, 4), _ => (InterpolationMode::Nearest, 0), }; - + *value = new_value; state.settings.organya_interpolation = new_mode; state.sound_manager.set_org_interpolation(new_mode); diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 87f7356..a4b733b 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -1,5 +1,4 @@ use std::cell::RefCell; -use std::collections::HashMap; use std::ops::{Deref, Range}; use std::rc::Rc; @@ -2229,17 +2228,17 @@ impl Scene for GameScene { } }; - let text = state.tt("game.cutscene_skip", HashMap::from([("key".to_owned(), key)])); + let text = state.tt("game.cutscene_skip", &[("key", key.as_str())]); let gamepad_sprite_offset = match state.settings.player1_controller_type { ControllerType::Keyboard => 1, ControllerType::Gamepad(index) => ctx.gamepad_context.get_gamepad_sprite_offset(index as usize), }; - let rect_map = HashMap::from([( + let rect_map = [( '=', state.settings.player1_controller_button_map.skip.get_rect(gamepad_sprite_offset, &state.constants), - )]); + )]; let width = state.font.text_width_with_rects(text.chars(), &rect_map, &state.constants); let pos_x = state.canvas_size.0 - width - 20.0; diff --git a/src/scripting/tsc/text_script.rs b/src/scripting/tsc/text_script.rs index b4b73c3..a1a9055 100644 --- a/src/scripting/tsc/text_script.rs +++ b/src/scripting/tsc/text_script.rs @@ -29,6 +29,8 @@ use crate::shared_game_state::ReplayState; use crate::shared_game_state::SharedGameState; use crate::weapon::WeaponType; +const TSC_SUBSTITUTION_MAP_SIZE: usize = 1; + bitfield! { pub struct TextScriptFlags(u16); impl Debug; @@ -134,7 +136,7 @@ pub struct TextScriptVM { pub current_illustration: Option, pub illustration_state: IllustrationState, prev_char: char, - pub substitution_rect_map: HashMap>, + pub substitution_rect_map: [(char, Rect); TSC_SUBSTITUTION_MAP_SIZE], } pub struct Scripts { @@ -210,7 +212,7 @@ impl TextScriptVM { current_illustration: None, illustration_state: IllustrationState::Hidden, prev_char: '\x00', - substitution_rect_map: HashMap::new(), + substitution_rect_map: [('=', Rect::new(0, 0, 0, 0))], } } @@ -251,7 +253,7 @@ impl TextScriptVM { scripts.debug_script = script; } - pub fn set_substitution_rect_map(&mut self, rect_map: HashMap>) { + pub fn set_substitution_rect_map(&mut self, rect_map: [(char, Rect); TSC_SUBSTITUTION_MAP_SIZE]) { self.substitution_rect_map = rect_map; } diff --git a/src/shared_game_state.rs b/src/shared_game_state.rs index fdd834a..962ff9c 100644 --- a/src/shared_game_state.rs +++ b/src/shared_game_state.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::{cmp, ops::Div}; use bitvec::vec::BitVec; @@ -499,7 +498,7 @@ impl SharedGameState { let stage_select_script = TextScript::load_from(stage_select_tsc, &self.constants)?; self.textscript_vm.set_stage_select_script(stage_select_script); - let substitution_rect_map = HashMap::from([('=', self.constants.textscript.textbox_item_marker_rect)]); + let substitution_rect_map = [('=', self.constants.textscript.textbox_item_marker_rect)]; self.textscript_vm.set_substitution_rect_map(substitution_rect_map); if filesystem::exists_find(ctx, &self.constants.base_paths, "Credit.tsc") { @@ -848,7 +847,7 @@ impl SharedGameState { return self.get_active_locale().t(key); } - pub fn tt(&self, key: &str, args: HashMap) -> String { + pub fn tt(&self, key: &str, args: &[(&str, &str)]) -> String { return self.get_active_locale().tt(key, args); } }