182 lines
5.4 KiB
C
182 lines
5.4 KiB
C
#ifndef UI_H
|
|
#define UI_H
|
|
|
|
#include "platform.h"
|
|
#include "render.h"
|
|
#include "../core.h"
|
|
#include "GLFW/glfw3.h"
|
|
|
|
enum UI_Flag {
|
|
UI_Flag_WidthGrow=1<<0, // Default is fixed
|
|
UI_Flag_HeightGrow=1<<1, // Default is fixed
|
|
UI_Flag_Vertical=1<<2, // Default is horizontal
|
|
UI_Flag_3DScene=1<<3,
|
|
UI_Flag_Center=1<<4,
|
|
UI_Flag_Ignore=1<<7, // For optional parameters
|
|
UI_Flag_Pos_Absolute=1<<8, // Default is relative
|
|
// ..
|
|
UI_Flag_COUNT,
|
|
};
|
|
|
|
typedef struct UI_Padding UI_Padding;
|
|
struct UI_Padding {
|
|
real32 top;
|
|
real32 right;
|
|
real32 bottom;
|
|
real32 left;
|
|
};
|
|
|
|
enum UI_Cursor {
|
|
UI_Cursor_Arrow=1<<0,
|
|
UI_Cursor_Pointer=1<<1,
|
|
UI_Cursor_Forbidden=1<<2,
|
|
UI_Cursor_Count=1<<3,
|
|
};
|
|
|
|
enum UI_TxtAlign {
|
|
UI_TxtAlign_Left=1<<0, // Default
|
|
UI_TxtAlign_Center=1<<1,
|
|
UI_TxtAlign_Right=1<<2,
|
|
};
|
|
|
|
typedef struct UI_RectStr UI_RectStr;
|
|
struct UI_RectStr {
|
|
string s;
|
|
real32 xOffset;
|
|
real32 yOffset;
|
|
real32 lineHeight;
|
|
real32 fontSize;
|
|
Vec4 color;
|
|
enum UI_TxtAlign alignment;
|
|
};
|
|
|
|
typedef struct UI_Rect UI_Rect;
|
|
struct UI_Rect {
|
|
enum UI_Flag flags;
|
|
|
|
int32 parent;
|
|
int32 firstChild;
|
|
int32 lastChild;
|
|
int32 nextSibling;
|
|
|
|
real32 xOffset;
|
|
real32 yOffset;
|
|
|
|
real32 width;
|
|
real32 minWidth;
|
|
real32 maxWidth;
|
|
|
|
real32 height;
|
|
real32 minHeight;
|
|
real32 maxHeight;
|
|
|
|
real32 borderRadius;
|
|
real32 borderThickness;
|
|
|
|
Vec4 color;
|
|
Vec4 borderColor;
|
|
|
|
UI_Padding padding;
|
|
real32 childGap;
|
|
|
|
real32 x;
|
|
real32 y;
|
|
real32 resolvedWidth;
|
|
real32 resolvedHeight;
|
|
|
|
UI_RectStr *stringData;
|
|
/**
|
|
* Inherited from parent to propagate attributes. Actual string is ignored, only used for filling out defaults in
|
|
* the next stringData pointer that is set.
|
|
* This pointer is always set, as the global UI context will set it on the root node if it does not present its own
|
|
* text data.
|
|
*/
|
|
UI_RectStr *inheritedTextAttr;
|
|
};
|
|
DefineList(UI_Rect, UI_Rect);
|
|
|
|
typedef struct UI_Context UI_Context;
|
|
struct UI_Context {
|
|
Arena *arena;
|
|
UI_RectList prevRects;
|
|
UI_RectList rects;
|
|
int32 hotNode;
|
|
int32 hoveredNode;
|
|
int32 prevHoveredNode;
|
|
int32 scene3DHandle;
|
|
int32 prevHotNode;
|
|
Renderer *renderer;
|
|
|
|
OS_Input *prevInput;
|
|
OS_Input *input;
|
|
enum UI_Cursor cursorType;
|
|
|
|
int32 rootRect;
|
|
int32 currRect;
|
|
};
|
|
|
|
void ui_begin(UI_Context *ui);
|
|
void ui_end(UI_Context *ui);
|
|
UI_Context ui_initContext(Arena *arena, Renderer *renderer);
|
|
void ui_resolve();
|
|
void ui_rect(UI_Context *ui, UI_Rect rect);
|
|
void ui_placeText(UI_Context *ui, UI_RectStr strData);
|
|
void ui_attachTextAttr(UI_Context *ui, UI_Rect *rect, UI_RectStr strData);
|
|
void ui_openElement(UI_Context *ui, UI_Rect rect);
|
|
void ui_closeElement(UI_Context *ui);
|
|
|
|
bool ui_CheckboxRect(UI_Context *ui, bool *value, UI_Rect rect);
|
|
bool ui_Button(UI_Context *ui, UI_Rect rect, UI_RectStr textAttr);
|
|
bool ui_ButtonWithHover(UI_Context *ui, UI_Rect rect, UI_Rect hovered, UI_RectStr textAttr);
|
|
UI_Rect ui_HoverRect(UI_Context *ui, UI_Rect rect, UI_Rect hovered);
|
|
|
|
extern UI_Context *__UI_current_ctx__;
|
|
|
|
#if 0
|
|
#define UI_DEBUG_ATTR .borderColor=COLOR_RED, .borderThickness=1,
|
|
#else
|
|
#define UI_DEBUG_ATTR
|
|
#endif
|
|
|
|
#define UI_Pass(ui) DeferLoop(ui_begin((ui)), ui_end((ui)))
|
|
#define UI_PadUniform(padding) ((UI_Padding){ (padding), (padding), (padding), (padding) })
|
|
#define UI_NextID() ((__UI_current_ctx__)->rects.length)
|
|
|
|
#define UI(...)\
|
|
/** Place a UI_Rect defined in-place in the current position in the UI tree */\
|
|
DeferLoop(ui_openElement((__UI_current_ctx__), UI_RectAttr(__VA_ARGS__)), ui_closeElement((__UI_current_ctx__)))
|
|
|
|
#define UI_RectAttr(...)\
|
|
/** Generate a UI_Rect to be passed as a value */\
|
|
((UI_Rect){UI_DEBUG_ATTR .minHeight=-1, .minWidth=-1, .width=-1, .height=-1, .inheritedTextAttr=(__UI_current_ctx__->rects.data[(__UI_current_ctx__)->currRect].inheritedTextAttr), __VA_ARGS__})
|
|
|
|
#define UI_FromRect(rect)\
|
|
/** Place a UI_Rect in the current position in the UI tree, as defined by an existing value */\
|
|
DeferLoop(ui_openElement((__UI_current_ctx__), (rect)), ui_closeElement((__UI_current_ctx__)))
|
|
|
|
#define UI_TxtAttrS(str, ...)\
|
|
/** Generate UI text to be used as a value */\
|
|
((UI_RectStr){ .color={-1,-1,-1,-1}, .alignment=-1, .xOffset=0, .yOffset=0, .fontSize=-1, .lineHeight=-1, .s=(str), __VA_ARGS__ })
|
|
|
|
#define UI_TxtAttr(...)\
|
|
/** Generate UI text to be used as a value, attributes only, no string */\
|
|
((UI_RectStr){ .color={-1,-1,-1,-1}, .alignment=-1, .xOffset=0, .yOffset=0, .fontSize=-1, .lineHeight=-1, .s=((string){.str=NULL,.length=0}), __VA_ARGS__ })
|
|
|
|
#define UI_Txt(str, ...)\
|
|
/** Place UI text in the current position in the UI tree. Attaches to the current UI_Rect */\
|
|
(ui_placeText((__UI_current_ctx__), (UI_TxtAttrS(str, __VA_ARGS__))))
|
|
|
|
#define UI_AttachTxtAttr(rect, txtAttr)\
|
|
/** Attach "phantom" text to the specified rect in order to set its heritable attributes for subsequent text in the UI subtrees */\
|
|
(ui_attachTextAttr((__UI_current_ctx__), (rect), (txtAttr)))
|
|
|
|
#define UI_SetTxtAttr(...)\
|
|
/** Attach "phantom" text to the current rect in order to set its heritable attributes for subsequent text in the UI subtrees */\
|
|
(ui_placeText((__UI_current_ctx__), (UI_TxtAttr(__VA_ARGS__))))
|
|
|
|
#define UI_TxtSeg(str, ...)\
|
|
/** Place a text fragment in its own box (useful for placing many text fragments in a row */\
|
|
UI() (UI_Txt((str), __VA_ARGS__))
|
|
|
|
#endif
|