Вопросы по Lua скриптингу

Общая тема для вопросов по разработке скриптов на языке программирования Lua, в частности под MoonLoader.
  • Задавая вопрос, убедитесь, что его нет в списке частых вопросов и что на него ещё не отвечали (воспользуйтесь поиском).
  • Поищите ответ в теме посвященной разработке Lua скриптов в MoonLoader
  • Отвечая, убедитесь, что ваш ответ корректен.
  • Старайтесь как можно точнее выразить мысль, а если проблема связана с кодом, то обязательно прикрепите его к сообщению, используя блок [code=lua]здесь мог бы быть ваш код[/code].
  • Если вопрос связан с MoonLoader-ом первым делом желательно поискать решение на wiki.

Частые вопросы

Как научиться писать скрипты? С чего начать?
Информация - Гайд - Всё о Lua скриптинге для MoonLoader(https://blast.hk/threads/22707/)
Как вывести текст на русском? Вместо русского текста у меня какие-то каракули.
Изменить кодировку файла скрипта на Windows-1251. В Atom: комбинация клавиш Ctrl+Shift+U, в Notepad++: меню Кодировки -> Кодировки -> Кириллица -> Windows-1251.
Как получить транспорт, в котором сидит игрок?
Lua:
local veh = storeCarCharIsInNoSave(PLAYER_PED)
Как получить свой id или id другого игрока?
Lua:
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- получить свой ид
local _, id = sampGetPlayerIdByCharHandle(ped) -- получить ид другого игрока. ped - это хендл персонажа
Как проверить, что строка содержит какой-то текст?
Lua:
if string.find(str, 'текст', 1, true) then
-- строка str содержит "текст"
end
Как эмулировать нажатие игровой клавиши?
Lua:
local game_keys = require 'game.keys' -- где-нибудь в начале скрипта вне функции main

setGameKeyState(game_keys.player.FIREWEAPON, -1) -- будет сэмулировано нажатие клавиши атаки
Все иды клавиш находятся в файле moonloader/lib/game/keys.lua.
Подробнее о функции setGameKeyState здесь: lua - setgamekeystate | BlastHack — DEV_WIKI(https://www.blast.hk/wiki/lua:setgamekeystate)
Как получить id другого игрока, в которого целюсь я?
Lua:
local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- получить хендл персонажа, в которого целится игрок
if valid and doesCharExist(ped) then -- если цель есть и персонаж существует
  local result, id = sampGetPlayerIdByCharHandle(ped) -- получить samp-ид игрока по хендлу персонажа
  if result then -- проверить, прошло ли получение ида успешно
    -- здесь любые действия с полученным идом игрока
  end
end
Как зарегистрировать команду чата SAMP?
Lua:
-- До бесконечного цикла/задержки
sampRegisterChatCommand("mycommand", function (param)
     -- param будет содержать весь текст введенный после команды, чтобы разделить его на аргументы используйте string.match()
    sampAddChatMessage("MyCMD", -1)
end)
Крашит игру при вызове sampSendChat. Как это исправить?
Это происходит из-за бага в SAMPFUNCS, когда производится попытка отправки пакета определенными функциями изнутри события исходящих RPC и пакетов. Исправления для этого бага нет, но есть способ не провоцировать его. Вызов sampSendChat изнутри обработчика исходящих RPC/пакетов нужно обернуть в скриптовый поток с нулевой задержкой:
Lua:
function onSendRpc(id)
  -- крашит:
  -- sampSendChat('Send RPC: ' .. id)

  -- норм:
  lua_thread.create(function()
    wait(0)
    sampSendChat('Send RPC: ' .. id)
  end)
end
 
Последнее редактирование:

Мира

Участник
455
9
Как сохранять выбор Checkbox?
Lua:
  imgui.Checkbox(u8"Женские отыгровки?", checked_test)
  end
    imgui.End()
end
 

|DEVIL|

Известный
359
273
Как сделать круглую фигню в которой мышкой надо крутить число в имгуи?
 

Мира

Участник
455
9
Как сделать круглую фигню в которой мышкой надо крутить число в имгуи?
Lua:
local pie = require 'imgui_piemenu'

if imgui.IsWindowHovered() and imgui.IsMouseClicked(1) then
  imgui.OpenPopup('PieMenu')
end
if pie.BeginPiePopup('PieMenu', 1) then
  if pie.PieMenuItem('Test1') then end
if pie.PieMenuItem('Test2') then end
  --if pie.PieMenuItem('Test5') then end
  if pie.PieMenuItem('Test3', false) then end
  if pie.BeginPieMenu('Sub') then
    if pie.BeginPieMenu('Sub sub\nmenu') then
      if pie.PieMenuItem('SubSub') then end
      if pie.PieMenuItem('SubSub2') then end
      pie.EndPieMenu()
    end
    if pie.PieMenuItem('TestSub') then end
    if pie.PieMenuItem('TestSub2') then end
   pie.EndPieMenu()
  end
  pie.EndPiePopup()
end
Lua:
-- https://gist.github.com/thennequin/64b4b996ec990c6ddc13a48c6a0ba68c
-- ported to Lua by FYP
local imgui = require 'imgui'
local vmajor, vminor, vpatch = string.match(imgui._VERSION, '(%d+)%.(%d+)%.(%d+)')
assert(tonumber(vmajor) == 1 and (tonumber(vminor) > 1 or (tonumber(vminor) == 1 and tonumber(vpatch) >= 3)),
    'ImGui Pie requires Moon ImGui v1.1.4 or greater')
local ImVec2 = imgui.ImVec2
local ImVec4 = imgui.ImVec4
local ImColor = imgui.ImColor

local function ImRectAdd(rect, rhs)
    local Min, Max = rect.Min, rect.Max
    if Min.x > rhs.x then Min.x = rhs.x end
    if Min.y > rhs.y then Min.y = rhs.y end
    if Max.x < rhs.x then Max.x = rhs.x end
    if Max.y < rhs.y then Max.y = rhs.y end
end

local function NewPieMenu(context)
    local obj = {
        m_iCurrentIndex = 0,
        m_fMaxItemSqrDiameter = 0,
        m_fLastMaxItemSqrDiameter = 0,
        m_iHoveredItem = 0,
        m_iLastHoveredItem = 0,
        m_iClickedItem = 0,
        m_oItemIsSubMenu = {}, -- [c_iMaxPieItemCount]
        m_oItemNames = {}, -- [c_iMaxPieItemCount]
        m_oItemSizes = {}, -- [c_iMaxPieItemCount]
    }
    return obj
end

local function NewPieMenuContext(MaxPieMenuStack, MaxPieItemCount, RadiusEmpty, RadiusMin, MinItemCount, MinItemCountPerLevel)
    local obj = {
        c_iMaxPieMenuStack = MaxPieMenuStack or 8,
        c_iMaxPieItemCount = MaxPieItemCount or 12,
        c_iRadiusEmpty = RadiusEmpty or 30,
        c_iRadiusMin = RadiusMin or 30,
        c_iMinItemCount = MinItemCount or 3,
        c_iMinItemCountPerLevel = MinItemCountPerLevel or 3,

        m_oPieMenuStack = {},
        m_iCurrentIndex = -1,
        m_iLastFrame = 0,
        m_iMaxIndex = 0,
        m_oCenter = ImVec2(0, 0),
        m_iMouseButton = 0,
        m_bClose = false,
    }
    for i = 0, obj.c_iMaxPieMenuStack - 1 do
        obj.m_oPieMenuStack[i] = NewPieMenu(obj)
    end
    return obj
end

--local menuCtx = NewPieMenuContext()

local function BeginPieMenuEx(menuCtx)
    assert(menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieMenuStack)
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex + 1
    menuCtx.m_iMaxIndex = menuCtx.m_iMaxIndex + 1
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    oPieMenu.m_iCurrentIndex = 0
    oPieMenu.m_fMaxItemSqrDiameter = 0
    if not imgui.IsMouseReleased( menuCtx.m_iMouseButton ) then
        oPieMenu.m_iHoveredItem = -1
    end
    if menuCtx.m_iCurrentIndex > 0 then
        oPieMenu.m_fMaxItemSqrDiameter = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex - 1].m_fMaxItemSqrDiameter
    end
end

local function EndPieMenuEx(menuCtx)
    assert(menuCtx.m_iCurrentIndex >= 0)
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex - 1
end

local function BeginPiePopup(menuCtx, pName, iMouseButton)
    iMouseButton = iMouseButton or 0
    if imgui.IsPopupOpen(pName) then
        imgui.PushStyleColor(imgui.Col.WindowBg, ImVec4(0, 0, 0, 0))
        imgui.PushStyleColor(imgui.Col.Border, ImVec4(0, 0, 0, 0))
        imgui.PushStyleVar(imgui.StyleVar.WindowRounding, 0.0)
        imgui.PushStyleVar(imgui.StyleVar.Alpha, 1.0)
        menuCtx.m_iMouseButton = iMouseButton
        menuCtx.m_bClose = false
        imgui.SetNextWindowPos( ImVec2( -100, -100 ), imgui.Cond.Appearing )
        imgui.SetNextWindowSize(ImVec2(0, 0), imgui.Cond.Always)
        local bOpened = imgui.BeginPopup(pName)
        if bOpened then
            local iCurrentFrame = imgui.GetFrameCount()
            if menuCtx.m_iLastFrame < (iCurrentFrame - 1) then
                menuCtx.m_oCenter = ImVec2(imgui.GetIO().MousePos)
            end
            menuCtx.m_iLastFrame = iCurrentFrame
            menuCtx.m_iMaxIndex = -1
            BeginPieMenuEx(menuCtx)
            return true
        else
            imgui.End()
            imgui.PopStyleColor(2)
            imgui.PopStyleVar(2)
        end
    end
    return false
end

local function EndPiePopup(menuCtx)
    EndPieMenuEx(menuCtx)
    local oStyle = imgui.GetStyle()
    local pDrawList = imgui.GetWindowDrawList()
    pDrawList:PushClipRectFullScreen()
    local oMousePos = imgui.GetIO().MousePos
    local oDragDelta = ImVec2(oMousePos.x - menuCtx.m_oCenter.x, oMousePos.y - menuCtx.m_oCenter.y)
    local fDragDistSqr = oDragDelta.x*oDragDelta.x + oDragDelta.y*oDragDelta.y
    local fCurrentRadius = menuCtx.c_iRadiusEmpty
    -- ImRect
    local oArea = {Min = ImVec2(menuCtx.m_oCenter), Max = ImVec2(menuCtx.m_oCenter)}
    local bItemHovered = false
    local c_fDefaultRotate = -math.pi / 2
    local fLastRotate = c_fDefaultRotate
    for iIndex = 0, menuCtx.m_iMaxIndex do
        local oPieMenu = menuCtx.m_oPieMenuStack[iIndex]
        local fMenuHeight = math.sqrt(oPieMenu.m_fMaxItemSqrDiameter)
        local fMinRadius = fCurrentRadius
        local fMaxRadius = fMinRadius + (fMenuHeight * oPieMenu.m_iCurrentIndex) / 2
        local item_arc_span = 2 * math.pi / math.max(menuCtx.c_iMinItemCount + menuCtx.c_iMinItemCountPerLevel * iIndex, oPieMenu.m_iCurrentIndex)
        local drag_angle = math.atan2(oDragDelta.y, oDragDelta.x)
        local fRotate = fLastRotate - item_arc_span * ( oPieMenu.m_iCurrentIndex - 1 ) / 2
        local item_hovered = -1
        for item_n = 0, oPieMenu.m_iCurrentIndex - 1 do
            local item_label = oPieMenu.m_oItemNames[ item_n ]
            local inner_spacing = oStyle.ItemInnerSpacing.x / fMinRadius / 2
            local fMinInnerSpacing = oStyle.ItemInnerSpacing.x / ( fMinRadius * 2 )
            local fMaxInnerSpacing = oStyle.ItemInnerSpacing.x / ( fMaxRadius * 2 )
            local item_inner_ang_min = item_arc_span * ( item_n - 0.5 + fMinInnerSpacing ) + fRotate
            local item_inner_ang_max = item_arc_span * ( item_n + 0.5 - fMinInnerSpacing ) + fRotate
            local item_outer_ang_min = item_arc_span * ( item_n - 0.5 + fMaxInnerSpacing ) + fRotate
            local item_outer_ang_max = item_arc_span * ( item_n + 0.5 - fMaxInnerSpacing ) + fRotate
            local hovered = false
            if fDragDistSqr >= fMinRadius * fMinRadius and fDragDistSqr < fMaxRadius * fMaxRadius  then
                while (drag_angle - item_inner_ang_min) < 0 do
                    drag_angle = drag_angle + (2 * math.pi)
                end
                while (drag_angle - item_inner_ang_min) > 2 * math.pi do
                    drag_angle = drag_angle - (2 * math.pi)
                end
                if drag_angle >= item_inner_ang_min and drag_angle < item_inner_ang_max  then
                    hovered = true
                    bItemHovered = not oPieMenu.m_oItemIsSubMenu[ item_n ]
                end
            end
            -- draw segments
            local arc_segments = math.floor(( 32 * item_arc_span / ( 2 * math.pi ) ) + 1)
            local iColor = imgui.GetStyleColorU32( hovered and imgui.Col.ButtonHovered or imgui.Col.Button )
            local fAngleStepInner = (item_inner_ang_max - item_inner_ang_min) / arc_segments
            local fAngleStepOuter = ( item_outer_ang_max - item_outer_ang_min ) / arc_segments
            pDrawList:PrimReserve(arc_segments * 6, (arc_segments + 1) * 2)
            for iSeg = 0, arc_segments do
                local fCosInner = math.cos(item_inner_ang_min + fAngleStepInner * iSeg)
                local fSinInner = math.sin(item_inner_ang_min + fAngleStepInner * iSeg)
                local fCosOuter = math.cos(item_outer_ang_min + fAngleStepOuter * iSeg)
                local fSinOuter = math.sin(item_outer_ang_min + fAngleStepOuter * iSeg)

                if iSeg < arc_segments then
                    local VtxCurrentIdx = pDrawList._VtxCurrentIdx
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 0)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 2)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 1)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 3)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 2)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 1)
                end
                local pos = ImVec2(menuCtx.m_oCenter.x + fCosInner * (fMinRadius + oStyle.ItemInnerSpacing.x), menuCtx.m_oCenter.y + fSinInner * (fMinRadius + oStyle.ItemInnerSpacing.x))
                local pos2 = ImVec2(menuCtx.m_oCenter.x + fCosOuter * (fMaxRadius - oStyle.ItemInnerSpacing.x), menuCtx.m_oCenter.y + fSinOuter * (fMaxRadius - oStyle.ItemInnerSpacing.x))
                pDrawList:PrimWriteVtx(pos, ImVec2(0, 0), iColor)
                pDrawList:PrimWriteVtx(pos2, ImVec2(0, 0), iColor)
            end

            --[[ old way without pDrawList._VtxCurrentIdx
            pDrawList:PathArcTo(menuCtx.m_oCenter, fMaxRadius - oStyle.ItemInnerSpacing.x, item_outer_ang_min, item_outer_ang_max, arc_segments)
            pDrawList:PathArcTo(menuCtx.m_oCenter, fMinRadius + oStyle.ItemInnerSpacing.x, item_outer_ang_max, item_outer_ang_min, arc_segments)
            pDrawList:PathFillConvex(iColor)
            ]]

            local fRadCenter = ( item_arc_span * item_n ) + fRotate
            local oOuterCenter = ImVec2( menuCtx.m_oCenter.x + math.cos( fRadCenter ) * fMaxRadius, menuCtx.m_oCenter.y + math.sin( fRadCenter ) * fMaxRadius )
            ImRectAdd(oArea, oOuterCenter)
            if oPieMenu.m_oItemIsSubMenu[item_n] then
                local oTrianglePos = {ImVec2(), ImVec2(), ImVec2()}
                local fRadLeft = fRadCenter - 5 / fMaxRadius
                local fRadRight = fRadCenter + 5 / fMaxRadius
                oTrianglePos[ 0+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadCenter ) * ( fMaxRadius - 5 )
                oTrianglePos[ 0+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadCenter ) * ( fMaxRadius - 5 )
                oTrianglePos[ 1+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadLeft ) * ( fMaxRadius - 10 )
                oTrianglePos[ 1+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadLeft ) * ( fMaxRadius - 10 )
                oTrianglePos[ 2+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadRight ) * ( fMaxRadius - 10 )
                oTrianglePos[ 2+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadRight ) * ( fMaxRadius - 10 )
                pDrawList:AddTriangleFilled(oTrianglePos[1], oTrianglePos[2], oTrianglePos[3], 0xFFFFFFFF)
            end
            local text_size = ImVec2(oPieMenu.m_oItemSizes[item_n])
            local text_pos = ImVec2(
                menuCtx.m_oCenter.x + math.cos((item_inner_ang_min + item_inner_ang_max) * 0.5) * (fMinRadius + fMaxRadius) * 0.5 - text_size.x * 0.5,
                menuCtx.m_oCenter.y + math.sin((item_inner_ang_min + item_inner_ang_max) * 0.5) * (fMinRadius + fMaxRadius) * 0.5 - text_size.y * 0.5)
            pDrawList:AddText(text_pos, imgui.GetStyleColorU32(imgui.Col.Text), item_label)
            if hovered then
                item_hovered = item_n
            end
        end
        fCurrentRadius = fMaxRadius
        oPieMenu.m_fLastMaxItemSqrDiameter = oPieMenu.m_fMaxItemSqrDiameter
        oPieMenu.m_iHoveredItem = item_hovered
        if fDragDistSqr >= fMaxRadius * fMaxRadius then
            item_hovered = oPieMenu.m_iLastHoveredItem
        end
        oPieMenu.m_iLastHoveredItem = item_hovered
        fLastRotate = item_arc_span * oPieMenu.m_iLastHoveredItem + fRotate
        if item_hovered == -1 or not oPieMenu.m_oItemIsSubMenu[item_hovered] then
            break
        end
    end
    pDrawList:PopClipRect()
    if oArea.Min.x < 0  then
        menuCtx.m_oCenter.x = ( menuCtx.m_oCenter.x - oArea.Min.x )
    end
    if oArea.Min.y < 0  then
        menuCtx.m_oCenter.y = ( menuCtx.m_oCenter.y - oArea.Min.y )
    end
    local oDisplaySize = imgui.GetIO().DisplaySize
    if oArea.Max.x > oDisplaySize.x  then
        menuCtx.m_oCenter.x = ( menuCtx.m_oCenter.x - oArea.Max.x ) + oDisplaySize.x
    end
    if oArea.Max.y > oDisplaySize.y  then
        menuCtx.m_oCenter.y = ( menuCtx.m_oCenter.y - oArea.Max.y ) + oDisplaySize.y
    end
    if menuCtx.m_bClose or ( not bItemHovered and imgui.IsMouseReleased( menuCtx.m_iMouseButton ) ) then
        imgui.CloseCurrentPopup()
    end
    imgui.EndPopup()
    imgui.PopStyleColor(2)
    imgui.PopStyleVar(2)
