Merge remote-tracking branch 'origin/main' into SP3-2-Physics

This commit is contained in:
Diren D Bharwani 2022-10-24 02:46:08 +08:00
commit 7643ca4289
207 changed files with 8909 additions and 1962 deletions

2
.gitignore vendored
View File

@ -362,3 +362,5 @@ MigrationBackup/
*.csproj
*.filters
Assets/Editor/Layouts/UserLayout.ini

View File

@ -0,0 +1,3 @@
Name: Cube.003
ID: 110152941
Type: 6

View File

@ -0,0 +1,3 @@
Name: Cube.012
ID: 107348815
Type: 6

Binary file not shown.

View File

@ -0,0 +1,48 @@
[Window][MainStatusBar]
Pos=0,1060
Size=1920,20
Collapsed=0
[Window][SHEditorMenuBar]
Pos=0,24
Size=1920,1036
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,120
Size=225,940
Collapsed=0
DockId=0x00000004,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Inspector]
Pos=1686,24
Size=234,1036
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,24
Size=225,94
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=227,24
Size=1457,1036
Collapsed=0
DockId=0x00000002,0
[Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252

View File

@ -0,0 +1,54 @@
[Window][MainStatusBar]
Pos=0,1060
Size=1920,20
Collapsed=0
[Window][SHEditorMenuBar]
Pos=0,48
Size=1920,1012
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,142
Size=387,918
Collapsed=0
DockId=0x00000004,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Inspector]
Pos=1649,48
Size=271,1012
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,48
Size=387,92
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=648,48
Size=2519,1319
Collapsed=0
DockId=0x00000002,0
[Window][ Viewport]
Pos=389,48
Size=1258,1012
Collapsed=0
DockId=0x00000002,0
[Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

View File

@ -0,0 +1,3 @@
Name: RaccoonPreTexturedVer1_Base9
ID: 91918845
Type: 4

View File

@ -37,7 +37,8 @@ project "SHADE_Application"
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.tinyddsloader}",
"%{IncludeDir.reactphysics3d}\\include"
"%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.yamlcpp}"
}
externalwarnings "Off"
@ -51,6 +52,7 @@ project "SHADE_Application"
{
"SHADE_Engine",
"SHADE_Managed",
"yaml-cpp",
"SDL2.lib",
"SDL2main.lib"
}

View File

@ -30,6 +30,7 @@
#include "Input/SHInputManager.h"
#include "FRC/SHFramerateController.h"
#include "AudioSystem/SHAudioSystem.h"
#include "Camera/SHCameraSystem.h"
// Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
@ -67,6 +68,7 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHTransformSystem>();
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHSystemManager::CreateSystem<SHAudioSystem>();
SHSystemManager::CreateSystem<SHCameraSystem>();
#ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO);
@ -81,15 +83,20 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
#ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
#endif
@ -101,13 +108,14 @@ namespace Sandbox
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
//TODO: REMOVE AFTER PRESENTATION
//SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
//SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
//TODO: REMOVE AFTER PRESENTATION
@ -125,21 +133,27 @@ namespace Sandbox
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC();
SHAssetManager::Load();
}
void SBApplication::Update(void)
{
SHGraphicsSystem* graphicsSystem = SHADE::SHSystemManager::GetSystem<SHGraphicsSystem>();
SHEditor* editor = SHADE::SHSystemManager::GetSystem<SHEditor>();
//TODO: Change true to window is open
while (!window.WindowShouldClose())
{
SHFrameRateController::UpdateFRC();
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
SHSceneManager::UpdateSceneManager();
#ifdef SHEDITOR
if(editor->editorState == SHEditor::State::PLAY)
SHSceneManager::SceneUpdate(0.016f);
SHSystemManager::RunRoutines(false, 0.016f);
#endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
//editor->PollPicking();
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
}
@ -154,6 +168,7 @@ namespace Sandbox
SHSceneManager::Exit();
SHSystemManager::Exit();
SHAssetManager::Unload();
}
}

View File

@ -1,4 +1,4 @@
#include "SBpch.h"
#include "SBpch.h"
#include "SBTestScene.h"
#include "ECS_Base/Managers/SHSystemManager.h"
@ -14,6 +14,8 @@
#include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h"
#include "Resource/SHResourceManager.h"
using namespace SHADE;
@ -40,34 +42,22 @@ namespace Sandbox
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
//Test Racoon mesh
auto meshes = SHADE::SHAssetManager::GetAllMeshes();
std::vector<Handle<SHMesh>> handles;
for (auto const& mesh : meshes)
{
if (mesh.header.meshName == "Cube.012")
{
handles.push_back(graphicsSystem->AddMesh(
mesh.header.vertexCount,
mesh.vertexPosition.data(),
mesh.texCoords.data(),
mesh.vertexTangent.data(),
mesh.vertexNormal.data(),
mesh.header.indexCount,
mesh.indices.data()
));
}
}
graphicsSystem->BuildMeshBuffers();
// Load Textures
auto textures = SHADE::SHAssetManager::GetAllTextures();
std::vector<Handle<SHTexture>> texHandles;
for (const auto& tex : textures)
for (const auto& asset : SHAssetManager::GetAllAssets())
{
auto texture = graphicsSystem->Add(tex);
texHandles.push_back(texture);
switch (asset.type)
{
case AssetType::MESH:
if (asset.name == "Cube.012")
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
break;
case AssetType::IMAGE:
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
break;
}
graphicsSystem->BuildTextures();
}
SHResourceManager::FinaliseChanges();
// Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
@ -77,9 +67,9 @@ namespace Sandbox
customMat->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
constexpr int NUM_ROWS = 10;
constexpr int NUM_COLS = 10;
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
constexpr int NUM_ROWS = 3;
constexpr int NUM_COLS = 1;
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
@ -101,13 +91,13 @@ namespace Sandbox
//Set initial positions
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
transform.SetWorldScale(TEST_OBJ_SCALE);
if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
else
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
//else
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
stressTestObjects.emplace_back(entity);
}
@ -166,6 +156,10 @@ namespace Sandbox
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
SHComponentManager::AddComponent<SHCameraComponent>(0);
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
}
void SBTestScene::Update(float dt)

View File

@ -0,0 +1,30 @@
/*************************************************************************//**
* \file SHAnimationAsset.h
* \author Loh Xiao Qi
* \date October 2022
* \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 <vector>
#include <assimp/anim.h>
#include "SH_API.power h"
namespace SHADE
{
struct SH_API SHAnimationAsset
{
std::string name;
std::vector<aiNodeAnim*> nodeChannels;
std::vector<aiMeshAnim*> meshChannels;
std::vector<aiMeshMorphAnim*> morphMeshChannels;
double duration;
double ticksPerSecond;
};
}

View File

@ -0,0 +1,30 @@
/*************************************************************************//**
* \file SHAnimationAsset.h
* \author Loh Xiao Qi
* \date October 2022
* \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 <vector>
#include <assimp/anim.h>
#include "SHAssetData.h"
namespace SHADE
{
struct SH_API SHAnimationAsset : SHAssetData
{
std::string name;
std::vector<aiNodeAnim*> nodeChannels;
std::vector<aiMeshAnim*> meshChannels;
std::vector<aiMeshMorphAnim*> morphMeshChannels;
double duration;
double ticksPerSecond;
};
}

View File

@ -0,0 +1,19 @@
/*************************************************************************//**
* \file SHAssetDataBase.h
* \author Loh Xiao Qi
* \date October 2022
* \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
namespace SHADE
{
struct SHAssetData
{
virtual ~SHAssetData(){}
};
}

View File

@ -0,0 +1,4 @@
#pragma once
#include "SHMeshAsset.h"
#include "SHTextureAsset.h"

View File

@ -0,0 +1,21 @@
/*************************************************************************//**
* \file SHInternalAsset.h
* \author Loh Xiao Qi
* \date October 2022
* \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 "SHAsset.h"
namespace SHADE
{
struct SHInternalAsset : SHAsset
{
};
}

View File

@ -14,7 +14,7 @@
#include <vector>
#include "Math/SHMath.h"
#include "SH_API.h"
#include "SHAssetData.h"
namespace SHADE
{
@ -22,10 +22,10 @@ namespace SHADE
{
uint32_t vertexCount;
uint32_t indexCount;
std::string meshName;
std::string name;
};
struct SH_API SHMeshAsset
struct SH_API SHMeshAsset : SHAssetData
{
bool compiled;
bool changed;

View File

@ -2,13 +2,15 @@
#include "tinyddsloader.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "SHAssetData.h"
namespace SHADE
{
struct SHTextureAsset
struct SHTextureAsset : SHAssetData
{
bool compiled;
std::string name;
uint32_t numBytes;
uint32_t width;
uint32_t height;

View File

@ -0,0 +1,21 @@
/*************************************************************************//**
* \file SHAssetLoader.h
* \author Loh Xiao Qi
* \date October 2022
* \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 "Assets/Asset Types/SHAssetData.h"
namespace SHADE
{
struct SHAssetLoader
{
virtual SHAssetData* Load(AssetPath path) = 0;
};
}

View File

@ -0,0 +1,141 @@
/*************************************************************************//**
* \file SHAssimpLibrary.cpp
* \author Loh Xiao Qi
* \date October 2022
* \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.
*****************************************************************************/
#include "SHpch.h"
#include "SHAssimpLibrary.h"
#include <assimp/postprocess.h>
namespace SHADE
{
Assimp::Importer SHAssimpLibrary::aiImporter;
void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
{
for (size_t i {0}; i < node.mNumMeshes; ++i)
{
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
meshes.push_back(ProcessMesh(*mesh));
}
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
{
ProcessNode(*node.mChildren[i], scene, meshes);
}
}
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
{
if (scene.HasAnimations())
{
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
for (auto i{0}; i < scene.mNumAnimations; ++i)
{
auto const& anim {*scene.mAnimations[i]};
anims[i].name = anim.mName.C_Str();
anims[i].duration = anim.mDuration;
anims[i].ticksPerSecond = anim.mTicksPerSecond;
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
}
}
}
SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
{
SHMeshAsset* result = new SHMeshAsset();
result->compiled = false;
result->changed = false;
for (size_t i{0}; i < mesh.mNumVertices; ++i)
{
// Vertex position
SHVec3 vertex;
vertex.x = mesh.mVertices[i].x;
vertex.y = mesh.mVertices[i].y;
vertex.z = mesh.mVertices[i].z;
result->vertexPosition.push_back(vertex);
// Tex coords
SHVec2 texCoord{0.f, 0.f};
if (mesh.mTextureCoords[0])
{
texCoord.x = mesh.mTextureCoords[0][i].x;
texCoord.y = mesh.mTextureCoords[0][i].y;
}
result->texCoords.push_back(texCoord);
// Normals
SHVec3 normal{0.f, 0.f, 0.f};
if (mesh.mNormals)
{
normal.x = mesh.mNormals[i].x;
normal.y = mesh.mNormals[i].y;
normal.z = mesh.mNormals[i].z;
}
result->vertexNormal.push_back(normal);
// Tangent
SHVec3 tangent{0.f, 0.f, 0.f};
if (mesh.mTangents)
{
tangent.x = mesh.mTangents[i].x;
tangent.y = mesh.mTangents[i].y;
tangent.z = mesh.mTangents[i].z;
}
result->vertexTangent.push_back(tangent);
}
for (size_t i {0}; i < mesh.mNumFaces; ++i)
{
aiFace face = mesh.mFaces[i];
for (size_t j{0}; j < face.mNumIndices; ++j)
{
result->indices.push_back(face.mIndices[j]);
}
}
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
result->header.name = mesh.mName.C_Str();
return result;
}
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
{
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
| aiProcess_RemoveRedundantMaterials // remove redundant materials
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
);
if (!scene || !scene->HasMeshes())
{
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
return;
}
ExtractAnimations(*scene, anims);
ProcessNode(*scene->mRootNode, *scene, meshes);
aiImporter.FreeScene();
}
}

View File

