Полезные сниппеты и функции

invilso.

Известный
248
89
Рисует Progress Bar, есть возможность выводить значение сбоку него.
Вроде была такая штука на БХ, но у меня она почему-то не работала, мб руки кривые.
ФУНКЦИЯ:
-- font - шрифт, если не используется пишите nil
-- pos_x и pos_x - позиция по x и y
-- size_x и size_x - размер прогрессбара по x и y
-- outline - толщина обводки
-- show_text - показывать ли значение текстом
-- color_outline - цвет обводки - ARGB
-- color_line - цвет динамической линии - ARGB
-- color_underline - цвет под динамической линией - ARGB
-- color_font - цвет шрифта - ARGB
-- color_numfield - цвет поля под значением
-- value - значение
-- max_value - максимально возможное значение, или nil если хотите использовать автоопределитель наибольшего значения.

local max = 0 --нужно для автоматического определения максимального значения, держите эту переменную не в цикле.

function renderProgress(font, pos_x, pos_y, size_x, size_y, outline, show_secs, color_outline, color_line, color_underline, color_font, color_numfield, value, max_value)
    if type(max_value) == 'nil' and value ~= nil then
        if max < value then
            max = value
            max_value = max
        else
            max_value = max
        end
    end
    renderDrawBox(pos_x - (outline / 2), pos_y - (outline / 2), size_x + outline, size_y + outline, color_outline) --рамка
    renderDrawBox(pos_x, pos_y, size_x, size_y, color_underline) -- под полоской
    renderDrawBox(pos_x, pos_y, (value * (size_x / (max_value + 1))), size_y, color_line) -- динамическая полоска
    if show_secs then   
        local drawtext = string.format('%0.1f', value)
        renderDrawBox(pos_x + (size_x + 5), pos_y - (outline / 2), renderGetFontDrawTextLength(font, drawtext) + 1, size_y + outline, color_numfield) -- поле сбоку для числа
        renderFontDrawText(font, drawtext, pos_x + (size_x + 6), pos_y - (outline / 2), color_font) -- число
    end
end

ПРИМЕР [Показывает сколько осталось спринта]:
function onD3DPresent()
    local value = getSprintLocalPlayer()
    if value < 95 then
        local px, py, pz = getCharCoordinates(playerPed)
        px, py, pz = px + 0.1, py, pz - 0.8
        if isPointOnScreen(px, py, pz, 1) then
            local pos_x, pos_y = convert3DCoordsToScreen(px, py, pz)
            local pos_x, pos_y = round(pos_x), round(pos_y)
            renderProgress(font, pos_x, pos_y, sx, sy, 4, true, 0xA0000000, 0xAA00CC00, 0xAA013220, 0xFF00CCD0, 0xA0000000, value, nil)
        end
    end
end

-- font - шрифт, если не используется пишите nil
-- pos_x и pos_x - позиция по x и y
-- size_x и size_x - размер прогрессбара по x и y
-- outline - толщина обводки
-- show_text - показывать ли значение текстом
-- color_outline - цвет обводки - ARGB
-- color_line - цвет динамической линии - ARGB
-- color_underline - цвет под динамической линией - ARGB
-- color_font - цвет шрифта - ARGB
-- color_numfield - цвет поля под значением
-- value - значение
-- max_value - максимально возможное значение, или nil если хотите использовать автоопределитель наибольшего значения.

function renderProgress(font, pos_x, pos_y, size_x, size_y, outline, show_text, color_outline, color_line, color_underline, color_font, color_numfield, value, max_value)
    if type(max_value) == 'nil' and value ~= nil then
        if max < value then
            max = value
            max_value = max
        else
            max_value = max
        end
    end
    renderDrawBox(pos_x - (outline / 2), pos_y - (outline / 2), size_x + outline, size_y + outline, color_outline) --рамка
    renderDrawBox(pos_x, pos_y, size_x, size_y, color_underline) -- под полоской
    renderDrawBox(pos_x, pos_y, (value * (size_x / (max_value + 1))), size_y, color_line) -- динамическая полоска
    if show_text then   
        local drawtext = string.format('%0.1f', value)
        renderDrawBox(pos_x + (size_x + 5), pos_y - (outline / 2), renderGetFontDrawTextLength(font, drawtext) + 1, size_y + outline, color_numfield) -- поле сбоку для числа
        renderFontDrawText(font, drawtext, pos_x + (size_x + 6), pos_y - (outline / 2), color_font) -- число
    end