end

local function BeginPieMenu(menuCtx, pName, bEnabled)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    bEnabled = bEnabled or true
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    local oTextSize = imgui.CalcTextSize(pName, true)
    oPieMenu.m_oItemSizes[oPieMenu.m_iCurrentIndex] = oTextSize
     local fSqrDiameter = oTextSize.x * oTextSize.x + oTextSize.y * oTextSize.y
    if fSqrDiameter > oPieMenu.m_fMaxItemSqrDiameter then
        oPieMenu.m_fMaxItemSqrDiameter = fSqrDiameter
    end
    oPieMenu.m_oItemIsSubMenu[oPieMenu.m_iCurrentIndex] = true
    oPieMenu.m_oItemNames[oPieMenu.m_iCurrentIndex] = pName
    if oPieMenu.m_iLastHoveredItem == oPieMenu.m_iCurrentIndex then
        oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
        BeginPieMenuEx(menuCtx)
        return true
    end
    oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
    return false
end

local function EndPieMenu(menuCtx)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex - 1
end

local function PieMenuItem(menuCtx, pName, bEnabled)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    bEnabled = bEnabled or true
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    local oTextSize = imgui.CalcTextSize(pName, true)
    oPieMenu.m_oItemSizes[oPieMenu.m_iCurrentIndex] = oTextSize
    local fSqrDiameter = oTextSize.x * oTextSize.x + oTextSize.y * oTextSize.y
    if fSqrDiameter > oPieMenu.m_fMaxItemSqrDiameter then
        oPieMenu.m_fMaxItemSqrDiameter = fSqrDiameter
    end
    oPieMenu.m_oItemIsSubMenu[oPieMenu.m_iCurrentIndex] = false
    oPieMenu.m_oItemNames[oPieMenu.m_iCurrentIndex] = pName
    local bActive = oPieMenu.m_iCurrentIndex == oPieMenu.m_iHoveredItem
    oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
    if bActive then
        menuCtx.m_bClose = true
    end
    return bActive
end

local function New(...)
    local menuContext = NewPieMenuContext(...)
    return {
        BeginPiePopup = function(name, mouseButton)
            return BeginPiePopup(menuContext, name, mouseButton)
        end,
        EndPiePopup = function()
            return EndPiePopup(menuContext)
        end,
        PieMenuItem = function(name, enabled)
            return PieMenuItem(menuContext, name, enabled)
        end,
        BeginPieMenu = function(name, enabled)
            return BeginPieMenu(menuContext, name, enabled)
        end,
        EndPieMenu = function()
            return EndPieMenu(menuContext)
        end
    }
end

local defaultPieMenu = New()
defaultPieMenu.New = New
return defaultPieMenu
 

|DEVIL|

Известный
359
273
Lua:
-- https://gist.github.com/thennequin/64b4b996ec990c6ddc13a48c6a0ba68c
-- ported to Lua by FYP
local imgui = require 'imgui'
local vmajor, vminor, vpatch = string.match(imgui._VERSION, '(%d+)%.(%d+)%.(%d+)')
assert(tonumber(vmajor) == 1 and (tonumber(vminor) > 1 or (tonumber(vminor) == 1 and tonumber(vpatch) >= 3)),
    'ImGui Pie requires Moon ImGui v1.1.4 or greater')
