Moon ImGui — Dear ImGui for MoonLoader

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


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

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

Начнём с самого элементарного:
Lua:
local imgui = require 'imgui' -- загружаем библиотеку

-- в этой функции осуществляется вся работа с ImGui
-- она вызывается каждый кадр, но только если imgui.Process равен true
function imgui.OnDrawFrame()
  imgui.Begin('My window') -- новое окно с заголовком 'My window'
  imgui.Text('Hello world') -- простой текст внутри этого окна
  imgui.End() -- конец окна
end

function main()
  imgui.Process = true -- ImGui будет обрабатываться, пока imgui.Process равен true
  -- в этом примере мы просто активируем ImGui сразу же после загрузки игры
end
Результат:
upload_2017-11-25_18-29-2.png


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

-- одно из основных отличий от оригинального апи
-- все переменные, значения которых записываются в ImGui по указателю, могут использоваться только через специальные типы
local main_window_state = imgui.ImBool(false)
function imgui.OnDrawFrame()
  if main_window_state.v then -- чтение и запись значения такой переменной осуществляется через поле v (или Value)
    imgui.SetNextWindowSize(imgui.ImVec2(150, 200), imgui.Cond.FirstUseEver) -- меняем размер
    -- но для передачи значения по указателю - обязательно напрямую
    -- тут main_window_state передаётся функции imgui.Begin, чтобы можно было отследить закрытие окна нажатием на крестик
    imgui.Begin('My window', main_window_state)
    imgui.Text('Hello world')
    if imgui.Button('Press me') then -- а вот и кнопка с действием
      -- условие будет выполнено при нажатии на неё
      printStringNow('Button pressed!', 1000)
    end
    imgui.End()
  end
end

function main()
  while true do
    wait(0)
    if wasKeyPressed(key.VK_X) then -- активация по нажатию клавиши X
        main_window_state.v = not main_window_state.v -- переключаем статус активности окна, не забываем про .v
    end
    imgui.Process = main_window_state.v -- теперь значение imgui.Process всегда будет задаваться в зависимости от активности основного окна
  end
end
Теперь окно выглядит так и его можно скрыть:
upload_2017-11-25_18-29-17.png


В коде была использована переменная типа 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 для float[2-4], ImInt2-4 для int[2-4]static 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[] = {"1", "2", "3"}; ImGui::ListBox("list", &lb_cur, items, 3)imgui.ListBox('list', lb_cur, {'1', '2', '3'})
Функции с аргументами 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)
Теперь, зная всё это, вы уже можете начать работать с Moon ImGui. За списком функций ImGui и примерами на C++ обращайтесь на официальную страницу.

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

Работа с другими языками на примере русского
В MoonLoader v.025 были добавлены библиотеки lua-iconv и encoding, они призваны помочь в работе с разными кодировками текста.
Следующий пример показывает как использовать текст на русском в ImGui:
Скрипт должен быть сохранён в кодировке Windows-1251
Lua:
local imgui = require 'imgui'
local encoding = require 'encoding' -- загружаем библиотеку
encoding.default = 'CP1251' -- указываем кодировку по умолчанию, она должна совпадать с кодировкой файла. CP1251 - это Windows-1251
u8 = encoding.UTF8 -- и создаём короткий псевдоним для кодировщика UTF-8

local test_text_buffer = imgui.ImBuffer(256)
function imgui.OnDrawFrame()
  imgui.Begin(u8'Основное окно') -- обратите внимание на u8 перед текстом, это и есть преобразование кодировки
  if imgui.InputText(u8'Вводить текст сюда', test_text_buffer) then -- условие будет срабатывать при изменении текста
    -- здесь первая строка передаётся по-обычному, без u8
    -- но введённый текст при выводе преобразуется обратно из UTF-8 в кодировку по умолчанию, т.е. в Windows-1251
    print('Введённый текст:', u8:decode(test_text_buffer.v)) -- при работе с ImBuffer тоже не забывайте о .v
  end
  imgui.Text(u8'Введённый текст: ' .. test_text_buffer.v) -- но тут обратное преобразование введённого текста не требуется, т.к. текст буфера и так в UTF-8
  imgui.Text(u8(string.format('Текущая дата: %s', os.date()))) -- u8 - это функция, её можно использовать и с неконстантными строками
  imgui.End()