@ -0,0 +1,36 @@
/*************************************************************************//**
* \file SHAssimpLibrary.h
* \author Loh Xiao Qi
* \date October 2022
* \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 <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <vector>
#include "../SHAssetMacros.h"
#include "../Asset Types/SHMeshAsset.h"
#include "../Asset Types/SHAnimationAsset.h"
namespace SHADE
{
class SHAssimpLibrary
{
private:
using MeshVectorRef = std::vector<SHMeshAsset*>&;
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
static Assimp::Importer aiImporter;
static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
public:
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
};
}

View File

@ -16,11 +16,11 @@
#include <fstream>
void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
{
std::string newPath{ path.string() };
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
newPath += asset.header.meshName + MESH_EXTENSION;
newPath += asset.header.name + MESH_EXTENSION.data();
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
if (!file.is_open())
@ -67,4 +67,6 @@ void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPat
);
file.close();
return newPath;
}

View File

@ -21,6 +21,6 @@ namespace SHADE
{
private:
public:
static void CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
static std::string CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
};
}

View File

@ -12,129 +12,11 @@
*****************************************************************************/
#include "SHpch.h"
#include "SHMeshLoader.h"
#include <assimp/postprocess.h>
#include <fstream>
namespace SHADE
{
Assimp::Importer SHMeshLoader::aiImporter;
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
{
for (size_t i {0}; i < node.mNumMeshes; ++i)
{
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
meshes.push_back(ProcessMesh(*mesh, scene));
}
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
{
ProcessNode(*node.mChildren[i], scene, meshes);
}
}
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
{
(void)scene;
SHMeshAsset result
{
.compiled { false},
.changed { false }
};
for (size_t i{0}; i < mesh.mNumVertices; ++i)
{
// Vertex position
SHVec3 vertex;
vertex.x = mesh.mVertices[i].x;
vertex.y = mesh.mVertices[i].y;
vertex.z = mesh.mVertices[i].z;
result.vertexPosition.push_back(vertex);
// Tex coords
SHVec2 texCoord{0.f, 0.f};
if (mesh.mTextureCoords[0])
{
texCoord.x = mesh.mTextureCoords[0][i].x;
texCoord.y = mesh.mTextureCoords[0][i].y;
}
result.texCoords.push_back(texCoord);
// Normals
SHVec3 normal{0.f, 0.f, 0.f};
if (mesh.mNormals)
{
normal.x = mesh.mNormals[i].x;
normal.y = mesh.mNormals[i].y;
normal.z = mesh.mNormals[i].z;
}
result.vertexNormal.push_back(normal);
// Tangent
SHVec3 tangent{0.f, 0.f, 0.f};
if (mesh.mTangents)
{
tangent.x = mesh.mTangents[i].x;
tangent.y = mesh.mTangents[i].y;
tangent.z = mesh.mTangents[i].z;
}
result.vertexTangent.push_back(tangent);
}
for (size_t i {0}; i < mesh.mNumFaces; ++i)
{
aiFace face = mesh.mFaces[i];
for (size_t j{0}; j < face.mNumIndices; ++j)
{
result.indices.push_back(face.mIndices[j]);
}
}
result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
result.header.indexCount = static_cast<uint32_t>(result.indices.size());
result.header.meshName = mesh.mName.C_Str();
return result;
}
void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
{
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
| aiProcess_RemoveRedundantMaterials // remove redundant materials
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
);
if (!scene || !scene->HasMeshes())
{
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
return;
}
//TODO MATERIALS FROM MESHES
//if (scene->HasMaterials())
//{
// for (int i{0}; i < scene->mNumMaterials; ++i)
// {
// if (scene->mMaterials[i]->mNumProperties > 0)
// {
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
// }
//std::cout << scene->mMaterials[i]->;
// }
//}
ProcessNode(*scene->mRootNode, *scene, meshes);
}
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
{
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open())
@ -142,8 +24,7 @@ namespace SHADE
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
}
std::string name{ path.filename().string() };
name = name.substr(0, name.find_last_of('.'));
const std::string name{ path.stem().string() };
file.seekg(0);
@ -170,44 +51,12 @@ namespace SHADE
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
//for (auto i{ 0 }; i < vertCount; ++i)
//{
// file >> vertPos[i].x;
// file >> vertPos[i].y;
// file >> vertPos[i].z;
//}
//
//for (auto i{ 0 }; i < vertCount; ++i)
//{
// file >> vertTan[i].x;
// file >> vertTan[i].y;
// file >> vertTan[i].z;
//}
//for (auto i{ 0 }; i < vertCount; ++i)
//{
// file >> vertNorm[i].x;
// file >> vertNorm[i].y;
// file >> vertNorm[i].z;
//}
//for (auto i{ 0 }; i < vertCount; ++i)
//{
// file >> texCoord[i].x;
// file >> texCoord[i].y;
//}
//for (auto i{ 0 }; i < indexCount; ++i)
//{
// file >> indices[i];
//}
mesh.compiled = true;
mesh.changed = false;
mesh.header.indexCount = indexCount;
mesh.header.vertexCount = vertCount;
mesh.header.meshName = name;
mesh.header.name = name;
mesh.vertexPosition = std::move(vertPos);
mesh.vertexTangent = std::move(vertTan);
@ -218,15 +67,12 @@ namespace SHADE
file.close();
}
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
SHAssetData* SHMeshLoader::Load(AssetPath path)
{
if (path.extension().string() == GLTF_EXTENSION)
{
LoadExternal(meshes, path);
return;
}
auto result = new SHMeshAsset();
meshes.emplace_back();
LoadSHMesh(meshes.back(), path);
LoadSHMesh(path, *result);
return result;
}
}

View File

@ -10,27 +10,15 @@
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#pragma once
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include "../SHAssetMacros.h"
#include "../Asset Types/SHMeshAsset.h"
#include <vector>
#include "SHAssetLoader.h"
namespace SHADE
{
class SHMeshLoader
struct SHMeshLoader : public SHAssetLoader
{
private:
static Assimp::Importer aiImporter;
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
public:
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
SHAssetData* Load(AssetPath path) override;
};
}

View File

@ -17,7 +17,7 @@
namespace SHADE
{
void SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
std::string SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
{
std::string newPath{ path.string() };
newPath = newPath.substr(0, newPath.find_last_of('.'));
@ -69,5 +69,7 @@ namespace SHADE
);
file.close();
return newPath;
}
}

View File

@ -19,6 +19,6 @@ namespace SHADE
{
struct SHTextureCompiler
{
static void CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
static std::string CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
};
}

View File

@ -93,6 +93,7 @@ namespace SHADE
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
asset.name = path.stem().string();
asset.compiled = false;
asset.numBytes = static_cast<uint32_t>(totalBytes);
asset.width = file.GetWidth();
@ -132,6 +133,15 @@ namespace SHADE
file.close();
}
SHAssetData* SHTextureLoader::Load(AssetPath path)
{
auto result = new SHTextureAsset();
LoadImageAsset(path, *result);
return result;
}
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
{
if (path.extension().string() == DDS_EXTENSION)

View File

@ -15,19 +15,20 @@
#include "../SHAssetMacros.h"
#include "../Asset Types/SHTextureAsset.h"
#include "tinyddsloader.h"
#include "SHAssetLoader.h"
namespace SHADE
{
class SHTextureLoader
class SHTextureLoader : public SHAssetLoader
{
private:
static std::string TinyDDSResultToString(tinyddsloader::Result value);
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
std::string TinyDDSResultToString(tinyddsloader::Result value);
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
public:
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
SHAssetData* Load(AssetPath path) override;
};
}

View File

@ -12,11 +12,12 @@
#pragma once
#include "Filesystem/SHFileSystem.h"
#include "SHAssetMacros.h"
#include "Assets/SHAssetMacros.h"
#include "SH_API.h"
namespace SHADE
{
struct SHAsset
struct SH_API SHAsset
{
AssetName name;
AssetID id;

View File

@ -32,15 +32,15 @@ typedef std::filesystem::path AssetPath;
typedef unsigned char* AssetData;
typedef std::string AssetMetaVersion;
typedef std::string AssetExtension;
typedef unsigned char AssetTypeMeta;
typedef size_t AssetTypeMeta;
typedef FMOD::Sound* SHSound;
// Asset Meta Version
#define ASSET_META_VER "1.0"
constexpr std::string_view ASSET_META_VER { "1.0" };
// Asset type enum
enum class AssetType : uint8_t
enum class AssetType : AssetTypeMeta
{
INVALID = 0,
AUDIO = 1,
@ -53,29 +53,35 @@ enum class AssetType : uint8_t
SCENE,
PREFAB,
AUDIO_WAV,
DDS
DDS,
MAX_COUNT
};
//Directory
#define ASSET_ROOT "./Assets/"
#ifdef _PUBLISH
constexpr std::string_view ASSET_ROOT {"Assets"};
#else
constexpr std::string_view ASSET_ROOT {"../../Assets"};
#endif
// ASSET EXTENSIONS
#define META_EXTENSION ".shmeta"
#define IMAGE_EXTENSION ".png"
#define AUDIO_EXTENSION ".ogg"
#define AUDIO_WAV_EXTENSION ".wav"
#define SHADER_EXTENSION ".glsl"
#define SCRIPT_EXTENSION ".cs"
#define SCENE_EXTENSION ".SHADE"
#define PREFAB_EXTENSION ".SHPrefab"
#define MATERIAL_EXTENSION ".SHMat"
#define TEXTURE_EXTENSION ".shtex"
#define DDS_EXTENSION ".dds"
#define FBX_EXTENSION ".fbx"
#define GLTF_EXTENSION ".gltf"
#define MESH_EXTENSION ".shmesh"
constexpr std::string_view META_EXTENSION {".shmeta"};
constexpr std::string_view IMAGE_EXTENSION {".png"};
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
constexpr std::string_view SHADER_EXTENSION {".glsl"};
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
constexpr std::string_view SCENE_EXTENSION {".SHADE"};
constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
constexpr std::string_view DDS_EXTENSION {".dds"};
constexpr std::string_view FBX_EXTENSION {".fbx"};
constexpr std::string_view GLTF_EXTENSION {".gltf"};
constexpr std::string_view MESH_EXTENSION {".shmesh"};
std::string const EXTENSIONS[] = {
constexpr std::string_view EXTENSIONS[] = {
AUDIO_EXTENSION,
SHADER_EXTENSION,
MATERIAL_EXTENSION,
@ -91,10 +97,12 @@ std::string const EXTENSIONS[] = {
GLTF_EXTENSION
};
constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
// Error flags
#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
#define META_NOT_FOUND_ERR "META NOT FOUND"
#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
#endif // !SH_ASSET_MACROS_H

View File

@ -14,6 +14,7 @@
#include "SHAssetMetaHandler.h"
#include "Filesystem/SHFileSystem.h"
#include "Libraries/SHAssimpLibrary.h"
#include "Libraries/SHMeshLoader.h"
#include "Libraries/SHTextureLoader.h"
@ -25,11 +26,10 @@ namespace SHADE
FMOD::System* SHAssetManager::audioSystem;
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
std::vector<SHAsset> SHAssetManager::assetCollection;
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
std::vector<SHAsset> SHAssetManager::assetCollection;
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
/****************************************************************************
* \brief Static function to generate asset ID.
@ -56,10 +56,12 @@ namespace SHADE
****************************************************************************/
void SHAssetManager::Unload() noexcept
{
for (auto const& asset : assetCollection)
{
SHAssetMetaHandler::WriteMetaData(asset);
}
void SHAssetManager::Unload(AssetID assetId) noexcept
{
// TODO
}
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
@ -80,7 +82,37 @@ namespace SHADE
// return std::filesystem::path();
//}
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string());
}
AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type)
{
std::string folder;
switch(type)
{
case AssetType::SCENE:
folder = "scenes/";
break;
case AssetType::PREFAB:
folder = "prefabs/";
break;
case AssetType::MATERIAL:
folder = "materials/";
break;
default:
folder = "/";
}
return std::filesystem::path{
std::string(ASSET_ROOT) +
folder +
name +
std::string(EXTENSIONS[static_cast<size_t>(type)])
};
}
/****************************************************************************
@ -116,7 +148,7 @@ namespace SHADE
// folder = "";
// break;
//}
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
SHAssetMetaHandler::WriteMetaData(meta);
@ -125,6 +157,19 @@ namespace SHADE
return id;
}
AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
{
AssetID id = GenerateAssetID(type);
assetCollection.emplace_back(
name,
id,
type,
GenerateNewPath(name, type),
0
);
return id;
}
/****************************************************************************
* \brief Import new asset from outside editor window.
*
@ -135,6 +180,9 @@ namespace SHADE
{
std::filesystem::path const path{ p };
auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
auto const id = GenerateAssetID(type);
std::filesystem::path const newPath{ GenerateLocalPath(path) };
if (newPath.empty())
{
@ -144,11 +192,7 @@ namespace SHADE
std::filesystem::copy(path, newPath);
AssetID id{ RetrieveAsset(newPath.string().c_str()) };
if (id != 0)
{
LoadData(id);
}
assetCollection.push_back(CreateAssetFromPath(newPath));
return id;
}
@ -159,138 +203,14 @@ namespace SHADE
****************************************************************************/
void SHAssetManager::RefreshAllAssets() noexcept
{
std::vector<AssetPath> metaFiles;
std::vector<AssetPath> AssetFiles;
//SHFileSystem::LoadAllFiles(metaFiles, AssetFiles);
//std::vector<AssetPath> AssetFilesVerified;
std::vector<AssetPath> AssetFilesNew;
for (auto const& asset : AssetFiles)
{
bool found = false;
for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it)
{
std::string fileExtCheck{ asset.filename().string() };
fileExtCheck += META_EXTENSION;
if (it->filename().string() == fileExtCheck)
{
metaFiles.erase(it);
found = true;
break;
}
}
if (!found && IsRecognised(asset.extension().string().c_str()))
{
AssetFilesNew.push_back(asset);
}
}
std::vector<SHAsset> newLoad;
newLoad.reserve(AssetFilesNew.size());
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
for (auto const& file : AssetFilesNew)
{
newLoad.push_back(RegisterAssetNew(file));
}
//UpdateAllSpriteSets();
}
void SHAssetManager::LoadDataTemp(std::string p) noexcept
{
AssetPath path{ p };
if (path.extension().string() == FBX_EXTENSION
|| path.extension().string() == GLTF_EXTENSION
|| path.extension().string() == MESH_EXTENSION)
{
LoadGLTF(
{
.name {path.filename().string()},
.id {0},
.type {AssetType::MESH},
.path {path},
.location {0}
}
);
}
else if (path.extension().string() == DDS_EXTENSION
|| path.extension().string() == TEXTURE_EXTENSION)
{
LoadDDS(
{
.name {path.filename().string()},
.id {0},
.type {AssetType::DDS},
.path {path},
.location {0}
}
);
}
}
std::vector<SHMeshAsset> SHAssetManager::GetAllMeshes() noexcept
{
std::vector<SHMeshAsset> result;
for (auto const& mesh : meshCollection)
{
result.push_back(mesh.second);
}
return result;
}
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
{
std::vector<SHTextureAsset> result;
for (auto const& dds : textureCollection)
{
result.push_back(dds.second);
}
return result;
}
/****************************************************************************
* \param Path for meta data file
* \param Path for asset file
* \brief Links meta data to asset in registries. Meta data should
* already exist
****************************************************************************/
void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept
{
SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath);
assetCollection.push_back(meta);
}
/****************************************************************************
* \param Path for asset file
* \brief Creates new meta data for new asset.
****************************************************************************/
SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept
{
SHAsset meta;
meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string());
meta.id = GenerateAssetID(meta.type);
assetCollection.push_back(meta);
SHAssetMetaHandler::WriteMetaData(meta);
return assetCollection.back();
}
bool SHAssetManager::IsRecognised(char const* ext) noexcept
{
for (auto const& e : EXTENSIONS)
{
if (strcmp(ext, e.c_str()) == 0)
if (strcmp(ext, e.data()) == 0)
{
return true;
}
@ -299,35 +219,31 @@ namespace SHADE
return false;
}
void SHAssetManager::LoadGLTF(SHAsset asset) noexcept
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
{
std::vector<SHMeshAsset> meshes;
SHAsset result;
SHMeshLoader::LoadMesh(meshes, asset.path);
result.name = path.stem().string();
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
result.id = GenerateAssetID(result.type);
result.path = path;
for (auto const& mesh : meshes)
{
meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh);
if (!mesh.compiled)
{
SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
}
}
return result;
}
void SHAssetManager::LoadDDS(SHAsset asset) noexcept
void SHAssetManager::InitLoaders() noexcept
{
SHTextureAsset image;
SHTextureLoader::LoadImageAsset(asset.path, image);
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
if (!image.compiled)
{
SHTextureCompiler::CompileTextureBinary(image, asset.path);
}
loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
}
/****************************************************************************
@ -335,8 +251,9 @@ namespace SHADE
****************************************************************************/
void SHAssetManager::Load() noexcept
{
RetrieveAssets();
LoadAllData();
InitLoaders();
BuildAssetCollection();
//LoadAllData();
}
/****************************************************************************
@ -346,114 +263,38 @@ namespace SHADE
{
for (auto const& asset : assetCollection)
{
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
assetData.emplace(asset.id, data);
}
}
void SHAssetManager::LoadData(AssetID id) noexcept
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
{
(void)id;
}
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
/****************************************************************************
* \brief Retrieve all asset files and meta files from filesystem
****************************************************************************/
void SHAssetManager::RetrieveAssets() noexcept
if (data == nullptr)
{
std::vector<AssetPath> metaFiles;
std::vector<AssetPath> AssetFiles;
//TODO: Write new function for file manager to loop through all files
SHFileSystem::StartupFillDirectories(ASSET_ROOT);
FolderPointer rootFolder = SHFileSystem::GetRoot();
for (auto const& meta : metaFiles)
{
for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
it != AssetFiles.cend();
++it)
{
// Asset exists for meta file
std::string fileExtCheck{ it->filename().string() };
fileExtCheck += META_EXTENSION;
if (meta.filename().string() == fileExtCheck)
{
RegisterAsset(meta, *it);
AssetFiles.erase(it);
break;
}
}
}
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
for (auto const& file : AssetFiles)
{
if (IsRecognised(file.extension().string().c_str()))
{
SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
}
else
{
std::cout << "Unsupported File Format: " << file.filename() << "\n";
}
}
assetData.emplace(asset.id, data);
}
AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
return data;
}
void SHAssetManager::BuildAssetCollection() noexcept
{
std::filesystem::path p{ path };
if (IsRecognised(p.extension().string().c_str()))
for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
{
SHAsset const& meta{ RegisterAssetNew(p) };
SHAssetMetaHandler::WriteMetaData(meta);
return meta.id;
}
else
if (dir.is_regular_file())
{
std::cout << "Unsupported File Format: " << p.filename() << "\n";
}
// Assert that file imported is not recognised
return 0;
}
/****************************************************************************
* \param Full path of file
* \brief Extracts file name from path. Formats file name into readable
* with spaces and capitalises first letter of every word
****************************************************************************/
AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept
if (dir.path().extension().string() == META_EXTENSION.data())
{
std::string name{ filepath.filename().string() };
name = name.substr(0, name.find_last_of('.'));
//if (name[0] <= 122 && name[0] >= 97)
//{
// name[0] -= 32;
//}
//for (size_t i{ 1 }; i < name.length(); ++i)
//{
// // Replace all underscores with spaces
// if (name[i] == '_')
// {
// name[i] = ' ';
// continue;
// }
// if (name[i + 1] <= 'Z' && name[i + 1] >= 'A'
// && name[i] <= 'z' && name[i] >= 'a')
// {
// name.insert(i + 1, 1, ' ');
// continue;
// }
// if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a')
// {
// name[i] -= 32;
// }
//}
return name;
assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
}
}
}
}
}

