☝️ Используйте HTML вместо VGUI для интерфейсов

Использование DHTML в Garry’s Mod

Введение
Давно меня интересовал вопрос: зачем нам дали такой инструмент, как DHTML? Разве его можно применять только для серверных синем? Возможно, он способен принести ещё больше пользы для разработчиков.


Что такое DHTML?

DHTML в контексте Garry’s Mod — это аналог DPanel, но с возможностью рендеринга HTML-страниц. Его ключевые особенности:

  • Загрузка HTML: Можно отображать страницу как по ссылке, так и из локального файла.
  • Поддержка прозрачного фона: Хотя зачастую фон закрашивают, прозрачность может оказаться весьма полезной.

На практике DHTML чаще всего используется в меню Garry’s Mod. Например, всё меню ESC создаётся с его помощью, рендеря HTML-страницу из файла, расположенного в папке html в корневой директории игры. Существуют модификации, создающие альтернативные интерфейсы — от копий меню S&Box и CSGO до вариантов в стиле neon wave. Это показывает, что DHTML — универсальный инструмент, позволяющий не только создавать меню, но и реализовывать другие визуальные элементы на серверах и в игровых режимах.


Пример: HUD на базе Chromium

В качестве эксперимента я решил создать HUD, используя ветку Chromium (аналогичные возможности имеются и в Awesomium, но я выбрал более современную и мощную технологию). Итоговый результат выглядит следующим образом:


Особенности реализации:

  • HTML как основа: Весь HUD работает на HTML, включая обработку кликов и других пользовательских событий.
  • Взаимодействие Lua и JS: Lua отвечает за вызов необходимых JavaScript-функций, так как стандартный JS не имеет доступа к данным на стороне Lua.
  • Многопоточность: Рендеринг разделён на два потока — игровой и браузерный. Это позволяет существенно снизить нагрузку на FPS, даже если рендер HTML-элементов работает с небольшой задержкой.


Преимущества DHTML по сравнению с HudPaint

Использование DHTML вместо отрисовки интерфейса средствами Lua (например, через HudPaint) предлагает ряд преимуществ:

  1. Работа с CSS: Забудьте о необходимости использовать сторонние библиотеки для отрисовки арок, кругов, теней и прочего — всё это можно настроить с помощью CSS.
  2. Многопоточность: Разделение рендеринга на два потока помогает поддерживать стабильный FPS.
  3. Перенос вычислений на JavaScript: Многие расчёты можно выполнять в JS, который зачастую работает быстрее Lua (зависит от используемого API, например, Awesomium).
  4. Интеграция с современными фреймворками: Возможность использования таких инструментов, как React, Svelte и других, позволяет создавать ещё более гибкий и масштабируемый интерфейс.

( Худ на Svelte ):


Почему DHTML используется не так часто?

На данный момент точных причин может быть несколько:

  • Нестабильность на начальном этапе внедрения: Многие реализации HUD на DHTML сталкивались с проблемами стабильности (Сейчас проблем что на Chromium что на Awesomium не встречал, хотя делал довольно нагруженные интерфейсы)
  • Ограниченное количество примеров: Хотя я встречал удачные примеры работы HUD на DHTML, достоверных доказательств их надёжности пока немного.

Если у вас есть успешные кейсы или пруфы, буду рад увидеть их в комментариях.


Организация обмена данными между Lua и JavaScript

Самый простой способ установить связь между Lua и JS — это вызывать соответствующие JavaScript-функции для обновления переменных. Я разработал модуль-мост, который:

  • Позволяет слушать хуки внутри JS без дополнительного Lua-кода.
  • Отслеживает изменения переменных (аналог функции watch в реактивных фреймворках).

На данный момент модуль ещё дорабатывается, и я планирую улучшить его, сделав взаимодействие ещё удобнее на стороне JavaScript.


Передача HTML-кода пользователю

Существует несколько подходов для передачи HTML:

  • Инлайн-HTML в Lua: Можно встроить HTML-код непосредственно в скрипты на Lua.
  • Передача через data-файлы: HTML можно отправлять с сервера, что позволяет создавать разные версии HUD для различных групп пользователей.

Заключение

Использование DHTML в Garry’s Mod открывает широкие возможности для создания сложных и производительных интерфейсов. Благодаря разделению рендеринга, перераспределению вычислений в сторону JavaScript и гибкости современных веб-технологий, вы сможете создавать HUD и другие визуальные элементы, сравнимые по качеству с аналогами из FiveM, MTA и других игр.

