Merge pull request #724 from UnknownShadow200/MobileInv

Improve inventory (especially for mobile)
This commit is contained in:
UnknownShadow200 2020-09-27 09:30:17 +10:00 committed by GitHub
commit fe44fb336d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 200 additions and 136 deletions

View File

@ -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) { void Drawer2D_MakeTexture(struct Texture* tex, struct Bitmap* bmp, int width, int height) {
tex->ID = Gfx_CreateTexture(bmp, false, false); tex->ID = Gfx_CreateTexture(bmp, false, false);
tex->X = 0; tex->Width = width; tex->Width = width;
tex->Y = 0; tex->Height = height; tex->Height = height;
tex->uv.U1 = 0.0f; tex->uv.V1 = 0.0f; tex->uv.U1 = 0.0f; tex->uv.V1 = 0.0f;
tex->uv.U2 = (float)width / (float)bmp->width; tex->uv.U2 = (float)width / (float)bmp->width;

View File

@ -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_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 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_BuildMesh(widget, vertices) (widget)->VTABLE->BuildMesh(widget, vertices)
#define Widget_Render2(widget, offset) (widget)->VTABLE->Render2(widget, offset); #define Widget_Render2(widget, offset) (widget)->VTABLE->Render2(widget, offset)
#define Widget_Layout(widget) (widget)->VTABLE->Reposition(widget); #define Widget_Layout(widget) (widget)->VTABLE->Reposition(widget)
#define Elem_TryFree(elem) if ((elem)->VTABLE) { Elem_Free(elem); }
#endif #endif

View File

@ -13,6 +13,7 @@ extern struct IGameComponent Inventory_Component;
#define INVENTORY_BLOCKS_PER_HOTBAR 9 #define INVENTORY_BLOCKS_PER_HOTBAR 9
/* Number of hotbars that can be selected between */ /* Number of hotbars that can be selected between */
#define INVENTORY_HOTBARS 9 #define INVENTORY_HOTBARS 9
#define HOTBAR_MAX_INDEX (INVENTORY_BLOCKS_PER_HOTBAR - 1)
CC_VAR extern struct _InventoryData { CC_VAR extern struct _InventoryData {
/* Stores the currently bound blocks for all hotbars. */ /* Stores the currently bound blocks for all hotbars. */

View File

@ -47,8 +47,7 @@ struct LWebTask {
cc_result res; /* Error returned (e.g. for DNS failure) */ cc_result res; /* Error returned (e.g. for DNS failure) */
int status; /* HTTP return code for the request */ int status; /* HTTP return code for the request */
int reqID; /* Unique identifier for this web task. */ int reqID; /* Unique request identifier for this web task. */
String url; /* URL this task is downloading from/uploading to. */
/* Called when task successfully downloaded/uploaded data. */ /* Called when task successfully downloaded/uploaded data. */
void (*Handle)(cc_uint8* data, cc_uint32 len); void (*Handle)(cc_uint8* data, cc_uint32 len);
}; };
@ -65,7 +64,7 @@ void GetTokenTask_Run(void);
extern struct SignInTaskData { extern struct SignInTaskData {
struct LWebTask Base; struct LWebTask Base;
String username; /* Username to sign in as. Changed to case correct username. */ 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 */ cc_bool needMFA; /* need login code for multifactor authentication */
} SignInTask; } SignInTask;
void SignInTask_Run(const String* user, const String* pass, const String* mfaCode); void SignInTask_Run(const String* user, const String* pass, const String* mfaCode);

View File

@ -154,7 +154,7 @@ static void Menu_Remove(void* screen, int i) {
struct Screen* s = (struct Screen*)screen; struct Screen* s = (struct Screen*)screen;
struct Widget** widgets = s->widgets; struct Widget** widgets = s->widgets;
if (widgets[i]) { Elem_TryFree(widgets[i]); } if (widgets[i]) { Elem_Free(widgets[i]); }
widgets[i] = NULL; 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) { CC_NOINLINE static void MenuOptionsScreen_FreeExtHelp(struct MenuOptionsScreen* s) {
Elem_TryFree(&s->extHelp); Elem_Free(&s->extHelp);
s->extHelp.lines = 0; s->extHelp.lines = 0;
} }
@ -3041,7 +3041,8 @@ static void NostalgiaScreen_InitWidgets(struct MenuOptionsScreen* s) {
s->DoRecreateExtra = NostalgiaScreen_RecreateExtra; s->DoRecreateExtra = NostalgiaScreen_RecreateExtra;
MenuOptionsScreen_InitButtons(s, buttons, Array_Elems(buttons), NostalgiaScreen_SwitchBack); 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; s->widgets[9] = (struct Widget*)&nostalgia_desc;
} }
@ -3568,9 +3569,9 @@ static void TouchMore_Chat(void* s, void* w) {
Gui_Remove((struct Screen*)&TouchMoreScreen); Gui_Remove((struct Screen*)&TouchMoreScreen);
ChatScreen_OpenInput(&String_Empty); 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); Gui_Remove((struct Screen*)&TouchMoreScreen);
InventoryScreen_Show(); Game_ScreenshotRequested = true;
} }
static void TouchMore_Menu(void* s, void* w) { static void TouchMore_Menu(void* s, void* w) {
Gui_Remove((struct Screen*)&TouchMoreScreen); Gui_Remove((struct Screen*)&TouchMoreScreen);
@ -3587,7 +3588,7 @@ static const struct SimpleButtonDesc touchMore_btns[8] = {
{ -160, 0, "Speed", TouchMore_Speed }, { -160, 0, "Speed", TouchMore_Speed },
{ -160, 50, "Fly", TouchMore_Fly }, { -160, 50, "Fly", TouchMore_Fly },
{ -160, 100, "Menu", TouchMore_Menu }, { -160, 100, "Menu", TouchMore_Menu },
{ 160, -50, "Inventory", TouchMore_Inv }, { 160, -50, "Screenshot", TouchMore_Take },
{ 160, 0, "Fullscreen", TouchMore_Screen }, { 160, 0, "Fullscreen", TouchMore_Screen },
{ 160, 50, "Noclip", TouchMore_Noclip }, { 160, 50, "Noclip", TouchMore_Noclip },
{ 160, 100, "Fog", TouchMore_Fog } { 160, 100, "Fog", TouchMore_Fog }

View File

@ -168,8 +168,9 @@ static void HUDScreen_ContextLost(void* screen) {
struct HUDScreen* s = (struct HUDScreen*)screen; struct HUDScreen* s = (struct HUDScreen*)screen;
Font_Free(&s->font); Font_Free(&s->font);
TextAtlas_Free(&s->posAtlas); TextAtlas_Free(&s->posAtlas);
Elem_TryFree(&s->line1); Elem_Free(&s->hotbar);
Elem_TryFree(&s->line2); Elem_Free(&s->line1);
Elem_Free(&s->line2);
} }
static void HUDScreen_ContextRecreated(void* screen) { static void HUDScreen_ContextRecreated(void* screen) {
@ -179,32 +180,16 @@ static void HUDScreen_ContextRecreated(void* screen) {
struct HUDScreen* s = (struct HUDScreen*)screen; struct HUDScreen* s = (struct HUDScreen*)screen;
struct TextWidget* line1 = &s->line1; struct TextWidget* line1 = &s->line1;
struct TextWidget* line2 = &s->line2; struct TextWidget* line2 = &s->line2;
int y;
Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_NORMAL); Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_NORMAL);
Font_ReducePadding(&s->font, 4); Font_ReducePadding(&s->font, 4);
HotbarWidget_SetFont(&s->hotbar, &s->font);
y = 2;
TextWidget_Make(line1, ANCHOR_MIN, ANCHOR_MIN, 2, y);
HUDScreen_Update(s, 1.0); HUDScreen_Update(s, 1.0);
y += line1->height;
TextAtlas_Make(&s->posAtlas, &chars, &s->font, &prefix); 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) { 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); TextWidget_SetConst(line2, "0.30", &s->font);
Widget_Layout(line1);
Widget_Layout(line2);
} else { } else {
HUDScreen_UpdateHackState(s); HUDScreen_UpdateHackState(s);
} }
@ -214,7 +199,27 @@ static void HUDScreen_BuildMesh(void* screen) { }
static void HUDScreen_Layout(void* screen) { static void HUDScreen_Layout(void* screen) {
struct HUDScreen* s = (struct HUDScreen*)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(&s->hotbar);
Widget_Layout(line2);
} }
static int HUDScreen_KeyDown(void* screen, int key) { 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) { static void HUDScreen_Init(void* screen) {
struct HUDScreen* s = (struct HUDScreen*)screen; struct HUDScreen* s = (struct HUDScreen*)screen;
HotbarWidget_Create(&s->hotbar); HotbarWidget_Create(&s->hotbar);
TextWidget_Init(&s->line1);
TextWidget_Init(&s->line2);
} }
static void HUDScreen_Render(void* screen, double delta) { static void HUDScreen_Render(void* screen, double delta) {
@ -399,7 +406,8 @@ static void TabListOverlay_Layout(void* screen) {
minHeight = Display_ScaleY(300); minHeight = Display_ScaleY(300);
s->height = max(minHeight, height + s->title.height); 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); Widget_Layout(&s->title);
} }
@ -682,7 +690,7 @@ static void TabListOverlay_Init(void* screen) {
s->active = true; s->active = true;
s->classic = Gui.ClassicTabList || !Server.SupportsExtPlayerList; s->classic = Gui.ClassicTabList || !Server.SupportsExtPlayerList;
s->elementOffset = s->classic ? 0 : 10; 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.Added, s, TabListOverlay_Add);
Event_Register_(&TabListEvents.Changed, s, TabListOverlay_Update); 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, */ /* Destroy announcement texture before even rendering it at all, */
/* otherwise changing texture pack shows announcement for one frame */ /* otherwise changing texture pack shows announcement for one frame */
if (s->announcement.tex.ID && now > Chat_AnnouncementReceived + 5) { if (s->announcement.tex.ID && now > Chat_AnnouncementReceived + 5) {
Elem_TryFree(&s->announcement); Elem_Free(&s->announcement);
} }
Elem_Render(&s->announcement, delta); Elem_Render(&s->announcement, delta);
@ -985,17 +993,18 @@ static void ChatScreen_ContextLost(void* screen) {
struct ChatScreen* s = (struct ChatScreen*)screen; struct ChatScreen* s = (struct ChatScreen*)screen;
ChatScreen_FreeChatFonts(s); ChatScreen_FreeChatFonts(s);
Elem_TryFree(&s->chat); Elem_Free(&s->chat);
Elem_TryFree(&s->input.base); Elem_Free(&s->input.base);
Elem_TryFree(&s->altText); Elem_Free(&s->altText);
Elem_TryFree(&s->status); Elem_Free(&s->status);
Elem_TryFree(&s->bottomRight); Elem_Free(&s->bottomRight);
Elem_TryFree(&s->clientStatus); Elem_Free(&s->clientStatus);
Elem_TryFree(&s->announcement); Elem_Free(&s->announcement);
#ifdef CC_BUILD_TOUCH #ifdef CC_BUILD_TOUCH
Elem_TryFree(&s->send); if (!Input_TouchMode) return;
Elem_TryFree(&s->cancel); Elem_Free(&s->send);
Elem_Free(&s->cancel);
#endif #endif
} }
@ -1032,7 +1041,10 @@ static void ChatScreen_Layout(void* screen) {
Widget_SetLocation(&s->clientStatus, ANCHOR_MIN, ANCHOR_MAX, 10, 0); Widget_SetLocation(&s->clientStatus, ANCHOR_MIN, ANCHOR_MAX, 10, 0);
ChatScreen_UpdateChatYOffsets(s); ChatScreen_UpdateChatYOffsets(s);
Widget_SetLocation(&s->announcement, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 0);
s->announcement.yOffset = -WindowInfo.Height / 4; s->announcement.yOffset = -WindowInfo.Height / 4;
Widget_Layout(&s->announcement);
#ifdef CC_BUILD_TOUCH #ifdef CC_BUILD_TOUCH
if (!Input_TouchMode) return; if (!Input_TouchMode) return;
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MIN, 10, 10); Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MIN, 10, 10);
@ -1191,7 +1203,7 @@ static void ChatScreen_Init(void* screen) {
s->chatTextures, ChatScreen_GetChat); s->chatTextures, ChatScreen_GetChat);
TextGroupWidget_Create(&s->clientStatus, CHAT_MAX_CLIENTSTATUS, TextGroupWidget_Create(&s->clientStatus, CHAT_MAX_CLIENTSTATUS,
s->clientStatusTextures, ChatScreen_GetClientStatus); 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->status.collapsible[0] = true; /* Texture pack download status */
s->clientStatus.collapsible[0] = true; s->clientStatus.collapsible[0] = true;
@ -1300,7 +1312,7 @@ static void InventoryScreen_OnBlockChanged(void* screen) {
static void InventoryScreen_ContextLost(void* screen) { static void InventoryScreen_ContextLost(void* screen) {
struct InventoryScreen* s = (struct InventoryScreen*)screen; struct InventoryScreen* s = (struct InventoryScreen*)screen;
Font_Free(&s->font); Font_Free(&s->font);
Elem_TryFree(&s->table); Elem_Free(&s->table);
} }
static void InventoryScreen_ContextRecreated(void* screen) { static void InventoryScreen_ContextRecreated(void* screen) {

View File

@ -64,11 +64,6 @@ static const struct WidgetVTABLE TextWidget_VTABLE = {
Widget_Pointer, Widget_Pointer, Widget_PointerMove, Widget_Pointer, Widget_Pointer, Widget_PointerMove,
TextWidget_BuildMesh, TextWidget_Render2 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) { void TextWidget_Init(struct TextWidget* w) {
Widget_Reset(w); Widget_Reset(w);
w->VTABLE = &TextWidget_VTABLE; w->VTABLE = &TextWidget_VTABLE;
@ -256,30 +251,26 @@ void ButtonWidget_SetConst(struct ButtonWidget* w, const char* text, struct Font
/*########################################################################################################################* /*########################################################################################################################*
*-----------------------------------------------------ScrollbarWidget-----------------------------------------------------* *-----------------------------------------------------ScrollbarWidget-----------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
#define TABLE_MAX_ROWS_DISPLAYED 8 #define SCROLL_BACK_COL PackedCol_Make( 10, 10, 10, 220)
#define SCROLL_WIDTH 22 #define SCROLL_BAR_COL PackedCol_Make(100, 100, 100, 220)
#define SCROLL_BORDER 2 #define SCROLL_HOVER_COL PackedCol_Make(122, 122, 122, 220)
#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);
static void ScrollbarWidget_ClampTopRow(struct ScrollbarWidget* w) { 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 >= maxTop) w->topRow = maxTop;
if (w->topRow < 0) w->topRow = 0; if (w->topRow < 0) w->topRow = 0;
} }
static float ScrollbarWidget_GetScale(struct ScrollbarWidget* w) { static float ScrollbarWidget_GetScale(struct ScrollbarWidget* w) {
float rows = (float)w->totalRows; float rows = (float)w->rowsTotal;
return (w->height - SCROLL_BORDER * 2) / rows; return (w->height - w->borderY * 2) / rows;
} }
static void ScrollbarWidget_GetScrollbarCoords(struct ScrollbarWidget* w, int* y, int* height) { static void ScrollbarWidget_GetScrollbarCoords(struct ScrollbarWidget* w, int* y, int* height) {
float scale = ScrollbarWidget_GetScale(w); float scale = ScrollbarWidget_GetScale(w);
*y = Math_Ceil(w->topRow * scale) + SCROLL_BORDER; *y = Math_Ceil(w->topRow * scale) + w->borderY;
*height = Math_Ceil(TABLE_MAX_ROWS_DISPLAYED * scale); *height = Math_Ceil(w->rowsVisible * scale);
*height = min(*y + *height, w->height - SCROLL_BORDER) - *y; *height = min(*y + *height, w->height - w->borderY) - *y;
} }
static void ScrollbarWidget_Render(void* widget, double delta) { static void ScrollbarWidget_Render(void* widget, double delta) {
@ -289,23 +280,23 @@ static void ScrollbarWidget_Render(void* widget, double delta) {
cc_bool hovered; cc_bool hovered;
x = w->x; width = w->width; 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); ScrollbarWidget_GetScrollbarCoords(w, &y, &height);
x += SCROLL_BORDER; y += w->y; x += w->borderX; y += w->y;
width -= SCROLL_BORDER * 2; width -= w->borderX * 2;
hovered = Gui_ContainsPointers(x, y, width, height); 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); Gfx_Draw2DFlat(x, y, width, height, barCol);
if (height < 20) return; if (height < 20) return;
x += SCROLL_NUBS_WIDTH; y += (height / 2); x += w->nubsWidth; y += (height / 2);
width -= SCROLL_NUBS_WIDTH * 2; width -= w->nubsWidth * 2;
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 - 1, width, SCROLL_BORDER, Scroll_BackCol); Gfx_Draw2DFlat(x, y + w->offsets[1], width, w->borderY, SCROLL_BACK_COL);
Gfx_Draw2DFlat(x, y - 1 + 4, width, SCROLL_BORDER, Scroll_BackCol); 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) { 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); ScrollbarWidget_GetScrollbarCoords(w, &posY, &height);
if (y < posY) { if (y < posY) {
w->topRow -= TABLE_MAX_ROWS_DISPLAYED; w->topRow -= w->rowsVisible;
} else if (y >= posY + height) { } else if (y >= posY + height) {
w->topRow += TABLE_MAX_ROWS_DISPLAYED; w->topRow += w->rowsVisible;
} else { } else {
w->draggingId = id; w->draggingId = id;
w->dragOffset = y - posY; w->dragOffset = y - posY;
@ -371,9 +362,18 @@ static const struct WidgetVTABLE ScrollbarWidget_VTABLE = {
}; };
void ScrollbarWidget_Create(struct ScrollbarWidget* w) { void ScrollbarWidget_Create(struct ScrollbarWidget* w) {
Widget_Reset(w); Widget_Reset(w);
w->VTABLE = &ScrollbarWidget_VTABLE; w->VTABLE = &ScrollbarWidget_VTABLE;
w->width = SCROLL_WIDTH; w->width = Display_ScaleX(22);
w->totalRows = 0; 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->topRow = 0;
w->scrollingAcc = 0.0f; w->scrollingAcc = 0.0f;
w->draggingId = 0; w->draggingId = 0;
@ -384,20 +384,18 @@ void ScrollbarWidget_Create(struct ScrollbarWidget* w) {
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------HotbarWidget-------------------------------------------------------* *------------------------------------------------------HotbarWidget-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
#define HotbarWidget_TileX(w, idx) (int)(w->x + w->slotXOffset + w->slotWidth * (idx))
static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) { static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) {
PackedCol white = PACKEDCOL_WHITE; PackedCol white = PACKEDCOL_WHITE;
GfxResourceID tex; GfxResourceID tex;
float width; int x;
int i, x;
tex = Gui.ClassicTexture ? Gui.GuiClassicTex : Gui.GuiTex; tex = Gui.ClassicTexture ? Gui.GuiClassicTex : Gui.GuiTex;
w->backTex.ID = tex; w->backTex.ID = tex;
Texture_Render(&w->backTex); Texture_Render(&w->backTex);
i = Inventory.SelectedIndex; x = HotbarWidget_TileX(w, Inventory.SelectedIndex);
width = w->slotWidth;
x = (int)(w->x + w->slotXOffset + width * i);
w->selTex.ID = tex; w->selTex.ID = tex;
w->selTex.X = (int)(x - w->selWidth / 2); w->selTex.X = (int)(x - w->selWidth / 2);
Gfx_Draw2DTexture(&w->selTex, white); Gfx_Draw2DTexture(&w->selTex, white);
@ -406,16 +404,19 @@ static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) {
static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) { static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
/* TODO: Should hotbar use its own VB? */ /* TODO: Should hotbar use its own VB? */
struct VertexTextured vertices[INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES]; struct VertexTextured vertices[INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES];
float width, scale; float scale;
int i, x, y; int i, x, y;
IsometricDrawer_BeginBatch(vertices, Models.Vb); IsometricDrawer_BeginBatch(vertices, Models.Vb);
width = w->slotWidth;
scale = w->elemSize / 2.0f; scale = w->elemSize / 2.0f;
for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) { 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); 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_DrawBatch(Inventory_Get(i), scale, x, y);
} }
IsometricDrawer_EndBatch(); IsometricDrawer_EndBatch();
@ -460,6 +461,13 @@ static void HotbarWidget_Render(void* widget, double delta) {
struct HotbarWidget* w = (struct HotbarWidget*)widget; struct HotbarWidget* w = (struct HotbarWidget*)widget;
HotbarWidget_RenderHotbarOutline(w); HotbarWidget_RenderHotbarOutline(w);
HotbarWidget_RenderHotbarBlocks(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) { 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++) { for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) {
cellX = (int)(w->x + width * i); cellX = (int)(w->x + width * i);
cellY = w->y; cellY = w->y;
if (!Gui_Contains(cellX, cellY, width, height, x, y)) continue;
if (Gui_Contains(cellX, cellY, width, height, x, y)) { #ifdef CC_BUILD_TOUCH
Inventory_SetSelectedIndex(i); if (i == HOTBAR_MAX_INDEX && Input_TouchMode) {
return true; InventoryScreen_Show(); return true;
} }
#endif
Inventory_SetSelectedIndex(i);
return true;
} }
return false; return false;
} }
@ -535,8 +547,17 @@ static int HotbarWidget_MouseScroll(void* widget, float delta) {
return true; 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 = { 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_KeyDown, HotbarWidget_KeyUp, HotbarWidget_MouseScroll,
HotbarWidget_PointerDown, Widget_Pointer, Widget_PointerMove HotbarWidget_PointerDown, Widget_Pointer, Widget_PointerMove
}; };
@ -547,17 +568,28 @@ void HotbarWidget_Create(struct HotbarWidget* w) {
w->verAnchor = ANCHOR_MAX; 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-------------------------------------------------------* *-------------------------------------------------------TableWidget-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static int Table_X(struct TableWidget* w) { return w->x - 5 - 10; } static int Table_X(struct TableWidget* w) { return w->x - w->paddingX; }
static int Table_Y(struct TableWidget* w) { return w->y - 5 - 30; } static int Table_Y(struct TableWidget* w) { return w->y - w->paddingTopY; }
static int Table_Width(struct TableWidget* w) { 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) { 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) #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; x = i % w->blocksPerRow;
y = i / w->blocksPerRow - w->scroll.topRow; y = i / w->blocksPerRow - w->scroll.topRow;
*cellX = w->x + w->cellSize * x; *cellX = w->x + w->cellSizeX * x;
*cellY = w->y + w->cellSize * y + 3; *cellY = w->y + w->cellSizeY * y + 3;
return y >= 0 && y < TABLE_MAX_ROWS_DISPLAYED; return y >= 0 && y < w->rowsVisible;
} }
static void TableWidget_MoveCursorToSelected(struct TableWidget* w) { static void TableWidget_MoveCursorToSelected(struct TableWidget* w) {
@ -579,7 +611,7 @@ static void TableWidget_MoveCursorToSelected(struct TableWidget* w) {
idx = w->selectedIndex; idx = w->selectedIndex;
TableWidget_GetCoords(w, idx, &x, &y); 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); Cursor_SetPosition(x, y);
} }
@ -652,14 +684,14 @@ void TableWidget_RecreateBlocks(struct TableWidget* w) {
i++; i++;
} }
w->rowsCount = Math_CeilDiv(w->blocksCount, w->blocksPerRow); w->rowsTotal = Math_CeilDiv(w->blocksCount, w->blocksPerRow);
Widget_Layout(w); Widget_Layout(w);
} }
static void TableWidget_Render(void* widget, double delta) { static void TableWidget_Render(void* widget, double delta) {
struct TableWidget* w = (struct TableWidget*)widget; struct TableWidget* w = (struct TableWidget*)widget;
struct VertexTextured vertices[TABLE_MAX_VERTICES]; struct VertexTextured vertices[TABLE_MAX_VERTICES];
int cellSize, size; int cellSizeX, cellSizeY, size;
float off; float off;
int i, x, y; int i, x, y;
@ -674,16 +706,18 @@ static void TableWidget_Render(void* widget, double delta) {
Gfx_Draw2DGradient(Table_X(w), Table_Y(w), Gfx_Draw2DGradient(Table_X(w), Table_Y(w),
Table_Width(w), Table_Height(w), topBackCol, bottomBackCol); 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); 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) { if (w->selectedIndex != -1 && Game_ClassicMode && w->blocks[w->selectedIndex] != BLOCK_AIR) {
TableWidget_GetCoords(w, w->selectedIndex, &x, &y); TableWidget_GetCoords(w, w->selectedIndex, &x, &y);
off = cellSize * 0.1f; /* TODO: Need two size arguments, in case X/Y dpi differs */
size = (int)(cellSize + off * 2); off = cellSizeX * 0.1f;
size = (int)(cellSizeX + off * 2);
Gfx_Draw2DGradient((int)(x - off), (int)(y - off), Gfx_Draw2DGradient((int)(x - off), (int)(y - off),
size, size, topSelCol, bottomSelCol); size, size, topSelCol, bottomSelCol);
} }
@ -695,9 +729,10 @@ static void TableWidget_Render(void* widget, double delta) {
if (!TableWidget_GetCoords(w, i, &x, &y)) continue; if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
/* We want to always draw the selected block on top of others */ /* 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; if (i == w->selectedIndex) continue;
IsometricDrawer_DrawBatch(w->blocks[i], cellSize * 0.7f / 2.0f, IsometricDrawer_DrawBatch(w->blocks[i], cellSizeX * 0.7f / 2.0f,
x + cellSize / 2, y + cellSize / 2); x + cellSizeX / 2, y + cellSizeY / 2);
} }
i = w->selectedIndex; i = w->selectedIndex;
@ -705,8 +740,8 @@ static void TableWidget_Render(void* widget, double delta) {
TableWidget_GetCoords(w, i, &x, &y); TableWidget_GetCoords(w, i, &x, &y);
IsometricDrawer_DrawBatch(w->blocks[i], IsometricDrawer_DrawBatch(w->blocks[i],
(cellSize + w->selBlockExpand) * 0.7f / 2.0f, (cellSizeX + w->selBlockExpand) * 0.7f / 2.0f,
x + cellSize / 2, y + cellSize / 2); x + cellSizeX / 2, y + cellSizeY / 2);
} }
IsometricDrawer_EndBatch(); IsometricDrawer_EndBatch();
@ -722,7 +757,7 @@ static void TableWidget_Free(void* widget) {
} }
void TableWidget_Recreate(struct TableWidget* w) { void TableWidget_Recreate(struct TableWidget* w) {
Elem_TryFree(w); Elem_Free(w);
w->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, TABLE_MAX_VERTICES); w->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, TABLE_MAX_VERTICES);
TableWidget_RecreateDescTex(w); TableWidget_RecreateDescTex(w);
} }
@ -730,21 +765,31 @@ void TableWidget_Recreate(struct TableWidget* w) {
static void TableWidget_Reposition(void* widget) { static void TableWidget_Reposition(void* widget) {
struct TableWidget* w = (struct TableWidget*)widget; struct TableWidget* w = (struct TableWidget*)widget;
float scale = Gui_GetInventoryScale(); 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); 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; do {
w->height = w->cellSize * rowsDisplayed; w->width = w->cellSizeX * w->blocksPerRow;
Widget_CalcPosition(w); w->height = w->cellSizeY * w->rowsVisible;
TableWidget_UpdateDescTexPos(w); 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.x = Table_X(w) + Table_Width(w);
w->scroll.y = Table_Y(w); w->scroll.y = Table_Y(w);
w->scroll.height = Table_Height(w); w->scroll.height = Table_Height(w);
w->scroll.totalRows = w->rowsCount; w->scroll.rowsTotal = w->rowsTotal;
w->scroll.rowsVisible = w->rowsVisible;
} }
static void TableWidget_ScrollRelative(struct TableWidget* w, int delta) { 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) { static int TableWidget_PointerMove(void* widget, int id, int x, int y) {
struct TableWidget* w = (struct TableWidget*)widget; struct TableWidget* w = (struct TableWidget*)widget;
int cellSize, maxHeight; int cellSizeX, cellSizeY, maxHeight;
int i, cellX, cellY; int i, cellX, cellY;
if (Elem_HandlesPointerMove(&w->scroll, id, x, y)) return true; 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->lastX = x; w->lastY = y;
w->selectedIndex = -1; w->selectedIndex = -1;
cellSize = w->cellSize; cellSizeX = w->cellSizeX;
maxHeight = cellSize * TABLE_MAX_ROWS_DISPLAYED; cellSizeY = w->cellSizeY;
maxHeight = cellSizeY * w->rowsVisible;
if (Gui_Contains(w->x, w->y + 3, w->width, maxHeight - 3 * 2, x, y)) { if (Gui_Contains(w->x, w->y + 3, w->width, maxHeight - 3 * 2, x, y)) {
for (i = 0; i < w->blocksCount; i++) { for (i = 0; i < w->blocksCount; i++) {
TableWidget_GetCoords(w, i, &cellX, &cellY); 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; w->selectedIndex = i;
break; break;
} }
@ -863,6 +909,10 @@ void TableWidget_Create(struct TableWidget* w) {
w->horAnchor = ANCHOR_CENTRE; w->horAnchor = ANCHOR_CENTRE;
w->verAnchor = ANCHOR_CENTRE; w->verAnchor = ANCHOR_CENTRE;
w->lastX = -20; w->lastY = -20; 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) { 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; if (block == BLOCK_AIR) w->selectedIndex = -1;
w->scroll.topRow = w->selectedIndex / w->blocksPerRow; 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); ScrollbarWidget_ClampTopRow(&w->scroll);
TableWidget_MoveCursorToSelected(w); TableWidget_MoveCursorToSelected(w);
TableWidget_RecreateDescTex(w); TableWidget_RecreateDescTex(w);

View File

@ -17,9 +17,6 @@ struct TextWidget {
}; };
#define TEXTWIDGET_MAX 4 #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. */ /* Initialises a text widget. */
CC_NOINLINE void TextWidget_Init(struct TextWidget* w); CC_NOINLINE void TextWidget_Init(struct TextWidget* w);
/* Draws the given text into a texture, then updates the position and size of this widget. */ /* 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. */ /* Clickable and draggable scrollbar. */
struct ScrollbarWidget { struct ScrollbarWidget {
Widget_Body Widget_Body
int totalRows, topRow; int topRow, rowsTotal, rowsVisible;
float scrollingAcc; float scrollingAcc;
int dragOffset; int dragOffset;
int draggingId; int draggingId;
int borderX, borderY;
int nubsWidth, offsets[3];
}; };
/* Resets state of the given scrollbar widget to default. */ /* Resets state of the given scrollbar widget to default. */
CC_NOINLINE void ScrollbarWidget_Create(struct ScrollbarWidget* w); CC_NOINLINE void ScrollbarWidget_Create(struct ScrollbarWidget* w);
@ -70,18 +69,20 @@ struct HotbarWidget {
float slotXOffset, elemSize; float slotXOffset, elemSize;
float scrollAcc; float scrollAcc;
cc_bool altHandled; cc_bool altHandled;
struct Texture ellipsisTex;
}; };
/* Resets state of the given hotbar widget to default. */ /* Resets state of the given hotbar widget to default. */
CC_NOINLINE void HotbarWidget_Create(struct HotbarWidget* w); CC_NOINLINE void HotbarWidget_Create(struct HotbarWidget* w);
CC_NOINLINE void HotbarWidget_SetFont(struct HotbarWidget* w, struct FontDesc* font);
/* A table of blocks. */ /* A table of blocks. */
struct TableWidget { struct TableWidget {
Widget_Body Widget_Body
int blocksCount, blocksPerRow, rowsCount; int blocksCount, blocksPerRow;
int rowsTotal, rowsVisible;
int lastCreatedIndex; int lastCreatedIndex;
struct FontDesc* font; struct FontDesc* font;
int selectedIndex, cellSize; int selectedIndex, cellSizeX, cellSizeY;
float selBlockExpand; float selBlockExpand;
GfxResourceID vb; GfxResourceID vb;
cc_bool pendingClose; cc_bool pendingClose;
@ -89,7 +90,8 @@ struct TableWidget {
BlockID blocks[BLOCK_COUNT]; BlockID blocks[BLOCK_COUNT];
struct ScrollbarWidget scroll; struct ScrollbarWidget scroll;
struct Texture descTex; struct Texture descTex;
int lastX, lastY; int lastX, lastY, paddingX;
int paddingTopY, paddingMaxY;
}; };
CC_NOINLINE void TableWidget_Create(struct TableWidget* w); CC_NOINLINE void TableWidget_Create(struct TableWidget* w);