248 lines
5.3 KiB
C
248 lines
5.3 KiB
C
/* date = March 28th 2022 10:52 pm */
|
|
|
|
#ifndef LUMENARIUM_UI_H
|
|
#define LUMENARIUM_UI_H
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// Interface
|
|
|
|
typedef struct UI_Vertex UI_Vertex;
|
|
struct UI_Vertex
|
|
{
|
|
v4 pos;
|
|
v2 uv;
|
|
v4 color;
|
|
};
|
|
|
|
#define UI_WIDGET_ID_VALID_BIT 1 << 31
|
|
|
|
typedef union UI_Widget_Id UI_Widget_Id;
|
|
union UI_Widget_Id
|
|
{
|
|
// equality of widget id's only relies on the value field
|
|
// which is a hash of the widget's string
|
|
u32 value;
|
|
|
|
// this struct tracks the index of the widget only to be able
|
|
// to override next hot in cases where an earlier element became
|
|
// next hot that is in the same location as the current one
|
|
u32 index;
|
|
};
|
|
|
|
typedef u32 UI_Widget_Style_Flags;
|
|
enum
|
|
{
|
|
UIWidgetStyle_None = 0,
|
|
UIWidgetStyle_Bg = 1 << 0,
|
|
UIWidgetStyle_TextClip = 1 << 1,
|
|
UIWidgetStyle_TextWrap = 1 << 2,
|
|
UIWidgetStyle_Outline = 1 << 3,
|
|
UIWidgetStyle_MouseClick = 1 << 4,
|
|
UIWidgetStyle_MouseDragH = 1 << 5,
|
|
UIWidgetStyle_MouseDragV = 1 << 6,
|
|
UIWidgetStyle_FillH = 1 << 7,
|
|
UIWidgetStyle_FillV = 1 << 8,
|
|
UIWidgetStyle_LineInsteadOfFill = 1 << 9,
|
|
};
|
|
|
|
// akin to a css class, could be used to style multiple
|
|
// elements
|
|
typedef struct UI_Widget_Style UI_Widget_Style;
|
|
struct UI_Widget_Style
|
|
{
|
|
UI_Widget_Style_Flags flags;
|
|
v4 color_bg;
|
|
v4 color_fg;
|
|
u32 sprite;
|
|
};
|
|
|
|
// combination of style info and per-instance data
|
|
typedef struct UI_Widget_Desc UI_Widget_Desc;
|
|
struct UI_Widget_Desc
|
|
{
|
|
UI_Widget_Style style;
|
|
v2 fill_pct;
|
|
String string;
|
|
v2 p_min;
|
|
v2 p_max;
|
|
};
|
|
|
|
typedef struct UI_Widget UI_Widget;
|
|
struct UI_Widget
|
|
{
|
|
UI_Widget_Id id;
|
|
UI_Widget_Desc desc;
|
|
|
|
UI_Widget* parent;
|
|
UI_Widget* next;
|
|
UI_Widget* child_first;
|
|
UI_Widget* child_last;
|
|
};
|
|
|
|
typedef u32 UI_Widget_Result_Flags;
|
|
enum
|
|
{
|
|
UIWidgetResult_None = 0,
|
|
UIWidgetResult_MouseLeft_IsDown = 1,
|
|
UIWidgetResult_MouseLeft_WentUp = 2,
|
|
};
|
|
|
|
typedef struct UI_Widget_Result UI_Widget_Result;
|
|
struct UI_Widget_Result
|
|
{
|
|
UI_Widget_Id id;
|
|
UI_Widget_Result_Flags flags;
|
|
v2 drag;
|
|
};
|
|
|
|
typedef u32 UI_Widget_Kind;
|
|
enum
|
|
{
|
|
UIWidget_Text,
|
|
|
|
// Buttons
|
|
UIWidget_Button,
|
|
UIWidget_Toggle,
|
|
UIWidget_Menu,
|
|
UIWidget_Dropdown,
|
|
|
|
// Sliders
|
|
UIWidget_HSlider,
|
|
UIWidget_VSlider,
|
|
UIWidget_HScroll,
|
|
UIWidget_VScroll,
|
|
|
|
// Panels
|
|
UIWidget_Window,
|
|
|
|
UIWidget_Count,
|
|
};
|
|
|
|
typedef struct UI_Style_Sheet UI_Style_Sheet;
|
|
struct UI_Style_Sheet
|
|
{
|
|
UI_Widget_Style styles[UIWidget_Count];
|
|
};
|
|
|
|
typedef struct UI_Widget_State UI_Widget_State;
|
|
struct UI_Widget_State
|
|
{
|
|
v2 scroll;
|
|
};
|
|
|
|
typedef struct UI_Widget_Pool UI_Widget_Pool;
|
|
struct UI_Widget_Pool
|
|
{
|
|
UI_Widget* free;
|
|
u32 free_cap;
|
|
u32 free_len;
|
|
|
|
UI_Widget* root;
|
|
UI_Widget* active_parent;
|
|
|
|
UI_Widget_State* states;
|
|
u32* states_hash;
|
|
u32 states_cap;
|
|
};
|
|
|
|
typedef u8 UI_Layout_Mode;
|
|
enum
|
|
{
|
|
// each element takes up a whole row
|
|
UILayout_Columns,
|
|
|
|
// each element takes up one column in the row. If you overflow,
|
|
// the layout manager overflows to the next row
|
|
UILayout_Rows,
|
|
};
|
|
|
|
typedef struct UI_Layout UI_Layout;
|
|
struct UI_Layout
|
|
{
|
|
UI_Layout_Mode mode;
|
|
UI_Layout* parent;
|
|
|
|
v2 bounds_min;
|
|
v2 bounds_max;
|
|
r32 row_height;
|
|
r32 row_gap;
|
|
r32 col_gap;
|
|
v2 at;
|
|
u32 cols;
|
|
};
|
|
|
|
typedef struct UI_Layout_Bounds UI_Layout_Bounds;
|
|
struct UI_Layout_Bounds
|
|
{
|
|
v2 min;
|
|
v2 max;
|
|
};
|
|
|
|
typedef void UI_Draw_Panel_Cb(u8* user_data, BSP_Node_Id id, BSP_Node node, BSP_Area area);
|
|
|
|
typedef struct UI UI;
|
|
struct UI
|
|
{
|
|
Geo_Quad_Buffer_Builder geo;
|
|
|
|
Texture_Atlas atlas;
|
|
r32 font_ascent, font_descent, font_line_gap, font_space_width;
|
|
r32 font_texture_scale;
|
|
|
|
UI_Widget_Pool widgets;
|
|
UI_Style_Sheet* style_sheet;
|
|
|
|
UI_Widget_Id widget_next_hot;
|
|
UI_Widget_Id widget_hot;
|
|
|
|
UI_Layout* layout;
|
|
|
|
BSP panels;
|
|
UI_Draw_Panel_Cb* draw_panel_cb;
|
|
u8* draw_panel_cb_data;
|
|
|
|
// frames since these values were set
|
|
u16 widget_next_hot_frames;
|
|
u16 widget_hot_frames;
|
|
|
|
Input_State* input;
|
|
|
|
m44 proj;
|
|
Shader shader;
|
|
Texture atlas_texture;
|
|
Geometry_Buffer per_frame_buffer;
|
|
|
|
Allocator* per_frame;
|
|
};
|
|
|
|
// Interface
|
|
|
|
internal UI ui_create();
|
|
internal void ui_quad_push(UI* ui, v3 pmin, v3 pmax, v2 tmin, v2 tmax, v4 c);
|
|
internal void ui_sprite_register(UI* ui, u8* pixels, u32 w, u32 h, u32 id);
|
|
internal void ui_sprite_push_color(UI* ui, v3 pmin, v3 pmax, u32 id, v4 color);
|
|
internal void ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id);
|
|
internal v3 ui_sprite_char_push(UI* ui, v2 at, u32 codepoint, v4 color);
|
|
internal void ui_draw(UI* ui);
|
|
|
|
// Widgets
|
|
|
|
internal void ui_create_default_style_sheet();
|
|
|
|
internal UI_Widget_Id ui_widget_id_create(String string, u32 index_in_parent);
|
|
internal bool ui_widget_id_equals(UI_Widget_Id a, UI_Widget_Id b);
|
|
internal bool ui_widget_id_is_valid(UI_Widget_Id h);
|
|
|
|
internal void ui_widget_next_hot_set(UI* ui, UI_Widget* w);
|
|
internal void ui_widget_hot_set(UI* ui, UI_Widget* w);
|
|
|
|
internal UI_Widget* ui_widget_pool_push(UI_Widget_Pool* pool, String string);
|
|
internal void ui_widget_pool_pop(UI_Widget_Pool* pool);
|
|
|
|
internal UI_Widget_Result ui_widget_push(UI* ui, UI_Widget_Desc desc);
|
|
internal void ui_widget_pop(UI* ui, UI_Widget_Id widget_id);
|
|
|
|
internal r32 ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_step);
|
|
|
|
#endif //LUMENARIUM_UI_H
|