Lumenarium/src_v2/editor/lumenarium_editor_ui.h

246 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;
};
// 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