end

function main()
  imgui.Process = true
end
Результат:
upload_2017-11-25_18-29-37.png


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

Остальные особенности
В Moon ImGui есть несколько дополнительных возможностей. В частности, они реализуют взаимодействие с игрой и управление интерфейсом.
Код:
Параметры
imgui.BeforeDrawFrame = nil  -  опциональный калбэк. Если он задан, будет вызываться каждый кадр перед OnDrawFrame и NewFrame самого ImGui. Его можно использовать для загрузки шрифтов и текстур (будьте осторожны, он вызывается каждый кадр)
imgui.OnDrawFrame = nil  -  основной калбэк для рендера, о нём вы уже знаете
imgui.Process = false  -  только если задано true, имгуи будет обрабатываться и выводиться
imgui.RenderInMenu = false  -  показывать интерфейс в меню паузы, по умолчанию отключено
imgui.ShowCursor = true  -  показывать курсор, по умолчанию включен. Отключение может пригодиться, если нужно рисовать только какой-то оверлей без взаимодействия с ним
imgui.LockPlayer = false  -  отключить управление игроком, пока ImGui активен. Если не задано, то управление игроком будет отключаться только когда ImGui требуется обработать ввод с клавиатуры

Функции
после загрузки новых шрифтов и обязательно вне OnDrawFrame
function imgui.CreateTextureFromFile(path)  -  загрузить текстуру из файла. Возвращает загруженную текстуру или nil в случае неудачи
function imgui.CreateTextureFromMemory(address, size)  -  загрузить текстуру из изображения, хранящегося по указанному адресу в памяти. Возвращает загруженную текстуру или nil в случае неудачи
function imgui.GetTextureFromAddress(address)  -  получить ImGui-совместимую текстуру по адресу памяти
function imgui.ReleaseTexture(texture)  -  выгрузить текстуру, загруженную с помощью CreateTextureFromFile или CreateTextureFromMemory\
function imgui.RebuildFonts()  -  пересобрать внутреннюю текстуру шрифтов. Необходимо использовать
function imgui.SwitchContext()  -  переключить ImGui-контекст на принадлежащий скрипту. В BeforeDrawFrame и OnDrawFrame контекст переключается автоматически, так что в них эту функцию использовать нет нужды.

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

upload_2017-11-25_18-28-12.png

Полезные штуки для разработчиков
FontAwesome 4: https://blast.hk/threads/19292/post-168990
FontAwesome 5: https://blast.hk/threads/19292/post-335148
ImGui Pie: https://blast.hk/threads/19648/post-226145
Внутриигровая песочница: https://blast.hk/threads/19292/post-219453
ImGui Custom (хоткеи и ещё чет): https://blast.hk/threads/22080/
Global notification: https://blast.hk/threads/21619/
Стили:
https://blast.hk/threads/19292/post-260462

Ссылки
Скачать Moon ImGui (Download)
Установка:
распаковать содержимое архива в корневую папку игры.
Требуется MoonLoader v.026 или выше
Официальная страница ImGui
Пример на C++ с применением большинства возможностей (imgui_demo.cpp)
Все функции ImGui (imgui.h. Список поддерживаемых также есть в imgui.lua)
 

Вложения

  • moon imgui demo.lua
    9.2 KB · Просмотры: 122,240
Последнее редактирование:

Шурик

Активный
216
43
на пк код(
там все сложно, но у меня получалось с одним колбеком.
скинь код c++. нашаманим если вспомню))
Lua:
  struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
 

AnWu

Известный
Всефорумный модератор
4,777
5,400
Lua:
  struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
не, так точно не вспомню. ща мб найду в переписке одной