View File

@ -11,9 +11,10 @@
#pragma once
#include "tinyddsloader.h"
#include "SHAsset.h"
#include "Asset Types/SHAssetData.h"
#include "Libraries/SHAssetLoader.h"
#include <memory>
#include "Asset Types/SHMeshAsset.h"
#include "Asset Types/SHTextureAsset.h"
#include "SH_API.h"
namespace SHADE
@ -28,10 +29,13 @@ namespace SHADE
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
static AssetPath GenerateNewPath(AssetName name, AssetType type);
/****************************************************************************
* \brief Deallocate all memory used by resource data
****************************************************************************/
static void Unload() noexcept;
static void Unload(AssetID assetId) noexcept;
/****************************************************************************
* \brief Load all resources that are in the folder
@ -54,6 +58,7 @@ namespace SHADE
* \return resource id generated for new asset
****************************************************************************/
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
/****************************************************************************
* \brief Import new resource from outside editor window.
@ -70,64 +75,33 @@ namespace SHADE
static void RefreshAllAssets() noexcept;
// -------------------------------------------------------------------------/
//TODO: TEMPORARY FOR TESTING GLTF & DDS
static void LoadDataTemp(std::string path) noexcept;
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
template<typename T>
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
private:
/****************************************************************************
* \brief Load resource data into memory
****************************************************************************/
static void LoadAllData() noexcept;
static void LoadData(AssetID id) noexcept;
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
/****************************************************************************
* \brief Retrieve all resource files and meta files from filesystem
****************************************************************************/
static void RetrieveAssets() noexcept;
static AssetID RetrieveAsset(char const* path) noexcept;
/****************************************************************************
* \param Full path of file
* \brief Extracts file name from path. Formats file name into readable
* with spaces and capitalises first letter of every word
****************************************************************************/
static AssetName GetNameFromPath(AssetPath) noexcept;
/****************************************************************************
* \param Path for meta data file
* \param Path for resource file
* \brief Links meta data to resource in registries. Meta data should
* already exist
****************************************************************************/
static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept;
/****************************************************************************
* \param Path for resource file
* \brief Creates new meta data for new resource.
****************************************************************************/
static SHAsset RegisterAssetNew(AssetPath const&) noexcept;
inline static void BuildAssetCollection() noexcept;
static bool IsRecognised(char const*) noexcept;
// Specialised load calls
static void LoadGLTF(SHAsset asset) noexcept;
static void LoadDDS(SHAsset asset) noexcept;
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
static void InitLoaders() noexcept;
static FMOD::System* audioSystem;
static std::unordered_map<AssetID,SHSound>* audioSoundList;
static std::vector<SHAssetLoader*> loaders;
// For all resources
static std::vector<SHAsset> assetCollection;
static std::unordered_map<AssetID, SHAsset> assetRegistry;
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
static std::unordered_map<AssetID, SHAssetData * const> assetData;
};
}
#include "SHAssetManager.hpp"

View File

@ -0,0 +1,26 @@
#include "SHAssetManager.h"
namespace SHADE
{
template<typename T>
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
{
if (!assetData.contains(id))
{
for (auto const& asset : assetCollection)
{
if (asset.id == id)
{
assetData.emplace(id, LoadData(asset));
return dynamic_cast<T const* const>(assetData[id]);
}
}
SHLOG_ERROR("Asset ID provided does not exist: {}", id);
return nullptr;
}
return dynamic_cast<T const* const>(assetData[id]);
}
}

View File