end[/SPOILER]

function getSprintLocalPlayer()
    local float = memory.getfloat(0xB7CDB4)
    return float/31.47000244
end
 
  • Bug
  • Нравится
Реакции: BARRY BRADLEY и The Spark

kin4stat

mq-team
Всефорумный модератор
2,731
4,693
Перенаправляет io и print в стандартную консоль(для ее открытия можете заюзать https://www.blast.hk/threads/22179/)
attachcons.lua:
io.stdin = io.open("CONIN$", "r")
io.stdout = io.open("CONOUT$", "w")
io.stderr = io.open("CONOUT$", "w")

_origprint = print

function print(...)
    local res = ''
    for i = 1, select('#', ...) do
        res = res .. tostring(select(i, ...)) .. '   '
    end
    io.stdout:write(res.."\r\n")
    io.stdout:flush()
    return _origprint(...)
end

Пример (взят у @imring):
test.lua:
require 'attachcons'

function main()
    io.stdout:write("Hello from stdout!\r\n")
    io.stdout:flush()
    io.stderr:write("Hello from stderr!\r\n")
    io.stderr:flush()
    io.write("Hello from iowrite!\r\n")
    io.write("Enter your name: ")
    name = io.stdin:read()
    print("Your name is: " .. name)
end

1623242616889.png
 
Последнее редактирование:

_raz0r

t.me/sssecretway | ТГК: t.me/razor_code
Модератор
1,889
3,041
Описание: Функция получает сервера из вкладок лаунчера SA:MP (Internet / Hosted, вкладка Internet это Hosted)
Lua:
local copas = require 'copas'
local http = require 'copas.http'


function getSAMPMasterList()
    local masterList = {}
    local response, code, headers, status = httpRequest("http://lists.sa-mp.com/0.3.7/internet")
    if response then
        for str in string.gmatch(response,"([^\n\r]+)") do
            table.insert(masterList, str)
        end
    end
    return masterList
end


function httpRequest(request, body, handler) -- copas.http
    -- start polling task
    if not copas.running then
        copas.running = true
        lua_thread.create(function()
            wait(0)
            while not copas.finished() do
                local ok, err = copas.step(0)
                if ok == nil then error(err) end
                wait(0)
            end
            copas.running = false
        end)
    end
    -- do request
    if handler then
        return copas.addthread(function(r, b, h)
            copas.setErrorHandler(function(err) h(nil, err) end)
            h(http.request(r, b))
        end, request, body, handler)
    else
        local results
        local thread = copas.addthread(function(r, b)
            copas.setErrorHandler(function(err) results = {nil, err} end)
            results = table.pack(http.request(r, b))
        end, request, body)
        while coroutine.status(thread) ~= 'dead' do wait(0) end
        return table.unpack(results)
    end
end
Пример использования:
Lua:
function main()
    local t = getSAMPMasterList()
    print(t[1]) -- когда-то я хотел сделать внутриигровой лаунчер на imgui, с фаворит списком и вкладками, но руки не дошли.
end
 

Cosmo

Известный
Друг
644
2,581
Описание:
Красивый анимированный Tooltip (Подсказка)
Цвет шрифта подбирается сам в зависимости от цвета фона
По умолчанию выравнивание текста по центру, последним аргументом можно выключить выравнивание по левому краю

Lua:
function imgui.Hint(str_id, hint_text, color, no_center)
    color = color or imgui.GetStyle().Colors[imgui.Col.PopupBg]
    local p_orig = imgui.GetCursorPos()
    local hovered = imgui.IsItemHovered()
    imgui.SameLine(nil, 0)

    local animTime = 0.2
    local show = true

    if not POOL_HINTS then POOL_HINTS = {} end
    if not POOL_HINTS[str_id] then
        POOL_HINTS[str_id] = {
            status = false,
            timer = 0
        }
    end

    if hovered then
        for k, v in pairs(POOL_HINTS) do
            if k ~= str_id and os.clock() - v.timer <= animTime  then
                show = false
            end
        end
    end

    if show and POOL_HINTS[str_id].status ~= hovered then
        POOL_HINTS[str_id].status = hovered
        POOL_HINTS[str_id].timer = os.clock()
    end

    local getContrastColor = function(col)
        local luminance = 1 - (0.299 * col.x + 0.587 * col.y + 0.114 * col.z)
        return luminance < 0.5 and imgui.ImVec4(0, 0, 0, 1) or imgui.ImVec4(1, 1, 1, 1)
    end

    local rend_window = function(alpha)
        local size = imgui.GetItemRectSize()
        local scrPos = imgui.GetCursorScreenPos()
        local DL = imgui.GetWindowDrawList()
        local center = imgui.ImVec2( scrPos.x - (size.x / 2), scrPos.y + (size.y / 2) - (alpha * 4) + 10 )
        local a = imgui.ImVec2( center.x - 7, center.y - size.y - 3 )
        local b = imgui.ImVec2( center.x + 7, center.y - size.y - 3)
        local c = imgui.ImVec2( center.x, center.y - size.y + 3 )
        local col = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha))

        DL:AddTriangleFilled(a, b, c, col)
        imgui.SetNextWindowPos(imgui.ImVec2(center.x, center.y - size.y - 3), imgui.Cond.Always, imgui.ImVec2(0.5, 1.0))
        imgui.PushStyleColor(imgui.Col.PopupBg, color)
        imgui.PushStyleColor(imgui.Col.Border, color)
        imgui.PushStyleColor(imgui.Col.Text, getContrastColor(color))
        imgui.PushStyleVarVec2(imgui.StyleVar.WindowPadding, imgui.ImVec2(8, 8))
        imgui.PushStyleVarFloat(imgui.StyleVar.WindowRounding, 6)
        imgui.PushStyleVarFloat(imgui.StyleVar.Alpha, alpha)

        local max_width = function(text)
            local result = 0
            for line in text:gmatch('[^\n]+') do
                local len = imgui.CalcTextSize(line).x
                if len > result then
                    result = len
                end
            end
            return result
        end

        local hint_width = max_width(hint_text) + (imgui.GetStyle().WindowPadding.x * 2)
        imgui.SetNextWindowSize(imgui.ImVec2(hint_width, -1), imgui.Cond.Always)
        imgui.Begin('##' .. str_id, _, imgui.WindowFlags.Tooltip + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoTitleBar)
            for line in hint_text:gmatch('[^\n]+') do
                if no_center then
                    imgui.Text(line)
                else
                    imgui.SetCursorPosX((hint_width - imgui.CalcTextSize(line).x) / 2)
                    imgui.Text(line)
                end
            end
        imgui.End()

        imgui.PopStyleVar(3)
        imgui.PopStyleColor(3)
    end

    if show then
        local between = os.clock() - POOL_HINTS[str_id].timer
        if between <= animTime then
            local s = function(f)
                return f < 0.0 and 0.0 or (f > 1.0 and 1.0 or f)
            end
            local alpha = hovered and s(between / animTime) or s(1.00 - between / animTime)
            rend_window(alpha)
        elseif hovered then
            rend_window(1.00)
        end
    end

    imgui.SetCursorPos(p_orig)
