SP3-16 Quaternions #112

Merged
direnbharwani merged 17 commits from SP3-16-Math into main 2022-10-23 20:07:17 +08:00
144 changed files with 5143 additions and 1632 deletions
Showing only changes of commit 610ecc6baa - Show all commits

2
.gitignore vendored
View File

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

View File

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

View File

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

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,48 @@
[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=571,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=571,92
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=573,48
Size=1074,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=571,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=1074,1036 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

View File

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

View File

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

View File

@ -30,6 +30,7 @@
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "FRC/SHFramerateController.h" #include "FRC/SHFramerateController.h"
#include "AudioSystem/SHAudioSystem.h" #include "AudioSystem/SHAudioSystem.h"
#include "Camera/SHCameraSystem.h"
// Components // Components
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
@ -56,46 +57,62 @@ namespace Sandbox
) )
{ {
// Set working directory // Set working directory
SHADE::SHFileUtilities::SetWorkDirToExecDir(); SHFileUtilities::SetWorkDirToExecDir();
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
// Create Systems // Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>(); SHSystemManager::CreateSystem<SHGraphicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>(); SHSystemManager::CreateSystem<SHScriptEngine>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHPhysicsSystem>(); SHSystemManager::CreateSystem<SHPhysicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHSystemManager::CreateSystem<SHTransformSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>(); SHSystemManager::CreateSystem<SHAudioSystem>();
SHSystemManager::CreateSystem<SHCameraSystem>();
#ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHSystemManager::CreateSystem<SHEditor>();
SHSystemManager::GetSystem<SHEditor>()->SetSDLWindow(sdlWindow);
#endif
// Create Routines // Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameSetUpRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::UpdateRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::UpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsFixedUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHPhysicsSystem, SHADE::SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRigidBodyComponent>(); SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHColliderComponent>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>(); #ifdef SHEDITOR
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>(); SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
#endif
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::RenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::EndRoutine>();
SHComponentManager::CreateComponentSparseSet<SHRigidBodyComponent>();
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf"); //SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh"); //SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); //SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); //SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex"); //SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
@ -103,47 +120,36 @@ namespace Sandbox
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>(); auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>(); auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>(); SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();
// Set up graphics system and windows // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);
SHADE::SHSystemManager::Init(); SHSystemManager::Init();
#ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHADE::SHEditor::Initialise(sdlWindow);
#else
#endif
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
SHAssetManager::Load();
} }
void SBApplication::Update(void) void SBApplication::Update(void)
{ {
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHGraphicsSystem* graphicsSystem = SHADE::SHSystemManager::GetSystem<SHGraphicsSystem>();
SHEditor* editor = SHADE::SHSystemManager::GetSystem<SHEditor>();
//TODO: Change true to window is open //TODO: Change true to window is open
while (!window.WindowShouldClose()) while (!window.WindowShouldClose())
{ {
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime()); SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
SHSceneManager::UpdateSceneManager(); SHSceneManager::UpdateSceneManager();
SHSceneManager::SceneUpdate(1/60.0f); #ifdef SHEDITOR
//#ifdef SHEDITOR if(editor->editorState == SHEditor::State::PLAY)
//#endif SHSceneManager::SceneUpdate(0.016f);
graphicsSystem->BeginRender(); #endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
#ifdef SHEDITOR editor->PollPicking();
SHADE::SHEditor::Update(0.16f);
#endif
graphicsSystem->Run(1.0f);
graphicsSystem->EndRender();
SHADE::SHSystemManager::RunRoutines(false, 0.016f);
} }
// Finish all graphics jobs first // Finish all graphics jobs first
@ -154,13 +160,13 @@ namespace Sandbox
void SBApplication::Exit(void) void SBApplication::Exit(void)
{ {
#ifdef SHEDITOR #ifdef SHEDITOR
SHADE::SHEditor::Exit();
SDL_DestroyWindow(sdlWindow); SDL_DestroyWindow(sdlWindow);
SDL_Quit(); SDL_Quit();
#endif #endif
SHSceneManager::Exit(); SHSceneManager::Exit();
SHADE::SHSystemManager::Exit(); SHSystemManager::Exit();
SHAssetManager::Unload();
} }
} }

View File

@ -99,13 +99,15 @@ namespace Sandbox
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f)); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
//Set initial positions //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(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.SetWorldPosition({-1.0f, -1.0f, -1.0f});
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
transform.SetWorldScale(TEST_OBJ_SCALE); transform.SetWorldScale(TEST_OBJ_SCALE);
auto* box = collider.AddBoundingBox(); if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
box->SetHalfExtents(transform.GetWorldScale() * 0.5f); collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
else
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
stressTestObjects.emplace_back(entity); stressTestObjects.emplace_back(entity);
} }
@ -133,12 +135,12 @@ namespace Sandbox
floorRenderable.SetMaterial(customMat); floorRenderable.SetMaterial(customMat);
floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
floorTransform.SetWorldScale({7.5f, 0.5f, 7.5}); floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
floorTransform.SetWorldPosition({0.0f, -3.0f, -5.0f}); floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
auto* floorBox = floorCollider.AddBoundingBox(); auto* floorBox = floorCollider.AddBoundingBox();
floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f); floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f);
// Create blank entity with a script // Create blank entity with a script

View File

@ -9,6 +9,7 @@ namespace SHADE
{ {
bool compiled; bool compiled;
std::string name;
uint32_t numBytes; uint32_t numBytes;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;

View File

@ -16,7 +16,7 @@
#include <fstream> #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() }; std::string newPath{ path.string() };
newPath = newPath.substr(0, newPath.find_last_of('/') + 1); newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
@ -67,4 +67,6 @@ void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPat
); );
file.close(); file.close();
return newPath;
} }

View File

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

View File

@ -142,8 +142,7 @@ namespace SHADE
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string()); SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
} }
std::string name{ path.filename().string() }; const std::string name{ path.stem().string() };
name = name.substr(0, name.find_last_of('.'));
file.seekg(0); file.seekg(0);

View File

@ -29,8 +29,8 @@ namespace SHADE
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept; static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
public: public:
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept; static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
}; };
} }

View File

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

View File

@ -19,6 +19,6 @@ namespace SHADE
{ {
struct SHTextureCompiler 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); std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData())); //pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
asset.name = path.stem().string();
asset.compiled = false; asset.compiled = false;
asset.numBytes = static_cast<uint32_t>(totalBytes); asset.numBytes = static_cast<uint32_t>(totalBytes);
asset.width = file.GetWidth(); asset.width = file.GetWidth();

View File

@ -26,8 +26,8 @@ namespace SHADE
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept; static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
public: public:
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image); static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
}; };
} }

View File

@ -40,7 +40,7 @@ typedef FMOD::Sound* SHSound;
#define ASSET_META_VER "1.0" #define ASSET_META_VER "1.0"
// Asset type enum // Asset type enum
enum class AssetType : uint8_t enum class AssetType : AssetTypeMeta
{ {
INVALID = 0, INVALID = 0,
AUDIO = 1, AUDIO = 1,
@ -57,7 +57,12 @@ enum class AssetType : uint8_t
}; };
//Directory //Directory
#define ASSET_ROOT "./Assets/" #ifdef _PUBLISH
#define ASSET_ROOT "Assets"
#else
#define ASSET_ROOT "../../Assets"
#endif
// ASSET EXTENSIONS // ASSET EXTENSIONS
#define META_EXTENSION ".shmeta" #define META_EXTENSION ".shmeta"

View File

@ -255,6 +255,26 @@ namespace SHADE
return result; return result;
} }
SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
{
if (meshCollection.find(id) == meshCollection.end())
{
return nullptr;
}
return &meshCollection[id];
}
SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
{
if (textureCollection.find(id) == textureCollection.end())
{
return nullptr;
}
return &textureCollection[id];
}
/**************************************************************************** /****************************************************************************
* \param Path for meta data file * \param Path for meta data file
* \param Path for asset file * \param Path for asset file
@ -307,12 +327,22 @@ namespace SHADE
for (auto const& mesh : meshes) for (auto const& mesh : meshes)
{ {
meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh); auto id{ GenerateAssetID(AssetType::MESH) };
meshCollection.emplace(id, mesh);
AssetPath path;
if (!mesh.compiled) if (!mesh.compiled)
{ {
SHMeshCompiler::CompileMeshBinary(mesh, asset.path); path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
} }
assetCollection.emplace_back(
mesh.header.meshName,
id,
AssetType::MESH,
path,
0
);
} }
} }
@ -322,11 +352,20 @@ namespace SHADE
SHTextureLoader::LoadImageAsset(asset.path, image); SHTextureLoader::LoadImageAsset(asset.path, image);
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
if (!image.compiled) if (!image.compiled)
{ {
SHTextureCompiler::CompileTextureBinary(image, asset.path); auto id{ GenerateAssetID(AssetType::TEXTURE) };
textureCollection.emplace(id, image);
auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
assetCollection.emplace_back(
image.name,
id,
AssetType::TEXTURE,
path,
0
);
} }
} }
@ -344,8 +383,24 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
void SHAssetManager::LoadAllData() noexcept void SHAssetManager::LoadAllData() noexcept
{ {
//TODO Remove when on demand loading is done
for (auto const& asset : assetCollection) for (auto const& asset : assetCollection)
{ {
switch (asset.type)
{
case AssetType::MESH:
meshCollection.emplace(asset.id, SHMeshAsset());
SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
break;
case AssetType::TEXTURE:
textureCollection.emplace(asset.id, SHTextureAsset());
SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
break;
default:
void;
}
} }
} }
@ -362,40 +417,51 @@ namespace SHADE
std::vector<AssetPath> metaFiles; std::vector<AssetPath> metaFiles;
std::vector<AssetPath> AssetFiles; std::vector<AssetPath> AssetFiles;
//TODO: Write new function for file manager to loop through all files for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
SHFileSystem::StartupFillDirectories(ASSET_ROOT);
FolderPointer rootFolder = SHFileSystem::GetRoot();
for (auto const& meta : metaFiles)
{ {
for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() }; if (dir.path().extension().string() == META_EXTENSION)
it != AssetFiles.cend();
++it)
{ {
// Asset exists for meta file auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
std::string fileExtCheck{ it->filename().string() };
fileExtCheck += META_EXTENSION; assetCollection.push_back(meta);
if (meta.filename().string() == fileExtCheck) assetRegistry.emplace(meta.id, meta);
{
RegisterAsset(meta, *it);
AssetFiles.erase(it);
break;
}
} }
} }
//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) //TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
for (auto const& file : AssetFiles) //for (auto const& file : AssetFiles)
{ //{
if (IsRecognised(file.extension().string().c_str())) // if (IsRecognised(file.extension().string().c_str()))
{ // {
SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file)); // SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
} // }
else // else
{ // {
std::cout << "Unsupported File Format: " << file.filename() << "\n"; // std::cout << "Unsupported File Format: " << file.filename() << "\n";
} // }
} //}
} }
AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept

View File

@ -75,6 +75,8 @@ namespace SHADE
static std::vector<SHMeshAsset> GetAllMeshes() noexcept; static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
static std::vector<SHTextureAsset> GetAllTextures() noexcept; static std::vector<SHTextureAsset> GetAllTextures() noexcept;
static SHMeshAsset const* GetMesh(AssetID id) noexcept;
static SHTextureAsset const* GetTexture(AssetID id) noexcept;
private: private:
/**************************************************************************** /****************************************************************************
* \brief Load resource data into memory * \brief Load resource data into memory

View File

@ -72,6 +72,13 @@ namespace SHADE
std::string line; std::string line;
SHAsset meta; SHAsset meta;
// Get resource name
GetFieldValue(metaFile, line);
std::stringstream nameStream{ line };
AssetName name;
nameStream >> name;
meta.name = name;
// Get resource id // Get resource id
GetFieldValue(metaFile, line); GetFieldValue(metaFile, line);
std::stringstream idStream{ line }; std::stringstream idStream{ line };
@ -88,6 +95,8 @@ namespace SHADE
metaFile.close(); metaFile.close();
meta.path = path.parent_path().string() + "/" + path.stem().string();
return meta; return meta;
} }
@ -103,7 +112,7 @@ namespace SHADE
std::string path{ meta.path.string() }; std::string path{ meta.path.string() };
path.append(META_EXTENSION); 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()) if (!metaFile.is_open())
{ {
@ -113,17 +122,17 @@ namespace SHADE
metaFile << "Name: " << meta.name << "\n"; metaFile << "Name: " << meta.name << "\n";
metaFile << "ID: " << meta.id << "\n"; metaFile << "ID: " << meta.id << "\n";
metaFile << "Type: " << static_cast<int>(meta.type) << std::endl; metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
//TODO Add in information that is specific to types like mesh ////TODO Add in information that is specific to types like mesh
switch(meta.type) //switch(meta.type)
{ //{
case AssetType::MESH: //case AssetType::MESH:
break; // break;
default: //default:
break; // break;
} //}
metaFile.close(); metaFile.close();
} }

View File

@ -0,0 +1,131 @@
#include "SHpch.h"
#include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.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;
dirtyView = true;
}
void SHCameraComponent::SetPitch(float pitch) noexcept
{
this->pitch = pitch;
dirtyView = true;
}
void SHCameraComponent::SetRoll(float roll) noexcept
{
this->roll = roll;
dirtyView = true;
}
void SHCameraComponent::SetPositionX(float x) noexcept
{
position.x = x;
dirtyView = true;
}
void SHCameraComponent::SetPositionY(float y) noexcept
{
position.y = y;
dirtyView = true;
}
void SHCameraComponent::SetPositionZ(float z) noexcept
{
position.z = z;
dirtyView = true;
}
void SHCameraComponent::SetPosition(float x,float y, float z) noexcept
{
position.x = x;
position.y = y;
position.z = z;
dirtyView = true;
}
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
{
this->position = 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;
}
}

View File

@ -0,0 +1,85 @@
#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;
float movementSpeed;
SHVec3 turnSpeed;
protected:
};
}

View File

@ -0,0 +1,173 @@
#include "SHpch.h"
#include "SHCameraSystem.h"
#include "Math/SHMathHelpers.h"
#include "Input/SHInputManager.h"
#include "Math/Vector/SHVec2.h"
namespace SHADE
{
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))
{
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;
}
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 (camera.dirtyView)
{
SHVec3 view, right, UP;
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));
std::cout << "Target vec: " << target.x<<", "<<target.y<<", "<<target.z << std::endl;
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);
}
}

View File

@ -0,0 +1,49 @@
#pragma once
#include "ECS_Base/System/SHSystem.h"
#include "SHCameraComponent.h"
#include "ECS_Base/System/SHSystemRoutine.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;
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;
SHCameraComponent* GetEditorCamera (void) noexcept;
protected:
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
};
}

View File

@ -48,6 +48,9 @@ namespace SHADE
{ {
} }
public: public:
//Whether or not this component is active. //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. //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 * \return uint32_t
* The entityID that this component belongs to. * The entityID that this component belongs to.
***************************************************************************/ ***************************************************************************/
uint32_t GetEID()const uint32_t GetEID()const noexcept
{ {
return this->entityID; return this->entityID;
} }

