pie menu lua

Мемори

Участник
Автор темы
84
10
Версия SA-MP
  1. 0.3.7 (R1)
Приветствую! Помогите реализовать радиальное меню выбор как в МВД хелпере. Не могу разобраться как реализовать. За ранее спасибо

up
 
Последнее редактирование:

Мемори

Участник
Автор темы
84
10
Lua:
local imgui = require 'mimgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8

local CVET_NAVODKI = {0.2, 0.8, 0.2}  -- зеленоватый при наведении
local CVET_OBYCHNIY = {0.1, 0.1, 0.1} -- темно-серый в покое

local pokazat_menu = imgui.new.bool(false)
local animaciya_prozrachnosti = 0.0 -- переменная для плавного появления (анимация)

local RADIUS_VNUTRENNIY = 55 -- внутренний радиус круга
local RADIUS_VNESHNIY = 160   -- внешний радиус круга
local ZAZOR_MEZHDU_SEKTORAMI = 0.04 -- небольшой отступ между кусками пирога

-- список названий в меню
local PUNKTY_MENU = {u8"Статистика", u8"Инвентарь", u8"Настройки", u8"Репорт", u8"Телефон", u8"Выход"}

function dejstvie_statistika()
    sampAddChatMessage("{FFFFFF}вы открыли статистику", -1)
end
function dejstvie_inventar()  
    sampAddChatMessage("{FFFFFF}вы открыли инвентарь", -1)
end
function dejstvie_nastrojki()
    sampAddChatMessage("{FFFFFF}настройки скрипта", -1)
end
function dejstvie_report()    
    sampAddChatMessage("{FFFFFF}связь с администрулькиными", -1)
end
function dejstvie_telefon()  
    sampAddChatMessage("{FFFFFF}достаем звонилку", -1)
end
function dejstvie_vyhod()    
    sampAddChatMessage("{FFFFFF}менюшка закрыта", -1)
end

-- связываем номер кнопки с функцией (какой индекс — такая и функция)
local TABLICA_FUNKCIY = {
    [1] = dejstvie_statistika, -- действие статистика
    [2] = dejstvie_inventar, -- действие инвентарь
    [3] = dejstvie_nastrojki, -- действие настройки
    [4] = dejstvie_report, -- действие репорта
    [5] = dejstvie_telefon, -- действие телефона
    [6] = dejstvie_vyhod -- действие выхода
}

imgui.OnFrame(function() return pokazat_menu[0] or animaciya_prozrachnosti > 0.01 end, function(player)
    -- математика плавного появления и исчезновения (прозрачность)
    if pokazat_menu[0] then
        if animaciya_prozrachnosti < 1.0 then animaciya_prozrachnosti = animaciya_prozrachnosti + 0.1 end
    else
        if animaciya_prozrachnosti > 0.0 then animaciya_prozrachnosti = animaciya_prozrachnosti - 0.1 end
    end

    local shirina_ekrana, visota_ekrana = getScreenResolution()
    imgui.SetNextWindowPos(imgui.ImVec2(0, 0))
    imgui.SetNextWindowSize(imgui.ImVec2(shirina_ekrana, visota_ekrana))
   
    -- окно на весь экран, прозрачное и без рамок
    imgui.Begin('RadialMenu', _, imgui.WindowFlags.NoDecoration + imgui.WindowFlags.NoBackground + imgui.WindowFlags.NoMove + (not pokazat_menu[0] and imgui.WindowFlags.NoInputs or 0))
   
    local io = imgui.GetIO()
    local spisok_otrisovki = imgui.GetWindowDrawList()
    local centr_menu = imgui.ImVec2(shirina_ekrana / 2, visota_ekrana / 2) -- привязка к центру экрана
    local kolvo_punktov = #PUNKTY_MENU
    local shag_ugla = (math.pi * 2) / kolvo_punktov

    for i = 1, kolvo_punktov do
        local nachalo_ugla = shag_ugla * (i - 1) + ZAZOR_MEZHDU_SEKTORAMI
        local konec_ugla = shag_ugla * i - ZAZOR_MEZHDU_SEKTORAMI
       
        -- считаем положение мышки относительно центра меню
        local mishi_x, mishi_y = io.MousePos.x - centr_menu.x, io.MousePos.y - centr_menu.y
        local rasteyanie_mishi = math.sqrt(mishi_x * mishi_x + mishi_y * mishi_y)
        local ugol_mishi = math.atan2(mishi_y, mishi_x)
        if ugol_mishi < 0 then ugol_mishi = ugol_mishi + math.pi * 2 end
       
        -- проверка: наведена ли мышка на конкретный сектор
        local misha_na_sektore = rasteyanie_mishi > RADIUS_VNUTRENNIY and rasteyanie_mishi < RADIUS_VNESHNIY and ugol_mishi > nachalo_ugla and ugol_mishi < konec_ugla and pokazat_menu[0]
       
        -- формируем цвета сектора и текста с учетом анимации прозрачности
        local r, g, b = unpack(misha_na_sektore and CVET_NAVODKI or CVET_OBYCHNIY)
        local cvet_zakraski = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(r, g, b, animaciya_prozrachnosti * 0.8))
        local cvet_teksta = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1, 1, 1, animaciya_prozrachnosti))

        -- рисуем сам сектор
        spisok_otrisovki:PathArcTo(centr_menu, RADIUS_VNUTRENNIY, nachalo_ugla, konec_ugla, 20)
        spisok_otrisovki:PathArcTo(centr_menu, RADIUS_VNESHNIY, konec_ugla, nachalo_ugla, 20)
        spisok_otrisovki:PathFillConvex(cvet_zakraski)
       
        -- считаем координаты для центрирования текста в секторе
        local ugol_dlya_teksta = nachalo_ugla + (konec_ugla - nachalo_ugla) / 2
        local tekst_x = centr_menu.x + math.cos(ugol_dlya_teksta) * (RADIUS_VNUTRENNIY + RADIUS_VNESHNIY) / 2
        local tekst_y = centr_menu.y + math.sin(ugol_dlya_teksta) * (RADIUS_VNUTRENNIY + RADIUS_VNESHNIY) / 2
        local razmer_teksta = imgui.CalcTextSize(PUNKTY_MENU[i])
       
        -- вывод текста
        spisok_otrisovki:AddText(imgui.ImVec2(tekst_x - razmer_teksta.x / 2, tekst_y - razmer_teksta.y / 2), cvet_teksta, PUNKTY_MENU[i])
       
        -- обработка клика левой кнопкой мыши (ЛКМ)
        if misha_na_sektore and imgui.IsMouseReleased(0) then
            if TABLICA_FUNKCIY[i] then TABLICA_FUNKCIY[i]() end
            pokazat_menu[0] = false
        end
    end
   
    -- закрытие меню на правую кнопку мыши (ПКМ)
    if imgui.IsMouseReleased(1) then pokazat_menu[0] = false end
    imgui.End()
end)

function main()
    while not isSampAvailable() do wait(0) end
   
    -- открытие через команду
    sampRegisterChatCommand("rmenu", function() pokazat_menu[0] = not pokazat_menu[0] end)
   
    while true do
        wait(0)
        -- открытие на нажатие клавиши X (0x58)
        if isKeyDown(0x58) and not sampIsCursorActive() and not pokazat_menu[0] then
            pokazat_menu[0] = true
        end
    end
end


думаю это покроет все твои нужды.
Реализовано не так кая я хотел, но работает хорошо, спасибо большое