upd: не нашел. го шаманить. напиши в телегу или Aleksandr Jigarev(http://vk.com/donhomka)
 
Последнее редактирование:

datguymedusa

Новичок
5
1
Подскажите пожалуйста, как можно сделать кастомный CheckBox? Я бы сделал в самом скрипте, но не смогу перевести этот код на Lua.

PHP:
bool ImGui::Checkbox(const char* label, bool* v)
{
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
        return false;
    ImGuiContext& g = *GImGui;
    const ImGuiStyle& style = ImGuiStyle::ImGuiStyle();
    const ImGuiID id = window->GetID(label);
    const ImVec2 label_size = CalcTextSize(label, NULL, true);
    const ImVec2 pading = ImVec2(2, 2);
    const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.x * 6, label_size.y + style.FramePadding.y / 2));
    ItemSize(check_bb, style.FramePadding.y);
    ImRect total_bb = check_bb;
    if (label_size.x > 0)
        SameLine(0, style.ItemInnerSpacing.x);
    const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
    if (label_size.x > 0)
    {
        ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);
        total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
    }
    if (!ItemAdd(total_bb, &id))
        return false;
    bool hovered, held;
    bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
    if (pressed)
        *v = !(*v);
    const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
    const float check_sz2 = check_sz / 2;
    const float pad = ImMax(1.0f, (float)(int)(check_sz / 4.f));
    //window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), style.FrameRounding);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 5, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 4, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 3, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 1, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 1, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 3, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 4, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 5, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), 12);
    window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), 12);
    if (*v)//от исовка галочки
    {
        //window->DrawList->AddRectFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2, check_bb.Min.y), check_bb.Max, GetColorU32(ImVec4(0.34f, 1.0f, 0.54f, 1.0f)), 0);
        //window->DrawList->AddRectFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2, check_bb.Min.y), check_bb.Max, GetColorU32(ImVec4(0.34f, 1.0f, 0.54f, 1.0f)), 0);


        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 5, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 4, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 3, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 1, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 1, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 2, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 3, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 4, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 5, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)), 12);
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 + 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), 12);
    }
    else
    {
        window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2 - 6, check_bb.Min.y + 9), 7, GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), 12);
    }
    if (label_size.x > 0.0f)
        RenderText(text_bb.GetTL(), label);
    return pressed;
}
 

kektop1

Новичок
62
12
подскажите, как сделать переключение на страницу или что-то вроде этого, типо нажал на imgui.Button(u8"Пролог") - открылась первая страница из массива и т.д
 

~Justie~

