Stupid-GUI

shrug228

Активный
Автор темы
212
75
Stupid-GUI(SGUI) | v2


Дисклеймер: Представляю, сколько будет хейта в мою сторону в комментариях) В общем, здесь я немного расскажу про свое творение под названием SGUI. Работает на рендере, огромном количестве костылей и говнокода. Особенность в том, что гемороя из-за моего гениального проектирования будет максимально много. Разработчику предстоит познать все прелести ООП в Lua, в связи с чем советую с ними ознакомиться по этой статье, например. Но сначала дочитайте пост до конца. ;) Кстати, одновременно использовать приватные поля у классов и наследование нельзя(опять же по этой статье если действовать).


Для начала подключим саму библиотеку:
Lua:
require("lib.sgui")
Начнем с самого основного - создадим окно. Для этого достаточно строчки кода для создания окна и еще одной для его отображения:

Lua:
win= Window:new('Window')
while true do
    win:draw()
end
Почему же ничего не произошло? Дело в том, что изначально наше окно закрыто. За отображение окна отвечает поле win.state, в котором нам соответственно нужно поставить значение true. Результат:
E5zQf9q.png
Вообще у всех классов в SGUI довольно большое количество параметров если чуть подразобраться. Но для упрощения работы я проставил каждому дефолтное значение, так что аргументы можно не указывать вообще(или везде вписать nil). Другой вопрос, что тогда не будет даже заголовка окна. Ладно, вернемся к нашим баранам. Я лично предпочитаю использовать заодно вот такой шаблон для команд открытия/закрытия окон. Можете взять себе на вооружение)
Lua:
    sampRegisterChatCommand(string.sub(thisScript().name, 1, string.len(thisScript().name) - 4), function () win.state = not win.state end)
    -- мы берем название скрипта и отрезаем кусок от 1 до 4 до с конца символа. это будет работать, если у вы не скомпилировали файл(не получили .luac)
    -- если вы предварительно задали название скрипта через script_name(), то можно ничего не отрезать и использовать просто thisScript().name
Окно можно стилизовать, как вашей душе угодно. Стиль элемента хранится соответственно в поле obj.style и является таблицей(aka table). В качестве примера ниже разберем стандартный стиль - DEFAULT_STYLE:
Lua:
local DEFAULT_STYLE = {
    bg = 0x99000000, -- фон окна
    top = 0xff000000, -- шапка окна
    color = 0xffc0c0c0, -- фон кнопки
    press = 0xff7b68ee, -- цвет кнопки при нажати и второстепенный цвет некоторых виджетов
    fcolor = 0xffffffff, -- цвет шрифта
    close = 0xffff6347, -- цвет кнопки закрытия
    font = renderCreateFont("Trebuchet MS", 16, font_flag.SHADIW + font_flag.BORDER) -- шрифт
}
Ладно, перейдем к функционалу. Создадим кнопку, это можно сделать несколькими способами.
Lua:
-- 1
btn = Button:new('1') -- создаем кнопку
btn:bind(function () -- задаем функцию, которая сработает при нажатии
    printStringNow('pressed', 1000)
end)
win:tieElement(btn)   -- передаем отрисовщику окна(расположит автоматически)

-- 2
win:tieElement(Button:new('2', nil, nil, 'right')) -- создаем кнопку и передаем отрисовщику окна(параметр 'right' означает, что кнопка будет справа от предыдущего элемента. иначе указывайте nil)
win:getElement(2):bind(function () -- также задаем функцию, которая сработает при нажатии
    printStringNow('pressed', 1000)
end)

-- 3
btn2 = Button:new('3') -- создаем еще одну кнопку
btn2.func = function () -- задаем функцию, но уже не через метод, а напрямую
    printStringNow('pressed', 1000)
end

while true do
    win:draw()
    if win.state then -- проверяем, что окно открыто
        btn2:draw(win.pos.x + win.size.x / 2, win.pos.y + win.size.y / 2) -- эта кнопка не подключена к отрисовщику окна, так что отрисовываем самостоятельно
    end
end
Я лично бы предпочел воспользоваться 1-ым, но тут уже, как хотите. Задачу свою кнопка выполнит в любом случае. Результат всех этих манипуляций:
LI77stJ.png
Ну и на последок взглянем на одну по моему скромному мнению очень удобную штуку.

