Poke_Transporter_GB/source/select_menu.cpp
Philippe Symons b0abeaf5f6 Create vertical_menu widget
This commit implements a vertical menu widget, which should be quite a bit more flexible than
what we currently have.

It defines interfaces in order to respond to selection changes, show and hide. And has a i_item_widget
interface class to allow you to use custom item widgets.

This is done in preparation for adding a debug menu, in which I kinda want to add toggle options
while using the same vertical_menu widget.

Right now, vertical_menu is only used in Select_Menu. Needless to say that Select_Menu was reworked quite a bit.
Still, in terms of visuals or functionality, the changes should be invisible for now. I mean, I didn't do anything *new* with it yet.
2026-03-03 00:15:18 +01:00

141 lines
3.7 KiB
C++

#include "select_menu.h"
#include "sprite_data.h"
#include "translated_text.h"
#include "text_data_table.h"
#include "global_frame_controller.h"
#define TEXT_HEIGHT 10
#define TEXT_WIDTH 8
#define TILE_HEIGHT 8
#define TILE_WIDTH 8
Select_Menu::Select_Menu(bool enable_cancel, u8 nMenu_type, unsigned nStartTileX, unsigned nStartTileY)
: menu_widget_(vertical_menu_settings{
.x = static_cast<unsigned>(nStartTileX * TILE_WIDTH),
.y = static_cast<unsigned>(nStartTileY * TILE_HEIGHT),
.width = 10 * TEXT_WIDTH,
.height = TILE_HEIGHT * 2, // to account for the margins
.margin_top = TILE_HEIGHT,
.margin_bottom = TILE_HEIGHT,
.initial_focus_index = 0,
.item_height = TEXT_HEIGHT,
.text_table_index = GENERAL_INDEX,
.allow_cancel = enable_cancel,
.should_delete_item_widgets_on_destruct = true,
.should_hide_state_changed_handler_on_not_focused = false
})
, menu_type(nMenu_type)
, lang(0)
{
menu_widget_.set_state_changed_handler(this);
menu_widget_.set_run_cycle_handler(this);
}
void Select_Menu::add_option(const u8 option, u8 return_value)
{
const simple_item_widget_data item_data = {
.text = {
.text_table_index = option,
.margin_left = 2 * TILE_WIDTH,
.margin_top = 0
},
.value = return_value,
.on_execute_callback = nullptr
};
menu_widget_.add_item_widget(new simple_item_renderer(item_data));
vertical_menu_settings settings = menu_widget_.get_settings();
settings.height += TEXT_HEIGHT + (item_data.text.margin_top * 2);
menu_widget_.set_settings(settings);
}
void Select_Menu::clear_options()
{
menu_widget_.clear_item_widgets();
vertical_menu_settings settings = menu_widget_.get_settings();
settings.height = TILE_HEIGHT * 2; // reset to just the margins
menu_widget_.set_settings(settings);
}
int Select_Menu::select_menu_main()
{
unsigned choice_index;
unsigned item_value;
simple_item_renderer* widget = nullptr;
menu_widget_.show();
choice_index = menu_widget_.run();
if(choice_index != UINT32_MAX)
{
widget = static_cast<simple_item_renderer*>(menu_widget_.get_item_widget_at(choice_index));
}
item_value = (widget) ? widget->get_data().value : UINT8_MAX;
menu_widget_.hide();
global_next_frame();
return item_value;
}
void Select_Menu::set_lang(u8 nLang)
{
lang = nLang;
}
void Select_Menu::on_show()
{
obj_unhide(point_arrow, 0);
}
void Select_Menu::on_hide()
{
obj_hide(point_arrow);
obj_hide(cart_shell);
obj_hide(cart_label);
obj_hide(flag);
}
void Select_Menu::on_selection_changed(unsigned new_index, unsigned x, unsigned y)
{
// set the cursor accordingly
obj_set_pos(point_arrow, x + TEXT_WIDTH, y + 3);
simple_item_renderer* widget = static_cast<simple_item_renderer*>(menu_widget_.get_item_widget_at(new_index));
const unsigned item_value = (widget) ? widget->get_data().value : UINT8_MAX;
if (item_value == UINT8_MAX)
{
switch (menu_type)
{
case CART_MENU:
obj_hide(cart_shell);
obj_hide(cart_label);
break;
case LANG_MENU:
obj_hide(flag);
break;
}
}
else
{
switch (menu_type)
{
case CART_MENU:
load_select_sprites(item_value, lang);
obj_unhide(cart_shell, 0);
obj_unhide(cart_label, 0);
break;
case LANG_MENU:
load_select_sprites(0, item_value);
obj_unhide(flag, 0);
break;
}
}
}
void Select_Menu::on_run_cycle()
{
update_y_offset();
}