local ImVec2 = imgui.ImVec2
local ImVec4 = imgui.ImVec4
local ImColor = imgui.ImColor

local function ImRectAdd(rect, rhs)
    local Min, Max = rect.Min, rect.Max
    if Min.x > rhs.x then Min.x = rhs.x end
    if Min.y > rhs.y then Min.y = rhs.y end
    if Max.x < rhs.x then Max.x = rhs.x end
    if Max.y < rhs.y then Max.y = rhs.y end
end

local function NewPieMenu(context)
    local obj = {
        m_iCurrentIndex = 0,
        m_fMaxItemSqrDiameter = 0,
        m_fLastMaxItemSqrDiameter = 0,
        m_iHoveredItem = 0,
        m_iLastHoveredItem = 0,
        m_iClickedItem = 0,
        m_oItemIsSubMenu = {}, -- [c_iMaxPieItemCount]
        m_oItemNames = {}, -- [c_iMaxPieItemCount]
        m_oItemSizes = {}, -- [c_iMaxPieItemCount]
    }
    return obj
end

local function NewPieMenuContext(MaxPieMenuStack, MaxPieItemCount, RadiusEmpty, RadiusMin, MinItemCount, MinItemCountPerLevel)
    local obj = {
        c_iMaxPieMenuStack = MaxPieMenuStack or 8,
        c_iMaxPieItemCount = MaxPieItemCount or 12,
        c_iRadiusEmpty = RadiusEmpty or 30,
        c_iRadiusMin = RadiusMin or 30,
        c_iMinItemCount = MinItemCount or 3,
        c_iMinItemCountPerLevel = MinItemCountPerLevel or 3,

        m_oPieMenuStack = {},
        m_iCurrentIndex = -1,
        m_iLastFrame = 0,
        m_iMaxIndex = 0,
        m_oCenter = ImVec2(0, 0),
        m_iMouseButton = 0,
        m_bClose = false,
    }
    for i = 0, obj.c_iMaxPieMenuStack - 1 do
        obj.m_oPieMenuStack[i] = NewPieMenu(obj)
    end
    return obj