View File

@ -6,11 +6,11 @@
//#==============================================================# //#==============================================================#
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "Editor/SHEditor.hpp"
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "SHHierarchyPanel.h" #include "SHHierarchyPanel.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Editor/SHEditor.hpp"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Editor/DragDrop/SHDragDrop.hpp" #include "Editor/DragDrop/SHDragDrop.hpp"
#include "Tools/SHException.h" #include "Tools/SHException.h"
@ -21,6 +21,8 @@
//#==============================================================# //#==============================================================#
#include <imgui.h> #include <imgui.h>
#include "Serialization/SHSerialization.h"
namespace SHADE namespace SHADE
{ {
@ -62,11 +64,12 @@ namespace SHADE
if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{ {
SHEditor::selectedEntities.clear(); if(auto editor = SHSystemManager::GetSystem<SHEditor>())
editor->selectedEntities.clear();
} }
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal); ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
ImGui::End();
} }
ImGui::End();
} }
void SHHierarchyPanel::Exit() void SHHierarchyPanel::Exit()
@ -74,6 +77,11 @@ namespace SHADE
SHEditorWindow::Exit(); SHEditorWindow::Exit();
} }
void SHHierarchyPanel::SetScrollTo(EntityID eid)
{
scrollTo = eid;
}
//#==============================================================# //#==============================================================#
//|| Private Member Functions || //|| Private Member Functions ||
//#==============================================================# //#==============================================================#
@ -81,7 +89,20 @@ namespace SHADE
{ {
if (ImGui::BeginMenuBar()) if (ImGui::BeginMenuBar())
{ {
if (ImGui::SmallButton(ICON_MD_ADD))
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
if(ImGui::SmallButton(ICON_MD_DESELECT))
{
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))
{ {
SHEntityManager::CreateEntity(); SHEntityManager::CreateEntity();
} }
@ -102,7 +123,16 @@ namespace SHADE
//Get node data (Children, eid, selected) //Get node data (Children, eid, selected)
auto& children = currentNode->GetChildren(); auto& children = currentNode->GetChildren();
EntityID eid = currentNode->GetEntityID(); EntityID eid = currentNode->GetEntityID();
const bool isSelected = (std::ranges::find(SHEditor::selectedEntities, eid) != SHEditor::selectedEntities.end());
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());
const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow); const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow);
@ -140,8 +170,12 @@ namespace SHADE
{ {
if(!isSelected) if(!isSelected)
{ {
SHEditor::selectedEntities.clear(); editor->selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
}
if(ImGui::Selectable("Copy"))
{
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
} }
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{ {
@ -163,19 +197,19 @@ namespace SHADE
if (!isSelected) if (!isSelected)
{ {
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
SHEditor::selectedEntities.clear(); editor->selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
}//if not selected }//if not selected
else else
{ {
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
{ {
auto it = std::ranges::remove(SHEditor::selectedEntities, eid).begin(); auto it = std::ranges::remove(editor->selectedEntities, eid).begin();
}//if mod ctrl is not pressed }//if mod ctrl is not pressed
else else
{ {
SHEditor::selectedEntities.clear(); editor->selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
} }
}//if selected }//if selected
}//if left mouse button released }//if left mouse button released

View File

@ -23,11 +23,13 @@ namespace SHADE
void Init() override; void Init() override;
void Update() override; void Update() override;
void Exit() override; void Exit() override;
void SetScrollTo(EntityID eid);
private: private:
void DrawMenuBar() const noexcept; void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode*); ImRect RecursivelyDrawEntityNode(SHSceneNode*);
void CreateChildEntity(EntityID parentEID) const noexcept; void CreateChildEntity(EntityID parentEID) const noexcept;
std::string filter; std::string filter;
bool isAnyNodeSelected = false; bool isAnyNodeSelected = false;
EntityID scrollTo = MAX_EID;
};//class SHHierarchyPanel };//class SHHierarchyPanel
}//namespace SHADE }//namespace SHADE

View File

@ -12,13 +12,14 @@
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "Physics/Components/SHColliderComponent.h"
#include "Reflection/SHReflectionMetadata.h" #include "Reflection/SHReflectionMetadata.h"
namespace SHADE namespace SHADE
{ {
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true> template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
static void DrawContextMenu(T* component) static void DrawContextMenu(T* component)
{ {
if(!component) if (!component)
return; return;
rttr::string_view componentName = rttr::type::get<T>().get_name(); rttr::string_view componentName = rttr::type::get<T>().get_name();
@ -45,7 +46,7 @@ namespace SHADE
{ {
if (!component) if (!component)
return; return;
auto componentType = rttr::type::get(*component); const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data())) if (ImGui::CollapsingHeader(componentType.get_name().data()))
@ -56,26 +57,26 @@ namespace SHADE
{ {
auto const& type = property.get_type(); auto const& type = property.get_type();
if(type.is_enumeration()) if (type.is_enumeration())
{ {
auto enumAlign = type.get_enumeration(); auto enumAlign = type.get_enumeration();
auto names = enumAlign.get_names(); auto names = enumAlign.get_names();
std::vector<const char*> list; std::vector<const char*> list;
for(auto const& name : names) for (auto const& name : names)
list.push_back(name.data()); list.push_back(name.data());
SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx) SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& idx)
{ {
auto enumAlign = property.get_enumeration(); auto enumAlign = property.get_enumeration();
auto values = enumAlign.get_values(); auto values = enumAlign.get_values();
auto it = std::next(values.begin(), idx); auto it = std::next(values.begin(), idx);
property.set_value(component, *it); property.set_value(component, *it);
}); });
} }
else if(type.is_arithmetic()) else if (type.is_arithmetic())
{ {
if (type == rttr::type::get<bool>()) if (type == rttr::type::get<bool>())
{ {
SHEditorWidgets::CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);}); SHEditorWidgets::CheckBox(property.get_name().data(), [component, property] {return property.get_value(component).to_bool(); }, [component, property](bool const& result) {property.set_value(component, result); });
} }
//else if (type == rttr::type::get<char>()) //else if (type == rttr::type::get<char>())
//{ //{
@ -85,39 +86,39 @@ namespace SHADE
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin && metaMax) if (metaMin && metaMax)
{ {
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
} }
else else
{ {
SHEditorWidgets::DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); SHEditorWidgets::DragInt(property.get_name().data(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
} }
} }
else if (type == rttr::type::get<uint8_t>()) else if (type == rttr::type::get<uint8_t>())
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, "%zu");
} }
else else
{ {
SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
} }
} }
else if (type == rttr::type::get<uint16_t>()) else if (type == rttr::type::get<uint16_t>())
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
} }
else else
{ {
SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
} }
} }
else if (type == rttr::type::get<uint32_t>()) else if (type == rttr::type::get<uint32_t>())
@ -126,50 +127,50 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if (metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },"%zu"); SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
} }
else else
{ {
SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
} }
} }
else if (type == rttr::type::get<uint64_t>()) else if (type == rttr::type::get<uint64_t>())
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
} }
else else
{ {
SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu");
} }
} }
else if (type == rttr::type::get<float>()) else if (type == rttr::type::get<float>())
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
} }
else else
{ {
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
} }
} }
else if (type == rttr::type::get<double>()) else if (type == rttr::type::get<double>())
{ {
auto metaMin = property.get_metadata(META::min); auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}); SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
} }
else else
{ {
SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f); SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }, 0.1f);
} }
} }
} }
@ -183,11 +184,83 @@ namespace SHADE
} }
else if (type == rttr::type::get<SHVec2>()) else if (type == rttr::type::get<SHVec2>())
{ {
SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); }); SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y" }, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); });
} }
} }
} }
else DrawContextMenu(component); else DrawContextMenu(component);
} }
template<>
static void DrawComponent(SHColliderComponent* component)
{
if (!component)
return;
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
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 });
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);});
}
else if (collider.GetType() == SHCollider::Type::SPHERE)
{
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
SHEditorWidgets::DragFloat("Radius", [sphere] {return sphere->GetRadius(); }, [sphere](float const& value) {sphere->SetRadius(value);});
}
else if (collider.GetType() == SHCollider::Type::CAPSULE)
{
}
{
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider.GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider.SetPositionOffset(vec); });
SHEditorWidgets::EndPanel();
}
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
{
colliderToDelete = i;
}
SHEditorWidgets::EndPanel();
ImGui::PopID();
}
if(colliderToDelete.has_value())
{
component->RemoveCollider(colliderToDelete.value());
}
ImGui::EndChild();
if (ImGui::BeginMenu("Add Collider"))
{
if(ImGui::Selectable("Box Collider"))
{
component->AddBoundingBox();
}
if(ImGui::Selectable("Sphere Collider"))
{
component->AddBoundingSphere();
}
ImGui::EndMenu();
}
}
else DrawContextMenu(component);
}
} }

View File

@ -1,5 +1,6 @@
#include "SHpch.h" #include "SHpch.h"
#include "Editor/SHEditor.hpp"
#include "SHEditorInspector.h" #include "SHEditorInspector.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
@ -7,7 +8,6 @@
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Editor/SHEditor.hpp"
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
#include "SHEditorComponentView.hpp" #include "SHEditorComponentView.hpp"
@ -24,12 +24,15 @@
namespace SHADE namespace SHADE
{ {
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
void DrawAddComponentButton(EntityID const& eid) bool DrawAddComponentButton(EntityID const& eid)
{ {
if(!SHComponentManager::HasComponent<ComponentType>(eid) && ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data())) bool selected = false;
if(!SHComponentManager::HasComponent<ComponentType>(eid))
{ {
SHComponentManager::AddComponent<ComponentType>(eid); if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
SHComponentManager::AddComponent<ComponentType>(eid);
} }
return selected;
} }
SHEditorInspector::SHEditorInspector() SHEditorInspector::SHEditorInspector()
@ -47,15 +50,10 @@ namespace SHADE
SHEditorWindow::Update(); SHEditorWindow::Update();
if (Begin()) if (Begin())
{ {
if (ImGui::Button("AUDIO")) auto editor = SHSystemManager::GetSystem<SHEditor>();
if (editor && !editor->selectedEntities.empty())
{ {
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>(); EntityID const& eid = editor->selectedEntities[0];
audioSystem->PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
}
if (!SHEditor::selectedEntities.empty())
{
EntityID const& eid = SHEditor::selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid); SHEntity* entity = SHEntityManager::GetEntityByID(eid);
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid); ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
@ -90,13 +88,19 @@ namespace SHADE
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid); DrawAddComponentButton<SHRenderable>(eid);
DrawAddComponentButton<SHColliderComponent>(eid); DrawAddComponentButton<SHColliderComponent>(eid);
DrawAddComponentButton<SHRigidBodyComponent>(eid); if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
{
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
{
SHComponentManager::AddComponent<SHTransformComponent>(eid);
}
}
ImGui::EndMenu(); ImGui::EndMenu();
} }
} }
ImGui::End();
} }
ImGui::End();
} }
void SHEditorInspector::Exit() void SHEditorInspector::Exit()

View File

@ -3,11 +3,11 @@
//#==============================================================# //#==============================================================#
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "Editor/SHEditor.hpp"
#include "SHEditorMenuBar.h" #include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h" #include "Editor/Command/SHCommandManager.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Editor/SHEditor.hpp"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
//#==============================================================# //#==============================================================#
@ -17,6 +17,8 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <rttr/type> #include <rttr/type>
#include "Serialization/SHSerialization.h"
namespace SHADE namespace SHADE
{ {
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -36,6 +38,11 @@ namespace SHADE
void SHEditorMenuBar::Init() void SHEditorMenuBar::Init()
{ {
SHEditorWindow::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() void SHEditorMenuBar::Update()
@ -68,7 +75,14 @@ namespace SHADE
{ {
if (ImGui::BeginMenu("File")) 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(); ImGui::EndMenu();
} }
if(ImGui::BeginMenu("Edit")) if(ImGui::BeginMenu("Edit"))
@ -87,19 +101,6 @@ namespace SHADE
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenu(); 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()))
{
SHEditor::SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scripts")) if (ImGui::BeginMenu("Scripts"))
{ {
if (ImGui::Selectable("Generate Visual Studio Project")) if (ImGui::Selectable("Generate Visual Studio Project"))
@ -119,18 +120,79 @@ namespace SHADE
} }
ImGui::EndMenu(); 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(); ImGui::EndMainMenuBar();
} }
const ImGuiID dockspace_id = ImGui::GetID("DockSpace"); const ImGuiID dockspaceId = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspaceFlags); ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
ImGui::End(); ImGui::End();
} }
} }
void SHEditorMenuBar::DrawSecondaryBar() const noexcept 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 void SHEditorMenuBar::DrawStatusBar() const noexcept
@ -141,8 +203,8 @@ namespace SHADE
if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags)) if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags))
{ {
ImGui::Text("Entity count: "); ImGui::Text("Entity count: ");
ImGui::End();
} }
ImGui::End();
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);
} }

