Add menu lib

This commit is contained in:
Robin Jones 2023-02-23 02:31:56 +00:00
parent ffb6b3fd53
commit 3a2b908a4f
8 changed files with 855 additions and 0 deletions

View File

@ -17,6 +17,7 @@ SRCS = \
menu/menu.c \ menu/menu.c \
utils/fs.c \ utils/fs.c \
libs/toml/toml.c \ libs/toml/toml.c \
libs/menu_utils/menu.c \
main.c main.c
OBJS = $(addprefix $(BUILD_DIR)/, $(addsuffix .o,$(basename $(SRCS)))) OBJS = $(addprefix $(BUILD_DIR)/, $(addsuffix .o,$(basename $(SRCS))))

View File

@ -0,0 +1,11 @@
# Source
https://github.com/stefanmielke/libdragon-extensions
# License
MIT
# Description
Used for generating the menu GUI
# Notes
It might be preferable to change to a submodule.

View File

@ -0,0 +1,42 @@
#include "../include/mem_pool.h"
#include <string.h>
#include <libdragon.h>
void mem_zone_init(MemZone *z, size_t size) {
disable_interrupts();
void *ptr = malloc(size);
if (ptr == NULL) {
abort(); // Put your error handling here.
}
z->pos = (char *)ptr;
z->start = z->pos;
z->end = z->start + size;
memset(z->start, 0, size);
enable_interrupts();
}
void *mem_zone_alloc(MemZone *z, size_t size) {
if (size == 0) {
return NULL;
}
// Round up to multiple of 16 bytes.
size = (size + 15) & ~(size_t)15;
// How much free space remaining in zone?
size_t rem = z->end - z->pos;
if (rem < size) {
return NULL; // Out of memory. Put your error handling here.
}
void *ptr = (void *)z->pos;
z->pos += size;
return ptr;
}
void mem_zone_free_all(MemZone *z) {
z->pos = z->start;
}

View File

@ -0,0 +1,49 @@
#pragma once
#include <malloc.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A contiguous zone where memory can be allocated.
*/
typedef struct {
/// Pointer to current free space position.
char *pos;
/// Pointer to start of zone.
char *start;
/// Pointer to end of zone.
char *end;
} MemZone;
/**
* @brief Allocate a memory zone with the given size.
*
* @param memory_zone MemZone to use.
* @param size Size in bytes that the MemZone will have. (eg.: '1*1024*1024' for 1MB)
*/
void mem_zone_init(MemZone *memory_zone, size_t size);
/**
* @brief Allocate memory from the zone.
*
* @param memory_zone MemZone to use.
* @param size Size in bytes of the memory. (eg.: sizeof(int))
*
* @return the memory allocated.
*/
void *mem_zone_alloc(MemZone *memory_zone, size_t size);
/**
* @brief Free all objects in the zone.
*
* @param memory_zone MemZone to use.
*/
void mem_zone_free_all(MemZone *memory_zone);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,6 @@
#include "mem_pool.h"
/**
* @brief Used to allocate an object using either a MemZone or malloc according to the parameters.
*/
#define MEM_ALLOC(SIZE, MEMPOOL) ((MEMPOOL) ? mem_zone_alloc((MEMPOOL), (SIZE)) : malloc(SIZE))

415
src/libs/menu_utils/menu.c Normal file
View File

