diff --git a/src/Screens.c b/src/Screens.c index bcbf81f62..91269d289 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -1047,6 +1047,8 @@ static void ChatScreen_ChatReceived(void* screen, const cc_string* msg, int type if (type == MSG_TYPE_NORMAL) { s->chatIndex++; if (!Gui.Chatlines) return; + + s->dirty = true; TextGroupWidget_ShiftUp(&s->chat); } else if (type >= MSG_TYPE_STATUS_1 && type <= MSG_TYPE_STATUS_3) { /* Status[0] is for texture pack downloading message */ @@ -1116,9 +1118,12 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) { Elem_Render(&s->bottomRight, delta); Elem_Render(&s->clientStatus, delta); + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); + Gfx_BindDynamicVb(s->vb); now = Game.Time; + if (s->grabsInput) { - Elem_Render(&s->chat, delta); + Widget_Render2(&s->chat, 0); } else { /* Only render recent chat */ for (i = 0; i < s->chat.lines; i++) { @@ -1127,7 +1132,11 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) { if (!tex.ID) continue; if (logIdx < 0 || logIdx >= Chat_Log.count) continue; - if (Chat_GetLogTime(logIdx) + 10 >= now) Texture_Render(&tex); + /* Only draw chat within last 10 seconds */ + if (Chat_GetLogTime(logIdx) + 10 < now) continue; + + Gfx_BindTexture(tex.ID); + Gfx_DrawVb_IndexedTris_Range(4, i * 4); } } @@ -1153,6 +1162,7 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) { 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); @@ -1176,6 +1186,7 @@ static void ChatScreen_ContextRecreated(void* screen) { struct FontDesc font; ChatScreen_ChatUpdateFont(s); ChatScreen_Redraw(s); + Screen_UpdateVb(s); #ifdef CC_BUILD_TOUCH if (!Input_TouchMode) return; @@ -1187,7 +1198,24 @@ static void ChatScreen_ContextRecreated(void* screen) { #endif } -static void ChatScreen_BuildMesh(void* screen) { } +static int ChatScreen_CalcMaxVertices(void* screen) { + struct ChatScreen* s = (struct ChatScreen*)screen; + struct TextGroupWidget* chat = &s->chat; + /* In case chatlines is 0 */ + return max(4, chat->VTABLE->GetMaxVertices(chat)); +} + +static void ChatScreen_BuildMesh(void* screen) { + struct ChatScreen* s = (struct ChatScreen*)screen; + struct VertexTextured* data; + struct VertexTextured** ptr; + + data = Screen_LockVb(s); + ptr = &data; + + Widget_BuildMesh(&s->chat, ptr); + Gfx_UnlockDynamicVb(s->vb); +} static void ChatScreen_Layout(void* screen) { struct ChatScreen* s = (struct ChatScreen*)screen; @@ -1416,6 +1444,8 @@ static void ChatScreen_Init(void* screen) { Event_Register_(&ChatEvents.ChatReceived, s, ChatScreen_ChatReceived); Event_Register_(&ChatEvents.ColCodeChanged, s, ChatScreen_ColCodeChanged); + + s->maxVertices = ChatScreen_CalcMaxVertices(s); #ifdef CC_BUILD_TOUCH ButtonWidget_Init(&s->send, 100, NULL); @@ -1490,6 +1520,10 @@ void ChatScreen_SetChatlines(int lines) { s->chatIndex += s->chat.lines - lines; s->chat.lines = lines; TextGroupWidget_RedrawAll(&s->chat); + + s->maxVertices = ChatScreen_CalcMaxVertices(s); + Screen_UpdateVb(s); + s->dirty = true; } diff --git a/src/Widgets.c b/src/Widgets.c index 01ba93ea9..63a438fb0 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -1982,7 +1982,8 @@ void TextGroupWidget_ShiftUp(struct TextGroupWidget* w) { Gfx_DeleteTexture(&w->textures[0].ID); last = w->lines - 1; - for (i = 0; i < last; i++) { + for (i = 0; i < last; i++) + { w->textures[i] = w->textures[i + 1]; } w->textures[last].ID = 0; /* Gfx_DeleteTexture() called by TextGroupWidget_Redraw otherwise */ @@ -1994,7 +1995,8 @@ void TextGroupWidget_ShiftDown(struct TextGroupWidget* w) { last = w->lines - 1; Gfx_DeleteTexture(&w->textures[last].ID); - for (i = last; i > 0; i--) { + for (i = last; i > 0; i--) + { w->textures[i] = w->textures[i - 1]; } w->textures[0].ID = 0; /* Gfx_DeleteTexture() called by TextGroupWidget_Redraw otherwise */ @@ -2005,10 +2007,12 @@ int TextGroupWidget_UsedHeight(struct TextGroupWidget* w) { struct Texture* textures = w->textures; int i, height = 0; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { if (textures[i].ID) break; } - for (; i < w->lines; i++) { + for (; i < w->lines; i++) + { height += textures[i].Height; } return height; @@ -2020,7 +2024,8 @@ static void TextGroupWidget_Reposition(void* widget) { int i, y, width = 0, height = 0; /* Work out how big the text group is now */ - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { width = max(width, textures[i].Width); height += textures[i].Height; } @@ -2028,7 +2033,8 @@ static void TextGroupWidget_Reposition(void* widget) { w->width = width; w->height = height; Widget_CalcPosition(w); - for (i = 0, y = w->y; i < w->lines; i++) { + for (i = 0, y = w->y; i < w->lines; i++) + { textures[i].X = Gui_CalcPos(w->horAnchor, w->xOffset, textures[i].Width, WindowInfo.Width); textures[i].Y = y; y += textures[i].Height; @@ -2043,7 +2049,8 @@ struct Portion { short Beg, Len, LineBeg, LineLen; }; static int TextGroupWidget_NextUrl(char* chars, int charsLen, int i) { int start, left; - for (; i < charsLen; i++) { + for (; i < charsLen; i++) + { if (!(chars[i] == 'h' || chars[i] == '&')) continue; left = charsLen - i; if (left < TEXTGROUPWIDGET_HTTP_LEN) return charsLen; @@ -2069,7 +2076,8 @@ static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int* begs, int begs int next, left; cc_bool isBeg; - for (; i < charsLen && chars[i] != ' '; i++) { + for (; i < charsLen && chars[i] != ' '; i++) + { /* Is this character the start of a line */ isBeg = false; for (j = 0; j < begsLen; j++) { @@ -2124,7 +2132,8 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta cc_string line; int nextStart, i, total = 0, end; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { line = TextGroupWidget_UNSAFE_Get(w, i); begs[i] = -1; ends[i] = -1; if (!line.length) continue; @@ -2135,7 +2144,8 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta } end = 0; - for (;;) { + for (;;) + { nextStart = TextGroupWidget_NextUrl(chars, total, end); /* add normal portion between urls */ @@ -2161,7 +2171,8 @@ static void TextGroupWidget_FormatUrl(cc_string* text, const cc_string* url) { /* Delete "> " multiline chars from URLs */ dst = text->buffer; - for (i = text->length - 2; i >= 0; i--) { + for (i = text->length - 2; i >= 0; i--) + { if (dst[i] != '>' || dst[i + 1] != ' ') continue; String_DeleteAt(text, i + 1); @@ -2185,7 +2196,8 @@ static cc_bool TextGroupWidget_GetUrl(struct TextGroupWidget* w, cc_string* text if (Game_ClassicMode) return false; portionsCount = TextGroupWidget_Reduce(w, chars, index, portions); - for (i = 0, x = 0; i < portionsCount; i++) { + for (i = 0, x = 0; i < portionsCount; i++) + { bit = portions[i]; args.text = String_UNSAFE_Substring(&line, bit.LineBeg, bit.LineLen); args.font = w->font; @@ -2208,7 +2220,8 @@ int TextGroupWidget_GetSelected(struct TextGroupWidget* w, cc_string* text, int cc_string line; int i; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { if (!w->textures[i].ID) continue; tex = w->textures[i]; if (!Gui_Contains(tex.X, tex.Y, tex.Width, tex.Height, x, y)) continue; @@ -2226,7 +2239,8 @@ static cc_bool TextGroupWidget_MightHaveUrls(struct TextGroupWidget* w) { cc_string line; int i; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { line = TextGroupWidget_UNSAFE_Get(w, i); if (String_IndexOf(&line, '/') >= 0) return true; } @@ -2308,11 +2322,13 @@ void TextGroupWidget_RedrawAllWithCol(struct TextGroupWidget* group, char col) { cc_string line; int i, j; - for (i = 0; i < group->lines; i++) { + for (i = 0; i < group->lines; i++) + { line = TextGroupWidget_UNSAFE_Get(group, i); if (!line.length) continue; - for (j = 0; j < line.length - 1; j++) { + for (j = 0; j < line.length - 1; j++) + { if (line.buffer[j] == '&' && line.buffer[j + 1] == col) { TextGroupWidget_Redraw(group, i); break; @@ -2329,7 +2345,8 @@ void TextGroupWidget_SetFont(struct TextGroupWidget* w, struct FontDesc* font) { Drawer2D_ReducePadding_Height(&height, font->size, 3); w->defaultHeight = height; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { w->textures[i].Height = w->collapsible[i] ? 0 : height; } w->font = font; @@ -2341,7 +2358,8 @@ static void TextGroupWidget_Render(void* widget, double delta) { struct Texture* textures = w->textures; int i; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { if (!textures[i].ID) continue; Texture_Render(&textures[i]); } @@ -2351,15 +2369,47 @@ static void TextGroupWidget_Free(void* widget) { struct TextGroupWidget* w = (struct TextGroupWidget*)widget; int i; - for (i = 0; i < w->lines; i++) { + for (i = 0; i < w->lines; i++) + { Gfx_DeleteTexture(&w->textures[i].ID); } } +static void TextGroupWidget_BuildMesh(void* widget, struct VertexTextured** vertices) { + struct TextGroupWidget* w = (struct TextGroupWidget*)widget; + int i; + + for (i = 0; i < w->lines; i++) + { + Gfx_Make2DQuad(&w->textures[i], PACKEDCOL_WHITE, vertices); + } +} + +static int TextGroupWidget_Render2(void* widget, int offset) { + struct TextGroupWidget* w = (struct TextGroupWidget*)widget; + struct Texture* textures = w->textures; + int i; + + for (i = 0; i < w->lines; i++, offset += 4) + { + if (!textures[i].ID) continue; + + Gfx_BindTexture(textures[i].ID); + Gfx_DrawVb_IndexedTris_Range(4, offset); + } + return offset; +} + +static int TextGroupWidget_MaxVertices(void* widget) { + struct TextGroupWidget* w = (struct TextGroupWidget*)widget; + return w->lines * 4; +} + static const struct WidgetVTABLE TextGroupWidget_VTABLE = { TextGroupWidget_Render, TextGroupWidget_Free, TextGroupWidget_Reposition, Widget_InputDown, Widget_InputUp, Widget_MouseScroll, - Widget_Pointer, Widget_PointerUp, Widget_PointerMove + Widget_Pointer, Widget_PointerUp, Widget_PointerMove, + TextGroupWidget_BuildMesh, TextGroupWidget_Render2, TextGroupWidget_MaxVertices }; void TextGroupWidget_Create(struct TextGroupWidget* w, int lines, struct Texture* textures, TextGroupWidget_Get getLine) { Widget_Reset(w);