It would be nice if the menu had an immediate mode API rather than only the callback-based retained-mode one. So instead of doing this:
// Current API:
struct MyMenu {
PDMenuItem *item_a;
PDMenuItem *item_b;
PDMenuItem *item_c;
};
void callback_a(void *state)
{
// do thing A
}
static const char *items_b[] = { "Foo", "Bar" };
void callback_b(void *state_ptr)
{
GameState *state = (GameState *)state_ptr;
state->selected_b_index = pd->system->getMenuItemValue(state->menu.item_b);
// do thing B
}
void menu_init(MyMenu *menu, GameState *state)
{
menu->item_a = pd->system->addMenuItem("a", callback_a, state);
menu->item_b = pd->system->addOptionsMenuItem("b", items_b, 2,
callback_b, state);
// ...
}
You could instead do this:
// Immediate mode API:
static const char *items_b[] = { "Foo", "Bar" };
void update_menu(GameState *state)
{
if (pd->system->menuItem("a")) {
// do thing A
}
if (pd->system->optionMenuItem("b", items_b, 2, &state->selected_b_index)) {
// do thing B
}
// ...
}
This style of API not only means less code, but it also removes the duplication of the menu state between the playdate library and the user code. The code also gets easier and more debuggable due to not having callbacks.
The biggest practical advantage I see is being able to very easily present different menu choices depending on the state of the game:
// This option only makes sense while we're in a level
if (game_state->phase == Phase_InGame) {
if (pd->system->menuItem("Quit Level"))
quit_level();
} else if (game_state->phase == Phase_Cutscene) {
if (pd->system->menuItem("Skip"))
skip_cutscene();
}
This is much less convenient to achieve with the current API, as you need to remove and re-add the item(s) in the proper position.
Of course I’m not calling for replacing the current API, but it’d be nice to have both alternatives.
EDIT: if this is too big of a feature to add, it would at least be nice to have the option of adding a menu item in a specific position so one doesn’t need to remove and re-add all items if they want to change the first or second one; something like:
pd->system->addMenuItemAtPosition(int index, // ...same args as addMenuItem);