end

Пример реализации:
Lua:
imgui.Button(u8'Разделить на ноль!')
imgui.Hint('delzero', u8'Твоя математичка будет в шоке!')
hint.gif
 

k1zn

О КУ)))
Всефорумный модератор
2,404
2,052
Описание: проверка на то, содержит ли строка русские символы.


Lua:
function isCyrillic(text)
  return text:match("[а-яА-ЯЁё]+") ~= nil
end

Пример использования:

Lua:
print(isCyrillic("nonCyrillic")) -- false
print(isCyrillic("krutoi872 русь крестил")) -- true
print(isCyrillic("ивангомо2004")) -- true
 

k1zn

О КУ)))
Всефорумный модератор
2,404
2,052
Описание: проверка на то, является ли корректной дата в строке формата dd.mm.yyyy

Lua:
function isDateCorrect(dateString)
    local d, m, Y = dateString:match("(%d+)%.(%d+)%.(%d+)")
    if d and m and Y then
        local epoch = os.time({year = Y, month = m, day = d})
        local date = string.format("%02d.%02d.%04d", d, m, Y)
        return date == os.date("%d.%m.%Y", epoch)
    end
    return false
end

Пример использования:
Lua:
print(isDateCorrect("29.12.2020")) -- true
print(isDateCorrect("29.13.2020")) -- false (не существует 13 месяца)
print(isDateCorrect("32.12.2020")) -- false (в декабре не 32 дня)