View File

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

View File

@ -37,8 +37,8 @@ namespace SHADE
if(Begin()) if(Begin())
{ {
ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f); ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f);
ImGui::End();
} }
ImGui::End();
} }
void SHEditorProfiler::Exit() void SHEditorProfiler::Exit()

View File

@ -19,7 +19,7 @@ namespace SHADE
//|| Public Member Functions || //|| Public Member Functions ||
//#==============================================================# //#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags) 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,30 @@ namespace SHADE
//#==============================================================# //#==============================================================#
bool SHEditorWindow::Begin() bool SHEditorWindow::Begin()
{ {
return ImGui::Begin(windowName.data(), &isOpen, windowFlags); bool result = ImGui::Begin(windowName.data(), &isOpen, windowFlags);
auto wndSize = ImGui::GetWindowSize();
if(windowSize.x != wndSize.x || windowSize.y != wndSize.y)
{
windowSize = {wndSize.x, wndSize.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 }//namespace SHADE

View File

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

View File

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

View File

@ -0,0 +1,84 @@
#include "SHpch.h"
#include "SHEditorViewport.h"
#include "ECS_Base/Managers/SHSystemManager.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"
namespace SHADE
{
SHEditorViewport::SHEditorViewport()
:SHEditorWindow("Viewport", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoScrollbar)
{
}
void SHEditorViewport::Init()
{
SHEditorWindow::Init();
}
void SHEditorViewport::Update()
{
SHEditorWindow::Update();
if(Begin())
{
DrawMenuBar();
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
auto mousePos = ImGui::GetMousePos();
auto cursorPos = ImGui::GetCursorScreenPos();
viewportMousePos = {mousePos.x - cursorPos.x, mousePos.y - cursorPos.y};
gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
//if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
//{
// auto eid = gfxSystem->GetMousePickSystem ()->GetPickedEntity();
// if(eid != MAX_EID)
// {
// auto editor = SHSystemManager::GetSystem<SHEditor>();
// editor->selectedEntities.clear();
// editor->selectedEntities.push_back(eid);
// if (const auto hierarchyPanel = SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>())
// {
// hierarchyPanel->SetScrollTo(eid);
// }
// }
//}
ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
}
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 = {}
gfxSystem->PrepareResize(static_cast<uint32_t>(windowSize.x), static_cast<uint32_t>(windowSize.y));
}
void SHEditorViewport::OnPosChange()
{
SHEditorWindow::OnPosChange();
}
void SHEditorViewport::DrawMenuBar() const noexcept
{
if(ImGui::BeginMenuBar())
{
ImGui::EndMenuBar();
}
}
}//namespace SHADE

View File

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

View File

@ -43,6 +43,8 @@
#include <backends/imgui_impl_sdl.h> #include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h> #include <backends/imgui_impl_vulkan.h>
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
RTTR_REGISTRATION RTTR_REGISTRATION
{ {
using namespace SHADE; using namespace SHADE;
@ -60,19 +62,20 @@ RTTR_REGISTRATION
namespace SHADE namespace SHADE
{ {
//#==============================================================# //#==============================================================#
//|| Initialise static members || //|| Init static members ||
//#==============================================================# //#==============================================================#
Handle<SHVkCommandPool> SHEditor::imguiCommandPool; //Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer; //Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
SHEditor::EditorWindowMap SHEditor::editorWindows{}; SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{};
SHEditor::EditorWindowID SHEditor::windowCount{}; SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{};
std::vector<EntityID> SHEditor::selectedEntities; //std::vector<EntityID> SHEditor::selectedEntities;
//#==============================================================# //#==============================================================#
//|| Public Member Functions || //|| Public Member Functions ||
//#==============================================================# //#==============================================================#
void SHEditor::Initialise(SDL_Window* const sdlWindow) void SHEditor::Init()
{ {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
if(auto context = ImGui::CreateContext()) if(auto context = ImGui::CreateContext())
{ {
@ -82,36 +85,46 @@ namespace SHADE
} }
} }
ImGuiIO& io = ImGui::GetIO(); (void)io; //Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io = &ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking 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";
InitLayout();
InitFonts(); InitFonts();
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>(); auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>(); auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>(); auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
InitBackend(sdlWindow);
InitBackend();
SetStyle(Style::SHADE); SetStyle(Style::SHADE);
//Add editor windows
CreateEditorWindow<SHEditorMenuBar>(); for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
CreateEditorWindow<SHHierarchyPanel>(); {
CreateEditorWindow<SHEditorInspector>(); window->Init();
CreateEditorWindow<SHEditorProfiler>(); }
SHLOG_INFO("Successfully initialised SHADE Engine Editor") SHLOG_INFO("Successfully initialised SHADE Engine Editor")
} }
void SHEditor::Update(float const dt) void SHEditor::Update(double const dt)
{ {
(void)dt; (void)dt;
NewFrame(); NewFrame();
for (const auto& window : editorWindows | std::views::values) for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{ {
if(window->isOpen) if(window->isOpen)
window->Update(); window->Update();
@ -126,35 +139,45 @@ namespace SHADE
SHCommandManager::UndoCommand(); SHCommandManager::UndoCommand();
} }
Render(); Render();
} }
void SHEditor::Render() void SHEditor::Render()
{ {
ImGui::Render(); ImGui::Render();
ImGuiIO& io = ImGui::GetIO(); if (io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{ {
ImGui::UpdatePlatformWindows(); ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault(); 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 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 }; constexpr ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.PixelSnapH = true; 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 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(); io->Fonts->Build();
} }
void SHEditor::Exit() void SHEditor::Exit()
{ {
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
window->Init();
}
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
@ -167,86 +190,86 @@ namespace SHADE
default: default:
case Style::SHADE: case Style::SHADE:
{ {
ImGuiStyle& imStyle = ImGui::GetStyle(); ImGuiStyle& imStyle = ImGui::GetStyle();
ImVec4* colors = imStyle.Colors; ImVec4* colors = imStyle.Colors;
colors[ImGuiCol_Text] = ImVec4(0.706f, 0.729f, 0.757f, 1.00f); colors[ImGuiCol_Text] = ImVec4(0.706f, 0.729f, 0.757f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.172f, 0.184f, 0.203f, 1.f); colors[ImGuiCol_WindowBg] = ImVec4(0.172f, 0.184f, 0.203f, 1.f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f); colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f);
colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f); colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f);
colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_TitleBg] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_TitleBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgActive] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_TitleBgActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgCollapsed] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_TitleBgCollapsed] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_MenuBarBg] = ImVec4(0.129f, 0.141f, 0.157f, 1.f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.129f, 0.141f, 0.157f, 1.f);
colors[ImGuiCol_ScrollbarBg] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_ScrollbarBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f); colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_CheckMark] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f); colors[ImGuiCol_CheckMark] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.15f, 0.15f, 0.15f, 0.54f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.15f, 0.15f, 0.15f, 0.54f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f); colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f);
colors[ImGuiCol_Separator] = colors[ImGuiCol_MenuBarBg]; colors[ImGuiCol_Separator] = colors[ImGuiCol_MenuBarBg];
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_Tab] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_Tab] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.14f, 0.14f, 0.14f, 0.8f); colors[ImGuiCol_TabActive] = ImVec4(0.14f, 0.14f, 0.14f, 0.8f);
colors[ImGuiCol_TabUnfocused] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_TabUnfocused] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabUnfocusedActive] = colors[ImGuiCol_WindowBg]; colors[ImGuiCol_TabUnfocusedActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_DockingPreview] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f); colors[ImGuiCol_DockingPreview] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.855f, 0.6f, 0.941f, 1.00f); colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.855f, 0.6f, 0.941f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.73f, 0.73f, 0.73f, 0.7f); colors[ImGuiCol_NavHighlight] = ImVec4(0.73f, 0.73f, 0.73f, 0.7f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.141f, 0.141f, 0.141f, 0.70f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.141f, 0.141f, 0.141f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = colors[ImGuiCol_NavHighlight]; colors[ImGuiCol_NavWindowingDimBg] = colors[ImGuiCol_NavHighlight];
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.2f, 0.2f, 0.2f, 0.65f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.2f, 0.2f, 0.2f, 0.65f);
imStyle.WindowPadding = ImVec2(8.00f, 8.00f); imStyle.WindowPadding = ImVec2(8.00f, 8.00f);
imStyle.FramePadding = ImVec2(5.00f, 2.00f); imStyle.FramePadding = ImVec2(5.00f, 2.00f);
imStyle.CellPadding = ImVec2(6.00f, 8.00f); imStyle.CellPadding = ImVec2(6.00f, 8.00f);
imStyle.ItemSpacing = ImVec2(6.00f, 6.00f); imStyle.ItemSpacing = ImVec2(6.00f, 6.00f);
imStyle.ItemInnerSpacing = ImVec2(6.00f, 6.00f); imStyle.ItemInnerSpacing = ImVec2(6.00f, 6.00f);
imStyle.TouchExtraPadding = ImVec2(0.00f, 0.00f); imStyle.TouchExtraPadding = ImVec2(0.00f, 0.00f);
imStyle.IndentSpacing = 25; imStyle.IndentSpacing = 25;
imStyle.ScrollbarSize = 15; imStyle.ScrollbarSize = 15;
imStyle.GrabMinSize = 10; imStyle.GrabMinSize = 10;
imStyle.WindowBorderSize = 0.6f; imStyle.WindowBorderSize = 0.6f;
imStyle.ChildBorderSize = 1; imStyle.ChildBorderSize = 1;
imStyle.PopupBorderSize = 1; imStyle.PopupBorderSize = 1;
imStyle.FrameBorderSize = 1; imStyle.FrameBorderSize = 1;
imStyle.TabBorderSize = 1; imStyle.TabBorderSize = 1;
imStyle.WindowRounding = 7; imStyle.WindowRounding = 7;
imStyle.ChildRounding = 4; imStyle.ChildRounding = 4;
imStyle.FrameRounding = 3; imStyle.FrameRounding = 3;
imStyle.PopupRounding = 4; imStyle.PopupRounding = 4;
imStyle.ScrollbarRounding = 9; imStyle.ScrollbarRounding = 9;
imStyle.GrabRounding = 3; imStyle.GrabRounding = 3;
imStyle.LogSliderDeadzone = 4; imStyle.LogSliderDeadzone = 4;
imStyle.TabRounding = 4; imStyle.TabRounding = 4;
imStyle.WindowMenuButtonPosition = ImGuiDir_None; imStyle.WindowMenuButtonPosition = ImGuiDir_None;
} }
break; break;
@ -260,7 +283,7 @@ namespace SHADE
//#==============================================================# //#==============================================================#
//|| Private Member Functions || //|| Private Member Functions ||
//#==============================================================# //#==============================================================#
void SHEditor::InitBackend(SDL_Window* sdlWindow) void SHEditor::InitBackend()
{ {
if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false) if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false)
{ {
@ -281,10 +304,11 @@ namespace SHADE
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); 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); 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") 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(); auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false) if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
@ -309,6 +333,29 @@ namespace SHADE
}); });
} }
void SHEditor::PollPicking()
{
if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
{
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
if (viewportWindow->isWindowHovered && 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() void SHEditor::NewFrame()
{ {
SDL_Event event; SDL_Event event;
@ -322,4 +369,9 @@ namespace SHADE
} }
void SHEditor::EditorRoutine::Execute(double dt) noexcept
{
reinterpret_cast<SHEditor*>(system)->Update(dt);
}
}//namespace SHADE }//namespace SHADE

View File

@ -11,6 +11,8 @@
//#==============================================================# //#==============================================================#
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/Handle.h" #include "Resource/Handle.h"
#include "EditorWindow/SHEditorWindow.h" #include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
@ -28,11 +30,7 @@ namespace SHADE
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkCommandPool; class SHVkCommandPool;
/** class SHEditorWindowManager
* @brief SHEditor static class contains editor variables and implementation of editor functions.
*
*/
class SH_API SHEditor
{ {
public: public:
//#==============================================================# //#==============================================================#
@ -41,46 +39,6 @@ namespace SHADE
using EditorWindowID = uint8_t; using EditorWindowID = uint8_t;
using EditorWindowPtr = std::unique_ptr<SHEditorWindow>; using EditorWindowPtr = std::unique_ptr<SHEditorWindow>;
using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>; using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>;
/**
* @brief Style options
*
*/
enum class Style : uint8_t
{
SHADE,
DARK,
LIGHT,
CLASSIC
};
/**
* @brief Initialise the editor
*
* @param sdlWindow pointer to SDL_Window object created in application
*/
static void Initialise(SDL_Window* sdlWindow);
/**
* @brief Update the editor and add to ImGui DrawList
*
* @param dt Delta-time of the frame
*/
static void Update(float dt);
/**
* @brief Safely shutdown the editor
*
*/
static void Exit();
/**
* @brief Set the Style for the editor
*
* @param style Desired style
*/
static void SetStyle(Style style);
/** /**
* @brief Get ID for the Editor Window Type * @brief Get ID for the Editor Window Type
* *
@ -100,39 +58,6 @@ namespace SHADE
return id; return id;
} }
/**
* @brief Get pointer to the Editor Window
*
* @tparam T Type of editor window to retrieve
* @return T* Pointer to the editor window
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static T* GetEditorWindow()
{
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
}
// List of selected entities
static std::vector<EntityID> selectedEntities;
private:
/**
* @brief Initialise Backend for ImGui (SDL and Vulkan backend)
*
* @param sdlWindow Pointer to SDL_Window
*/
static void InitBackend(SDL_Window* sdlWindow);
/**
* @brief Start new frame for editor
*
*/
static void NewFrame();
/**
* @brief Perform ImGui and ImGui Backend Render
*
*/
static void Render();
/** /**
* @brief Create an Editor Window * @brief Create an Editor Window
* *
@ -153,16 +78,127 @@ namespace SHADE
} }
} }
static void InitFonts() noexcept; /**
* @brief Get pointer to the Editor Window
// Handle to command pool used for ImGui Vulkan Backend *
static Handle<SHVkCommandPool> imguiCommandPool; * @tparam T Type of editor window to retrieve
// Handle to command buffer used for ImGui Vulkan Backend * @return T* Pointer to the editor window
static Handle<SHVkCommandBuffer> imguiCommandBuffer; */
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static T* GetEditorWindow()
{
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
}
static EditorWindowMap editorWindows;
private:
// Number of windows; used for Editor Window ID Generation // Number of windows; used for Editor Window ID Generation
static EditorWindowID windowCount; static EditorWindowID windowCount;
// Map of Editor Windows // Map of Editor Windows
static EditorWindowMap editorWindows; friend class SHEditor;
};
/**
* @brief SHEditor static class contains editor variables and implementation of editor functions.
*
*/
class SH_API SHEditor final : public SHSystem
{
public:
class SH_API EditorRoutine final : public SHSystemRoutine
{
public:
EditorRoutine():SHSystemRoutine("Editor routine", true) {};
void Execute(double dt) noexcept override final;
};
enum class State : uint8_t
{
PLAY,
PAUSE,
STOP
};
/**
* @brief Style options
*
*/
enum class Style : uint8_t
{
SHADE,
DARK,
LIGHT,
CLASSIC
};
/**
* @brief Initialise the editor
*
* @param sdlWindow pointer to SDL_Window object created in application
*/
void Init();
/**
* @brief Update the editor and add to ImGui DrawList
*
* @param dt Delta-time of the frame
*/
void Update(double dt);
/**
* @brief Safely shutdown the editor
*
*/
void Exit();
/**
* @brief Set the Style for the editor
*
* @param style Desired style
*/
void SetStyle(Style style);
/**
* @brief Initialise Backend for ImGui (SDL and Vulkan backend)
*
* @param sdlWindow Pointer to SDL_Window
*/
void InitBackend();
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
*
*/
void NewFrame();
/**
* @brief Perform ImGui and ImGui Backend Render
*
*/
void Render();
void InitLayout() noexcept;
void InitFonts() noexcept;
// Handle to command pool used for ImGui Vulkan Backend
Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend
Handle<SHVkCommandBuffer> imguiCommandBuffer;
SDL_Window* sdlWindow {nullptr};
ImGuiIO* io{nullptr};
};//class SHEditor };//class SHEditor
}//namespace SHADE }//namespace SHADE

View File

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

View File

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

View File

@ -16,11 +16,11 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Widgets */ /* ImGui Wrapper Functions - Widgets */
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename Enum> 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; std::vector<Enum> values;
for (int i = 0; i <= maxVal; ++i) for (int i = 0; i <= maxVal; ++i)
@ -28,6 +28,11 @@ namespace SHADE
values.emplace_back(static_cast<Enum>(i)); values.emplace_back(static_cast<Enum>(i));
} }
bool b = false; 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)) if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
{ {
for (int i = 0; i <= maxVal; ++i) for (int i = 0; i <= maxVal; ++i)

View File

@ -26,7 +26,7 @@ namespace SHADE
{ {
class SH_API SHEditorWidgets class SH_API SHEditorWidgets
{ {
public: public:
//#==============================================================# //#==============================================================#
//|| Constructor || //|| Constructor ||
//#==============================================================# //#==============================================================#
@ -35,6 +35,118 @@ namespace SHADE
//#==============================================================# //#==============================================================#
//|| Custom Widgets || //|| Custom Widgets ||
//#==============================================================# //#==============================================================#
inline static ImVector<ImRect> panelStack{};
static void BeginPanel(std::string_view const& name, const ImVec2& size)
{
ImGui::BeginGroup();
auto cursorPos = ImGui::GetCursorScreenPos();
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
auto frameHeight = ImGui::GetFrameHeight();
ImGui::BeginGroup();
ImVec2 effectiveSize = size;
if (size.x < 0.0f)
effectiveSize.x = ImGui::GetContentRegionAvail().x;
else
effectiveSize.x = size.x;
ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f));
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
ImGui::SameLine(0.0f, 0.0f);
ImGui::BeginGroup();
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
ImGui::SameLine(0.0f, 0.0f);
ImGui::TextUnformatted(name.data());
auto labelMin = ImGui::GetItemRectMin();
auto labelMax = ImGui::GetItemRectMax();
ImGui::SameLine(0.0f, 0.0f);
ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y));
ImGui::BeginGroup();
ImGui::PopStyleVar(2);
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f;
ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f;
ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f;
ImGui::GetCurrentWindow()->Size.x -= frameHeight;
auto itemWidth = ImGui::CalcItemWidth();
ImGui::PushItemWidth(ImMax(0.0f, itemWidth - frameHeight));
panelStack.push_back(ImRect(labelMin, labelMax));
}
static void EndPanel()
{
ImGui::PopItemWidth();
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
auto frameHeight = ImGui::GetFrameHeight();
ImGui::EndGroup();
ImGui::EndGroup();
ImGui::SameLine(0.0f, 0.0f);
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y));
ImGui::EndGroup();
auto itemMin = ImGui::GetItemRectMin();
auto itemMax = ImGui::GetItemRectMax();
auto labelRect = panelStack.back();
panelStack.pop_back();
ImVec2 halfFrame = ImVec2(frameHeight * 0.25f, frameHeight) * 0.5f;
ImRect frameRect = ImRect(itemMin + halfFrame, itemMax - ImVec2(halfFrame.x, 0.0f));
labelRect.Min.x -= itemSpacing.x;
labelRect.Max.x += itemSpacing.x;
for (int i = 0; i < 4; ++i)
{
switch (i)
{
// left half-plane
case 0: ImGui::PushClipRect(ImVec2(-FLT_MAX, -FLT_MAX), ImVec2(labelRect.Min.x, FLT_MAX), true); break;
// right half-plane
case 1: ImGui::PushClipRect(ImVec2(labelRect.Max.x, -FLT_MAX), ImVec2(FLT_MAX, FLT_MAX), true); break;
// top
case 2: ImGui::PushClipRect(ImVec2(labelRect.Min.x, -FLT_MAX), ImVec2(labelRect.Max.x, labelRect.Min.y), true); break;
// bottom
case 3: ImGui::PushClipRect(ImVec2(labelRect.Min.x, labelRect.Max.y), ImVec2(labelRect.Max.x, FLT_MAX), true); break;
}
ImGui::GetWindowDrawList()->AddRect(
frameRect.Min, frameRect.Max,
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Button)),
halfFrame.x);
ImGui::PopClipRect();
}
ImGui::PopStyleVar(2);
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f;
ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f;
ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f;
ImGui::GetCurrentWindow()->Size.x += frameHeight;
ImGui::Dummy(ImVec2(0.0f, 0.0f));
ImGui::EndGroup();
}
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f) static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{ {
ImGuiWindow* window = ImGui::GetCurrentWindow(); ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -48,7 +160,7 @@ namespace SHADE
template <typename T, std::size_t N> template <typename T, std::size_t N>
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, 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(), 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(); const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -62,6 +174,8 @@ namespace SHADE
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f); ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str()); ImGui::Text(fieldLabel.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::NextColumn(); ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
{ {
@ -103,11 +217,11 @@ namespace SHADE
if (changed) if (changed)
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
} }
return changed; return changed;
@ -119,7 +233,7 @@ namespace SHADE
{ {
SHVec3 values = get(); SHVec3 values = get();
bool changed = false; bool changed = false;
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
{ {
changed = true; changed = true;
} }
@ -127,11 +241,11 @@ namespace SHADE
if (changed) if (changed)
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
} }
return changed; return changed;
@ -143,7 +257,7 @@ namespace SHADE
{ {
SHVec4 values = get(); SHVec4 values = get();
bool changed = false; bool changed = false;
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
{ {
changed = true; changed = true;
} }
@ -151,11 +265,11 @@ namespace SHADE
if (changed) if (changed)
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
} }
return changed; return changed;
@ -170,21 +284,21 @@ namespace SHADE
bool value = get(); bool value = get();
if (ImGui::Checkbox(label.c_str(), &value)) if (ImGui::Checkbox(label.c_str(), &value))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
return true; return true;
} }
return false; return false;
} }
template<typename T> template<typename T>
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set) static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
{ {
T type = get(); T type = get();
for (size_t i = 0; i < listTypes.size(); i++) for (size_t i = 0; i < listTypes.size(); i++)
{ {
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i])) if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
} }
ImGui::SameLine(); ImGui::SameLine();
} }
@ -199,7 +313,7 @@ namespace SHADE
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData)) if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
{ {
if (ImGui::IsItemDeactivatedAfterEdit()) if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
return true; return true;
} }
@ -211,17 +325,17 @@ namespace SHADE
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{ {
T value = get(); T value = get();
std::cout << value <<" \n"; std::cout << value << " \n";
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags)) if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
return true; return true;
} }
@ -236,11 +350,11 @@ namespace SHADE
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
return true; return true;
} }
@ -256,35 +370,35 @@ namespace SHADE
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit()) else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
return true; return true;
} }
return false; return false;
} }
template <typename T> template <typename T>
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set, static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{
T value = get();
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
{ {
T value = get(); if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
{ else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
return true; return true;
}
return false;
} }
return false;
}
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set, static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{ {
@ -292,9 +406,9 @@ namespace SHADE
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
return true; return true;
@ -310,9 +424,9 @@ namespace SHADE
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
return true; return true;
} }
@ -329,7 +443,7 @@ namespace SHADE
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size()))) if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
} }
ImGui::PopID(); ImGui::PopID();
return edited; return edited;

