Как сделать 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
Известный
- Название
- Скриншот
- Описание
- Код
- Пример использования
Абстрактный пример использования
Абстрактный пример использования
Абстрактный пример использования
Абстрактный пример использования
Абстрактный пример использования
Абстрактный пример использования
Описание: заменяет цвет текста форматом RRGGBB(AA).
Вернуть цвет текста на стандартный (ImGuiCol_Text) - .
Абстрактный пример использования
В примере я использую модифицированный модуль 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. Если зеленой кнопочки нет или нет ссылки - то зарегистрируйтесь на этом сайте)
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.
Это 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_NoTitleBar | imgui.WindowFlags.NoTitleBar |
Значения базовых типов, которые в ImGui записываются по указателю, должны быть использованы через специальные типы: ImBool для bool, ImFloat для float, ImInt для int и unsigned int, ImFloat2-4 для float3, ImInt2-4 для int3 | static bool win = false; ImGui::Begin("window", &win); win = false; | local win = imgui.ImBool(false) imgui.Begin("window", win) win.v = false |
Функции с переменным количеством аргументов для форматирования текста не поддерживают форматирование, используйте string.format | ImGui::Text("hey, %s", name) | imgui.Text(string.format('hey, %s', name)) |
Функции InputText и InputTextMultiline принимают ImBuffer вместо char* buf + size_t buf_size | char 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, принимают ImCallback | void 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 автоматически обновляет длину и задаёт значение BufDirty | s.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!
Читайте также: