diff --git a/Assets/Navigation Data/Level2_AITest_NavData.shnav b/Assets/Navigation Data/Level2_AITest_NavData.shnav new file mode 100644 index 00000000..845951a5 Binary files /dev/null and b/Assets/Navigation Data/Level2_AITest_NavData.shnav differ diff --git a/Assets/Navigation Data/Level2_AITest_NavData.shnav.shmeta b/Assets/Navigation Data/Level2_AITest_NavData.shnav.shmeta new file mode 100644 index 00000000..9a745d73 --- /dev/null +++ b/Assets/Navigation Data/Level2_AITest_NavData.shnav.shmeta @@ -0,0 +1,3 @@ +Name: Level2_AITest_NavData +ID: 255209218 +Type: 15 diff --git a/Assets/Scenes/Level2_AITest.shade b/Assets/Scenes/Level2_AITest.shade index d9bca4e7..d09afa6a 100644 --- a/Assets/Scenes/Level2_AITest.shade +++ b/Assets/Scenes/Level2_AITest.shade @@ -1,3 +1,4 @@ +- NavData: 255209218 - EID: 20 Name: ===== Light ===== IsActive: true @@ -2945,6 +2946,7 @@ Scripts: - Type: PlayerController Enabled: true + smokeCount: 4 respawnPoint: 239 currentState: 0 walkMaxMoveVel: 2.5 @@ -2963,6 +2965,8 @@ heavyMultiper: 0.5 silhouettePlayer: 462 silhouetteBag: 465 + leftParticle: 51000 + rightParticle: 51000 - Type: PickAndThrow Enabled: true throwForce: [10, 4, 10] @@ -2975,6 +2979,8 @@ lerpPickUpDuration: 0.75 tweenAimDuration: 0.300000012 aimingFOV: 15 + trajMaxSteps: 50 + trajTimeSteps: 0.0299999993 - Type: PlayerAnimations Enabled: true playerIdleClip: 227450439 diff --git a/SHADE_Engine/src/Assets/Asset Types/SHNavDataAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHNavDataAsset.h new file mode 100644 index 00000000..650c6136 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHNavDataAsset.h @@ -0,0 +1,30 @@ +/*************************************************************************//** + * \file SHNavDataAsset.h + * \author Loh Xiao Qi + * \date 20 March 2023 + * \brief + * + * 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 "SH_API.h" + +#include + +#include "Math/Vector/SHVec3.h" +#include "SHAssetData.h" + +namespace SHADE +{ + struct SH_API SHNavDataAsset : SHAssetData + { + uint16_t rows; + uint16_t cols; + SHVec3 origin; + SHVec3 size; + std::vector grid; + }; +} diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp index a8663dde..b1ccde87 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp @@ -5,8 +5,12 @@ #include +#include "Assets/Asset Types/SHNavDataAsset.h" + namespace SHADE { + struct SHNavDataAsset; + SHAssetData* SHBinaryLoader::Load(AssetPath path) { std::ifstream file{ path, std::ios::in | std::ios::binary }; @@ -21,7 +25,11 @@ namespace SHADE if (extension == ANIM_CONTAINER_EXTENSION) { - LoadAnimClipContainer(file, result, path); + LoadAnimClipContainer(file, result); + } + else if(extension == NAV_DATA_EXTENSION) + { + LoadNavData(file, result); } file.close(); @@ -43,13 +51,17 @@ namespace SHADE if (extension == ANIM_CONTAINER_EXTENSION) { - WriteAnimClipContainer(file, data, path); + WriteAnimClipContainer(file, data); + } + else if(extension == NAV_DATA_EXTENSION) + { + WriteNavData(file, data); } file.close(); } - void SHBinaryLoader::WriteAnimClipContainer(std::ofstream& file, SHAssetData const* data, AssetPath path) + void SHBinaryLoader::WriteAnimClipContainer(std::ofstream& file, SHAssetData const* data) { auto const& anim = *dynamic_cast(data); file.write( @@ -84,7 +96,7 @@ namespace SHADE } } - void SHBinaryLoader::LoadAnimClipContainer(std::ifstream& file, SHAssetData*& result, AssetPath path) + void SHBinaryLoader::LoadAnimClipContainer(std::ifstream& file, SHAssetData*& result) { auto const data = new SHAnimClipContainerAsset(); @@ -126,4 +138,58 @@ namespace SHADE result = data; } + + void SHBinaryLoader::WriteNavData(std::ofstream& file, SHAssetData const* data) + { + auto const& navData = *reinterpret_cast(data); + file.write( + reinterpret_cast(&navData.rows), + sizeof(uint32_t) + ); + + file.write( + reinterpret_cast(&navData.origin), + sizeof(SHVec3) * 2 + ); + + auto const count {navData.grid.size()}; + file.write( + reinterpret_cast(&count), + sizeof(count) + ); + + file.write( + reinterpret_cast(navData.grid.data()), + count + ); + } + + void SHBinaryLoader::LoadNavData(std::ifstream& file, SHAssetData*& result) + { + auto const data = new SHNavDataAsset(); + + file.read( + reinterpret_cast(&data->rows), + sizeof(uint32_t) + ); + + file.read( + reinterpret_cast(&data->origin), + sizeof(SHVec3) * 2 + ); + + size_t count; + file.read( + reinterpret_cast(&count), + sizeof(size_t) + ); + + data->grid.resize(count); + file.read( + reinterpret_cast(data->grid.data()), + count + ); + + result = data; + } } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h index 5689901d..fa3daf64 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h @@ -11,7 +11,10 @@ namespace SHADE private: //Individual functions to write files - void WriteAnimClipContainer(std::ofstream& file,SHAssetData const* data, AssetPath path); - void LoadAnimClipContainer(std::ifstream& file,SHAssetData*& result, AssetPath path); + void WriteAnimClipContainer(std::ofstream& file,SHAssetData const* data); + void LoadAnimClipContainer(std::ifstream& file,SHAssetData*& result); + + void WriteNavData(std::ofstream& file, SHAssetData const* data); + void LoadNavData(std::ifstream& file, SHAssetData*& result); }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index f12cc56f..0616471c 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -61,6 +61,7 @@ enum class AssetType : AssetTypeMeta ANIM_CONTAINER, ANIM_CLIP, ANIM_CONTROLLER, + NAV_DATA, MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -84,6 +85,7 @@ constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" }; constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" }; constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" }; +constexpr std::string_view NAV_DATA_FOLDER{ "/Navigation Data/" }; // ASSET EXTENSIONS @@ -102,6 +104,7 @@ constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view MODEL_EXTENSION{ ".shmodel" }; constexpr std::string_view ANIM_CONTAINER_EXTENSION{ ".shanimcontainer" }; constexpr std::string_view ANIM_CONTROLLER_EXTENSION{ ".shanimcontroller" }; +constexpr std::string_view NAV_DATA_EXTENSION{ ".shnav" }; constexpr std::string_view FILLER_EXTENSION{"dummy"}; constexpr std::string_view EXTENSIONS[] = { @@ -119,7 +122,8 @@ constexpr std::string_view EXTENSIONS[] = { AUDIO_BANK_EXTENSION, ANIM_CONTAINER_EXTENSION, ANIM_CONTROLLER_EXTENSION, - FILLER_EXTENSION + FILLER_EXTENSION, + NAV_DATA_EXTENSION }; constexpr size_t EXTENSIONS_COUNT{ static_cast(AssetType::MAX_COUNT) }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index dc9d9587..14b5b0a7 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -33,6 +33,8 @@ #include "Filesystem/SHFileSystem.h" #include + +#include "Asset Types/SHNavDataAsset.h" #include "Assets/Events/SHAssetManagerEvents.h" #include "Events/SHEventManager.hpp" @@ -259,6 +261,17 @@ namespace SHADE } break; + case AssetType::NAV_DATA: + newPath += NAV_DATA_FOLDER; + newPath += name; + newPath += NAV_DATA_EXTENSION; + + { + auto navData = new SHNavDataAsset(); + data = navData; + } + break; + default: SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name); return 0; @@ -336,7 +349,8 @@ namespace SHADE asset.type == AssetType::SCENE || asset.type == AssetType::PREFAB || asset.type == AssetType::MATERIAL || - asset.type == AssetType::ANIM_CONTAINER + asset.type == AssetType::ANIM_CONTAINER || + asset.type == AssetType::NAV_DATA ) { if (assetData.contains(id)) @@ -585,17 +599,20 @@ namespace SHADE void SHAssetManager:: InitLoaders() noexcept { loaders[static_cast(AssetType::SHADER)] = dynamic_cast(new SHShaderSourceLoader()); - loaders[static_cast(AssetType::SHADER_BUILT_IN)] = loaders[static_cast(AssetType::SHADER)]; loaders[static_cast(AssetType::TEXTURE)] = dynamic_cast(new SHTextureLoader()); loaders[static_cast(AssetType::MODEL)] = dynamic_cast(new SHModelLoader()); loaders[static_cast(AssetType::SCENE)] = dynamic_cast(new SHTextBasedLoader()); + loaders[static_cast(AssetType::FONT)] = dynamic_cast(new SHFontLoader()); + loaders[static_cast(AssetType::ANIM_CONTAINER)] = dynamic_cast(new SHBinaryLoader()); + loaders[static_cast(AssetType::PREFAB)] = loaders[static_cast(AssetType::SCENE)]; loaders[static_cast(AssetType::MATERIAL)] = loaders[static_cast(AssetType::SCENE)]; + loaders[static_cast(AssetType::AUDIO_BANK)] = loaders[static_cast(AssetType::SCENE)]; + loaders[static_cast(AssetType::SHADER_BUILT_IN)] = loaders[static_cast(AssetType::SHADER)]; + loaders[static_cast(AssetType::NAV_DATA)] = loaders[static_cast(AssetType::ANIM_CONTAINER)]; + loaders[static_cast(AssetType::MESH)] = nullptr; loaders[static_cast(AssetType::SCRIPT)] = nullptr; - loaders[static_cast(AssetType::FONT)] = dynamic_cast(new SHFontLoader()); - loaders[static_cast(AssetType::AUDIO_BANK)] = loaders[static_cast(AssetType::SCENE)]; - loaders[static_cast(AssetType::ANIM_CONTAINER)] = dynamic_cast(new SHBinaryLoader()); loaders[static_cast(AssetType::ANIM_CLIP)] = nullptr; } @@ -892,6 +909,21 @@ namespace SHADE SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]); } + else if (ext == NAV_DATA_EXTENSION) + { + SHAsset newAsset{ + path.stem().string(), + GenerateAssetID(AssetType::NAV_DATA), + AssetType::NAV_DATA, + path, + false + }; + + assetCollection.emplace(newAsset.id, newAsset); + SHAssetMetaHandler::WriteMetaData(newAsset); + + return newAsset.id; + } } void SHAssetManager::BuildAssetCollection() noexcept @@ -950,7 +982,8 @@ namespace rttr value("Script", AssetType::SCRIPT), value("Font", AssetType::FONT), value("Animation Container", AssetType::ANIM_CONTAINER), - value("Animation Clip", AssetType::ANIM_CLIP) + value("Animation Clip", AssetType::ANIM_CLIP), + value("Navigation Data", AssetType::NAV_DATA) ); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 65e497aa..e458bbf6 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -29,6 +29,7 @@ #include "Physics/System/SHPhysicsDebugDrawSystem.h" #include "Camera/SHCameraSystem.h" #include "Tools/Utilities/SHClipboardUtilities.h" +#include const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" }; @@ -93,6 +94,7 @@ namespace SHADE DrawLayoutMenu(); DrawApplicationConfig(); DrawPhysicsSettings(); + DrawNavMenu(); std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())}; auto const size = ImGui::CalcTextSize(sceneName.data()); @@ -418,6 +420,41 @@ namespace SHADE + ImGui::EndMenu(); + } + } + + void SHEditorMenuBar::DrawNavMenu() noexcept + { + ImGui::SetNextWindowSize({ 400.0f, 0.0f }); + if (ImGui::BeginMenu("Nav")) + { + if (auto navSystem = SHSystemManager::GetSystem()) + { + if (SHEditorWidgets::DragN("Origin", { "X", "Y", "Z" }, {&navSystem->origin_editor.x, &navSystem->origin_editor .y, &navSystem->origin_editor.z})) + { + + } + if (SHEditorWidgets::DragN("Size", { "X", "Y", "Z" }, { &navSystem->size_editor.x, &navSystem->size_editor.y, &navSystem->size_editor.z })) + { + + } + + if (ImGui::DragScalar("Col", ImGuiDataType_U16, &navSystem->numCols_editor)) {} + if(ImGui::DragScalar("Row", ImGuiDataType_U16, &navSystem->numRows_editor)){} + + if (ImGui::Button("Generate")) + { + navSystem->Clear(); + navSystem->GenerateNavigationGridData(); + std::string name = SHSceneManager::GetSceneName(); + name += "_NavData"; + navSystem->SaveToFile(name); + + } + } + + ImGui::EndMenu(); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h index 945ee81b..e132d042 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h @@ -27,6 +27,7 @@ namespace SHADE void DrawLayoutMenu() noexcept; void DrawApplicationConfig() noexcept; void DrawPhysicsSettings() noexcept; + void DrawNavMenu() noexcept; float menuBarHeight = 20.0f; std::vector layoutPaths; diff --git a/SHADE_Engine/src/Navigation/SHNavigationSystem.cpp b/SHADE_Engine/src/Navigation/SHNavigationSystem.cpp index d8ea3d32..8f692d90 100644 --- a/SHADE_Engine/src/Navigation/SHNavigationSystem.cpp +++ b/SHADE_Engine/src/Navigation/SHNavigationSystem.cpp @@ -7,7 +7,8 @@ #include "Editor/SHEditor.h" #include "Scene/SHSceneManager.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" - +#include "Assets/SHAssetManager.h" +#include "Assets/Asset Types/SHNavDataAsset.h" #include #include @@ -82,6 +83,52 @@ namespace SHADE return result; } + void SHNavigationSystem::Clear() noexcept + { + numRows = 0; + numCols = 0; + origin = SHVec3{ 0.0f }; + size = SHVec3{ 0.0f }; + navigationGrid.clear(); + + navDataAsset = 0; + } + + void SHNavigationSystem::LoadFromFile(AssetID id) noexcept + { + auto data = SHAssetManager::GetData(id); + if (data != nullptr) + { + this->origin = data->origin; + this->navigationGrid = data->grid; + this->size = data->size; + this->numRows = data->rows; + this->numCols = data->cols; + } + + navDataAsset = id; + } + + + + + AssetID SHNavigationSystem::SaveToFile(std::string const& name) noexcept + { + AssetID result = SHAssetManager::CreateNewAsset(AssetType::NAV_DATA, name); + auto data = SHAssetManager::GetData(result); + data->origin = this->origin; + data->grid = this->navigationGrid; + data->size = this->size; + data->rows = this->numRows; + data->cols = this->numCols; + + SHAssetManager::SaveAsset(result); + + navDataAsset = result; + + return result; + } + SHVec3 SHNavigationSystem::GetGridWorldPos(NavigationGridIndex index) noexcept { SHVec3 result{0.0f}; @@ -164,6 +211,11 @@ namespace SHADE } + void SHNavigationSystem::GenerateNavigationGridData() noexcept + { + GenerateNavigationGridData(origin_editor, size_editor, numRows_editor, numCols_editor); + } + void SHNavigationSystem::NavigationSystemGenerateRoutine::Execute(double dt) noexcept diff --git a/SHADE_Engine/src/Navigation/SHNavigationSystem.h b/SHADE_Engine/src/Navigation/SHNavigationSystem.h index d9a5209f..5b3fa0ca 100644 --- a/SHADE_Engine/src/Navigation/SHNavigationSystem.h +++ b/SHADE_Engine/src/Navigation/SHNavigationSystem.h @@ -5,7 +5,7 @@ #include "SHNavigationComponent.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" - +#include "Assets/SHAssetMacros.h" #include "SH_API.h" @@ -61,8 +61,24 @@ namespace SHADE virtual void Init(); virtual void Exit(); + + //Number of subdivision on the x axis + uint16_t numRows_editor{ 0 }; + //Number of subdivision on the z axis + uint16_t numCols_editor{ 0 }; + + //The center of the navigation area. + SHVec3 origin_editor{ 0.0f }; + + //Size of the navigation area + SHVec3 size_editor{ 0.0f }; + + AssetID navDataAsset{}; + + void GenerateNavigationGridData(SHVec3 origin, SHVec3 size, uint16_t numRow, uint16_t numCol) noexcept; + void GenerateNavigationGridData() noexcept; void GeneratePath(SHNavigationComponent& comp) noexcept; bool GetNavigationData(uint16_t row, uint16_t col) noexcept; @@ -71,7 +87,9 @@ namespace SHADE NavigationGridIndex GetNavigationGridIndex(SHVec3 const& worldPosition) noexcept; - + void Clear() noexcept; + void LoadFromFile(AssetID id) noexcept; + AssetID SaveToFile(std::string const& name) noexcept; class SH_API NavigationSystemGenerateRoutine final: public SHSystemRoutine { diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 842c0c4e..5b0aaced 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -16,6 +16,7 @@ #include "Scripting/SHScriptEngine.h" #include "Tools/FileIO/SHFileIO.h" #include "Prefab/SHPrefabManager.h" +#include namespace SHADE { @@ -50,6 +51,12 @@ namespace SHADE auto const& children = root->GetChildren(); out << YAML::BeginSeq; + if (auto navSystem = SHSystemManager::GetSystem()) + { + YAML::Node navData; + navData["NavData"] = navSystem->navDataAsset; + out << navData; + } auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; sceneGraph.Traverse(pred); @@ -113,9 +120,20 @@ namespace SHADE } YAML::Node entities = YAML::Load(assetData->data); CreatedEntitiesList createdEntities{}; - + auto entitiesBegin = entities.begin(); + if (auto navSystem = SHSystemManager::GetSystem()) + { + navSystem->Clear(); + YAML::Node navDataNode = *entitiesBegin; + if (navDataNode["NavData"].IsDefined()) + { + AssetID navDataAssetID = navDataNode["NavData"].as(); + navSystem->LoadFromFile(navDataAssetID); + ++entitiesBegin; + } + } //Create Entities - for (auto it = entities.begin(); it != entities.end(); ++it) + for (auto it = entitiesBegin; it != entities.end(); ++it) { DeserializeEntity(it, (*it), createdEntities); } @@ -126,14 +144,14 @@ namespace SHADE } auto entityVecIt = createdEntities.begin(); AssetQueue assetQueue; - for (auto it = entities.begin(); it != entities.end(); ++it) + for (auto it = entitiesBegin; it != entities.end(); ++it) { SHSerializationHelper::FetchAssetsFromComponent((*it)[ComponentsNode], createdEntities[(*it)[EIDNode].as()], assetQueue); } LoadAssetsFromAssetQueue(assetQueue); //Initialize Entity entityVecIt = createdEntities.begin(); - for (auto it = entities.begin(); it != entities.end(); ++it) + for (auto it = entitiesBegin; it != entities.end(); ++it) { InitializeEntity(*it, createdEntities[(*it)[EIDNode].as()]); }