View File

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

View File

@ -105,6 +105,17 @@ namespace SHADE
vk::Buffer GetVkBuffer (void) const noexcept; vk::Buffer GetVkBuffer (void) const noexcept;
vk::BufferUsageFlags GetUsageBits(void) const noexcept; vk::BufferUsageFlags GetUsageBits(void) const noexcept;
template <typename T>
T GetDataFromMappedPointer(uint32_t index) const noexcept
{
if (mappedPtr && index < sizeStored / sizeof (T))
{
return (static_cast<T*>(mappedPtr))[index];
}
else
return {};
};
}; };
} }

View File

@ -461,6 +461,11 @@ namespace SHADE
); );
} }
void SHVkCommandBuffer::CopyImageToBuffer(const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{
vkCommandBuffer.copyImageToBuffer (src, vk::ImageLayout::eTransferSrcOptimal, dst, copyInfo);
}
void SHVkCommandBuffer::PipelineBarrier( void SHVkCommandBuffer::PipelineBarrier(
vk::PipelineStageFlags srcStage, vk::PipelineStageFlags srcStage,
vk::PipelineStageFlags dstStage, vk::PipelineStageFlags dstStage,

View File

@ -120,7 +120,8 @@ namespace SHADE
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount); void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Buffer Copy // Buffer Copy
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo); 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);
// memory barriers // memory barriers
void PipelineBarrier ( void PipelineBarrier (

View File

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

View File

@ -172,7 +172,7 @@ namespace SHADE
// write sampler and image view // write sampler and image view
auto& [view, sampler, layout] = imageViewsAndSamplers[i]; auto& [view, sampler, layout] = imageViewsAndSamplers[i];
writeInfo.descImageInfos[i].imageView = view->GetImageView(); 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; writeInfo.descImageInfos[i].imageLayout = layout;
} }
} }

View File

@ -1,16 +1,18 @@
#include "SHPch.h" #include "SHPch.h"
#include "SHVkDescriptorSetLayout.h" #include "SHVkDescriptorSetLayout.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkSampler.h"
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructor/Destructor */ /* 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 } : device { device }
, layoutDesc { bindings } , layoutDesc { bindings }
, setIndex {set} , setIndex {set}
, immutableSampler{}
{ {
// Check if auto-binding point calculation configuration is valid // Check if auto-binding point calculation configuration is valid
bool autoCalc = false; 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 // Fill up VK bindings with auto calculated bind points if needed
std::vector<vk::DescriptorSetLayoutBinding> layoutBindings; std::vector<vk::DescriptorSetLayoutBinding> layoutBindings;
layoutBindings.reserve(bindings.size()); layoutBindings.reserve(bindings.size());
@ -39,7 +60,7 @@ namespace SHADE
.descriptorType = binding.Type, .descriptorType = binding.Type,
.descriptorCount = binding.DescriptorCount, .descriptorCount = binding.DescriptorCount,
.stageFlags = binding.Stage, .stageFlags = binding.Stage,
.pImmutableSamplers = nullptr // We will create our own samplers .pImmutableSamplers = genImmutableSamplers ? &tempVkSampler : nullptr,
}; };
layoutBindings.emplace_back(VK_BINDING); layoutBindings.emplace_back(VK_BINDING);
@ -75,7 +96,8 @@ namespace SHADE
: device {rhs.device} : device {rhs.device}
, setLayout {rhs.setLayout} , setLayout {rhs.setLayout}
, layoutDesc{std::move (rhs.layoutDesc)} , layoutDesc{std::move (rhs.layoutDesc)}
, setIndex {rhs.setIndex} , setIndex{ rhs.setIndex }
, immutableSampler{ rhs.immutableSampler }
{ {
rhs.setLayout = VK_NULL_HANDLE; rhs.setLayout = VK_NULL_HANDLE;
} }
@ -106,6 +128,7 @@ namespace SHADE
setLayout = rhs.setLayout; setLayout = rhs.setLayout;
layoutDesc = std::move(rhs.layoutDesc); layoutDesc = std::move(rhs.layoutDesc);
setIndex = rhs.setIndex; setIndex = rhs.setIndex;
immutableSampler = rhs.immutableSampler;
rhs.setLayout = VK_NULL_HANDLE; rhs.setLayout = VK_NULL_HANDLE;

View File

@ -10,6 +10,7 @@ namespace SHADE
/* Forward Declarations */ /* Forward Declarations */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkSampler;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -74,7 +75,7 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="device"></param> /// <param name="device"></param>
/// <param name="bindings"></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(const SHVkDescriptorSetLayout&) = delete;
SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept; SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept;
/// <summary> /// <summary>
@ -107,5 +108,6 @@ namespace SHADE
vk::DescriptorSetLayout setLayout; vk::DescriptorSetLayout setLayout;
std::vector<Binding> layoutDesc; // Stores description of the layout std::vector<Binding> layoutDesc; // Stores description of the layout
SetIndex setIndex; // Index of the set SetIndex setIndex; // Index of the set
Handle<SHVkSampler> immutableSampler;
}; };
} }