@ -37,7 +37,7 @@ namespace SHADE
{
for (int i{0}; i < EXTENSIONS->size(); ++i)
{
if (ext == EXTENSIONS[i])
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
{
return static_cast<AssetType>(i);
}
@ -53,7 +53,7 @@ namespace SHADE
****************************************************************************/
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
{
return EXTENSIONS[static_cast<size_t>(type)];
return AssetExtension(EXTENSIONS[static_cast<size_t>(type)]);
}
/****************************************************************************
@ -72,6 +72,13 @@ namespace SHADE
std::string line;
SHAsset meta;
// Get resource name
GetFieldValue(metaFile, line);
std::stringstream nameStream{ line };
AssetName name;
nameStream >> name;
meta.name = name;
// Get resource id
GetFieldValue(metaFile, line);
std::stringstream idStream{ line };
@ -88,6 +95,8 @@ namespace SHADE
metaFile.close();
meta.path = path.parent_path().string() + "/" + path.stem().string();
return meta;
}
@ -103,7 +112,7 @@ namespace SHADE
std::string path{ meta.path.string() };
path.append(META_EXTENSION);
std::ofstream metaFile{ path, std::ios_base::out };
std::ofstream metaFile{ path, std::ios_base::out | std::ios_base::trunc };
if (!metaFile.is_open())
{
@ -113,17 +122,7 @@ namespace SHADE
metaFile << "Name: " << meta.name << "\n";
metaFile << "ID: " << meta.id << "\n";
metaFile << "Type: " << static_cast<int>(meta.type) << std::endl;
//TODO Add in information that is specific to types like mesh
switch(meta.type)
{
case AssetType::MESH:
break;
default:
break;
}
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
metaFile.close();
}

View File

@ -0,0 +1,189 @@
#include "SHpch.h"
#include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "SHCameraSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
SHCameraComponent::SHCameraComponent()
:yaw(0.0f), pitch(0.0f), roll(0.0f)
, width(1920.0f), height(1080.0f), zNear(0.01f), zFar(10000.0f), fov(90.0f), movementSpeed(1.0f), turnSpeed(0.5f)
, perspProj(true), dirtyView(true), dirtyProj(true)
, viewMatrix(), projMatrix()
, position()
{
ComponentFamily::GetID<SHCameraComponent>();
}
SHCameraComponent::~SHCameraComponent()
{
}
void SHCameraComponent::SetYaw(float yaw) noexcept
{
this->yaw = yaw;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{rotation.x,yaw, rotation.z});
}
dirtyView = true;
}
void SHCameraComponent::SetPitch(float pitch) noexcept
{
this->pitch = pitch;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ pitch,rotation.y, rotation.z });
}
dirtyView = true;
}
void SHCameraComponent::SetRoll(float roll) noexcept
{
this->roll = roll;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, roll});
}
dirtyView = true;
}
void SHCameraComponent::SetPositionX(float x) noexcept
{
position.x = x;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,position.y, position.z});
}
dirtyView = true;
}
void SHCameraComponent::SetPositionY(float y) noexcept
{
position.y = y;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,y, position.z });
}
dirtyView = true;
}
void SHCameraComponent::SetPositionZ(float z) noexcept
{
position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,position.y, z });
}
dirtyView = true;
}
void SHCameraComponent::SetPosition(float x,float y, float z) noexcept
{
position.x = x;
position.y = y;
position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,y, z });
}
dirtyView = true;
}
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
{
this->position = pos;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(pos);
}
dirtyView = true;
}
void SHCameraComponent::SetWidth(float width) noexcept
{
this->width = width;
dirtyProj = true;
}
void SHCameraComponent::SetHeight(float height) noexcept
{
this->height = height;
dirtyProj = true;
}
void SHCameraComponent::SetNear(float znear) noexcept
{
this->zNear = znear;
dirtyProj = true;
}
void SHCameraComponent::SetFar(float zFar) noexcept
{
this->zFar = zFar;
dirtyProj = true;
}
void SHCameraComponent::SetFOV(float fov) noexcept
{
this->fov = fov;
dirtyProj = true;
}
float SHCameraComponent::GetYaw() const noexcept
{
return yaw;
}
float SHCameraComponent::GetPitch() const noexcept
{
return pitch;
}
float SHCameraComponent::GetRoll() const noexcept
{
return roll;
}
float SHCameraComponent::GetAspectRatio() const noexcept
{
return width/height;
}
float SHCameraComponent::GetFOV() const noexcept
{
return fov;
}
const SHMatrix& SHCameraComponent::GetViewMatrix() const noexcept
{
return viewMatrix;
}
const SHMatrix& SHCameraComponent::GetProjMatrix() const noexcept
{
return projMatrix;
}
void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->GetDirector(directorCameraIndex)->SetMainCamera(*this);
}
}

View File

@ -0,0 +1,87 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
#include "Math/Vector/SHVec3.h"
#include "Math/SHMatrix.h"
#include "SH_API.h"
namespace SHADE
{
class SH_API SHCameraComponent final : public SHComponent
{
private:
float yaw;
float pitch;
float roll;
float width;
float height;
float zNear;
float zFar;
float fov;
bool dirtyView;
bool dirtyProj;
SHMatrix viewMatrix;
SHMatrix projMatrix;
SHVec3 position;
bool perspProj;
public:
friend class SHCameraSystem;
SHCameraComponent();
~SHCameraComponent();
//Getters and setters.
void SetYaw(float yaw) noexcept;
void SetPitch(float pitch) noexcept;
void SetRoll(float roll) noexcept;
void SetPositionX(float x) noexcept;
void SetPositionY(float y) noexcept;
void SetPositionZ(float z) noexcept;
void SetPosition(float x, float y, float z) noexcept;
void SetPosition(SHVec3& pos) noexcept;
void SetWidth(float width) noexcept;
void SetHeight(float height) noexcept;
void SetNear(float znear) noexcept;
void SetFar(float zfar) noexcept;
void SetFOV(float fov) noexcept;
float GetYaw() const noexcept;
float GetPitch() const noexcept;
float GetRoll() const noexcept;
float GetAspectRatio() const noexcept;
float GetFOV() const noexcept;
const SHMatrix& GetViewMatrix() const noexcept;
const SHMatrix& GetProjMatrix() const noexcept;
void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
float movementSpeed;
SHVec3 turnSpeed;
protected:
};
}

View File

@ -0,0 +1,65 @@
#include "SHpch.h"
#include "SHCameraDirector.h"
#include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Tools/SHLog.h"
namespace SHADE
{
SHCameraDirector::SHCameraDirector()
:mainCameraEID(MAX_EID), transitionCameraEID(MAX_EID)
{
}
SHMatrix SHCameraDirector::GetViewMatrix() const noexcept
{
return viewMatrix;
}
SHMatrix SHCameraDirector::GetProjMatrix() const noexcept
{
return projMatrix;
}
SHMatrix SHCameraDirector::GetVPMatrix() const noexcept
{
return projMatrix * viewMatrix;
}
void SHCameraDirector::UpdateMatrix() noexcept
{
if (mainCameraEID == MAX_EID)
{
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
if (dense.size() == 0)
{
return;
}
mainCameraEID = dense[0].GetEID();
}
SHCameraComponent* camComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(mainCameraEID);
if (!camComponent)
{
SHLOG_WARNING("Camera Director warning: Entity does not have a camera");
}
else
{
viewMatrix = camComponent->GetViewMatrix();
projMatrix = camComponent->GetProjMatrix();
}
}
void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept
{
if (SHEntityManager::IsValidEID(camera.GetEID()) == false)
{
SHLOG_WARNING("Camera Director Warning: Attempting to set an invalid entity as main camera.")
return;
}
mainCameraEID = camera.GetEID();
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "SH_API.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "Math/SHMatrix.h"
#include "Resource/SHHandle.h"
namespace SHADE
{
class SHCameraComponent;
class SH_API SHCameraDirector
{
public:
SHCameraDirector();
~SHCameraDirector() = default;
EntityID mainCameraEID;
EntityID transitionCameraEID;
SHMatrix GetViewMatrix() const noexcept;
SHMatrix GetProjMatrix() const noexcept;
SHMatrix GetVPMatrix() const noexcept;
void UpdateMatrix() noexcept;
void SetMainCamera(SHCameraComponent& cam) noexcept;
private:
protected:
SHMatrix viewMatrix;
SHMatrix projMatrix;
};
typedef Handle<SHCameraDirector> DirectorHandle;
}

View File

@ -0,0 +1,291 @@
#include "SHpch.h"
#include "SHCameraSystem.h"
#include "Math/SHMathHelpers.h"
#include "Input/SHInputManager.h"
#include "Math/Vector/SHVec2.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
void SHCameraSystem::UpdateEditorCamera(double dt) noexcept
{
auto& camera = editorCamera;
SHVec3 view, right, UP;
GetCameraAxis(camera, view, right, UP);
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
{
camera.position -= right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
{
camera.position += right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
{
camera.position += view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
{
camera.position -= view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::Q))
{
camera.position += UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::E))
{
camera.position -= UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::RMB))
{
double mouseX, mouseY;
SHInputManager::GetMouseVelocity(&mouseX, &mouseY);
//std::cout << camera.yaw << std::endl;
camera.pitch -= mouseY * dt * camera.turnSpeed.x;
camera.yaw -= mouseX * dt * camera.turnSpeed.y;
camera.dirtyView = true;
}
UpdateCameraComponent(editorCamera);
}
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
{
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
auto& camera = system->editorCamera;
SHVec3 view, right, UP;
system->GetCameraAxis(camera, view, right, UP);
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
{
//std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
camera.position -= right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
{
camera.position += right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
{
camera.position += view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
{
camera.position -= view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::Q))
{
camera.position += UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::E))
{
camera.position -= UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::RMB))
{
double mouseX, mouseY;
SHInputManager::GetMouseVelocity(&mouseX,&mouseY);
//std::cout << camera.yaw << std::endl;
camera.pitch -= mouseY * dt * camera.turnSpeed.x;
camera.yaw -= mouseX * dt * camera.turnSpeed.y;
camera.dirtyView = true;
}
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
system->UpdateCameraComponent(system->editorCamera);
}
void SHCameraSystem::Init(void)
{
editorCamera.SetPosition(0.0f, 0.0f, 0.0f);
editorCamera.SetPitch(0.0f);
editorCamera.SetYaw(0.0f);
editorCamera.SetRoll(0.0f);
editorCamera.movementSpeed = 2.0f;
}
void SHCameraSystem::Exit(void)
{
}
SHCameraComponent* SHCameraSystem::GetEditorCamera(void) noexcept
{
return &editorCamera;
}
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
{
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
SHVec3 rotation = transform->GetWorldRotation();
camera.pitch = SHMath::RadiansToDegrees(rotation.x);
camera.yaw = SHMath::RadiansToDegrees(rotation.y);
camera.roll = SHMath::RadiansToDegrees(rotation.z);
camera.position = transform->GetWorldPosition();
camera.dirtyView = true;
}
if (camera.dirtyView)
{
SHVec3 view, right, UP;
//ClampCameraRotation(camera);
GetCameraAxis(camera, view, right, UP);
camera.viewMatrix = SHMatrix::Identity;
camera.viewMatrix(0, 0) = right[0];
camera.viewMatrix(0, 1) = right[1];
camera.viewMatrix(0, 2) = right[2];
camera.viewMatrix(1, 0) = UP[0];
camera.viewMatrix(1, 1) = UP[1];
camera.viewMatrix(1, 2) = UP[2];
camera.viewMatrix(2, 0) = view[0];
camera.viewMatrix(2, 1) = view[1];
camera.viewMatrix(2, 2) = view[2];
camera.viewMatrix(0, 3) = -right.Dot(camera.position);
camera.viewMatrix(1, 3) = -UP.Dot(camera.position);
camera.viewMatrix(2, 3) = -view.Dot(camera.position);
camera.dirtyView = false;
}
if (camera.dirtyProj == true)
{
if (camera.perspProj == true)
{
const float ASPECT_RATIO = (camera.GetAspectRatio());
const float TAN_HALF_FOV = tan(SHMath::DegreesToRadians(camera.fov) * 0.5f);
camera.projMatrix = SHMatrix::Identity;
camera.projMatrix(0, 0) = 1.0f / (ASPECT_RATIO * TAN_HALF_FOV);
camera.projMatrix(1, 1) = 1.0f / TAN_HALF_FOV;
camera.projMatrix(2, 2) = camera.zFar / (camera.zFar - camera.zNear);
camera.projMatrix(3, 3) = 0.0f;
camera.projMatrix(3, 2) = 1.0f;
camera.projMatrix(2, 3) = -(camera.zFar * camera.zNear) / (camera.zFar - camera.zNear);
camera.dirtyProj = false;
}
else
{
//const float R = camera.width * 0.5f;
//const float L = -R;
//const float T = camera.height * 0.5f;
//const float B = -T;
//camera.projMatrix = SHMatrix::Identity;
//camera.projMatrix(0, 0) = 2.0f / (R - L);
//camera.projMatrix(1, 1) = 2.0f / (B - T);
//camera.projMatrix(2, 2) = 1.0f / (camera.zFar - camera.zNear);
//camera.projMatrix(3, 0) = -(R + L) / (R - L);
//camera.projMatrix(3, 1) = -(B + T) / (B - T);
//camera.projMatrix(3, 2) = -camera.zNear / (camera.zFar - camera.zNear);
camera.dirtyProj = false;
}
}
}
void SHCameraSystem::GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& upVec) const noexcept
{
SHVec3 target{ 0.0f,0.0f,-1.0f };
SHVec3 up = { 0.0f,1.0f,0.0f };
target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
target =SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
target += camera.position;
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
//target = SHVec3::Normalise(target);
SHVec3::RotateZ(up, camera.roll);
up = SHVec3::Normalise(up);
forward = target - camera.position; forward = SHVec3::Normalise(forward);
right = SHVec3::Cross(forward, up); right = SHVec3::Normalise(right);
upVec = SHVec3::Cross(forward, right);
}
void SHCameraSystem::CameraSystemUpdate::Execute(double dt) noexcept
{
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
for (auto& cam : dense)
{
system->UpdateCameraComponent(cam);
}
for (auto& handle : system->directorHandleList)
{
handle->UpdateMatrix();
}
}
DirectorHandle SHCameraSystem::CreateDirector() noexcept
{
auto handle = directorLibrary.Create();
directorHandleList.emplace_back(handle);
return handle;
}
DirectorHandle SHCameraSystem::GetDirector(size_t index) noexcept
{
if (index < directorHandleList.size())
{
return directorHandleList[index];
}
else
{
return CreateDirector();
}
}
void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept
{
if (camera.pitch > 85)
camera.SetPitch(85);
if (camera.pitch < -85)
camera.SetPitch(-85);
if (camera.roll > 85)
camera.SetRoll(85);
if (camera.roll < -85)
camera.SetRoll(-85);
}
}

View File

@ -0,0 +1,64 @@
#pragma once
#include "ECS_Base/System/SHSystem.h"
#include "SHCameraComponent.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/SHResourceLibrary.h"
#include "SHCameraDirector.h"
#include "SH_API.h"
namespace SHADE
{
class SH_API SHCameraSystem final : public SHSystem
{
private:
//A camera component that represents editor camera.
//This is not tied to any entity. Hence this EID should not be used.
SHCameraComponent editorCamera;
SHResourceLibrary<SHCameraDirector> directorLibrary;
std::vector<DirectorHandle> directorHandleList;
public:
SHCameraSystem(void) = default;
virtual ~SHCameraSystem(void) = default;
void Init (void);
void Exit (void);
class SH_API EditorCameraUpdate final : public SHSystemRoutine
{
public:
EditorCameraUpdate() : SHSystemRoutine("Editor Camera Update", true) { };
virtual void Execute(double dt) noexcept override final;
};
friend class EditorCameraUpdate;
class SH_API CameraSystemUpdate final: public SHSystemRoutine
{
public:
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {};
virtual void Execute(double dt)noexcept override final;
};
friend class CameraSystemUpdate;
SHCameraComponent* GetEditorCamera (void) noexcept;
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
DirectorHandle CreateDirector() noexcept;
DirectorHandle GetDirector(size_t index) noexcept;
void ClampCameraRotation(SHCameraComponent& camera) noexcept;
void UpdateEditorCamera(double dt) noexcept;
protected:
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
};
}

View File

@ -48,6 +48,9 @@ namespace SHADE
{
}
public:
//Whether or not this component is active.
//Systems using this component should are responsible for checking the active state of the component before running their functionality.
@ -59,7 +62,7 @@ namespace SHADE
* \return uint32_t
* The entityID that this component belongs to.
***************************************************************************/
uint32_t GetEID()const
uint32_t GetEID()const noexcept
{
return this->entityID;
}

View File

@ -24,6 +24,7 @@ namespace SHADE
class SHCommand : SHBaseCommand
{
public:
using SHCommandPtr = std::unique_ptr<T>;
typedef std::function<void(T const&)> SetterFunction;
SHCommand(T const& oldVal, T const& value, SetterFunction setFnc)

View File

@ -13,7 +13,7 @@ namespace SHADE
SHCommandManager::CommandStack SHCommandManager::undoStack{};
SHCommandManager::CommandStack SHCommandManager::redoStack{};
void SHCommandManager::PerformCommand(CommandPtr commandPtr, bool const& overrideValue)
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
{
redoStack = CommandStack();
commandPtr->Execute();
@ -27,7 +27,7 @@ namespace SHADE
}
}
void SHCommandManager::RegisterCommand(CommandPtr commandPtr)
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
{
undoStack.push(commandPtr);
}
@ -59,4 +59,14 @@ namespace SHADE
{
return redoStack.size();
}
void SHCommandManager::PopLatestCommandFromRedoStack()
{
redoStack.pop();
}
void SHCommandManager::PopLatestCommandFromUndoStack()
{
undoStack.pop();
}
}//namespace SHADE

View File

@ -19,16 +19,21 @@ namespace SHADE
//#==============================================================#
//|| Type Aliases ||
//#==============================================================#
using CommandPtr = std::shared_ptr<SHBaseCommand>;
using CommandStack = std::stack<CommandPtr>;
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
template<typename T>
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
using CommandStack = std::stack<BaseCommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(CommandPtr commandPtr);
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(BaseCommandPtr commandPtr);
static void UndoCommand();
static void RedoCommand();
static std::size_t GetUndoStackSize();
static std::size_t GetRedoStackSize();
static void PopLatestCommandFromRedoStack();
static void PopLatestCommandFromUndoStack();
private:
static CommandStack undoStack;
static CommandStack redoStack;

View File

@ -21,6 +21,9 @@
//#==============================================================#
#include <imgui.h>
#include "Serialization/SHSerialization.h"
#include "Tools/SHClipboardUtilities.h"
namespace SHADE
{
@ -50,6 +53,7 @@ namespace SHADE
if(const auto root = sceneGraph.GetRoot())
{
auto const& children = root->GetChildren();
for (const auto child : children)
{
RecursivelyDrawEntityNode(child);
@ -66,8 +70,8 @@ namespace SHADE
editor->selectedEntities.clear();
}
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
ImGui::End();
}
ImGui::End();
}
void SHHierarchyPanel::Exit()
@ -75,6 +79,13 @@ namespace SHADE
SHEditorWindow::Exit();
}
void SHHierarchyPanel::SetScrollTo(EntityID eid)
{
if(eid == MAX_EID)
return;
scrollTo = eid;
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
@ -82,9 +93,22 @@ namespace SHADE
{
if (ImGui::BeginMenuBar())
{
if (ImGui::SmallButton(ICON_MD_ADD))
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
if(ImGui::SmallButton(ICON_MD_DESELECT))
{
SHEntityManager::CreateEntity();
auto editor = SHSystemManager::GetSystem<SHEditor>();
editor->selectedEntities.clear();
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Clear Selections");
ImGui::EndTooltip();
}
if (ImGui::SmallButton(ICON_MD_ADD_CIRCLE))
{
SHCommandManager::PerformCommand(std::make_shared<SHCreateEntityCommand>());
}
if (ImGui::IsItemHovered())
{
@ -103,6 +127,13 @@ namespace SHADE
//Get node data (Children, eid, selected)
auto& children = currentNode->GetChildren();
EntityID eid = currentNode->GetEntityID();
if(scrollTo != MAX_EID && eid == scrollTo)
{
ImGui::SetScrollHereY();
scrollTo = MAX_EID;
}
auto editor = SHSystemManager::GetSystem<SHEditor>();
const bool isSelected = (std::ranges::find(editor->selectedEntities, eid) != editor->selectedEntities.end());
@ -117,23 +148,32 @@ namespace SHADE
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
//Draw Node
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//Check For Begin Drag
if (SHDragDrop::BeginSource())
{
ImGui::Text("Moving EID: %zu", eid);
SHDragDrop::SetPayload<EntityID>(DRAG_EID, &eid);
std::string moveLabel = "Moving EID: ";
if(!isSelected)
editor->selectedEntities.push_back(eid);
for(int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
{
moveLabel.append(std::to_string(editor->selectedEntities[i]));
if(i + 1 < static_cast<int>(editor->selectedEntities.size()))
{
moveLabel.append(", ");
}
}
ImGui::Text(moveLabel.c_str());
SHDragDrop::SetPayload<std::vector<EntityID>>(DRAG_EID, &editor->selectedEntities);
SHDragDrop::EndSource();
}
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
{
if (const EntityID* eidPayload = SHDragDrop::AcceptPayload<EntityID>(DRAG_EID)) //If payload is valid
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(DRAG_EID)) //If payload is valid
{
EntityID const dropEID = *eidPayload;
if(!sceneGraph.GetChild(dropEID, eid))
sceneGraph.SetParent(dropEID, eid); //Set dropEID parent to eid (belonging to current Node)
ParentSelectedEntities(eid);
SHDragDrop::EndTarget();
}
}
@ -146,6 +186,18 @@ namespace SHADE
editor->selectedEntities.clear();
editor->selectedEntities.push_back(eid);
}
if(ImGui::Selectable("Copy"))
{
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
}
if(ImGui::Selectable("Paste"))
{
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
}
if(ImGui::Selectable("Paste as Child"))
{
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
}
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{
SHEntityManager::DestroyEntity(eid);
@ -153,7 +205,7 @@ namespace SHADE
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
{
sceneGraph.SetParent(currentNode->GetEntityID(), nullptr);
ParentSelectedEntities(MAX_EID);
}
ImGui::EndPopup();
}
@ -165,7 +217,15 @@ namespace SHADE
{
if (!isSelected)
{
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
if(ImGui::IsKeyDown(ImGuiKey_LeftShift))
{
if(editor->selectedEntities.size() >= 1)
{
SelectRangeOfEntities(editor->selectedEntities[0], eid);
}
else editor->selectedEntities.clear();
}
else if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
editor->selectedEntities.clear();
editor->selectedEntities.push_back(eid);
}//if not selected
@ -212,4 +272,90 @@ namespace SHADE
{
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
}
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID) const noexcept
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData;
std::vector<EntityID> parentedEIDS;
for(auto const& eid : editor->selectedEntities)
{
if(sceneGraph.GetChild(eid, parentEID) == nullptr)
{
parentedEIDS.push_back(eid);
if(auto parent = sceneGraph.GetParent(eid))
entityParentData[eid].oldParentEID = parent->GetEntityID();
entityParentData[eid].newParentEID = parentEID;
}
}
SHCommandManager::PerformCommand(std::make_shared<SHEntityParentCommand>(parentedEIDS, entityParentData));
}
void SHHierarchyPanel::SelectRangeOfEntities(EntityID beginEID, EntityID endEID)
{
bool startSelecting = false; bool endSelecting = false;
auto const editor = SHSystemManager::GetSystem<SHEditor>();
editor->selectedEntities.clear();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
{
auto eid = nodePtr->GetEntityID();
if(!startSelecting)
{
if(eid == beginEID || eid == endEID)
{
startSelecting = true;
editor->selectedEntities.push_back(eid);
}
}
else
{
if(!endSelecting)
{
editor->selectedEntities.push_back(eid);
if(eid == endEID || eid == beginEID)
{
endSelecting = true;
}
}
}
});
}
void SHCreateEntityCommand::Execute()
{
EntityID newEID = SHEntityManager::CreateEntity(eid);
if(eid == MAX_EID)
eid = newEID;
}
void SHCreateEntityCommand::Undo()
{
SHEntityManager::DestroyEntity(eid);
}
void SHEntityParentCommand::Execute()
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for(auto const& eid : entities)
{
if(entityParentData[eid].newParentEID == MAX_EID)
sceneGraph.SetParent(eid, nullptr);
else
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
}
}
void SHEntityParentCommand::Undo()
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for(auto const& eid : entities)
{
if(entityParentData[eid].oldParentEID == MAX_EID)
sceneGraph.SetParent(eid, nullptr);
else
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
}
}
}//namespace SHADE

