Исходник Modernized form.cpp // supremacy c+p ready

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
15 Окт 2019
Сообщения
45
Реакции
8
render.cpp:
Expand Collapse Copy
int render::Font::calc_width(const std::string& text) {
    // get the width of the string in pixels.
    FontSize_t size = this->size(text);
    return size.m_width;
}

form.h:
Expand Collapse Copy
#pragma once

class Form {
    friend class GUI;
    friend class Element;
    friend class Dropdown;
    friend class MultiDropdown;
    friend class Colorpicker;
    friend class Edit;
    friend class Config;

public:
    bool m_open;
    float m_opacity;
    int m_alpha;

private:
    std::string m_title;
    int m_key;
    int m_x;
    int m_y;
    int m_width;
    int m_height;
    int m_tick;
    std::vector<Tab*> m_tabs;
    Tab* m_active_tab;
    Element* m_active_element;

public:
    __forceinline Form() : m_open{ true }, m_opacity{}, m_alpha{}, m_title{}, m_key{ -1 }, m_x{}, m_y{}, m_width{}, m_height{}, m_tick{}, m_tabs{}, m_active_tab{}, m_active_element{} {
    }

    __forceinline void SetTitle(const std::string& title) {
        m_title = title;
    }

    __forceinline void SetPosition(int x, int y) {
        m_x = x;
        m_y = y;
    }

    __forceinline void SetSize(int w, int h) {
        m_width = w;
        m_height = h;
    }

    __forceinline void SetToggle(int key) {
        m_key = key;
    }

    // adds a new tab.
    __forceinline void RegisterTab(Tab* tab) {
        // if this is the first tab, set the active tab.
        if (!m_tabs.size())
            m_active_tab = tab;

        // this form is the owner of the tab.
        tab->m_parent = this;

        // add the tab to our container.
        m_tabs.push_back(tab);
    }

    // get specific tab based off name.
    __forceinline Tab* GetTabByName(const std::string& name) const {
        auto it = std::find_if(m_tabs.begin(), m_tabs.end(),
            [&name](Tab* tab) {
                return !tab->m_title.compare(name);
            });

        if (it != m_tabs.end())
            return *it;

        return nullptr;
    }

    // toggles the form.
    __forceinline void toggle() {
        m_open = !m_open;
    }

    // get the click-able area.
    __forceinline Rect GetClientRect() const {
        return { m_x + 6, m_y + 28, m_width - 12, m_height - 34 };
    }

    __forceinline Rect GetFormRect() const {
        return { m_x, m_y, m_width, m_height };
    }

    __forceinline Rect GetTabsRect() const {
        return { m_x + 20, m_y + 40, 100, m_height - 60 };
    }

    __forceinline Rect GetElementsRect() const {
        Rect tabs_area = GetTabsRect();
        return { tabs_area.x + tabs_area.w + 20, m_y + 40, m_width - tabs_area.w - 60, m_height - 60 };
    }

private:
    __forceinline void update_opacity();
    __forceinline void draw_background(int x, int y, int width, int height, Color color);
    __forceinline void draw_tabs();
    __forceinline void draw_elements();

public:
    void draw();
};

form.cpp:
Expand Collapse Copy
#include "../../../includes.h"

// underline animation state.
struct TabUnderlineAnim {
    float x;
    float w;
    float target_x;
    float target_w;
    float speed;
    bool initialized;

    TabUnderlineAnim() : x(0), w(0), target_x(0), target_w(0), speed(12.0f), initialized(false) {}
};

static TabUnderlineAnim g_tab_underline;

void Form::update_opacity() {
    // opacity should reach 1 in 500 milliseconds.
    constexpr float frequency = 1.f / 0.5f;

    // the increment / decrement per frame.
    float step = frequency * g_csgo.m_globals->m_frametime;

    // if open     -> increment
    // if closed -> decrement
    m_open ? m_opacity += step : m_opacity -= step;

    // clamp the opacity.
    math::clamp(m_opacity, 0.f, 1.f);

    // apply ease-out curve for a smoother animation.
    float eased_opacity = 1.f - (1.f - m_opacity) * (1.f - m_opacity);
    m_alpha = 0xff * eased_opacity;
}

