Dear ImGui

Тема в разделе "Lua", создана пользователем FYP, 25 ноя 2017.

Метки:
  1. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    [​IMG]

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

    Представляю вам Moon ImGui - Lua биндинг ImGui для MoonLoader. Он включает все основные возможности фреймворка, а API максимально приближен к оригинальному по мере возможного.
    Тут не будут подробно рассматриваться возможности и особенности ImGui, в этой теме будет рассказано и показано как использовать Moon ImGui в Lua. За информацией по самому ImGui сюда:
    GitHub - ocornut/imgui: Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies(https://github.com/ocornut/imgui)

    Начнём с самого элементарного:
    
    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

    Это работает, но что-то не впечатляет, согласитесь. Окно изначально маленькое, показывается сразу при старте и его нельзя закрыть.
    Сделаем его побольше, добавим активацию и какое-нибудь действие:
    
    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
    
    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: https://blast.hk/threads/19292/page-3#post-168990
    ImGui Pie: https://blast.hk/threads/19648/page-3#post-226145
    Внутриигровая песочница: https://blast.hk/threads/19292/page-19#post-219453
    ImGui Custom (хоткеи и ещё чет): https://blast.hk/threads/22080/
    Global notification: https://blast.hk/threads/21619/
    Стили:
    https://blast.hk/threads/19292/page-28#post-260462

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

    Вложения:

    #1 FYP, 25 ноя 2017
    Последнее редактирование: 9 окт 2018
    k0$$0lapiy, c.h.e.a.t.e.r, social enemy и 41 другим нравится это.
  2. Dark_Knight

    Dark_Knight Режим чтения

    Регистрация:
    18 мар 2013
    Сообщения:
    3.358
    Симпатии:
    1.688
    Год сижу на ИмГуи и скажу, что пока(ключ. слово "пока") не видел)
     
  3. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    позже сделаю ещё несколько нормальных примеров, а пока вот вам бесплатные идеи где его можно применить:
    для сампа
    • scoreboard
    • браузер серверов
    • биндер
    • патчер пакетов и не только (нопы)
    • замена интерфейса (диалогов, чата)
    • замена неймтегов
    для обоих
    • менеджер скриптов
    • редактор скриптов
    • консоль
    • тюнинг машин
    • хак на оружие
    • редактор параметров оружия
    • редактор параметров транспорта
    • редактор параметров погоды
    для сингла
    • спавнер транспорта
    • простой редактор карты, спавнер объектов, персонажей
    • редактор миссий (как DYOM)
    некоторые из них примитивные, многие уже реализованы, но для практики годятся и, к тому же, вы только представьте насколько пизже можно сделать каждую из них с использованием ImGui.
     
    #kerosin, _=Gigant=_, kraft1k и ещё 1-му нравится это.
  4. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    что не видел?
     
    -PALAMAL- нравится это.
  5. Dark_Knight

    Dark_Knight Режим чтения

    Регистрация:
    18 мар 2013
    Сообщения:
    3.358
    Симпатии:
    1.688
    Гуи. Забыл дописать.
     
  6. D3.Pheonix

    D3.Pheonix Всефорумный нагибатор
    Проверенный

    Регистрация:
    21 мар 2013
    Сообщения:
    1.243
    Симпатии:
    620
    Красивый интерфейс)
    Хотя бы кастомный ТАб увидеть
     
  7. DarkP1xel

    BH Team

    Регистрация:
    17 июн 2013
    Сообщения:
    3.048
    Симпатии:
    3.410
    Хотел для CLEO такое сделать, но теперь вообще смысл потерял. Пропёр ты свой Lua :pidrila:.
     
    Cherepaxa leonardo, surfer, Mike Rockwell и 5 другим нравится это.
  8. ATTACKER™

    Проверенный

    Регистрация:
    15 окт 2016
    Сообщения:
    1.049
    Симпатии:
    460
    deStrange нравится это.
  9. D3.Pheonix

    D3.Pheonix Всефорумный нагибатор
    Проверенный

    Регистрация:
    21 мар 2013
    Сообщения:
    1.243
    Симпатии:
    620
    Dugger нравится это.
  10. uryukhai

    uryukhai Интересующийся

    Регистрация:
    1 июл 2017
    Сообщения:
    193
    Симпатии:
    70
    сцука, при открытии съедает 10-20 фпс, а иногда 50 даже
     
  11. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    при открытии или пока открыто?
     
  12. mrdiimax

    mrdiimax Свой человек

    Регистрация:
    24 янв 2016
    Сообщения:
    348
    Симпатии:
    43
    На какую кнопку активируется диалог который во вложениях?
     
  13. randazzo

    randazzo не админ какой-то
    Всефорумный модератор

    Регистрация:
    21 май 2014
    Сообщения:
    1.242
    Симпатии:
    726
    на X
     
  14. DonHomka

    Друг

    Регистрация:
    8 ноя 2017
    Сообщения:
    2.343
    Симпатии:
    1.454
    Текст удаляется из инпутбокса ток на Delete, как исправить? BackSpace one love.
     
  15. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    у меня всё ок
     
  16. DonHomka

    Друг

    Регистрация:
    8 ноя 2017
    Сообщения:
    2.343
    Симпатии:
    1.454
    а ну да. Оказывается если AHK блокирует клавишу, imGui не видит её. Касается почему-то именно BackSpace.
    AHK:
    $*BackSpace::SendInput {BackSpace}
    Как правильно убить стрелочку в шапке окна? Туплю дико.

    
        IMGUI_API void          SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0);      // set named window position.
        IMGUI_API void          SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0);    // set named window size. set axis to 0.0f to force an auto-fit on this axis.
        IMGUI_API void          SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0);   // set named window collapsed state
        IMGUI_API void          SetWindowFocus(const char* name);                                           // set named window to be focused / front-most. use NULL to remove focus.
    
    А это как использовать, имя из imGui.Begin? а если 2 окна одинаковых.
     
    #16 DonHomka, 26 ноя 2017
    Последнее редактирование модератором: 26 ноя 2017
  17. inf

    inf Постоянный участник

    Регистрация:
    23 июн 2014
    Сообщения:
    77
    Симпатии:
    94
    первый пример работает нормально, а дальше не очень
    [​IMG]
    [​IMG]
    [​IMG]
    то же самое
     
  18. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    да
    коротко: в название можно добавить ##vasha_huinya, эту строку в названии видно не будет, но её идентификатор будет уникальным
    флаг WindowFlags.NoCollapse
     
    DonHomka нравится это.
  19. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    уже разбираюсь с этим
     
  20. DonHomka

    Друг

    Регистрация:
    8 ноя 2017
    Сообщения:
    2.343
    Симпатии:
    1.454
    Возможно ли сделать так чтобы ники не исчезали при активном курсоре?
    Еще есть проблемы с двойным кликом, кликнул надо раз 20 чтобы скрыть или показать окно.
     
  21. Dark_Knight

    Dark_Knight Режим чтения

    Регистрация:
    18 мар 2013
    Сообщения:
    3.358
    Симпатии:
    1.688
    Нет такого в ImGUI. Ищи проблемы в своих плагинах/скриптах/пидороАХКскриптах
     
  22. DonHomka

    Друг

    Регистрация:
    8 ноя 2017
    Сообщения:
    2.343
    Симпатии:
    1.454
    Из АХК ток биндер, отключил, не помогло. Среди скриптов нигде нет работы с курсором.
    ПС: Ники скрываются ток при открытии демо-окна. Которое на X.
     
  23. ufdhbi

    ufdhbi уфдхби
    Проверенный

    Регистрация:
    3 фев 2015
    Сообщения:
    791
    Симпатии:
    312
    У меня так же, надо много раз кликнуть
     
  24. #kerosin

    #kerosin канистра керосина
    Проверенный

    Регистрация:
    10 апр 2017
    Сообщения:
    194
    Симпатии:
    124
    Где взять код этого скрипта?
    0.png
     
  25. inf

    inf Постоянный участник

    Регистрация:
    23 июн 2014
    Сообщения:
    77
    Симпатии:
    94
  26. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    они не исчезают
    @A1K8M4
    imgui.GetIO().MouseDoubleClickTime = 0.8
     
  27. ufdhbi

    ufdhbi уфдхби
    Проверенный

    Регистрация:
    3 фев 2015
    Сообщения:
    791
    Симпатии:
    312
        inp1 = u8"Hello"
        imgui.PushItemWidth(80)
        imgui.InputText(u8'<- Сюда кнопку для /tazer', inp1)
        imgui.PopItemWidth()
    Зависает игра с таким кодом, перед рендером стоит: local inp1 = imgui.ImBuffer(256)
    Как задать начальный текст в Input`e?
     
  28. Alfinity

    Alfinity Постоянный участник

    Регистрация:
    13 сен 2015
    Сообщения:
    90
    Симпатии:
    51
  29. Zodiak1337

    Zodiak1337 Участник

    Регистрация:
    19 мар 2017
    Сообщения:
    19
    Симпатии:
    2
    Обычно использую ImGui на С++. К примеру, для читов на CS. Будет неплохо поработать и в ImGui для GTA:SA.
     
  30. mirapi

    mirapi Постоянный участник

    Регистрация:
    24 июл 2017
    Сообщения:
    51
    Симпатии:
    3
    Поставил пример, выходит ошибка:
    [ML] (error) D:\San Andreas Multiplayer\moonloader\lib\imgui.lua:6: module 'windows.message' not found:
    Где взять недостающий модуль и куда запихнуть? )
     
  31. ufdhbi

    ufdhbi уфдхби
    Проверенный

    Регистрация:
    3 фев 2015
    Сообщения:
    791
    Симпатии:
    312
    Windows 7?
     
  32. Revalto

    Revalto Свой человек

    Регистрация:
    13 фев 2016
    Сообщения:
    442
    Симпатии:
    122
    Dark Knight его уже давно использует в сампе (SAMPFUNCS API)
     
  33. FYP

    FYP
    not-set

    Регистрация:
    9 мар 2013
    Сообщения:
    1.656
    Симпатии:
    4.486
    установить moonloader v.025
     
  34. DonHomka

    Друг

    Регистрация:
    8 ноя 2017
    Сообщения:
    2.343
    Симпатии:
    1.454
    Куда это определить? В main()? И как задать стилистику окна. Padding например.
    Нашел стилистику. А вот куда даблклик вписать не допер.
     
    #34 DonHomka, 27 ноя 2017
    Последнее редактирование: 27 ноя 2017
  35. ufdhbi

    ufdhbi уфдхби
    Проверенный

    Регистрация:
    3 фев 2015
    Сообщения:
    791
    Симпатии:
    312
    function imgui.OnDrawFrame()
        imgui.SwitchContext()
        local style = imgui.GetStyle()
        local colors = style.Colors
        local clr = imgui.Col
        local ImVec4 = imgui.ImVec4
        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)
        imgui.LockPlayer = true
        imgui.SetNextWindowSize(imgui.ImVec2(280, 200))
        imgui.SetNextWindowPos(imgui.ImVec2(650, 300))
        imgui.Begin(u8'Windows', main_window_state, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize)
    
        imgui.End()
    end