end

--local menuCtx = NewPieMenuContext()

local function BeginPieMenuEx(menuCtx)
    assert(menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieMenuStack)
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex + 1
    menuCtx.m_iMaxIndex = menuCtx.m_iMaxIndex + 1
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    oPieMenu.m_iCurrentIndex = 0
    oPieMenu.m_fMaxItemSqrDiameter = 0
    if not imgui.IsMouseReleased( menuCtx.m_iMouseButton ) then
        oPieMenu.m_iHoveredItem = -1
    end
    if menuCtx.m_iCurrentIndex > 0 then
        oPieMenu.m_fMaxItemSqrDiameter = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex - 1].m_fMaxItemSqrDiameter
    end
end

local function EndPieMenuEx(menuCtx)
    assert(menuCtx.m_iCurrentIndex >= 0)
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex - 1
end

local function BeginPiePopup(menuCtx, pName, iMouseButton)
    iMouseButton = iMouseButton or 0
    if imgui.IsPopupOpen(pName) then
        imgui.PushStyleColor(imgui.Col.WindowBg, ImVec4(0, 0, 0, 0))
        imgui.PushStyleColor(imgui.Col.Border, ImVec4(0, 0, 0, 0))
        imgui.PushStyleVar(imgui.StyleVar.WindowRounding, 0.0)
        imgui.PushStyleVar(imgui.StyleVar.Alpha, 1.0)
        menuCtx.m_iMouseButton = iMouseButton
        menuCtx.m_bClose = false
        imgui.SetNextWindowPos( ImVec2( -100, -100 ), imgui.Cond.Appearing )
        imgui.SetNextWindowSize(ImVec2(0, 0), imgui.Cond.Always)
        local bOpened = imgui.BeginPopup(pName)
        if bOpened then
            local iCurrentFrame = imgui.GetFrameCount()
            if menuCtx.m_iLastFrame < (iCurrentFrame - 1) then
                menuCtx.m_oCenter = ImVec2(imgui.GetIO().MousePos)
            end
            menuCtx.m_iLastFrame = iCurrentFrame
            menuCtx.m_iMaxIndex = -1
            BeginPieMenuEx(menuCtx)
            return true
        else
            imgui.End()
            imgui.PopStyleColor(2)
            imgui.PopStyleVar(2)
        end
    end
    return false
