diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Gui.h |
initial commit
Diffstat (limited to 'src/Gui.h')
-rw-r--r-- | src/Gui.h | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/Gui.h b/src/Gui.h new file mode 100644 index 0000000..16e0c73 --- /dev/null +++ b/src/Gui.h @@ -0,0 +1,306 @@ +#ifndef CC_GUI_H +#define CC_GUI_H +#include "Core.h" +/* Describes and manages 2D GUI elements on screen. + Copyright 2014-2023 ClassiCube | Licensed under BSD-3 +*/ + +enum GuiAnchor { + ANCHOR_MIN, /* = offset */ + ANCHOR_CENTRE, /* = (axis/2) - (size/2) - offset; */ + ANCHOR_MAX, /* = axis - size - offset */ + ANCHOR_CENTRE_MIN, /* = (axis/2) + offset */ + ANCHOR_CENTRE_MAX /* = (axis/2) - size - offset */ +}; + +struct IGameComponent; +struct VertexTextured; +struct FontDesc; +struct Widget; +extern struct IGameComponent Gui_Component; + +CC_VAR extern struct _GuiData { + /* The list of screens currently shown. */ + struct Screen** Screens; + /* The number of screens currently shown. */ + int ScreensCount; + /* Whether vanilla Minecraft Classic gui texture is used. */ + cc_bool ClassicTexture; + /* Whether tab list is laid out like vanilla Minecraft Classic. */ + cc_bool ClassicTabList; + /* Whether menus are laid out like vanilla Minecraft Classic. */ + cc_bool ClassicMenu; + /* Whether classic-style chat screen is used */ + cc_bool ClassicChat; + /* Maximum number of visible chatlines on screen. Can be 0. */ + int Chatlines; + /* Whether clicking on a chatline inserts it into chat input. */ + cc_bool ClickableChat; + /* Whether pressing tab in chat input attempts to autocomplete player names. */ + cc_bool TabAutocomplete; + /* Whether FPS counter (and other info) is shown in top left. */ + cc_bool ShowFPS; + /* Whether classic-style inventory is used */ + cc_bool ClassicInventory; + float RawHotbarScale, RawChatScale, RawInventoryScale, RawCrosshairScale; + GfxResourceID GuiTex, GuiClassicTex, IconsTex, TouchTex; + int DefaultLines; + int _unused; + float RawTouchScale; + /* The highest priority screen that has grabbed input. */ + struct Screen* InputGrab; + /* Whether chat automatically scales based on window size. */ + cc_bool AutoScaleChat; + /* Whether the touch UI is currently being displayed */ + cc_bool TouchUI; +} Gui; + +#ifdef CC_BUILD_TOUCH +#define Gui_TouchUI Gui.TouchUI +#else +#define Gui_TouchUI false +#endif + +float Gui_Scale(float value); +float Gui_GetHotbarScale(void); +float Gui_GetInventoryScale(void); +float Gui_GetChatScale(void); +float Gui_GetCrosshairScale(void); + +CC_NOINLINE void Gui_MakeTitleFont(struct FontDesc* font); +CC_NOINLINE void Gui_MakeBodyFont(struct FontDesc* font); + +/* Functions for a Screen instance. */ +struct ScreenVTABLE { + /* Initialises persistent state. */ + void (*Init)(void* elem); + /* Updates this screen, called every frame just before Render(). */ + void (*Update)(void* elem, float delta); + /* Frees/releases persistent state. */ + void (*Free)(void* elem); + /* Draws this screen and its widgets on screen. */ + void (*Render)(void* elem, float delta); + /* Builds the vertex mesh for all the widgets in the screen. */ + void (*BuildMesh)(void* elem); + /* Returns non-zero if an input press is handled. */ + int (*HandlesInputDown)(void* elem, int key); + /* Called when an input key or button is released */ + void (*OnInputUp)(void* elem, int key); + /* Returns non-zero if a key character press is handled. */ + int (*HandlesKeyPress)(void* elem, char keyChar); + /* Returns non-zero if on-screen keyboard text changed is handled. */ + int (*HandlesTextChanged)(void* elem, const cc_string* str); + /* Returns non-zero if a pointer press is handled. */ + int (*HandlesPointerDown)(void* elem, int id, int x, int y); + /* Called when a pointer is released. */ + void (*OnPointerUp)(void* elem, int id, int x, int y); + /* Returns non-zero if a pointer movement is handled. */ + int (*HandlesPointerMove)(void* elem, int id, int x, int y); + /* Returns non-zero if a mouse wheel scroll is handled. */ + int (*HandlesMouseScroll)(void* elem, float delta); + /* Positions widgets on screen. Typically called on window resize. */ + void (*Layout)(void* elem); + /* Destroys graphics resources. (textures, vertex buffers, etc) */ + void (*ContextLost)(void* elem); + /* Allocates graphics resources. (textures, vertex buffers, etc) */ + void (*ContextRecreated)(void* elem); + /* Returns non-zero if a pad axis update is handled. */ + int (*HandlesPadAxis)(void* elem, int axis, float x, float y); +}; +#define Screen_Body const struct ScreenVTABLE* VTABLE; \ + cc_bool grabsInput; /* Whether this screen grabs input. Causes the cursor to become visible. */ \ + cc_bool blocksWorld; /* Whether this screen completely and opaquely covers the game world behind it. */ \ + cc_bool closable; /* Whether this screen is automatically closed when pressing Escape */ \ + cc_bool dirty; /* Whether this screens needs to have its mesh rebuilt. */ \ + int maxVertices; GfxResourceID vb; /* Vertex buffer storing the contents of the screen */ \ + struct Widget** widgets; int numWidgets; /* The widgets/individual elements in the screen */ \ + int selectedI, maxWidgets; + +/* Represents a container of widgets and other 2D elements. May cover entire window. */ +struct Screen { Screen_Body }; +/* Calls Widget_Render2 on each widget in the screen. */ +void Screen_Render2Widgets(void* screen, float delta); +void Screen_UpdateVb(void* screen); +struct VertexTextured* Screen_LockVb(void* screen); +int Screen_DoPointerDown(void* screen, int id, int x, int y); +int Screen_CalcDefaultMaxVertices(void* screen); + +/* Default mesh building implementation for a screen */ +/* (Locks vb, calls Widget_BuildMesh on each widget, then unlocks vb) */ +void Screen_BuildMesh(void* screen); +/* Default layout implementation for a screen */ +/* (Calls Widget_Layout on each widget) */ +void Screen_Layout(void* screen); +/* Default context lost implementation for a screen */ +/* (Deletes vb, then calls Elem_Free on each widget) */ +void Screen_ContextLost(void* screen); +/* Default input down implementation for a screen */ +/* (returns true if key is NOT a function key) */ +int Screen_InputDown(void* screen, int key); +/* Default input up implementation for a screen */ +/* (does nothing) */ +void Screen_InputUp(void* screen, int key); +/* Default pointer release implementation for a screen */ +/* (does nothing) */ +void Screen_PointerUp(void* s, int id, int x, int y); + + +typedef void (*Widget_LeftClick)(void* screen, void* widget); +union WidgetMeta { int val; void* ptr; }; + +struct WidgetVTABLE { + /* Draws this widget on-screen. */ + void (*Render)(void* elem, float delta); + /* Destroys allocated graphics resources. */ + void (*Free)(void* elem); + /* Positions this widget on-screen. */ + void (*Reposition)(void* elem); + /* Returns non-zero if an input press is handled. */ + int (*HandlesKeyDown)(void* elem, int key); + /* Called when an input key or button is released. */ + void (*OnInputUp)(void* elem, int key); + /* Returns non-zero if a mouse wheel scroll is handled. */ + int (*HandlesMouseScroll)(void* elem, float delta); + /* Returns non-zero if a pointer press is handled. */ + int (*HandlesPointerDown)(void* elem, int id, int x, int y); + /* Called when a pointer is released. */ + void (*OnPointerUp)(void* elem, int id, int x, int y); + /* Returns non-zero if a pointer movement is handled. */ + int (*HandlesPointerMove)(void* elem, int id, int x, int y); + /* Builds the mesh of vertices for this widget. */ + void (*BuildMesh)(void* elem, struct VertexTextured** vertices); + /* Draws this widget on-screen. */ + int (*Render2)(void* elem, int offset); + /* Returns the maximum number of vertices this widget may use */ + int (*GetMaxVertices)(void* elem); + /* Returns non-zero if a pad axis update is handled. */ + int (*HandlesPadAxis)(void* elem, int axis, float x, float y); +}; + +#define Widget_Body const struct WidgetVTABLE* VTABLE; \ + int x, y, width, height; /* Top left corner, and dimensions, of this widget */ \ + cc_bool active; /* Whether this widget is currently being moused over */ \ + cc_uint8 flags; /* Flags controlling the widget's interactability */ \ + cc_uint8 horAnchor, verAnchor; /* The reference point for when this widget is resized */ \ + int xOffset, yOffset; /* Offset from the reference point */ \ + Widget_LeftClick MenuClick; \ + union WidgetMeta meta; + +/* Whether a widget is prevented from being interacted with */ +#define WIDGET_FLAG_DISABLED 0x01 +/* Whether a widget can be selected via up/down */ +#define WIDGET_FLAG_SELECTABLE 0x02 +/* Whether for dual screen builds, this widget still appears on */ +/* the main game screen instead of the dedicated UI screen */ +#define WIDGET_FLAG_MAINSCREEN 0x04 +#ifdef CC_BUILD_DUALSCREEN + #define Window_UI Window_Alt +#else + #define Window_UI Window_Main +#endif + +/* Represents an individual 2D gui component. */ +struct Widget { Widget_Body }; +void Widget_SetLocation(void* widget, cc_uint8 horAnchor, cc_uint8 verAnchor, int xOffset, int yOffset); +/* Calculates where this widget should be on-screen based on its attributes. */ +/* These attributes are width/height, horAnchor/verAnchor, xOffset/yOffset */ +void Widget_CalcPosition(void* widget); +/* Resets Widget struct fields to 0/NULL (except VTABLE) */ +void Widget_Reset(void* widget); +/* Returns non-zero if the given point is located within the bounds of the widget. */ +int Widget_Contains(void* widget, int x, int y); +/* Sets whether the widget is prevented from being interacted with */ +void Widget_SetDisabled(void* widget, int disabled); + + +/* Higher priority handles input first and draws on top */ +/* NOTE: Values are 5 apart to allow plugins to insert custom screens */ +enum GuiPriority { + GUI_PRIORITY_DISCONNECT = 60, + GUI_PRIORITY_OLDLOADING = 55, + GUI_PRIORITY_MENUINPUT = 57, + GUI_PRIORITY_MENU = 50, + GUI_PRIORITY_TOUCHMORE = 45, + GUI_PRIORITY_URLWARNING = 40, + GUI_PRIORITY_TEXPACK = 35, + GUI_PRIORITY_TEXIDS = 30, + GUI_PRIORITY_TOUCH = 25, + GUI_PRIORITY_INVENTORY = 20, + GUI_PRIORITY_TABLIST = 17, + GUI_PRIORITY_CHAT = 15, + GUI_PRIORITY_HUD = 10, + GUI_PRIORITY_LOADING = 5 +}; + +#define GUI_MAX_SCREENS 10 +extern struct Screen* Gui_Screens[GUI_MAX_SCREENS]; + +/* Calculates position of an element on a particular axis */ +/* For example, to calculate X position of a text widget on screen */ +int Gui_CalcPos(cc_uint8 anchor, int offset, int size, int axisLen); +/* Returns non-zero if the given rectangle contains the given point. */ +int Gui_Contains(int recX, int recY, int width, int height, int x, int y); +/* Returns non-zero if one or more pointers lie within the given rectangle. */ +int Gui_ContainsPointers(int x, int y, int width, int height); +/* Shows HUD and Status screens. */ +void Gui_ShowDefault(void); +#ifdef CC_BUILD_TOUCH +/* Sets whether touch UI should be displayed or not */ +void Gui_SetTouchUI(cc_bool enabled); +#endif + +/* (internal) Removes the screen from the screens list. */ +/* NOTE: This does NOT perform the usual 'screens changed' behaviour. */ +void Gui_RemoveCore(struct Screen* s); +/* Removes the screen from the screens list. */ +CC_API void Gui_Remove(struct Screen* screen); +/* Inserts a screen into the screen lists with the given priority. */ +/* NOTE: If there is an existing screen with the same priority, it is removed. */ +CC_API void Gui_Add(struct Screen* screen, int priority); + +/* Returns highest priority screen that has grabbed input. */ +CC_API struct Screen* Gui_GetInputGrab(void); +/* Returns highest priority screen that blocks world rendering. */ +struct Screen* Gui_GetBlocksWorld(void); +/* Returns highest priority screen that is closable. */ +struct Screen* Gui_GetClosable(void); +/* Returns screen with the given priority */ +CC_API struct Screen* Gui_GetScreen(int priority); +void Gui_UpdateInputGrab(void); +void Gui_ShowPauseMenu(void); + +void Gui_LayoutAll(void); +void Gui_RefreshAll(void); +void Gui_Refresh(struct Screen* s); +void Gui_RenderGui(float delta); + +#define TEXTATLAS_MAX_WIDTHS 16 +struct TextAtlas { + struct Texture tex; + int offset, curX; + float uScale; + short widths[TEXTATLAS_MAX_WIDTHS]; + short offsets[TEXTATLAS_MAX_WIDTHS]; +}; +void TextAtlas_Make(struct TextAtlas* atlas, const cc_string* chars, struct FontDesc* font, const cc_string* prefix); +void TextAtlas_Free(struct TextAtlas* atlas); +void TextAtlas_Add(struct TextAtlas* atlas, int charI, struct VertexTextured** vertices); +void TextAtlas_AddInt(struct TextAtlas* atlas, int value, struct VertexTextured** vertices); + +#define Elem_Render(elem, delta) (elem)->VTABLE->Render(elem, delta) +#define Elem_Free(elem) (elem)->VTABLE->Free(elem) +#define Elem_HandlesKeyPress(elem, key) (elem)->VTABLE->HandlesKeyPress(elem, key) +#define Elem_HandlesKeyDown(elem, key) (elem)->VTABLE->HandlesKeyDown(elem, key) +#define Elem_OnInputUp(elem, key) (elem)->VTABLE->OnInputUp(elem, key) + +#define Elem_HandlesMouseScroll(elem, delta) (elem)->VTABLE->HandlesMouseScroll(elem, delta) +#define Elem_HandlesPointerDown(elem, id, x, y) (elem)->VTABLE->HandlesPointerDown(elem, id, x, y) +#define Elem_OnPointerUp(elem, id, x, y) (elem)->VTABLE->OnPointerUp(elem, id, x, y) +#define Elem_HandlesPointerMove(elem, id, x, y) (elem)->VTABLE->HandlesPointerMove(elem, id, x, y) + +#define Elem_HandlesPadAxis(elem, axis, x, y) (elem)->VTABLE->HandlesPadAxis(elem, axis, x, y) + +#define Widget_BuildMesh(widget, vertices) (widget)->VTABLE->BuildMesh(widget, vertices) +#define Widget_Render2(widget, offset) (widget)->VTABLE->Render2(widget, offset) +#define Widget_Layout(widget) (widget)->VTABLE->Reposition(widget) +#endif |