Участник
133
25
  • Сделал кнопку, что-бы при нажатии на нее открывалось новое окно. Сама менюшка нормально работает, а вот когда нажимаю на кнопку. Просто пропадает окно, а курсор остается.
  • И в консоли SampFuncs:
  • [ML] (error) moon imgui demo.lua: Script died due to an error. (01C30104)
    Вот код:

    Lua:
    local imgui = require 'imgui'
    local key = require 'vkeys'
    local encoding = require 'encoding'
    encoding.default = 'CP1251'
    u8 = encoding.UTF8
    
    local main_window_state = imgui.ImBool(false)
    function imgui.OnDrawFrame()
    imgui.SwitchContext()
        local style = imgui.GetStyle()
        local colors = style.Colors
        local clr = imgui.Col
        local ImVec4 = imgui.ImVec4
        local show_another_window = imgui.ImBool(false)
        colors[clr.Button]                 = ImVec4(0.26, 0.59, 0.98, 0.40)
        colors[clr.ButtonHovered]          = ImVec4(0.26, 0.59, 0.98, 1.00)
        colors[clr.ButtonActive]           = ImVec4(0.06, 0.53, 0.98, 1.00)
        colors[clr.TitleBg]                = ImVec4(0.04, 0.04, 0.04, 1.00)
        colors[clr.TitleBgActive]          = ImVec4(0.16, 0.29, 0.48, 1.00)
        colors[clr.TitleBgCollapsed]       = ImVec4(0.00, 0.00, 0.00, 0.51)
        colors[clr.CloseButton]            = ImVec4(0.41, 0.41, 0.41, 0.50)
        colors[clr.CloseButtonHovered]     = ImVec4(0.98, 0.39, 0.36, 1.00)
        colors[clr.CloseButtonActive]      = ImVec4(0.98, 0.39, 0.36, 1.00)
        colors[clr.TextSelectedBg]         = ImVec4(0.26, 0.59, 0.98, 0.35)
        colors[clr.Text]                   = ImVec4(1.00, 1.00, 1.00, 1.00)
        colors[clr.FrameBg]                = ImVec4(0.16, 0.29, 0.48, 0.54)
        colors[clr.FrameBgHovered]         = ImVec4(0.26, 0.59, 0.98, 0.40)
        colors[clr.FrameBgActive]          = ImVec4(0.26, 0.59, 0.98, 0.67)
      if main_window_state.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))   
        imgui.Begin(u8'Мое меню', main_window_state)
        local btn_size = imgui.ImVec2(-0.1, 0)
        if imgui.Button(u8'Прост', btn_size) then
        end
        if imgui.Button(u8'Нажми, будет другое окно', btn_size) then 
    
            show_another_window.v = not show_another_window.v
        end
        imgui.End()
      end
        if show_another_window.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver) 
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))   
            imgui.begin(u8'Ну тип вот оно', show_another_window)
            imgui.text(u8'ага')
        end
    end
    
    function main()
      while true do
        wait(0)
        if wasKeyPressed(key.VK_X) then
            main_window_state.v = not main_window_state.v
        end
        imgui.Process = main_window_state.v
      end
    end
    .
  • Помогите пожалуйста
 

Adventurer

Известный
151
69
  • Сделал кнопку, что-бы при нажатии на нее открывалось новое окно. Сама менюшка нормально работает, а вот когда нажимаю на кнопку. Просто пропадает окно, а курсор остается.
  • И в консоли SampFuncs:
  • [ML] (error) moon imgui demo.lua: Script died due to an error. (01C30104)
    Вот код:

    Lua:
    local imgui = require 'imgui'
    local key = require 'vkeys'
    local encoding = require 'encoding'
    encoding.default = 'CP1251'
    u8 = encoding.UTF8
    
    local main_window_state = imgui.ImBool(false)
    function imgui.OnDrawFrame()
    imgui.SwitchContext()
        local style = imgui.GetStyle()
        local colors = style.Colors
        local clr = imgui.Col
        local ImVec4 = imgui.ImVec4
        local show_another_window = imgui.ImBool(false)
        colors[clr.Button]                 = ImVec4(0.26, 0.59, 0.98, 0.40)
        colors[clr.ButtonHovered]          = ImVec4(0.26, 0.59, 0.98, 1.00)
        colors[clr.ButtonActive]           = ImVec4(0.06, 0.53, 0.98, 1.00)
        colors[clr.TitleBg]                = ImVec4(0.04, 0.04, 0.04, 1.00)
        colors[clr.TitleBgActive]          = ImVec4(0.16, 0.29, 0.48, 1.00)
        colors[clr.TitleBgCollapsed]       = ImVec4(0.00, 0.00, 0.00, 0.51)
        colors[clr.CloseButton]            = ImVec4(0.41, 0.41, 0.41, 0.50)
        colors[clr.CloseButtonHovered]     = ImVec4(0.98, 0.39, 0.36, 1.00)
        colors[clr.CloseButtonActive]      = ImVec4(0.98, 0.39, 0.36, 1.00)
        colors[clr.TextSelectedBg]         = ImVec4(0.26, 0.59, 0.98, 0.35)
        colors[clr.Text]                   = ImVec4(1.00, 1.00, 1.00, 1.00)
        colors[clr.FrameBg]                = ImVec4(0.16, 0.29, 0.48, 0.54)
        colors[clr.FrameBgHovered]         = ImVec4(0.26, 0.59, 0.98, 0.40)
        colors[clr.FrameBgActive]          = ImVec4(0.26, 0.59, 0.98, 0.67)
      if main_window_state.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))   
        imgui.Begin(u8'Мое меню', main_window_state)
        local btn_size = imgui.ImVec2(-0.1, 0)
        if imgui.Button(u8'Прост', btn_size) then
        end
        if imgui.Button(u8'Нажми, будет другое окно', btn_size) then 
    
            show_another_window.v = not show_another_window.v
        end
        imgui.End()
      end
        if show_another_window.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver) 
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))   
            imgui.begin(u8'Ну тип вот оно', show_another_window)
            imgui.text(u8'ага')
        end
    end
    
    function main()
      while true do
        wait(0)
        if wasKeyPressed(key.VK_X) then
            main_window_state.v = not main_window_state.v
        end
        imgui.Process = main_window_state.v
      end
    end
    .
  • Помогите пожалуйста