void Form::draw_background(int x, int y, int width, int height, Color color) {
    // draw background.
    render::rect_filled(x, y, width, height, color);

    // draw a subtle border.
    render::rect(x, y, width, height, { 5, 5, 5, m_alpha });

    // draw the title text.
    render::menu.string(x + width / 2, y + 10, { 205, 205, 205, m_alpha }, m_title, render::ALIGN_CENTER);
}

void Form::draw_tabs() {
    // check if we have any tabs.
    if (m_tabs.empty())
        return;

    // get the tabs area.
    Rect tabs_area = GetTabsRect();

    // draw the background.
    draw_background(tabs_area.x, tabs_area.y, tabs_area.w, tabs_area.h, { 17, 17, 17, m_alpha });

    Color color = g_gui.m_color;
    color.a() = m_alpha;

    // tab height and padding.
    const int tab_height = 16;
    const int tab_padding = 5;
    const int tab_text_x = tabs_area.x + 10;
    const int tab_text_y = tabs_area.y + tab_padding;

    // find active tab index.
    int active_index = 0;
    for (size_t i = 0; i < m_tabs.size(); ++i) {
        if (m_tabs[i] == m_active_tab) {
            active_index = (int)i;
            break;
        }
    }

    // measure tab widths.
    std::vector<int> tab_widths;
    tab_widths.reserve(m_tabs.size());
    for (const auto& t : m_tabs) {
        int w = render::menu.calc_width(t->m_title);
        tab_widths.push_back(w);
    }

    // calculate underline target x and width.
    int underline_x = tab_text_x;
    for (int i = 0; i < active_index; ++i)
        underline_x += tab_widths[i] + 2 * tab_padding;

    int underline_w = tab_widths[active_index] + 2 * tab_padding;

    // initialize or update underline animation state.
    if (!g_tab_underline.initialized || g_tab_underline.target_x != underline_x || g_tab_underline.target_w != underline_w) {
        g_tab_underline.target_x = (float)underline_x;
        g_tab_underline.target_w = (float)underline_w;
        if (!g_tab_underline.initialized) {
            g_tab_underline.x = g_tab_underline.target_x;
            g_tab_underline.w = g_tab_underline.target_w;
            g_tab_underline.initialized = true;
        }
    }

    // interpolate underline position and width.
    float lerp_speed = g_tab_underline.speed * g_csgo.m_globals->m_frametime;
    g_tab_underline.x += (g_tab_underline.target_x - g_tab_underline.x) * lerp_speed;
    g_tab_underline.w += (g_tab_underline.target_w - g_tab_underline.w) * lerp_speed;

    // draw tabs vertically, one per row.
    int y = tab_text_y;
    for (size_t i = 0; i < m_tabs.size(); ++i) {
        const auto& t = m_tabs[i];
        Color tab_col = (t == m_active_tab) ? color : Color{ 152, 152, 152, m_alpha };
        render::menu.string(tab_text_x, y, tab_col, t->m_title);
        y += tab_height;
    }

    // draw animated underline.
    Color underline_col = color;
    underline_col.a() = m_alpha;
    int underline_y = tab_text_y + active_index * tab_height;
    render::rect_filled(tab_text_x - 4, underline_y, 2, tab_height, underline_col);
}

void Form::draw_elements() {
    // check if we have an active tab.
    if (m_active_tab->m_elements.empty())
        return;

    // elements background and border.
    Rect el = GetElementsRect();

    // draw the background.
    draw_background(el.x, el.y, el.w, el.h, { 17, 17, 17, m_alpha });

    // draw the date and username.
    std::string date = XOR(__DATE__);
    std::string text = tfm::format(XOR("%s | %s"), date.c_str(), g_cl.m_user);
    render::menu.string(el.x + el.w - 5, el.y + el.h - 16, { 205, 205, 205, m_alpha }, text, render::ALIGN_RIGHT);

    // iterate elements.
    for (const auto& e : m_active_tab->m_elements) {
        // skip elements that are not to be drawn.
        if (!e || (m_active_element && e == m_active_element) || !e->m_show || !(e->m_flags & DRAW))
            continue;

        // draw the element.
        e->draw();
    }

    // draw the active element last.
    if (m_active_element && m_active_element->m_show)
        m_active_element->draw();
}

void Form::draw() {
    update_opacity();
    if (!m_alpha)
        return;

    draw_background(m_x, m_y, m_width, m_height, { 12, 12, 12, m_alpha });

    draw_tabs();
    draw_elements();
}
 
Назад
Сверху Снизу