end

local function EndPiePopup(menuCtx)
    EndPieMenuEx(menuCtx)
    local oStyle = imgui.GetStyle()
    local pDrawList = imgui.GetWindowDrawList()
    pDrawList:PushClipRectFullScreen()
    local oMousePos = imgui.GetIO().MousePos
    local oDragDelta = ImVec2(oMousePos.x - menuCtx.m_oCenter.x, oMousePos.y - menuCtx.m_oCenter.y)
    local fDragDistSqr = oDragDelta.x*oDragDelta.x + oDragDelta.y*oDragDelta.y
    local fCurrentRadius = menuCtx.c_iRadiusEmpty
    -- ImRect
    local oArea = {Min = ImVec2(menuCtx.m_oCenter), Max = ImVec2(menuCtx.m_oCenter)}
    local bItemHovered = false
    local c_fDefaultRotate = -math.pi / 2
    local fLastRotate = c_fDefaultRotate
    for iIndex = 0, menuCtx.m_iMaxIndex do
        local oPieMenu = menuCtx.m_oPieMenuStack[iIndex]
        local fMenuHeight = math.sqrt(oPieMenu.m_fMaxItemSqrDiameter)
        local fMinRadius = fCurrentRadius
        local fMaxRadius = fMinRadius + (fMenuHeight * oPieMenu.m_iCurrentIndex) / 2
        local item_arc_span = 2 * math.pi / math.max(menuCtx.c_iMinItemCount + menuCtx.c_iMinItemCountPerLevel * iIndex, oPieMenu.m_iCurrentIndex)
        local drag_angle = math.atan2(oDragDelta.y, oDragDelta.x)
        local fRotate = fLastRotate - item_arc_span * ( oPieMenu.m_iCurrentIndex - 1 ) / 2
        local item_hovered = -1
        for item_n = 0, oPieMenu.m_iCurrentIndex - 1 do
            local item_label = oPieMenu.m_oItemNames[ item_n ]
            local inner_spacing = oStyle.ItemInnerSpacing.x / fMinRadius / 2
            local fMinInnerSpacing = oStyle.ItemInnerSpacing.x / ( fMinRadius * 2 )
            local fMaxInnerSpacing = oStyle.ItemInnerSpacing.x / ( fMaxRadius * 2 )
            local item_inner_ang_min = item_arc_span * ( item_n - 0.5 + fMinInnerSpacing ) + fRotate
            local item_inner_ang_max = item_arc_span * ( item_n + 0.5 - fMinInnerSpacing ) + fRotate
            local item_outer_ang_min = item_arc_span * ( item_n - 0.5 + fMaxInnerSpacing ) + fRotate
            local item_outer_ang_max = item_arc_span * ( item_n + 0.5 - fMaxInnerSpacing ) + fRotate
            local hovered = false
            if fDragDistSqr >= fMinRadius * fMinRadius and fDragDistSqr < fMaxRadius * fMaxRadius  then
                while (drag_angle - item_inner_ang_min) < 0 do
                    drag_angle = drag_angle + (2 * math.pi)
                end
                while (drag_angle - item_inner_ang_min) > 2 * math.pi do
                    drag_angle = drag_angle - (2 * math.pi)
                end
                if drag_angle >= item_inner_ang_min and drag_angle < item_inner_ang_max  then
                    hovered = true
                    bItemHovered = not oPieMenu.m_oItemIsSubMenu[ item_n ]
                end
            end
            -- draw segments
            local arc_segments = math.floor(( 32 * item_arc_span / ( 2 * math.pi ) ) + 1)
            local iColor = imgui.GetStyleColorU32( hovered and imgui.Col.ButtonHovered or imgui.Col.Button )
            local fAngleStepInner = (item_inner_ang_max - item_inner_ang_min) / arc_segments
            local fAngleStepOuter = ( item_outer_ang_max - item_outer_ang_min ) / arc_segments
            pDrawList:PrimReserve(arc_segments * 6, (arc_segments + 1) * 2)
            for iSeg = 0, arc_segments do
                local fCosInner = math.cos(item_inner_ang_min + fAngleStepInner * iSeg)
                local fSinInner = math.sin(item_inner_ang_min + fAngleStepInner * iSeg)
                local fCosOuter = math.cos(item_outer_ang_min + fAngleStepOuter * iSeg)
                local fSinOuter = math.sin(item_outer_ang_min + fAngleStepOuter * iSeg)

                if iSeg < arc_segments then
                    local VtxCurrentIdx = pDrawList._VtxCurrentIdx
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 0)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 2)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 1)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 3)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 2)
                    pDrawList:PrimWriteIdx(VtxCurrentIdx + 1)
                end
                local pos = ImVec2(menuCtx.m_oCenter.x + fCosInner * (fMinRadius + oStyle.ItemInnerSpacing.x), menuCtx.m_oCenter.y + fSinInner * (fMinRadius + oStyle.ItemInnerSpacing.x))
                local pos2 = ImVec2(menuCtx.m_oCenter.x + fCosOuter * (fMaxRadius - oStyle.ItemInnerSpacing.x), menuCtx.m_oCenter.y + fSinOuter * (fMaxRadius - oStyle.ItemInnerSpacing.x))
                pDrawList:PrimWriteVtx(pos, ImVec2(0, 0), iColor)
                pDrawList:PrimWriteVtx(pos2, ImVec2(0, 0), iColor)
            end

            --[[ old way without pDrawList._VtxCurrentIdx
            pDrawList:PathArcTo(menuCtx.m_oCenter, fMaxRadius - oStyle.ItemInnerSpacing.x, item_outer_ang_min, item_outer_ang_max, arc_segments)
            pDrawList:PathArcTo(menuCtx.m_oCenter, fMinRadius + oStyle.ItemInnerSpacing.x, item_outer_ang_max, item_outer_ang_min, arc_segments)
            pDrawList:PathFillConvex(iColor)
            ]]

            local fRadCenter = ( item_arc_span * item_n ) + fRotate
            local oOuterCenter = ImVec2( menuCtx.m_oCenter.x + math.cos( fRadCenter ) * fMaxRadius, menuCtx.m_oCenter.y + math.sin( fRadCenter ) * fMaxRadius )
            ImRectAdd(oArea, oOuterCenter)
            if oPieMenu.m_oItemIsSubMenu[item_n] then
                local oTrianglePos = {ImVec2(), ImVec2(), ImVec2()}
                local fRadLeft = fRadCenter - 5 / fMaxRadius
                local fRadRight = fRadCenter + 5 / fMaxRadius
                oTrianglePos[ 0+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadCenter ) * ( fMaxRadius - 5 )
                oTrianglePos[ 0+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadCenter ) * ( fMaxRadius - 5 )
                oTrianglePos[ 1+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadLeft ) * ( fMaxRadius - 10 )
                oTrianglePos[ 1+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadLeft ) * ( fMaxRadius - 10 )
                oTrianglePos[ 2+1 ].x = menuCtx.m_oCenter.x + math.cos( fRadRight ) * ( fMaxRadius - 10 )
                oTrianglePos[ 2+1 ].y = menuCtx.m_oCenter.y + math.sin( fRadRight ) * ( fMaxRadius - 10 )
                pDrawList:AddTriangleFilled(oTrianglePos[1], oTrianglePos[2], oTrianglePos[3], 0xFFFFFFFF)
            end
            local text_size = ImVec2(oPieMenu.m_oItemSizes[item_n])
            local text_pos = ImVec2(
                menuCtx.m_oCenter.x + math.cos((item_inner_ang_min + item_inner_ang_max) * 0.5) * (fMinRadius + fMaxRadius) * 0.5 - text_size.x * 0.5,
                menuCtx.m_oCenter.y + math.sin((item_inner_ang_min + item_inner_ang_max) * 0.5) * (fMinRadius + fMaxRadius) * 0.5 - text_size.y * 0.5)
            pDrawList:AddText(text_pos, imgui.GetStyleColorU32(imgui.Col.Text), item_label)
            if hovered then
                item_hovered = item_n
            end
        end
        fCurrentRadius = fMaxRadius
        oPieMenu.m_fLastMaxItemSqrDiameter = oPieMenu.m_fMaxItemSqrDiameter
        oPieMenu.m_iHoveredItem = item_hovered
        if fDragDistSqr >= fMaxRadius * fMaxRadius then
            item_hovered = oPieMenu.m_iLastHoveredItem
        end
        oPieMenu.m_iLastHoveredItem = item_hovered
        fLastRotate = item_arc_span * oPieMenu.m_iLastHoveredItem + fRotate
        if item_hovered == -1 or not oPieMenu.m_oItemIsSubMenu[item_hovered] then
            break
        end
    end
    pDrawList:PopClipRect()
    if oArea.Min.x < 0  then
        menuCtx.m_oCenter.x = ( menuCtx.m_oCenter.x - oArea.Min.x )
    end
    if oArea.Min.y < 0  then
        menuCtx.m_oCenter.y = ( menuCtx.m_oCenter.y - oArea.Min.y )
    end
    local oDisplaySize = imgui.GetIO().DisplaySize
    if oArea.Max.x > oDisplaySize.x  then
        menuCtx.m_oCenter.x = ( menuCtx.m_oCenter.x - oArea.Max.x ) + oDisplaySize.x
    end
    if oArea.Max.y > oDisplaySize.y  then
        menuCtx.m_oCenter.y = ( menuCtx.m_oCenter.y - oArea.Max.y ) + oDisplaySize.y
    end
    if menuCtx.m_bClose or ( not bItemHovered and imgui.IsMouseReleased( menuCtx.m_iMouseButton ) ) then
        imgui.CloseCurrentPopup()
    end
    imgui.EndPopup()
    imgui.PopStyleColor(2)
    imgui.PopStyleVar(2)
