mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2024-10-31 19:44:20 +00:00
settings menu rework
This commit is contained in:
parent
c815c91541
commit
a601d6c044
|
@ -1,16 +1,19 @@
|
|||
use std::cell::Cell;
|
||||
|
||||
use crate::common::Rect;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::input::combined_menu_controller::CombinedMenuController;
|
||||
use crate::player::skin::basic::BasicPlayerSkin;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use std::cell::Cell;
|
||||
|
||||
pub mod settings_menu;
|
||||
|
||||
pub struct MenuSaveInfo {}
|
||||
|
||||
pub enum MenuEntry {
|
||||
Hidden,
|
||||
Active(String),
|
||||
DisabledWhite(String),
|
||||
Disabled(String),
|
||||
Toggle(String, bool),
|
||||
Options(String, usize, Vec<String>),
|
||||
|
@ -23,6 +26,7 @@ impl MenuEntry {
|
|||
match self {
|
||||
MenuEntry::Hidden => 0.0,
|
||||
MenuEntry::Active(_) => 14.0,
|
||||
MenuEntry::DisabledWhite(_) => 14.0,
|
||||
MenuEntry::Disabled(_) => 14.0,
|
||||
MenuEntry::Toggle(_, _) => 14.0,
|
||||
MenuEntry::Options(_, _, _) => 14.0,
|
||||
|
@ -30,6 +34,19 @@ impl MenuEntry {
|
|||
MenuEntry::NewSave => 30.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn selectable(&self) -> bool {
|
||||
match self {
|
||||
MenuEntry::Hidden => false,
|
||||
MenuEntry::Active(_) => true,
|
||||
MenuEntry::DisabledWhite(_) => false,
|
||||
MenuEntry::Disabled(_) => false,
|
||||
MenuEntry::Toggle(_, _) => true,
|
||||
MenuEntry::Options(_, _, _) => true,
|
||||
MenuEntry::SaveData(_) => true,
|
||||
MenuEntry::NewSave => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MenuSelectionResult<'a> {
|
||||
|
@ -210,7 +227,7 @@ impl Menu {
|
|||
y = self.y as f32 + 6.0;
|
||||
for entry in self.entries.iter() {
|
||||
match entry {
|
||||
MenuEntry::Active(name) => {
|
||||
MenuEntry::Active(name) | MenuEntry::DisabledWhite(name) => {
|
||||
state.font.draw_text(
|
||||
name.chars(),
|
||||
self.x as f32 + 20.0,
|
||||
|
@ -253,7 +270,28 @@ impl Menu {
|
|||
ctx,
|
||||
)?;
|
||||
}
|
||||
MenuEntry::Hidden => {}
|
||||
MenuEntry::Options(name, index, value) => {
|
||||
let value_text = if let Some(text) = value.get(*index) { text.as_str() } else { "???" };
|
||||
let val_text_len = state.font.text_width(value_text.chars(), &state.constants);
|
||||
|
||||
state.font.draw_text(
|
||||
name.chars(),
|
||||
self.x as f32 + 20.0,
|
||||
y,
|
||||
&state.constants,
|
||||
&mut state.texture_set,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
state.font.draw_text(
|
||||
value_text.chars(),
|
||||
self.x as f32 + self.width as f32 - val_text_len,
|
||||
y,
|
||||
&state.constants,
|
||||
&mut state.texture_set,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -289,14 +327,8 @@ impl Menu {
|
|||
}
|
||||
|
||||
if let Some(entry) = self.entries.get(self.selected) {
|
||||
match entry {
|
||||
MenuEntry::Active(_) => {
|
||||
break;
|
||||
}
|
||||
MenuEntry::Toggle(_, _) => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
if entry.selectable() {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
@ -314,7 +346,7 @@ impl Menu {
|
|||
y += entry.height() as f32;
|
||||
|
||||
match entry {
|
||||
MenuEntry::Active(_) | MenuEntry::Toggle(_, _)
|
||||
MenuEntry::Active(_) | MenuEntry::Toggle(_, _) | MenuEntry::Options(_, _, _)
|
||||
if (self.selected == idx && controller.trigger_ok())
|
||||
|| state.touch_controls.consume_click_in(entry_bounds) =>
|
||||
{
|
||||
|
|
233
src/menu/settings_menu.rs
Normal file
233
src/menu/settings_menu.rs
Normal file
|
@ -0,0 +1,233 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::input::combined_menu_controller::CombinedMenuController;
|
||||
use crate::menu::{Menu, MenuSelectionResult};
|
||||
use crate::menu::MenuEntry;
|
||||
use crate::shared_game_state::{SharedGameState, TimingMode};
|
||||
use crate::sound::InterpolationMode;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
#[allow(unused)]
|
||||
enum CurrentMenu {
|
||||
MainMenu,
|
||||
GraphicsMenu,
|
||||
SoundMenu,
|
||||
}
|
||||
|
||||
pub struct SettingsMenu {
|
||||
current: CurrentMenu,
|
||||
main: Menu,
|
||||
graphics: Menu,
|
||||
sound: Menu,
|
||||
}
|
||||
|
||||
static DISCORD_LINK: &str = "https://discord.gg/fbRsNNB";
|
||||
|
||||
impl SettingsMenu {
|
||||
pub fn new() -> SettingsMenu {
|
||||
let main = Menu::new(0, 0, 200, 0);
|
||||
let graphics = Menu::new(0, 0, 180, 0);
|
||||
let sound = Menu::new(0, 0, 260, 0);
|
||||
|
||||
SettingsMenu { current: CurrentMenu::MainMenu, main, graphics, sound }
|
||||
}
|
||||
|
||||
pub fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
self.graphics.push_entry(MenuEntry::Toggle("Lighting effects:".to_string(), state.settings.shader_effects));
|
||||
self.graphics
|
||||
.push_entry(MenuEntry::Toggle("Motion interpolation:".to_string(), state.settings.motion_interpolation));
|
||||
self.graphics.push_entry(MenuEntry::Toggle("Subpixel scrolling:".to_string(), state.settings.subpixel_coords));
|
||||
|
||||
if state.constants.supports_og_textures {
|
||||
self.graphics
|
||||
.push_entry(MenuEntry::Toggle("Original textures".to_string(), state.settings.original_textures));
|
||||
} else {
|
||||
self.graphics.push_entry(MenuEntry::Hidden);
|
||||
}
|
||||
|
||||
if state.constants.is_cs_plus {
|
||||
self.graphics
|
||||
.push_entry(MenuEntry::Toggle("Seasonal textures".to_string(), state.settings.seasonal_textures));
|
||||
} else {
|
||||
self.graphics.push_entry(MenuEntry::Hidden);
|
||||
}
|
||||
|
||||
self.graphics
|
||||
.push_entry(MenuEntry::Disabled(format!("Renderer: {}", ctx.renderer.as_ref().unwrap().renderer_name())));
|
||||
|
||||
self.graphics.push_entry(MenuEntry::Active("< Back".to_owned()));
|
||||
|
||||
self.main.push_entry(MenuEntry::Active("Graphics...".to_owned()));
|
||||
self.main.push_entry(MenuEntry::Active("Sound...".to_owned()));
|
||||
|
||||
self.main.push_entry(MenuEntry::Options(
|
||||
"Game timing:".to_owned(),
|
||||
if state.timing_mode == TimingMode::_50Hz { 0 } else { 1 },
|
||||
vec!["50tps (freeware)".to_owned(), "60tps (CS+)".to_owned()],
|
||||
));
|
||||
|
||||
self.main.push_entry(MenuEntry::Active(DISCORD_LINK.to_owned()));
|
||||
|
||||
self.main.push_entry(MenuEntry::Active("< Back".to_owned()));
|
||||
|
||||
self.sound.push_entry(MenuEntry::DisabledWhite("BGM Interpolation:".to_owned()));
|
||||
self.sound.push_entry(MenuEntry::Options(
|
||||
"".to_owned(),
|
||||
state.settings.organya_interpolation as usize,
|
||||
vec![
|
||||
"Nearest (fastest, lowest quality)".to_owned(),
|
||||
"Linear (fast, similar to freeware on Vista+)".to_owned(),
|
||||
"Cosine".to_owned(),
|
||||
"Cubic".to_owned(),
|
||||
"Polyphase (slowest, similar to freeware on XP)".to_owned()
|
||||
],
|
||||
));
|
||||
self.sound.push_entry(MenuEntry::Disabled(format!("Soundtrack: {}", state.settings.soundtrack)));
|
||||
self.sound.push_entry(MenuEntry::Active("< Back".to_owned()));
|
||||
|
||||
self.update_sizes(state);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_sizes(&mut self, state: &SharedGameState) {
|
||||
self.main.update_height();
|
||||
self.main.x = ((state.canvas_size.0 - self.main.width as f32) / 2.0).floor() as isize;
|
||||
self.main.y = 30 + ((state.canvas_size.1 - self.main.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.graphics.update_height();
|
||||
self.graphics.x = ((state.canvas_size.0 - self.graphics.width as f32) / 2.0).floor() as isize;
|
||||
self.graphics.y = 30 + ((state.canvas_size.1 - self.graphics.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.sound.update_height();
|
||||
self.sound.x = ((state.canvas_size.0 - self.sound.width as f32) / 2.0).floor() as isize;
|
||||
self.sound.y = 30 + ((state.canvas_size.1 - self.sound.height as f32) / 2.0).floor() as isize;
|
||||
}
|
||||
|
||||
pub fn tick(
|
||||
&mut self,
|
||||
exit_action: &mut dyn FnMut(),
|
||||
controller: &mut CombinedMenuController,
|
||||
state: &mut SharedGameState,
|
||||
ctx: &mut Context,
|
||||
) -> GameResult {
|
||||
self.update_sizes(state);
|
||||
|
||||
match self.current {
|
||||
CurrentMenu::MainMenu => match self.main.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) => {
|
||||
self.current = CurrentMenu::GraphicsMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(1, _) => {
|
||||
self.current = CurrentMenu::SoundMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
match state.timing_mode {
|
||||
TimingMode::_50Hz => {
|
||||
state.timing_mode = TimingMode::_60Hz;
|
||||
*value = 1;
|
||||
}
|
||||
TimingMode::_60Hz => {
|
||||
state.timing_mode = TimingMode::_50Hz;
|
||||
*value = 0;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) => {
|
||||
if let Err(e) = webbrowser::open(DISCORD_LINK) {
|
||||
log::warn!("Error opening web browser: {}", e);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::GraphicsMenu => match self.graphics.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(0, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.shader_effects = !state.settings.shader_effects;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.shader_effects;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(1, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.motion_interpolation = !state.settings.motion_interpolation;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.motion_interpolation;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.subpixel_coords = !state.settings.subpixel_coords;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.subpixel_coords;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.original_textures = !state.settings.original_textures;
|
||||
state.reload_textures();
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.original_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.seasonal_textures = !state.settings.seasonal_textures;
|
||||
state.reload_textures();
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.seasonal_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(6, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
CurrentMenu::SoundMenu => match self.sound.tick(controller, state) {
|
||||
MenuSelectionResult::Selected(1, toggle) => {
|
||||
if let MenuEntry::Options(_, value, _) = toggle {
|
||||
let (new_mode, new_value) = match *value {
|
||||
0 => (InterpolationMode::Linear, 1),
|
||||
1 => (InterpolationMode::Cosine, 2),
|
||||
2 => (InterpolationMode::Cubic, 3),
|
||||
3 => (InterpolationMode::Polyphase, 4),
|
||||
_ => (InterpolationMode::Nearest, 0),
|
||||
};
|
||||
|
||||
*value = new_value;
|
||||
state.settings.organya_interpolation = new_mode;
|
||||
state.sound_manager.set_org_interpolation(new_mode);
|
||||
|
||||
let _ = state.settings.save(ctx);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, _) | MenuSelectionResult::Canceled => {
|
||||
self.current = CurrentMenu::MainMenu
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
match self.current {
|
||||
CurrentMenu::MainMenu => self.main.draw(state, ctx)?,
|
||||
CurrentMenu::GraphicsMenu => self.graphics.draw(state, ctx)?,
|
||||
CurrentMenu::SoundMenu => self.sound.draw(state, ctx)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -4,9 +4,10 @@ use crate::framework::error::GameResult;
|
|||
use crate::framework::graphics;
|
||||
use crate::input::combined_menu_controller::CombinedMenuController;
|
||||
use crate::input::touch_controls::TouchControlType;
|
||||
use crate::menu::settings_menu::SettingsMenu;
|
||||
use crate::menu::{Menu, MenuEntry, MenuSelectionResult};
|
||||
use crate::scene::Scene;
|
||||
use crate::shared_game_state::{SharedGameState, TimingMode};
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
|
@ -25,7 +26,7 @@ pub struct TitleScene {
|
|||
controller: CombinedMenuController,
|
||||
current_menu: CurrentMenu,
|
||||
main_menu: Menu,
|
||||
option_menu: Menu,
|
||||
option_menu: SettingsMenu,
|
||||
save_select_menu: Menu,
|
||||
}
|
||||
|
||||
|
@ -36,7 +37,7 @@ impl TitleScene {
|
|||
controller: CombinedMenuController::new(),
|
||||
current_menu: CurrentMenu::MainMenu,
|
||||
main_menu: Menu::new(0, 0, 100, 0),
|
||||
option_menu: Menu::new(0, 0, 180, 0),
|
||||
option_menu: SettingsMenu::new(),
|
||||
save_select_menu: Menu::new(0, 0, 200, 0),
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +86,6 @@ impl TitleScene {
|
|||
|
||||
// asset copyright for freeware version
|
||||
static COPYRIGHT_PIXEL: &str = "2004.12 Studio Pixel";
|
||||
static DISCORD_LINK: &str = "https://discord.gg/fbRsNNB";
|
||||
|
||||
impl Scene for TitleScene {
|
||||
fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
|
@ -103,27 +103,7 @@ impl Scene for TitleScene {
|
|||
}
|
||||
self.main_menu.push_entry(MenuEntry::Active("Quit".to_string()));
|
||||
|
||||
self.option_menu.push_entry(MenuEntry::Toggle(
|
||||
"Original timing (50TPS)".to_string(),
|
||||
state.timing_mode == TimingMode::_50Hz,
|
||||
));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Lighting effects".to_string(), state.settings.shader_effects));
|
||||
if state.constants.supports_og_textures {
|
||||
self.option_menu
|
||||
.push_entry(MenuEntry::Toggle("Original textures".to_string(), state.settings.original_textures));
|
||||
} else {
|
||||
self.option_menu.push_entry(MenuEntry::Disabled("Original textures".to_string()));
|
||||
}
|
||||
|
||||
if state.constants.is_cs_plus {
|
||||
self.option_menu
|
||||
.push_entry(MenuEntry::Toggle("Seasonal textures".to_string(), state.settings.seasonal_textures));
|
||||
} else {
|
||||
self.option_menu.push_entry(MenuEntry::Disabled("Seasonal textures".to_string()));
|
||||
}
|
||||
self.option_menu.push_entry(MenuEntry::Active(DISCORD_LINK.to_owned()));
|
||||
self.option_menu.push_entry(MenuEntry::Disabled(["Renderer: ", &ctx.renderer.as_ref().unwrap().renderer_name()].join("")));
|
||||
self.option_menu.push_entry(MenuEntry::Active("Back".to_string()));
|
||||
self.option_menu.init(state, ctx)?;
|
||||
|
||||
self.save_select_menu.push_entry(MenuEntry::NewSave);
|
||||
self.save_select_menu.push_entry(MenuEntry::NewSave);
|
||||
|
@ -146,10 +126,6 @@ impl Scene for TitleScene {
|
|||
self.main_menu.x = ((state.canvas_size.0 - self.main_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.main_menu.y = ((state.canvas_size.1 + 70.0 - self.main_menu.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.option_menu.update_height();
|
||||
self.option_menu.x = ((state.canvas_size.0 - self.option_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.option_menu.y = ((state.canvas_size.1 + 70.0 - self.option_menu.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
match self.current_menu {
|
||||
CurrentMenu::MainMenu => match self.main_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(0, _) => {
|
||||
|
@ -171,55 +147,17 @@ impl Scene for TitleScene {
|
|||
}
|
||||
_ => {}
|
||||
},
|
||||
CurrentMenu::OptionMenu => match self.option_menu.tick(&mut self.controller, state) {
|
||||
MenuSelectionResult::Selected(0, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
match state.timing_mode {
|
||||
TimingMode::_50Hz => state.timing_mode = TimingMode::_60Hz,
|
||||
TimingMode::_60Hz => state.timing_mode = TimingMode::_50Hz,
|
||||
_ => {}
|
||||
}
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.timing_mode == TimingMode::_50Hz;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(1, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.shader_effects = !state.settings.shader_effects;
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.shader_effects;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(2, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.original_textures = !state.settings.original_textures;
|
||||
state.reload_textures();
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.original_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(3, toggle) => {
|
||||
if let MenuEntry::Toggle(_, value) = toggle {
|
||||
state.settings.seasonal_textures = !state.settings.seasonal_textures;
|
||||
state.reload_textures();
|
||||
let _ = state.settings.save(ctx);
|
||||
|
||||
*value = state.settings.seasonal_textures;
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(4, _) => {
|
||||
if let Err(e) = webbrowser::open(DISCORD_LINK) {
|
||||
log::warn!("Error opening web browser: {}", e);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(6, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
CurrentMenu::OptionMenu => {
|
||||
let cm = &mut self.current_menu;
|
||||
self.option_menu.tick(
|
||||
&mut || {
|
||||
*cm = CurrentMenu::MainMenu;
|
||||
},
|
||||
&mut self.controller,
|
||||
state,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
CurrentMenu::StartGame => {
|
||||
if self.tick == 10 {
|
||||
state.reset_skip_flags();
|
||||
|
@ -262,12 +200,8 @@ impl Scene for TitleScene {
|
|||
self.draw_text_centered(COPYRIGHT_PIXEL, state.canvas_size.1 - 30.0, state, ctx)?;
|
||||
|
||||
match self.current_menu {
|
||||
CurrentMenu::MainMenu => {
|
||||
self.main_menu.draw(state, ctx)?;
|
||||
}
|
||||
CurrentMenu::OptionMenu => {
|
||||
self.option_menu.draw(state, ctx)?;
|
||||
}
|
||||
CurrentMenu::MainMenu => self.main_menu.draw(state, ctx)?,
|
||||
CurrentMenu::OptionMenu => self.option_menu.draw(state, ctx)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::filesystem::{user_create, user_open};
|
||||
|
@ -8,9 +6,12 @@ use crate::input::keyboard_player_controller::KeyboardController;
|
|||
use crate::input::player_controller::PlayerController;
|
||||
use crate::input::touch_player_controller::TouchPlayerController;
|
||||
use crate::player::TargetPlayer;
|
||||
use crate::sound::InterpolationMode;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Settings {
|
||||
#[serde(default = "current_version")]
|
||||
pub version: u32,
|
||||
pub seasonal_textures: bool,
|
||||
pub original_textures: bool,
|
||||
pub shader_effects: bool,
|
||||
|
@ -18,6 +19,8 @@ pub struct Settings {
|
|||
pub motion_interpolation: bool,
|
||||
pub touch_controls: bool,
|
||||
pub soundtrack: String,
|
||||
#[serde(default = "default_interpolation")]
|
||||
pub organya_interpolation: InterpolationMode,
|
||||
#[serde(default = "p1_default_keymap")]
|
||||
pub player1_key_map: PlayerKeyMap,
|
||||
#[serde(default = "p2_default_keymap")]
|
||||
|
@ -32,6 +35,13 @@ pub struct Settings {
|
|||
pub debug_outlines: bool,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn current_version() -> u32 { 2 }
|
||||
|
||||
#[inline(always)]
|
||||
fn default_interpolation() -> InterpolationMode { InterpolationMode::Linear }
|
||||
|
||||
#[inline(always)]
|
||||
fn default_speed() -> f64 {
|
||||
1.0
|
||||
}
|
||||
|
@ -70,6 +80,7 @@ impl Settings {
|
|||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Settings {
|
||||
version: 2,
|
||||
seasonal_textures: true,
|
||||
original_textures: false,
|
||||
shader_effects: true,
|
||||
|
@ -77,6 +88,7 @@ impl Default for Settings {
|
|||
motion_interpolation: true,
|
||||
touch_controls: cfg!(target_os = "android"),
|
||||
soundtrack: "".to_string(),
|
||||
organya_interpolation: InterpolationMode::Linear,
|
||||
player1_key_map: p1_default_keymap(),
|
||||
player2_key_map: p2_default_keymap(),
|
||||
speed: 1.0,
|
||||
|
@ -87,7 +99,7 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct PlayerKeyMap {
|
||||
pub left: ScanCode,
|
||||
pub up: ScanCode,
|
||||
|
@ -102,6 +114,7 @@ pub struct PlayerKeyMap {
|
|||
pub map: ScanCode,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn p1_default_keymap() -> PlayerKeyMap {
|
||||
PlayerKeyMap {
|
||||
left: ScanCode::Left,
|
||||
|
@ -118,6 +131,7 @@ fn p1_default_keymap() -> PlayerKeyMap {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn p2_default_keymap() -> PlayerKeyMap {
|
||||
PlayerKeyMap {
|
||||
left: ScanCode::Comma,
|
||||
|
|
|
@ -96,6 +96,10 @@ impl SoundManager {
|
|||
let _ = self.tx.send(PlaybackMessage::StopSample(id));
|
||||
}
|
||||
|
||||
pub fn set_org_interpolation(&self, interpolation: InterpolationMode) {
|
||||
let _ = self.tx.send(PlaybackMessage::SetOrgInterpolation(interpolation));
|
||||
}
|
||||
|
||||
pub fn play_song(
|
||||
&mut self,
|
||||
song_id: usize,
|
||||
|
@ -113,6 +117,7 @@ impl SoundManager {
|
|||
self.prev_song_id = self.current_song_id;
|
||||
self.current_song_id = 0;
|
||||
|
||||
self.tx.send(PlaybackMessage::SetOrgInterpolation(settings.organya_interpolation))?;
|
||||
self.tx.send(PlaybackMessage::SaveState)?;
|
||||
self.tx.send(PlaybackMessage::Stop)?;
|
||||
} else if let Some(song_name) = constants.music_table.get(song_id) {
|
||||
|
@ -152,6 +157,7 @@ impl SoundManager {
|
|||
|
||||
self.prev_song_id = self.current_song_id;
|
||||
self.current_song_id = song_id;
|
||||
self.tx.send(PlaybackMessage::SetOrgInterpolation(settings.organya_interpolation))?;
|
||||
self.tx.send(PlaybackMessage::SaveState)?;
|
||||
self.tx.send(PlaybackMessage::PlayOrganyaSong(Box::new(org)))?;
|
||||
|
||||
|
@ -339,6 +345,7 @@ enum PlaybackMessage {
|
|||
SaveState,
|
||||
RestoreState,
|
||||
SetSampleParams(u8, PixToneParameters),
|
||||
SetOrgInterpolation(InterpolationMode),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
|
@ -520,6 +527,9 @@ where
|
|||
Ok(PlaybackMessage::SetSampleParams(id, params)) => {
|
||||
pixtone.set_sample_parameters(id, params);
|
||||
}
|
||||
Ok(PlaybackMessage::SetOrgInterpolation(interpolation)) => {
|
||||
org_engine.interpolation = interpolation;
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
|
@ -626,11 +636,11 @@ where
|
|||
|
||||
if state {
|
||||
if let Err(e) = stream.pause() {
|
||||
log::error!("Failed to pause the stream: {}", e);
|
||||
log::error!("Failed to pause the stream: {:?}", e);
|
||||
}
|
||||
} else {
|
||||
if let Err(e) = stream.play() {
|
||||
log::error!("Failed to unpause the stream: {}", e);
|
||||
log::error!("Failed to unpause the stream: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue