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,232
Последнее редактирование:

RENNY

Известный
14
4
Напишу при этом и сюда.
Крашит именно эта вырезка из кода. Я основной скрипт убрал, работаю с этим маленьким кодом, который крашит. Проблему решить так и не могу.
Lua:
-- подгрузка библиотек
require "lib.moonloader"
local inicfg = require 'inicfg'
local dlstatus = require('moonloader').download_status
local sampev = require "samp.events"
local imgui = require 'imgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8

local resX, resY = getScreenResolution()
local main_window_state = imgui.ImBool(false)

function imgui.OnDrawFrame()
    imgui.SetNextWindowPos(imgui.ImVec2(resX/2 - 250, resY/2 - 100))
    imgui.SetNextWindowSize(imgui.ImVec2(500, 200))
    imgui.Begin('Menu Light Police Helper', main_window_state, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove)
    imgui.End()
end




-- МЕЙН СКРИПТА
function main()
  if not isSampfuncsLoaded() or not isSampLoaded() then return end
  while not isSampAvailable() do wait(2000) end

lua_thread.create(combinationsFunc)

    while true do wait(0) imgui.Process = main_window_state.v end
end

function combinationsFunc()
    while true do
        wait(0)

        if isKeyDown(VK_P) and isKeyJustPressed(VK_L) and not sampIsChatInputActive() and not sampIsDialogActive() then
            main_window_state.v = not main_window_state.v
            end
    end
end

Вызываются краши. Максимальная стабильность игры - 15 минут. После краш.
Про сборку неактуально говорить, всё уже несколько раз проверялось на чистейшей девственной сборке и не помогало. По крашу видно, что ошибка происходит в lua, а именно Backtrace ведёт к MoonImgui.dll. Хотелось бы узнать, в чем проблема.
@FYP , помоги, твоё же детище)
Я думаю, что ты лучше всех можешь знать, в чем эта проблема заключается.

Код:
SA-MP 0.3.7
Exception At Address: 0x5C6977D8 in lua51.dll+0x77D8
Exception: 0xC0000005 - Access violation reading location 0x6C754D7D

Registers:
EAX: 0x0F900960    EBX: 0x0000001F    ECX: 0x6C754D65    EDX: 0x00000000
ESI: 0x0FEA49E8    EDI: 0x0FEA49E8    EBP: 0x0F8F01C0    ESP: 0x0177F3D0
EFLAGS: 0x00210212

Backtrace:
0x5C6977D8 lua_rawgeti+0x18 in lua51.dll+0x77D8
0x5C6D9325 luaL_unref+0x35 in lua51.dll+0x49325
0x5A239825 in MoonLoader.asi+0x119825
0x5A150197 in MoonLoader.asi+0x30197
0x5A129BD9 in MoonLoader.asi+0x9BD9
0x5C69280D in lua51.dll+0x280D
0x7605506C NtGdiDdDDIUnlock2+0xC in win32u.dll+0x506C
0x5DF604EC in d3d9.dll+0x504EC
0x5C6B7AFB lua_error+0x357B in lua51.dll+0x27AFB
0x5C6B7D07 lua_error+0x3787 in lua51.dll+0x27D07
0x5C6B76C0 lua_error+0x3140 in lua51.dll+0x276C0
0x5C697577 lua_pushlstring+0x17 in lua51.dll+0x7577
0x5C6D916C luaL_pushresult+0x1C in lua51.dll+0x4916C
0x55720AC4 in MoonImGui.dll+0x40AC4
0x5571CECD in MoonImGui.dll+0x3CECD
0x556E86FC in MoonImGui.dll+0x86FC
0x556F1BBE in MoonImGui.dll+0x11BBE
0x557D3BA3 in MoonImGui.dll+0xF3BA3
0x557C59FD in MoonImGui.dll+0xE59FD

ASI plugins:
CLEO.asi
crashes.asi
MoonLoader.asi
radarrect.asi
SAMP.asi
SAMPFUNCS.asi
SAMPGraphicRestore.asi
sa_widescreenfix_lite.asi
SilentPatchSA.asi

d3d9.dll: unknown

Cleo:
anticrasher037.cs
ccontrol.cs
limit.cs

Address code: 3B 51 18 73 08
Before address code: 83 C4 08 8B 08

Crash module: lua51.dll
Size: 606208
CRC32: C5307085