View File

@ -10,7 +10,7 @@
#include "imgui_internal.h"
#include "ECS_Base/SHECSMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h"
#include "Editor/Command/SHCommand.hpp"
namespace SHADE
{
class SHSceneNode;
@ -23,11 +23,45 @@ namespace SHADE
void Init() override;
void Update() override;
void Exit() override;
void SetScrollTo(EntityID eid);
private:
void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode*);
void CreateChildEntity(EntityID parentEID) const noexcept;
void ParentSelectedEntities(EntityID parentEID) const noexcept;
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
std::string filter;
bool isAnyNodeSelected = false;
EntityID scrollTo = MAX_EID;
};//class SHHierarchyPanel
//Might move to a different file
class SHCreateEntityCommand final : public SHBaseCommand
{
public:
void Execute() override;
void Undo() override;
private:
EntityID eid = MAX_EID;
};
class SHEntityParentCommand final : public SHBaseCommand
{
public:
struct Data
{
EntityID oldParentEID = MAX_EID;
EntityID newParentEID = MAX_EID;
};
using EntityParentData = std::unordered_map<EntityID, Data>;
SHEntityParentCommand(std::vector<EntityID> entityIDs, EntityParentData inEntityParentData):entities(entityIDs),entityParentData(inEntityParentData){}
void Execute() override;
void Undo() override;
private:
std::vector<EntityID> entities;
std::unordered_map<EntityID, Data> entityParentData;
};
}//namespace SHADE

View File

@ -10,6 +10,7 @@
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/IconsMaterialDesign.h"
#include "Editor/IconsFontAwesome6.h"
#include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp"
#include "Physics/Components/SHColliderComponent.h"
@ -207,14 +208,16 @@ namespace SHADE
auto& colliders = component->GetColliders();
int const size = static_cast<int>(colliders.size());
ImGui::BeginChild("Colliders", {0.0f, colliders.empty() ? 1.0f : 250.0f}, true);
std::optional<int> colliderToDelete{std::nullopt};
for (int i{}; i < size; ++i)
{
ImGui::PushID(i);
SHCollider& collider = component->GetCollider(i);
auto cursorPos = ImGui::GetCursorPos();
if (collider.GetType() == SHCollider::Type::BOX)
{
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_MD_VIEW_IN_AR, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
auto box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);});
}
@ -235,9 +238,14 @@ namespace SHADE
}
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
{
component->RemoveCollider(i);
colliderToDelete = i;
}
SHEditorWidgets::EndPanel();
ImGui::PopID();
}
if(colliderToDelete.has_value())
{
component->RemoveCollider(colliderToDelete.value());
}
ImGui::EndChild();

View File

@ -55,7 +55,11 @@ namespace SHADE
{
EntityID const& eid = editor->selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
if(!entity)
{
ImGui::End();
return;
}
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
ImGui::SameLine();
@ -99,8 +103,8 @@ namespace SHADE
}
}
ImGui::End();
}
ImGui::End();
}
void SHEditorInspector::Exit()

View File

@ -17,6 +17,8 @@
#include <imgui_internal.h>
#include <rttr/type>
#include "Serialization/SHSerialization.h"
namespace SHADE
{
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -36,6 +38,11 @@ namespace SHADE
void SHEditorMenuBar::Init()
{
SHEditorWindow::Init();
constexpr std::string_view path = "../../Assets/Editor/Layouts";
for(auto const& entry : std::filesystem::directory_iterator(path))
{
layoutPaths.push_back(entry.path());
}
}
void SHEditorMenuBar::Update()
@ -68,7 +75,14 @@ namespace SHADE
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::Selectable("Save"))
{
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
}
if(ImGui::Selectable("Load"))
{
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
}
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Edit"))
@ -87,20 +101,6 @@ namespace SHADE
ImGui::EndDisabled();
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Theme"))
{
auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
auto values = styles.get_values();
for (auto style : values)
{
if(ImGui::Selectable(style.to_string().c_str()))
{
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
editor->SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scripts"))
{
if (ImGui::Selectable("Generate Visual Studio Project"))
@ -120,18 +120,79 @@ namespace SHADE
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Window"))
{
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
if (window.get() != this)
ImGui::Checkbox(window->windowName.data(), &window->isOpen);
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Theme"))
{
const auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
auto values = styles.get_values();
for (auto style : values)
{
if (ImGui::Selectable(style.to_string().c_str()))
{
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
editor->SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Layout"))
{
for(auto const& entry : layoutPaths)
{
if(ImGui::Selectable(entry.stem().string().c_str()))
{
ImGui::LoadIniSettingsFromDisk(entry.string().c_str());
}
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
const ImGuiID dockspace_id = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspaceFlags);
const ImGuiID dockspaceId = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
ImGui::End();
}
}
void SHEditorMenuBar::DrawSecondaryBar() const noexcept
{
ImGuiViewport* viewport = ImGui::GetMainViewport();
if(ImGui::BeginViewportSideBar("##SecondaryMenuBar", viewport, ImGuiDir_Up, ImGui::GetFrameHeight(), ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_MenuBar))
{
ImGui::BeginMenuBar();
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.5f - 80.f);
const auto editor = SHSystemManager::GetSystem<SHEditor>();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{
editor->editorState = SHEditor::State::PLAY;
}
ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE))
{
editor->editorState = SHEditor::State::PAUSE;
}
ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
if(ImGui::SmallButton(ICON_MD_STOP))
{
editor->editorState = SHEditor::State::STOP;
}
ImGui::EndDisabled();
ImGui::EndMenuBar();
}
ImGui::End();
}
void SHEditorMenuBar::DrawStatusBar() const noexcept
@ -142,8 +203,8 @@ namespace SHADE
if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags))
{
ImGui::Text("Entity count: ");
ImGui::End();
}
ImGui::End();
ImGui::PopStyleVar(3);
}

View File

@ -18,5 +18,6 @@ namespace SHADE
void DrawSecondaryBar() const noexcept;
void DrawStatusBar() const noexcept;
float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar
}//namespace SHADE

View File

@ -3,6 +3,7 @@
#include <imgui.h>
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/Command/SHCommandManager.h"
#include "FRC/SHFramerateController.h"
namespace SHADE
@ -37,8 +38,13 @@ namespace SHADE
if(Begin())
{
ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f);
ImGui::End();
}
if(ImGui::CollapsingHeader("Command Manager"))
{
ImGui::Text("Undo: %zu", SHCommandManager::GetUndoStackSize());
ImGui::Text("Redo: %zu", SHCommandManager::GetRedoStackSize());
}
ImGui::End();
}
void SHEditorProfiler::Exit()

View File

@ -19,7 +19,7 @@ namespace SHADE
//|| Public Member Functions ||
//#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags)
: isOpen(true), windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
: windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
{
}
@ -40,7 +40,33 @@ namespace SHADE
//#==============================================================#
bool SHEditorWindow::Begin()
{
return ImGui::Begin(windowName.data(), &isOpen, windowFlags);
bool result = ImGui::Begin(windowName.data(), &isOpen, windowFlags);
auto wndSize = ImGui::GetWindowSize();
auto contentRegionAvail = ImGui::GetContentRegionAvail();
if( beginContentRegionAvailable.x != contentRegionAvail.x || beginContentRegionAvailable.y != contentRegionAvail.y || windowSize.x != wndSize.x || windowSize.y != wndSize.y)
{
windowSize = {wndSize.x, wndSize.y};
beginContentRegionAvailable = {contentRegionAvail.x, contentRegionAvail.y};
OnResize();
}
auto wndPos = ImGui::GetWindowPos();
if(windowPos.x != wndPos.x || windowPos.y != wndPos.y)
{
windowPos = {wndPos.x, wndPos.y};
OnPosChange();
}
isWindowHovered = ImGui::IsWindowHovered();
return result;
}
void SHEditorWindow::OnResize()
{
}
void SHEditorWindow::OnPosChange()
{
}
}//namespace SHADE

View File

@ -5,6 +5,8 @@
//#==============================================================#
#include <string>
#include "Math/Vector/SHVec2.h"
//#==============================================================#
//|| Forward Declarations ||
//#==============================================================#
@ -21,11 +23,20 @@ namespace SHADE
virtual void Init();
virtual void Update();
virtual void Exit();
bool isOpen = false;
bool isOpen;
bool isWindowHovered;
std::string_view windowName;
SHVec2 windowSize;
SHVec2 windowPos;
SHVec2 viewportMousePos;
SHVec2 beginContentRegionAvailable;
protected:
virtual bool Begin();
virtual void OnResize();
virtual void OnPosChange();
ImGuiWindowFlags windowFlags = 0;
ImGuiIO& io;
};//class SHEditorWindow
}//namespace SHADE

View File

@ -3,3 +3,4 @@
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector
#include "Profiling/SHEditorProfiler.h" //Profiler
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport

View File