View File

@ -550,10 +550,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 Handle<SHVkDescriptorPool> SHVkLogicalDevice::CreateDescriptorPools(const SHVkDescriptorPool::Config& config /*= {}*/) noexcept

View File

@ -186,7 +186,7 @@ namespace SHADE
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::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<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<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<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept;
Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool, Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts, std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,

View File

@ -24,14 +24,15 @@ namespace SHADE
{ {
const vk::SamplerCreateInfo SAMPLER_CREATE_INFO const vk::SamplerCreateInfo SAMPLER_CREATE_INFO
{ {
.magFilter = params.magFilter, .magFilter = params.magFilter,
.minFilter = params.minFilter, .minFilter = params.minFilter,
.mipmapMode = params.mipmapMode, .mipmapMode = params.mipmapMode,
.addressModeU = params.addressMode, .addressModeU = params.addressMode,
.addressModeV = params.addressMode, .addressModeV = params.addressMode,
.addressModeW = params.addressMode, .addressModeW = params.addressMode,
.minLod = params.minLod, .maxAnisotropy = 1.0f,
.maxLod = params.maxLod .minLod = params.minLod,
.maxLod = params.maxLod,
}; };
// Create the sampler // Create the sampler
@ -39,7 +40,8 @@ namespace SHADE
} }
SHVkSampler::SHVkSampler(SHVkSampler&& rhs) noexcept SHVkSampler::SHVkSampler(SHVkSampler&& rhs) noexcept
: vkSampler { rhs.vkSampler } : vkSampler{ rhs.vkSampler }
, device{ rhs.device }
{ {
rhs.vkSampler = nullptr; rhs.vkSampler = nullptr;
} }
@ -56,6 +58,7 @@ namespace SHADE
SHADE::SHVkSampler& SHVkSampler::operator=(SHVkSampler&& rhs) noexcept SHADE::SHVkSampler& SHVkSampler::operator=(SHVkSampler&& rhs) noexcept
{ {
vkSampler = rhs.vkSampler; vkSampler = rhs.vkSampler;
device = rhs.device;
rhs.vkSampler = nullptr; rhs.vkSampler = nullptr;
return *this; return *this;
} }

View File

@ -110,6 +110,7 @@ namespace SHADE
// Clear CPU buffers // Clear CPU buffers
drawData.clear(); drawData.clear();
transformData.clear(); transformData.clear();
eidData.clear();
matPropsData.reset(); matPropsData.reset();
matPropsDataSize = 0; matPropsDataSize = 0;
@ -119,6 +120,7 @@ namespace SHADE
{ {
drawDataBuffer[i].Free(); drawDataBuffer[i].Free();
transformDataBuffer[i].Free(); transformDataBuffer[i].Free();
eidBuffer[i].Free();
matPropsBuffer[i].Free(); matPropsBuffer[i].Free();
} }
} }
@ -206,7 +208,31 @@ namespace SHADE
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0); transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
} }
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) void SHBatch::UpdateEIDBuffer(uint32_t frameIndex)
{
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update eid buffers with an invalid frame index.");
return;
}
// Reset Transform Data
eidData.clear();
// Populate on the CPU
for (auto& subBatch : subBatches)
for (const SHRenderable* renderable : subBatch.Renderables)
{
eidData.emplace_back(renderable->GetEID());
}
// Transfer to GPU
if (eidBuffer[frameIndex])
eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast<EntityID>(eidData.size() * sizeof(EntityID)), 0, 0);
}
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -237,6 +263,11 @@ namespace SHADE
// - Transform data // - Transform data
transformData.reserve(numTotalElements); transformData.reserve(numTotalElements);
transformData.clear(); transformData.clear();
// - EID data
eidData.reserve(numTotalElements);
eidData.clear();
// - Material Properties Data // - Material Properties Data
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
( (
@ -277,7 +308,8 @@ namespace SHADE
for (const SHRenderable* renderable : subBatch.Renderables) for (const SHRenderable* renderable : subBatch.Renderables)
{ {
// Transform // Transform
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(renderable->GetEID()); EntityID eid = renderable->GetEID();
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
if (!transform) if (!transform)
{ {
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
@ -288,6 +320,8 @@ namespace SHADE
transformData.emplace_back(transform->GetTRS()); transformData.emplace_back(transform->GetTRS());
} }
eidData.emplace_back(eid);
// Material Properties // Material Properties
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
@ -317,6 +351,12 @@ namespace SHADE
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer
); );
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(eidData.size() * sizeof(EntityID));
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES,
BuffUsage::eVertexBuffer
);
// - Material Properties Buffer // - Material Properties Buffer
rebuildMaterialBuffers(frameIndex, descPool); rebuildMaterialBuffers(frameIndex, descPool);
@ -339,6 +379,7 @@ namespace SHADE
static std::array<uint32_t, 1> dynamicOffset { 0 }; static std::array<uint32_t, 1> dynamicOffset { 0 };
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0);
if (matPropsDescSet[frameIndex]) if (matPropsDescSet[frameIndex])
{ {
cmdBuffer->BindDescriptorSet cmdBuffer->BindDescriptorSet

View File

@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "ECS_Base/SHECSMacros.h"
namespace SHADE namespace SHADE
{ {
@ -78,6 +79,7 @@ namespace SHADE
void Clear(); void Clear();
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateTransformBuffer(uint32_t frameIndex);
void UpdateEIDBuffer(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ; void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex); void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
@ -109,14 +111,16 @@ namespace SHADE
// CPU Buffers // CPU Buffers
std::vector<vk::DrawIndexedIndirectCommand> drawData; std::vector<vk::DrawIndexedIndirectCommand> drawData;
std::vector<SHMatrix> transformData; std::vector<SHMatrix> transformData;
std::vector<EntityID> eidData;
std::unique_ptr<char> matPropsData; std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
Byte singleMatPropAlignedSize = 0; Byte singleMatPropAlignedSize = 0;
Byte singleMatPropSize = 0; Byte singleMatPropSize = 0;
bool isCPUBuffersDirty = true; bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
TripleBuffer drawDataBuffer; TripleBuffer drawDataBuffer;
TripleBuffer transformDataBuffer; TripleBuffer transformDataBuffer;
TripleBuffer eidBuffer;
TripleBuffer matPropsBuffer; TripleBuffer matPropsBuffer;
TripleDescSet matPropsDescSet; TripleDescSet matPropsDescSet;

View File

@ -83,8 +83,9 @@ namespace SHADE
{ {
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.UpdateMaterialBuffer(frameIndex, descPool); batch.UpdateMaterialBuffer(frameIndex, descPool);
batch.UpdateTransformBuffer(frameIndex); batch.UpdateTransformBuffer(frameIndex);
batch.UpdateEIDBuffer(frameIndex);
} }
} }

View File

@ -91,9 +91,10 @@ namespace SHADE
{ {
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Normals at binding 2 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Tangents at binding 3 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
defaultVertexInputState.AddBinding(true, true, {SHVertexAttribute(SHAttribFormat::MAT_4D)}); // Transform at binding 4 - 7 (4 slots) defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8
} }
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept

View File

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

View File

@ -17,64 +17,66 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/***********************************************************************************/ /***********************************************************************************/
/*! /*!
\brief \brief
Object that manages the view and projection transformations for rendering Object that manages the view and projection transformations for rendering
a 3D scene. a 3D scene.
*/ */
/***********************************************************************************/ /***********************************************************************************/
class SHCamera class SHCamera
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* View Set Functions */ /* View Set Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up); void SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Projection Set Functions */ /* Projection Set Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetPerspective(float fov, float width, float height, float zNear, float zFar); void SetPerspective(float fov, float width, float height, float zNear, float zFar);
void SetOrthographic(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 GetViewProjectionMatrix();
SHMatrix GetInverseViewMatrix() const;
SHMatrix GetInverseProjectionMatrix() const;
SHMatrix GetInverseViewProjectionMatrix();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Mapping Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
SHVec3 ScreenToWorld(const SHVec3& vec) const; SHMatrix GetViewMatrix();
SHVec3 WorldToScreen(const SHVec3& vec) const; SHMatrix GetProjectionMatrix();
SHVec3 CameraToWorld(const SHVec3& vec) const; SHMatrix GetViewProjectionMatrix();
SHVec3 WorldToCamera(const SHVec3& vec) const; SHMatrix GetInverseViewMatrix() const;
SHMatrix GetInverseProjectionMatrix() const;
SHMatrix GetInverseViewProjectionMatrix();
private: /*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/ /* Mapping Functions */
/* Data Members */ /*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/ SHVec3 ScreenToWorld(const SHVec3& vec) const;
SHMatrix viewMatrix; SHVec3 WorldToScreen(const SHVec3& vec) const;
SHMatrix projMatrix; SHVec3 CameraToWorld(const SHVec3& vec) const;
SHMatrix vpMatrix; SHVec3 WorldToCamera(const SHVec3& vec) const;
SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix;
bool isDirty = true;
/*-----------------------------------------------------------------------------*/ private:
/* Helper Functions */ /*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/ /* Data Members */
void updateMatrices(); /*-----------------------------------------------------------------------------*/
static SHVec3 multiplyHomogenous(const SHMatrix& mat, const SHVec3& vec); SHMatrix viewMatrix;
}; SHMatrix projMatrix;
SHMatrix vpMatrix;
SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix;
bool isDirty = true;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void updateMatrices();
static SHVec3 multiplyHomogenous(const SHMatrix& mat, const SHVec3& vec);
};
} }

View File

@ -25,6 +25,12 @@ namespace SHADE
struct SHGraphicsConstants struct SHGraphicsConstants
{ {
public: public:
struct RenderGraphIndices
{
static constexpr uint32_t WORLD = 0;
static constexpr uint32_t EDITOR = 0;
};
struct DescriptorSetIndex struct DescriptorSetIndex
{ {
/***************************************************************************/ /***************************************************************************/
@ -144,6 +150,14 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t TRANSFORM = 4; static constexpr uint32_t TRANSFORM = 4;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the eid buffer.
*/
/***************************************************************************/
static constexpr uint32_t EID = 5;
}; };
/*******************************************************************************/ /*******************************************************************************/

View File

@ -16,6 +16,9 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Instance/SHVkInstance.h" #include "Graphics/Instance/SHVkInstance.h"
#include "Graphics/Windowing/Surface/SHVkSurface.h" #include "Graphics/Windowing/Surface/SHVkSurface.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Camera/SHCameraSystem.h"
#include "Editor/SHEditor.hpp"
#include "ECS_Base/Managers/SHSystemManager.h"
//#include "SHRenderer.h" //#include "SHRenderer.h"
#include "Graphics/Windowing/SHWindow.h" #include "Graphics/Windowing/SHWindow.h"
#include "Graphics/MiddleEnd/PerFrame/SHPerFrameData.h" #include "Graphics/MiddleEnd/PerFrame/SHPerFrameData.h"
@ -32,14 +35,13 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkSampler.h" #include "Graphics/Images/SHVkSampler.h"
#include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHTextureAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
namespace SHADE namespace SHADE
{ {
#pragma region INIT_EXIT
/*---------------------------------------------------------------------------------*/ void SHGraphicsSystem::InitBoilerplate(void) noexcept
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{ {
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* BACKEND BOILERPLATE */ /* BACKEND BOILERPLATE */
@ -70,7 +72,15 @@ namespace SHADE
if (width == 0 || height == 0) if (width == 0 || height == 0)
return; return;
renderContext.SetIsResized(true); #ifdef SHEDITOR
//PrepareResize(1, 1, SHVec2(0, 0));
#else
PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0));
#endif
}); });
window->RegisterWindowCloseCallback([&](void) window->RegisterWindowCloseCallback([&](void)
@ -105,9 +115,10 @@ namespace SHADE
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
}
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
{
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* MIDDLE END SETUP /* MIDDLE END SETUP
- Viewports - Viewports
@ -117,8 +128,8 @@ namespace SHADE
- Default vertex input state - Default vertex input state
- Global data - Global data
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize();
SHGraphicsGlobalData::Init(device);
// Set Up Cameras // Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
@ -130,12 +141,12 @@ namespace SHADE
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f); worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport // 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 // Get render graph from default viewport world renderer
worldRenderGraph = resourceManager.Create<SHRenderGraph>(); 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) for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
{ {
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0]; renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
@ -143,48 +154,27 @@ namespace SHADE
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
//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
worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Depth Buffer", "Present" }, {}); // no predecessors
//First subpass to write to G-Buffer //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
//gBufferWriteSubpass->AddColorOutput("Scene"); gBufferWriteSubpass->AddColorOutput("Scene");
gBufferWriteSubpass->AddColorOutput("Present"); gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL); gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
//writeSubpass->AddColorOutput("Normals");
// //Second subpass to read from G-Buffer // We do this to just transition our scene layout to shader read
//auto compositeSubpass = node->AddSubpass("G-Buffer Composite"); auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
//compositeSubpass->AddColorOutput("Present"); // TODO: This should be "Composite" and then composite will write to swapchain image "Present" sceneLayoutTransitionSubpass->AddInput("Scene");
//compositeSubpass->AddInput("Normals");
//compositeSubpass->AddInput("Position");
// TODO: Use macro to add this node when SH_EDITOR is enabled
auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
// Generate world render graph
worldRenderGraph->Generate(); 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 // Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); worldRenderer->SetCamera(worldCamera);
@ -203,6 +193,95 @@ namespace SHADE
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
{
SHGraphicsGlobalData::Init(device);
InitSceneRenderGraph();
#ifdef SHEDITOR
InitEditorRenderGraph();
#endif
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
}
void SHGraphicsSystem::InitSubsystems(void) noexcept
{
mousePickSystem = resourceManager.Create<SHMousePickSystem>();
std::vector<Handle<SHVkCommandPool>> cmdPools;
cmdPools.reserve(swapchain->GetNumImages());
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
// Register the post offscreen render to the system
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
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 */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -221,12 +300,6 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead()) if (window->IsMinimized() || renderContext.GetWindowIsDead())
return; return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame // Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData(); auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame(); uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -248,6 +321,23 @@ namespace SHADE
// Bind textures // Bind textures
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
{
worldRenderer->SetViewProjectionMatrix(SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
}
else
{
// main camera
}
#else
// main camera
#endif
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -323,13 +413,6 @@ namespace SHADE
} }
} }
void SHGraphicsSystem::Exit(void)
{
}
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -394,16 +477,10 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead()) if (window->IsMinimized() || renderContext.GetWindowIsDead())
return; return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData(); auto& currFrameData = renderContext.GetCurrentFrameData();
mousePickSystem->Run(graphicsQueue, CURR_FRAME_IDX);
// #BackEndTest: queues an image for presentation // #BackEndTest: queues an image for presentation
if (auto result = graphicsQueue->Present(swapchain, { currFrameData.semRenderFinishHdl }, CURR_FRAME_IDX); result != vk::Result::eSuccess) if (auto result = graphicsQueue->Present(swapchain, { currFrameData.semRenderFinishHdl }, CURR_FRAME_IDX); result != vk::Result::eSuccess)
@ -411,9 +488,7 @@ namespace SHADE
// If swapchain is incompatible/outdated // If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{ {
HandleResize(); HandleResize();
} }
} }
@ -421,6 +496,10 @@ namespace SHADE
renderContext.AdvanceFrame(); renderContext.AdvanceFrame();
} }
#pragma endregion LIFECYCLE
#pragma region ADD_REMOVE_BUILD
Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport) Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport)
{ {
// Create the viewport // Create the viewport
@ -531,41 +610,14 @@ namespace SHADE
); );
} }
void SHGraphicsSystem::HandleResize(void) noexcept #pragma endregion ADD_REMOVE
{
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);
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 region ROUTINES
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */ /* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine() SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false) : SHSystemRoutine("Graphics System Frame Set Up", true)
{} {}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
@ -577,7 +629,7 @@ namespace SHADE
/* System Routine Functions - RenderRoutine */ /* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine() SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false) : SHSystemRoutine("Graphics System Render", true)
{} {}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
@ -589,7 +641,7 @@ namespace SHADE
/* System Routine Functions - EndRoutine */ /* System Routine Functions - EndRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::EndRoutine::EndRoutine() SHGraphicsSystem::EndRoutine::EndRoutine()
: SHSystemRoutine("Graphics System Frame Clean Up", false) : SHSystemRoutine("Graphics System Frame Clean Up", true)
{} {}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
@ -601,7 +653,7 @@ namespace SHADE
/* System Routine Functions - BatcherDispatcherRoutine */ /* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine() SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false) : SHSystemRoutine("Graphics System Batcher Dispatcher", true)
{} {}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
@ -632,5 +684,70 @@ namespace SHADE
renderable.ResetChangedFlag(); 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(resizeWidth);
cameraSystem->GetEditorCamera()->SetHeight(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

@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h" #include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
#include "../Textures/SHTextureLibrary.h" #include "../Textures/SHTextureLibrary.h"
#include "../Textures/SHVkSamplerCache.h" #include "../Textures/SHVkSamplerCache.h"
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
namespace SHADE namespace SHADE
{ {
@ -52,6 +53,7 @@ namespace SHADE
class SHVkShaderModule; class SHVkShaderModule;
class SHMaterial; class SHMaterial;
class SHMaterialInstance; class SHMaterialInstance;
class SHMousePickSystem;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -65,6 +67,16 @@ namespace SHADE
/***********************************************************************************/ /***********************************************************************************/
class SH_API SHGraphicsSystem : public SHSystem 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: public:
class SH_API BeginRoutine final : public SHSystemRoutine class SH_API BeginRoutine final : public SHSystemRoutine
{ {
@ -250,6 +262,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void BuildTextures(); void BuildTextures();
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept; void HandleResize(void) noexcept;
void AwaitGraphicsExecution(); void AwaitGraphicsExecution();
@ -261,19 +274,25 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getters (Temporary) */ /* Getters (Temporary) */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> GetDevice() const { return device; } Handle<SHVkLogicalDevice> GetDevice() const { return device; }
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; } Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; } Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; } Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; } Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; } 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; //SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; } //Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -294,13 +313,19 @@ namespace SHADE
SHWindow* window = nullptr; SHWindow* window = nullptr;
// Middle End Resources // Middle End Resources
ResourceManager resourceManager; ResourceManager resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary; SHTextureLibrary texLibrary;
SHSamplerCache samplerCache; SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache; SHMaterialInstanceCache materialInstanceCache;
// Viewports // 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 std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers // Debug Renderers
@ -322,5 +347,12 @@ namespace SHADE
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHRenderGraph> worldRenderGraph; Handle<SHRenderGraph> worldRenderGraph;
// Sub systems
Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
uint32_t resizeWidth;
uint32_t resizeHeight;
}; };
} }

View File

@ -0,0 +1,91 @@
#include "SHpch.h"
#include "SHMousePickSystem.h"
#include "Input/SHInputManager.h"
#include "Graphics/Commands/SHVkCommandPool.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Synchronization/SHVkFence.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
namespace SHADE
{
void SHMousePickSystem::Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept
{
logicalDevice = device;
pickedEID = MAX_EID;
// Create command buffers
for (auto& pool : cmdPools)
{
commandBuffers.push_back(pool->RequestCommandBuffer (SH_CMD_BUFFER_TYPE::PRIMARY));
}
// assign the attachment
entityIDAttachment = eidAttachment;
HandleResize();
}
void SHMousePickSystem::Run(Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept
{
// if input detected
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB))
{
afterCopyFence->Reset();
// begin command buffer for recording
commandBuffers[frameIndex]->BeginRecording();
// transition the image for optimized copying
entityIDAttachment->TransitionImage (vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal, commandBuffers[frameIndex], vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eTransfer, 0);
// copy the image here. Last argument is 0 because the attachment isn't a swapchain image.
entityIDAttachment->CopyToBuffer(imageDataDstBuffer, commandBuffers[frameIndex], 0);
// end command buffer for recording
commandBuffers[frameIndex]->EndRecording();
// submit the command buffer to copy image to buffer
queue->SubmitCommandBuffer({ commandBuffers[frameIndex] }, {}, {}, vk::PipelineStageFlagBits::eColorAttachmentOutput, afterCopyFence);
// wait for the copy to be done
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
}
}
void SHMousePickSystem::HandleResize(void) noexcept
{
if (afterCopyFence)
{
afterCopyFence->Reset();
afterCopyFence.Free();
}
if (imageDataDstBuffer)
imageDataDstBuffer.Free();
// Create the fence
afterCopyFence = logicalDevice->CreateFence();
uint32_t bufferSize = entityIDAttachment->GetWidth() * entityIDAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
// Create the buffer
imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
}
void SHMousePickSystem::SetViewportMousePos(SHVec2 vpMousePos) noexcept
{
viewportMousePos = vpMousePos;
}
EntityID SHMousePickSystem::GetPickedEntity(void) const noexcept
{
return pickedEID;
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
#include "ECS_Base/SHECSMacros.h"
#include "Math/Vector/SHVec2.h"
#include <span>
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkCommandPool;
class SHVkCommandBuffer;
class SHVkFence;
class SHVkQueue;
class SHVkBuffer;
class SHViewport;
class SHMousePickSystem
{
private:
Handle<SHVkLogicalDevice> logicalDevice;
//! Handle to the render graph resource that will contain the entity IDs
Handle<SHRenderGraphResource> entityIDAttachment;
//! Command buffers meant for copying image to buffer
std::vector<Handle<SHVkCommandBuffer>> commandBuffers;
//! After the attachment has copied its data to a buffer, we want to signal this fence
Handle<SHVkFence> afterCopyFence;
//! buffer to contain the attachment data after copying
Handle<SHVkBuffer> imageDataDstBuffer;
//! eid picked from screen
EntityID pickedEID;
//! mouse position relative to the viewport window displaying the world
SHVec2 viewportMousePos;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept;
void Run (Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
void SetViewportMousePos (SHVec2 vpMousePos) noexcept;
EntityID GetPickedEntity (void) const noexcept;
};
}

View File

@ -0,0 +1,84 @@
#include "SHpch.h"
#include "SHPostOffscreenRenderSystem.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkSampler.h"
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
namespace SHADE
{
/***************************************************************************/
/*!
\brief
This function basically creates the entities required for offscreen
rendering. It takes in a render graph resource. Side note: it creates
a descriptor set layout that is similar to the one created in imgui. This
is so that the descriptor set passed to imGui won't be invalid.
\param logicalDevice
For vulkan object creation
\param renderGraphResource
The resource in which has been
\param descriptorPool
\return
*/
/***************************************************************************/
void SHPostOffscreenRenderSystem::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHRenderGraphResource> renderGraphResource, Handle<SHVkDescriptorPool> descriptorPool) noexcept
{
offscreenRender = renderGraphResource;
// Create sampler
offscreenRenderSampler = logicalDevice->CreateSampler(
{
.minFilter = vk::Filter::eLinear,
.magFilter = vk::Filter::eLinear,
.addressMode = vk::SamplerAddressMode::eRepeat,
.mipmapMode = vk::SamplerMipmapMode::eLinear,
.minLod = -1000,
.maxLod = 1000
}
);
// Create descriptor set layout binding
SHVkDescriptorSetLayout::Binding imageBinding
{
.Type = vk::DescriptorType::eCombinedImageSampler,
.Stage = vk::ShaderStageFlagBits::eFragment,
.BindPoint = 0,
.DescriptorCount = 1,
};
// Create descriptor set layout
offscreenRenderDescSetLayout = logicalDevice->CreateDescriptorSetLayout(0, { imageBinding }, false);
// Create descriptor set
offscreenRenderDescSet = descriptorPool->Allocate({ offscreenRenderDescSetLayout }, { 1 });
HandleResize();
}
void SHPostOffscreenRenderSystem::HandleResize(void) noexcept
{
std::vector combinedImageSampler
{
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
};
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
offscreenRenderDescSet->ModifyWriteDescImage(0, 0, combinedImageSampler);
offscreenRenderDescSet->UpdateDescriptorSetImages(0, 0);
}
Handle<SHVkDescriptorSetGroup> SHPostOffscreenRenderSystem::GetDescriptorSetGroup(void) const noexcept
{
return offscreenRenderDescSet;
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "Resource/Handle.h"
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHVkSampler;
class SHRenderGraphResource;
class SHPostOffscreenRenderSystem
{
private:
Handle<SHRenderGraphResource> offscreenRender;
Handle<SHVkDescriptorSetLayout> offscreenRenderDescSetLayout;
Handle<SHVkDescriptorSetGroup> offscreenRenderDescSet;
Handle<SHVkSampler> offscreenRenderSampler;
public:
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHRenderGraphResource> renderGraphResource, Handle<SHVkDescriptorPool> descriptorPool) noexcept;
//void Run ()
void HandleResize (void) noexcept;
Handle<SHVkDescriptorSetGroup> GetDescriptorSetGroup (void) const noexcept;
};
}

View File

@ -75,18 +75,27 @@ namespace SHADE
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{ {
cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); if (camera)
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex); {
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
} }
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{ {
} }
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& vpMatrix) noexcept
{
//cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix();
cpuCameraData.viewProjectionMatrix = vpMatrix;
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
{ {
return renderGraph; return renderGraph;

View File

@ -78,6 +78,7 @@ namespace SHADE
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters and Getters */ /* Setters and Getters */

View File

@ -85,4 +85,14 @@ namespace SHADE
} }
void SHViewport::SetX(float x) noexcept
{
viewport.x = x;
}
void SHViewport::SetY(float y) noexcept
{
viewport.y = y;
}
} }

View File

@ -67,6 +67,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetWidth(float w) noexcept; void SetWidth(float w) noexcept;
void SetHeight (float h) noexcept; void SetHeight (float h) noexcept;
void SetX (float x) noexcept;
void SetY (float y) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getters */ /* Getters */

View File

@ -52,7 +52,6 @@ namespace SHADE
{ {
frameData[i].cmdPoolHdls.push_back(logicalDeviceHdl->CreateCommandPool(params.cmdPoolQueueFamilyType, params.cmdPoolResetMode, params.cmdBufferTransient)); frameData[i].cmdPoolHdls.push_back(logicalDeviceHdl->CreateCommandPool(params.cmdPoolQueueFamilyType, params.cmdPoolResetMode, params.cmdBufferTransient));
} }
} }
// Initialize all the info. // Initialize all the info.

View File

@ -2,6 +2,8 @@
#include "SHPipelineLibrary.h" #include "SHPipelineLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/RenderGraph/SHSubpass.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -21,6 +23,31 @@ namespace SHADE
auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsGlobalData::GetDefaultViState()); newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsGlobalData::GetDefaultViState());
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
colorBlendState.attachments.reserve(subpassColorReferences.size());
for (auto& att : subpassColorReferences)
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible (subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false,
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
);
}
newPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
// Actually construct the pipeline // Actually construct the pipeline
newPipeline->ConstructPipeline(); newPipeline->ConstructPipeline();

View File

