latest state
This commit is contained in:
188
src/graphics/renderers/UIRenderer.cpp
Normal file
188
src/graphics/renderers/UIRenderer.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
#include "UIRenderer.h"
|
||||
#include "../ui/Font.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
void UIRenderer::drawSciFiPanel(SDL_Renderer* renderer, const SDL_FRect& rect, float alpha) {
|
||||
if (!renderer) return;
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
Uint8 alphaUint = static_cast<Uint8>(std::clamp(alpha * 255.0f, 0.0f, 255.0f));
|
||||
|
||||
// Drop shadow
|
||||
SDL_FRect shadow{rect.x + 6.0f, rect.y + 10.0f, rect.w, rect.h};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, static_cast<Uint8>(120.0f * alpha));
|
||||
SDL_RenderFillRect(renderer, &shadow);
|
||||
|
||||
// Glow aura
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
SDL_FRect glow{rect.x - float(i * 2), rect.y - float(i * 2), rect.w + float(i * 4), rect.h + float(i * 4)};
|
||||
Uint8 glowAlpha = static_cast<Uint8>((42 - i * 8) * alpha);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 180, 255, glowAlpha);
|
||||
SDL_RenderRect(renderer, &glow);
|
||||
}
|
||||
|
||||
// Body
|
||||
SDL_SetRenderDrawColor(renderer, 18, 30, 52, alphaUint);
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
|
||||
// Border
|
||||
SDL_SetRenderDrawColor(renderer, 70, 120, 210, alphaUint);
|
||||
SDL_RenderRect(renderer, &rect);
|
||||
}
|
||||
|
||||
void UIRenderer::drawButton(SDL_Renderer* renderer, FontAtlas* font, float cx, float cy, float w, float h,
|
||||
const std::string& label, bool isHovered, bool isSelected,
|
||||
SDL_Color bgColor, SDL_Color borderColor, bool textOnly, SDL_Texture* icon) {
|
||||
if (!renderer) return;
|
||||
|
||||
float x = cx - w * 0.5f;
|
||||
float y = cy - h * 0.5f;
|
||||
|
||||
if (!textOnly) {
|
||||
// Adjust colors based on state
|
||||
if (isSelected) {
|
||||
bgColor = {160, 190, 255, 255};
|
||||
SDL_SetRenderDrawColor(renderer, 255, 220, 0, 110);
|
||||
SDL_FRect glow{x - 10, y - 10, w + 20, h + 20};
|
||||
SDL_RenderFillRect(renderer, &glow);
|
||||
} else if (isHovered) {
|
||||
bgColor = {static_cast<Uint8>(std::min(255, bgColor.r + 40)),
|
||||
static_cast<Uint8>(std::min(255, bgColor.g + 40)),
|
||||
static_cast<Uint8>(std::min(255, bgColor.b + 40)),
|
||||
bgColor.a};
|
||||
}
|
||||
|
||||
// Draw button background with border
|
||||
SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, borderColor.a);
|
||||
SDL_FRect borderRect{x - 2, y - 2, w + 4, h + 4};
|
||||
SDL_RenderFillRect(renderer, &borderRect);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, bgColor.a);
|
||||
SDL_FRect bgRect{x, y, w, h};
|
||||
SDL_RenderFillRect(renderer, &bgRect);
|
||||
}
|
||||
|
||||
// Draw icon if provided, otherwise draw text
|
||||
if (icon) {
|
||||
// Get icon dimensions
|
||||
float iconW = 0.0f, iconH = 0.0f;
|
||||
SDL_GetTextureSize(icon, &iconW, &iconH);
|
||||
|
||||
// Scale icon to fit nicely in button (60% of button height)
|
||||
float maxIconH = h * 0.6f;
|
||||
float scale = maxIconH / iconH;
|
||||
float scaledW = iconW * scale;
|
||||
float scaledH = iconH * scale;
|
||||
|
||||
// Center icon in button
|
||||
float iconX = cx - scaledW * 0.5f;
|
||||
float iconY = cy - scaledH * 0.5f;
|
||||
|
||||
// Apply yellow tint when selected
|
||||
if (isSelected) {
|
||||
SDL_SetTextureColorMod(icon, 255, 220, 0);
|
||||
} else {
|
||||
SDL_SetTextureColorMod(icon, 255, 255, 255);
|
||||
}
|
||||
|
||||
SDL_FRect iconRect{iconX, iconY, scaledW, scaledH};
|
||||
SDL_RenderTexture(renderer, icon, nullptr, &iconRect);
|
||||
|
||||
// Reset color mod
|
||||
SDL_SetTextureColorMod(icon, 255, 255, 255);
|
||||
} else if (font) {
|
||||
// Draw text
|
||||
float textScale = 1.5f;
|
||||
int textW = 0, textH = 0;
|
||||
font->measure(label, textScale, textW, textH);
|
||||
float tx = x + (w - static_cast<float>(textW)) * 0.5f;
|
||||
// Adjust vertical position for better alignment with background buttons
|
||||
float ty = y + (h - static_cast<float>(textH)) * 0.5f + 2.0f;
|
||||
|
||||
// Choose text color based on selection state
|
||||
SDL_Color textColor = {255, 255, 255, 255}; // Default white
|
||||
if (isSelected) {
|
||||
textColor = {255, 220, 0, 255}; // Yellow when selected
|
||||
}
|
||||
|
||||
// Text shadow
|
||||
font->draw(renderer, tx + 2.0f, ty + 2.0f, label, textScale, {0, 0, 0, 200});
|
||||
// Text
|
||||
font->draw(renderer, tx, ty, label, textScale, textColor);
|
||||
}
|
||||
}
|
||||
|
||||
void UIRenderer::computeContentOffsets(float winW, float winH, float logicalW, float logicalH, float logicalScale, float& outOffsetX, float& outOffsetY) {
|
||||
float contentW = logicalW * logicalScale;
|
||||
float contentH = logicalH * logicalScale;
|
||||
outOffsetX = (winW - contentW) * 0.5f / logicalScale;
|
||||
outOffsetY = (winH - contentH) * 0.5f / logicalScale;
|
||||
}
|
||||
|
||||
void UIRenderer::drawLogo(SDL_Renderer* renderer, SDL_Texture* logoTex, float logicalW, float logicalH, float contentOffsetX, float contentOffsetY, int texW, int texH) {
|
||||
if (!renderer || !logoTex) return;
|
||||
|
||||
float w = 0.0f;
|
||||
float h = 0.0f;
|
||||
|
||||
if (texW > 0 && texH > 0) {
|
||||
w = static_cast<float>(texW);
|
||||
h = static_cast<float>(texH);
|
||||
} else {
|
||||
SDL_GetTextureSize(logoTex, &w, &h);
|
||||
}
|
||||
|
||||
if (w > 0.0f && h > 0.0f) {
|
||||
float maxWidth = logicalW * 0.6f;
|
||||
float scale = std::min(1.0f, maxWidth / w);
|
||||
float dw = w * scale;
|
||||
float dh = h * scale;
|
||||
float logoX = (logicalW - dw) * 0.5f + contentOffsetX;
|
||||
float logoY = logicalH * 0.05f + contentOffsetY;
|
||||
SDL_FRect dst{logoX, logoY, dw, dh};
|
||||
SDL_RenderTexture(renderer, logoTex, nullptr, &dst);
|
||||
}
|
||||
}
|
||||
|
||||
void UIRenderer::drawSettingsPopup(SDL_Renderer* renderer, FontAtlas* font, float logicalW, float logicalH, bool musicEnabled, bool soundEnabled) {
|
||||
if (!renderer || !font) return;
|
||||
|
||||
float popupW = 350, popupH = 260;
|
||||
float popupX = (logicalW - popupW) / 2;
|
||||
float popupY = (logicalH - popupH) / 2;
|
||||
|
||||
// Semi-transparent overlay
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 128);
|
||||
SDL_FRect overlay{0, 0, logicalW, logicalH};
|
||||
SDL_RenderFillRect(renderer, &overlay);
|
||||
|
||||
// Popup background
|
||||
SDL_SetRenderDrawColor(renderer, 100, 120, 160, 255);
|
||||
SDL_FRect bord{popupX-4, popupY-4, popupW+8, popupH+8};
|
||||
SDL_RenderFillRect(renderer, &bord);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 40, 50, 70, 255);
|
||||
SDL_FRect body{popupX, popupY, popupW, popupH};
|
||||
SDL_RenderFillRect(renderer, &body);
|
||||
|
||||
// Title
|
||||
font->draw(renderer, popupX + 20, popupY + 20, "SETTINGS", 2.0f, {255, 220, 0, 255});
|
||||
|
||||
// Music toggle
|
||||
font->draw(renderer, popupX + 20, popupY + 70, "MUSIC:", 1.5f, {255, 255, 255, 255});
|
||||
const char* musicStatus = musicEnabled ? "ON" : "OFF";
|
||||
SDL_Color musicColor = musicEnabled ? SDL_Color{0, 255, 0, 255} : SDL_Color{255, 0, 0, 255};
|
||||
font->draw(renderer, popupX + 120, popupY + 70, musicStatus, 1.5f, musicColor);
|
||||
|
||||
// Sound effects toggle
|
||||
font->draw(renderer, popupX + 20, popupY + 100, "SOUND FX:", 1.5f, {255, 255, 255, 255});
|
||||
const char* soundStatus = soundEnabled ? "ON" : "OFF";
|
||||
SDL_Color soundColor = soundEnabled ? SDL_Color{0, 255, 0, 255} : SDL_Color{255, 0, 0, 255};
|
||||
font->draw(renderer, popupX + 140, popupY + 100, soundStatus, 1.5f, soundColor);
|
||||
|
||||
// Instructions
|
||||
font->draw(renderer, popupX + 20, popupY + 150, "M = TOGGLE MUSIC", 1.0f, {200, 200, 220, 255});
|
||||
font->draw(renderer, popupX + 20, popupY + 170, "S = TOGGLE SOUND FX", 1.0f, {200, 200, 220, 255});
|
||||
font->draw(renderer, popupX + 20, popupY + 190, "ESC = CLOSE", 1.0f, {200, 200, 220, 255});
|
||||
}
|
||||
Reference in New Issue
Block a user