end

local function BeginPieMenu(menuCtx, pName, bEnabled)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    bEnabled = bEnabled or true
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    local oTextSize = imgui.CalcTextSize(pName, true)
    oPieMenu.m_oItemSizes[oPieMenu.m_iCurrentIndex] = oTextSize
     local fSqrDiameter = oTextSize.x * oTextSize.x + oTextSize.y * oTextSize.y
    if fSqrDiameter > oPieMenu.m_fMaxItemSqrDiameter then
        oPieMenu.m_fMaxItemSqrDiameter = fSqrDiameter
    end
    oPieMenu.m_oItemIsSubMenu[oPieMenu.m_iCurrentIndex] = true
    oPieMenu.m_oItemNames[oPieMenu.m_iCurrentIndex] = pName
    if oPieMenu.m_iLastHoveredItem == oPieMenu.m_iCurrentIndex then
        oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
        BeginPieMenuEx(menuCtx)
        return true
    end
    oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
    return false
end

local function EndPieMenu(menuCtx)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    menuCtx.m_iCurrentIndex = menuCtx.m_iCurrentIndex - 1
end

local function PieMenuItem(menuCtx, pName, bEnabled)
    assert(menuCtx.m_iCurrentIndex >= 0 and menuCtx.m_iCurrentIndex < menuCtx.c_iMaxPieItemCount)
    bEnabled = bEnabled or true
    local oPieMenu = menuCtx.m_oPieMenuStack[menuCtx.m_iCurrentIndex]
    local oTextSize = imgui.CalcTextSize(pName, true)
    oPieMenu.m_oItemSizes[oPieMenu.m_iCurrentIndex] = oTextSize
    local fSqrDiameter = oTextSize.x * oTextSize.x + oTextSize.y * oTextSize.y
    if fSqrDiameter > oPieMenu.m_fMaxItemSqrDiameter then
        oPieMenu.m_fMaxItemSqrDiameter = fSqrDiameter
    end
    oPieMenu.m_oItemIsSubMenu[oPieMenu.m_iCurrentIndex] = false
    oPieMenu.m_oItemNames[oPieMenu.m_iCurrentIndex] = pName
    local bActive = oPieMenu.m_iCurrentIndex == oPieMenu.m_iHoveredItem
    oPieMenu.m_iCurrentIndex = oPieMenu.m_iCurrentIndex + 1
    if bActive then
        menuCtx.m_bClose = true
    end
    return bActive