@ -0,0 +1,129 @@
#include "SHpch.h"
#include "Editor/SHImGuiHelpers.hpp"
#include "SHEditorViewport.h"
#include "ImGuizmo.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/IconsMaterialDesign.h"
#include "Editor/SHEditor.hpp"
#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include <Editor/IconsFontAwesome6.h>
constexpr std::string_view windowName = "\xef\x80\x95 Viewport";
namespace SHADE
{
SHEditorViewport::SHEditorViewport()
:SHEditorWindow("\xee\x90\x8b Viewport", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoScrollbar)
{
}
void SHEditorViewport::Init()
{
SHEditorWindow::Init();
}
void SHEditorViewport::Update()
{
SHEditorWindow::Update();
if(Begin())
{
ImGuizmo::SetDrawlist();
DrawMenuBar();
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
auto mousePos = ImGui::GetMousePos();
beginCursorPos = ImGui::GetCursorScreenPos();
viewportMousePos = {mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y};
gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
ImGui::Image((ImTextureID)descriptorSet, {beginContentRegionAvailable.x, beginContentRegionAvailable.y});
if(ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
{
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
ImGui::SetCursorScreenPos(ImGui::GetMousePos());
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiColors::green);
ImGui::Text(ICON_FA_EYE);
ImGui::PopStyleColor();
}
}
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
transformGizmo.Draw();
ImGui::End();
}
void SHEditorViewport::Exit()
{
SHEditorWindow::Exit();
}
void SHEditorViewport::OnResize()
{
SHEditorWindow::OnResize();
//Get graphics system to resize swapchain image
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto pos = ImGui::GetCursorPos();
//windowCursorPos = {}
if(beginContentRegionAvailable.x == 0 || beginContentRegionAvailable.y == 0)
{
beginContentRegionAvailable = windowSize;
}
gfxSystem->PrepareResize(static_cast<uint32_t>(beginContentRegionAvailable.x), static_cast<uint32_t>(beginContentRegionAvailable.y));
}
void SHEditorViewport::OnPosChange()
{
SHEditorWindow::OnPosChange();
}
void SHEditorViewport::DrawMenuBar() noexcept
{
if(ImGui::BeginMenuBar())
{
bool const isTranslate = transformGizmo.operation == SHTransformGizmo::Operation::TRANSLATE;
ImGui::BeginDisabled(isTranslate);
if(isTranslate)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
if(ImGui::Button(ICON_MD_OPEN_WITH))
{
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
}
ImGui::EndDisabled();
if(isTranslate)
ImGui::PopStyleColor();
bool const isRotate = transformGizmo.operation == SHTransformGizmo::Operation::ROTATE;
ImGui::BeginDisabled(isRotate);
if(isRotate)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
if(ImGui::Button(ICON_MD_AUTORENEW))
{
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
}
ImGui::EndDisabled();
if(isRotate)
ImGui::PopStyleColor();
bool const isScale = transformGizmo.operation == SHTransformGizmo::Operation::SCALE;
ImGui::BeginDisabled(isScale);
if(isScale)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_CheckMark]);
if(ImGui::Button(ICON_MD_EXPAND))
{
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
}
ImGui::EndDisabled();
if(isScale)
ImGui::PopStyleColor();
ImGui::EndMenuBar();
}
}
}//namespace SHADE

View File

@ -0,0 +1,32 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "imgui_internal.h"
#include "ECS_Base/SHECSMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h"
#include "Editor/Gizmos/SHTransformGizmo.h"
namespace SHADE
{
class SHEditorViewport final : public SHEditorWindow
{
public:
SHEditorViewport();
void Init() override;
void Update() override;
void Exit() override;
SHTransformGizmo transformGizmo;
protected:
void OnResize() override;
void OnPosChange() override;
private:
void DrawMenuBar() noexcept;
SHVec2 beginCursorPos;
};//class SHEditorViewport
}//namespace SHADE

View File

@ -0,0 +1,85 @@
#include "SHpch.h"
#include "SHTransformGizmo.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.hpp"
#include "Editor/SHImGuiHelpers.hpp"
#include <imgui.h>
#include <ImGuizmo.h>
#include "Camera/SHCameraSystem.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
namespace SHADE
{
void SHTransformGizmo::Draw()
{
bool justChangedTfm = false;
if (!editorCamera)
{
auto const cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
editorCamera = cameraSystem->GetEditorCamera();
}
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
ImGuizmo::SetOrthographic(false);
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
proj(1, 1) *= -1;
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
//ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f);
if (selectedEntityTransformComponent == nullptr)
{
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
if (editor->selectedEntities.empty())
return;
EntityID eid = editor->selectedEntities.back();
selectedEntityTransformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
justChangedTfm = true;
}
else
{
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
if (editor->selectedEntities.empty())
return;
EntityID eid = editor->selectedEntities.back();
auto tfmComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
if (selectedEntityTransformComponent != tfmComponent)
{
selectedEntityTransformComponent = tfmComponent;
justChangedTfm = true;
}
}
if (selectedEntityTransformComponent == nullptr)
return;
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11);
if (!justChangedTfm)
{
if (ImGui::IsItemClicked())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
{
if (!tfm)
return;
SHVec3 translate{}, rotate{}, scale{};
mtx.Decompose(translate, rotate, scale);
tfm->SetWorldPosition(translate);
tfm->SetWorldRotation(rotate);
tfm->SetWorldScale(scale);
})));
else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating)
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
{
if (!tfm)
return;
SHVec3 translate{}, rotate{}, scale{};
mtx.Decompose(translate, rotate, scale);
tfm->SetWorldPosition(translate);
tfm->SetWorldRotation(rotate);
tfm->SetWorldScale(scale);
})), true);
}
}
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "Camera/SHCameraComponent.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
class SHTransformGizmo
{
public:
enum class Mode
{
WORLD,
LOCAL
};
enum class Operation
{
TRANSLATE_X = (1u << 0),
TRANSLATE_Y = (1u << 1),
TRANSLATE_Z = (1u << 2),
ROTATE_X = (1u << 3),
ROTATE_Y = (1u << 4),
ROTATE_Z = (1u << 5),
ROTATE_SCREEN = (1u << 6),
SCALE_X = (1u << 7),
SCALE_Y = (1u << 8),
SCALE_Z = (1u << 9),
BOUNDS = (1u << 10),
SCALE_XU = (1u << 11),
SCALE_YU = (1u << 12),
SCALE_ZU = (1u << 13),
TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,
ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,
SCALE = SCALE_X | SCALE_Y | SCALE_Z,
SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
};
void Draw();
bool isManipulating = false;
Mode mode = Mode::WORLD;
Operation operation = Operation::TRANSLATE;
private:
SHTransformComponent* selectedEntityTransformComponent{nullptr};
SHCameraComponent* editorCamera{nullptr};
};
}

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
#include "SHpch.h"
#include "IconsMaterialDesign.h"
#include "IconsFontAwesome6.h"
#include "DragDrop/SHDragDrop.hpp"
//#==============================================================#
@ -36,6 +37,7 @@
#include <imgui.h>
#include <SDL.h>
#include <rttr/registration>
#include <ImGuizmo.h>
//#==============================================================#
//|| ImGui Backend Includes ||
@ -43,6 +45,8 @@
#include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h>
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
RTTR_REGISTRATION
{
using namespace SHADE;
@ -73,6 +77,7 @@ namespace SHADE
//#==============================================================#
void SHEditor::Init()
{
IMGUI_CHECKVERSION();
if(auto context = ImGui::CreateContext())
{
@ -82,11 +87,21 @@ namespace SHADE
}
}
ImGuiIO& io = ImGui::GetIO(); (void)io;
//Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
io = &ImGui::GetIO();
io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini";
io->ConfigWindowsMoveFromTitleBarOnly = true;
InitLayout();
InitFonts();
@ -98,11 +113,11 @@ namespace SHADE
SetStyle(Style::SHADE);
//Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
window->Init();
}
SHLOG_INFO("Successfully initialised SHADE Engine Editor")
}
@ -114,8 +129,12 @@ namespace SHADE
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
if(window->isOpen)
{
window->Update();
}
}
PollPicking();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{
@ -126,35 +145,46 @@ namespace SHADE
SHCommandManager::UndoCommand();
}
Render();
}
void SHEditor::Render()
{
ImGui::Render();
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
if (io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
}
void SHEditor::InitLayout() noexcept
{
if(!std::filesystem::exists(io->IniFilename))
{
std::filesystem::copy_file("../../Assets/Editor/Layouts/Default.ini", io->IniFilename);
}
//eventually load preferred layout here
}
void SHEditor::InitFonts() noexcept
{
ImGuiIO& io = ImGui::GetIO();
ImFont* mainFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path
ImFont* mainFont = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path
static const ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f;
ImFont* UIFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges); //TODO: Change to config based assets path
io.Fonts->Build();
constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/fa-solid-900.ttf", 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path
constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_MD, 0 };
ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path
io->Fonts->Build();
}
void SHEditor::Exit()
{
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
window->Init();
}
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
@ -281,10 +311,11 @@ namespace SHADE
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
//auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
auto const& renderers = gfxSystem->GetEditorViewport()->GetRenderers();
SHASSERT(!renderers.empty(), "No Renderers available")
auto renderGraph = renderers[0]->GetRenderGraph();
auto renderGraph = renderers[SHGraphicsConstants::RenderGraphIndices::EDITOR]->GetRenderGraph();
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
@ -309,6 +340,29 @@ namespace SHADE
});
}
void SHEditor::PollPicking()
{
if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
{
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
if (viewportWindow->isWindowHovered && !viewportWindow->transformGizmo.isManipulating && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity();
if(pickedEID == MAX_EID)
return;
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
{
if (const auto hierarchyPanel = SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>())
{
hierarchyPanel->SetScrollTo(pickedEID);
}
selectedEntities.clear();
}
selectedEntities.push_back(pickedEID);
}
}
}
void SHEditor::NewFrame()
{
SDL_Event event;
@ -319,6 +373,7 @@ namespace SHADE
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
ImGuizmo::BeginFrame();
}

View File

@ -13,9 +13,11 @@
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLogger.h"
#include "Gizmos/SHTransformGizmo.h"
//#==============================================================#
//|| Library Includes ||
@ -90,11 +92,11 @@ namespace SHADE
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
}
static EditorWindowMap editorWindows;
private:
// Number of windows; used for Editor Window ID Generation
static EditorWindowID windowCount;
// Map of Editor Windows
static EditorWindowMap editorWindows;
friend class SHEditor;
};
@ -110,10 +112,17 @@ namespace SHADE
class SH_API EditorRoutine final : public SHSystemRoutine
{
public:
EditorRoutine() = default;
EditorRoutine():SHSystemRoutine("Editor routine", true) {};
void Execute(double dt) noexcept override final;
};
enum class State : uint8_t
{
PLAY,
PAUSE,
STOP
};
/**
* @brief Style options
*
@ -162,9 +171,13 @@ namespace SHADE
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
void PollPicking();
// List of selected entities
std::vector<EntityID> selectedEntities;
State editorState = State::STOP;
private:
/**
* @brief Start new frame for editor
@ -177,7 +190,7 @@ namespace SHADE
*/
void Render();
void InitLayout() noexcept;
void InitFonts() noexcept;
@ -186,6 +199,10 @@ namespace SHADE
// Handle to command buffer used for ImGui Vulkan Backend
Handle<SHVkCommandBuffer> imguiCommandBuffer;
SDL_Window* sdlWindow;
SDL_Window* sdlWindow {nullptr};
ImGuiIO* io{nullptr};
//SHTransformGizmo transformGizmo;
};//class SHEditor
}//namespace SHADE

View File

