feature: export Runtime to Distribution#27
Conversation
- For compilation, will use Lux-Runtime to Run and distribute games - Added File > Export Runtime... in the editor - Added swapchain-target framebuffer support for runtime final output - Deleted the root Sandbox project. - Cleaned lingering repo references: Linux build no longer tries to build removed Sandbox, README now mentions Lux-Runtime. - Added script shutdown guards so early runtime startup failures do not crash during app teardown.
- use the same technique as the font, texture, mesh and envmap to get a startup scene - also correctly gets the exe from the - switch to single threaded to start up the window (Temp)
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Pull request overview
Adds a “Runtime Export” pipeline to package a project into a distributable runtime build, alongside a new Lux-Runtime executable and supporting runtime project/asset serialization changes.
Changes:
- Editor: new “Export Runtime…” workflow that builds an asset pack, writes a
Project.luxruntime, and copies runtime/resources into an export directory. - Core: adds runtime project loading (
Project::LoadRuntime) and runtime project serialization (SerializeRuntime/DeserializeRuntime). - Runtime: introduces the
Lux-Runtimeapp that loads an exported project + asset pack and presents via a swapchain-target framebuffer.
Reviewed changes
Copilot reviewed 89 out of 151 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| premake5.lua | Adds Lux-Runtime to the workspace under a new “Runtime” group. |
| scripts/Linux-Build.sh | Removes Sandbox build steps from the Linux build script. |
| README.md | Updates setup/docs to include Lux-Runtime project generation. |
| .gitignore | Ignores runtime pack artifacts (e.g., *.lap). |
| Editor/Source/EditorLayer.h | Declares the new ExportRuntime() entry point. |
| Editor/Source/EditorLayer.cpp | Implements export helpers + the runtime export workflow and menu integration. |
| Editor/Source/LuxEditorApp.cpp | Renames the Editor app name string to “Lux Editor”. |
| Editor/SandboxProject/Sandbox.luxproj | Updates default project configuration/settings used by the sample project. |
| Editor/SandboxProject/Assets/Scenes/NewSceneSystem.luxscene | Updates the sample project’s scene configuration/content. |
| Core/Source/Lux/Project/Project.h | Adds runtime-loading API surface (LoadRuntime) and related runtime activation hooks. |
| Core/Source/Lux/Project/Project.cpp | Implements Project::LoadRuntime and updates runtime activation behavior. |
| Core/Source/Lux/Project/ProjectSerializer.h | Exposes runtime project serialization/deserialization API. |
| Core/Source/Lux/Project/ProjectSerializer.cpp | Implements runtime project binary format and YAML overrides. |
| Core/Source/Lux/Renderer/Framebuffer.h | Adjusts framebuffer API to support swapchain-target framebuffers. |
| Core/Source/Lux/Renderer/Framebuffer.cpp | Implements swapchain-target handle/size behavior used by the runtime presentation path. |
| Core/Source/Lux/Scripting/ScriptEngine.h | Declares updated shutdown helpers for Mono lifecycle. |
| Core/Source/Lux/Scripting/ScriptEngine.cpp | Adds safety guards in shutdown paths (null checks for Mono/domain state). |
| Lux-Runtime/premake5.lua | Defines the new runtime target (platform filters, postbuild deps, etc.). |
| Lux-Runtime/Lux-Runtime.rc | Adds Windows resources for the runtime application (icon/version resources). |
| Lux-Runtime/resource.h | Declares Windows resource IDs for the runtime application. |
| Lux-Runtime/src/RuntimeApplication.cpp | Adds runtime app entry point + CLI parsing (-C, --project). |
| Lux-Runtime/src/RuntimeLayer.h | Declares runtime layer responsible for loading and presenting an exported project. |
| Lux-Runtime/src/RuntimeLayer.cpp | Implements runtime project resolution, load, scene start, overlay, and swapchain submission. |
| Sandbox/Source/SandboxApp.cpp | Removes legacy Sandbox application entry point (deleted). |
| Sandbox/Source/Sandbox2D.h | Removes legacy Sandbox layer header (deleted). |
| Sandbox/Resources/Shaders/Wireframe.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/Wireframe_Anim.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/TexturePass.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/SpotShadowMap.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/SpotShadowMap_Anim.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/Skybox.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/shader.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/SelectedGeometry.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/SelectedGeometry_Anim.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/Renderer2D.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/Renderer2D_Text.glsl | Removes legacy Sandbox shader (deleted). |
| Sandbox/Resources/Shaders/Renderer2D_Line.glsl | Removes legacy Sandbox shader (deleted). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| project->m_ProjectFilePath = path.lexically_normal(); | ||
| project->m_ProjectDirectory = path.parent_path(); | ||
| project->m_Config.ProjectDirectory = project->m_ProjectDirectory; | ||
| project->m_Config.ProjectFileName = project->m_ProjectFilePath.filename().string(); |
| const std::filesystem::path scriptModule = Project::GetActiveScriptModuleFilePath(); | ||
| if (std::filesystem::exists(scriptModule, ec)) | ||
| CopyFileIfExists(scriptModule, exportAssets / project->GetConfig().ScriptModulePath); |
| return; | ||
| } | ||
|
|
||
| CopyFileIfExists(Project::GetActiveAssetDirectory() / s_RuntimeAssetPackFile, exportAssets / s_RuntimeAssetPackFile, true); |
| const std::string buildName = SanitizeBuildName(project->GetConfig().Name); | ||
| const std::filesystem::path exportRoot = selectedFolder / (buildName + "-Windows-x86_64"); | ||
| const std::filesystem::path exportAssets = exportRoot / "Assets"; |
| for (const auto& entry : std::filesystem::recursive_directory_iterator(source, ec)) | ||
| { | ||
| if (ec) | ||
| break; | ||
|
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Core/Source/Lux/Project/Project.cpp`:
- Around line 69-70: The early return when s_ActiveProject is null in
Project::SetActiveRuntime skips the cleanup that should uninitialize the audio
engine; remove the early return (or move the cleanup block above it) so the
audio shutdown logic always runs when SetActiveRuntime(nullptr, nullptr) is
called, and explicitly invoke the audio cleanup/uninitialize routine used by the
project (the audio shutdown function your project normally calls during project
teardown) as part of the same cleanup sequence to ensure the audio engine is
always shut down even if s_ActiveProject is nullptr.
In `@Core/Source/Lux/Renderer/Framebuffer.cpp`:
- Around line 64-68: Add a guard when handling m_Specification.SwapChainTarget
in the Framebuffer constructor so we don't early-return with zero attachments:
before the "if (m_Specification.SwapChainTarget) { PopulateClearValues(...);
return; }" check, validate that m_Specification.Attachments is not empty (or
assert/log+return) and fail-fast if it is, ensuring PopulateClearValues is only
called when there are attachments and preventing m_ClearValues from remaining
empty; reference m_Specification.SwapChainTarget, m_Specification.Attachments,
PopulateClearValues, and m_ClearValues.
In `@Core/Source/Lux/Scripting/ScriptEngine.cpp`:
- Around line 239-248: The shutdown sequence must stop and reset the
AppAssemblyFileWatcher before tearing down s_Data/AppDomain to avoid races;
update the code in ScriptEngine (around mono_domain_unload and s_Data handling)
to stop/unregister the AppAssemblyFileWatcher and set it to nullptr before
calling mono_domain_unload and clearing s_Data, and also update the
OnAppAssemblyFileSystemEvent callback/lambdas to defensively check s_Data and
s_Data->RootDomain (or capture weak state) before dereferencing; ensure
AppAssemblyFileWatcher::Stop/Unregister is invoked prior to mono_domain_unload
and that any remaining callbacks bail out if s_Data is null.
In `@Lux-Runtime/premake5.lua`:
- Around line 47-48: The call to os.outputof("pkg-config --libs gtk+-3.0") is
executed unconditionally during script load; wrap that call in a host check so
it only runs on Linux: use a local variable (e.g. local result, err) and call
os.outputof only when os.host() == "linux", then validate result and error out
or raise a clear message if the output is empty/invalid; remove the redundant
inner filter "system:linux" around the exec and keep the Premake filter
"system:linux" only for applying linkoptions { result } so linkoptions is set
only on Linux when result is present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 71882a7f-1c2c-45bf-b259-1b7db5f7c0b2
⛔ Files ignored due to path filters (107)
Lux-Runtime/Lux-Runtime.icois excluded by!**/*.icoSandbox/Resources/Fonts/FontAwesome/fontawesome-webfont.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Black.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-BlackItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Bold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-BoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Italic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Light.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-LightItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Medium.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-MediumItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Regular.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-SemiMedium.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-Thin.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/Roboto/Roboto-ThinItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/SourceCodePro-Italic-VariableFont_wght.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/SourceCodePro-VariableFont_wght.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Black.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-BlackItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Bold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-BoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-ExtraBold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-ExtraBoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-ExtraLight.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-ExtraLightItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Italic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Light.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-LightItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Medium.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-MediumItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-Regular.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-SemiBold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/SourceCodePro/static/SourceCodePro-SemiBoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-Bold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-BoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-ExtraBold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-ExtraBoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-Italic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-Light.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-LightItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-Regular.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-SemiBold.ttfis excluded by!**/*.ttfSandbox/Resources/Fonts/opensans/OpenSans-SemiBoldItalic.ttfis excluded by!**/*.ttfSandbox/Resources/Renderer/BRDF_LUT.pngis excluded by!**/*.pngSandbox/Resources/Shaders/DirShadowMap.glslis excluded by!**/*.glslSandbox/Resources/Shaders/DirShadowMap_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/EnvironmentIrradiance.glslis excluded by!**/*.glslSandbox/Resources/Shaders/EnvironmentMipFilter.glslis excluded by!**/*.glslSandbox/Resources/Shaders/EquirectangularToCubeMap.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Grid.glslis excluded by!**/*.glslSandbox/Resources/Shaders/HZB.glslis excluded by!**/*.glslSandbox/Resources/Shaders/HazelPBR_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/HazelPBR_Static.glslis excluded by!**/*.glslSandbox/Resources/Shaders/HazelPBR_Transparent.glslis excluded by!**/*.glslSandbox/Resources/Shaders/ImGui.glslis excluded by!**/*.glslSandbox/Resources/Shaders/ImGui.hlslis excluded by!**/*.hlslSandbox/Resources/Shaders/JumpFlood_Composite.glslis excluded by!**/*.glslSandbox/Resources/Shaders/JumpFlood_Init.glslis excluded by!**/*.glslSandbox/Resources/Shaders/JumpFlood_Pass.glslis excluded by!**/*.glslSandbox/Resources/Shaders/LightCulling.glslis excluded by!**/*.glslSandbox/Resources/Shaders/LinearSample.glslis excluded by!**/*.glslSandbox/Resources/Shaders/LinearSampleUInt.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/AO-Composite.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/Bloom.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/DOF.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/EdgeDetection.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/GTAO-Denoise.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/GTAO.hlslis excluded by!**/*.hlslSandbox/Resources/Shaders/PostProcessing/Pre-Convolution.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/SSR-Composite.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/SSR.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PostProcessing/SceneComposite.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Pre-Integration.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PreDepth.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PreDepth_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/PreethamSky.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Renderer2D.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Renderer2D_Circle.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Renderer2D_Line.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Renderer2D_Text.glslis excluded by!**/*.glslSandbox/Resources/Shaders/SelectedGeometry.glslis excluded by!**/*.glslSandbox/Resources/Shaders/SelectedGeometry_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Skybox.glslis excluded by!**/*.glslSandbox/Resources/Shaders/SpotShadowMap.glslis excluded by!**/*.glslSandbox/Resources/Shaders/SpotShadowMap_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/TexturePass.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Wireframe.glslis excluded by!**/*.glslSandbox/Resources/Shaders/Wireframe_Anim.glslis excluded by!**/*.glslSandbox/Resources/Shaders/shader.glslis excluded by!**/*.glslSandbox/Resources/Textures/ErrorTexture.pngis excluded by!**/*.pngSandbox/assets/fonts/opensans/OpenSans-Bold.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-BoldItalic.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-ExtraBold.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-ExtraBoldItalic.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-Italic.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-Light.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-LightItalic.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-Medium.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-MediumItalic.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-Regular.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-SemiBold.ttfis excluded by!**/*.ttfSandbox/assets/fonts/opensans/OpenSans-SemiBoldItalic.ttfis excluded by!**/*.ttfSandbox/assets/game/textures/RPGpack_sheet_2X.pngis excluded by!**/*.pngSandbox/assets/shaders/FlatColor.glslis excluded by!**/*.glslSandbox/assets/shaders/Texture.glslis excluded by!**/*.glslSandbox/assets/textures/Checkerboard.pngis excluded by!**/*.pngSandbox/assets/textures/luxLogo.pngis excluded by!**/*.png
📒 Files selected for processing (44)
.gitignoreCore/Source/Lux/Project/Project.cppCore/Source/Lux/Project/Project.hCore/Source/Lux/Renderer/Framebuffer.cppCore/Source/Lux/Renderer/Framebuffer.hCore/Source/Lux/Scripting/ScriptEngine.cppEditor/SandboxProject/Assets/Scenes/NewSceneSystem.luxsceneEditor/SandboxProject/Sandbox.luxprojEditor/Source/EditorLayer.cppEditor/Source/EditorLayer.hEditor/Source/LuxEditorApp.cppEditor/Source/Panels/ProjectSettingsWindow.cppLux-Runtime/Lux-Runtime.rcLux-Runtime/premake5.luaLux-Runtime/resource.hLux-Runtime/src/RuntimeApplication.cppLux-Runtime/src/RuntimeLayer.cppLux-Runtime/src/RuntimeLayer.hREADME.mdSandbox/Resources/Fonts/FontAwesome/LICENSE.txtSandbox/Resources/Fonts/Roboto/LICENSE.txtSandbox/Resources/Fonts/SourceCodePro/OFL.txtSandbox/Resources/Fonts/SourceCodePro/README.txtSandbox/Resources/Fonts/msgothic.ttcSandbox/Resources/Fonts/opensans/LICENSE.txtSandbox/Resources/Shaders/Include/Common/Common.slhSandbox/Resources/Shaders/Include/Common/GTAO.slhSandbox/Resources/Shaders/Include/GLSL/Buffers.glslhSandbox/Resources/Shaders/Include/GLSL/Common.glslhSandbox/Resources/Shaders/Include/GLSL/EnvironmentMapping.glslhSandbox/Resources/Shaders/Include/GLSL/Lighting.glslhSandbox/Resources/Shaders/Include/GLSL/PBR.glslhSandbox/Resources/Shaders/Include/GLSL/PBR_Resources.glslhSandbox/Resources/Shaders/Include/GLSL/Samplers.glslhSandbox/Resources/Shaders/Include/GLSL/ShadowMapping.glslhSandbox/Resources/Shaders/Include/HLSL/Buffers.hlslhSandbox/Resources/Shaders/Include/HLSL/Types.hlslhSandbox/Source/Sandbox2D.cppSandbox/Source/Sandbox2D.hSandbox/Source/SandboxApp.cppSandbox/assets/fonts/opensans/LICENSE.txtSandbox/premake5.luapremake5.luascripts/Linux-Build.sh
💤 Files with no reviewable changes (23)
- Sandbox/Resources/Fonts/opensans/LICENSE.txt
- Sandbox/Resources/Fonts/SourceCodePro/README.txt
- Sandbox/Resources/Shaders/Include/Common/Common.slh
- Sandbox/Resources/Fonts/SourceCodePro/OFL.txt
- Sandbox/Source/Sandbox2D.h
- scripts/Linux-Build.sh
- Sandbox/Resources/Shaders/Include/GLSL/Common.glslh
- Sandbox/Resources/Shaders/Include/Common/GTAO.slh
- Sandbox/Resources/Shaders/Include/GLSL/PBR_Resources.glslh
- Sandbox/Resources/Shaders/Include/HLSL/Buffers.hlslh
- Sandbox/Resources/Shaders/Include/GLSL/Lighting.glslh
- Sandbox/Resources/Fonts/FontAwesome/LICENSE.txt
- Sandbox/Resources/Shaders/Include/GLSL/EnvironmentMapping.glslh
- Sandbox/Resources/Shaders/Include/GLSL/PBR.glslh
- Sandbox/Source/SandboxApp.cpp
- Sandbox/Resources/Fonts/Roboto/LICENSE.txt
- Sandbox/Source/Sandbox2D.cpp
- Sandbox/Resources/Shaders/Include/GLSL/Buffers.glslh
- Sandbox/assets/fonts/opensans/LICENSE.txt
- Sandbox/Resources/Shaders/Include/GLSL/ShadowMapping.glslh
- Sandbox/Resources/Shaders/Include/HLSL/Types.hlslh
- Sandbox/premake5.lua
- Sandbox/Resources/Shaders/Include/GLSL/Samplers.glslh
| if (!s_ActiveProject) | ||
| return; |
There was a problem hiding this comment.
Do not skip audio shutdown when clearing the active runtime project.
Line 70 returns on nullptr and bypasses the cleanup block at Line 80, so Project::SetActiveRuntime(nullptr, nullptr) can leave the audio engine initialized.
🛠️ Suggested fix
s_ActiveProject = project;
- if (!s_ActiveProject)
- return;
-
- if (s_ActiveProject->m_ProjectDirectory.empty())
- s_ActiveProject->m_ProjectDirectory = s_ActiveProject->m_Config.ProjectDirectory;
- if (s_ActiveProject->m_ProjectFilePath.empty() && !s_ActiveProject->m_ProjectDirectory.empty())
- s_ActiveProject->m_ProjectFilePath = s_ActiveProject->m_ProjectDirectory / s_ActiveProject->m_Config.ProjectFileName;
-
- s_ActiveProject->m_Config.ProjectDirectory = s_ActiveProject->m_ProjectDirectory;
- s_ActiveProject->m_Config.ProjectFileName = s_ActiveProject->m_ProjectFilePath.filename().string();
-
if (AudioEngine::HasInitializedEngine())
{
AudioEngine::Shutdown();
AudioEngine::SetInitalizedEngine(false);
}
+
+ if (!s_ActiveProject)
+ return;
+
+ if (s_ActiveProject->m_ProjectDirectory.empty())
+ s_ActiveProject->m_ProjectDirectory = s_ActiveProject->m_Config.ProjectDirectory;
+ if (s_ActiveProject->m_ProjectFilePath.empty() && !s_ActiveProject->m_ProjectDirectory.empty())
+ s_ActiveProject->m_ProjectFilePath = s_ActiveProject->m_ProjectDirectory / s_ActiveProject->m_Config.ProjectFileName;
+
+ s_ActiveProject->m_Config.ProjectDirectory = s_ActiveProject->m_ProjectDirectory;
+ s_ActiveProject->m_Config.ProjectFileName = s_ActiveProject->m_ProjectFilePath.filename().string();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!s_ActiveProject) | |
| return; | |
| s_ActiveProject = project; | |
| if (AudioEngine::HasInitializedEngine()) | |
| { | |
| AudioEngine::Shutdown(); | |
| AudioEngine::SetInitalizedEngine(false); | |
| } | |
| if (!s_ActiveProject) | |
| return; | |
| if (s_ActiveProject->m_ProjectDirectory.empty()) | |
| s_ActiveProject->m_ProjectDirectory = s_ActiveProject->m_Config.ProjectDirectory; | |
| if (s_ActiveProject->m_ProjectFilePath.empty() && !s_ActiveProject->m_ProjectDirectory.empty()) | |
| s_ActiveProject->m_ProjectFilePath = s_ActiveProject->m_ProjectDirectory / s_ActiveProject->m_Config.ProjectFileName; | |
| s_ActiveProject->m_Config.ProjectDirectory = s_ActiveProject->m_ProjectDirectory; | |
| s_ActiveProject->m_Config.ProjectFileName = s_ActiveProject->m_ProjectFilePath.filename().string(); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Core/Source/Lux/Project/Project.cpp` around lines 69 - 70, The early return
when s_ActiveProject is null in Project::SetActiveRuntime skips the cleanup that
should uninitialize the audio engine; remove the early return (or move the
cleanup block above it) so the audio shutdown logic always runs when
SetActiveRuntime(nullptr, nullptr) is called, and explicitly invoke the audio
cleanup/uninitialize routine used by the project (the audio shutdown function
your project normally calls during project teardown) as part of the same cleanup
sequence to ensure the audio engine is always shut down even if s_ActiveProject
is nullptr.
| if (m_Specification.SwapChainTarget) | ||
| { | ||
| PopulateClearValues(m_Specification, m_ClearValues); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Add a swapchain-target attachment guard before the early return.
Line 67 returns before the constructor reaches the general attachment validation, so a swapchain framebuffer with zero attachments can leave m_ClearValues empty and later break clear indexing during render-pass setup.
🛠️ Suggested fix
if (m_Specification.SwapChainTarget)
{
+ LUX_CORE_ASSERT(!m_Specification.Attachments.Attachments.empty(), "SwapChainTarget framebuffer requires at least one attachment");
PopulateClearValues(m_Specification, m_ClearValues);
return;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Core/Source/Lux/Renderer/Framebuffer.cpp` around lines 64 - 68, Add a guard
when handling m_Specification.SwapChainTarget in the Framebuffer constructor so
we don't early-return with zero attachments: before the "if
(m_Specification.SwapChainTarget) { PopulateClearValues(...); return; }" check,
validate that m_Specification.Attachments is not empty (or assert/log+return)
and fail-fast if it is, ensuring PopulateClearValues is only called when there
are attachments and preventing m_ClearValues from remaining empty; reference
m_Specification.SwapChainTarget, m_Specification.Attachments,
PopulateClearValues, and m_ClearValues.
| if (!s_Data || !s_Data->RootDomain) | ||
| return; | ||
|
|
||
| mono_domain_set(mono_get_root_domain(), false); | ||
|
|
||
| mono_domain_unload(s_Data->AppDomain); | ||
| s_Data->AppDomain = nullptr; | ||
| if (s_Data->AppDomain) | ||
| { | ||
| mono_domain_unload(s_Data->AppDomain); | ||
| s_Data->AppDomain = nullptr; | ||
| } |
There was a problem hiding this comment.
Stop file-watch callbacks before domain teardown to avoid shutdown races.
AppAssemblyFileWatcher can still trigger OnAppAssemblyFileSystemEvent while shutdown is in progress; that path dereferences s_Data and can crash after Line 205 sets it to nullptr. Reset the watcher before unload and guard callback/lambda dereferences.
Proposed fix
diff --git a/Core/Source/Lux/Scripting/ScriptEngine.cpp b/Core/Source/Lux/Scripting/ScriptEngine.cpp
@@
static void OnAppAssemblyFileSystemEvent(const std::string& path, const filewatch::Event change_type)
{
+ if (!s_Data)
+ return;
+
if (!s_Data->AssemblyReloadPending && change_type == filewatch::Event::modified)
{
s_Data->AssemblyReloadPending = true;
Application::Get().QueueEvent([]()
{
+ if (!s_Data)
+ return;
s_Data->AppAssemblyFileWatcher.reset();
ScriptEngine::ReloadAssembly();
});
}
}
@@
void ScriptEngine::Shutdown()
{
if (!s_Data)
return;
+ s_Data->AppAssemblyFileWatcher.reset();
ShutdownMono();
delete s_Data;
s_Data = nullptr;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Core/Source/Lux/Scripting/ScriptEngine.cpp` around lines 239 - 248, The
shutdown sequence must stop and reset the AppAssemblyFileWatcher before tearing
down s_Data/AppDomain to avoid races; update the code in ScriptEngine (around
mono_domain_unload and s_Data handling) to stop/unregister the
AppAssemblyFileWatcher and set it to nullptr before calling mono_domain_unload
and clearing s_Data, and also update the OnAppAssemblyFileSystemEvent
callback/lambdas to defensively check s_Data and s_Data->RootDomain (or capture
weak state) before dereferencing; ensure AppAssemblyFileWatcher::Stop/Unregister
is invoked prior to mono_domain_unload and that any remaining callbacks bail out
if s_Data is null.
| result, err = os.outputof("pkg-config --libs gtk+-3.0") | ||
| linkoptions { result } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Premake5 behavior check: does filter "system:linux"apply only to Premake API calls (e.g.,links, defines) and not to plain Lua statements like os.outputof(...)?
💡 Result:
Yes. filter "system:linux" only affects Premake API calls that add/modify settings in Premake’s internal output model (e.g., defines, links, includedirs, etc.). It does not “guard” plain Lua statements from executing. 1) What filter actually does (Premake model scoping) Premake’s filter documentation says calling filter() makes that filter condition “active”, and “All settings which subsequently appear in the script will be filtered by this condition” until a new filter or container is activated [1]. This implies it gates Premake “settings” (i.e., the things that Premake APIs record for later generation), not arbitrary Lua code. It also states that filters are “evaluated at generation time” based on the currently generated configuration/project context [1]. That further indicates the filter isn’t a runtime Lua control-flow construct; it’s a selection mechanism for what ends up in generated project files. 2) Direct evidence: os.outputof(...) runs regardless of the active filter An issue discussion explicitly demonstrates this with os.outputof(...) inside filter "system:windows" / filter "system:linux" blocks. The author explains that “filter... is just a call to a function, that has no effect on the execution order”, and shows that what looks like conditional execution is really just sequential Lua function calls; filter “add[s] a ‘block’ to the internal premake tree” while the Lua code (including os.outputof) executes during script loading [2]. So if you write: filter "system:linux" local tmp = os.outputof("linuxcommand...") then the os.outputof(...) call still executes when Premake parses/loads the script, regardless of whether the generator is targeting Linux. The filter only determines whether any Premake settings you emit after it end up in the Linux-specific generated output [1][2]. Bottom line Use normal Lua conditionals (e.g., if os.host() == "linux" then ... end) when you need to conditionally execute Lua code at script-load time [3]. Use filter "system:linux" when you want certain Premake settings to appear only in the generated output for Linux configurations [1].
Citations:
- 1: https://premake.github.io/docs/filter/
- 2: os.outputof and filter; commands are executed regardless? premake/premake-core#212
- 3: Certain filters not working properly premake/premake-core#1204
Guard pkg-config execution with os.host(); filter "system:linux" doesn’t prevent Lua from running
filter "system:linux" only scopes Premake settings—it doesn’t guard execution of plain Lua, so os.outputof("pkg-config --libs gtk+-3.0") can still run during script load on non-Linux hosts. Keep the output in a local variable and run the os.outputof call only when os.host() == "linux", failing clearly when output is missing.
- The proposed fix is directionally correct, but the inner
filter "system:linux"in the diff is redundant.
Proposed fix
filter "system:linux"
defines { "LUX_PLATFORM_LINUX", "__EMULATE_UUID", "BACKWARD_HAS_DW", "BACKWARD_HAS_LIBUNWIND" }
links { "dw", "dl", "unwind", "pthread" }
- result, err = os.outputof("pkg-config --libs gtk+-3.0")
- linkoptions { result }
+if os.host() == "linux" then
+ local gtk_libs = os.outputof("pkg-config --libs gtk+-3.0")
+ if not gtk_libs or gtk_libs == "" then
+ error("pkg-config --libs gtk+-3.0 failed. Install gtk+-3.0 development packages and pkg-config.")
+ end
+ filter "system:linux"
+ linkoptions { gtk_libs }
+end🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Lux-Runtime/premake5.lua` around lines 47 - 48, The call to
os.outputof("pkg-config --libs gtk+-3.0") is executed unconditionally during
script load; wrap that call in a host check so it only runs on Linux: use a
local variable (e.g. local result, err) and call os.outputof only when os.host()
== "linux", then validate result and error out or raise a clear message if the
output is empty/invalid; remove the redundant inner filter "system:linux" around
the exec and keep the Premake filter "system:linux" only for applying
linkoptions { result } so linkoptions is set only on Linux when result is
present.
This pull request introduces several new features and improvements across the project, most notably the implementation of a "Runtime Export" workflow in the Editor, enhancements to project and asset serialization. The changes are grouped below by theme.
Editor: Runtime Export Workflow
EditorLayer.cpp,EditorLayer.h) [1] [2] [3] [4]EditorLayer.cpp) [1] [2]Project & Asset Serialization
Project::LoadRuntimefor loading runtime project configurations and asset packs, and improved initialization logic for project directories, file paths, and audio engine state during runtime project loading. (Project.cpp,Project.h) [1] [2] [3]Project and Scene Configuration Tweaks
Sandbox.luxproj,NewSceneSystem.luxscene) [1] [2] [3]LuxEditorApp.cpp)Summary by CodeRabbit
New Features
Improvements
Chores