-------------

Описание: проверка на то, является ли корректным время в формате hh:mm:ss

Lua:
function isTimeCorrect(timeString)
    local H, M, S = timeString:match("(%d+):(%d+):(%d+)")
    if H and M and S then
        local epoch = os.time({year = 2021, month = 12, day = 31, hour = H, min = M, sec = S})
        local time = string.format("%02d:%02d:%02d", H, M, S)
        return time == os.date("%H:%M:%S", epoch)
    end
    return false
end

Пример использования:
Lua:
print(isTimeCorrect("13:69:59")) -- false
print(isTimeCorrect("12:30:50")) -- true
 
Последнее редактирование:

Fott

Известный
3,400
2,208
Описание: проверка на то, содержит ли строка русские символы.


Lua:
function isCyrillic(text)
  return text:match("[а-яА-ЯЁё]+") ~= nil
end

Пример использования:

Lua:
print(isCyrillic("nonCyrillic")) -- false
print(isCyrillic("krutoi872 русь крестил")) -- true
print(isCyrillic("ивангомо2004")) -- true
Описание: проверка на то, содержит ли строка английские буквы.
Lua:
function isEnglish(text)
  return text:match("[a-zA-z]+") ~= nil
end
Пример использования:
Lua:
print(isEnglish('Hyi')) -- true
print(isEnglish('хуй')) -- false
print(isEnglish('че за hyi'))

--------------------------------------------------------------

Описание: проверка на то, содержит ли строка число.
Lua:
function isNumber(text)
  return text:match("[0-9]+") ~= nil
end
Пример использования:
Lua:
print(isNumber('тыща минус семь')) -- false
print(isNumber('1000-7')) -- true
print(isNumber('я гуль 1000-7')) -- true

--------------------------------------------------------------

Описание: проверка на то, содержит ли строка символ.
Lua:
function isSymbol(text)
  return text:match("%p+") ~= nil
end
Пример использования:
Lua:
print(isSymbol('где символы')) -- false
print(isSymbol('где символы?')) -- true
print(isSymbol('Нету simvolov.')) -- true
 

AnWu

Guardian of Order
Всефорумный модератор
4,683
5,128
Описание: проверка на то, содержит ли строка английские буквы.
Lua:
function isEnglish(text)
  return text:match("[a-zA-z]+") ~= nil
end
Пример использования:
Lua:
print(isEnglish('Hyi')) -- true
print(isEnglish('хуй')) -- false
print(isEnglish('че за hyi'))

--------------------------------------------------------------

Описание: проверка на то, содержит ли строка число.
Lua:
function isNumber(text)
  return text:match("[0-9]+") ~= nil
end
Пример использования:
Lua:
print(isNumber('тыща минус семь')) -- false
print(isNumber('1000-7')) -- true
print(isNumber('я гуль 1000-7')) -- true

--------------------------------------------------------------

Описание: проверка на то, содержит ли строка символ.
Lua:
function isSymbol(text)
  return text:match("%p+") ~= nil
end
Пример использования:
Lua:
print(isSymbol('где символы')) -- false
print(isSymbol('где символы?')) -- true
print(isSymbol('Нету simvolov.')) -- true
нахера обертка в три строки для одной строки?
 

imring

Ride the Lightning
Всефорумный модератор
2,353
2,512
проверка на то, содержит ли строка английские буквы
Lua:
function is_eng(arg) return arg:find('%a') ~= nil end
1625250754121.png


проверка на то, содержит ли строка число
про %d ты, видимо, забыл

проверка на то, содержит ли строка символ
какой символ?
 

mzxer

Активный
81
118
Описание: оператор множественного выбора switch.
Код:
Lua:
function switch(key)
    return function(tab)
        local current = tab[key] or tab['default']
        if type(current) == 'function' then current() end
    end
