#include "gui.h" #include "blocks.h" int BUFFER_HALF_W = BUFFER_W / 2; int BUFFER_HALF_H = BUFFER_H / 2; int WINDOW_W = BUFFER_W * BUFFER_SCALE; int WINDOW_H = BUFFER_H * BUFFER_SCALE; char chatHistory[11][64] = {0}; int chatHistoryFade[11] = {0}; int chatHistoryIndex = 0; /* strnum * Takes in a char array and an offset and puts the specified * number into it. Make sure there is sufficient space in the * string. */ void strnum(char *ptr, int offset, int num) { sprintf(ptr + offset, "%d", num); } /* drawChar * Takes in a pointer to a renderer, a character (as an int), * draws it at the specified x and y coordinates, and then returns * the character's width. */ int drawChar(SDL_Renderer *renderer, int c, int x, int y) { for (int yy = 0; yy < 8; yy++) { for (int xx = 0; xx < 8; xx++) { if ((font[c][yy] >> (7 - xx)) & 0x1) { SDL_RenderDrawPoint(renderer, x + xx, y + yy); } } } return font[c][8]; } /* drawStr * Takes in a pointer to a renderer, a string, draws it at the * specified x and y coordinates, and then returns the x position * it left off on. */ int drawStr(SDL_Renderer *renderer, const char *str, int x, int y) { while (*str > 0) { x += drawChar(renderer, *(str++), x, y); } return x; } /* shadowStr * Identical to drawStr, but draws white text with a grey shadow. */ int shadowStr(SDL_Renderer *renderer, const char *str, int x, int y) { SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255); drawStr(renderer, str, x + 1, y + 1); white(renderer); return drawStr(renderer, str, x, y); } /* centerStr * Identical to drawStr, but centers the text */ int centerStr(SDL_Renderer *renderer, const char *str, int x, int y) { x *= 2; int i = 0; while (str[i] > 0) { x -= font[(int)str[i++]][8]; } x /= 2; i = 0; while (str[i] > 0) { x += drawChar(renderer, str[i++], x, y); } return x; } /* shadowStr * Identical to centerStr, but draws white text with a grey shadow. */ int shadowCenterStr(SDL_Renderer *renderer, const char *str, int x, int y) { SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255); centerStr(renderer, str, x + 1, y + 1); white(renderer); return centerStr(renderer, str, x, y); } /* drawBig * Draws centered text at a large scale */ int drawBig(SDL_Renderer *renderer, const char *str, int x, int y) { int i = 0; while (str[i] > 0) x -= font[(int)str[i++]][8]; i = 0; while (str[i] > 0) { int c = str[i++]; for (int yy = 0; yy < 16; yy++) { for (int xx = 0; xx < 16; xx++) { if ((font[c][yy / 2] >> (7 - xx / 2)) & 0x1) { SDL_RenderDrawPoint( renderer, x + xx, y + yy); } } } x += font[c][8] * 2; } return x; } /* drawBGStr * Like drawStr, but also draws a semitransparent background * behind the text. */ int drawBGStr(SDL_Renderer *renderer, const char *str, int x, int y) { static int len; static SDL_Rect bg = {0, 0, 0, 9}; int i = 0; len = 0; while (str[i] > 0) { len += font[(int)str[i++]][8]; } bg.x = x; bg.y = y; bg.w = len + 1; tblack(renderer); SDL_RenderFillRect(renderer, &bg); white(renderer); return drawStr(renderer, str, ++x, ++y); } /* button * Takes in a pointer to a renderer, a string, draws a button with * the specified x and y coordinates and width, and then returns * wether or not the specified mouse coordinates are within it. */ int button( SDL_Renderer *renderer, const char *str, int x, int y, int w, int mouseX, int mouseY) { int hover = mouseX >= x && mouseY >= y && mouseX < x + w && mouseY < y + 16; SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = 16; if (hover) { SDL_SetRenderDrawColor(renderer, 116, 134, 230, 255); } else { SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255); } SDL_RenderFillRect(renderer, &rect); x += w / 2 + 1; y += 5; if (hover) { SDL_SetRenderDrawColor(renderer, 63, 63, 40, 255); } else { SDL_SetRenderDrawColor(renderer, 56, 56, 56, 255); } centerStr(renderer, str, x, y); x--; y--; if (hover) { SDL_SetRenderDrawColor(renderer, 255, 255, 160, 255); } else { white(renderer); } centerStr(renderer, str, x, y); if (hover) { white(renderer); } else { SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); } SDL_RenderDrawRect(renderer, &rect); return hover; } /* input * Draws a simple text input. Draws the string in buffer. If buffer is empty, * the placeholder text is drawn instead (but in a darker color). Returns * whether or not the mouse is inside of the input. */ int input( SDL_Renderer *renderer, const char *placeholder, const char *buffer, int x, int y, int w, int mouseX, int mouseY, int active) { static int flash = 0; int hover = mouseX >= x && mouseY >= y && mouseX < x + w && mouseY < y + 16; SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = 16; SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderFillRect(renderer, &rect); if (hover || active) { white(renderer); } else { SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255); } SDL_RenderDrawRect(renderer, &rect); int textX = x + 4; if (buffer[0] != 0) { white(renderer); textX = drawStr(renderer, buffer, x + 4, y + 4); } else { SDL_SetRenderDrawColor(renderer, 63, 63, 63, 255); drawStr(renderer, placeholder, x + 4, y + 4); } if (flash < 32 && active) { white(renderer); drawChar(renderer, '_', textX, y + 4); } flash++; flash %= 64; return hover; } /* scrollbar * Draws a scrollbar of the specified length at the specified coordinates. * Able to modify the level value when the user interacts with it. */ void scrollbar( SDL_Renderer *renderer, int x, int y, int length, int mouseX, int mouseY, int mouseLeft, int *level, int max) { float sectionLength = (float)length / (float)max; SDL_Rect background = { .x = x, .y = y, .w = 4, .h = length}; SDL_Rect foreground = { .x = x, .y = (float)*level * sectionLength, .w = 4, .h = ceil(sectionLength)}; int hover = mouseX >= background.x && mouseY >= background.y && mouseX < background.x + background.w && mouseY < background.y + background.h; if (hover && mouseLeft) { *level = (mouseY - background.y) / sectionLength; } tblack(renderer); SDL_RenderFillRect(renderer, &background); SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255); SDL_RenderFillRect(renderer, &foreground); SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255); SDL_RenderDrawLine( renderer, foreground.x + foreground.w - 1, foreground.y, foreground.x + foreground.w - 1, foreground.y + foreground.h - 1); } /* drawSlot * Takes in a pointer to a renderer, an InvSlot, draws the item * with the specified x and y coordinates and width, and then * returns wether or not the specified mouse coordinates are * within it. */ int drawSlot(SDL_Renderer *renderer, InvSlot *slot, int x, int y, int mouseX, int mouseY) { int hover, i, xx, yy, color; char count[4]; hover = mouseX >= x && mouseY >= y && mouseX < x + 16 && mouseY < y + 16; if (slot->amount == 0) { return hover; } i = slot->blockid * 256 * 3; for (yy = 0; yy < 16; yy++) { for (xx = 0; xx < 16; xx++) { color = textures[i + BLOCK_TEXTURE_H * BLOCK_TEXTURE_W]; SDL_SetRenderDrawColor( renderer, (color >> 16 & 0xFF), (color >> 8 & 0xFF), (color & 0xFF), 255); if (color > 0) { SDL_RenderDrawPoint(renderer, x + xx, y + yy); } i++; } } strnum(count, 0, slot->amount); shadowStr(renderer, count, x + (slot->amount >= 10 ? 4 : 10), y + 8); return hover; } /* drawWorldListItem * Draws a world list item and reurns whether the mouse is inside of it or one * of its buttons. */ int drawWorldListItem(SDL_Renderer *renderer, data_WorldListItem *item, int x, int y, int mouseX, int mouseY) { int hover; hover = mouseX >= x && mouseY >= y && mouseX < x + 128 && mouseY < y + 16; SDL_Rect rect; rect.x = x - 1; rect.y = y - 1; rect.w = 130; rect.h = 18; SDL_Rect thumbnailShadow; thumbnailShadow.x = x + 1; thumbnailShadow.y = y + 1; thumbnailShadow.w = 16; thumbnailShadow.h = 16; tblack(renderer); SDL_RenderFillRect(renderer, &thumbnailShadow); int *pixel = item->thumbnail.buffer; for (int yy = 0; yy < 16; yy++) { for (int xx = 0; xx < 16; xx++) { SDL_SetRenderDrawColor( renderer, (*pixel >> 16 & 0xFF), (*pixel >> 8 & 0xFF), (*pixel & 0xFF), 255); SDL_RenderDrawPoint(renderer, x + xx, y + yy); pixel++; } } shadowStr(renderer, item->name, x + 20, y + 4); if (button(renderer, "x", x + 128 - 16, y, 16, mouseX, mouseY)) { hover = 2; } if (hover == 1) { white(renderer); SDL_RenderDrawRect(renderer, &rect); } return hover; } /* dirtBg * Draws a dirt textured background */ void dirtBg(SDL_Renderer *renderer) { int color; for (int y = 0; y < BUFFER_H; y++) { for (int x = 0; x < BUFFER_W; x++) { color = textures[(x & 0xF) + (y & 0xF) * 16 + BLOCK_DIRT * 256 * 3]; SDL_SetRenderDrawColor( renderer, (color >> 16 & 0xFF) >> 1, (color >> 8 & 0xFF) >> 1, (color & 0xFF) >> 1, 255); SDL_RenderDrawPoint(renderer, x, y); } } } /* loadScreen * Draws a loading screen */ void loadScreen( SDL_Renderer *renderer, const char *str, float prog, float max) { dirtBg(renderer); shadowCenterStr(renderer, str, BUFFER_HALF_W, BUFFER_HALF_H - 8); SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255); SDL_RenderDrawLine( renderer, BUFFER_HALF_W - 32, BUFFER_HALF_H + 6, BUFFER_HALF_W + 32, BUFFER_HALF_H + 6); SDL_SetRenderDrawColor(renderer, 132, 255, 132, 255); SDL_RenderDrawLine( renderer, BUFFER_HALF_W - 32, BUFFER_HALF_H + 6, BUFFER_HALF_W - 32 + (prog / max) * 64, BUFFER_HALF_H + 6); } /* chatAdd * Adds a message to chat */ void chatAdd(const char *str) { chatHistoryFade[chatHistoryIndex] = 480; memcpy( chatHistory[(chatHistoryIndex)++], str, sizeof(char) * 64); chatHistoryIndex = nmod(chatHistoryIndex, 11); } /* white * Sets the render color to white */ void white(SDL_Renderer *renderer) { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); } /* tblack * Sets the render color to transparent black */ void tblack(SDL_Renderer *renderer) { #ifdef _KOLIBRI SDL_SetRenderDrawColor(renderer, 15, 15, 15, 255); #else SDL_SetRenderDrawColor(renderer, 0, 0, 0, 128); #endif }