Stack:
+0000: 0xFFFFD8F0   0x5C6D9325   0x0FEA49E8   0xFFFFD8F0
+0010: 0x00000000   0xFFFFFFFF   0x0D8863F8   0x0F8F0D58
+0020: 0x5A239825   0x0FEA49E8   0xFFFFD8F0   0x0000001F
+0030: 0x0D8863F8   0x5A150197   0x5A129BB0   0x0F8F02CC
+0040: 0x5A129BD9   0x0FEA5178   0x0F8F01C0   0x00000001
+0050: 0x5C69280D   0x0F8F01C0   0x00000000   0x00000000
+0060: 0x28C1EBF0   0x0177F48C   0x00000001   0x0F8F01C0
+0070: 0x7605506C   0x5DF604EC   0x0177F888   0x5C6B4360

SCM Op: 0x6BD, lDbg: 0 LastRendObj: 19477

Game work: 255 sec

Pos: 2819.466553 882.488098 1045.526733

Game Version: US 1.0

Memory: 470 MB

Windows 10
 
Последнее редактирование:

FYP

Известный
Автор темы
Администратор
1,764
5,924
@sanya_firsov если трассировка стека верная, у тебя установлен не moonloader v.026.5. установи последний moonimgui и moonloader.
 

RENNY

Известный
14
4
@sanya_firsov если трассировка стека верная, у тебя установлен не moonloader v.026.5. установи последний moonimgui и moonloader.
upload_2019-6-19_11-40-47.png

Походу я нашел решение проблемы. Я вынес imgui.ImVec2(x,y) из-под OnDrawFrame в отдельные локальные переменные скрипта. Пока что крашей не наблюдается, но если появятся, то я отпишусь. Также для всех SetNext_ я добавил imgui.Cond.FirstUseEver.
Также я вынес все ImBuffer, которые у меня были, в локалки скрипта на всякий случай.

По логике OnDrawFrame вызывается каждый кадр и каждый кадр обращался к imgui.ImVec2 и прочим, что вызывало краш. Если интересно, то сам попробуй, вдруг поможет в следующих версиях mimgui пофиксить это.

@FYP
Частично решено способом выше. Краши теперь хотя бы не столь частые, но происходят по той же причине. Причем вылетает 2 крашлога (я так понимаю, что SetNextWindowPos и Size это). Убираю - работает целый час и никаких намёков на краш. Возвращаю их в строй - краш через 10 минут.
mimgui даже еще раз обновил и moonloader (хотя и так последние стояли, догадываюсь, что ты по lua51.dll подумал, что старая версия, хотя luajit уже на 5.2+ перешел). Какие будут предложения?)