@ -67,6 +67,11 @@ namespace SHADE
ImGui::Separator();
}
bool SHEditorUI::IsItemHovered()
{
return ImGui::IsItemHovered();
}
bool SHEditorUI::BeginMenu(const std::string& label)
{
return ImGui::BeginMenu(label.data());
@ -82,6 +87,16 @@ namespace SHADE
ImGui::EndMenu();
}
void SHEditorUI::BeginTooltip()
{
ImGui::BeginTooltip();
}
void SHEditorUI::EndTooltip()
{
ImGui::EndTooltip();
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
/*-----------------------------------------------------------------------------------*/
@ -135,24 +150,30 @@ namespace SHADE
return ImGui::Selectable(std::format("{} {}", icon, label).data());
}
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::Checkbox("#", &value);
}
bool SHEditorUI::InputInt(const std::string& label, int& value)
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputInt("#", &value,
1, 10,
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
{
int signedVal = static_cast<int>(value);
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal);
if (CHANGED)
@ -162,64 +183,101 @@ namespace SHADE
}
return CHANGED;
}
bool SHEditorUI::InputFloat(const std::string& label, float& value)
bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputFloat("#", &value,
0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputDouble(const std::string& label, double& value)
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputDouble("#", &value,
0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputAngle(const std::string& label, double& value)
bool SHEditorUI::InputAngle(const std::string& label, double& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputDouble("#", &value,
1.0, 45.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value)
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
{
float val = static_cast<float>(value);
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = ImGui::SliderFloat("#", &val,
static_cast<float>(min), static_cast<float>(max), "%.3f",
return ImGui::SliderInt("##", &value,
static_cast<float>(min), static_cast<float>(max), "%d",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/)
{
int val = static_cast<int>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = val;
value = static_cast<int>(val);
}
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y });
}
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f");
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderFloat("##", &value,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/)
{
float val = static_cast<float>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<double>(val);
}
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
}
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered, float speed)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f", float{}, float{}, 0, isHovered);
}
bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered)
{
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED)
@ -229,13 +287,15 @@ namespace SHADE
return CHANGED;
}
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered)
{
// Clamp input value
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
bool b = false;
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{

View File

@ -90,12 +90,19 @@ namespace SHADE
static void SameLine();
static void Separator();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Queries */
/*-----------------------------------------------------------------------------*/
static bool IsItemHovered();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Menu */
/*-----------------------------------------------------------------------------*/
static bool BeginMenu(const std::string& label);
static bool BeginMenu(const std::string& label, const char* icon);
static void EndMenu();
static void BeginTooltip();
static void EndTooltip();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
@ -165,8 +172,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputCheckbox(const std::string& label, bool& value);
static bool InputCheckbox(const std::string& label, bool& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a integer field widget for integer input.
/// <br/>
@ -174,8 +182,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputInt(const std::string& label, int& value);
static bool InputInt(const std::string& label, int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a integer field widget for unsigned integer input.
/// <br/>
@ -186,8 +195,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputUnsignedInt(const std::string& label, unsigned int& value);
static bool InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for single precision float input.
/// <br/>
@ -195,8 +205,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputFloat(const std::string& label, float& value);
static bool InputFloat(const std::string& label, float& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for double precision float input.
/// <br/>
@ -204,8 +215,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputDouble(const std::string& label, double& value);
static bool InputDouble(const std::string& label, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for double input with increments of higher
/// steps meant for angle variables.
@ -214,19 +226,57 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputAngle(const std::string& label, double& value);
static bool InputAngle(const std::string& label, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a double slider field widget for double input.
/// Creates an int slider field widget for double input.
/// <br/>
/// Wraps up ImGui::InputSliderFloat().
/// Wraps up ImGui::SliderInt().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="min">Minimum value of the slider.</param>
/// <param name="max">Maximum value of the slider.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, double min, double max, double& value);
static bool InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates an unsigned int slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderInt().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="min">Minimum value of the slider.</param>
/// <param name="max">Maximum value of the slider.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a float slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderFloat().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="min">Minimum value of the slider.</param>
/// <param name="max">Maximum value of the slider.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a double slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderFloat().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="min">Minimum value of the slider.</param>
/// <param name="max">Maximum value of the slider.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a 2x double field widget for Vector2 input.
/// <br/>
@ -234,8 +284,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec2(const std::string& label, SHVec2& value);
static bool InputVec2(const std::string& label, SHVec2& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a 3x double field widget for Vector3 input.
/// <br/>
@ -243,8 +294,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
static bool InputVec3(const std::string& label, SHVec3& value, bool* isHovered = nullptr, float speed = 0.1f);
/// <summary>
/// Creates a text field widget for string input.
/// <br/>
@ -252,8 +304,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputTextField(const std::string& label, std::string& value);
static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a combo box for enumeration input.
/// </summary>
@ -264,17 +317,19 @@ namespace SHADE
/// <param name="toStrFn">
/// Conversion function from the type of enum to C-style string.
/// </param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>Whether the value was modified.</returns>
template<typename Enum>
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn);
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn, bool* isHovered = nullptr);
/// <summary>
/// Creates a combo box for enumeration input using a specified list of names.
/// </summary>
/// <param name="label">The name of the input.</param>
/// <param name="v">The reference to the value to modify.</param>
/// <param name="enumNames">Vector of names for each enumeration value.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>Whether the value was modified.</returns>
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered = nullptr);
private:

View File

@ -16,11 +16,11 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Widgets */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
template<typename Enum>
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn)
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn, bool* isHovered)
{
std::vector<Enum> values;
for (int i = 0; i <= maxVal; ++i)
@ -28,6 +28,11 @@ namespace SHADE
values.emplace_back(static_cast<Enum>(i));
}
bool b = false;
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
{
for (int i = 0; i <= maxVal; ++i)

View File

@ -160,7 +160,7 @@ namespace SHADE
template <typename T, std::size_t N>
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
ImGuiSliderFlags flags = 0)
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
@ -174,6 +174,8 @@ namespace SHADE
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i)
{

View File

@ -43,6 +43,10 @@ namespace SHADE
constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f};
constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f};
constexpr int colors_red = 0;
constexpr int colors_green = 1;
constexpr int colors_blue = 2;
constexpr int colors_white = 3;
constexpr ImU32 colors[] = {
0xBB0000FF, // red
0xBB00FF00, // green

View File

@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier;
typedef uint32_t SHEventHandle;
//Add your event identifiers here:
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };

View File

@ -14,7 +14,6 @@
#pragma once
#include <chrono>
#include "Tools/SHLogger.h"
#include "SH_API.h"
namespace SHADE

View File

@ -3,7 +3,7 @@
#include "Graphics/SHVulkanIncludes.h"
#include "vk_mem_alloc.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
namespace SHADE
{

View File

@ -10,6 +10,7 @@
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE
@ -299,7 +300,7 @@ namespace SHADE
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
return;
}
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
}
@ -358,9 +359,10 @@ namespace SHADE
}
}
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{
vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
uint32_t bindPointIndex = static_cast<uint32_t>(bindPoint);
vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
}
/***************************************************************************/
@ -452,6 +454,11 @@ namespace SHADE
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
}
void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept
{
vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ);
}
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{
vkCommandBuffer.copyBufferToImage
@ -500,9 +507,9 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier()
//}
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
{
boundPipelineLayoutHdl = pipelineLayout;
bindPointData[static_cast<uint32_t>(pipelineType)].boundPipelineLayoutHdl = pipelineLayout;
}
/***************************************************************************/
@ -513,12 +520,13 @@ namespace SHADE
*/
/***************************************************************************/
void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept
void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept
{
vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(),
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
0,
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
}
/***************************************************************************/
@ -695,7 +703,7 @@ namespace SHADE
, usageFlags{ rhs.usageFlags }
, commandBufferCount{ rhs.commandBufferCount }
, parentPool{ rhs.parentPool }
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
, bindPointData{ std::move (rhs.bindPointData)}
{
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
@ -728,7 +736,7 @@ namespace SHADE
usageFlags = rhs.usageFlags;
commandBufferCount = rhs.commandBufferCount;
parentPool = rhs.parentPool;
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl;
bindPointData = std::move(rhs.bindPointData);
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
rhs.vkCommandBuffer = VK_NULL_HANDLE;

View File

@ -4,8 +4,9 @@
#include "Graphics/SHVulkanIncludes.h"
#include "Graphics/SHVulkanDefines.h"
#include "SHCommandPoolResetMode.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHResourceLibrary.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Pipeline/SHPipelineType.h"
namespace SHADE
{
@ -36,10 +37,17 @@ namespace SHADE
class SHVkCommandBuffer
{
friend class SHVkCommandPool;
friend class ResourceLibrary<SHVkCommandBuffer>;
friend class SHResourceLibrary<SHVkCommandBuffer>;
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
private:
struct PipelineBindPointData
{
//! The currently bound pipeline
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
};
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
@ -66,8 +74,8 @@ namespace SHADE
//! The command pool that this command buffer belongs to
Handle<SHVkCommandPool> parentPool;
//! The currently bound pipeline
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
//! Every command buffer will have a set of pipeline bind point specific data
std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
//! The push constant data for the command buffer
uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
@ -112,13 +120,16 @@ namespace SHADE
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
// Draw Commands
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Compute Commands
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
// Buffer Copy
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
@ -138,13 +149,13 @@ namespace SHADE
// Push Constant variable setting
template <typename T>
void SetPushConstantVariable(std::string variableName, T const& data) noexcept
void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept
{
memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
};
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept;
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
void SubmitPushConstants (void) const noexcept;
void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */

View File

@ -2,7 +2,7 @@
#include "SHVkCommandPool.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Instance/SHVkInstance.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHResourceLibrary.h"
#include "Tools/SHLogger.h"
namespace SHADE

View File

@ -6,7 +6,7 @@
#include "Graphics/Queues/SHVkQueue.h"
#include "SHCommandPoolResetMode.h"
#include "SHVkCommandBuffer.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHResourceLibrary.h"
namespace SHADE
{

View File

@ -99,7 +99,7 @@ namespace SHADE
void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message) noexcept
{
SHLOGV_INFO(message);
//SHLOGV_INFO(message);
}
/***************************************************************************/

View File

@ -25,7 +25,8 @@ namespace SHADE
}
SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
: device{ rhs.device }
: ISelfHandle (rhs)
, device{ rhs.device }
, pool{ rhs.pool }
{
rhs.pool = VK_NULL_HANDLE;

View File

@ -2,7 +2,7 @@
// Project Includes
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
namespace SHADE
{

View File

@ -91,7 +91,7 @@ namespace SHADE
// new write for the binding
updater.writeInfos.emplace_back();
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1);
updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
auto& writeInfo = updater.writeInfos.back();
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
@ -102,10 +102,10 @@ namespace SHADE
//case vk::DescriptorType::eSampler:
//case vk::DescriptorType::eSampledImage:
case vk::DescriptorType::eCombinedImageSampler:
case vk::DescriptorType::eStorageImage:
case vk::DescriptorType::eInputAttachment:
writeInfo.descImageInfos.resize(descriptorCount);
break;
//case vk::DescriptorType::eStorageImage:
// break;
case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageTexelBuffer:
case vk::DescriptorType::eUniformBuffer:
@ -165,6 +165,7 @@ namespace SHADE
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
{
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
return;
}
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
@ -172,7 +173,7 @@ namespace SHADE
// write sampler and image view
auto& [view, sampler, layout] = imageViewsAndSamplers[i];
writeInfo.descImageInfos[i].imageView = view->GetImageView();
writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
writeInfo.descImageInfos[i].sampler = sampler ? sampler->GetVkSampler() : nullptr;
writeInfo.descImageInfos[i].imageLayout = layout;
}
}

View File

@ -4,7 +4,7 @@
// Project Includes
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "Graphics/Shaders/SHShaderReflected.h"
#include "SHDescriptorSetUpdater.h"
@ -31,6 +31,8 @@ namespace SHADE
class SHVkDescriptorSetGroup
{
public:
using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/

View File

@ -1,16 +1,18 @@
#include "SHPch.h"
#include "SHVkDescriptorSetLayout.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkSampler.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructor */
/*---------------------------------------------------------------------------------*/
SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex set, const std::vector<Binding>& bindings)
SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex set, const std::vector<Binding>& bindings, bool genImmutableSamplers/* = false*/)
: device { device }
, layoutDesc { bindings }
, setIndex {set}
, immutableSampler{}
{
// Check if auto-binding point calculation configuration is valid
bool autoCalc = false;
@ -26,6 +28,25 @@ namespace SHADE
}
}
vk::Sampler tempVkSampler = nullptr;
if (genImmutableSamplers)
{
// Create sampler
immutableSampler = device->CreateSampler(
{
.minFilter = vk::Filter::eLinear,
.magFilter = vk::Filter::eLinear,
.addressMode = vk::SamplerAddressMode::eRepeat,
.mipmapMode = vk::SamplerMipmapMode::eLinear,
.minLod = -1000,
.maxLod = 1000
}
);
tempVkSampler = immutableSampler->GetVkSampler();
}
// Fill up VK bindings with auto calculated bind points if needed
std::vector<vk::DescriptorSetLayoutBinding> layoutBindings;
layoutBindings.reserve(bindings.size());
@ -39,7 +60,7 @@ namespace SHADE
.descriptorType = binding.Type,
.descriptorCount = binding.DescriptorCount,
.stageFlags = binding.Stage,
.pImmutableSamplers = nullptr // We will create our own samplers
.pImmutableSamplers = genImmutableSamplers ? &tempVkSampler : nullptr,
};
layoutBindings.emplace_back(VK_BINDING);
@ -75,7 +96,8 @@ namespace SHADE
: device {rhs.device}
, setLayout {rhs.setLayout}
, layoutDesc{std::move (rhs.layoutDesc)}
, setIndex {rhs.setIndex}
, setIndex{ rhs.setIndex }
, immutableSampler{ rhs.immutableSampler }
{
rhs.setLayout = VK_NULL_HANDLE;
}
@ -106,6 +128,7 @@ namespace SHADE
setLayout = rhs.setLayout;
layoutDesc = std::move(rhs.layoutDesc);
setIndex = rhs.setIndex;
immutableSampler = rhs.immutableSampler;
rhs.setLayout = VK_NULL_HANDLE;

View File

@ -2,7 +2,7 @@
// Project Includes
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
namespace SHADE
{
@ -10,6 +10,7 @@ namespace SHADE
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkLogicalDevice;
class SHVkSampler;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
@ -74,7 +75,7 @@ namespace SHADE
/// </summary>
/// <param name="device"></param>
/// <param name="bindings"></param>
SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex setIndex, const std::vector<Binding>& bindings);
SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex setIndex, const std::vector<Binding>& bindings, bool genImmutableSamplers = false);
SHVkDescriptorSetLayout(const SHVkDescriptorSetLayout&) = delete;
SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept;
/// <summary>
@ -107,5 +108,6 @@ namespace SHADE
vk::DescriptorSetLayout setLayout;
std::vector<Binding> layoutDesc; // Stores description of the layout
SetIndex setIndex; // Index of the set
Handle<SHVkSampler> immutableSampler;
};
}

View File

@ -233,6 +233,8 @@ namespace SHADE
, vmaAllocator{rhs.vmaAllocator}
, nonDedicatedBestIndex {0}
, parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
, uboBufferMemoryAlignment{ 0 }
, ssboBufferMemoryAlignment{ 0 }
{
rhs.vkLogicalDevice = VK_NULL_HANDLE;
}
@ -261,6 +263,8 @@ namespace SHADE
vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
uboBufferMemoryAlignment = rhs.uboBufferMemoryAlignment;
ssboBufferMemoryAlignment = rhs.ssboBufferMemoryAlignment;
rhs.vkLogicalDevice = VK_NULL_HANDLE;
@ -529,6 +533,11 @@ namespace SHADE
}
Handle<SHVkPipeline> SHVkLogicalDevice::CreateComputePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl);
}
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
@ -550,10 +559,9 @@ namespace SHADE
}
Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept
Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers/* = false*/) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex, bindings);
return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex, bindings, genImmutableSamplers);
}
Handle<SHVkDescriptorPool> SHVkLogicalDevice::CreateDescriptorPools(const SHVkDescriptorPool::Config& config /*= {}*/) noexcept

View File

@ -8,8 +8,8 @@
#include "Graphics/SHVulkanIncludes.h"
#include "Graphics/Devices/SHVkPhysicalDevice.h"
#include "Graphics/Queues/SHVkQueue.h"
#include "Resource/Handle.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHHandle.h"
#include "Resource/SHResourceLibrary.h"
#include "Graphics/Swapchain/SHSwapchainParams.h"
#include "Graphics/Commands/SHCommandPoolResetMode.h"
#include "Graphics/Commands/SHVkCommandPool.h"
@ -181,12 +181,17 @@ namespace SHADE
Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass
) noexcept;
Handle<SHVkPipeline> CreateComputePipeline (
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl
) noexcept;
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
Handle<SHVkFramebuffer> CreateFramebuffer (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept;
Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers = false) noexcept;
Handle<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept;
Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,

View File

