Начинающий
- Статус
- Оффлайн
- Регистрация
- 15 Окт 2019
- Сообщения
- 45
- Реакции
- 8
complete overhaul soon...
button.h:
#pragma once
#define BUTTON_X_OFFSET 20
#define BUTTON_BOX_HEIGHT 20
#define BUTTON_ITEM_X_OFFSET 10
class Button : public Element {
friend class GUI;
public:
__forceinline Button() : m_label{} {
m_flags = DRAW | CLICK;
m_type = BUTTON;
m_base_h = m_h = BUTTON_BOX_HEIGHT;
m_use_label = false;
}
__forceinline void setup(const std::string& label) {
m_label = label;
}
protected:
std::string m_label;
void draw() override;
void click() override;
};
button.cpp:
#include "../../../includes.h"
// button animation state.
struct ButtonAnimState {
float bg_lerp; // background color lerp [0..1].
float border_lerp; // border color lerp [0..1].
float scale_lerp; // scale lerp [0..1].
bool hovered;
bool pressed;
bool initialized;
ButtonAnimState() : bg_lerp(0.f), border_lerp(0.f), scale_lerp(0.f), hovered(false), pressed(false), initialized(false) {}
};
void Button::draw() {
Rect area{ m_parent->GetElementsRect() };
Point p{ area.x + m_pos.x, area.y + m_pos.y };
// static anim state per button.
static std::unordered_map<Button*, ButtonAnimState> anims;
ButtonAnimState& anim = anims[this];
// button area.
Rect btn_rect = { p.x + BUTTON_X_OFFSET, p.y, m_w - BUTTON_X_OFFSET, BUTTON_BOX_HEIGHT };
// check hover and pressed state.
bool is_hovered = g_input.IsCursorInRect(btn_rect);
bool is_pressed = is_hovered && g_input.GetKeyState(VK_LBUTTON);
// update anim state.
float speed = 10.0f * g_csgo.m_globals->m_frametime;
if (!anim.initialized) {
anim.bg_lerp = anim.border_lerp = anim.scale_lerp = 0.f;
anim.hovered = is_hovered;
anim.pressed = is_pressed;
anim.initialized = true;
}
// lerp background color.
float target_bg = is_hovered ? 1.f : 0.f;
anim.bg_lerp += (target_bg - anim.bg_lerp) * speed;
// lerp border color.
float target_border = is_pressed ? 1.f : (is_hovered ? 1.f : 0.f);
anim.border_lerp += (target_border - anim.border_lerp) * speed;
// lerp scale.
float target_scale = is_pressed ? 1.04f : (is_hovered ? 1.02f : 1.f);
anim.scale_lerp += (target_scale - anim.scale_lerp) * speed;
// compute colors.
Color base_bg = { 41, 41, 41, m_parent->m_alpha };
Color hover_bg = { 60, 60, 60, m_parent->m_alpha };
Color bg_col = Color(
(int)(base_bg.r() + (hover_bg.r() - base_bg.r()) * anim.bg_lerp),
(int)(base_bg.g() + (hover_bg.g() - base_bg.g()) * anim.bg_lerp),
(int)(base_bg.b() + (hover_bg.b() - base_bg.b()) * anim.bg_lerp),
m_parent->m_alpha
);
Color base_border = { 0, 0, 0, m_parent->m_alpha };
Color hover_border = g_gui.m_color;
hover_border.a() = m_parent->m_alpha;
Color press_border = g_gui.m_color;
press_border.a() = m_parent->m_alpha;
// border color interpolation.
Color border_col = base_border;
if (anim.border_lerp > 0.f) {
border_col = Color(
(int)(base_border.r() + (hover_border.r() - base_border.r()) * anim.border_lerp),
(int)(base_border.g() + (hover_border.g() - base_border.g()) * anim.border_lerp),
(int)(base_border.b() + (hover_border.b() - base_border.b()) * anim.border_lerp),
m_parent->m_alpha
);
}
// scale effect.
float scale = anim.scale_lerp;
int cx = p.x + BUTTON_X_OFFSET + (m_w - BUTTON_X_OFFSET) / 2;
int cy = p.y + BUTTON_BOX_HEIGHT / 2;
int w = int((m_w - BUTTON_X_OFFSET) * scale);
int h = int(BUTTON_BOX_HEIGHT * scale);
int x = cx - w / 2;
int y = cy - h / 2;
// box outline.
render::rect(x, y, w, h, border_col);
// inner blob.
render::rect_filled(x + 1, y + 1, w - 2, h - 2, bg_col);
// button name.
render::menu.string(cx, y + 4, { 205, 205, 205, m_parent->m_alpha }, m_label, render::ALIGN_CENTER);
}
void Button::click() {
Rect area{ m_parent->GetElementsRect() };
Point p{ area.x + m_pos.x, area.y + m_pos.y };
// area where user has to click.
Rect btn = { p.x + BUTTON_X_OFFSET, p.y, m_w - BUTTON_X_OFFSET, BUTTON_BOX_HEIGHT };
if (g_input.IsCursorInRect(btn) && m_callback)
m_callback();
}