diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..ff664441 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Report a bug that should be fixed +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..23094e9d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest a feature for the project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index 21050428..8b61dc67 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -21,141 +21,6 @@ Layer: 4294967295 Strength: 0 Scripts: ~ -- EID: 1 - Name: Floor - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -1.440328, y: -4.41369677, z: -5} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 49.4798889, y: 0.5, z: 17.5} - Renderable Component: - Mesh: 149697411 - Material: 126974645 - RigidBody Component: - Type: Static - Mass: 1 - Drag: 0.00999999978 - Angular Drag: 0.00999999978 - Use Gravity: true - Interpolate: true - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Scripts: ~ -- EID: 10 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436} - Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684} - Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165} - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: true - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Scripts: ~ -- EID: 3 - Name: Empty - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -0.0094268322, y: 0, z: 0} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 1, y: 1, z: 1} - Scripts: ~ -- EID: 4 - Name: Empty2 - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Scripts: ~ -- EID: 9 - Name: Bag - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Renderable Component: - Mesh: 144838771 - Material: 123745521 - Scripts: ~ -- EID: 6 - Name: AI - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -8, y: -2, z: 2.5} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Renderable Component: - Mesh: 149697411 - Material: 126974645 - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: true - Freeze Rotation Y: true - Freeze Rotation Z: true - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 0.5, y: 0.5, z: 0.5} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: ~ - EID: 7 Name: BigBoi IsActive: true @@ -181,51 +46,4 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 0.25 - Scripts: ~ -- EID: 5 - Name: item - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: -2, z: -5} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 2, y: 2, z: 2} - Renderable Component: - Mesh: 144838771 - Material: 123745521 - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: true - Freeze Rotation Y: true - Freeze Rotation Z: true - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - - Is Trigger: true - Type: Box - Half Extents: {x: 2, y: 2, z: 2} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: - - Type: Item - currCategory: 0 - - Type: PickAndThrow - throwForce: [100, 200, 100] - item: 51000 \ No newline at end of file + Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/Normals_FS.glsl b/Assets/Shaders/Normals_FS.glsl new file mode 100644 index 00000000..ba260d82 --- /dev/null +++ b/Assets/Shaders/Normals_FS.glsl @@ -0,0 +1,50 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#extension GL_EXT_nonuniform_qualifier : require + +struct MatPropData +{ + vec4 color; + int textureIndex; + float alpha; + vec3 beta; +}; + +layout(location = 0) in struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + +} In; + +// material stuff +layout(location = 3) flat in struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; +} In2; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) +layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials +{ + MatPropData data[]; +} MatProp; + +layout(location = 0) out vec4 position; +layout(location = 1) out uint outEntityID; +layout(location = 2) out uint lightLayerIndices; +layout(location = 3) out vec4 normals; +layout(location = 4) out vec4 albedo; + +void main() +{ + position = In.vertPos; + normals = In.normal; + albedo = normals * texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color; + + outEntityID = In2.eid; + lightLayerIndices = In2.lightLayerIndex; +} \ No newline at end of file diff --git a/Assets/Shaders/Normals_FS.shshaderb b/Assets/Shaders/Normals_FS.shshaderb new file mode 100644 index 00000000..7595ece9 Binary files /dev/null and b/Assets/Shaders/Normals_FS.shshaderb differ diff --git a/Assets/Shaders/Normals_FS.shshaderb.shmeta b/Assets/Shaders/Normals_FS.shshaderb.shmeta new file mode 100644 index 00000000..38544c0a --- /dev/null +++ b/Assets/Shaders/Normals_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Normals_FS +ID: 48689301 +Type: 2 diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua index 395c3a48..cba0c35e 100644 --- a/SHADE_Application/premake5.lua +++ b/SHADE_Application/premake5.lua @@ -75,7 +75,8 @@ project "SHADE_Application" "26439", "26451", "26437", - "4275" + "4275", + "4635" } linkoptions { "-IGNORE:4006" } diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 57b4c189..291fdcb1 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -8,8 +8,8 @@ //#include "Scenes/SBEditorScene.h" #endif // SHEDITOR -#include "Tools/SHLogger.h" -#include "Tools/SHFileUtilties.h" +#include "Tools/Logger/SHLogger.h" +#include "Tools/Utilities/SHFileUtilties.h" #include #include @@ -45,7 +45,7 @@ #include "Scenes/SBMainScene.h" #include "Serialization/Configurations/SHConfigurationManager.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Tools/SHDebugDraw.h" using namespace SHADE; @@ -61,6 +61,8 @@ namespace Sandbox _In_ INT nCmdShow ) { + SHLOG_INFO_D("Initialising SHADE engine") + // Set working directory SHFileUtilities::SetWorkDirToExecDir(); WindowData wndData{}; @@ -115,6 +117,7 @@ namespace Sandbox SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Application/src/WinMain.cpp b/SHADE_Application/src/WinMain.cpp index f672cead..9dcab1ab 100644 --- a/SHADE_Application/src/WinMain.cpp +++ b/SHADE_Application/src/WinMain.cpp @@ -1,6 +1,6 @@ #include "SBpch.h" #include -#include +#include #include #include "Application/SBApplication.h" diff --git a/SHADE_CSharp/premake5.lua b/SHADE_CSharp/premake5.lua index 2d6c1edb..39ef8281 100644 --- a/SHADE_CSharp/premake5.lua +++ b/SHADE_CSharp/premake5.lua @@ -27,6 +27,12 @@ project "SHADE_CSharp" warnings 'Extra' + postbuildcommands + { + "xcopy /r /y /q \"%{outputdir}\\net5.0\\SHADE_CSharp.xml\" \"%{outputdir}\"", + "xcopy /r /y /q \"%{outputdir}\\net5.0\\SHADE_CSharp.pdb\" \"%{outputdir}\"" + } + filter "configurations:Debug" symbols "On" defines {"_DEBUG"} @@ -41,12 +47,18 @@ project "SHADE_CSharp" require "vstudio" - function platformsElement(cfg) + function platformsElementCS(cfg) _p(2,'x64') end + function docsElementCS(cfg) + _p(2,'true') + end + function docsLocationElementCS(cfg) + _p(2,'$(OutDir)') + end premake.override(premake.vstudio.cs2005.elements, "projectProperties", function (oldfn, cfg) return table.join(oldfn(cfg), { - platformsElement, + platformsElementCS, docsElementCS, docsLocationElementCS, }) end) \ No newline at end of file diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 42f95520..1d6d7bef 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -78,7 +78,8 @@ project "SHADE_Engine" "26439", "26451", "26437", - "4275" + "4275", + "4635" } linkoptions { "-IGNORE:4006" } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 968e76dd..1569a13c 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -143,7 +143,29 @@ namespace SHADE return result; } - /**************************************************************************** + AssetType SHAssetManager::GetType(AssetID id) noexcept + { + if (assetCollection.contains(id)) + { + return assetCollection[id].type; + } + + SHLOG_WARNING("AssetID {}, does not belong to an asset", id) + + return AssetType::INVALID; + } + + std::optional SHAssetManager::GetAsset(AssetID id) noexcept + { + if (assetCollection.contains(id)) + { + return assetCollection[id]; + } + + return {}; + } + + /**************************************************************************** * \brief Create record for new asset. CAN ONLY CREATE FOR CUSTOM * ASSETS CREATED BY THE ENGINE. * @@ -161,21 +183,39 @@ namespace SHADE newPath += PREFAB_FOLDER; newPath += name; newPath += PREFAB_EXTENSION; - data = new SHPrefabAsset(); + { + auto prefab = new SHPrefabAsset(); + prefab->name = name; + + data = prefab; + } + break; case AssetType::SCENE: newPath += SCENE_FOLDER; newPath += name; newPath += SCENE_EXTENSION; - data = new SHSceneAsset(); + + { + auto scene = new SHSceneAsset(); + scene->name = name; + + data = scene; + } break; case AssetType::MATERIAL: newPath += MATERIAL_FOLDER; newPath += name; newPath += MATERIAL_EXTENSION; - data = new SHMaterialAsset(); + + { + auto material = new SHMaterialAsset(); + material->name = name; + + data = material; + } break; default: @@ -192,7 +232,7 @@ namespace SHADE false }; - assetCollection.insert({ + auto result = assetCollection.emplace( id, SHAsset( name, @@ -201,10 +241,13 @@ namespace SHADE newPath, false ) - }); + ); assetData.emplace(id, data); + SHAssetMetaHandler::WriteMetaData(asset); + SaveAsset(id); + return id; } @@ -361,6 +404,21 @@ namespace SHADE modelPath += MODEL_EXTENSION; newPath = modelPath; } + else if (ext == DDS_EXTENSION.data()) + { + auto pathGen = SHTextureCompiler::CompileTextureAsset(path); + if (!pathGen.has_value()) + { + SHLOG_ERROR("Texture Compilation Failed for: {}", path.string()); + return; + } + newPath = pathGen.value(); + } + else + { + SHLOG_WARNING("File Type compilation not yet Implemented: {}", path.string()); + return; + } if (genMeta) { @@ -376,7 +434,7 @@ namespace SHADE void SHAssetManager::RefreshDirectory() noexcept { SHFileSystem::DestroyDirectory(folderRoot); - assetCollection.clear(); + //assetCollection.clear(); BuildAssetCollection(); } @@ -507,7 +565,7 @@ namespace SHADE { SHAsset newAsset{ path.stem().string(), - GenerateAssetID(AssetType::SHADER_BUILT_IN), + GenerateAssetID(AssetType::TEXTURE), AssetType::SHADER_BUILT_IN, path, false @@ -560,6 +618,34 @@ namespace SHADE assetCollection.emplace(newAsset.id, newAsset); SHAssetMetaHandler::WriteMetaData(newAsset); + return newAsset.id; + } + else if (ext == SCENE_EXTENSION) + { + SHAsset newAsset{ + path.stem().string(), + GenerateAssetID(AssetType::SCENE), + AssetType::SCENE, + path, + false + }; + assetCollection.emplace(newAsset.id, newAsset); + SHAssetMetaHandler::WriteMetaData(newAsset); + + return newAsset.id; + } + else if (ext == FONT_EXTENSION) + { + SHAsset newAsset{ + path.stem().string(), + GenerateAssetID(AssetType::FONT), + AssetType::FONT, + path, + false + }; + assetCollection.emplace(newAsset.id, newAsset); + SHAssetMetaHandler::WriteMetaData(newAsset); + return newAsset.id; } } @@ -571,8 +657,11 @@ namespace SHADE for (auto& file : toGenNew) { - auto newID{ GenerateNewMeta(file->path).value() }; - file->assetMeta = &assetCollection[newID]; + auto newID{ GenerateNewMeta(file->path) }; + if (newID.has_value()) + { + file->assetMeta = &assetCollection[newID.value()]; + } } for (auto& asset : std::ranges::views::values(assetCollection)) @@ -583,6 +672,12 @@ namespace SHADE for (auto i{ 0 }; i < asset.subAssets.size(); ++i) { auto const id = asset.subAssets[i]->id; + + if (assetCollection.contains(id)) + { + continue; + } + assetCollection[id] = *asset.subAssets[i]; delete asset.subAssets[i]; asset.subAssets[i] = &assetCollection[id]; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index f6ecb3a3..6cac6c71 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -50,6 +50,9 @@ namespace SHADE * \return const& to unordered_map ****************************************************************************/ static std::vector GetAllAssets() noexcept; + static std::optional GetAsset(AssetID id) noexcept; + + static AssetType GetType(AssetID id) noexcept; /**************************************************************************** * \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp index f3b24ed1..b5c78514 100644 --- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp +++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp @@ -138,6 +138,7 @@ namespace SHADE metaFile.close(); meta.path = path.parent_path().string() + "/" + path.stem().string(); + meta.path.make_preferred(); return meta; } diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.h b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h index f19fcc3b..7196b40d 100644 --- a/SHADE_Engine/src/AudioSystem/SHAudioSystem.h +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h @@ -7,7 +7,7 @@ #include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/SHECSMacros.h" -#include "Math/SHMath.h" +#include "Math/Vector/SHVec3.h" #include #include #include "SH_API.h" diff --git a/SHADE_Engine/src/Camera/SHCameraDirector.cpp b/SHADE_Engine/src/Camera/SHCameraDirector.cpp index 98341098..9e9ddb5c 100644 --- a/SHADE_Engine/src/Camera/SHCameraDirector.cpp +++ b/SHADE_Engine/src/Camera/SHCameraDirector.cpp @@ -5,7 +5,7 @@ #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/SHECSMacros.h" #include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" namespace SHADE { diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp index 050d0c2e..db41d848 100644 --- a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp @@ -5,7 +5,7 @@ #include "../Managers/SHSystemManager.h" #include "SHTestComponents.h" #include "SHTestSystems.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" diff --git a/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.cpp b/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.cpp index 97fd8a22..4c56d032 100644 --- a/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.cpp +++ b/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.cpp @@ -5,6 +5,7 @@ namespace SHADE { bool SHDragDrop::hasDragDrop = false; + SHDragDrop::DragDropTag SHDragDrop::currentDragDropTag{}; bool SHDragDrop::BeginSource(ImGuiDragDropFlags const flags) { return ImGui::BeginDragDropSource(flags); } @@ -16,6 +17,10 @@ namespace SHADE { return ImGui::BeginDragDropTarget(); } void SHDragDrop::EndTarget() - { ImGui::EndDragDropTarget(); hasDragDrop = false;} + { + ImGui::EndDragDropTarget(); + hasDragDrop = false; + currentDragDropTag = {}; + } } diff --git a/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.hpp b/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.hpp index ce0615e1..f111eaeb 100644 --- a/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.hpp +++ b/SHADE_Engine/src/Editor/DragDrop/SHDragDrop.hpp @@ -19,9 +19,13 @@ namespace SHADE static void EndSource(); template - static bool SetPayload(std::string_view const type, T* object, ImGuiCond const cond = 0) + static bool SetPayload(DragDropTag const& type, T* object, ImGuiCond const cond = 0) { - hasDragDrop = ImGui::SetDragDropPayload(type.data(), static_cast(object), sizeof(T), cond); + ImGui::SetDragDropPayload(type.data(), static_cast(object), sizeof(T), cond); + + hasDragDrop = true; + currentDragDropTag = type; + return hasDragDrop; } @@ -32,13 +36,16 @@ namespace SHADE static void EndTarget(); template - static T* AcceptPayload(std::string_view const type, ImGuiDragDropFlags const flags = 0) + static T* AcceptPayload(DragDropTag const& type, ImGuiDragDropFlags const flags = 0) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(type.data(), flags)) + { return static_cast(payload->Data); + } return nullptr; } static bool hasDragDrop; + static DragDropTag currentDragDropTag; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 889c24cc..66b3c962 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -109,7 +109,7 @@ namespace SHADE ImVec2 vertLineEnd = vertLineStart; for (auto const& subFolder : subFolders) { - const float horizontalLineSize = 8.0f; + const float horizontalLineSize = (subFolder->subFolders.empty() && subFolder->files.empty()) ? 25.0f : 8.0f; const ImRect childRect = RecursivelyDrawTree(subFolder); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); @@ -117,7 +117,7 @@ namespace SHADE } for (auto& file : files) { - const float horizontalLineSize = 25.0f; + const float horizontalLineSize = (file.assetMeta && !file.assetMeta->subAssets.empty()) ? 8.0f : 25.0f; const ImRect childRect = DrawFile(file); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); @@ -182,7 +182,10 @@ namespace SHADE return nodeRect; } if(file.assetMeta) - DrawAsset(file.assetMeta, file.ext); + { + const ImRect childRect = DrawAsset(file.assetMeta, file.ext); + return childRect; + } } ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 6be89a8b..2235f831 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -23,7 +23,7 @@ #include #include "Serialization/SHSerialization.h" -#include "Tools/SHClipboardUtilities.h" +#include "Tools/Utilities/SHClipboardUtilities.h" namespace SHADE @@ -117,9 +117,12 @@ namespace SHADE { if(ImGui::IsDragDropActive()) { - ParentSelectedEntities(MAX_EID, draggingEntities); - draggingEntities.clear(); - ImGui::ClearDragDrop(); + if (SHDragDrop::currentDragDropTag == SHDragDrop::DRAG_EID) + { + ParentSelectedEntities(MAX_EID, draggingEntities); + draggingEntities.clear(); + ImGui::ClearDragDrop(); + } } } ImGui::End(); @@ -233,8 +236,9 @@ namespace SHADE { ParentSelectedEntities(eid, draggingEntities); draggingEntities.clear(); - SHDragDrop::EndTarget(); + //ImGui::ClearDragDrop(); } + SHDragDrop::EndTarget(); } //Context menu @@ -342,13 +346,16 @@ namespace SHADE SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID); } - void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector const& entities) const noexcept + void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector const& entities) noexcept { auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + + std::vector entitiesToParent = CleanUpEIDList(entities); + //auto const editor = SHSystemManager::GetSystem(); SHEntityParentCommand::EntityParentData entityParentData; std::vector parentedEIDS; - for (auto const& eid : entities) + for (auto const& eid : entitiesToParent) { if(eid == parentEID) continue; @@ -411,14 +418,7 @@ namespace SHADE void SHHierarchyPanel::CopySelectedEntities() { const auto editor = SHSystemManager::GetSystem(); - auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - std::vector entitiesToCopy{}; - std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToCopy), [&sceneGraph](EntityID const& eid) - { - if(sceneGraph.GetParent(eid)->GetEntityID() == MAX_EID) - return true; - return false; - }); + std::vector entitiesToCopy = CleanUpEIDList(editor->selectedEntities); SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(entitiesToCopy)); } @@ -431,19 +431,25 @@ namespace SHADE void SHHierarchyPanel::DeleteSelectedEntities() { const auto editor = SHSystemManager::GetSystem(); + std::vector entitiesToDelete = CleanUpEIDList(editor->selectedEntities); + SHCommandManager::PerformCommand(std::make_shared(entitiesToDelete)); + } + + std::vector SHHierarchyPanel::CleanUpEIDList(std::vector const& entities) + { + std::vector result; auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - std::vector entitiesToDelete{}; - std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToDelete), [&sceneGraph, &selectedEntities = editor->selectedEntities](EntityID const& eid) + std::ranges::copy_if(entities, std::back_inserter(result), [&sceneGraph, &entities](EntityID const& eid) { EntityID parentEID = sceneGraph.GetParent(eid)->GetEntityID(); if (parentEID == MAX_EID) return true; - else if(std::ranges::find(selectedEntities, parentEID) == selectedEntities.end()) + if (std::ranges::find(entities, parentEID) == entities.end()) return true; return false; }); - SHCommandManager::PerformCommand(std::make_shared(entitiesToDelete)); + return result; } }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h index 66b9ca2f..9278a0a3 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h @@ -27,12 +27,13 @@ namespace SHADE void DrawMenuBar() const noexcept; ImRect RecursivelyDrawEntityNode(SHSceneNode* const); void CreateChildEntity(EntityID parentEID) const noexcept; - void ParentSelectedEntities(EntityID parentEID, std::vector const& entities) const noexcept; + void ParentSelectedEntities(EntityID parentEID, std::vector const& entities) noexcept; void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID); void SelectAllEntities(); void CopySelectedEntities(); void PasteEntities(EntityID parentEID = MAX_EID); void DeleteSelectedEntities(); + std::vector CleanUpEIDList(std::vector const& entities); bool skipFrame = false; std::string filter; bool isAnyNodeSelected = false; diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2e55ea7a..46ffd3bf 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -68,10 +68,10 @@ namespace SHADE { if (!component) return; + const auto componentType = rttr::type::get(); ImGui::PushID(SHFamilyID::GetID()); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); - ImGui::PopID(); ImGui::SameLine(); if (ImGui::CollapsingHeader(componentType.get_name().data())) { @@ -216,6 +216,90 @@ namespace SHADE } } else DrawContextMenu(component); + ImGui::PopID(); + + } + + template<> + static void DrawComponent(SHRigidBodyComponent* component) + { + if(!component) + return; + ImGui::PushID(SHFamilyID::GetID()); + + const auto componentType = rttr::type::get(); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); + ImGui::SameLine(); + if (ImGui::CollapsingHeader(componentType.get_name().data())) + { + DrawContextMenu(component); + + SHRigidBodyComponent::Type rbType = component->GetType(); + + auto enumAlign = rttr::type::get().get_enumeration(); + auto names = enumAlign.get_names(); + std::vector list; + for (auto const& name : names) + list.push_back(name.data()); + SHEditorWidgets::ComboBox("Type", list, [component] {return static_cast(component->GetType()); }, [component, enumAlign](int const& idx) + { + auto values = enumAlign.get_values(); + auto it = std::next(values.begin(), idx); + component->SetType((*it).convert()); + }, "RigidBody Type"); + + + if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields + { + SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity"); + SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass"); + } + if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields + { + SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag"); + SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag"); + + SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate"); + + SHEditorWidgets::BeginPanel(std::format("{} Constraints", ICON_FA_LOCK).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); + + SHEditorWidgets::TextLabel("Freeze Position"); + SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezePositionX(); }, [component](bool const& value) {component->SetFreezePositionX(value); }, "Freeze Position - X"); ImGui::SameLine(); + SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezePositionY(); }, [component](bool const& value) {component->SetFreezePositionY(value); }, "Freeze Position - Y"); ImGui::SameLine(); + SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezePositionZ(); }, [component](bool const& value) {component->SetFreezePositionZ(value); }, "Freeze Position - Z"); + + SHEditorWidgets::TextLabel("Freeze Rotation"); + SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezeRotationX(); }, [component](bool const& value) {component->SetFreezeRotationX(value); }, "Freeze Rotation - X"); ImGui::SameLine(); + SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezeRotationY(); }, [component](bool const& value) {component->SetFreezeRotationY(value); }, "Freeze Rotation - Y"); ImGui::SameLine(); + SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezeRotationZ(); }, [component](bool const& value) {component->SetFreezeRotationZ(value); }, "Freeze Rotation - Z"); + + SHEditorWidgets::EndPanel(); + } + + //Debug Info (Read-Only) + if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields + { + SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields + { + SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + SHEditorWidgets::DragVec3("Angular\nVelocity", { "X", "Y", "Z" }, [component] {return component->GetAngularVelocity(); }, [](SHVec3 const& value) {}, false, "Angular Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + } + if (rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields + { + SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); + SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep"); + } + } + + } + else + { + DrawContextMenu(component); + } + ImGui::PopID(); } template<> @@ -223,6 +307,7 @@ namespace SHADE { if (!component) return; + ImGui::PushID(SHFamilyID::GetID()); const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); @@ -246,7 +331,7 @@ namespace SHADE if (collider->GetType() == SHCollisionShape::Type::BOX) { SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* BOX = reinterpret_cast(collider->GetShape()); + const auto* BOX = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragVec3 ( "Half Extents", { "X", "Y", "Z" }, @@ -256,7 +341,7 @@ namespace SHADE else if (collider->GetType() == SHCollisionShape::Type::SPHERE) { SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* SPHERE = reinterpret_cast(collider->GetShape()); + const auto* SPHERE = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragFloat ( "Radius", @@ -275,21 +360,12 @@ namespace SHADE [&collider] { auto offset = collider->GetRotationOffset(); - offset.x = SHMath::RadiansToDegrees(offset.x); - offset.y = SHMath::RadiansToDegrees(offset.y); - offset.z = SHMath::RadiansToDegrees(offset.z); return offset; }, [&collider](SHVec3 const& vec) { - const SHVec3 vecInRad - { - SHMath::DegreesToRadians(vec.x) - , SHMath::DegreesToRadians(vec.y) - , SHMath::DegreesToRadians(vec.z) - }; - collider->SetRotationOffset(vecInRad); - }); + collider->SetRotationOffset(vec); + }, true); SHEditorWidgets::EndPanel(); } @@ -322,6 +398,7 @@ namespace SHADE } } else DrawContextMenu(component); + ImGui::PopID(); } template<> @@ -329,6 +406,7 @@ namespace SHADE { if (!component) return; + ImGui::PushID(SHFamilyID::GetID()); const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); @@ -352,6 +430,7 @@ namespace SHADE { DrawContextMenu(component); } + ImGui::PopID(); } template<> @@ -359,6 +438,7 @@ namespace SHADE { if (!component) return; + ImGui::PushID(SHFamilyID::GetID()); const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); @@ -367,27 +447,39 @@ namespace SHADE DrawContextMenu(component); Handle const& mesh = component->GetMesh(); Handle const& mat = component->GetMaterial(); - - SHEditorWidgets::DragDropReadOnlyField("Mesh", std::to_string(SHResourceManager::GetAssetID(mesh).value_or(0)).data(), [component]() + const auto MESH_NAME = SHResourceManager::GetAssetName(mesh).value_or(""); + SHEditorWidgets::DragDropReadOnlyField("Mesh", MESH_NAME, [component]() { Handle const& mesh = component->GetMesh(); return SHResourceManager::GetAssetID(mesh).value_or(0); }, [component](AssetID const& id) { + if(SHAssetManager::GetType(id) != AssetType::MESH) + { + SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!") + return; + } component->SetMesh(SHResourceManager::LoadOrGet(id)); SHResourceManager::FinaliseChanges(); }, SHDragDrop::DRAG_RESOURCE); - SHEditorWidgets::DragDropReadOnlyField("Material", mat ? std::to_string(SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]() - { - Handle const& mat = component->GetMaterial(); - if(!mat) - return static_cast(0); - return SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0); - }, + const auto MAT_NAME = mat ? SHResourceManager::GetAssetName(mat->GetBaseMaterial()).value_or("") : ""; + SHEditorWidgets::DragDropReadOnlyField("Material", MAT_NAME, + [component]() + { + Handle const& mat = component->GetMaterial(); + if (!mat) + return static_cast(0); + return SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0); + }, [component](AssetID const& id) { + if (SHAssetManager::GetType(id) != AssetType::MATERIAL) + { + SHLOG_WARNING("Attempted to assign non material asset to Renderable Mesh property!") + return; + } auto gfxSystem = SHSystemManager::GetSystem(); component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet(id))); }, SHDragDrop::DRAG_RESOURCE); @@ -396,5 +488,6 @@ namespace SHADE { DrawContextMenu(component); } + ImGui::PopID(); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp index 13ecb9fa..88de7b73 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp @@ -78,7 +78,26 @@ namespace SHADE ImGui::BeginDisabled(!isDirty); if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data())) { - //save + auto gfxSystem = SHSystemManager::GetSystem(); + // Replace Material if it's been instantiated + auto matHandle = SHResourceManager::Get(currentViewedMaterial); + if (matHandle) + { + // - Get Shader Modules + auto vertShader = SHResourceManager::LoadOrGet(currentMatSpec->vertexShader); + auto fragShader = SHResourceManager::LoadOrGet(currentMatSpec->fragShader); + if (vertShader && fragShader && gfxSystem) + { + // - Retrieve pipeline from pipeline library + auto renderPass = gfxSystem->GetPrimaryRenderpass(); + auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName); + auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass); + // - Set Pipeline + matHandle->SetPipeline(pipeline); + } + } + + // Save Properties if(auto matAsset = SHAssetManager::GetData(currentViewedMaterial)) { YAML::Emitter out; @@ -102,7 +121,20 @@ namespace SHADE currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); break; case SHADE::SHShaderBlockInterface::Variable::Type::INT: - currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); + { + Handle texture = SHResourceManager::LoadOrGet(PROP_NODE.as()); + // HACK: Need to split this out to a separate pass before loading the materials and subsequently, the scenes + gfxSystem->BuildTextures(); + if (texture) + { + matHandle->SetProperty(VARIABLE->offset, texture->TextureArrayIndex); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid texture! Setting to 0."); + matHandle->SetProperty(VARIABLE->offset, 0); + } + } break; case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); @@ -136,12 +168,38 @@ namespace SHADE { /*if(!shaderModule) return;*/ - auto gfxSystem = SHSystemManager::GetSystem(); - auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface(); //auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA); - int const varCount = static_cast(interface->GetVariableCount()); + // Shader + bool shaderChanged = false; + const auto* SHADER_INFO = SHAssetManager::GetData(currentMatSpec->fragShader); + const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader"; + ImGui::BeginDisabled(); + isDirty |= SHEditorWidgets::DragDropReadOnlyField + ( + "Fragment Shader", SHADER_NAME.data(), + [this]() { return currentMatSpec->fragShader; }, + [this](const AssetID& id) { currentMatSpec->fragShader = id; }, + SHDragDrop::DRAG_RESOURCE + ); + ImGui::EndDisabled(); + // Load the shader to access it's data + auto fragShader = SHResourceManager::LoadOrGet(currentMatSpec->fragShader); + if (!fragShader) + return; + + // Get interface for the shader combination + auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA + ); + if (!interface) + return; + + // Properties + int const varCount = static_cast(interface->GetVariableCount()); for (int i = 0; i < varCount; ++i) { auto variable = interface->GetVariable(i); diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 223f9b83..2912a0bc 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -35,7 +35,7 @@ namespace SHADE constexpr ImGuiWindowFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode; - //#==============================================================# + //#==============================================================# //|| Public Member Functions || //#==============================================================# SHEditorMenuBar::SHEditorMenuBar() @@ -221,13 +221,20 @@ namespace SHADE ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY); if(ImGui::SmallButton(ICON_MD_PLAY_ARROW)) { - if(editor->SaveScene()) + if(editor->editorState == SHEditor::State::STOP) + { + if (editor->SaveScene()) + { + editor->Play(); + } + } + else { editor->Play(); } } ImGui::EndDisabled(); - ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE); + ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP || editor->editorState == SHEditor::State::PAUSE); if(ImGui::SmallButton(ICON_MD_PAUSE)) { editor->Pause(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h index 9e6dd3f4..60730f0e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h @@ -3,7 +3,7 @@ #include #include #include "SHEditorWindow.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" namespace SHADE { diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index d0b32ff5..93f4a615 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -14,6 +14,7 @@ #include "Camera/SHCameraSystem.h" #include "FRC/SHFramerateController.h" +#include "../../SHEditorWidgets.hpp" constexpr std::string_view windowName = "\xef\x80\x95 Viewport"; @@ -85,7 +86,7 @@ namespace SHADE shouldUpdateCamArm = ImGui::IsWindowHovered() && ImGui::IsKeyDown(ImGuiKey_LeftAlt) && ImGui::IsMouseDown(ImGuiMouseButton_Left); - if (editor->editorState != SHEditor::State::PLAY && ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) + if (editor->editorState != SHEditor::State::PLAY && !ImGui::IsAnyItemActive() && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) { if (ImGui::IsKeyReleased(ImGuiKey_W)) { @@ -151,7 +152,7 @@ namespace SHADE if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::BeginTooltip(); - ImGui::Text("Translate [Q]"); + ImGui::Text("Translate [W]"); ImGui::EndTooltip(); } if (isTranslate) @@ -169,7 +170,7 @@ namespace SHADE if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::BeginTooltip(); - ImGui::Text("Rotate [W]"); + ImGui::Text("Rotate [E]"); ImGui::EndTooltip(); } if (isRotate) @@ -187,12 +188,19 @@ namespace SHADE if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::BeginTooltip(); - ImGui::Text("Scale [E]"); + ImGui::Text("Scale [R]"); ImGui::EndTooltip(); } if (isScale) ImGui::PopStyleColor(); ImGui::EndDisabled(); + + auto camSystem = SHSystemManager::GetSystem(); + auto editorCamera = camSystem->GetEditorCamera(); + //ImGui::SetNextItemWidth(10.0f); + SHEditorWidgets::SliderFloat("CamSpeed", 0.0f, 5.0f, [editorCamera] {return editorCamera->movementSpeed; }, [editorCamera](float const& value) {editorCamera->movementSpeed = value; }); + SHEditorWidgets::DragVec3("TurnSpeed", { "X", "Y", "Z" }, [editorCamera] {return editorCamera->turnSpeed; }, [editorCamera](SHVec3 const& value) {editorCamera->turnSpeed = value; }); + ImGui::EndMenuBar(); } } diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 077c7025..7372f227 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -10,7 +10,7 @@ //#==============================================================# //|| SHADE Includes || //#==============================================================# -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Tools/SHException.h" #include "ECS_Base/Managers/SHSystemManager.h" diff --git a/SHADE_Engine/src/Editor/SHEditor.h b/SHADE_Engine/src/Editor/SHEditor.h index 5897c8b7..0a485109 100644 --- a/SHADE_Engine/src/Editor/SHEditor.h +++ b/SHADE_Engine/src/Editor/SHEditor.h @@ -15,7 +15,7 @@ #include "ECS_Base/System/SHSystemRoutine.h" #include "Resource/SHHandle.h" #include "EditorWindow/SHEditorWindow.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" #include "Gizmos/SHTransformGizmo.h" #include "Events/SHEventDefines.h" #include "Events/SHEvent.h" diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 0855d68d..2681e916 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -166,14 +166,14 @@ namespace SHADE const ImGuiWindow* const window = ImGui::GetCurrentWindow(); if (window->SkipItems) return false; - + static constexpr float defaultLabelColWidth = 80.0f; const ImGuiContext& g = *GImGui; bool valueChanged = false; ImGui::BeginGroup(); ImGui::PushID(label.c_str()); PushMultiItemsWidthsAndLabels(componentLabels, 0.0f); ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); - ImGui::SetColumnWidth(-1, 80.0f); + ImGui::SetColumnWidth(-1, defaultLabelColWidth); ImGui::Text(label.c_str()); if (isHovered) *isHovered |= ImGui::IsItemHovered(); @@ -219,7 +219,7 @@ namespace SHADE } bool const changed = DragN(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; - if (changed) + if (!(flags & ImGuiSliderFlags_ReadOnly) && changed) { if(isAnAngleInRad) { @@ -255,7 +255,7 @@ namespace SHADE bool isHovered = false; bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags, &isHovered); static bool startRecording = false; - if (changed) + if (!(flags & ImGuiSliderFlags_ReadOnly) && changed) { SHVec3 old = get(); if(isAnAngleInRad) @@ -293,7 +293,7 @@ namespace SHADE } bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; - if (changed) + if (!(flags & ImGuiSliderFlags_ReadOnly) && changed) { if(isAnAngleInRad) { @@ -422,7 +422,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - bool changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr); + bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr); if(SHDragDrop::BeginTarget()) { if(T* payload = SHDragDrop::AcceptPayload(dragDropTag)) @@ -454,7 +454,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + const bool hasChange = ImGui::DragScalar("##dragScalar", data_type, &value, speed, &p_min, &p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -487,7 +487,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags); + const bool hasChange = ImGui::DragFloat("##dragFloat", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -520,7 +520,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags); + const bool hasChange = ImGui::DragInt("##dragInt", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -553,7 +553,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags); + bool const hasChange = ImGui::SliderScalar("##sliderScalar", data_type, &value, &min, &max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -587,7 +587,8 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags); + ImGui::SetNextItemWidth(ImGui::CalcTextSize(displayFormat).x + ImGui::GetStyle().ItemInnerSpacing.x * 2.0f); + bool const hasChange = ImGui::SliderFloat("##sliderFloat", &value, min, max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -621,7 +622,7 @@ namespace SHADE ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); - bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags); + bool const hasChange = ImGui::SliderInt("##sliderInt", &value, min, max, displayFormat, flags); static bool startRecording = false; if (hasChange) { diff --git a/SHADE_Engine/src/FRC/SHFramerateController.cpp b/SHADE_Engine/src/FRC/SHFramerateController.cpp index 0791d628..02e0f430 100644 --- a/SHADE_Engine/src/FRC/SHFramerateController.cpp +++ b/SHADE_Engine/src/FRC/SHFramerateController.cpp @@ -12,11 +12,11 @@ //TODO Legacy code. Delete soon +#include + #include #include -#include #include "SHFramerateController.h" -#include "../Tools/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index fa5f718e..a28f70ca 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -152,7 +152,10 @@ namespace SHADE bool found{ false }; for (auto const& asset : assets) { - assetCollection.emplace(asset.id, asset); + if (!assetCollection.contains(asset.id)) + { + assetCollection.emplace(asset.id, asset); + } if (file.name == asset.name) { AssetPath path{ file.path }; @@ -170,22 +173,6 @@ namespace SHADE toGenerate.push_back(&file); } } - //for (auto const& asset : assets) - //{ - // assetCollection.emplace(asset.id, asset); - // for(auto& file : folder->files) - // { - // if (file.name == asset.name) - // { - // AssetPath path{ file.path }; - // if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type) - // { - // file.assetMeta = &assetCollection[asset.id]; - // break; - // } - // } - // } - //} for (auto i {0}; i < folder->files.size(); ++i) { diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index cc35303b..05fd4288 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -3,7 +3,7 @@ #include "SHVkCommandPool.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "SHVkCommandPool.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Renderpass/SHVkRenderpass.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Pipeline/SHVkPipeline.h" diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp index 375ece4d..fc9769d9 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp @@ -3,7 +3,7 @@ #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Instance/SHVkInstance.h" #include "Resource/SHResourceLibrary.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Debugging/SHValidationLayersQuery.cpp b/SHADE_Engine/src/Graphics/Debugging/SHValidationLayersQuery.cpp index 420fa9e5..0dba5c5b 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHValidationLayersQuery.cpp +++ b/SHADE_Engine/src/Graphics/Debugging/SHValidationLayersQuery.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHValidationLayersQuery.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVkDebugMessenger.cpp b/SHADE_Engine/src/Graphics/Debugging/SHVkDebugMessenger.cpp index 3ca5c94d..fd7d55e9 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVkDebugMessenger.cpp +++ b/SHADE_Engine/src/Graphics/Debugging/SHVkDebugMessenger.cpp @@ -3,8 +3,8 @@ #include "SHVkDebugMessenger.h" #include "SHVulkanDebugUtil.h" #include "Graphics/Instance/SHVkInstance.h" -#include "Tools/SHLogger.h" -//#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" +//#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp index fd39da24..eea07ed6 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp +++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHVulkanDebugUtil.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h index c822829a..1e8d6a3e 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h @@ -38,11 +38,11 @@ namespace SHADE /// std::vector Limits = { - { vk::DescriptorType::eCombinedImageSampler, 100 }, - { vk::DescriptorType::eUniformBuffer, 100 }, - { vk::DescriptorType::eUniformBufferDynamic, 100 }, - { vk::DescriptorType::eStorageImage, 100}, - { vk::DescriptorType::eStorageBufferDynamic, 100 } + { vk::DescriptorType::eCombinedImageSampler, 1000 }, + { vk::DescriptorType::eUniformBuffer, 1000 }, + { vk::DescriptorType::eUniformBufferDynamic, 1000 }, + { vk::DescriptorType::eStorageImage, 1000 }, + { vk::DescriptorType::eStorageBufferDynamic, 1000 } }; /// /// Maximum number of descriptor sets allowed diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp index de68c583..adb51586 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp @@ -6,7 +6,7 @@ #include "SHVkDescriptorPool.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkSampler.h" diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp index 808ce750..272a838d 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -2,7 +2,7 @@ #include "SHVkLogicalDevice.h" #include "SHVkPhysicalDevice.h" #include "Graphics/Instance/SHVkInstance.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Windowing/Surface/SHVkSurface.h" #include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Commands/SHVkCommandPool.h" diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDevice.cpp index 53b352b7..1f40a533 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDevice.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp index 3cf0a8e6..050ca769 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp @@ -3,7 +3,7 @@ #include #include "SHVkPhysicalDeviceLibrary.h" #include "Graphics/Instance/SHVkInstance.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Framebuffer/SHVkFramebuffer.cpp b/SHADE_Engine/src/Graphics/Framebuffer/SHVkFramebuffer.cpp index 76e627d3..7a46c473 100644 --- a/SHADE_Engine/src/Graphics/Framebuffer/SHVkFramebuffer.cpp +++ b/SHADE_Engine/src/Graphics/Framebuffer/SHVkFramebuffer.cpp @@ -3,7 +3,7 @@ #include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImage.h" #include "Graphics/Renderpass/SHVkRenderpass.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Devices/SHVkLogicalDevice.h" namespace SHADE diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp index 33bed1b5..fa43cd53 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp @@ -2,7 +2,7 @@ #include "SHVkImage.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "SHVkImageView.h" #include "Graphics/Instance/SHVkInstance.h" #include "Graphics/Buffers/SHVkBuffer.h" diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImageView.cpp b/SHADE_Engine/src/Graphics/Images/SHVkImageView.cpp index 44b5718c..d07c66b7 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImageView.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkImageView.cpp @@ -2,7 +2,7 @@ #include "SHVkImageView.h" #include "SHVkImage.h" #include "Graphics/Devices/SHVkLogicalDevice.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp b/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp index edfe4b46..237c6fee 100644 --- a/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp +++ b/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp @@ -3,7 +3,7 @@ #include "Graphics/Debugging/SHValidationLayersQuery.h" #include "Graphics/Debugging/SHVkDebugMessenger.h" #include "Graphics/Devices/SHVkPhysicalDeviceLibrary.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Devices/SHVkPhysicalDeviceLibrary.h" //#include diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 1829096f..2a2b66d4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -43,6 +43,85 @@ namespace SHADE setAllDirtyFlags(); } + SHBatch::SHBatch(SHBatch&& rhs) + : device { rhs.device } + , pipeline { rhs.pipeline } + , referencedMatInstances { std::move(rhs.referencedMatInstances) } + , matBufferDirty { std::move(rhs.matBufferDirty) } + , subBatches { std::move(rhs.subBatches) } + , drawData { std::move(drawData) } + , transformData { std::move(rhs.transformData) } + , instancedIntegerData { std::move(rhs.instancedIntegerData) } + , matPropsData { std::move(rhs.matPropsData) } + , matPropsDataSize { rhs.matPropsDataSize } + , singleMatPropAlignedSize { rhs.singleMatPropAlignedSize } + , singleMatPropSize { rhs.singleMatPropSize } + , isCPUBuffersDirty { rhs.isCPUBuffersDirty } + , drawDataBuffer { rhs.drawDataBuffer } + , transformDataBuffer { rhs.transformDataBuffer } + , instancedIntegerBuffer { rhs.instancedIntegerBuffer } + , matPropsBuffer { rhs.matPropsBuffer } + , matPropsDescSet { rhs.matPropsDescSet } + { + rhs.drawDataBuffer = {}; + rhs.transformDataBuffer = {}; + rhs.instancedIntegerBuffer = {}; + rhs.matPropsBuffer = {}; + rhs.matPropsDescSet = {}; + } + + SHBatch& SHBatch::operator=(SHBatch&& rhs) + { + if (this == &rhs) + return *this; + + device = rhs.device ; + pipeline = rhs.pipeline ; + referencedMatInstances = std::move(rhs.referencedMatInstances); + matBufferDirty = std::move(rhs.matBufferDirty) ; + subBatches = std::move(rhs.subBatches) ; + drawData = std::move(drawData) ; + transformData = std::move(rhs.transformData) ; + instancedIntegerData = std::move(rhs.instancedIntegerData) ; + matPropsData = std::move(rhs.matPropsData) ; + matPropsDataSize = rhs.matPropsDataSize ; + singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ; + singleMatPropSize = rhs.singleMatPropSize ; + isCPUBuffersDirty = rhs.isCPUBuffersDirty ; + drawDataBuffer = rhs.drawDataBuffer ; + transformDataBuffer = rhs.transformDataBuffer ; + instancedIntegerBuffer = rhs.instancedIntegerBuffer ; + matPropsBuffer = rhs.matPropsBuffer ; + matPropsDescSet = rhs.matPropsDescSet ; + + // Unset values + rhs.drawDataBuffer = {}; + rhs.transformDataBuffer = {}; + rhs.instancedIntegerBuffer = {}; + rhs.matPropsBuffer = {}; + rhs.matPropsDescSet = {}; + + return *this; + } + + SHBatch::~SHBatch() + { + // Free GPU buffers + for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + if (drawDataBuffer[i]) + drawDataBuffer[i].Free(); + if (transformDataBuffer[i]) + transformDataBuffer[i].Free(); + if (instancedIntegerBuffer[i]) + instancedIntegerBuffer[i].Free(); + if (matPropsBuffer[i]) + matPropsBuffer[i].Free(); + if (matPropsDescSet[i]) + matPropsDescSet[i].Free(); + } + } + void SHBatch::Add(const SHRenderable* renderable) { // Ignore if null diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index c9dd4eda..dd4d33fd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -71,6 +71,11 @@ namespace SHADE /* Constructor/Destructors */ /*-----------------------------------------------------------------------------*/ SHBatch(Handle pipeline); + SHBatch(const SHBatch&) = delete; + SHBatch(SHBatch&& rhs); + SHBatch& operator=(const SHBatch&) = delete; + SHBatch& operator=(SHBatch&& rhs); + ~SHBatch(); /*-----------------------------------------------------------------------------*/ /* Usage Functions */ @@ -117,7 +122,7 @@ namespace SHADE std::unique_ptr matPropsData; Byte matPropsDataSize = 0; Byte singleMatPropAlignedSize = 0; - Byte singleMatPropSize = 0; + Byte singleMatPropSize = 0; bool isCPUBuffersDirty = true; // GPU Buffers TripleBuffer drawDataBuffer; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp index dc44e7f9..41aebeb6 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp @@ -22,7 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/Pipeline/SHVkPipeline.h" #include "ECS_Base/Managers/SHComponentManager.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index b827652e..6760d937 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -69,9 +69,9 @@ namespace SHADE batch->Remove(renderable); - // If batch is empty, remove batch - if (batch->IsEmpty()) - batches.erase(batch); + // TODO: If the pipeline is unloaded, we remove the batch + /*if (batch->IsEmpty() && !batch->GetPipeline()) + batches.erase(batch);*/ } void SHSuperBatch::Clear() noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index de42d9a3..28333820 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -5,7 +5,7 @@ #include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/MiddleEnd/Lights/SHLightData.h" -#include "Tools/SHUtilities.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 15c8ec5d..ff265c49 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -570,13 +570,6 @@ namespace SHADE return; } - // Finalise all batches - for (auto vp : viewports) - for (auto renderer : vp->GetRenderers()) - { - renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool); - } - // Resize auto windowDims = window->GetWindowSize(); if (renderContext.GetResizeAndReset()) @@ -591,6 +584,13 @@ namespace SHADE // #BackEndTest: For for the fence initialized by queue submit renderContext.WaitForFence(); + // Finalise all batches + for (auto vp : viewports) + for (auto renderer : vp->GetRenderers()) + { + renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool); + } + // #BackEndTest: Acquire the next image in the swapchain available renderContext.AcquireNextIamge(); const uint32_t CURR_FRAME_IDX_2 = renderContext.GetCurrentFrame(); @@ -602,8 +602,6 @@ namespace SHADE if (currFrameData.cmdPoolHdls.empty()) throw std::runtime_error("No command pools available!"); currFrameData.cmdPoolHdls[0]->Reset(); - - } /***************************************************************************/ @@ -710,6 +708,11 @@ namespace SHADE return resourceManager.Create(materialInst->GetBaseMaterial()); } + std::pair, typename SHResourceHub::dense_iterator> SHGraphicsSystem::GetAllMaterialInstances() + { + return resourceManager.GetDenseAccess(); + } + void SHGraphicsSystem::RemoveMaterialInstance(Handle materialInstance) { resourceManager.Free(materialInstance); @@ -807,7 +810,7 @@ namespace SHADE void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept { - SHResourceManager::FinaliseChanges(); + // Begin rendering reinterpret_cast(system)->BeginRender(); } @@ -833,8 +836,38 @@ namespace SHADE void SHGraphicsSystem::EndRoutine::Execute(double) noexcept { reinterpret_cast(system)->EndRender(); + + // Reset all material isDirty + auto gfxSystem = reinterpret_cast(system); + auto [matBegin, matEnd] = gfxSystem->resourceManager.GetDenseAccess(); + for (auto iter = matBegin; iter != matEnd; ++iter) + { + iter->ClearChangeFlag(); + } } - + + SHGraphicsSystem::PrepareRenderRoutine::PrepareRenderRoutine() + : SHSystemRoutine("Graphics System Pre-Render", true) + {} + + void SHGraphicsSystem::PrepareRenderRoutine::Execute(double) noexcept + { + // Finish up, loading, unloading any resources + SHResourceManager::FinaliseChanges(); + + // Clean up and update all materials + auto gfxSystem = reinterpret_cast(system); + auto [matInstBegin, matInstEnd] = gfxSystem->resourceManager.GetDenseAccess(); + for (auto iter = matInstBegin; iter != matInstEnd; ++iter) + { + auto baseMat = iter->GetBaseMaterial(); + if (baseMat && baseMat->HasPipelineChanged()) + { + iter->ResetProperties(); + } + } + } + /*-----------------------------------------------------------------------------------*/ /* System Routine Functions - BatcherDispatcherRoutine */ /*-----------------------------------------------------------------------------------*/ @@ -844,11 +877,14 @@ namespace SHADE void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept { - auto& renderables = SHComponentManager::GetDense(); + auto& renderables = SHComponentManager::GetDense(); for (auto& renderable : renderables) { + // Check if the material instance is now unused + renderable.CleanUpMaterials(); + if (!renderable.HasChanged()) - continue; + continue; // Remove from the SuperBatch it is previously in (prevMat if mat has changed) Handle prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial(); @@ -857,9 +893,8 @@ namespace SHADE Handle oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); oldSuperBatch->Remove(&renderable); } - - // Add to new SuperBatch if there is a material - // Add to new SuperBatch if there is a material and a mesh to render + + // Add to new SuperBatch if there is a material and a mesh to render Handle newMatInstance = renderable.GetMaterial(); if (newMatInstance && renderable.GetMesh()) { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index a5a5ada0..2a186041 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -95,25 +95,31 @@ namespace SHADE class SH_API BeginRoutine final : public SHSystemRoutine { public: - BeginRoutine(); + BeginRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API RenderRoutine final : public SHSystemRoutine { public: - RenderRoutine(); + RenderRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API EndRoutine final : public SHSystemRoutine { public: - EndRoutine(); + EndRoutine(); + virtual void Execute(double dt) noexcept override final; + }; + class SH_API PrepareRenderRoutine final : public SHSystemRoutine + { + public: + PrepareRenderRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine { public: - BatcherDispatcherRoutine(); + BatcherDispatcherRoutine(); virtual void Execute(double dt) noexcept override final; }; @@ -156,6 +162,7 @@ namespace SHADE Handle AddOrGetBaseMaterialInstance(); Handle AddOrGetBaseMaterialInstance(Handle material); Handle AddMaterialInstanceCopy(Handle materialInst); + std::pair, typename SHResourceHub::dense_iterator> GetAllMaterialInstances(); void RemoveMaterialInstance(Handle materialInstance); Handle GetDefaultMaterial() { return defaultMaterial; } Handle GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); } @@ -166,10 +173,10 @@ namespace SHADE /*******************************************************************************/ /*! - \brief - Adds a mesh to the Mesh Library. But this does not mean that the meshes have - been added yet. A call to "BuildBuffers()" is required to transfer all - meshes into the GPU. + \brief + Adds a mesh to the Mesh Library. But this does not mean that the meshes have + been added yet. A call to "BuildBuffers()" is required to transfer all + meshes into the GPU. \param vertexCount Number of vertices in this Mesh. diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp index b27f48b9..7ca7c394 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp @@ -6,91 +6,109 @@ #include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h" #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "SHGraphicsSystem.h" +#include "SHMaterialInstance.h" namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Pipeline Functions */ - /*---------------------------------------------------------------------------------*/ - void SHMaterial::SetPipeline(Handle _pipeline) - { - pipeline = _pipeline; + /*-----------------------------------------------------------------------------------*/ + /* Pipeline Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::SetPipeline(Handle _pipeline) + { + // Reassignment, we ignore + if (_pipeline == pipeline) + return; - // Set up properties based on the pipeline - if (!pipeline) - { - // Clear memory and all that - propMemory.reset(); - return; - } + pipeline = _pipeline; - // Allocate memory for properties - const Handle SHADER_INFO = GetShaderBlockInterface(); - propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; - if (propMemorySize <= 0) - { - propMemory.reset(); - } - else - { - propMemory.reset(new char[propMemorySize]); - } - ResetProperties(); - } - - Handle SHMaterial::GetPipeline() const - { - return pipeline; - } - - /*---------------------------------------------------------------------------------*/ - /* Property Functions */ - /*---------------------------------------------------------------------------------*/ - void SHMaterial::ResetProperties() + // Set up properties based on the pipeline + if (pipeline) { - // Reset all the properties to default values - if (propMemory) - memset(propMemory.get(), 0, propMemorySize); + // Allocate memory for properties + const Handle SHADER_INFO = GetShaderBlockInterface(); + propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; + if (propMemorySize <= 0) + { + propMemory.reset(); + } + else + { + propMemory.reset(new char[propMemorySize]); + } + } + + // Reset since pipeline changed + ResetProperties(); - // Initialize Vectors to all 1.0 by default - const Handle SHADER_INFO = GetShaderBlockInterface(); - for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i) - { - const auto& VAR = SHADER_INFO->GetVariable(i); - switch (VAR->type) - { - case SHShaderBlockInterface::Variable::Type::VECTOR3: - setPropertyUnsafe(VAR->offset, SHVec3::One); - break; - case SHShaderBlockInterface::Variable::Type::VECTOR4: - setPropertyUnsafe(VAR->offset, SHVec4::One); - break; - } - } + // Mark changed so that we know to update dependent material instances + propertiesChanged = true; + } + + Handle SHMaterial::GetPipeline() const + { + return pipeline; + } + + /*-----------------------------------------------------------------------------------*/ + /* Property Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::ResetProperties() + { + // Reset all the properties to default values + if (propMemory) + memset(propMemory.get(), 0, propMemorySize); + + // Initialize Vectors to all 1.0 by default + const Handle SHADER_INFO = GetShaderBlockInterface(); + for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i) + { + const auto& VAR = SHADER_INFO->GetVariable(i); + switch (VAR->type) + { + case SHShaderBlockInterface::Variable::Type::VECTOR3: + setPropertyUnsafe(VAR->offset, SHVec3::One); + break; + case SHShaderBlockInterface::Variable::Type::VECTOR4: + setPropertyUnsafe(VAR->offset, SHVec4::One); + break; + } } - void SHMaterial::ExportProperties(void* dest) const noexcept - { - if (propMemory) - memcpy(dest, propMemory.get(), propMemorySize); - } + propertiesChanged = true; + } - size_t SHMaterial::GetPropertiesMemorySize() const noexcept - { - const Handle SHADER_INFO = GetShaderBlockInterface(); - return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; - } + void SHMaterial::ExportProperties(void* dest) const noexcept + { + if (propMemory) + memcpy(dest, propMemory.get(), propMemorySize); + } - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ - Handle SHMaterial::GetShaderBlockInterface() const noexcept - { - return pipeline->GetPipelineLayout()->GetShaderBlockInterface - ( - SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, - SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, - vk::ShaderStageFlagBits::eFragment - ); - } + size_t SHMaterial::GetPropertiesMemorySize() const noexcept + { + const Handle SHADER_INFO = GetShaderBlockInterface(); + return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ + Handle SHMaterial::GetShaderBlockInterface() const noexcept + { + return pipeline->GetPipelineLayout()->GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, + vk::ShaderStageFlagBits::eFragment + ); + } + + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::ClearChangeFlag() noexcept + { + propertiesChanged = false; + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h index 964f9e34..c75692f2 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h @@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Resource/SHHandle.h" #include "SHCommonTypes.h" +#include "SH_API.h" namespace SHADE { @@ -35,7 +36,7 @@ namespace SHADE Describes a Pipeline along with it's associated properties for this instance. */ /***********************************************************************************/ - class SHMaterial + class SH_API SHMaterial : public ISelfHandle { public: /*-----------------------------------------------------------------------------*/ @@ -67,6 +68,10 @@ namespace SHADE /* Query Functions */ /*-----------------------------------------------------------------------------*/ Handle GetShaderBlockInterface() const noexcept; + bool HasPipelineChanged() const noexcept { return pipelineChanged; } + bool HasPropertiesChanged() const noexcept { return propertiesChanged; } + bool HasChanged() const noexcept { return pipelineChanged || propertiesChanged; } + void ClearChangeFlag() noexcept; private: /*-----------------------------------------------------------------------------*/ @@ -75,6 +80,8 @@ namespace SHADE Handle pipeline; std::unique_ptr propMemory; Byte propMemorySize = 0; + bool propertiesChanged = true; + bool pipelineChanged = true; /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp index f81cfa5c..880fba69 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp @@ -33,8 +33,7 @@ namespace SHADE } // Get offset and modify the memory directly - T* dataPtr = reinterpret_cast(propMemory.get() + PROP_INFO->offset); - *dataPtr = value; + setPropertyUnsafe(PROP_INFO->offset, value); } template @@ -85,6 +84,12 @@ namespace SHADE template void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value) { + // Size check + if (memOffset + sizeof(T) > propMemorySize) + { + throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory"); + } (*reinterpret_cast(propMemory.get() + memOffset)) = value; + propertiesChanged = true; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp index 350580bf..7526538f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #include "SHGraphicsConstants.h" #include "SHMaterial.h" #include "Graphics/Pipeline/SHVkPipeline.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { @@ -31,11 +31,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ void SHMaterialInstance::ResetProperties() noexcept { - // Reset all the properties to default values memset(dataStore.get(), 0, dataStoreSize); overrideData.clear(); dataStore.reset(); + dataWasChanged = true; } void SHMaterialInstance::ExportProperties(void* dest) @@ -65,9 +65,17 @@ namespace SHADE dataWasChanged = false; } - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + bool SHMaterialInstance::HasChanged() const noexcept + { + return dataWasChanged || (baseMaterial && baseMaterial->HasChanged()); + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ Handle SHMaterialInstance::getShaderBlockInterface() const noexcept { return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h index b6fcc830..57e3dfce 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h @@ -43,9 +43,9 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ struct OverrideData { - size_t Index; - size_t DataSize; - size_t StoredDataOffset; + uint32_t Index; + uint32_t DataSize; + uint32_t StoredDataOffset; }; /*-----------------------------------------------------------------------------*/ @@ -69,7 +69,8 @@ namespace SHADE /* Getter Functions */ /*-----------------------------------------------------------------------------*/ Handle GetBaseMaterial() const noexcept { return baseMaterial; } - bool HasChanged() const noexcept { return dataWasChanged; } + bool HasChanged() const noexcept; + bool IsBlank() const noexcept { return overrideData.empty(); } // No overrides private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp index e70631ea..7bd1c106 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp @@ -11,6 +11,7 @@ of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ #pragma once #include "SHMaterialInstance.h" +#include "SHMaterial.h" namespace SHADE { @@ -34,26 +35,45 @@ namespace SHADE dataStore.reset(new char[dataStoreSize]); } - OverrideData od; - od.Index = SHADER_INFO->GetVariableIndex(key); - od.DataSize = sizeof(T); - if (overrideData.empty()) + // Check if this was stored before + const uint32_t VAR_IDX = SHADER_INFO->GetVariableIndex(key); + auto existingOverride = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& od) { - od.StoredDataOffset = 0; - } - else + return od.Index == VAR_IDX; + }); + + // Otherwise, create it + if (existingOverride == overrideData.end()) { - const OverrideData& lastInsertedData = overrideData.back(); - od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize; + OverrideData od; + od.Index = VAR_IDX; + od.DataSize = sizeof(T); + + if (overrideData.empty()) + { + od.StoredDataOffset = 0; + } + else + { + const OverrideData& lastInsertedData = overrideData.back(); + od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize; + } + + // Size check + if (od.StoredDataOffset + sizeof(T) > dataStoreSize) + { + throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory"); + } + + // Save the override data information + overrideData.emplace_back(std::move(od)); + existingOverride = overrideData.end() - 1; } // Get offset and modify the memory directly - T* dataPtr = reinterpret_cast(dataStore.get() + od.StoredDataOffset); + T* dataPtr = reinterpret_cast(dataStore.get() + existingOverride->StoredDataOffset); *dataPtr = value; - - // Save the override data information - overrideData.emplace_back(std::move(od)); - + // Flag dataWasChanged = true; } @@ -70,11 +90,22 @@ namespace SHADE // Search Override Data for the property uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key); auto prop = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& data) - { - return PROP_IDX == data.Index; - }); + { + return PROP_IDX == data.Index; + }); + + // No overrides, we get from the base material instead if (prop == overrideData.end()) - throw std::invalid_argument("Attempted to get an property that was not set previously!"); + { + if (baseMaterial) + { + return baseMaterial->GetProperty(key); + } + else + { + throw std::invalid_argument("Attempted to get an property that was not set previously!"); + } + } // Get offset and return the memory directly T* dataPtr = reinterpret_cast(dataStore.get() + prop->StoredDataOffset); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 57762324..e22de5ab 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -34,8 +34,11 @@ namespace SHADE void SHRenderable::OnDestroy() { // Remove from SuperBatch - Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); - superBatch->Remove(this); + if (sharedMaterial) + { + Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + superBatch->Remove(this); + } // Free resources if (material) @@ -88,11 +91,20 @@ namespace SHADE { SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); material = gfxSystem->AddMaterialInstanceCopy(sharedMaterial); + matChanged = true; } return material; } + void SHRenderable::CleanUpMaterials() noexcept + { + if (material && material->IsBlank()) + { + SetMaterial(sharedMaterial); + } + } + /*-----------------------------------------------------------------------------------*/ /* Mesh Functions */ /*-----------------------------------------------------------------------------------*/ @@ -111,6 +123,20 @@ namespace SHADE return lightLayer; } + bool SHRenderable::HasChanged() const noexcept + { + if (matChanged || meshChanged) + return true; + + // If the underlying material has changed + auto mat = GetMaterial(); + if (mat) + { + return mat->HasChanged(); + } + return false; + } + /*-----------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 8893c43b..f1455ef4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -53,6 +53,10 @@ namespace SHADE Handle GetModifiableMaterial(); Handle GetPrevMaterial() const noexcept { return oldMaterial; } bool HasMaterialChanged() const noexcept { return matChanged; } + /// + /// Clears the modifiable material if it is unused. + /// + void CleanUpMaterials() noexcept; /*-------------------------------------------------------------------------------*/ /* Mesh Functions */ @@ -70,7 +74,7 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-------------------------------------------------------------------------------*/ - bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed + bool HasChanged() const noexcept; // Whether or not the mesh or material has changed void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this private: diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp index df9e244e..7bd0049f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Commands/SHVkCommandBuffer.h" #include "Graphics/Instance/SHVkInstance.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "SHRenderer.h" #include "Resource/SHResourceLibrary.h" #include "Graphics/RenderGraph/SHRenderGraph.h" diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 51eaf5f1..2949ad43 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -1,7 +1,7 @@ #include "SHpch.h" #include "SHLightingSubSystem.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" -#include "Tools/SHUtilities.h" +#include "Tools/Utilities/SHUtilities.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp index 1d24d6f7..b12ac75d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHRenderContext.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Swapchain/SHVkSwapchain.h" diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp index 495a3d37..05bd8813 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp @@ -34,7 +34,7 @@ namespace SHADE { colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState { - .blendEnable = SHVkUtil::IsBlendCompatible (subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false, + .blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)), .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, .colorBlendOp = vk::BlendOp::eAdd, diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp index b92ccddf..dfb3f3b9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp @@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Commands/SHVkCommandBuffer.h" #include "Graphics/SHVkUtil.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Images/SHVkImage.h" diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp index 47b2e010..589e66d2 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp @@ -2,7 +2,7 @@ #include "SHVkPipelineLayout.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Shaders/SHVkShaderModule.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Instance/SHVkInstance.h" namespace SHADE diff --git a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp index dcb3ff6a..4d8b0d76 100644 --- a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp +++ b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHVkQueue.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Synchronization/SHVkSemaphore.h" #include "Graphics/Synchronization/SHVkFence.h" diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 500bcf04..e798bfe7 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -7,7 +7,7 @@ #include "Graphics/Images/SHVkImageView.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Buffers/SHVkBuffer.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "SHAttachmentDescInitParams.h" #include "SHRenderGraphStorage.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" @@ -129,11 +129,11 @@ namespace SHADE for (auto& predResource : prereq->attResources) { // if a predecessor's resource is used by this node, we want to copy the final layout from the pred to the initial of this node - if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping.contains(resourceID)) + if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping->contains(resourceID)) { // Get the resource's attachment index in BOTH the predecessor and the current node - uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping[resourceID]; - uint32_t resourceAttIndex = node->resourceAttachmentMapping[resourceID]; + uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping->at(resourceID); + uint32_t resourceAttIndex = node->resourceAttachmentMapping->at(resourceID); // Use the resource attachment index to get the attachment description in the renderpass auto& attDesc = node->attachmentDescriptions[resourceAttIndex]; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index b3b5b58b..3f6be1d9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -124,7 +124,7 @@ namespace SHADE , framebuffers{} , prereqNodes{ std::move(predecessors) } , attachmentDescriptions{} - , resourceAttachmentMapping{} + , resourceAttachmentMapping { new std::unordered_map } , attResources{ } , subpasses{} , executed{ false } @@ -163,7 +163,7 @@ namespace SHADE if (attResources[i]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) containsSwapchainImage = true; - resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i); + resourceAttachmentMapping->try_emplace(attResources[i].GetId().Raw, i); } if (!containsSwapchainImage) @@ -254,7 +254,7 @@ namespace SHADE ( subpassName, graphStorage, GetHandle(), static_cast(subpasses.size()), - &resourceAttachmentMapping + resourceAttachmentMapping.get() ) ); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index 4fdac45c..299578f2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -60,7 +60,7 @@ namespace SHADE std::vector spDeps; //! For indexing resources fast - std::unordered_map resourceAttachmentMapping; + std::unique_ptr> resourceAttachmentMapping; //! For indexing subpasses std::map subpassIndexing; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 2ed84d92..dfa5977b 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -97,7 +97,7 @@ namespace SHADE colorReferences = std::move(rhs.colorReferences); depthReferences = std::move(rhs.depthReferences); inputReferences = std::move(rhs.inputReferences); - resourceAttachmentMapping = rhs.resourceAttachmentMapping; + resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); descriptorSetLayout = rhs.descriptorSetLayout; exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); graphStorage = rhs.graphStorage; diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index a9ac543f..3a405e0d 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -86,8 +86,16 @@ namespace SHADE { if (bufferHandle) { - // Resize - bufferHandle->ResizeReplace(size, src, size); + // Resize if we need to resize + if (bufferHandle->GetSizeStored() < size) + { + bufferHandle->ResizeReplace(size, src, size); + } + // Otherwise just copy the data over + else + { + bufferHandle->MapWriteUnmap(src, size, 0, 0); + } } else { @@ -113,8 +121,16 @@ namespace SHADE { if (bufferHandle) { - // Resize - bufferHandle->ResizeReplace(size, src, size); // TODO: Set to host visible method? + // Resize if we need to resize + if (bufferHandle->GetSizeStored() < size) + { + bufferHandle->ResizeReplace(size, src, size); + } + // Otherwise just copy the data over + else + { + bufferHandle->MapWriteUnmap(src, size, 0, 0); + } } else { diff --git a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp index 67c83266..dfb91193 100644 --- a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHShaderBlockInterface.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp index 96fa77ab..96de87bb 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp @@ -1,6 +1,6 @@ #include "SHPch.h" #include "SHShaderReflected.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Instance/SHVkInstance.h" diff --git a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp index c1fac76c..fa6b3182 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp @@ -2,7 +2,7 @@ #include "SHVkShaderModule.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp b/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp index f46d5d17..40f917a0 100644 --- a/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp +++ b/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp @@ -3,7 +3,7 @@ #include "Graphics/Devices/SHVkPhysicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Windowing/Surface/SHVkSurface.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Graphics/Images/SHVkImage.h" #include "Graphics/Instance/SHVkInstance.h" diff --git a/SHADE_Engine/src/Graphics/Windowing/Surface/SHVkSurface.cpp b/SHADE_Engine/src/Graphics/Windowing/Surface/SHVkSurface.cpp index f9cb16c6..7d55ab72 100644 --- a/SHADE_Engine/src/Graphics/Windowing/Surface/SHVkSurface.cpp +++ b/SHADE_Engine/src/Graphics/Windowing/Surface/SHVkSurface.cpp @@ -4,7 +4,7 @@ #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Instance/SHVkInstance.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBox.cpp similarity index 71% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp rename to SHADE_Engine/src/Math/Geometry/SHBox.cpp index 5bbf5e15..a52cf0d2 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBox.cpp @@ -1,5 +1,5 @@ /**************************************************************************************** - * \file SHBoundingBox.cpp + * \file SHBox.cpp * \author Diren D Bharwani, diren.dbharwani, 390002520 * \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box * @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingBox.h" +#include "SHBox.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox::SHBoundingBox() noexcept + SHBox::SHBox() noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; } - SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept + SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; @@ -40,7 +40,7 @@ namespace SHADE } - SHBoundingBox::SHBoundingBox(const SHBoundingBox& rhs) noexcept + SHBox::SHBox(const SHBox& rhs) noexcept { if (this == &rhs) return; @@ -52,7 +52,7 @@ namespace SHADE RelativeExtents = rhs.RelativeExtents; } - SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept + SHBox::SHBox(SHBox&& rhs) noexcept { type = Type::BOX; @@ -65,7 +65,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox& SHBoundingBox::operator=(const SHBoundingBox& rhs) noexcept + SHBox& SHBox::operator=(const SHBox& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -81,7 +81,7 @@ namespace SHADE return *this; } - SHBoundingBox& SHBoundingBox::operator=(SHBoundingBox&& rhs) noexcept + SHBox& SHBox::operator=(SHBox&& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -101,27 +101,27 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingBox::GetCenter() const noexcept + SHVec3 SHBox::GetCenter() const noexcept { return Center; } - SHVec3 SHBoundingBox::GetWorldExtents() const noexcept + SHVec3 SHBox::GetWorldExtents() const noexcept { return Extents; } - const SHVec3& SHBoundingBox::GetRelativeExtents() const noexcept + const SHVec3& SHBox::GetRelativeExtents() const noexcept { return RelativeExtents; } - SHVec3 SHBoundingBox::GetMin() const noexcept + SHVec3 SHBox::GetMin() const noexcept { return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; } - SHVec3 SHBoundingBox::GetMax() const noexcept + SHVec3 SHBox::GetMax() const noexcept { return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; } @@ -130,22 +130,22 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingBox::SetCenter(const SHVec3& newCenter) noexcept + void SHBox::SetCenter(const SHVec3& newCenter) noexcept { Center = newCenter; } - void SHBoundingBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept + void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept { Extents = newWorldExtents; } - void SHBoundingBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept + void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept { RelativeExtents = newRelativeExtents; } - void SHBoundingBox::SetMin(const SHVec3& min) noexcept + void SHBox::SetMin(const SHVec3& min) noexcept { const SHVec3 MAX = GetMax(); @@ -153,7 +153,7 @@ namespace SHADE Extents = SHVec3::Abs((MAX - min) * 0.5f); } - void SHBoundingBox::SetMax(const SHVec3& max) noexcept + void SHBox::SetMax(const SHVec3& max) noexcept { const SHVec3 MIN = GetMin(); @@ -161,13 +161,13 @@ namespace SHADE Extents = SHVec3::Abs((max - MIN) * 0.5f); } - void SHBoundingBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept + void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept { Center = SHVec3::Lerp(min, max, 0.5f); Extents = SHVec3::Abs((max - min) * 0.5f); } - std::vector SHBoundingBox::GetVertices() const noexcept + std::vector SHBox::GetVertices() const noexcept { std::vector vertices{ 8 }; GetCorners(vertices.data()); @@ -178,27 +178,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingBox::TestPoint(const SHVec3& point) noexcept + bool SHBox::TestPoint(const SHVec3& point) noexcept { return BoundingBox::Contains(point); } - bool SHBoundingBox::Raycast(const SHRay& ray, float& distance) noexcept + bool SHBox::Raycast(const SHRay& ray, float& distance) noexcept { return BoundingBox::Intersects(ray.position, ray.direction, distance); } - bool SHBoundingBox::Contains(const SHBoundingBox& rhs) const noexcept + bool SHBox::Contains(const SHBox& rhs) const noexcept { return BoundingBox::Contains(rhs); } - float SHBoundingBox::Volume() const noexcept + float SHBox::Volume() const noexcept { return 8.0f * (Extents.x * Extents.y * Extents.z); } - float SHBoundingBox::SurfaceArea() const noexcept + float SHBox::SurfaceArea() const noexcept { return 8.0f * ((Extents.x * Extents.y) + (Extents.x * Extents.z) @@ -209,21 +209,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox SHBoundingBox::Combine(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept { - SHBoundingBox result; + SHBox result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingBox::Intersect(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingBox SHBoundingBox::BuildFromBoxes(const SHBoundingBox* boxes, size_t numBoxes) noexcept + SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept { - SHBoundingBox result; + SHBox result; for (size_t i = 1; i < numBoxes; ++i) CreateMerged(result, boxes[i - 1], boxes[i]); @@ -231,9 +231,9 @@ namespace SHADE return result; } - SHBoundingBox SHBoundingBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingBox result; + SHBox result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h b/SHADE_Engine/src/Math/Geometry/SHBox.h similarity index 75% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.h rename to SHADE_Engine/src/Math/Geometry/SHBox.h index e2757c17..19c80bd2 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h +++ b/SHADE_Engine/src/Math/Geometry/SHBox.h @@ -1,5 +1,5 @@ /**************************************************************************************** - * \file SHBoundingBox.h + * \file SHBox.h * \author Diren D Bharwani, diren.dbharwani, 390002520 * \brief Interface for a 3-Dimensional Axis Aligned Bounding Box * @@ -22,8 +22,8 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingBox : public SHShape, - private DirectX::BoundingBox + class SH_API SHBox : public SHShape, + private DirectX::BoundingBox { public: /*---------------------------------------------------------------------------------*/ @@ -36,19 +36,19 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - ~SHBoundingBox () override = default; + ~SHBox () override = default; - SHBoundingBox () noexcept; - SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBoundingBox (const SHBoundingBox& rhs) noexcept; - SHBoundingBox (SHBoundingBox&& rhs) noexcept; + SHBox () noexcept; + SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHBox (const SHBox& rhs) noexcept; + SHBox (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; - SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; + SHBox& operator= (const SHBox& rhs) noexcept; + SHBox& operator= (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -79,18 +79,18 @@ namespace SHADE [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; + [[nodiscard]] bool Contains (const SHBox& rhs) const noexcept; + [[nodiscard]] float Volume () const noexcept; + [[nodiscard]] float SurfaceArea () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept; - [[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + [[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept; + [[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp similarity index 70% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp rename to SHADE_Engine/src/Math/Geometry/SHSphere.cpp index f843a6bb..d310e30e 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingSphere.h" +#include "SHSphere.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere::SHBoundingSphere() noexcept + SHSphere::SHSphere() noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; } - SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept + SHSphere::SHSphere(const SHVec3& center, float radius) noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; @@ -39,7 +39,7 @@ namespace SHADE Radius = radius; } - SHBoundingSphere::SHBoundingSphere(const SHBoundingSphere& rhs) noexcept + SHSphere::SHSphere(const SHSphere& rhs) noexcept { if (this == &rhs) return; @@ -51,7 +51,7 @@ namespace SHADE RelativeRadius = rhs.RelativeRadius; } - SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept + SHSphere::SHSphere(SHSphere&& rhs) noexcept { type = Type::SPHERE; @@ -64,7 +64,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere& SHBoundingSphere::operator=(const SHBoundingSphere& rhs) noexcept + SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -80,7 +80,7 @@ namespace SHADE return *this; } - SHBoundingSphere& SHBoundingSphere::operator=(SHBoundingSphere&& rhs) noexcept + SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -100,17 +100,17 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingSphere::GetCenter() const noexcept + SHVec3 SHSphere::GetCenter() const noexcept { return Center; } - float SHBoundingSphere::GetWorldRadius() const noexcept + float SHSphere::GetWorldRadius() const noexcept { return Radius; } - float SHBoundingSphere::GetRelativeRadius() const noexcept + float SHSphere::GetRelativeRadius() const noexcept { return RelativeRadius; } @@ -119,17 +119,17 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingSphere::SetCenter(const SHVec3& center) noexcept + void SHSphere::SetCenter(const SHVec3& center) noexcept { Center = center; } - void SHBoundingSphere::SetWorldRadius(float newWorldRadius) noexcept + void SHSphere::SetWorldRadius(float newWorldRadius) noexcept { Radius = newWorldRadius; } - void SHBoundingSphere::SetRelativeRadius(float newRelativeRadius) noexcept + void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept { RelativeRadius = newRelativeRadius; } @@ -138,27 +138,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingSphere::TestPoint(const SHVec3& point) noexcept + bool SHSphere::TestPoint(const SHVec3& point) noexcept { return BoundingSphere::Contains(point); } - bool SHBoundingSphere::Raycast(const SHRay& ray, float& distance) noexcept + bool SHSphere::Raycast(const SHRay& ray, float& distance) noexcept { return Intersects(ray.position, ray.direction, distance); } - bool SHBoundingSphere::Contains(const SHBoundingSphere& rhs) const noexcept + bool SHSphere::Contains(const SHSphere& rhs) const noexcept { return BoundingSphere::Contains(rhs); } - float SHBoundingSphere::Volume() const noexcept + float SHSphere::Volume() const noexcept { return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); } - float SHBoundingSphere::SurfaceArea() const noexcept + float SHSphere::SurfaceArea() const noexcept { return 4.0f * SHMath::PI * (Radius * Radius); } @@ -167,21 +167,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere SHBoundingSphere::Combine(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept { - SHBoundingSphere result; + SHSphere result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingSphere::Intersect(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingSphere SHBoundingSphere::BuildFromSpheres(const SHBoundingSphere* spheres, size_t numSpheres) noexcept + SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept { - SHBoundingSphere result; + SHSphere result; for (size_t i = 1; i < numSpheres; ++i) CreateMerged(result, spheres[i - 1], spheres[i]); @@ -189,9 +189,9 @@ namespace SHADE return result; } - SHBoundingSphere SHBoundingSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingSphere result; + SHSphere result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h b/SHADE_Engine/src/Math/Geometry/SHSphere.h similarity index 76% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h rename to SHADE_Engine/src/Math/Geometry/SHSphere.h index d94722d6..c13076aa 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.h @@ -22,27 +22,27 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingSphere : public SHShape, - private DirectX::BoundingSphere + class SH_API SHSphere : public SHShape, + private DirectX::BoundingSphere { public: /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHBoundingSphere () noexcept; - SHBoundingSphere (const SHVec3& center, float radius) noexcept; - SHBoundingSphere (const SHBoundingSphere& rhs) noexcept; - SHBoundingSphere (SHBoundingSphere&& rhs) noexcept; + SHSphere () noexcept; + SHSphere (const SHVec3& center, float radius) noexcept; + SHSphere (const SHSphere& rhs) noexcept; + SHSphere (SHSphere&& rhs) noexcept; - ~SHBoundingSphere () override = default; + ~SHSphere () override = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingSphere& operator= (const SHBoundingSphere& rhs) noexcept; - SHBoundingSphere& operator= (SHBoundingSphere&& rhs) noexcept; + SHSphere& operator= (const SHSphere& rhs) noexcept; + SHSphere& operator= (SHSphere&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -67,7 +67,7 @@ namespace SHADE [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingSphere& rhs) const noexcept; + [[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept; [[nodiscard]] float Volume () const noexcept; [[nodiscard]] float SurfaceArea () const noexcept; @@ -76,10 +76,10 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingSphere Combine (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; - [[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept; - [[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + [[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; + [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHMatrix.cpp b/SHADE_Engine/src/Math/SHMatrix.cpp index 5f082ae5..3d450a88 100644 --- a/SHADE_Engine/src/Math/SHMatrix.cpp +++ b/SHADE_Engine/src/Math/SHMatrix.cpp @@ -483,6 +483,16 @@ namespace SHADE return result; } + SHMatrix SHMatrix::Transform(const SHVec3& pos, const SHVec3& eulerAngles, const SHVec3& scale) noexcept + { + return Scale(scale) * Rotate(eulerAngles) * Translate(pos); + } + + SHMatrix SHMatrix::Transform(const SHVec3& pos, const SHQuaternion& rot, const SHVec3& scale) noexcept + { + return Scale(scale) * Rotate(rot) * Translate(pos); + } + SHMatrix SHMatrix::LookAtRH(const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept { SHMatrix result; diff --git a/SHADE_Engine/src/Math/SHMatrix.h b/SHADE_Engine/src/Math/SHMatrix.h index 4d8f1bfe..6af8fdc9 100644 --- a/SHADE_Engine/src/Math/SHMatrix.h +++ b/SHADE_Engine/src/Math/SHMatrix.h @@ -131,34 +131,37 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHMatrix Transpose (const SHMatrix& matrix) noexcept; - [[nodiscard]] static SHMatrix Inverse (const SHMatrix& matrix) noexcept; + [[nodiscard]] static SHMatrix Transpose (const SHMatrix& matrix) noexcept; + [[nodiscard]] static SHMatrix Inverse (const SHMatrix& matrix) noexcept; - [[nodiscard]] static SHMatrix Translate (float x, float y, float z) noexcept; - [[nodiscard]] static SHMatrix Translate (const SHVec3& pos) noexcept; + [[nodiscard]] static SHMatrix Translate (float x, float y, float z) noexcept; + [[nodiscard]] static SHMatrix Translate (const SHVec3& pos) noexcept; - [[nodiscard]] static SHMatrix Rotate (const SHVec3& axis, float angleInRad) noexcept; - [[nodiscard]] static SHMatrix Rotate (float yaw, float pitch, float roll) noexcept; - [[nodiscard]] static SHMatrix Rotate (const SHVec3& eulerAngles) noexcept; - [[nodiscard]] static SHMatrix Rotate (const SHQuaternion& q) noexcept; - [[nodiscard]] static SHMatrix RotateX (float angleInRad) noexcept; - [[nodiscard]] static SHMatrix RotateY (float angleInRad) noexcept; - [[nodiscard]] static SHMatrix RotateZ (float angleInRad) noexcept; + [[nodiscard]] static SHMatrix Rotate (const SHVec3& axis, float angleInRad) noexcept; + [[nodiscard]] static SHMatrix Rotate (float yaw, float pitch, float roll) noexcept; + [[nodiscard]] static SHMatrix Rotate (const SHVec3& eulerAngles) noexcept; + [[nodiscard]] static SHMatrix Rotate (const SHQuaternion& q) noexcept; + [[nodiscard]] static SHMatrix RotateX (float angleInRad) noexcept; + [[nodiscard]] static SHMatrix RotateY (float angleInRad) noexcept; + [[nodiscard]] static SHMatrix RotateZ (float angleInRad) noexcept; - [[nodiscard]] static SHMatrix Scale (float uniformScaleFactor) noexcept; - [[nodiscard]] static SHMatrix Scale (float x, float y, float z) noexcept; - [[nodiscard]] static SHMatrix Scale (const SHVec3& scale) noexcept; + [[nodiscard]] static SHMatrix Scale (float uniformScaleFactor) noexcept; + [[nodiscard]] static SHMatrix Scale (float x, float y, float z) noexcept; + [[nodiscard]] static SHMatrix Scale (const SHVec3& scale) noexcept; - [[nodiscard]] static SHMatrix LookAtRH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept; - [[nodiscard]] static SHMatrix LookAtLH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept; - [[nodiscard]] static SHMatrix CamToWorldRH (const SHVec3& pos, const SHVec3& forward, const SHVec3& up) noexcept; - [[nodiscard]] static SHMatrix CamToWorldLH (const SHVec3& pos, const SHVec3& forward, const SHVec3& up) noexcept; - [[nodiscard]] static SHMatrix PerspectiveFovRH (float fov, float aspectRatio, float nearPlane, float farPlane) noexcept; - [[nodiscard]] static SHMatrix PerspectiveFovLH (float fov, float aspectRatio, float nearPlane, float farPlane) noexcept; - [[nodiscard]] static SHMatrix PerspectiveRH (float width, float height, float nearPlane, float farPlane) noexcept; - [[nodiscard]] static SHMatrix PerspectiveLH (float width, float height, float nearPlane, float farPlane) noexcept; - [[nodiscard]] static SHMatrix OrthographicRH (float width, float height, float nearPlane, float farPlane) noexcept; - [[nodiscard]] static SHMatrix OrthographicLH (float width, float height, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix Transform (const SHVec3& pos, const SHVec3& eulerAngles, const SHVec3& scale) noexcept; + [[nodiscard]] static SHMatrix Transform (const SHVec3& pos, const SHQuaternion& rot, const SHVec3& scale) noexcept; + + [[nodiscard]] static SHMatrix LookAtRH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept; + [[nodiscard]] static SHMatrix LookAtLH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept; + [[nodiscard]] static SHMatrix CamToWorldRH (const SHVec3& pos, const SHVec3& forward, const SHVec3& up) noexcept; + [[nodiscard]] static SHMatrix CamToWorldLH (const SHVec3& pos, const SHVec3& forward, const SHVec3& up) noexcept; + [[nodiscard]] static SHMatrix PerspectiveFovRH (float fov, float aspectRatio, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix PerspectiveFovLH (float fov, float aspectRatio, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix PerspectiveRH (float width, float height, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix PerspectiveLH (float width, float height, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix OrthographicRH (float width, float height, float nearPlane, float farPlane) noexcept; + [[nodiscard]] static SHMatrix OrthographicLH (float width, float height, float nearPlane, float farPlane) noexcept; // TODO(Diren): Billboard, Shadow, Projection & Reflection }; diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 3564916a..8904cb05 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -16,7 +16,7 @@ #include "Vector/SHVec3.h" #include "SHMatrix.h" #include "SHMathHelpers.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" using namespace DirectX; diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.cpp b/SHADE_Engine/src/Math/Vector/SHVec2.cpp index 195a8b14..9573be01 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec2.cpp @@ -14,7 +14,7 @@ #include "SHVec2.h" // Project Headers #include "Math/SHMatrix.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" using namespace DirectX; diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.cpp b/SHADE_Engine/src/Math/Vector/SHVec3.cpp index cbd8ca32..a696f341 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec3.cpp @@ -15,7 +15,7 @@ // Project Headers #include "Math/SHMatrix.h" #include "Math/SHQuaternion.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" using namespace DirectX; diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index 943d540e..c6f01d9e 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -15,7 +15,7 @@ // Project Headers #include "Math/SHMatrix.h" #include "Math/SHColour.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" using namespace DirectX; diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp index e8379b09..f16303f4 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp @@ -16,6 +16,7 @@ // Project Headers #include "Physics/PhysicsObject/SHPhysicsObject.h" #include "Physics/System/SHPhysicsSystem.h" +#include "Scene/SHSceneManager.h" /*-------------------------------------------------------------------------------------*/ /* Local Helper Functions */ @@ -80,10 +81,15 @@ namespace SHADE { for (auto eventIter = container.begin(); eventIter != container.end();) { - const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionInfo::State::EXIT - || eventIter->GetCollisionState() == SHCollisionInfo::State::INVALID; + const SHCollisionInfo& C_INFO = *eventIter; - if (CLEAR_EVENT) + const bool CLEAR_EVENT = C_INFO.GetCollisionState() == SHCollisionInfo::State::EXIT + || C_INFO.GetCollisionState() == SHCollisionInfo::State::INVALID; + + const bool INACTIVE_OBJECT = !SHSceneManager::CheckNodeAndComponentsActive(C_INFO.GetEntityA()) + || !SHSceneManager::CheckNodeAndComponentsActive(C_INFO.GetEntityB()); + + if (CLEAR_EVENT || INACTIVE_OBJECT) eventIter = container.erase(eventIter); else ++eventIter; diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 1c8149ad..877d238f 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -95,7 +95,7 @@ namespace SHADE { case SHCollisionShape::Type::BOX: { - auto* box = reinterpret_cast(collisionShape.shape); + auto* box = reinterpret_cast(collisionShape.shape); const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents(); // Recompute world extents based on new scale and fixed relative extents @@ -106,7 +106,7 @@ namespace SHADE } case SHCollisionShape::Type::SPHERE: { - auto* sphere = reinterpret_cast(collisionShape.shape); + auto* sphere = reinterpret_cast(collisionShape.shape); const float RELATIVE_RADIUS = sphere->GetRelativeRadius(); // Recompute world radius based on new scale and fixed radius diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 88dc306f..0781f3cf 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -14,8 +14,8 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "SHCollisionShape.h" //namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp index 1ea2a7d3..14743845 100644 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp @@ -13,8 +13,8 @@ // Primary Header #include "SHCollisionShape.h" // Project Headers -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Math/SHMathHelpers.h" #include "Reflection/SHReflectionMetadata.h" #include "SHColliderComponent.h" @@ -37,12 +37,12 @@ namespace SHADE { case Type::BOX: { - shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; + shape = new SHBox{ SHVec3::Zero, SHVec3::One }; break; } case Type::SPHERE: { - shape = new SHBoundingSphere{ SHVec3::Zero, 0.5f }; + shape = new SHSphere{ SHVec3::Zero, 0.5f }; break; } default: break; @@ -177,30 +177,48 @@ namespace SHADE { dirty = true; - const auto* colliderComponent = SHComponentManager::GetComponent(entityID); + const auto* COLLIDER = SHComponentManager::GetComponent(entityID); + auto* box = reinterpret_cast(shape); + + SHVec3 correctedHalfExtents = halfExtents; + + // Get current relative halfExtents for error checking. 0 is ignored + const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents(); + for (size_t i = 0; i < SHVec3::SIZE; ++i) + { + if (SHMath::CompareFloat(halfExtents[i], 0.0f)) + correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i]; + } + // Set the half extents relative to world scale - const SHVec3 WORLD_EXTENTS = halfExtents * colliderComponent->GetScale() * 0.5f; + const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f; if (type != Type::BOX) { type = Type::BOX; delete shape; - shape = new SHBoundingBox{ positionOffset, WORLD_EXTENTS }; + shape = new SHBox{ positionOffset, WORLD_EXTENTS }; } - auto* box = reinterpret_cast(shape); box->SetWorldExtents(WORLD_EXTENTS); - box->SetRelativeExtents(halfExtents); + box->SetRelativeExtents(correctedHalfExtents); } void SHCollisionShape::SetBoundingSphere(float radius) { dirty = true; - const auto* colliderComponent = SHComponentManager::GetComponent(entityID); + auto* sphere = reinterpret_cast(shape); + const auto* COLLIDER = SHComponentManager::GetComponent(entityID); + + // Get current relative halfExtents for error checking. 0 is ignored + const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius(); + if (SHMath::CompareFloat(radius, 0.0f)) + radius = CURRENT_RELATIVE_RADIUS; + // Set the radius relative to world scale - const SHVec3 WORLD_SCALE = colliderComponent->GetScale(); + const SHVec3 WORLD_SCALE = COLLIDER->GetScale(); const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z }); const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f; @@ -209,11 +227,11 @@ namespace SHADE type = Type::SPHERE; delete shape; - shape = new SHBoundingSphere{ positionOffset, WORLD_RADIUS }; + shape = new SHSphere{ positionOffset, WORLD_RADIUS }; } - auto* sphere = reinterpret_cast(shape); sphere->SetWorldRadius(WORLD_RADIUS); + sphere->SetRelativeRadius(radius); } void SHCollisionShape::SetIsTrigger(bool trigger) noexcept @@ -255,12 +273,12 @@ namespace SHADE { case Type::BOX: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } case Type::SPHERE: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } default: break; @@ -283,16 +301,22 @@ namespace SHADE { case Type::BOX: { - const auto* RHS_BOX = reinterpret_cast(rhs); + const auto* RHS_BOX = reinterpret_cast(rhs); + + shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() }; + auto* lhsBox = reinterpret_cast(shape); + lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents()); - shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetWorldExtents() }; break; } case Type::SPHERE: { - const auto* RHS_SPHERE = reinterpret_cast(rhs); + const auto* RHS_SPHERE = reinterpret_cast(rhs); + + shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; + auto* lhsSphere = reinterpret_cast(shape); + lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius()); - shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; break; } default: break; diff --git a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp b/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp index 677e448f..95141501 100644 --- a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp @@ -44,7 +44,7 @@ namespace SHADE && SHMath::CompareFloat(density, rhs.density); } - bool SHPhysicsMaterial::operator!=(const SHPhysicsMaterial& rhs) const noexcept + bool SHPhysicsMaterial::operator!=(const SHPhysicsMaterial& rhs) const noexcept { return !SHMath::CompareFloat(friction, rhs.friction) || !SHMath::CompareFloat(bounciness, rhs.bounciness) diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index 5fe1e55e..28b6f842 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -29,7 +29,6 @@ namespace SHADE SHRigidBodyComponent::SHRigidBodyComponent() noexcept : type { Type::DYNAMIC } - , interpolate { true } , flags { 0 } , dirtyFlags { std::numeric_limits::max() } , mass { 1.0f } @@ -40,6 +39,7 @@ namespace SHADE // Initialise default flags flags |= 1U << 0; // Gravity set to true flags |= 1U << 1; // Sleeping allowed + flags |= 1U << 8; // Interpolate by default } /*-----------------------------------------------------------------------------------*/ @@ -60,7 +60,16 @@ namespace SHADE bool SHRigidBodyComponent::IsInterpolating() const noexcept { - return interpolate; + static constexpr int FLAG_POS = 8; + return flags & (1U << FLAG_POS); + } + + bool SHRigidBodyComponent::GetIsSleeping() const noexcept + { + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + return physicsObject->GetRigidBody()->isSleeping(); + + return false; } SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept @@ -68,21 +77,6 @@ namespace SHADE return type; } - float SHRigidBodyComponent::GetMass() const noexcept - { - return mass; - } - - float SHRigidBodyComponent::GetDrag() const noexcept - { - return drag; - } - - float SHRigidBodyComponent::GetAngularDrag() const noexcept - { - return angularDrag; - } - bool SHRigidBodyComponent::GetFreezePositionX() const noexcept { static constexpr int FLAG_POS = 2; @@ -119,6 +113,27 @@ namespace SHADE return flags & (1U << FLAG_POS); } + //bool SHRigidBodyComponent::GetAutoMass() const noexcept + //{ + // static constexpr int FLAG_POS = 9; + // return flags & (1U << FLAG_POS); + //} + + float SHRigidBodyComponent::GetMass() const noexcept + { + return mass; + } + + float SHRigidBodyComponent::GetDrag() const noexcept + { + return drag; + } + + float SHRigidBodyComponent::GetAngularDrag() const noexcept + { + return angularDrag; + } + SHVec3 SHRigidBodyComponent::GetForce() const noexcept { if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) @@ -295,13 +310,25 @@ namespace SHADE void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept { - interpolate = allowInterpolation; + static constexpr int FLAG_POS = 8; + allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } + //void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept + //{ + // static constexpr int FLAG_POS = 9; + // autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); + + // dirtyFlags |= 1U << FLAG_POS; + //} + void SHRigidBodyComponent::SetMass(float newMass) noexcept { static constexpr int FLAG_POS = 9; + if (newMass < 0.0f) + return; + if (type != Type::DYNAMIC) { SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) @@ -310,6 +337,9 @@ namespace SHADE dirtyFlags |= 1U << FLAG_POS; mass = newMass; + + // Turn off automass + flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetDrag(float newDrag) noexcept @@ -385,42 +415,62 @@ namespace SHADE void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { - system->AddForce(GetEID(), force); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyWorldForceAtCenterOfMass(force); } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - system->AddForceAtLocalPos(GetEID(), force, localPos); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos); } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - system->AddForceAtWorldPos(GetEID(), force, worldPos); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos); } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - system->AddRelativeForce(GetEID(), relativeForce); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce); } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - system->AddRelativeForceAtLocalPos(GetEID(), relativeForce, localPos); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos); } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - system->AddRelativeForceAtWorldPos(GetEID(), relativeForce, worldPos); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos); } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - system->AddTorque(GetEID(), torque); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyWorldTorque(torque); } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - system->AddRelativeTorque(GetEID(), relativeTorque); + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->applyLocalTorque(relativeTorque); + } + + void SHRigidBodyComponent::ClearForces() const noexcept + { + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->resetForce(); + } + + void SHRigidBodyComponent::ClearTorque() const noexcept + { + if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) + physicsObject->GetRigidBody()->resetTorque(); } } // namespace SHADE @@ -444,6 +494,8 @@ RTTR_REGISTRATION .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate ) + .property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep) + //.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass ) .property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX ) .property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY ) .property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ ) diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index 48a5d723..d5204d94 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -71,19 +71,23 @@ namespace SHADE [[nodiscard]] bool IsAllowedToSleep () const noexcept; [[nodiscard]] bool IsInterpolating () const noexcept; + [[nodiscard]] bool GetIsSleeping () const noexcept; + [[nodiscard]] Type GetType () const noexcept; - [[nodiscard]] float GetMass () const noexcept; - [[nodiscard]] float GetDrag () const noexcept; - [[nodiscard]] float GetAngularDrag () const noexcept; - + [[nodiscard]] bool GetFreezePositionX () const noexcept; [[nodiscard]] bool GetFreezePositionY () const noexcept; [[nodiscard]] bool GetFreezePositionZ () const noexcept; - [[nodiscard]] bool GetFreezeRotationX () const noexcept; [[nodiscard]] bool GetFreezeRotationY () const noexcept; [[nodiscard]] bool GetFreezeRotationZ () const noexcept; + //[[nodiscard]] bool GetAutoMass () const noexcept; + + [[nodiscard]] float GetMass () const noexcept; + [[nodiscard]] float GetDrag () const noexcept; + [[nodiscard]] float GetAngularDrag () const noexcept; + [[nodiscard]] SHVec3 GetForce () const noexcept; [[nodiscard]] SHVec3 GetTorque () const noexcept; [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; @@ -108,6 +112,7 @@ namespace SHADE void SetFreezeRotationY (bool freezeRotationY) noexcept; void SetFreezeRotationZ (bool freezeRotationZ) noexcept; void SetInterpolate (bool allowInterpolation) noexcept; + //void SetAutoMass (bool autoMass) noexcept; void SetMass (float newMass) noexcept; void SetDrag (float newDrag) noexcept; @@ -125,14 +130,15 @@ namespace SHADE void AddForce (const SHVec3& force) const noexcept; void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept; void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept; - void AddRelativeForce (const SHVec3& relativeForce) const noexcept; void AddRelativeForceAtLocalPos (const SHVec3& relativeForce, const SHVec3& localPos) const noexcept; void AddRelativeForceAtWorldPos (const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept; - void AddTorque (const SHVec3& torque) const noexcept; void AddRelativeTorque (const SHVec3& relativeTorque) const noexcept; + void ClearForces () const noexcept; + void ClearTorque () const noexcept; + private: /*---------------------------------------------------------------------------------*/ /* Data Members */ @@ -143,8 +149,7 @@ namespace SHADE Type type; - bool interpolate; - uint8_t flags; // aZ aY aX lZ lY lX slp g + uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g float mass; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 0c9fa405..0a0ff201 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHComponentManager.h" +#include "Scene/SHSceneManager.h" namespace SHADE @@ -25,10 +26,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } + : entityID { eid } + , collidersActive { true } + , factory { physicsFactory } + , world { physicsWorld } + , rp3dBody { nullptr } { // Implicitly create a static body. @@ -107,8 +109,17 @@ namespace SHADE { // TODO(Diren): Add more collider shapes - case SHCollisionShape::Type::BOX: addBoxShape(collisionShape); break; - case SHCollisionShape::Type::SPHERE: addSphereShape(collisionShape); break; + case SHCollisionShape::Type::BOX: + { + addBoxShape(collisionShape); + break; + } + + case SHCollisionShape::Type::SPHERE: + { + addSphereShape(collisionShape); + break; + } default: break; } @@ -148,6 +159,10 @@ namespace SHADE void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept { + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + if (component.dirtyFlags == 0) return; @@ -239,9 +254,17 @@ namespace SHADE } case 9: // Mass { - rp3dBody->setMass(component.mass); - rp3dBody->updateLocalCenterOfMassFromColliders(); - rp3dBody->updateLocalInertiaTensorFromColliders(); + //if (component.GetAutoMass()) + //{ + // rp3dBody->updateMassPropertiesFromColliders(); + // component.mass = rp3dBody->getMass(); + //} + //else + //{ + rp3dBody->setMass(component.mass); + rp3dBody->updateLocalCenterOfMassFromColliders(); + rp3dBody->updateLocalInertiaTensorFromColliders(); + //} break; } @@ -267,23 +290,28 @@ namespace SHADE void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept { - int index = 0; - for (auto& collisionShape : component.collisionShapes) + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + + const int NUM_SHAPES = static_cast(component.collisionShapes.size()); + for (int i = 0; i < NUM_SHAPES; ++i) { + auto& collisionShape = component.collisionShapes[i]; + if (!collisionShape.dirty) continue; switch (collisionShape.GetType()) { - case SHCollisionShape::Type::BOX: syncBoxShape(index, collisionShape); break; - case SHCollisionShape::Type::SPHERE: syncSphereShape(index, collisionShape); break; + case SHCollisionShape::Type::BOX: syncBoxShape(i, collisionShape); break; + case SHCollisionShape::Type::SPHERE: syncSphereShape(i, collisionShape); break; default: break; } - // TODO(Diren): Update Material + syncMaterial(i, collisionShape); collisionShape.dirty = false; - ++index; } } @@ -291,6 +319,14 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsObject::syncMaterial(int colliderIndex, SHCollisionShape& collisionShape) const noexcept + { + auto& rp3dMaterial = rp3dBody->getCollider(colliderIndex)->getMaterial(); + rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction()); + rp3dMaterial.setBounciness(collisionShape.GetBounciness()); + rp3dMaterial.setMassDensity(collisionShape.GetDensity()); + } + void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept { const rp3d::Transform OFFSETS @@ -299,7 +335,7 @@ namespace SHADE , boxShape.GetRotationOffset() }; - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); rp3dBody->addCollider(newBox, OFFSETS); @@ -307,7 +343,7 @@ namespace SHADE void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept { - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dBox = reinterpret_cast(rp3dCollider->getCollisionShape()); @@ -332,7 +368,7 @@ namespace SHADE , sphereShape.GetRotationOffset() }; - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); rp3dBody->addCollider(newSphere, OFFSETS); @@ -340,7 +376,7 @@ namespace SHADE void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept { - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dSphere = reinterpret_cast(rp3dCollider->getCollisionShape()); diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h index f18a0738..5a0e62ac 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h @@ -84,17 +84,20 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ EntityID entityID; + bool collidersActive; // Only used to sync with SHADE components rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; rp3d::RigidBody* rp3dBody; - rp3d::Transform prevTransform; // Cached transform for interpolation + rp3d::Transform prevTransform; // Cached transform for interpolation /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ + void syncMaterial (int colliderIndex, SHCollisionShape& collisionShape) const noexcept; + // Box Shapes void addBoxShape (SHCollisionShape& boxShape) const noexcept; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp index 13f525e6..ffd10e0c 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp @@ -15,7 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/SHUtilities.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { @@ -167,6 +167,7 @@ namespace SHADE if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent) { destroyPhysicsObject(COMMAND.eid); + wakeAllObjects(); continue; } @@ -176,6 +177,10 @@ namespace SHADE physicsObject = createPhysicsObject(COMMAND.eid); componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP); + + // If any removal was done, wake all objects + if (COMMAND.command == QueueCommand::Command::REMOVE) + wakeAllObjects(); } } @@ -297,5 +302,11 @@ namespace SHADE physicsObject->RemoveCollisionShape(command.shapeIndex); } + void SHPhysicsObjectManager::wakeAllObjects() noexcept + { + for (auto& physicsObject : physicsObjects | std::views::values) + physicsObject.GetRigidBody()->setIsSleeping(false); + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h index d8c9b805..641fd9df 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h @@ -165,6 +165,8 @@ namespace SHADE SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept; void destroyPhysicsObject (EntityID eid) noexcept; + void wakeAllObjects () noexcept; + static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); @@ -172,6 +174,8 @@ namespace SHADE static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/SHPhysicsWorld.h index 091ae062..c5152c44 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsWorld.h +++ b/SHADE_Engine/src/Physics/SHPhysicsWorld.h @@ -38,8 +38,8 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ SHVec3 gravity = SHVec3{ 0.0f, -9.81f, 0.0f }; - uint16_t numVelocitySolverIterations = 15; - uint16_t numPositionSolverIterations = 8; + uint16_t numVelocitySolverIterations = 10; + uint16_t numPositionSolverIterations = 5; bool sleepingEnabled = true; }; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index ff441ac2..7ccfb225 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" +#include "Scene/SHSceneManager.h" namespace SHADE { @@ -23,7 +24,7 @@ namespace SHADE /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ - const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[SHPhysicsDebugDrawSystem::NUM_FLAGS] = + const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] = { SHPhysicsDebugDrawSystem::drawColliders , SHPhysicsDebugDrawSystem::drawColliderAABBs @@ -32,6 +33,8 @@ namespace SHADE , SHPhysicsDebugDrawSystem::drawContactNormals }; + SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES]; + /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -41,7 +44,7 @@ namespace SHADE , physicsSystem { nullptr } , rp3dDebugRenderer { nullptr } { - debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = + debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN; debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW; debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN; debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED; @@ -94,6 +97,9 @@ namespace SHADE SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!") physicsSystem = SHSystemManager::GetSystem(); + + // Generate shapes + generateBox(); } void SHPhysicsDebugDrawSystem::Exit() @@ -122,6 +128,10 @@ namespace SHADE const auto& COLLIDER_SET = SHComponentManager::GetDense(); for (const auto& COLLIDER : COLLIDER_SET) { + // Skip inactive colliders + if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) + continue; + for (auto& collisionShape : COLLIDER.GetCollisionShapes()) { switch (collisionShape.GetType()) @@ -154,21 +164,20 @@ namespace SHADE } + void SHPhysicsDebugDrawSystem::generateBox() noexcept + { + boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK + boxVertices[1] = { -0.5f, 0.5f, -0.5f }; // TOP_LEFT_BACK + boxVertices[2] = { 0.5f, -0.5f, -0.5f }; // BTM_RIGHT_BACK + boxVertices[3] = { -0.5f, -0.5f, -0.5f }; // BTM_LEFT_BACK + boxVertices[4] = { 0.5f, 0.5f, 0.5f }; // TOP_RIGHT_FRONT + boxVertices[5] = { -0.5f, 0.5f, 0.5f }; // TOP_LEFT_FRONT + boxVertices[6] = { 0.5f, -0.5f, 0.5f }; // BTM_RIGHT_FRONT + boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT + } + void SHPhysicsDebugDrawSystem::debugDrawBox(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept { - static constexpr uint32_t NUM_BOX_VERTICES = 8; - static const SHVec3 boxVertices[NUM_BOX_VERTICES] - { - { 0.5f, 0.5f, -0.5f } // TOP_RIGHT_BACK - , { -0.5f, 0.5f, -0.5f } // TOP_LEFT_BACK - , { 0.5f, -0.5f, -0.5f } // BTM_RIGHT_BACK - , { -0.5f, -0.5f, -0.5f } // BTM_LEFT_BACK - , { 0.5f, 0.5f, 0.5f } // TOP_RIGHT_FRONT - , { -0.5f, 0.5f, 0.5f } // TOP_LEFT_FRONT - , { 0.5f, -0.5f, 0.5f } // BTM_RIGHT_FRONT - , { -0.5f, -0.5f, 0.5f } // BTM_LEFT_FRONT - }; - auto* debugDrawSystem = SHSystemManager::GetSystem(); if (debugDrawSystem == nullptr) { @@ -176,13 +185,19 @@ namespace SHADE return; } - auto* BOX = reinterpret_cast(collisionShape.GetShape()); + auto* BOX = reinterpret_cast(collisionShape.GetShape()); // Calculate final position & orientation - const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset(); - const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset()); + const SHVec3 COLLIDER_POS = colliderComponent.GetPosition(); + const SHVec3 BOX_POS = collisionShape.GetPositionOffset(); + const SHQuaternion COLLIDER_ROT = colliderComponent.GetOrientation(); + const SHQuaternion BOX_ROT = SHQuaternion::FromEuler(collisionShape.GetRotationOffset()); - const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(FINAL_POS); + + const SHMatrix COLLIDER_TR = SHMatrix::Rotate(COLLIDER_ROT) * SHMatrix::Translate(COLLIDER_POS); + const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(BOX_ROT) * SHMatrix::Translate(BOX_POS); + + const SHMatrix FINAL_TRS = BOX_TRS * COLLIDER_TR; const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; @@ -192,8 +207,8 @@ namespace SHADE const uint32_t IDX1 = i; const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2; - transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], BOX_TRS); - transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], BOX_TRS); + transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], FINAL_TRS); + transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS); // Draw 4 line to connect the quads debugDrawSystem->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]); @@ -202,6 +217,7 @@ namespace SHADE // A, B, C, D std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] }; debugDrawSystem->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end()); + // E, F, G, H std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] }; debugDrawSystem->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end()); @@ -216,13 +232,15 @@ namespace SHADE return; } - auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); + auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; // Calculate final position & orientation - const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset(); - debugDrawSystem->DrawSphere(COLLIDER_COLOUR, FINAL_POS, SPHERE->GetWorldRadius()); + const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset()); + const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition()); + + debugDrawSystem->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius()); } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h index 53037ab2..149ed6c1 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h @@ -16,7 +16,7 @@ #include "ECS_Base/System/SHSystemRoutine.h" #include "Math/SHColour.h" #include "SHPhysicsSystem.h" -#include "Tools/SHUtilities.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { @@ -97,25 +97,38 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); - + static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); static const DebugDrawFunction drawFunctions[NUM_FLAGS]; - uint8_t debugDrawFlags; - SHPhysicsSystem* physicsSystem; - rp3d::DebugRenderer* rp3dDebugRenderer; - SHColour debugColours[NUM_FLAGS]; + // SHAPES INFO + + static constexpr size_t NUM_BOX_VERTICES = 8; + static SHVec3 boxVertices[NUM_BOX_VERTICES]; + + + uint8_t debugDrawFlags; + SHPhysicsSystem* physicsSystem; + rp3d::DebugRenderer* rp3dDebugRenderer; + SHColour debugColours[NUM_FLAGS]; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ + // Generic Draw Functions + static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept; static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept; static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept; static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept; static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept; + // Shape Generation Functions + + static void generateBox () noexcept; + + // Shape Draw Functions + static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept; static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept; }; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 34f0c698..50590e04 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -20,6 +20,7 @@ #include "Editor/SHEditor.h" #include "Physics/SHPhysicsEvents.h" #include "Scene/SHSceneManager.h" +#include "Scripting/SHScriptEngine.h" /*-------------------------------------------------------------------------------------*/ /* Local Helper Functions */ @@ -34,16 +35,16 @@ namespace SHADE SHPhysicsSystem::SHPhysicsSystem() : worldUpdated { false } , interpolationFactor { 0.0 } - , fixedDT { 60.0 } + , fixedDT { DEFAULT_FIXED_STEP } {} /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - double SHPhysicsSystem::GetFixedDT() const noexcept + double SHPhysicsSystem::GetFixedUpdateRate() const noexcept { - return fixedDT; + return 1.0 / fixedDT; } const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept @@ -61,7 +62,7 @@ namespace SHADE return collisionListener.GetTriggerInfoContainer(); } - const SHPhysicsObject* const SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept + const SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept { return objectManager.GetPhysicsObject(eid); } @@ -76,9 +77,9 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept + void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept { - fixedDT = fixedUpdateRate; + fixedDT = 1.0 / fixedUpdateRate; } void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept @@ -126,6 +127,63 @@ namespace SHADE worldState.DestroyWorld(factory); } + void SHPhysicsSystem::ForceUpdate() + { + if (!worldState.world) + { + SHLOGV_ERROR("Unable to force update without a Physics world!") + return; + } + + auto* scriptingSystem = SHSystemManager::GetSystem(); + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); + } + + // Force the physics world to update once + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteFixedUpdates(); + + worldState.world->update(static_cast(fixedDT)); + + // Sync transforms. No interpolation applied here + for (auto& [entityID, physicsObject] : objectManager.physicsObjects) + { + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + + const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); + const auto& RENDER_POS = CURRENT_TF.getPosition(); + const auto& RENDER_ROT = CURRENT_TF.getOrientation(); + + // Cache transform + physicsObject.prevTransform = CURRENT_TF; + + // Sync with physics components + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(entityID)) + { + rigidBodyComponent->position = RENDER_POS; + rigidBodyComponent->orientation = RENDER_ROT; + } + + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(entityID)) + { + colliderComponent->position = RENDER_POS; + colliderComponent->orientation = RENDER_ROT; + } + + // Set transform for rendering + if (transformComponent) + { + transformComponent->SetWorldPosition(RENDER_POS); + transformComponent->SetWorldOrientation(RENDER_ROT); + } + } + } + + void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex) { static const auto ADD_SHAPE = [&](EntityID entityID, int index) @@ -183,48 +241,6 @@ namespace SHADE #endif } - void SHPhysicsSystem::AddForce(EntityID eid, const SHVec3& force) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - - } - - void SHPhysicsSystem::AddForceAtLocalPos(EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - void SHPhysicsSystem::AddForceAtWorldPos(EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - void SHPhysicsSystem::AddRelativeForce(EntityID eid, const SHVec3& relativeForce) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - - void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - void SHPhysicsSystem::AddTorque(EntityID eid, const SHVec3& torque) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - - void SHPhysicsSystem::AddRelativeTorque(EntityID eid, const SHVec3& relativeTorque) noexcept - { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - } - /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -339,5 +355,4 @@ namespace SHADE return onStopEvent->handle; } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 4254efc7..9638e05c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -55,20 +55,20 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] double GetFixedUpdateRate () const noexcept; [[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; - [[nodiscard]] const SHPhysicsObject* const GetPhysicsObject (EntityID eid) noexcept; + [[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept; [[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedDT (double fixedUpdateRate) noexcept; - void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; + void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -77,25 +77,15 @@ namespace SHADE void Init () override; void Exit () override; - // Specific Handling for Collision Shapes as they are not under the Component System + void ForceUpdate (); + + // Specific Handling for Collision Shapes as they are not under the Component System. + // This is done as events need to be sent out. + // TODO(Diren): Consider using a static method through the ColliderComponent. void AddCollisionShape (EntityID eid, int shapeIndex); void RemoveCollisionShape (EntityID eid, int shapeIndex); - // Forces are applied from components here. These functions should only be invoked during play (through scripts) - // Thus there is no need to check for an editor. - - void AddForce (EntityID eid, const SHVec3& force) noexcept; - void AddForceAtLocalPos (EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept; - void AddForceAtWorldPos (EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept; - - void AddRelativeForce (EntityID eid, const SHVec3& relativeForce) noexcept; - void AddRelativeForceAtLocalPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept; - void AddRelativeForceAtWorldPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept; - - void AddTorque (EntityID eid, const SHVec3& torque) noexcept; - void AddRelativeTorque (EntityID eid, const SHVec3& relativeTorque) noexcept; - /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ @@ -120,12 +110,14 @@ namespace SHADE /* Function Members */ /*-------------------------------------------------------------------------------*/ - static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; + void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; static void preUpdateSyncTransform ( SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent + , SHTransformComponent* transformComponent , SHRigidBodyComponent* rigidBodyComponent , SHColliderComponent* colliderComponent ) noexcept; @@ -163,6 +155,7 @@ namespace SHADE void Execute(double dt) noexcept override; private: + /*-------------------------------------------------------------------------------*/ /* Function Members */ /*-------------------------------------------------------------------------------*/ @@ -170,7 +163,7 @@ namespace SHADE static void postUpdateSyncTransforms ( SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent + , SHTransformComponent* transformComponent , SHRigidBodyComponent* rigidBodyComponent , SHColliderComponent* colliderComponent , double interpolationFactor diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 30d29167..b142d54c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -55,7 +55,7 @@ namespace SHADE auto phySystem = SHSystemManager::GetSystem(); if (phySystem) { - return phySystem->GetFixedDT(); + return phySystem->GetFixedUpdateRate(); } SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get fixed delta time. 0.0 returned instead."); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index 059202e5..9d860bf9 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -13,10 +13,14 @@ // Primary Header #include "SHPhysicsSystem.h" // Project Headers +#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" +#include "Scene/SHSceneManager.h" #include "Scripting/SHScriptEngine.h" +#include "Input/SHInputManager.h" + namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -43,65 +47,13 @@ namespace SHADE { auto* physicsSystem = reinterpret_cast(GetSystem()); - #ifdef SHEDITOR - - auto* editor = SHSystemManager::GetSystem(); - - // Only Sync on Play. - // Otherwise, Components are only holding data until the world is built on play. - - if (editor) - { - if (editor->editorState != SHEditor::State::STOP) - { - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - syncOnPlay(entityID, physicsObject); - } - } - else - { - auto& rigidBodyDense = SHComponentManager::GetDense(); - auto& colliderDense = SHComponentManager::GetDense(); - - for (auto& rigidBodyComponent : rigidBodyDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); - rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); - } - } - - for (auto& colliderComponent : colliderDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - colliderComponent.position = TRANSFORM->GetWorldPosition(); - colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); - colliderComponent.scale = TRANSFORM->GetWorldScale(); - - colliderComponent.RecomputeCollisionShapes(); - } - } - } - } - - #else - - // Always sync Rigid Body & Collider Components with Physics Objects - // Do not check for an editor here + #ifdef SHEDITOR + // Only Sync on Play. + // Otherwise, Components are only holding data until the world is built on play. + const auto* EDITOR = SHSystemManager::GetSystem(); + if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) + { physicsSystem->objectManager.UpdateCommands(); for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) @@ -110,10 +62,64 @@ namespace SHADE if (physicsObject.rp3dBody == nullptr) continue; + // Sync active states between SHADE & RP3D + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + syncOnPlay(entityID, physicsObject); } + } + else + { + auto& rigidBodyDense = SHComponentManager::GetDense(); + auto& colliderDense = SHComponentManager::GetDense(); - #endif + for (auto& rigidBodyComponent : rigidBodyDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); + rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); + } + } + + for (auto& colliderComponent : colliderDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + colliderComponent.position = TRANSFORM->GetWorldPosition(); + colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); + colliderComponent.scale = TRANSFORM->GetWorldScale(); + + colliderComponent.RecomputeCollisionShapes(); + } + } + } + + #else + + // Always sync Rigid Body & Collider Components with Physics Objects + // Do not check for an editor here + + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + + syncOnPlay(entityID, physicsObject); + } + + #endif } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -125,18 +131,18 @@ namespace SHADE SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); } - fixedTimeStep = 1.0 / physicsSystem->fixedDT; + const double FIXED_DT = physicsSystem->fixedDT; accumulatedTime += dt; int count = 0; - while (accumulatedTime > fixedTimeStep) + while (accumulatedTime > FIXED_DT) { if (scriptingSystem != nullptr) scriptingSystem->ExecuteFixedUpdates(); - - physicsSystem->worldState.world->update(static_cast(fixedTimeStep)); - accumulatedTime -= fixedTimeStep; + physicsSystem->worldState.world->update(static_cast(FIXED_DT)); + + accumulatedTime -= FIXED_DT; ++count; } @@ -165,17 +171,14 @@ namespace SHADE auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - if (transformComponent) - { - postUpdateSyncTransforms - ( - physicsObject - , *transformComponent - , rigidBodyComponent - , colliderComponent - , physicsSystem->interpolationFactor - ); - } + postUpdateSyncTransforms + ( + physicsObject + , transformComponent + , rigidBodyComponent + , colliderComponent + , physicsSystem->interpolationFactor + ); } // Collision & Trigger messages @@ -191,6 +194,48 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + if (!SHComponentManager::HasComponent(eid)) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive(); + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE) + physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE); + } + + void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + const auto* COLLIDER = SHComponentManager::GetComponent_s(eid); + if (!COLLIDER) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive; + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE) + { + // HACK: If active state turned off, remove all collision shapes. If turned on, add them back. + auto* physicsSystem = reinterpret_cast(GetSystem()); + + const int NUM_SHAPES = static_cast(COLLIDER->GetCollisionShapes().size()); + if (IS_ACTIVE_IN_SCENE) + { + for (int i = 0; i < NUM_SHAPES; ++i) + physicsSystem->objectManager.AddCollisionShape(eid, i); + } + else + { + for (int i = NUM_SHAPES - 1; i >= 0; --i) + physicsSystem->objectManager.RemoveCollisionShape(eid, i); + } + + physicsObject.collidersActive = IS_ACTIVE_IN_SCENE; + } + } + void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept { auto* transformComponent = SHComponentManager::GetComponent_s(eid); @@ -203,7 +248,7 @@ namespace SHADE preUpdateSyncTransform ( physicsObject - , *transformComponent + , transformComponent , rigidBodyComponent , colliderComponent ); @@ -221,25 +266,29 @@ namespace SHADE void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform ( SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent + , SHTransformComponent* transformComponent , SHRigidBodyComponent* rigidBodyComponent , SHColliderComponent* colliderComponent ) noexcept { - const SHVec3& WORLD_POS = transformComponent.GetWorldPosition(); - const SHQuaternion& WORLD_ROT = transformComponent.GetWorldOrientation(); - const SHVec3& WORLD_SCL = transformComponent.GetWorldScale(); + if (!transformComponent) + return; + + const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation(); + const SHVec3& WORLD_SCL = transformComponent->GetWorldScale(); const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); + physicsObject.prevTransform = RP3D_TRANSFORM; - if (rigidBodyComponent) + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->orientation = WORLD_ROT; } - if (colliderComponent) + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { colliderComponent->position = WORLD_POS; colliderComponent->orientation = WORLD_ROT; @@ -252,25 +301,28 @@ namespace SHADE void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms ( SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent + , SHTransformComponent* transformComponent , SHRigidBodyComponent* rigidBodyComponent , SHColliderComponent* colliderComponent , double interpolationFactor ) noexcept { - rp3d::Vector3 rp3dPos; - rp3d::Quaternion rp3dRot; + const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); + auto renderPos = CURRENT_TF.getPosition(); + auto renderRot = CURRENT_TF.getOrientation(); - const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); + // Cache transforms + if (physicsObject.GetRigidBody()->isActive()) + physicsObject.prevTransform = CURRENT_TF; - // Check if transform should be interpolated - - if (rigidBodyComponent) + // Sync with rigid bodies + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { // Skip static bodies if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) return; + // Check if transform should be interpolated if (rigidBodyComponent->IsInterpolating()) { // Interpolate transforms between current and predicted next transform @@ -278,38 +330,26 @@ namespace SHADE const rp3d::Transform PREV_TF = physicsObject.prevTransform; const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); - rp3dPos = INTERPOLATED_TF.getPosition(); - rp3dRot = INTERPOLATED_TF.getOrientation(); - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); + renderPos = INTERPOLATED_TF.getPosition(); + renderRot = INTERPOLATED_TF.getOrientation(); } rigidBodyComponent->position = CURRENT_TF.getPosition(); rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - - if (colliderComponent) - { - // Sync with colliders - - colliderComponent->position = CURRENT_TF.getPosition(); - colliderComponent->orientation = CURRENT_TF.getOrientation(); - } } - else + + // Sync with colliders + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); } - // Convert RP3D Transform to SHADE - transformComponent.SetWorldPosition(rp3dPos); - transformComponent.SetWorldOrientation(rp3dRot); - - // Cache transforms - physicsObject.prevTransform = CURRENT_TF; + // Set transform for rendering + if (transformComponent) + { + transformComponent->SetWorldPosition(renderPos); + transformComponent->SetWorldOrientation(renderRot); + } } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.h b/SHADE_Engine/src/Resource/SHResourceLibrary.h index 46ae4572..a6f772fe 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.h +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.h @@ -38,6 +38,11 @@ namespace SHADE class SHResourceLibrary : public SHResourceLibraryBase { public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + using dense_iterator = typename SparseSet::dense_iterator; + /*-----------------------------------------------------------------------------*/ /* Constructor */ /*-----------------------------------------------------------------------------*/ @@ -74,6 +79,16 @@ namespace SHADE /// Read-only reference to the resource object. const T& Get(Handle handle) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Pair of begin and end iterators to the dense vector. + std::pair GetDenseAccess(); + private: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -96,6 +111,12 @@ namespace SHADE class SHResourceHub final { public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + template + using dense_iterator = typename SHResourceLibrary::dense_iterator; + /*-----------------------------------------------------------------------------*/ /* Constructors/Destructors */ /*-----------------------------------------------------------------------------*/ @@ -138,6 +159,18 @@ namespace SHADE template const T& Get(Handle handle) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Type of resource to access. + /// Pair of begin and end iterators to the dense vector. + template + std::pair, dense_iterator> GetDenseAccess(); + private: /*-----------------------------------------------------------------------------*/ /* Type Definition */ diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp index 411f6bf5..98ad91a3 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp @@ -79,6 +79,15 @@ namespace SHADE return objects[handle.GetId().Data.Index]; } + /*---------------------------------------------------------------------------------*/ + /* ResourceLibrary - Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair::dense_iterator, typename SHResourceLibrary::dense_iterator> SHResourceLibrary::GetDenseAccess() + { + return objects.GetDenseAccess(); + } + /*---------------------------------------------------------------------------------*/ /* ResourceLibrary - Helper Functions */ /*---------------------------------------------------------------------------------*/ @@ -105,7 +114,7 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* ResourceManager - Usage Functions */ + /* ResourceHub - Usage Functions */ /*---------------------------------------------------------------------------------*/ template Handle SHResourceHub::Create(Args&&... args) @@ -132,7 +141,7 @@ namespace SHADE } /*-----------------------------------------------------------------------------*/ - /* ResourceManager - Helper Functions */ + /* ResourceHub - Helper Functions */ /*-----------------------------------------------------------------------------*/ template SHResourceLibrary& SHResourceHub::getLibrary() @@ -161,4 +170,13 @@ namespace SHADE { return const_cast(this).getLibrary(); } + + /*---------------------------------------------------------------------------------*/ + /* ResourceHub - Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair, typename SHResourceHub::dense_iterator> SHResourceHub::GetDenseAccess() + { + return getLibrary().GetDenseAccess(); + } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.cpp b/SHADE_Engine/src/Resource/SHResourceManager.cpp index dad9fd9f..077835f5 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.cpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.cpp @@ -103,4 +103,17 @@ namespace SHADE return {}; } + + std::optional SHResourceManager::GetAssetName(Handle handle) + { + const Handle GENERIC_HANDLE = Handle(handle); + auto assetId = GetAssetID(GENERIC_HANDLE); + if (assetId.has_value()) + { + const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); + if (ASSET_INFO.has_value()) + return ASSET_INFO.value().name; + } + return {}; + } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index d660ada7..dae20f99 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -13,8 +13,6 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include - -namespace SHADE { class SHMaterial; } // Project Includes #include "SH_API.h" #include "SHResourceLibrary.h" @@ -31,17 +29,26 @@ namespace SHADE { class SHMaterial; } namespace SHADE { + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHMaterial; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ /// /// Template structs that maps a resource to their loaded asset representation type. /// template struct SHResourceLoader { using AssetType = void; }; - template<> struct SHResourceLoader { using AssetType = SHMeshData; }; + template<> struct SHResourceLoader { using AssetType = SHMeshData; }; template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; -/// + + /// /// Static class responsible for loading and caching runtime resources from their /// serialised Asset IDs. /// @@ -57,9 +64,7 @@ namespace SHADE /// Note that for specific types, the retrieved Handle may not be valid until after /// FinaliseChanges() is called. /// - /// - /// Type of resource to load. - /// + /// Type of resource to load. /// Asset ID of the resource to load. /// Handle to a loaded runtime asset. template @@ -67,6 +72,17 @@ namespace SHADE template<> static inline Handle LoadOrGet(AssetID assetId); /// + /// Retrieves an existing loaded object of the specified type if it has already been + /// loaded prior. + /// + /// Type of resource to load. + /// Asset ID of the resource to retrieve. + /// + /// Handle to a loaded runtime asset. Null handle if not loaded before. + /// + template + static Handle Get(AssetID assetId); + /// /// Unloads an existing loaded asset. Attempting to unload an invalid Handle will /// simply do nothing except emit a warning. /// Faster than the untemplated version. @@ -114,6 +130,31 @@ namespace SHADE /// value. /// static std::optional GetAssetID(Handle handle); + /// + /// Retrieves the name associated with the AssetID that is associated with the + /// specified Handle. + /// Faster than the untemplated version. + /// + /// Type of resource to get the name of. + /// Handle to get the name of. + /// + /// Name for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + template + static std::optional GetAssetName(Handle handle); + /// + /// Retrieves the name associated with the AssetID that is associated with the + /// specified Handle. + /// Compared to the templated version, this function is slower as it requires + /// searching through the storage of all resource types. + /// + /// Handle to get the name of. + /// + /// Name for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + static std::optional GetAssetName(Handle handle); private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index 01d82a7b..d0488e66 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/Asset Types/SHAssetIncludes.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "ECS_Base/Managers/SHSystemManager.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" @@ -93,6 +93,16 @@ namespace SHADE return handle; } + template + Handle SHResourceManager::Get(AssetID assetId) + { + auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); + if (typedHandleMap.get().contains(assetId)) + return Handle(typedHandleMap.get()[assetId]); + else + return Handle(); + } + template void SHResourceManager::Unload(Handle asset) { @@ -139,6 +149,18 @@ namespace SHADE return {}; } + template + std::optional SHADE::SHResourceManager::GetAssetName(Handle handle) + { + auto assetId = GetAssetID(handle); + if (assetId.has_value()) + { + const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); + if (ASSET_INFO.has_value()) + return ASSET_INFO.value().name; + } + return {}; + } /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Resource/SparseSet.h b/SHADE_Engine/src/Resource/SparseSet.h index fb4a8311..3d763b01 100644 --- a/SHADE_Engine/src/Resource/SparseSet.h +++ b/SHADE_Engine/src/Resource/SparseSet.h @@ -49,6 +49,7 @@ namespace SHADE using const_pointer = const T*; using reference = T&; using const_reference = const T&; + using dense_iterator = typename std::vector::iterator; /*-----------------------------------------------------------------------------*/ /* Constructors/Destructors */ @@ -59,10 +60,6 @@ namespace SHADE SparseSet(); ~SparseSet() = default; - //// Disallow moving or copying - //SparseSet(const SparseSet&) = delete; - //SparseSet(SparseSet&&) = delete; - /*-----------------------------------------------------------------------------*/ /* Usage Functions */ /*-----------------------------------------------------------------------------*/ @@ -192,6 +189,16 @@ namespace SHADE /// const T& operator[](index_type idx) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Pair of begin and end iterators to the dense vector. + std::pair GetDenseAccess(); + protected: /*-----------------------------------------------------------------------------*/ /* Constants */ diff --git a/SHADE_Engine/src/Resource/SparseSet.hpp b/SHADE_Engine/src/Resource/SparseSet.hpp index 816ca432..b6c7a511 100644 --- a/SHADE_Engine/src/Resource/SparseSet.hpp +++ b/SHADE_Engine/src/Resource/SparseSet.hpp @@ -143,4 +143,13 @@ namespace SHADE { return at(idx); } + + /*---------------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair::dense_iterator, typename SparseSet::dense_iterator> SparseSet::GetDenseAccess() + { + return { denseArray.begin(), denseArray.end() }; + } } \ No newline at end of file diff --git a/SHADE_Engine/src/SHpch.h b/SHADE_Engine/src/SHpch.h index 7e308829..31553611 100644 --- a/SHADE_Engine/src/SHpch.h +++ b/SHADE_Engine/src/SHpch.h @@ -37,5 +37,5 @@ #include #include "Common/SHCommonTypes.h" -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" #include "Tools/SHException.h" diff --git a/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp b/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp index 6226949e..955a8474 100644 --- a/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp +++ b/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include // External Dependencies #include // PathRemoveFileSpecA -#include "Tools/SHLogger.h" +#include "Tools/Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 9d3ad3e8..84b50373 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -19,8 +19,8 @@ of DigiPen Institute of Technology is prohibited. #include // std::shared_ptr #include // std::this_thread::sleep_for // Project Headers -#include "Tools/SHLogger.h" -#include "Tools/SHStringUtils.h" +#include "Tools/Logger/SHLogger.h" +#include "Tools/Utilities/SHStringUtilities.h" #include "ECS_Base/Events/SHEntityDestroyedEvent.h" #include "Events/SHEvent.h" #include "Events/SHEventReceiver.h" @@ -58,10 +58,9 @@ namespace SHADE loadFunctions(); // Generate script assembly if it hasn't been before - if (!fileExists(std::string(MANAGED_SCRIPT_LIB_NAME) + ".dll")) - { - BuildScriptAssembly(); - } +#ifndef _PUBLISH + BuildScriptAssembly(); +#endif // Initialise the CSharp Engine csEngineInit(); @@ -272,6 +271,7 @@ namespace SHADE \n\ \n\ \n\ + \n\ \n\ \n\ \n"; @@ -306,7 +306,7 @@ namespace SHADE SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr) { auto eventData = reinterpret_cast*>(eventPtr.get()); - csScriptsRemoveAll(eventData->data->eid); + csScriptsRemoveAllImmediately(eventData->data->eid, true); return eventData->handle; } @@ -615,7 +615,7 @@ namespace SHADE auto err = GetLastError(); std::ostringstream oss; oss << "[ScriptEngine] Failed to launch process. Error code: " << std::hex << err - << " (" << SHStringUtils::GetWin32ErrorMessage(err) << ")"; + << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; throw std::runtime_error(oss.str()); } @@ -629,7 +629,7 @@ namespace SHADE auto err = GetLastError(); std::ostringstream oss; oss << "[ScriptEngine] Failed to query process. Error code: " << std::hex << err - << " (" << SHStringUtils::GetWin32ErrorMessage(err) << ")"; + << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; throw std::runtime_error(oss.str()); } @@ -646,7 +646,7 @@ namespace SHADE std::wstring SHScriptEngine::generateBuildCommand(bool debug) { std::wostringstream oss; - oss << "dotnet build \"" << SHStringUtils::StrToWstr(CSPROJ_PATH) << "\" -c "; + oss << "dotnet build \"" << SHStringUtilities::StrToWstr(CSPROJ_PATH) << "\" -c "; oss << debug ? "Debug" : "Release"; oss << " -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet -r \"win-x64\""; return oss.str(); diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 8e4e350c..3ed96d7d 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -12,8 +12,8 @@ #include "Assets/Asset Types/SHSceneAsset.h" #include "Camera/SHCameraComponent.h" -#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Math/Transform/SHTransformComponent.h" +#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Physics/Interface/SHRigidBodyComponent.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" @@ -179,7 +179,9 @@ namespace SHADE { if (ComponentType* component = SHComponentManager::GetComponent_s(eid)) { - componentsNode[rttr::type::get().get_name().data()] = YAML::convert::encode(*component); + auto componentNode = YAML::convert::encode(*component); + componentNode[IsActive.data()] = component->isActive; + componentsNode[rttr::type::get().get_name().data()] = componentNode; } } diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index b062b348..b560acae 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -9,11 +9,13 @@ #include "ECS_Base/Managers/SHComponentManager.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" namespace SHADE { + static constexpr std::string_view IsActive = "IsActive"; + using AssetQueue = std::unordered_map; struct SHSerializationHelper { @@ -118,9 +120,9 @@ namespace SHADE YAML::Node node{}; if (!component) return node; - auto componentType = rttr::type::get(); node = RTTRToNode(*component); + node[IsActive.data()] = component->isActive; return node; } @@ -198,6 +200,9 @@ namespace SHADE auto componentNode = componentsNode[rttrType.get_name().data()]; if (!componentNode.IsDefined()) return; + if(componentNode[IsActive.data()].IsDefined()) + component->isActive = componentNode[IsActive.data()].as(); + auto properties = rttrType.get_properties(); for (auto const& prop : properties) { @@ -227,8 +232,10 @@ namespace SHADE auto component = SHComponentManager::GetComponent_s(eid); if (componentsNode.IsNull() && !component) return; - - YAML::convert::decode(GetComponentNode(componentsNode, eid), *component); + auto componentNode = GetComponentNode(componentsNode, eid); + if (componentNode[IsActive.data()].IsDefined()) + component->isActive = componentNode[IsActive.data()].as(); + YAML::convert::decode(componentNode, *component); } template , bool> = true> diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 0f8933e2..d66a7506 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -1,8 +1,8 @@ #pragma once #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Physics/Interface/SHCollisionShape.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" @@ -130,13 +130,13 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - const auto* BOX = reinterpret_cast(rhs.GetShape()); + const auto* BOX = reinterpret_cast(rhs.GetShape()); node[HalfExtents] = BOX->GetRelativeExtents(); } break; case SHCollisionShape::Type::SPHERE: { - const auto* SPHERE = reinterpret_cast(rhs.GetShape()); + const auto* SPHERE = reinterpret_cast(rhs.GetShape()); node[Radius] = SPHERE->GetRelativeRadius(); } break; @@ -288,7 +288,15 @@ namespace YAML { YAML::Node node; node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMesh()).value_or(0); - node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMaterial()->GetBaseMaterial()).value_or(0); + auto mat = rhs.GetMaterial(); + if (mat) + { + node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMaterial()->GetBaseMaterial()).value_or(0); + } + else + { + node[MAT_YAML_TAG.data()] = 0; + } return node; } static bool decode(YAML::Node const& node, SHRenderable& rhs) diff --git a/SHADE_Engine/src/Tools/SHLog.cpp b/SHADE_Engine/src/Tools/Logger/SHLog.cpp similarity index 93% rename from SHADE_Engine/src/Tools/SHLog.cpp rename to SHADE_Engine/src/Tools/Logger/SHLog.cpp index 30a79338..139a731e 100644 --- a/SHADE_Engine/src/Tools/SHLog.cpp +++ b/SHADE_Engine/src/Tools/Logger/SHLog.cpp @@ -44,13 +44,6 @@ namespace SHADE SHLOG_FLOOR() } -#ifdef _DEBUG - void SHLog::Trace(const std::string& msg) noexcept - { - SHLOG_TRACE(msg) - } -#endif - void SHLog_Info(const char* msg) noexcept { SHLOG_INFO(msg) diff --git a/SHADE_Engine/src/Tools/SHLog.h b/SHADE_Engine/src/Tools/Logger/SHLog.h similarity index 100% rename from SHADE_Engine/src/Tools/SHLog.h rename to SHADE_Engine/src/Tools/Logger/SHLog.h diff --git a/SHADE_Engine/src/Tools/SHLogger.cpp b/SHADE_Engine/src/Tools/Logger/SHLogger.cpp similarity index 95% rename from SHADE_Engine/src/Tools/SHLogger.cpp rename to SHADE_Engine/src/Tools/Logger/SHLogger.cpp index 9c1e76fc..72791eb1 100644 --- a/SHADE_Engine/src/Tools/SHLogger.cpp +++ b/SHADE_Engine/src/Tools/Logger/SHLogger.cpp @@ -323,34 +323,6 @@ namespace SHADE SHLOG_FLOOR() } - #ifdef _DEBUG - void SHLogger::LogTrace(const std::string& msg) noexcept - { - SHLOG_TRACE(msg) - } - - void SHLogger::LogVerboseTrace(const std::string& msg, const std::source_location& src) noexcept - { - const bool SHOW_SRC_FILE = configFlags & (1U << 3); - const bool SHOW_SRC_LINE = configFlags & (1U << 4); - - std::stringstream ss; - ss << "["; - if (SHOW_SRC_FILE) - { - ss << std::filesystem::path(src.file_name()).filename().string() << ", "; - if (SHOW_SRC_LINE) - { - ss << src.line() << ", "; - } - } - - ss << src.function_name() << "] " << msg; - - SHLOG_TRACE(ss.str()) - } - #endif - /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Tools/SHLogger.h b/SHADE_Engine/src/Tools/Logger/SHLogger.h similarity index 88% rename from SHADE_Engine/src/Tools/SHLogger.h rename to SHADE_Engine/src/Tools/Logger/SHLogger.h index e4a4928c..1a14df9c 100644 --- a/SHADE_Engine/src/Tools/SHLogger.h +++ b/SHADE_Engine/src/Tools/Logger/SHLogger.h @@ -177,8 +177,34 @@ namespace SHADE /*-------------------------------------------------------------------------------------*/ #ifdef _DEBUG - #define SHLOG_TRACE(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); - #define SHLOGV_TRACE(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + + #define SHLOG_INFO_D(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + #define SHLOGV_INFO_D(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + + #define SHLOG_WARNING_D(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + #define SHLOGV_WARNING_D(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + + #define SHLOG_ERROR_D(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + #define SHLOGV_ERROR_D(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + + #define SHLOG_CRITICAL_D(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + #define SHLOGV_CRITICAL_D(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); + +#else + + #define SHLOG_INFO_D(format, ...) + #define SHLOGV_INFO_D(format, ...) + + #define SHLOG_WARNING_D(format, ...) + #define SHLOGV_WARNING_D(format, ...) + + #define SHLOG_ERROR_D(format, ...) + #define SHLOGV_ERROR_D(format, ...) + + #define SHLOG_CRITICAL_D(format, ...) + #define SHLOGV_CRITICAL_D(format, ...) + + #endif #define SHLOG_INFO(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__); diff --git a/SHADE_Engine/src/Tools/SHException.h b/SHADE_Engine/src/Tools/SHException.h index 2e0b82a9..ac6a11b7 100644 --- a/SHADE_Engine/src/Tools/SHException.h +++ b/SHADE_Engine/src/Tools/SHException.h @@ -18,7 +18,7 @@ #include // Project Headers -#include "SHLogger.h" +#include "Logger/SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Tools/SHExceptionHandler.cpp b/SHADE_Engine/src/Tools/SHExceptionHandler.cpp index ff6df05c..a4892321 100644 --- a/SHADE_Engine/src/Tools/SHExceptionHandler.cpp +++ b/SHADE_Engine/src/Tools/SHExceptionHandler.cpp @@ -12,10 +12,8 @@ // Primary Header #include "SHExceptionHandler.h" - // Project Headers #include "SHException.h" -#include "SHLogger.h" namespace SHADE { diff --git a/SHADE_Engine/src/Tools/SHClipboardUtilities.cpp b/SHADE_Engine/src/Tools/Utilities/SHClipboardUtilities.cpp similarity index 100% rename from SHADE_Engine/src/Tools/SHClipboardUtilities.cpp rename to SHADE_Engine/src/Tools/Utilities/SHClipboardUtilities.cpp diff --git a/SHADE_Engine/src/Tools/SHClipboardUtilities.h b/SHADE_Engine/src/Tools/Utilities/SHClipboardUtilities.h similarity index 100% rename from SHADE_Engine/src/Tools/SHClipboardUtilities.h rename to SHADE_Engine/src/Tools/Utilities/SHClipboardUtilities.h diff --git a/SHADE_Engine/src/Tools/SHFileUtilties.cpp b/SHADE_Engine/src/Tools/Utilities/SHFileUtilties.cpp similarity index 100% rename from SHADE_Engine/src/Tools/SHFileUtilties.cpp rename to SHADE_Engine/src/Tools/Utilities/SHFileUtilties.cpp diff --git a/SHADE_Engine/src/Tools/SHFileUtilties.h b/SHADE_Engine/src/Tools/Utilities/SHFileUtilties.h similarity index 100% rename from SHADE_Engine/src/Tools/SHFileUtilties.h rename to SHADE_Engine/src/Tools/Utilities/SHFileUtilties.h diff --git a/SHADE_Engine/src/Tools/SHStringUtils.cpp b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.cpp similarity index 79% rename from SHADE_Engine/src/Tools/SHStringUtils.cpp rename to SHADE_Engine/src/Tools/Utilities/SHStringUtilities.cpp index a2594888..b1e4aa92 100644 --- a/SHADE_Engine/src/Tools/SHStringUtils.cpp +++ b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.cpp @@ -1,5 +1,5 @@ /************************************************************************************//*! -\file StringUtilities.cpp +\file SHStringUtilities.cpp \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Nov 29, 2021 @@ -12,22 +12,22 @@ of DigiPen Institute of Technology is prohibited. // Precompiled Header #include // Primary Header -#include "SHStringUtils.h" +#include "SHStringUtilities.h" namespace SHADE { /*---------------------------------------------------------------------------------*/ /* Utility Functions */ /*---------------------------------------------------------------------------------*/ - std::vector SHStringUtils::Split(const std::string& str, const char& delim) + std::vector SHStringUtilities::Split(const std::string& str, const char& delim) { return Split(str, delim); } - std::vector SHStringUtils::Split(const std::wstring& str, const wchar_t& delim) + std::vector SHStringUtilities::Split(const std::wstring& str, const wchar_t& delim) { return Split(str, delim); } - std::string SHStringUtils::WstrToStr(const std::wstring& wstr) + std::string SHStringUtilities::WstrToStr(const std::wstring& wstr) { static std::vector buffer; const int STR_SIZE = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.size()), nullptr, 0, nullptr, nullptr) + 1 /* Null Terminator */; @@ -35,7 +35,7 @@ namespace SHADE WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.size()), buffer.data(), MAX_PATH, nullptr, nullptr); return std::string(buffer.data()); } - std::wstring SHStringUtils::StrToWstr(const std::string& str) + std::wstring SHStringUtilities::StrToWstr(const std::string& str) { static std::vector buffer; const int WSTR_SIZE = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0) + 1 /* Null Terminator */; @@ -44,7 +44,7 @@ namespace SHADE return std::wstring(buffer.data()); } - std::string SHStringUtils::GetWin32ErrorMessage(unsigned long errorCode) + std::string SHStringUtilities::GetWin32ErrorMessage(unsigned long errorCode) { return std::system_category().message(errorCode); } diff --git a/SHADE_Engine/src/Tools/SHStringUtils.h b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.h similarity index 96% rename from SHADE_Engine/src/Tools/SHStringUtils.h rename to SHADE_Engine/src/Tools/Utilities/SHStringUtilities.h index 1c895b99..bac83b07 100644 --- a/SHADE_Engine/src/Tools/SHStringUtils.h +++ b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.h @@ -1,5 +1,5 @@ /************************************************************************************//*! -\file StringUtilities.h +\file SHStringUtilities.h \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Nov 29, 2021 @@ -19,7 +19,7 @@ namespace SHADE /// /// Contains useful functions for operating on strings. /// - class SHStringUtils + class SHStringUtilities { public: /*-----------------------------------------------------------------------------*/ @@ -74,8 +74,8 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ /* Constructors/Destructors */ /*-------------------------------------------------------------------------------*/ - SHStringUtils() = delete; + SHStringUtilities() = delete; }; } -#include "SHStringUtils.hpp" +#include "SHStringUtilities.hpp" diff --git a/SHADE_Engine/src/Tools/SHStringUtils.hpp b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.hpp similarity index 89% rename from SHADE_Engine/src/Tools/SHStringUtils.hpp rename to SHADE_Engine/src/Tools/Utilities/SHStringUtilities.hpp index 8b83187a..2e29c684 100644 --- a/SHADE_Engine/src/Tools/SHStringUtils.hpp +++ b/SHADE_Engine/src/Tools/Utilities/SHStringUtilities.hpp @@ -1,5 +1,5 @@ /************************************************************************************//*! -\file StringUtilities.hpp +\file SHStringUtilities.hpp \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Nov 29, 2021 @@ -12,7 +12,7 @@ of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ #pragma once // Primary Header -#include "SHStringUtils.h" +#include "SHStringUtilities.h" namespace SHADE { @@ -20,7 +20,7 @@ namespace SHADE /* Template Function Definitions */ /*-------------------------------------------------------------------------------*/ template - inline std::vector> SHStringUtils::Split(const std::basic_string& str, const T& delim) + inline std::vector> SHStringUtilities::Split(const std::basic_string& str, const T& delim) { std::vector> results; std::basic_string remaining = str; diff --git a/SHADE_Engine/src/Tools/SHUtilities.h b/SHADE_Engine/src/Tools/Utilities/SHUtilities.h similarity index 100% rename from SHADE_Engine/src/Tools/SHUtilities.h rename to SHADE_Engine/src/Tools/Utilities/SHUtilities.h diff --git a/SHADE_Engine/src/Tools/SHUtilities.hpp b/SHADE_Engine/src/Tools/Utilities/SHUtilities.hpp similarity index 100% rename from SHADE_Engine/src/Tools/SHUtilities.hpp rename to SHADE_Engine/src/Tools/Utilities/SHUtilities.hpp diff --git a/SHADE_Managed/premake5.lua b/SHADE_Managed/premake5.lua index 88021071..2384cae8 100644 --- a/SHADE_Managed/premake5.lua +++ b/SHADE_Managed/premake5.lua @@ -39,13 +39,15 @@ project "SHADE_Managed" "%{IncludeDir.dotnet}\\include", "%{IncludeDir.reactphysics3d}\\include", "%{IncludeDir.VULKAN}\\include", + "%{IncludeDir.fmod}\\include", "%{wks.location}/SHADE_Engine/src" } libdirs { "%{IncludeDir.RTTR}/lib", - "%{IncludeDir.SDL}/lib" + "%{IncludeDir.SDL}/lib", + "%{IncludeDir.fmod}/lib" } links @@ -75,7 +77,8 @@ project "SHADE_Managed" disablewarnings { - "4275" + "4275", + "4635" } @@ -92,13 +95,28 @@ project "SHADE_Managed" symbols "On" defines {"_DEBUG"} links{"librttr_core_d.lib"} + links{"fmodstudioL_vc.lib", "fmodL_vc.lib"} filter "configurations:Release" optimize "On" defines{"_RELEASE"} links{"librttr_core.lib"} + links{"fmodstudio_vc.lib", "fmod_vc.lib"} filter "configurations:Publish" optimize "On" defines{"_RELEASE"} links{"librttr_core.lib"} + links{"fmodstudio_vc.lib", "fmod_vc.lib"} + + require "vstudio" + + function docsElementCPP(cfg) + _p(3,'true') + end + + premake.override(premake.vstudio.vc2010.elements, "clCompile", function (oldfn, cfg) + return table.join(oldfn(cfg), { + docsElementCPP, + }) + end) \ No newline at end of file diff --git a/SHADE_Managed/src/Audio/Audio.cxx b/SHADE_Managed/src/Audio/Audio.cxx new file mode 100644 index 00000000..52e29529 --- /dev/null +++ b/SHADE_Managed/src/Audio/Audio.cxx @@ -0,0 +1,101 @@ +/************************************************************************************//*! +\file Audio.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Nov 16, 2022 +\brief Contains the function definitions of the managed Audio static class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Header +#include "SHpch.h" +// Primary Header +#include "Audio.hxx" +// External Dependencies +#include "AudioSystem/SHAudioSystem.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Utility/Convert.hxx" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + float Audio::BGMVolume::get() + { + auto audioSys = SHSystemManager::GetSystem(); + return audioSys->GetBgmVolume(); + } + void Audio::BGMVolume::set(float value) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->SetBgmVolume(System::Math::Clamp(value, 0.0f, 1.0f)); + } + float Audio::SFXVolume::get() + { + auto audioSys = SHSystemManager::GetSystem(); + return audioSys->GetSfxVolume(); + } + void Audio::SFXVolume::set(float value) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->SetSfxVolume(System::Math::Clamp(value, 0.0f, 1.0f)); + } + float Audio::MasterVolume::get() + { + auto audioSys = SHSystemManager::GetSystem(); + return audioSys->GetMasterVolume(); + } + void Audio::MasterVolume::set(float value) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->SetMasterVolume(System::Math::Clamp(value, 0.0f, 1.0f)); + } + bool Audio::IsPaused::get() + { + auto audioSys = SHSystemManager::GetSystem(); + return audioSys->GetPaused(); + } + void Audio::IsPaused::set(bool value) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->SetPaused(value); + } + + /*-----------------------------------------------------------------------------*/ + /* Playback Control Functions */ + /*-----------------------------------------------------------------------------*/ + void Audio::PlaySFXOnce2D(System::String^ path) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->PlayEventOnce(Convert::ToNative(path).data()); + } + + void Audio::PlaySFXOnce3D(System::String^ path, GameObject gameObject) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->PlayEventOnce(Convert::ToNative(path).data(), true, gameObject.GetEntity(), true); + } + + void Audio::PlayBGMOnce2D(System::String^ path) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->PlayEventOnce(Convert::ToNative(path).data(), false); + } + + void Audio::PlayBGMOnce3D(System::String^ path, GameObject gameObject) + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->PlayEventOnce(Convert::ToNative(path).data(), false, gameObject.GetEntity(), true); + } + + void Audio::StopAllSounds() + { + auto audioSys = SHSystemManager::GetSystem(); + audioSys->StopAllSounds(); + } +} diff --git a/SHADE_Managed/src/Audio/Audio.hxx b/SHADE_Managed/src/Audio/Audio.hxx new file mode 100644 index 00000000..d568dc90 --- /dev/null +++ b/SHADE_Managed/src/Audio/Audio.hxx @@ -0,0 +1,103 @@ +/************************************************************************************//*! +\file Audio.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Nov 16, 2022 +\brief Contains the definitions of the managed Audio static class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once +#include "Engine/GameObject.hxx" + +namespace SHADE +{ + /// + /// Static class that contains the functions for interfacing with the Audio system. + /// + public ref class Audio abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Volume of background music playback. Clamped between 0.0 and 1.0. + /// + static property float BGMVolume + { + float get(); + void set(float value); + } + /// + /// Volume of sound effects playback. Clamped between 0.0 and 1.0. + /// + static property float SFXVolume + { + float get(); + void set(float value); + } + /// + /// Overall volume for all audio playback. Clamped between 0.0 and 1.0. + /// + static property float MasterVolume + { + float get(); + void set(float value); + } + /// + /// Whether or not all audio playback is paused. + /// + static property bool IsPaused + { + bool get(); + void set(bool value); + } + + /*-----------------------------------------------------------------------------*/ + /* Playback Control Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Plays a sound effect without looping without spatial attenuation. + /// + /// + /// Path to the audio file relative to the working directory. + /// + static void PlaySFXOnce2D(System::String^ path); + /// + /// Plays a sound effect without looping with spatial attenuation. + /// + /// + /// Path to the audio file relative to the working directory. + /// + /// + /// Object whose position is used to play the sound effect. + /// + static void PlaySFXOnce3D(System::String^ path, GameObject gameObject); + /// + /// Plays background music without looping without spatial attenuation. + /// + /// + /// Path to the audio file relative to the working directory. + /// + static void PlayBGMOnce2D(System::String^ path); + /// + /// Plays background music without looping with spatial attenuation. + /// + /// + /// Path to the audio file relative to the working directory. + /// + /// + /// Object whose position is used to play the background music. + /// + static void PlayBGMOnce3D(System::String^ path, GameObject gameObject); + /// + /// Stops playback of all sound effects and music. + /// + static void StopAllSounds(); + }; +} diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index 0e916b7b..41910d66 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /*---------------------------------------------------------------------------------*/ - /* ColliderBound - Constructors */ + /* CollisionShape - Constructors */ /*---------------------------------------------------------------------------------*/ CollisionShape::CollisionShape(int arrayIdx, Entity attachedEntity) : arrayIndex { arrayIdx } @@ -28,102 +28,183 @@ namespace SHADE {} /*---------------------------------------------------------------------------------*/ - /* ColliderBound - Setter Functions */ + /* CollisionShape - Properties */ + /*---------------------------------------------------------------------------------*/ + + bool CollisionShape::IsTrigger::get() + { + return getNativeCollisionShape().IsTrigger(); + } + + void CollisionShape::IsTrigger::set(bool value) + { + getNativeCollisionShape().SetIsTrigger(value); + } + + Vector3 CollisionShape::PositionOffset::get() + { + return Convert::ToCLI(getNativeCollisionShape().GetPositionOffset()); + } + + void CollisionShape::PositionOffset::set(Vector3 value) + { + getNativeCollisionShape().SetPositionOffset(Convert::ToNative(value)); + } + + Vector3 CollisionShape::RotationOffset::get() + { + return Convert::ToCLI(getNativeCollisionShape().GetRotationOffset()); + } + + void CollisionShape::RotationOffset::set(Vector3 value) + { + getNativeCollisionShape().SetRotationOffset(Convert::ToNative(value)); + } + + float CollisionShape::Friction::get() + { + return getNativeCollisionShape().GetFriction(); + } + + void CollisionShape::Friction::set(float value) + { + getNativeCollisionShape().SetFriction(value); + } + + float CollisionShape::Bounciness::get() + { + return getNativeCollisionShape().GetBounciness(); + } + + void CollisionShape::Bounciness::set(float value) + { + getNativeCollisionShape().SetBounciness(value); + } + + float CollisionShape::Density::get() + { + return getNativeCollisionShape().GetDensity(); + } + + void CollisionShape::Density::set(float value) + { + getNativeCollisionShape().SetDensity(value); + } + + /*---------------------------------------------------------------------------------*/ + /* CollisionShape - helper Functions */ /*---------------------------------------------------------------------------------*/ void CollisionShape::updateArrayIndex(int index) { arrayIndex = index; } + SHCollisionShape& SHADE::CollisionShape::getNativeCollisionShape() + { + SHColliderComponent* collider = SHComponentManager::GetComponent_s(entity); + if (!collider) + throw gcnew System::InvalidOperationException("Unable to retrieve Collider component!"); + + try + { + auto& shape = collider->GetCollisionShape(arrayIndex); + return shape; + } + catch (std::invalid_argument&) + { + throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range CollisionShape!"); + } + } + /*---------------------------------------------------------------------------------*/ - /* BoxColliderBound - Constructors */ + /* BoxCollider - Constructors */ /*---------------------------------------------------------------------------------*/ BoxCollider::BoxCollider(int arrayIdx, Entity attachedEntity) : CollisionShape { arrayIndex, attachedEntity } {} /*---------------------------------------------------------------------------------*/ - /* BoxColliderBound - Properties */ + /* BoxCollider - Properties */ /*---------------------------------------------------------------------------------*/ Vector3 BoxCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeCollisionShape().GetCenter()); } void BoxCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeCollisionShape().SetCenter(Convert::ToNative(value)); } Vector3 BoxCollider::HalfExtents::get() { - return Convert::ToCLI(getNativeBoundObject().GetWorldExtents()); + return Convert::ToCLI(getNativeCollisionShape().GetWorldExtents()); } void BoxCollider::HalfExtents::set(Vector3 value) { - getNativeBoundObject().SetWorldExtents(Convert::ToNative(value)); + getNativeCollisionShape().SetWorldExtents(Convert::ToNative(value)); } Vector3 BoxCollider::Min::get() { - return Convert::ToCLI(getNativeBoundObject().GetMin()); + return Convert::ToCLI(getNativeCollisionShape().GetMin()); } void BoxCollider::Min::set(Vector3 value) { - getNativeBoundObject().SetMin(Convert::ToNative(value)); + getNativeCollisionShape().SetMin(Convert::ToNative(value)); } Vector3 BoxCollider::Max::get() { - return Convert::ToCLI(getNativeBoundObject().GetMax()); + return Convert::ToCLI(getNativeCollisionShape().GetMax()); } void BoxCollider::Max::set(Vector3 value) { - getNativeBoundObject().SetMax(Convert::ToNative(value)); + getNativeCollisionShape().SetMax(Convert::ToNative(value)); } /*---------------------------------------------------------------------------------*/ - /* BoxColliderBound - Usage Functions */ + /* BoxCollider - Usage Functions */ /*---------------------------------------------------------------------------------*/ bool BoxCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); } bool BoxCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeCollisionShape().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ - /* BoxColliderBound - Properties */ + /* SphereCollider - Properties */ /*---------------------------------------------------------------------------------*/ Vector3 SphereCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeCollisionShape().GetCenter()); } void SphereCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeCollisionShape().SetCenter(Convert::ToNative(value)); } float SphereCollider::Radius::get() { - return getNativeBoundObject().GetWorldRadius(); + return getNativeCollisionShape().GetWorldRadius(); } void SphereCollider::Radius::set(float value) { - getNativeBoundObject().SetWorldRadius(value); + getNativeCollisionShape().SetWorldRadius(value); } /*---------------------------------------------------------------------------------*/ - /* SphereColliderBound - Usage Functions */ + /* SphereCollider - Usage Functions */ /*---------------------------------------------------------------------------------*/ bool SphereCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); } bool SphereCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeCollisionShape().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ - /* SphereColliderBound - Constructors */ + /* SphereCollider - Constructors */ /*---------------------------------------------------------------------------------*/ SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity) : CollisionShape{ arrayIndex, attachedEntity } @@ -154,7 +235,7 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* Collider - ColliderBound Functions */ + /* Collider - Collider Functions */ /*---------------------------------------------------------------------------------*/ CollisionShape^ Collider::GetCollisionShape(int index) { @@ -166,7 +247,7 @@ namespace SHADE // Check if valid if (index < 0 || index >= subColliderList->Count) - throw gcnew System::ArgumentException("[Collider] Invalid index for Collider Bound retrieval."); + throw gcnew System::ArgumentException("[Collider] Invalid index for Collision Shape retrieval."); // Return the bound return subColliderList[index]; @@ -217,7 +298,7 @@ namespace SHADE { collidersList->Remove(wr); } - SAFE_NATIVE_CALL_END("Collider.OnColliderBoundChanged") + SAFE_NATIVE_CALL_END("Collider.OnCollisionShapeChanged") } void Collider::updateSubColliderList() diff --git a/SHADE_Managed/src/Components/Collider.h++ b/SHADE_Managed/src/Components/Collider.h++ index 6e165619..8ea648aa 100644 --- a/SHADE_Managed/src/Components/Collider.h++ +++ b/SHADE_Managed/src/Components/Collider.h++ @@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { template - CollisionShapeType& SHADE::CollisionShape::getNativeBoundObject() + CollisionShapeType& SHADE::CollisionShape::getNativeCollisionShape() { SHColliderComponent* collider = SHComponentManager::GetComponent_s(entity); if (!collider) @@ -29,13 +29,13 @@ namespace SHADE { auto& shape = collider->GetCollisionShape(arrayIndex); if (shape.GetType() != SHCollisionShape::Type::BOX) - throw gcnew System::InvalidOperationException("Attempted to retrieve invalid ColliderBound."); + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); return reinterpret_cast(shape); } catch (std::invalid_argument&) { - throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range ColliderBound!"); + throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range CollisionShape!"); } } } diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index 1711e8b9..a649483f 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -30,6 +30,61 @@ namespace SHADE public ref class CollisionShape abstract { public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Whether or not this CollisionShape is a trigger. + /// + property bool IsTrigger + { + bool get(); + void set(bool value); + } + /// + /// The positional offset of this collision shape from the transform's position. + /// + property Vector3 PositionOffset + { + Vector3 get(); + void set(Vector3 value); + } + /// + /// The rotational offset of this collision shape from the transform's rotation. + /// + property Vector3 RotationOffset + { + Vector3 get(); + void set(Vector3 value); + } + + // TODO(Diren): Swap this to Physics Materials once asset implementation for that is done + /// + /// The frictional coefficient of the shape. Clamped between 0 and 1. + /// + property float Friction + { + float get(); + void set(float value); + } + /// + /// The bounciness factor of the shape. Clamped between 0 and 1. + /// + property float Bounciness + { + float get(); + void set(float value); + } + /// + /// The mass density of this shape. Cannot be negative. + /// + property float Density + { + float get(); + void set(float value); + } + /*-----------------------------------------------------------------------------*/ /* Usage Functions */ /*-----------------------------------------------------------------------------*/ @@ -56,20 +111,25 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ - int arrayIndex; // Index into the colliders vector on the native object - Entity entity; // Entity holding the collider component that this collider bounds is on + int arrayIndex; // Index into the colliders vector on the native object + Entity entity; // Entity holding the collider component that this collider bounds is on /*-----------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------*/ template - CollisionShapeType& getNativeBoundObject(); + CollisionShapeType& getNativeCollisionShape(); internal: /*-----------------------------------------------------------------------------*/ /* Setter Functions */ /*-----------------------------------------------------------------------------*/ void updateArrayIndex(int index); + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + SHCollisionShape& getNativeCollisionShape(); }; /// @@ -205,18 +265,18 @@ namespace SHADE /* Usage Functions */ /*-----------------------------------------------------------------------------*/ /// - /// Retrieves a ColliderBound at the specified index in the ColliderBound list. + /// Retrieves a CollisionShape at the specified index in the CollisionShapes list. /// /// Index to retrieve a ColliderBound from. /// ColliderBound for the specified index. CollisionShape^ GetCollisionShape(int index); /// - /// Retrieves a ColliderBound at the specified index in the ColliderBound list + /// Retrieves a CollisionShape at the specified index in the CollisionShapes list /// and casts it to the appropriate type. /// - /// Type of the ColliderBound to cast to. - /// Index to retrieve a ColliderBound from. - /// ColliderBound for the specified index. + /// Type of the CollisionShape to cast to. + /// Index to retrieve a CollisionShape from. + /// CollisionShape for the specified index. generic where T:CollisionShape T GetCollisionShape(int index); diff --git a/SHADE_Managed/src/Components/RigidBody.cxx b/SHADE_Managed/src/Components/RigidBody.cxx index 12861600..cdaa296a 100644 --- a/SHADE_Managed/src/Components/RigidBody.cxx +++ b/SHADE_Managed/src/Components/RigidBody.cxx @@ -189,7 +189,17 @@ namespace SHADE { GetNativeComponent()->AddRelativeForceAtWorldPos(Convert::ToNative(relativeForce), Convert::ToNative(worldPos)); } - + + Vector3 RigidBody::GetForce() + { + return Convert::ToCLI(GetNativeComponent()->GetForce()); + } + + void RigidBody::ClearForces() + { + GetNativeComponent()->ClearForces(); + } + /*---------------------------------------------------------------------------------*/ /* Torque Functions */ /*---------------------------------------------------------------------------------*/ @@ -202,4 +212,15 @@ namespace SHADE { GetNativeComponent()->AddRelativeTorque(Convert::ToNative(relativeTorque)); } + + Vector3 RigidBody::GetTorque() + { + return Convert::ToCLI(GetNativeComponent()->GetTorque()); + } + + void RigidBody::ClearTorque() + { + GetNativeComponent()->ClearTorque(); + } + } \ No newline at end of file diff --git a/SHADE_Managed/src/Components/RigidBody.hxx b/SHADE_Managed/src/Components/RigidBody.hxx index f2953bbd..8bfe34aa 100644 --- a/SHADE_Managed/src/Components/RigidBody.hxx +++ b/SHADE_Managed/src/Components/RigidBody.hxx @@ -145,11 +145,17 @@ namespace SHADE void AddRelativeForceAtLocalPos(Vector3 relativeForce, Vector3 localPos); void AddRelativeForceAtWorldPos(Vector3 relativeForce, Vector3 worldPos); + Vector3 GetForce(); + void ClearForces(); + /*-----------------------------------------------------------------------------*/ /* Torque Functions */ /*-----------------------------------------------------------------------------*/ void AddTorque(Vector3 force); void AddRelativeTorque(Vector3 relativeForce); + + Vector3 GetTorque(); + void ClearTorque(); }; } \ No newline at end of file diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 80f070e2..ffdffd12 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -26,7 +26,8 @@ of DigiPen Institute of Technology is prohibited. #include "Physics/Interface/SHRigidBodyComponent.h" #include "Scene/SHSceneManager.h" #include "Scene/SHSceneGraph.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" +#include "Graphics\MiddleEnd\Interface\SHRenderable.h" // Project Headers #include "Utility/Convert.hxx" #include "Utility/Debug.hxx" @@ -36,6 +37,7 @@ of DigiPen Institute of Technology is prohibited. #include "Components/Camera.hxx" #include "Components/CameraArm.hxx" #include "Components/Light.hxx" +#include "Components\Renderable.hxx" namespace SHADE { @@ -166,6 +168,70 @@ namespace SHADE return T(); } + generic + System::Collections::Generic::IEnumerable^ ECS::GetComponentsInChildren(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to retrieve Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return nullptr; + } + + // Search all elements via a iterative breadth first search + System::Collections::Generic::List^ results; + System::Collections::Generic::Queue^ searchSpace = gcnew System::Collections::Generic::Queue(); + // Start off with direct children + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity); + if (entityNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + } + for (const auto& child : entityNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + // Continue with all subsequent children + while (searchSpace->Count > 0) + { + // Check if this entity has the component we need + Entity curr = searchSpace->Dequeue(); + T component = GetComponent(curr); + if (component != nullptr) + { + // We only construct if we need to + if (results == nullptr) + results = gcnew System::Collections::Generic::List(); + results->Add(component); + } + + // Add children to the queue + SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(curr); + if (sceneGraphNode == nullptr) + { + std::ostringstream oss; + oss << "[ECS_CLI] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + continue; + } + for (const auto& child : sceneGraphNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + } + + // None here + return results; + } + generic T ECS::EnsureComponent(EntityID entity) { @@ -249,6 +315,7 @@ namespace SHADE static ECS::ECS() { componentMap.Add(createComponentSet()); + componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); diff --git a/SHADE_Managed/src/Engine/ECS.hxx b/SHADE_Managed/src/Engine/ECS.hxx index 0563f678..18acf30d 100644 --- a/SHADE_Managed/src/Engine/ECS.hxx +++ b/SHADE_Managed/src/Engine/ECS.hxx @@ -51,9 +51,9 @@ namespace SHADE /// specified Component. /// generic where T : BaseComponent - static T GetComponent(EntityID entity); + static T GetComponent(EntityID entity); /// - /// Retrieves the first Component from the specified GameObjectt's children that + /// Retrieves the first Component from the specified GameObject's children that /// matches the specified type. /// /// Type of the Component to get. @@ -65,6 +65,20 @@ namespace SHADE generic where T : BaseComponent static T GetComponentInChildren(EntityID entity); /// + /// Retrieves a list of Components from the specified GameObject's children that + /// matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// This does not search the specified entity. + /// + /// Type of the Component to get. + /// Entity object to get the Component from. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + static System::Collections::Generic::IEnumerable^ GetComponentsInChildren(EntityID entity); + /// /// Ensures a Component on the specified Entity. /// /// Type of the Component to ensure. diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 017366fe..200b2079 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -170,6 +170,14 @@ namespace SHADE return ECS::GetComponentInChildren(entity); } + generic + System::Collections::Generic::IEnumerable^ GameObject::GetComponentsInChildren() + { + if (!valid) + throw gcnew System::NullReferenceException(); + return ECS::GetComponentsInChildren(entity); + } + generic T GameObject::EnsureComponent() { @@ -212,6 +220,13 @@ namespace SHADE throw gcnew System::NullReferenceException(); return ScriptStore::GetScriptInChildren(entity); } + generic + System::Collections::Generic::IEnumerable^ GameObject::GetScriptsInChildren() + { + if (!valid) + throw gcnew System::NullReferenceException(); + return ScriptStore::GetScriptsInChildren(entity); + } generic System::Collections::Generic::IEnumerable^ GameObject::GetScripts() diff --git a/SHADE_Managed/src/Engine/GameObject.hxx b/SHADE_Managed/src/Engine/GameObject.hxx index 2e0f360c..64d1b428 100644 --- a/SHADE_Managed/src/Engine/GameObject.hxx +++ b/SHADE_Managed/src/Engine/GameObject.hxx @@ -153,6 +153,7 @@ namespace SHADE /// /// Retrieves the first Component from this GameObject's children that matches /// the specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// Type of the Component to get. /// @@ -162,6 +163,19 @@ namespace SHADE generic where T : BaseComponent T GetComponentInChildren(); /// + /// Retrieves a list of Components from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + System::Collections::Generic::IEnumerable^ GetComponentsInChildren(); + /// /// Ensures a Component on this GameObject. /// /// Type of the Component to ensure. @@ -201,12 +215,26 @@ namespace SHADE /// Retrieves a Script of the specified type from child GameObjects. /// If multiple Scripts of the same specified type are added on the same /// child GameObject, this will retrieve the first one added. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// Type of Script to retrieve. /// Reference to the Script to retrieve. generic where T : ref class, Script T GetScriptInChildren(); /// + /// Retrieves a list of Scripts from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : ref class, Script + System::Collections::Generic::IEnumerable^ GetScriptsInChildren(); + /// /// Retrieves a immutable list of Scripts of the specified type from this /// GameObject. /// diff --git a/SHADE_Managed/src/Math/Vector3.cxx b/SHADE_Managed/src/Math/Vector3.cxx index f2286aa7..edd78f6b 100644 --- a/SHADE_Managed/src/Math/Vector3.cxx +++ b/SHADE_Managed/src/Math/Vector3.cxx @@ -52,7 +52,7 @@ namespace SHADE Vector3 Vector3::GetNormalised() { - return *this / GetSqrMagnitude(); + return *this / GetMagnitude(); } float Vector3::GetMagnitude() diff --git a/SHADE_Managed/src/Scripts/Script.cxx b/SHADE_Managed/src/Scripts/Script.cxx index 017242d6..a2af38a3 100644 --- a/SHADE_Managed/src/Scripts/Script.cxx +++ b/SHADE_Managed/src/Scripts/Script.cxx @@ -42,6 +42,12 @@ namespace SHADE return owner.GetComponentInChildren(); } + generic + System::Collections::Generic::IEnumerable^ Script::GetComponentsInChildren() + { + return owner.GetComponentsInChildren(); + } + generic T Script::EnsureComponent() { @@ -72,6 +78,11 @@ namespace SHADE { return ScriptStore::GetScriptInChildren(owner.GetEntity()); } + generic + System::Collections::Generic::IEnumerable^ Script::GetScriptsInChildren() + { + return ScriptStore::GetScriptsInChildren(owner.GetEntity()); + } generic System::Collections::Generic::IEnumerable^ Script::GetScripts() diff --git a/SHADE_Managed/src/Scripts/Script.hxx b/SHADE_Managed/src/Scripts/Script.hxx index fb564d27..46736245 100644 --- a/SHADE_Managed/src/Scripts/Script.hxx +++ b/SHADE_Managed/src/Scripts/Script.hxx @@ -69,6 +69,7 @@ namespace SHADE /// /// Retrieves the first Component from this GameObject's children that matches /// the specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// /// Type of the Component to get. Must be derived from BaseComponent. @@ -77,6 +78,19 @@ namespace SHADE generic where T : BaseComponent T GetComponentInChildren(); /// + /// Retrieves a list of Components from this GameObject's children that + /// matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + System::Collections::Generic::IEnumerable^ GetComponentsInChildren(); + /// /// Ensures a Component on the GameObject that this Script belongs to. /// /// @@ -121,6 +135,7 @@ namespace SHADE /// /// Retrieves the first Script from this GameObject's children that matches the /// specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// /// Type of script to get. @@ -130,6 +145,19 @@ namespace SHADE generic where T : ref class, Script T GetScriptInChildren(); /// + /// Retrieves a list of Scripts from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : ref class, Script + System::Collections::Generic::IEnumerable^ GetScriptsInChildren(); + /// /// Retrieves a immutable list of scripts from the specified Entity that /// matches the specified type. ///
diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 318f5839..29ba6e52 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include // External Dependencies #include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" // Project Headers #include "Utility/Debug.hxx" #include "Utility/Convert.hxx" @@ -211,6 +211,70 @@ namespace SHADE return T(); } + generic + System::Collections::Generic::IEnumerable^ ScriptStore::GetScriptsInChildren(Entity entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ScriptStore] Attempted to retrieve Script \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return nullptr; + } + + // Search all elements via a iterative breadth first search + System::Collections::Generic::List^ results; + System::Collections::Generic::Queue^ searchSpace = gcnew System::Collections::Generic::Queue(); + // Start off with direct children + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity); + if (entityNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + } + for (const auto& child : entityNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + // Continue with all subsequent children + while (searchSpace->Count > 0) + { + // Check if this entity has the component we need + Entity curr = searchSpace->Dequeue(); + T script = GetScript(curr); + if (script != nullptr) + { + // We only construct if we need to + if (results == nullptr) + results = gcnew System::Collections::Generic::List(); + results->Add(script); + } + + // Add children to the queue + SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(curr); + if (sceneGraphNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + continue; + } + for (const auto& child : sceneGraphNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + } + + // None here + return results; + } + generic System::Collections::Generic::IEnumerable^ ScriptStore::GetScripts(Entity entity) { @@ -338,8 +402,8 @@ namespace SHADE System::Collections::Generic::List^ scriptList = scripts[entity]; for each (Script ^ script in scriptList) { - // Call OnDestroy only if indicated and also in play mode - if (callOnDestroy) + // Call OnDestroy only if indicated and also if the game has run + if (callOnDestroy && Application::IsPlaying || Application::IsPaused) { script->OnDestroy(); } @@ -405,7 +469,7 @@ namespace SHADE script->OnDestroy(); } auto entity = script->Owner.GetEntity(); - auto scriptList = scripts[script->Owner.GetEntity()]; + auto scriptList = scripts[script->Owner.GetEntity()]; // Unable to find here scriptList->Remove(script); if (scriptList->Count <= 0) { diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index 62e3003a..78f8c787 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -137,6 +137,29 @@ namespace SHADE generic where T : ref class, Script static T GetScriptInChildren(Entity entity); /// + /// Retrieves the list of Scripts from the specified Entity and the Entity's + /// children that matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetScriptInChildren() instead. + /// This does not search the specified entity. + /// + /// + /// Type of script to get. + /// This needs to be a default constructable Script. + /// + /// + /// The entity which the script to retrieve is attached. + /// + /// + /// Reference to the script. This can be null if no script of the specified + /// type is attached. + /// + /// + /// If the specified Entity is invalid. + /// + generic where T : ref class, Script + static System::Collections::Generic::IEnumerable^ GetScriptsInChildren(Entity entity); + /// /// Retrieves a immutable list of scripts from the specified Entity that /// matches the specified type. ///
diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx index 147591a5..cfa94540 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx @@ -45,12 +45,22 @@ namespace SHADE System::Collections::Generic::IEnumerable^ fields = ReflectionUtilities::GetInstanceFields(object); for each (FieldInfo^ field in fields) { - // Ignore private and non-SerialiseField - if (!ReflectionUtilities::FieldIsSerialisable(field)) - continue; + try + { + // Ignore private and non-SerialiseField + if (!ReflectionUtilities::FieldIsSerialisable(field)) + continue; - // Serialise - writeFieldIntoYaml(field, object, scriptNode); + // Serialise + writeFieldIntoYaml(field, object, scriptNode); + } + catch (System::Exception^ e) + { + Debug::LogError + ( + System::String::Format("[SerialisationUtilities] Failed to serialise field ({0}): {1}", field->Name, e->ToString()) + ); + } } scriptListNode.push_back(scriptNode); @@ -74,15 +84,25 @@ namespace SHADE System::Collections::Generic::IEnumerable^ fields = ReflectionUtilities::GetInstanceFields(object); for each (FieldInfo^ field in fields) { - // Ignore private and non-SerialiseField - if (!ReflectionUtilities::FieldIsSerialisable(field)) - continue; - - // Deserialise - const std::string FIELD_NAME = Convert::ToNative(field->Name); - if (yamlNode[FIELD_NAME]) + try { - writeYamlIntoField(field, object, yamlNode[FIELD_NAME]); + // Ignore private and non-SerialiseField + if (!ReflectionUtilities::FieldIsSerialisable(field)) + continue; + + // Deserialise + const std::string FIELD_NAME = Convert::ToNative(field->Name); + if (yamlNode[FIELD_NAME]) + { + writeYamlIntoField(field, object, yamlNode[FIELD_NAME]); + } + } + catch (System::Exception^ e) + { + Debug::LogError + ( + System::String::Format("[SerialisationUtilities] Failed to deserialise field ({0}): {1}", field->Name, e->ToString()) + ); } } } diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ index 3e756ce4..2c943452 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ @@ -28,7 +28,47 @@ namespace SHADE template bool SerialisationUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Node& fieldNode) { - return varInsertYamlInternal(fieldInfo->GetValue(object), fieldNode); + // Handle null objects + System::Object^ fieldObject = fieldInfo->GetValue(object); + if (fieldObject == nullptr) + { + // Default construct if null + if (fieldInfo->FieldType == FieldType::typeid) + { + if constexpr (std::is_same_v) + { + fieldNode = 0; + } + else if constexpr (std::is_same_v) + { + fieldNode = ""; + } + else if constexpr (std::is_same_v) + { + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + } + else if constexpr (std::is_same_v) + { + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + } + else if constexpr (std::is_same_v) + { + fieldNode = MAX_EID; + } + else + { + fieldNode = FieldType(); + } + return true; + } + return false; + } + return varInsertYamlInternal(fieldObject, fieldNode); } template bool SerialisationUtilities::varInsertYamlInternal(System::Object^ object, YAML::Node& fieldNode) @@ -102,6 +142,31 @@ namespace SHADE bool SerialisationUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) { System::Object^ valueObj = fieldInfo->GetValue(object); + if (valueObj == nullptr) + { + if constexpr (std::is_same_v) + { + if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid)) + { + valueObj = 0; + } + } + else + { + if (fieldInfo->FieldType == FieldType::typeid) + { + if constexpr (std::is_same_v) + { + valueObj = ""; + } + else + { + valueObj = FieldType(); + } + } + } + } + if (varAssignYamlInternal(valueObj, node)) { fieldInfo->SetValue(object, valueObj); diff --git a/SHADE_Managed/src/Utility/Debug.cxx b/SHADE_Managed/src/Utility/Debug.cxx index 8a107ab3..cdc19df0 100644 --- a/SHADE_Managed/src/Utility/Debug.cxx +++ b/SHADE_Managed/src/Utility/Debug.cxx @@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited. // Standard Libraries #include // External Libraries -#include "Tools/SHLog.h" +#include "Tools/Logger/SHLog.h" // Project Headers #include "Convert.hxx"