end

local function New(...)
    local menuContext = NewPieMenuContext(...)
    return {
        BeginPiePopup = function(name, mouseButton)
            return BeginPiePopup(menuContext, name, mouseButton)
        end,
        EndPiePopup = function()
            return EndPiePopup(menuContext)
        end,
        PieMenuItem = function(name, enabled)
            return PieMenuItem(menuContext, name, enabled)
        end,
        BeginPieMenu = function(name, enabled)
            return BeginPieMenu(menuContext, name, enabled)
        end,
        EndPieMenu = function()
            return EndPieMenu(menuContext)
        end
    }
end

local defaultPieMenu = New()
defaultPieMenu.New = New
return defaultPieMenu
Не, имею в виду не это, как на скрине

1594301875354.png
 

Мира

Участник
455
9
Подскажите пж сохранение выбора в Checkbox`е.
Lua:
    if imgui.SliderInt("##rang", rang, 1, 10, u8"Ранг: "..rang.v) then
        mainIni.settings.rang = rang.v
        inicfg.save(mainIni, "Random.ini")
    end
 

Anton Nixon

Активный
474
48
Вопрос такой:
Что это за ошибка и как она исправляется:
Lua:
[ML] (error) at.lua: D:\Games\GTA 130K BY DAPO SHOW\moonloader\at.lua:876: stack index 2, expected userdata, received string: value is not a valid userdata (bad argument into 'bool(const char*, ImBuffer*, sol::optional<int>, sol::optional<ImCallback *>)')
stack traceback:
    [C]: in function 'InputText'
Вот эта строчка с ошибкой
Lua:
imgui.InputText(u8"##pass", password, imgui.InputTextFlags.Password + imgui.InputTextFlags.EnterReturnsTrue + imgui.InputTextFlags.CharsNoBlank); imgui.SameLine(); imgui.Text(u8"Введите пароль")
 

AnWu

Guardian of Order
Всефорумный модератор
4,689
5,200
Вопрос такой:
Что это за ошибка и как она исправляется:
Lua:
[ML] (error) at.lua: D:\Games\GTA 130K BY DAPO SHOW\moonloader\at.lua:876: stack index 2, expected userdata, received string: value is not a valid userdata (bad argument into 'bool(const char*, ImBuffer*, sol::optional<int>, sol::optional<ImCallback *>)')
stack traceback:
    [C]: in function 'InputText'
Вот эта строчка с ошибкой
Lua:
imgui.InputText(u8"##pass", password, imgui.InputTextFlags.Password + imgui.InputTextFlags.EnterReturnsTrue + imgui.InputTextFlags.CharsNoBlank); imgui.SameLine(); imgui.Text(u8"Введите пароль")
password покажи как инициализируешь
 

|DEVIL|

Известный
359
273
К какой палитре относятся цвета ImVec4 в стилях? Не могу понять как RGB превратить в нецелочисленные