diff --git a/src/Drawer2D.c b/src/Drawer2D.c index c0e2aa7fd..9cd2538bd 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -339,9 +339,9 @@ void Drawer2D_MakeTextTexture(struct Texture* tex, struct DrawTextArgs* args) { } void Drawer2D_MakeTexture(struct Texture* tex, struct Bitmap* bmp, int width, int height) { - tex->ID = Gfx_CreateTexture(bmp, false, false); - tex->X = 0; tex->Width = width; - tex->Y = 0; tex->Height = height; + tex->ID = Gfx_CreateTexture(bmp, false, false); + tex->Width = width; + tex->Height = height; tex->uv.U1 = 0.0f; tex->uv.V1 = 0.0f; tex->uv.U2 = (float)width / (float)bmp->width; diff --git a/src/Gui.h b/src/Gui.h index 255eb81b9..029af0142 100644 --- a/src/Gui.h +++ b/src/Gui.h @@ -231,8 +231,7 @@ void TextAtlas_AddInt(struct TextAtlas* atlas, int value, struct VertexTextured* #define Elem_HandlesPointerUp(elem, id, x, y) (elem)->VTABLE->HandlesPointerUp(elem, id, x, y) #define Elem_HandlesPointerMove(elem, id, x, y) (elem)->VTABLE->HandlesPointerMove(elem, id, 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); -#define Elem_TryFree(elem) if ((elem)->VTABLE) { Elem_Free(elem); } +#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 diff --git a/src/Inventory.h b/src/Inventory.h index 8facc746f..8ef3907cf 100644 --- a/src/Inventory.h +++ b/src/Inventory.h @@ -13,6 +13,7 @@ extern struct IGameComponent Inventory_Component; #define INVENTORY_BLOCKS_PER_HOTBAR 9 /* Number of hotbars that can be selected between */ #define INVENTORY_HOTBARS 9 +#define HOTBAR_MAX_INDEX (INVENTORY_BLOCKS_PER_HOTBAR - 1) CC_VAR extern struct _InventoryData { /* Stores the currently bound blocks for all hotbars. */ diff --git a/src/LWeb.h b/src/LWeb.h index 9afd70e96..f1f6dacb4 100644 --- a/src/LWeb.h +++ b/src/LWeb.h @@ -47,8 +47,7 @@ struct LWebTask { cc_result res; /* Error returned (e.g. for DNS failure) */ int status; /* HTTP return code for the request */ - int reqID; /* Unique identifier for this web task. */ - String url; /* URL this task is downloading from/uploading to. */ + int reqID; /* Unique request identifier for this web task. */ /* Called when task successfully downloaded/uploaded data. */ void (*Handle)(cc_uint8* data, cc_uint32 len); }; @@ -65,7 +64,7 @@ void GetTokenTask_Run(void); extern struct SignInTaskData { struct LWebTask Base; String username; /* Username to sign in as. Changed to case correct username. */ - const char* error; /* If sign in fails, the reason as to why. */ + const char* error; /* If sign in fails, the reason why. */ cc_bool needMFA; /* need login code for multifactor authentication */ } SignInTask; void SignInTask_Run(const String* user, const String* pass, const String* mfaCode); diff --git a/src/Menus.c b/src/Menus.c index ca84ec228..41ca9339f 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -154,7 +154,7 @@ static void Menu_Remove(void* screen, int i) { struct Screen* s = (struct Screen*)screen; struct Widget** widgets = s->widgets; - if (widgets[i]) { Elem_TryFree(widgets[i]); } + if (widgets[i]) { Elem_Free(widgets[i]); } widgets[i] = NULL; } @@ -2059,7 +2059,7 @@ CC_NOINLINE static void MenuOptionsScreen_Set(struct MenuOptionsScreen* s, int i } CC_NOINLINE static void MenuOptionsScreen_FreeExtHelp(struct MenuOptionsScreen* s) { - Elem_TryFree(&s->extHelp); + Elem_Free(&s->extHelp); s->extHelp.lines = 0; } @@ -3041,7 +3041,8 @@ static void NostalgiaScreen_InitWidgets(struct MenuOptionsScreen* s) { s->DoRecreateExtra = NostalgiaScreen_RecreateExtra; MenuOptionsScreen_InitButtons(s, buttons, Array_Elems(buttons), NostalgiaScreen_SwitchBack); - TextWidget_Make(&nostalgia_desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 100); + TextWidget_Init(&nostalgia_desc); + Widget_SetLocation(&nostalgia_desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 100); s->widgets[9] = (struct Widget*)&nostalgia_desc; } @@ -3568,9 +3569,9 @@ static void TouchMore_Chat(void* s, void* w) { Gui_Remove((struct Screen*)&TouchMoreScreen); ChatScreen_OpenInput(&String_Empty); } -static void TouchMore_Inv(void* s, void* w) { +static void TouchMore_Take(void* s, void* w) { Gui_Remove((struct Screen*)&TouchMoreScreen); - InventoryScreen_Show(); + Game_ScreenshotRequested = true; } static void TouchMore_Menu(void* s, void* w) { Gui_Remove((struct Screen*)&TouchMoreScreen); @@ -3587,7 +3588,7 @@ static const struct SimpleButtonDesc touchMore_btns[8] = { { -160, 0, "Speed", TouchMore_Speed }, { -160, 50, "Fly", TouchMore_Fly }, { -160, 100, "Menu", TouchMore_Menu }, - { 160, -50, "Inventory", TouchMore_Inv }, + { 160, -50, "Screenshot", TouchMore_Take }, { 160, 0, "Fullscreen", TouchMore_Screen }, { 160, 50, "Noclip", TouchMore_Noclip }, { 160, 100, "Fog", TouchMore_Fog } diff --git a/src/Screens.c b/src/Screens.c index bb6bafe02..e93b33a7f 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -168,8 +168,9 @@ static void HUDScreen_ContextLost(void* screen) { struct HUDScreen* s = (struct HUDScreen*)screen; Font_Free(&s->font); TextAtlas_Free(&s->posAtlas); - Elem_TryFree(&s->line1); - Elem_TryFree(&s->line2); + Elem_Free(&s->hotbar); + Elem_Free(&s->line1); + Elem_Free(&s->line2); } static void HUDScreen_ContextRecreated(void* screen) { @@ -179,32 +180,16 @@ static void HUDScreen_ContextRecreated(void* screen) { struct HUDScreen* s = (struct HUDScreen*)screen; struct TextWidget* line1 = &s->line1; struct TextWidget* line2 = &s->line2; - int y; Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_NORMAL); Font_ReducePadding(&s->font, 4); - - y = 2; - TextWidget_Make(line1, ANCHOR_MIN, ANCHOR_MIN, 2, y); + HotbarWidget_SetFont(&s->hotbar, &s->font); + HUDScreen_Update(s, 1.0); - - y += line1->height; TextAtlas_Make(&s->posAtlas, &chars, &s->font, &prefix); - s->posAtlas.tex.Y = y; - - y += s->posAtlas.tex.Height; - TextWidget_Make(line2, ANCHOR_MIN, ANCHOR_MIN, 2, 0); - /* We can't use y in TextWidget_Make because that DPI scales it */ - line2->yOffset = y; if (Game_ClassicMode) { - /* Swap around so 0.30 version is at top */ - line2->yOffset = 2; - line1->yOffset = s->posAtlas.tex.Y; TextWidget_SetConst(line2, "0.30", &s->font); - - Widget_Layout(line1); - Widget_Layout(line2); } else { HUDScreen_UpdateHackState(s); } @@ -214,7 +199,27 @@ static void HUDScreen_BuildMesh(void* screen) { } static void HUDScreen_Layout(void* screen) { struct HUDScreen* s = (struct HUDScreen*)screen; + struct TextWidget* line1 = &s->line1; + struct TextWidget* line2 = &s->line2; + int posY; + + Widget_SetLocation(line1, ANCHOR_MIN, ANCHOR_MIN, 2, 2); + posY = line1->y + line1->height; + s->posAtlas.tex.Y = posY; + Widget_SetLocation(line2, ANCHOR_MIN, ANCHOR_MIN, 2, 0); + + if (Game_ClassicMode) { + /* Swap around so 0.30 version is at top */ + line2->yOffset = line1->yOffset; + line1->yOffset = posY; + Widget_Layout(line1); + } else { + /* We can't use y in TextWidget_Make because that DPI scales it */ + line2->yOffset = posY + s->posAtlas.tex.Height; + } + Widget_Layout(&s->hotbar); + Widget_Layout(line2); } static int HUDScreen_KeyDown(void* screen, int key) { @@ -242,6 +247,8 @@ static int HUDscreen_PointerDown(void* screen, int id, int x, int y) { static void HUDScreen_Init(void* screen) { struct HUDScreen* s = (struct HUDScreen*)screen; HotbarWidget_Create(&s->hotbar); + TextWidget_Init(&s->line1); + TextWidget_Init(&s->line2); } static void HUDScreen_Render(void* screen, double delta) { @@ -399,7 +406,8 @@ static void TabListOverlay_Layout(void* screen) { minHeight = Display_ScaleY(300); s->height = max(minHeight, height + s->title.height); - s->title.yOffset = s->y + paddingY / 2; + s->title.horAnchor = ANCHOR_CENTRE; + s->title.yOffset = s->y + paddingY / 2; Widget_Layout(&s->title); } @@ -682,7 +690,7 @@ static void TabListOverlay_Init(void* screen) { s->active = true; s->classic = Gui.ClassicTabList || !Server.SupportsExtPlayerList; s->elementOffset = s->classic ? 0 : 10; - TextWidget_Make(&s->title, ANCHOR_CENTRE, ANCHOR_MIN, 0, 0); + TextWidget_Init(&s->title); Event_Register_(&TabListEvents.Added, s, TabListOverlay_Add); Event_Register_(&TabListEvents.Changed, s, TabListOverlay_Update); @@ -963,7 +971,7 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) { /* Destroy announcement texture before even rendering it at all, */ /* otherwise changing texture pack shows announcement for one frame */ if (s->announcement.tex.ID && now > Chat_AnnouncementReceived + 5) { - Elem_TryFree(&s->announcement); + Elem_Free(&s->announcement); } Elem_Render(&s->announcement, delta); @@ -985,17 +993,18 @@ static void ChatScreen_ContextLost(void* screen) { struct ChatScreen* s = (struct ChatScreen*)screen; ChatScreen_FreeChatFonts(s); - Elem_TryFree(&s->chat); - Elem_TryFree(&s->input.base); - Elem_TryFree(&s->altText); - Elem_TryFree(&s->status); - Elem_TryFree(&s->bottomRight); - Elem_TryFree(&s->clientStatus); - Elem_TryFree(&s->announcement); + Elem_Free(&s->chat); + Elem_Free(&s->input.base); + Elem_Free(&s->altText); + Elem_Free(&s->status); + Elem_Free(&s->bottomRight); + Elem_Free(&s->clientStatus); + Elem_Free(&s->announcement); #ifdef CC_BUILD_TOUCH - Elem_TryFree(&s->send); - Elem_TryFree(&s->cancel); + if (!Input_TouchMode) return; + Elem_Free(&s->send); + Elem_Free(&s->cancel); #endif } @@ -1032,7 +1041,10 @@ static void ChatScreen_Layout(void* screen) { Widget_SetLocation(&s->clientStatus, ANCHOR_MIN, ANCHOR_MAX, 10, 0); ChatScreen_UpdateChatYOffsets(s); + Widget_SetLocation(&s->announcement, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 0); s->announcement.yOffset = -WindowInfo.Height / 4; + Widget_Layout(&s->announcement); + #ifdef CC_BUILD_TOUCH if (!Input_TouchMode) return; Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MIN, 10, 10); @@ -1191,7 +1203,7 @@ static void ChatScreen_Init(void* screen) { s->chatTextures, ChatScreen_GetChat); TextGroupWidget_Create(&s->clientStatus, CHAT_MAX_CLIENTSTATUS, s->clientStatusTextures, ChatScreen_GetClientStatus); - TextWidget_Make(&s->announcement, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 0); + TextWidget_Init(&s->announcement); s->status.collapsible[0] = true; /* Texture pack download status */ s->clientStatus.collapsible[0] = true; @@ -1300,7 +1312,7 @@ static void InventoryScreen_OnBlockChanged(void* screen) { static void InventoryScreen_ContextLost(void* screen) { struct InventoryScreen* s = (struct InventoryScreen*)screen; Font_Free(&s->font); - Elem_TryFree(&s->table); + Elem_Free(&s->table); } static void InventoryScreen_ContextRecreated(void* screen) { diff --git a/src/Widgets.c b/src/Widgets.c index 484e8dbfc..51996baea 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -64,11 +64,6 @@ static const struct WidgetVTABLE TextWidget_VTABLE = { Widget_Pointer, Widget_Pointer, Widget_PointerMove, TextWidget_BuildMesh, TextWidget_Render2 }; -void TextWidget_Make(struct TextWidget* w, cc_uint8 horAnchor, cc_uint8 verAnchor, int xOffset, int yOffset) { - TextWidget_Init(w); - Widget_SetLocation(w, horAnchor, verAnchor, xOffset, yOffset); -} - void TextWidget_Init(struct TextWidget* w) { Widget_Reset(w); w->VTABLE = &TextWidget_VTABLE; @@ -256,30 +251,26 @@ void ButtonWidget_SetConst(struct ButtonWidget* w, const char* text, struct Font /*########################################################################################################################* *-----------------------------------------------------ScrollbarWidget-----------------------------------------------------* *#########################################################################################################################*/ -#define TABLE_MAX_ROWS_DISPLAYED 8 -#define SCROLL_WIDTH 22 -#define SCROLL_BORDER 2 -#define SCROLL_NUBS_WIDTH 3 -static PackedCol Scroll_BackCol = PackedCol_Make( 10, 10, 10, 220); -static PackedCol Scroll_BarCol = PackedCol_Make(100, 100, 100, 220); -static PackedCol Scroll_HoverCol = PackedCol_Make(122, 122, 122, 220); +#define SCROLL_BACK_COL PackedCol_Make( 10, 10, 10, 220) +#define SCROLL_BAR_COL PackedCol_Make(100, 100, 100, 220) +#define SCROLL_HOVER_COL PackedCol_Make(122, 122, 122, 220) static void ScrollbarWidget_ClampTopRow(struct ScrollbarWidget* w) { - int maxTop = w->totalRows - TABLE_MAX_ROWS_DISPLAYED; + int maxTop = w->rowsTotal - w->rowsVisible; if (w->topRow >= maxTop) w->topRow = maxTop; if (w->topRow < 0) w->topRow = 0; } static float ScrollbarWidget_GetScale(struct ScrollbarWidget* w) { - float rows = (float)w->totalRows; - return (w->height - SCROLL_BORDER * 2) / rows; + float rows = (float)w->rowsTotal; + return (w->height - w->borderY * 2) / rows; } static void ScrollbarWidget_GetScrollbarCoords(struct ScrollbarWidget* w, int* y, int* height) { float scale = ScrollbarWidget_GetScale(w); - *y = Math_Ceil(w->topRow * scale) + SCROLL_BORDER; - *height = Math_Ceil(TABLE_MAX_ROWS_DISPLAYED * scale); - *height = min(*y + *height, w->height - SCROLL_BORDER) - *y; + *y = Math_Ceil(w->topRow * scale) + w->borderY; + *height = Math_Ceil(w->rowsVisible * scale); + *height = min(*y + *height, w->height - w->borderY) - *y; } static void ScrollbarWidget_Render(void* widget, double delta) { @@ -289,23 +280,23 @@ static void ScrollbarWidget_Render(void* widget, double delta) { cc_bool hovered; x = w->x; width = w->width; - Gfx_Draw2DFlat(x, w->y, width, w->height, Scroll_BackCol); + Gfx_Draw2DFlat(x, w->y, width, w->height, SCROLL_BACK_COL); ScrollbarWidget_GetScrollbarCoords(w, &y, &height); - x += SCROLL_BORDER; y += w->y; - width -= SCROLL_BORDER * 2; + x += w->borderX; y += w->y; + width -= w->borderX * 2; hovered = Gui_ContainsPointers(x, y, width, height); - barCol = hovered ? Scroll_HoverCol : Scroll_BarCol; + barCol = hovered ? SCROLL_HOVER_COL : SCROLL_BAR_COL; Gfx_Draw2DFlat(x, y, width, height, barCol); if (height < 20) return; - x += SCROLL_NUBS_WIDTH; y += (height / 2); - width -= SCROLL_NUBS_WIDTH * 2; + x += w->nubsWidth; y += (height / 2); + width -= w->nubsWidth * 2; - Gfx_Draw2DFlat(x, y - 1 - 4, width, SCROLL_BORDER, Scroll_BackCol); - Gfx_Draw2DFlat(x, y - 1, width, SCROLL_BORDER, Scroll_BackCol); - Gfx_Draw2DFlat(x, y - 1 + 4, width, SCROLL_BORDER, Scroll_BackCol); + Gfx_Draw2DFlat(x, y + w->offsets[0], width, w->borderY, SCROLL_BACK_COL); + Gfx_Draw2DFlat(x, y + w->offsets[1], width, w->borderY, SCROLL_BACK_COL); + Gfx_Draw2DFlat(x, y + w->offsets[2], width, w->borderY, SCROLL_BACK_COL); } static int ScrollbarWidget_PointerDown(void* widget, int id, int x, int y) { @@ -321,9 +312,9 @@ static int ScrollbarWidget_PointerDown(void* widget, int id, int x, int y) { ScrollbarWidget_GetScrollbarCoords(w, &posY, &height); if (y < posY) { - w->topRow -= TABLE_MAX_ROWS_DISPLAYED; + w->topRow -= w->rowsVisible; } else if (y >= posY + height) { - w->topRow += TABLE_MAX_ROWS_DISPLAYED; + w->topRow += w->rowsVisible; } else { w->draggingId = id; w->dragOffset = y - posY; @@ -371,9 +362,18 @@ static const struct WidgetVTABLE ScrollbarWidget_VTABLE = { }; void ScrollbarWidget_Create(struct ScrollbarWidget* w) { Widget_Reset(w); - w->VTABLE = &ScrollbarWidget_VTABLE; - w->width = SCROLL_WIDTH; - w->totalRows = 0; + w->VTABLE = &ScrollbarWidget_VTABLE; + w->width = Display_ScaleX(22); + w->borderX = Display_ScaleX(2); + w->borderY = Display_ScaleY(2); + w->nubsWidth = Display_ScaleX(3); + + w->offsets[0] = Display_ScaleY(-1 - 4); + w->offsets[1] = Display_ScaleY(-1); + w->offsets[2] = Display_ScaleY(-1 + 4); + + w->rowsTotal = 0; + w->rowsVisible = 0; w->topRow = 0; w->scrollingAcc = 0.0f; w->draggingId = 0; @@ -384,20 +384,18 @@ void ScrollbarWidget_Create(struct ScrollbarWidget* w) { /*########################################################################################################################* *------------------------------------------------------HotbarWidget-------------------------------------------------------* *#########################################################################################################################*/ +#define HotbarWidget_TileX(w, idx) (int)(w->x + w->slotXOffset + w->slotWidth * (idx)) + static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) { PackedCol white = PACKEDCOL_WHITE; GfxResourceID tex; - float width; - int i, x; + int x; tex = Gui.ClassicTexture ? Gui.GuiClassicTex : Gui.GuiTex; w->backTex.ID = tex; Texture_Render(&w->backTex); - i = Inventory.SelectedIndex; - width = w->slotWidth; - x = (int)(w->x + w->slotXOffset + width * i); - + x = HotbarWidget_TileX(w, Inventory.SelectedIndex); w->selTex.ID = tex; w->selTex.X = (int)(x - w->selWidth / 2); Gfx_Draw2DTexture(&w->selTex, white); @@ -406,16 +404,19 @@ static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) { static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) { /* TODO: Should hotbar use its own VB? */ struct VertexTextured vertices[INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES]; - float width, scale; + float scale; int i, x, y; IsometricDrawer_BeginBatch(vertices, Models.Vb); - width = w->slotWidth; scale = w->elemSize / 2.0f; for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) { - x = (int)(w->x + w->slotXOffset + width * i); + x = HotbarWidget_TileX(w, i); y = w->y + (w->height / 2); + +#ifdef CC_BUILD_TOUCH + if (i == HOTBAR_MAX_INDEX && Input_TouchMode) continue; +#endif IsometricDrawer_DrawBatch(Inventory_Get(i), scale, x, y); } IsometricDrawer_EndBatch(); @@ -460,6 +461,13 @@ static void HotbarWidget_Render(void* widget, double delta) { struct HotbarWidget* w = (struct HotbarWidget*)widget; HotbarWidget_RenderHotbarOutline(w); HotbarWidget_RenderHotbarBlocks(w); + +#ifdef CC_BUILD_TOUCH + if (!Input_TouchMode) return; + w->ellipsisTex.X = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.Width / 2; + w->ellipsisTex.Y = w->y + (w->height / 2) - w->ellipsisTex.Height / 2; + Texture_Render(&w->ellipsisTex); +#endif } static int HotbarWidget_KeyDown(void* widget, int key) { @@ -510,11 +518,15 @@ static int HotbarWidget_PointerDown(void* widget, int id, int x, int y) { for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) { cellX = (int)(w->x + width * i); cellY = w->y; + if (!Gui_Contains(cellX, cellY, width, height, x, y)) continue; - if (Gui_Contains(cellX, cellY, width, height, x, y)) { - Inventory_SetSelectedIndex(i); - return true; +#ifdef CC_BUILD_TOUCH + if (i == HOTBAR_MAX_INDEX && Input_TouchMode) { + InventoryScreen_Show(); return true; } +#endif + Inventory_SetSelectedIndex(i); + return true; } return false; } @@ -535,8 +547,17 @@ static int HotbarWidget_MouseScroll(void* widget, float delta) { return true; } +static void HotbarWidget_Free(void* widget) { +#ifdef CC_BUILD_TOUCH + struct HotbarWidget* w = (struct HotbarWidget*)widget; + if (!Input_TouchMode) return; + + Gfx_DeleteTexture(&w->ellipsisTex.ID); +#endif +} + static const struct WidgetVTABLE HotbarWidget_VTABLE = { - HotbarWidget_Render, Widget_NullFunc, HotbarWidget_Reposition, + HotbarWidget_Render, HotbarWidget_Free, HotbarWidget_Reposition, HotbarWidget_KeyDown, HotbarWidget_KeyUp, HotbarWidget_MouseScroll, HotbarWidget_PointerDown, Widget_Pointer, Widget_PointerMove }; @@ -547,17 +568,28 @@ void HotbarWidget_Create(struct HotbarWidget* w) { w->verAnchor = ANCHOR_MAX; } +void HotbarWidget_SetFont(struct HotbarWidget* w, struct FontDesc* font) { +#ifdef CC_BUILD_TOUCH + static const String dots = String_FromConst("..."); + struct DrawTextArgs args; + if (!Input_TouchMode) return; + + DrawTextArgs_Make(&args, &dots, font, true); + Drawer2D_MakeTextTexture(&w->ellipsisTex, &args); +#endif +} + /*########################################################################################################################* *-------------------------------------------------------TableWidget-------------------------------------------------------* *#########################################################################################################################*/ -static int Table_X(struct TableWidget* w) { return w->x - 5 - 10; } -static int Table_Y(struct TableWidget* w) { return w->y - 5 - 30; } +static int Table_X(struct TableWidget* w) { return w->x - w->paddingX; } +static int Table_Y(struct TableWidget* w) { return w->y - w->paddingTopY; } static int Table_Width(struct TableWidget* w) { - return w->blocksPerRow * w->cellSize + 10 + 20; + return w->blocksPerRow * w->cellSizeX + w->paddingX * 2; } static int Table_Height(struct TableWidget* w) { - return min(w->rowsCount, TABLE_MAX_ROWS_DISPLAYED) * w->cellSize + 10 + 40; + return w->rowsVisible * w->cellSizeY + w->paddingTopY + w->paddingMaxY; } #define TABLE_MAX_VERTICES (8 * 10 * ISOMETRICDRAWER_MAXVERTICES) @@ -567,9 +599,9 @@ static cc_bool TableWidget_GetCoords(struct TableWidget* w, int i, int* cellX, i x = i % w->blocksPerRow; y = i / w->blocksPerRow - w->scroll.topRow; - *cellX = w->x + w->cellSize * x; - *cellY = w->y + w->cellSize * y + 3; - return y >= 0 && y < TABLE_MAX_ROWS_DISPLAYED; + *cellX = w->x + w->cellSizeX * x; + *cellY = w->y + w->cellSizeY * y + 3; + return y >= 0 && y < w->rowsVisible; } static void TableWidget_MoveCursorToSelected(struct TableWidget* w) { @@ -579,7 +611,7 @@ static void TableWidget_MoveCursorToSelected(struct TableWidget* w) { idx = w->selectedIndex; TableWidget_GetCoords(w, idx, &x, &y); - x += w->cellSize / 2; y += w->cellSize / 2; + x += w->cellSizeX / 2; y += w->cellSizeY / 2; Cursor_SetPosition(x, y); } @@ -652,14 +684,14 @@ void TableWidget_RecreateBlocks(struct TableWidget* w) { i++; } - w->rowsCount = Math_CeilDiv(w->blocksCount, w->blocksPerRow); + w->rowsTotal = Math_CeilDiv(w->blocksCount, w->blocksPerRow); Widget_Layout(w); } static void TableWidget_Render(void* widget, double delta) { struct TableWidget* w = (struct TableWidget*)widget; struct VertexTextured vertices[TABLE_MAX_VERTICES]; - int cellSize, size; + int cellSizeX, cellSizeY, size; float off; int i, x, y; @@ -674,16 +706,18 @@ static void TableWidget_Render(void* widget, double delta) { Gfx_Draw2DGradient(Table_X(w), Table_Y(w), Table_Width(w), Table_Height(w), topBackCol, bottomBackCol); - if (w->rowsCount > TABLE_MAX_ROWS_DISPLAYED) { + if (w->rowsVisible < w->rowsTotal) { Elem_Render(&w->scroll, delta); } - cellSize = w->cellSize; + cellSizeX = w->cellSizeX; + cellSizeY = w->cellSizeY; if (w->selectedIndex != -1 && Game_ClassicMode && w->blocks[w->selectedIndex] != BLOCK_AIR) { TableWidget_GetCoords(w, w->selectedIndex, &x, &y); - off = cellSize * 0.1f; - size = (int)(cellSize + off * 2); + /* TODO: Need two size arguments, in case X/Y dpi differs */ + off = cellSizeX * 0.1f; + size = (int)(cellSizeX + off * 2); Gfx_Draw2DGradient((int)(x - off), (int)(y - off), size, size, topSelCol, bottomSelCol); } @@ -695,9 +729,10 @@ static void TableWidget_Render(void* widget, double delta) { if (!TableWidget_GetCoords(w, i, &x, &y)) continue; /* We want to always draw the selected block on top of others */ + /* TODO: Need two size arguments, in case X/Y dpi differs */ if (i == w->selectedIndex) continue; - IsometricDrawer_DrawBatch(w->blocks[i], cellSize * 0.7f / 2.0f, - x + cellSize / 2, y + cellSize / 2); + IsometricDrawer_DrawBatch(w->blocks[i], cellSizeX * 0.7f / 2.0f, + x + cellSizeX / 2, y + cellSizeY / 2); } i = w->selectedIndex; @@ -705,8 +740,8 @@ static void TableWidget_Render(void* widget, double delta) { TableWidget_GetCoords(w, i, &x, &y); IsometricDrawer_DrawBatch(w->blocks[i], - (cellSize + w->selBlockExpand) * 0.7f / 2.0f, - x + cellSize / 2, y + cellSize / 2); + (cellSizeX + w->selBlockExpand) * 0.7f / 2.0f, + x + cellSizeX / 2, y + cellSizeY / 2); } IsometricDrawer_EndBatch(); @@ -722,7 +757,7 @@ static void TableWidget_Free(void* widget) { } void TableWidget_Recreate(struct TableWidget* w) { - Elem_TryFree(w); + Elem_Free(w); w->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, TABLE_MAX_VERTICES); TableWidget_RecreateDescTex(w); } @@ -730,21 +765,31 @@ void TableWidget_Recreate(struct TableWidget* w) { static void TableWidget_Reposition(void* widget) { struct TableWidget* w = (struct TableWidget*)widget; float scale = Gui_GetInventoryScale(); - int rowsDisplayed; + int cellSize; + + cellSize = (int)(50 * Math_SqrtF(scale)); + w->cellSizeX = Display_ScaleX(cellSize); + w->cellSizeY = Display_ScaleY(cellSize); - w->cellSize = (int)(50 * Math_SqrtF(scale)); w->selBlockExpand = 25.0f * Math_SqrtF(scale); - rowsDisplayed = min(TABLE_MAX_ROWS_DISPLAYED, w->rowsCount); + w->rowsVisible = min(8, w->rowsTotal); /* 8 rows max */ - w->width = w->cellSize * w->blocksPerRow; - w->height = w->cellSize * rowsDisplayed; - Widget_CalcPosition(w); - TableWidget_UpdateDescTexPos(w); + do { + w->width = w->cellSizeX * w->blocksPerRow; + w->height = w->cellSizeY * w->rowsVisible; + Widget_CalcPosition(w); + TableWidget_UpdateDescTexPos(w); + + /* Does the table fit on screen? */ + if (Game_ClassicMode || Table_Y(w) >= 0) break; + w->rowsVisible--; + } while (w->rowsVisible > 1); w->scroll.x = Table_X(w) + Table_Width(w); w->scroll.y = Table_Y(w); - w->scroll.height = Table_Height(w); - w->scroll.totalRows = w->rowsCount; + w->scroll.height = Table_Height(w); + w->scroll.rowsTotal = w->rowsTotal; + w->scroll.rowsVisible = w->rowsVisible; } static void TableWidget_ScrollRelative(struct TableWidget* w, int delta) { @@ -806,7 +851,7 @@ static int TableWidget_MouseScroll(void* widget, float delta) { static int TableWidget_PointerMove(void* widget, int id, int x, int y) { struct TableWidget* w = (struct TableWidget*)widget; - int cellSize, maxHeight; + int cellSizeX, cellSizeY, maxHeight; int i, cellX, cellY; if (Elem_HandlesPointerMove(&w->scroll, id, x, y)) return true; @@ -814,14 +859,15 @@ static int TableWidget_PointerMove(void* widget, int id, int x, int y) { w->lastX = x; w->lastY = y; w->selectedIndex = -1; - cellSize = w->cellSize; - maxHeight = cellSize * TABLE_MAX_ROWS_DISPLAYED; + cellSizeX = w->cellSizeX; + cellSizeY = w->cellSizeY; + maxHeight = cellSizeY * w->rowsVisible; if (Gui_Contains(w->x, w->y + 3, w->width, maxHeight - 3 * 2, x, y)) { for (i = 0; i < w->blocksCount; i++) { TableWidget_GetCoords(w, i, &cellX, &cellY); - if (Gui_Contains(cellX, cellY, cellSize, cellSize, x, y)) { + if (Gui_Contains(cellX, cellY, cellSizeX, cellSizeY, x, y)) { w->selectedIndex = i; break; } @@ -863,6 +909,10 @@ void TableWidget_Create(struct TableWidget* w) { w->horAnchor = ANCHOR_CENTRE; w->verAnchor = ANCHOR_CENTRE; w->lastX = -20; w->lastY = -20; + + w->paddingX = Display_ScaleX(15); + w->paddingTopY = Display_ScaleY(15 + 20); + w->paddingMaxY = Display_ScaleX(15); } void TableWidget_SetBlockTo(struct TableWidget* w, BlockID block) { @@ -876,7 +926,7 @@ void TableWidget_SetBlockTo(struct TableWidget* w, BlockID block) { if (block == BLOCK_AIR) w->selectedIndex = -1; w->scroll.topRow = w->selectedIndex / w->blocksPerRow; - w->scroll.topRow -= (TABLE_MAX_ROWS_DISPLAYED - 1); + w->scroll.topRow -= (w->rowsVisible - 1); ScrollbarWidget_ClampTopRow(&w->scroll); TableWidget_MoveCursorToSelected(w); TableWidget_RecreateDescTex(w); diff --git a/src/Widgets.h b/src/Widgets.h index 5e7282828..14ff1e28b 100644 --- a/src/Widgets.h +++ b/src/Widgets.h @@ -17,9 +17,6 @@ struct TextWidget { }; #define TEXTWIDGET_MAX 4 -/* Initialises a text widget. */ -CC_NOINLINE void TextWidget_Make(struct TextWidget* w, - cc_uint8 horAnchor, cc_uint8 verAnchor, int xOffset, int yOffset); /* Initialises a text widget. */ CC_NOINLINE void TextWidget_Init(struct TextWidget* w); /* Draws the given text into a texture, then updates the position and size of this widget. */ @@ -54,10 +51,12 @@ CC_NOINLINE void ButtonWidget_SetConst(struct ButtonWidget* w, const char* text, /* Clickable and draggable scrollbar. */ struct ScrollbarWidget { Widget_Body - int totalRows, topRow; + int topRow, rowsTotal, rowsVisible; float scrollingAcc; int dragOffset; int draggingId; + int borderX, borderY; + int nubsWidth, offsets[3]; }; /* Resets state of the given scrollbar widget to default. */ CC_NOINLINE void ScrollbarWidget_Create(struct ScrollbarWidget* w); @@ -70,18 +69,20 @@ struct HotbarWidget { float slotXOffset, elemSize; float scrollAcc; cc_bool altHandled; + struct Texture ellipsisTex; }; /* 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); /* A table of blocks. */ struct TableWidget { Widget_Body - int blocksCount, blocksPerRow, rowsCount; + int blocksCount, blocksPerRow; + int rowsTotal, rowsVisible; int lastCreatedIndex; struct FontDesc* font; - int selectedIndex, cellSize; + int selectedIndex, cellSizeX, cellSizeY; float selBlockExpand; GfxResourceID vb; cc_bool pendingClose; @@ -89,7 +90,8 @@ struct TableWidget { BlockID blocks[BLOCK_COUNT]; struct ScrollbarWidget scroll; struct Texture descTex; - int lastX, lastY; + int lastX, lastY, paddingX; + int paddingTopY, paddingMaxY; }; CC_NOINLINE void TableWidget_Create(struct TableWidget* w);