Попробуйте интегрировать DHTML в свои проекты — возможно, он станет тем инструментом, который позволит реализовать самые смелые идеи!

a yellow cartoon character is sitting at a desk in front of a computer .


Warning
Это тестовый пост по данной теме, планирую её развивать и делать много поправок, если есть замечания пишите.

*кратко затрагивал эту тему тут: Новый оптимизированный HUD для DarkRP (Модеры не бейте)

4 лайка

Не бейте лучше обоссыте✈️

Переименовал

  • :point_up: Учимся рисовать HUD “По правильному”
  • :point_up: Используйте HTML вместо VGUI для интерфейсов
1 лайк

Приветствую, наткнулся на ваш пост уже будучи погружённым в тему html-HUD-а.
Я хотел бы узнать, вы делали на таком HUD какие-либо динамически меняющиеся элементы? Например, таймеры раундов/событий или постепенно убывающие полосы здоровья/выносливости/брони и прочего?

Например, у меня есть полоса выносливости, и я всё ломаю голову, как мне её динамически менять? Подход через Think или HUDPaint — слишком ресурсозатратный, а поэтому использую таймеры, но тогда хромает плавность.
Может, я глупый и не вижу очевидных способов?
Буду благодарен, если поможете. Спасибо.

Посмотри в сторону RunJS, к примеру можешь назначить своей полоске условный width, а далее просто получи эту полоску по #id и задай параметры стиля
document.getElementById("myHealthBar").style.width = "300px";

А по поводу обновления, тут увы, нужно использовать таймеры просто тебе дополнительно нужно запоминать предыдущее значение и если оно поменялось то выполнять RunJS

Хорошо, благодарю. А вы не знаете, что будет более оптимизировано: RunJS или Call ?

А так же я так и не понял, а как вы указываете какой рендер использовать: Chromium или Awesomium. Я вроде ничего такого не указывал и у меня работает, но тогда на какой работает?

Chromium x64(Бетка) ветка Gmod
Awesomium x32 Стандартный Gmod

Почитай тут, можно вытянуть версию игры

Хорошо, спасибо.

С июня 25 года awesomium больше не существует.
Chromium ветку замёрджили в main, сейчас CEF 86 используется на всех бранчах.

Так же в ближайшее время планируется перешагнуть крупный milestone “vphysics issues”, а так же ожидается обновление CEF до 137+ (жизненно необходимо для полноценной поддержки Linux & MacOS).

Плюс мы наконец получили шейдеры, в общем рубат в последний год оч много годноты сделал!

Алсо CEF 86 на main ещё и дал доступ к WASM,
Так что теперь можно писать код например на Rust, C++ и тд.
Вот например GIF decoder & animated VTF encoder написанный на Rust GitHub - WilliamVenner/gmod-animated-avatars: 🖼️ Drop-in Steam animated avatars for Garry's Mod

Касаемо сабжа:

WebUI это стандарт во многих игрушках:

Например FiveM, RedM, BeamNG, Rust, MS Flight Simulator, The Sims 4 и тд - используют полноценный CEF.

А вот s&box, CS2, Dota 2, War Thunder, World of Tanks, Star Citizen, EVE Online - используют HTML подобный DSL (собственный ui движок который просто копирует подходы из полноценных браузерных движков)

У полноценного CEF есть как и плюсы так и минусы.

Из минусов могу выделить:

  1. CEF это жир, он большой

  2. Input Lag и IPC + сериализация тудой сюдой (для вещей где требуется идеальная плавность CEF не лучший выбор, но большинству кейсов это и не требуется)

  3. Отдельный апдейт луп (хотя момент спорный, иногда это плюс а иногда это минус)

  4. В гмодике CEF тротлит, например FPS около 40 (что для худов не идеально, но для менюшек этого с большим запасом) - в большинстве кейсов я даже наобарот тротрлю UI до 15-25 фпс, например ui мани притнеров.

Но плюсы перевешивают всё!

  1. DX у web это эталон, любые интерфейсы реализуются быстро и комфортно.

  2. Возможностей и ассетов миллион, в распоряжении фреймворки (svelte, vue, react etc), миллиарды npm пакетов, кучу фичей css/js и тд.
    Что бы сделать vgui интерфейс сравнимый по качеству с webui потребуется в 100 раз больше времени и усилий, абсолютно всё нужно писать с нуля и очень долго оптимизировать.

  3. Апдейт луп, поток и процесс отдельные - это киллер фича во многих кейсах.

  4. WASM, пишем C++ код для клиентсайда.

Я по мимо гмодика ещё в FiveM вещи делаю, а там весь UI это CEF.
Вот в качестве демонстрации какие крутые штуки можно сделать на webui:

Под капотом Svelte, D3, Font Awesome & NumberFlow.
По времени ушло пару дней, в гмодике я только NumberFlow библиотеку писал часов 5 - а на такой hud ушло бы пару недель.

Вот ещё прикольчик, сделал за день/два.
В гмодике подобное можно было делать и раньше - но совсем другого качества и DX был ужасен.
Для справки, awesomium (это CEF 18) был огромной жопа болью, без возможностей, с кучей проблем и ужасным DX.

А вот такое сделать на vgui слабо?
Устанете с математикой и рендером мучаться :joy:

Окей, с возможностями и юзабилити разобрались - webui идеален для большинства интерфейсов, DX и возможности на 100 голов выше.

Теперь перейдем реальным кейсам, реализованным для проекта Monolith (возможно самый известный в гмоде рп проект, в своё время были EU, RU, FR сервера и несколько франчайзи)

  1. Тимлид сделал HUD на Svelte (к сожалению скринов из игры у меня не сохранилось - по этому могу показать только скрин дизайна).

  2. Я сделал Delivery System типо Ozon/Amazon, UX/UI это мобильное приложение реализованное на Svelte.
    Маркетплейс где игроки могут заказывать товары, а курьеры выполнять заказы.

Я делал именно приложение и систему вокруг него, сам monophone это пожилой аддон.
В видео кстати старая версия худа, webui hud замёрджили в staging ветку после того как я закончил работу над Delivery System.

  1. Есть ещё кейс Escape Menu, я делал его сразу после мерджа CEF 86 на main.
    Но там была цель протестировать CEF и сделать фреймворк для удобного DX.
    Сам UI ни какой ценности не представляет, я просто взял старый дизайн который будет не долго реализовывать и погнал тестить.
    По этому скринов не осталось, могу показать только скрин дизайна и сказать что на разработку vgui имплементации этого ui 3 года назад было потрачено полтора дня, а с CEF ушло всего 40 минут.

P.S. если кто ещё шейдеры не тыкал но желание имеет - делайте смело, у меня всего полтора дня ушло что бы полностью разобраться в сабже и сделать пару тройку шейдеров (с нуля, ранее не работал с таким).

1

2 лайка

Вау, спасибо за пост!


Я начал разработку HTML UI еще за долго до релиза в основную ветку, в целом по скольку камюнити у меня было закрытое, то все знали что для игры необходимо было использовать другую ветку игры.

По стабильности я бы наверное пока не использовал react подобные фейрмворки ибо бывают просадки fps рендера html фрейма.

При использовании чистого html css + vite, все работало просто шикарно!
Правда я так и не добрался до рефактора своей либы по связке glua + js (надеюсь руки дойдут и я релизну)

Из текущих проблем:

  • Рефактор системы прокидывания рендера из игры в canvas
  • Поддержка backdrop фильтров
2 лайка

пробуй svelte/solid - реакт это прошлый век, я бы даже сказал JQuery из 2020 XD
vdom как идея мертва, по перфу и размеру бандла разница в разы, чуть ли не в десятки раз.

кстати мой nui inspired bridge поддерживает рендер vgui внутри веб компонентов, вот например камера встроенная в приложение для курьеров это vgui

пысы присоседятся в сообщество https://discord.gmod.one/
мы там обсуждаем всякое - гмодик, вебдев, дизайн и тд.

Я занимаюсь редером моделей внутри веба, по крайней мере почти доделал

А у тебя судя по всему это rt материал?

пысы: Ну если можно и то в моё тоже)

проще бро) что бы передать rt нужен capture, сериализация и ipc - юзлесс прожорливый оверхед.
ты же 2д канвас рендеришь, дык и делай оверлей.
просто нужно сделать компонент который автоматом следит за node size/viewport-pos, z-stacking и тд, а так же контролирует лайф цикл луа компонентов.
компонент = точка входа, он сам всё инстанцирует и контролирует.