JacksEscape/ui.h

148 lines
4.8 KiB
C
Raw Normal View History

2024-04-23 16:34:01 +08:00
#pragma once
#include "types.h"
#include "util/vector.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _App App;
typedef enum {
ui_Running,
ui_Paused,
ui_TitleMenu,
2024-04-24 21:30:28 +08:00
ui_SceneSelect,
ui_Options,
ui_InterMission,
ui_Leaderboards,
2024-04-23 16:34:01 +08:00
ui_StateCount // Keep at last
2024-04-24 21:30:28 +08:00
} ui_State;
extern const char *ui_StateTitle[ui_StateCount];
2024-04-23 16:34:01 +08:00
// Forward declarations
typedef struct _System_UI System_UI;
// a Part of the UI.
2024-04-24 21:30:28 +08:00
typedef struct _ui_Part {
Box2 box; // bounding box of the UI element
float progress; // hover process, from 0 to 1
bool hovered; // Whether the part is hovered
uintptr_t user; // user data
void (*draw)(System_UI *sys, struct _ui_Part *part, uintptr_t user); // called when the UI is to be drawn
void (*update)(System_UI *sys, struct _ui_Part *part, uintptr_t user, Duration deltatime); // called when the element is to be updated
void (*free)(System_UI *sys, struct _ui_Part *part, uintptr_t user); // called when the element is to be deleted, dont free part!
2024-04-23 16:34:01 +08:00
} ui_Part;
// UI system with its own state machine.
typedef struct _System_UI {
App *super;
2024-04-24 21:30:28 +08:00
vector_Vector *parts[ui_StateCount]; // A vector of ui_Parts
vector_Vector *state; // A stack of ui_States
Box2 bg, bg_target;
2024-04-23 16:34:01 +08:00
} System_UI;
2024-04-24 21:30:28 +08:00
System_UI *ui_NewSystem(App *super);
void ui_DeleteSystem(System_UI *sys);
// Clears and refills every menu with its widgets
void ui_RebuildUI(System_UI *sys);
void ui_PushPart(System_UI *sys, ui_State layer, ui_Part part);
void ui_Advance(System_UI *sys, Duration deltaTime);
void ui_Render(System_UI *sys);
void ui_PushState(System_UI *sys, ui_State push_state);
void ui_PopState(System_UI *sys);
2024-04-24 21:30:28 +08:00
ui_State ui_CurrentState(System_UI *sys);
// Called when the level is finished
// If next_level is NULL, there are no next level and the
// button returns to title screen
void ui_EnterIntermission(System_UI *sys, const char *next_level);
2024-04-24 22:23:01 +08:00
#define UI_PADDING (16)
2024-04-24 21:30:28 +08:00
#define UI_BACKGROUND (0)
#define UI_BACKGROUND_FADE_MOVE_SPEED (20.0)
#define UI_BUTTON_HOVER_SPEED (5.0)
#define UI_BUTTON_BACKGROUND (RGB(50, 50, 50))
#define UI_BUTTON_HOVERED (RGB(75, 75, 75))
#define UI_BUTTON_CLICKED (RGB(90, 90, 90))
typedef void (*ui_ActionCallback)(System_UI *sys, ui_Part *part, uintptr_t data);
// An Action to pop the UI state stack once
void ui_Action_PopState(System_UI *sys, ui_Part *part, uintptr_t data);
// An Action to push the state, casted directly from data
void ui_Action_PushState(System_UI *sys, ui_Part *part, uintptr_t data);
// Allocated & passed in as user data for ui part
typedef struct _ui_Button {
ui_ActionCallback callback;
uintptr_t callback_data;
uint32_t bg, bg_hover, clicked;
char *label; // Allocated & copied
bool left_aligned;
} ui_Button;
ui_Part ui_Button_New(Box2 box, const char *label, ui_ActionCallback callback, uintptr_t data);
ui_Part ui_Button_NewLeftAligned(Box2 box, const char *label, ui_ActionCallback callback, uintptr_t data);
// ui_Part ui_Button_NewColored(Box2 box, const char *label, uint32_t bg, uint32_t hover, uint32_t clicked, ui_ActionCallback callback, uintptr_t data);
2024-04-23 16:34:01 +08:00
typedef struct {
char *label; // Allocated & copied, NULL means no label
int align; // <0: left aligned; ==0: center aligned; >0: right aligned
} ui_Label;
ui_Part ui_Label_New(Box2 box, const char *label, int alignment);
void ui_Label_SetLabel(ui_Part *part, const char *label);
// Creates a new box fill with the given color
ui_Part ui_Fill_New(Box2 box, uint32_t color);
// Box organizer
typedef struct {
vector_Vector *rows; // vector of vector_Vector* of Box2
vector_Vector *row_counts; // vector of Ints
double width; // Total width, excluding external padding
double line_height; // Line height
Vec2 position; // Position of the entire bounding box on screen
Vec2 pivot; // Pivot or Origin of the position, [0, 1]
} ui_BoxBuilder;
#define UI_BOXBUILDER_DEFAULT_LINEHEIGHT (48)
#define UI_BOXBUILDER_DEFAULT_WIDTH (400)
#define UI_BOXBUILDER_DEFAULT_PIVOT_X (0.5)
#define UI_BOXBUILDER_DEFAULT_PIVOT_Y (0.0)
ui_BoxBuilder *ui_BoxBuilder_New();
void ui_BoxBuilder_Delete(ui_BoxBuilder *builder);
// Set that this row should have this many columns
void ui_BoxBuilder_SetCount(ui_BoxBuilder *builder, int row, int num_cols);
// Assemble everything
void ui_BoxBuilder_Assemble(ui_BoxBuilder *builder);
// Every number starts from 1
Box2 ui_BoxBuilder_At(ui_BoxBuilder *builder, int row, int col);
2024-04-23 16:34:01 +08:00
#ifdef __cplusplus
}
#endif