@ -137,22 +137,9 @@ namespace SHADE
{ {
VkBool32 logic_op_enable{ VK_FALSE }; VkBool32 logic_op_enable{ VK_FALSE };
vk::LogicOp logic_op{ VK_LOGIC_OP_COPY }; vk::LogicOp logic_op{ vk::LogicOp::eCopy };
std::vector<vk::PipelineColorBlendAttachmentState> attachments = std::vector<vk::PipelineColorBlendAttachmentState> attachments{};
{
vk::PipelineColorBlendAttachmentState
{
.blendEnable = true,
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
};
}; };
// TODO: Specialization constants // TODO: Specialization constants

View File

@ -0,0 +1,7 @@
#include "SHpch.h"
#include "SHAttachmentDescInitParams.h"
namespace SHADE
{
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Resource/Handle.h"
namespace SHADE
{
class SHRenderGraphResource;
struct SHAttachmentDescInitParams
{
Handle<SHRenderGraphResource> resourceHdl;
bool dontClearOnLoad{false};
};
}

View File

@ -3,12 +3,13 @@
namespace SHADE namespace SHADE
{ {
// Used for attachment description creation for renderpass node // Used for attachment description creation for renderpass node
enum class SH_ATT_DESC_TYPE enum class SH_ATT_DESC_TYPE_FLAGS
{ {
COLOR, COLOR = 0x01,
COLOR_PRESENT, COLOR_PRESENT = 0x02,
DEPTH, DEPTH = 0x04,
STENCIL, STENCIL = 0x08,
DEPTH_STENCIL, DEPTH_STENCIL = 0x10,
INPUT = 0x20
}; };
} }

View File

@ -8,10 +8,17 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h"
namespace SHADE namespace SHADE
{ {
SHRenderGraph::ResourceInstruction::ResourceInstruction(char const* resourceName, bool dontClearOnLoad /*= false*/) noexcept
: resourceName{ resourceName }
, dontClearOnLoad{ dontClearOnLoad }
{
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -40,7 +47,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
{ {
// If we set to // If we set to
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
@ -50,7 +57,7 @@ namespace SHADE
format = swapchainHdl->GetSurfaceFormatKHR().format; format = swapchainHdl->GetSurfaceFormatKHR().format;
} }
graphResources.try_emplace(resourceName, resourceManager.Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, type, format, w, h, levels, createFlags)); graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
} }
/***************************************************************************/ /***************************************************************************/
@ -82,7 +89,7 @@ namespace SHADE
{ {
for (auto& color : subpass->colorReferences) for (auto& color : subpass->colorReferences)
{ {
if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else else
resourceAttLayouts[color.attachment] = color.layout; resourceAttLayouts[color.attachment] = color.layout;
@ -95,11 +102,11 @@ namespace SHADE
resourceAttLayouts[input.attachment] = input.layout; resourceAttLayouts[input.attachment] = input.layout;
} }
for (uint32_t i = 0; i < node->attachmentDescriptions.size(); ++i) for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
{ {
auto& att = node->attachmentDescriptions[i]; auto& att = node->attachmentDescriptions[j];
att.initialLayout = vk::ImageLayout::eUndefined; att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[i]; att.finalLayout = resourceAttLayouts[j];
} }
++i; ++i;
} }
@ -210,10 +217,18 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
auto resource = node->attResources[inputAtt.attachment]; auto resource = node->attResources[inputAtt.attachment];
if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::INPUT))
colorRead |= (1 << i); {
else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR) ||
depthRead |= (1 << i); resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
colorRead |= (1 << i);
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL))
depthRead |= (1 << i);
}
else
{
SHLOG_ERROR("While configuring subpass, an input reference was detected but the resource to be used is not marked as SH_ATT_DESC_TYPE_FLAGS::INPUT. ");
}
} }
++i; ++i;
@ -350,10 +365,9 @@ namespace SHADE
, swapchainHdl{ } , swapchainHdl{ }
, nodes{} , nodes{}
, graphResources{} , graphResources{}
, resourceManager{} , resourceManager{nullptr}
{ {
resourceManager = std::make_shared<ResourceManager>();
} }
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
@ -400,7 +414,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHRenderGraphNode> SHRenderGraph::AddNode(std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept SHADE::Handle<SHADE::SHRenderGraphNode> SHRenderGraph::AddNode(std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept
{ {
if (nodeIndexing.contains(nodeName)) if (nodeIndexing.contains(nodeName))
{ {
@ -408,12 +422,19 @@ namespace SHADE
return {}; return {};
} }
std::vector<Handle<SHRenderGraphResource>> resources; std::vector<SHAttachmentDescInitParams> descInitParams;
for (auto const& name : resourceNames) for (auto const& instruction : resourceInstruction)
{ {
// If the resource that the new node is requesting for exists, allow the graph to reference it // If the resource that the new node is requesting for exists, allow the graph to reference it
if (graphResources.contains(name)) if (graphResources.contains(instruction.resourceName))
resources.push_back(graphResources.at(name)); {
descInitParams.push_back(
{
.resourceHdl = graphResources.at(instruction.resourceName),
.dontClearOnLoad = false,
}
);
}
else else
{ {
SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node."); SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node.");
@ -435,7 +456,7 @@ namespace SHADE
} }
} }
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources)); nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(descInitParams), std::move(predecessors), &graphResources));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u); nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]); return nodes.at(nodeIndexing[nodeName]);
} }
@ -498,4 +519,13 @@ namespace SHADE
} }
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
{
if (graphResources.contains(resourceName))
{
return graphResources.at(resourceName);
}
return {};
}
} }

View File

@ -16,6 +16,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <memory>
namespace SHADE namespace SHADE
{ {
@ -33,7 +34,17 @@ namespace SHADE
class SH_API SHRenderGraph class SH_API SHRenderGraph
{ {
public:
struct ResourceInstruction
{
std::string resourceName;
bool dontClearOnLoad;
ResourceInstruction (char const* resourceName, bool dontClearOnLoad = false) noexcept;
};
private: private:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -60,7 +71,7 @@ namespace SHADE
std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources; std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
//! Resource library for graph handles //! Resource library for graph handles
ResourceManager resourceManager; std::shared_ptr<ResourceManager> resourceManager;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -74,18 +85,20 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept; void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept; void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept; Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
Handle<SHRenderGraphResource> GetRenderGraphResource (std::string const& resourceName) const noexcept;
}; };
} }

View File

@ -42,7 +42,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j) for (uint32_t j = 0; j < attResources.size(); ++j)
{ {
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0; uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
imageViews[j] = attResources[j]->imageViews[imageViewIndex]; imageViews[j] = attResources[j]->imageViews[imageViewIndex];
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -69,7 +69,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j) for (uint32_t j = 0; j < attResources.size(); ++j)
{ {
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0; uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
imageViews[j] = attResources[j]->imageViews[imageViewIndex]; imageViews[j] = attResources[j]->imageViews[imageViewIndex];
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's // We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -104,14 +104,14 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<ResourceManager> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
: logicalDeviceHdl{ logicalDevice } : logicalDeviceHdl{ logicalDevice }
, renderpass{} , renderpass{}
, framebuffers{} , framebuffers{}
, prereqNodes{ std::move(predecessors) } , prereqNodes{ std::move(predecessors) }
, attachmentDescriptions{} , attachmentDescriptions{}
, resourceAttachmentMapping{} , resourceAttachmentMapping{}
, attResources{ std::move(attRes) } , attResources{ }
, subpasses{} , subpasses{}
, executed{ false } , executed{ false }
, configured{ false } , configured{ false }
@ -121,6 +121,12 @@ namespace SHADE
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(logicalDeviceHdl); pipelineLibrary.Init(logicalDeviceHdl);
// Store all the handles to resources
attResources.reserve (attDescInitParams.size());
for (auto& param : attDescInitParams)
attResources.push_back(param.resourceHdl);
// We have as many descriptions as we have resources
attachmentDescriptions.resize(attResources.size()); attachmentDescriptions.resize(attResources.size());
bool containsSwapchainImage = false; bool containsSwapchainImage = false;
@ -140,7 +146,7 @@ namespace SHADE
newDesc.format = attResources[i]->resourceFormat; newDesc.format = attResources[i]->resourceFormat;
if (attResources[i]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
containsSwapchainImage = true; containsSwapchainImage = true;
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i); resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
@ -156,7 +162,7 @@ namespace SHADE
} }
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
: resourceManager{ rhs.resourceManager } : resourceManager{ std::move (rhs.resourceManager) }
, logicalDeviceHdl{ rhs.logicalDeviceHdl } , logicalDeviceHdl{ rhs.logicalDeviceHdl }
, renderpass{ rhs.renderpass } , renderpass{ rhs.renderpass }
, framebuffers{ std::move(rhs.framebuffers) } , framebuffers{ std::move(rhs.framebuffers) }
@ -171,6 +177,8 @@ namespace SHADE
, ptrToResources{ rhs.ptrToResources } , ptrToResources{ rhs.ptrToResources }
, pipelineLibrary{ std::move(rhs.pipelineLibrary) } , pipelineLibrary{ std::move(rhs.pipelineLibrary) }
, batcher{ std::move(rhs.batcher) } , batcher{ std::move(rhs.batcher) }
, spDescs{ std::move(rhs.spDescs) }
, spDeps{ std::move(rhs.spDeps) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -181,7 +189,7 @@ namespace SHADE
if (&rhs == this) if (&rhs == this)
return *this; return *this;
resourceManager = rhs.resourceManager; resourceManager = std::move(rhs.resourceManager);
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
renderpass = rhs.renderpass; renderpass = rhs.renderpass;
framebuffers = std::move(rhs.framebuffers); framebuffers = std::move(rhs.framebuffers);
@ -194,6 +202,9 @@ namespace SHADE
ptrToResources = std::move(rhs.ptrToResources); ptrToResources = std::move(rhs.ptrToResources);
pipelineLibrary = std::move(rhs.pipelineLibrary); pipelineLibrary = std::move(rhs.pipelineLibrary);
batcher = std::move(rhs.batcher); batcher = std::move(rhs.batcher);
spDescs = std::move(rhs.spDescs);
spDeps = std::move(rhs.spDeps);
rhs.renderpass = {}; rhs.renderpass = {};
@ -224,10 +235,10 @@ namespace SHADE
} }
// Add subpass to container and create mapping for it // Add subpass to container and create mapping for it
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(resourceManager); subpass->Init(*resourceManager);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -261,6 +272,7 @@ namespace SHADE
return {}; return {};
} }
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair); Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
if (!pipeline) if (!pipeline)
{ {
@ -301,4 +313,12 @@ namespace SHADE
return subpasses[subpassIndexing.at(subpassName.data())]; return subpasses[subpassIndexing.at(subpassName.data())];
} }
Handle<SHRenderGraphResource> SHRenderGraphNode::GetResource(uint32_t resourceIndex) const noexcept
{
if (resourceIndex < attResources.size())
return attResources[resourceIndex];
else
return {};
}
} }

View File

@ -9,6 +9,7 @@
#include "SH_API.h" #include "SH_API.h"
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h" #include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
#include "Graphics/MiddleEnd/Batching/SHBatcher.h" #include "Graphics/MiddleEnd/Batching/SHBatcher.h"
#include "SHAttachmentDescInitParams.h"
namespace SHADE namespace SHADE
{ {
@ -25,7 +26,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
ResourceManager& resourceManager; std::shared_ptr<ResourceManager> resourceManager;
//! For Vulkan object creation //! For Vulkan object creation
Handle<SHVkLogicalDevice> logicalDeviceHdl; Handle<SHVkLogicalDevice> logicalDeviceHdl;
@ -87,7 +88,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept; SHRenderGraphNode(std::shared_ptr<ResourceManager> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
@ -105,6 +106,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept; Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept; Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
}; };

View File

@ -3,6 +3,8 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -43,10 +45,10 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: logicalDevice {logicalDevice} : logicalDevice {logicalDevice}
, swapchain{ swapchain } , swapchain{ swapchain }
, resourceType{ type } , resourceTypeFlags{ }
, resourceFormat{ format } , resourceFormat{ format }
, images{} , images{}
, imageViews{} , imageViews{}
@ -56,52 +58,10 @@ namespace SHADE
, resourceName{ name } , resourceName{ name }
{ {
// If the resource type is an arbitrary image and not swapchain image // If the resource type is an arbitrary image and not swapchain image
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT) if (typeFlags.size() == 1 && *typeFlags.begin() == SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)
{ {
imageAspectFlags = vk::ImageAspectFlags{}; resourceTypeFlags |= static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT);
usage = {};
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType)
{
case SH_ATT_DESC_TYPE::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break;
case SH_ATT_DESC_TYPE::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break;
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break;
}
// The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
// just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
}
else // if swapchain image resource
{
// Prepare image view details // Prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
{ {
@ -124,6 +84,65 @@ namespace SHADE
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails); imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
} }
} }
else // if swapchain image resource
{
imageAspectFlags = vk::ImageAspectFlags{};
usage = usageFlags;
for (auto& type : typeFlags)
{
// store the flags
resourceTypeFlags |= static_cast<uint32_t>(type);
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (type)
{
case SH_ATT_DESC_TYPE_FLAGS::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::INPUT:
usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
{
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
return;
}
}
}
// The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
// just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
}
} }
/***************************************************************************/ /***************************************************************************/
@ -139,7 +158,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
: resourceName{ std::move(rhs.resourceName) } : resourceName{ std::move(rhs.resourceName) }
, resourceType{ std::move(rhs.resourceType) } , resourceTypeFlags{ std::move(rhs.resourceTypeFlags) }
, images{ std::move(rhs.images) } , images{ std::move(rhs.images) }
, imageViews{ std::move(rhs.imageViews) } , imageViews{ std::move(rhs.imageViews) }
, resourceFormat{ std::move(rhs.resourceFormat) } , resourceFormat{ std::move(rhs.resourceFormat) }
@ -147,6 +166,7 @@ namespace SHADE
, height{ rhs.height } , height{ rhs.height }
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags } , imageAspectFlags{ rhs.imageAspectFlags }
, swapchain {rhs.swapchain}
{ {
} }
@ -170,7 +190,7 @@ namespace SHADE
return *this; return *this;
resourceName = std::move(rhs.resourceName); resourceName = std::move(rhs.resourceName);
resourceType = std::move(rhs.resourceType); resourceTypeFlags = std::move(rhs.resourceTypeFlags);
images = std::move(rhs.images); images = std::move(rhs.images);
imageViews = std::move(rhs.imageViews); imageViews = std::move(rhs.imageViews);
resourceFormat = std::move(rhs.resourceFormat); resourceFormat = std::move(rhs.resourceFormat);
@ -178,6 +198,7 @@ namespace SHADE
height = rhs.height; height = rhs.height;
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags; imageAspectFlags = rhs.imageAspectFlags;
swapchain = rhs.swapchain;
return *this; return *this;
} }
@ -200,7 +221,7 @@ namespace SHADE
width = newWidth; width = newWidth;
height = newHeight; height = newHeight;
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT) if ((resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0)
{ {
// prepare image view details // prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -242,4 +263,64 @@ namespace SHADE
} }
} }
void SHRenderGraphResource::TransitionImage(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, Handle<SHVkCommandBuffer> commandBuffer, vk::PipelineStageFlagBits srcStage, vk::PipelineStageFlagBits dstStage, uint32_t frameIndex) noexcept
{
vk::ImageMemoryBarrier barrier;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = images[frameIndex]->GetVkImage(),
barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format.
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1; // always 1 since we wont have array of images for attachments
commandBuffer->PipelineBarrier(srcStage, dstStage, {}, {}, {}, {barrier});
}
void SHRenderGraphResource::CopyToBuffer(Handle<SHVkBuffer> dstBuffer, Handle<SHVkCommandBuffer> commandBuffer, uint32_t frameIndex) const noexcept
{
vk::ImageSubresourceLayers subResource
{
.aspectMask = SHVkUtil::IsDepthOnlyFormat(resourceFormat) ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1
};
vk::BufferImageCopy region
{
.bufferOffset = 0,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource = subResource,
.imageOffset = vk::Offset3D {0,0,0},
.imageExtent = vk::Extent3D {width, height, 1}
};
commandBuffer->CopyImageToBuffer(images[frameIndex]->GetVkImage(), dstBuffer->GetVkBuffer(), {region});
}
vk::Format SHRenderGraphResource::GetResourceFormat(void) const noexcept
{
return resourceFormat;
}
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
{
return width;
}
uint32_t SHRenderGraphResource::GetHeight(void) const noexcept
{
return height;
}
Handle<SHVkImageView> SHRenderGraphResource::GetImageView(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
{
return imageViews [index];
}
} }