Lua:
dlg = Dialog:new('Какой-то вопрос.', {'Ответ 1', 'Ответ 2', 'Ответ 3', 'И т.д.'}) -- ответы отображаются в обратном порядке, их количество может быть любым
-- также по умолчанию включен автоперенос текста(Dialog.wrapping). Не нравится - поставьте на false и переносите сами(\n)
dlg.win.state = true -- класс Dialog лишь оболочка, он просто приводит в нужный вам вид окно. само окно - Dialog.win

while true do
    dlg:draw() -- но при этом отрисовка происходит через собственный метод класса Dialog
end
Результат:
1QAB2ka.png


Установка: закинуть sgui.lua в moonloader/lib. Требования: moonloader 0.26. Предназначено для SAMP-а, в одиночке скорее всего работать не будет, но я не проверял.
Если вас заинтересовала эта библиотека - не бойтесь залезть в исходники, там все относительно понятно. И много новых свойств объектов узнаете)
 

Вложения

  • sgui.lua
    13.4 KB · Просмотры: 47
Последнее редактирование:

shrug228

Активный
Автор темы
212
75
чем он лучше, чем отличается, или какие преимущества от imgui/mimgui?
Отличие упомянуто в теме много раз - ООП. Преимуществ нагреб несколько, хотя они немного сомнительные:
1) Шире возможности в плане изменения библиотеки. Не нравится отрисовка кнопки - пожалуйста, меняй, никто не запрещает. Это следствие ООП. ImGui же написан на плюсах, как я знаю, так что и отредактировать отрисовку кнопки, например, не вариант.
2) Проще стилизовать окно. Стиль представляет из себя просто массив(таблицу aka table). Элементы можно располагать, как душе угодно. Да, в imgui тоже есть некоторые возможности, но тут их больше, так как располагаешь все вручную.
3) Скорее всего перейти на эту штуку людям, которые до селе не работали с imgui/mimgui, но имели опыт работы с обычным GUI(Qt, GTK и т.д.) будет проще.
Всё бы ничего, но зачем?
По приколу, если честно. Я вообще не думал, что развивать буду эту штуку после выкладывания. Но лайков накидали - придется продолжать)
 
Последнее редактирование:
  • Bug
Реакции: etereon и kin4stat

kin4stat

mq-team
Всефорумный модератор
2,730
4,710
2) Проще стилизовать окно. Стиль представляет из себя просто массив(таблицу aka table).
Ты не представляешь, в ImGui это структура, которую также легко менять, и причем работает это по принципу стека
Элементы можно располагать, как душе угодно.
Ты не представляешь, но в ImGui тоже
Это следствие ООП.
спс поржал
 
  • Нравится
Реакции: etereon

shrug228

Активный
Автор темы
212
75
Обращайся, я тупой)
Ты не представляешь, в ImGui это структура, которую также легко менять, и причем работает это по принципу стека
Взгляни на стили imgui и на их размеры. Согласись, накидать массив намного проще и гемороя поменьше будет)
Ты не представляешь, но в ImGui тоже
Хочешь ты того или нет, но при ручном расположении по координатам все будет можно расположить интереснее, только нужна фантазия.
 

kin4stat

mq-team
Всефорумный модератор
2,730
4,710
Взгляни на стили imgui и на их размеры.
Ты немного путаешь.
Хочешь ты того или нет, но при ручном расположении по координатам все будет можно расположить интереснее, только нужна фантазия.
Красивые меню на имгуи так и делаются
 

The Spark

Известный
653
671
SetCursorPos()

Я не выкупаю или ты действительно думаешь что m/imgui дубовый и там не где развернуться?
А как же стили, флаги, свой рендер, селекторы, гистограммы и ещё много всего? Глянь imgui demo.
Строить интерфейс всегда удобнее через стек, но и указать абсолютную позицию никто не запрещает. Создаёшь окошко без тайтла и перед тобой открываются огромные возможности рендера gui. Зайди в полезные сниппеты, смотри какую красоту люди делают.
Сейчас sgui не лучше dxut диалогов (там кста тоже все через x y).
 

imring

Ride the Lightning
Всефорумный модератор
2,355
2,516
Lua:
if self.pos ~= {x = self.selfpos.x + parent.pos.x, y = self.selfpos.y + parent.pos.y} then -- 65 строка
эта проверка всегда будет срабатывать т.к. таблицы сравниваются не по их элементам, а скорее всего по адресу
1640692762418.png