diff --git a/BuildProject.bat b/BuildProject.bat index 11869de..0b17e82 100644 --- a/BuildProject.bat +++ b/BuildProject.bat @@ -1,2 +1,2 @@ -call third-party\bin\premake\premake5.exe vs2022 +call third-party\bin\premake\premake5.exe vs2026 PAUSE \ No newline at end of file diff --git a/Dependencies.lua b/Dependencies.lua index 93efa52..11c9e77 100644 --- a/Dependencies.lua +++ b/Dependencies.lua @@ -6,4 +6,7 @@ IncludeDir["tinyobj"] = "%{wks.location}/GameSmithEngine/third-party/tinyobjload IncludeDir["googletest"] = "%{wks.location}/third-party/googletest/googletest/include" IncludeDir["spdlog"] = "%{wks.location}/GameSmithEngine/third-party/spdlog/include" IncludeDir["CLI11"] = "%{wks.location}/GameSmithEngine/third-party/CLI11/include" -IncludeDir["json"] = "%{wks.location}/GameSmithEngine/third-party/json/include" \ No newline at end of file +IncludeDir["json"] = "%{wks.location}/GameSmithEngine/third-party/json/include" + +DLLDir = {} +DLLDir["dxc"] = "%{wks.location}/GameSmithEngine/third-party/dxc" \ No newline at end of file diff --git a/GEStandaloneGameApp/GEStandaloneGameApp.vcxproj b/GEStandaloneGameApp/GEStandaloneGameApp.vcxproj index 16de2a0..6bb7c5b 100644 --- a/GEStandaloneGameApp/GEStandaloneGameApp.vcxproj +++ b/GEStandaloneGameApp/GEStandaloneGameApp.vcxproj @@ -26,19 +26,19 @@ Application true Unicode - v143 + v145 Application false Unicode - v143 + v145 Application false Unicode - v143 + v145 @@ -83,7 +83,7 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -91,6 +91,8 @@ Console true + + @@ -105,7 +107,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -115,6 +117,8 @@ true true + + @@ -129,7 +133,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -139,6 +143,8 @@ true true + + diff --git a/GEStandaloneGameApp/premake5.lua b/GEStandaloneGameApp/premake5.lua index f50d820..a4a95ce 100644 --- a/GEStandaloneGameApp/premake5.lua +++ b/GEStandaloneGameApp/premake5.lua @@ -26,7 +26,10 @@ project "GEStandaloneGameApp" filter "system:windows" systemversion "latest" - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } defines { "GE_PLATFORM_WINDOWS" } filter "configurations:Debug" diff --git a/GameSmithEditor/GameSmithEditor.vcxproj b/GameSmithEditor/GameSmithEditor.vcxproj index a22d7fe..8d3173e 100644 --- a/GameSmithEditor/GameSmithEditor.vcxproj +++ b/GameSmithEditor/GameSmithEditor.vcxproj @@ -26,19 +26,19 @@ Application true Unicode - v143 + v145 Application false Unicode - v143 + v145 Application false Unicode - v143 + v145 @@ -83,7 +83,7 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -91,6 +91,12 @@ Console true + + + + cmd /c robocopy "$(SolutionDir)\GameSmithEditor\Icons" "$(SolutionDir)\bin\Debug-windows-x86_64\GameSmithEditor\Icons" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% +cmd /c robocopy "$(SolutionDir)\GameSmithEditor\ProjectPresets" "$(SolutionDir)\bin\Debug-windows-x86_64\GameSmithEditor\ProjectPresets" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% + @@ -104,7 +110,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -113,6 +119,12 @@ true true + + + + cmd /c robocopy "$(SolutionDir)\GameSmithEditor\Icons" "$(SolutionDir)\bin\Release-windows-x86_64\GameSmithEditor\Icons" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% +cmd /c robocopy "$(SolutionDir)\GameSmithEditor\ProjectPresets" "$(SolutionDir)\bin\Release-windows-x86_64\GameSmithEditor\ProjectPresets" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% + @@ -126,7 +138,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -135,22 +147,34 @@ true true + + + + cmd /c robocopy "$(SolutionDir)\GameSmithEditor\Icons" "$(SolutionDir)\bin\Dist-windows-x86_64\GameSmithEditor\Icons" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% +cmd /c robocopy "$(SolutionDir)\GameSmithEditor\ProjectPresets" "$(SolutionDir)\bin\Dist-windows-x86_64\GameSmithEditor\ProjectPresets" /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL% + + + + + + + @@ -158,14 +182,19 @@ + + + + + diff --git a/GameSmithEditor/GameSmithEditor.vcxproj.filters b/GameSmithEditor/GameSmithEditor.vcxproj.filters index 1fcdb80..f68ea5b 100644 --- a/GameSmithEditor/GameSmithEditor.vcxproj.filters +++ b/GameSmithEditor/GameSmithEditor.vcxproj.filters @@ -19,6 +19,9 @@ {5032B729-BC11-36C5-C529-C19B31889C26} + + {E5C83B5E-D1C2-64B0-BA2F-FBC0A6C8CA1C} + @@ -33,6 +36,9 @@ CustomWidgets + + CustomWidgets + Icons @@ -42,6 +48,9 @@ SampleComponents + + Utils + Utils @@ -54,15 +63,27 @@ Windows + + Windows + Windows + + Windows + Windows Windows + + Windows\PrivateWindows + + + Windows + @@ -80,6 +101,9 @@ CustomWidgets + + CustomWidgets + Icons @@ -89,6 +113,9 @@ SampleComponents + + Utils + Utils @@ -98,11 +125,20 @@ Windows + + Windows + Windows Windows + + Windows\PrivateWindows + + + Windows + \ No newline at end of file diff --git a/GameSmithEditor/Icons/open-folder.png b/GameSmithEditor/Icons/open-folder.png new file mode 100644 index 0000000..505a57a Binary files /dev/null and b/GameSmithEditor/Icons/open-folder.png differ diff --git a/GameSmithEditor/Icons/stack.png b/GameSmithEditor/Icons/stack.png new file mode 100644 index 0000000..57c5691 Binary files /dev/null and b/GameSmithEditor/Icons/stack.png differ diff --git a/GameSmithEditor/ProjectPresets/premake5.lua b/GameSmithEditor/ProjectPresets/premake5.lua new file mode 100644 index 0000000..21dcdc2 --- /dev/null +++ b/GameSmithEditor/ProjectPresets/premake5.lua @@ -0,0 +1,92 @@ +IncludeDir = {} +IncludeDir["ImGui"] = "%{wks.location}/GameSmithEngine/third-party/imgui" +IncludeDir["glm"] = "%{wks.location}/GameSmithEngine/third-party/glm" +IncludeDir["stb"] = "%{wks.location}/GameSmithEngine/third-party/stb" +IncludeDir["tinyobj"] = "%{wks.location}/GameSmithEngine/third-party/tinyobjloader" +IncludeDir["spdlog"] = "%{wks.location}/GameSmithEngine/third-party/spdlog/include" +IncludeDir["CLI11"] = "%{wks.location}/GameSmithEngine/third-party/CLI11/include" +IncludeDir["json"] = "%{wks.location}/GameSmithEngine/third-party/json/include" +IncludeDir["GameSmithEngine"] = "%{wks.location}/GameSmithEngine/src" + +workspace "GameProject" + architecture "x64" + + configurations{ + "Debug", + "Release", + "Dist" + } + + newoption { + trigger = "prjName", + value = "ProjectName", + description = "The name of the game project", + default = "DefaultGameProject" + } + +outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" + + +libdirs { "C:\\Users\\esaus\\Documents\\Coding Projects\\GameSmithEngine\\bin\\Debug-windows-x86_64\\GameSmithEngine" } + +project(_OPTIONS["prjName"]) + location "." + kind "SharedLib" + + language "C++" + cppdialect "C++20" + + staticruntime "on" + + links { "GameSmithEngine" } + + targetdir ("bin/" .. outputdir .. "/%{prj.name}") + objdir ("bin-int/" .. outputdir .. "/%{prj.name}") + + files{ + "src/**.h", + "src/**.cpp", + "%{IncludeDir.GameSmithEngine}/**.h" + } + + includedirs{ + "%{IncludeDir.GameSmithEngine}", + "%{IncludeDir.spdlog}", + "%{IncludeDir.stb}", + "%{IncludeDir.ImGui}", + "%{IncludeDir.glm}", + "%{IncludeDir.tinyobj}" + } + + defines{ + "GE_PLATFORM_WINDOWS", + "GE_DYNAMIC_LINK" + } + + filter "system:windows" + systemversion "latest" + + buildoptions { "/utf-8" } + + defines{ + "GE_PLATFORM_WINDOWS" + } + + postbuildcommands{ + ("cmd /c robocopy %[%{cfg.targetdir}/] %[%{wks.location}/Cache] " .. _OPTIONS["prjName"] .. ".dll ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL%") + } + + filter "configurations:Debug" + defines "GE_DEBUG" + runtime "Debug" + symbols "on" + + filter "configurations:Release" + defines "GE_Release" + runtime "Release" + optimize "on" + + filter "configurations:Dist" + defines "GE_Dist" + runtime "Release" + optimize "on" \ No newline at end of file diff --git a/GameSmithEditor/imgui.ini b/GameSmithEditor/imgui.ini index e5692da..5b20cb2 100644 --- a/GameSmithEditor/imgui.ini +++ b/GameSmithEditor/imgui.ini @@ -15,10 +15,10 @@ Size=1280,700 Collapsed=0 [Window][Game View] -Pos=247,19 -Size=685,700 +Pos=324,19 +Size=613,700 Collapsed=0 -DockId=0x00000003,0 +DockId=0x00000009,0 [Window][Simulation Content View] Pos=0,19 @@ -33,43 +33,79 @@ Collapsed=0 DockId=0x00000004,0 [Window][Component Picker] -Pos=405,176 -Size=435,261 +ViewportPos=1425,457 +ViewportId=0x07F4CE8B +Size=476,253 Collapsed=0 [Window][Game Stats] -Pos=1097,242 +ViewportPos=1854,529 +ViewportId=0x565DA749 Size=150,55 Collapsed=0 [Window][Asset Database] -Pos=247,342 -Size=595,377 +Pos=0,450 +Size=1280,269 Collapsed=0 -DockId=0x00000006,0 +DockId=0x0000000A,0 [Window][Inspector] -Pos=934,19 -Size=346,700 +Pos=939,19 +Size=341,700 Collapsed=0 +DockId=0x00000008,0 [Window][Content View] Pos=0,19 -Size=245,700 +Size=322,700 Collapsed=0 +DockId=0x00000005,0 [Window][WindowOverViewport_11111111] Pos=0,19 Size=1280,700 Collapsed=0 +[Window][Project Create Window] +Pos=60,60 +Size=471,43 +Collapsed=0 + +[Window][Project Creator] +Pos=221,148 +Size=712,278 +Collapsed=0 + +[Window][Editor View] +Pos=324,19 +Size=608,429 +Collapsed=0 +DockId=0x00000009,0 + +[Window][Asset Inspector] +ViewportPos=1532,339 +ViewportId=0x45169E18 +Size=498,261 +Collapsed=0 + +[Window][Asset Inspector##] +ViewportPos=1701,418 +ViewportId=0x15E1757C +Size=729,337 +Collapsed=0 + [Docking][Data] -DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=190,232 Size=1280,700 CentralNode=1 -DockSpace ID=0x8B93E3BD Pos=86,128 Size=1280,700 Split=Y Selected=0x642CEEBB - DockNode ID=0x00000005 Parent=0x8B93E3BD SizeRef=1280,321 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=289,700 Selected=0x08B21A54 - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=989,700 Split=X - DockNode ID=0x00000003 Parent=0x00000002 SizeRef=703,700 CentralNode=1 Selected=0x642CEEBB - DockNode ID=0x00000004 Parent=0x00000002 SizeRef=284,700 Selected=0x65070D15 - DockNode ID=0x00000006 Parent=0x8B93E3BD SizeRef=1280,377 Selected=0x1F2CDDE0 +DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,102 Size=1280,700 Split=X + DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=322,700 Selected=0xBEC5A1CE + DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=956,700 Split=X + DockNode ID=0x00000007 Parent=0x00000006 SizeRef=613,694 Split=Y Selected=0x8065DB7E + DockNode ID=0x00000009 Parent=0x00000007 SizeRef=930,20 CentralNode=1 Selected=0x8065DB7E + DockNode ID=0x0000000A Parent=0x00000007 SizeRef=930,269 Selected=0x0B48A3F1 + DockNode ID=0x00000008 Parent=0x00000006 SizeRef=341,694 Selected=0x36DC96AB +DockSpace ID=0x8B93E3BD Pos=86,128 Size=1280,700 Split=X Selected=0x642CEEBB + DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=289,700 Selected=0x08B21A54 + DockNode ID=0x00000002 Parent=0x8B93E3BD SizeRef=989,700 Split=X + DockNode ID=0x00000003 Parent=0x00000002 SizeRef=703,700 CentralNode=1 Selected=0x642CEEBB + DockNode ID=0x00000004 Parent=0x00000002 SizeRef=284,700 Selected=0x65070D15 diff --git a/GameSmithEditor/premake5.lua b/GameSmithEditor/premake5.lua index 0b15ddc..f0fea34 100644 --- a/GameSmithEditor/premake5.lua +++ b/GameSmithEditor/premake5.lua @@ -33,7 +33,15 @@ project "GameSmithEditor" filter "system:windows" systemversion "latest" - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } + + postbuildcommands{ + ("cmd /c robocopy %[%{wks.location}/GameSmithEditor/Icons] %[%{wks.location}/bin/" .. outputdir .. "/GameSmithEditor/Icons] /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL%"), + ("cmd /c robocopy %[%{wks.location}/GameSmithEditor/ProjectPresets] %[%{wks.location}/bin/" .. outputdir .. "/GameSmithEditor/ProjectPresets] /E ^& if %ERRORLEVEL% LSS 2 exit /b 0 ^& exit /b %ERRORLEVEL%") + } defines{ "GE_PLATFORM_WINDOWS" diff --git a/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.cpp b/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.cpp index bd16af5..0d05d47 100644 --- a/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.cpp @@ -1,16 +1,8 @@ #include "EditorCoreLayer.h" - -//TODO: Temporary, remove after demo -#include "GameSmithEditor/SampleComponents/OrbitScript.h" -#include "GameSmithEditor/SampleComponents/BurstOrbitScript.h" - +#include "GameSmithEditor/Core/EditorMenu.h" +#include "GameSmithEditor/Core/GameProject.h" #include "GameSmithEditor/Windows/AccessibleWindows.h" - #include "imgui.h" -#include "GameSmithEditor/Core/GameProject.h" - -#include "GameSmithEditor/Core/EditorMenu.h" -#include "GameSmithEditor/Utils/SystemCallUtils.h" namespace GameSmithEditor { EditorCoreLayer* EditorCoreLayer::s_Instance = nullptr; @@ -29,8 +21,6 @@ namespace GameSmithEditor { renderManager->SetFrameTexture(m_EditorScreen); GameViewLayer::SetScreenTexture(m_EditorScreen); - - MenuRegistry::GetInstance()->RegisterMenuEntry("Files_Extra_Test", []() {GE_APP_INFO("HI"); }); } } @@ -42,13 +32,6 @@ namespace GameSmithEditor { ImGui::SetCurrentContext(ImGuiInstance->GetImGuiContext()); ImGuiInstance->SetDockspace(true); - - if (GameProject::IsLoaded()) { - - } - else { - - } } void EditorCoreLayer::OnImGuiRender() @@ -108,4 +91,10 @@ namespace GameSmithEditor { auto renderManager = GameSmith::RenderingManager::GetInstance(); renderManager->SetForClear(m_EditorScreen); } + + void EditorWindow::CloseWindow() + { + EditorWindowClose closeEvent(this); + m_CloseDispatcher.Dispatch(closeEvent); + } }; diff --git a/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.h b/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.h index 8823f2c..42de866 100644 --- a/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.h +++ b/GameSmithEditor/src/GameSmithEditor/Core/EditorCoreLayer.h @@ -1,9 +1,20 @@ #pragma once #include "GameSmithEngine.h" +#include "GameSmithEditor/Windows/EditorWindowEvents.h" #define EDITOR_WINDOW_TITLE "Game Smith Editor" namespace GameSmithEditor { + class EditorWindow : public GameSmith::Layer { + public: + EditorWindow(std::string name) : GameSmith::Layer(name) {} + GameSmith::EventDispatcher& GetCloseEventDispatch() { return m_CloseDispatcher; } + protected: + void CloseWindow(); + private: + GameSmith::EventDispatcher m_CloseDispatcher; + }; + class EditorCoreLayer : public GameSmith::Layer { public: @@ -15,7 +26,33 @@ namespace GameSmithEditor { template static void CreateEditorWindow() { - W* window = new W(); + EditorWindow* window = new W(); + + window->GetCloseEventDispatch().AddListener( + [window](EditorWindowClose& evn) { + auto& app = GameSmith::Application::Get(); + app.PopLayer(window); + + return true; + }, false + ); + + auto& app = GameSmith::Application::Get(); + app.PushLayer(window); + } + + template + static void AppendEditorWindow(W* newWindow) { + EditorWindow* window = newWindow; + + window->GetCloseEventDispatch().AddListener( + [window](EditorWindowClose& evn) { + auto& app = GameSmith::Application::Get(); + app.PopLayer(window); + + return true; + }, false + ); auto& app = GameSmith::Application::Get(); app.PushLayer(window); @@ -24,6 +61,7 @@ namespace GameSmithEditor { inline static EditorCoreLayer* GetInstance() { return s_Instance; } private: static EditorCoreLayer* s_Instance; + static std::vector> m_EditorWindows; GameSmith::Application& m_App; GameSmith::Ref m_EditorScreen; diff --git a/GameSmithEditor/src/GameSmithEditor/Core/GameProject.cpp b/GameSmithEditor/src/GameSmithEditor/Core/GameProject.cpp index 9fdda10..923d95e 100644 --- a/GameSmithEditor/src/GameSmithEditor/Core/GameProject.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Core/GameProject.cpp @@ -4,26 +4,36 @@ #include "GameSmithEditor/Core/EditorMenu.h" #include "GameSmithEditor/Utils/SystemCallUtils.h" +namespace fs = std::filesystem; + namespace GameSmithEditor { - REGISTER_EDITOR_MENU_OPTION(Files_CreateProject, &MenuCreateProject); REGISTER_EDITOR_MENU_OPTION(Files_LoadProject, &MenuLoadProject); GameSmith::Scope GameProject::s_CurProject = nullptr; void MenuCreateProject() { - std::string rootFolder = PickFolderDialog("C:\\Users\\esaus\\Documents\\Coding Projects\\GameSmithEngine\\bin\\Debug-windows-x86_64\\TestZone"); - GameSmithEditor::GameProject::CreateProject("TestProjectDir2", rootFolder); + std::string rootFolder; + if (PickFolderDialog(std::filesystem::current_path().string(), &rootFolder)) { + GameSmithEditor::GameProject::CreateProject("TestProjectDir2", rootFolder); + } } void MenuLoadProject() { - std::string rootFolder = PickFolderDialog("C:\\Users\\esaus\\Documents\\Coding Projects\\GameSmithEngine\\bin\\Debug-windows-x86_64\\TestZone"); - GameSmithEditor::GameProject::LoadProject(rootFolder); + std::string rootFolder; + if (PickFolderDialog(std::filesystem::current_path().string(), &rootFolder)) { + GameSmithEditor::GameProject::LoadProject(rootFolder); + } + } static void SetupProjectResources() { auto resourceManager = GameSmith::AssetManager::GetInstance(); - resourceManager->SetAssetDirectory(GameProject::GetRootFolder()); + resourceManager->SetAssetDirectory(GameProject::GetAssetFolder()); resourceManager->ScanResources(); + + auto contentLibraryManager = GameSmith::ContentLibraryManager::GetInstance(); + contentLibraryManager->SetLibrarySearchPath(GameProject::GetCacheFolder()); + contentLibraryManager->ScanForContentLibraries(); } void GameProject::CreateProject(std::string projectName, std::string projectPath) @@ -32,30 +42,64 @@ namespace GameSmithEditor { s_CurProject = GameSmith::Scope(new GameProject()); } + std::string fullProjectPath = std::format("{0}\\{1}", projectPath, projectName); + fs::create_directories(fullProjectPath); + + // Copy preset files + std::string curDir = fs::current_path().string(); + std::string parentDir = fs::current_path().parent_path().string(); + fs::copy(std::format( + "{0}\\{1}", + curDir, + PROJECT_PRESET_FOLDER), + fullProjectPath, + fs::copy_options::recursive | fs::copy_options::overwrite_existing + ); + + // Symlink Engine Source + if (fs::exists(std::format("{0}\\{1}", fullProjectPath, "GameSmithEngine"))) { + fs::remove(std::format("{0}\\{1}", fullProjectPath, "GameSmithEngine")); + } + + // TODO: Update this with installation bundled with editor + fs::create_directory_symlink(std::format( + "{0}\\{1}", + parentDir, + "GameSmithEngine"), + std::format( + "{0}\\{1}", + fullProjectPath, + "GameSmithEngine" + ) + ); + + const std::string folders[] = { PROJECT_ASSET_FOLDER_NAME, PROJECT_CACHE_FOLDER_NAME, PROJECT_SRC_FOLDER_NAME, PROJECT_EDITOR_RESOURCE_FOLDER_NAME }; const unsigned int folderCount = 4; for (unsigned int i = 0; i < folderCount; i++) { - std::string fullPath = std::format("{0}\\{1}\\{2}", projectPath, projectName, folders[i]); - std::filesystem::create_directories(fullPath); + std::string fullPath = std::format("{0}\\{1}", fullProjectPath, folders[i]); + fs::create_directories(fullPath); } - std::string projRoot = std::format("{0}\\{1}", projectPath, projectName); - - s_CurProject->SetRootFolder(projRoot); + s_CurProject->SetRootFolder(fullProjectPath); s_CurProject->SetProjectName(projectName); auto buf = s_CurProject->Serialize(); - GameSmith::BinaryStreamWriter writer(buf.get(), s_CurProject->RequiredSpace()); - writer.CommitToFile(std::format("{0}\\{1}\\{2}.{3}", projectPath, projectName, projectName, s_CurProject->GetFileExtension())); + unsigned int serializedSize = s_CurProject->RequiredSpace(); + GameSmith::BinaryStreamWriter writer(buf.get(), serializedSize); + writer.MoveCurPtr(serializedSize); + + writer.CommitToFile(std::format("{0}\\{1}.{2}", fullProjectPath, projectName, s_CurProject->GetFileExtension())); SetupProjectResources(); } void GameProject::LoadProject(std::string projectFolder) { - auto reader = GameSmith::BinaryStreamReader::ReadDirectlyFromFile(std::format("{0}\\{1}.GameSmithPrj", projectFolder, "TestProjectDir2")); + std::string projectName = projectFolder.substr(projectFolder.find_last_of("\\")); + auto reader = GameSmith::BinaryStreamReader::ReadDirectlyFromFile(std::format("{0}\\{1}.GameSmithPrj", projectFolder, projectName)); if (s_CurProject == nullptr) { s_CurProject = GameSmith::Scope(new GameProject()); diff --git a/GameSmithEditor/src/GameSmithEditor/Core/GameProject.h b/GameSmithEditor/src/GameSmithEditor/Core/GameProject.h index 166c5a7..6bdaf4d 100644 --- a/GameSmithEditor/src/GameSmithEditor/Core/GameProject.h +++ b/GameSmithEditor/src/GameSmithEditor/Core/GameProject.h @@ -5,13 +5,15 @@ #define PROJECT_ASSET_FOLDER_NAME "Assets" #define PROJECT_EDITOR_RESOURCE_FOLDER_NAME "EditorResources" #define PROJECT_CACHE_FOLDER_NAME "Cache" -#define PROJECT_SRC_FOLDER_NAME "Src" +#define PROJECT_SRC_FOLDER_NAME "src" + +#define PROJECT_PRESET_FOLDER "ProjectPresets" namespace GameSmithEditor { void MenuCreateProject(); void MenuLoadProject(); - class GameProject : public GameSmith::Serializeable + class GameProject : public GameSmith::Asset { public: static void CreateProject(std::string projectName, std::string projectPath); @@ -20,6 +22,7 @@ namespace GameSmithEditor { static std::string GetRootFolder() { return s_CurProject->m_RootFolder; } static std::string GetAssetFolder() { return std::format("{0}\\{1}", s_CurProject->m_RootFolder, PROJECT_ASSET_FOLDER_NAME); } static std::string GetEditorResourceFolder() { return std::format("{0}\\{1}", s_CurProject->m_RootFolder, PROJECT_EDITOR_RESOURCE_FOLDER_NAME); } + static std::string GetCacheFolder() { return std::format("{0}\\{1}", s_CurProject->m_RootFolder, PROJECT_CACHE_FOLDER_NAME); } static std::string GetProjectName() { return s_CurProject->m_ProjectName; } static bool IsLoaded() { return s_CurProject != nullptr; } @@ -32,7 +35,7 @@ namespace GameSmithEditor { SERIAL_FILE(GameSmith Project, GameSmithPrj) private: - GameProject() = default; + GameProject() : Asset("Empty") {}; inline void SetRootFolder(std::string root) { m_RootFolder = root; }; inline void SetProjectName(std::string name) { m_ProjectName = name; } private: diff --git a/GameSmithEditor/src/GameSmithEditor/CustomWidgets/ReferenceInputWidget.cpp b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/ReferenceInputWidget.cpp index b5b40d6..f2ac415 100644 --- a/GameSmithEditor/src/GameSmithEditor/CustomWidgets/ReferenceInputWidget.cpp +++ b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/ReferenceInputWidget.cpp @@ -53,6 +53,13 @@ namespace GameSmithEditor { if (ImGui::SmallButton("Select")) { } + ImGui::SameLine(); + const std::string clearLabel = std::format("{0}##{1}", "Clear", varName); + if (ImGui::SmallButton(clearLabel.c_str())) { + refCon->ResetRef(); + found = false; + } + return found; } @@ -61,17 +68,18 @@ namespace GameSmithEditor { bool found = false; ImGui::Text(varName.c_str()); ImGui::SameLine(); - std::string refInfo = std::format("{0}:{1}", "Empty", refCon->GetTypeName()); + std::string refInfo = std::format("{0}:{1}##{2}", "Empty", refCon->GetTypeName(), varName); auto curRef = refCon->GetCurrentRef(); if (curRef != nullptr) { const GameSmith::ID& id = curRef->GetID(); refInfo = std::format( - "{0}:{1},{2},{3},{4}", + "{0}:{1},{2},{3},{4}##{5}", refCon->GetTypeName(), id.getData().ID1, id.getData().ID2, id.getData().ID3, - id.getData().ID4 + id.getData().ID4, + varName ); } @@ -82,13 +90,11 @@ namespace GameSmithEditor { GameSmith::ID* assetID = (GameSmith::ID*)(payload->Data); auto resourceManager = GameSmith::AssetManager::GetInstance(); - GameSmith::Ref asset = resourceManager->GetResource(*assetID); - // TODO: Update resource manager to return asset classes - GameSmith::Ref tmpUpgrade = CastPtr(asset); + GameSmith::Ref asset = resourceManager->GetResource(*assetID); - if (refCon->TypeCheck(tmpUpgrade)) { - refCon->AssignRef(tmpUpgrade); - refCon->AssignID(tmpUpgrade->GetID()); + if (refCon->TypeCheck(asset)) { + refCon->AssignRef(asset); + refCon->AssignID(asset->GetID()); found = true; } } @@ -98,7 +104,16 @@ namespace GameSmithEditor { ImGui::SameLine(); - if (ImGui::SmallButton("Select")) { + const std::string buttonLabel = std::format("{0}##{1}", "Select", varName); + if (ImGui::SmallButton(buttonLabel.c_str())) { + } + + ImGui::SameLine(); + + const std::string clearLabel = std::format("{0}##{1}", "Clear", varName); + if (ImGui::SmallButton(clearLabel.c_str())) { + refCon->ResetRef(); + found = false; } return found; diff --git a/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.cpp b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.cpp new file mode 100644 index 0000000..dc59360 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.cpp @@ -0,0 +1,26 @@ +#include "SelectableImage.h" + +namespace GameSmithEditor { + bool SelectableImage(const std::string& label, const bool selected, const ImTextureRef image, const ImVec2& imageSize) + { + ImGui::Image(image, imageSize); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorScreenPos(ImGui::GetItemRectMin()); + std::string uniqueLabel = "##SelectableImage_" + label; + bool result = selected; + + const ImVec2 min = ImGui::GetItemRectMin(); + const ImVec2 max = ImGui::GetItemRectMax(); + + if (ImGui::InvisibleButton(uniqueLabel.c_str(), imageSize)) { + result = true; + } + + ImDrawList* dl = ImGui::GetWindowDrawList(); + if (ImGui::IsItemHovered() || result ) { + dl->AddRectFilled(min, max, IM_COL32(255, 255, 255, 40), 3.0f); + } + + return result; + } +}; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.h b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.h new file mode 100644 index 0000000..a0d0b5a --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/CustomWidgets/SelectableImage.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "imgui.h" + +namespace GameSmithEditor { + bool SelectableImage(const std::string& label, const bool selected, const ImTextureRef image, const ImVec2& imageSize); +}; diff --git a/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.cpp b/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.cpp index 22855dc..45c167e 100644 --- a/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.cpp @@ -30,7 +30,7 @@ namespace GameSmithEditor { return m_IconMap.find(fileExtention)->second.assetRef->GetTexture(); } else { - LoadIcon(fileExtention); + FindIcon(fileExtention); if (m_IconMap.contains(fileExtention)) { return m_IconMap.find(fileExtention)->second.assetRef->GetTexture(); @@ -51,7 +51,7 @@ namespace GameSmithEditor { return m_IconMap.find(fileExtention)->second.imguiRef; } else { - LoadIcon(fileExtention); + FindIcon(fileExtention); if (m_IconMap.contains(fileExtention)) { return m_IconMap.find(fileExtention)->second.imguiRef; @@ -65,7 +65,7 @@ namespace GameSmithEditor { } } - void IconManager::LoadIcon(std::string fileExtention) + void IconManager::FindIcon(std::string fileExtention) { auto editorIconRoot = std::format("{0}/{1}", GameProject::GetEditorResourceFolder(), "/Icons"); if (std::filesystem::exists(editorIconRoot)) { diff --git a/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.h b/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.h index ca42897..0bc0b53 100644 --- a/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.h +++ b/GameSmithEditor/src/GameSmithEditor/Icons/IconManager.h @@ -14,7 +14,7 @@ namespace GameSmithEditor { const GameSmith::ImGuiTextureSpace* GetImGuiIcon(std::string fileExtention); private: IconManager() = default; - void LoadIcon(std::string fileExtention); + void FindIcon(std::string fileExtention); private: struct IconEntry { const GameSmith::ImGuiTextureSpace* imguiRef; diff --git a/GameSmithEditor/src/GameSmithEditor/SampleComponents/BurstOrbitScript.h b/GameSmithEditor/src/GameSmithEditor/SampleComponents/BurstOrbitScript.h index 41041da..c9f7c14 100644 --- a/GameSmithEditor/src/GameSmithEditor/SampleComponents/BurstOrbitScript.h +++ b/GameSmithEditor/src/GameSmithEditor/SampleComponents/BurstOrbitScript.h @@ -3,31 +3,31 @@ #include namespace GameSmithEditor { - class BurstOrbitScript : public GameSmith::Component { - public: - BurstOrbitScript(GameSmith::GameObject* gameObject, GameSmith::Transform* transform) : Component(gameObject, transform) { - m_Registry.AddExposedVariable("Num of Objects", &m_NumObjs, GameSmith::ContainerDataType::Int); - m_Registry.AddExposedVariable("Origin Point", glm::value_ptr(m_Center), GameSmith::ContainerDataType::Float3); - m_Registry.AddExposedVariable("Time Scale", &m_TimeScale, GameSmith::ContainerDataType::Float); - } + class BurstOrbitScript : public GameSmith::Component { + public: + BurstOrbitScript(GameSmith::GameObject* gameObject, GameSmith::Transform* transform) : Component(gameObject, transform) { + m_Registry.AddExposedVariable("Num of Objects", GameSmith::ContainerDataType::Int, &m_NumObjs); + m_Registry.AddExposedVariable("Origin Point", GameSmith::ContainerDataType::Float3, glm::value_ptr(m_Center)); + m_Registry.AddExposedVariable("Time Scale", GameSmith::ContainerDataType::Float , &m_TimeScale); + } - virtual void OnStart() override { } - virtual void OnUpdate(float dt); - virtual void OnDestroy() override {} - virtual std::string GetName() const override { return "Burst Demo Script"; }; - virtual int GetPriority() const { return 0; } + virtual void OnStart() override { } + virtual void OnUpdate(float dt); + virtual void OnDestroy() override {} + virtual std::string GetName() const override { return "Burst Demo Script"; }; + virtual int GetPriority() const { return 0; } - private: - std::vector> m_Objs; - glm::vec3 m_Center = {0, 0, 0}; - float m_TimeScale = 1; - int m_NumObjs = 0; + private: + std::vector> m_Objs; + glm::vec3 m_Center = {0, 0, 0}; + float m_TimeScale = 1; + int m_NumObjs = 0; - // Rando paraneters - std::mt19937 rng{ std::random_device{}() }; - std::uniform_real_distribution adist{ 0.0f, 2 * glm::pi() }; - std::uniform_real_distribution ddist{ 0.0f, 2 * glm::pi() }; - std::uniform_real_distribution odist{ 0.0f, 2 * glm::pi() }; - std::uniform_real_distribution rdist{ 6.0f, 20.0f }; - }; + // Rando paraneters + std::mt19937 rng{ std::random_device{}() }; + std::uniform_real_distribution adist{ 0.0f, 2 * glm::pi() }; + std::uniform_real_distribution ddist{ 0.0f, 2 * glm::pi() }; + std::uniform_real_distribution odist{ 0.0f, 2 * glm::pi() }; + std::uniform_real_distribution rdist{ 6.0f, 20.0f }; + }; }; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.cpp b/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.cpp index a5d9044..703f0b2 100644 --- a/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.cpp +++ b/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.cpp @@ -2,20 +2,21 @@ namespace GameSmithEditor { - void OrbitScript::OnUpdate(float dt) - { - m_t.SetPosition(m_Origin); - m_Transform->SetPosition(glm::vec3(m_Radius, 0, 0)); + void OrbitScript::OnUpdate(float dt) + { + m_t.SetPosition(m_Origin); + auto transform = GetTransform(); + transform->SetPosition(glm::vec3(m_Radius, 0, 0)); - auto orbit = m_t.GetRotation(); - orbit += m_OribitSpeeds * dt * m_TimeScale; - orbit = glm::mod(orbit, 2 * glm::pi()); - m_t.SetRotation(orbit); - auto localRot = m_Transform->GetRotation(); - localRot += m_LocalSpeeds * dt * m_TimeScale; - localRot = glm::mod(localRot, 2 * glm::pi()); - m_Transform->SetRotation(localRot); - } + auto orbit = m_t.GetRotation(); + orbit += m_OribitSpeeds * dt * m_TimeScale; + orbit = glm::mod(orbit, 2 * glm::pi()); + m_t.SetRotation(orbit); + auto localRot = transform->GetRotation(); + localRot += m_LocalSpeeds * dt * m_TimeScale; + localRot = glm::mod(localRot, 2 * glm::pi()); + transform->SetRotation(localRot); + } }; diff --git a/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.h b/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.h index 4a3681b..6bdbca7 100644 --- a/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.h +++ b/GameSmithEditor/src/GameSmithEditor/SampleComponents/OrbitScript.h @@ -2,34 +2,34 @@ #include "GameSmithEngine.h" namespace GameSmithEditor { - class OrbitScript : public GameSmith::Component { - public: - OrbitScript(GameSmith::GameObject* gameObject, GameSmith::Transform* transform) : Component(gameObject, transform) { - m_Transform->SetCoordinateFrame(&m_t); - m_Registry.AddExposedVariable("Origin Point", glm::value_ptr(m_Origin), GameSmith::ContainerDataType::Float3); - m_Registry.AddExposedVariable("Oribit Radius", &m_Radius, GameSmith::ContainerDataType::Float); - m_Registry.AddExposedVariable("Oribit Speed", glm::value_ptr(m_OribitSpeeds), GameSmith::ContainerDataType::Float3); - m_Registry.AddExposedVariable("Local Rotation Speed", glm::value_ptr(m_LocalSpeeds), GameSmith::ContainerDataType::Float3); - m_Registry.AddExposedVariable("Time Scale", &m_TimeScale, GameSmith::ContainerDataType::Float); - } + class OrbitScript : public GameSmith::Component { + public: + OrbitScript(GameSmith::GameObject* gameObject, GameSmith::Transform* transform) : Component(gameObject, transform) { + GetTransform()->SetCoordinateFrame(&m_t); + m_Registry.AddExposedVariable("Origin Point", GameSmith::ContainerDataType::Float3, glm::value_ptr(m_Origin)); + m_Registry.AddExposedVariable("Oribit Radius", GameSmith::ContainerDataType::Float , &m_Radius); + m_Registry.AddExposedVariable("Oribit Speed", GameSmith::ContainerDataType::Float3, glm::value_ptr(m_OribitSpeeds)); + m_Registry.AddExposedVariable("Local Rotation Speed", GameSmith::ContainerDataType::Float3, glm::value_ptr(m_LocalSpeeds)); + m_Registry.AddExposedVariable("Time Scale", GameSmith::ContainerDataType::Float, &m_TimeScale); + } - virtual void OnStart() override { } - virtual void OnUpdate(float dt); - virtual void OnDestroy() override {} - virtual std::string GetName() const override { return "Demo Script"; }; - virtual int GetPriority() const override { return 0; } - inline void SetTimeScale(float scale) { m_TimeScale = scale; } - inline void SetOribitSpeeds(glm::vec3 speeds) { m_OribitSpeeds = speeds; } - inline void SetLocalRotationSpeed(glm::vec3 speeds) { m_LocalSpeeds = speeds; } - inline void SetOrigin(glm::vec3 newOrigin) { m_Origin = newOrigin; } - inline void SetSphereSize(float newRadius) { m_Radius = newRadius; } + virtual void OnStart() override { } + virtual void OnUpdate(float dt); + virtual void OnDestroy() override {} + virtual std::string GetName() const override { return "Demo Script"; }; + virtual int GetPriority() const override { return 0; } + inline void SetTimeScale(float scale) { m_TimeScale = scale; } + inline void SetOribitSpeeds(glm::vec3 speeds) { m_OribitSpeeds = speeds; } + inline void SetLocalRotationSpeed(glm::vec3 speeds) { m_LocalSpeeds = speeds; } + inline void SetOrigin(glm::vec3 newOrigin) { m_Origin = newOrigin; } + inline void SetSphereSize(float newRadius) { m_Radius = newRadius; } - private: - GameSmith::Transform m_t; - glm::vec3 m_OribitSpeeds = {0,0,0}; - glm::vec3 m_LocalSpeeds = {0,0,0}; - glm::vec3 m_Origin = {0,0,0}; - float m_Radius = 0; - float m_TimeScale = 1; - }; + private: + GameSmith::Transform m_t; + glm::vec3 m_OribitSpeeds = {0,0,0}; + glm::vec3 m_LocalSpeeds = {0,0,0}; + glm::vec3 m_Origin = {0,0,0}; + float m_Radius = 0; + float m_TimeScale = 1; + }; }; diff --git a/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.cpp b/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.cpp new file mode 100644 index 0000000..d304653 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.cpp @@ -0,0 +1,38 @@ +#include "ExposedVariableWidgetConverter.h" +#include "imgui.h" + +namespace GameSmithEditor { + void GenerateVariableUI(GameSmith::Ref container) { + auto name = container->GetName(); + + switch (container->GetType()) { + case GameSmith::ContainerDataType::Float: + ImGui::InputFloat(name.c_str(), (float*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Float2: + ImGui::InputFloat2(name.c_str(), (float*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Float3: + ImGui::InputFloat3(name.c_str(), (float*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Float4: + ImGui::InputFloat4(name.c_str(), (float*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Int: + ImGui::InputInt(name.c_str(), (int*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Int2: + ImGui::InputInt2(name.c_str(), (int*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Int3: + ImGui::InputInt3(name.c_str(), (int*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::Int4: + ImGui::InputInt4(name.c_str(), (int*)container->GetCharData()); + break; + case GameSmith::ContainerDataType::CBuffer: + ImGui::InputText(name.c_str(), (char*)container->GetCharData(), container->GetSize()); + break; + } + } +}; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.h b/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.h new file mode 100644 index 0000000..27fa12a --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Utils/ExposedVariableWidgetConverter.h @@ -0,0 +1,6 @@ +#pragma once +#include "GameSmithEngine.h" + +namespace GameSmithEditor { + void GenerateVariableUI(GameSmith::Ref container); +}; diff --git a/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.cpp b/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.cpp index e4a3a4c..9faa9a3 100644 --- a/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.cpp @@ -14,7 +14,7 @@ namespace GameSmithEditor { - std::string PickFolderDialog(std::string path) + bool PickFolderDialog(const std::string& path, std::string* outPath) { #ifdef GE_PLATFORM_WINDOWS Microsoft::WRL::ComPtr pFileDialog; @@ -37,21 +37,26 @@ namespace GameSmithEditor { Microsoft::WRL::ComPtr pPickedFolder; pFileDialog->GetResult(&pPickedFolder); + if (pPickedFolder.Get() == nullptr) { + return false; + } + wchar_t* filepath; res = FAILED(pPickedFolder->GetDisplayName(SIGDN_FILESYSPATH, &filepath)); GE_APP_ASSERT(!res, "Failed to get result folder name"); std::wstring_convert> wtosConvert; std::wstring resultPath(filepath); - std::string convertResult = wtosConvert.to_bytes(resultPath); + *outPath = wtosConvert.to_bytes(resultPath); - return convertResult; + return true; #endif // GE_PLATFORM_WINDOWS + return false; } - std::string PickFileDialog(std::string path, std::string fileType, std::string filePrefix) + bool PickFileDialog(const FileSearchCriteria& criteria, std::string* outPath) { #ifdef GE_PLATFORM_WINDOWS Microsoft::WRL::ComPtr pFileDialog; @@ -63,8 +68,8 @@ namespace GameSmithEditor { pFileDialog->SetOptions(FOS_STRICTFILETYPES); - std::wstring convertType(fileType.begin(), fileType.end()); - std::string regex = std::format("*.{0}", filePrefix); + std::wstring convertType(criteria.fileType.begin(), criteria.fileType.end()); + std::string regex = std::format("*.{0}", criteria.filePrefix); std::wstring convertPrefix(regex.begin(), regex.end()); COMDLG_FILTERSPEC filter; filter.pszName = convertType.c_str(); @@ -72,7 +77,7 @@ namespace GameSmithEditor { pFileDialog->SetFileTypes(1, &filter); - std::wstring convertPath(path.begin(), path.end()); + std::wstring convertPath(criteria.filePath.begin(), criteria.filePath.end()); Microsoft::WRL::ComPtr pShellItem; res = FAILED(SHCreateItemFromParsingName(convertPath.c_str(), NULL, IID_PPV_ARGS(&pShellItem))); @@ -83,21 +88,25 @@ namespace GameSmithEditor { Microsoft::WRL::ComPtr pPickedFolder; pFileDialog->GetResult(&pPickedFolder); + if (pPickedFolder.Get() == nullptr) { + return false; + } + wchar_t* filepath; res = FAILED(pPickedFolder->GetDisplayName(SIGDN_FILESYSPATH, &filepath)); GE_APP_ASSERT(!res, "Failed to get result folder name"); std::wstring_convert> wtosConvert; std::wstring resultPath(filepath); - std::string convertResult = wtosConvert.to_bytes(resultPath); + *outPath = wtosConvert.to_bytes(resultPath); - return convertResult; + return true; #endif // GE_PLATFORM_WINDOWS - return std::string(); + return false; } - std::string CreateFileDialog(std::string path, std::string fileType, std::string filePrefix) + bool CreateFileDialog(const FileSearchCriteria& criteria, std::string* outPath) { #ifdef GE_PLATFORM_WINDOWS Microsoft::WRL::ComPtr pFileDialog; @@ -109,9 +118,9 @@ namespace GameSmithEditor { pFileDialog->SetOptions(FOS_STRICTFILETYPES | FOS_CREATEPROMPT); - std::wstring convertType(fileType.begin(), fileType.end()); - std::string regex = std::format("*.{0}", filePrefix); - std::string startingFilename = std::format("{0}.{1}", fileType, filePrefix); + std::wstring convertType(criteria.fileType.begin(), criteria.fileType.end()); + std::string regex = std::format("*.{0}", criteria.filePrefix); + std::string startingFilename = std::format("{0}.{1}", criteria.fileType, criteria.filePrefix); std::wstring convertPrefix(regex.begin(), regex.end()); std::wstring convertFilename(startingFilename.begin(), startingFilename.end()); COMDLG_FILTERSPEC filter; @@ -121,7 +130,7 @@ namespace GameSmithEditor { pFileDialog->SetFileTypes(1, &filter); pFileDialog->SetFileName(convertFilename.c_str()); - std::wstring convertPath(path.begin(), path.end()); + std::wstring convertPath(criteria.filePath.begin(), criteria.filePath.end()); Microsoft::WRL::ComPtr pShellItem; res = FAILED(SHCreateItemFromParsingName(convertPath.c_str(), NULL, IID_PPV_ARGS(&pShellItem))); @@ -132,18 +141,22 @@ namespace GameSmithEditor { Microsoft::WRL::ComPtr pPickedFolder; pFileDialog->GetResult(&pPickedFolder); + if (pPickedFolder.Get() == nullptr) { + return false; + } + wchar_t* filepath; res = FAILED(pPickedFolder->GetDisplayName(SIGDN_FILESYSPATH, &filepath)); GE_APP_ASSERT(!res, "Failed to get result folder name"); std::wstring_convert> wtosConvert; std::wstring resultPath(filepath); - std::string convertResult = wtosConvert.to_bytes(resultPath); + *outPath = wtosConvert.to_bytes(resultPath); - return convertResult; + return true; #endif // GE_PLATFORM_WINDOWS - return std::string(); + return false; } diff --git a/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.h b/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.h index 96490b7..aa3ad4c 100644 --- a/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.h +++ b/GameSmithEditor/src/GameSmithEditor/Utils/SystemCallUtils.h @@ -1,9 +1,15 @@ #pragma once namespace GameSmithEditor { - std::string PickFolderDialog(std::string path); - std::string PickFileDialog(std::string path, std::string fileType, std::string filePrefix); - std::string CreateFileDialog(std::string path, std::string fileType, std::string filePrefix); + struct FileSearchCriteria { + std::string filePath; + std::string fileType; + std::string filePrefix = "*"; + }; + + bool PickFolderDialog(const std::string& path, std::string* outPath); + bool PickFileDialog(const FileSearchCriteria& criteria, std::string* outPath); + bool CreateFileDialog(const FileSearchCriteria& criteria, std::string* outPath); }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.cpp index cb041fe..508150d 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.cpp @@ -1,8 +1,11 @@ #include "AssetDatabaseWindow.h" -#include "imgui.h" #include "GameSmithEditor/Core/GameProject.h" -#include "GameSmithEditor/Icons/IconManager.h" #include "GameSmithEditor/CustomWidgets/ReferenceInputWidget.h" +#include "GameSmithEditor/CustomWidgets/SelectableImage.h" +#include "GameSmithEditor/Icons/IconManager.h" +#include "GameSmithEditor/Utils/SystemCallUtils.h" +#include "GameSmithEditor/Windows/PrivateWindows/AssetInspector.h" +#include "imgui.h" using recursive_directory_iterator = std::filesystem::recursive_directory_iterator; @@ -16,6 +19,8 @@ namespace GameSmithEditor { if (GameProject::IsLoaded()) { m_CurrentPath = std::filesystem::path(GameProject::GetAssetFolder()); } + + m_RegisteredAssets = GameSmith::AssetRegistry::GetInstance()->ListRegisteredAssets(); } void AssetDatabaseWindow::OnAttach(const GameSmith::ApplicationSpecs& specs) @@ -36,84 +41,150 @@ namespace GameSmithEditor { void AssetDatabaseWindow::OnImGuiRender() { - ImGui::Begin("Asset Database"); - static float padding = 16.0f; - static float thumbailSize = 256; - float cellSize = thumbailSize + padding; - - float windowWidth = ImGui::GetContentRegionAvail().x; - int columnCount = (int)(windowWidth / cellSize); - if (columnCount < 1) { - columnCount = 1; - } - - if (GameProject::IsLoaded()) { - if (m_CurrentPath == "") { - m_CurrentPath = std::filesystem::path(GameProject::GetAssetFolder()); + if (ImGui::Begin("Asset Database", &m_Open)) { + static float padding = 16.0f; + static float thumbailSize = 256; + float cellSize = thumbailSize + padding; + + float windowWidth = ImGui::GetContentRegionAvail().x; + int columnCount = (int)(windowWidth / cellSize); + if (columnCount < 1) { + columnCount = 1; } - if (m_CurrentPath != std::filesystem::path(GameProject::GetAssetFolder())) { - if (ImGui::Button("Back")) { - m_CurrentPath = m_CurrentPath.parent_path(); + if (GameProject::IsLoaded()) { + if (m_CurrentPath == "") { + m_CurrentPath = std::filesystem::path(GameProject::GetAssetFolder()); } - } - ImGui::Text(m_CurrentPath.filename().string().c_str()); - - if (ImGui::BeginTable("Assets", columnCount)) { - ImGuiStyle& style = ImGui::GetStyle(); - auto oldFramePadding = style.FramePadding; - style.FramePadding = { 0,0 }; - for (const auto& dirEntry : recursive_directory_iterator(m_CurrentPath)) { - std::string fileName = dirEntry.path().filename().string(); - if (fileName.ends_with(".meta")) { - continue; - } - - std::string path = dirEntry.path().string(); - bool isDir = dirEntry.is_directory(); - IconManager* iconManager = IconManager::GetInstance(); - ImTextureID image; - if (isDir) { - void* spot = iconManager->GetImGuiIcon("folder")->gpuSpot; - image = reinterpret_cast(spot); + if (m_CurrentPath != std::filesystem::path(GameProject::GetAssetFolder())) { + if (ImGui::Button("Back")) { + m_CurrentPath = m_CurrentPath.parent_path(); } - else { - auto index = fileName.find_last_of("."); - std::string fileExtention = fileName.substr(index + 1); + } + + ImGui::Text(m_CurrentPath.filename().string().c_str()); - auto filePtr = iconManager->GetImGuiIcon(fileExtention); - if (filePtr == nullptr) { - filePtr = iconManager->GetImGuiIcon("file"); + if (ImGui::Button("+")) { + ImGui::OpenPopup("AssetDatabaseModMenu"); + } + + if (ImGui::BeginPopup("AssetDatabaseModMenu")) { + if (ImGui::Button("ImportAsset")) { + std::string filePath; + FileSearchCriteria criteria; + criteria.filePath = GameProject::GetAssetFolder(); + if (PickFileDialog(criteria, &filePath)) { + auto resourceManager = GameSmith::AssetManager::GetInstance(); + resourceManager->ImportResource(filePath); } + + } - image = reinterpret_cast(filePtr->gpuSpot); + if (ImGui::Button("CreateAsset")) { + ImGui::OpenPopup("AssetDatabaseCreateAssetMenu"); } - if (ImGui::ImageButton(fileName.c_str(), image, { thumbailSize, thumbailSize })) { - if (isDir) { - m_CurrentPath = dirEntry.path(); + if (ImGui::BeginPopup("AssetDatabaseCreateAssetMenu")) { + for (const auto& entry : m_RegisteredAssets) { + const std::string menuLabel = std::format("{1} ({0})", entry.first, entry.second); + if (ImGui::MenuItem(menuLabel.c_str())) { + auto manager = GameSmith::AssetManager::GetInstance(); + + const std::string fileName = std::format("New {1}{0}", entry.first, entry.second); + const std::string path = m_CurrentPath.string(); + manager->CreateResource(fileName, path); + } } + ImGui::EndPopup(); } - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - GameSmith::AssetManager* rManager = GameSmith::AssetManager::GetInstance(); - auto id = rManager->GetAssetID(path); - ImGui::SetDragDropPayload(IMGUI_PAYLOAD_TYPE_ASSET_REF, &id, sizeof(GameSmith::ID)); - ImGui::EndDragDropSource(); - } + ImGui::EndPopup(); + } + + - ImGui::TextWrapped(fileName.c_str()); + ImGui::Separator(); + + if (ImGui::BeginTable("Assets", columnCount)) { ImGui::TableNextColumn(); + ImGuiStyle& style = ImGui::GetStyle(); + auto oldFramePadding = style.FramePadding; + style.FramePadding = { 0,0 }; + for (const auto& dirEntry : recursive_directory_iterator(m_CurrentPath)) { + std::string fileName = dirEntry.path().filename().string(); + if (fileName.ends_with(".meta")) { + continue; + } + + std::string path = dirEntry.path().string(); + bool isDir = dirEntry.is_directory(); + IconManager* iconManager = IconManager::GetInstance(); + ImTextureID image; + if (isDir) { + void* spot = iconManager->GetImGuiIcon("folder")->gpuSpot; + image = reinterpret_cast(spot); + } + else { + auto index = fileName.find_last_of("."); + std::string fileExtention = fileName.substr(index + 1); + + auto filePtr = iconManager->GetImGuiIcon(fileExtention); + if (filePtr == nullptr) { + filePtr = iconManager->GetImGuiIcon("file"); + } + + image = reinterpret_cast(filePtr->gpuSpot); + + } + + ImTextureRef imageRef = ImTextureRef(image); + ImVec2 imageSize = { thumbailSize, thumbailSize }; + bool selected = m_SelectedAsset == fileName; + if (SelectableImage(fileName, selected, imageRef, imageSize)) { + m_SelectedAsset = fileName; + + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { + if (isDir) { + m_CurrentPath = dirEntry.path(); + m_SelectedAsset = ""; + } + else { + GameSmith::AssetManager* rManager = GameSmith::AssetManager::GetInstance(); + auto id = rManager->GetAssetID(path); + auto asset = rManager->GetResource(id); + auto inspector = new AssetInspector(asset); + EditorCoreLayer::GetInstance()->AppendEditorWindow(inspector); + } + } + } + + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + GameSmith::AssetManager* rManager = GameSmith::AssetManager::GetInstance(); + auto id = rManager->GetAssetID(path); + ImGui::SetDragDropPayload(IMGUI_PAYLOAD_TYPE_ASSET_REF, &id, sizeof(GameSmith::ID)); + ImGui::EndDragDropSource(); + } + + ImGui::TextWrapped(fileName.c_str()); + ImGui::TableNextColumn(); + } + style.FramePadding = oldFramePadding; + ImGui::EndTable(); } - style.FramePadding = oldFramePadding; - ImGui::EndTable(); } - } - ImGui::SliderFloat("Thumnail Size", &thumbailSize, 16, 512); - ImGui::SliderFloat("Min Padding", &padding, 0, 32); + ImGui::SliderFloat("Thumnail Size", &thumbailSize, 16, 512); + ImGui::SliderFloat("Min Padding", &padding, 0, 32); + } ImGui::End(); } + + void AssetDatabaseWindow::OnUpdate(float dt) + { + if (!m_Open) { + CloseWindow(); + } + } }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.h b/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.h index 4825780..fdffbe7 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.h +++ b/GameSmithEditor/src/GameSmithEditor/Windows/AssetDatabaseWindow.h @@ -12,9 +12,14 @@ namespace GameSmithEditor { void OnAttach(const GameSmith::ApplicationSpecs& specs) override; void OnDetach() override; void OnImGuiRender() override; + void OnUpdate(float dt) override; private: static int s_Count; std::filesystem::path m_CurrentPath; + std::string m_SelectedAsset = ""; + bool m_Open = true; + + std::vector> m_RegisteredAssets; }; } diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.cpp index bff3592..4632457 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.cpp @@ -12,65 +12,74 @@ namespace GameSmithEditor { void ContentView::OnImGuiRender() { ImGui::SetNextWindowSizeConstraints(ImVec2(20, 20), ImVec2(FLT_MAX, FLT_MAX)); - ImGui::Begin("Content View"); - if (ImGui::Button("Create GameObject")) { - auto gm = GameSmith::GameObjectManager::GetInstance(); - auto object = gm->CreateGameObject(); + if (ImGui::Begin("Content View", &m_Open)) { auto chunkManager = GameSmith::ChunkManager::GetInstance(); - chunkManager->GetCurrentMainChunk().lock()->AddObjectToChunk(object); - m_NamesStd.push_back(object.lock()->GetName()); - } + if (ImGui::Button("Create GameObject")) { + auto gm = GameSmith::GameObjectManager::GetInstance(); + auto object = gm->CreateGameObject(); + chunkManager->GetCurrentMainChunk().lock()->AddObjectToChunk(object); + m_NamesStd.push_back(object.lock()->GetName()); + } - ImGui::SameLine(); + ImGui::SameLine(); - if (ImGui::Button("Save Chunk")) { - auto assetManager = GameSmith::AssetManager::GetInstance(); - auto chunkManager = GameSmith::ChunkManager::GetInstance(); - auto chunk = chunkManager->GetCurrentMainChunk().lock(); - - std::string file = CreateFileDialog( - "C:\\Users\\esaus\\Documents\\Coding Projects\\GameSmithEngine\\bin\\Debug-windows-x86_64\\TestZone", - GameSmith::GameChunkAsset::GetStaticFileType(), - GameSmith::GameChunkAsset::GetStaticFileExtension() - ); - assetManager->WriteResource(chunk, file); - - } + if (ImGui::Button("Save Chunk")) { + auto assetManager = GameSmith::AssetManager::GetInstance(); + auto chunk = chunkManager->GetCurrentMainChunk().lock(); - if (ImGui::Button("Load Chunk")) { - std::string file = PickFileDialog( - "C:\\Users\\esaus\\Documents\\Coding Projects\\GameSmithEngine\\bin\\Debug-windows-x86_64\\TestZone", - GameSmith::GameChunkAsset::GetStaticFileType(), - GameSmith::GameChunkAsset::GetStaticFileExtension() - ); + GameSmith::Ref asset = GameSmith::Ref(new GameSmith::GameChunkAsset(chunk)); - auto assetManager = GameSmith::AssetManager::GetInstance(); - auto ID = assetManager->GetAssetID(file); - auto chunkManager = GameSmith::ChunkManager::GetInstance(); - chunkManager->LoadChunk(ID); - } + std::string location = std::format( + "{0}\\{1}.{2}", + GameProject::GetAssetFolder(), + chunk->GetChunkName(), + GameSmith::GameChunkAsset::GetStaticFileExtension() + ); + assetManager->WriteResource(asset, location); - if (ImGui::BeginListBox("Objects", ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight()))) { - for (int i = 0; i < m_NamesStd.size(); i++) { - bool selected = (m_Selection == i); - if (ImGui::Selectable(m_NamesStd[i].c_str(), selected)) { - auto gm = GameSmith::GameObjectManager::GetInstance(); - Inspector::SetInspectedGameObject(gm->FindGameObject(m_NamesStd[i])); - m_Selection = i; - } + } - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - auto gm = GameSmith::GameObjectManager::GetInstance(); - auto g = gm->FindGameObject(m_NamesStd[i]); - ImGui::SetDragDropPayload(IMGUI_PAYLOAD_TYPE_GAMEOBJECT_REF, &g, sizeof(GameSmith::Connection)); - ImGui::EndDragDropSource(); + if (ImGui::Button("Load Chunk")) { + std::string file; + FileSearchCriteria criteria; + criteria.filePath = GameProject::GetAssetFolder(); + criteria.fileType = GameSmith::GameChunkAsset::GetStaticFileType(); + criteria.filePrefix = GameSmith::GameChunkAsset::GetStaticFileExtension(); + if (PickFileDialog(criteria, &file)) { + auto assetManager = GameSmith::AssetManager::GetInstance(); + auto ID = assetManager->GetAssetID(file); + auto chunkManager = GameSmith::ChunkManager::GetInstance(); + chunkManager->LoadChunk(ID); } + } + + std::string chunkName = chunkManager->GetCurrentMainChunk().lock()->GetChunkName(); + std::string labelName = std::format("##{}", chunkName); + if (ImGui::CollapsingHeader(chunkName.c_str())) { + if (ImGui::BeginListBox(labelName.c_str(), ImVec2(ImGui::GetWindowWidth() - 25, ImGui::GetWindowHeight() / 2))) { + for (int i = 0; i < m_NamesStd.size(); i++) { + bool selected = (m_Selection == i); + if (ImGui::Selectable(m_NamesStd[i].c_str(), selected)) { + auto gm = GameSmith::GameObjectManager::GetInstance(); + Inspector::SetInspectedGameObject(gm->FindGameObject(m_NamesStd[i])); + m_Selection = i; + } + + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + auto gm = GameSmith::GameObjectManager::GetInstance(); + auto g = gm->FindGameObject(m_NamesStd[i]); + ImGui::SetDragDropPayload(IMGUI_PAYLOAD_TYPE_GAMEOBJECT_REF, &g, sizeof(GameSmith::Connection)); + ImGui::EndDragDropSource(); + } - if (selected) { - ImGui::SetItemDefaultFocus(); + if (selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndListBox(); } } - ImGui::EndListBox(); + } ImGui::End(); @@ -78,9 +87,13 @@ namespace GameSmithEditor { void ContentView::OnUpdate(float dt) { - auto gameObjectMang = GameSmith::GameObjectManager::GetInstance(); m_NamesStd.clear(); - gameObjectMang->GetGameObjectNames(&m_NamesStd); + auto chunkManager = GameSmith::ChunkManager::GetInstance(); + chunkManager->GetCurrentMainChunk().lock()->GetChunkGameObjectNames(&m_NamesStd); + + if (!m_Open) { + CloseWindow(); + } } }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.h b/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.h index 78f0fd4..2a93044 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.h +++ b/GameSmithEditor/src/GameSmithEditor/Windows/ContentView.h @@ -12,6 +12,7 @@ namespace GameSmithEditor { private: int m_Selection = 0; std::vector m_NamesStd; + bool m_Open = true; }; }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.cpp new file mode 100644 index 0000000..b78fb49 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.cpp @@ -0,0 +1,66 @@ +#include "EditorView.h" +#include "imgui.h" + +namespace GameSmithEditor { + REGISTER_WINDOW_DEFAULT_CALLBACK(Windows_EditorView, EditorView); + + GameSmith::Ref EditorView::s_EditorScreenTexture = nullptr; + GameSmith::PerspectiveCamera EditorView::s_PerpCamera = GameSmith::PerspectiveCamera(1, 1, 1, 1, 1); + GameSmith::OrthoCamera EditorView::s_OrthoCamera = GameSmith::OrthoCamera(); + + EditorView::EditorView() : EditorWindow("Editor View") { + auto& app = GameSmith::Application::Get(); + auto renderManager = GameSmith::RenderingManager::GetInstance(); + if (s_EditorScreenTexture == nullptr) { + float color[4] = { 0.07f, 0.0f, 0.12f, 1.0f }; + s_EditorScreenTexture = renderManager->GetRenderAPI()->CreateRenderTexture(app.GetWindow()->GetWidth(), app.GetWindow()->GetHeight(), color); + GameSmith::RegisterEvent(&GameSmith::Window::s_Resized, GE_BIND_EVENT_FN(GameSmith::RenderTexture::WindowResized, s_EditorScreenTexture.get()), false); + s_PerpCamera = GameSmith::PerspectiveCamera(); + } + + m_EditorViewHandle = app.GetImGuiInstance()->GenerateTextureSpace(s_EditorScreenTexture); + } + + void EditorView::OnImGuiRender() + { + if (ImGui::Begin("Editor View", &m_Open)) { + ImTextureRef texRef = ImTextureRef((ImTextureID)m_EditorViewHandle->gpuSpot); + ImGui::Image(texRef, ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight())); + + if (ImGui::IsWindowFocused()) { + m_Dragging = ImGui::IsMouseDragging(ImGuiMouseButton_::ImGuiMouseButton_Middle); + if (m_Dragging) { + const ImVec2 drag = ImGui::GetMouseDragDelta(ImGuiMouseButton_::ImGuiMouseButton_Middle); + m_DragDir = glm::vec2(drag.x, drag.y); + GE_APP_INFO("DRAGGING: ({0}, {1})", drag.x, drag.y); + } + } + } + ImGui::End(); + } + + void EditorView::OnUpdate(float dt) + { + if (!m_Open) { + CloseWindow(); + } + + auto entityPreparer = GameSmith::EntityRenderPreparer::GetInstance(); + GameSmith::RenderableCamera renderCam; + renderCam.cam = &s_PerpCamera; + renderCam.targetTex = s_EditorScreenTexture; + entityPreparer->AddAdditionalCamera(renderCam); + + if (m_Dragging) { + auto& perCamTrans = s_PerpCamera.GetTransform(); + glm::vec3 curPosition = perCamTrans.GetPosition(); + glm::vec2 camChange = m_DragDir * m_DragSensitivity * dt; + + glm::vec3 newPosition = glm::vec3(curPosition.x + camChange.x, curPosition.y + camChange.y, curPosition.z); + perCamTrans.SetPosition(newPosition); + } + + auto renderManager = GameSmith::RenderingManager::GetInstance(); + renderManager->SetForClear(s_EditorScreenTexture); + } +}; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.h b/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.h new file mode 100644 index 0000000..00c273d --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/EditorView.h @@ -0,0 +1,25 @@ +#pragma once +#include "GameSmithEngine.h" +#include "EditorWindow.h" + +#define DEFAULT_SENSITIVITY 1 +namespace GameSmithEditor { + class EditorView : public EditorWindow { + public: + EditorView(); + void OnImGuiRender() override; + void OnUpdate(float dt) override; + private: + static GameSmith::Ref s_EditorScreenTexture; + static GameSmith::PerspectiveCamera s_PerpCamera; + static GameSmith::OrthoCamera s_OrthoCamera; + private: + const GameSmith::ImGuiTextureSpace* m_EditorViewHandle; + bool m_Open = true; + + bool m_Dragging; + glm::vec2 m_DragDir; + + float m_DragSensitivity = DEFAULT_SENSITIVITY; + }; +}; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindow.h b/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindow.h index a460aa4..3c4e294 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindow.h +++ b/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindow.h @@ -1,5 +1,4 @@ #pragma once -#include "GameSmithEngine.h" #include "GameSmithEditor/Core/EditorMenu.h" #include "GameSmithEditor/Core/EditorCoreLayer.h" @@ -7,10 +6,3 @@ MENUPATH,\ []() {GameSmithEditor::EditorCoreLayer::CreateEditorWindow(); } \ ) - -namespace GameSmithEditor { - class EditorWindow : public GameSmith::Layer { - public: - EditorWindow(std::string name) : GameSmith::Layer(name) {} - }; -}; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindowEvents.h b/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindowEvents.h new file mode 100644 index 0000000..14f7a1e --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/EditorWindowEvents.h @@ -0,0 +1,19 @@ +#pragma once +#include + +namespace GameSmithEditor { + // Forward declaration + class EditorWindow; + + class EditorWindowClose : public GameSmith::Event { + public: + EditorWindowClose(EditorWindow* window) : m_ClosingWindow(window) { + } + + EVENT_TYPE(MISCELLENIOUS) + private: + CATEGORY_TYPE(GameSmith::EventCategory::APP_EVENT) + private: + EditorWindow* m_ClosingWindow; + }; +}; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.cpp index bc79be9..7fbea03 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.cpp @@ -19,10 +19,10 @@ namespace GameSmithEditor { void GameViewLayer::OnImGuiRender() { - if (ImGui::Begin("Game View")) { + if (ImGui::Begin("Game View", &m_Open)) { ImGui::Image((ImTextureID)m_GameViewHandle->gpuSpot, ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight())); - ImGui::End(); } + ImGui::End(); } @@ -33,6 +33,9 @@ namespace GameSmithEditor { m_GameScreenTexture->CopyTexture(m_GameViewTexture); } + if (!m_Open) { + CloseWindow(); + } } }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.h b/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.h index b421510..6a562ae 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.h +++ b/GameSmithEditor/src/GameSmithEditor/Windows/GameViewLayer.h @@ -13,6 +13,7 @@ namespace GameSmithEditor { static GameSmith::Ref m_GameScreenTexture; GameSmith::Ref m_GameViewTexture; const GameSmith::ImGuiTextureSpace* m_GameViewHandle; + bool m_Open = true; }; }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.cpp index d949c3c..49629b6 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.cpp +++ b/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.cpp @@ -1,7 +1,7 @@ #include "Inspector.h" -#include "ContentView.h" #include "GameSmithEditor/CustomWidgets/ReferenceInputWidget.h" #include "imgui.h" +#include "GameSmithEditor/Utils/ExposedVariableWidgetConverter.h" namespace GameSmithEditor { @@ -9,154 +9,122 @@ namespace GameSmithEditor { REGISTER_WINDOW_DEFAULT_CALLBACK(Windows_Inspector, Inspector); - - static void GenerateVariableUI(GameSmith::Ref container) { - auto name = container->GetName(); - - switch (container->GetType()) { - case GameSmith::ContainerDataType::Float: - ImGui::InputFloat(name.c_str(), (float*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Float2: - ImGui::InputFloat2(name.c_str(), (float*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Float3: - ImGui::InputFloat3(name.c_str(), (float*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Float4: - ImGui::InputFloat4(name.c_str(), (float*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Int: - ImGui::InputInt(name.c_str(), (int*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Int2: - ImGui::InputInt2(name.c_str(), (int*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Int3: - ImGui::InputInt3(name.c_str(), (int*)container->GetCharData()); - break; - case GameSmith::ContainerDataType::Int4: - ImGui::InputInt4(name.c_str(), (int*)container->GetCharData()); - break; - } - } - void Inspector::OnImGuiRender() { - ImGui::Begin("Inspector"); - if (!m_Object.expired()) { - auto name = m_Object.lock()->GetName(); - strcpy(m_InputName, name.c_str()); - ImGui::PushItemWidth(ImGui::GetWindowWidth() / 2); - ImGui::SameLine(); - ImGui::InputText("##GameObjectName", m_InputName, GAMEOBJECT_NAME_SIZE); - if (ImGui::IsItemDeactivatedAfterEdit()) { - m_Object.lock()->SetName(std::string(m_InputName, GAMEOBJECT_NAME_SIZE)); - } - ImGui::PopItemWidth(); - ImGui::SameLine(); - - - ImGuiStyle& style = ImGui::GetStyle(); - auto defaultStyle = style.Colors[ImGuiCol_Button]; - style.Colors[ImGuiCol_Button] = ImVec4(0.95f, 0.125f, 0.344f, 1.0f); - if (ImGui::Button("Delete")) { - GameSmith::GameObjectManager::GetInstance()->DestroyGameObject(m_Object); - } - style.Colors[ImGuiCol_Button] = defaultStyle; - - ImGui::Separator(); + if (ImGui::Begin("Inspector", &m_Open)) { + if (!m_Object.expired()) { + auto name = m_Object.lock()->GetName(); + strcpy(m_InputName, name.c_str()); + ImGui::PushItemWidth(ImGui::GetWindowWidth() / 2); + ImGui::SameLine(); + ImGui::InputText("##GameObjectName", m_InputName, GAMEOBJECT_NAME_SIZE); + if (ImGui::IsItemDeactivatedAfterEdit()) { + m_Object.lock()->SetName(std::string(m_InputName, GAMEOBJECT_NAME_SIZE)); + } + ImGui::PopItemWidth(); + ImGui::SameLine(); - if (ImGui::CollapsingHeader("Transform")) { - auto lockTransform = m_Object.lock()->GetTransform().lock(); - glm::vec3 pos = lockTransform->GetPosition(); - glm::vec3 rot = lockTransform->GetRotation(); - glm::vec3 scale = lockTransform->GetScale(); - ImGui::InputFloat3("Position", glm::value_ptr(pos)); - ImGui::InputFloat3("Rotation", glm::value_ptr(rot)); - ImGui::InputFloat3("Scale", glm::value_ptr(scale)); + ImGuiStyle& style = ImGui::GetStyle(); + auto defaultStyle = style.Colors[ImGuiCol_Button]; + style.Colors[ImGuiCol_Button] = ImVec4(0.95f, 0.125f, 0.344f, 1.0f); + if (ImGui::Button("Delete")) { + GameSmith::GameObjectManager::GetInstance()->DestroyGameObject(m_Object); + } + style.Colors[ImGuiCol_Button] = defaultStyle; - lockTransform->SetPosition(pos); - lockTransform->SetRotation(rot); - lockTransform->SetScale(scale); - } + ImGui::Separator(); - for (auto comp : m_Components) { - std::string name = comp.lock()->GetName(); - if (ImGui::CollapsingHeader(name.c_str())) { - //TODO: Reflect the components on the gameobject - auto variableMap = m_ExposedVariables.find(name)->second; - for (auto& entry : variableMap) { - auto parameter = entry.second; - GenerateVariableUI(parameter); - } + if (ImGui::CollapsingHeader("Transform")) { + auto lockTransform = m_Object.lock()->GetTransform().lock(); + glm::vec3 pos = lockTransform->GetPosition(); + glm::vec3 rot = lockTransform->GetRotation(); + glm::vec3 scale = lockTransform->GetScale(); - auto refMap = m_ExposedRefs.find(name)->second; - for (auto& entry : refMap) { - InputReference(entry.first, entry.second); - } - - auto assetMap = m_ExposedAssets.find(name)->second; - for (auto& entry : assetMap) { - InputReference(entry.first, entry.second); - } + ImGui::InputFloat3("Position", glm::value_ptr(pos)); + ImGui::InputFloat3("Rotation", glm::value_ptr(rot)); + ImGui::InputFloat3("Scale", glm::value_ptr(scale)); + lockTransform->SetPosition(pos); + lockTransform->SetRotation(rot); + lockTransform->SetScale(scale); } - } - - if (ImGui::Button("AddComponent")) { - ImGui::OpenPopup("Component Picker"); - } - if (ImGui::BeginPopupModal("Component Picker")) { - if (ImGui::BeginListBox("Component Options", ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight() * 0.5f))) { - auto compRegistry = GameSmith::ComponentRegistry::GetInstance(); - std::vector availableComps; - compRegistry->ListRegisteredComponents(&availableComps); - - for (auto entry : availableComps) { - if (ImGui::Selectable(entry.c_str(), entry == m_CurCompSelection)) { - m_CurCompSelection = entry; + for (auto comp : m_Components) { + std::string name = comp.lock()->GetName(); + if (ImGui::CollapsingHeader(name.c_str())) { + auto& groupings = comp.lock()->GetExposedGroupings(); + for (auto& group : groupings) { + bool showVariables = true; + if (group.first != "") { + showVariables = ImGui::CollapsingHeader(group.first.c_str()); + } + + if (showVariables) { + auto& variableMap = m_ExposedVariables[name]; + auto& refMap = m_ExposedRefs[name]; + auto& assetMap = m_ExposedAssets[name]; + + for (auto& variableName : group.second) { + if (variableMap.contains(variableName)) { + auto parameter = variableMap[variableName]; + GenerateVariableUI(parameter); + } + else if (refMap.contains(variableName)) { + auto connection = refMap[variableName]; + InputReference(variableName, connection); + } + else if (assetMap.contains(variableName)) { + auto assetRef = assetMap[variableName]; + InputReference(variableName, assetRef); + } + } + } } + //TODO: Reflect the components on the gameobject } + } - - ImGui::EndListBox(); + if (ImGui::Button("AddComponent")) { + ImGui::OpenPopup("Component Picker"); } - if (ImGui::Button("Add", ImVec2(120, 0))) { - auto newComponent = m_Object.lock()->AddComponent(m_CurCompSelection).lock(); - m_Components.push_back(newComponent); - std::unordered_map> compMap; - std::unordered_map> refMap; - std::unordered_map> assetMap; - newComponent->GenerateVariableEntries(&compMap); - newComponent->GenerateConnectionEntries(&refMap); - newComponent->GenerateAssetEntries(&assetMap); - m_ExposedVariables.insert({ newComponent->GetName(), compMap }); - m_ExposedRefs.insert({ newComponent->GetName(), refMap }); - m_ExposedAssets.insert({ newComponent->GetName(), assetMap }); - - // TODO: Temporary - if (m_CurCompSelection == "MeshRenderer") { - auto renderer = GameSmith::CastPtr(newComponent); - renderer->SetMesh(GameSmith::AssetManager::GetInstance()->GetResource(GameSmith::ID(250309786, 50043, 18339, 17854270087279912363))); - - auto mat = GameSmith::AssetManager::GetInstance()->GetResource(GameSmith::ID(2652798047, 63418, 17489, 6150598651790595990)); - for (unsigned int i = 0; i < renderer->GetMaterialSlots(); i++) { - renderer->SetMaterial(i, mat); + if (ImGui::BeginPopupModal("Component Picker")) { + if (ImGui::BeginListBox("Component Options", ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight() * 0.5f))) { + auto compRegistry = GameSmith::ComponentRegistry::GetInstance(); + std::vector availableComps; + compRegistry->ListRegisteredComponents(&availableComps); + + for (auto entry : availableComps) { + if (ImGui::Selectable(entry.c_str(), entry == m_CurCompSelection)) { + m_CurCompSelection = entry; + } } + ImGui::EndListBox(); } - m_CurCompSelection = ""; - ImGui::CloseCurrentPopup(); + if (ImGui::Button("Add", ImVec2(120, 0))) { + auto newComponent = m_Object.lock()->AddComponent(m_CurCompSelection).lock(); + m_Components.push_back(newComponent); + std::unordered_map> compMap; + std::unordered_map> refMap; + std::unordered_map> assetMap; + newComponent->GenerateVariableEntries(&compMap); + newComponent->GenerateConnectionEntries(&refMap); + newComponent->GenerateAssetEntries(&assetMap); + m_ExposedVariables.insert({ newComponent->GetName(), compMap }); + m_ExposedRefs.insert({ newComponent->GetName(), refMap }); + m_ExposedAssets.insert({ newComponent->GetName(), assetMap }); + + m_CurCompSelection = ""; + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - 120); + if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } + ImGui::EndPopup(); } - ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - 120); - if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } - ImGui::EndPopup(); } } @@ -169,6 +137,7 @@ namespace GameSmithEditor { m_Components.clear(); m_ExposedVariables.clear(); m_ExposedRefs.clear(); + m_ExposedAssets.clear(); if (s_SelectedObject.lock().get()) { m_Object = s_SelectedObject; @@ -197,6 +166,10 @@ namespace GameSmithEditor { comp.lock()->BootstrapAssetRegistry(assetMap); } } + + if (!m_Open) { + CloseWindow(); + } } void Inspector::SetInspectedGameObject(GameSmith::Connection object) diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.h b/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.h index 2d1397a..4597ef1 100644 --- a/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.h +++ b/GameSmithEditor/src/GameSmithEditor/Windows/Inspector.h @@ -12,7 +12,6 @@ namespace GameSmithEditor { void OnUpdate(float dt) override; private: GameSmith::Connection m_Object; - GameSmith::Connection m_Asset; std::vector> m_Components; @@ -26,6 +25,8 @@ namespace GameSmithEditor { static void SetInspectedGameObject(GameSmith::Connection object); private: static GameSmith::Connection s_SelectedObject; + private: + bool m_Open = true; }; }; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.cpp new file mode 100644 index 0000000..64d47b3 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.cpp @@ -0,0 +1,78 @@ +#include "AssetInspector.h" +#include "imgui.h" + +#include "GameSmithEditor/Utils/ExposedVariableWidgetConverter.h" +#include "GameSmithEditor/CustomWidgets/ReferenceInputWidget.h" + +#include + +namespace fs = std::filesystem; + +namespace GameSmithEditor { + AssetInspector::AssetInspector(GameSmith::Ref asset) : EditorWindow("AssetInspector"), m_InspectedAsset(asset) + { + m_InspectedAsset->GenerateVariableEntries(&m_ExposedVariables); + m_InspectedAsset->GenerateAssetEntries(&m_ExposedAssets); + m_InspectedAsset->GenerateConnectionEntries(&m_ExposedRefs); + } + + void AssetInspector::OnImGuiRender() + { + if (ImGui::Begin("Asset Inspector##", &m_Open)) { + const std::string& assetName = m_InspectedAsset->GetName(); + ImGui::PushItemWidth(ImGui::GetWindowWidth() / 2); + ImGui::Text(assetName.c_str()); + ImGui::PopItemWidth(); + ImGui::SameLine(); + if (ImGui::Button("Save")) { + auto assetManager = GameSmith::AssetManager::GetInstance(); + const std::string filePath = assetManager->GetAssetPath(m_InspectedAsset->GetID()); + fs::path filePathObj(filePath); + assetManager->WriteResource(m_InspectedAsset, filePathObj.parent_path().string()); + } + + ImGui::Separator(); + + auto& groupings = m_InspectedAsset->GetExposedGroupings(); + for (auto& group : groupings) { + bool showVariables = true; + if (group.first != "") { + showVariables = ImGui::CollapsingHeader(group.first.c_str()); + } + + if (showVariables) { + auto& variableMap = m_ExposedVariables; + auto& refMap = m_ExposedRefs; + auto& assetMap = m_ExposedAssets; + + for (auto& variableName : group.second) { + if (variableMap.contains(variableName)) { + auto parameter = variableMap[variableName]; + GenerateVariableUI(parameter); + } + else if (refMap.contains(variableName)) { + auto connection = refMap[variableName]; + InputReference(variableName, connection); + } + else if (assetMap.contains(variableName)) { + auto assetRef = assetMap[variableName]; + InputReference(variableName, assetRef); + } + } + } + } + } + ImGui::End(); + } + + void AssetInspector::OnUpdate(float dt) + { + if (!m_Open) { + CloseWindow(); + } + + m_InspectedAsset->BootstrapVariableRegistry(m_ExposedVariables); + m_InspectedAsset->BootstrapAssetRegistry(m_ExposedAssets); + m_InspectedAsset->BootstrapConnectionRegistry(m_ExposedRefs); + } +}; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.h b/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.h new file mode 100644 index 0000000..1394141 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/PrivateWindows/AssetInspector.h @@ -0,0 +1,19 @@ +#pragma once +#include "GameSmithEditor/Windows/EditorWindow.h" +#include "GameSmithEngine.h" + +namespace GameSmithEditor { + class AssetInspector : public EditorWindow { + public: + AssetInspector(GameSmith::Ref asset); + void OnImGuiRender() override; + void OnUpdate(float dt) override; + private: + GameSmith::Ref m_InspectedAsset; + std::unordered_map> m_ExposedVariables; + std::unordered_map> m_ExposedRefs; + std::unordered_map> m_ExposedAssets; + + bool m_Open = true; + }; +}; diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.cpp b/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.cpp new file mode 100644 index 0000000..656811b --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.cpp @@ -0,0 +1,62 @@ +#include "GameSmithEditor/Core/GameProject.h" +#include "GameSmithEditor/Utils/SystemCallUtils.h" +#include "imgui.h" +#include "ProjectCreatorWindow.h" + +namespace GameSmithEditor { + REGISTER_WINDOW_DEFAULT_CALLBACK(Files_CreateProject, ProjectCreatorWindow); + + void ProjectCreatorWindow::OnImGuiRender() + { + ImGuiWindowFlags windowFlags = 0; + windowFlags |= ImGuiWindowFlags_NoBackground; + windowFlags |= ImGuiWindowFlags_NoTitleBar; + + if (ImGui::Begin("Project Create Window", &m_Open, windowFlags)) { + if (!m_PopupOpen) { + ImGui::OpenPopup("Project Creator"); + m_PopupOpen = true; + } + + if (ImGui::BeginPopupModal("Project Creator")) { + ImGui::InputText("Project Name", m_ProjectName.data(), m_ProjectName.size()); + ImGui::InputText("Project Path", m_ProjectPath.data(), m_ProjectPath.size()); + ImGui::SameLine(); + if (ImGui::Button("Browse", ImVec2(120, 0))) { + std::string path; + if (PickFolderDialog("", &path)) { + path.copy(m_ProjectPath.data(), m_ProjectPath.size()); + } + }; + + ImGui::Separator(); + + const float footer_height = ImGui::GetFrameHeightWithSpacing(); + ImGui::SetCursorPosY(ImGui::GetWindowHeight() - footer_height); + if (ImGui::Button("Create", ImVec2(120, 0))) { + m_Complete = true; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + } + + ImGui::End(); + + } + + void ProjectCreatorWindow::OnUpdate(float dt) + { + if (m_Complete) { + GameProject::CreateProject( + std::string(m_ProjectName.data(), strlen(m_ProjectName.data())), + std::string(m_ProjectPath.data(), strlen(m_ProjectPath.data())) + ); + m_Open = false; + } + + if (!m_Open) { + CloseWindow(); + } + } +}; \ No newline at end of file diff --git a/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.h b/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.h new file mode 100644 index 0000000..173e7c2 --- /dev/null +++ b/GameSmithEditor/src/GameSmithEditor/Windows/ProjectCreatorWindow.h @@ -0,0 +1,21 @@ +#pragma once +#include "GameSmithEngine.h" +#include "EditorWindow.h" + +#define PROJECT_NAME_SIZE 256 +#define PROJECT_PATH_SIZE 256 +namespace GameSmithEditor { + class ProjectCreatorWindow : public EditorWindow + { + public: + ProjectCreatorWindow() : EditorWindow("Project Creator") {} + void OnImGuiRender() override; + void OnUpdate(float dt) override; + private: + bool m_Open = true; + bool m_Complete = false; + bool m_PopupOpen = false; + std::array m_ProjectName = { '\0' }; + std::array m_ProjectPath = { '\0' }; + }; +}; diff --git a/GameSmithEngine/GameSmithEngine.vcxproj b/GameSmithEngine/GameSmithEngine.vcxproj index 55bf673..50b0614 100644 --- a/GameSmithEngine/GameSmithEngine.vcxproj +++ b/GameSmithEngine/GameSmithEngine.vcxproj @@ -26,19 +26,19 @@ DynamicLibrary true Unicode - v143 + v145 DynamicLibrary false Unicode - v143 + v145 DynamicLibrary false Unicode - v143 + v145 @@ -84,17 +84,24 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 Windows true + third-party\dxc;%(AdditionalLibraryDirectories) ..\bin\Debug-windows-x86_64\GameSmithEngine\GameSmithEngine.lib + + - cmd /c xcopy "..\bin\Debug-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Debug-windows-x86_64\TestZone" /E /Y /I + cmd /c xcopy "$(SolutionDir)\GameSmithEngine\third-party\dxc\*" %[../bin/Debug-windows-x86_64/GameSmithEngine /E /Y /I +cmd /c xcopy "..\bin\Debug-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Debug-windows-x86_64\GameSmithEngineTestSuite" /E /Y /I +cmd /c xcopy "..\bin\Debug-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Debug-windows-x86_64\TestZone" /E /Y /I +cmd /c xcopy "..\bin\Debug-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Debug-windows-x86_64\GameSmithEditor" /E /Y /I +cmd /c xcopy "..\bin\Debug-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Debug-windows-x86_64\GEStandaloneGameApp" /E /Y /I @@ -110,7 +117,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -118,10 +125,17 @@ Windows true true + third-party\dxc;%(AdditionalLibraryDirectories) ..\bin\Release-windows-x86_64\GameSmithEngine\GameSmithEngine.lib + + - cmd /c xcopy "..\bin\Release-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Release-windows-x86_64\TestZone" /E /Y /I + cmd /c xcopy "$(SolutionDir)\GameSmithEngine\third-party\dxc\*" %[../bin/Release-windows-x86_64/GameSmithEngine /E /Y /I +cmd /c xcopy "..\bin\Release-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Release-windows-x86_64\GameSmithEngineTestSuite" /E /Y /I +cmd /c xcopy "..\bin\Release-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Release-windows-x86_64\TestZone" /E /Y /I +cmd /c xcopy "..\bin\Release-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Release-windows-x86_64\GameSmithEditor" /E /Y /I +cmd /c xcopy "..\bin\Release-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Release-windows-x86_64\GEStandaloneGameApp" /E /Y /I @@ -137,7 +151,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -145,10 +159,17 @@ Windows true true + third-party\dxc;%(AdditionalLibraryDirectories) ..\bin\Dist-windows-x86_64\GameSmithEngine\GameSmithEngine.lib + + - cmd /c xcopy "..\bin\Dist-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Dist-windows-x86_64\TestZone" /E /Y /I + cmd /c xcopy "$(SolutionDir)\GameSmithEngine\third-party\dxc\*" %[../bin/Dist-windows-x86_64/GameSmithEngine /E /Y /I +cmd /c xcopy "..\bin\Dist-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Dist-windows-x86_64\GameSmithEngineTestSuite" /E /Y /I +cmd /c xcopy "..\bin\Dist-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Dist-windows-x86_64\TestZone" /E /Y /I +cmd /c xcopy "..\bin\Dist-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Dist-windows-x86_64\GameSmithEditor" /E /Y /I +cmd /c xcopy "..\bin\Dist-windows-x86_64\GameSmithEngine\*" "$(SolutionDir)\bin\Dist-windows-x86_64\GEStandaloneGameApp" /E /Y /I @@ -196,6 +217,7 @@ + @@ -208,6 +230,7 @@ + @@ -231,6 +254,7 @@ + @@ -254,6 +278,8 @@ + + @@ -264,13 +290,17 @@ + + - + + + @@ -279,6 +309,7 @@ + @@ -810,6 +841,7 @@ + @@ -819,6 +851,7 @@ + @@ -836,12 +869,16 @@ + + + + @@ -849,15 +886,19 @@ + - + + + + Create diff --git a/GameSmithEngine/GameSmithEngine.vcxproj.filters b/GameSmithEngine/GameSmithEngine.vcxproj.filters index 89b703c..e6abfb1 100644 --- a/GameSmithEngine/GameSmithEngine.vcxproj.filters +++ b/GameSmithEngine/GameSmithEngine.vcxproj.filters @@ -121,6 +121,9 @@ {79567AD4-E572-6CC5-AE4A-D9321A26D686} + + {74095786-E027-6B53-29F5-70659552A65C} + {2FAB3559-1B92-F750-C4E2-5D6EB0A870B7} @@ -345,6 +348,9 @@ src\GameSmithEngine\ImGui + + src\GameSmithEngine\ImGui + src\GameSmithEngine\Platform\Window @@ -381,6 +387,9 @@ src\GameSmithEngine\Rendering\DirectX12 + + src\GameSmithEngine\Rendering\DirectX12 + src\GameSmithEngine\Rendering\DirectX12\HeapStructures @@ -450,6 +459,9 @@ src\GameSmithEngine\Rendering\DirectX12\Util + + src\GameSmithEngine\Rendering\DirectX12\Util + src\GameSmithEngine\Rendering\DirectX12\Util @@ -519,6 +531,12 @@ src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders @@ -549,6 +567,9 @@ src\GameSmithEngine\ResourceManagement\ResourceLoaders + + src\GameSmithEngine\SerializeableFiles + src\GameSmithEngine\SerializeableFiles\GenericFileTypes @@ -558,6 +579,9 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets + src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -567,8 +591,14 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets - - src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes + + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes + + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -594,6 +624,9 @@ src\GameSmithEngine\Utilities\Locks + + src\GameSmithEngine\Utilities + src\GameSmithEngine\Utilities @@ -2183,6 +2216,9 @@ src\GameSmithEngine\ImGui + + src\GameSmithEngine\ImGui + src\GameSmithEngine\Platform\Window @@ -2210,6 +2246,9 @@ src\GameSmithEngine\Rendering\DirectX12 + + src\GameSmithEngine\Rendering\DirectX12 + src\GameSmithEngine\Rendering\DirectX12\HeapStructures @@ -2261,6 +2300,9 @@ src\GameSmithEngine\Rendering\DirectX12\State + + src\GameSmithEngine\Rendering\DirectX12\Util + src\GameSmithEngine\Rendering\DirectX12\Util @@ -2279,6 +2321,15 @@ src\GameSmithEngine\Rendering\RenderAgnostics\MaterialSystem + + src\GameSmithEngine\Rendering\RenderAgnostics\RenderComponents + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders + src\GameSmithEngine\Rendering @@ -2300,6 +2351,9 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets + src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -2309,8 +2363,8 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets - - src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -2327,11 +2381,16 @@ src\GameSmithEngine\Utilities\Locks + + src\GameSmithEngine\Utilities + src third-party\stb + + \ No newline at end of file diff --git a/GameSmithEngine/GameSmithEngineStatic.vcxproj b/GameSmithEngine/GameSmithEngineStatic.vcxproj index d2683eb..2dbafb9 100644 --- a/GameSmithEngine/GameSmithEngineStatic.vcxproj +++ b/GameSmithEngine/GameSmithEngineStatic.vcxproj @@ -26,19 +26,19 @@ StaticLibrary true Unicode - v143 + v145 StaticLibrary false Unicode - v143 + v145 StaticLibrary false Unicode - v143 + v145 @@ -81,7 +81,7 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -89,9 +89,8 @@ Windows true - - IF EXIST ..\bin\Debug-windows-x86_64\GameSmithEngineStatic\**.cso\ (xcopy /Q /E /Y /I ..\bin\Debug-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Debug-windows-x86_64\TestZone > nul) ELSE (xcopy /Q /Y /I ..\bin\Debug-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Debug-windows-x86_64\TestZone > nul) - + + @@ -106,7 +105,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -115,9 +114,8 @@ true true - - IF EXIST ..\bin\Release-windows-x86_64\GameSmithEngineStatic\**.cso\ (xcopy /Q /E /Y /I ..\bin\Release-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Release-windows-x86_64\TestZone > nul) ELSE (xcopy /Q /Y /I ..\bin\Release-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Release-windows-x86_64\TestZone > nul) - + + @@ -132,7 +130,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -141,9 +139,8 @@ true true - - IF EXIST ..\bin\Dist-windows-x86_64\GameSmithEngineStatic\**.cso\ (xcopy /Q /E /Y /I ..\bin\Dist-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Dist-windows-x86_64\TestZone > nul) ELSE (xcopy /Q /Y /I ..\bin\Dist-windows-x86_64\GameSmithEngineStatic\**.cso ..\bin\Dist-windows-x86_64\TestZone > nul) - + + @@ -190,6 +187,7 @@ + @@ -202,6 +200,7 @@ + @@ -225,6 +224,7 @@ + @@ -248,6 +248,8 @@ + + @@ -258,13 +260,17 @@ + + - + + + @@ -273,6 +279,7 @@ + @@ -804,6 +811,7 @@ + @@ -813,6 +821,7 @@ + @@ -830,12 +839,16 @@ + + + + @@ -843,15 +856,17 @@ + - + + Create diff --git a/GameSmithEngine/GameSmithEngineStatic.vcxproj.filters b/GameSmithEngine/GameSmithEngineStatic.vcxproj.filters index 89b703c..5c02e65 100644 --- a/GameSmithEngine/GameSmithEngineStatic.vcxproj.filters +++ b/GameSmithEngine/GameSmithEngineStatic.vcxproj.filters @@ -121,6 +121,9 @@ {79567AD4-E572-6CC5-AE4A-D9321A26D686} + + {74095786-E027-6B53-29F5-70659552A65C} + {2FAB3559-1B92-F750-C4E2-5D6EB0A870B7} @@ -345,6 +348,9 @@ src\GameSmithEngine\ImGui + + src\GameSmithEngine\ImGui + src\GameSmithEngine\Platform\Window @@ -381,6 +387,9 @@ src\GameSmithEngine\Rendering\DirectX12 + + src\GameSmithEngine\Rendering\DirectX12 + src\GameSmithEngine\Rendering\DirectX12\HeapStructures @@ -450,6 +459,9 @@ src\GameSmithEngine\Rendering\DirectX12\Util + + src\GameSmithEngine\Rendering\DirectX12\Util + src\GameSmithEngine\Rendering\DirectX12\Util @@ -519,6 +531,12 @@ src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders @@ -549,6 +567,9 @@ src\GameSmithEngine\ResourceManagement\ResourceLoaders + + src\GameSmithEngine\SerializeableFiles + src\GameSmithEngine\SerializeableFiles\GenericFileTypes @@ -558,6 +579,9 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets + src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -567,8 +591,14 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets - - src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes + + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes + + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -594,6 +624,9 @@ src\GameSmithEngine\Utilities\Locks + + src\GameSmithEngine\Utilities + src\GameSmithEngine\Utilities @@ -2183,6 +2216,9 @@ src\GameSmithEngine\ImGui + + src\GameSmithEngine\ImGui + src\GameSmithEngine\Platform\Window @@ -2210,6 +2246,9 @@ src\GameSmithEngine\Rendering\DirectX12 + + src\GameSmithEngine\Rendering\DirectX12 + src\GameSmithEngine\Rendering\DirectX12\HeapStructures @@ -2261,6 +2300,9 @@ src\GameSmithEngine\Rendering\DirectX12\State + + src\GameSmithEngine\Rendering\DirectX12\Util + src\GameSmithEngine\Rendering\DirectX12\Util @@ -2279,6 +2321,15 @@ src\GameSmithEngine\Rendering\RenderAgnostics\MaterialSystem + + src\GameSmithEngine\Rendering\RenderAgnostics\RenderComponents + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders\SLab + + + src\GameSmithEngine\Rendering\RenderAgnostics\Shaders + src\GameSmithEngine\Rendering @@ -2300,6 +2351,9 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets + src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -2309,8 +2363,8 @@ src\GameSmithEngine\SerializeableFiles\ResourceAssets - - src\GameSmithEngine\SerializeableFiles\ResourceAssets + + src\GameSmithEngine\SerializeableFiles\ResourceAssets\ShaderTypes src\GameSmithEngine\SerializeableFiles\ResourceAssets @@ -2327,6 +2381,9 @@ src\GameSmithEngine\Utilities\Locks + + src\GameSmithEngine\Utilities + src diff --git a/GameSmithEngine/premake5.lua b/GameSmithEngine/premake5.lua index 58ba7de..9e21c91 100644 --- a/GameSmithEngine/premake5.lua +++ b/GameSmithEngine/premake5.lua @@ -37,6 +37,10 @@ project "GameSmithEngine" "ImGui" } + libdirs{ + "%{DLLDir.dxc}" + } + defines { "_CRT_SECURE_NO_WARNINGS", @@ -51,10 +55,17 @@ project "GameSmithEngine" "GE_PLATFORM_WINDOWS" } - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } postbuildcommands{ - ("cmd /c xcopy %[%{cfg.targetdir}/*] %[%{wks.location}/bin/" .. outputdir .. "/TestZone] /E /Y /I") + ("cmd /c xcopy %[%{DLLDir.dxc}/*] %[%{cfg.targetdir} /E /Y /I"), + ("cmd /c xcopy %[%{cfg.targetdir}/*] %[%{wks.location}/bin/" .. outputdir .. "/GameSmithEngineTestSuite] /E /Y /I"), + ("cmd /c xcopy %[%{cfg.targetdir}/*] %[%{wks.location}/bin/" .. outputdir .. "/TestZone] /E /Y /I"), + ("cmd /c xcopy %[%{cfg.targetdir}/*] %[%{wks.location}/bin/" .. outputdir .. "/GameSmithEditor] /E /Y /I"), + ("cmd /c xcopy %[%{cfg.targetdir}/*] %[%{wks.location}/bin/" .. outputdir .. "/GEStandaloneGameApp] /E /Y /I") } @@ -120,15 +131,14 @@ project "GameSmithEngineStatic" filter "system:windows" systemversion "latest" - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } defines{ "GE_PLATFORM_WINDOWS" } - - postbuildcommands{ - ("{COPY} %{cfg.buildtarget.relpath}/../**.cso ../bin/" ..outputdir .. "/TestZone") - } filter "configurations:Debug" diff --git a/GameSmithEngine/src/GameSmithEngine.h b/GameSmithEngine/src/GameSmithEngine.h index b9eec19..2c9313f 100644 --- a/GameSmithEngine/src/GameSmithEngine.h +++ b/GameSmithEngine/src/GameSmithEngine.h @@ -47,6 +47,7 @@ // ----------- Entity System ------------- #include "GameSmithEngine/EntitySystem/GameObjectManager.h" #include "GameSmithEngine/EntitySystem/GameObject.h" +#include "GameSmithEngine/EntitySystem/EnitityRenderPreparer.h" // Component System #include "GameSmithEngine/EntitySystem/Components/Component.h" @@ -64,10 +65,12 @@ // -----------RescourceManagement----------- #include "GameSmithEngine/ResourceManagement/AssetManager.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/TestResource.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.h" -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.h" diff --git a/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.cpp b/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.cpp index c5deb1f..f2195c8 100644 --- a/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.cpp +++ b/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.cpp @@ -1,8 +1,13 @@ #include "gepch.h" #include "ContentLibraryManager.h" #include "GameSmithEngine/Core/Log.h" +#include "GameSmithEngine/EngineConfiguration/ConfigManager.h" #define CONNECT_LIBRARY_FUNC_NAME "ConnectToContentLibrary" +#define LIBRARY_FILE_EXTENSION ".dll" + +namespace fs = std::filesystem; +using recursive_directory_iterator = fs::recursive_directory_iterator; namespace GameSmith { ContentLibraryManager* ContentLibraryManager::s_Instance = nullptr; @@ -11,14 +16,13 @@ namespace GameSmith { ContentLibraryManager::ContentLibraryManager(){} - void ContentLibraryManager::Init(const std::unordered_map& startingLibraries) + void ContentLibraryManager::Init() { if (s_Instance == nullptr) { s_Instance = new ContentLibraryManager(); - for (const auto& libEntry : startingLibraries) { - s_Instance->LoadContentLibrary(libEntry.first, libEntry.second); - } + auto contentLibConfig = ConfigManager::GetInstance()->GetContentLibraryConfig(); + s_Instance->SetLibrarySearchPath(contentLibConfig.GetContentLibraryDirectory()); } } @@ -33,7 +37,7 @@ namespace GameSmith { ContentLibraryManager::~ContentLibraryManager() { std::vector keys; - for (auto& libEntry : m_Libraries) { + for (auto& libEntry : m_LoadedLibraries) { keys.push_back(libEntry.first); } @@ -47,26 +51,70 @@ namespace GameSmith { return s_Instance; } - void ContentLibraryManager::LoadContentLibrary(std::string libraryName, std::string libraryPath) + void ContentLibraryManager::ScanForContentLibraries() + { + if (m_LibrarySearchPath != "") { + m_LibraryPaths.clear(); + + // Current search method is directly looking for the files in a path. Future improvements is baking paths as a file during build time + for (const auto& dirEntry : recursive_directory_iterator(m_LibrarySearchPath)) { + if (dirEntry.is_regular_file()) { + std::string fileNameWithExt = dirEntry.path().filename().string(); + std::string path = dirEntry.path().string(); + + if (fileNameWithExt.ends_with(LIBRARY_FILE_EXTENSION)) { + std::string fileName = fileNameWithExt.substr(0, fileNameWithExt.find_last_of('.')); + m_LibraryPaths[fileName] = path; + } + } + } + } + } + + void ContentLibraryManager::FlushLoadedLibraries() + { + std::vector loadedLibs; + for (auto& entry : m_LoadedLibraries) { + loadedLibs.push_back(entry.first); + } + + for (auto& libName : loadedLibs) { + UnloadContentLibrary(libName); + } + } + + void ContentLibraryManager::LoadAllContentLibraries() + { + std::vector knownLibs; + for (auto& entry : m_LibraryPaths) { + knownLibs.push_back(entry.first); + } + + for (auto& libName : knownLibs) { + LoadContentLibrary(libName); + } + } + + void ContentLibraryManager::LoadContentLibrary(std::string libraryName) { - GE_CORE_ASSERT(!m_Libraries.contains(libraryName), "This DLL/ContentLibrary is already loaded"); + GE_CORE_ASSERT(!m_LoadedLibraries.contains(libraryName), "This DLL/ContentLibrary is already loaded"); + GE_CORE_ASSERT(m_LibraryPaths.contains(libraryName), "This DLL/ContentLibrary is not recognized"); #ifdef GE_PLATFORM_WINDOWS DynamicLibraryDetails libDetails; - libDetails.LibraryName = libraryName; - libDetails.LibraryPath = libraryPath; - auto module = LoadLibraryA(libDetails.LibraryPath.c_str()); + auto libraryPath = m_LibraryPaths[libraryName]; + auto module = LoadLibraryA(libraryPath.c_str()); libDetails.loadedLib = (LibraryHandle)module; if (module == nullptr) { - GE_CORE_ERROR("Failed to load library: {0}", libDetails.LibraryPath); + GE_CORE_ERROR("Failed to load library: {0}", libraryPath); return; } auto func = (ConnectLibraryFunc)GetProcAddress(module, CONNECT_LIBRARY_FUNC_NAME); if (func == nullptr) { - GE_CORE_ERROR("Failed to find function {0} in library: {1}", CONNECT_LIBRARY_FUNC_NAME, libDetails.LibraryPath); + GE_CORE_ERROR("Failed to find function {0} in library: {1}", CONNECT_LIBRARY_FUNC_NAME, libraryName); FreeLibrary(module); return; } @@ -75,13 +123,13 @@ namespace GameSmith { #endif libDetails.ContentLib->Init(); - m_Libraries[libraryName] = libDetails; + m_LoadedLibraries[libraryName] = libDetails; } void ContentLibraryManager::UnloadContentLibrary(std::string libraryName) { - GE_CORE_ASSERT(m_Libraries.contains(libraryName), "This DLL/ContentLibrary is currently in use"); - auto libEntry = m_Libraries.find(libraryName); + GE_CORE_ASSERT(m_LoadedLibraries.contains(libraryName), "This DLL/ContentLibrary is currently in use"); + auto libEntry = m_LoadedLibraries.find(libraryName); libEntry->second.ContentLib->Shutdown(); libEntry->second.ContentLib = nullptr; @@ -89,6 +137,6 @@ namespace GameSmith { #ifdef GE_PLATFORM_WINDOWS FreeLibrary((HMODULE)libEntry->second.loadedLib); #endif - m_Libraries.erase(libEntry); + m_LoadedLibraries.erase(libEntry); } }; diff --git a/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.h b/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.h index afb2fe7..a89037a 100644 --- a/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.h +++ b/GameSmithEngine/src/GameSmithEngine/ContentLibrarySystem/ContentLibraryManager.h @@ -7,8 +7,6 @@ namespace GameSmith { typedef void* LibraryHandle; struct DynamicLibraryDetails { - std::string LibraryName = ""; - std::string LibraryPath = ""; LibraryHandle loadedLib = nullptr; Ref ContentLib = nullptr; }; @@ -16,19 +14,37 @@ namespace GameSmith { class GE_API ContentLibraryManager { public: - static void Init(const std::unordered_map& startingLibraries); + static void Init(); static void Shutdown(); ~ContentLibraryManager(); static ContentLibraryManager* GetInstance(); - void LoadContentLibrary(std::string libraryName, std::string libraryPath); + /// + /// This sets the search path for content libraries to be loaded from. + /// This should be treated as an override functionality. + /// + /// Default path/searching functionality will be determined by the engine configuration + /// + /// + /// + inline void SetLibrarySearchPath(std::string path) { m_LibrarySearchPath = path; FlushLoadedLibraries(); } + void ScanForContentLibraries(); + + void FlushLoadedLibraries(); + void LoadAllContentLibraries(); + + void LoadContentLibrary(std::string libraryName); void UnloadContentLibrary(std::string libraryName); private: ContentLibraryManager(); private: - std::unordered_map m_Libraries; + std::string m_LibrarySearchPath; + std::unordered_map m_LoadedLibraries; + std::unordered_map m_LibraryPaths; + + private: static ContentLibraryManager* s_Instance; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/Core/Application.cpp b/GameSmithEngine/src/GameSmithEngine/Core/Application.cpp index a4a04bf..ca3ef0d 100644 --- a/GameSmithEngine/src/GameSmithEngine/Core/Application.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Core/Application.cpp @@ -3,7 +3,6 @@ #include "Log.h" - #include "GameSmithEngine/Core/Layers/EntitySystemLayer.h" #include "GameSmithEngine/Core/Layers/RenderLayer.h" #include "GameSmithEngine/Core/Layers/ResourceLayer.h" @@ -58,7 +57,7 @@ namespace GameSmith { void Application::PushLayer(Layer* layer) { if (m_LoopStarted) { - m_PendingLayers.push(layer); + m_PendingAddLayers.push(layer); } else { layer->OnAttach(m_AppSpecs); @@ -69,7 +68,7 @@ namespace GameSmith { void Application::PushOverlay(Layer* layer) { if (m_LoopStarted) { - m_PendingSpecialLayers.push(layer); + m_PendingAddSpecialLayers.push(layer); } else { layer->OnAttach(m_AppSpecs); @@ -78,6 +77,18 @@ namespace GameSmith { } + void Application::PopLayer(Layer* layer) + { + if (m_LoopStarted) { + m_PendingRemoveLayers.push(layer); + } + else { + m_LayerStack.Pop(layer); + layer->OnDetach(); + delete layer; + } + } + void Application::Execute() { m_Timer.Reset(); while (m_Running) { @@ -90,20 +101,28 @@ namespace GameSmith { m_Window->OnUpdate(); - while (!m_PendingSpecialLayers.empty()) { - auto layer = m_PendingSpecialLayers.front(); - m_PendingSpecialLayers.pop(); + while (!m_PendingAddSpecialLayers.empty()) { + auto layer = m_PendingAddSpecialLayers.front(); + m_PendingAddSpecialLayers.pop(); layer->OnAttach(m_AppSpecs); m_LayerStack.PushSpecial(layer); } - while (!m_PendingLayers.empty()) { - auto layer = m_PendingLayers.front(); - m_PendingLayers.pop(); + while (!m_PendingAddLayers.empty()) { + auto layer = m_PendingAddLayers.front(); + m_PendingAddLayers.pop(); layer->OnAttach(m_AppSpecs); m_LayerStack.Push(layer); } + while (!m_PendingRemoveLayers.empty()) { + auto layer = m_PendingRemoveLayers.front(); + m_PendingRemoveLayers.pop(); + m_LayerStack.Pop(layer); + layer->OnDetach(); + delete layer; + } + for (Layer* layer : m_LayerStack) { layer->OnUpdate(dt); } diff --git a/GameSmithEngine/src/GameSmithEngine/Core/Application.h b/GameSmithEngine/src/GameSmithEngine/Core/Application.h index 1cadaa2..5d58c6f 100644 --- a/GameSmithEngine/src/GameSmithEngine/Core/Application.h +++ b/GameSmithEngine/src/GameSmithEngine/Core/Application.h @@ -21,11 +21,13 @@ namespace GameSmith { Application(ApplicationSpecs& appSpecs); virtual ~Application(); - // Add a layer into the Engine Structure + // Add a layer into the Engine Structure (Take overnship of layer) void PushLayer(Layer* layer); - // Add a layer as an overlay in the Engine Structure + // Add a layer as an overlay in the Engine Structure (Take overnship of layer) void PushOverlay(Layer* layer); + void PopLayer(Layer* layer); + // Start executing the game engine (will block until the engine has been dismissed/shutdown) void Execute(); @@ -45,8 +47,9 @@ namespace GameSmith { FrameRateController m_FrameRateController;; Scope m_Window; - std::queue m_PendingLayers; - std::queue m_PendingSpecialLayers; + std::queue m_PendingAddLayers; + std::queue m_PendingAddSpecialLayers; + std::queue m_PendingRemoveLayers; ImGuiLayer* m_ImGuiLayer; MixStack m_LayerStack; diff --git a/GameSmithEngine/src/GameSmithEngine/Core/Layers/RenderLayer.cpp b/GameSmithEngine/src/GameSmithEngine/Core/Layers/RenderLayer.cpp index 3f5cee9..edfb582 100644 --- a/GameSmithEngine/src/GameSmithEngine/Core/Layers/RenderLayer.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Core/Layers/RenderLayer.cpp @@ -3,12 +3,28 @@ #include "GameSmithEngine/EntitySystem/EnitityRenderPreparer.h" #include "GameSmithEngine/Rendering/RenderingManager.h" +#include "GameSmithEngine/ResourceManagement/AssetManager.h" namespace GameSmith { void RenderLayer::OnAttach(const ApplicationSpecs& specs) { RenderingManager::Init(); EntityRenderPreparer::Init(); + + auto assetManager = AssetManager::GetInstance(); + if (assetManager) { + std::vector> shaderFiles; + assetManager->GetAssetPathsOfType(&shaderFiles); + + std::unordered_map shaderFileCache; + for (auto& entry : shaderFiles) { + auto id = assetManager->GetAssetID(entry.second); + shaderFileCache[entry.first] = id; + } + + auto rm = GameSmith::RenderingManager::GetInstance(); + rm->SetShaderSourceCache(shaderFileCache); + } } void RenderLayer::OnDetach() @@ -21,6 +37,9 @@ namespace GameSmith { { auto renderPreparer = EntityRenderPreparer::GetInstance(); renderPreparer->SendForRendering(); + + auto renderManager = RenderingManager::GetInstance(); + renderManager->SyncDataTransfer(); } void RenderLayer::OnEndUpdate() diff --git a/GameSmithEngine/src/GameSmithEngine/Core/Layers/ResourceLayer.cpp b/GameSmithEngine/src/GameSmithEngine/Core/Layers/ResourceLayer.cpp index f95a5a2..9360d66 100644 --- a/GameSmithEngine/src/GameSmithEngine/Core/Layers/ResourceLayer.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Core/Layers/ResourceLayer.cpp @@ -28,8 +28,10 @@ namespace GameSmith { AssetManager::GetInstance()->SetAssetDirectory(assetDir); } - auto& contentLibs = AssetManager::GetInstance()->GetContentLibrariesFiles(); - ContentLibraryManager::Init(contentLibs); + ContentLibraryManager::Init(); + if (contentDir != "") { + ContentLibraryManager::GetInstance()->SetLibrarySearchPath(contentDir); + } } void ResourceLayer::OnDetach() diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.cpp index 4462976..ca0e256 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.cpp @@ -28,10 +28,10 @@ namespace GameSmith { switch (m_CamType) { case Perspective: default: - renderPrep->AddCamera({ &m_PerpCam }); + renderPrep->SetMainCamera({ &m_PerpCam }); break; case Orthographic: - renderPrep->AddCamera({ &m_OrthoCam }); + renderPrep->SetMainCamera({ &m_OrthoCam }); break; } } diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.h index 3008375..f141ae4 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/CameraComponent.h @@ -12,6 +12,7 @@ namespace GameSmith { class GE_API CameraComponent : public Component { public: CameraComponent(GameObject* gameObject, Transform* transform); + virtual ~CameraComponent() = default; virtual void OnStart() override; virtual void OnUpdate(float dt) override; virtual void OnDestroy() override {} diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/Component.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/Component.h index 0eb1a07..e9aea79 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/Component.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/Component.h @@ -1,56 +1,37 @@ #pragma once #include "GameSmithEngine/Core/Core.h" -#include "GameSmithEngine/Utilities/ExposedVariableRegistry.h" +#include "GameSmithEngine/SerializeableFiles/ExposedMemberSerializeable.h" namespace GameSmith { class GameObject; class Transform; - class GE_API Component : public IDObject { + class GE_API IComponent : public virtual ISerializeable, public virtual IExposedMembers { public: - Component() = delete; - Component(GameObject* gameObject, Transform* transform): m_Initialized(false), m_GameObject(gameObject), m_Transform(transform) {} - void Init() { if (!m_Initialized) { OnStart(); m_Initialized = true; } } + virtual ~IComponent() = default; + virtual void Init() = 0; virtual void OnStart() = 0; virtual void OnUpdate(float dt) = 0; virtual void OnDestroy() = 0; virtual int GetPriority() const = 0; virtual std::string GetName() const = 0; - inline void BootstrapVariableRegistry(std::unordered_map>& variableEntries) { - m_Registry.BootstrapFromValueMap(variableEntries); - PostRegistryBootstrap(); - } - - inline void BootstrapConnectionRegistry(std::unordered_map>& refEntries) { - m_Registry.BootstrapFromConnectionsMap(refEntries); - PostRegistryBootstrap(); - } - - inline void BootstrapAssetRegistry(std::unordered_map>& refEntries) { - m_Registry.BootstrapFromAssetMap(refEntries); - PostRegistryBootstrap(); - } - - inline unsigned int RegistrySerializationSize() { return m_Registry.RequiredSpace(); } - inline void SerializeRegistry(char* byteStream, unsigned int availableBytes) { m_Registry.Serialize(byteStream, availableBytes); } - inline void DeserializeRegistry(char* inData, unsigned int bytes) { m_Registry.Deserialize(inData, bytes); } - - // Can be empty function - virtual void PostRegistryBootstrap() {}; - - void GenerateVariableEntries(std::unordered_map>* outMap) { m_Registry.GenerateVariableMap(outMap); } - void GenerateConnectionEntries(std::unordered_map>* outMap) { m_Registry.GenerateConnectionsMap(outMap); } - void GenerateAssetEntries(std::unordered_map>* outMap) { m_Registry.GenerateAssetMap(outMap); } + virtual GameObject* GetGameObject() = 0; + virtual Transform* GetTransform() = 0; + }; - GameObject* GetGameObject() { return m_GameObject; } - Transform* GetTransform() { return m_Transform; } - protected: + class GE_API Component : public ExposedMemberSerializeable, public IComponent { + public: + Component() = delete; + Component(GameObject* gameObject, Transform* transform): m_Initialized(false), m_GameObject(gameObject), m_Transform(transform) {} + void Init() override final { if (!m_Initialized) { OnStart(); m_Initialized = true; } } + GameObject* GetGameObject() override final { return m_GameObject; } + Transform* GetTransform() override final { return m_Transform; } + private: bool m_Initialized; GameObject* m_GameObject; Transform* m_Transform; - ExposedVariableRegistry m_Registry; }; struct ComponentCompare { diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.cpp index d890979..b4ac3f4 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.cpp @@ -7,13 +7,20 @@ namespace GameSmith { GE_REGISTERCOMPONENT(MeshRenderer) + MeshRenderer::MeshRenderer(GameObject* gameObject, Transform* transform) : Component(gameObject, transform) + { + m_Registry.AddExposedAsset("Mesh", (Ref*)&m_Mesh, CLASS_TO_STRING(MeshAsset)); + m_Registry.AddExposedAsset("TestMat", (Ref*) &m_TestAsset, CLASS_TO_STRING(MaterialAsset)); + } + void MeshRenderer::OnUpdate(float dt) { auto renderPrep = EntityRenderPreparer::GetInstance(); if (renderPrep != nullptr && m_Mesh != nullptr) { - glm::mat4 model = m_Transform->GetModelMatrix(); - bool changed = m_Transform->HasChanged(); + auto transform = GetTransform(); + glm::mat4 model = transform->GetModelMatrix(); + bool changed = transform->HasChanged(); unsigned int size = m_Mesh->GetSubMeshSize(); for (unsigned int i = 0; i < size; i++) { if (m_Materials[i].first == nullptr) { @@ -32,6 +39,19 @@ namespace GameSmith { GE_CORE_INFO("Something went wrong updating"); } + } + void MeshRenderer::PostRegistryBootstrap() + { + if (m_Mesh != nullptr) { + unsigned subMeshSize = m_Mesh->GetSubMeshSize(); + if (subMeshSize != m_Materials.size()) { + m_Materials.resize(subMeshSize); + } + } + + if (m_TestAsset != nullptr) { + SetMaterial(0, m_TestAsset); + } } }; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.h index cc31642..9e8f251 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/MeshRenderer.h @@ -6,7 +6,7 @@ namespace GameSmith { class GE_API MeshRenderer : public Component { public: - MeshRenderer(GameObject* gameObject, Transform* transform) : Component(gameObject, transform) {} + MeshRenderer(GameObject* gameObject, Transform* transform); virtual void OnStart() override {} virtual void OnUpdate(float dt) override; virtual void OnDestroy() override {} @@ -16,9 +16,11 @@ namespace GameSmith { void SetMesh(Ref newMesh) { m_Mesh = newMesh; m_Materials.resize(m_Mesh->GetSubMeshSize()); } void SetMaterial(unsigned int index, Ref mat) { m_Materials[index] = { mat->CreateInstance(), mat }; }; unsigned int GetMaterialSlots() { return m_Mesh->GetSubMeshSize(); } + void PostRegistryBootstrap() override; private: Ref m_Mesh; + Ref m_TestAsset; std::vector, Ref>> m_Materials; }; diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/TestComponent.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/TestComponent.cpp index 0d6ce69..f780042 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/TestComponent.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Components/TestComponent.cpp @@ -9,17 +9,17 @@ namespace GameSmith { GE_REGISTERCOMPONENT(TestComponent) TestComponent::TestComponent(GameObject* gameObject, Transform* transform) : Component(gameObject, transform) { - m_Registry.AddExposedVariable("Test Variable1", (void*)&expose1, ContainerDataType::Float); - m_Registry.AddExposedVariable("Test Variable2", (void*)glm::value_ptr(expose2), ContainerDataType::Float2); - m_Registry.AddExposedVariable("Test Variable3", (void*)glm::value_ptr(expose3), ContainerDataType::Float3); - m_Registry.AddExposedVariable("Test Variable4", (void*)glm::value_ptr(expose4), ContainerDataType::Float4); - m_Registry.AddExposedVariable("Test Variable5", (void*)&expose5, ContainerDataType::Int); - m_Registry.AddExposedVariable("Test Variable6", (void*)&expose6, ContainerDataType::Int2); - m_Registry.AddExposedVariable("Test Variable7", (void*)&expose7, ContainerDataType::Int3); - m_Registry.AddExposedVariable("Test Variable8", (void*)&expose8, ContainerDataType::Int4); - m_Registry.AddExposedConnection("TestRef", (Connection*) & m_TestRef, CLASS_TO_STRING(GameObject)); - m_Registry.AddExposedConnection("TestRef1", (Connection*) & m_TestCompRef, CLASS_TO_STRING(TestComponent)); - m_Registry.AddExposedAsset("TestRef2", (Ref*) & m_GameChunkAsset, CLASS_TO_STRING(GameChunkAsset)); + m_Registry.AddExposedVariable("Test Variable1", ContainerDataType::Float, (void*)&expose1); + m_Registry.AddExposedVariable("Test Variable2", ContainerDataType::Float2, (void*)glm::value_ptr(expose2)); + m_Registry.AddExposedVariable("Test Variable3", ContainerDataType::Float3, (void*)glm::value_ptr(expose3)); + m_Registry.AddExposedVariable("Test Variable4", ContainerDataType::Float4, (void*)glm::value_ptr(expose4)); + m_Registry.AddExposedVariable("Test Variable5", ContainerDataType::Int, (void*)&expose5); + m_Registry.AddExposedVariable("Test Variable6", ContainerDataType::Int2, (void*)&expose6); + m_Registry.AddExposedVariable("Test Variable7", ContainerDataType::Int3, (void*)&expose7); + m_Registry.AddExposedVariable("Test Variable8", ContainerDataType::Int4, (void*)&expose8); + m_Registry.AddExposedConnection("TestRef", (Connection*) & m_TestRef, CLASS_TO_STRING(GameObject)); + m_Registry.AddExposedConnection("TestRef1", (Connection*) & m_TestCompRef, CLASS_TO_STRING(TestComponent)); + m_Registry.AddExposedAsset("TestRef2", (Ref*) & m_GameChunkAsset, CLASS_TO_STRING(GameChunkAsset)); } void TestComponent::OnStart() diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.cpp index 3172241..3659b3a 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.cpp @@ -26,20 +26,38 @@ namespace GameSmith { m_RenderRequests.push_back(req); } - void EntityRenderPreparer::AddCamera(RenderableCamera cam) + void EntityRenderPreparer::SetMainCamera(RenderableCamera cam) { - m_Cameras.push(cam); + m_MainCamera = cam; + } + + void EntityRenderPreparer::AddAdditionalCamera(RenderableCamera cam) + { + GE_CORE_ASSERT(cam.targetTex != nullptr, "Additional Cameras need a target render texture"); + m_AdditionalCameras.push(cam); } void EntityRenderPreparer::SendForRendering() { - while (!m_Cameras.empty()) { - auto cam = m_Cameras.front(); - // TODO: Send for rendering - m_Cameras.pop(); + auto renderMang = RenderingManager::GetInstance(); + auto frameTex = renderMang->GetTextureForFrame(); + renderMang->GetRenderAPI()->SetRenderTexture(frameTex, 0); + + renderMang->BeginScene(m_MainCamera.cam, nullptr); + for (auto req : m_RenderRequests) { + renderMang->Submit(req.vBuf, req.iBuf, req.mat); + } + renderMang->EndScene(); + + + while (!m_AdditionalCameras.empty()) { + auto& cam = m_AdditionalCameras.front(); + m_AdditionalCameras.pop(); auto renderMang = RenderingManager::GetInstance(); + renderMang->GetRenderAPI()->SetRenderTexture(cam.targetTex, 0); + renderMang->BeginScene(cam.cam, nullptr); for (auto req : m_RenderRequests) { renderMang->Submit(req.vBuf, req.iBuf, req.mat); @@ -48,6 +66,7 @@ namespace GameSmith { } m_RenderRequests.clear(); + renderMang->GetRenderAPI()->SetRenderTexture(frameTex, 0); } }; diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.h index 9458999..5773ca6 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/EnitityRenderPreparer.h @@ -6,25 +6,27 @@ #include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/VertexBuffer.h" namespace GameSmith { - struct RenderRequest { + struct GE_API RenderRequest { Ref vBuf; Ref iBuf; Ref mat; }; - struct RenderableCamera { + struct GE_API RenderableCamera { Camera* cam; + Ref targetTex = nullptr; }; // This class collects information on which entities want to be renderered and prepares to make calls to the render manager - class EntityRenderPreparer { + class GE_API EntityRenderPreparer { public: static void Init(); static void Shutdown(); static inline EntityRenderPreparer* GetInstance() { return s_Instance; } void AddRenderRequest(RenderRequest req); - void AddCamera(RenderableCamera cam); + void SetMainCamera(RenderableCamera cam); + void AddAdditionalCamera(RenderableCamera cam); void SendForRendering(); private: EntityRenderPreparer() = default; @@ -32,6 +34,7 @@ namespace GameSmith { static EntityRenderPreparer* s_Instance; private: std::vector m_RenderRequests; - std::queue m_Cameras; + RenderableCamera m_MainCamera; + std::queue m_AdditionalCameras; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.cpp index 94daecb..0621df5 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.cpp @@ -55,7 +55,7 @@ namespace GameSmith { writer.WriteString(comp->GetName()); idData data = comp->GetID().getData(); writer.WriteClass(&data); - comp->SerializeRegistry(writer.GetCurPtr(), writer.GetRemainingSpace()); + comp->Serialize(writer.GetCurPtr(), writer.GetRemainingSpace()); } return writer.GetBuffer(); @@ -83,7 +83,7 @@ namespace GameSmith { writer.WriteString(comp->GetName()); idData data = comp->GetID().getData(); writer.WriteClass(&data); - comp->SerializeRegistry(writer.GetCurPtr(), writer.GetRemainingSpace()); + comp->Serialize(writer.GetCurPtr(), writer.GetRemainingSpace()); } } @@ -99,7 +99,7 @@ namespace GameSmith { for (auto comp : m_Components) { size += (unsigned int)comp->GetName().length() + 1; size += sizeof(idData); - size += comp->RegistrySerializationSize(); + size += comp->RequiredSpace(); } return size; @@ -127,9 +127,9 @@ namespace GameSmith { auto id = reader.ReadClass(); ID newID(*id); auto comp = AddComponent(compName).lock(); - comp->DeserializeRegistry(reader.GetCurPtr(), reader.GetRemainingBytes()); + comp->Deserialize(reader.GetCurPtr(), reader.GetRemainingBytes()); comp->SetID(newID); - reader.MoveForward(comp->RegistrySerializationSize()); + reader.MoveForward(comp->RequiredSpace()); } } }; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.h index 502d403..75b1d9a 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObject.h @@ -6,12 +6,12 @@ #include "GameSmithEngine/Core/Log.h" #include "GameSmithEngine/EntitySystem/Transform.h" -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" +#include "GameSmithEngine/SerializeableFiles/Serializable.h" namespace GameSmith { - class GE_API GameObject : public Asset { + class GE_API GameObject : public AbstractBaseSerializeable { public: GameObject(std::string name = DEFAULT_GAMEOBJECT_NAME); inline std::string GetName() const { return m_Name; } diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.cpp b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.cpp index b99542b..eba9fb2 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.cpp +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.cpp @@ -67,7 +67,7 @@ namespace GameSmith { Connection GameSmith::GameObjectManager::FindGameObject(std::string gameObjectName) { - // TODO: Fix this when a solution for String -> Is completed + // TODO: Fix this when a solution for CString -> Is completed if (m_ObjectMaps->objectNames.contains(gameObjectName)) { auto& id = *(m_ObjectMaps->objectNames.find(gameObjectName)->second.begin()); return m_ObjectMaps->objects.find(id)->second; @@ -84,7 +84,7 @@ namespace GameSmith { } } - void GameObjectManager::GetGameObjectNames(std::vector* outNames) + void GameObjectManager::GetAllGameObjectNames(std::vector* outNames) { for (auto object : m_ObjectMaps->objectNames) { outNames->push_back(object.first); diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.h index e4191df..5778c5e 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/GameObjectManager.h @@ -23,7 +23,7 @@ namespace GameSmith { Connection CreateGameObject(glm::vec3 startingPos = glm::vec3(0), glm::vec3 startingRotation = glm::vec3(0)); Connection FindGameObject(std::string gameObjectName); void GetGameObjects(std::vector>* outObjects); - void GetGameObjectNames(std::vector* outNames); + void GetAllGameObjectNames(std::vector* outNames); void DestroyGameObject(Connection object); private: friend class GameObjectProxy; diff --git a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Transform.h b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Transform.h index e868881..e7f252a 100644 --- a/GameSmithEngine/src/GameSmithEngine/EntitySystem/Transform.h +++ b/GameSmithEngine/src/GameSmithEngine/EntitySystem/Transform.h @@ -5,7 +5,7 @@ #include "GameSmithEngine/SerializeableFiles/Serializable.h" namespace GameSmith { - class GE_API Transform : public Serializeable + class GE_API Transform : public AbstractBaseSerializeable { public: Transform(); diff --git a/GameSmithEngine/src/GameSmithEngine/Events/Event.h b/GameSmithEngine/src/GameSmithEngine/Events/Event.h index f627026..feb8346 100644 --- a/GameSmithEngine/src/GameSmithEngine/Events/Event.h +++ b/GameSmithEngine/src/GameSmithEngine/Events/Event.h @@ -23,7 +23,7 @@ namespace GameSmith { APP_TICK, APP_UPDATE, APP_RENDER, MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_MOVE, MOUSE_SCROLL, KEY_PRESSED, KEY_RELEASED, CHAR_TYPED, - FRAME_END + FRAME_END, MISCELLENIOUS }; @@ -41,8 +41,8 @@ namespace GameSmith { }; -#define EVENT_TYPE(type) static EventType GetStaticType() {return EventType::##type; } \ - virtual EventType GetEventType() const override {return GetStaticType();} \ +#define EVENT_TYPE(type) static GameSmith::EventType GetStaticType() {return GameSmith::EventType::##type; } \ + virtual GameSmith::EventType GetEventType() const override {return GetStaticType();} \ virtual const char* GetName() const override {return #type;} #define CATEGORY_TYPE(category) virtual int GetCategoryFlags() const override {return category;} diff --git a/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.cpp b/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.cpp index 514808c..db8afa7 100644 --- a/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.cpp +++ b/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.cpp @@ -3,6 +3,7 @@ #include "GameSmithEngine/EntitySystem/GameObjectManager.h" #include "GameSmithEngine/ResourceManagement/AssetManager.h" #include "GameSmithEngine/ResourceManagement/ResourceAssetHelper.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" namespace GameSmith { GameChunk::~GameChunk() @@ -14,16 +15,25 @@ namespace GameSmith { } } + void GameChunk::GetChunkGameObjectNames(std::vector* nameOut) + { + for (auto& object : m_GameObjects) { + if (!object.expired()) { + nameOut->push_back(object.lock()->GetName()); + } + } + } + Ref GameChunk::Serialize() { BinaryStreamWriter writer(RequiredSpace()); - ChunkMetadata metadata = {}; + unsigned int gmCount = 0; for (auto& gm : m_GameObjects) { - metadata.gmCount += gm.expired() ? 0 : 1; + gmCount += gm.expired() ? 0 : 1; } - writer.WriteClass(&metadata); + writer.WriteUInt(gmCount); for (auto& gm : m_GameObjects) { if (!gm.expired()) { @@ -32,7 +42,6 @@ namespace GameSmith { } } - return writer.GetBuffer(); } @@ -42,7 +51,7 @@ namespace GameSmith { unsigned int GameChunk::RequiredSpace() const { - unsigned int size = sizeof(ChunkMetadata); + unsigned int size = sizeof(unsigned int); for (auto& gm : m_GameObjects) { if (!gm.expired()) { @@ -55,15 +64,15 @@ namespace GameSmith { void GameChunk::Deserialize(char* inData, unsigned int size) { - std::unordered_map, IDHasher> collectedIDs; + std::unordered_map, IDHasher> collectedIDs; std::vector> createdComps; BinaryStreamReader reader(inData, size); - auto metadata = reader.ReadClass(); + unsigned int gmCount = reader.GetUInt(); auto gmManager = GameObjectManager::GetInstance(); - for (unsigned int i = 0; i < metadata->gmCount; i++) { + for (unsigned int i = 0; i < gmCount; i++) { // Create a game object (treat it as a fresh canvas) auto gm = gmManager->CreateGameObject(); @@ -107,14 +116,14 @@ namespace GameSmith { for (auto& entry : assetRefs) { if (collectedIDs.contains(entry.second->GetCurrentRefID())) { auto foundEntry = collectedIDs.find(entry.second->GetCurrentRefID()); - entry.second->AssignRef(CastPtr(foundEntry->second)); + entry.second->AssignRef(CastPtr(foundEntry->second)); } else { // Attempt to load asset auto resourceManager = AssetManager::GetInstance(); auto asset = resourceManager->GetResource(entry.second->GetCurrentRefID()); // TODO: Change resource manager to return asset class for default - entry.second->AssignRef(CastPtr(asset)); + entry.second->AssignRef(CastPtr(asset)); collectedIDs.insert({ asset->GetID(), asset }); } } diff --git a/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.h b/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.h index eb8e186..d2164f3 100644 --- a/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.h +++ b/GameSmithEngine/src/GameSmithEngine/GameChunkSystem/GameChunk.h @@ -1,17 +1,24 @@ #pragma once +#include #include "GameSmithEngine/Core/Core.h" #include "GameSmithEngine/EntitySystem/GameObject.h" #include "GameSmithEngine/SerializeableFiles/Serializable.h" +#define GAMECHUNK_DEFAULT_NAME "NewChunk" + namespace GameSmith { - class GE_API GameChunk : public Serializeable + class GE_API GameChunk : public AbstractBaseSerializeable { public: - GameChunk() = default; - GameChunk(std::vector>& objects) : m_GameObjects(objects) {}; - inline void AddObjectToChunk(Connection object) { m_GameObjects.push_back(object); } + GameChunk() : m_ChunkName(GAMECHUNK_DEFAULT_NAME) {}; + GameChunk(std::vector>& objects) : m_GameObjects(objects), m_ChunkName(GAMECHUNK_DEFAULT_NAME) {}; ~GameChunk(); + inline void AddObjectToChunk(Connection object) { m_GameObjects.push_back(object); } + inline void SetChunkName(std::string& name) { m_ChunkName = name; } + inline std::string GetChunkName() const { return m_ChunkName; } + void GetChunkGameObjectNames(std::vector* nameOut); + virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; virtual unsigned int RequiredSpace() const override; @@ -19,9 +26,7 @@ namespace GameSmith { private: std::vector> m_GameObjects; private: - struct ChunkMetadata { - unsigned int gmCount; - }; + std::string m_ChunkName; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.cpp b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.cpp index 913b5c5..60f3a42 100644 --- a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.cpp +++ b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.cpp @@ -12,105 +12,22 @@ #include "GameSmithEngine/Core/Application.h" #include "GameSmithEngine/Core/Log.h" #include "imgui.h" +#include "ImGuiThemes.h" #define HEAP_INCREASE 5 namespace GameSmith { - Ref ImGuiLayer::m_Heap = nullptr; + Ref ImGuiLayer::s_Heap = nullptr; + unsigned int ImGuiLayer::s_HeapCurSlot = 0; static void SetupImGuiStyle() { - // Moonlight style by Madam-Herta from ImThemes - ImGuiStyle& style = ImGui::GetStyle(); - - style.Alpha = 1.0f; - style.DisabledAlpha = 1.0f; - style.WindowPadding = ImVec2(12.0f, 12.0f); - style.WindowRounding = 11.5f; - style.WindowBorderSize = 0.0f; - style.WindowMinSize = ImVec2(20.0f, 20.0f); - style.WindowTitleAlign = ImVec2(0.5f, 0.5f); - style.WindowMenuButtonPosition = ImGuiDir_Right; - style.ChildRounding = 0.0f; - style.ChildBorderSize = 1.0f; - style.PopupRounding = 0.0f; - style.PopupBorderSize = 1.0f; - style.FramePadding = ImVec2(20.0f, 3.400000095367432f); - style.FrameRounding = 11.89999961853027f; - style.FrameBorderSize = 0.0f; - style.ItemSpacing = ImVec2(4.300000190734863f, 5.5f); - style.ItemInnerSpacing = ImVec2(7.099999904632568f, 1.799999952316284f); - style.CellPadding = ImVec2(12.10000038146973f, 9.199999809265137f); - style.IndentSpacing = 0.0f; - style.ColumnsMinSpacing = 4.900000095367432f; - style.ScrollbarSize = 11.60000038146973f; - style.ScrollbarRounding = 15.89999961853027f; - style.GrabMinSize = 3.700000047683716f; - style.GrabRounding = 20.0f; - style.TabRounding = 0.0f; - style.TabBorderSize = 0.0f; - style.ColorButtonPosition = ImGuiDir_Right; - style.ButtonTextAlign = ImVec2(0.5f, 0.5f); - style.SelectableTextAlign = ImVec2(0.0f, 0.0f); - - style.Colors[ImGuiCol_Text] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.2745098173618317f, 0.3176470696926117f, 0.4509803950786591f, 1.0f); - style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_ChildBg] = ImVec4(0.09411764889955521f, 0.1019607856869698f, 0.1176470592617989f, 1.0f); - style.Colors[ImGuiCol_PopupBg] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_Border] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); - style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_FrameBg] = ImVec4(0.1137254908680916f, 0.125490203499794f, 0.1529411822557449f, 1.0f); - style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); - style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); - style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); - style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); - style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.09803921729326248f, 0.105882354080677f, 0.1215686276555061f, 1.0f); - style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); - style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); - style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_CheckMark] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); - style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); - style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(1.0f, 0.7960784435272217f, 0.4980392158031464f, 1.0f); - style.Colors[ImGuiCol_Button] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.1803921610116959f, 0.1882352977991104f, 0.196078434586525f, 1.0f); - style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.1529411822557449f, 0.1529411822557449f, 0.1529411822557449f, 1.0f); - style.Colors[ImGuiCol_Header] = ImVec4(0.1411764770746231f, 0.1647058874368668f, 0.2078431397676468f, 1.0f); - style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.105882354080677f, 0.105882354080677f, 0.105882354080677f, 1.0f); - style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_Separator] = ImVec4(0.1294117718935013f, 0.1490196138620377f, 0.1921568661928177f, 1.0f); - style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.1568627506494522f, 0.1843137294054031f, 0.250980406999588f, 1.0f); - style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.1568627506494522f, 0.1843137294054031f, 0.250980406999588f, 1.0f); - style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.1450980454683304f, 0.1450980454683304f, 0.1450980454683304f, 1.0f); - style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); - style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - style.Colors[ImGuiCol_Tab] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_TabHovered] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_TabActive] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); - style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.125490203499794f, 0.2745098173618317f, 0.572549045085907f, 1.0f); - style.Colors[ImGuiCol_PlotLines] = ImVec4(0.5215686559677124f, 0.6000000238418579f, 0.7019608020782471f, 1.0f); - style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.03921568766236305f, 0.9803921580314636f, 0.9803921580314636f, 1.0f); - style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.8823529481887817f, 0.7960784435272217f, 0.5607843399047852f, 1.0f); - style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.95686274766922f, 0.95686274766922f, 0.95686274766922f, 1.0f); - style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); - style.Colors[ImGuiCol_TableBorderStrong] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); - style.Colors[ImGuiCol_TableBorderLight] = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); - style.Colors[ImGuiCol_TableRowBg] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); - style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.09803921729326248f, 0.105882354080677f, 0.1215686276555061f, 1.0f); - style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.9372549057006836f, 0.9372549057006836f, 0.9372549057006836f, 1.0f); - style.Colors[ImGuiCol_DragDropTarget] = ImVec4(0.4980392158031464f, 0.5137255191802979f, 1.0f, 1.0f); - style.Colors[ImGuiCol_NavHighlight] = ImVec4(0.2666666805744171f, 0.2901960909366608f, 1.0f, 1.0f); - style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.4980392158031464f, 0.5137255191802979f, 1.0f, 1.0f); - style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.196078434586525f, 0.1764705926179886f, 0.5450980663299561f, 0.501960813999176f); - style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.196078434586525f, 0.1764705926179886f, 0.5450980663299561f, 0.501960813999176f); + ApplyMoonlightTheme(); } - ImGuiLayer::ImGuiLayer() : Layer("ImGui Layer"), m_CurSlot(1), m_DockEnabled(false) { - m_Heap = DirectX12Core::GetCore().GetHeapDatabase()->AllocateHeap(50, DescriptorHeapType::CBVSRVUAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, "IMGui Heap"); + ImGuiLayer::ImGuiLayer() : Layer("ImGui Layer"), m_DockEnabled(false) { + s_Heap = DirectX12Core::GetCore().GetHeapDatabase()->AllocateHeap(50, DescriptorHeapType::CBVSRVUAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, "IMGui Heap"); } ImGuiLayer::~ImGuiLayer() { @@ -146,16 +63,17 @@ namespace GameSmith { init_info.NumFramesInFlight = 2; init_info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM; init_info.DSVFormat = DXGI_FORMAT_UNKNOWN; - init_info.SrvDescriptorHeap = m_Heap->GetHeapReference(); - init_info.SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle) {*out_cpu_handle = m_Heap->GetCPUReference(0); *out_gpu_handle = m_Heap->GetGPUReference(0); }; - init_info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle) {}; + init_info.SrvDescriptorHeap = s_Heap->GetHeapReference(); + init_info.SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle) { + // Get descriptor from end of heap + *out_cpu_handle = s_Heap->GetCPUReference(s_HeapCurSlot); + *out_gpu_handle = s_Heap->GetGPUReference(s_HeapCurSlot); + s_HeapCurSlot++; + }; + init_info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle) { + }; - /*ImGui_ImplDX12_Init(DirectX12Core::GetCore().GetDevice(), - 2, - DXGI_FORMAT_R8G8B8A8_UNORM, - m_Heap->GetHeapReference(), - m_Heap->GetCPUReference(0), m_Heap->GetGPUReference(0));*/ ImGui_ImplDX12_Init(&init_info); SetupImGuiStyle(); @@ -179,17 +97,17 @@ namespace GameSmith { const ImGuiTextureSpace* ImGuiLayer::GenerateTextureSpace(Ref tex) { - D3D12_CPU_DESCRIPTOR_HANDLE slot = m_Heap->GetCPUReference(m_CurSlot); - D3D12_GPU_DESCRIPTOR_HANDLE gpuSlot = m_Heap->GetGPUReference(m_CurSlot); + D3D12_CPU_DESCRIPTOR_HANDLE slot = s_Heap->GetCPUReference(s_HeapCurSlot); + D3D12_GPU_DESCRIPTOR_HANDLE gpuSlot = s_Heap->GetGPUReference(s_HeapCurSlot); auto device = DirectX12Core::GetCore().GetDevice(); auto d3Tex = CastPtr(tex); auto texRef = d3Tex->GetSRVHandle(); device->CopyDescriptorsSimple(1, slot, texRef, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - m_CurSlot++; + s_HeapCurSlot++; Ref space = Ref(new ImGuiTextureSpace()); - *space = { (void*)gpuSlot.ptr, m_CurSlot - 1 }; + *space = { (void*)gpuSlot.ptr, s_HeapCurSlot - 1 }; m_CurrentSpaces.emplace_back(space, texRef); return space.get(); @@ -208,15 +126,15 @@ namespace GameSmith { auto& entry = m_SpacesToMigrate.front(); device->CopyDescriptorsSimple( 1, - m_Heap->GetCPUReference(m_CurSlot), + s_Heap->GetCPUReference(s_HeapCurSlot), entry.originalHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ); - entry.space->index = m_CurSlot; - entry.space->gpuSpot = (void*)m_Heap->GetGPUReference(m_CurSlot).ptr; + entry.space->index = s_HeapCurSlot; + entry.space->gpuSpot = (void*)s_Heap->GetGPUReference(s_HeapCurSlot).ptr; - m_CurSlot++; + s_HeapCurSlot++; m_SpacesToMigrate.pop(); } m_PreviousHeap->Free(); @@ -246,7 +164,7 @@ namespace GameSmith { context->GetStateManager().BindRenderTargetsOnly(); ID3D12DescriptorHeap* descriptorHeaps[] = { - m_Heap->GetHeapReference() + s_Heap->GetHeapReference() }; commandList->SetDescriptorHeaps(1, descriptorHeaps); diff --git a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.h b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.h index bdc38ad..7fc67b5 100644 --- a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.h +++ b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiLayer.h @@ -36,12 +36,12 @@ namespace GameSmith { D3D12_CPU_DESCRIPTOR_HANDLE originalHandle; }; private: - static Ref m_Heap; + static Ref s_Heap; + static unsigned int s_HeapCurSlot; std::vector m_CurrentSpaces; Ref m_PreviousHeap; std::queue m_SpacesToMigrate; - unsigned int m_CurSlot; bool m_DockEnabled; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.cpp b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.cpp new file mode 100644 index 0000000..82fee5f --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.cpp @@ -0,0 +1,293 @@ +#include "gepch.h" +#include "ImGuiThemes.h" +#include "imgui.h" + +namespace GameSmith { + void ApplyCatpuchinnTheme() + { + ImGuiStyle& style = ImGui::GetStyle(); + ImVec4* colors = style.Colors; + + // Catppuccin Mocha Palette + // -------------------------------------------------------- + const ImVec4 base = ImVec4(0.117f, 0.117f, 0.172f, 1.0f); // #1e1e2e + const ImVec4 mantle = ImVec4(0.109f, 0.109f, 0.156f, 1.0f); // #181825 + const ImVec4 surface0 = ImVec4(0.200f, 0.207f, 0.286f, 1.0f); // #313244 + const ImVec4 surface1 = ImVec4(0.247f, 0.254f, 0.337f, 1.0f); // #3f4056 + const ImVec4 surface2 = ImVec4(0.290f, 0.301f, 0.388f, 1.0f); // #4a4d63 + const ImVec4 overlay0 = ImVec4(0.396f, 0.403f, 0.486f, 1.0f); // #65677c + const ImVec4 overlay2 = ImVec4(0.576f, 0.584f, 0.654f, 1.0f); // #9399b2 + const ImVec4 text = ImVec4(0.803f, 0.815f, 0.878f, 1.0f); // #cdd6f4 + const ImVec4 subtext0 = ImVec4(0.639f, 0.658f, 0.764f, 1.0f); // #a3a8c3 + const ImVec4 mauve = ImVec4(0.796f, 0.698f, 0.972f, 1.0f); // #cba6f7 + const ImVec4 peach = ImVec4(0.980f, 0.709f, 0.572f, 1.0f); // #fab387 + const ImVec4 yellow = ImVec4(0.980f, 0.913f, 0.596f, 1.0f); // #f9e2af + const ImVec4 green = ImVec4(0.650f, 0.890f, 0.631f, 1.0f); // #a6e3a1 + const ImVec4 teal = ImVec4(0.580f, 0.886f, 0.819f, 1.0f); // #94e2d5 + const ImVec4 sapphire = ImVec4(0.458f, 0.784f, 0.878f, 1.0f); // #74c7ec + const ImVec4 blue = ImVec4(0.533f, 0.698f, 0.976f, 1.0f); // #89b4fa + const ImVec4 lavender = ImVec4(0.709f, 0.764f, 0.980f, 1.0f); // #b4befe + + // Main window and backgrounds + colors[ImGuiCol_WindowBg] = base; + colors[ImGuiCol_ChildBg] = base; + colors[ImGuiCol_PopupBg] = surface0; + colors[ImGuiCol_Border] = surface1; + colors[ImGuiCol_BorderShadow] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f); + colors[ImGuiCol_FrameBg] = surface0; + colors[ImGuiCol_FrameBgHovered] = surface1; + colors[ImGuiCol_FrameBgActive] = surface2; + colors[ImGuiCol_TitleBg] = mantle; + colors[ImGuiCol_TitleBgActive] = surface0; + colors[ImGuiCol_TitleBgCollapsed] = mantle; + colors[ImGuiCol_MenuBarBg] = mantle; + colors[ImGuiCol_ScrollbarBg] = surface0; + colors[ImGuiCol_ScrollbarGrab] = surface2; + colors[ImGuiCol_ScrollbarGrabHovered] = overlay0; + colors[ImGuiCol_ScrollbarGrabActive] = overlay2; + colors[ImGuiCol_CheckMark] = green; + colors[ImGuiCol_SliderGrab] = sapphire; + colors[ImGuiCol_SliderGrabActive] = blue; + colors[ImGuiCol_Button] = surface0; + colors[ImGuiCol_ButtonHovered] = surface1; + colors[ImGuiCol_ButtonActive] = surface2; + colors[ImGuiCol_Header] = surface0; + colors[ImGuiCol_HeaderHovered] = surface1; + colors[ImGuiCol_HeaderActive] = surface2; + colors[ImGuiCol_Separator] = surface1; + colors[ImGuiCol_SeparatorHovered] = mauve; + colors[ImGuiCol_SeparatorActive] = mauve; + colors[ImGuiCol_ResizeGrip] = surface2; + colors[ImGuiCol_ResizeGripHovered] = mauve; + colors[ImGuiCol_ResizeGripActive] = mauve; + colors[ImGuiCol_Tab] = surface0; + colors[ImGuiCol_TabHovered] = surface2; + colors[ImGuiCol_TabActive] = surface1; + colors[ImGuiCol_TabUnfocused] = surface0; + colors[ImGuiCol_TabUnfocusedActive] = surface1; + colors[ImGuiCol_DockingPreview] = sapphire; + colors[ImGuiCol_DockingEmptyBg] = base; + colors[ImGuiCol_PlotLines] = blue; + colors[ImGuiCol_PlotLinesHovered] = peach; + colors[ImGuiCol_PlotHistogram] = teal; + colors[ImGuiCol_PlotHistogramHovered] = green; + colors[ImGuiCol_TableHeaderBg] = surface0; + colors[ImGuiCol_TableBorderStrong] = surface1; + colors[ImGuiCol_TableBorderLight] = surface0; + colors[ImGuiCol_TableRowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f); + colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.0f, 1.0f, 1.0f, 0.06f); + colors[ImGuiCol_TextSelectedBg] = surface2; + colors[ImGuiCol_DragDropTarget] = yellow; + colors[ImGuiCol_NavHighlight] = lavender; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.0f, 1.0f, 1.0f, 0.7f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.8f, 0.8f, 0.8f, 0.2f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.35f); + colors[ImGuiCol_Text] = text; + colors[ImGuiCol_TextDisabled] = subtext0; + + // Rounded corners + style.WindowRounding = 6.0f; + style.ChildRounding = 6.0f; + style.FrameRounding = 4.0f; + style.PopupRounding = 4.0f; + style.ScrollbarRounding = 9.0f; + style.GrabRounding = 4.0f; + style.TabRounding = 4.0f; + + // Padding and spacing + style.WindowPadding = ImVec2(8.0f, 8.0f); + style.FramePadding = ImVec2(5.0f, 3.0f); + style.ItemSpacing = ImVec2(8.0f, 4.0f); + style.ItemInnerSpacing = ImVec2(4.0f, 4.0f); + style.IndentSpacing = 21.0f; + style.ScrollbarSize = 14.0f; + style.GrabMinSize = 10.0f; + + // Borders + style.WindowBorderSize = 1.0f; + style.ChildBorderSize = 1.0f; + style.PopupBorderSize = 1.0f; + style.FrameBorderSize = 0.0f; + style.TabBorderSize = 0.0f; + } + + void ApplyMoonlightTheme() + { + // Moonlight style by Madam-Herta from ImThemes + ImGuiStyle& style = ImGui::GetStyle(); + + style.Alpha = 1.0f; + style.DisabledAlpha = 1.0f; + style.WindowPadding = ImVec2(12.0f, 12.0f); + style.WindowRounding = 11.5f; + style.WindowBorderSize = 0.0f; + style.WindowMinSize = ImVec2(20.0f, 20.0f); + style.WindowTitleAlign = ImVec2(0.5f, 0.5f); + style.WindowMenuButtonPosition = ImGuiDir_Right; + style.ChildRounding = 0.0f; + style.ChildBorderSize = 1.0f; + style.PopupRounding = 0.0f; + style.PopupBorderSize = 1.0f; + style.FramePadding = ImVec2(20.0f, 3.400000095367432f); + style.FrameRounding = 11.89999961853027f; + style.FrameBorderSize = 0.0f; + style.ItemSpacing = ImVec2(4.300000190734863f, 5.5f); + style.ItemInnerSpacing = ImVec2(7.099999904632568f, 1.799999952316284f); + style.CellPadding = ImVec2(12.10000038146973f, 9.199999809265137f); + style.IndentSpacing = 0.0f; + style.ColumnsMinSpacing = 4.900000095367432f; + style.ScrollbarSize = 11.60000038146973f; + style.ScrollbarRounding = 15.89999961853027f; + style.GrabMinSize = 3.700000047683716f; + style.GrabRounding = 20.0f; + style.TabRounding = 0.0f; + style.TabBorderSize = 0.0f; + style.ColorButtonPosition = ImGuiDir_Right; + style.ButtonTextAlign = ImVec2(0.5f, 0.5f); + style.SelectableTextAlign = ImVec2(0.0f, 0.0f); + + style.Colors[ImGuiCol_Text] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.2745098173618317f, 0.3176470696926117f, 0.4509803950786591f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_ChildBg] = ImVec4(0.09411764889955521f, 0.1019607856869698f, 0.1176470592617989f, 1.0f); + style.Colors[ImGuiCol_PopupBg] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_Border] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); + style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_FrameBg] = ImVec4(0.1137254908680916f, 0.125490203499794f, 0.1529411822557449f, 1.0f); + style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); + style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.09803921729326248f, 0.105882354080677f, 0.1215686276555061f, 1.0f); + style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.1568627506494522f, 0.168627455830574f, 0.1921568661928177f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); + style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); + style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(1.0f, 0.7960784435272217f, 0.4980392158031464f, 1.0f); + style.Colors[ImGuiCol_Button] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.1803921610116959f, 0.1882352977991104f, 0.196078434586525f, 1.0f); + style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.1529411822557449f, 0.1529411822557449f, 0.1529411822557449f, 1.0f); + style.Colors[ImGuiCol_Header] = ImVec4(0.1411764770746231f, 0.1647058874368668f, 0.2078431397676468f, 1.0f); + style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.105882354080677f, 0.105882354080677f, 0.105882354080677f, 1.0f); + style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_Separator] = ImVec4(0.1294117718935013f, 0.1490196138620377f, 0.1921568661928177f, 1.0f); + style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.1568627506494522f, 0.1843137294054031f, 0.250980406999588f, 1.0f); + style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.1568627506494522f, 0.1843137294054031f, 0.250980406999588f, 1.0f); + style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.1450980454683304f, 0.1450980454683304f, 0.1450980454683304f, 1.0f); + style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.9725490212440491f, 1.0f, 0.4980392158031464f, 1.0f); + style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_Tab] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_TabHovered] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_TabActive] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.0784313753247261f, 0.08627451211214066f, 0.1019607856869698f, 1.0f); + style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.125490203499794f, 0.2745098173618317f, 0.572549045085907f, 1.0f); + style.Colors[ImGuiCol_PlotLines] = ImVec4(0.5215686559677124f, 0.6000000238418579f, 0.7019608020782471f, 1.0f); + style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.03921568766236305f, 0.9803921580314636f, 0.9803921580314636f, 1.0f); + style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.8823529481887817f, 0.7960784435272217f, 0.5607843399047852f, 1.0f); + style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.95686274766922f, 0.95686274766922f, 0.95686274766922f, 1.0f); + style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); + style.Colors[ImGuiCol_TableBorderStrong] = ImVec4(0.0470588244497776f, 0.05490196123719215f, 0.07058823853731155f, 1.0f); + style.Colors[ImGuiCol_TableBorderLight] = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); + style.Colors[ImGuiCol_TableRowBg] = ImVec4(0.1176470592617989f, 0.1333333402872086f, 0.1490196138620377f, 1.0f); + style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.09803921729326248f, 0.105882354080677f, 0.1215686276555061f, 1.0f); + style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.9372549057006836f, 0.9372549057006836f, 0.9372549057006836f, 1.0f); + style.Colors[ImGuiCol_DragDropTarget] = ImVec4(0.4980392158031464f, 0.5137255191802979f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavHighlight] = ImVec4(0.2666666805744171f, 0.2901960909366608f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.4980392158031464f, 0.5137255191802979f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.196078434586525f, 0.1764705926179886f, 0.5450980663299561f, 0.501960813999176f); + style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.196078434586525f, 0.1764705926179886f, 0.5450980663299561f, 0.501960813999176f); + } + + void ApplyComfortableTheme() + { + // Comfortable Dark Cyan style by SouthCraftX from ImThemes + ImGuiStyle& style = ImGui::GetStyle(); + + style.Alpha = 1.0f; + style.DisabledAlpha = 1.0f; + style.WindowPadding = ImVec2(20.0f, 20.0f); + style.WindowRounding = 11.5f; + style.WindowBorderSize = 0.0f; + style.WindowMinSize = ImVec2(20.0f, 20.0f); + style.WindowTitleAlign = ImVec2(0.5f, 0.5f); + style.WindowMenuButtonPosition = ImGuiDir_None; + style.ChildRounding = 20.0f; + style.ChildBorderSize = 1.0f; + style.PopupRounding = 17.4f; + style.PopupBorderSize = 1.0f; + style.FramePadding = ImVec2(20.0f, 3.4f); + style.FrameRounding = 11.9f; + style.FrameBorderSize = 0.0f; + style.ItemSpacing = ImVec2(8.9f, 13.4f); + style.ItemInnerSpacing = ImVec2(7.1f, 1.8f); + style.CellPadding = ImVec2(12.1f, 9.2f); + style.IndentSpacing = 0.0f; + style.ColumnsMinSpacing = 8.7f; + style.ScrollbarSize = 11.6f; + style.ScrollbarRounding = 15.9f; + style.GrabMinSize = 3.7f; + style.GrabRounding = 20.0f; + style.TabRounding = 9.8f; + style.TabBorderSize = 0.0f; + style.ColorButtonPosition = ImGuiDir_Right; + style.ButtonTextAlign = ImVec2(0.5f, 0.5f); + style.SelectableTextAlign = ImVec2(0.0f, 0.0f); + + style.Colors[ImGuiCol_Text] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.27450982f, 0.31764707f, 0.4509804f, 1.0f); + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_ChildBg] = ImVec4(0.09411765f, 0.101960786f, 0.11764706f, 1.0f); + style.Colors[ImGuiCol_PopupBg] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_Border] = ImVec4(0.15686275f, 0.16862746f, 0.19215687f, 1.0f); + style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_FrameBg] = ImVec4(0.11372549f, 0.1254902f, 0.15294118f, 1.0f); + style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.15686275f, 0.16862746f, 0.19215687f, 1.0f); + style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.15686275f, 0.16862746f, 0.19215687f, 1.0f); + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.047058824f, 0.05490196f, 0.07058824f, 1.0f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.047058824f, 0.05490196f, 0.07058824f, 1.0f); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.09803922f, 0.105882354f, 0.12156863f, 1.0f); + style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.047058824f, 0.05490196f, 0.07058824f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.15686275f, 0.16862746f, 0.19215687f, 1.0f); + style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.03137255f, 0.9490196f, 0.84313726f, 1.0f); + style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.03137255f, 0.9490196f, 0.84313726f, 1.0f); + style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.6f, 0.9647059f, 0.03137255f, 1.0f); + style.Colors[ImGuiCol_Button] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.18039216f, 0.1882353f, 0.19607843f, 1.0f); + style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.15294118f, 0.15294118f, 0.15294118f, 1.0f); + style.Colors[ImGuiCol_Header] = ImVec4(0.14117648f, 0.16470589f, 0.20784314f, 1.0f); + style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.105882354f, 0.105882354f, 0.105882354f, 1.0f); + style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_Separator] = ImVec4(0.12941177f, 0.14901961f, 0.19215687f, 1.0f); + style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.15686275f, 0.18431373f, 0.2509804f, 1.0f); + style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.15686275f, 0.18431373f, 0.2509804f, 1.0f); + style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.14509805f, 0.14509805f, 0.14509805f, 1.0f); + style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.03137255f, 0.9490196f, 0.84313726f, 1.0f); + style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + style.Colors[ImGuiCol_Tab] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_TabHovered] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_TabActive] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.078431375f, 0.08627451f, 0.101960786f, 1.0f); + style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.1254902f, 0.27450982f, 0.57254905f, 1.0f); + style.Colors[ImGuiCol_PlotLines] = ImVec4(0.52156866f, 0.6f, 0.7019608f, 1.0f); + style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.039215688f, 0.98039216f, 0.98039216f, 1.0f); + style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.03137255f, 0.9490196f, 0.84313726f, 1.0f); + style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.15686275f, 0.18431373f, 0.2509804f, 1.0f); + style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.047058824f, 0.05490196f, 0.07058824f, 1.0f); + style.Colors[ImGuiCol_TableBorderStrong] = ImVec4(0.047058824f, 0.05490196f, 0.07058824f, 1.0f); + style.Colors[ImGuiCol_TableBorderLight] = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); + style.Colors[ImGuiCol_TableRowBg] = ImVec4(0.11764706f, 0.13333334f, 0.14901961f, 1.0f); + style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.09803922f, 0.105882354f, 0.12156863f, 1.0f); + style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.9372549f, 0.9372549f, 0.9372549f, 1.0f); + style.Colors[ImGuiCol_DragDropTarget] = ImVec4(0.49803922f, 0.5137255f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavHighlight] = ImVec4(0.26666668f, 0.2901961f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.49803922f, 0.5137255f, 1.0f, 1.0f); + style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.19607843f, 0.1764706f, 0.54509807f, 0.5019608f); + style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.19607843f, 0.1764706f, 0.54509807f, 0.5019608f); + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.h b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.h new file mode 100644 index 0000000..33eb60c --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/ImGui/ImGuiThemes.h @@ -0,0 +1,6 @@ +#pragma once +namespace GameSmith { + void ApplyCatpuchinnTheme(); + void ApplyMoonlightTheme(); + void ApplyComfortableTheme(); +}; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Context.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Context.cpp index 9980ea8..894783d 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Context.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Context.cpp @@ -125,6 +125,8 @@ namespace GameSmith { m_BackBuffer->GetResourceStateTracker().TransitionBarrier(D3D12_RESOURCE_STATE_PRESENT, context); context->FinalizeCommandList(); + + // This expects there are no more commands lists to be submitted context->SubmitCommandLists(); core.InitializeCPUQueueWait(DirectX12QueueType::Direct); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Core.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Core.h index 4c3fad9..ebe0089 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Core.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12Core.h @@ -20,14 +20,18 @@ namespace GameSmith { static DirectX12Core& GetCore(); inline ID3D12Device8* GetDevice() { return m_Device.Get(); } inline IDXGIFactory5* GetFactory() { return m_Factory.Get(); } + inline void FrameCompletedRecording() { m_FrameIds.push(m_DirectContext->GetLastSubmissionID()); } + inline void FrameSkipped() { if (!m_FrameIds.empty()) { m_FrameIds.pop(); GE_CORE_INFO("Skipping this frame"); } } + inline void SwappingFrame() { if (!m_FrameIds.empty()) { InitializeCPUQueueWait(m_FrameIds.front(), Direct); m_FrameIds.pop(); } } + inline bool FrameReady() { return m_FrameIds.empty() || FindQueue(Direct).IsFenceComplete(m_FrameIds.front()); } inline DirectX12CommandContextDirect* GetDirectCommandContext() { return m_DirectContext.get(); } inline DirectX12CommandContextCopy* GetCopyCommandContext() { return m_CopyContext.get(); } diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.cpp index ae09d04..403a48c 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.cpp @@ -64,11 +64,22 @@ namespace GameSmith { return Ref(new DirectX12Shader(path)); } - Ref DirectX12RendererAPI::LoadShader(char* byteCode, unsigned int length) + Ref DirectX12RendererAPI::LoadShader(const char* byteCode, unsigned int length) { return Ref(new DirectX12Shader(byteCode, length)); } + Ref DirectX12RendererAPI::CompileShader(const Stages stage, const char* rawCode, const unsigned int length, const char* entryPt, const ShaderIncludeCache* includeCache, unsigned int* outSize) + { + const std::string model = TranslateStageToShaderModel(stage); + Ref compiledShader = m_ShaderCompiler.CompileShader(rawCode, length, entryPt, model.c_str(), includeCache, outSize); + if (compiledShader == nullptr) { + GE_CORE_ERROR("Shader compilation failed for entry point {0} with model {1}", entryPt, model); + } + + return compiledShader; + } + Ref DirectX12RendererAPI::CreateConstantBuffer(UINT size, std::string name) { return Ref(new DirectX12ConstantBuffer(size, name)); @@ -240,6 +251,13 @@ namespace GameSmith { directContext->SubmitCommandLists(); } + void DirectX12RendererAPI::FlushDataTransfer() + { + auto copyContext = m_Core.GetCopyCommandContext(); + copyContext->FinalizeCommandList(); + copyContext->SubmitCommandLists(); + } + void DirectX12RendererAPI::CompleteFrameSubmissions() { m_Core.FrameCompletedRecording(); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.h index b0b11d7..5962a50 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererAPI.h @@ -8,46 +8,49 @@ namespace GameSmith { { public: DirectX12RendererAPI(); - virtual ~DirectX12RendererAPI() override; - inline virtual API GetAPI() override { return API::DirectX12; } + ~DirectX12RendererAPI() override; + inline API GetAPI() override { return API::DirectX12; } - virtual void SetClearColor(const glm::vec4& color) override; - virtual void Clear() override; + void SetClearColor(const glm::vec4& color) override; + void Clear() override; - virtual void DrawIndexed(UINT indecies, UINT instances) override; + void DrawIndexed(UINT indecies, UINT instances) override; - virtual Ref CreateVertexBuffer(BYTE* data, int vertexByteSize, int vertexCount) override; - virtual void SetVertexBuffer(Ref vbuffer) override; - virtual Ref CreateIndexBuffer(unsigned int* data, unsigned int indexCount) override; - virtual void SetIndexBuffer(Ref ibuffer) override; - virtual Ref LoadShader(std::string path) override; - virtual Ref LoadShader(char* byteCode, unsigned int length) override; + Ref CreateVertexBuffer(BYTE* data, int vertexByteSize, int vertexCount) override; + void SetVertexBuffer(Ref vbuffer) override; + Ref CreateIndexBuffer(unsigned int* data, unsigned int indexCount) override; + void SetIndexBuffer(Ref ibuffer) override; + Ref LoadShader(std::string path) override; + Ref LoadShader(const char* byteCode, unsigned int length) override; + Ref CompileShader(const Stages stage, const char* rawCode, const unsigned int length, const char* entryPt, const ShaderIncludeCache* includeCache, unsigned int* outSize) override; - virtual Ref CreateConstantBuffer(UINT size, std::string name) override; - virtual Ref CreateConstantBuffer(UINT size) override; - virtual void SetConstantBuffer(Ref cbuffer, Stages stage, ShaderConstantType constantType) override; + Ref CreateConstantBuffer(UINT size, std::string name) override; + Ref CreateConstantBuffer(UINT size) override; + void SetConstantBuffer(Ref cbuffer, Stages stage, ShaderConstantType constantType) override; - virtual Ref CreateTexture2D(char* data, UINT size) override; - virtual Ref CreateRenderTexture(unsigned int width, unsigned int height) override; - virtual Ref CreateRenderTexture(unsigned int width, unsigned int height, float* clearColor) override;; + Ref CreateTexture2D(char* data, UINT size) override; + Ref CreateRenderTexture(unsigned int width, unsigned int height) override; + Ref CreateRenderTexture(unsigned int width, unsigned int height, float* clearColor) override;; - virtual void SetRenderTexture(Ref rt, UINT index) override; - virtual void SetTexture2D(Ref tex, UINT slot, Stages stage) override; + void SetRenderTexture(Ref rt, UINT index) override; + void SetTexture2D(Ref tex, UINT slot, Stages stage) override; - virtual Ref CreateSampler(FilterType img, PaddingMethod padMode) override; - virtual void SetSampler(Ref sampler, Stages stage) override; + Ref CreateSampler(FilterType img, PaddingMethod padMode) override; + void SetSampler(Ref sampler, Stages stage) override; - virtual void SetTopology(TopologyType& type, bool tesselation) override; + void SetTopology(TopologyType& type, bool tesselation) override; - virtual Ref CreateGraphicsPipelineState(PipelineStateInitializer& init) override; - virtual void SetGraphicsPipelineState(Ref pso) override; + Ref CreateGraphicsPipelineState(PipelineStateInitializer& init) override; + void SetGraphicsPipelineState(Ref pso) override; - virtual void SubmitRecording() override; - virtual void CompleteFrameSubmissions() override; + void SubmitRecording() override; + void FlushDataTransfer() override; + void CompleteFrameSubmissions() override; - inline virtual void ClearCachedAssets() override { } + inline void ClearCachedAssets() override { } private: DirectX12Core& m_Core; + DirectX12ShaderCompiler m_ShaderCompiler; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererHeaders.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererHeaders.h index d3499ae..5cbe609 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererHeaders.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12RendererHeaders.h @@ -1,6 +1,7 @@ #pragma once #include "GameSmithEngine/Rendering/DirectX12/DirectX12Core.h" +#include "GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.h" #include "GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12PipelineState.h" #include "GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12RootSignature.h" diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.cpp new file mode 100644 index 0000000..6fc964b --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.cpp @@ -0,0 +1,103 @@ +#include "gepch.h" +#include "GameSmithEngine/Core/Log.h" +#include "DirectX12ShaderCompiler.h" +#include "GameSmithEngine/Utilities/MiscellaneousUtilities.h" + +#pragma comment(lib, "dxcompiler.lib") + +// TODO: Revisit optimization settings and make them configurable based on debug/release and other settings +// Starting optimization flags +#define SHADER_COMPILATION_FLAGS { DXC_ARG_ENABLE_STRICTNESS, DXC_ARG_OPTIMIZATION_LEVEL2 } + +namespace GameSmith { + DirectX12ShaderCompiler::DirectX12ShaderCompiler() + { + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&m_DxCompiler)); + DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&m_DxUtils)); + + m_IncludeResolver = new DirectX12ShaderIncludeResolver(m_DxUtils); + } + + Ref DirectX12ShaderCompiler::CompileShader( + const char* source, + const unsigned int sourceLength, + const std::string entryPoint, + const std::string profile, + const ShaderIncludeCache* cache, + unsigned int* outSize) + { + m_IncludeResolver->SetIncludeCache(cache); + + const DxcBuffer sourceBuffer = { + source, + sourceLength, + DXC_CP_UTF8 + }; + + LPCWSTR arguments[] = SHADER_COMPILATION_FLAGS; + + const std::wstring entryPointW = ToWideString(entryPoint); + const std::wstring profileW = ToWideString(profile); + + ComPtr compilerArgs; + m_DxUtils->BuildArguments( + L"Shader", + entryPointW.c_str(), + profileW.c_str(), + arguments, + ARRAYSIZE(arguments), + nullptr, + 0, + &compilerArgs + ); + + ComPtr result; + m_DxCompiler->Compile( + &sourceBuffer, + compilerArgs->GetArguments(), + compilerArgs->GetCount(), + m_IncludeResolver.Get(), + IID_PPV_ARGS(&result) + ); + + HRESULT hr; + result->GetStatus(&hr); + if (!FAILED(hr)) { + GE_CORE_ASSERT(result->HasOutput(DXC_OUT_OBJECT), "Compiled shader was not returned"); + + ComPtr compiledShader; + hr = result->GetOutput( + DXC_OUT_OBJECT, + IID_PPV_ARGS(&compiledShader), + nullptr + ); + + GE_CORE_ASSERT(!FAILED(hr), "Failed to retrieve compiled shader blob"); + + char* compiledCode = new char[compiledShader->GetBufferSize()]; + memcpy(compiledCode, compiledShader->GetBufferPointer(), compiledShader->GetBufferSize()); + + *outSize = static_cast(compiledShader->GetBufferSize()); + return Ref(compiledCode); + } + else { + std::string errorMsg = ""; + if (result->HasOutput(DXC_OUT_ERRORS)) { + ComPtr errors; + hr = result->GetOutput( + DXC_OUT_ERRORS, + IID_PPV_ARGS(&errors), + nullptr + ); + + GE_CORE_ASSERT(!FAILED(hr), "Failed to retrieve shader compilation error message"); + errorMsg = std::string(errors->GetStringPointer(), errors->GetStringLength()); + } + + GE_CORE_ERROR("Shader compilation failed: {0}", errorMsg); + } + + + return Ref(); + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.h new file mode 100644 index 0000000..d0287bb --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.h @@ -0,0 +1,31 @@ +#pragma once + +#include "GameSmithEngine/Core/Core.h" +#include +#include +#include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h" +#include "GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.h" + +using Microsoft::WRL::ComPtr; + +namespace GameSmith { + class GE_API DirectX12ShaderCompiler + { + public: + DirectX12ShaderCompiler(); + + Ref CompileShader( + const char* source, + const unsigned int sourceLength, + const std::string entryPoint, + const std::string profile, + const ShaderIncludeCache* cache, + unsigned int* outSize + ); + private: + ComPtr m_DxCompiler; + ComPtr m_DxUtils; + + ComPtr m_IncludeResolver; + }; +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.cpp index d818872..2ecd70b 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.cpp @@ -20,7 +20,7 @@ namespace GameSmith { GenerateHash(); } - DirectX12Shader::DirectX12Shader(char* byteCode, unsigned int length) + DirectX12Shader::DirectX12Shader(const char* byteCode, unsigned int length) { bool res = FAILED(D3DCreateBlob(length, &m_Blob)); GE_CORE_ASSERT(!res, "Failed to create blob buffer"); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.h index 7cfebde..db128cb 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/DirectX12Shader.h @@ -12,21 +12,21 @@ namespace GameSmith { public: DirectX12Shader(const std::string path); DirectX12Shader(ComPtr loadedByteCode); - DirectX12Shader(char* byteCode, unsigned int length); + DirectX12Shader(const char* byteCode, unsigned int length); inline ID3DBlob* ByteCode() const { return m_Blob.Get(); } - inline virtual Stages GetShaderType() override { + inline Stages GetShaderType() override { // TODO: Return actual shader type return Stages::STAGE_NUM; } - inline virtual unsigned int GetHash() override { return m_Hash; } + inline unsigned int GetHash() override { return m_Hash; } - inline virtual const char* GetRawByteCode() override { + inline const char* GetRawByteCode() override { return (char*)m_Blob->GetBufferPointer(); }; - inline virtual unsigned int GetByteCodeSize() override { + inline unsigned int GetByteCodeSize() override { return (unsigned int)m_Blob->GetBufferSize(); }; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/Texture/DirectX12RenderTexture.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/Texture/DirectX12RenderTexture.cpp index 71f7201..01af4ea 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/Texture/DirectX12RenderTexture.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/RenderComponents/Texture/DirectX12RenderTexture.cpp @@ -92,6 +92,7 @@ namespace GameSmith { void DirectX12RenderTexture::ClearTexture() { auto context = DirectX12Core::GetCore().GetDirectCommandContext(); + ChangeState(RTState::WRITE); context->GetCommandList()->ClearRenderTargetView(m_RTDescriptor, m_Metadata.clearColor, 0, nullptr); } diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.cpp new file mode 100644 index 0000000..2d5ec62 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.cpp @@ -0,0 +1,34 @@ +#include "gepch.h" +#include "DirectX12ShaderIncludeResolver.h" +#include "GameSmithEngine/Core/Log.h" +#include "GameSmithEngine/Utilities/MiscellaneousUtilities.h" +#include + +using Microsoft::WRL::ComPtr; + +namespace GameSmith { + HRESULT DirectX12ShaderIncludeResolver::LoadSource(LPCWSTR pFilename, IDxcBlob** ppIncludeSource) + { + GE_CORE_ASSERT(m_IncludeCache != nullptr, "No Shader Cache has been set in the include resolver"); + + const std::wstring fileNameW(pFilename); + const std::string fileName = ToNarrowString(fileNameW); + const std::string cleanedFileName = fileName.find_last_of("\\/") != std::string::npos ? fileName.substr(fileName.find_last_of("\\/") + 1) : fileName; + + unsigned int sourceSize = 0; + const char* source = m_IncludeCache->RetrieveShaderContent(cleanedFileName, &sourceSize); + + IDxcBlobEncoding* blob; + m_Utils->CreateBlob( + source, + sourceSize, + DXC_CP_UTF8, + &blob + ); + + *ppIncludeSource = blob; + + return S_OK; + } +}; + diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.h new file mode 100644 index 0000000..4ccd3f9 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderIncludeResolver.h @@ -0,0 +1,54 @@ +#pragma once + +#include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h" +#include +#include + +using Microsoft::WRL::ComPtr; + +namespace GameSmith { + class DirectX12ShaderIncludeResolver : public IDxcIncludeHandler + { + public: + DirectX12ShaderIncludeResolver(ComPtr utilInstance) : m_IncludeCache(nullptr), m_Utils(utilInstance) {} + + inline void SetIncludeCache(const ShaderIncludeCache* cache) { m_IncludeCache = cache; } + + HRESULT LoadSource(LPCWSTR pFilename, IDxcBlob** ppIncludeSource) override; + + HRESULT QueryInterface(REFIID riid, void** ppvObject) override + { + if (riid == __uuidof(IDxcIncludeHandler)) { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + else if (riid == __uuidof(IUnknown)) { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + else { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + } + + ULONG AddRef() override + { + m_RefCount++; + return m_RefCount; + } + + ULONG Release() override + { + m_RefCount--; + return m_RefCount; + } + private: + const ShaderIncludeCache* m_IncludeCache; + ComPtr m_Utils; + + unsigned int m_RefCount = 0; + }; +} \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.cpp index 36eea17..9fb5061 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.cpp @@ -1,12 +1,12 @@ #include "gepch.h" #include "DirectX12ShaderUtils.h" -#define VS_MODEL "vs_5_0" -#define PS_MODEL "ps_5_0" +#define VS_MODEL "vs_6_5" +#define PS_MODEL "ps_6_5" namespace GameSmith { - static std::string TranslateStageToShaderModel(Stages stage) { + std::string TranslateStageToShaderModel(Stages stage) { switch (stage) { case STAGE_VERTEX: return VS_MODEL; @@ -16,15 +16,6 @@ namespace GameSmith { return VS_MODEL; } - - ComPtr CompileShaderForDX12(std::string rawCode, std::string entryFunction, Stages stage, std::string destFile) - { - ComPtr resultShader; - std::string shaderModel = TranslateStageToShaderModel(stage); - D3DCompile2(rawCode.c_str(), rawCode.size(), NULL, NULL, NULL, entryFunction.c_str(), shaderModel.c_str(), NULL, NULL, NULL, NULL, NULL, &resultShader, NULL); - - return resultShader; - } }; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.h b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.h index f2a3909..7ec2f3c 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/DirectX12/Util/DirectX12ShaderUtils.h @@ -5,10 +5,10 @@ #include #define SHADER_STATE_STREAM_NULL_SAFE(x, StreamType) x != nullptr ? \ -CD3DX12_SHADER_BYTECODE(CastPtr(x->GetShader())->ByteCode()) : StreamType() +CD3DX12_SHADER_BYTECODE(CastPtr(x)->ByteCode()) : StreamType() using Microsoft::WRL::ComPtr; namespace GameSmith { - extern ComPtr CompileShaderForDX12(std::string rawCode, std::string entryFunction, Stages stage, std::string destFile); + std::string TranslateStageToShaderModel(Stages stage); }; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/Camera.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/Camera.h index 72a4fe1..2864f9f 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/Camera.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/Camera.h @@ -1,12 +1,13 @@ #pragma once #include "GameSmithEngine/EntitySystem/Transform.h" +#include namespace GameSmith { // An abstract representation of a Camera in 3D space // Takes care of computing transformation matricies related to a camera (View-Projection Matrix) // Note: Camera base class does not compute any special projection matrix, inheritors hold the responsibility of setting the projection matrix - class Camera + class GE_API Camera { public: Camera(); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/OrthoCamera.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/OrthoCamera.h index 102df3f..98134a3 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/OrthoCamera.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/OrthoCamera.h @@ -1,10 +1,11 @@ #pragma once #include "Camera.h" +#include namespace GameSmith { // This class representes an Orthographic Camera (Orthographics Projection) - class OrthoCamera : public Camera + class GE_API OrthoCamera : public Camera { public: OrthoCamera(float left = 0.0f, float right = 0.0f, float bottom = 1.0f, float top = 1.0f, float zNear = -1000.0f, float zFar = 1000.0f); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/PerspectiveCamera.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/PerspectiveCamera.h index e116dc7..b21f4c2 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/PerspectiveCamera.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Camera/PerspectiveCamera.h @@ -1,8 +1,9 @@ #pragma once #include "Camera.h" +#include namespace GameSmith { - class PerspectiveCamera : public Camera + class GE_API PerspectiveCamera : public Camera { public: PerspectiveCamera(float width, float height, float FOV = glm::radians(60.0f), float zNear = 0.2f, float zFar = 500.0f); diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.cpp new file mode 100644 index 0000000..e4d9285 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.cpp @@ -0,0 +1,17 @@ +#include "gepch.h" +#include "Shader.h" + +std::string GameSmith::ConvertShaderStageToString(Stages stage) +{ + switch (stage) { + case STAGE_VERTEX: + return "Vertex"; + case STAGE_HULL: + return "Hull"; + case STAGE_DOMAIN: + return "Domain"; + case STAGE_PIXEL: + return "Pixel"; + } + return std::string(); +} diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h index dbef6c8..18020fc 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h @@ -10,6 +10,8 @@ namespace GameSmith { STAGE_NUM }; + std::string ConvertShaderStageToString(Stages stage); + // INTERFACE // A piece of code to be ran on the GPU in some part of a render pipline class Shader diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.cpp new file mode 100644 index 0000000..747f4c8 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.cpp @@ -0,0 +1,20 @@ +#include "gepch.h" +#include "ShaderMetadata.h" + +#define PROPERTIES_KEY "Properties" + +namespace GameSmith { + void ShaderMetadata::ExtractJsonData(const json& newJson) + { + if (newJson.contains(PROPERTIES_KEY)) { + m_Properties = newJson[PROPERTIES_KEY].get>(); + } + } + + void ShaderMetadata::RefreshConfig() + { + json newJson; + newJson[PROPERTIES_KEY] = m_Properties; + UpdateJson(newJson); + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.h new file mode 100644 index 0000000..6aab181 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/SLab/ShaderMetadata.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include "GameSmithEngine/Utilities/ParameterContainer.h" +#include "GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.h" + +namespace GameSmith { + enum class ShaderDataType { + None = 0, + Float, + Float2, + Float3, + Float4, + Int, + Int2, + Int3, + Int4, + Bool, + Matrix + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(ShaderDataType, { + {ShaderDataType::None, "None"}, + {ShaderDataType::Float, "Float"}, + {ShaderDataType::Float2, "Float2"}, + {ShaderDataType::Float3, "Float3"}, + {ShaderDataType::Float4, "Float4"}, + {ShaderDataType::Int, "Int"}, + {ShaderDataType::Int2, "Int2"}, + {ShaderDataType::Int3, "Int3"}, + {ShaderDataType::Int4, "Int4"}, + {ShaderDataType::Bool, "Bool"}, + {ShaderDataType::Matrix, "Matrix"} + }) + + class ShaderMetadata : public JsonFile { + public: + ShaderMetadata() = default; + void ExtractJsonData(const json& newJson) override; + private: + void RefreshConfig(); + private: + std::unordered_map m_Properties; + }; +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.cpp new file mode 100644 index 0000000..efddab4 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.cpp @@ -0,0 +1,29 @@ +#include "gepch.h" +#include "GameSmithEngine/Core/Core.h" +#include "GameSmithEngine/Core/Log.h" +#include "ShaderIncludeCache.h" + +#include "GameSmithEngine/ResourceManagement/AssetManager.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h" + +namespace GameSmith { + void ShaderIncludeCache::AddInclude(const std::string& includeName, const ID& includeID) + { + GE_APP_ASSERT(!m_IncludeCache.contains(includeName), "Shader include already exists in cache"); + m_IncludeCache[includeName] = includeID; + } + + const char* ShaderIncludeCache::RetrieveShaderContent(const std::string& includeName, unsigned int* outSourceSize) const + { + auto assetManager = AssetManager::GetInstance(); + GE_CORE_ASSERT(assetManager != nullptr, "AssetManager is not loaded, cannot retrieve shader content"); + GE_CORE_ASSERT(m_IncludeCache.contains(includeName), "Not shader entry for {0}", includeName); + + const ID& includeID = m_IncludeCache.find(includeName)->second; + + auto source = assetManager->GetResource(includeID); + + *outSourceSize = source->GetSize(); + return source->GetBytes(); + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h new file mode 100644 index 0000000..d202290 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include "GameSmithEngine/Utilities/GUIDGenerator.h" + +namespace GameSmith { + class GE_API ShaderIncludeCache { + public: + ShaderIncludeCache() = default; + ~ShaderIncludeCache() = default; + // Adds a shader include to the cache + void AddInclude(const std::string& includeName, const ID& includeID); + // Retrieves a shader include from the cache and allocates space on the heap (ownership is tranferred to caller) + const char* RetrieveShaderContent(const std::string& includeName, unsigned int* outSourceSize) const; + private: + std::unordered_map m_IncludeCache; // Maps include names to their content + }; +} \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderUtil.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderUtil.h index dc5af66..411e9a7 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderUtil.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderUtil.h @@ -1,6 +1,6 @@ #pragma once #include "GameSmithEngine/Core/Core.h" -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h" #include namespace GameSmith { @@ -19,7 +19,7 @@ namespace GameSmith { }; struct ShaderSet { - Ref shaders[STAGE_NUM]; + Ref shaders[STAGE_NUM]; std::size_t operator()(const ShaderSet& key) const { std::size_t hash = 0; @@ -29,7 +29,7 @@ namespace GameSmith { Stages stage = (Stages)i; if (shaders[i] != nullptr) { - hash ^= shaders[i]->GetShader()->GetHash(); + hash ^= shaders[i]->GetHash(); } } diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RendererAPI.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RendererAPI.h index af52dcd..eb14896 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RendererAPI.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RendererAPI.h @@ -11,6 +11,7 @@ #include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/PipelineStateInitializer.h" #include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/PipelineStateObject.h" #include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderUtil.h" +#include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h" #include "GameSmithEngine/Core/Core.h" namespace GameSmith { @@ -33,8 +34,10 @@ namespace GameSmith { virtual void SetVertexBuffer(Ref vbuffer) = 0; virtual Ref CreateIndexBuffer(unsigned int* data, unsigned int indexCount) = 0; virtual void SetIndexBuffer(Ref ibuffer) = 0; + virtual Ref LoadShader(std::string path) = 0; - virtual Ref LoadShader(char* byteCode, unsigned int length) = 0; + virtual Ref LoadShader(const char* byteCode, unsigned int length) = 0; + virtual Ref CompileShader(const Stages stage, const char* rawCode, const unsigned int length, const char* entryPt, const ShaderIncludeCache* includeCache, unsigned int* outSize) = 0; virtual Ref CreateConstantBuffer(UINT size, std::string name) = 0; virtual Ref CreateConstantBuffer(UINT size) = 0; @@ -56,6 +59,7 @@ namespace GameSmith { virtual void SetGraphicsPipelineState(Ref pso) = 0; virtual void SubmitRecording() = 0; + virtual void FlushDataTransfer() = 0; virtual void CompleteFrameSubmissions() = 0; virtual void ClearCachedAssets() = 0; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.cpp b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.cpp index 0f79698..705ccce 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.cpp @@ -37,11 +37,20 @@ namespace GameSmith { } } + void RenderingManager::SetShaderSourceCache(const std::unordered_map& shaderFiles) + { + for (auto& entry : shaderFiles) { + m_ShaderIncludeCache.AddInclude(entry.first, entry.second); + } + } + void RenderingManager::BeginScene(Camera* cam, LightSource* mainLight) { //m_RenderAPI->ClearCachedAssets(); - m_SceneData.VP = cam->GetMatrix(); - m_SceneData.CameraWorldPos = cam->GetTransform().GetPosition(); + if (cam != nullptr) { + m_SceneData.VP = cam->GetMatrix(); + m_SceneData.CameraWorldPos = cam->GetTransform().GetPosition(); + } if (mainLight != nullptr) { m_SceneData.LightWorldPos = mainLight->GetLightVector(); @@ -88,5 +97,20 @@ namespace GameSmith { m_RenderAPI->SubmitRecording(); } - + void RenderingManager::SyncDataTransfer() + { + m_RenderAPI->FlushDataTransfer(); + } + + Ref RenderingManager::CompileOrRetrieveShader(const Stages stage, const char* shaderCode, unsigned int size, const ID& sourceAssetID) + { + if (m_CompiledShaderCache.contains(sourceAssetID)) { + // Load asset file and return shader + } + + unsigned int compiledSize; + Ref compiledShader = m_RenderAPI->CompileShader(stage, shaderCode, size, "main", &m_ShaderIncludeCache, &compiledSize); + + return m_RenderAPI->LoadShader(compiledShader.get(), compiledSize); + } }; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.h b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.h index 7edff46..fd55a42 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.h +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/RenderingManager.h @@ -1,15 +1,17 @@ #pragma once #include "GameSmithEngine/Core/Core.h" -#include "RendererAPI.h" +#include "GameSmithEngine/Events/RenderingEvents.h" #include "PipelineStateObjectManager.h" +#include "RendererAPI.h" #include "RenderWorkflow.h" -#include "GameSmithEngine/Events/RenderingEvents.h" #include "GameSmithEngine/Rendering/RenderAgnostics/Camera/Camera.h" #include "GameSmithEngine/Rendering/RenderAgnostics/LightingSystem/LightSource.h" -#include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h" #include "GameSmithEngine/Rendering/RenderAgnostics/MaterialSystem/Material.h" +#include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h" + + namespace GameSmith { // A class that can submit high level rendering commands (Taking a scene and drawing it to the screen) // This can appear as handling some high level logic and then executing commands to perform low level logic related to Rendering @@ -28,6 +30,8 @@ namespace GameSmith { /// static void ShutDown(); + void SetShaderSourceCache(const std::unordered_map& shaderFiles); + /// /// Sets the render workflow to be used when processing a submission /// @@ -43,6 +47,9 @@ namespace GameSmith { void ClearTextures(); void Submit(Ref vBuff, Ref iBuff, Ref mat); + void SyncDataTransfer(); + + Ref CompileOrRetrieveShader(const Stages stage, const char* shaderCode, unsigned int size, const ID& sourceAssetID); inline RendererAPI::API GetAPI() { return m_RenderAPI->GetAPI(); }; inline RendererAPI* GetRenderAPI() { return m_RenderAPI.get(); } @@ -76,6 +83,12 @@ namespace GameSmith { // The texture to render submissions to Ref m_FrameTexture; + // A cache for shader includes + ShaderIncludeCache m_ShaderIncludeCache; + + // Maps shader asset IDs to their compiled shader IDs + std::unordered_map m_CompiledShaderCache; + // A list of textures to clear after a swap chain switch std::queue> m_ClearOnSwap; diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Core.hlsli b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Core.hlsl similarity index 100% rename from GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Core.hlsli rename to GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Core.hlsl diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/BlinnPhongPixelShader.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/BlinnPhongPixelShader.hlsl index 823b97a..5ff0e03 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/BlinnPhongPixelShader.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/BlinnPhongPixelShader.hlsl @@ -13,7 +13,7 @@ cbuffer Instance : register(b1) { matrix M; }; -#include "../Core.hlsli" +#include "../Core.hlsl" float4 main(VertexShaderOutput input) : SV_TARGET { diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/FlatColorPixelShader.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/FlatColorPixelShader.hlsl index cce8ef0..8b87c95 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/FlatColorPixelShader.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/FlatColorPixelShader.hlsl @@ -3,7 +3,7 @@ cbuffer Instance : register(b1) matrix model; }; -#include "../Core.hlsli" +#include "../Core.hlsl" float4 main() : SV_TARGET { diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/RandomColorPS.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/RandomColorPS.hlsl index cdfdbe3..aa7720f 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/RandomColorPS.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Pixel/RandomColorPS.hlsl @@ -10,7 +10,7 @@ cbuffer Instance : register(b1) matrix model; float4 colors[8]; }; -#include "../Core.hlsli" +#include "../Core.hlsl" float4 main(VertexShaderOutput input) : SV_TARGET { diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/BasicRenderVS.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/BasicRenderVS.hlsl index 28bf4a7..b61af0e 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/BasicRenderVS.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/BasicRenderVS.hlsl @@ -3,7 +3,7 @@ struct VertexShaderOutput float4 Position : SV_POSITION; }; -#include "../Core.hlsli" +#include "../Core.hlsl" VertexShaderOutput main(DefaultVertexData input ) { diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexShader.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexShader.hlsl index d1132e4..15db8b5 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexShader.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexShader.hlsl @@ -14,7 +14,7 @@ cbuffer Instance : register(b1) { float3 inputColor; }; -#include "../Core.hlsli" +#include "../Core.hlsl" VertexShaderOutput main(DefaultVertexData input, uint id : SV_VertexID) { diff --git a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexTesShader.hlsl b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexTesShader.hlsl index 4e04af6..a6cbc52 100644 --- a/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexTesShader.hlsl +++ b/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/SampleVertexTesShader.hlsl @@ -10,7 +10,7 @@ cbuffer Instance : register(b1) { float3 inputColor; }; -#include "../Core.hlsli" +#include "../Core.hlsl" VertexShaderOutput main(DefaultVertexData input) { diff --git a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.cpp b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.cpp index 62a0e14..ef1df3c 100644 --- a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.cpp +++ b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.cpp @@ -4,20 +4,17 @@ #include "ResourceLoaders/HeapResourceLoader.h" -#include - #include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" #define META_FILE_EXTENSION ".meta" #define CONTENT_LIBRARY_FILE_EXTENSION "dll" -namespace fs = std::filesystem; using recursive_directory_iterator = fs::recursive_directory_iterator; namespace GameSmith { AssetManager* AssetManager::s_Instance = nullptr; - static Ref GetLoader(ResourceLoaderType loaderType) { + static Ref GetLoader(const ResourceLoaderType loaderType) { switch (loaderType) { case ResourceLoaderType::Heap: return Ref(new HeapResourceLoader()); @@ -34,7 +31,7 @@ namespace GameSmith { } - void AssetManager::Init(ResourceLoaderType loaderType) + void AssetManager::Init(const ResourceLoaderType loaderType) { if (s_Instance == nullptr) { s_Instance = new AssetManager(); @@ -54,19 +51,23 @@ namespace GameSmith { } } - ID AssetManager::WriteResource(Ref resource, std::string path) + ID AssetManager::WriteResource(const Ref resource, const std::string& destDir) { - std::fstream pFile(path, std::ios::out | std::ios::binary | std::ios::ate); - GE_CORE_ASSERT(pFile.is_open(), std::format("Asset file {0} cannot be opened", path)); + const std::string filePath = std::format("{0}\\{1}{2}", destDir, resource->GetName(), resource->GetFileExtension()); + std::fstream pFile(filePath, std::ios::out | std::ios::binary | std::ios::ate); + GE_CORE_ASSERT(pFile.is_open(), std::format("Asset file {0} cannot be opened", destDir)); - std::fstream metaFile(path + ".meta", std::ios::out | std::ios::binary | std::ios::ate); - GE_CORE_ASSERT(metaFile.is_open(), std::format("Asset file {0} cannot be opened", path)); + std::fstream metaFile(filePath + META_FILE_EXTENSION, std::ios::out | std::ios::binary | std::ios::ate); + GE_CORE_ASSERT(metaFile.is_open(), std::format("Asset file {0} cannot be opened", destDir)); - auto serial = resource->Serialize(); - auto id = resource->GetID(); + const auto serial = resource->Serialize(); + const auto id = resource->GetID(); pFile.seekg(0, pFile.beg); - pFile.write(serial.get(), resource->RequiredSpace()); + unsigned int size = resource->RequiredSpace(); + if (size > 0) { + pFile.write(serial.get(), resource->RequiredSpace()); + } pFile.close(); ResourceFileMetadata meta; @@ -76,19 +77,50 @@ namespace GameSmith { metaFile.write((char*)&meta, sizeof(meta)); metaFile.close(); - m_ResourceMaps->ResourceRegistry.insert({ id, path }); - m_ResourceMaps->ReverseResourceRegistry.insert({ path, meta.ID }); + const fs::path filePathObj(filePath); + const std::string fileName = filePathObj.stem().string(); + const std::string ext = filePathObj.extension().string(); + m_ResourceMaps->ResourceRegistry.insert({ id, filePath }); + m_ResourceMaps->ReverseResourceRegistry.insert({ filePath, id }); + if (m_ResourceMaps->ExtensionToFilePaths.contains(ext)) { + m_ResourceMaps->ExtensionToFilePaths[ext].push_back(filePath); + } + else { + m_ResourceMaps->ExtensionToFilePaths.insert({ ext, { filePath } }); + } return id; } - ID AssetManager::ImportResource(std::string path) + ID AssetManager::CreateResource(const std::string& fileName, const std::string& destDir) { - // TOOD: Add more to import logic, for now it's just ID assignment - std::fstream metaFile(path + ".meta", std::ios::out | std::ios::binary | std::ios::ate); - GE_CORE_ASSERT(metaFile.is_open(), std::format("Asset file {0} cannot be opened", path)); + const std::string filePath = std::format("{0}\\{1}", destDir, fileName); + GE_CORE_ASSERT(!m_ResourceMaps->ReverseResourceRegistry.contains(filePath), "Resource already exists at the desired path"); + + const fs::path filePathObj(filePath); + const std::string ext = filePathObj.extension().string(); + const std::string fileNameNoExt = filePathObj.stem().string(); + Ref asset = AssetFactory::GenerateAsset(ext, fileNameNoExt); + + return WriteResource(asset, destDir); + } + + ID AssetManager::ImportResource(const std::string& path) + { + const fs::path filePath(path); + const std::string fileNameWithExt = filePath.filename().string(); + const std::string ext = filePath.extension().string(); + const std::string fileName = filePath.filename().stem().string(); + std::string destPath = std::format("{0}\\{1}", m_AssetDirectory, fileNameWithExt); + if (!fs::copy_file(filePath.string(), destPath)) { + GE_CORE_ERROR("Failed to import resource"); + return ID(); + } + + std::fstream metaFile(destPath + META_FILE_EXTENSION, std::ios::out | std::ios::binary | std::ios::ate); + GE_CORE_ASSERT(metaFile.is_open(), std::format("Asset file {0} cannot be opened", destPath)); - auto newID = GUIDGenerator::GenerateID(); + const auto newID = GUIDGenerator::GenerateID(); ResourceFileMetadata meta; meta.ID = newID.getData(); @@ -97,13 +129,19 @@ namespace GameSmith { metaFile.write((char*)&meta, sizeof(meta)); metaFile.close(); - m_ResourceMaps->ResourceRegistry.insert({ meta.ID, path }); - m_ResourceMaps->ReverseResourceRegistry.insert({ path, meta.ID }); + m_ResourceMaps->ResourceRegistry.insert({ meta.ID, destPath }); + m_ResourceMaps->ReverseResourceRegistry.insert({ destPath, meta.ID }); + if (m_ResourceMaps->ExtensionToFilePaths.contains(ext)) { + m_ResourceMaps->ExtensionToFilePaths[ext].push_back(destPath); + } else { + m_ResourceMaps->ExtensionToFilePaths.insert({ ext, { destPath } }); + } + return newID; } - ID AssetManager::GetAssetID(std::string path) + ID AssetManager::GetAssetID(const std::string& path) const { if (m_ResourceMaps->ReverseResourceRegistry.contains(path)) { return m_ResourceMaps->ReverseResourceRegistry.find(path)->second; @@ -112,25 +150,45 @@ namespace GameSmith { return ID(); } + std::string AssetManager::GetAssetPath(const ID& id) const + { + if (m_ResourceMaps->ResourceRegistry.contains(id)) { + return m_ResourceMaps->ResourceRegistry[id]; + } + + return std::string(); + } + void AssetManager::ScanResources() { if (m_AssetDirectory != "") { for (const auto& dirEntry : recursive_directory_iterator(m_AssetDirectory)) { if (dirEntry.is_regular_file()) { - std::string fileName = dirEntry.path().filename().string(); - std::string path = dirEntry.path().string(); + const fs::path filePath = dirEntry.path(); + const std::string fileName = filePath.filename().stem().string(); + const std::string ext = filePath.extension().string(); + const std::string path = filePath.string(); if (std::filesystem::exists(path + META_FILE_EXTENSION)) { unsigned int metaSize; - // Ptr leak? TODO: Review later + char* meta = m_Loader->LoadResource(path + META_FILE_EXTENSION, &metaSize); - ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; - ID metaId(metaPtr->ID); + const ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; + const ID metaId(metaPtr->ID); if (!m_ResourceMaps->ResourceRegistry.contains(metaId)) { m_ResourceMaps->ResourceRegistry.insert({ metaId, path }); m_ResourceMaps->ReverseResourceRegistry.insert({ path, metaId }); + + if (m_ResourceMaps->ExtensionToFilePaths.contains(ext)) { + m_ResourceMaps->ExtensionToFilePaths[ext].push_back(path); + } + else { + m_ResourceMaps->ExtensionToFilePaths.insert({ ext, { path } }); + } } + + m_Loader->CleanResource(meta); } } } @@ -162,7 +220,7 @@ namespace GameSmith { } } - Ref AssetManager::GetResource(ID asset) { + Ref AssetManager::GetResource(const ID asset) { if (m_ResourceMaps->ActiveIDResources.contains(asset)) { return (*m_ResourceMaps->ActiveIDResources.find(asset)).second; } @@ -170,7 +228,9 @@ namespace GameSmith { GE_CORE_ASSERT(m_ResourceMaps->ResourceRegistry.contains(asset), "No UUID entry for asset"); GE_CORE_INFO("Loading file into memory!"); - std::string path = m_ResourceMaps->ResourceRegistry.find(asset)->second; + const std::string path = m_ResourceMaps->ResourceRegistry.find(asset)->second; + const fs::path filePath(path); + const std::string fileName = filePath.stem().string(); UINT size; char* data = m_Loader->LoadResource(path, &size); @@ -181,11 +241,11 @@ namespace GameSmith { GE_CORE_ASSERT(metaSize == sizeof(ResourceFileMetadata), "Meta data of resource has been manipulated and does not match the expected size"); - std::string ext = path.substr(path.find_last_of('.') + 1); - Ref resource = AssetFactory::GenerateAsset(ext); + const std::string ext = filePath.extension().string(); + const Ref resource = AssetFactory::GenerateAsset(ext, fileName); resource->Deserialize(data, size); - ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; + const ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; ID metaId(metaPtr->ID); resource->SetID(metaId); @@ -198,7 +258,7 @@ namespace GameSmith { return resource; } - Ref AssetManager::GetResource(std::string asset) { + Ref AssetManager::GetResource(const std::string& asset) { if (m_ResourceMaps->ActivePathResources.contains(asset)) { return (*m_ResourceMaps->ActivePathResources.find(asset)).second; } @@ -207,8 +267,10 @@ namespace GameSmith { UINT size; char* data = m_Loader->LoadResource(asset, &size); - std::string ext = asset.substr(asset.find_last_of('.') + 1); - Ref resource = AssetFactory::GenerateAsset(ext); + const fs::path filePath(asset); + const std::string fileName = filePath.stem().string(); + const std::string ext = filePath.extension().string(); + const Ref resource = AssetFactory::GenerateAsset(ext, fileName); resource->Deserialize(data, size); m_ResourceMaps->ActivePathResources.insert({ asset, resource }); diff --git a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.h b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.h index fbb4032..bf51544 100644 --- a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.h +++ b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/AssetManager.h @@ -2,9 +2,11 @@ #include "gepch.h" #include "GameSmithEngine/Core/Core.h" #include "GameSmithEngine/Core/Log.h" -#include "GameSmithEngine/SerializeableFiles/Serializable.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" #include "ResourceLoaders/ResourceLoader.h" +#include +namespace fs = std::filesystem; namespace GameSmith { enum class ResourceLoaderType { @@ -16,42 +18,56 @@ namespace GameSmith { }; struct ResourceMaps { - std::unordered_map, IDHasher> ActiveIDResources; - std::unordered_map> ActivePathResources; + std::unordered_map, IDHasher> ActiveIDResources; + std::unordered_map> ActivePathResources; std::unordered_map ResourceRegistry; std::unordered_map ReverseResourceRegistry; - std::unordered_map ContentLibraryRegistry; + std::unordered_map > ExtensionToFilePaths; }; + /// + /// This class is intended to manage game assets throughout their lifetime + /// + /// It will provide, cache, and coordinate asset's creation and deletion in memory + /// class GE_API AssetManager { public: inline static AssetManager* GetInstance() { return s_Instance; } - static void Init(ResourceLoaderType loaderType); + static void Init(const ResourceLoaderType loaderType); static void Shutdown(); + /// + /// Loads a requested resource into memory and caches for future requests + /// + /// The Asset type to load + /// The ID tied to the resource to load + /// A shared ownership reference to the loaded resource template - Ref GetResource(ID asset) { + Ref GetResource(const ID asset) { if (m_ResourceMaps->ActiveIDResources.contains(asset)) { - Ref ptr = (*m_ResourceMaps->ActiveIDResources.find(asset)).second; + Ref ptr = (*m_ResourceMaps->ActiveIDResources.find(asset)).second; return CastPtr(ptr); } GE_CORE_ASSERT(m_ResourceMaps->ResourceRegistry.contains(asset), "No UUID entry for asset"); GE_CORE_INFO("Loading file into memory!"); + const std::string filePath = m_ResourceMaps->ResourceRegistry.find(asset)->second; + const std::string fileName = fs::path(filePath).stem().string(); + UINT size; - char* data = m_Loader->LoadResource(m_ResourceMaps->ResourceRegistry.find(asset)->second, &size); + char* data = m_Loader->LoadResource(filePath, &size); unsigned int metaSize; - char* meta = m_Loader->LoadResource(m_ResourceMaps->ResourceRegistry.find(asset)->second + ".meta", &metaSize); + char* meta = m_Loader->LoadResource(filePath + ".meta", &metaSize); GE_CORE_ASSERT(metaSize == sizeof(ResourceFileMetadata), "Meta data of resource has been manipulated and does not match the expected size"); - Ref resource = Ref(new T()); + const Ref resource = Ref(new T(fileName)); resource->Deserialize(data, size); - ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; + const ResourceFileMetadata* metaPtr = (ResourceFileMetadata*)meta; ID metaId(metaPtr->ID); resource->SetID(metaId); @@ -64,20 +80,35 @@ namespace GameSmith { return resource; } - Ref GetResource(ID asset); - + /// + /// Loads a requested resource into memory and caches for future requests + /// + /// The ID tied to the resource to load + /// A shared ownership reference to the loaded resource + Ref GetResource(const ID asset); + + /// + /// Loads a requested resource into memory and caches for future requests + /// + /// The Asset type to load + /// The filepath to find the resource + /// A shared ownership reference to the loaded resource template - Ref GetResource(std::string asset) { + Ref GetResource(const std::string& asset) { if (m_ResourceMaps->ActivePathResources.contains(asset)) { - Ref ptr = (*m_ResourceMaps->ActivePathResources.find(asset)).second; + Ref ptr = (*m_ResourceMaps->ActivePathResources.find(asset)).second; return CastPtr(ptr); } + // Because this is a resource that hasn't been indexed, we need to perform string manipulation during runtime + const std::string fileNameWithExt = asset.substr(asset.find_last_of("/") + 1); + const std::string fileName = fileNameWithExt.substr(0, asset.find_last_of(".")); + GE_CORE_INFO("Loading file into memory!"); UINT size; char* data = m_Loader->LoadResource(asset, &size); - Ref resource = Ref(new T()); + const Ref resource = Ref(new T(fileName)); resource->Deserialize(data, size); m_ResourceMaps->ActivePathResources.insert({ asset, resource }); @@ -87,22 +118,35 @@ namespace GameSmith { return resource; } - Ref GetResource(std::string asset); - - const std::unordered_map& GetContentLibrariesFiles() { return m_ResourceMaps->ContentLibraryRegistry; }; - - // Expected to be used only during testing + /// + /// Loads a requested resource into memory and caches for future requests + /// + /// The filepath to find the resource + /// A shared ownership reference to the loaded resource + Ref GetResource(const std::string& asset); + + + /// + /// Ingests a requested resource into memory and caches for future requests + /// + /// EXPECTED TO BE USED ONLY FOR TESTING + /// + /// The Asset type to load + /// The ID to associate the resource with + /// The data stream to pull the resource from + /// The size of the data stream + /// A shared ownership reference to the loaded resource template - Ref GetResource(ID key, char* inData, UINT size) { + Ref GetResource(const ID key, const char* inData, const UINT size) { if (m_ResourceMaps->ActiveIDResources.contains(key)) { - Ref ptr = (*m_ResourceMaps->ActiveIDResources.find(key)).second; + Ref ptr = (*m_ResourceMaps->ActiveIDResources.find(key)).second; return CastPtr(ptr); } GE_CORE_INFO("Copying data into memory!"); - char* data = m_Loader->LoadResource(inData, size); + const char* data = m_Loader->LoadResource(inData, size); - Ref resource = Ref(new T()); + const Ref resource = Ref(new T()); resource->Deserialize(data, size); m_ResourceMaps->ActiveIDResources.insert({ key, resource }); @@ -111,15 +155,67 @@ namespace GameSmith { return resource; } + + template + void GetAssetPathsOfType(std::vector>* outResults) const { + const std::string targetExt = T::GetStaticFileExtension(); + if (m_ResourceMaps->ExtensionToFilePaths.contains(targetExt)) { + const std::vector& paths = m_ResourceMaps->ExtensionToFilePaths.find(targetExt)->second; + for (const std::string& path : paths) { + fs::path fsPath(path); + + outResults->push_back({ fsPath.filename().string(), path }); + } + } + } - ID WriteResource(Ref resource, std::string path); - ID ImportResource(std::string path); - ID GetAssetID(std::string path); - + /// + /// Writes a new resource to the file system and associates an ID to the resource + /// + /// The resource to serialize + /// The file system destination for the resource + /// The ID associated with the resource + ID WriteResource(const Ref resource, const std::string& path); + /// + /// Create and write a new resource to the file system and associates an ID to the resource + /// + /// The resource to create (including extention) + /// The file system destination for the resoruce + /// The ID associated with the resource + ID CreateResource(const std::string& filename, const std::string& path); + /// + /// Imports a raw file into the engine asset management system + /// + /// The file system source to import the resource from + /// The ID associated with the imported resource + ID ImportResource(const std::string& path); + /// + /// Looks up the ID associated with the requested resource + /// + /// The file system source to lookup + /// The requested resource's ID + ID GetAssetID(const std::string& path) const; + /// + /// Looks up the path associated with the requested resource + /// + /// The asset ID to look up + /// The requested resource's file path + std::string GetAssetPath(const ID& id) const; + + /// + /// Scans all resources available under the monitored asset directory + /// void ScanResources(); + /// + /// Cleans up resources no longer referenced outside of the asset management system + /// void CleanResources(); - void SetAssetDirectory(std::string dir) { m_AssetDirectory = dir; } + /// + /// Sets the asset directory path used by the asset management system + /// + /// The directory path to use for locating assets + void SetAssetDirectory(const std::string& dir) { m_AssetDirectory = dir; } private: AssetManager(); private: diff --git a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.cpp b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.cpp index 3c264c1..be487e4 100644 --- a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.cpp +++ b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.cpp @@ -1,5 +1,6 @@ #include "gepch.h" #include "GameSmithEngine/Core/Log.h" +#include "GameSmithEngine/SerializeableFiles/Serializable.h" #include "ResourceAssetHelper.h" namespace GameSmith { @@ -49,6 +50,45 @@ namespace GameSmith { m_CurPtr += sizeof(int); } + void BinaryStreamWriter::WriteSerializeable(ISerializeable* serializeable) + { + unsigned int requiredSize = serializeable->RequiredSpace(); + GE_CORE_ASSERT(GetRemainingSpace() >= requiredSize, "Not enough space in buffer to write serializeable"); + serializeable->Serialize(m_CurPtr, GetRemainingSpace()); + m_CurPtr += requiredSize; + } + + void BinaryStreamWriter::WriteVector(const std::vector> vector) + { + unsigned int requiredSize = sizeof(unsigned int); + for (auto& item : vector) { + requiredSize += item->RequiredSpace(); + } + GE_CORE_ASSERT(GetRemainingSpace() >= requiredSize, "Not enough space in buffer to write serializeable vector"); + + WriteUInt((unsigned int)vector.size()); + for (auto& item : vector) { + item->Serialize(m_CurPtr, GetRemainingSpace()); + m_CurPtr += item->RequiredSpace(); + } + } + + void BinaryStreamWriter::WriteVector(const std::vector> vector) { + unsigned int requiredSize = sizeof(unsigned int); + for (auto& item : vector) { + requiredSize += item.lock()->RequiredSpace(); + } + + GE_CORE_ASSERT(GetRemainingSpace() >= requiredSize, "Not enough space in buffer to write serializeable vector"); + + WriteUInt((unsigned int)vector.size()); + for (auto& item : vector) { + auto lockedItem = item.lock(); + lockedItem->Serialize(m_CurPtr, GetRemainingSpace()); + m_CurPtr += lockedItem->RequiredSpace(); + } + } + void BinaryStreamWriter::WriteByte(char* bytes, unsigned int byteCount) { memcpy(m_CurPtr, bytes, byteCount); @@ -61,10 +101,23 @@ namespace GameSmith { GE_CORE_ASSERT(pFile.is_open(), std::format("Asset file {0} cannot be opened", destination)); pFile.seekg(0, pFile.beg); - pFile.write(m_Buffer.get(), m_CurPtr - m_Buffer.get()); + if (m_outsideSrc) { + pFile.write(m_OutSideStartPtr, m_CurPtr - m_OutSideStartPtr); + } + else { + pFile.write(m_Buffer.get(), m_CurPtr - m_Buffer.get()); + } + pFile.close(); } + void BinaryStreamWriter::MoveCurPtr(unsigned int bytes) + { + GE_CORE_ASSERT(bytes <= GetRemainingSpace(), "Not enough space to move writer {} bytes", bytes); + + m_CurPtr += bytes; + } + BinaryStreamReader BinaryStreamReader::ReadDirectlyFromFile(std::string fileName) { std::fstream pFile(fileName, std::ios::in | std::ios::binary | std::ios::ate); diff --git a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.h b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.h index 26701f4..e3357be 100644 --- a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.h +++ b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceAssetHelper.h @@ -4,6 +4,9 @@ #include "GameSmithEngine/Core/Log.h" namespace GameSmith { + // FORWARD DECLARATIONS + class AbstractBaseSerializeable; + class GE_API BinaryStreamReader { public: inline BinaryStreamReader(char* buffer, unsigned int byteSize) : m_CurPtr(buffer), m_EndPtr(buffer + byteSize) {} @@ -46,12 +49,16 @@ namespace GameSmith { m_CurPtr += sizeof(T); } + void WriteSerializeable(ISerializeable* serializeable); + void WriteVector(const std::vector> vector); + void WriteVector(const std::vector> vector); + void WriteByte(char* bytes, unsigned int byteCount); void CommitToFile(std::string destination); - inline Ref GetBuffer() { if (m_outsideSrc) { return nullptr; }return m_Buffer; } + inline Ref GetBuffer() { if (m_outsideSrc) { return nullptr; } return m_Buffer; } inline char* GetCurPtr() const { return m_CurPtr; } - inline void MoveCurPtr(unsigned int bytes) { m_CurPtr += bytes; } + void MoveCurPtr(unsigned int bytes); inline unsigned int GetBufferSize() const { return m_BufferSize; } diff --git a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceLoaders/HeapResourceLoader.h b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceLoaders/HeapResourceLoader.h index e78d2ba..bc19c7e 100644 --- a/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceLoaders/HeapResourceLoader.h +++ b/GameSmithEngine/src/GameSmithEngine/ResourceManagement/ResourceLoaders/HeapResourceLoader.h @@ -1,8 +1,9 @@ #pragma once #include "GameSmithEngine/ResourceManagement/ResourceLoaders/ResourceLoader.h" +#include "GameSmithEngine/Core/Core.h" namespace GameSmith { - class HeapResourceLoader : public ResourceLoader { + class GE_API HeapResourceLoader : public ResourceLoader { public: virtual char* LoadResource(std::string file, UINT* outSize) override; // Purpose only for testing diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ExposedMemberSerializeable.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ExposedMemberSerializeable.h new file mode 100644 index 0000000..93528fb --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ExposedMemberSerializeable.h @@ -0,0 +1,51 @@ +#pragma once +#include "Serializable.h" +#include "GameSmithEngine/Utilities/ExposedVariableRegistry.h" +#include "GameSmithEngine/ResourceManagement/ResourceAssetHelper.h" + +namespace GameSmith { + class GE_API ExposedMemberSerializeable : public AbstractBaseSerializeable, public virtual IExposedMembers { + public: + inline void GenerateVariableEntries(std::unordered_map>* outMap) override { m_Registry.GenerateVariableMap(outMap); } + inline void GenerateConnectionEntries(std::unordered_map>* outMap) override { m_Registry.GenerateConnectionsMap(outMap); } + inline void GenerateAssetEntries(std::unordered_map>* outMap) override { m_Registry.GenerateAssetMap(outMap); } + inline const std::unordered_map>& GetExposedGroupings() const override { return m_Registry.GetGroupingRegistry(); } + + inline void BootstrapVariableRegistry(std::unordered_map>& variableEntries) override { + m_Registry.BootstrapFromValueMap(variableEntries); + PostRegistryBootstrap(); + } + + inline void BootstrapConnectionRegistry(std::unordered_map>& refEntries) override { + m_Registry.BootstrapFromConnectionsMap(refEntries); + PostRegistryBootstrap(); + } + + inline void BootstrapAssetRegistry(std::unordered_map>& refEntries) override { + m_Registry.BootstrapFromAssetMap(refEntries); + PostRegistryBootstrap(); + } + + // It's not recommended to rely on the default implementation of the serialization functions, as it adds a layer of indirection with the registry + // that is not nessecary for most derive classes. + // If possible, override this function and serialize the data connected to the registry directly + Ref Serialize() override { + BinaryStreamWriter writer(RequiredSpace()); + Serialize(writer.GetCurPtr(), writer.GetRemainingSpace()); + return writer.GetBuffer(); + }; + + void Serialize(char* byteStream, unsigned int availableBytes) override { m_Registry.Serialize(byteStream, availableBytes); } + + // Returns the amount of bytes required to serialize the interface implementor + unsigned int RequiredSpace() const override { return m_Registry.RequiredSpace(); } + + // Deserializes a byte array into the given class + void Deserialize(char* inData, unsigned int size) override { + m_Registry.Deserialize(inData, size); + PostRegistryBootstrap(); + } + protected: + ExposedVariableRegistry m_Registry; + }; +}; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.cpp index f908af3..9c6c3d5 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.cpp +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.cpp @@ -20,7 +20,7 @@ namespace GameSmith { unsigned int JsonFile::RequiredSpace() const { - return m_JsonString.length() + 1; + return ((unsigned int)m_JsonString.length()) + 1; } void JsonFile::Deserialize(char* inData, unsigned int size) diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.h index b8b11ce..86fe29c 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/GenericFileTypes/JsonFile.h @@ -7,7 +7,7 @@ using json = nlohmann::json; namespace GameSmith { - class JsonFile : public Serializeable { + class JsonFile : public AbstractBaseSerializeable { public: JsonFile() : m_JsonData({}) { m_JsonString = m_JsonData.dump(JSON_INDENTATION_SPACES); @@ -20,7 +20,7 @@ namespace GameSmith { virtual unsigned int RequiredSpace() const override; virtual void Deserialize(char* inData, unsigned int size) override; protected: - void UpdateJson(const json& newJson); + void UpdateJson(const json& newJson); virtual void ExtractJsonData(const json& newJson) = 0; private: json m_JsonData; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h index 85b1c16..068bb2f 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h @@ -1,6 +1,11 @@ #pragma once -#include "GameSmithEngine/SerializeableFiles/Serializable.h" +#include "GameSmithEngine/SerializeableFiles/ExposedMemberSerializeable.h" + +#define SERIAL_FILE(FILE_TYPE, FILE_EXT) static std::string GetStaticFileExtension() {return "."#FILE_EXT;} \ + static std::string GetStaticFileType() {return #FILE_TYPE;} \ + const std::string GetFileExtension() const override {return GetStaticFileExtension();} \ + const std::string GetFileType() const override {return GetStaticFileType();} namespace GameSmith { // A serializeable object that is defined to be an @@ -9,7 +14,22 @@ namespace GameSmith { // // // (either single serializable or bundled serializables) - class GE_API Asset : public Serializeable { - // No special behavior besides identifier + class GE_API IAsset : public virtual ISerializeable, public virtual IExposedMembers { + public: + virtual ~IAsset() = default; + virtual const std::string& GetName() const = 0; + virtual const std::string GetFileExtension() const = 0; + virtual const std::string GetFileType() const = 0; + }; + + class GE_API Asset : public ExposedMemberSerializeable, public IAsset { + public: + Asset(std::string fileName) : m_FileName(fileName) {} + + const std::string& GetName() const override { return m_FileName; } + const std::string GetFileExtension() const override { return "*"; } + const std::string GetFileType() const override { return "Any"; } + private: + const std::string m_FileName; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.cpp index 2b4aa1c..d66d154 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.cpp +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.cpp @@ -13,21 +13,23 @@ namespace GameSmith { return s_Instance.get(); } - void AssetRegistry::RegisterAsset(std::string ext, std::function creationFunction) + + void AssetRegistry::RegisterAsset(std::string ext, std::string assetLabel, std::function creationFunction) { if (!m_ExtToAsset.contains(ext)) { m_ExtToAsset.insert({ ext, creationFunction }); + m_RegisteredAssets.push_back({ ext, assetLabel }); } } - Ref AssetFactory::GenerateAsset(std::string ext) + Ref AssetFactory::GenerateAsset(std::string ext, std::string fileName) { auto registry = AssetRegistry::GetInstance(); GE_CORE_ASSERT(registry->m_ExtToAsset.contains(ext), std::format("No definition for requested extention: {0}", ext)); auto entry = registry->m_ExtToAsset.find(ext); - return Ref(entry->second()); + return Ref(entry->second(fileName)); } }; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h index 7d3b7b3..ed1c8ad 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h @@ -1,35 +1,39 @@ #pragma once #include -#include "GameSmithEngine/SerializeableFiles/Serializable.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" #define GE_REGISTERASSET(ClassType) \ static struct ClassType##RegisterAction { \ ClassType##RegisterAction() { \ GameSmith::AssetRegistry::GetInstance()->RegisterAsset( \ - ClassType::GetStaticFileExtension(), []() {return new ClassType(); } \ + ClassType::GetStaticFileExtension(), \ + ClassType::GetStaticFileType(), \ + [](std::string name) {return new ClassType(name); } \ ); \ } \ }ClassType##Instance; namespace GameSmith { - class AssetRegistry { + class GE_API AssetRegistry { public: static AssetRegistry* GetInstance(); - void RegisterAsset(std::string ext, std::function creationFunction); + void RegisterAsset(std::string ext, std::string assetLabel, std::function creationFunction); + const std::vector>& ListRegisteredAssets() { return m_RegisteredAssets; } private: static Scope s_Instance; - std::unordered_map> m_ExtToAsset; + std::unordered_map> m_ExtToAsset; + std::vector> m_RegisteredAssets; friend class AssetFactory; }; class AssetFactory { private: - static Ref GenerateAsset(std::string ext); + static Ref GenerateAsset(std::string ext, std::string fileName); friend class AssetManager; }; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.cpp new file mode 100644 index 0000000..40840e6 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.cpp @@ -0,0 +1,35 @@ +#include "gepch.h" +#include "BlobAsset.h" + +namespace GameSmith { + Ref BlobAsset::Serialize() + { + if (m_Size != 0 && m_Bytes != nullptr) { + Ref byteStream = Ref(new char[m_Size]); + memcpy(byteStream.get(), m_Bytes.get(), m_Size); + return byteStream; + } + + return Ref(); + } + + void BlobAsset::Serialize(char* byteStream, unsigned int availableBytes) + { + GE_CORE_ASSERT(availableBytes >= m_Size, "Not enough space to serialize BlobAsset"); + if (m_Size != 0 && m_Bytes != nullptr) { + memcpy(byteStream, m_Bytes.get(), m_Size); + } + + } + unsigned int BlobAsset::RequiredSpace() const + { + return m_Size; + } + + void BlobAsset::Deserialize(char* inData, unsigned int size) + { + m_Bytes = Ref(new char[size]); + memcpy(m_Bytes.get(), inData, size); + m_Size = size; + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.h new file mode 100644 index 0000000..645b7cf --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/BlobAsset.h @@ -0,0 +1,22 @@ +#pragma once +#include "Asset.h" + +namespace GameSmith { + class GE_API BlobAsset : public Asset { + public: + BlobAsset(std::string fileName) : Asset(fileName) {} + virtual ~BlobAsset() = default; + virtual Ref Serialize() override; + virtual void Serialize(char* byteStream, unsigned int availableBytes) override; + virtual unsigned int RequiredSpace() const override; + virtual void Deserialize(char* inData, unsigned int size) override; + + const char* GetBytes() const { return m_Bytes.get(); } + const unsigned int GetSize() const { return m_Size; } + + SERIAL_FILE(Blob, blob) + private: + Ref m_Bytes; + unsigned int m_Size = 0; + }; +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.cpp index 67c28cb..2271dd1 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.cpp +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.cpp @@ -5,9 +5,10 @@ namespace GameSmith { GE_REGISTERASSET(GameChunkAsset) - GameChunkAsset::GameChunkAsset(Ref snapShot) : m_ChunkSerialization(snapShot->Serialize()), m_ByteSize(snapShot->RequiredSpace()) - { - } + GameChunkAsset::GameChunkAsset(Ref snapShot) : + Asset(snapShot->GetChunkName()), + m_ChunkSerialization(snapShot->Serialize()), + m_ByteSize(snapShot->RequiredSpace()) {} Ref GameChunkAsset::Serialize() { diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.h index 77f0659..45572be 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/GameChunkAsset.h @@ -7,7 +7,7 @@ namespace GameSmith { class GE_API GameChunkAsset : public Asset { public: - GameChunkAsset() = default; + GameChunkAsset(std::string name) : Asset(name) {}; GameChunkAsset(Ref snapShot); virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.cpp index eed9aa0..c10e148 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.cpp +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.cpp @@ -6,15 +6,14 @@ #include "GameSmithEngine/ResourceManagement/ResourceAssetHelper.h" #include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h" -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h" namespace GameSmith { GE_REGISTERASSET(MaterialAsset); - Ref MaterialAsset::Serialize() + void MaterialAsset::Serialize(char* byteStream, unsigned int availableBytes) { - BinaryStreamWriter writer(RequiredSpace()); + BinaryStreamWriter writer(byteStream, availableBytes); writer.WriteClass(&m_Metadata); // Write Config @@ -22,25 +21,19 @@ namespace GameSmith { // Write Shader Paths // Write Parameters // Write Texture Paths - //writer.WriteClass(&m_) - // TODO: Remove this MaterialConfig config; writer.WriteClass(&config); - for (unsigned int i = 0; i < STAGE_NUM; i++) { - if (m_Metadata.Shaders[i].UsedShader) { - idData shaderID = m_ShaderIds[i].getData(); - writer.WriteClass(&shaderID); - } + idData shaderID = { 0,0,0,0 }; + if (m_Shader != nullptr) { + shaderID = m_Shader->GetID().getData(); } + writer.WriteClass(&shaderID); // Parameters - auto& map = m_GlobalVer->DumpCurrentParameterMap(); - auto& order = m_GlobalVer->DumpParameterOrder(); - - for (const std::string& parm : order) { - const auto& entry = map.find(parm)->second; + for (const auto& parm : m_ParameterKeys) { + const auto& entry = m_Parameters.find(parm)->second; writer.WriteString(parm); auto type = entry->GetType(); writer.WriteClass(&type); @@ -48,45 +41,31 @@ namespace GameSmith { } - for (auto& texture : m_MatInfo->TextureIds) { - writer.WriteString(texture.first); - idData texID = texture.second.getData(); + for (const auto& texture : m_TextureKeys) { + const auto& entry = m_Textures.find(texture)->second; + writer.WriteString(texture); + idData texID = entry->asset->GetID().getData(); writer.WriteClass(&texID); } - - return writer.GetBuffer(); - } - - void MaterialAsset::Serialize(char* byteStream, unsigned int availableBytes) - { - // TODO: Implement } unsigned int MaterialAsset::RequiredSpace() const { - // TODO: Implement unsigned int size = 0; size += sizeof(MaterialAssetMetadata); size += sizeof(MaterialConfig); - for (unsigned int i = 0; i < STAGE_NUM; i++) { - if (m_Metadata.Shaders[i].UsedShader) { - size += sizeof(idData); - } - } + size += sizeof(idData); - auto& map = m_GlobalVer->DumpCurrentParameterMap(); - auto& order = m_GlobalVer->DumpParameterOrder(); - - for (const std::string& parm : order) { - const auto& entry = map.find(parm)->second; + for (const auto& parm : m_ParameterKeys) { + const auto& entry = m_Parameters.find(parm)->second; size += (unsigned int)(parm.length()+1); size += sizeof(ContainerDataType); size += entry->GetSize(); } - for (auto& texture : m_MatInfo->TextureIds) { - size += (unsigned int)(texture.first.length()+1); + for (const auto& texture : m_TextureKeys) { + size += (unsigned int)(texture.length()+1); size += sizeof(idData); } @@ -104,21 +83,14 @@ namespace GameSmith { auto instance = AssetManager::GetInstance(); - ShaderSet shaders; - for (unsigned int i = 0; i < STAGE_NUM; i++) { - Stages stage = (Stages)i; - if (matMetadata->Shaders[i].UsedShader) { - auto shaderId = reader.ReadClass(); - ID newId(*shaderId); - shaders.shaders[i] = instance->GetResource(newId); - m_ShaderIds[i] = newId; - } + auto shaderId = reader.ReadClass(); + ID newId(*shaderId); + if (newId == ID({ 0,0,0,0 })) { + m_Shader = nullptr; + } + else { + m_Shader = instance->GetResource(newId); } - - std::vector parameterNames; - std::vector textureNames; - std::unordered_map> parameterMap; - std::unordered_map> textureMap; for (unsigned int i = 0; i < matMetadata->ParamterCount; i++) { GE_CORE_INFO("Loading parameter {0}", i); @@ -127,10 +99,11 @@ namespace GameSmith { unsigned int dataSize = GetParameterSize(*dataType); char* data = reader.GetBytes(dataSize); - Ref parm = ConvertToParameter(paramName, *dataType, data); + Ref param = ConvertToParameter(paramName, *dataType, data); - parameterNames.push_back(paramName); - parameterMap.insert({ paramName, parm }); + m_ParameterKeys.push_back(paramName); + m_Parameters[paramName] = param; + m_Registry.AddExposedVariable(paramName, param); } for (unsigned int i = 0; i < matMetadata->TetureCount; i++) { @@ -139,65 +112,104 @@ namespace GameSmith { std::string texName = reader.GetString(); auto texId = reader.ReadClass(); ID newID(*texId); - m_MatInfo->TextureIds.push_back({ texName, newID }); Ref tex = instance->GetResource(newID); - textureNames.push_back(texName); - textureMap.insert({ texName, tex->GetTexture() }); + m_TextureKeys.push_back(texName); + Ref container = Ref(new TextureRefContainer{ tex }); + m_Textures[texName] = container; } + } - m_GlobalVer = Ref(new Material(shaders, *config, parameterNames, textureNames, parameterMap, textureMap)); + void MaterialAsset::PostRegistryBootstrap() + { + if (m_Shader != nullptr) { + m_ParameterKeys.clear(); + m_Parameters.clear(); + // Assuming there is a config attached + // TODO: Add check if config exists + auto& parameterMap = m_Shader->GetShaderConfig()->GetPrimitiveProperties(); + for (const auto& entry : parameterMap) { + const auto& name = entry->name; + const auto& type = entry->type; + auto container = CreateContainer(name, type); + m_Parameters[name] = container; + m_ParameterKeys.push_back(name); + m_Metadata.ParamterCount = (unsigned int)m_ParameterKeys.size(); + m_Registry.RemoveExposedVariable(name); + m_Registry.AddExposedVariable(name, container); + } + } } Ref MaterialAsset::CreateInstance() { - return Ref(new Material(*m_GlobalVer)); + MaterialConfig config; + + std::unordered_map> textureMap; + for (auto& entry : m_Textures) { + textureMap[entry.first] = entry.second->asset->GetTexture(); + } + + ShaderSet shaderSet; + for (int i = 0; i < STAGE_NUM; i++) { + Stages stage = (Stages)i; + if (m_Shader->HasShader(stage)) { + shaderSet.shaders[stage] = m_Shader->GetShader(stage); + } + else { + shaderSet.shaders[stage] = nullptr; + } + } + + return Ref(new Material(shaderSet, config, m_ParameterKeys, m_TextureKeys, m_Parameters, textureMap)); } - MaterialAsset::MaterialAsset() : m_MatInfo(new MaterialInfo()) + MaterialAsset::MaterialAsset(std::string name) : Asset(name) { + m_Registry.AddExposedAsset( + "Shader", + (Ref*) & (m_Shader), + CLASS_TO_STRING(ShaderAsset) + ); } - MaterialAsset::MaterialAsset( - std::vector>& shaderIds, - std::vector>& textureIds, - std::vector>& variables - ) : m_MatInfo(new MaterialInfo()) + /*MaterialAsset::MaterialAsset( + const std::string name, + const std::unordered_map& shaderIds, + const std::vector& textureOrder, + const std::unordered_map& textureIds, + const std::vector& parameterOrder, + const std::unordered_map& variables + ) : Asset(name), m_TextureKeys(textureOrder), m_ParameterKeys(parameterOrder) { - GE_CORE_ASSERT(shaderIds.size() <= STAGE_NUM, "More shader entries than there are stages"); - auto instance = AssetManager::GetInstance(); - ShaderSet shaders; for (auto& entry : shaderIds) { - GE_CORE_ASSERT(shaders.shaders[entry.second] == nullptr, "ShaderPath parameter passed has a double entry for a stage"); - - shaders.shaders[entry.second] = instance->GetResource(entry.first); - m_ShaderIds[entry.second] = entry.first; - - m_Metadata.Shaders[entry.second].UsedShader = true; + m_Shaders.shaders[entry.first] = instance->GetResource(entry.second); + m_Metadata.Shaders[entry.first].UsedShader = true; + m_Registry.AddExposedAsset( + std::format("Shader:Stage:{}", entry.first), + (Ref*) &(m_Shaders.shaders[entry.first]), + CLASS_TO_STRING(ShaderAsset) + ); } m_Metadata.TetureCount = (unsigned int)textureIds.size(); std::vector textureNames; std::unordered_map> textureMap; for (auto& textureEntry : textureIds) { - m_MatInfo->TextureIds.push_back({ textureEntry.first, textureEntry.second }); Ref tex = instance->GetResource(textureEntry.second); - textureNames.push_back(textureEntry.first); - textureMap.insert({ textureEntry.first, tex->GetTexture() }); + Ref container = Ref(new TextureRefContainer{ tex }); + m_Textures[textureEntry.first] = container; + m_Registry.AddExposedAsset(textureEntry.first, (Ref*)&container->asset, CLASS_TO_STRING(TextureAsset)); } m_Metadata.ParamterCount = (unsigned int)variables.size(); - std::vector parameterNames; - std::unordered_map> parameterMap; for (auto& entry : variables) { auto variableContainor = CreateContainer(entry.first, entry.second); - parameterNames.push_back(entry.first); - parameterMap.insert({ entry.first, variableContainor }); - } + m_Parameters[entry.first] = variableContainor; + m_Registry.AddExposedVariable(entry.first, variableContainor); - MaterialConfig emptyConfig; - m_GlobalVer = Ref(new Material(shaders, emptyConfig, parameterNames, textureNames, parameterMap, textureMap)); - } + } + }*/ }; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.h index 6d26d2c..39d6936 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MaterialAsset.h @@ -2,45 +2,54 @@ #include "Asset.h" #include "GameSmithEngine/Core/Core.h" #include "GameSmithEngine/Rendering/RenderAgnostics/MaterialSystem/Material.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h" namespace GameSmith { - struct MaterialInfo { - std::vector> TextureIds; - }; - class GE_API MaterialAsset : public Asset { public: - MaterialAsset(); - MaterialAsset( - std::vector>& shaderIds, - std::vector>& textureIds, - std::vector>& variables - ); - - virtual Ref Serialize() override; - virtual void Serialize(char* byteStream, unsigned int availableBytes) override; - virtual unsigned int RequiredSpace() const override; - virtual void Deserialize(char* inData, unsigned int size) override; + MaterialAsset(std::string name); + /*MaterialAsset( + const std::string name, + const std::unordered_map& shaderIds, + const std::vector& textureOrder, + const std::unordered_map& textureIds, + const std::vector& parameterOrder, + const std::unordered_map& variables + );*/ + + void Serialize(char* byteStream, unsigned int availableBytes) override; + unsigned int RequiredSpace() const override; + void Deserialize(char* inData, unsigned int size) override; + + void PostRegistryBootstrap() override; SERIAL_FILE(Material, mat) Ref CreateInstance(); private: struct MaterialAssetMetadata { - unsigned int ParamterCount; - unsigned int TetureCount; - struct ShaderMetadata { - bool UsedShader = false; - }Shaders[STAGE_NUM]; + unsigned int ParamterCount = 0; + unsigned int TetureCount = 0; }; - Ref m_GlobalVer; + // We need a layer of indirection because we need to expose textures to the exposed member system + // This expects the location of the pointer to manipulate to be consistent, + // so we can't just store the Ref directly in the map + struct TextureRefContainer { + Ref asset = nullptr; + }; MaterialAssetMetadata m_Metadata; - ID m_ShaderIds[STAGE_NUM]; + Ref m_Shader; + + // Order is important for materials + std::vector m_ParameterKeys; + std::vector m_TextureKeys; - Scope m_MatInfo; + std::unordered_map> m_Textures; + std::unordered_map> m_Parameters; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.cpp index 06b64e7..c8fbbc2 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.cpp +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.cpp @@ -1,4 +1,5 @@ #include "gepch.h" +#include "AssetFactory.h" #include "GameSmithEngine/Core/Log.h" #include "GameSmithEngine/Rendering/RenderAgnostics/BasicStructs.h" #include "GameSmithEngine/Rendering/RenderingManager.h" @@ -6,6 +7,8 @@ #include "MeshAsset.h" namespace GameSmith { + GE_REGISTERASSET(MeshAsset) + Ref MeshAsset::Serialize() { // TODO: Implement diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.h index 69674b1..2e9af90 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/MeshAsset.h @@ -15,6 +15,7 @@ namespace GameSmith { class GE_API MeshAsset : public Asset { public: + MeshAsset(std::string name) : Asset(name) {}; virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; virtual unsigned int RequiredSpace() const override; @@ -24,7 +25,7 @@ namespace GameSmith { inline SubMesh GetSubMesh(unsigned int index) { return m_SubMeshes[index]; } inline unsigned int GetSubMeshSize() { return (unsigned int)m_SubMeshes.size(); } - SERIAL_FILE(Mesh, mesh) + SERIAL_FILE(Mesh, obj) // Temporarily take obj only asset private: Ref m_Vert; std::vector m_SubMeshes; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.cpp deleted file mode 100644 index 3dbb67d..0000000 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "gepch.h" -#include "GameSmithEngine/Core/Log.h" -#include "GameSmithEngine/Rendering/RenderingManager.h" -#include "ShaderAsset.h" - -namespace GameSmith { - - Ref ShaderAsset::Serialize() - { - auto byteArray = Ref(new char[RequiredSpace()]); - - memcpy(byteArray.get(), m_Shader->GetRawByteCode(), RequiredSpace()); - - return byteArray; - } - void ShaderAsset::Serialize(char* byteStream, unsigned int availableBytes) - { - // TODO: Implement - auto requiredSize = RequiredSpace(); - - GE_CORE_ASSERT( - requiredSize <= availableBytes, - "The given byte array (given: {0}) is not big enough to serialize this shader (required: {1})", - availableBytes, requiredSize); - - memcpy(byteStream, m_Shader->GetRawByteCode(), RequiredSpace()); - } - - unsigned int ShaderAsset::RequiredSpace() const - { - return m_Shader->GetByteCodeSize(); - } - - void ShaderAsset::Deserialize(char* inData, unsigned int size) - { - auto renderAPI = RenderingManager::GetInstance()->GetRenderAPI(); - m_Shader = renderAPI->LoadShader(inData, size); - } -}; - diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h deleted file mode 100644 index 339aede..0000000 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderAsset.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Asset.h" -#include "GameSmithEngine/Core/Core.h" -#include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h" - -namespace GameSmith { - class GE_API ShaderAsset : public Asset - { - public: - ShaderAsset() = default; - inline ShaderAsset(Ref shader) : m_Shader(shader) {}; - - virtual Ref Serialize() override; - virtual void Serialize(char* byteStream, unsigned int availableBytes) override; - virtual unsigned int RequiredSpace() const override; - virtual void Deserialize(char* inData, unsigned int size) override; - - inline Ref GetShader() const { return m_Shader != nullptr ? m_Shader : nullptr; } - private: - Ref m_Shader; - }; -}; - - diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.cpp new file mode 100644 index 0000000..014c714 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.cpp @@ -0,0 +1,7 @@ +#include "gepch.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" +#include "HLSLAsset.h" + +namespace GameSmith { + GE_REGISTERASSET(HLSLAsset); +} \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h new file mode 100644 index 0000000..8e1b30f --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h @@ -0,0 +1,10 @@ +#pragma once +#include "../BlobAsset.h" + +namespace GameSmith { + class GE_API HLSLAsset : public BlobAsset { + public: + HLSLAsset(std::string fileName) : BlobAsset(fileName) {} + SERIAL_FILE(HLSL, hlsl) + }; +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.cpp new file mode 100644 index 0000000..b278852 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.cpp @@ -0,0 +1,88 @@ +#include "gepch.h" +#include "GameSmithEngine/Core/Log.h" +#include "GameSmithEngine/Rendering/RenderingManager.h" +#include "GameSmithEngine/ResourceManagement/AssetManager.h" +#include "GameSmithEngine/ResourceManagement/ResourceAssetHelper.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" +#include "ShaderAsset.h" + +namespace GameSmith { + GE_REGISTERASSET(ShaderAsset); + + + void ShaderAsset::Serialize(char* byteStream, unsigned int availableBytes) + { + auto requiredSize = RequiredSpace(); + + GE_CORE_ASSERT( + requiredSize <= availableBytes, + "The given byte array (given: {0}) is not big enough to serialize this shader (required: {1})", + availableBytes, requiredSize); + + BinaryStreamWriter writer(byteStream, availableBytes); + for (unsigned int i = 0; i < STAGE_NUM; i++) { + if (m_HLSLSource.sources[i] != nullptr) { + idData sourceID = m_HLSLSource.sources[i]->GetID().getData(); + writer.WriteClass(&sourceID); + } + else { + idData emptyID = { 0, 0, 0, 0 }; + writer.WriteClass(&emptyID); + } + } + + if (m_ShaderConfig != nullptr) { + idData configID = m_ShaderConfig->GetID().getData(); + writer.WriteClass(&configID); + } + else { + idData emptyID = { 0, 0, 0, 0 }; + writer.WriteClass(&emptyID); + } + } + + unsigned int ShaderAsset::RequiredSpace() const + { + unsigned int requiredSize = sizeof(idData) * (STAGE_NUM+1); + + return requiredSize; + } + + void ShaderAsset::Deserialize(char* inData, unsigned int size) + { + BinaryStreamReader reader(inData, size); + auto assetManager = AssetManager::GetInstance(); + for (unsigned int i = 0; i < STAGE_NUM; i++) { + idData sourceID = *reader.ReadClass(); + ID sourceFullID(sourceID); + if (sourceFullID != ID()) { + m_HLSLSource.sources[i] = assetManager->GetResource(sourceFullID); + } + } + + idData configID = *reader.ReadClass(); + ID configFullID(configID); + if (configFullID != ID()) { + m_ShaderConfig = assetManager->GetResource(configFullID); + } + } + + bool ShaderAsset::HasShader(const Stages stage) const + { + return m_HLSLSource.sources[stage] != nullptr; + } + + Ref ShaderAsset::GetShader(const Stages stage) + { + if (m_Shaders[stage] == nullptr) { + GE_CORE_ASSERT(m_HLSLSource.sources[stage] != nullptr, "Shader stage {0} does not have a source to compile from", ConvertShaderStageToString(stage)); + + auto renderManager = RenderingManager::GetInstance(); + const ID assetID = GetID(); + m_Shaders[stage] = renderManager->CompileOrRetrieveShader(stage, m_HLSLSource.sources[stage]->GetBytes(), m_HLSLSource.sources[stage]->GetSize(), assetID); + } + + return m_Shaders[stage]; + } +}; + diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h new file mode 100644 index 0000000..ebcf002 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderAsset.h @@ -0,0 +1,69 @@ +#pragma once +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/HLSLAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.h" +#include "GameSmithEngine/Core/Core.h" +#include "GameSmithEngine/Rendering/RenderAgnostics/RenderComponents/Shader.h" + +namespace GameSmith { + struct HLSLSourceSet { + Ref sources[STAGE_NUM]; + }; + + class GE_API ShaderAsset : public Asset + { + public: + ShaderAsset(std::string name) : Asset(name) { + for (int i = 0; i < STAGE_NUM; i++) { + Stages stage = (Stages)i; + m_Registry.AddExposedAsset( + ConvertShaderStageToString(stage), + (Ref*) & (m_HLSLSource.sources[i]), + CLASS_TO_STRING(HLSLAsset) + ); + m_Shaders[i] = nullptr; + } + + m_Registry.AddExposedAsset( + "ShaderConfig", + (Ref*)&m_ShaderConfig, + CLASS_TO_STRING(ShaderConfigAsset) + ); + }; + + ShaderAsset(std::string name, HLSLSourceSet source) : Asset(name), m_HLSLSource(source) { + for (int i = 0; i < STAGE_NUM; i++) { + Stages stage = (Stages)i; + m_Registry.AddExposedAsset( + ConvertShaderStageToString(stage), + (Ref*) & (m_HLSLSource.sources[i]), + CLASS_TO_STRING(HLSLAsset) + ); + m_Shaders[i] = nullptr; + } + + m_Registry.AddExposedAsset( + "ShaderConfig", + (Ref*) & m_ShaderConfig, + CLASS_TO_STRING(ShaderConfigAsset) + ); + }; + + virtual void Serialize(char* byteStream, unsigned int availableBytes) override; + virtual unsigned int RequiredSpace() const override; + virtual void Deserialize(char* inData, unsigned int size) override; + + bool HasShader(const Stages stage) const; + Ref GetShader(const Stages stage); + Ref GetShaderConfig() const { return m_ShaderConfig; } + + SERIAL_FILE(GMShader, sr) + + private: + Ref m_Shaders[STAGE_NUM]; + HLSLSourceSet m_HLSLSource; + Ref m_ShaderConfig; + }; +}; + + diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.cpp b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.cpp new file mode 100644 index 0000000..646f1a6 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.cpp @@ -0,0 +1,91 @@ +#include "gepch.h" +#include "ShaderConfigAsset.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/AssetFactory.h" + +#define PROPERTIES_KEY "Property" + +namespace GameSmith { + GE_REGISTERASSET(ShaderConfigAsset); + + ShaderConfigAsset::ShaderConfigAsset(std::string name) : Asset(name) + { + m_Registry.AddExposedVariable( + "PropertyCount", + ContainerDataType::Int, + &m_PropertyCount + ); + } + + void ShaderConfigAsset::Serialize(char* byteStream, unsigned int availableBytes) + { + GE_CORE_ASSERT(availableBytes >= RequiredSpace(), "There's not enough space to serialize ShaderConfigAsset"); + BinaryStreamWriter writer(byteStream, availableBytes); + writer.WriteUInt((unsigned int)m_PropertyCount); + for (auto& property : m_PrimitiveProperties) { + writer.WriteClass(property.get()); + } + } + + void ShaderConfigAsset::Deserialize(char* inData, unsigned int size) + { + BinaryStreamReader reader(inData, size); + m_PropertyCount = reader.GetUInt(); + m_PrimitiveProperties.resize(m_PropertyCount); + for (int i = 0; i < m_PrimitiveProperties.size(); i++) { + auto* details = reader.ReadClass(); + auto propertyDetails = Ref(new PrimitivePropertyDetails(*details)); + m_PrimitiveProperties[i] = propertyDetails; + + RegisterProperty(i, propertyDetails); + } + } + + void ShaderConfigAsset::PostRegistryBootstrap() + { + if (m_PropertyCount != m_PrimitiveProperties.size()) + { + for (int i = 0; i < m_PrimitiveProperties.size(); i++) { + const std::string nameKey = std::format("{0}_{1}: {2}", PROPERTIES_KEY, i, "Name"); + m_Registry.RemoveExposedVariable(nameKey); + + const std::string dataTypeKey = std::format("{0}_{1}: {2}", PROPERTIES_KEY, i, "DataType"); + m_Registry.RemoveExposedVariable(dataTypeKey); + } + + + m_PrimitiveProperties.resize(m_PropertyCount); + for (int i = 0; i < m_PrimitiveProperties.size(); i++) { + auto propertyDetails = m_PrimitiveProperties[i]; + if (propertyDetails == nullptr) { + propertyDetails = Ref(new PrimitivePropertyDetails{}); + m_PrimitiveProperties[i] = propertyDetails; + } + + RegisterProperty(i, propertyDetails); + } + } + } + + void ShaderConfigAsset::RegisterProperty(unsigned int index, Ref propertyDetails) + { + const std::string parameterName = std::format("{0}_{1}", PROPERTIES_KEY, index); + const std::string nameKey = std::format("{0}: {1}", parameterName, "Name"); + char* namePtr = propertyDetails->name; + m_Registry.AddExposedVariable( + nameKey, + ContainerDataType::CBuffer, + namePtr, + CONTAINER_BUFFER_DEFAULT_SIZE, + parameterName + ); + + const std::string dataTypeKey = std::format("{0}: {1}", parameterName, "DataType"); + m_Registry.AddExposedVariable( + dataTypeKey, + ContainerDataType::Int, + &(propertyDetails->type), + 0, + parameterName + ); + } +} \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.h new file mode 100644 index 0000000..7eb1a6d --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/ShaderTypes/ShaderConfigAsset.h @@ -0,0 +1,29 @@ +#pragma once +#include "../Asset.h" +#include "GameSmithEngine/Utilities/ParameterContainer.h" + +namespace GameSmith { + struct PrimitivePropertyDetails { + char name[CONTAINER_BUFFER_DEFAULT_SIZE] = {'\0'}; + ContainerDataType type; + }; + + class ShaderConfigAsset : public Asset { + public: + ShaderConfigAsset(std::string name); + + const std::vector>& GetPrimitiveProperties() const { return m_PrimitiveProperties; } + void Serialize(char* byteStream, unsigned int availableBytes) override; + unsigned int RequiredSpace() const override { return (unsigned int)(sizeof(unsigned int) + sizeof(PrimitivePropertyDetails) * m_PrimitiveProperties.size()); } + void Deserialize(char* inData, unsigned int size) override; + + void PostRegistryBootstrap() override; + + SERIAL_FILE(ShaderConfig, GMsrcfg) + private: + void RegisterProperty(unsigned int index, Ref propertyDetails); + private: + int m_PropertyCount = 0; + std::vector> m_PrimitiveProperties; + }; +}; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TestResource.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TestResource.h index 6148d78..f8f4269 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TestResource.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TestResource.h @@ -5,6 +5,7 @@ namespace GameSmith { class TestResource : public Asset { public: + TestResource(std::string name) : Asset(name) {}; virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; virtual unsigned int RequiredSpace() const override; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h index ab899a2..1a6672c 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/ResourceAssets/TextureAsset.h @@ -9,6 +9,8 @@ namespace GameSmith { class GE_API TextureAsset : public Asset { public: + TextureAsset(std::string name) : Asset(name) {}; + virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; virtual unsigned int RequiredSpace() const override; diff --git a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/Serializable.h b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/Serializable.h index 431fe93..3f38f8f 100644 --- a/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/Serializable.h +++ b/GameSmithEngine/src/GameSmithEngine/SerializeableFiles/Serializable.h @@ -2,15 +2,12 @@ #include "GameSmithEngine/Core/Core.h" #include "GameSmithEngine/Utilities/GUIDGenerator.h" -#define SERIAL_FILE(FILE_TYPE, FILE_EXT) static std::string GetStaticFileExtension() {return #FILE_EXT;} \ - static std::string GetStaticFileType() {return #FILE_TYPE;} \ - virtual std::string GetFileExtension() const override {return GetStaticFileExtension();} \ - virtual std::string GetFileType() const override {return GetStaticFileType();} - namespace GameSmith { // Intertface for a class that can be serialize/deserialized - class GE_API Serializeable : public IDObject { + class GE_API ISerializeable : public virtual IDObjectInterface { public: + virtual ~ISerializeable() = default; + // Serialize the interface implementor // Returns a pointer to a byte array containing the serialized class virtual Ref Serialize() = 0; @@ -24,8 +21,9 @@ namespace GameSmith { // Deserializes a byte array into the given class virtual void Deserialize(char* inData, unsigned int size) = 0; + }; - virtual std::string GetFileExtension() const { return "*"; } - virtual std::string GetFileType() const { return "Any"; } + // An abstract base class for serializeable files + class GE_API AbstractBaseSerializeable : public IDObject, public virtual ISerializeable { }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.cpp b/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.cpp index a64968d..3a6ca01 100644 --- a/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.cpp +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.cpp @@ -1,12 +1,53 @@ #include "gepch.h" #include "ExposedVariableRegistry.h" #include "GameSmithEngine/ResourceManagement/ResourceAssetHelper.h" +#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" namespace GameSmith { + void ExposedVariableRegistry::AddExposedVariable(const std::string variableName, Ref container, const std::string& groupName) + { + m_ValueRegistry.insert({ variableName, {nullptr, 0, container->GetType(), groupName, container->GetFlags(), container, true} }); + AddToGroup(groupName, variableName); + } + + void ExposedVariableRegistry::RemoveExposedVariable(const std::string variableName) + { + if (m_ValueRegistry.contains(variableName)) { + std::string groupName = m_ValueRegistry[variableName].groupName; + m_ValueRegistry.erase(variableName); + RemoveFromGroup(groupName, variableName); + } + } + + void ExposedVariableRegistry::RemoveExposedConnection(const std::string refName) + { + if (m_ConnectionsRegistry.contains(refName)) { + std::string groupName = m_ConnectionsRegistry[refName].groupName; + m_ConnectionsRegistry.erase(refName); + RemoveFromGroup(groupName, refName); + } + } + + void ExposedVariableRegistry::RemoveExposedAsset(const std::string refName) + { + if (m_AssetRegistry.contains(refName)) { + std::string groupName = m_AssetRegistry[refName].groupName; + m_AssetRegistry.erase(refName); + RemoveFromGroup(groupName, refName); + } + } + void ExposedVariableRegistry::GenerateVariableMap(std::unordered_map>* outMap) { for (auto& entry : m_ValueRegistry) { - auto container = ConvertToParameter(entry.first, entry.second.variableDataType, (char*)entry.second.originalVariableRef); + Ref container; + + if (entry.second.ownsContainer) { + container = entry.second.containerRef->MakeCopy(); + } + else { + container = ConvertToParameter(entry.first, entry.second.variableDataType, (char*)entry.second.originalVariableRef, entry.second.variableSize); + } outMap->insert({ container->GetName(), container }); } } @@ -38,7 +79,13 @@ namespace GameSmith { for (auto& entry : m_ValueRegistry) { if (inMap.contains(entry.first)) { const auto& variable = inMap.find(entry.first); - memcpy(entry.second.originalVariableRef, variable->second->GetCharData(), variable->second->GetSize()); + if (!entry.second.ownsContainer) { + memcpy(entry.second.originalVariableRef, variable->second->GetCharData(), variable->second->GetSize()); + } + else { + memcpy(entry.second.containerRef->GetCharData(), variable->second->GetCharData(), variable->second->GetSize()); + } + } } } @@ -70,35 +117,8 @@ namespace GameSmith { Ref ExposedVariableRegistry::Serialize() { BinaryStreamWriter writer(RequiredSpace()); - - RegistrySerializeMetadata meta; - meta.numVariables = (unsigned int)m_ValueRegistry.size(); - meta.numConnections = (unsigned int)m_ConnectionsRegistry.size(); - - writer.WriteClass(&meta); - - for (auto& entry : m_ValueRegistry) { - writer.WriteString(entry.first); - writer.WriteClass(&(entry.second.variableDataType)); - writer.WriteByte((char*)entry.second.originalVariableRef, GetParameterSize(entry.second.variableDataType)); - } - for (auto& entry : m_ConnectionsRegistry) { - writer.WriteString(entry.first); - idData rawId = entry.second.objectID.getData(); - writer.WriteClass(&rawId); - writer.WriteUInt(entry.second.flag); - } - - for (auto& entry : m_AssetRegistry) { - writer.WriteString(entry.first); - idData rawId = entry.second.objectID.getData(); - writer.WriteClass(&rawId); - writer.WriteUInt(entry.second.flag); - } - - // TODO: Test that doing this instead works - //Serialize(writer.GetCurPtr(), writer.GetBufferSize()); + Serialize(writer.GetCurPtr(), writer.GetRemainingSpace()); return Ref(writer.GetBuffer()); } @@ -181,8 +201,8 @@ namespace GameSmith { reader.MoveForward(paramSize); i++; } - + // Only the IDs are saved, the original pointers will need to be updated by the caller after deserialization using the saved IDs i = 0; while (i < meta->numConnections) { std::string name = reader.GetString(); @@ -211,4 +231,25 @@ namespace GameSmith { i++; } } -}; + + void ExposedVariableRegistry::AddToGroup(const std::string& groupName, const std::string& variableName) + { + if (m_GroupingRegistry.contains(groupName)) { + m_GroupingRegistry[groupName].insert(variableName); + } + else { + m_GroupingRegistry[groupName] = { variableName }; + } + } + + void ExposedVariableRegistry::RemoveFromGroup(const std::string& groupName, const std::string& variableName) + { + if (m_GroupingRegistry.contains(groupName)) { + auto& group = m_GroupingRegistry[groupName]; + group.erase(variableName); + if (group.empty()) { + m_GroupingRegistry.erase(groupName); + } + } + } +}; \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.h b/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.h index 167274c..fc1ac3c 100644 --- a/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.h +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/ExposedVariableRegistry.h @@ -1,10 +1,13 @@ #pragma once -#include "GameSmithEngine/SerializeableFiles/ResourceAssets/Asset.h" +#include "GameSmithEngine/SerializeableFiles/Serializable.h" #include "GameSmithEngine/Utilities/GUIDGenerator.h" #include "ParameterContainer.h" #include "UtilMacros.h" namespace GameSmith { + // Forward declarations + class IAsset; + enum ExposedVariableFlags { AssetGameObject = 0x1 }; @@ -21,6 +24,8 @@ namespace GameSmith { m_CopyRef = toAssign; } + + void ResetRef() { m_CopyRef = m_OriginalRef; m_ExpectedID = ID({ 0,0,0,0 }); } void AssignID(ID id) { m_ExpectedID = id; } std::string GetTypeName() const { return m_TypeName; } ID GetCurrentRefID() const { return m_ExpectedID; } @@ -30,16 +35,17 @@ namespace GameSmith { std::function m_TypeCheckFunc; std::string m_TypeName; T m_CopyRef; + T m_OriginalRef; ID m_ExpectedID; unsigned int m_Flag; }; // A ref container that only wants to establish a watching connection to an object - using ConnectionContainer = ObjectRefContainer>; + using ConnectionContainer = ObjectRefContainer>; // A ref container that wants to both establish and own a connection to an asset/serializable object - using AssetRefContainer = ObjectRefContainer>; + using AssetRefContainer = ObjectRefContainer>; - class GE_API ExposedVariableRegistry : public Serializeable + class GE_API ExposedVariableRegistry : public AbstractBaseSerializeable { public: /* Adds a definition for an exposed variable @@ -47,7 +53,14 @@ namespace GameSmith { * entry: a pointer to update with new variable data * entryType: the type of variable to treat this entry as */ - inline void AddExposedVariable(std::string variableName, void* entry, ContainerDataType entryType) { if (entry == nullptr) return; m_ValueRegistry.insert({ variableName, {entry, entryType} }); } + inline void AddExposedVariable(const std::string variableName, ContainerDataType entryType, void* entry, unsigned int entrySize = 0, const std::string& groupName = "") { + if (entry == nullptr) return; + m_ValueRegistry.insert({ variableName, {entry, entrySize, entryType, groupName} }); + AddToGroup(groupName, variableName); + } + void AddExposedVariable(const std::string variableName, Ref container, const std::string& groupName = ""); + + void RemoveExposedVariable(const std::string variableName); /* Adds a definition for an exposed connection * refName: A string to tie this new exposed connection definition @@ -56,7 +69,7 @@ namespace GameSmith { * flags: Any special flags to determine how the connection is interpreted (view ExposedVariableFlags) */ template - inline void AddExposedConnection(std::string refName, Connection* entry, std::string typeName, unsigned int flags = 0) { + inline void AddExposedConnection(const std::string refName, Connection* entry, std::string typeName, unsigned int flags = 0, const std::string& groupName = "") { if (entry == nullptr) return; m_ConnectionsRegistry.insert( @@ -64,23 +77,26 @@ namespace GameSmith { refName, { entry, - [](Connection* origin, Connection curPtr) + [](Connection* origin, Connection curPtr) { *((Connection*)origin) = CastPtr(curPtr.lock()); }, - - [](Connection curPtr) + [](Connection curPtr) { return CastPtr(curPtr.lock()) != nullptr; }, typeName, {}, - flags + flags, + groupName } } ); + AddToGroup(groupName, refName); } + void RemoveExposedConnection(const std::string refName); + /* Adds a definition for an exposed asset * refName: A string to tie this new exposed reference definition * entry: a pointer to update with new reference data @@ -88,7 +104,7 @@ namespace GameSmith { * flags: Any special flags to determine how the reference is interpreted (view ExposedVariableFlags) */ template - inline void AddExposedAsset(std::string refName, Ref* entry, std::string typeName, unsigned int flags = 0) { + inline void AddExposedAsset(const std::string refName, Ref* entry, std::string typeName, unsigned int flags = 0, const std::string& groupName = "") { if (entry == nullptr) return; m_AssetRegistry.insert( @@ -96,23 +112,26 @@ namespace GameSmith { refName, { entry, - [](Ref* origin, Ref curPtr) + [](Ref* origin, Ref curPtr) { *((Ref*)origin) = CastPtr(curPtr); }, - - [](Ref curPtr) + [](Ref curPtr) { return CastPtr(curPtr) != nullptr; }, typeName, {}, - flags + flags, + groupName } } ); + AddToGroup(groupName, refName); } + void RemoveExposedAsset(const std::string refName); + void GenerateVariableMap(std::unordered_map>* outMap); void GenerateConnectionsMap(std::unordered_map>* outMap); void GenerateAssetMap(std::unordered_map>* outMap); @@ -122,21 +141,30 @@ namespace GameSmith { void BootstrapFromAssetMap(const std::unordered_map>& inMap); + const std::unordered_map>& GetGroupingRegistry() const { return m_GroupingRegistry; } + virtual Ref Serialize() override; virtual void Serialize(char* byteStream, unsigned int availableBytes) override; virtual unsigned int RequiredSpace() const override; virtual void Deserialize(char* inData, unsigned int size) override; + private: + void AddToGroup(const std::string& groupName, const std::string& variableName); + void RemoveFromGroup(const std::string& groupName, const std::string& variableName); private: struct RegistrySerializeMetadata { - unsigned int numVariables; - unsigned int numConnections; - unsigned int numAssetRefs; + unsigned int numVariables = 0; + unsigned int numConnections = 0; + unsigned int numAssetRefs = 0; }; struct ExposedVariableEntry { void* originalVariableRef; + unsigned int variableSize; ContainerDataType variableDataType; + std::string groupName; unsigned int flags; + Ref containerRef = nullptr; + bool ownsContainer = false; }; template @@ -147,15 +175,35 @@ namespace GameSmith { std::string typeName; ID objectID; unsigned int flag; + std::string groupName; }; - using ExposedAssetEntry = ExposedObjectRefEntry>; - using ExposedConnectionEntry = ExposedObjectRefEntry>; + using ExposedAssetEntry = ExposedObjectRefEntry>; + using ExposedConnectionEntry = ExposedObjectRefEntry>; private: std::unordered_map m_ValueRegistry; std::unordered_map m_ConnectionsRegistry; std::unordered_map m_AssetRegistry; + std::unordered_map> m_GroupingRegistry; // Maps variable/connection/asset names to group names for organizational purposes + }; + + class GE_API IExposedMembers { + public: + virtual ~IExposedMembers() = default; + virtual void GenerateVariableEntries(std::unordered_map>* outMap) = 0; + virtual void GenerateConnectionEntries(std::unordered_map>* outMap) = 0; + virtual void GenerateAssetEntries(std::unordered_map>* outMap) = 0; + virtual const std::unordered_map>& GetExposedGroupings() const = 0; + + // Can be empty function + virtual void PostRegistryBootstrap() {}; + + virtual void BootstrapVariableRegistry(std::unordered_map>& variableEntries) = 0; + + virtual void BootstrapConnectionRegistry(std::unordered_map>& refEntries) = 0; + + virtual void BootstrapAssetRegistry(std::unordered_map>& refEntries) = 0; }; }; diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/GUIDGenerator.h b/GameSmithEngine/src/GameSmithEngine/Utilities/GUIDGenerator.h index 21a32ef..843e2f8 100644 --- a/GameSmithEngine/src/GameSmithEngine/Utilities/GUIDGenerator.h +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/GUIDGenerator.h @@ -15,7 +15,6 @@ namespace GameSmith { ID() : m_Data() {} ID(unsigned long ID1, unsigned short ID2, unsigned short ID3, unsigned long long ID4) : m_Data({ID1, ID2, ID3, ID4}) {} ID(idData externalData) : m_Data(externalData) {} - //ID operator=(ID& other) { return ID(other.m_Data.ID1, other.m_Data.ID2, m_Data.ID3, other.m_Data.ID4); } void operator=(ID& other) { m_Data = other.m_Data; } void operator=(const ID& other) { m_Data = other.m_Data; } @@ -39,16 +38,23 @@ namespace GameSmith { static ID GenerateID(); }; - class GE_API IDObject { + class GE_API IDObjectInterface { + public: + virtual ~IDObjectInterface() = default; + virtual const ID& GetID() const = 0; + virtual void SetID(ID& newID) = 0; + + }; + + class GE_API IDObject : public virtual IDObjectInterface { public: IDObject() : m_ID(GUIDGenerator::GenerateID()) {} virtual ~IDObject() = default; - inline const ID& GetID() const { return m_ID; } - inline void SetID(ID& newID) { m_ID = newID; } + inline const ID& GetID() const override { return m_ID; } + inline void SetID(ID& newID) override { m_ID = newID; } private: ID m_ID; }; - }; struct IDHasher { diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.cpp b/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.cpp new file mode 100644 index 0000000..04dc4a4 --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.cpp @@ -0,0 +1,27 @@ +#include "gepch.h" +#include "MiscellaneousUtilities.h" +#include +std::wstring GameSmith::ToWideString(const std::string& toConvert) +{ +#ifdef GE_PLATFORM_WINDOWS + int expectedSize = MultiByteToWideChar(CP_UTF8, 0, toConvert.c_str(), toConvert.size(), nullptr, 0); + std::wstring result(expectedSize, 0); + MultiByteToWideChar(CP_UTF8, 0, toConvert.c_str(), toConvert.size(), result.data(), expectedSize); + + return result; +#endif // GE_PLATFORM_WINDOW + + return std::wstring(); +} + +std::string GameSmith::ToNarrowString(const std::wstring& toConvert) +{ +#ifdef GE_PLATFORM_WINDOWS + int expectedSize = WideCharToMultiByte(CP_UTF8, 0, toConvert.c_str(), toConvert.size(), nullptr, 0, nullptr, nullptr); + std::string result(expectedSize, 0); + WideCharToMultiByte(CP_UTF8, 0, toConvert.c_str(), toConvert.size(), result.data(), expectedSize, nullptr, nullptr); + return result; +#endif // GE_PLATFORM_WINDOWS + + return std::string(); +} diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.h b/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.h new file mode 100644 index 0000000..5c4893d --- /dev/null +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/MiscellaneousUtilities.h @@ -0,0 +1,8 @@ +#pragma once +#include +namespace GameSmith { + // A collection of utilities that do not fit into a specific category but are used in multiple places + std::wstring ToWideString(const std::string& toConvert); + + std::string ToNarrowString(const std::wstring& toConvert); +} \ No newline at end of file diff --git a/GameSmithEngine/src/GameSmithEngine/Utilities/ParameterContainer.h b/GameSmithEngine/src/GameSmithEngine/Utilities/ParameterContainer.h index 385e988..40352e6 100644 --- a/GameSmithEngine/src/GameSmithEngine/Utilities/ParameterContainer.h +++ b/GameSmithEngine/src/GameSmithEngine/Utilities/ParameterContainer.h @@ -4,6 +4,8 @@ #include #include +#define CONTAINER_BUFFER_DEFAULT_SIZE 256 + namespace GameSmith { enum class ContainerDataType { None = 0, @@ -16,7 +18,8 @@ namespace GameSmith { Int3, Int4, Bool, - Matrix + Matrix, + CBuffer }; static UINT GetParameterSize(ContainerDataType type) { @@ -37,6 +40,9 @@ namespace GameSmith { return sizeof(int) * 2; case ContainerDataType::Int3: return sizeof(int) * 3; + // CString has the sames size of general buffer + case ContainerDataType::CBuffer: + return CONTAINER_BUFFER_DEFAULT_SIZE; default: return 0; } @@ -177,7 +183,27 @@ namespace GameSmith { glm::mat4 m_Data; }; - static Ref ConvertToParameter(std::string name, ContainerDataType type, char* data, unsigned int flags = 0) { + class CBufferContainer : public ParameterContainer { + public: + CBufferContainer(std::string name, unsigned int flags = 0) : ParameterContainer(name, ContainerDataType::CBuffer, flags) { memset(m_Buffer, 0, CONTAINER_BUFFER_DEFAULT_SIZE); } + CBufferContainer(std::string name, const char* data, unsigned int size, unsigned int flags = 0) : ParameterContainer(name, ContainerDataType::CBuffer, flags) + { + GE_CORE_ASSERT(size <= CONTAINER_BUFFER_DEFAULT_SIZE, "Buffer size exceeds default size"); + memset(m_Buffer, 0, CONTAINER_BUFFER_DEFAULT_SIZE); + memcpy(m_Buffer, data, size); + } + inline char* GetCharData() override { return m_Buffer; }; + inline void SetData(char* data, unsigned int size) { + GE_CORE_ASSERT(size <= CONTAINER_BUFFER_DEFAULT_SIZE, "Buffer size exceeds default size"); + memcpy(m_Buffer, data, size); + } + inline void ResetData() override {} + inline Ref MakeCopy() override { return Ref(new CBufferContainer(GetName(), m_Buffer, CONTAINER_BUFFER_DEFAULT_SIZE, GetFlags())); } + private: + char m_Buffer[CONTAINER_BUFFER_DEFAULT_SIZE]; + }; + + static Ref ConvertToParameter(std::string name, ContainerDataType type, const char* data, unsigned int size = 0, unsigned int flags = 0) { switch (type) { case ContainerDataType::Matrix: return Ref(new MatrixContainor(name, *((glm::mat4*)data), flags)); @@ -197,6 +223,9 @@ namespace GameSmith { return Ref(new Int3Container(name, (int*)data, flags)); case ContainerDataType::Int4: return Ref(new Int4Container(name, (int*)data, flags)); + case ContainerDataType::CBuffer: { + return Ref(new CBufferContainer(name, data, size, flags)); + } default: return 0; } @@ -222,6 +251,8 @@ namespace GameSmith { return Ref(new Int3Container(name, flags)); case ContainerDataType::Int4: return Ref(new Int4Container(name, flags)); + case ContainerDataType::CBuffer: + return Ref(new CBufferContainer(name, flags)); default: return 0; } diff --git a/GameSmithEngine/third-party/dxc/dxcompiler.dll b/GameSmithEngine/third-party/dxc/dxcompiler.dll new file mode 100644 index 0000000..430abcc Binary files /dev/null and b/GameSmithEngine/third-party/dxc/dxcompiler.dll differ diff --git a/GameSmithEngine/third-party/dxc/dxcompiler.lib b/GameSmithEngine/third-party/dxc/dxcompiler.lib new file mode 100644 index 0000000..3aa46db Binary files /dev/null and b/GameSmithEngine/third-party/dxc/dxcompiler.lib differ diff --git a/GameSmithEngine/third-party/dxc/dxil.dll b/GameSmithEngine/third-party/dxc/dxil.dll new file mode 100644 index 0000000..e22fc91 Binary files /dev/null and b/GameSmithEngine/third-party/dxc/dxil.dll differ diff --git a/GameSmithEngine/third-party/dxc/dxil.lib b/GameSmithEngine/third-party/dxc/dxil.lib new file mode 100644 index 0000000..8bac5c2 Binary files /dev/null and b/GameSmithEngine/third-party/dxc/dxil.lib differ diff --git a/GameSmithEngineProject.slnx b/GameSmithEngineProject.slnx new file mode 100644 index 0000000..445a9f0 --- /dev/null +++ b/GameSmithEngineProject.slnx @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GameSmithEngineTestSuite/GameSmithEngineTestSuite.vcxproj b/GameSmithEngineTestSuite/GameSmithEngineTestSuite.vcxproj index 27f2c26..a517fac 100644 --- a/GameSmithEngineTestSuite/GameSmithEngineTestSuite.vcxproj +++ b/GameSmithEngineTestSuite/GameSmithEngineTestSuite.vcxproj @@ -26,19 +26,19 @@ Application true Unicode - v143 + v145 Application false Unicode - v143 + v145 Application false Unicode - v143 + v145 @@ -83,7 +83,7 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -91,6 +91,8 @@ Console true + + xcopy /Q /E /Y /I "$(ProjectDir)resources" "$(TargetDir)resources" @@ -107,7 +109,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -116,6 +118,8 @@ true true + + xcopy /Q /E /Y /I "$(ProjectDir)resources" "$(TargetDir)resources" @@ -128,13 +132,15 @@ tst;..\GameSmithEngine\src;..\GameSmithEngine\third-party\spdlog\include;..\GameSmithEngine\third-party\glm;..\third-party\googletest\googletest\include;..\third-party\googletest\googletest\src;%(AdditionalIncludeDirectories) Disabled MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 Console + + xcopy /Q /E /Y /I "$(ProjectDir)resources" "$(TargetDir)resources" diff --git a/GameSmithEngineTestSuite/GoogleTest.vcxproj b/GameSmithEngineTestSuite/GoogleTest.vcxproj index 69d1613..f2cffd8 100644 --- a/GameSmithEngineTestSuite/GoogleTest.vcxproj +++ b/GameSmithEngineTestSuite/GoogleTest.vcxproj @@ -26,19 +26,19 @@ StaticLibrary true Unicode - v143 + v145 StaticLibrary false Unicode - v143 + v145 StaticLibrary false Unicode - v143 + v145 @@ -87,6 +87,8 @@ Windows true + + @@ -108,6 +110,8 @@ true true + + @@ -122,6 +126,8 @@ Windows + + diff --git a/GameSmithEngineTestSuite/premake5.lua b/GameSmithEngineTestSuite/premake5.lua index 8a8d219..1b1ba89 100644 --- a/GameSmithEngineTestSuite/premake5.lua +++ b/GameSmithEngineTestSuite/premake5.lua @@ -62,7 +62,10 @@ project "GameSmithEngineTestSuite" filter "system:windows" systemversion "latest" - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } defines{ "GE_PLATFORM_WINDOWS" diff --git a/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.cso b/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.cso deleted file mode 100644 index 36508be..0000000 Binary files a/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.cso and /dev/null differ diff --git a/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.hlsl b/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.hlsl new file mode 100644 index 0000000..15db8b5 --- /dev/null +++ b/GameSmithEngineTestSuite/resources/shaders/SampleVertexShader.hlsl @@ -0,0 +1,30 @@ +struct VertexShaderOutput +{ + float4 Position : SV_POSITION; + float2 UV : UV_TEXCOORD; + float3 Normal : NORMAL; + float3 WorldNormal : WORLDNORMAL; + float3 WorldPos : WORLDPOS; + uint vert_Id : ID; +}; + + +cbuffer Instance : register(b1) { + matrix M; + float3 inputColor; +}; + +#include "../Core.hlsl" + +VertexShaderOutput main(DefaultVertexData input, uint id : SV_VertexID) +{ + VertexShaderOutput output; + output.vert_Id = id; + output.Normal = input.Normal; + output.WorldPos = mul(float4(input.Position, 1.0f), M).xyz; + output.WorldNormal = mul(float4(input.Normal, 0.0f), M).xyz; + output.Position = mul(float4(output.WorldPos, 1.0f), VP); + output.UV = input.UV; + + return output; +} \ No newline at end of file diff --git a/GameSmithEngineTestSuite/tst/GameSmithEngineTest/ResourceAssets/ShaderAssetTest.cpp b/GameSmithEngineTestSuite/tst/GameSmithEngineTest/ResourceAssets/ShaderAssetTest.cpp index 697fb0c..60ae379 100644 --- a/GameSmithEngineTestSuite/tst/GameSmithEngineTest/ResourceAssets/ShaderAssetTest.cpp +++ b/GameSmithEngineTestSuite/tst/GameSmithEngineTest/ResourceAssets/ShaderAssetTest.cpp @@ -18,20 +18,15 @@ static GameSmith::Ref loadFile(std::string file, unsigned int* outSize) { } static unsigned int testShaderSize; -static GameSmith::Ref testShader = loadFile(std::format("{0}{1}", TEST_RESOURCES, "/shaders/SampleVertexShader.cso"), &testShaderSize); +static GameSmith::Ref testShader = loadFile(std::format("{0}{1}", TEST_RESOURCES, "/shaders/SampleVertexShader.hlsl"), &testShaderSize); -TEST(ShaderAssetTest, Deserialize) { - GameSmith::RenderingManager::Init(); - - GameSmith::ShaderAsset asset; +TEST(HLSLAssetTest, Deserialize) { + GameSmith::HLSLAsset asset("Test"); EXPECT_NO_THROW(asset.Deserialize(testShader.get(), testShaderSize)); - GameSmith::RenderingManager::ShutDown(); } -TEST(ShaderAssetTest, SerializeNew) { - GameSmith::RenderingManager::Init(); - - GameSmith::ShaderAsset asset; +TEST(HLSLAssetTest, SerializeNew) { + GameSmith::HLSLAsset asset("Test"); EXPECT_NO_THROW(asset.Deserialize(testShader.get(), testShaderSize)); GameSmith::Ref serial = asset.Serialize(); @@ -39,13 +34,10 @@ TEST(ShaderAssetTest, SerializeNew) { for (unsigned int i = 0; i < testShaderSize; i++) { EXPECT_EQ(*(testShader.get() + i), *(serial.get() + i)); } - GameSmith::RenderingManager::ShutDown(); } -TEST(ShaderAssetTest, SerializeAppend) { - GameSmith::RenderingManager::Init(); - - GameSmith::ShaderAsset asset; +TEST(HLSLAssetTest, SerializeAppend) { + GameSmith::HLSLAsset asset("Test"); EXPECT_NO_THROW(asset.Deserialize(testShader.get(), testShaderSize)); GameSmith::Ref serial = GameSmith::Ref(new char[testShaderSize + 5]); @@ -54,15 +46,11 @@ TEST(ShaderAssetTest, SerializeAppend) { for (unsigned int i = 0; i < testShaderSize; i++) { EXPECT_EQ(*(testShader.get() + i), *(serial.get() + i + 5)); } - GameSmith::RenderingManager::ShutDown(); } -TEST(ShaderAssetTest, GetRequiredSize) { - GameSmith::RenderingManager::Init(); - - GameSmith::ShaderAsset asset; +TEST(HLSLAssetTest, GetRequiredSize) { + GameSmith::HLSLAsset asset("Test"); EXPECT_NO_THROW(asset.Deserialize(testShader.get(), testShaderSize)); EXPECT_EQ(testShaderSize, asset.RequiredSpace()); - GameSmith::RenderingManager::ShutDown(); } \ No newline at end of file diff --git a/GameSmithEngineTestSuite/tst/GameSmithEngineTest/Utilities/ExposedVariableRegistryTest.cpp b/GameSmithEngineTestSuite/tst/GameSmithEngineTest/Utilities/ExposedVariableRegistryTest.cpp index 585813c..0c64d43 100644 --- a/GameSmithEngineTestSuite/tst/GameSmithEngineTest/Utilities/ExposedVariableRegistryTest.cpp +++ b/GameSmithEngineTestSuite/tst/GameSmithEngineTest/Utilities/ExposedVariableRegistryTest.cpp @@ -17,34 +17,76 @@ TEST(ExposedVariableRegistryTest, GenerateVariableMapSingleEntry) { EXPECT_EQ(testMap.size(), 0); bool testVar; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", &testVar, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", GameSmith::ContainerDataType::Int , &testVar, 0, "SampleGroup")); registry.GenerateVariableMap(&testMap); EXPECT_EQ(testMap.size(), 1); EXPECT_TRUE(testMap.contains("TestVariable")); + auto& groupings = registry.GetGroupingRegistry(); + EXPECT_TRUE(groupings.contains("SampleGroup")); + EXPECT_TRUE(groupings.find("SampleGroup")->second.contains("TestVariable")); + const auto& mapEntry = testMap.find("TestVariable"); EXPECT_EQ(mapEntry->second->GetName(), "TestVariable"); EXPECT_EQ(mapEntry->second->GetType(), GameSmith::ContainerDataType::Int); } -TEST(ExposedVariableRegistryTest, GenerateVariableMapMultipleEntry) { +TEST(ExposedVariableRegistryTest, GenerateVariableMapMultipleEntrySameGroup) { + std::unordered_map> testMap; + GameSmith::ExposedVariableRegistry registry; + + EXPECT_EQ(testMap.size(), 0); + + bool testVar1; + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable1", GameSmith::ContainerDataType::Int, &testVar1, 0, "SampleGroup")); + + int testVar2; + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable2", GameSmith::ContainerDataType::Int, &testVar2, 0, "SampleGroup")); + + registry.GenerateVariableMap(&testMap); + EXPECT_EQ(testMap.size(), 2); + EXPECT_TRUE(testMap.contains("TestVariable1")); + EXPECT_TRUE(testMap.contains("TestVariable2")); + + auto& groupings = registry.GetGroupingRegistry(); + EXPECT_TRUE(groupings.contains("SampleGroup")); + auto& sampleGroup = groupings.find("SampleGroup")->second; + EXPECT_TRUE(sampleGroup.contains("TestVariable1")); + EXPECT_TRUE(sampleGroup.contains("TestVariable2")); + + const auto& mapEntry1 = testMap.find("TestVariable1"); + EXPECT_EQ(mapEntry1->second->GetName(), "TestVariable1"); + EXPECT_EQ(mapEntry1->second->GetType(), GameSmith::ContainerDataType::Int); + + const auto& mapEntry2 = testMap.find("TestVariable2"); + EXPECT_EQ(mapEntry2->second->GetName(), "TestVariable2"); + EXPECT_EQ(mapEntry2->second->GetType(), GameSmith::ContainerDataType::Int); +} + +TEST(ExposedVariableRegistryTest, GenerateVariableMapMultipleEntryDifferentGroup) { std::unordered_map> testMap; GameSmith::ExposedVariableRegistry registry; EXPECT_EQ(testMap.size(), 0); bool testVar1; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable1", &testVar1, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable1", GameSmith::ContainerDataType::Int, &testVar1, 0, "SampleGroup")); int testVar2; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable2", &testVar2, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable2", GameSmith::ContainerDataType::Int, &testVar2, 0, "SampleGroup2")); registry.GenerateVariableMap(&testMap); EXPECT_EQ(testMap.size(), 2); EXPECT_TRUE(testMap.contains("TestVariable1")); EXPECT_TRUE(testMap.contains("TestVariable2")); + auto& groupings = registry.GetGroupingRegistry(); + EXPECT_TRUE(groupings.contains("SampleGroup")); + EXPECT_TRUE(groupings.contains("SampleGroup2")); + + EXPECT_TRUE(groupings.find("SampleGroup")->second.contains("TestVariable1")); + EXPECT_TRUE(groupings.find("SampleGroup2")->second.contains("TestVariable2")); const auto& mapEntry1 = testMap.find("TestVariable1"); EXPECT_EQ(mapEntry1->second->GetName(), "TestVariable1"); @@ -60,7 +102,7 @@ TEST(ExposedVariableRegistryTest, AddExposedVariableNullReference) { GameSmith::ExposedVariableRegistry registry; EXPECT_EQ(testMap.size(), 0); - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", nullptr, GameSmith::ContainerDataType::Bool)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", GameSmith::ContainerDataType::Bool, nullptr)); registry.GenerateVariableMap(&testMap); EXPECT_EQ(testMap.size(), 0); @@ -72,7 +114,7 @@ TEST(ExposedVariableRegistryTest, BootstrapVariableMapSingleVariable) { EXPECT_EQ(testMap.size(), 0); int testVar; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", &testVar, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", GameSmith::ContainerDataType::Int, &testVar)); registry.GenerateVariableMap(&testMap); EXPECT_EQ(testMap.size(), 1); @@ -92,10 +134,10 @@ TEST(ExposedVariableRegistryTest, BootstrapVariableMapMultipleVariable) { EXPECT_EQ(testMap.size(), 0); int testVar; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", &testVar, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable", GameSmith::ContainerDataType::Int, &testVar)); int testVar1; - EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable1", &testVar1, GameSmith::ContainerDataType::Int)); + EXPECT_NO_THROW(registry.AddExposedVariable("TestVariable1", GameSmith::ContainerDataType::Int, &testVar1)); registry.GenerateVariableMap(&testMap); EXPECT_EQ(testMap.size(), 2); diff --git a/TestZone/TestZone.vcxproj b/TestZone/TestZone.vcxproj index 5e34f93..7ad872a 100644 --- a/TestZone/TestZone.vcxproj +++ b/TestZone/TestZone.vcxproj @@ -26,19 +26,19 @@ Application true Unicode - v143 + v145 Application false Unicode - v143 + v145 Application false Unicode - v143 + v145 @@ -83,7 +83,7 @@ EditAndContinue Disabled MultiThreadedDebugDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -91,6 +91,8 @@ Console true + + @@ -104,7 +106,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -113,6 +115,8 @@ true true + + @@ -126,7 +130,7 @@ false true MultiThreadedDLL - /utf-8 %(AdditionalOptions) + /utf-8 /wd4250 %(AdditionalOptions) stdcpp20 Level3 @@ -135,6 +139,8 @@ true true + + diff --git a/TestZone/premake5.lua b/TestZone/premake5.lua index 61c99cc..ce63f0c 100644 --- a/TestZone/premake5.lua +++ b/TestZone/premake5.lua @@ -33,7 +33,10 @@ project "TestZone" filter "system:windows" systemversion "latest" - buildoptions { "/utf-8" } + buildoptions { + "/utf-8", + "/wd4250" + } defines{ "GE_PLATFORM_WINDOWS" diff --git a/TestZone/src/TestingLayer.cpp b/TestZone/src/TestingLayer.cpp index 380c355..fb85298 100644 --- a/TestZone/src/TestingLayer.cpp +++ b/TestZone/src/TestingLayer.cpp @@ -1,4 +1,7 @@ #include "TestingLayer.h" +#include "GameSmithEngine/ResourceManagement/ResourceLoaders/HeapResourceLoader.h" +#include "GameSmithEngine/Rendering/DirectX12/DirectX12ShaderCompiler.h" +#include "GameSmithEngine/Rendering/RenderAgnostics/Shaders/ShaderIncludeCache.h" GE_REGISTERCOMPONENT(TestLayerComponent) @@ -82,6 +85,29 @@ TestingLayer::TestingLayer() : GameSmith::Layer("Testing Layer") auto gm1 = GameSmith::GameObjectManager::GetInstance()->CreateGameObject(); gm1.lock()->GetTransform().lock()->SetPosition({ 6, 8, 1 }); + auto assetManager = GameSmith::AssetManager::GetInstance(); + assetManager->ImportResource("C:/Users/esaus/Documents/Coding Projects/GameSmithEngine/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Core.hlsl"); + auto importedAsset = assetManager->ImportResource("C:/Users/esaus/Documents/Coding Projects/GameSmithEngine/GameSmithEngine/src/GameSmithEngine/Rendering/SampleShaders/Vertex/BasicRenderVS.hlsl"); + + std::vector> shaderFiles; + assetManager->GetAssetPathsOfType(&shaderFiles); + + std::unordered_map shaderFileCache; + for (auto& entry : shaderFiles) { + auto id = assetManager->GetAssetID(entry.second); + shaderFileCache[entry.first] = id; + } + + auto rm = GameSmith::RenderingManager::GetInstance(); + rm->SetShaderSourceCache(shaderFileCache); + + + auto vertex = assetManager->GetResource(importedAsset); + GameSmith::HLSLSourceSet sourceSet; + sourceSet.sources[GameSmith::Stages::STAGE_VERTEX] = vertex; + GameSmith::ShaderAsset shader("Main", sourceSet); + shader.GetShader(GameSmith::Stages::STAGE_VERTEX); + /*std::vector> objs; objs.push_back(gm); objs.push_back(gm1); @@ -148,7 +174,7 @@ void TestingLayer::OnImGuiRender() { } -void TestingLayer::OnUpdate(float dt) +void TestingLayer::OnUpdate(float dt) { auto renderManager = GameSmith::RenderingManager::GetInstance(); renderManager->SetForClear(m_RenderTex); diff --git a/TestZone/src/TestingLayer.h b/TestZone/src/TestingLayer.h index acbf72a..849c49e 100644 --- a/TestZone/src/TestingLayer.h +++ b/TestZone/src/TestingLayer.h @@ -4,7 +4,7 @@ class TestLayerComponent : public GameSmith::Component { public: TestLayerComponent(GameSmith::GameObject* gameObject, GameSmith::Transform* transform) : Component(gameObject, transform) { - m_Registry.AddExposedConnection("TestRef", (GameSmith::Connection*) & m_TestRef, CLASS_TO_STRING(GameSmith::GameObject)); + m_Registry.AddExposedConnection("TestRef", (GameSmith::Connection*) & m_TestRef, CLASS_TO_STRING(GameSmith::GameObject)); } virtual void OnStart() override {};