@ -0,0 +1,415 @@
#include "../include/menu.h"
#include "../include/memory_alloc.h"
void menu_scroll_up(Menu *menu);
void menu_scroll_down(Menu *menu);
uint32_t MENU_C_SELECTED;
uint32_t MENU_C_ENABLED;
uint32_t MENU_C_DISABLED;
uint32_t MENU_C_BACKGROUND;
uint32_t MENU_C_MENU_BACKGROUND;
uint32_t MENU_C_OUT_OF_BOUNDS;
sprite_t *menu_background_sprite;
sprite_t *menu_hand_sprite;
uint8_t menu_hand_sprite_offset;
void menu_global_init() {
MENU_C_SELECTED = graphics_make_color(0, 0, 255, 255);
MENU_C_ENABLED = graphics_make_color(255, 255, 255, 255);
MENU_C_DISABLED = graphics_make_color(100, 100, 255, 255);
MENU_C_BACKGROUND = graphics_make_color(0, 0, 0, 0);
MENU_C_OUT_OF_BOUNDS = graphics_make_color(0, 0, 0, 255);
MENU_C_MENU_BACKGROUND = graphics_make_color(255, 255, 255, 255);
}
void menu_global_set_default_colors(uint32_t selected, uint32_t enabled, uint32_t disabled,
uint32_t background, uint32_t out_of_bounds,
uint32_t menu_background) {
MENU_C_SELECTED = selected;
MENU_C_ENABLED = enabled;
MENU_C_DISABLED = disabled;
MENU_C_BACKGROUND = background;
MENU_C_OUT_OF_BOUNDS = out_of_bounds;
MENU_C_MENU_BACKGROUND = menu_background;
}
void menu_global_set_sprites(sprite_t *menu_sprite, sprite_t *hand_sprite,
uint8_t hand_sprite_offset) {
menu_background_sprite = menu_sprite;
menu_hand_sprite = hand_sprite;
menu_hand_sprite_offset = hand_sprite_offset;
}
Menu *menu_init(MemZone *memory_pool, uint8_t total_items, uint8_t max_items, int top, int left,
uint8_t item_height, fnMenuCallback callback) {
Menu *menu = MEM_ALLOC(sizeof(Menu), memory_pool);
menu->total_items = total_items;
menu->items = MEM_ALLOC(sizeof(MenuItem) * total_items, memory_pool);
menu->current_menu_option = 0;
menu_reset_items(menu);
menu->active_submenu = -1;
menu->submenus = NULL;
menu->display_when_on_submenu = false;
menu->display_background = false;
menu->menu_width = 0;
menu->item_vertical_limit = max_items;
menu->item_height = item_height;
menu->top = top;
menu->left = left;
menu->cur_top_item = 0;
menu->cur_bottom_item = 0;
menu->callback = callback;
menu->display_hand = false;
menu->hand_position_x = 0;
menu->hand_position_y_offset = 0;
return menu;
}
void menu_set_background(Menu *menu, int menu_width) {
menu->display_background = true;
menu->menu_width = menu_width;
}
void menu_reset_items(Menu *menu) {
menu->current_add_index = 0;
for (uint8_t i = 0; i < menu->total_items; ++i) {
menu->items[i].enabled = false;
menu->items[i].text = NULL;
menu->items[i].x = 0;
menu->items[i].y = 0;
}
}
void menu_set_hand(Menu *menu, int hand_position_x, int hand_position_y_offset) {
menu->display_hand = true;
menu->hand_position_x = hand_position_x;
menu->hand_position_y_offset = hand_position_y_offset;
}
void menu_add_item(Menu *menu, char *text, bool enabled, void *object) {
if (menu->current_add_index >= menu->total_items)
return;
MenuItem *item = &menu->items[menu->current_add_index];
item->text = text;
item->x = menu->left;
item->y = menu->top + (menu->item_height * menu->current_add_index);
item->enabled = enabled;
item->has_custom_colors = false;
item->sprite_index = -1;
item->object = object;
if (menu->current_add_index == menu->item_vertical_limit)
item->state = MSIS_OnBorder;
else if (menu->current_add_index > menu->item_vertical_limit)
item->state = MSIS_Outside;
else
item->state = MSIS_Inside;
menu->current_add_index++;
menu->cur_bottom_item = menu->current_add_index >= menu->item_vertical_limit
? menu->item_vertical_limit - 1
: menu->current_add_index - 1;
}
void menu_add_item_image(Menu *menu, sprite_t *sprite, int sprite_index, bool enabled,
void *object) {
if (menu->current_add_index >= menu->total_items)
return;
MenuItem *item = &menu->items[menu->current_add_index];
item->sprite = sprite;
item->sprite_index = sprite_index;
item->x = menu->left;
item->y = menu->top + (menu->item_height * menu->current_add_index);
item->enabled = enabled;
item->has_custom_colors = false;
item->object = object;
if (menu->current_add_index == menu->item_vertical_limit)
item->state = MSIS_OnBorder;
else if (menu->current_add_index > menu->item_vertical_limit)
item->state = MSIS_Outside;
else
item->state = MSIS_Inside;
menu->current_add_index++;
menu->cur_bottom_item = menu->current_add_index >= menu->item_vertical_limit
? menu->item_vertical_limit - 1
: menu->current_add_index - 1;
}
void menu_add_item_colored(Menu *menu, char *text, bool enabled, uint32_t color_selected,
uint32_t color_enabled, uint32_t color_disabled, void *object) {
if (menu->current_add_index >= menu->total_items)
return;
MenuItem *item = &menu->items[menu->current_add_index];
item->text = text;
item->x = menu->left;
item->y = menu->top + (menu->item_height * menu->current_add_index);
item->enabled = enabled;
item->has_custom_colors = true;
item->sprite_index = -1;
item->object = object;
item->color_selected = color_selected;
item->color_enabled = color_enabled;
item->color_disabled = color_disabled;
if (menu->current_add_index == menu->item_vertical_limit)
item->state = MSIS_OnBorder;
else if (menu->current_add_index > menu->item_vertical_limit)
item->state = MSIS_Outside;
else
item->state = MSIS_Inside;
menu->current_add_index++;
menu->cur_bottom_item = menu->current_add_index >= menu->item_vertical_limit
? menu->item_vertical_limit - 1
: menu->current_add_index - 1;
}
int menu_tick(Menu *menu, struct controller_data *keys_down) {
if (menu->active_submenu >= 0 && menu->submenus) {
Menu **menus = menu->submenus;
Menu *active_submenu = menus[menu->active_submenu];
int option = menu_tick(active_submenu, keys_down);
// go back from submenu
if (option == -2) {
menu->active_submenu = -1;
return -1;
}
return option;
}
if (menu->current_add_index <= 0)
return -1;
if (keys_down->c[0].up) {
if (menu->current_menu_option > 0) {
menu->current_menu_option -= 1;
menu_scroll_up(menu);
}
} else if (keys_down->c[0].down) {
if (menu->current_menu_option < menu->current_add_index - 1) {
menu->current_menu_option += 1;
menu_scroll_down(menu);
}
} else if (keys_down->c[0].A || keys_down->c[0].start) {
if (menu->items[menu->current_menu_option].enabled) {
if (menu->callback) {
menu->callback(menu->current_menu_option, &menu->items[menu->current_menu_option]);
}
return menu->current_menu_option;
}
} else if (keys_down->c[0].B) {
return -2;
}
return -1;
}
void menu_render(Menu *menu, display_context_t disp) {
if (menu->active_submenu >= 0 && menu->submenus) {
Menu *active_submenu = menu->submenus[menu->active_submenu];
menu_render(active_submenu, disp);
if (!menu->display_when_on_submenu)
return;
}
// render window background
if (menu->display_background) {
const int item_count = menu->current_add_index < menu->item_vertical_limit
? menu->current_add_index
: menu->item_vertical_limit;
const int menu_left = menu->left - 8;
const int menu_top = menu->top - menu->item_height;
const int menu_bottom = menu->top + (menu->item_height * item_count);
const int menu_right = menu->left + menu->menu_width;
menu_draw_background_center(disp, menu_top, menu_left, menu_bottom, menu_right);
}
for (uint8_t i = 0; i < menu->current_add_index; ++i) {
if (menu->items[i].state == MSIS_Outside)
continue;
if (menu->items[i].sprite_index == -1) {
if (menu->items[i].state == MSIS_Inside) {
if (i == menu->current_menu_option) {
if (menu->items[i].has_custom_colors) {
graphics_set_color(menu->items[i].color_selected, MENU_C_BACKGROUND);
} else {
graphics_set_color(MENU_C_SELECTED, MENU_C_BACKGROUND);
}
} else if (menu->items[i].enabled) {
if (menu->items[i].has_custom_colors) {
graphics_set_color(menu->items[i].color_enabled, MENU_C_BACKGROUND);
} else {
graphics_set_color(MENU_C_ENABLED, MENU_C_BACKGROUND);
}
} else {
if (menu->items[i].has_custom_colors) {
graphics_set_color(menu->items[i].color_disabled, MENU_C_BACKGROUND);
} else {
graphics_set_color(MENU_C_DISABLED, MENU_C_BACKGROUND);
}
}
} else {
graphics_set_color(MENU_C_OUT_OF_BOUNDS, MENU_C_BACKGROUND);
}
graphics_draw_text(disp, menu->items[i].x, menu->items[i].y, menu->items[i].text);
} else {
graphics_draw_sprite_trans_stride(disp, menu->items[i].x, menu->items[i].y,
menu->items[i].sprite, menu->items[i].sprite_index);
}
}
if (menu->display_background) {
const int item_count = menu->current_add_index < menu->item_vertical_limit
? menu->current_add_index
: menu->item_vertical_limit;
const int menu_left = menu->left - 8;
const int menu_top = menu->top - menu->item_height;
const int menu_bottom = menu->top + (menu->item_height * item_count);
const int menu_right = menu->left + menu->menu_width;
menu_draw_background_borders(disp, menu_top, menu_left, menu_bottom, menu_right);
}
// render hand icon
if (menu->display_hand && menu->current_add_index > 0) {
int option = menu->current_menu_option;
if (menu->current_add_index > 0)
graphics_draw_sprite_trans_stride(disp, menu->hand_position_x,
menu->items[option].y + menu->hand_position_y_offset,
menu_hand_sprite, menu_hand_sprite_offset);
}
}
void menu_init_submenus(Menu *menu, MemZone *memory_pool, uint8_t total_submenus,
bool display_when_on_submenu) {
// do not recreate submenus
if (menu->submenus)
return;
menu->submenus = MEM_ALLOC(sizeof(Menu *) * total_submenus, memory_pool);
menu->display_when_on_submenu = display_when_on_submenu;
}
void menu_draw_background_borders(display_context_t disp, int top, int left, int bottom,
int right) {
graphics_draw_sprite_trans_stride(disp, left, top, menu_background_sprite,
SPRITE_menu_top_left);
graphics_draw_sprite_trans_stride(disp, left, bottom, menu_background_sprite,
SPRITE_menu_bottom_left);
graphics_draw_sprite_trans_stride(disp, right, top, menu_background_sprite,
SPRITE_menu_top_right);
graphics_draw_sprite_trans_stride(disp, right, bottom, menu_background_sprite,
SPRITE_menu_bottom_right);
const int repeat_x = (right - left - 8) / 8;
for (size_t i = 0; i < repeat_x; ++i) {
graphics_draw_sprite_trans_stride(disp, left + 8 + (i * 8), top, menu_background_sprite,
SPRITE_menu_top);
graphics_draw_sprite_trans_stride(disp, left + 8 + (i * 8), bottom, menu_background_sprite,
SPRITE_menu_bottom);
}
const int repeat_y = ((bottom - top) / 8) - 1;
for (size_t i = 0; i < repeat_y; ++i) {
graphics_draw_sprite_trans_stride(disp, left, top + 8 + (i * 8), menu_background_sprite,
SPRITE_menu_left);
graphics_draw_sprite_trans_stride(disp, right, top + 8 + (i * 8), menu_background_sprite,
SPRITE_menu_right);
}
}
void menu_draw_background_center(display_context_t disp, int top, int left, int bottom, int right) {
// TODO: remove this "hack" and properly render the texture. Cause: libdragon issue with 32 bits
left += 8;
top += 8;
rdp_sync(SYNC_PIPE);
rdp_attach_display(disp);
rdp_enable_blend_fill();
rdp_set_default_clipping();
rdp_sync(SYNC_PIPE);
rdp_set_blend_color(MENU_C_MENU_BACKGROUND);
rdp_draw_filled_triangle(left, top, right, top, right, bottom);
rdp_draw_filled_triangle(left, top, left, bottom, right, bottom);
rdp_detach_display();
}
void menu_scroll_fix_y(Menu *menu) {
if (menu->cur_top_item > 0) {
menu->items[menu->cur_top_item - 1].y = menu->top - menu->item_height;
}
for (size_t ix = menu->cur_top_item, i = 0; i <= menu->cur_bottom_item; ++i, ++ix) {
menu->items[ix].y = menu->top + (i * menu->item_height);
}
if (menu->cur_bottom_item + 1 < menu->current_add_index) {
menu->items[menu->cur_bottom_item + 1].y = menu->top +
(menu->item_vertical_limit * menu->item_height);
}
}
void menu_scroll_up(Menu *menu) {
if (menu->current_menu_option < menu->cur_top_item) {
if (menu->cur_bottom_item + 1 < menu->current_add_index)
menu->items[menu->cur_bottom_item + 1].state = MSIS_Outside;
menu->items[menu->cur_bottom_item].state = MSIS_OnBorder;
if (menu->cur_top_item - 2 >= 0)
menu->items[menu->cur_top_item - 2].state = MSIS_OnBorder;
menu->items[menu->current_menu_option].state = MSIS_Inside;
menu->cur_top_item--;
menu->cur_bottom_item--;
menu_scroll_fix_y(menu);
}
}
void menu_scroll_down(Menu *menu) {
if (menu->current_menu_option > menu->cur_bottom_item) {
if (menu->cur_top_item > 0)
menu->items[menu->cur_top_item - 1].state = MSIS_Outside;
menu->items[menu->cur_top_item].state = MSIS_OnBorder;
menu->items[menu->current_menu_option].state = MSIS_Inside;
if (menu->current_menu_option + 1 < menu->current_add_index)
menu->items[menu->current_menu_option + 1].state = MSIS_OnBorder;
menu->cur_top_item++;
menu->cur_bottom_item++;
menu_scroll_fix_y(menu);
}
}

