Как сделать imgui окно в lua

Обновлено: 19.04.2024

Часть 1 :
Заранее скажу, что гайд не полный даже близко, и я много чего не сказал.
Привет. Всех рад видеть в треде о базовых пониманиях при работе в ImGui.
Сначала я бы хотел уяснить, что я буду рассматривать последнюю версию фреймворка. Имгуи используется для создания интерфейса программ, меню или другие визуальные функции. Думаю не стоит тут зацикливаться. Приступим к практике.
Сначала разберём классы в имгуи для работы :


>ImVec2 - Используется для задачи позиции, размера объекта или чего либо. Конструкция - ImVec2(float x, float y);
>ImVec4 - используется для установки цвета обьекта (редко), и для установки чего либо с 4 аргументами.
Конструктор - ImVec4(float x, float y, float w, float h); PS: для установки цвета имеет максимальное значение 1.f. Пример:
ImVec4(1.f, 0.2f, 0.1f)
>ImColor - используется для установки только цвета для объектов и тд. Конструктор - ImColor(float red, float green, float blue, float alpha);
Пример : ImColor(37, 73, 243)
>Это близко не все, я разобрал самые основные.
Хотел бы сразу предупредить, что создавать элементы с одинаковыми именами не стоит, тк это сломает имгуи.
Первое что мы должны сделать, это создать окно. Процесс создания контекста и др рассматривать не буду.

Стоит сказать, что обязательно вконце окна, после всего прописать End, что бы фреймворк понял, что мы закончили отрсовку элементов на этом окне

1. Первый аргумент в функции как не странно отвечат за название окна.
2.Второй аргумент это переменная bool, которая будет влиять на открытие или закрытие окна. Оно так же может меняться через само окно,если неправильно настроить флаги. Можем ставить nullptr если нас этот вопрос не ебет.
3. Третий аргумент как раз таки меняет внешний вид окна и придаёт ему какие либо изменения. Рассмотрим по подробнее. флаги здесь реализованы через енум, который содержит название флагов.

Абсолютно все флаги рассматривать долго и неудобно, поэтому рассмотрим мы щас самые важные и удобные.

Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.

Double Tap Inside

Известный
  • Название
  • Скриншот
  • Описание
  • Код
  • Пример использования

qWgQRwq.jpg

Абстрактный пример использования

apEn0zH.jpg

Абстрактный пример использования

OH9Uz0n.jpg

Абстрактный пример использования

Абстрактный пример использования

Абстрактный пример использования

f4imdhV.jpg

Абстрактный пример использования


Описание: заменяет цвет текста форматом RRGGBB(AA).
Вернуть цвет текста на стандартный (ImGuiCol_Text) - .

Абстрактный пример использования

meZoK5f.jpg

В примере я использую модифицированный модуль inicfg_ex.lua, который может сохранять нормально строки и таблици.
Внимание: Файлы созданные через inicfg_ex.lua несовместимы с файлами созданными через inicfg.lua

Для работы самого примера также нужно:
Dear ImGui
[Module] ImGui Addons | v1.0.0
[Module] RKeys v2.1.1 (Там ссылка на GitHub, Переходим, жмем зеленую кнопочку "Code", выбираем строчку "Download Zip", внутри архива находим rkeys.lua и закидываем его в свою папку lib. Если зеленой кнопочки нет или нет ссылки - то зарегистрируйтесь на этом сайте)

Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.

29072770-aef614e2-7c7b-11e7-8861-212c2c416439.jpg

Это ImGui - самый функциональный и одновременно самый простой GUI-фреймворк из всех, что мне известны.
И теперь каждый из вас сможет использовать его в своих Lua скриптах для MoonLoader.


Представляю вам Moon ImGui - Lua биндинг ImGui для MoonLoader. Он включает все основные возможности фреймворка, а API максимально приближен к оригинальному по мере возможного.
Тут не будут подробно рассматриваться возможности и особенности ImGui, в этой теме будет рассказано и показано как использовать Moon ImGui в Lua. За информацией по самому ImGui сюда:

GitHub - ocornut/imgui: Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies - GitHub - ocornut/imgui: Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies

Это работает, но что-то не впечатляет, согласитесь. Окно изначально маленькое, показывается сразу при старте и его нельзя закрыть.
Сделаем его побольше, добавим активацию и какое-нибудь действие:

В коде была использована переменная типа ImBool - это один из новых типов, добавленных в Moon ImGui. Такой подход неизбежен, поскольку в луа невозможна передача базовых типов по ссылке. Это не единственное изменение, есть и другие, вам потребуется о них знать. Вот их полный список:

Разница между C++ API и Lua API

