1df8402900
* initial commit * wip * WIP * WIP * clang format * Choose Seed navigation mostly done * seed input navigation done * seed input done * cleanup and clang format * Implement base 10 to 36 conversions * Enable seeded runs * clang format * show default deck sprite, name and description * Rename Deck enum to DeckType * Implement arbitrary 9-patch expand system * Make 9-patch example smaller in the docs * Improve NinePatchRect docs * fix Deck back side sprite palette * clang format * Add last deck description * clang format * Fix 'Z' in seed input keyboard * Fix rebase issue * fix deck sprite not updating * Documents static funcs in run_setup.c * more documentation * clang format * Move Play button to the left in its row * Tests WIP * removing tests for random.h * use the new StateMachine struct * First wave of fixes * Fix the 9-patch again * Changed the base 36 logic so it's in big endian * properly set end of base 36 string to '\0' * typos * fix cursor position after rolling a seed + fix random seed generation * Make keyboard more intuitive to use * static const var * Address more comment from @ricfehr3 * clang format * clang format * clang format * clang format * clang format * clang format * clang format * fix deck palette * create the `DEF_SEED_KEYBOARD_BUTTON_OBJECT` macro * Replace `expand_3x3` by a call to `expand_9-patch` * clang format * clang format * clang format * fix rebase iussue in state_machine.h --------- Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com>
644 lines
21 KiB
C
644 lines
21 KiB
C
#include "game/options_menu.h"
|
|
|
|
#include "affine_background.h"
|
|
#include "audio_utils.h"
|
|
#include "background_options_menu_gfx.h"
|
|
#include "button.h"
|
|
#include "card.h"
|
|
#include "game.h"
|
|
#include "game/common_ui.h"
|
|
#include "game_variables.h"
|
|
#include "graphic_utils.h"
|
|
#include "save.h"
|
|
#include "selection_grid.h"
|
|
#include "soundbank.h"
|
|
#include "util.h"
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <tonc.h>
|
|
#include <tonc_math.h>
|
|
#include <tonc_memdef.h>
|
|
|
|
enum OptionButtonRows
|
|
{
|
|
GAME_SPEED_ROW_IDX,
|
|
HIGH_CONTRAST_ROW_IDX,
|
|
MUSIC_VOLUME_ROW_IDX,
|
|
SOUND_VOLUME_ROW_IDX,
|
|
SAVE_BACK_ROW_IDX,
|
|
NB_OPTIONS_ROWS
|
|
};
|
|
enum OptionSpeedButtons
|
|
{
|
|
GAME_SPEED_DOWN_BTN_IDX,
|
|
GAME_SPEED_UP_BTN_IDX,
|
|
NB_GAME_SPEED_BUTTONS
|
|
};
|
|
|
|
// Color palette indices
|
|
#define MENU_BUTTON_MAIN_COLOR_PAL_IDX 1
|
|
#define SAVE_BUTTON_MAIN_COLOR_PAL_IDX 3
|
|
#define BACK_BUTTON_MAIN_COLOR_PAL_IDX 4
|
|
#define SPEED_DOWN_BUTTON_OUTLINE_COLOR_PAL_IDX 16
|
|
#define SPEED_BUTTON_OUTLINE_COLOR_PAL_IDX 17
|
|
#define SPEED_UP_BUTTON_OUTLINE_COLOR_PAL_IDX 18
|
|
#define CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX 19
|
|
#define READABLE_BUTTON_OUTLINE_COLOR_PAL_IDX 20
|
|
#define MUSIC_BUTTON_OUTLINE_COLOR_PAL_IDX 21
|
|
#define SOUND_BUTTON_OUTLINE_COLOR_PAL_IDX 22
|
|
#define SAVE_BUTTON_OUTLINE_COLOR_PAL_IDX 23
|
|
#define BACK_BUTTON_OUTLINE_COLOR_PAL_IDX 24
|
|
|
|
// Define selection grid for the menu buttons
|
|
|
|
static void game_speed_down_on_pressed(void);
|
|
static void game_speed_up_on_pressed(void);
|
|
static void high_contrast_on_pressed(void);
|
|
static void more_readable_on_pressed(void);
|
|
static void save_on_pressed(void);
|
|
static void back_on_pressed(void);
|
|
static int options_menu_return_upper_rows_size(void);
|
|
static int options_menu_return_card_sprites_row_size(void);
|
|
static int options_menu_return_bottom_row_size(void);
|
|
static void options_menu_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection);
|
|
static bool game_speed_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
);
|
|
static bool music_volume_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
);
|
|
static bool sound_volume_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
);
|
|
static bool regular_button_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
);
|
|
|
|
// clang-format off
|
|
static SelectionGridRow options_menu_selection_rows[] = {
|
|
{
|
|
GAME_SPEED_ROW_IDX,
|
|
options_menu_return_upper_rows_size,
|
|
game_speed_row_on_selection_changed,
|
|
NULL,
|
|
{.wrap = true} // The wrapping is used to allow button activation with Left/Right arrows by
|
|
// putting logic into the `game_speed_row_on_selection_changed` function
|
|
},
|
|
{
|
|
HIGH_CONTRAST_ROW_IDX,
|
|
options_menu_return_card_sprites_row_size,
|
|
regular_button_row_on_selection_changed,
|
|
options_menu_row_on_key_transit,
|
|
{.wrap = false}
|
|
},
|
|
{
|
|
MUSIC_VOLUME_ROW_IDX,
|
|
options_menu_return_upper_rows_size,
|
|
music_volume_row_on_selection_changed,
|
|
NULL,
|
|
{.wrap = true} // Same trick as Game Speed button
|
|
},
|
|
{
|
|
SOUND_VOLUME_ROW_IDX,
|
|
options_menu_return_upper_rows_size,
|
|
sound_volume_row_on_selection_changed,
|
|
NULL,
|
|
{.wrap = true} // Same trick as Game Speed button
|
|
},
|
|
{
|
|
SAVE_BACK_ROW_IDX,
|
|
options_menu_return_bottom_row_size,
|
|
regular_button_row_on_selection_changed,
|
|
options_menu_row_on_key_transit,
|
|
{.wrap = false}
|
|
}
|
|
};
|
|
|
|
static Button options_menu_buttons[NB_OPTIONS_ROWS][2] = {
|
|
{{SPEED_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}},
|
|
{
|
|
{CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, high_contrast_on_pressed, NULL},
|
|
{READABLE_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, more_readable_on_pressed, NULL}
|
|
},
|
|
{{MUSIC_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}},
|
|
{{SOUND_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}},
|
|
{
|
|
{SAVE_BUTTON_OUTLINE_COLOR_PAL_IDX, SAVE_BUTTON_MAIN_COLOR_PAL_IDX, save_on_pressed, NULL},
|
|
{BACK_BUTTON_OUTLINE_COLOR_PAL_IDX, BACK_BUTTON_MAIN_COLOR_PAL_IDX, back_on_pressed, NULL},
|
|
}
|
|
};
|
|
|
|
static Button game_speed_buttons[] = {
|
|
{SPEED_DOWN_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, game_speed_down_on_pressed, NULL},
|
|
{SPEED_UP_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, game_speed_up_on_pressed, NULL},
|
|
};
|
|
// clang-format on
|
|
|
|
const Selection OPTIONS_MENU_INIT_SEL = {0, 0};
|
|
|
|
static SelectionGrid options_menu_selection_grid = {
|
|
options_menu_selection_rows,
|
|
NB_OPTIONS_ROWS,
|
|
OPTIONS_MENU_INIT_SEL
|
|
};
|
|
|
|
// Positions/Rects used to construct and update the menu
|
|
// clang-format off
|
|
|
|
// Values in tiles
|
|
static const Rect OPTIONS_SPEED_DOWN_ACTIVE_BTN_SRC_RECT = { 0, 20, 0, 21};
|
|
static const Rect OPTIONS_SPEED_DOWN_DISABLED_BTN_SRC_RECT = { 6, 22, 6, 23};
|
|
static const BG_POINT OPTIONS_SPEED_DOWN_BTN_DEST_POS = {11, 3};
|
|
static const Rect OPTIONS_SPEED_UP_ACTIVE_BTN_SRC_RECT = { 7, 20, 7, 21};
|
|
static const Rect OPTIONS_SPEED_UP_DISABLED_BTN_SRC_RECT = { 7, 22, 7, 23};
|
|
static const BG_POINT OPTIONS_SPEED_UP_BTN_DEST_POS = {18, 3};
|
|
static const Rect OPTIONS_SPEED_VALUES[GAME_SPEED_MAX] = { { 3, 20, 4, 21},
|
|
{ 0, 22, 1, 23},
|
|
{ 2, 22, 3, 23},
|
|
{ 4, 22, 5, 23} };
|
|
static const BG_POINT OPTIONS_SPEED_VALUE_DEST_POS = {14, 3};
|
|
|
|
static const Rect OPTIONS_CONTRAST_CHECK_NO_SRC_RECT = { 0, 24, 1, 25};
|
|
static const Rect OPTIONS_CONTRAST_CHECK_YES_SRC_RECT = { 2, 24, 3, 25};
|
|
static const BG_POINT OPTIONS_CONTRAST_CHECK_DEST_POS = {14, 7};
|
|
static const Rect OPTIONS_READABLE_CHECK_NO_SRC_RECT = { 4, 24, 5, 25};
|
|
static const Rect OPTIONS_READABLE_CHECK_YES_SRC_RECT = { 6, 24, 7, 25};
|
|
static const BG_POINT OPTIONS_READABLE_CHECK_DEST_POS = {21, 7};
|
|
|
|
static const Rect OPTIONS_MUSIC_SLIDER_FULL_SRC = { 9, 20, 9, 20};
|
|
static const Rect OPTIONS_MUSIC_SLIDER_MID_SRC = {10, 20, 10, 20};
|
|
static const Rect OPTIONS_MUSIC_SLIDER_EMPTY_SRC = {11, 20, 11, 20};
|
|
static const Rect OPTIONS_SOUND_SLIDER_FULL_SRC = { 9, 22, 9, 22};
|
|
static const Rect OPTIONS_SOUND_SLIDER_MID_SRC = {10, 22, 10, 22};
|
|
static const Rect OPTIONS_SOUND_SLIDER_EMPTY_SRC = {11, 22, 11, 22};
|
|
static const BG_POINT OPTIONS_MUSIC_SLIDER_START_POS = { 5, 11};
|
|
static const BG_POINT OPTIONS_SOUND_SLIDER_START_POS = { 5, 14};
|
|
static const BG_POINT OPTIONS_MUSIC_SLIDER_END_POS = {24, 11};
|
|
static const BG_POINT OPTIONS_SOUND_SLIDER_END_POS = {24, 14};
|
|
static const u8 OPTIONS_MUSIC_SLIDER_SEGMENT_LENGTH = (OPTIONS_MUSIC_SLIDER_END_POS.x - OPTIONS_MUSIC_SLIDER_START_POS.x + 1)
|
|
/ VOLUME_OPTION_MAX;
|
|
static const u8 OPTIONS_SOUND_SLIDER_SEGMENT_LENGTH = (OPTIONS_SOUND_SLIDER_END_POS.x - OPTIONS_SOUND_SLIDER_START_POS.x + 1)
|
|
/ VOLUME_OPTION_MAX;
|
|
|
|
// Values in pixels
|
|
static const BG_POINT OPTIONS_GAME_SPEED_TEXT_POS = { 82, 16};
|
|
static const BG_POINT OPTIONS_CARD_SPRITES_TEXT_POS = { 72, 48};
|
|
static const BG_POINT OPTIONS_MUSIC_VOLUME_TEXT_POS = { 56, 80};
|
|
static const BG_POINT OPTIONS_MUSIC_VALUE_TEXT_POS = {160, 80};
|
|
static const BG_POINT OPTIONS_SOUND_VOLUME_TEXT_POS = { 56, 104};
|
|
static const BG_POINT OPTIONS_SOUND_VALUE_TEXT_POS = {160, 104};
|
|
static const BG_POINT OPTIONS_BACK_SAVE_TEXT_POS = { 64, 136};
|
|
// clang-format on
|
|
|
|
#define GAME_SPEED_ARROW_HIGHLIGHT_DURATION 10
|
|
enum OptionSpeedButtons game_speed_arrow_highlight_button = GAME_SPEED_UP_BTN_IDX;
|
|
static s32 game_speed_arrow_highlight_start = UNDEFINED;
|
|
|
|
static void disable_all_game_speed_outlines_except_self(enum OptionSpeedButtons highlighted_btn)
|
|
{
|
|
for (int i = 0; i < NB_GAME_SPEED_BUTTONS; i++)
|
|
{
|
|
button_set_highlight(&game_speed_buttons[i], i == highlighted_btn);
|
|
}
|
|
}
|
|
|
|
static void disable_all_outlines_except_self(Selection sel_btn)
|
|
{
|
|
// These two get disabled no matter what here
|
|
disable_all_game_speed_outlines_except_self(NB_GAME_SPEED_BUTTONS);
|
|
|
|
for (int j = 0; j < NB_OPTIONS_ROWS; j++)
|
|
{
|
|
int nb_buttons_in_row;
|
|
|
|
switch (j)
|
|
{
|
|
case HIGH_CONTRAST_ROW_IDX:
|
|
nb_buttons_in_row = options_menu_return_card_sprites_row_size();
|
|
break;
|
|
case SAVE_BACK_ROW_IDX:
|
|
nb_buttons_in_row = options_menu_return_bottom_row_size();
|
|
break;
|
|
default:
|
|
nb_buttons_in_row = options_menu_return_upper_rows_size();
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < nb_buttons_in_row; i++)
|
|
{
|
|
button_set_highlight(&options_menu_buttons[j][i], i == sel_btn.x && j == sel_btn.y);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void update_game_speed_button_graphics()
|
|
{
|
|
// check if need to disable game speed arrows
|
|
|
|
Rect speed_down_btn_tiles = (g_game_vars.game_speed == GAME_SPEED_MIN)
|
|
? OPTIONS_SPEED_DOWN_DISABLED_BTN_SRC_RECT
|
|
: OPTIONS_SPEED_DOWN_ACTIVE_BTN_SRC_RECT;
|
|
main_bg_se_copy_rect(speed_down_btn_tiles, OPTIONS_SPEED_DOWN_BTN_DEST_POS);
|
|
|
|
Rect speed_up_btn_tiles = (g_game_vars.game_speed == GAME_SPEED_MAX)
|
|
? OPTIONS_SPEED_UP_DISABLED_BTN_SRC_RECT
|
|
: OPTIONS_SPEED_UP_ACTIVE_BTN_SRC_RECT;
|
|
main_bg_se_copy_rect(speed_up_btn_tiles, OPTIONS_SPEED_UP_BTN_DEST_POS);
|
|
|
|
main_bg_se_copy_rect(
|
|
OPTIONS_SPEED_VALUES[g_game_vars.game_speed - 1],
|
|
OPTIONS_SPEED_VALUE_DEST_POS
|
|
);
|
|
}
|
|
|
|
static void update_high_contrast_button_graphics(void)
|
|
{
|
|
Rect contrast_btn_tiles = (get_cards_high_contrast()) ? OPTIONS_CONTRAST_CHECK_YES_SRC_RECT
|
|
: OPTIONS_CONTRAST_CHECK_NO_SRC_RECT;
|
|
main_bg_se_copy_rect(contrast_btn_tiles, OPTIONS_CONTRAST_CHECK_DEST_POS);
|
|
}
|
|
|
|
static void update_more_readable_button_graphics(void)
|
|
{
|
|
Rect readable_btn_tiles = (get_cards_more_readable()) ? OPTIONS_READABLE_CHECK_YES_SRC_RECT
|
|
: OPTIONS_READABLE_CHECK_NO_SRC_RECT;
|
|
main_bg_se_copy_rect(readable_btn_tiles, OPTIONS_READABLE_CHECK_DEST_POS);
|
|
}
|
|
|
|
static void update_volume_slider_graphics(enum OptionButtonRows sel_row)
|
|
{
|
|
u8 slider_value;
|
|
BG_POINT slider_segment_dest;
|
|
int slider_segment_length;
|
|
Rect slider_segment_full;
|
|
Rect slider_segment_mid;
|
|
Rect slider_segment_empty;
|
|
BG_POINT slider_text_pos;
|
|
|
|
switch (sel_row)
|
|
{
|
|
case MUSIC_VOLUME_ROW_IDX:
|
|
slider_value = g_game_vars.music_volume;
|
|
slider_segment_dest = OPTIONS_MUSIC_SLIDER_START_POS;
|
|
slider_segment_length = OPTIONS_MUSIC_SLIDER_SEGMENT_LENGTH;
|
|
slider_segment_full = OPTIONS_MUSIC_SLIDER_FULL_SRC;
|
|
slider_segment_mid = OPTIONS_MUSIC_SLIDER_MID_SRC;
|
|
slider_segment_empty = OPTIONS_MUSIC_SLIDER_EMPTY_SRC;
|
|
slider_text_pos = OPTIONS_MUSIC_VALUE_TEXT_POS;
|
|
break;
|
|
case SOUND_VOLUME_ROW_IDX:
|
|
slider_value = g_game_vars.sound_volume;
|
|
slider_segment_dest = OPTIONS_SOUND_SLIDER_START_POS;
|
|
slider_segment_length = OPTIONS_SOUND_SLIDER_SEGMENT_LENGTH;
|
|
slider_segment_full = OPTIONS_SOUND_SLIDER_FULL_SRC;
|
|
slider_segment_mid = OPTIONS_SOUND_SLIDER_MID_SRC;
|
|
slider_segment_empty = OPTIONS_SOUND_SLIDER_EMPTY_SRC;
|
|
slider_text_pos = OPTIONS_SOUND_VALUE_TEXT_POS;
|
|
break;
|
|
// This function only takes in a volume slider
|
|
default:
|
|
return;
|
|
}
|
|
|
|
int i = 0;
|
|
|
|
// full part of the bar
|
|
for (; i < slider_value * slider_segment_length - 1; i++)
|
|
{
|
|
main_bg_se_copy_rect(slider_segment_full, slider_segment_dest);
|
|
slider_segment_dest.x++;
|
|
}
|
|
|
|
// at exactly `slider_value` we either:
|
|
// - are in the middle of the bar, then we draw the frontier between full and empty tiles
|
|
// - are at the end, then draw a full segment
|
|
if (slider_value == VOLUME_OPTION_MAX)
|
|
{
|
|
main_bg_se_copy_rect(slider_segment_full, slider_segment_dest);
|
|
}
|
|
else
|
|
{
|
|
if (slider_value != VOLUME_OPTION_MIN)
|
|
{
|
|
// draw middle point
|
|
main_bg_se_copy_rect(slider_segment_mid, slider_segment_dest);
|
|
i++;
|
|
slider_segment_dest.x++;
|
|
}
|
|
|
|
// empty part of the bar
|
|
for (; i < VOLUME_OPTION_MAX * slider_segment_length; i++)
|
|
{
|
|
main_bg_se_copy_rect(slider_segment_empty, slider_segment_dest);
|
|
slider_segment_dest.x++;
|
|
}
|
|
}
|
|
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}%3d",
|
|
slider_text_pos.x,
|
|
slider_text_pos.y,
|
|
TTE_WHITE_PB,
|
|
(slider_value * VOLUME_OPTION_INCREMENT)
|
|
);
|
|
}
|
|
|
|
void game_options_menu_change_background(void)
|
|
{
|
|
tte_erase_screen();
|
|
|
|
GRIT_CPY(pal_bg_mem, background_options_menu_gfxPal);
|
|
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_options_menu_gfxTiles);
|
|
GRIT_CPY(&se_mem[MAIN_BG_SBB], background_options_menu_gfxMap);
|
|
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}Game Speed",
|
|
OPTIONS_GAME_SPEED_TEXT_POS.x,
|
|
OPTIONS_GAME_SPEED_TEXT_POS.y,
|
|
TTE_WHITE_PB
|
|
);
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}Card Sprites",
|
|
OPTIONS_CARD_SPRITES_TEXT_POS.x,
|
|
OPTIONS_CARD_SPRITES_TEXT_POS.y,
|
|
TTE_WHITE_PB
|
|
);
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}Music Volume",
|
|
OPTIONS_MUSIC_VOLUME_TEXT_POS.x,
|
|
OPTIONS_MUSIC_VOLUME_TEXT_POS.y,
|
|
TTE_WHITE_PB
|
|
);
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}Sound Volume",
|
|
OPTIONS_SOUND_VOLUME_TEXT_POS.x,
|
|
OPTIONS_SOUND_VOLUME_TEXT_POS.y,
|
|
TTE_WHITE_PB
|
|
);
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}Save Cancel",
|
|
OPTIONS_BACK_SAVE_TEXT_POS.x,
|
|
OPTIONS_BACK_SAVE_TEXT_POS.y,
|
|
TTE_WHITE_PB
|
|
);
|
|
}
|
|
|
|
void game_options_menu_on_init(void)
|
|
{
|
|
change_background(BG_OPTIONS_MENU, false);
|
|
|
|
// Select game speed button by default
|
|
options_menu_selection_grid.selection = OPTIONS_MENU_INIT_SEL;
|
|
disable_all_outlines_except_self(OPTIONS_MENU_INIT_SEL);
|
|
|
|
// Do an update on the first frame
|
|
update_game_speed_button_graphics();
|
|
update_high_contrast_button_graphics();
|
|
update_more_readable_button_graphics();
|
|
update_volume_slider_graphics(MUSIC_VOLUME_ROW_IDX);
|
|
update_volume_slider_graphics(SOUND_VOLUME_ROW_IDX);
|
|
}
|
|
|
|
void game_options_menu_on_update(void)
|
|
{
|
|
selection_grid_process_input(&options_menu_selection_grid);
|
|
|
|
// game speed arrows small animation: they stay highlighted for a few frames
|
|
if (game_speed_arrow_highlight_start != UNDEFINED &&
|
|
(g_game_vars.timer - game_speed_arrow_highlight_start) >
|
|
GAME_SPEED_ARROW_HIGHLIGHT_DURATION)
|
|
{
|
|
game_speed_arrow_highlight_start = UNDEFINED;
|
|
button_set_highlight(&game_speed_buttons[game_speed_arrow_highlight_button], false);
|
|
}
|
|
}
|
|
|
|
void game_options_menu_on_exit(void)
|
|
{
|
|
tte_erase_screen();
|
|
}
|
|
|
|
static void game_speed_down_on_pressed(void)
|
|
{
|
|
g_game_vars.game_speed--;
|
|
game_speed_arrow_highlight_start = g_game_vars.timer;
|
|
game_speed_arrow_highlight_button = GAME_SPEED_DOWN_BTN_IDX;
|
|
disable_all_game_speed_outlines_except_self(GAME_SPEED_DOWN_BTN_IDX);
|
|
update_game_speed_button_graphics();
|
|
}
|
|
|
|
static void game_speed_up_on_pressed(void)
|
|
{
|
|
g_game_vars.game_speed++;
|
|
game_speed_arrow_highlight_start = g_game_vars.timer;
|
|
game_speed_arrow_highlight_button = GAME_SPEED_UP_BTN_IDX;
|
|
disable_all_game_speed_outlines_except_self(GAME_SPEED_UP_BTN_IDX);
|
|
update_game_speed_button_graphics();
|
|
}
|
|
|
|
/**
|
|
* @brief Handles input for the high contrast card toggle button and nothing more.
|
|
*/
|
|
static void high_contrast_on_pressed(void)
|
|
{
|
|
set_cards_high_contrast(!get_cards_high_contrast());
|
|
update_high_contrast_button_graphics();
|
|
}
|
|
|
|
/**
|
|
* @brief Handles input for the more readable card toggle button and nothing more.
|
|
*/
|
|
static void more_readable_on_pressed(void)
|
|
{
|
|
set_cards_more_readable(!get_cards_more_readable());
|
|
update_more_readable_button_graphics();
|
|
}
|
|
|
|
/**
|
|
* @brief Handles input for the Save button.
|
|
*/
|
|
static void save_on_pressed(void)
|
|
{
|
|
save_options();
|
|
game_change_state(GAME_STATE_MAIN_MENU);
|
|
}
|
|
|
|
/**
|
|
* @brief Handles input for the Back button.
|
|
*/
|
|
static void back_on_pressed(void)
|
|
{
|
|
load_options();
|
|
game_change_state(GAME_STATE_MAIN_MENU);
|
|
}
|
|
|
|
/**
|
|
* @brief Gives the width of normal options rows in selection grid.
|
|
*
|
|
* @returns 1
|
|
*/
|
|
static int options_menu_return_upper_rows_size(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Gives the width of Card Sprites options row in selection grid.
|
|
*
|
|
* @returns 2
|
|
*/
|
|
static int options_menu_return_card_sprites_row_size(void)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
/**
|
|
* @brief Gives the width of the Save and Back buttons' row.
|
|
*
|
|
* @returns 2
|
|
*/
|
|
static int options_menu_return_bottom_row_size(void)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static void change_button_highlight(
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
if (prev_selection->y == row_idx)
|
|
{
|
|
button_set_highlight(&options_menu_buttons[row_idx][prev_selection->x], false);
|
|
}
|
|
|
|
if (new_selection->y == row_idx)
|
|
{
|
|
play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME);
|
|
button_set_highlight(&options_menu_buttons[row_idx][new_selection->x], true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Handles left/Right inputs on the row of the Game Speed button.
|
|
* Is used to increased/decrease the speed value, instead of relying on a
|
|
* `on_key_transit` function because the latter does not take directional
|
|
* inputs.
|
|
*/
|
|
static bool game_speed_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
change_button_highlight(row_idx, prev_selection, new_selection);
|
|
disable_all_game_speed_outlines_except_self(NB_GAME_SPEED_BUTTONS);
|
|
|
|
// Can only change game speed by pressing left/right while staying on the button's row
|
|
if (prev_selection->y != new_selection->y)
|
|
return true;
|
|
|
|
if (key_hit(KEY_LEFT) && g_game_vars.game_speed > GAME_SPEED_MIN)
|
|
{
|
|
button_press(&game_speed_buttons[GAME_SPEED_DOWN_BTN_IDX]);
|
|
}
|
|
else if (key_hit(KEY_RIGHT) && g_game_vars.game_speed < GAME_SPEED_MAX)
|
|
{
|
|
button_press(&game_speed_buttons[GAME_SPEED_UP_BTN_IDX]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Handles input for all SelectionGridRows in options menu, only actually does
|
|
* something on rows containing "normal" buttons (those for which the on_pressed
|
|
* method in options_menu_buttons is not NULL).
|
|
*/
|
|
static void options_menu_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection)
|
|
{
|
|
if (key_hit(SELECT_CARD))
|
|
{
|
|
button_press(&options_menu_buttons[selection->y][selection->x]);
|
|
}
|
|
}
|
|
|
|
static bool regular_button_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
change_button_highlight(row_idx, prev_selection, new_selection);
|
|
return true;
|
|
}
|
|
|
|
static bool music_volume_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
change_button_highlight(row_idx, prev_selection, new_selection);
|
|
|
|
if (prev_selection->y != new_selection->y)
|
|
return true;
|
|
|
|
if (key_hit(KEY_LEFT) && g_game_vars.music_volume > VOLUME_OPTION_MIN)
|
|
{
|
|
g_game_vars.music_volume--;
|
|
}
|
|
else if (key_hit(KEY_RIGHT) && g_game_vars.music_volume < VOLUME_OPTION_MAX)
|
|
{
|
|
g_game_vars.music_volume++;
|
|
}
|
|
|
|
update_volume_slider_graphics(MUSIC_VOLUME_ROW_IDX);
|
|
set_volume(volume_module_step_to_val(g_game_vars.music_volume));
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool sound_volume_row_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
change_button_highlight(row_idx, prev_selection, new_selection);
|
|
|
|
if (prev_selection->y != new_selection->y)
|
|
return true;
|
|
|
|
if (key_hit(KEY_LEFT) && g_game_vars.sound_volume > VOLUME_OPTION_MIN)
|
|
{
|
|
g_game_vars.sound_volume--;
|
|
}
|
|
else if (key_hit(KEY_RIGHT) && g_game_vars.sound_volume < VOLUME_OPTION_MAX)
|
|
{
|
|
g_game_vars.sound_volume++;
|
|
}
|
|
|
|
update_volume_slider_graphics(SOUND_VOLUME_ROW_IDX);
|
|
|
|
return true;
|
|
}
|