331
src/libs/menu_utils/menu.h Normal file
View File

@ -0,0 +1,331 @@
#pragma once
#include <libdragon.h>
#include "mem_pool.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enum with the order of the background sprites in a texture. Any texture has to have this
* order.
*/
typedef enum MenuBackgroundSprite {
SPRITE_menu_bottom,
SPRITE_menu_bottom_left,
SPRITE_menu_bottom_right,
SPRITE_menu_center,
SPRITE_menu_left,
SPRITE_menu_right,
SPRITE_menu_top,
SPRITE_menu_top_left,
SPRITE_menu_top_right,
SPRITE_menu_SPRITES_MAX
} MenuBackgroundSprite;
/**
* @brief Enum that contains the state of a given item in relation with the current selected item.
*/
typedef enum MenuItemState {
/// The item is inside the menu.
MSIS_Inside,
/// The item is on the edge of the menu.
MSIS_OnBorder,
/// The item is outside of the range of displayed items and will not be rendered.
MSIS_Outside,
} MenuItemState;
/**
* @brief Struct that represents an item inside the menu. Used internally when using
* 'menu_add_item*' functions.
*/
typedef struct MenuItem {
/// Text that will be rendered. Not used when is an image.
char *text;
/// Sprite that will be rendered. Used only when an image.
sprite_t *sprite;
/// Index of the sprite that will be rendered. Used only when an image.
int sprite_index;
/// X position of this item. Calculated whenever the state of the menu changes.
int x;
/// Y position of this item. Calculated whenever the state of the menu changes.
int y;
/// If the item is enabled. An enabled item can be used.
bool enabled;
/// If the item has custom colors. If false, will use the default colors. Default colors can be
/// changed using 'menu_global_set_default_colors'.
bool has_custom_colors;
/// Color for when this item is enabled. Used when 'has_custom_colors' is true.
uint32_t color_enabled;
/// Color for when this item is disabled ('enabled' == false). Used when 'has_custom_colors' is
/// true.
uint32_t color_disabled;
/// Color for when this item is selected. Used when 'has_custom_colors' is true.
uint32_t color_selected;
/// State of the item in relation to the menu. @see MenuItemState
MenuItemState state;
/// Custom object that is set by the user when creating the item.
void *object;
} MenuItem;
/**
* @brief Optional callback for when an item is used.
*
* @param[in] option
* The index of the used item.
* @param[in] menu_item
* A reference to the used menu item. @see MenuItem
*/
typedef void (*fnMenuCallback)(int option, MenuItem *menu_item);
/**
* @brief Struct used to hold a Menu. Created by the 'menu_init' function.
*/
typedef struct Menu {
/// Array of items of this menu.
MenuItem *items;
/// Maximum amount of items this menu can have. Also the size of 'items'.
uint8_t total_items;
/// Current index when inserting new MenuItems. Has the current amount of used items.
uint8_t current_add_index;
/// Current selected menu item index.
int current_menu_option;
/// Current active submenu. If '-1', no submenu is active.
int active_submenu;
/// Array with references to all submenus.
struct Menu **submenus;
/// If this menu should be rendered even when a submenu is active.
bool display_when_on_submenu;
/// If this menu should display a background. Configured using 'menu_global_set_sprites' and
/// 'menu_set_background'.
bool display_background;
/// Width of the background. Configured using 'menu_set_background'.
int menu_width;
/// If the hand should be displayed for this menu
bool display_hand;
/// X position of the hand cursor. Configured using 'menu_global_set_sprites' and
/// 'menu_set_hand'.
int hand_position_x;
/// Y offset for the hand cursor. Configured using 'menu_global_set_sprites' and
/// 'menu_set_hand'.
int hand_position_y_offset;
/// Amount of items that can be displayed at once.
uint8_t item_vertical_limit;
/// Height of each item inside the menu. Used to calculate Y position of items.
uint8_t item_height;
/// Y position of the menu.
int top;
/// X position of the menu.
int left;
/// Index of the item currently at the top of rendered menu.
uint8_t cur_top_item;
/// Index of the item currently at the bottom of rendered menu.
uint8_t cur_bottom_item;
/// Callback function for when an item is used. @see fnMenuCallback
fnMenuCallback callback;
} Menu;
/**
* @brief Allocates and returns a new Menu object.
*
* @param memory_pool
* The memory pool to be used. If NULL will use malloc.
* @param total_items
* Total items that can be created inside the Menu.
* @param max_items
* Count of items that will be displayed at once.
* @param top
* Y position of the menu.
* @param left
* X position of the menu.
* @param item_height
* Height of each item inside the menu.
* @param callback
* Callback function for when an item is used. @see fnMenuCallback
*
* @return A new Menu object.
*/
Menu *menu_init(MemZone *memory_pool, uint8_t total_items, uint8_t max_items, int top, int left,
uint8_t item_height, fnMenuCallback callback);
/**
* @brief Set the background for the Menu. Should only be called after calling
* 'menu_global_set_sprites' at least once in the game.
*
* @param menu
* Reference to the menu object.
* @param menu_width
* Width of the background.
*/
void menu_set_background(Menu *menu, int menu_width);
/**
* @brief Resets the items inside a menu. After calling this method you can add items to refill it.
*
* @param menu
* Reference to the menu object.
*/
void menu_reset_items(Menu *menu);
/**
* @brief Set the hand cursor for the Menu. Should only be called after calling
* 'menu_global_set_sprites' at least once in the game.
*
* @param menu
* Reference to the menu object.
* @param hand_position_x
* X position for the hand cursor.
* @param hand_position_y_offset
* Y position offset for the hand cursor.
*/
void menu_set_hand(Menu *menu, int hand_position_x, int hand_position_y_offset);
/**
* @brief Ticks the menu. Should be called every frame.
*
* @param menu
* Reference to the menu object.
* @param keys_down
* Reference to the controller data for the current frame. You can get this data using the
* 'get_keys_down()' function.
*
* @return Index of the item used, or '-1' is none.
*/
int menu_tick(Menu *menu, struct controller_data *keys_down);
/**
* @brief Add a new text item to the menu without any custom colors.
*
* @param menu
* Reference to the menu object.
* @param text
* Text that will be rendered.
* @param enabled
* If the item will start enabled.
* @param object
* Reference to a custom object that can be used later by the user.
*/
void menu_add_item(Menu *menu, char *text, bool enabled, void *object);
/**
* @brief Add a new image item to the menu.
*
* @param menu
* Reference to the menu object.
* @param sprite
* Sprite that will be used by this item.
* @param sprite_index
* Index inside the sprite.
* @param enabled
* If the item will start enabled.
* @param object
* Reference to a custom object that can be used later by the user.
*/
void menu_add_item_image(Menu *menu, sprite_t *sprite, int sprite_index, bool enabled,
void *object);
/**
* @brief Add a new text item to the menu with custom colors.
*
* @param menu
* Reference to the menu object.
* @param text
* Text that will be rendered.
* @param enabled
* If the item will start enabled.
* @param color_selected
* Color for this object when selected.
* @param color_enabled
* Color for this object when enabled and not selected.
* @param color_disabled
* Color for this object when disabled and not selected.
* @param object
* Reference to a custom object that can be used later by the user.
*/
void menu_add_item_colored(Menu *menu, char *text, bool enabled, uint32_t color_selected,
uint32_t color_enabled, uint32_t color_disabled, void *object);
/**
* @brief Render the menu.
*
* @param menu
* Reference to the menu object.
* @param disp
* The display context used in the game.
*/
void menu_render(Menu *menu, display_context_t disp);
/**
* @brief Allocates and initializes submenus for the menu.
*
* @param menu
* Reference to the menu object.
* @param memory_pool
* The memory pool to be used. If NULL will use malloc.
* @param total_submenus
* Total count of submenus that will be created.
* @param display_when_on_submenu
* If the menu will be displayed even when a submenu is active.
*/
void menu_init_submenus(Menu *menu, MemZone *memory_pool, uint8_t total_submenus,
bool display_when_on_submenu);
/**
* @brief Method that will render the borders of the menu.
*/
void menu_draw_background_borders(display_context_t disp, int top, int left, int bottom, int right);
/**
* @brief Method that will render the center of the menu.
*/
void menu_draw_background_center(display_context_t disp, int top, int left, int bottom, int right);
/**
* @brief Initializes the menu default colors
*/
void menu_global_init();
/**
* @brief Set the sprite used by the background menu
*
* @param menu_sprite
* Sprite that will be used. See `sample_assets/menu.png` for example.
* Order should be according to enum `MenuBackgroundSprite`.
* @param hand_sprite
* Sprite that will be used as the 'hand'.
* @param hand_sprite_offset
* Offset of the sprite (used by `graphics_draw_sprite_trans_stride`).
*/
void menu_global_set_sprites(sprite_t *menu_sprite, sprite_t *hand_sprite,
uint8_t hand_sprite_offset);
/**
* @brief Set the default colors for all menus when the item doesn't have any set.
*
* @param selected
* Color used when the item is the current selected one. Default is {0,0,255,255}
* @param enabled
* Color used when the item is enabled but not selected. Default is {255,255,255,255}
* @param disabled
* Color used when the item is disabled. Default is {100,100,255,255}
* @param background
* Color used for the background of the text. Default is {0,0,0,0}
* @param out_of_bounds
* Color used when the item is out of the bounds of the menu (when scrolling). Default is
* {0,0,0,255}
* @param menu_background
* Color used for the background. Due to 32 bits issue, we do not use the background from the
* sprite.
*/
void menu_global_set_default_colors(uint32_t selected, uint32_t enabled, uint32_t disabled,
uint32_t background, uint32_t out_of_bounds,
uint32_t menu_background);
#ifdef __cplusplus
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B