A basic twitch chat viewer for windows written in C++20. It streams chat from the twitch IRC server using sockets, and uses SDL2 and SDL2_ttf to render.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.8 KiB

#include <string>
#include <deque>
#include "draw.h"
#include "colours.h"
struct chat_line_shape {
SDL_Surface* surf;
SDL_Texture* tex;
SDL_Rect rect;
void destroy() {
SDL_FreeSurface(surf);
SDL_DestroyTexture(tex);
}
};
struct chat_line_shape draw_text(struct sdl_context c, TTF_Font* f, SDL_Color col, int width, const std::string &text, bool wrapped = true) {
SDL_Surface* surf;
if (wrapped) {
surf = TTF_RenderUTF8_Solid_Wrapped(f, text.c_str(), col, width);
} else {
surf = TTF_RenderUTF8_Solid(f, text.c_str(), col);
}
SDL_Texture* tex = SDL_CreateTextureFromSurface(c.ren, surf);
SDL_Rect msgrect = {};
SDL_QueryTexture(tex, NULL, NULL, &msgrect.w, &msgrect.h);
return { surf, tex, msgrect };
}
void render_text(struct sdl_context c, TTF_Font* f, SDL_Color col, int x, int y, int width, const std::string &text) {
auto t = draw_text(c, f, col, width, text);
t.rect.x = x;
t.rect.y = y;
SDL_RenderCopy(c.ren, t.tex, NULL, &t.rect);
t.destroy();
}
void draw_messages(struct drawinfo d, std::deque<msg> &message_display_queue) {
int height = d.drawcontext.height - 20;
int linesep = 0;
int i = message_display_queue.size() - 1;
unsigned int now = SDL_GetTicks();
int name_margin = 150;
for (; i >= 0 && height > 20; i--) {
msg m = message_display_queue.at(i);
if (now - m.received_at > d.max_age) {
continue;
}
struct chat_line_shape s = draw_text(d.drawcontext, d.fonts.messages, d.colours.messages, d.drawcontext.width - 20 - name_margin, m.message);
height -= s.rect.h + linesep;
s.rect.x = 20 + name_margin;
s.rect.y = height;
SDL_Color uname_col = get_uname_colour(m.user);
struct chat_line_shape userline = draw_text(d.drawcontext, d.fonts.usernames, uname_col, name_margin - 20, m.user, false);
userline.rect.y = height;
if (userline.rect.w > name_margin - 20) {
userline.rect.w = name_margin - 20;
}
userline.rect.x = name_margin - userline.rect.w;
SDL_RenderCopy(d.drawcontext.ren, userline.tex, NULL, &userline.rect);
SDL_RenderCopy(d.drawcontext.ren, s.tex, NULL, &s.rect);
userline.destroy();
s.destroy();
}
for (; i > 0; i--) {
// remove offscreen messages from queue
message_display_queue.pop_front();
}
}
void draw(struct drawinfo d, std::deque<msg> &messages) {
auto col = d.colours.background;
SDL_SetRenderDrawColor(d.drawcontext.ren, col.r, col.g, col.b, 255);
SDL_RenderClear(d.drawcontext.ren);
// background
int wmargin, hmargin;
wmargin = 10;
hmargin = 10;
SDL_Rect bg{ wmargin, hmargin, d.drawcontext.width - wmargin * 2, d.drawcontext.height - hmargin * 2 };
auto bc = d.colours.background;
// SDL_SetRenderDrawColor(d.drawcontext.ren, bc.r, bc.g, bc.b, 0);
// SDL_RenderFillRect(d.drawcontext.ren, &bg);
draw_messages(d, messages);
SDL_RenderPresent(d.drawcontext.ren);
}