#include "button.hpp" #include // #include #include "../vulkan-game.hpp" // TODO: Figure out a good way to return errors instead of just printing them // Probably throw an exception // Make sure to cleanup anythign that was initialized correctly before the error // TODO: Support better positioning options (e.g. align to left, right, top, bottom, center, // and offsets from those positions) Button::Button(string label, int x, int y, int padding, uint32_t color, uint32_t textColor, VulkanGame& gameInfo, SDL_Renderer& renderer, void (*onMouseClick)(VulkanGame& gameInfo), void (*onMouseEnter)(UIElement& element), void (*onMouseLeave)(UIElement& element)) : UIElement(x, y, 0, 0, renderer, onMouseClick, onMouseEnter, onMouseLeave), color(color), focused(false), gameInfo(gameInfo) { SDL_Color sdlTextColor { static_cast((textColor >> 24) & 0xFF), static_cast((textColor >> 16) & 0xFF), static_cast((textColor >> 8) & 0xFF), static_cast(textColor & 0xFF) }; SDL_Surface* labelSurface = TTF_RenderText_Blended(this->gameInfo.proggyFont, label.c_str(), sdlTextColor); if (labelSurface == nullptr) { cout << "Unable to render text surface! SDL_ttf Error: " << TTF_GetError() << endl; } this->labelTexture = SDL_CreateTextureFromSurface(&this->renderer, labelSurface); if (this->labelTexture == nullptr) { cout << "Unable to create texture from rendered text! SDL Error: " << SDL_GetError() << endl; // SDL_FreeSurface(labelSurface); } SDL_FreeSurface(labelSurface); TTF_SizeText(this->gameInfo.proggyFont, label.c_str(), &this->labelWidth, &this->labelHeight); this->width = this->labelWidth + padding; this->height = this->labelHeight + padding; uint32_t rgb = color & 0xFFFFFF00; uint32_t a = color & 0xFF; this->focusColor = (int)(rgb * 1.6) | a; } Button::~Button() { if (this->labelTexture != nullptr) { SDL_DestroyTexture(this->labelTexture); this->labelTexture = nullptr; } } void Button::init() { this->focused = false; } void Button::render(int x, int y) { uint32_t cur_color = this->focused ? this->focusColor : this->color; uint8_t colorR = (cur_color >> 24) & 0xFF; uint8_t colorG = (cur_color >> 16) & 0xFF; uint8_t colorB = (cur_color >> 8) & 0xFF; uint8_t colorA = cur_color & 0xFF; /* boxRGBA(&this->renderer, this->x + x, this->y + y, this->x + this->width, this->y + this->height, colorR, colorG, colorB, colorA); */ SDL_Rect rect = { this->x + (this->width - this->labelWidth) / 2 + x, this->y + (this->height - this->labelHeight) / 2 + y, this->labelWidth, this->labelHeight }; SDL_RenderCopy(&this->renderer, this->labelTexture, nullptr, &rect); } void Button::handleEvent(UIEvent& e) { switch(e.type) { case UI_EVENT_MOUSEMOTION: if (this->x < e.mouse.x && e.mouse.x < this->x + this->width && this->y < e.mouse.y && e.mouse.y < this->y + this->height) { if (!this->focused) { this->focused = true; if (this->onMouseEnter != nullptr) { this->onMouseEnter(*this); } } } else if (this->focused) { this->focused = false; if (this->onMouseLeave != nullptr) { this->onMouseLeave(*this); } } break; case UI_EVENT_MOUSEBUTTONDOWN: break; case UI_EVENT_MOUSEBUTTONUP: if (this->x < e.mouse.x && e.mouse.x < this->x + this->width && this->y < e.mouse.y && e.mouse.y < this->y + this->height) { if (this->onMouseClick != nullptr) { this->onMouseClick(this->gameInfo); } } break; default: //cout << "Unhandled UI event: " << e.type << endl; break; } }