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/Widgets.h |
initial commit
Diffstat (limited to 'src/Widgets.h')
-rw-r--r-- | src/Widgets.h | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/Widgets.h b/src/Widgets.h new file mode 100644 index 0000000..0e57dab --- /dev/null +++ b/src/Widgets.h @@ -0,0 +1,319 @@ +#ifndef CC_WIDGETS_H +#define CC_WIDGETS_H +#include "Gui.h" +#include "BlockID.h" +#include "Constants.h" +#include "Entity.h" +#include "Inventory.h" +#include "IsometricDrawer.h" +/* Contains all 2D widget implementations. + Copyright 2014-2023 ClassiCube | Licensed under BSD-3 +*/ +struct FontDesc; + +/* A text label. */ +struct TextWidget { + Widget_Body + struct Texture tex; + PackedCol color; +}; +#define TEXTWIDGET_MAX 4 + +/* Initialises a text widget. */ +CC_NOINLINE void TextWidget_Init(struct TextWidget* w); +/* Initialises then adds a text widget. */ +CC_NOINLINE void TextWidget_Add(void* screen, struct TextWidget* w); +/* Draws the given text into a texture, then updates the position and size of this widget. */ +CC_NOINLINE void TextWidget_Set(struct TextWidget* w, const cc_string* text, struct FontDesc* font); +/* Shorthand for TextWidget_Set using String_FromReadonly */ +CC_NOINLINE void TextWidget_SetConst(struct TextWidget* w, const char* text, struct FontDesc* font); + + +typedef void (*Button_Get)(cc_string* raw); +typedef void (*Button_Set)(const cc_string* raw); +/* A labelled button that can be clicked on. */ +struct ButtonWidget { + Widget_Body + struct Texture tex; + PackedCol color; + int minWidth, minHeight; + const char* optName; + Button_Get GetValue; + Button_Set SetValue; +}; +#define BUTTONWIDGET_MAX 12 + +/* Initialises a button widget. */ +CC_NOINLINE void ButtonWidget_Init(struct ButtonWidget* w, int minWidth, Widget_LeftClick onClick); +/* Initialises then adds a button widget. */ +CC_NOINLINE void ButtonWidget_Add(void* screen, struct ButtonWidget* w, int minWidth, Widget_LeftClick onClick); +/* Draws the given text into a texture, then updates the position and size of this widget. */ +CC_NOINLINE void ButtonWidget_Set(struct ButtonWidget* w, const cc_string* text, struct FontDesc* font); +/* Shorthand for ButtonWidget_Set using String_FromReadonly */ +CC_NOINLINE void ButtonWidget_SetConst(struct ButtonWidget* w, const char* text, struct FontDesc* font); + +/* Clickable and draggable scrollbar. */ +struct ScrollbarWidget { + Widget_Body + int topRow, rowsTotal, rowsVisible; + float scrollingAcc; + int dragOffset; + int draggingId, padding; + int borderX, borderY; + int nubsWidth, offsets[3]; +}; +/* Resets state of the given scrollbar widget to default. */ +CC_NOINLINE void ScrollbarWidget_Create(struct ScrollbarWidget* w, int width); + +#define HOTBAR_CORE_VERTICES (INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES) +/* A row of blocks with a background. */ +struct HotbarWidget { + Widget_Body + struct Texture selTex, backTex; + float slotWidth, selWidth; + float slotXOffset, elemSize; + float scrollAcc, scale; + cc_bool altHandled; + struct Texture ellipsisTex; + int state[HOTBAR_CORE_VERTICES / 4]; + int verticesCount; + int touchId[HOTBAR_MAX_INDEX]; + float touchTime[HOTBAR_MAX_INDEX]; +}; +#define HOTBAR_MAX_VERTICES (4 + 4 + HOTBAR_CORE_VERTICES) + +/* Resets state of the given hotbar widget to default. */ +CC_NOINLINE void HotbarWidget_Create(struct HotbarWidget* w); +CC_NOINLINE void HotbarWidget_SetFont(struct HotbarWidget* w, struct FontDesc* font); +CC_NOINLINE void HotbarWidget_Update(struct HotbarWidget* w, float delta); + +#define TABLE_MAX_VERTICES (8 * 10 * ISOMETRICDRAWER_MAXVERTICES) +/* A table of blocks. */ +struct TableWidget { + Widget_Body + int blocksCount, blocksPerRow; + int rowsTotal, rowsVisible; + int lastCreatedIndex; + int selectedIndex, cellSizeX, cellSizeY; + float normBlockSize, selBlockSize; + GfxResourceID vb; + cc_bool pendingClose, everCreated; + float scale; + float padXAcc, padYAcc; + + BlockID blocks[BLOCK_COUNT]; + struct ScrollbarWidget scroll; + int lastX, lastY, paddingX; + int paddingL, paddingR, paddingT, paddingB; + void (*UpdateTitle)(BlockID block); + + int state[TABLE_MAX_VERTICES / 4]; + int verticesCount; +}; + +CC_NOINLINE void TableWidget_Add(void* screen, struct TableWidget* w, int sbWidth); +/* Sets the selected block in the table to the given block. */ +/* Also adjusts scrollbar and moves cursor to be over the given block. */ +CC_NOINLINE void TableWidget_SetToBlock(struct TableWidget* w, BlockID block); +CC_NOINLINE void TableWidget_SetToIndex(struct TableWidget* w, int index); +CC_NOINLINE void TableWidget_RecreateBlocks(struct TableWidget* w); +CC_NOINLINE void TableWidget_OnInventoryChanged(struct TableWidget* w); +CC_NOINLINE void TableWidget_RecreateTitle(struct TableWidget* w, cc_bool force); + + +#define INPUTWIDGET_MAX_LINES 3 +#define INPUTWIDGET_LEN STRING_SIZE +struct InputWidget { + Widget_Body + struct FontDesc* font; + int (*GetMaxLines)(void); + void (*RemakeTexture)(void* elem); /* Remakes the raw texture containing all the chat lines. Also updates dimensions. */ + void (*OnPressedEnter)(void* elem); /* Invoked when the user presses enter. */ + cc_bool (*AllowedChar)(void* elem, char c); + void (*OnTextChanged)(void* elem); /* Callback invoked whenever text changes. */ + + cc_string text; /* The actual raw text */ + cc_string lines[INPUTWIDGET_MAX_LINES]; /* text of each line after word wrapping */ + int lineWidths[INPUTWIDGET_MAX_LINES]; /* Width of each line in pixels */ + int lineHeight; /* Height of a line in pixels */ + struct Texture inputTex; + int prefixWidth; + cc_bool convertPercents; + + cc_uint8 padding; + cc_bool showCaret; + int caretWidth; + int caretX, caretY; /* Coordinates of caret in lines */ + int caretPos; /* Position of caret, -1 for at end of string */ + int caretOffset; + PackedCol caretCol; + struct Texture caretTex; + float caretAccumulator; +}; + +/* Removes all characters and then deletes the input texture. */ +CC_NOINLINE void InputWidget_Clear(struct InputWidget* w); +/* Tries appending all characters from the given string, then update the input texture. */ +CC_NOINLINE void InputWidget_AppendText(struct InputWidget* w, const cc_string* text); +/* Tries appending the given character, then updates the input texture. */ +CC_NOINLINE void InputWidget_Append(struct InputWidget* w, char c); +/* Redraws text and recalculates associated state. */ +/* Also calls OnscreenKeyboard_SetText with the text in the input widget. */ +/* This way native text input state stays synchronised with the input widget. */ +/* (e.g. may only accept numerical input, so 'c' gets stripped from str) */ +CC_NOINLINE void InputWidget_UpdateText(struct InputWidget* w); +/* Shorthand for InputWidget_Clear followed by InputWidget_AppendText, */ +/* then calls OnscreenKeyboard_SetText with the text in the input widget. */ +/* This way native text input state stays synchronised with the input widget. */ +/* (e.g. may only accept numerical input, so 'c' gets stripped from str) */ +CC_NOINLINE void InputWidget_SetText(struct InputWidget* w, const cc_string* str); + + +struct MenuInputDesc; +struct MenuInputVTABLE { + /* Returns a description of the range of valid values (e.g. "0 - 100") */ + void (*GetRange)(struct MenuInputDesc* d, cc_string* range); + /* Whether the given character is acceptable for this input */ + cc_bool (*IsValidChar)(struct MenuInputDesc* d, char c); + /* Whether the characters of the given string are acceptable for this input */ + /* e.g. for an integer, '-' is only valid for the first character */ + cc_bool (*IsValidString)(struct MenuInputDesc* d, const cc_string* s); + /* Whether the characters of the given string produce a valid value */ + cc_bool (*IsValidValue)(struct MenuInputDesc* d, const cc_string* s); + /* Gets the default value for this input. */ + void (*GetDefault)(struct MenuInputDesc* d, cc_string* value); + /* Whether the given input button was processed */ + /* E.g. Int input accepts using lef/right to increment/decrement */ + cc_bool (*ProcessInput)(struct MenuInputDesc* d, cc_string* value, int btn); +}; + +struct MenuInputDesc { + const struct MenuInputVTABLE* VTABLE; + union { + struct { const char* const* Names; int Count; } e; + struct { int Min, Max, Default; } i; + struct { float Min, Max, Default; } f; + struct { PackedCol Default; } h; + } meta; +}; + +extern const struct MenuInputVTABLE HexInput_VTABLE; +extern const struct MenuInputVTABLE IntInput_VTABLE; +extern const struct MenuInputVTABLE SeedInput_VTABLE; +extern const struct MenuInputVTABLE FloatInput_VTABLE; +extern const struct MenuInputVTABLE PathInput_VTABLE; +extern const struct MenuInputVTABLE StringInput_VTABLE; + +#define MenuInput_Hex(v, def) v.VTABLE = &HexInput_VTABLE; v.meta.h.Default = def; +#define MenuInput_Int(v, lo, hi, def) v.VTABLE = &IntInput_VTABLE; v.meta.i.Min = lo; v.meta.i.Max = hi; v.meta.i.Default = def; +#define MenuInput_Seed(v) v.VTABLE = &SeedInput_VTABLE; v.meta.i.Min = Int32_MinValue; v.meta.i.Max = Int32_MaxValue; +#define MenuInput_Float(v, lo, hi, def) v.VTABLE = &FloatInput_VTABLE; v.meta.f.Min = lo; v.meta.f.Max = hi; v.meta.f.Default = def; +#define MenuInput_Path(v) v.VTABLE = &PathInput_VTABLE; +#define MenuInput_Enum(v, names, count) v.VTABLE = NULL; v.meta.e.Names = names; v.meta.e.Count = count; +#define MenuInput_String(v) v.VTABLE = &StringInput_VTABLE; + +struct TextInputWidget { + struct InputWidget base; + int minWidth, minHeight; + struct MenuInputDesc desc; + char _textBuffer[INPUTWIDGET_LEN]; + /* variables for on-screen keyboard */ + const char* onscreenPlaceholder; + int onscreenType; +}; +#define MENUINPUTWIDGET_MAX 8 + +CC_NOINLINE void TextInputWidget_Create(struct TextInputWidget* w, int width, const cc_string* text, struct MenuInputDesc* d); +CC_NOINLINE void TextInputWidget_Add(void* screen, struct TextInputWidget* w, int width, const cc_string* text, struct MenuInputDesc* d); +/* Sets the font used, then redraws the input widget. */ +CC_NOINLINE void TextInputWidget_SetFont(struct TextInputWidget* w, struct FontDesc* font); + + +struct ChatInputWidget { + struct InputWidget base; + int typingLogPos; + cc_string origStr; + char _textBuffer[INPUTWIDGET_MAX_LINES * INPUTWIDGET_LEN]; + char _origBuffer[INPUTWIDGET_MAX_LINES * INPUTWIDGET_LEN]; +}; + +CC_NOINLINE void ChatInputWidget_Create(struct ChatInputWidget* w); +CC_NOINLINE void ChatInputWidget_SetFont(struct ChatInputWidget* w, struct FontDesc* font); + + +/* Retrieves the text for the i'th line in the group */ +typedef cc_string (*TextGroupWidget_Get)(int i); +#define TEXTGROUPWIDGET_LEN (STRING_SIZE + (STRING_SIZE / 2)) + +/* A group of text labels. */ +struct TextGroupWidget { + Widget_Body + int lines, defaultHeight; + struct FontDesc* font; + /* Whether a line has zero height when that line has no text in it. */ + cc_bool collapsible[GUI_MAX_CHATLINES]; + cc_bool underlineUrls; + struct Texture* textures; + TextGroupWidget_Get GetLine; +}; + +CC_NOINLINE void TextGroupWidget_Create(struct TextGroupWidget* w, int lines, struct Texture* textures, TextGroupWidget_Get getLine); +CC_NOINLINE void TextGroupWidget_SetFont(struct TextGroupWidget* w, struct FontDesc* font); +/* Deletes first line, then moves all other lines upwards, then redraws last line. */ +/* NOTE: GetLine must also adjust the lines it returns for this to behave properly. */ +CC_NOINLINE void TextGroupWidget_ShiftUp(struct TextGroupWidget* w); +/* Deletes last line, then moves all other lines downwards, then redraws first line. */ +/* NOTE: GetLine must also adjust the lines it returns for this to behave properly. */ +CC_NOINLINE void TextGroupWidget_ShiftDown(struct TextGroupWidget* w); +/* Returns height of lines, except for the first 0 or more empty lines. */ +CC_NOINLINE int TextGroupWidget_UsedHeight(struct TextGroupWidget* w); +/* Returns either the URL or the line underneath the given coordinates. */ +CC_NOINLINE int TextGroupWidget_GetSelected(struct TextGroupWidget* w, cc_string* text, int mouseX, int mouseY); +/* Redraws the given line, updating the texture and Y position of other lines. */ +CC_NOINLINE void TextGroupWidget_Redraw(struct TextGroupWidget* w, int index); +/* Calls TextGroupWidget_Redraw for all lines */ +CC_NOINLINE void TextGroupWidget_RedrawAll(struct TextGroupWidget* w); +/* Calls TextGroupWidget_Redraw for all lines which have the given colour code. */ +/* Typically only called in response to the ChatEvents.ColCodeChanged event. */ +CC_NOINLINE void TextGroupWidget_RedrawAllWithCol(struct TextGroupWidget* w, char col); +/* Gets the text for the i'th line. */ +static CC_INLINE cc_string TextGroupWidget_UNSAFE_Get(struct TextGroupWidget* w, int i) { return w->GetLine(i); } + + +typedef void (*SpecialInputAppendFunc)(void* userData, char c); +struct SpecialInputTab { + int itemsPerRow, charsPerItem, titleWidth; + cc_string title, contents; +}; + +struct SpecialInputWidget { + Widget_Body + int elementWidth, elementHeight; + int selectedIndex; + cc_bool pendingRedraw; + struct InputWidget* target; + struct Texture tex; + struct FontDesc* font; + int titleHeight; + struct SpecialInputTab tabs[5]; + cc_string colString; + char _colBuffer[DRAWER2D_MAX_COLORS * 4]; +}; + +CC_NOINLINE void SpecialInputWidget_Create(struct SpecialInputWidget* w, struct FontDesc* font, struct InputWidget* target); +CC_NOINLINE void SpecialInputWidget_Redraw(struct SpecialInputWidget* w); +CC_NOINLINE void SpecialInputWidget_UpdateCols(struct SpecialInputWidget* w); +CC_NOINLINE void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, cc_bool active); + +#ifdef CC_BUILD_TOUCH +struct ThumbstickWidget { + Widget_Body + float scale; +}; +#define THUMBSTICKWIDGET_PER (4 * 4) +#define THUMBSTICKWIDGET_MAX (THUMBSTICKWIDGET_PER * 2) + +void ThumbstickWidget_Init(struct ThumbstickWidget* w); +void ThumbstickWidget_GetMovement(struct ThumbstickWidget* w, float* xMoving, float* zMoving); +#endif +#endif |