Объявление второго окна не в том месте у тебя указано. Ты объявляешь его в цикле.
Перенеси 14-ю строчку к седьмой, чтобы она не была не в каких функциях и циклах.
И вообще код мне твой не нравится.

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

подскажите, как сделать переключение на страницу или что-то вроде этого, типо нажал на imgui.Button(u8"Пролог") - открылась первая страница из массива и т.д
Ну смотри, допустим, у тебя есть окошко.

В коде у тебя будет так, получается.
Lua:
if окно then
    --code
    if not window_tab then window_tab = 1; end
   
    if window_tab == 1 then
        if imgui.Button(u8"страница 2") then window_tab = 2; end
        if imgui.Button(u8"страница 3") then window_tab = 3; end
    end
    if window_tab == 2 then
        if imgui.Button(u8"Вернуться обратно") then window_tab = 1; end
        if imgui.Button(u8"Страница 3") then window_tab = 3; end
    end
    if window_tab == 3 then
        if imgui.Button(u8"Страница 1") then window_tab = 1; end
        if imgui.Button(u8"Страница 2") then window_tab = 2; end
    end

    imgui.End()
end
Есть, наверное, более умный способ сделать это, но я тебе привел в пример самый доступный, простой и не очень большой по размеру.
 
Последнее редактирование:
  • Нравится
Реакции: N1ghT и kektop1

~Justie~

Участник
133
25
Объявление второго окна не в том месте у тебя указано. Ты объявляешь его в цикле.
Перенеси 14-ю строчку к седьмой, чтобы она не была не в каких функциях и циклах.
И вообще код мне твой не нравится.
Мне тоже мой код не нравится :D Сегодня первый день на lua и imgui

Объявление второго окна не в том месте у тебя указано. Ты объявляешь его в цикле.
Перенеси 14-ю строчку к седьмой, чтобы она не была не в каких функциях и циклах.
И вообще код мне твой не нравится.
Перенес 14-ю строчку к седьмой, все тоже самое. Может у меня с сампом проблемы?
Вот, что в консоли
[ML] (error) moon imgui demo.lua: Script died due to an error. (01BD93A4)
 
Последнее редактирование модератором:

Adventurer

Известный
151
69
Перенес 14-ю строчку к седьмой, все тоже самое. Может у меня с сампом проблемы?
Вот, что в консоли
[ML] (error) moon imgui demo.lua: Script died due to an error. (01BD93A4)
Код:
    if show_another_window.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300)) 
        imgui.Begin(u8'Ну тип вот оно', show_another_window)
        imgui.Text(u8'ага')
        imgui.End()
    end

Сноси свои строки, вставляй мои.
Обязательно соблюдай регистр, луа очень чувствителен к нему.
И бери в привычку, что imgui.Begin(), как и любое условие и тому подобное, нужно закрывать, то бишь imgui.End()

56 строка кода:
imgui.Process = main_window_state.v or show_another_window.v
Вроде бы, сейчас все должно быть окей.
 
Последнее редактирование:

~Justie~

Участник
133
25
Код:
    if show_another_window.v then
        imgui.SetNextWindowSize(imgui.ImVec2(400, 150), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))
        imgui.Begin(u8'Ну тип вот оно', show_another_window)
        imgui.Text(u8'ага')
        imgui.End()
    end