@ -2,7 +2,7 @@
#define SH_VK_FRAMEBUFFER_H
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include <span>
namespace SHADE

View File

@ -3,7 +3,7 @@
#include "SHImageViewDetails.h"
#include "Graphics/SHVulkanDefines.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHResourceLibrary.h"
#include "vk_mem_alloc.h"
namespace SHADE

View File

@ -2,7 +2,7 @@
#define SH_VK_IMAGE_VIEW_H
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "SHImageViewDetails.h"
namespace SHADE

View File

@ -30,8 +30,9 @@ namespace SHADE
.addressModeU = params.addressMode,
.addressModeV = params.addressMode,
.addressModeW = params.addressMode,
.maxAnisotropy = 1.0f,
.minLod = params.minLod,
.maxLod = params.maxLod
.maxLod = params.maxLod,
};
// Create the sampler

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
#include <vector>
// Project Includes
#include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
namespace SHADE
{

View File

@ -15,7 +15,7 @@ namespace SHADE
bool SHVkInstance::validationLayersOn;
vk::Instance SHVkInstance::vkInstance;
SHVkDebugMessenger SHVkInstance::debugMessenger;
ResourceManager SHVkInstance::resourceManager;
SHResourceHub SHVkInstance::resourceManager;
/***************************************************************************/
/*!
@ -258,7 +258,7 @@ namespace SHADE
return vkInstance;
}
ResourceManager& SHVkInstance::GetResourceManager(void) noexcept
SHResourceHub& SHVkInstance::GetResourceManager(void) noexcept
{
return resourceManager;
}

View File

@ -18,7 +18,7 @@ written consent of DigiPen Institute of Technology is prohibited.
#include "Graphics/Debugging/SHVkDebugMessenger.h"
#include "Graphics/Devices/SHVkPhysicalDevice.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Resource/ResourceLibrary.h"
#include "Resource/SHResourceLibrary.h"
namespace SHADE
@ -61,7 +61,7 @@ namespace SHADE
static SHVkDebugMessenger debugMessenger;
//! Resource management for vulkan project
static ResourceManager resourceManager;
static SHResourceHub resourceManager;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
@ -85,7 +85,7 @@ namespace SHADE
/* Getters and Setters */
/*-----------------------------------------------------------------------*/
static vk::Instance const& GetVkInstance (void) noexcept;
static ResourceManager& GetResourceManager(void) noexcept;
static SHResourceHub& GetResourceManager(void) noexcept;
};
}

View File

@ -385,7 +385,7 @@ namespace SHADE
cmdBuffer->BindDescriptorSet
(
matPropsDescSet[frameIndex],
vk::PipelineBindPoint::eGraphics,
SH_PIPELINE_TYPE::GRAPHICS,
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
dynamicOffset
);

View File

@ -18,7 +18,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Math/SHMatrix.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <vector>
// Project Includes
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
namespace SHADE
{

View File

@ -25,7 +25,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
: subpass { sp }
: subpass{ sp }
{}
/*---------------------------------------------------------------------------------*/

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "SHBatch.h"
#include "Graphics/Pipeline/SHVkPipeline.h"

View File

@ -97,13 +97,15 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
SHMatrix SHCamera::GetViewMatrix() const
SHMatrix SHCamera::GetViewMatrix()
{
updateMatrices();
return viewMatrix;
}
SHMatrix SHCamera::GetProjectionMatrix() const
SHMatrix SHCamera::GetProjectionMatrix()
{
updateMatrices();
return projMatrix;
}
SHMatrix SHCamera::GetViewProjectionMatrix()

View File

@ -41,11 +41,13 @@ namespace SHADE
void SetPerspective(float fov, float width, float height, float zNear, float zFar);
void SetOrthographic(float width, float height, float zNear, float zFar);
//void SetPerspectiveMatrixExplicit (
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
SHMatrix GetViewMatrix() const;
SHMatrix GetProjectionMatrix() const;
SHMatrix GetViewMatrix();
SHMatrix GetProjectionMatrix();
SHMatrix GetViewProjectionMatrix();
SHMatrix GetInverseViewMatrix() const;
SHMatrix GetInverseProjectionMatrix() const;

View File

@ -25,6 +25,12 @@ namespace SHADE
struct SHGraphicsConstants
{
public:
struct RenderGraphIndices
{
static constexpr uint32_t WORLD = 0;
static constexpr uint32_t EDITOR = 0;
};
struct DescriptorSetIndex
{
/***************************************************************************/
@ -57,6 +63,14 @@ namespace SHADE
*/
/***************************************************************************/
static constexpr uint32_t PER_INSTANCE = 3;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for render graph resources.
*/
/***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
};

View File

@ -16,6 +16,9 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Instance/SHVkInstance.h"
#include "Graphics/Windowing/Surface/SHVkSurface.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Camera/SHCameraSystem.h"
#include "Editor/SHEditor.hpp"
#include "ECS_Base/Managers/SHSystemManager.h"
//#include "SHRenderer.h"
#include "Graphics/Windowing/SHWindow.h"
#include "Graphics/MiddleEnd/PerFrame/SHPerFrameData.h"
@ -36,11 +39,9 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
#pragma region INIT_EXIT
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
void SHGraphicsSystem::InitBoilerplate(void) noexcept
{
/*-----------------------------------------------------------------------*/
/* BACKEND BOILERPLATE */
@ -71,7 +72,15 @@ namespace SHADE
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true);
#ifdef SHEDITOR
//PrepareResize(1, 1, SHVec2(0, 0));
#else
PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0));
#endif
});
window->RegisterWindowCloseCallback([&](void)
@ -108,7 +117,25 @@ namespace SHADE
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
greyscale->Reflect();
}
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
{
/*-----------------------------------------------------------------------*/
/* MIDDLE END SETUP
- Viewports
@ -118,8 +145,9 @@ namespace SHADE
- Default vertex input state
- Global data
/*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize();
SHGraphicsGlobalData::Init(device);
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
// Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>();
@ -131,12 +159,12 @@ namespace SHADE
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
worldViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer
worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
{
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
@ -144,64 +172,57 @@ namespace SHADE
// Initialize world render graph
worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Present", {SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT}, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Scene", {SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT}, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", {SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL}, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", {SH_ATT_DESC_TYPE_FLAGS::COLOR}, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
//First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Scene");
gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
// We do this to just transition our scene layout to shader read
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
sceneLayoutTransitionSubpass->AddInput("Scene");
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
// Generate world render graph
worldRenderGraph->Generate();
// Add world renderer to default viewport
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
}
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
{
SHGraphicsGlobalData::Init(device);
InitSceneRenderGraph();
#ifdef SHEDITOR
auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
InitEditorRenderGraph();
#endif
worldRenderGraph->Generate();
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
}
// Create Debug Renderers
/*debugScreenRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugScreenRenderer->SetCamera(screenCamera);
debugWorldRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugWorldRenderer->SetCamera(worldCamera);*/
// Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
void SHGraphicsSystem::InitSubsystems(void) noexcept
{
mousePickSystem = resourceManager.Create<SHMousePickSystem>();
@ -217,6 +238,61 @@ namespace SHADE
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
}
#ifdef SHEDITOR
void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept
{
auto windowDims = window->GetWindowSize();
// Create Default Viewport
editorViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 1.0f));
// Get render graph from viewport editor renderer
editorRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
editorRenderGraph->Init(device, swapchain);
editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
auto imguiNode = editorRenderGraph->AddNode("ImGui Node", { "Present"}, {});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
// Generate world render graph
editorRenderGraph->Generate();
// Add world renderer to default viewport
editorRenderer = editorViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], editorRenderGraph);
editorRenderer->SetCamera(worldCamera);
}
#endif
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
InitBoilerplate();
InitMiddleEnd();
InitSubsystems();
}
void SHGraphicsSystem::Exit(void)
{
}
#pragma endregion INIT_EXIT
#pragma region LIFECYCLE
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
@ -235,12 +311,6 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -262,6 +332,9 @@ namespace SHADE
// Bind textures
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
// For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -284,7 +357,7 @@ namespace SHADE
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
// Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA)
@ -304,14 +377,29 @@ namespace SHADE
currentCmdBuffer->BindDescriptorSet
(
textureDescSet,
vk::PipelineBindPoint::eGraphics,
SH_PIPELINE_TYPE::GRAPHICS,
0,
texDynamicOffset
);
}
// bind camera data
//renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#ifdef SHEDITOR
if (renderers[renIndex] == worldRenderer)
{
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
}
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#endif
// Draw first
renderers[renIndex]->Draw(frameIndex, descPool);
@ -337,13 +425,6 @@ namespace SHADE
}
}
void SHGraphicsSystem::Exit(void)
{
}
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
@ -408,12 +489,6 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
@ -425,9 +500,7 @@ namespace SHADE
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{
HandleResize();
}
}
@ -435,6 +508,10 @@ namespace SHADE
renderContext.AdvanceFrame();
}
#pragma endregion LIFECYCLE
#pragma region ADD_REMOVE_BUILD
Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport)
{
// Create the viewport
@ -520,19 +597,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Texture Registration Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHGraphicsSystem::Add(const SHTextureAsset& texAsset)
Handle<SHTexture> SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset)
{
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) });
return texLibrary.Add(texAsset, sampler);
}
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
{
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) });
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
}
void SHGraphicsSystem::Remove(Handle<SHTexture> tex)
void SHGraphicsSystem::RemoveTexture(Handle<SHTexture> tex)
{
texLibrary.Remove(tex);
}
@ -545,43 +622,14 @@ namespace SHADE
);
}
void SHGraphicsSystem::HandleResize(void) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(windowDims.first, windowDims.second);
mousePickSystem->HandleResize();
defaultViewport->SetWidth(static_cast<float>(windowDims.first));
defaultViewport->SetHeight(static_cast<float>(windowDims.second));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
}
#pragma endregion ADD_REMOVE
#pragma region ROUTINES
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false)
: SHSystemRoutine("Graphics System Frame Set Up", true)
{}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
@ -593,7 +641,7 @@ namespace SHADE
/* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false)
: SHSystemRoutine("Graphics System Render", true)
{}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
@ -605,7 +653,7 @@ namespace SHADE
/* System Routine Functions - EndRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::EndRoutine::EndRoutine()
: SHSystemRoutine("Graphics System Frame Clean Up", false)
: SHSystemRoutine("Graphics System Frame Clean Up", true)
{}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
@ -617,7 +665,7 @@ namespace SHADE
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false)
: SHSystemRoutine("Graphics System Batcher Dispatcher", true)
{}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
@ -648,5 +696,70 @@ namespace SHADE
renderable.ResetChangedFlag();
}
}
#pragma endregion ROUTINES
#pragma region MISC
void SHGraphicsSystem::PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
resizeWidth = newWidth;
resizeHeight = newHeight;
renderContext.SetIsResized(true);
}
void SHGraphicsSystem::HandleResize(void) noexcept
{
device->WaitIdle();
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
graphSemaphores[0].Free();
graphSemaphores[1].Free();
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(resizeWidth, resizeHeight);
editorRenderGraph->HandleResize(windowDims.first, windowDims.second);
mousePickSystem->HandleResize();
postOffscreenRender->HandleResize();
worldViewport->SetWidth(static_cast<float>(resizeWidth));
worldViewport->SetHeight(static_cast<float>(resizeHeight));
worldCamera->SetPerspective(90.0f, static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.0f, 100.0f);
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR
cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
#else
#endif
for (auto& semaHandle : graphSemaphores)
semaHandle = device->CreateSemaphore();
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
}
#pragma endregion MISC
}

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include <array>
// Project Includes
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h"
#include "Graphics/MiddleEnd/PerFrame/SHRenderContext.h"
#include "Graphics/RenderGraph/SHRenderGraph.h"
@ -67,6 +67,16 @@ namespace SHADE
/***********************************************************************************/
class SH_API SHGraphicsSystem : public SHSystem
{
private:
void InitBoilerplate (void) noexcept;
void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept;
#ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept;
#endif
public:
class SH_API BeginRoutine final : public SHSystemRoutine
{
@ -221,8 +231,8 @@ namespace SHADE
*/
/*******************************************************************************/
Handle<SHTexture> Add(const SHTextureAsset& texAsset);
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
Handle<SHTexture> AddTexture(const SHTextureAsset& texAsset);
Handle<SHTexture> AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
/*******************************************************************************/
/*!
@ -236,7 +246,7 @@ namespace SHADE
*/
/*******************************************************************************/
void Remove(Handle<SHTexture> tex);
void RemoveTexture(Handle<SHTexture> tex);
/***************************************************************************/
/*!
@ -252,6 +262,7 @@ namespace SHADE
/***************************************************************************/
void BuildTextures();
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept;
void AwaitGraphicsExecution();
@ -269,7 +280,10 @@ namespace SHADE
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
Handle<SHViewport> GetDefaultViewport() const {return defaultViewport;}
Handle<SHViewport> GetDefaultViewport() const {return worldViewport;}
#ifdef SHEDITOR
Handle<SHViewport> GetEditorViewport () const {return editorViewport;};
#endif
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
@ -278,6 +292,7 @@ namespace SHADE
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
@ -298,13 +313,19 @@ namespace SHADE
SHWindow* window = nullptr;
// Middle End Resources
ResourceManager resourceManager;
SHResourceHub resourceManager;
SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary;
SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache;
// Viewports
Handle<SHViewport> defaultViewport; // Whole screen
#ifdef SHEDITOR
Handle<SHViewport> editorViewport;
Handle<SHRenderer> editorRenderer;
Handle<SHRenderGraph> editorRenderGraph;
#endif
Handle<SHViewport> worldViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers
@ -331,5 +352,7 @@ namespace SHADE
Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
uint32_t resizeWidth;
uint32_t resizeHeight;
};
}

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <unordered_map>
// Project Includes
#include "Resource/Handle.h"
#include "Resource/SHHandle.h"
#include "SHCommonTypes.h"
namespace SHADE

Some files were not shown because too many files have changed in this diff Show More