mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-05-21 14:21:06 +00:00
use localized soundtrack names
This commit is contained in:
parent
7630a9b60e
commit
9c95b20f5c
|
@ -207,7 +207,7 @@ pub struct AnimatedFace {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExtraSoundtrack {
|
||||
pub name: String,
|
||||
pub id: String,
|
||||
pub path: String,
|
||||
pub available: bool,
|
||||
}
|
||||
|
@ -1613,10 +1613,10 @@ impl EngineConstants {
|
|||
font_path: "csfont.fnt".to_owned(),
|
||||
font_space_offset: 0.0,
|
||||
soundtracks: vec![
|
||||
ExtraSoundtrack { name: "Remastered".to_owned(), path: "/base/Ogg11/".to_owned(), available: false },
|
||||
ExtraSoundtrack { name: "New".to_owned(), path: "/base/Ogg/".to_owned(), available: false },
|
||||
ExtraSoundtrack { name: "Famitracks".to_owned(), path: "/base/ogg17/".to_owned(), available: false },
|
||||
ExtraSoundtrack { name: "Ridiculon".to_owned(), path: "/base/ogg_ridic/".to_owned(), available: false },
|
||||
ExtraSoundtrack { id: "remastered".to_owned(), path: "/base/Ogg11/".to_owned(), available: false },
|
||||
ExtraSoundtrack { id: "new".to_owned(), path: "/base/Ogg/".to_owned(), available: false },
|
||||
ExtraSoundtrack { id: "famitracks".to_owned(), path: "/base/ogg17/".to_owned(), available: false },
|
||||
ExtraSoundtrack { id: "ridiculon".to_owned(), path: "/base/ogg_ridic/".to_owned(), available: false },
|
||||
],
|
||||
music_table: vec![
|
||||
"xxxx".to_owned(),
|
||||
|
|
|
@ -95,7 +95,7 @@ fn default_true() -> bool {
|
|||
|
||||
#[inline(always)]
|
||||
fn current_version() -> u32 {
|
||||
24
|
||||
25
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -347,6 +347,18 @@ impl Settings {
|
|||
self.allow_strafe = true;
|
||||
}
|
||||
|
||||
if self.version == 24 {
|
||||
self.version = 25;
|
||||
self.soundtrack = match self.soundtrack.as_str() {
|
||||
"Organya" => "organya".to_owned(),
|
||||
"Remastered" => "remastered".to_owned(),
|
||||
"New" => "new".to_owned(),
|
||||
"Famitracks" => "famitracks".to_owned(),
|
||||
"Ridiculon" => "ridiculon".to_owned(),
|
||||
_ => self.soundtrack.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
if self.version != initial_version {
|
||||
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ use crate::game::profile::GameProfile;
|
|||
#[cfg(feature = "scripting-lua")]
|
||||
use crate::game::scripting::lua::LuaScriptingState;
|
||||
use crate::game::scripting::tsc::credit_script::{CreditScript, CreditScriptVM};
|
||||
use crate::game::scripting::tsc::text_script::{ScriptMode, TextScript, TextScriptEncoding, TextScriptExecutionState, TextScriptVM};
|
||||
use crate::game::scripting::tsc::text_script::{
|
||||
ScriptMode, TextScript, TextScriptEncoding, TextScriptExecutionState, TextScriptVM,
|
||||
};
|
||||
use crate::game::settings::Settings;
|
||||
use crate::game::stage::StageData;
|
||||
use crate::graphics::bmfont::BMFont;
|
||||
|
@ -408,7 +410,7 @@ impl SharedGameState {
|
|||
|
||||
for soundtrack in constants.soundtracks.iter_mut() {
|
||||
if filesystem::exists(ctx, &soundtrack.path) {
|
||||
log::info!("Enabling soundtrack {} from {}.", soundtrack.name, soundtrack.path);
|
||||
log::info!("Enabling soundtrack {} from {}.", soundtrack.id, soundtrack.path);
|
||||
soundtrack.available = true;
|
||||
}
|
||||
}
|
||||
|
@ -420,11 +422,11 @@ impl SharedGameState {
|
|||
|
||||
let locale = SharedGameState::get_locale(&constants, &settings.locale).unwrap_or_default();
|
||||
if (locale.code == "jp" || locale.code == "en") && constants.is_base() {
|
||||
constants.textscript.encoding = TextScriptEncoding::ShiftJIS
|
||||
constants.textscript.encoding = TextScriptEncoding::ShiftJIS
|
||||
} else {
|
||||
constants.textscript.encoding = TextScriptEncoding::UTF8
|
||||
constants.textscript.encoding = TextScriptEncoding::UTF8
|
||||
}
|
||||
|
||||
|
||||
let font = BMFont::load(&constants.base_paths, &locale.font.path, ctx, locale.font.scale).or_else(|e| {
|
||||
log::warn!("Failed to load font, using built-in: {}", e);
|
||||
BMFont::load(&vec!["/".to_owned()], "builtin/builtin_font.fnt", ctx, 1.0)
|
||||
|
@ -573,9 +575,9 @@ impl SharedGameState {
|
|||
if let Some(locale) = SharedGameState::get_locale(&self.constants, &self.settings.locale) {
|
||||
self.loc = locale;
|
||||
if (self.loc.code == "jp" || self.loc.code == "en") && self.constants.is_base() {
|
||||
self.constants.textscript.encoding = TextScriptEncoding::ShiftJIS
|
||||
self.constants.textscript.encoding = TextScriptEncoding::ShiftJIS
|
||||
} else {
|
||||
self.constants.textscript.encoding = TextScriptEncoding::UTF8
|
||||
self.constants.textscript.encoding = TextScriptEncoding::UTF8
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +649,12 @@ impl SharedGameState {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save_game(&mut self, game_scene: &mut GameScene, ctx: &mut Context, target_player: Option<TargetPlayer>) -> GameResult {
|
||||
pub fn save_game(
|
||||
&mut self,
|
||||
game_scene: &mut GameScene,
|
||||
ctx: &mut Context,
|
||||
target_player: Option<TargetPlayer>,
|
||||
) -> GameResult {
|
||||
if let Some(save_path) = self.get_save_filename(self.save_slot) {
|
||||
if let Ok(data) = filesystem::open_options(ctx, save_path, OpenOptions::new().write(true).create(true)) {
|
||||
let profile = GameProfile::dump(self, game_scene, target_player);
|
||||
|
@ -896,6 +903,18 @@ impl SharedGameState {
|
|||
out_locale
|
||||
}
|
||||
|
||||
pub fn get_localized_soundtrack_name(&self, id: &str) -> String {
|
||||
if id == "organya" {
|
||||
return self.loc.t("soundtrack.organya").to_owned();
|
||||
}
|
||||
|
||||
self.constants
|
||||
.soundtracks
|
||||
.iter()
|
||||
.find(|s| s.id == id)
|
||||
.map_or_else(|| id.to_owned(), |s| self.loc.t(format!("soundtrack.{}", s.id).as_str()).to_owned())
|
||||
}
|
||||
|
||||
pub fn tt(&self, key: &str, args: &[(&str, &str)]) -> String {
|
||||
return self.loc.tt(key, args);
|
||||
}
|
||||
|
|
|
@ -500,18 +500,21 @@ impl SettingsMenu {
|
|||
);
|
||||
self.sound.push_entry(
|
||||
SoundMenuEntry::Soundtrack,
|
||||
MenuEntry::Active(
|
||||
state.tt(
|
||||
"menus.options_menu.sound_menu.soundtrack",
|
||||
&[("soundtrack", state.settings.soundtrack.as_str())],
|
||||
),
|
||||
),
|
||||
MenuEntry::Active(state.loc.tt(
|
||||
"menus.options_menu.sound_menu.soundtrack",
|
||||
&[("soundtrack", state.get_localized_soundtrack_name(&state.settings.soundtrack).as_str())],
|
||||
)),
|
||||
);
|
||||
self.sound.push_entry(SoundMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
||||
|
||||
let mut soundtrack_entries =
|
||||
state.constants.soundtracks.iter().filter(|s| s.available).map(|s| s.name.to_owned()).collect_vec();
|
||||
soundtrack_entries.push("Organya".to_owned());
|
||||
let mut soundtrack_entries = state
|
||||
.constants
|
||||
.soundtracks
|
||||
.iter()
|
||||
.filter(|s| s.available)
|
||||
.map(|s| state.loc.t(format!("soundtrack.{}", s.id).as_str()).to_owned())
|
||||
.collect_vec();
|
||||
soundtrack_entries.push(state.loc.t("soundtrack.organya").to_owned());
|
||||
|
||||
if let Ok(dir) = filesystem::read_dir(ctx, "/Soundtracks/") {
|
||||
for entry in dir {
|
||||
|
@ -882,7 +885,7 @@ impl SettingsMenu {
|
|||
|
||||
for (id, entry) in &self.soundtrack.entries {
|
||||
if let MenuEntry::Active(soundtrack) = entry {
|
||||
if soundtrack == &state.settings.soundtrack {
|
||||
if soundtrack == &state.get_localized_soundtrack_name(&state.settings.soundtrack) {
|
||||
active_soundtrack = *id;
|
||||
let _ = state.settings.save(ctx);
|
||||
break;
|
||||
|
@ -937,12 +940,28 @@ impl SettingsMenu {
|
|||
CurrentMenu::SoundtrackMenu => match self.soundtrack.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(SoundtrackMenuEntry::Soundtrack(_), entry) => {
|
||||
if let MenuEntry::Active(name) = entry {
|
||||
state.settings.soundtrack = name.to_owned();
|
||||
state.settings.soundtrack = state
|
||||
.constants
|
||||
.soundtracks
|
||||
.iter()
|
||||
.find(|s| state.loc.t(format!("soundtrack.{}", s.id).as_str()) == name)
|
||||
.map_or_else(|| name.to_owned(), |s| s.id.clone());
|
||||
|
||||
if state.settings.soundtrack == "Organya" {
|
||||
state.settings.soundtrack = "organya".to_owned()
|
||||
}
|
||||
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
self.sound.set_entry(
|
||||
SoundMenuEntry::Soundtrack,
|
||||
MenuEntry::Active(format!("Soundtrack: {}", state.settings.soundtrack)),
|
||||
MenuEntry::Active(state.loc.tt(
|
||||
"menus.options_menu.sound_menu.soundtrack",
|
||||
&[(
|
||||
"soundtrack",
|
||||
state.get_localized_soundtrack_name(&state.settings.soundtrack).as_str(),
|
||||
)],
|
||||
)),
|
||||
);
|
||||
state.sound_manager.reload_songs(&state.constants, &state.settings, ctx)?;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use itertools::Itertools;
|
|||
use crate::common::Color;
|
||||
use crate::common::Rect;
|
||||
use crate::components::background::Background;
|
||||
use crate::engine_constants::ExtraSoundtrack;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::filesystem;
|
||||
|
@ -16,10 +17,43 @@ use crate::input::combined_menu_controller::CombinedMenuController;
|
|||
use crate::scene::title_scene::TitleScene;
|
||||
use crate::scene::Scene;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum JukeboxSoundtrackKind {
|
||||
Organya,
|
||||
Extra(ExtraSoundtrack),
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl JukeboxSoundtrackKind {
|
||||
pub fn eq_str(&self, other: &str) -> bool {
|
||||
match self {
|
||||
JukeboxSoundtrackKind::Organya => other == "organya",
|
||||
JukeboxSoundtrackKind::Extra(s) => other == s.id,
|
||||
JukeboxSoundtrackKind::Custom(s) => other == s,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_localized_string(&self, state: &mut SharedGameState) -> String {
|
||||
match self {
|
||||
JukeboxSoundtrackKind::Organya => state.loc.t("soundtrack.organya").to_owned(),
|
||||
JukeboxSoundtrackKind::Extra(s) => state.loc.t(format!("soundtrack.{}", s.id).as_str()).to_owned(),
|
||||
JukeboxSoundtrackKind::Custom(s) => s.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_id(&self) -> String {
|
||||
match self {
|
||||
JukeboxSoundtrackKind::Organya => "organya".to_owned(),
|
||||
JukeboxSoundtrackKind::Extra(s) => s.id.clone(),
|
||||
JukeboxSoundtrackKind::Custom(s) => s.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JukeboxScene {
|
||||
selected_song: u16,
|
||||
song_list: Vec<String>,
|
||||
soundtracks: Vec<String>,
|
||||
soundtracks: Vec<JukeboxSoundtrackKind>,
|
||||
selected_soundtrack: usize,
|
||||
controller: CombinedMenuController,
|
||||
background: Background,
|
||||
|
@ -79,17 +113,26 @@ impl Scene for JukeboxScene {
|
|||
.cloned()
|
||||
.collect();
|
||||
|
||||
let mut soundtrack_entries =
|
||||
state.constants.soundtracks.iter().filter(|s| s.available).map(|s| s.name.to_owned()).collect_vec();
|
||||
soundtrack_entries.push("Organya".to_owned());
|
||||
let mut soundtrack_entries = state
|
||||
.constants
|
||||
.soundtracks
|
||||
.iter()
|
||||
.filter(|s| s.available)
|
||||
.map(|s| JukeboxSoundtrackKind::Extra(s.clone()))
|
||||
.collect_vec();
|
||||
soundtrack_entries.push(JukeboxSoundtrackKind::Organya);
|
||||
|
||||
if let Ok(dir) = filesystem::read_dir(ctx, "/Soundtracks/") {
|
||||
for entry in dir {
|
||||
if filesystem::is_dir(ctx, &entry) {
|
||||
let filename = entry.file_name().unwrap().to_string_lossy().to_string();
|
||||
|
||||
if !soundtrack_entries.contains(&filename) {
|
||||
soundtrack_entries.push(filename);
|
||||
if soundtrack_entries
|
||||
.iter()
|
||||
.find(|s| matches!(s, JukeboxSoundtrackKind::Custom(s) if s == &filename))
|
||||
.is_none()
|
||||
{
|
||||
soundtrack_entries.push(JukeboxSoundtrackKind::Custom(filename.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +141,7 @@ impl Scene for JukeboxScene {
|
|||
self.soundtracks = soundtrack_entries.clone();
|
||||
|
||||
let selected_soundtrack_index =
|
||||
self.soundtracks.iter().position(|s| s == &state.settings.soundtrack).unwrap_or(0);
|
||||
self.soundtracks.iter().position(|s| s.eq_str(&state.settings.soundtrack)).unwrap_or(0);
|
||||
self.selected_soundtrack = selected_soundtrack_index;
|
||||
|
||||
self.previous_pause_on_focus_loss_setting = state.settings.pause_on_focus_loss;
|
||||
|
@ -150,13 +193,13 @@ impl Scene for JukeboxScene {
|
|||
|
||||
if self.controller.trigger_shift_left() {
|
||||
self.selected_soundtrack = self.selected_soundtrack.checked_sub(1).unwrap_or(self.soundtracks.len() - 1);
|
||||
state.settings.soundtrack = self.soundtracks[self.selected_soundtrack].to_string();
|
||||
state.settings.soundtrack = self.soundtracks[self.selected_soundtrack].to_id();
|
||||
state.sound_manager.reload_songs(&state.constants, &state.settings, ctx)?;
|
||||
}
|
||||
|
||||
if self.controller.trigger_shift_right() {
|
||||
self.selected_soundtrack = (self.selected_soundtrack + 1) % self.soundtracks.len();
|
||||
state.settings.soundtrack = self.soundtracks[self.selected_soundtrack].to_string();
|
||||
state.settings.soundtrack = self.soundtracks[self.selected_soundtrack].to_id();
|
||||
state.sound_manager.reload_songs(&state.constants, &state.settings, ctx)?;
|
||||
}
|
||||
|
||||
|
@ -284,9 +327,9 @@ impl Scene for JukeboxScene {
|
|||
|
||||
// Write Soundtrack name
|
||||
|
||||
let text = &state.settings.soundtrack;
|
||||
let text = self.soundtracks[self.selected_soundtrack].to_localized_string(state);
|
||||
state.font.builder().center(state.canvas_size.0).y(20.0).shadow(true).draw(
|
||||
text,
|
||||
text.as_str(),
|
||||
ctx,
|
||||
&state.constants,
|
||||
&mut state.texture_set,
|
||||
|
|
|
@ -11,8 +11,8 @@ use num_traits::clamp;
|
|||
|
||||
use crate::engine_constants::EngineConstants;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
use crate::framework::error::GameError::{AudioError, InvalidValue};
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
use crate::framework::filesystem;
|
||||
use crate::framework::filesystem::File;
|
||||
use crate::game::settings::Settings;
|
||||
|
@ -286,20 +286,19 @@ impl SoundManager {
|
|||
|
||||
paths.insert(0, "/Soundtracks/".to_owned() + &settings.soundtrack + "/");
|
||||
|
||||
if let Some(soundtrack) =
|
||||
constants.soundtracks.iter().find(|s| s.available && s.name == settings.soundtrack)
|
||||
if let Some(soundtrack) = constants.soundtracks.iter().find(|s| s.available && s.id == settings.soundtrack)
|
||||
{
|
||||
paths.insert(0, soundtrack.path.clone());
|
||||
}
|
||||
|
||||
let songs_paths = paths.iter().map(|prefix| {
|
||||
[
|
||||
#[cfg(feature = "ogg-playback")]
|
||||
#[cfg(feature = "ogg-playback")]
|
||||
(
|
||||
SongFormat::OggMultiPart,
|
||||
vec![format!("{}{}_intro.ogg", prefix, song_name), format!("{}{}_loop.ogg", prefix, song_name)],
|
||||
),
|
||||
#[cfg(feature = "ogg-playback")]
|
||||
#[cfg(feature = "ogg-playback")]
|
||||
(SongFormat::OggSinglePart, vec![format!("{}{}.ogg", prefix, song_name)]),
|
||||
(SongFormat::Organya, vec![format!("{}{}.org", prefix, song_name)]),
|
||||
]
|
||||
|
@ -307,7 +306,7 @@ impl SoundManager {
|
|||
|
||||
for songs in songs_paths {
|
||||
for (format, paths) in
|
||||
songs.iter().filter(|(_, paths)| paths.iter().all(|path| filesystem::exists(ctx, path)))
|
||||
songs.iter().filter(|(_, paths)| paths.iter().all(|path| filesystem::exists(ctx, path)))
|
||||
{
|
||||
match format {
|
||||
SongFormat::Organya => {
|
||||
|
@ -385,7 +384,7 @@ impl SoundManager {
|
|||
Box::new(song_intro),
|
||||
Box::new(song_loop),
|
||||
))
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -597,8 +596,8 @@ fn run<T>(
|
|||
device: cpal::Device,
|
||||
config: cpal::StreamConfig,
|
||||
) -> GameResult<cpal::Stream>
|
||||
where
|
||||
T: cpal::SizedSample + cpal::FromSample<u16>,
|
||||
where
|
||||
T: cpal::SizedSample + cpal::FromSample<u16>,
|
||||
{
|
||||
let sample_rate = config.sample_rate.0 as f32;
|
||||
let channels = config.channels as usize;
|
||||
|
@ -732,7 +731,7 @@ fn run<T>(
|
|||
assert!(new_speed > 0.0);
|
||||
speed = new_speed;
|
||||
#[cfg(feature = "ogg-playback")]
|
||||
ogg_engine.set_sample_rate((sample_rate / new_speed) as usize);
|
||||
ogg_engine.set_sample_rate((sample_rate / new_speed) as usize);
|
||||
org_engine.set_sample_rate((sample_rate / new_speed) as usize);
|
||||
}
|
||||
Ok(PlaybackMessage::SetSongVolume(new_volume)) => {
|
||||
|
@ -895,7 +894,7 @@ fn run<T>(
|
|||
}
|
||||
},
|
||||
err_fn,
|
||||
None
|
||||
None,
|
||||
);
|
||||
|
||||
if stream_result.is_err() {
|
||||
|
|
Loading…
Reference in a new issue