153 lines
5.5 KiB
C++
153 lines
5.5 KiB
C++
#include "StatBar.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
#include "Gui.h"
|
|
|
|
static constexpr float BAR_BORDER = 3.0f;
|
|
static constexpr float LABEL_HEIGHT = 26.0f;
|
|
static constexpr float LABEL_GAP = 2.0f;
|
|
static constexpr float TRAIL_DELAY = 0.45f; // seconds the lost amount lingers before draining
|
|
static constexpr float TRAIL_DRAIN_SPEED = 0.6f; // of the whole bar a second
|
|
static constexpr float FLASH_TIME = 0.35f;
|
|
|
|
static const glm::vec3 BACKGROUND_COLOR(0.03f, 0.04f, 0.06f);
|
|
static const glm::vec3 HURT_BACKGROUND_COLOR(0.45f, 0.06f, 0.05f);
|
|
static const glm::vec3 TRAIL_COLOR(0.98f, 0.92f, 0.80f);
|
|
static const glm::vec3 DIMMED_COLOR(0.38f, 0.40f, 0.44f);
|
|
static const glm::vec3 TEXT_COLOR(0.95f, 0.97f, 1.0f);
|
|
|
|
// Drawn from images: the empty part is the fill image darkened, the lost part the fill image brightened
|
|
static const glm::vec3 IMAGE_EMPTY_TINT(0.16f, 0.13f, 0.13f);
|
|
static const glm::vec3 IMAGE_HURT_TINT(0.55f, 0.18f, 0.16f);
|
|
static const glm::vec3 IMAGE_TRAIL_TINT(2.2f, 1.9f, 1.7f);
|
|
|
|
static ImageBox* MakeImage(Texture* texture) {
|
|
ImageBox* image = new ImageBox();
|
|
image->surface = SurfaceTexture::Stretched(texture);
|
|
image->Opacity = 0.0f;
|
|
image->BindToRenderSystem();
|
|
return image;
|
|
}
|
|
|
|
static Box* MakeBox(const glm::vec3& color) {
|
|
Box* box = new Box();
|
|
box->Color = color;
|
|
box->Opacity = 0.0f;
|
|
box->BindToRenderSystem();
|
|
return box;
|
|
}
|
|
|
|
StatBar::StatBar(Font* font, const Style& newStyle) : style(newStyle) {
|
|
if (Images()) {
|
|
background = MakeImage(style.fillImage);
|
|
trail = MakeImage(style.fillImage);
|
|
fill = MakeImage(style.fillImage);
|
|
if (style.frameImage)
|
|
frame = MakeImage(style.frameImage);
|
|
}
|
|
else {
|
|
background = MakeBox(BACKGROUND_COLOR);
|
|
background->rounding = 0.5f;
|
|
trail = MakeBox(TRAIL_COLOR);
|
|
fill = MakeBox(style.fillColor);
|
|
}
|
|
|
|
label = new TextBox();
|
|
label->font = font;
|
|
label->fontsize = style.labelSize;
|
|
label->Color = TEXT_COLOR;
|
|
label->Opacity = 0.0f;
|
|
label->textCenter = { 0.0f, 1.0f };
|
|
label->BindToRenderSystem();
|
|
}
|
|
|
|
float StatBar::GetHeight() const {
|
|
return LABEL_HEIGHT + LABEL_GAP + style.height;
|
|
}
|
|
|
|
void StatBar::Update(float dt, float opacity, float target, const std::string& text, const glm::vec2& position,
|
|
bool reset, bool dimmed) {
|
|
target = glm::clamp(target, 0.0f, 1.0f);
|
|
if (reset) {
|
|
fraction = trailFraction = target;
|
|
flash = 0.0f;
|
|
trailWait = 0.0f;
|
|
}
|
|
|
|
if (style.showLoss && target < fraction - 0.0001f) {
|
|
flash = 1.0f;
|
|
trailWait = TRAIL_DELAY;
|
|
}
|
|
fraction = target;
|
|
|
|
if (style.showLoss) {
|
|
trailWait -= dt;
|
|
if (trailWait <= 0.0f)
|
|
trailFraction = std::max(trailFraction - TRAIL_DRAIN_SPEED * dt, fraction);
|
|
trailFraction = std::max(trailFraction, fraction); // filling back up doesn't leave a trail
|
|
}
|
|
else {
|
|
trailFraction = fraction;
|
|
}
|
|
flash = std::max(flash - dt / FLASH_TIME, 0.0f);
|
|
dim += ((dimmed ? 1.0f : 0.0f) - dim) * (1.0f - std::exp(-10.0f * dt));
|
|
|
|
const glm::vec2 barTopLeft = glm::round(position + glm::vec2(0.0f, LABEL_HEIGHT + LABEL_GAP));
|
|
|
|
label->text = text;
|
|
label->t2d.position = { 0.0f, 0.0f, std::round(position.x + 2.0f), std::round(position.y) };
|
|
label->t2d.size = { 0.0f, 0.0f, style.width, LABEL_HEIGHT };
|
|
label->Opacity = text.empty() ? 0.0f : opacity;
|
|
|
|
// The fill color all the way down to lowFraction, then turning to lowColor
|
|
const float low = 1.0f - glm::clamp(fraction / std::max(style.lowFraction, 0.0001f), 0.0f, 1.0f);
|
|
glm::vec3 color = glm::mix(style.fillColor, style.lowColor, low);
|
|
color = glm::mix(color, DIMMED_COLOR, dim);
|
|
color = glm::mix(color, glm::vec3(1.0f), flash * 0.5f);
|
|
|
|
if (Images()) {
|
|
// Every layer covers the whole bar, the trail and fill cropped from the left to how much they show
|
|
auto Place = [&](Box* box, float shown) {
|
|
box->t2d.position = { 0.0f, 0.0f, barTopLeft.x, barTopLeft.y };
|
|
box->t2d.size = { 0.0f, 0.0f, std::round(style.width * shown), style.height };
|
|
static_cast<ImageBox*>(box)->crop = glm::vec2(shown, 1.0f);
|
|
};
|
|
Place(background, 1.0f);
|
|
background->Color = glm::mix(IMAGE_EMPTY_TINT, IMAGE_HURT_TINT, flash);
|
|
background->Opacity = opacity * 0.9f;
|
|
|
|
Place(trail, trailFraction);
|
|
trail->Color = IMAGE_TRAIL_TINT;
|
|
trail->Opacity = trailFraction > fraction ? opacity : 0.0f;
|
|
|
|
Place(fill, fraction);
|
|
fill->Color = color;
|
|
fill->Opacity = fraction > 0.0f ? opacity : 0.0f;
|
|
|
|
if (frame) {
|
|
Place(frame, 1.0f);
|
|
frame->Opacity = opacity;
|
|
}
|
|
return;
|
|
}
|
|
|
|
const float inner = style.width - BAR_BORDER * 2.0f;
|
|
const float innerHeight = style.height - BAR_BORDER * 2.0f;
|
|
|
|
background->t2d.position = { 0.0f, 0.0f, barTopLeft.x, barTopLeft.y };
|
|
background->t2d.size = { 0.0f, 0.0f, style.width, style.height };
|
|
background->Color = glm::mix(BACKGROUND_COLOR, HURT_BACKGROUND_COLOR, flash);
|
|
background->Opacity = opacity * 0.8f;
|
|
|
|
trail->t2d.position = { 0.0f, 0.0f, barTopLeft.x + BAR_BORDER, barTopLeft.y + BAR_BORDER };
|
|
trail->t2d.size = { 0.0f, 0.0f, std::round(inner * trailFraction), innerHeight };
|
|
trail->Opacity = opacity * 0.85f;
|
|
|
|
fill->t2d.position = { 0.0f, 0.0f, barTopLeft.x + BAR_BORDER, barTopLeft.y + BAR_BORDER };
|
|
fill->t2d.size = { 0.0f, 0.0f, std::round(inner * fraction), innerHeight };
|
|
fill->Color = color;
|
|
fill->Opacity = opacity;
|
|
}
|