end
Пример:
Lua:
switch(2)
{
  function() print'hello' end,
  function() print'bye' end,
  ['default'] = function() print'error' end
}
-- console: bye
Описание: оператор switch с возможностью сразу обращаться к функции. (для меня использование выглядит более красивым и практичным)
Lua:
function switch(key)
    return function(tab)
        if type(tab[key]) == "table" then
            if type(tab[key][1]) == "function" then
                tab[key][1](unpack(tab[key], 2))
            end
        else
            local current = tab[key]
            if not current then
                if tab["default"] ~= nil and type(tab["default"]) == "function" then
                    tab["default"]()
                elseif tab["default"] ~=nil and type(tab["default"] == "table") then
                    if type(tab["default"][1]) == "function" then
                        tab["default"][1](unpack(tab["default"], 2))
                    end
                end
            else
                if type(current) == "function" then
                    current()
                end
            end
        end
    end
end

Пример использования:
example for new method:
switch("world")
{
    ["world"] = {print, "hello, world!"},
    ["default"] = {print, "hello, stranger!"}
}

-- console output: hello, world!
-- print - наименование функции. всё что после - аргументы, передаются через запятую

сравнение:
for i = 1, 4 do
    switch(i)
    {
        [1] = function() sampAddChatMessage("[1]{FFFFFF} Function (old) method.", 0x1f8cb8) end, -- раньше
        [2] = {sampAddChatMessage, "[2]{FFFFFF} Table (new) method.", 0x1f8cb8}, --сейчас. как по мне - куда более красивее, чем строка выше
        ["default"] = {sampAddChatMessage, "i dont know what to do with this value: {FFFFFF}" .. i, 0xFF0000} --эквивалентно: function() sampAddChatMessage("i dont know what to do with this value: {FFFFFF}" .. i, 0xFF0000) end, работать будет тоже.
    }
end
конечно не всегда приходится обрабатывать значение одним лишь выводом в консоль. я не увидел особого смысла реализовывать возможность вызова двух и более функций, для этого куда лучше создать отдельную и писать код уже там
 
Последнее редактирование:

_raz0r

t.me/sssecretway | ТГК: t.me/razor_code
Модератор
1,889
3,041
Описание: Рисует фигуру с градиентом.
Lua:
function renderGradient(x, y, width, height, color1, color2)
    renderBegin(5)
    renderColor(color2)
    renderVertex(x, y + height)
    renderColor(color1)
    renderVertex(x, y)
    renderColor(color2)
    renderVertex(x + width, y + height)
    renderColor(color1)
    renderVertex(x + width, y)
    renderSetRenderState(9, 2)
    renderEnd()
end
Пример использования:
Lua:
function main()
    while true do
        wait(0)
        renderGradient(100, 100, 300, 300, 0xFFFFFFFF, 0x00000000)
    end
end
1625480467085.png
 

meowprd

Тот самый Котовский
Проверенный
1,283
711
Описание: Автоматически выравнивает текст относительно его положения
Lua:
function renderFontDrawTextAutoAlign(font, text, x, y, color)
    local sw, sh = getScreenResolution()
    if x <= sw/3 then renderFontDrawText(font, text, x, y, color)
    elseif x <= sw/1.5 then renderFontDrawText(font, text, x - renderGetFontDrawTextLength(font, text) / 2, y, color)
    else renderFontDrawText(font, text, x - renderGetFontDrawTextLength(font, text), y, color)
    end
end
Пример использования:
Lua:
local x, y = getCursorPos()
renderFontDrawTextAutoAlign(font, "Some text", x, y, 0xFFA77BCA)