View File

@ -13,6 +13,10 @@ namespace SHADE
class SHVkImageView; class SHVkImageView;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkSwapchain; class SHVkSwapchain;
class SHVkCommandBuffer;
class SHVkBuffer;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
class SH_API SHRenderGraphResource class SH_API SHRenderGraphResource
{ {
@ -30,7 +34,7 @@ namespace SHADE
std::string resourceName; std::string resourceName;
//! Used for initializing image layouts //! Used for initializing image layouts
SH_ATT_DESC_TYPE resourceType; SHRenderGraphResourceFlags resourceTypeFlags;
//! The resource itself (this is a vector because if the resource happens //! The resource itself (this is a vector because if the resource happens
//! to be a swapchain image, then we need however many frames in flight). //! to be a swapchain image, then we need however many frames in flight).
@ -65,12 +69,25 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept; SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
void TransitionImage(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, Handle<SHVkCommandBuffer> commandBuffer, vk::PipelineStageFlagBits srcStage, vk::PipelineStageFlagBits dstStage, uint32_t frameIndex) noexcept;
void CopyToBuffer (Handle<SHVkBuffer> dstBuffer, Handle<SHVkCommandBuffer> commandBuffer, uint32_t frameIndex = 0) const noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Format GetResourceFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept;
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;

View File

@ -2,6 +2,8 @@
#include "SHSubpass.h" #include "SHSubpass.h"
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h" #include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "SHRenderGraphNode.h"
#include "SHRenderGraphResource.h"
namespace SHADE namespace SHADE
{ {
@ -21,7 +23,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHSubpass::SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
: resourceAttachmentMapping{ mapping } : resourceAttachmentMapping{ mapping }
, ptrToResources{ resources } , ptrToResources{ resources }
, parentNode{ parent } , parentNode{ parent }
@ -53,6 +55,8 @@ namespace SHADE
, inputReferences{ std::move(rhs.inputReferences) } , inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping } , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, ptrToResources{ rhs.ptrToResources } , ptrToResources{ rhs.ptrToResources }
, descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) }
{ {
} }
@ -81,6 +85,8 @@ namespace SHADE
inputReferences = std::move(rhs.inputReferences); inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping; resourceAttachmentMapping = rhs.resourceAttachmentMapping;
ptrToResources = rhs.ptrToResources; ptrToResources = rhs.ptrToResources;
descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
return *this; return *this;
} }
@ -118,18 +124,18 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType) noexcept
{ {
vk::ImageLayout imageLayout; vk::ImageLayout imageLayout;
switch (attachmentDescriptionType) switch (attachmentDescriptionType)
{ {
case SH_ATT_DESC_TYPE::DEPTH: case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal; imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
break; break;
case SH_ATT_DESC_TYPE::STENCIL: case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal; imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
break; break;
case SH_ATT_DESC_TYPE::DEPTH_STENCIL: case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
break; break;
default: default:
@ -207,4 +213,15 @@ namespace SHADE
{ {
return superBatch; return superBatch;
} }
std::vector<vk::AttachmentReference> const& SHSubpass::GetColorAttachmentReferences(void) const noexcept
{
return colorReferences;
}
vk::Format SHSubpass::GetFormatFromAttachmentReference(uint32_t attachmentReference) const noexcept
{
return parentNode->GetResource(attachmentReference)->GetResourceFormat();
}
} }

View File

@ -62,7 +62,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept; SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -71,7 +71,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Preparation functions // Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept; void AddColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept; void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddInput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept;
// Runtime functions // Runtime functions
@ -86,7 +86,8 @@ namespace SHADE
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept; Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
SHSubPassIndex GetIndex() const noexcept; SHSubPassIndex GetIndex() const noexcept;
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept; Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
std::vector<vk::AttachmentReference> const& GetColorAttachmentReferences (void) const noexcept;
vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;

View File

@ -253,7 +253,8 @@ namespace SHADE
SHVkRenderpass::~SHVkRenderpass(void) noexcept SHVkRenderpass::~SHVkRenderpass(void) noexcept
{ {
logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr); if (vkRenderpass)
logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr);
} }

View File

@ -23,6 +23,38 @@ namespace SHADE
IsDepthOnlyFormat(format); IsDepthOnlyFormat(format);
} }
bool SHVkUtil::IsBlendCompatible(vk::Format format) noexcept
{
// TODO: Update with all formats
switch (format)
{
case vk::Format::eR32Sint:
case vk::Format::eR32G32Sint:
case vk::Format::eR32G32B32Sint:
case vk::Format::eR32G32B32A32Sint:
return false;
case vk::Format::eR32Sfloat:
case vk::Format::eR32G32Sfloat:
case vk::Format::eR32G32B32Sfloat:
case vk::Format::eR32G32B32A32Sfloat:
return true;
}
return false;
}
uint32_t SHVkUtil::GetBytesPerPixelFromFormat(vk::Format format) noexcept
{
// TODO: Update with all formats
switch (format)
{
case vk::Format::eR32Sint:
case vk::Format::eR32Uint:
case vk::Format::eR32Sfloat:
return 4;
}
return 0;
}
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{ {
if (bufferHandle) if (bufferHandle)

View File

@ -20,8 +20,11 @@ namespace SHADE
class SHVkUtil class SHVkUtil
{ {
public: public:
static bool IsDepthOnlyFormat (vk::Format format) noexcept; static bool IsDepthOnlyFormat (vk::Format format) noexcept;
static bool IsDepthStencilAttachment(vk::Format format) noexcept; static bool IsDepthStencilAttachment (vk::Format format) noexcept;
static bool IsBlendCompatible (vk::Format format) noexcept;
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
/***********************************************************************************/ /***********************************************************************************/
/*! /*!

View File

@ -12,6 +12,7 @@ namespace SHADE
using BindingAndSetHash = uint64_t; using BindingAndSetHash = uint64_t;
using SetIndex = uint32_t; using SetIndex = uint32_t;
using SHSubPassIndex = uint32_t; using SHSubPassIndex = uint32_t;
using SHRenderGraphResourceFlags = uint32_t;
} }

View File

@ -44,6 +44,9 @@ namespace SHADE
void SHInputManager::UpdateInput(double dt) noexcept void SHInputManager::UpdateInput(double dt) noexcept
{ {
//Keyboard and Mouse Buttons//////////////////////////////////////////////// //Keyboard and Mouse Buttons////////////////////////////////////////////////
//Write to lastKeys
memcpy(keysLast, keys, sizeof(keys));
//Poll //Poll
unsigned char keyboardState[MAX_KEYS]; unsigned char keyboardState[MAX_KEYS];
//if (GetKeyboardState(keyboardState) == false) return; //if (GetKeyboardState(keyboardState) == false) return;
@ -96,9 +99,6 @@ namespace SHADE
} }
} }
//Write to lastKeys
memcpy(keysLast, keys, sizeof(keys));
//Mouse Positioning///////////////////////////////////// //Mouse Positioning/////////////////////////////////////
//https://stackoverflow.com/a/6423739 //https://stackoverflow.com/a/6423739

View File

@ -95,12 +95,12 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
const SHVec3& SHBoundingBox::GetCenter() const noexcept SHVec3 SHBoundingBox::GetCenter() const noexcept
{ {
return Center; return Center;
} }
const SHVec3& SHBoundingBox::GetHalfExtents() const noexcept SHVec3 SHBoundingBox::GetHalfExtents() const noexcept
{ {
return Extents; return Extents;
} }

View File

@ -54,8 +54,8 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] const SHVec3& GetCenter () const noexcept; [[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodsicard]] const SHVec3& GetHalfExtents() const noexcept; [[nodiscard]] SHVec3 GetHalfExtents() const noexcept;
[[nodiscard]] SHVec3 GetMin () const noexcept; [[nodiscard]] SHVec3 GetMin () const noexcept;
[[nodiscard]] SHVec3 GetMax () const noexcept; [[nodiscard]] SHVec3 GetMax () const noexcept;
[[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept; [[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept;

View File

@ -94,7 +94,7 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
const SHVec3& SHBoundingSphere::GetCenter() const noexcept SHVec3 SHBoundingSphere::GetCenter() const noexcept
{ {
return Center; return Center;
} }

View File

@ -48,8 +48,8 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] const SHVec3& GetCenter () const noexcept; [[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] float GetRadius () const noexcept; [[nodiscard]] float GetRadius () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */

View File

@ -12,7 +12,6 @@
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "Math/Transform/SHTransform.h"
#include "Math/SHRay.h" #include "Math/SHRay.h"

View File

@ -67,6 +67,19 @@ namespace SHADE
XMStoreFloat4(this, XMQuaternionRotationMatrix(M)); XMStoreFloat4(this, XMQuaternionRotationMatrix(M));
} }
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{
const SHVec3& SHADE_VEC{ rp3dEuler };
const XMVECTOR V = XMLoadFloat3(&SHADE_VEC);
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
}
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
: XMFLOAT4( rp3dQuat.x, rp3dQuat.y, rp3dQuat.z, rp3dQuat.w )
{}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */ /* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -176,6 +189,16 @@ namespace SHADE
return XMQuaternionNotEqual(Q1, Q2); return XMQuaternionNotEqual(Q1, Q2);
} }
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
{
return reactphysics3d::Quaternion{ x, y, z, w };
}
SHQuaternion::operator reactphysics3d::Vector3() const noexcept
{
return reactphysics3d::Vector3{ ToEuler() };
}
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
{ {
return rhs * lhs; return rhs * lhs;

View File

@ -11,6 +11,8 @@
#pragma once #pragma once
#include <DirectXMath.h> #include <DirectXMath.h>
#include <reactphysics3d/mathematics/Quaternion.h>
#include <string> #include <string>
// Project Headers // Project Headers
@ -46,12 +48,17 @@ namespace SHADE
SHQuaternion (const SHQuaternion& rhs) = default; SHQuaternion (const SHQuaternion& rhs) = default;
SHQuaternion (SHQuaternion&& rhs) = default; SHQuaternion (SHQuaternion&& rhs) = default;
SHQuaternion () noexcept; SHQuaternion () noexcept;
SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept;
SHQuaternion (float yaw, float pitch, float roll) noexcept; SHQuaternion (float yaw, float pitch, float roll) noexcept;
SHQuaternion (const SHVec3& eulerAngles) noexcept; SHQuaternion (const SHVec3& eulerAngles) noexcept;
SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; SHQuaternion (const SHVec3& axis, float angleInRad) noexcept;
SHQuaternion (const SHMatrix& rotationMatrix) noexcept; SHQuaternion (const SHMatrix& rotationMatrix) noexcept;
// Conversion from other math types
SHQuaternion (const reactphysics3d::Vector3& rp3dEuler) noexcept;
SHQuaternion (const reactphysics3d::Quaternion& rp3dQuat) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
@ -76,6 +83,11 @@ namespace SHADE
[[nodiscard]] bool operator== (const SHQuaternion& rhs) const noexcept; [[nodiscard]] bool operator== (const SHQuaternion& rhs) const noexcept;
[[nodiscard]] bool operator!= (const SHQuaternion& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHQuaternion& rhs) const noexcept;
// Conversion to other math types used by SHADE
operator reactphysics3d::Quaternion () const noexcept;
operator reactphysics3d::Vector3 () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -50,6 +50,10 @@ namespace SHADE
: XMFLOAT2( _x, _y ) : XMFLOAT2( _x, _y )
{} {}
SHVec2::SHVec2(const reactphysics3d::Vector2& rp3dVec2) noexcept
: XMFLOAT2( rp3dVec2.x, rp3dVec2.y )
{}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */ /* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -200,6 +204,11 @@ namespace SHADE
} }
} }
SHVec2::operator reactphysics3d::Vector2() const noexcept
{
return reactphysics3d::Vector2{ x, y };
}
SHVec2 operator* (float lhs, const SHVec2& rhs) noexcept SHVec2 operator* (float lhs, const SHVec2& rhs) noexcept
{ {
SHVec2 result; SHVec2 result;

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