Сноси свои строки, вставляй мои.
Обязательно соблюдай регистр, луа очень чувствителен к нему.
И бери в привычку, что imgui.Begin(), как и любое условие и тому подобное, нужно закрывать, то бишь imgui.End()
Вроде бы, сейчас все должно быть окей.
Спасибо огромное!
P.S Все равно пропадает сразу-же

Как переносить строку в imgui.Text(' ') ?
 
Последнее редактирование модератором:

qrlk

Известный
Друг
411
928
Возникла проблема, которая уже заебала. После активации main_window_state скрипт намертво виснет (не сразу, через 5-20 сек). SAMPFUNCS.log - флуд, 10-50 мб этой ошибкой. Иногда выбивает пустую ошибку с выходом из скрипта в лог муна. Код скинуть не могу, но надеюсь, что из лога что-то будет понятно/что кто-то уже с этим сталкивался.
На W7 проблема решалась установкой задержки в 4 секунды между require imgui и остальными библиотеками. На W10 это не спасает.
Код:
[16:44:53] SAMPFUNCS v5.3.3 release #19 (SA-MP 0.3.7) caught an exception.
[16:44:53] Base address: 07990000
[16:44:53] > Exception record:
[16:44:53] Exception at address: 0F9677D6, Flags: 00000000
[16:44:53] Module: C:\Program Files (x86)\Steam\steamapps\common\Grand Theft Auto San Andreas\lua51.dll (0F960000)
[16:44:53] Cause: EXCEPTION_ACCESS_VIOLATION
[16:44:53] Attempted to read from: 00000078
[16:44:53] > Exception context:
[16:44:53] EAX: 00000078    ESI: 07640898
[16:44:53] EBX: 00000018    EDX: 00000000
[16:44:53] ECX: FFFFD8F0    EDI: 07640898
[16:44:53] EBP: 075D01C0    ESP: 0177F700
[16:44:53] DR0: 00000000    DR1: 00000000
[16:44:53] DR2: 00000000    DR3: 00000000
[16:44:53] DR6: 00000000    DR7: 00000000
[16:44:53] SegGs: 0000002B    SegFs: 00000053
[16:44:53] SegEs: 0000002B    SegDs: 0000002B
[16:44:53] > Stack:
FFFFD8F0 0F9A9325 07640898 FFFFD8F0
00000000 FFFFFFFF 03BEF280 075D0D58
0F4AA935 07640898 FFFFD8F0 00000018
03BEF280 0F3C0957 0F399D70 075D02CC
0F399D99 081FB188 075D01C0 00000001
0F96280D 075D01C0 075D01C0 0177F868
075D0D58 5D1A20DD 00000001 075D01C0
075D01C0 FFFFFFFF 0177F894 0F984360
075D0100 0026A418 075D01F0 075D01C0
0F987AFB 075D01C0 0177F870 00000001
FFFFFFFF 075D01F0 081FB168 0177F7D8
075D01F0 0F987D07 075D01F0 075D01C0
076249C0 081FB168 075D01F0 075D01C0
075D0240 00000004 000006A4 0F9876C0
075D01C0 0761EEB8 075D01C0 0177F868
00000000 FFFFFFFF 075D01C0 0F98C3F9
[16:44:53] > Modules:
gta_sa.exe, 00400000, 01177000
ntdll.dll, 76F30000, 0018C000
KERNEL32.DLL, 74870000, 000D0000
KERNELBASE.dll, 73CD0000, 001D8000
apphelp.dll, 72EB0000, 0009A000
WS2_32.dll, 73A20000, 00066000
RPCRT4.dll, 73A90000, 000BE000
SspiCli.dll, 73950000, 00020000
CRYPTBASE.dll, 73940000, 0000A000
vorbisfile.dll, 0F1C0000, 00011000
bcryptPrimitives.dll, 76D30000, 00057000
WINMM.dll, 6CA90000, 00024000
sechost.dll, 75600000, 00043000
msvcrt.dll, 75650000, 000BD000
USER32.dll, 73B50000, 00175000
WINMMBASE.dll, 6C840000, 00023000
win32u.dll, 75210000, 00016000
cfgmgr32.dll, 75590000, 00038000
GDI32.dll, 755D0000, 00022000
ucrtbase.dll, 75230000, 00117000
gdi32full.dll, 74950000, 0015F000
EAX.DLL, 10000000, 00030000
ADVAPI32.dll, 74340000, 00078000
msvcp_win.dll, 750E0000, 0007C000
ole32.dll, 76E20000, 000F7000
combase.dll, 74620000, 00246000
IMM32.DLL, 751E0000, 00025000
samp.dll, 05B80000, 00330000
PSAPI.DLL, 75770000, 00006000
SHELL32.dll, 75810000, 01334000
COMCTL32.dll, 6DDA0000, 0008E000
shcore.dll, 73970000, 00088000
WSOCK32.dll, 68E90000, 00008000
BASS.dll, 0FD80000, 00055000
windows.storage.dll, 74AB0000, 005C4000
shlwapi.dll, 742F0000, 00045000
kernel.appcore.dll, 73EB0000, 0000E000
MSACM32.dll, 54CC0000, 00019000
powrprof.dll, 75350000, 00045000
profapi.dll, 73A00000, 00014000
d3dx9_25.dll, 05EB0000, 00253000
usp10.dll, 6A280000, 00017000
vorbishooked.DLL, 000D0000, 00011000
ogg.dll, 00030000, 00009000
vorbis.dll, 06110000, 00108000
CRYPTSP.dll, 72E60000, 00013000
rsaenh.dll, 72E30000, 0002F000
bcrypt.dll, 72E10000, 00019000
USERENV.dll, 6CDF0000, 00022000
CRYPT32.dll, 76B50000, 00182000
MSASN1.dll, 74940000, 0000E000
DPAPI.dll, 6D3C0000, 00008000
audio.asi, 06B40000, 00106000
CLEO.asi, 0FF20000, 0004B000
FileSystemOperations.cleo, 0F890000, 00004000
IniFiles.cleo, 0FA80000, 00005000
IntOperations.cleo, 0F640000, 00004000
fix.black_roads.asi, 0FEE0000, 00006000
MSVCR100.dll, 789E0000, 000BF000
MoonLoader.asi, 0F390000, 00208000
d3dx9_43.dll, 0FA90000, 001FF000
WININET.dll, 6D560000, 003E3000
urlmon.dll, 6F040000, 0018D000
imagehlp.dll, 75160000, 00019000
iertutil.dll, 6EE20000, 0021F000
lua51.dll, 0F960000, 00098000
mousefix.asi, 0FE30000, 00011000
NormalMapFix.asi, 01800000, 0000E000
OutFitFix.asi, 01830000, 0000E000
radarrect.asi, 0FA50000, 00013000
samp.asi, 06FE0000, 003AF000
dbghelp.dll, 6A7D0000, 00181000
VERSION.dll, 737A0000, 00008000
d3d9.dll, 692D0000, 0016C000
dwmapi.dll, 6C7E0000, 00023000
SAMPFUNCS.asi, 07990000, 00208000
Date&Time.sf, 01920000, 00029000
SAMPGraphicRestore.asi, 01960000, 00015000
ShellFix.asi, 042D0000, 00017000
StreamMemFix.asi, 044D0000, 0000E000
uxtheme.dll, 6C740000, 00079000
DDRAW.dll, 50170000, 000EA000
dxgi.dll, 6CAC0000, 00093000
DCIMAN32.dll, 50C10000, 00007000
DSOUND.dll, 54C30000, 00080000
clbcatq.dll, 75780000, 00082000
MMDevApi.dll, 6A0E0000, 0005B000
DEVOBJ.dll, 6EBA0000, 00022000
PROPSYS.dll, 70DB0000, 0017B000
OLEAUT32.dll, 754F0000, 00093000
AUDIOSES.DLL, 6A150000, 000F4000
wintypes.dll, 6CFE0000, 000CB000
AVRT.dll, 6A140000, 00008000
MSCTF.dll, 753A0000, 00144000
DINPUT8.dll, 67280000, 00038000
inputhost.dll, 66FC0000, 00026000
CoreMessaging.dll, 66960000, 0008C000
CoreUIComponents.dll, 5D5C0000, 00234000
ntmarta.dll, 71940000, 00028000
HID.DLL, 68E80000, 0000A000
SETUPAPI.DLL, 73EC0000, 00426000
WINTRUST.dll, 76CE0000, 00046000
nvldumd.dll, 0F730000, 000C6000
nvd3dum.dll, 09940000, 00EFB000
nvspcap.dll, 0A940000, 001DF000
gpapi.dll, 70D90000, 0001E000
cryptnet.dll, 70D20000, 00026000
TextInputFramework.dll, 54AE0000, 00077000
dcomp.dll, 68EF0000, 000FE000
lfs.dll, 0F5E0000, 00024000
Windows.UI.dll, 1A1E0000, 000CE000
wmvcore.dll, 1A6F0000, 0021C000
mfperfhelper.dll, 69B60000, 00107000
WMASF.DLL, 1A910000, 0003F000
MFPlat.DLL, 69ED0000, 00175000
RTWorkQ.DLL, 69EA0000, 00027000
mlang.dll, 54BC0000, 00035000
mswsock.dll, 72F50000, 00055000
napinsp.dll, 66280000, 00011000
pnrpnsp.dll, 66240000, 00016000
NLAapi.dll, 66260000, 00013000
DNSAPI.dll, 704D0000, 00094000
NSI.dll, 76F20000, 00007000
IPHLPAPI.DLL, 704A0000, 00030000
winrnr.dll, 66230000, 0000C000
wshbth.dll, 66220000, 00010000
fwpuclnt.dll, 702D0000, 0004E000
rasadhlp.dll, 70320000, 00008000
msiso.dll, 6EDC0000, 0005F000
ondemandconnroutehelper.dll, 6D540000, 00012000
winhttp.dll, 737B0000, 000AD000
WINNSI.DLL, 6F1D0000, 00008000
schannel.dll, 6D440000, 00068000
mskeyprotect.dll, 6FA40000, 00010000
ncrypt.dll, 6D420000, 00020000
NTASN1.dll, 6D3F0000, 0002C000
ncryptsslp.dll, 6D3D0000, 0001B000
MoonImGui.dll, 21F40000, 0035E000
Ninput.dll, 076D0000, 00055000
igdumdim32.dll, 07390000, 001AA000
igd9dxva32.dll, 14030000, 02F77000
igc32.dll, 62C60000, 019FD000
iconv.dll, 089E0000, 000F9000

[16:44:53] > Plugins:
Date&Time.sf

[16:44:53] > SCM Thread:
hj             00A903D0      00000000     00A561AD         true
noname         00A904B0      00000000     00A56B07         true
intman         00A90590      00000000     00A56FDA         true
main           00A90750      00000000     00A56123         true
sv.cs          1CA8CFA8      1CA8D0B8     1CA8D0D6         false
RadioDi        1CA889C8      1CA88AD8     1CA88ADE         true
PoolRen        1CA80FB8      1CA810C8     1CA812AD         true
Health-        1CA7C988      1CA7CA98     1CA7CAC0         true
sudak          06DD0970      1CA74840     1CA74A12         true
 

Че.

Новичок
9
1
Исправьте описание​
Требуется MoonLoader v.025 или выше
Когда 4 строка imgui.lua предупреждает : assert(getMoonloaderVersion() >= 026, 'Moon ImGui requires MoonLoader v.026 or greater.')
И в логе: GTA San Andreas\moonloader\lib\imgui.lua:4: Moon ImGui requires MoonLoader v.026 or greater.
Кому надо для .025 берите ImGui 1.1.2 из темы SR_team
 
Последнее редактирование: