Ну если я правильно понял, то холдеры и есть реализация Weak рефов, т.к в паскале до сих пор не подвезли нормальных темплейтов. Насколько легко добавлять новые типы ресурсов для загрузки?
В моем движке из примера выше это делалось в духе Resources.AddLoader<TextureLoader>();
Кстати, заметь что и в юнити и в ue сделано проще чем у тебя. Там нет приоритетов даже для уровней с стримингом(с урылом могу ошибаться, но приоритеты там скорее к лодам) и юнити не thread-safe(по крайней мере раньше был).
Dan написал:
и shared_ptr и weak_ptr на паскале реализуемы. можно паскаль упрекать в других проблемах но не в этих.
А кто упрекает то, и говорит что нельзя?) Без темплейтов это просто будет примерно как в FPC дженерики - надо реально объявлять новые контейнеры самому.
Скидывание файлов мышкой в саму программу -- это игрушка, которую я давно хотел себе сделать, но всё не было повода, а теперь вот появился.
Общая идея состоит в том, чтобы дать механизм докидывания ассетов в уже запущенное приложение без перезапуска. Не знаю действительно ли это будет полезно и удобно использовать без полноценного редактора, надо пробовать в боевых условиях. Но в этой минималистической демке работает потрясно!
Live Editing
У меня в основном движке DEng есть возможность автоматически перезагружать ресурсы, если они поменялись. По умолчанию эта опция отключена, она не нужна в финальных играх, но в x планирую её включить для всех ресурсов.
Это, опять же, позволяет редактировать ресурсы без перезапуска игры. Наиболее интересно выглядит при живом написании шейдеров, когда видишь результат или ошибку молниеносно.
Но чтобы это работало по-настоящему круто, нужна магия...
Наконец-то я начинаю первую фазу битвы с финальным боссом разработки Икса! А именно: автоматическое склеивание шейдеров, юниформов, вершинных аттрибутов, текстур и т.д. в рантайме. Буду иногда называть это "линковкой".
Для тех кто не знает: при написании рендиринга для OpenGL и Vulkan (оох, не спрашивайте про вулкан) код рендеринга почти всегда должен быть согласован с кодом шейдеров, которые будут использованы. Согласованию подлежат: названия вершинных аттрибутов (по кастомному имени, по числу-location'у, либо по предустановленному параметру типа gl_Vertex), их типы; названия юниформов (по кастомному имени, по числу-location'у, по числу-binding'у для текстур, либо опять же по предустановленному названию типа gl_ModelViewMatrix), их типы, а в некоторых случаях и нетривиальный лейаут, вроде размещения юниформов в одной структурке или вулкановский push_constant (не спрашивайте).
При итеративной разработке, когда постепенно разрабатываешь и смотришь что получается, постоянное согласование одного с другим может привести к сильной попаболи. Когда пытаешься поддерживать несколько GAPI (например, OpenGL 2.1, 3.2, 4.6 и Vulkan), эта поддержка может стать невыносимой (кстати, не спрашивайте про Vulkan).
Моя сверхзадача состоит в том, чтобы всю тяжёлую работу по линковке x делал самостоятельно. Пользователю достаточно просто передать данные и как они называются. При этом куча стандартных аттрибутов и юниформов уже будет встроенна по умолчанию: координаты вершин, нормали, текстурные координаты, Projection, View и Model матрицы, Time - текущее время для анимированных эффектов, и т.д. Эти стандартные частоиспользуемые параметры можно просто брать и использовать в шейдере без явного прописывания в коде.
Достигать планирую за счёт вытаскивания из шейдера метаинфы - про юниформы, про аттрибуты, про их лейаут. Благо, в OpenGL есть glGetActive* и glGetProgramInterfaceiv (а у Vulkan'а есть spirv-reflect). Если среди них находим предустановленные, и пользователь движка их не передал, -- устанавливаем сами.
В демке примером такого стандартного параметра является Time. Разберём на его примере как x действует в нескольких сценариях:
1. x нашёл в шейдере Time и получил от пользователя Uniform с ними (через Fluent Context) -- выставляем пользовательские данные
2. x нашёл в шейдере Time и не получил от пользователя Uniform с ними -- выставляем автоматические значения, а именно: таймер в миллисекундах
3. x не нашёл в шейдере Time и получил от пользователя Uniform с ними -- игнорируем
4. x не нашёл в шейдере Time и не получил от пользователя Uniform с ними -- не паримся
Именно качественная линковка и должна обеспечить настоящий Live Editing, а также по-настоящему быструю и простую разработку. Работы здесь ещё много, но план есть.
Вы могли заметить, что в демке можно крутить и скейлить модельку. Это достигается за счёт вызова всего лишь одной функции без параметров xStareCamera.
Её прямое действие состоит в том, что она выставляет специальную камеру для разглядывания, а непрямое -- включает пользовательское управление для вращения и скейлинга. Реализовано это тупо флажком StareEnabled внутри x, который приводит к автоматическому перехвату необходимого управления. Флажок перед каждым Render'ом автоматически сбрасывается, т.е. для поддержания режима нужно постоянно вызывать xStareCamera, а для выхода из режима -- просто перестать вызывать эту функцию.
Идея состоит в том, что можно будет быстро встраивать в игру режим "разглядывать такую-то фигню".
Release vs Debug
У меня при компиляции есть два основных режима сборки: Release и Debug. Основные различия заключаются в том, что в Debug версии отключены оптимизации и включены отладочные символы.
Раньше я разрабатывался в Debug режиме, а перед самим выкладыванием куда-то включал Release. Это приводило к некоторым казусам: иногда я забывал включать Release. А бывало и такое, что Release версия по какой-то причине не работала или работала не так, и дебагать её приходилось отдельно.
Со временем я пришёл к тому, что нужно разрабатывать и тестировать сразу Release версию, и только при необходимости отладить какой-то баг -- включать Debug режим, с тех пор так и делаю.
GUI vs Console
Похожая история с GUI и Console версиями. В винде в EXE'шниках есть поле Subsystem, оно либо IMAGE_SUBSYSTEM_WINDOWS_GUI - для гуи приложения, либо IMAGE_SUBSYSTEM_WINDOWS_CUI - для консольного.
Консольные программы при старте создают терминал (либо подцепляются к консоли родительского процесса, если запущены из терминала), могут писать в stdout и stderr, чем я активно пользуюсь для просмотра лога в реальном времени, это очень удобно.
К сожалению, когда наступает время выкладывать игру куда-то, я зачастую либо забываю пересобрать в GUI режиме, либо она внезапно падает из-за отсутствия stdout...
Я опять пришёл к выводу, что нужно сразу собирать и тестировать сразу GUI версию. И я даже придумал как это сделать, сохранив возможность смотреть лог в реальном времени:
xWrap
xWrap -- это программа-обёртка, через которую я теперь запускаю свои GUIшные игры:
xWrap.exe game.exe
Самое главное, что она делает -- в реальном времени читает log.txt и выводит в stdout.
В качестве приятного бонуса ещё и раскрашивает строки (ошибки подсвечивает красным, например), а в будущем будет делать и другие полезные вещи: подставлять описание ошибок вместо их числового кода (например, для OpenGL или WinApi ошибок, -- это облегчит движок, которому не придётся тащить внутри себя таблицу с расшифровками), вычислять какую-то статистику по таймстемпам в логе и т.д.
Если запускать игру напрямую, терминала создано не будет.
Ещё возможное будущее применение: передавать флажки для дебаг-режимов. Например, включать Vulkan Validation Layer, который при запуске без xWrap активироваться не будет.
Рад, что кто-то ещё пишет велосипеды в это непростое время :)
Я тоже пилю свой движок в качестве хобби. Иногда забиваю на несколько месяцев, потом опять продолжаю. Единственная польза - есть что показать на собеседованиях, да и на текущую работу устроился благодаря хобби движку.
Делать продакшен игру на таком - это чистое превозмогание, так что даже и в мыслях нету :)
я тоже пишу, хоть и просто из привычки. что-то в старом движке не так - надо писать новый. языки программирования развиваются медленнее чем моя фантазия, поэтому приходится писать препроцессоры (по типу unreal engine), чтобы реализовать свои идеи.
У меня движок закрытый по техническим причинам: я традиционно использую свой svn сервер для всех проектов сразу и ничем не ограничиваю себя по мусору, прикидками и нерабочему коду. Вытаскивание из него движковой части на экспорт, тестирование и оформление было бы лишней работой и тратой времени, которое лучше потрачу на то, чтобы доработать движок и начать им пользоваться :)
Планирую выложить исходники снапшотом вместе с ближайшим конкурсом/джемом, в котором буду участвовать (таким джемом должен был стать LD50, но, к сожалению, его вынужден был пропустить).
И я! И я пишу свой велосипед! Не такой крутой, как у вас всех конечно, но зато СВОЙ! Думаю тоже скоро темку создам. Уже даже набросал черновик, но что-то воды там много пока что.