ОписаниеВ C++В Lua
Все функции из пространства имён ImGui, как и все типы, и все перечисления находятся в таблице, возвращаемой модулемImGui::Text("text");
ImVec2(0.1f, 2.3f);
imgui.Text("text");
imgui.ImVec2(0.1, 2.3);
Названия перечислений (enum) и их значений лишились префиксов и символа "_" в концеImGuiWindowFlags_NoTitleBarimgui.WindowFlags.NoTitleBar
Значения базовых типов, которые в ImGui записываются по указателю, должны быть использованы через специальные типы: ImBool для bool, ImFloat для float, ImInt для int и unsigned int, ImFloat2-4 для float3, ImInt2-4 для int3static bool win = false; ImGui::Begin("window", &win);
win = false;
local win = imgui.ImBool(false) imgui.Begin("window", win)
win.v = false
Функции с переменным количеством аргументов для форматирования текста не поддерживают форматирование, используйте string.formatImGui::Text("hey, %s", name)imgui.Text(string.format('hey, %s', name))
Функции InputText и InputTextMultiline принимают ImBuffer вместо char* buf + size_t buf_sizechar buf[256]<>;
ImGui::InputText('input', buf, sizeof(buf))
local buf = imgui.ImBuffer(256);
imgui.InputText('input', buf)
Динамические массивы в виде массива указателей + количество элементов заменены таблицамиconst char* items[] = ; ImGui::ListBox("list", &lb_cur, items, 3)imgui.ListBox('list', lb_cur, )
Функции с аргументами const char* str_start, const char* str_end, идущими подряд, принимают обычную строкуImGui::TextUnformatted(some_str, some_str + 24)imgui.TextUnformatted(some_str)
Все функции, принимающие калбэк + user_data, принимают ImCallbackvoid swszCb(ImGuiSizeConstraintCallbackData*) <>;
ImGui::SetNextWindowSizeConstraints(size_min, size_max, &swszCb, (void*)&my_data)
local swszCb = imgui.ImCallback(function(data) end)
imgui.SetNextWindowSizeConstraints(size_min, size_max, swszCb)
ImFont::CalcTextSizeA,
ImFontAtlas::CustomRect::CalcCustomRectUV,
ImFontAtlas::GetTexDataAsRGBA32,
ImFontAtlas::GetTexDataAsAlpha8,
ImFontAtlas::GlyphRangesBuilder::BuildRanges,
ImGui::ColorConvertRGBtoHSV и
ImGui::ColorConvertHSVtoRGB
возвращают значения вместо изменения по ссылке
float r, g, b;
ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b);
local r, g, b = imgui.ColorConvertHSVtoRGB(h, s, v)
ImGuiIO::IniFilename и ImGuiIO::LogFilename принимают ImBuffer вместо указателя на строкуconst char ini_path[] = "my/path.ini";
ImGui::GetIO().IniFilename = ini_path;
local ini_path = imgui.ImBuffer('my/path.ini')
imgui.GetIO().IniFilename = ini_path
Изменение ImGuiTextEditCallbackData::Buf автоматически обновляет длину и задаёт значение BufDirtys.copy(data.Buf, data.BufSize);
data.BufTextLen = s.length();
data.BufDirty = true;
data.Buf = 'text'
  • Добавлено несколько дополнительных функций
    • ImColor::ToU32 - преобразование ImColor в целое
    • ImGui::GetStyleColorU32 вместо ImGui::GetColorU32 для цвета стиля
    • ImGui::PlotLinesEx вместо callback-варианта PlotLines
    • ImGui::PlotHistogramEx вместо callback-варианта PlotHistogram
    • ImDrawList::AddTextEx вместо AddText с дополнительными аргументами
    • Функции, принимающие и возвращающие void*-идентификаторы (например, PushID(void*) и GetID(void*))
    • Функции с va_list-форматированием текста (например, TextV)

    Но это ещё не всё. Вся работа с текстом в ImGui основана на UTF-8, т.е. текст не ограничен лишь стандартным набором символов. Но т.к. GTA, SAMP и MoonLoader не поддерживают юникод, кодировки необходимо конвертировать.

    Работа с другими языками на примере русского
    В MoonLoader v.025 были добавлены библиотеки lua-iconv и encoding, они призваны помочь в работе с разными кодировками текста.
    Следующий пример показывает как использовать текст на русском в ImGui:
    Скрипт должен быть сохранён в кодировке Windows-1251

    Не так уж и сложно, верно? Текст, передаваемый ImGui - кодируем, текст, получаемый из ImGui - декодируем. Если в вашем скрипте много текста на русском для ImGui, но мало текста, выводимого через MoonLoader (в лог или чат SA:MP, к примеру), то можно сделать наоборот - сохранить скрипт в кодировке UTF-8 и не кодировать текст, передаваемый ImGui, а вместо этого кодировать текст при работе с функциями мунлоадера.

    Остальные особенности
    В Moon ImGui есть несколько дополнительных возможностей. В частности, они реализуют взаимодействие с игрой и управление интерфейсом.

    На этом всё. Во вложениях есть пример с демонстрацией использования всех этих фич, рекомендую посмотреть код и пощупать его в игре. Вот скриншот:

    Всех приветствую! Сегодня речь пойдет о работе с библиотекой ImGui, которая нужна для создания пользовательских интерфейсов. В этом гайде я затрону стандартный функционал библиотеки, а также расскажу, как его использовать для реализации ваших фантазий.

    Начать стоит с того, что ImGui представляет из себя библиотеку, для отрисовки, которой требуется оверлей. Для данной цели подойдет DirectX или DiscordHook. Затрагивать реализацию оверлея в этой теме мы не будем т.к в большинстве готовых читов это уже реализовано. А значит теперь мы можем перейти к тому, какие функции есть и как они работают.

    Начать стоит с главной функции ImGui это

    Функция нужна для начала отрисовки меню и имеет большое количество настроек или же флагов. Флаги окна представляют из себя команды, которые прописываются после инициализации функции. Пример:

    Разберем аргументы функции. Первый аргумент это название вашего окна, второй булевая переменна для проверки того будет ли окно отрисовано, а затем идут сами флаги окна. Все флаги окна я перечислять не буду, вы можете посмотреть их сами просто поставив запятую после второго аргумента. В нашем случае мы создадим окно с названием "Ваше окно". Затем проверим открыто ли оно с помощью булевой переменной opened и только после проверим флаги нашего окна. В моем случае мы не можем изменить размер, а также свернуть и сохранить функции нашего окна. Перед реализацией этой функции стоит также поставить такие функции как:

    С помощью этих функций вы зададите окну стартовую позицию и размер. Затем можно перейти к созданию первого элемента. К примеру создадим кнопку.
    Для начала нужно создать функцию, которая определит откуда начать рисовать:

    В ImGui используется механика кисточки или же курсора, а все элементы рисуются по его текущей позиции. Мы нарисуем кнопку на координате 36 по X и 22 по Y. Выглядеть это будет примерно вот так:

    Стоит знать, что кнопка вернет True только после нажатии и сделает это один раз, то есть после того как вы отпустите кнопку код выполнен не будет.
    Для того, чтобы делать код, который будет выполняться всегда создадим Checkbox. Изменим позицию курсора и нарисуем чекбокс. Не забудьте создать булевую переменную:

    После чего у вас появится чекбокс, который по нажатию будет возвращать True, а по повторному нажатию False.
    Теперь создадим текст:

    Отлично. Теперь у нас кнопка, чекбокс и текст. С помощью этих элементов вы уже можете создать свое первое меню.
    Закончим наше меню функцией:

    These bindings support a lot of common imgui operations except for initializing imgui.

    This repo only deals with binding ImGui with lua and doesn't deal with setting up the ImGui impl files required to run ImGui, check out the ImGui repo for help with that.

    Function support for dear imgui 1.60:

    How to call these imgui bindings from lua

    It mostly is the same as calling from C++ except for dealing with pointers and ImVecs

    Function definition in C++

    How to call function in lua

    Lua doesn't have pointers but it has multiple return values so instead of giving it a pointer, you give it a value and it will pass back the new value.

    Function definition in C++

    How to call function in lua

    This can make some functions a bit weird. For example Begin.

    Function definition in C++

    How to call function in lua (Note: optional arguments still work)

    Begin normally returns whether it's desirable to draw or not as well as setting the value of p_opened to whether the window is open or not. Still use the first return value to decide to whether to call the ImGui functions for that window and imgui.End().

    Those are arguments are expanded to separate variables instead of one object.

    Function definition in C++

    How to call function in lua

    All functions that operate on drawlists are called with the prefix DrawList

    Function definition in C++

    How to call function in lua

    Note you must specifiy the color in hex for now 0x(ALPHA)(BLUE)(GREEN)(RED) 0xFF0000FF = full opacity red

    Enums are exposed through a "constant" table. They're namespaced with "ImGui" stripped from the name.

    Generate iterator file (or use the one for 1.50 already in the repo)

    This creates a file with info about imgui functions from the imgui.h file.

    Then copy the macro definitions in imgui_lua_bindings.cpp and include imgui_iterator.inl in that the cpp file. This will generate static int impl_FunctionName(lua_State*L) <> functions for each imgui function. Bind these to lua functions and you're good to go. (Check out imgui_lua_bindings.cpp for a full example)

    The imgui_lua_bindings.cpp has two functions RunString and LoadImguiBindings

    To use the functions there first assign the global lState to a valid lua_State, then call LoadImguiBindings then run as many strings as you want.

    What is ENABLE_IM_LUA_END_STACK?

    I made something to keep track of the imgui begin stack so that I could continue using imGui functions if an error ocurred in the lua script. If you don't care about that don't define ENABLE_IM_LUA_END_STACK. I'm using a std::deque of ints to store what the last begin calls were and then if the script errors I unwrap them with ends so that imgui won't complain when I render.

    I don't feel like writing a license so here's it in laymans terms.

    You can use this code for whatever just don't redistribute the exact same source code and try to sell it, or claim that the source code was made by you. You can compile this source code and sell it. You can change this source code and sell the modified version. You can include this source code in whatever open source project (let me know please!). You can include it in whatever closed source project.

    Just be chill and if you make a billion dollars send me an email or something.

    If you have any improvements create a pull request! If you want a function supported or disagree with how the bindings work make an issue!

    Читайте также: