Гайд Делаем Круглое Меню [Градиент] своему софтику

За этот гайд меня можно:


  • Всего проголосовало
    9
  • Опрос закрыт .
///
Пользователь
Статус
Оффлайн
Регистрация
25 Янв 2018
Сообщения
511
Реакции[?]
114
Поинты[?]
0
Привет ЛЮДЯМ И Мастерам искуссно-пастерской деятельносьти! Автор - XVII a.k.a _dev0x
Сегодня поведаю как сделать:​
  • Круглое меню для вашей очередной пасточки!
___________________________________________________________________________________________________________________​
Нам понадобится:​
  • Мозг
  • Руки
  • Visual Studio
  • Знание C++ (хотя бы Базовое)
  • Мой гайд :3
  • ImGui (Скачать можно тут:
    Пожалуйста, авторизуйтесь для просмотра ссылки.
  • НЕ РЕКЛАМА)
И так приступим​
Думаю как создавать проект, объяснять не нужно) Если нужно пишите в ВК помогу)
1. Создаём проект, далее в нём файлик где это будет хранится
Код:
]static float RADIUS_MIN = 0.f;
static float RADIUS_MAX = 0.f;
static float RADIUS_INTERACT_MIN = 30.0f;
int PiePopupSelectMenu(const ImVec2& center, const char* popup_id, const char** items, int items_count, int* p_selected)
{
    int ret = -1;
    ImGui::SetNextWindowPos({ -100, -100 });
    static bool p_open = true;
    if (ImGui::Begin(popup_id), &p_open)
    {
        const ImVec2 drag_delta = ImVec2(ImGui::GetIO().MousePos.x - center.x, ImGui::GetIO().MousePos.y - center.y);
        const float drag_dist2 = drag_delta.x*drag_delta.x + drag_delta.y*drag_delta.y;

        const ImGuiStyle& style = ImGui::GetStyle();
        const int ITEMS_MIN = 5;

        ImDrawList* draw_list = ImGui::GetWindowDrawList();
        draw_list->PushClipRectFullScreen();
        draw_list->PathArcTo(center, (RADIUS_MIN + RADIUS_MAX)*0.45f, 0.f, IM_PI*2.0f*0.99f, 32);
        draw_list->PathStroke(ImColor(0.f, 0.f, 0.f), true, RADIUS_MAX - RADIUS_MIN);

        const float item_arc_span = 2 * IM_PI / ImMax(ITEMS_MIN, items_count);
        float drag_angle = atan2f(drag_delta.y, drag_delta.x);
        if (drag_angle < -0.5f * item_arc_span)
            drag_angle += 2.0f * IM_PI;

        int item_hovered = -1;
        for (int item_n = 0; item_n < items_count; item_n++)
        {
            const char* item_label = items[item_n];
            const float item_ang_min = item_arc_span * (item_n + 0.02f) - item_arc_span * 0.50f;
            const float item_ang_max = item_arc_span * (item_n + 0.98f) - item_arc_span * 0.50f;

            bool hovered = false;
            if (drag_dist2 >= RADIUS_INTERACT_MIN * RADIUS_INTERACT_MIN && drag_dist2 < RADIUS_MAX*RADIUS_MAX)
            {
                if (drag_angle >= item_ang_min && drag_angle < item_ang_max)
                    hovered = true;
            }
            bool selected = p_selected && (*p_selected == item_n);

           
            int arc_segments = (int)(32 * item_arc_span / (2 * IM_PI));

            draw_list->PathArcTo(center, RADIUS_MAX - style.ItemInnerSpacing.x /*- 1.0f*/ , item_ang_min, item_ang_max,  arc_segments);
            draw_list->PathArcTo(center, RADIUS_MIN /*- 7.f*/+ style.ItemInnerSpacing.x , item_ang_max, item_ang_min, arc_segments);
            draw_list->PathFill(
                hovered ? ImColor((ImGui::GetColorU32(ImGuiCol_FirstTabColorHovered)))  : selected ? ImColor((ImGui::GetColorU32(ImGuiCol_FirstTabColorActive)))  : ImColor((ImGui::GetColorU32(ImGuiCol_FirstTabColor))),
                hovered ? ImColor((ImGui::GetColorU32(ImGuiCol_SecondTabColorHovered))) : selected ? ImColor((ImGui::GetColorU32(ImGuiCol_SecondTabColorActive))) : ImColor((ImGui::GetColorU32(ImGuiCol_SecondTabColor))));
 
 
            ImVec2 text_size = ImGui::GetWindowFont()->CalcTextSizeA(ImGui::GetWindowFontSize(), FLT_MAX, 0.0f, item_label);
            ImVec2 text_pos = ImVec2(
                center.x + cosf((item_ang_min + item_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.x * 0.5f,
                center.y + sinf((item_ang_min + item_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.y * 0.5f);
            draw_list->AddText(text_pos, ImColor(255, 255, 255), item_label);
   
            if (hovered)
                item_hovered = item_n;
        }

        draw_list->PopClipRect();

        if (drag_dist2 >= RADIUS_INTERACT_MIN * RADIUS_INTERACT_MIN && drag_dist2 < RADIUS_MAX*RADIUS_MAX)
        {
            if (ImGui::IsMouseReleased(0))
            {
                ImGui::CloseCurrentPopup();
                ret = item_hovered;
                if (p_selected)
                    *p_selected = item_hovered;
            }
        }
        ImGui::End();
    }
    return ret;
}

2. Далее, в EndScene или где вы меню будете рисовать пишем это:
Код:
if (RADIUS_MAX < 120.f)
            RADIUS_MAX += 7.f;

        if (RADIUS_MAX == 120.f && RADIUS_MIN < 35.f)
            RADIUS_MIN += 5.f;
 
        static const char* test_data = "Menu";
        const char* items[] = { u8"Rage", u8"Trigger", u8"Visual", u8"Misc", u8"Skins",u8"Legit" };
        int items_count = sizeof(items) / sizeof(*items);
        static int selected = -1;

        ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
        PiePopupSelectMenu(ImVec2(200, 200), "##piepopup", items, items_count, &selected);
        ImGui::PopStyleColor();

        if (selected > -1)
        {
            ImGui::Begin(charenc("##open_"), &MenuSettings.Menu.Opened, ImVec2(597, 340), 0.9f, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoFocusOnAppearing);
            {
                ImVec2 lPos = ImGui::GetCursorPos();
                ImGuiContext* io = ImGui::GetCurrentContext();
                ImGuiStyle& style = ImGui::GetStyle();

                ImGui::BeginChild(charenc("##Menu-Child"), ImVec2(0, 0), false);
                {
                    if (selected == 0)
                        RageTab();

                    if (selected == 1)
                        TrigTab();

                    if (selected == 2)
                        VisTab();

                    if (selected == 3)
                        MiscTab();

                    if (selected == 4)
                        SkinTab();

                    if (selected == 5)
                        LegitTab();

                }
                ImGui::EndChild();
            }
            ImGui::End(); //End main window
        }
    }

    else
    {
        RADIUS_MIN = 0.f;
        RADIUS_MAX = 0.f;
    }

3. Дальше используем ImGui, самое веселое настало - это градиент. Мучаемся с ImGui)
Идём в imgui_draw.cpp и заменяем этим кодом:
Код:
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased,ImU32 col2)
{
    const ImVec2 uv = GImGui->FontTexUvWhitePixel;
    const ImVec2 uv2 = GImGui->FontTexUvWhitePixel;
    anti_aliased &= GImGui->Style.AntiAliasedShapes;
    if (anti_aliased)
    {
        // Anti-aliased Fill
        const float AA_SIZE = 1.0f;
 
        const ImU32 col_trans  = /*ImU32(ImGui::GetColorU32(ImGuiCol_FirstTabColor)) */col & IM_COL32(255, 255, 255, 0);
        const ImU32 col_trans2 =/* ImU32(ImGui::GetColorU32(ImGuiCol_SecondTabColor))*/ col2 & IM_COL32(255, 255, 255, 0);
 
        const int idx_count = (points_count-2)*3 + points_count*6;
        const int vtx_count = (points_count*2);
        PrimReserve(idx_count, vtx_count);

        // Add indexes for fill
        unsigned int vtx_inner_idx = _VtxCurrentIdx;
        unsigned int vtx_outer_idx = _VtxCurrentIdx+1;
        for (int i = 2; i < points_count; i++)
        {
            _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1));
            _IdxWritePtr += 3;
        }

        // Compute normals
        ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2));
        for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)
        {
            const ImVec2& p0 = points[i0];
            const ImVec2& p1 = points[i1];
            ImVec2 diff = p1 - p0;
            diff *= ImInvLength(diff, 1.0f);
            temp_normals[i0].x = diff.y;
            temp_normals[i0].y = -diff.x;
        }

        for (int i0 = (points_count / 2) - 1, i1 = 0; i1 < points_count / 2; i0 = i1++)
        {
            // Average normals
            const ImVec2& n0 = temp_normals[i0];
            const ImVec2& n1 = temp_normals[i1];
            ImVec2 dm = (n0 + n1) * 0.5f;
            float dmr2 = dm.x*dm.x + dm.y*dm.y;
            if (dmr2 > 0.000001f)
            {
                float scale = 1.0f / dmr2;
                if (scale > 100.0f) scale = 100.0f;
                dm *= scale;
            }
            dm *= AA_SIZE * 0.5f;

   
            // Add indexes for fringes
            _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
            _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
            _IdxWritePtr += 6;

   
            _VtxWritePtr[0].pos = (points[i1]  - dm);
            _VtxWritePtr[0].uv = uv;
            _VtxWritePtr[0].col = col;

            _VtxWritePtr[1].pos = (points[i1] + dm);
            _VtxWritePtr[1].uv = uv;
            _VtxWritePtr[1].col = col_trans;

            _VtxWritePtr += 2;

 
        }

        for (int i0 = points_count - 1, i1 = (points_count / 2); i1 < points_count; i0 = i1++)
        {
            // Average normals
            const ImVec2& n0 = temp_normals[i0];
            const ImVec2& n1 = temp_normals[i1];
            ImVec2 dm = (n0 + n1) * 0.5f;
            float dmr2 = dm.x*dm.x + dm.y*dm.y;
            if (dmr2 > 0.000001f)
            {
                float scale = 1.0f / dmr2;
                if (scale > 100.0f) scale = 100.0f;
                dm *= scale;
            }
            dm *= AA_SIZE * 0.5f;

            // Add indexes for fringes
            _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
            _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
            _IdxWritePtr += 6;

            _VtxWritePtr[0].pos = (points[i1] - dm);
            _VtxWritePtr[0].uv = uv2;
            _VtxWritePtr[0].col = col2;

            _VtxWritePtr[1].pos = (points[i1] - dm);
            _VtxWritePtr[1].uv = uv2;
            _VtxWritePtr[1].col = col_trans2;

            _VtxWritePtr += 2;


        }

        _VtxCurrentIdx += (ImDrawIdx)vtx_count;
    }
    else
    {
        // Non Anti-aliased Fill
        const int idx_count = (points_count-2)*3;
        const int vtx_count = points_count;
        PrimReserve(idx_count, vtx_count);
        for (int i = 0; i < vtx_count; i++)
        {
            _VtxWritePtr[0].pos = points[i];
            _VtxWritePtr[0].uv = uv;
            _VtxWritePtr[0].col = col;
            _VtxWritePtr++;
        }
        for (int i = 2; i < points_count; i++)
        {
            _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i);
            _IdxWritePtr += 3;
        }
        _VtxCurrentIdx += (ImDrawIdx)vtx_count;
    }
}


4. Идём в файлик imgui.h и заменяем вот на эту строчку:
Код:
 IMGUI_API void  AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased,ImU32 col2 = 0xFFFFFFFF);

Это тоже:
Код:
inline    void  PathClear()                                                 { _Path.resize(0); }
    inline    void  PathLineTo(const ImVec2& pos)                               { _Path.push_back(pos); }
    inline    void  PathLineToMergeDuplicate(const ImVec2& pos)                 { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }
    inline    void  PathFill(ImU32 col,ImU32 col2 = 0xFFFFFFFF)                                         { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true , col2); PathClear(); }
    inline    void  PathStroke(ImU32 col, bool closed, float thickness = 1.0f)  { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
    IMGUI_API void  PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
    IMGUI_API void  PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12);                                // Use precomputed angles for a 12 steps circle
    IMGUI_API void  PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
    IMGUI_API void  PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ~0);   // rounding_corners_flags: 4-bits corresponding to which corner to round

5. Дальше, добавляем цвета. Для этого заменим:
Код:
enum ImGuiCol_
{
    ImGuiCol_Text,
    ImGuiCol_TextDisabled,
    ImGuiCol_WindowBg,              // Background of normal windows
    ImGuiCol_ChildWindowBg,         // Background of child windows
    ImGuiCol_PopupBg,               // Background of popups, menus, tooltips windows
    ImGuiCol_Border,
    ImGuiCol_BorderShadow,
    ImGuiCol_FrameBg,               // Background of checkbox, radio button, plot, slider, text input
    ImGuiCol_FrameBgHovered,
    ImGuiCol_FrameBgActive,
    ImGuiCol_TitleBg,
    ImGuiCol_TitleBgCollapsed,
    ImGuiCol_TitleBgActive,
    ImGuiCol_MenuBarBg,
    ImGuiCol_ScrollbarBg,
    ImGuiCol_ScrollbarGrab,
    ImGuiCol_ScrollbarGrabHovered,
    ImGuiCol_ScrollbarGrabActive,
    ImGuiCol_ComboBg,
    ImGuiCol_CheckMark,
    ImGuiCol_SliderGrab,
    ImGuiCol_SliderGrabActive,
    ImGuiCol_Button,
    ImGuiCol_ButtonHovered,
    ImGuiCol_ButtonActive,
    ImGuiCol_Tab,
    ImGuiCol_TabHovered,
    ImGuiCol_TabActive,
    ImGuiCol_TabText,
    ImGuiCol_TabTextActive,
    ImGuiCol_TabSelected,
    ImGuiCol_SelectedLine,
    ImGuiCol_Header,
    ImGuiCol_HeaderHovered,
    ImGuiCol_HeaderActive,
    ImGuiCol_HeaderSelected,
    ImGuiCol_Column,
    ImGuiCol_ColumnHovered,
    ImGuiCol_ColumnActive,
    ImGuiCol_ResizeGrip,
    ImGuiCol_ResizeGripHovered,
    ImGuiCol_ResizeGripActive,
    ImGuiCol_CloseButton,
    ImGuiCol_CloseButtonHovered,
    ImGuiCol_CloseButtonActive,
    ImGuiCol_PlotLines,
    ImGuiCol_PlotLinesHovered,
    ImGuiCol_PlotHistogram,
    ImGuiCol_PlotHistogramHovered,
    ImGuiCol_TextSelectedBg,
    ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active
    ImGuiCol_FirstTabColor,
    ImGuiCol_SecondTabColor,
    ImGuiCol_FirstTabColorHovered,
    ImGuiCol_SecondTabColorHovered,
    ImGuiCol_FirstTabColorActive,
    ImGuiCol_SecondTabColorActive,
    ImGuiCol_COUNT

};

6. И пропишем им цвет в инициализации:
Код:
style.Colors[ImGuiCol_FirstTabColor]  = ImVec4(0.16f, 0.18f, 0.20f, 1.00f);
    style.Colors[ImGuiCol_SecondTabColor] = ImVec4(0.14f, 0.15f, 0.18f, 1.00f);
    style.Colors[ImGuiCol_FirstTabColorHovered] = ImVec4(0.75f, 0.22f, 0.22f, 1.00f);
    style.Colors[ImGuiCol_SecondTabColorHovered] = ImVec4(0.73f, 0.20f, 0.22f, 0.71f);
    style.Colors[ImGuiCol_FirstTabColorActive] = ImVec4(1.00f, 0.49f, 0.51f, 1.00f);
    style.Colors[ImGuiCol_SecondTabColorActive] = ImVec4(0.85f, 0.27f, 0.29f, 1.00f);
Если вы всё сделали правильно, то у вас должно получиться
примерно это:​


P.S. Если я где-то ошибся, или оформил так как не надо или нельзя, поправьте поже)​
Адменам чайку с печеньками) :kissing::roflanEbalo:
 
Последнее редактирование:
Сверху Снизу