Split up ChatScreen into ChatScreen and ChatInputScreen, move ChatInputScreen to new widget rendering method

Also remove ButtonWidget old rendering method
This commit is contained in:
UnknownShadow200 2023-04-14 20:23:35 +10:00
parent ef345eb38a
commit 1a33352b6c
7 changed files with 495 additions and 401 deletions

View file

@ -190,6 +190,7 @@ enum GuiPriority {
GUI_PRIORITY_TOUCH = 25,
GUI_PRIORITY_INVENTORY = 20,
GUI_PRIORITY_TABLIST = 17,
GUI_PRIORITY_CHATINPUT = 16,
GUI_PRIORITY_CHAT = 15,
GUI_PRIORITY_HUD = 10,
GUI_PRIORITY_LOADING = 5

View file

@ -944,7 +944,7 @@ static void HandleHotkeyDown(int key) {
if (!(hkey->flags & HOTKEY_FLAG_STAYS_OPEN)) {
Chat_Send(&text, false);
} else if (!Gui.InputGrab) {
ChatScreen_OpenInput(&text);
ChatInputScreen_Open(&text);
}
}

View file

@ -3552,7 +3552,7 @@ static void UrlWarningOverlay_OpenUrl(void* screen, void* b) {
static void UrlWarningOverlay_AppendUrl(void* screen, void* b) {
struct UrlWarningOverlay* s = (struct UrlWarningOverlay*)screen;
if (Gui.ClickableChat) ChatScreen_AppendInput(&s->url);
if (Gui.ClickableChat) ChatInputScreen_Append(&s->url);
Gui_Remove((struct Screen*)s);
}

View file

@ -41,23 +41,9 @@ int Screen_TPointer(void* s, int id, int x, int y) { return true; }
void Screen_NullFunc(void* screen) { }
void Screen_NullUpdate(void* screen, double delta) { }
/* TODO: Remove these */
struct HUDScreen;
struct ChatScreen;
static struct HUDScreen* Gui_HUD;
static struct ChatScreen* Gui_Chat;
static cc_bool InventoryScreen_IsHotbarActive(void);
CC_NOINLINE static cc_bool IsOnlyChatActive(void) {
struct Screen* s;
int i;
for (i = 0; i < Gui.ScreensCount; i++) {
s = Gui_Screens[i];
if (s->grabsInput && s != (struct Screen*)Gui_Chat) return false;
}
return true;
}
static cc_bool ChatInputScreen_IsActive(void);
CC_NOINLINE static cc_bool IsOnlyChatActive(void);
/*########################################################################################################################*
@ -74,7 +60,7 @@ static struct HUDScreen {
float lastSpeed;
int lastFov;
struct HotbarWidget hotbar;
} HUDScreen_Instance;
} HUDScreen;
#define HUD_MAX_VERTICES (TEXTWIDGET_MAX * 2)
static void HUDScreen_RemakeLine1(struct HUDScreen* s) {
@ -199,7 +185,7 @@ static void HUDScreen_ContextRecreated(void* screen) {
}
static int HUDScreen_LayoutHotbar(void) {
struct HUDScreen* s = &HUDScreen_Instance;
struct HUDScreen* s = &HUDScreen;
s->hotbar.scale = Gui_GetHotbarScale();
Widget_Layout(&s->hotbar);
return s->hotbar.height;
@ -353,9 +339,8 @@ static const struct ScreenVTABLE HUDScreen_VTABLE = {
HUDScreen_Layout, HUDScreen_ContextLost, HUDScreen_ContextRecreated
};
void HUDScreen_Show(void) {
struct HUDScreen* s = &HUDScreen_Instance;
struct HUDScreen* s = &HUDScreen;
s->VTABLE = &HUDScreen_VTABLE;
Gui_HUD = s;
Gui_Add((struct Screen*)s, GUI_PRIORITY_HUD);
}
@ -656,7 +641,7 @@ static int TabListOverlay_PointerDown(void* screen, int id, int x, int y) {
cc_string player;
int i;
if (!((struct Screen*)Gui_Chat)->grabsInput) return false;
if (!ChatInputScreen_IsActive()) return false;
String_InitArray(text, textBuffer);
for (i = 0; i < s->namesCount; i++) {
@ -666,7 +651,7 @@ static int TabListOverlay_PointerDown(void* screen, int id, int x, int y) {
player = TabList_UNSAFE_GetPlayer(s->ids[i]);
String_Format1(&text, "%s ", &player);
ChatScreen_AppendInput(&text);
ChatInputScreen_Append(&text);
return TOUCH_TYPE_GUI;
}
return false;
@ -763,7 +748,7 @@ static const struct ScreenVTABLE TabListOverlay_VTABLE = {
TabListOverlay_PointerDown, Screen_PointerUp, Screen_FPointer, Screen_FMouseScroll,
TabListOverlay_Layout, TabListOverlay_ContextLost, TabListOverlay_ContextRecreated
};
void TabListOverlay_Show(void) {
static void TabListOverlay_Show(void) {
struct TabListOverlay* s = &TabListOverlay_Instance;
s->VTABLE = &TabListOverlay_VTABLE;
s->staysOpen = false;
@ -777,15 +762,11 @@ void TabListOverlay_Show(void) {
*#########################################################################################################################*/
static struct ChatScreen {
Screen_Body
float chatAcc;
cc_bool suppressNextPress;
int chatIndex, paddingX, paddingY;
int lastDownloadStatus;
int lastDownloadStatus, uiOffset;
struct FontDesc chatFont, announcementFont, bigAnnouncementFont, smallAnnouncementFont;
struct TextWidget announcement, bigAnnouncement, smallAnnouncement;
struct ChatInputWidget input;
struct TextGroupWidget status, bottomRight, chat, clientStatus;
struct SpecialInputWidget altText;
#ifdef CC_BUILD_TOUCH
struct ButtonWidget send, cancel, more;
#endif
@ -806,27 +787,15 @@ static struct Widget* chat_widgets[] = {
};
static void ChatScreen_UpdateChatYOffsets(struct ChatScreen* s) {
int pad, y;
/* Determining chat Y requires us to know hotbar's position */
HUDScreen_LayoutHotbar();
y = min(s->input.base.y, Gui_HUD->hotbar.y);
y -= s->input.base.yOffset; /* add some padding */
s->altText.yOffset = WindowInfo.Height - y;
Widget_Layout(&s->altText);
static void ChatScreen_UpdateChatYOffsets(void) {
struct ChatScreen* s = &ChatScreen_Instance;
pad = s->altText.active ? 5 : 10;
s->clientStatus.yOffset = WindowInfo.Height - s->altText.y + pad;
s->clientStatus.yOffset = s->uiOffset + 10; /* Max height of hotbar and chat input */
Widget_Layout(&s->clientStatus);
s->chat.yOffset = s->clientStatus.yOffset + s->clientStatus.height;
Widget_Layout(&s->chat);
}
static void ChatScreen_OnInputTextChanged(void* elem) {
ChatScreen_UpdateChatYOffsets(&ChatScreen_Instance);
}
static cc_string ChatScreen_GetChat(int i) {
i += ChatScreen_Instance.chatIndex;
@ -847,6 +816,7 @@ static void ChatScreen_FreeChatFonts(struct ChatScreen* s) {
Font_Free(&s->smallAnnouncementFont);
}
static void ChatInputScreen_OnFontChanged(void);
static cc_bool ChatScreen_ChatUpdateFont(struct ChatScreen* s) {
int size = (int)(8 * Gui_GetChatScale());
Math_Clamp(size, 8, 60);
@ -863,11 +833,12 @@ static cc_bool ChatScreen_ChatUpdateFont(struct ChatScreen* s) {
Font_Make(&s->bigAnnouncementFont, size * 1.33, FONT_FLAGS_NONE);
Font_Make(&s->smallAnnouncementFont, size * 0.67, FONT_FLAGS_NONE);
ChatInputWidget_SetFont(&s->input, &s->chatFont);
TextGroupWidget_SetFont(&s->status, &s->chatFont);
TextGroupWidget_SetFont(&s->bottomRight, &s->chatFont);
TextGroupWidget_SetFont(&s->chat, &s->chatFont);
TextGroupWidget_SetFont(&s->clientStatus, &s->chatFont);
ChatInputScreen_OnFontChanged();
return true;
}
@ -879,9 +850,6 @@ static void ChatScreen_Redraw(struct ChatScreen* s) {
TextGroupWidget_RedrawAll(&s->status);
TextGroupWidget_RedrawAll(&s->bottomRight);
TextGroupWidget_RedrawAll(&s->clientStatus);
if (s->grabsInput) InputWidget_UpdateText(&s->input.base);
SpecialInputWidget_Redraw(&s->altText);
}
static int ChatScreen_ClampChatIndex(int index) {
@ -891,7 +859,8 @@ static int ChatScreen_ClampChatIndex(int index) {
return index;
}
static void ChatScreen_ScrollChatBy(struct ChatScreen* s, int delta) {
static void ChatScreen_ScrollChatBy(int delta) {
struct ChatScreen* s = &ChatScreen_Instance;
int newIndex = ChatScreen_ClampChatIndex(s->chatIndex + delta);
delta = newIndex - s->chatIndex;
@ -908,44 +877,25 @@ static void ChatScreen_ScrollChatBy(struct ChatScreen* s, int delta) {
}
}
static void ChatScreen_EnterChatInput(struct ChatScreen* s, cc_bool close) {
struct InputWidget* input;
int defaultIndex;
s->grabsInput = false;
Gui_UpdateInputGrab();
Window_CloseKeyboard();
if (close) InputWidget_Clear(&s->input.base);
input = &s->input.base;
input->OnPressedEnter(input);
SpecialInputWidget_SetActive(&s->altText, false);
ChatScreen_UpdateChatYOffsets(s);
static void ChatScreen_ResetScroll(void) {
struct ChatScreen* s = &ChatScreen_Instance;
/* Reset chat when user has scrolled up in chat history */
defaultIndex = Chat_Log.count - Gui.Chatlines;
if (s->chatIndex != defaultIndex) {
s->chatIndex = defaultIndex;
TextGroupWidget_RedrawAll(&s->chat);
}
int defaultIndex = Chat_Log.count - Gui.Chatlines;
if (s->chatIndex == defaultIndex) return;
s->chatIndex = defaultIndex;
TextGroupWidget_RedrawAll(&s->chat);
s->dirty = true;
}
static void ChatScreen_ColCodeChanged(void* screen, int code) {
struct ChatScreen* s = (struct ChatScreen*)screen;
double caretAcc;
if (Gfx.LostContext) return;
SpecialInputWidget_UpdateCols(&s->altText);
TextGroupWidget_RedrawAllWithCol(&s->chat, code);
TextGroupWidget_RedrawAllWithCol(&s->status, code);
TextGroupWidget_RedrawAllWithCol(&s->bottomRight, code);
TextGroupWidget_RedrawAllWithCol(&s->clientStatus, code);
/* Some servers have plugins that redefine colours constantly */
/* Preserve caret accumulator so caret blinking stays consistent */
caretAcc = s->input.base.caretAccumulator;
InputWidget_UpdateText(&s->input.base);
s->input.base.caretAccumulator = caretAcc;
}
static void ChatScreen_ChatReceived(void* screen, const cc_string* msg, int type) {
@ -972,7 +922,7 @@ static void ChatScreen_ChatReceived(void* screen, const cc_string* msg, int type
TextWidget_Set(&s->smallAnnouncement, msg, &s->smallAnnouncementFont);
} else if (type >= MSG_TYPE_CLIENTSTATUS_1 && type <= MSG_TYPE_CLIENTSTATUS_2) {
TextGroupWidget_Redraw(&s->clientStatus, type - MSG_TYPE_CLIENTSTATUS_1);
ChatScreen_UpdateChatYOffsets(s);
ChatScreen_UpdateChatYOffsets();
} else if (type >= MSG_TYPE_EXTRASTATUS_1 && type <= MSG_TYPE_EXTRASTATUS_2) {
/* Status[0] is for texture pack downloading message */
/* Status[1] is for reduced performance mode message */
@ -1045,92 +995,25 @@ static void ChatScreen_DrawChatBackground(struct ChatScreen* s) {
}
}
static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) {
struct Texture tex;
double now;
int i, logIdx;
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
Gfx_BindDynamicVb(s->vb);
if (!Game_PureClassic) { Widget_Render2(&s->status); }
Widget_Render2(&s->bottomRight);
Widget_Render2(&s->clientStatus);
now = Game.Time;
if (s->grabsInput) {
Widget_Render2(&s->chat);
} else {
/* Only render recent chat */
for (i = 0; i < s->chat.lines; i++) {
tex = s->chat.textures[i];
logIdx = s->chatIndex + i;
if (!tex.ID) continue;
if (logIdx < 0 || logIdx >= Chat_Log.count) continue;
if (Chat_GetLogTime(logIdx) + 10 < now) continue;
Gfx_BindTexture(tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, s->chat.offset + i * 4);
}
}
Widget_Render2(&s->announcement);
Widget_Render2(&s->bigAnnouncement);
Widget_Render2(&s->smallAnnouncement);
if (s->grabsInput) {
Elem_Render(&s->input.base, delta);
if (s->altText.active) {
Elem_Render(&s->altText, delta);
}
#ifdef CC_BUILD_TOUCH
if (!Input_TouchMode) return;
Elem_Render(&s->more, delta);
Elem_Render(&s->send, delta);
Elem_Render(&s->cancel, delta);
#endif
}
}
static void ChatScreen_ContextLost(void* screen) {
struct ChatScreen* s = (struct ChatScreen*)screen;
ChatScreen_FreeChatFonts(s);
Screen_ContextLost(s);
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);
Elem_Free(&s->bigAnnouncement);
Elem_Free(&s->smallAnnouncement);
#ifdef CC_BUILD_TOUCH
Elem_Free(&s->more);
Elem_Free(&s->send);
Elem_Free(&s->cancel);
#endif
}
static void ChatScreen_ContextRecreated(void* screen) {
struct ChatScreen* s = (struct ChatScreen*)screen;
struct FontDesc font;
ChatScreen_ChatUpdateFont(s);
ChatScreen_Redraw(s);
Screen_UpdateVb(s);
#ifdef CC_BUILD_TOUCH
if (!Input_TouchMode) return;
Gui_MakeTitleFont(&font);
ButtonWidget_SetConst(&s->more, "More", &font);
ButtonWidget_SetConst(&s->send, "Send", &font);
ButtonWidget_SetConst(&s->cancel, "Cancel", &font);
Font_Free(&font);
#endif
}
static void ChatScreen_Layout(void* screen) {
@ -1140,13 +1023,11 @@ static void ChatScreen_Layout(void* screen) {
s->paddingX = Display_ScaleX(5);
s->paddingY = Display_ScaleY(5);
Widget_SetLocation(&s->input.base, ANCHOR_MIN, ANCHOR_MAX, 5, 5);
Widget_SetLocation(&s->altText, ANCHOR_MIN, ANCHOR_MAX, 5, 5);
Widget_SetLocation(&s->status, ANCHOR_MAX, ANCHOR_MIN, 0, 0);
Widget_SetLocation(&s->bottomRight, ANCHOR_MAX, ANCHOR_MAX, 0, 0);
Widget_SetLocation(&s->chat, ANCHOR_MIN, ANCHOR_MAX, 10, 0);
Widget_SetLocation(&s->clientStatus, ANCHOR_MIN, ANCHOR_MAX, 10, 0);
ChatScreen_UpdateChatYOffsets(s);
ChatScreen_UpdateChatYOffsets();
/* Can't use Widget_SetLocation because it DPI scales input */
s->bottomRight.yOffset = HUDScreen_LayoutHotbar() + Display_ScaleY(15);
@ -1163,81 +1044,20 @@ static void ChatScreen_Layout(void* screen) {
Widget_SetLocation(&s->smallAnnouncement, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 0);
s->smallAnnouncement.yOffset = WindowInfo.Height / 20;
Widget_Layout(&s->smallAnnouncement);
#ifdef CC_BUILD_TOUCH
if (WindowInfo.SoftKeyboard == SOFT_KEYBOARD_SHIFT) {
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MAX, 10, 60);
Widget_SetLocation(&s->cancel, ANCHOR_MAX, ANCHOR_MAX, 10, 10);
Widget_SetLocation(&s->more, ANCHOR_MAX, ANCHOR_MAX, 10, 110);
} else {
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MIN, 10, 10);
Widget_SetLocation(&s->cancel, ANCHOR_MAX, ANCHOR_MIN, 10, 60);
Widget_SetLocation(&s->more, ANCHOR_MAX, ANCHOR_MIN, 10, 110);
}
#endif
}
static int ChatScreen_KeyPress(void* screen, char keyChar) {
struct ChatScreen* s = (struct ChatScreen*)screen;
if (!s->grabsInput) return false;
if (s->suppressNextPress) {
s->suppressNextPress = false;
return false;
}
InputWidget_Append(&s->input.base, keyChar);
return true;
}
static int ChatScreen_TextChanged(void* screen, const cc_string* str) {
#ifdef CC_BUILD_TOUCH
struct ChatScreen* s = (struct ChatScreen*)screen;
if (!s->grabsInput) return false;
InputWidget_SetText(&s->input.base, str);
#endif
return true;
}
static int ChatScreen_KeyDown(void* screen, int key) {
static const cc_string slash = String_FromConst("/");
struct ChatScreen* s = (struct ChatScreen*)screen;
int playerListKey = KeyBinds[KEYBIND_TABLIST];
cc_bool handlesList = playerListKey != KEY_TAB || !Gui.TabAutocomplete || !s->grabsInput;
if (key == playerListKey && handlesList) {
if (key == KeyBinds[KEYBIND_TABLIST]) {
if (!TabListOverlay_Instance.active && !Server.IsSinglePlayer) {
TabListOverlay_Show();
TabListOverlay_Show(); /* TODO return true*/
}
return true;
}
s->suppressNextPress = false;
/* Handle chat text input */
if (s->grabsInput) {
#ifdef CC_BUILD_WEB
/* See reason for this in HandleInputUp */
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == KEY_KP_ENTER) {
ChatScreen_EnterChatInput(s, false);
#else
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == KEY_KP_ENTER || key == KEY_ESCAPE) {
ChatScreen_EnterChatInput(s, key == KEY_ESCAPE);
#endif
} else if (key == KEY_PAGEUP) {
ChatScreen_ScrollChatBy(s, -Gui.Chatlines);
} else if (key == KEY_PAGEDOWN) {
ChatScreen_ScrollChatBy(s, +Gui.Chatlines);
} else {
Elem_HandlesKeyDown(&s->input.base, key);
}
return key < KEY_F1 || key > KEY_F24;
}
if (key == KeyBinds[KEYBIND_CHAT]) {
ChatScreen_OpenInput(&String_Empty);
} else if (key == KeyBinds[KEYBIND_CHAT]) {
ChatInputScreen_Open(&String_Empty);
} else if (key == KEY_SLASH) {
ChatScreen_OpenInput(&slash);
ChatInputScreen_Open(&slash);
} else if (key == KeyBinds[KEYBIND_INVENTORY]) {
InventoryScreen_Show();
} else {
@ -1246,99 +1066,26 @@ static int ChatScreen_KeyDown(void* screen, int key) {
return true;
}
static void ChatScreen_ToggleAltInput(struct ChatScreen* s) {
SpecialInputWidget_SetActive(&s->altText, !s->altText.active);
ChatScreen_UpdateChatYOffsets(s);
}
static void ChatScreen_KeyUp(void* screen, int key) {
struct ChatScreen* s = (struct ChatScreen*)screen;
if (!s->grabsInput || (struct Screen*)s != Gui.InputGrab) return;
#ifdef CC_BUILD_WEB
/* See reason for this in HandleInputUp */
if (key == KEY_ESCAPE) ChatScreen_EnterChatInput(s, true);
#endif
if (Server.SupportsFullCP437 && key == KeyBinds[KEYBIND_EXT_INPUT]) {
if (!WindowInfo.Focused) return;
ChatScreen_ToggleAltInput(s);
}
}
static int ChatScreen_MouseScroll(void* screen, float delta) {
struct ChatScreen* s = (struct ChatScreen*)screen;
int steps;
if (!s->grabsInput) return false;
steps = Utils_AccumulateWheelDelta(&s->chatAcc, delta);
ChatScreen_ScrollChatBy(s, -steps);
return true;
}
static int ChatScreen_PointerDown(void* screen, int id, int x, int y) {
cc_string text; char textBuffer[STRING_SIZE * 4];
struct ChatScreen* s = (struct ChatScreen*)screen;
int height, chatY, i;
int i;
if (Game_HideGui) return false;
if (!s->grabsInput) {
if (!Input_TouchMode) return false;
String_InitArray(text, textBuffer);
/* Should be able to click on links with touch */
i = TextGroupWidget_GetSelected(&s->chat, &text, x, y);
if (!Utils_IsUrlPrefix(&text)) return false;
if (Chat_GetLogTime(s->chatIndex + i) + 10 < Game.Time) return false;
UrlWarningOverlay_Show(&text); return TOUCH_TYPE_GUI;
}
#ifdef CC_BUILD_TOUCH
if (Input_TouchMode) {
if (Widget_Contains(&s->send, x, y)) {
ChatScreen_EnterChatInput(s, false); return TOUCH_TYPE_GUI;
}
if (Widget_Contains(&s->cancel, x, y)) {
ChatScreen_EnterChatInput(s, true); return TOUCH_TYPE_GUI;
}
if (Widget_Contains(&s->more, x, y)) {
ChatScreen_ToggleAltInput(s); return TOUCH_TYPE_GUI;
}
}
#endif
if (!Widget_Contains(&s->chat, x, y)) {
if (s->altText.active && Widget_Contains(&s->altText, x, y)) {
Elem_HandlesPointerDown(&s->altText, id, x, y);
ChatScreen_UpdateChatYOffsets(s);
return TOUCH_TYPE_GUI;
}
Elem_HandlesPointerDown(&s->input.base, id, x, y);
return TOUCH_TYPE_GUI;
}
height = TextGroupWidget_UsedHeight(&s->chat);
chatY = s->chat.y + s->chat.height - height;
if (!Gui_Contains(s->chat.x, chatY, s->chat.width, height, x, y)) return false;
if (!Input_TouchMode) return false;
String_InitArray(text, textBuffer);
TextGroupWidget_GetSelected(&s->chat, &text, x, y);
if (!text.length) return false;
if (Utils_IsUrlPrefix(&text)) {
UrlWarningOverlay_Show(&text);
} else if (Gui.ClickableChat) {
ChatScreen_AppendInput(&text);
}
/* Should be able to click on links with touch */
i = TextGroupWidget_GetSelected(&s->chat, &text, x, y);
if (!Utils_IsUrlPrefix(&text)) return false;
if (Chat_GetLogTime(s->chatIndex + i) + 10 < Game.Time) return false;
UrlWarningOverlay_Show(&text);
return TOUCH_TYPE_GUI;
}
static void ChatScreen_Init(void* screen) {
struct ChatScreen* s = (struct ChatScreen*)screen;
ChatInputWidget_Create(&s->input);
s->input.base.OnTextChanged = ChatScreen_OnInputTextChanged;
SpecialInputWidget_Create(&s->altText, &s->chatFont, &s->input.base);
TextGroupWidget_Create(&s->status, CHAT_MAX_STATUS,
s->statusTextures, ChatScreen_GetStatus);
@ -1374,18 +1121,49 @@ static void ChatScreen_Init(void* screen) {
#endif
}
static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) {
struct Texture tex;
double now;
int i, logIdx;
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
Gfx_BindDynamicVb(s->vb);
if (!Game_PureClassic) { Widget_Render2(&s->status); }
Widget_Render2(&s->bottomRight);
Widget_Render2(&s->clientStatus);
now = Game.Time;
if (ChatInputScreen_IsActive()) {
Widget_Render2(&s->chat);
} else {
/* Only render recent chat */
for (i = 0; i < s->chat.lines; i++) {
tex = s->chat.textures[i];
logIdx = s->chatIndex + i;
if (!tex.ID) continue;
if (logIdx < 0 || logIdx >= Chat_Log.count) continue;
if (Chat_GetLogTime(logIdx) + 10 < now) continue;
Gfx_BindTexture(tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, s->chat.offset + i * 4);
}
}
Widget_Render2(&s->announcement);
Widget_Render2(&s->bigAnnouncement);
Widget_Render2(&s->smallAnnouncement);
}
static void ChatScreen_Render(void* screen, double delta) {
struct ChatScreen* s = (struct ChatScreen*)screen;
if (Game_HideGui && s->grabsInput) {
Elem_Render(&s->input.base, delta);
}
if (Game_HideGui) return;
if (!TabListOverlay_Instance.active && !Gui_GetBlocksWorld()) {
ChatScreen_DrawCrosshairs();
}
if (s->grabsInput && !Gui.ClassicChat) {
if (ChatInputScreen_IsActive() && !Gui.ClassicChat) {
ChatScreen_DrawChatBackground(s);
}
@ -1401,8 +1179,8 @@ static void ChatScreen_Free(void* screen) {
static const struct ScreenVTABLE ChatScreen_VTABLE = {
ChatScreen_Init, ChatScreen_Update, ChatScreen_Free,
ChatScreen_Render, Screen_BuildMesh,
ChatScreen_KeyDown, ChatScreen_KeyUp, ChatScreen_KeyPress, ChatScreen_TextChanged,
ChatScreen_PointerDown, Screen_PointerUp, Screen_FPointer, ChatScreen_MouseScroll,
ChatScreen_KeyDown, Screen_FInput, Screen_FKeyPress, Screen_FText,
ChatScreen_PointerDown, Screen_PointerUp, Screen_FPointer, Screen_FMouseScroll,
ChatScreen_Layout, ChatScreen_ContextLost, ChatScreen_ContextRecreated
};
void ChatScreen_Show(void) {
@ -1410,38 +1188,369 @@ void ChatScreen_Show(void) {
s->lastDownloadStatus = HTTP_PROGRESS_NOT_WORKING_ON;
s->VTABLE = &ChatScreen_VTABLE;
Gui_Chat = s;
Gui_Add((struct Screen*)s, GUI_PRIORITY_CHAT);
}
void ChatScreen_OpenInput(const cc_string* text) {
struct ChatScreen* s = &ChatScreen_Instance;
struct OpenKeyboardArgs args;
s->suppressNextPress = true;
s->grabsInput = true;
Gui_UpdateInputGrab();
OpenKeyboardArgs_Init(&args, text, KEYBOARD_TYPE_TEXT | KEYBOARD_FLAG_SEND);
args.placeholder = "Enter chat";
args.multiline = true;
Window_OpenKeyboard(&args);
s->input.base.disabled = args.opaque;
String_Copy(&s->input.base.text, text);
InputWidget_UpdateText(&s->input.base);
}
void ChatScreen_AppendInput(const cc_string* text) {
struct ChatScreen* s = &ChatScreen_Instance;
InputWidget_AppendText(&s->input.base, text);
}
void ChatScreen_SetChatlines(int lines) {
struct ChatScreen* s = &ChatScreen_Instance;
Elem_Free(&s->chat);
s->chatIndex += s->chat.lines - lines;
s->chat.lines = lines;
TextGroupWidget_RedrawAll(&s->chat);
s->dirty = true;
}
/*########################################################################################################################*
*-----------------------------------------------------ChatInputScreen-----------------------------------------------------*
*#########################################################################################################################*/
static struct ChatInputScreen {
Screen_Body
float chatAcc;
cc_bool suppressNextPress, active;
struct ChatInputWidget input;
struct SpecialInputWidget altText;
#ifdef CC_BUILD_TOUCH
struct ButtonWidget send, cancel, more;
#endif
} ChatInputScreen;
static struct Widget* chatinput_widgets[] = {
(struct Widget*)&ChatInputScreen.input, (struct Widget*)&ChatInputScreen.altText,
#ifdef CC_BUILD_TOUCH
(struct Widget*)&ChatInputScreen.send, (struct Widget*)&ChatInputScreen.cancel,
(struct Widget*)&ChatInputScreen.more
#endif
};
#define CHATINPUT_MAX_VERTICES MENUINPUTWIDGET_MAX + 4 /* TODO replace.. */
static cc_bool ChatInputScreen_IsActive(void) { return ChatInputScreen.active; }
static cc_bool IsOnlyChatActive(void) {
struct Screen* s;
int i;
for (i = 0; i < Gui.ScreensCount; i++) {
s = Gui_Screens[i];
if (s->grabsInput && s != (struct Screen*)&ChatInputScreen) return false;
}
return true;
}
static void ChatInputScreen_UpdateYOffsets(void) {
struct ChatInputScreen* s = &ChatInputScreen;
int y;
/* Determining input Y requires us to know hotbar's position */
HUDScreen_LayoutHotbar();
y = min(s->input.base.y, HUDScreen.hotbar.y);
y -= s->input.base.yOffset; /* add some padding */
s->altText.yOffset = WindowInfo.Height - y;
Widget_Layout(&s->altText);
ChatScreen_Instance.uiOffset = WindowInfo.Height - s->altText.y;
ChatScreen_UpdateChatYOffsets();
}
static void ChatInputScreen_OnInputTextChanged(void* elem) {
ChatInputScreen_UpdateYOffsets();
}
static void ChatInputScreen_OnFontChanged(void) {
struct ChatInputScreen* s = &ChatInputScreen;
if (!s->altText.font) return; /* Chat input never created */
ChatInputWidget_SetFont(&s->input, &ChatScreen_Instance.chatFont);
InputWidget_UpdateText(&s->input.base);
SpecialInputWidget_Redraw(&s->altText);
ChatInputScreen_UpdateYOffsets();
}
static void ChatInputScreen_EnterInput(struct ChatInputScreen* s, cc_bool close) {
struct InputWidget* input;
Gui_UpdateInputGrab();
Window_CloseKeyboard();
if (close) InputWidget_Clear(&s->input.base);
input = &s->input.base;
input->OnPressedEnter(input);
SpecialInputWidget_SetActive(&s->altText, false);
ChatInputScreen_UpdateYOffsets();
ChatScreen_ResetScroll();
Gui_Remove((struct Screen*)s);
}
static void ChatInputScreen_ColorCodeChanged(void* screen, int code) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
double caretAcc;
if (Gfx.LostContext) return;
SpecialInputWidget_UpdateCols(&s->altText);
/* Some servers have plugins that redefine colours constantly */
/* Preserve caret accumulator so caret blinking stays consistent */
caretAcc = s->input.base.caretAccumulator;
InputWidget_UpdateText(&s->input.base);
s->input.base.caretAccumulator = caretAcc;
}
static void ChatInputScreen_ContextLost(void* screen) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
Screen_ContextLost(s);
Elem_Free(&s->input.base);
Elem_Free(&s->altText);
#ifdef CC_BUILD_TOUCH
Elem_Free(&s->more);
Elem_Free(&s->send);
Elem_Free(&s->cancel);
#endif
}
static void ChatInputScreen_ContextRecreated(void* screen) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
struct FontDesc font;
ChatInputScreen_OnFontChanged();
Screen_UpdateVb(s);
#ifdef CC_BUILD_TOUCH
if (!Input_TouchMode) return;
Gui_MakeTitleFont(&font);
ButtonWidget_SetConst(&s->more, "More", &font);
ButtonWidget_SetConst(&s->send, "Send", &font);
ButtonWidget_SetConst(&s->cancel, "Cancel", &font);
Font_Free(&font);
#endif
}
static void ChatInputScreen_Layout(void* screen) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
Widget_SetLocation(&s->input.base, ANCHOR_MIN, ANCHOR_MAX, 5, 5);
Widget_SetLocation(&s->altText, ANCHOR_MIN, ANCHOR_MAX, 5, 5);
ChatInputScreen_UpdateYOffsets();
#ifdef CC_BUILD_TOUCH
if (WindowInfo.SoftKeyboard == SOFT_KEYBOARD_SHIFT) {
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MAX, 10, 60);
Widget_SetLocation(&s->cancel, ANCHOR_MAX, ANCHOR_MAX, 10, 10);
Widget_SetLocation(&s->more, ANCHOR_MAX, ANCHOR_MAX, 10, 110);
} else {
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MIN, 10, 10);
Widget_SetLocation(&s->cancel, ANCHOR_MAX, ANCHOR_MIN, 10, 60);
Widget_SetLocation(&s->more, ANCHOR_MAX, ANCHOR_MIN, 10, 110);
}
#endif
}
static int ChatInputScreen_KeyPress(void* screen, char keyChar) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
if (s->suppressNextPress) {
s->suppressNextPress = false;
return false;
}
InputWidget_Append(&s->input.base, keyChar);
return true;
}
static int ChatInputScreen_TextChanged(void* screen, const cc_string* str) {
#ifdef CC_BUILD_TOUCH
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
InputWidget_SetText(&s->input.base, str);
#endif
return true;
}
static int ChatInputScreen_KeyDown(void* screen, int key) {
static const cc_string slash = String_FromConst("/");
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
int playerListKey = KeyBinds[KEYBIND_TABLIST];
cc_bool handlesList = playerListKey != KEY_TAB || !Gui.TabAutocomplete;
if (key == playerListKey && handlesList) {
if (!TabListOverlay_Instance.active && !Server.IsSinglePlayer) {
TabListOverlay_Show();
}
return true;
}
s->suppressNextPress = false;
/* Handle chat text input */
#ifdef CC_BUILD_WEB
/* See reason for this in HandleInputUp */
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == KEY_KP_ENTER) {
ChatInputScreen_EnterChatInput(s, false);
#else
if (key == KeyBinds[KEYBIND_SEND_CHAT] || key == KEY_KP_ENTER || key == KEY_ESCAPE) {
ChatInputScreen_EnterInput(s, key == KEY_ESCAPE);
#endif
} else if (key == KEY_PAGEUP) {
ChatScreen_ScrollChatBy(-Gui.Chatlines);
} else if (key == KEY_PAGEDOWN) {
ChatScreen_ScrollChatBy(+Gui.Chatlines);
} else {
Elem_HandlesKeyDown(&s->input.base, key);
}
return key < KEY_F1 || key > KEY_F24;
}
static void ChatInputScreen_KeyUp(void* screen, int key) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
if ((struct Screen*)s != Gui.InputGrab) return;
#ifdef CC_BUILD_WEB
/* See reason for this in HandleInputUp */
if (key == KEY_ESCAPE) ChatInputScreen_EnterChatInput(s, true);
#endif
if (Server.SupportsFullCP437 && key == KeyBinds[KEYBIND_EXT_INPUT]) {
if (!WindowInfo.Focused) return;
SpecialInputWidget_SetActive(&s->altText, !s->altText.active);
ChatInputScreen_UpdateYOffsets();
}
}
static int ChatInputScreen_MouseScroll(void* screen, float delta) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
int steps = Utils_AccumulateWheelDelta(&s->chatAcc, delta);
ChatScreen_ScrollChatBy(-steps);
return true;
}
static int ChatInputScreen_PointerDown(void* screen, int id, int x, int y) {
cc_string text; char textBuffer[STRING_SIZE * 4];
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
struct TextGroupWidget* chat = &ChatScreen_Instance.chat;
int height, chatY;
if (Game_HideGui) return false;
#ifdef CC_BUILD_TOUCH
if (Input_TouchMode) {
if (Widget_Contains(&s->send, x, y)) {
ChatInputScreen_EnterChatInput(s, false); return TOUCH_TYPE_GUI;
}
if (Widget_Contains(&s->cancel, x, y)) {
ChatInputScreen_EnterChatInput(s, true); return TOUCH_TYPE_GUI;
}
if (Widget_Contains(&s->more, x, y)) {
ChatInputScreen_ToggleAltInput(s); return TOUCH_TYPE_GUI;
}
}
#endif
if (!Widget_Contains(chat, x, y)) {
if (s->altText.active && Widget_Contains(&s->altText, x, y)) {
Elem_HandlesPointerDown(&s->altText, id, x, y);
ChatInputScreen_UpdateYOffsets();
return TOUCH_TYPE_GUI;
}
Elem_HandlesPointerDown(&s->input.base, id, x, y);
return TOUCH_TYPE_GUI;
}
height = TextGroupWidget_UsedHeight(chat);
chatY = chat->y + chat->height - height;
if (!Gui_Contains(chat->x, chatY, chat->width, height, x, y)) return false;
String_InitArray(text, textBuffer);
TextGroupWidget_GetSelected(chat, &text, x, y);
if (!text.length) return false;
if (Utils_IsUrlPrefix(&text)) {
UrlWarningOverlay_Show(&text);
} else if (Gui.ClickableChat) {
ChatInputScreen_Append(&text);
}
return TOUCH_TYPE_GUI;
}
static void ChatInputScreen_Init(void* screen) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
ChatInputWidget_Create(&s->input);
s->input.base.OnTextChanged = ChatInputScreen_OnInputTextChanged;
SpecialInputWidget_Create(&s->altText, &ChatScreen_Instance.chatFont, &s->input.base);
Event_Register_(&ChatEvents.ColCodeChanged, s, ChatInputScreen_ColorCodeChanged);
s->active = true;
s->maxVertices = CHATINPUT_MAX_VERTICES;
s->widgets = chatinput_widgets;
s->numWidgets = Array_Elems(chatinput_widgets);
#ifdef CC_BUILD_TOUCH
ButtonWidget_Init(&s->send, 100, NULL);
ButtonWidget_Init(&s->cancel, 100, NULL);
ButtonWidget_Init(&s->more, 100, NULL);
#endif
}
static void ChatInputScreen_Update(void* screen, double delta) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
s->input.base.caretAccumulator += delta;
if (s->altText.active && s->altText.pendingRedraw) {
SpecialInputWidget_Redraw(&s->altText);
s->dirty = true;
}
}
static void ChatInputScreen_Render(void* screen, double delta) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
ChatInputWidget_RenderBackground(&s->input);
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
Gfx_BindDynamicVb(s->vb);
Widget_Render2(&s->input.base);
if (Game_HideGui) return;
if (s->altText.active) Widget_Render2(&s->altText);
#ifdef CC_BUILD_TOUCH
if (!Input_TouchMode) return;
Widget_Render2(&s->more);
Widget_Render2(&s->send);
Widget_Render2(&s->cancel);
#endif
}
static void ChatInputScreen_Free(void* screen) {
struct ChatInputScreen* s = (struct ChatInputScreen*)screen;
Event_Unregister_(&ChatEvents.ColCodeChanged, s, ChatInputScreen_ColorCodeChanged);
s->active = false;
}
static const struct ScreenVTABLE ChatInputScreen_VTABLE = {
ChatInputScreen_Init, ChatInputScreen_Update, ChatInputScreen_Free,
ChatInputScreen_Render, Screen_BuildMesh,
ChatInputScreen_KeyDown, ChatInputScreen_KeyUp, ChatInputScreen_KeyPress, ChatInputScreen_TextChanged,
ChatInputScreen_PointerDown, Screen_PointerUp, Screen_FPointer, ChatInputScreen_MouseScroll,
ChatInputScreen_Layout, ChatInputScreen_ContextLost, ChatInputScreen_ContextRecreated
};
void ChatInputScreen_Open(const cc_string* text) {
struct ChatInputScreen* s = &ChatInputScreen;
struct OpenKeyboardArgs args;
s->VTABLE = &ChatInputScreen_VTABLE;
OpenKeyboardArgs_Init(&args, text, KEYBOARD_TYPE_TEXT | KEYBOARD_FLAG_SEND);
args.placeholder = "Enter chat";
args.multiline = true;
Window_OpenKeyboard(&args);
s->suppressNextPress = true;
s->grabsInput = true;
Gui_Add((struct Screen*)s, GUI_PRIORITY_CHATINPUT);
s->input.base.disabled = args.opaque;
String_Copy(&s->input.base.text, text);
InputWidget_UpdateText(&s->input.base);
}
void ChatInputScreen_Append(const cc_string* text) {
struct ChatInputScreen* s = &ChatInputScreen;
InputWidget_AppendText(&s->input.base, text);
}
@ -1571,7 +1680,7 @@ static int InventoryScreen_KeyDown(void* screen, int key) {
Gui_Remove((struct Screen*)s);
} else if (Elem_HandlesKeyDown(table, key)) {
} else {
return Elem_HandlesKeyDown(&HUDScreen_Instance.hotbar, key);
return Elem_HandlesKeyDown(&HUDScreen.hotbar, key);
}
return true;
}
@ -1593,7 +1702,7 @@ static int InventoryScreen_PointerDown(void* screen, int id, int x, int y) {
cc_bool handled, hotbar;
if (table->scroll.draggingId == id) return TOUCH_TYPE_GUI;
if (HUDscreen_PointerDown(Gui_HUD, id, x, y)) return TOUCH_TYPE_GUI;
if (HUDscreen_PointerDown(&HUDScreen, id, x, y)) return TOUCH_TYPE_GUI;
handled = Elem_HandlesPointerDown(table, id, x, y);
if (!handled || table->pendingClose) {

View file

@ -35,9 +35,9 @@ void TouchScreen_Show(void);
#endif
/* Opens chat input for the HUD with the given initial text. */
void ChatScreen_OpenInput(const cc_string* text);
void ChatInputScreen_Open(const cc_string* text);
/* Appends text to the chat input in the HUD. */
void ChatScreen_AppendInput(const cc_string* text);
void ChatInputScreen_Append(const cc_string* text);
/* Sets number of visible lines in the main chat widget. */
void ChatScreen_SetChatlines(int lines);
#endif

View file

@ -125,42 +125,6 @@ static void ButtonWidget_Reposition(void* widget) {
w->tex.Y = w->y + (w->height / 2 - w->tex.Height / 2);
}
static void ButtonWidget_Render(void* widget, double delta) {
struct Texture back;
PackedCol color;
float scale;
struct ButtonWidget* w = (struct ButtonWidget*)widget;
back = w->active ? btnSelectedTex : btnShadowTex;
if (w->disabled) back = btnDisabledTex;
back.ID = Gui.ClassicTexture ? Gui.GuiClassicTex : Gui.GuiTex;
back.X = w->x; back.Width = w->width;
back.Y = w->y; back.Height = w->height;
/* TODO: Does this 400 need to take DPI into account */
if (w->width >= 400) {
/* Button can be drawn normally */
Texture_Render(&back);
} else {
/* Split button down the middle */
scale = (w->width / 400.0f) / (2 * DisplayInfo.ScaleX);
Gfx_BindTexture(back.ID); /* avoid bind twice */
back.Width = (w->width / 2);
back.uv.U1 = 0.0f; back.uv.U2 = BUTTON_uWIDTH * scale;
Gfx_Draw2DTexture(&back, w->color);
back.X += (w->width / 2);
back.uv.U1 = BUTTON_uWIDTH * (1.0f - scale); back.uv.U2 = BUTTON_uWIDTH;
Gfx_Draw2DTexture(&back, w->color);
}
if (!w->tex.ID) return;
color = w->disabled ? BTN_DISABLED_COLOR : (w->active ? BTN_ACTIVE_COLOR : BTN_NORMAL_COLOR);
Texture_RenderShaded(&w->tex, color);
}
static struct VertexTextured* ButtonWidget_BuildMesh(void* widget,
struct VertexTextured* vertices, struct VertexTextured* beg) {
struct Texture back;
@ -202,14 +166,13 @@ static void ButtonWidget_Render2(void* widget) {
/* TODO: Does this 400 need to take DPI into account */
Gfx_DrawVb_IndexedTris_Range(w->width >= 400 ? 4 : 8, w->offset);
if (w->tex.ID) {
Gfx_BindTexture(w->tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, w->offset + 8);
}
if (!w->tex.ID) return;
Gfx_BindTexture(w->tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, w->offset + 8);
}
static const struct WidgetVTABLE ButtonWidget_VTABLE = {
ButtonWidget_Render, ButtonWidget_Free, ButtonWidget_Reposition,
NULL, ButtonWidget_Free, ButtonWidget_Reposition,
Widget_InputDown, Widget_InputUp, Widget_MouseScroll,
Widget_Pointer, Widget_PointerUp, Widget_PointerMove,
ButtonWidget_BuildMesh, ButtonWidget_Render2
@ -997,7 +960,7 @@ static void InputWidget_CalculateLineSizes(struct InputWidget* w) {
}
}
static char InputWidget_GetLastCol(struct InputWidget* w, int x, int y) {
static char InputWidget_GetLastColor(struct InputWidget* w, int x, int y) {
cc_string line; char lineBuffer[STRING_SIZE];
char col;
String_InitArray(line, lineBuffer);
@ -1055,7 +1018,7 @@ static void InputWidget_UpdateCaret(struct InputWidget* w) {
w->caretTex.X = w->x + w->padding + lineWidth;
w->caretTex.Y = (w->inputTex.Y + w->caretOffset) + w->caretY * w->lineHeight;
colCode = InputWidget_GetLastCol(w, w->caretX, w->caretY);
colCode = InputWidget_GetLastColor(w, w->caretX, w->caretY);
if (colCode) {
col = Drawer2D_GetColor(colCode);
@ -1067,15 +1030,6 @@ static void InputWidget_UpdateCaret(struct InputWidget* w) {
}
}
static void InputWidget_RenderCaret(struct InputWidget* w, double delta) {
float second;
if (!w->showCaret) return;
w->caretAccumulator += delta;
second = Math_Mod1((float)w->caretAccumulator);
if (second < 0.5f) Texture_RenderShaded(&w->caretTex, w->caretCol);
}
static void InputWidget_OnPressedEnter(void* widget) {
struct InputWidget* w = (struct InputWidget*)widget;
InputWidget_Clear(w);
@ -1470,12 +1424,6 @@ const struct MenuInputVTABLE StringInput_VTABLE = {
/*########################################################################################################################*
*-----------------------------------------------------TextInputWidget-----------------------------------------------------*
*#########################################################################################################################*/
static void TextInputWidget_Render(void* widget, double delta) {
struct InputWidget* w = (struct InputWidget*)widget;
Texture_Render(&w->inputTex);
InputWidget_RenderCaret(w, delta);
}
static struct VertexTextured* TextInputWidget_BuildMesh(void* widget,
struct VertexTextured* vertices, struct VertexTextured* beg) {
struct InputWidget* w = (struct InputWidget*)widget;
@ -1581,7 +1529,7 @@ static int TextInputWidget_PointerDown(void* widget, int id, int x, int y) {
static int TextInputWidget_GetMaxLines(void) { return 1; }
static const struct WidgetVTABLE TextInputWidget_VTABLE = {
TextInputWidget_Render, InputWidget_Free, InputWidget_Reposition,
NULL, InputWidget_Free, InputWidget_Reposition,
InputWidget_KeyDown, Widget_InputUp, Widget_MouseScroll,
TextInputWidget_PointerDown, Widget_PointerUp, Widget_PointerMove,
TextInputWidget_BuildMesh, TextInputWidget_Render2
@ -1621,6 +1569,28 @@ void TextInputWidget_SetFont(struct TextInputWidget* w, struct FontDesc* font) {
*#########################################################################################################################*/
static const cc_string chatInputPrefix = String_FromConst("> ");
static struct VertexTextured* ChatInputWidget_BuildMesh(void* widget,
struct VertexTextured* vertices, struct VertexTextured* beg) {
struct InputWidget* w = (struct InputWidget*)widget;
w->offset = Widget_CalcVertexOffset(vertices, beg);
Gfx_Make2DQuad(&w->inputTex, PACKEDCOL_WHITE, vertices + 0);
Gfx_Make2DQuad(&w->caretTex, w->caretCol, vertices + 4);
return vertices + 8;
}
static void ChatInputWidget_Render2(void* widget) {
struct InputWidget* w = (struct InputWidget*)widget;
Gfx_BindTexture(w->inputTex.ID);
Gfx_DrawVb_IndexedTris_Range(4, w->offset);
if (w->showCaret && Math_Mod1((float)w->caretAccumulator) < 0.5f) {
Gfx_BindTexture(w->caretTex.ID);
Gfx_DrawVb_IndexedTris_Range(4, w->offset + 4);
}
}
static void ChatInputWidget_MakeTexture(struct InputWidget* w, int width, int height) {
cc_string line; char lineBuffer[STRING_SIZE + 2];
struct DrawTextArgs args;
@ -1639,7 +1609,7 @@ static void ChatInputWidget_MakeTexture(struct InputWidget* w, int width, int he
line.length = 0;
/* Color code continues in next line */
lastCol = InputWidget_GetLastCol(w, 0, i);
lastCol = InputWidget_GetLastColor(w, 0, i);
if (!Drawer2D_IsWhiteColor(lastCol)) {
String_Append(&line, '&'); String_Append(&line, lastCol);
}
@ -1684,7 +1654,7 @@ static void ChatInputWidget_RemakeTexture(void* widget) {
w->inputTex.Y = w->y;
}
static void ChatInputWidget_Render(void* widget, double delta) {
void ChatInputWidget_RenderBackground(void* widget) {
struct InputWidget* w = (struct InputWidget*)widget;
PackedCol backColor = PackedCol_Make(0, 0, 0, 127);
int x = w->x, y = w->y;
@ -1703,9 +1673,6 @@ static void ChatInputWidget_Render(void* widget, double delta) {
Gfx_Draw2DFlat(x, y, width + w->padding * 2, w->lineHeight, backColor);
y += w->lineHeight;
}
Texture_Render(&w->inputTex);
InputWidget_RenderCaret(w, delta);
}
static void ChatInputWidget_OnPressedEnter(void* widget) {
@ -1856,9 +1823,10 @@ static int ChatInputWidget_GetMaxLines(void) {
}
static const struct WidgetVTABLE ChatInputWidget_VTABLE = {
ChatInputWidget_Render, InputWidget_Free, InputWidget_Reposition,
ChatInputWidget_KeyDown, Widget_InputUp, Widget_MouseScroll,
InputWidget_PointerDown, Widget_PointerUp, Widget_PointerMove
NULL, InputWidget_Free, InputWidget_Reposition,
ChatInputWidget_KeyDown, Widget_InputUp, Widget_MouseScroll,
InputWidget_PointerDown, Widget_PointerUp, Widget_PointerMove,
ChatInputWidget_BuildMesh, ChatInputWidget_Render2
};
void ChatInputWidget_Create(struct ChatInputWidget* w) {
InputWidget_Reset(&w->base);
@ -2531,14 +2499,28 @@ static int SpecialInputWidget_PointerDown(void* widget, int id, int x, int y) {
return TOUCH_TYPE_GUI;
}
static struct VertexTextured* SpecialInputWidget_BuildMesh(void* widget,
struct VertexTextured* vertices, struct VertexTextured* beg) {
struct SpecialInputWidget* w = (struct SpecialInputWidget*)widget;
w->offset = Widget_CalcVertexOffset(vertices, beg);
Gfx_Make2DQuad(&w->tex, PACKEDCOL_WHITE, vertices);
return vertices + 8;
}
static void SpecialInputWidget_Render2(void* widget) {
struct SpecialInputWidget* w = (struct SpecialInputWidget*)widget;
Gfx_BindTexture(w->tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, w->offset);
}
void SpecialInputWidget_UpdateCols(struct SpecialInputWidget* w) {
SpecialInputWidget_UpdateColString(w);
w->tabs[0].contents = w->colString;
if (w->selectedIndex != 0) return;
/* defer updating colours tab until visible */
if (!w->active) { w->pendingRedraw = true; return; }
SpecialInputWidget_Redraw(w);
/* Currently displaying colours tab */
if (w->active) w->pendingRedraw = true;
}
void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, cc_bool active) {
@ -2548,9 +2530,10 @@ void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, cc_bool active)
}
static const struct WidgetVTABLE SpecialInputWidget_VTABLE = {
SpecialInputWidget_Render, SpecialInputWidget_Free, SpecialInputWidget_Reposition,
NULL, SpecialInputWidget_Free, SpecialInputWidget_Reposition,
Widget_InputDown, Widget_InputUp, Widget_MouseScroll,
SpecialInputWidget_PointerDown, Widget_PointerUp, Widget_PointerMove
SpecialInputWidget_PointerDown, Widget_PointerUp, Widget_PointerMove,
SpecialInputWidget_BuildMesh, SpecialInputWidget_Render2
};
void SpecialInputWidget_Create(struct SpecialInputWidget* w, struct FontDesc* font, struct InputWidget* target) {
Widget_Reset(w);

View file

@ -221,6 +221,7 @@ struct ChatInputWidget {
char _origBuffer[INPUTWIDGET_MAX_LINES * INPUTWIDGET_LEN];
};
CC_NOINLINE void ChatInputWidget_RenderBackground(void* widget);
CC_NOINLINE void ChatInputWidget_Create(struct ChatInputWidget* w);
CC_NOINLINE void ChatInputWidget_SetFont(struct ChatInputWidget* w, struct FontDesc* font);