Вот вырезка полная function imgui.OnRenderFrame()
Вдруг кто найдет потенциальные или грубые ошибки в написании. Краши происходят, просто открыв первое окно и дальше никуда не двигаясь.
Lua:
function imgui.OnDrawFrame()
    imgui.SetNextWindowPos(positionOfMainWindow, imgui.Cond.FirstUseEver)
    imgui.SetNextWindowSize(sizeOfMainWindow, imgui.Cond.FirstUseEver)
    imgui.Begin('Menu Light Police Helper', main_window_state, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove)

    if imgui.Button(u8'Помощь по Light Police Helper', sizeForWidth) then
        imgui.SetNextWindowPos(positionOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(sizeOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.OpenPopup(u8'Помощь по Light Police Helper')
    end

    if imgui.BeginPopupModal(u8'Помощь по Light Police Helper', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
        imgui.InputTextMultiline(u8'Помощь по Light Police Helper', bufhelp, sizeOfMultiline, imgui.InputTextFlags.ReadOnly)
        if imgui.Button(u8'Назад', sizeForWidth) then
            imgui.CloseCurrentPopup()
        end
        imgui.EndPopup()
    end

    if imgui.Button(u8'Изменение параметров скрипта', sizeForWidth) then
        imgui.SetNextWindowPos(positionOfChangeWindow, imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(sizeOfChangeWindow, imgui.Cond.FirstUseEver)
        imgui.OpenPopup(u8'Изменение параметров скрипта')
    end

    if imgui.BeginPopupModal(u8'Изменение параметров скрипта', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
        if imgui.Button(u8'Изменить текст тега рации', sizeForWidth) then
            imgui.SetNextWindowPos(positionOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.SetNextWindowSize(sizeOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.OpenPopup(u8'Изменить текст тега рации')
        end

        if imgui.BeginPopupModal(u8'Изменить текст тега рации', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
            imgui.TextWrapped(u8'Введите текст тега рации (\'plid\', если нужен ваш ID).')
            imgui.InputText('', radio_text_buffer)
            if imgui.Button(u8'Сохранить', sizeForWidth) then
                cfgfile.RADIO.RADIOTEXT = u8:decode(radio_text_buffer.v)
                inicfg.save(cfgfile, "light_police_helper")
                imgui.CloseCurrentPopup()
            end
            imgui.EndPopup()
        end

        if imgui.Button(u8'Изменить текст мегафона', sizeForWidth) then
            imgui.SetNextWindowPos(positionOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.SetNextWindowSize(sizeOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.OpenPopup(u8'Изменить текст мегафона')
        end

        if imgui.BeginPopupModal(u8'Изменить текст мегафона', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
            imgui.InputText(u8'Статический мегафнон', megaphone1_text_buffer)
            imgui.InputText(u8'Динамический мегафнон', megaphone2_text_buffer)
            if imgui.Button(u8'Сохранить', sizeForWidth) then
                cfgfile.MEGAPHONE.MEGAPHONETEXT = u8:decode(megaphone1_text_buffer.v)
                cfgfile.MEGAPHONE.MEGAPHONETEXT2 = u8:decode(megaphone2_text_buffer.v)
                inicfg.save(cfgfile, "light_police_helper")
                imgui.CloseCurrentPopup()
            end
            imgui.EndPopup()
        end

        if imgui.Button(u8'Изменить ID смены цвета NickName', sizeForWidth) then
            imgui.SetNextWindowPos(positionOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.SetNextWindowSize(sizeOfPopupChangeWindow, imgui.Cond.FirstUseEver)
            imgui.OpenPopup(u8'Изменить ID смены цвета NickName')
        end

        if imgui.BeginPopupModal(u8'Изменить ID смены цвета NickName', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
            imgui.InputText(u8'Номер цвета', colorid_text_buffer)
            if imgui.Button(u8'Сохранить', sizeForWidth) then
                cfgfile.COLOR_NUMBER.COLORID = u8:decode(colorid_text_buffer.v)
                inicfg.save(cfgfile, "light_police_helper")
                imgui.CloseCurrentPopup()
            end
            imgui.EndPopup()
        end

        if imgui.Button(u8'Изменить пол для отыгровок', sizeForWidth) then
            cfgfile.SEX.ISPLAYERMAN = not cfgfile.SEX.ISPLAYERMAN
            inicfg.save(cfgfile, "light_police_helper")
        end

        if imgui.Button(u8'Изменить расположение SUSPECT LIST', sizeForWidth) then
            lua_thread.create(changePosSuspectList)
        end
        if imgui.Button(u8'Изменить расположение TAZER STATUS', sizeForWidth) then
            lua_thread.create(changePosTazerStatus)
        end
        -- if imgui.Button(u8'Изменить расположение SECTOR TEXT', sizeForWidth) then
        --     lua_thread.create(changePosZoneText)
        -- end

        if imgui.Button(u8'Назад', sizeForWidth) then
            imgui.CloseCurrentPopup()
        end
        imgui.EndPopup()
    end

    if imgui.Button(u8'Включение/выключение отдельных элементов интерфейса', sizeForWidth) then
        imgui.SetNextWindowPos(positionOfChangeWindow, imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(sizeOfChangeWindow, imgui.Cond.FirstUseEver)
        imgui.OpenPopup(u8'Включение/выключение отдельных элементов интерфейса')
    end

    if imgui.BeginPopupModal(u8'Включение/выключение отдельных элементов интерфейса', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then

        if imgui.Button(u8'Включить/выключить SUSPECT LIST', sizeForWidth) then
            cfgfile.VISIBLE.SUSPECTVISIBLE = not dxutIsDialogVisible(dxutDialogTime)
            inicfg.save(cfgfile, "light_police_helper")
            dxutSetDialogVisible(dxutDialogTime, cfgfile.VISIBLE.SUSPECTVISIBLE)
            dxutSetDialogVisible(dxutDialogWanted, cfgfile.VISIBLE.SUSPECTVISIBLE)
            dxutSetDialogVisible(dxutDialogSuspect, cfgfile.VISIBLE.SUSPECTVISIBLE)
            dxutSetDialogVisible(dxutDialogOfficer, cfgfile.VISIBLE.SUSPECTVISIBLE)
            dxutSetDialogVisible(dxutDialogReason, cfgfile.VISIBLE.SUSPECTVISIBLE)
        end

        if imgui.Button(u8'Включить/выключить TAZER STATUS', sizeForWidth) then
            cfgfile.VISIBLE.TAZERVISIBLE = not dxutIsDialogVisible(dxutDialogTazer)
            inicfg.save(cfgfile, "light_police_helper")
            dxutSetDialogVisible(dxutDialogTazer, not dxutIsDialogVisible(dxutDialogTazer))
        end

        -- if imgui.Button(u8'Включить/выключить SECTOR TEXT', sizeForWidth) then
        --     cfgfile.VISIBLE.ZONETEXTVISIBLE = not cfgfile.VISIBLE.ZONETEXTVISIBLE
        --     inicfg.save(cfgfile, "light_police_helper")
        --     dxutSetDialogVisible(dxutDialogZone, cfgfile.VISIBLE.ZONETEXTVISIBLE)
        --     if cfgfile.VISIBLE.ZONETEXTVISIBLE then
        --         locationfunc_thread:run()
        --     else
        --         locationfunc_thread:terminate()
        --         locationfunc_thread = lua_thread.create_suspended(locationFunc)
        --     end
        -- end
        if imgui.Button(u8'Назад', sizeForWidth) then
            imgui.CloseCurrentPopup()
        end
        imgui.EndPopup()
    end

    if imgui.Button(u8'Лог SUSPECT LIST', sizeForWidth) then
        lua_thread.create(showSuspectListLog)
    end

    if imgui.Button(u8'Изменения в версиях скрипта', sizeForWidth) then
        imgui.SetNextWindowPos(positionOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(sizeOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.OpenPopup(u8'Изменения в версиях скрипта')
    end

    if imgui.BeginPopupModal(u8'Изменения в версиях скрипта', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
        imgui.InputTextMultiline(u8'Изменения в версиях скрипта', bufchanges, sizeOfMultiline, imgui.InputTextFlags.ReadOnly)
        if imgui.Button(u8'Назад', sizeForWidth) then
            imgui.CloseCurrentPopup()
        end
        imgui.EndPopup()
    end

    if imgui.Button(u8'Открыть записную книжку', sizeForWidth) then
        imgui.SetNextWindowPos(positionOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(sizeOfInputWindows, imgui.Cond.FirstUseEver)
        imgui.OpenPopup(u8'Открыть записную книжку')
    end

    if imgui.BeginPopupModal(u8'Открыть записную книжку', nil, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
        imgui.InputTextMultiline(u8'Записная книжка', bufnotepad, sizeOfMultiline, imgui.InputTextFlags.AllowTabInput)
        if imgui.Button(u8'Сохранить', sizeForWidth) then
            local notepad = io.open(getWorkingDirectory()..'\\light police helper\\notepad.txt', 'w+')
            local temptext = u8:decode(bufnotepad.v)
            notepad:write(temptext)
            notepad:close()
            imgui.CloseCurrentPopup()
        end
        imgui.EndPopup()
    end

    if imgui.Button(u8'Принудительная перезагрузка скрипта', sizeForWidth) then
        lua_thread.create(reloading)
    end
    imgui.End()
end

Еще PS: пару крашей покидаю, вдруг будут иметь смысл.
Код:
SA-MP 0.3.7
Exception At Address: 0x56635C32 in lua51.dll+0x45C32
Exception: 0xC0000005 - Access violation reading location 0x0000000C

Для исправления вылетов мгры
Рекомендуется установить SA-MP Addon с gta-samp.ru

Registers:
EAX: 0x00000000    EBX: 0x00000021    ECX: 0x00000000    EDX: 0x00000000
ESI: 0x02599840    EDI: 0x05CA20C8    EBP: 0x0177F060    ESP: 0x0177F050
EFLAGS: 0x00210246

Backtrace:
0x56635C32 lua_newstate+0x4042 in lua51.dll+0x45C32
0x565F77EA lua_rawgeti+0x2A in lua51.dll+0x77EA
0x56639325 luaL_unref+0x35 in lua51.dll+0x49325
0x567A9825 in MoonLoader.asi+0x119825
0x566C0197 in MoonLoader.asi+0x30197
0x56699BD9 in MoonLoader.asi+0x9BD9
0x565F280D in lua51.dll+0x280D
0x56617AFB lua_error+0x357B in lua51.dll+0x27AFB
0x56617D07 lua_error+0x3787 in lua51.dll+0x27D07
0x56617648 lua_error+0x30C8 in lua51.dll+0x27648
0x566176C0 lua_error+0x3140 in lua51.dll+0x276C0
0x565F7577 lua_pushlstring+0x17 in lua51.dll+0x7577
0x5676E9B5 in MoonLoader.asi+0xDE9B5
0x56771450 in MoonLoader.asi+0xE1450
0x56642944 luaopen_string+0xC14 in lua51.dll+0x52944
0x565F280D in lua51.dll+0x280D
0x559FF543 ?SetCondResult@CScriptThread@@QAEX_N@Z+0xC in SAMPFUNCS.asi+0x1F543
0x566992B2 in MoonLoader.asi+0x92B2
0x567B69F1 in MoonLoader.asi+0x1269F1

ASI plugins:
CLEO.asi
crashes.asi
MoonLoader.asi
radarrect.asi
SAMP.asi
SAMPFUNCS.asi
SAMPGraphicRestore.asi
sa_widescreenfix_lite.asi
SilentPatchSA.asi

d3d9.dll: unknown

Cleo:
anticrasher037.cs
ccontrol.cs
limit.cs

Address code: 83 79 0C F2 73
Before address code: 0C 52 8D 0C C8

Crash module: lua51.dll
Size: 606208
CRC32: C5307085

Stack:
+0000: 0x05CA20C8   0x2B94DFD8   0x00000000   0x00000000
+0010: 0x024801C0   0x565F77EA   0xFFFFD8F0   0x56639325
+0020: 0x05CA20C8   0xFFFFD8F0   0x00000000   0xFFFFFFFF
+0030: 0x16318D80   0x02480D58   0x567A9825   0x05CA20C8
+0040: 0xFFFFD8F0   0x00000021   0x16318D80   0x566C0197
+0050: 0x56699BB0   0x024802CC   0x56699BD9   0x05CA2838
+0060: 0x024801C0   0x00000001   0x565F280D   0x024801C0
+0070: 0x00000000   0x00000000   0x00000000   0x00000000

SCM Op: 0x685, lDbg: 0 LastRendObj: 19015

Game work: 929 sec

Pos: 997.365173 1850.207275 10.327156

Game Version: US 1.0

Memory: 553 MB

Windows 10
Код:
SA-MP 0.3.7
Exception At Address: 0x565F77F1 in lua51.dll+0x77F1
Exception: 0xC0000005 - Access violation reading location 0xFFFF00FF

Для исправления вылетов мгры
Рекомендуется установить SA-MP Addon с gta-samp.ru

Registers:
EAX: 0xFFFF00FF    EBX: 0x00000032    ECX: 0x090A0926    EDX: 0x7FE45312
ESI: 0x05CA23D0    EDI: 0x05CA23D0    EBP: 0x024801C0    ESP: 0x0177DF38
EFLAGS: 0x00210286

Backtrace:
0x565F77F1 lua_rawgeti+0x31 in lua51.dll+0x77F1
0x56639325 luaL_unref+0x35 in lua51.dll+0x49325
0x567A9825 in MoonLoader.asi+0x119825
0x566C0197 in MoonLoader.asi+0x30197
0x56699BD9 in MoonLoader.asi+0x9BD9
0x565F280D in lua51.dll+0x280D
0x55A96F0F ?unregisterConsoleCommand@SAMPFUNCS@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z+0x27B9F in SAMPFUNCS.asi+0xB6F0F
0x55A7A497 ?unregisterConsoleCommand@SAMPFUNCS@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z+0xB127 in SAMPFUNCS.asi+0x9A497
0x56617AFB lua_error+0x357B in lua51.dll+0x27AFB
0x56618714 lua_error+0x4194 in lua51.dll+0x28714
0x56631952 luaJIT_profile_stop+0x7142 in lua51.dll+0x41952
0x565F2BB4 in lua51.dll+0x2BB4
0x5661C21F luaJIT_version_2_1_0_beta3+0x3FF in lua51.dll+0x2C21F
0x56631B2A lua_close+0x7A in lua51.dll+0x41B2A
0x56785DF9 in MoonLoader.asi+0xF5DF9
0x56786408 in MoonLoader.asi+0xF6408
0x567C3F15 in MoonLoader.asi+0x133F15
0x050D953E in SAMP.asi+0x2953E
0x75D7635B AddClipboardFormatListener+0x4B in USER32.dll+0x4635B

ASI plugins:
CLEO.asi
crashes.asi
MoonLoader.asi
radarrect.asi
SAMP.asi
SAMPFUNCS.asi
SAMPGraphicRestore.asi
sa_widescreenfix_lite.asi
SilentPatchSA.asi

d3d9.dll: unknown

Cleo:
anticrasher037.cs
ccontrol.cs
limit.cs

Address code: 8B 08 89 0A 8B
Before address code: 14 85 C0 74 0C

Crash module: lua51.dll
Size: 606208
CRC32: C5307085

Stack:
+0000: 0xFFFFD8F0   0x56639325   0x05CA23D0   0xFFFFD8F0
+0010: 0x00000000   0xFFFFFFFF   0x16318CA0   0x02480D58
+0020: 0x567A9825   0x05CA23D0   0xFFFFD8F0   0x00000032
+0030: 0x16318CA0   0x566C0197   0x56699BB0   0x024802CC
+0040: 0x56699BD9   0x05CA2808   0x024801C0   0x00000001
+0050: 0x565F280D   0x024801C0   0x01D5BA58   0x0177DFA8
+0060: 0x55A96F0F   0x01D20000   0x00000000   0x024801C0
+0070: 0x0177DFB4   0x55A7A497   0x0177E04C   0x56614360

SCM Op: 0x685, lDbg: 0 LastRendObj: 19015

Game work: 999 sec

Pos: 997.365173 1850.207275 10.327156

Game Version: US 1.0

Memory: 552 MB

Windows 10
 

Вложения

  • upload_2019-6-19_11-40-22.png
    upload_2019-6-19_11-40-22.png
    38.2 KB · Просмотры: 169

FYP

Известный
Автор темы
Администратор
1,764
5,924
@sanya_firsov в том коде, который ты давал ранее, ничего подозрительного нет. функции SetNextWindowPos и SetNextWindowSize используются во многих скриптах и никто ранее на подобную проблему не жаловался. если краш возникает только с полным кодом, который ты показал сейчас, то проблема, очевидно, именно в нём, но читать я его не буду. в глаза сразу бросается только вызов SetNextWindowSize/Pos перед OpenPopup, мне кажется, эти вызовы должны быть перед BeginPopupModal, если ресайзить всплывающие окна вообще допустимо.

Moon ImGui и mimgui - это разные проекты. что относится к одному, не относится к другому, поэтому даже если это какой-то неведомый баг в Moon ImGui, к mimgui он может не иметь никакого отношения.
 
Последнее редактирование:

RENNY

Известный
14
4
@sanya_firsov в том коде, который ты давал ранее, ничего подозрительного нет. функции SetNextWindowPos и SetNextWindowSize используются во многих скриптах и никто ранее на подобную проблему не жаловался. если краш возникает только с полным кодом, который ты показал сейчас, то проблема, очевидно, именно в нём, но читать я его не буду. в глаза сразу бросается только вызов SetNextWindowSize/Pos перед OpenPopup, мне кажется, эти вызовы должны быть перед BeginPopupModal, если ресайзить всплывающие окна вообще допустимо.

Moon ImGui и mimgui - это разные проекты. что относится к одному, не относится к другому, поэтому даже если это какой-то неведомый баг в Moon ImGui, к mimgui он может не иметь никакого отношения.
Пришлось уехать срочно, не отписался, как решил проблему. Может кому-то понадобится при возникновении похожей ситуации.

Проблема и правда не в SetNextWindowSize/Pos была. Я просто им поставил флаг imgui.Cond.Once и всё.
Проблему тогда решило 2 вещи: это вынос ImBuffer и похожих функций по типу ImVec2, которые вызывались каждый кадр и каким-то образом вызывали краш то ли засорением, то ли каким-то еще несовершенством. Также я imgui.Process убрал из цикла и присваивал true/false вызовом кнопки или при main_state_window.v == false. Всё, после этих двух действий проблема с крашами сошла на нет и всё работает стабильно хоть сутками.

Почему-то циклические обращения к функциям imgui, свойствам или методам её классов вызывают краши. Как это можно решить - не знаю, детище всё-таки твоё.

За Moon ImGui и mimgui извиняюсь, не вникал в различие этих названий. Использовал твой... По логике, это твой Moon ImGuii, наверное))) Но не суть.

По поводу всплывающих окон: я хотел, чтобы SetNextWindowSize/Pos вызывались как можно меньше, как и остальные функции, свойства, методы, если таковые есть. Чисто для какой-никакой оптимизации. Всплывающие применял по ряду функциональных причин, отдельные окна мне таких возможностей не дали.
 
Последнее редактирование:

AnWu

Известный
Всефорумный модератор
4,777
5,400
Пришлось уехать срочно, не отписался, как решил проблему. Может кому-то понадобится при возникновении похожей ситуации.

Проблема и правда не в SetNextWindowSize/Pos была. Я просто им поставил флаг imgui.Cond.Once и всё.
Проблему тогда решило 2 вещи: это вынос ImBuffer и похожих функций по типу ImVec2, которые вызывались каждый кадр и каким-то образом вызывали краш то ли засорением, то ли каким-то еще несовершенством. Также я imgui.Process убрал из цикла и присваивал true/false вызовом кнопки или при main_state_window.v == false. Всё, после этих двух действий проблема с крашами сошла на нет и всё работает стабильно хоть сутками.

Почему-то циклические обращения к функциям imgui, свойствам или методам её классов вызывают краши. Как это можно решить - не знаю, детище всё-таки твоё.

За Moon ImGui и mimgui извиняюсь, не вникал в различие этих названий. Использовал твой... По логике, это твой Moon ImGuii, наверное))) Но не суть.

По поводу всплывающих окон: я хотел, чтобы SetNextWindowSize/Pos вызывались как можно меньше, как и остальные функции, свойства, методы, если таковые есть. Чисто для какой-никакой оптимизации. Всплывающие применял по ряду функциональных причин, отдельные окна мне таких возможностей не дали.
и то и то фипа, разница в том что Moon Imgui устарел по отношению к mimgui. Не знаю что ты там написал, но краши явно из-за неверного использования функций имгуи. Код скинул бы чтоли.

UPD: Краш вызывало пересоздание буффера (ImBuffer) внутри фрейма, функции инициализации нужно выносить за пределы фрейма, например:
Lua:
local buf = imgui.ImBuffer(128)
function imgui.OnDrawFrame()
    -- begin
    imgui.InputText("##1", buf)
    -- end
end

По поводу ImVec2 не верно, его можно использовать внутри фрейма.
 
Последнее редактирование:

RENNY

Известный
14
4
и то и то фипа, разница в том что Moon Imgui устарел по отношению к mimgui. Не знаю что ты там написал, но краши явно из-за неверного использования функций имгуи. Код скинул бы чтоли.

UPD: Краш вызывало пересоздание буффера (ImBuffer) внутри фрейма, функции инициализации нужно выносить за пределы фрейма, например:
Lua:
local buf = imgui.ImBuffer(128)
function imgui.OnDrawFrame()
    -- begin
    imgui.InputText("##1", buf)
    -- end
end

По поводу ImVec2 не верно, его можно использовать внутри фрейма.
код кидал
киньте мне mimgui тогда, коль я старое использую.

imgui.Process решило
вынос ImBuffer решило
ImVec2 сейчас проверю
 

AnWu

Известный
Всефорумный модератор
4,777
5,400
код кидал
киньте мне mimgui тогда, коль я старое использую.

imgui.Process решило
вынос ImBuffer решило
ImVec2 сейчас проверю
он на данный момент доступен только через менеджер зависимостей.
Lua:
require 'libstd.deps' {
    'fyp:mimgui'
}
 

RENNY

Известный
14
4
он на данный момент доступен только через менеджер зависимостей.
Lua:
require 'libstd.deps' {
    'fyp:mimgui'
}
ну, как мне его тогда подгружать другим игрокам
если людям сложно скачать Moon ImgUI или проверить свою версию Moonloader, то тут целый менеджер зависимостей еще надо подгрузить
 

AnWu

Известный
Всефорумный модератор
4,777
5,400
ну, как мне его тогда подгружать другим игрокам
если людям сложно скачать Moon ImgUI или проверить свою версию Moonloader, то тут целый менеджер зависимостей еще надо подгрузить
он и не расчитан на это. официально mimgui еще не в релизе. жди мунлоадер 0.27