Описание: Рисует квадрат вокруг заданной координаты с заданным радиусом (возможно есть лучшее решение), могут быть ошибки при рендере больших радиусов
Lua:
function renderRadius(x, y, z, radius, color)
    local x1, y1 = convert3DCoordsToScreen(x-radius, y-radius, z)
    local x2, y2 = convert3DCoordsToScreen(x+radius, y-radius, z)
    if isPointOnScreen(x-radius, y-radius, z, 0) or isPointOnScreen(x+radius, y-radius, z, 0) then
        renderDrawLine(x1, y1, x2, y2, 1, color)
    end
    local x1, y1 = convert3DCoordsToScreen(x+radius, y+radius, z)
    local x2, y2 = convert3DCoordsToScreen(x-radius, y+radius, z)
    if isPointOnScreen(x+radius, y+radius, z, 0) or isPointOnScreen(x-radius, y+radius, z, 0) then
        renderDrawLine(x1, y1, x2, y2, 1, color)
    end
    local x1, y1 = convert3DCoordsToScreen(x-radius, y-radius, z)
    local x2, y2 = convert3DCoordsToScreen(x-radius, y+radius, z)
    if isPointOnScreen(x-radius, y-radius, z, 0) or isPointOnScreen(x-radius, y+radius, z, 0) then
        renderDrawLine(x1, y1, x2, y2, 1, color)
    end
    local x1, y1 = convert3DCoordsToScreen(x+radius, y+radius, z)
    local x2, y2 = convert3DCoordsToScreen(x+radius, y-radius, z)
    if isPointOnScreen(x+radius, y+radius, z, 0) or isPointOnScreen(x+radius, y-radius, z, 0) then
        renderDrawLine(x1, y1, x2, y2, 1, color)
    end
end
Пример использования:
Lua:
local mx, my, mz = getCharCoordinates(PLAYER_PED)
renderRadius(mx, my, mz, 1.0, 0xFFA77BCA)
1625672552037.png
 

mzxer

Активный
81
118
Описание: проверка на то, сидит ли указанный игрок в одной машине с вами.
Lua:
function isPlayerInCarWithMe(playerId)
    local playerId = tonumber(playerId)
    if playerId and isCharSittingInAnyCar(PLAYER_PED) then
        local carHandle = storeCarCharIsInNoSave(PLAYER_PED)
        local _, playerHandle = sampGetCharHandleBySampPlayerId(playerId)
        if _ then
            return isCharInCar(playerHandle, carHandle)
        end
    end
    return false
end

Пример использования:
Lua:
function main()
    if not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    
    sampRegisterChatCommand("isInMyCar", function(arg)
        sampAddChatMessage(isPlayerInCarWithMe(arg) and "yes" or "no", -1)
    end)
    
    wait(-1)
end
 
  • Злость
  • Нравится
Реакции: THERION и Yakushizz

MrBidloKoder

Известный
425
248
Описание: Показывает радар и худ во время слежки.
Lua:
function radarAndHudPatch(bool)
    if bool then
        memory.write(sampGetBase() + 643864, 37008, 2, true)
    else
        memory.write(sampGetBase() + 643864, 3956, 2, true)
    end
end
Пример использования:
Lua:
local memory = require "memory"
function main()
    sampRegisterChatCommand("radarpatch", function()
        radarAndHudPatch(true)
        sampAddChatMessage("Патч включён", -1)
    end)
    wait(-1)
end
 

CaJlaT

Овощ
Модератор
2,809
2,596
Описание: Кастомное вертикальное меню для ImGui. Цвета берутся из кнопок.
P.s: Убирал говнокод как мог, если вы знаете как оптимизировать код, напишите пожалуйста.
Lua:
-- labels - Array - названия элементов меню
-- selected - imgui.ImInt() - выбранный пункт меню
-- size - imgui.ImVec2() - размер элементов
-- speed - float - скорость анимации выбора элемента (необязательно, по стандарту - 0.2)
-- centering - bool - центрирование текста в элементе (необязательно, по стандарту - false)
function imgui.CustomMenu(labels, selected, size, speed, centering)
    local bool = false
    speed = speed and speed or 0.2
    local radius = size.y * 0.50
    local draw_list = imgui.GetWindowDrawList()
    if LastActiveTime == nil then LastActiveTime = {} end
    if LastActive == nil then LastActive = {} end
    local function ImSaturate(f)
        return f < 0.0 and 0.0 or (f > 1.0 and 1.0 or f)
    end
    for i, v in ipairs(labels) do
        local c = imgui.GetCursorPos()
        local p = imgui.GetCursorScreenPos()
        if imgui.InvisibleButton(v..'##'..i, size) then
            selected.v = i
            LastActiveTime[v] = os.clock()
            LastActive[v] = true
            bool = true
        end
        imgui.SetCursorPos(c)
        local t = selected.v == i and 1.0 or 0.0
        if LastActive[v] then
            local time = os.clock() - LastActiveTime[v]
            if time <= 0.3 then
                local t_anim = ImSaturate(time / speed)
                t = selected.v == i and t_anim or 1.0 - t_anim
            else
                LastActive[v] = false
            end
        end
        local col_bg = imgui.GetColorU32(selected.v == i and imgui.GetStyle().Colors[imgui.Col.ButtonActive] or imgui.ImVec4(0,0,0,0))
        local col_box = imgui.GetColorU32(selected.v == i and imgui.GetStyle().Colors[imgui.Col.Button] or imgui.ImVec4(0,0,0,0))
        local col_hovered = imgui.GetStyle().Colors[imgui.Col.ButtonHovered]
        local col_hovered = imgui.GetColorU32(imgui.ImVec4(col_hovered.x, col_hovered.y, col_hovered.z, (imgui.IsItemHovered() and 0.2 or 0)))
        draw_list:AddRectFilled(imgui.ImVec2(p.x-size.x/6, p.y), imgui.ImVec2(p.x + (radius * 0.65) + t * size.x, p.y + size.y), col_bg, 10.0)
        draw_list:AddRectFilled(imgui.ImVec2(p.x-size.x/6, p.y), imgui.ImVec2(p.x + (radius * 0.65) + size.x, p.y + size.y), col_hovered, 10.0)
        draw_list:AddRectFilled(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x+5, p.y + size.y), col_box)
        imgui.SetCursorPos(imgui.ImVec2(c.x+(centering and (size.x-imgui.CalcTextSize(v).x)/2 or 15), c.y+(size.y-imgui.CalcTextSize(v).y)/2))
        imgui.Text(v)
        imgui.SetCursorPos(imgui.ImVec2(c.x, c.y+size.y))
    end
    return bool
end
Пример использования:
Lua:
local tab = imgui.ImInt(1)
local tabs = {
    fa.ICON_FA_GLOBE_ASIA..u8' Основное',
    fa.ICON_FA_COGS..u8' Настройки',
    fa.ICON_FA_SWATCHBOOK..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
}

function imgui.OnDrawFrame()
    local X, Y = getScreenResolution()
    imgui.SetNextWindowSize(imgui.ImVec2(700, 400), imgui.Cond.FirstUseEver)
    imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin('##window', _, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoTitleBar + imgui.WindowFlags.NoScrollbar)
        imgui.SetCursorPos(imgui.ImVec2(0, 45))

        if imgui.CustomMenu(tabs, tab, imgui.ImVec2(135, 30)) then
            sampAddChatMessage('Вы нажали на элемент №'..tab.v)
        end

        imgui.SetCursorPos(imgui.ImVec2(150, 35))
        imgui.BeginChild('##main', imgui.ImVec2(700, 400), true)
            if tab.v == 1 then
                imgui.TextColoredRGB(sc..u8'Информация:')
                imgui.TextColoredRGB(u8'Пользователь: '..sc..mynick..'['..myid..']')
            elseif tab.v == 2 then
                --code
            end
        imgui.EndChild()
    imgui.End()
end
ezgif-2-4fbbf317267f.gif
Lua:
local tab = imgui.ImInt(1)
local tabs = {
    fa.ICON_FA_GLOBE_ASIA..u8' Основное',
    fa.ICON_FA_COGS..u8' Настройки',
    fa.ICON_FA_SWATCHBOOK..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
    fa.ICON_FA_SPINNER..u8' В разработке',
}

function imgui.OnDrawFrame()
    local X, Y = getScreenResolution()
    imgui.SetNextWindowSize(imgui.ImVec2(700, 400), imgui.Cond.FirstUseEver)
    imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin('##window', _, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoTitleBar + imgui.WindowFlags.NoScrollbar)
        imgui.SetCursorPos(imgui.ImVec2(0, 45))

        if imgui.CustomMenu(tabs, tab, imgui.ImVec2(135, 30), _, true) then
            sampAddChatMessage('Вы нажали на элемент №'..tab.v)
        end

        imgui.SetCursorPos(imgui.ImVec2(150, 35))
        imgui.BeginChild('##main', imgui.ImVec2(700, 400), true)
            if tab.v == 1 then
                imgui.TextColoredRGB(sc..u8'Информация:')
                imgui.TextColoredRGB(u8'Пользователь: '..sc..mynick..'['..myid..']')
            elseif tab.v == 2 then
                --code
            end
        imgui.EndChild()
    imgui.End()
end
ezgif-2-d7dcae2853d7.gif