Merge branch 'Rendering-Camera-Integration' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-10-23 16:36:32 +08:00
commit 6d2affcbb9
107 changed files with 4372 additions and 527 deletions

Binary file not shown.

View File

@ -1,16 +1,16 @@
[Window][MainStatusBar] [Window][MainStatusBar]
Pos=0,1367 Pos=0,1060
Size=3440,20 Size=1920,20
Collapsed=0 Collapsed=0
[Window][SHEditorMenuBar] [Window][SHEditorMenuBar]
Pos=0,48 Pos=0,48
Size=3440,1319 Size=1920,1012
Collapsed=0 Collapsed=0
[Window][Hierarchy Panel] [Window][Hierarchy Panel]
Pos=0,170 Pos=0,142
Size=646,1197 Size=387,918
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@ -20,14 +20,14 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=3169,48 Pos=1649,48
Size=271,1319 Size=271,1012
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Profiler] [Window][Profiler]
Pos=0,48 Pos=0,48
Size=646,120 Size=387,92
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
@ -37,12 +37,18 @@ Size=2519,1319
Collapsed=0 Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
[Window][ Viewport]
Pos=389,48
Size=1258,1012
Collapsed=0
DockId=0x00000002,0
[Docking][Data] [Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=3440,1319 Split=X 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=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=646,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=999,1036 CentralNode=1 Selected=0x13926F0B DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

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

@ -93,6 +93,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>(); SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
#ifdef SHEDITOR #ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>(); SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
@ -149,11 +150,10 @@ namespace Sandbox
SHSceneManager::SceneUpdate(0.016f); SHSceneManager::SceneUpdate(0.016f);
#endif #endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f); SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking(); //editor->PollPicking();
} }
// Finish all graphics jobs first // Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution(); graphicsSystem->AwaitGraphicsExecution();
} }

View File

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

View File

@ -62,7 +62,12 @@ namespace SHADE
} }
} }
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept void SHAssetManager::Unload(AssetID assetId) noexcept
{
// TODO
}
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
{ {
if (!IsRecognised(path.extension().string().c_str())) if (!IsRecognised(path.extension().string().c_str()))
{ {

View File

@ -32,6 +32,7 @@ namespace SHADE
* \brief Deallocate all memory used by resource data * \brief Deallocate all memory used by resource data
****************************************************************************/ ****************************************************************************/
static void Unload() noexcept; static void Unload() noexcept;
static void Unload(AssetID assetId) noexcept;
/**************************************************************************** /****************************************************************************
* \brief Load all resources that are in the folder * \brief Load all resources that are in the folder

View File

@ -1,13 +1,15 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "SHCameraSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE namespace SHADE
{ {
SHCameraComponent::SHCameraComponent() SHCameraComponent::SHCameraComponent()
:yaw(0.0f), pitch(0.0f), roll(0.0f) :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(1.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) , perspProj(true), dirtyView(true), dirtyProj(true)
, viewMatrix(), projMatrix() , viewMatrix(), projMatrix()
, position() , position()
@ -22,33 +24,69 @@ namespace SHADE
void SHCameraComponent::SetYaw(float yaw) noexcept void SHCameraComponent::SetYaw(float yaw) noexcept
{ {
this->yaw = yaw; this->yaw = yaw;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{rotation.x,yaw, rotation.z});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPitch(float pitch) noexcept void SHCameraComponent::SetPitch(float pitch) noexcept
{ {
this->pitch = pitch; this->pitch = pitch;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ pitch,rotation.y, rotation.z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetRoll(float roll) noexcept void SHCameraComponent::SetRoll(float roll) noexcept
{ {
this->roll = roll; this->roll = roll;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, roll});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionX(float x) noexcept void SHCameraComponent::SetPositionX(float x) noexcept
{ {
position.x = x; position.x = x;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,position.y, position.z});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionY(float y) noexcept void SHCameraComponent::SetPositionY(float y) noexcept
{ {
position.y = y; position.y = y;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,y, position.z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionZ(float z) noexcept void SHCameraComponent::SetPositionZ(float z) noexcept
{ {
position.z = z; position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,position.y, z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPosition(float x,float y, float z) noexcept void SHCameraComponent::SetPosition(float x,float y, float z) noexcept
@ -56,11 +94,23 @@ namespace SHADE
position.x = x; position.x = x;
position.y = y; position.y = y;
position.z = z; position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,y, z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
{ {
this->position = pos; this->position = pos;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(pos);
}
dirtyView = true; dirtyView = true;
} }
@ -128,4 +178,12 @@ namespace SHADE
return projMatrix; return projMatrix;
} }
void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->GetDirector(directorCameraIndex)->SetMainCamera(*this);
}
} }

View File

@ -70,6 +70,8 @@ namespace SHADE
const SHMatrix& GetViewMatrix() const noexcept; const SHMatrix& GetViewMatrix() const noexcept;
const SHMatrix& GetProjMatrix() const noexcept; const SHMatrix& GetProjMatrix() const noexcept;
void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
float movementSpeed; float movementSpeed;
SHVec3 turnSpeed; SHVec3 turnSpeed;

View File

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

View File

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

View File

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

View File

@ -3,9 +3,10 @@
#include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystem.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/SHResourceLibrary.h"
#include "SHCameraDirector.h"
#include "SH_API.h" #include "SH_API.h"
namespace SHADE namespace SHADE
{ {
class SH_API SHCameraSystem final : public SHSystem class SH_API SHCameraSystem final : public SHSystem
@ -14,8 +15,9 @@ namespace SHADE
//A camera component that represents editor camera. //A camera component that represents editor camera.
//This is not tied to any entity. Hence this EID should not be used. //This is not tied to any entity. Hence this EID should not be used.
SHCameraComponent editorCamera; SHCameraComponent editorCamera;
SHResourceLibrary<SHCameraDirector> directorLibrary;
std::vector<DirectorHandle> directorHandleList;
public: public:
SHCameraSystem(void) = default; SHCameraSystem(void) = default;
@ -34,12 +36,27 @@ namespace SHADE
}; };
friend class EditorCameraUpdate; friend class EditorCameraUpdate;
SHCameraComponent* GetEditorCamera (void) noexcept; class SH_API CameraSystemUpdate final: public SHSystemRoutine
{
public:
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {};
virtual void Execute(double dt)noexcept override final;
};
friend class CameraSystemUpdate;
SHCameraComponent* GetEditorCamera (void) noexcept;
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
DirectorHandle CreateDirector() noexcept;
DirectorHandle GetDirector(size_t index) noexcept;
void ClampCameraRotation(SHCameraComponent& camera) noexcept;
void UpdateEditorCamera(double dt) noexcept;
protected: protected:
void UpdateCameraComponent(SHCameraComponent& camera) noexcept; void UpdateCameraComponent(SHCameraComponent& camera) 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

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#include <imgui.h> #include <imgui.h>
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include "Tools/SHClipboardUtilities.h"
namespace SHADE namespace SHADE
@ -52,6 +53,7 @@ namespace SHADE
if(const auto root = sceneGraph.GetRoot()) if(const auto root = sceneGraph.GetRoot())
{ {
auto const& children = root->GetChildren(); auto const& children = root->GetChildren();
for (const auto child : children) for (const auto child : children)
{ {
RecursivelyDrawEntityNode(child); RecursivelyDrawEntityNode(child);
@ -79,6 +81,8 @@ namespace SHADE
void SHHierarchyPanel::SetScrollTo(EntityID eid) void SHHierarchyPanel::SetScrollTo(EntityID eid)
{ {
if(eid == MAX_EID)
return;
scrollTo = eid; scrollTo = eid;
} }
@ -104,7 +108,7 @@ namespace SHADE
} }
if (ImGui::SmallButton(ICON_MD_ADD_CIRCLE)) if (ImGui::SmallButton(ICON_MD_ADD_CIRCLE))
{ {
SHEntityManager::CreateEntity(); SHCommandManager::PerformCommand(std::make_shared<SHCreateEntityCommand>());
} }
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
@ -144,23 +148,32 @@ namespace SHADE
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID()); auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
//Draw Node //Draw Node
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str()); bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//Check For Begin Drag //Check For Begin Drag
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
ImGui::Text("Moving EID: %zu", eid); std::string moveLabel = "Moving EID: ";
SHDragDrop::SetPayload<EntityID>(DRAG_EID, &eid); if(!isSelected)
editor->selectedEntities.push_back(eid);
for(int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
{
moveLabel.append(std::to_string(editor->selectedEntities[i]));
if(i + 1 < static_cast<int>(editor->selectedEntities.size()))
{
moveLabel.append(", ");
}
}
ImGui::Text(moveLabel.c_str());
SHDragDrop::SetPayload<std::vector<EntityID>>(DRAG_EID, &editor->selectedEntities);
SHDragDrop::EndSource(); SHDragDrop::EndSource();
} }
else if (SHDragDrop::BeginTarget()) //If Received DragDrop else if (SHDragDrop::BeginTarget()) //If Received DragDrop
{ {
if (const EntityID* eidPayload = SHDragDrop::AcceptPayload<EntityID>(DRAG_EID)) //If payload is valid if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(DRAG_EID)) //If payload is valid
{ {
EntityID const dropEID = *eidPayload; ParentSelectedEntities(eid);
if(!sceneGraph.GetChild(dropEID, eid))
sceneGraph.SetParent(dropEID, eid); //Set dropEID parent to eid (belonging to current Node)
SHDragDrop::EndTarget(); SHDragDrop::EndTarget();
} }
} }
@ -175,7 +188,15 @@ namespace SHADE
} }
if(ImGui::Selectable("Copy")) if(ImGui::Selectable("Copy"))
{ {
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities)) SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
}
if(ImGui::Selectable("Paste"))
{
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
}
if(ImGui::Selectable("Paste as Child"))
{
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
} }
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{ {
@ -184,7 +205,7 @@ namespace SHADE
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data())) if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
{ {
sceneGraph.SetParent(currentNode->GetEntityID(), nullptr); ParentSelectedEntities(MAX_EID);
} }
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -196,7 +217,15 @@ namespace SHADE
{ {
if (!isSelected) if (!isSelected)
{ {
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) if(ImGui::IsKeyDown(ImGuiKey_LeftShift))
{
if(editor->selectedEntities.size() >= 1)
{
SelectRangeOfEntities(editor->selectedEntities[0], eid);
}
else editor->selectedEntities.clear();
}
else if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
editor->selectedEntities.clear(); editor->selectedEntities.clear();
editor->selectedEntities.push_back(eid); editor->selectedEntities.push_back(eid);
}//if not selected }//if not selected
@ -243,4 +272,90 @@ namespace SHADE
{ {
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID); SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
} }
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID) const noexcept
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData;
std::vector<EntityID> parentedEIDS;
for(auto const& eid : editor->selectedEntities)
{
if(sceneGraph.GetChild(eid, parentEID) == nullptr)
{
parentedEIDS.push_back(eid);
if(auto parent = sceneGraph.GetParent(eid))
entityParentData[eid].oldParentEID = parent->GetEntityID();
entityParentData[eid].newParentEID = parentEID;
}
}
SHCommandManager::PerformCommand(std::make_shared<SHEntityParentCommand>(parentedEIDS, entityParentData));
}
void SHHierarchyPanel::SelectRangeOfEntities(EntityID beginEID, EntityID endEID)
{
bool startSelecting = false; bool endSelecting = false;
auto const editor = SHSystemManager::GetSystem<SHEditor>();
editor->selectedEntities.clear();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
sceneGraph.Traverse([&](SHSceneNode* nodePtr)
{
auto eid = nodePtr->GetEntityID();
if(!startSelecting)
{
if(eid == beginEID || eid == endEID)
{
startSelecting = true;
editor->selectedEntities.push_back(eid);
}
}
else
{
if(!endSelecting)
{
editor->selectedEntities.push_back(eid);
if(eid == endEID || eid == beginEID)
{
endSelecting = true;
}
}
}
});
}
void SHCreateEntityCommand::Execute()
{
EntityID newEID = SHEntityManager::CreateEntity(eid);
if(eid == MAX_EID)
eid = newEID;
}
void SHCreateEntityCommand::Undo()
{
SHEntityManager::DestroyEntity(eid);
}
void SHEntityParentCommand::Execute()
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for(auto const& eid : entities)
{
if(entityParentData[eid].newParentEID == MAX_EID)
sceneGraph.SetParent(eid, nullptr);
else
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
}
}
void SHEntityParentCommand::Undo()
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for(auto const& eid : entities)
{
if(entityParentData[eid].oldParentEID == MAX_EID)
sceneGraph.SetParent(eid, nullptr);
else
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
}
}
}//namespace SHADE }//namespace SHADE

View File

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

View File

@ -10,6 +10,7 @@
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/IconsFontAwesome6.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 "Physics/Components/SHColliderComponent.h"
@ -216,7 +217,7 @@ namespace SHADE
if (collider.GetType() == SHCollider::Type::BOX) if (collider.GetType() == SHCollider::Type::BOX)
{ {
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_MD_VIEW_IN_AR, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
auto box = reinterpret_cast<SHBoundingBox*>(collider.GetShape()); 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);}); SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);});
} }

View File

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

View File

@ -3,6 +3,7 @@
#include <imgui.h> #include <imgui.h>
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/Command/SHCommandManager.h"
#include "FRC/SHFramerateController.h" #include "FRC/SHFramerateController.h"
namespace SHADE namespace SHADE
@ -38,6 +39,11 @@ namespace SHADE
{ {
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);
} }
if(ImGui::CollapsingHeader("Command Manager"))
{
ImGui::Text("Undo: %zu", SHCommandManager::GetUndoStackSize());
ImGui::Text("Redo: %zu", SHCommandManager::GetRedoStackSize());
}
ImGui::End(); ImGui::End();
} }

View File

@ -43,9 +43,12 @@ namespace SHADE
bool result = ImGui::Begin(windowName.data(), &isOpen, windowFlags); bool result = ImGui::Begin(windowName.data(), &isOpen, windowFlags);
auto wndSize = ImGui::GetWindowSize(); auto wndSize = ImGui::GetWindowSize();
if(windowSize.x != wndSize.x || windowSize.y != wndSize.y) auto contentRegionAvail = ImGui::GetContentRegionAvail();
if( beginContentRegionAvailable.x != contentRegionAvail.x || beginContentRegionAvailable.y != contentRegionAvail.y || windowSize.x != wndSize.x || windowSize.y != wndSize.y)
{ {
windowSize = {wndSize.x, wndSize.y}; windowSize = {wndSize.x, wndSize.y};
beginContentRegionAvailable = {contentRegionAvail.x, contentRegionAvail.y};
OnResize(); OnResize();
} }
auto wndPos = ImGui::GetWindowPos(); auto wndPos = ImGui::GetWindowPos();

View File

@ -26,6 +26,10 @@ namespace SHADE
bool isOpen; bool isOpen;
bool isWindowHovered; bool isWindowHovered;
std::string_view windowName; std::string_view windowName;
SHVec2 windowSize;
SHVec2 windowPos;
SHVec2 viewportMousePos;
SHVec2 beginContentRegionAvailable;
protected: protected:
virtual bool Begin(); virtual bool Begin();
virtual void OnResize(); virtual void OnResize();
@ -33,8 +37,6 @@ namespace SHADE
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

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

View File

@ -10,6 +10,7 @@
#include "imgui_internal.h" #include "imgui_internal.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h" #include "Editor/EditorWindow/SHEditorWindow.h"
#include "Editor/Gizmos/SHTransformGizmo.h"
namespace SHADE namespace SHADE
{ {
@ -20,10 +21,12 @@ namespace SHADE
void Init() override; void Init() override;
void Update() override; void Update() override;
void Exit() override; void Exit() override;
SHTransformGizmo transformGizmo;
protected: protected:
void OnResize() override; void OnResize() override;
void OnPosChange() override; void OnPosChange() override;
private: private:
void DrawMenuBar() const noexcept; void DrawMenuBar() noexcept;
SHVec2 beginCursorPos;
};//class SHEditorViewport };//class SHEditorViewport
}//namespace SHADE }//namespace SHADE

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "IconsMaterialDesign.h" #include "IconsMaterialDesign.h"
#include "IconsFontAwesome6.h"
#include "DragDrop/SHDragDrop.hpp" #include "DragDrop/SHDragDrop.hpp"
//#==============================================================# //#==============================================================#
@ -36,6 +37,7 @@
#include <imgui.h> #include <imgui.h>
#include <SDL.h> #include <SDL.h>
#include <rttr/registration> #include <rttr/registration>
#include <ImGuizmo.h>
//#==============================================================# //#==============================================================#
//|| ImGui Backend Includes || //|| ImGui Backend Includes ||
@ -87,10 +89,10 @@ namespace SHADE
//Add editor windows //Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>(); SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>(); SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>(); SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>(); SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
io = &ImGui::GetIO(); io = &ImGui::GetIO();
@ -98,7 +100,7 @@ namespace SHADE
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini"; io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini";
io->ConfigWindowsMoveFromTitleBarOnly = true;
InitLayout(); InitLayout();
InitFonts(); InitFonts();
@ -127,9 +129,13 @@ namespace SHADE
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{ {
if(window->isOpen) if(window->isOpen)
{
window->Update(); window->Update();
}
} }
PollPicking();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{ {
SHCommandManager::RedoCommand(); SHCommandManager::RedoCommand();
@ -165,10 +171,11 @@ namespace SHADE
{ {
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
constexpr ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f; 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 constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/fa-solid-900.ttf", 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path
constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_MD, 0 };
ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path
io->Fonts->Build(); io->Fonts->Build();
} }
@ -338,7 +345,7 @@ namespace SHADE
if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>()) if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
{ {
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>(); auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
if (viewportWindow->isWindowHovered && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) if (viewportWindow->isWindowHovered && !viewportWindow->transformGizmo.isManipulating && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{ {
EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity(); EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity();
if(pickedEID == MAX_EID) if(pickedEID == MAX_EID)
@ -366,6 +373,7 @@ namespace SHADE
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
ImGuizmo::BeginFrame();
} }

View File

@ -13,9 +13,11 @@
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "EditorWindow/SHEditorWindow.h" #include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Gizmos/SHTransformGizmo.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -200,5 +202,7 @@ namespace SHADE
SDL_Window* sdlWindow {nullptr}; SDL_Window* sdlWindow {nullptr};
ImGuiIO* io{nullptr}; ImGuiIO* io{nullptr};
//SHTransformGizmo transformGizmo;
};//class SHEditor };//class SHEditor
}//namespace SHADE }//namespace SHADE

View File

@ -15,7 +15,7 @@
//#==============================================================# //#==============================================================#
#ifndef SH_IM_MATH #ifndef SH_IM_MATH
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \ ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \
operator SHADE::SHVec2() const {return SHADE::SHVec2(x,y);} operator SHADE::SHVec2() const {return SHADE::SHVec2(x,y);}
#define IM_VEC3_CLASS_EXTRA \ #define IM_VEC3_CLASS_EXTRA \
ImVec3(const SHADE::SHVec3& vec) {x = vec.x; y = vec.y; z = vec.z;} \ ImVec3(const SHADE::SHVec3& vec) {x = vec.x; y = vec.y; z = vec.z;} \
@ -43,6 +43,10 @@ namespace SHADE
constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f}; constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f};
constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f}; constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f};
constexpr int colors_red = 0;
constexpr int colors_green = 1;
constexpr int colors_blue = 2;
constexpr int colors_white = 3;
constexpr ImU32 colors[] = { constexpr ImU32 colors[] = {
0xBB0000FF, // red 0xBB0000FF, // red
0xBB00FF00, // green 0xBB00FF00, // green

View File

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

View File

@ -4,7 +4,7 @@
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Graphics/SHVulkanDefines.h" #include "Graphics/SHVulkanDefines.h"
#include "SHCommandPoolResetMode.h" #include "SHCommandPoolResetMode.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Pipeline/SHPipelineType.h" #include "Graphics/Pipeline/SHPipelineType.h"
@ -37,7 +37,7 @@ namespace SHADE
class SHVkCommandBuffer class SHVkCommandBuffer
{ {
friend class SHVkCommandPool; friend class SHVkCommandPool;
friend class ResourceLibrary<SHVkCommandBuffer>; friend class SHResourceLibrary<SHVkCommandBuffer>;
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512; static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
// Project Includes // Project Includes
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/Shaders/SHShaderReflected.h" #include "Graphics/Shaders/SHShaderReflected.h"
#include "SHDescriptorSetUpdater.h" #include "SHDescriptorSetUpdater.h"

View File

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

View File

@ -8,8 +8,8 @@
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Graphics/Devices/SHVkPhysicalDevice.h" #include "Graphics/Devices/SHVkPhysicalDevice.h"
#include "Graphics/Queues/SHVkQueue.h" #include "Graphics/Queues/SHVkQueue.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/Swapchain/SHSwapchainParams.h" #include "Graphics/Swapchain/SHSwapchainParams.h"
#include "Graphics/Commands/SHCommandPoolResetMode.h" #include "Graphics/Commands/SHCommandPoolResetMode.h"
#include "Graphics/Commands/SHVkCommandPool.h" #include "Graphics/Commands/SHVkCommandPool.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#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"

View File

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

View File

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

View File

@ -147,6 +147,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize(); auto windowDims = window->GetWindowSize();
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
// Set Up Cameras // Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
@ -171,16 +172,16 @@ namespace SHADE
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Scene Pre Postprocess", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre Postprocess"}, {}); // no predecessors auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
//First subpass to write to G-Buffer //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Scene Pre Postprocess"); gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
@ -189,7 +190,7 @@ namespace SHADE
//sceneLayoutTransitionSubpass->AddGeneralInput("Scene"); //sceneLayoutTransitionSubpass->AddGeneralInput("Scene");
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
node->AddNodeCompute (greyscale, {"Scene Pre Postprocess", "Scene"}); node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -198,6 +199,8 @@ namespace SHADE
worldRenderer = worldViewport->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);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
@ -335,21 +338,7 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); 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)
@ -399,7 +388,22 @@ namespace SHADE
} }
// bind camera data // bind camera data
//renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#ifdef SHEDITOR
if (renderers[renIndex] == worldRenderer)
{
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
}
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#endif
// Draw first // Draw first
renderers[renIndex]->Draw(frameIndex, descPool); renderers[renIndex]->Draw(frameIndex, descPool);
@ -597,19 +601,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Texture Registration Functions */ /* Texture Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHGraphicsSystem::Add(const SHTextureAsset& texAsset) Handle<SHTexture> SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset)
{ {
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) }); auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) });
return texLibrary.Add(texAsset, sampler); return texLibrary.Add(texAsset, sampler);
} }
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets) SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
{ {
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) }); auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) });
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler); return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
} }
void SHGraphicsSystem::Remove(Handle<SHTexture> tex) void SHGraphicsSystem::RemoveTexture(Handle<SHTexture> tex)
{ {
texLibrary.Remove(tex); texLibrary.Remove(tex);
} }

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include <array> #include <array>
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Graphics/MiddleEnd/PerFrame/SHRenderContext.h" #include "Graphics/MiddleEnd/PerFrame/SHRenderContext.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
@ -231,8 +231,8 @@ namespace SHADE
*/ */
/*******************************************************************************/ /*******************************************************************************/
Handle<SHTexture> Add(const SHTextureAsset& texAsset); Handle<SHTexture> AddTexture(const SHTextureAsset& texAsset);
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets); Handle<SHTexture> AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
/*******************************************************************************/ /*******************************************************************************/
/*! /*!
@ -246,7 +246,7 @@ namespace SHADE
*/ */
/*******************************************************************************/ /*******************************************************************************/
void Remove(Handle<SHTexture> tex); void RemoveTexture(Handle<SHTexture> tex);
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -313,7 +313,7 @@ namespace SHADE
SHWindow* window = nullptr; SHWindow* window = nullptr;
// Middle End Resources // Middle End Resources
ResourceManager resourceManager; SHResourceHub resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary; SHTextureLibrary texLibrary;
SHSamplerCache samplerCache; SHSamplerCache samplerCache;

View File

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

View File

@ -13,7 +13,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <memory> #include <memory>
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h" #include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
#include "SH_API.h" #include "SH_API.h"

View File

@ -15,8 +15,8 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <vector> #include <vector>
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Math/SHMath.h" #include "Math/SHMath.h"
namespace SHADE namespace SHADE
@ -167,7 +167,7 @@ namespace SHADE
std::vector<MeshAddJob> meshAddJobs; std::vector<MeshAddJob> meshAddJobs;
std::vector<Handle<SHMesh>> meshRemoveJobs; std::vector<Handle<SHMesh>> meshRemoveJobs;
// Tracking // Tracking
ResourceLibrary<SHMesh> meshes{}; SHResourceLibrary<SHMesh> meshes{};
std::vector<Handle<SHMesh>> meshOrder; std::vector<Handle<SHMesh>> meshOrder;
// CPU Storage // CPU Storage
std::vector<SHMesh::VertexPosition> vertPosStorage; std::vector<SHMesh::VertexPosition> vertPosStorage;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
namespace SHADE namespace SHADE
{ {

View File

@ -12,7 +12,7 @@ of DigiPen Institute of Technology is prohibited.
#pragma once #pragma once
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
//#include "SHTransform.h" //#include "SHTransform.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Camera/SHCameraDirector.h"
namespace SHADE namespace SHADE
{ {
@ -65,6 +66,11 @@ namespace SHADE
camera = _camera; camera = _camera;
} }
void SHRenderer::SetCameraDirector(Handle<SHCameraDirector> director) noexcept
{
cameraDirector = director;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -75,17 +81,24 @@ namespace SHADE
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{ {
if (camera) if (camera && cameraDirector)
{ {
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
} }
} }
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
{
SetViewProjectionMatrix(exteriorMatrix);
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{ {
} }

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "SHCamera.h" #include "SHCamera.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include <vector> #include <vector>
@ -40,6 +40,7 @@ namespace SHADE
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkBuffer; class SHVkBuffer;
class SHCameraDirector;
struct SHShaderCameraData struct SHShaderCameraData
{ {
@ -71,12 +72,14 @@ namespace SHADE
/* Camera Registration */ /* Camera Registration */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetCamera(Handle<SHCamera> _camera); void SetCamera(Handle<SHCamera> _camera);
void SetCameraDirector (Handle<SHCameraDirector> director) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
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 UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept; void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
@ -99,6 +102,8 @@ namespace SHADE
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet; Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
Handle<SHVkBuffer> cameraBuffer; Handle<SHVkBuffer> cameraBuffer;
Handle<SHCameraDirector> cameraDirector;
// we really only need 1 copy even though we need %swapchainImages copies for // we really only need 1 copy even though we need %swapchainImages copies for
// GPU. // GPU.
SHShaderCameraData cpuCameraData; SHShaderCameraData cpuCameraData;

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Instance/SHVkInstance.h" #include "Graphics/Instance/SHVkInstance.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHRenderer.h" #include "SHRenderer.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
namespace SHADE namespace SHADE
@ -49,7 +49,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Renderer Registration Functions */ /* Renderer Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHRenderer> SHViewport::AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph) Handle<SHRenderer> SHViewport::AddRenderer(SHResourceHub& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph)
{ {
// Create the renderer // Create the renderer
auto renderer = resourceManager.Create<SHRenderer>(device, numFrames, cmdPools, descriptorPool, cameraDescLayout, GetHandle(), renderGraph); auto renderer = resourceManager.Create<SHRenderer>(device, numFrames, cmdPools, descriptorPool, cameraDescLayout, GetHandle(), renderGraph);

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
namespace SHADE namespace SHADE
{ {
@ -28,7 +28,7 @@ namespace SHADE
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkImageView; class SHVkImageView;
class ResourceManager; class SHResourceHub;
class SHRenderGraph; class SHRenderGraph;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
@ -59,7 +59,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Renderers Registration Functions */ /* Renderers Registration Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph); Handle<SHRenderer> AddRenderer(SHResourceHub& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph);
void RemoveRenderer(Handle<SHRenderer> renderer); void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -14,7 +14,7 @@ of DigiPen Institute of Technology is prohibited.
#include "SHMaterialInstanceCache.h" #include "SHMaterialInstanceCache.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
namespace SHADE namespace SHADE
@ -22,7 +22,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMaterialInstance> SHMaterialInstanceCache::CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material) SHADE::Handle<SHADE::SHMaterialInstance> SHMaterialInstanceCache::CreateOrGet(SHResourceHub& manager, Handle<SHMaterial> material)
{ {
// Check if there is already an existing instance // Check if there is already an existing instance
auto matInst = cache.find(material); auto matInst = cache.find(material);

View File

@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <unordered_map> #include <unordered_map>
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
namespace SHADE namespace SHADE
{ {
@ -24,7 +24,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHMaterial; class SHMaterial;
class SHMaterialInstance; class SHMaterialInstance;
class ResourceManager; class SHResourceHub;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -56,7 +56,7 @@ namespace SHADE
*/ */
/***********************************************************************************/ /***********************************************************************************/
Handle<SHMaterialInstance> CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material); Handle<SHMaterialInstance> CreateOrGet(SHResourceHub& manager, Handle<SHMaterial> material);
/***********************************************************************************/ /***********************************************************************************/
/*! /*!

View File

@ -17,8 +17,8 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include "tinyddsloader.h" #include "tinyddsloader.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
@ -156,7 +156,7 @@ namespace SHADE
std::vector<AddJob> addJobs; std::vector<AddJob> addJobs;
std::vector<Handle<SHTexture>> removeJobs; std::vector<Handle<SHTexture>> removeJobs;
// Tracking // Tracking
ResourceManager resourceManager; SHResourceHub resourceManager;
std::vector<Handle<SHTexture>> texOrder; std::vector<Handle<SHTexture>> texOrder;
// CPU Storage // CPU Storage
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers; std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers;

View File

@ -16,7 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
namespace SHADE namespace SHADE
{ {

View File

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

View File

@ -3,7 +3,7 @@
#include "SHPipelineState.h" #include "SHPipelineState.h"
#include "SHPipelineType.h" #include "SHPipelineType.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h"
namespace SHADE namespace SHADE

View File

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

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
namespace SHADE namespace SHADE
{ {

View File

@ -352,7 +352,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
{ {
resourceManager = std::make_shared<ResourceManager>(); resourceManager = std::make_shared<SHResourceHub>();
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>(); renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>(); renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();

View File

@ -2,7 +2,7 @@
#define SH_RENDER_GRAPH_H #define SH_RENDER_GRAPH_H
#include "Graphics/Renderpass/SHVkRenderpass.h" #include "Graphics/Renderpass/SHVkRenderpass.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "SH_API.h" #include "SH_API.h"
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h" #include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h" #include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
@ -67,7 +67,7 @@ namespace SHADE
std::vector<Handle<SHRenderGraphNode>> nodes; std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<ResourceManager> resourceManager; std::shared_ptr<SHResourceHub> resourceManager;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -13,7 +13,7 @@
namespace SHADE namespace SHADE
{ {
class ResourceManager; class SHResourceHub;
class SHVkFramebuffer; class SHVkFramebuffer;
class SHRenderGraphResource; class SHRenderGraphResource;
class SHVkLogicalDevice; class SHVkLogicalDevice;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include <initializer_list> #include <initializer_list>
#include <string> #include <string>

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
#include "SHAttachmentDescriptionType.h" #include "SHAttachmentDescriptionType.h"
#include <vector> #include <vector>
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "SH_API.h" #include "SH_API.h"

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include <memory> #include <memory>
namespace SHADE namespace SHADE
@ -20,7 +20,7 @@ namespace SHADE
Handle<SHVkSwapchain> swapchain; Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects //! Resource manager for creation of objects
std::shared_ptr<ResourceManager> resourceManager; std::shared_ptr<SHResourceHub> resourceManager;
//! Descriptor pool for the descriptor sets to be created in the subpasses //! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool; Handle<SHVkDescriptorPool> descriptorPool;

View File

@ -223,8 +223,7 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall); exteriorDrawCalls.push_back(newDrawCall);
} }
void SHSubpass::Init(SHResourceHub& resourceManager) noexcept
void SHSubpass::Init(ResourceManager& resourceManager) noexcept
{ {
superBatch = resourceManager.Create<SHSuperBatch>(GetHandle()); superBatch = resourceManager.Create<SHSuperBatch>(GetHandle());

View File

@ -3,7 +3,7 @@
#include "SHAttachmentDescriptionType.h" #include "SHAttachmentDescriptionType.h"
#include <string> #include <string>
#include "SH_API.h" #include "SH_API.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
@ -103,8 +103,7 @@ namespace SHADE
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept; void HandleResize (void) noexcept;
void Init(SHResourceHub& resourceManager) noexcept;
void Init(ResourceManager& resourceManager) noexcept;
//void InitComputeBarriers (void) noexcept; //void InitComputeBarriers (void) noexcept;
void CreateInputDescriptors (void) noexcept; void CreateInputDescriptors (void) noexcept;

View File

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

View File

@ -3,7 +3,7 @@
#include "SHVkAttachDescGen.h" #include "SHVkAttachDescGen.h"
#include "SHVkSubpassParams.h" #include "SHVkSubpassParams.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include <span> #include <span>
namespace SHADE namespace SHADE

View File

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

View File

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

View File

@ -2,7 +2,7 @@
#define SH_VK_SHADER_MODULE_H #define SH_VK_SHADER_MODULE_H
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/Handle.h" #include "Resource/SHHandle.h"
#include "SHShaderReflected.h" #include "SHShaderReflected.h"
#include <vector> #include <vector>

View File

@ -4,7 +4,7 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/Swapchain/SHSwapchainParams.h" #include "Graphics/Swapchain/SHSwapchainParams.h"
namespace SHADE namespace SHADE

View File

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

View File

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

View File

@ -3,7 +3,7 @@
#include <windows.h> #include <windows.h>
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Resource/ResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
namespace SHADE namespace SHADE
{ {

View File

@ -19,6 +19,10 @@ namespace SHADE
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Static defines */ /* Static defines */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
bool SHInputManager::controllerInUse = false;
std::map<std::string, SHInputManager::SHLogicalBindingData> SHInputManager::bindings;
unsigned SHInputManager::keyCount = 0; unsigned SHInputManager::keyCount = 0;
bool SHInputManager::keys[MAX_KEYS]; bool SHInputManager::keys[MAX_KEYS];
@ -41,6 +45,60 @@ namespace SHADE
int SHInputManager::mouseWheelVerticalDelta = 0; int SHInputManager::mouseWheelVerticalDelta = 0;
int SHInputManager::mouseWheelVerticalDeltaPoll = 0; int SHInputManager::mouseWheelVerticalDeltaPoll = 0;
unsigned char SHInputManager::controllersConnectedCount = 0;
unsigned SHInputManager::controllersInputCount[XUSER_MAX_COUNT];
unsigned SHInputManager::controllersButtonCount[XUSER_MAX_COUNT];
short SHInputManager::controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
short SHInputManager::controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
double SHInputManager::controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
double SHInputManager::controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Internal helper function for splitting between inputs
bool SHInputManager::controllerConsideredHeld(size_t inputIdx, short value) noexcept
{
if (inputIdx >= MAX_CONTROLLER_INPUT) return false; //Bounds check
else
{
if (inputIdx < NUM_CONTROLLER_BUTTON)
{
return static_cast<bool>(value);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER)
{
return (value > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER + NUM_CONTROLLER_TRIGGER)
{
return (std::abs(value) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
}
else
{
return (std::abs(value) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
}
}
}
//Internal helper function for getting normalised input value
double SHInputManager::controllerNormalisedValue(size_t inputIdx, short value) noexcept
{
if (inputIdx >= MAX_CONTROLLER_INPUT) return 0.0; //Bounds check
else
{
if (inputIdx < NUM_CONTROLLER_BUTTON)
{
return static_cast<double>(value);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER) //8-bit triggers, 0 to 255
{
return static_cast<double>(value) / static_cast<double>(UCHAR_MAX);
}
else //16-bit thumbsticks, -32768 to 32767
{
return static_cast<double>(value) / static_cast<double>(SHRT_MAX);
}
}
}
void SHInputManager::UpdateInput(double dt) noexcept void SHInputManager::UpdateInput(double dt) noexcept
{ {
//Keyboard and Mouse Buttons//////////////////////////////////////////////// //Keyboard and Mouse Buttons////////////////////////////////////////////////
@ -120,6 +178,273 @@ namespace SHADE
mouseWheelVerticalDelta = 0; mouseWheelVerticalDelta = 0;
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll; mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
mouseWheelVerticalDeltaPoll = 0; mouseWheelVerticalDeltaPoll = 0;
//Controllers//////////////////////////////////////////////////////////////
controllersConnectedCount = 0;
//Set last controller states
memcpy(controllersLast, controllers, sizeof(controllers));
//Reset controller states
SecureZeroMemory(&controllers, sizeof(controllers));
//https://learn.microsoft.com/en-us/windows/win32/xinput/getting-started-with-xinput#getting-controller-state
for (DWORD c = 0; c < XUSER_MAX_COUNT; ++c)
{
controllersInputCount[c] = 0;
controllersButtonCount[c] = 0;
XINPUT_STATE state;
SecureZeroMemory(&state, sizeof(XINPUT_STATE));
//Get the state of controller from XInput
DWORD result = XInputGetState(c, &state);
//Write gamepad data
if (result == ERROR_SUCCESS)
{
++controllersConnectedCount;
//DIGITAL BUTTONS///////////////////////////////////////
//DPAD UP
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 0;
}
//DPAD DOWN
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 0;
}
//DPAD LEFT
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 0;
}
//DPAD RIGHT
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 0;
}
//START
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 0;
}
//BACK
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 0;
}
//LEFT THUMBSTICK BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 0;
}
//RIGHT THUMBSTICK BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 0;
}
//LEFT SHOULDER BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 0;
}
//RIGHT SHOULDER BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 0;
}
//A
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 0;
}
//B
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 0;
}
//X
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 0;
}
//Y
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 0;
}
//8 BIT VALUES (0 - 255)///////////////////////////////////
//LEFT TRIGGER
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_TRIGGER)] = state.Gamepad.bLeftTrigger;
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
++controllersInputCount[c]; //Registered as held
}
//RIGHT TRIGGER
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_TRIGGER)] = state.Gamepad.bRightTrigger;
if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
++controllersInputCount[c]; //Registered as held
}
//16 BIT VALUES (0 - 65535)////////////////////////////////
//LEFT THUMBSTICK X
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_X)] = state.Gamepad.sThumbLX;
if (std::abs(state.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//LEFT THUMBSTICK Y
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_Y)] = state.Gamepad.sThumbLY;
if (std::abs(state.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//RIGHT THUMBSTICK X
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_X)] = state.Gamepad.sThumbRX;
if (std::abs(state.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//RIGHT THUMBSTICK Y
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_Y)] = state.Gamepad.sThumbRY;
if (std::abs(state.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
}
//Timers and updating if controller is presently in use
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[c][i])) //Considered on
{
controllerInUse = true;
if (!controllerConsideredHeld(i, controllersLast[c][i])) //Just on
{
controllersHeldTime[c][i] = 0.0; //Reset timer
}
controllersHeldTime[c][i] += dt; //Tick up
}
else //Considered off
{
if (controllerConsideredHeld(i, controllersLast[c][i])) //Just off
{
controllersReleasedTime[c][i] = 0.0; //Reset timer
}
controllersReleasedTime[c][i] += dt; //Tick up
}
}
}
} }
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
@ -161,4 +486,336 @@ namespace SHADE
return false; return false;
} }
//Any controller input being held
//For analog, this means going being deadzone values
bool SHInputManager::AnyControllerInput(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButton(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
//Only get of largest magnitude
double SHInputManager::GetBindingAxis(std::string bindingName, size_t cNum) noexcept
{
//Over keycodes, prioritise positive
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKey(k)) return 1.0;
}
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKey(k)) return -1.0;
}
double largestMagnitude = 0.0;
//Over controllerCodes
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
double newValue = 0.0;
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = newValue;
}
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
double newValue = 0.0;
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = -newValue;
}
return largestMagnitude;
}
bool SHInputManager::GetBindingPositiveButton(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKey(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButton(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKey(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingPositiveButtonDown(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyDown(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputDown(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButtonDown(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyDown(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputDown(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingPositiveButtonUp(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyUp(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputUp(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButtonUp(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyUp(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputUp(c, nullptr, cNum)) return true;
}
return false;
}
//Fetches longest hold time
double SHInputManager::GetBindingPositiveHeldTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double maxHeldTime = 0.0;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
}
return maxHeldTime;
}
double SHInputManager::GetBindingNegativeHeldTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double maxHeldTime = 0.0;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
}
return maxHeldTime;
}
//Fetches shortest release time
double SHInputManager::GetBindingPositiveReleasedTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double minReleaseTime = _HUGE_ENUF;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
}
return minReleaseTime;
}
double SHInputManager::GetBindingNegativeReleasedTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double minReleaseTime = _HUGE_ENUF;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
}
return minReleaseTime;
}
//Only for mouse movement
//Get largest delta
double SHInputManager::GetBindingMouseVelocity(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
//Mouse velocity
double velX = 0.0;
double velY = 0.0;
GetMouseVelocity(&velX, &velY);
return bindings[bindingName].mouseXPositiveMultiplier * velX + bindings[bindingName].mouseYPositiveMultiplier * velY;
}
} //namespace SHADE } //namespace SHADE

View File

@ -10,9 +10,12 @@
*********************************************************************/ *********************************************************************/
#pragma once #pragma once
//#include <Xinput.h> #include <Xinput.h>
//#include "../../SHADE_Managed/src/SHpch.h" #include <map>
#include <set>
#include "../../SHADE_Managed/src/SHpch.h"
#include "SH_API.h" #include "SH_API.h"
#pragma comment(lib, "xinput.lib")
namespace SHADE namespace SHADE
{ {
@ -268,6 +271,58 @@ namespace SHADE
OEM_CLEAR OEM_CLEAR
}; };
enum class SH_CONTROLLERCODE
{
//Digital
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
START,
BACK,
LEFT_THUMBSTICK,
RIGHT_THUMBSTICK,
LEFT_SHOULDER,
RIGHT_SHOULDER,
A,
B,
X,
Y,
//1 Byte Unsigned Analog
LEFT_TRIGGER,
RIGHT_TRIGGER,
//2 Byte Signed Analog
LEFT_THUMBSTICK_X,
LEFT_THUMBSTICK_Y,
RIGHT_THUMBSTICK_X,
RIGHT_THUMBSTICK_Y
};
private:
/*------------------------------------------------------------------------*/
/* Struct for logical bindings */
/*------------------------------------------------------------------------*/
struct SH_API SHLogicalBindingData
{
//Key codes mapped to positive
std::set<SH_KEYCODE> positiveKeyCodes;
//Key codes mapped to negative
std::set<SH_KEYCODE> negativeKeyCodes;
//Controller Codes mapped to positive
std::set<SH_CONTROLLERCODE> positiveControllerCodes;
//Controller Codes mapped to negative
std::set<SH_CONTROLLERCODE> negativeControllerCodes;
//Mouse movement mapped to axes?
double mouseXPositiveMultiplier;
double mouseYPositiveMultiplier;
};
public: public:
//Updates current state of the input, with dt to be fetched from FRC //Updates current state of the input, with dt to be fetched from FRC
//TODO should dt be fixed or variable? //TODO should dt be fixed or variable?
@ -392,7 +447,7 @@ namespace SHADE
keysToggleLast[static_cast<int>(key)]); keysToggleLast[static_cast<int>(key)]);
} }
//Mouse///////////// //Mouse/////////////////////////////////////////////////////
//Get the mouse location with respect to the screen //Get the mouse location with respect to the screen
static inline void GetMouseScreenPosition (int* x = nullptr, static inline void GetMouseScreenPosition (int* x = nullptr,
@ -428,7 +483,95 @@ namespace SHADE
return mouseWheelVerticalDelta; return mouseWheelVerticalDelta;
} }
//GET INPUT TIMINGS/////////////////////////////////////////////////////////// /*------------------------------------------------------------------------*/
/* Input state accessors (KB & M) */
/*------------------------------------------------------------------------*/
//How many controller inputs of any kind are being used now
static inline unsigned GetControllerInputCount(size_t cNum = 0) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0;
return controllersInputCount[cNum];
}
//How many controller buttons are being pressed now
//Subtract from getControllerInputCount() for analog triggers / thumbsticks
static inline unsigned GetControllerButtonCount(size_t cNum = 0) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0;
return controllersButtonCount[cNum];
}
//Any controller input being held
//For analog, this means going being deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInput(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any controller input activated in THIS FRAME ONLY
//For analog, this means going being deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any controller input deactivated in THIS FRAME ONLY
//For analog, this means going below deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller buttons being held
//controllerNum should be between 0 and 3
static bool AnyControllerButton(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller button activated in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static bool AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller button deactivated in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static bool AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//If controller input is being held in the current frame
//normalisedValue is the value of the input between 0 and 1, relevant for trigger and thumbstick data
//controllerNum should be between 0 and 3
static inline bool GetControllerInput(SH_CONTROLLERCODE input,
double* normalisedValue = nullptr,
double* heldTime = nullptr,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (normalisedValue) *normalisedValue = controllerNormalisedValue(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
if (heldTime) *heldTime = controllersHeldTime[controllerNum][static_cast<size_t>(input)];
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
}
//If controller input was considered to be held down in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static inline bool GetControllerInputDown(SH_CONTROLLERCODE input,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return (controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
!controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
}
//If controller input was considered to be released in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static inline bool GetControllerInputUp(SH_CONTROLLERCODE input,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return (!controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
}
/*------------------------------------------------------------------------*/
/* Timing accessors */
/*------------------------------------------------------------------------*/
//Keyboard///////////// //Keyboard/////////////
@ -456,6 +599,191 @@ namespace SHADE
return keysToggleOffTime[static_cast<int>(key)]; return keysToggleOffTime[static_cast<int>(key)];
} }
//Controller//////////////////////
//How long has this controller input been considered to be held down for
static inline double GetControllerInputHeldTime(SH_CONTROLLERCODE code,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
return controllersHeldTime[controllerNum][static_cast<size_t>(code)];
}
//How long has this controller input been considered to be released for
static inline double GetControllerInputReleasedTime(SH_CONTROLLERCODE code,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
return controllersReleasedTime[controllerNum][static_cast<size_t>(code)];
}
/*------------------------------------------------------------------------*/
/* Binding Functions */
/*------------------------------------------------------------------------*/
//Add a new binding to the map
static inline void BindingsAdd(std::string newBindingName) noexcept
{
bindings.insert({ newBindingName, SHLogicalBindingData() });
}
//Remove a binding from the map
//Returns 1 if found and removed, 0 if not found
static inline size_t BindingsRemove(std::string targetBindingName) noexcept
{
return bindings.erase(targetBindingName);
}
//Clears all bindings from the list
static inline void BindingsClear() noexcept
{
bindings.clear();
}
//Get the number of bindings present
static inline size_t BindingsCount() noexcept
{
return bindings.size();
}
//Check positive keycodes to binding
static inline std::set<SH_KEYCODE> const& BindingsGetPositiveKeyCodes(std::string bindingName) noexcept
{
return bindings[bindingName].positiveKeyCodes;
}
//Add positive SH_KEYCODE to binding
static inline void BindingsAddPositiveKeyCode(std::string targetBindingName,
SH_KEYCODE toAdd) noexcept
{
bindings[targetBindingName].positiveKeyCodes.insert(toAdd);
}
//Remove positive SH_KEYCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemovePositiveKeyCode(std::string targetBindingName,
SH_KEYCODE toRemove) noexcept
{
return bindings[targetBindingName].positiveKeyCodes.erase(toRemove);
}
//Check negative keycodes to binding
static inline std::set<SH_KEYCODE> const& BindingsGetNegativeKeyCodes(std::string bindingName) noexcept
{
return bindings[bindingName].negativeKeyCodes;
}
//Add negative SH_KEYCODE to binding
static inline void BindingsAddNegativeKeyCode(std::string targetBindingName,
SH_KEYCODE toAdd) noexcept
{
bindings[targetBindingName].negativeKeyCodes.insert(toAdd);
}
//Remove negative SH_KEYCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemoveNegativeKeyCode(std::string targetBindingName,
SH_KEYCODE toRemove) noexcept
{
return bindings[targetBindingName].negativeKeyCodes.erase(toRemove);
}
//Check positive controllercodes to binding
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetPositiveControllerCodes(std::string bindingName) noexcept
{
return bindings[bindingName].positiveControllerCodes;
}
//Add positive SH_CONTROLLERCODE to binding
static inline void BindingsAddPositiveControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toAdd) noexcept
{
bindings[targetBindingName].positiveControllerCodes.insert(toAdd);
}
//Remove positive SH_CONTROLLERCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemovePositiveControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toRemove) noexcept
{
return bindings[targetBindingName].positiveControllerCodes.erase(toRemove);
}
//Check negative controllercodes to binding
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetNegativeControllerCodes(std::string bindingName) noexcept
{
return bindings[bindingName].negativeControllerCodes;
}
//Add negative SH_CONTROLLERCODE to binding
static inline void BindingsAddNegativeControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toAdd) noexcept
{
bindings[targetBindingName].negativeControllerCodes.insert(toAdd);
}
//Remove negative SH_CONTROLLERCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemoveNegativeControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toRemove) noexcept
{
return bindings[targetBindingName].negativeControllerCodes.erase(toRemove);
}
//Mouse movement bindings
static inline double const BindingsGetMouseXPositiveMultiplier(std::string bindingName) noexcept
{
return bindings[bindingName].mouseXPositiveMultiplier;
}
static inline void BindingsSetMouseXPositiveMultiplier(std::string bindingName, double newValue) noexcept
{
bindings[bindingName].mouseXPositiveMultiplier = newValue;
}
static inline double const BindingsGetMouseYPositiveMultiplier(std::string bindingName) noexcept
{
return bindings[bindingName].mouseXPositiveMultiplier;
}
static inline void BindingsSetMouseYPositiveMultiplier(std::string bindingName, double newValue) noexcept
{
bindings[bindingName].mouseXPositiveMultiplier = newValue;
}
//Get the axis value of binding, between -1 and 1
static double GetBindingAxis(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is being held or not
//Does not work for mouse movement
static bool GetBindingPositiveButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is pressed down IN THIS FRAME ONLY
//Does not work for mouse movement
static bool GetBindingPositiveButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is released IN THIS FRAME ONLY
//Does not work for mouse movement
static bool GetBindingPositiveButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Binding times
//Does not work for mouse movement
static double GetBindingPositiveHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
static double GetBindingNegativeHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Does not work for mouse movement
static double GetBindingPositiveReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
static double GetBindingNegativeReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Binding mouse velocity
//Only for mouse movement
static double GetBindingMouseVelocity(std::string bindingName, size_t controllerNumber = 0) noexcept;
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Other Functions */ /* Other Functions */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -482,10 +810,36 @@ namespace SHADE
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1; static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
//How many recognised controller inputs there are
//To see the list, see the enum class in this file
static constexpr size_t MAX_CONTROLLER_INPUT = 20;
//On/off button count
static constexpr size_t NUM_CONTROLLER_BUTTON = 14;
//8-bit trigger values
static constexpr size_t NUM_CONTROLLER_TRIGGER = 2;
//16-bit thumbstick values
static constexpr size_t NUM_CONTROLLER_THUMBSTICK = 4;
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
//If the last input is from controller(s) or KB/M
//True if from controller(s), False if from KB/M
//Useful for switching control hints between controllers and KB/M
static bool controllerInUse;
//BINDINGS//////////////////////////////////////////////////////////////////
//Key is for binding names, they must be unique
//Multiple physical inputs per virtual/logical input are to be added to
//sets inside the logicalBinding values
//TODO make this an array of 4 / 5 users for multiplayer support
static std::map<std::string, SHLogicalBindingData> bindings;
//KEYBOARD AND MOUSE BUTTONS//////////////////////////////////////////////// //KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
//How many keys are presently being pressed //How many keys are presently being pressed
@ -558,15 +912,48 @@ namespace SHADE
//CONTROLLER VARIABLES////////////////////////////////////////////////////// //CONTROLLER VARIABLES//////////////////////////////////////////////////////
//OTHER VARIABLES/////////////////////////////////////////////////////////// //Count how many controllers are presently connected
//Useful for if the game is to decide to take in controller or KB/M input
//Between 0 and 4 (inclusive)
static unsigned char controllersConnectedCount;
//Axis bindings //How many inputs (of any kind) on the controller are being used now
//X //Includes analog triggers and thumbsticks
static unsigned controllersInputCount[XUSER_MAX_COUNT];
//Y
//Other mappings //How many DIGITAL buttons on the controller are being pressed now
static unsigned controllersButtonCount[XUSER_MAX_COUNT];
//Buffer //Current state of controllers
//First index is for controller number
//Second index is for input type
static short controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//State of controllers in the last frame
//First index is for controller number
//Second index is for input type
static short controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Held and released times
//Controller held durations
//Stops ticking up when released
//Will be reset when held again
static double controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Key released durations
//Stops ticking up when held
//Will be reset when off again
static double controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
/*------------------------------------------------------------------------*/
/* Internal Helper Functions */
/*------------------------------------------------------------------------*/
//Internal helper function for checking if input is considered held or not
static bool controllerConsideredHeld(size_t inputIdx, short value) noexcept;
//Internal helper function for getting normalised controller value
static double controllerNormalisedValue(size_t inputIdx, short value) noexcept;
}; };
} }

View File

@ -8,8 +8,9 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Forward Declarations */ /* Forward Declarations */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
class SHResourceLibraryBase;
template<typename T> template<typename T>
class ResourceLibrary; class SHResourceLibrary;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -25,6 +26,20 @@ namespace SHADE
using std::runtime_error::runtime_error; using std::runtime_error::runtime_error;
}; };
/// <summary>
/// Exception thrown when a generic Handle is being casted to the wrong type.
/// </summary>
class BadHandleCastException : std::runtime_error
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
BadHandleCastException()
: std::runtime_error("Attempted to cast a generic Handle to the wrong type. ")
{}
};
/// <summary> /// <summary>
/// Base implementation of the Handle that is not templated to allow for holding /// Base implementation of the Handle that is not templated to allow for holding
/// generic non-type-specific Handles. /// generic non-type-specific Handles.
@ -80,7 +95,7 @@ namespace SHADE
/// Generic implementation of a Handle object /// Generic implementation of a Handle object
/// </summary> /// </summary>
/// <typeparam name="T">Type of the handle.</typeparam> /// <typeparam name="T">Type of the handle.</typeparam>
template<typename T> template<typename T = void>
class Handle : public HandleBase class Handle : public HandleBase
{ {
public: public:
@ -88,6 +103,16 @@ namespace SHADE
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle() = default; Handle() = default;
/// <summary>
/// Converts a generic/void Handle to a specific type.
/// Runtime type checking is enabled to ensure that Handles are only being casted
/// to the correct type.
/// </summary>
/// <param name="genericHandle">Generic handle to convert.</param>
/// <exception cref="std::bad_cast">
/// Thrown if an invalid conversion is made.
/// </exception>
explicit Handle(const Handle<void>& genericHandle);
~Handle() = default; ~Handle() = default;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -140,13 +165,48 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
ResourceLibrary<T>* library = nullptr; SHResourceLibrary<T>* library = nullptr;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Friend Declarations */ /* Friend Declarations */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
friend class ResourceLibrary<T>; friend class SHResourceLibrary<T>;
}; friend class Handle<void>;
};
/// <summary>
/// Template Specialization for Handle that represents a type-less Handle.
/// </summary>
template<>
class Handle<void> : public HandleBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
Handle() = default;
template<typename T>
explicit Handle(const Handle<T>& handle);
~Handle() = default;
/*-----------------------------------------------------------------------------*/
/* Overloaded Operators */
/*-----------------------------------------------------------------------------*/
template<typename T>
inline bool operator==(const Handle<T>& rhs) const noexcept;
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
SHResourceLibraryBase* library = nullptr;
/*-----------------------------------------------------------------------------*/
/* Friend Declarations */
/*-----------------------------------------------------------------------------*/
template<typename T>
friend class Handle;
};
/// <summary> /// <summary>
/// Interface that needs to be implemented by classes that want to store a Handle to /// Interface that needs to be implemented by classes that want to store a Handle to
@ -155,7 +215,7 @@ namespace SHADE
template<typename T> template<typename T>
class ISelfHandle class ISelfHandle
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -183,7 +243,7 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="rscLib">Required to lock usage to ResourceLibrary only.</param> /// <param name="rscLib">Required to lock usage to ResourceLibrary only.</param>
/// <param name="hdl">Handle to set.</param> /// <param name="hdl">Handle to set.</param>
void SetHandle(const ResourceLibrary<T>& rscLib, Handle<T> hdl); void SetHandle(const SHResourceLibrary<T>& rscLib, Handle<T> hdl);
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -220,4 +280,4 @@ namespace std
}; };
} }
#include "Handle.hpp" #include "SHHandle.hpp"

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
// Primary Header // Primary Header
#include "Handle.h" #include "SHHandle.h"
#include "ResourceLibrary.h" #include "SHResourceLibrary.h"
namespace SHADE namespace SHADE
{ {
@ -20,7 +20,21 @@ namespace SHADE
{ {
return id.Raw != INVALID_ID.Raw; return id.Raw != INVALID_ID.Raw;
} }
/*---------------------------------------------------------------------------------*/
/* Handle<T> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T>
Handle<T>::Handle(const Handle<void>& genericHandle)
: library { reinterpret_cast<SHResourceLibrary<T>*>(genericHandle.library) }
{
id = genericHandle.id;
// Check if valid
if (library != nullptr && library->GetType() != typeid(T))
throw BadHandleCastException();
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Handle<T> - Usage Functions */ /* Handle<T> - Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -63,6 +77,28 @@ namespace SHADE
return &library->Get(*this); return &library->Get(*this);
} }
/*---------------------------------------------------------------------------------*/
/* Handle<void> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T>
Handle<void>::Handle(const Handle<T>& handle)
: library{ static_cast<SHResourceLibraryBase*>(handle.library) }
{
id = handle.id;
}
/*---------------------------------------------------------------------------------*/
/* Handle<void> - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
template<typename T>
bool SHADE::Handle<void>::operator==(const Handle<T>& rhs) const noexcept
{
return id.Raw == rhs.id.Raw && library == static_cast<void*>(rhs.library);
}
/*---------------------------------------------------------------------------------*/
/* ISelfHandle<T> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T> template<typename T>
inline ISelfHandle<T>::ISelfHandle(const ISelfHandle& rhs) inline ISelfHandle<T>::ISelfHandle(const ISelfHandle& rhs)
: handle { rhs.handle } : handle { rhs.handle }
@ -73,6 +109,9 @@ namespace SHADE
: handle { rhs.handle } : handle { rhs.handle }
{} {}
/*---------------------------------------------------------------------------------*/
/* ISelfHandle<T> - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
template<typename T> template<typename T>
inline ISelfHandle<T>& ISelfHandle<T>::operator=(const ISelfHandle& rhs) inline ISelfHandle<T>& ISelfHandle<T>::operator=(const ISelfHandle& rhs)
{ {
@ -96,7 +135,7 @@ namespace SHADE
return handle; return handle;
} }
template<typename T> template<typename T>
inline void ISelfHandle<T>::SetHandle(const ResourceLibrary<T>&, Handle<T> hdl) inline void ISelfHandle<T>::SetHandle(const SHResourceLibrary<T>&, Handle<T> hdl)
{ {
handle = hdl; handle = hdl;
} }

View File

@ -1,11 +1,11 @@
#include "SHPch.h" #include "SHPch.h"
#include "ResourceLibrary.h" #include "SHResourceLibrary.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors/Destructors */ /* Constructors/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
ResourceManager::~ResourceManager() SHResourceHub::~SHResourceHub()
{ {
// Delete all resources libraries // Delete all resources libraries
for (auto iter = deleters.rbegin(); iter != deleters.rend(); ++iter) for (auto iter = deleters.rbegin(); iter != deleters.rend(); ++iter)

View File

@ -6,24 +6,42 @@
#include <queue> #include <queue>
// Project Headers // Project Headers
#include "Handle.h" #include "SHHandle.h"
#include "Resource/SparseSet.h" #include "Resource/SparseSet.h"
namespace SHADE namespace SHADE
{ {
/// <summary>
/// Base class for SHResourceLibrary that holds information about the library type.
/// </summary>
class SHResourceLibraryBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
inline std::type_index GetType() { return libraryType; }
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
std::type_index libraryType = typeid(void);
};
/// <summary> /// <summary>
/// Generic Resource Library for a specified type of Resource. This object will own /// Generic Resource Library for a specified type of Resource. This object will own
/// any resources created using it. /// any resources created using it.
/// </summary> /// </summary>
/// <typeparam name="T">Type of resources that this library stores.</typeparam> /// <typeparam name="T">Type of resources that this library stores.</typeparam>
template<typename T> template<typename T>
class ResourceLibrary class SHResourceLibrary : public SHResourceLibraryBase
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructor */ /* Constructor */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
ResourceLibrary(); SHResourceLibrary();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
@ -75,13 +93,13 @@ namespace SHADE
/// <summary> /// <summary>
/// Manages all resources in multiple ResourceLibraries. /// Manages all resources in multiple ResourceLibraries.
/// </summary> /// </summary>
class ResourceManager final class SHResourceHub final
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors/Destructors */ /* Constructors/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
~ResourceManager(); ~SHResourceHub();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
@ -136,10 +154,10 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
template<typename T> template<typename T>
ResourceLibrary<T>& getLibrary(); SHResourceLibrary<T>& getLibrary();
template<typename T> template<typename T>
const ResourceLibrary<T>& getLibrary() const; const SHResourceLibrary<T>& getLibrary() const;
}; };
} }
#include "ResourceLibrary.hpp" #include "SHResourceLibrary.hpp"

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
// Primary Header // Primary Header
#include "ResourceLibrary.h" #include "SHResourceLibrary.h"
// Standard Library // Standard Library
#include <utility> #include <utility>
@ -10,13 +10,14 @@ namespace SHADE
/* ResourceLibrary - Constructor */ /* ResourceLibrary - Constructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
template <typename T> template <typename T>
ResourceLibrary<T>::ResourceLibrary() SHResourceLibrary<T>::SHResourceLibrary()
{ {
// Type Checking // Type Checking
//static_assert(std::is_copy_assignable_v<T>, "Resource Library's resources must be copy assignable.");
//static_assert(std::is_copy_constructible_v<T>, "Resource Library's resources must be copy constructible.");
static_assert(std::is_move_assignable_v<T>, "Resource Library's resources must be move assignable."); static_assert(std::is_move_assignable_v<T>, "Resource Library's resources must be move assignable.");
static_assert(std::is_move_constructible_v<T>, "Resource Library's resources must be move constructible."); static_assert(std::is_move_constructible_v<T>, "Resource Library's resources must be move constructible.");
// Keep track of the type for conversions
libraryType = typeid(T);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -24,7 +25,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
template <typename T> template <typename T>
template <typename ... Args> template <typename ... Args>
Handle<T> ResourceLibrary<T>::Create(Args&&... args) Handle<T> SHResourceLibrary<T>::Create(Args&&... args)
{ {
// Create the handle // Create the handle
Handle<T> handle; Handle<T> handle;
@ -55,7 +56,7 @@ namespace SHADE
} }
template <typename T> template <typename T>
void ResourceLibrary<T>::Free(Handle<T> handle) void SHResourceLibrary<T>::Free(Handle<T> handle)
{ {
assertHandleValid(handle); assertHandleValid(handle);
@ -63,7 +64,7 @@ namespace SHADE
} }
template <typename T> template <typename T>
T& ResourceLibrary<T>::Get(Handle<T> handle) T& SHResourceLibrary<T>::Get(Handle<T> handle)
{ {
assertHandleValid(handle); assertHandleValid(handle);
@ -71,7 +72,7 @@ namespace SHADE
} }
template <typename T> template <typename T>
const T& ResourceLibrary<T>::Get(Handle<T> handle) const const T& SHResourceLibrary<T>::Get(Handle<T> handle) const
{ {
assertHandleValid(handle); assertHandleValid(handle);
@ -82,14 +83,14 @@ namespace SHADE
/* ResourceLibrary - Helper Functions */ /* ResourceLibrary - Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
template <typename T> template <typename T>
void ResourceLibrary<T>::assertHandleValid(Handle<T> handle) const void SHResourceLibrary<T>::assertHandleValid(Handle<T> handle) const
{ {
if (!handle || handle.id.Data.Version != versionCounts[handle.id.Data.Index]) if (!handle || handle.id.Data.Version != versionCounts[handle.id.Data.Index])
throw std::invalid_argument("Invalid handle provided!"); throw std::invalid_argument("Invalid handle provided!");
} }
template<typename T> template<typename T>
inline uint32_t ResourceLibrary<T>::getAvailableFreeIndex() inline uint32_t SHResourceLibrary<T>::getAvailableFreeIndex()
{ {
// Get from the free list if present // Get from the free list if present
if (!freeList.empty()) if (!freeList.empty())
@ -107,25 +108,25 @@ namespace SHADE
/* ResourceManager - Usage Functions */ /* ResourceManager - Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
template <typename T, typename ... Args> template <typename T, typename ... Args>
Handle<T> ResourceManager::Create(Args&&... args) Handle<T> SHResourceHub::Create(Args&&... args)
{ {
return getLibrary<T>().Create(std::forward<Args>(args) ...); return getLibrary<T>().Create(std::forward<Args>(args) ...);
} }
template <typename T> template <typename T>
void ResourceManager::Free(Handle<T> handle) void SHResourceHub::Free(Handle<T> handle)
{ {
getLibrary<T>().Free(handle); getLibrary<T>().Free(handle);
} }
template <typename T> template <typename T>
T& ResourceManager::Get(Handle<T> handle) T& SHResourceHub::Get(Handle<T> handle)
{ {
return getLibrary<T>().Get(handle); return getLibrary<T>().Get(handle);
} }
template <typename T> template <typename T>
const T& ResourceManager::Get(Handle<T> handle) const const T& SHResourceHub::Get(Handle<T> handle) const
{ {
return getLibrary<T>().Get(handle); return getLibrary<T>().Get(handle);
} }
@ -134,18 +135,18 @@ namespace SHADE
/* ResourceManager - Helper Functions */ /* ResourceManager - Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
template <typename T> template <typename T>
ResourceLibrary<T>& ResourceManager::getLibrary() SHResourceLibrary<T>& SHResourceHub::getLibrary()
{ {
// Attempt to retrieve the library // Attempt to retrieve the library
const std::type_index RSC_TYPE = typeid(T); const std::type_index RSC_TYPE = typeid(T);
if (resourceLibs.contains(RSC_TYPE)) if (resourceLibs.contains(RSC_TYPE))
{ {
return *static_cast<ResourceLibrary<T>*>(resourceLibs.at(RSC_TYPE)); return *static_cast<SHResourceLibrary<T>*>(resourceLibs.at(RSC_TYPE));
} }
else else
{ {
// Construct library if doesn't exist // Construct library if doesn't exist
ResourceLibrary<T>* lib = new ResourceLibrary<T>(); SHResourceLibrary<T>* lib = new SHResourceLibrary<T>();
resourceLibs.emplace(RSC_TYPE, static_cast<void*>(lib)); resourceLibs.emplace(RSC_TYPE, static_cast<void*>(lib));
// Construct deleter to properly delete objects with void* // Construct deleter to properly delete objects with void*
@ -156,8 +157,8 @@ namespace SHADE
} }
template <typename T> template <typename T>
const ResourceLibrary<T>& ResourceManager::getLibrary() const const SHResourceLibrary<T>& SHResourceHub::getLibrary() const
{ {
return const_cast<ResourceManager*>(this).getLibrary<T>(); return const_cast<SHResourceHub*>(this).getLibrary<T>();
} }
} }

View File

@ -0,0 +1,95 @@
/************************************************************************************//*!
\file SHResourceManager.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 21, 2022
\brief Contains the definition of the functions of the SHResourceManager static
class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
// Primary Include
#include "SHResourceManager.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHResourceHub SHResourceManager::resourceHub;
std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap;
std::unordered_map<std::type_index, SHADE::SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap;
std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap;
std::vector<AssetID> SHResourceManager::loadedAssetData;
/*-----------------------------------------------------------------------------------*/
/* Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHResourceManager::Unload(AssetID assetId)
{
// Search each library for the asset ID and try to free it
Handle handle;
for (auto& typedHandleMap : handlesMap)
{
if (typedHandleMap.second.contains(assetId))
{
// Save handle for later
handle = typedHandleMap.second[assetId];
// Dispose
typedFreeFuncMap[typedHandleMap.first](assetId);
typedHandleMap.second.erase(assetId);
}
}
// No handles were found
if (!handle)
return;
for (auto& typedAssetIdsMap : assetIdMap)
{
if (typedAssetIdsMap.second.contains(handle))
{
// Dispose
typedAssetIdsMap.second.erase(handle);
}
}
}
void SHResourceManager::FinaliseChanges()
{
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures();
// Free CPU Resources
for (auto assetId : loadedAssetData)
{
SHAssetManager::Unload(assetId);
}
loadedAssetData.clear();
}
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
std::optional<AssetID> SHResourceManager::GetAssetID(Handle<void> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
// Search each library for the asset ID and try to free it
for (auto& typedAssetIdsMap : assetIdMap)
{
if (typedAssetIdsMap.second.contains(GENERIC_HANDLE))
{
return typedAssetIdsMap.second[GENERIC_HANDLE];
}
}
return {};
}
}

View File

@ -0,0 +1,130 @@
/************************************************************************************//*!
\file SHResourceManager.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 21, 2022
\brief Contains the definition of the SHResourceManager static class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// STL Includes
#include <unordered_map>
// Project Includes
#include "SH_API.h"
#include "SHResourceLibrary.h"
#include "Assets/SHAssetMacros.h"
namespace SHADE
{
/// <summary>
/// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs.
/// </summary>
class SH_API SHResourceManager
{
public:
/*---------------------------------------------------------------------------------*/
/* Loading Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Loads or retrieves an existing loaded object of the specified type with the
/// specified asset ID.
/// Note that for specific types, the retrieved Handle may not be valid until after
/// FinaliseChanges() is called.
/// </summary>
/// <typeparam name="ResourceType">
/// Type of resource to load.
/// </typeparam>
/// <param name="assetId">Asset ID of the resource to load.</param>
/// <returns>Handle to a loaded runtime asset.</returns>
template<typename ResourceType>
static Handle<ResourceType> LoadOrGet(AssetID assetId);
/// <summary>
/// Unloads an existing loaded asset. Attempting to unload an invalid Handle will
/// simply do nothing except emit a warning.
/// Faster than the untemplated version.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to unload.</typeparam>
/// <param name="assetId">Handle to the resource to unload.</param>
template<typename ResourceType>
static void Unload(Handle<ResourceType> assetId);
/// <summary>
/// Unloads an existing loaded asset. Attempting to unload an invalid Handle will
/// simply do nothing except emit a warning.
/// Compared to the templated version, this function is slower as it requires
/// searching through the storage of all resource types.
/// </summary>
/// <param name="assetId">Handle to the resource to unload.</param>
static void Unload(AssetID assetId);
/// <summary>
/// Needs to be called to finalise all changes to loads.
/// </summary>
static void FinaliseChanges();
/*---------------------------------------------------------------------------------*/
/* Query Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Retrieves the AssetID associated with a specified Handle.
/// Faster than the untemplated version.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to get the ID of.</typeparam>
/// <param name="handle">Handle to get the AssetID of.</param>
/// <return>
/// AssetID for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
template<typename T>
static std::optional<AssetID> GetAssetID(Handle<T> handle);
/// <summary>
/// Retrieves the AssetID associated with a specified Handle.
/// Compared to the templated version, this function is slower as it requires
/// searching through the storage of all resource types.
/// </summary>
/// <param name="handle">Handle to get the AssetID of.</param>
/// <return>
/// AssetID for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
static std::optional<AssetID> GetAssetID(Handle<void> handle);
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using AssetHandleMap = std::unordered_map<AssetID, Handle<void>>;
using HandleAssetMap = std::unordered_map<Handle<void>, AssetID>;
using AssetHandleMapRef = std::reference_wrapper<AssetHandleMap>;
using HandleAssetMapRef = std::reference_wrapper<HandleAssetMap>;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
// Handles
static SHResourceHub resourceHub;
static std::unordered_map<std::type_index, AssetHandleMap> handlesMap;
static std::unordered_map<std::type_index, HandleAssetMap> assetIdMap;
static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap;
// Pointers to temp CPU resources
static std::vector<AssetID> loadedAssetData;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Retrieves or creates the AssetHandleMap for the specific type if it doesn't exist
/// </summary>
/// <typeparam name="ResourceType">
/// The type of AssetHandleMap to retrieve.
/// </typeparam>
/// <returns>Reference to the AssetHandleMap of the specified type.</returns>
template<typename ResourceType>
static std::pair<AssetHandleMapRef, HandleAssetMapRef> getAssetHandleMap();
};
}
#include "SHResourceManager.hpp"

View File

@ -0,0 +1,171 @@
/************************************************************************************//*!
\file SHResourceManager.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 21, 2022
\brief Contains the definition of the function templates of the
SHResourceManager static class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Primary Include
#include "SHResourceManager.h"
// Project Includes
#include "Assets/SHAssetManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Tools/SHLog.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Loading Functions */
/*-----------------------------------------------------------------------------------*/
template<typename ResourceType>
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
{
// Check if it is an unsupported type
if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>)
{
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
}
/* Attempt to get existing loaded asset */
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
return Handle<ResourceType>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */
// Meshes
if constexpr (std::is_same_v<ResourceType, SHMesh>)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId);
if (assetData == nullptr)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHMesh> meshHandle = gfxSystem->AddMesh
(
assetData->vertexPosition.size(),
assetData->vertexPosition.data(),
assetData->texCoords.data(),
assetData->vertexTangent.data(),
assetData->vertexNormal.data(),
assetData->indices.size(),
assetData->indices.data()
);
Handle genericHandle = Handle(meshHandle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle;
}
// Textures
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId);
if (assetData == nullptr)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHTexture> texHandle = gfxSystem->AddTexture
(
assetData->numBytes,
assetData->pixelData,
assetData->width,
assetData->height,
assetData->format,
assetData->mipOffsets
);
typedHandleMap.get().emplace(assetId, Handle(texHandle));
return texHandle;
}
}
template<typename ResourceType>
void SHResourceManager::Unload(Handle<ResourceType> assetId)
{
// Check if it is an unsupported type
if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>)
{
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
}
/* Attempt to get existing loaded asset */
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
{
// Dispose
Handle handle = typedHandleMap.get()[assetId];
Handle<ResourceType> typedHandle = static_cast<Handle<ResourceType>>(handle);
typedHandle.Free();
typedAssetIdMap.get().erase(handle);
typedHandleMap.get().erase(assetId);
}
else
{
// There's nothing to remove
SHLog::Warning("[SHResourceManager] Attempted to unload an invalid resource. Ignoring.");
}
}
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
template<typename T>
static std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
if (typedAssetIdMap.get().contains(GENERIC_HANDLE))
{
return typedAssetIdMap.GetId()[GENERIC_HANDLE];
}
return {};
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
template<typename ResourceType>
std::pair<SHResourceManager::AssetHandleMapRef, SHResourceManager::HandleAssetMapRef> SHResourceManager::getAssetHandleMap()
{
const std::type_index TYPE = typeid(ResourceType);
if (!handlesMap.contains(TYPE))
{
handlesMap.emplace(TYPE, AssetHandleMap{});
assetIdMap.emplace(TYPE, HandleAssetMap{});
typedFreeFuncMap.emplace
(
TYPE,
[TYPE](AssetID assetId)
{
static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[TYPE][assetId]).Free();
}
);
}
return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE]));
}
}

View File

@ -115,34 +115,22 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Script Serialisation Functions */ /* Script Serialisation Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
std::string SHScriptEngine::SerialiseScripts(EntityID entity) const bool SHScriptEngine::SerialiseScripts(EntityID entity, YAML::Node& scriptsNode) const
{ {
// Create buffer needed to store serialised script data
constexpr int BUFFER_SIZE = 10240;
std::unique_ptr<char> buffer { new char[BUFFER_SIZE] };
std::memset(buffer.get(), 0, BUFFER_SIZE);
// Attempt to serialise the script // Attempt to serialise the script
std::string result; if (csScriptsSerialiseYaml(entity, &scriptsNode))
if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE)) return true;
{
result = std::string(buffer.get());
}
else
{
SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts as string buffer is too small!");
}
// Return an empty string since we failed to serialise SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts for entity #{}.", entity);
return result; return false;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Script Serialisation Functions */ /* Script Serialisation Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const bool SHScriptEngine::DeserialiseScripts(EntityID entity, const YAML::Node& scriptsNode) const
{ {
csScriptDeserialise(entity, yaml.c_str()); return csScriptsDeserialiseYaml(entity, &scriptsNode);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -380,30 +368,18 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"RemoveAllScriptsImmediately" "RemoveAllScriptsImmediately"
); );
/*csScriptsSerialise = dotNet.GetFunctionPtr<CsScriptSerialiseFuncPtr> csScriptsSerialiseYaml = dotNet.GetFunctionPtr<CsScriptSerialiseYamlFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"SerialiseScripts" "SerialiseScripts"
); );
csScriptsSerialiseYaml = dotNet.GetFunctionPtr<CsScriptSerialiseYamlFuncPtr> csScriptsDeserialiseYaml = dotNet.GetFunctionPtr<CsScriptDeserialiseYamlFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"SerialiseScriptsYaml" "DeserialiseScripts"
); );
csScriptDeserialise = dotNet.GetFunctionPtr<CsScriptDeserialiseFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"DeserialiseScript"
);
csScriptDeserialiseYaml = dotNet.GetFunctionPtr<CsScriptSerialiseYamlFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"SerialiseScriptsYaml"
);*/
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr> csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,

View File

@ -13,7 +13,8 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <filesystem> #include <filesystem>
// External Dependencies
#include <yaml-cpp/yaml.h>
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "SHDotNetRuntime.h" #include "SHDotNetRuntime.h"
@ -141,23 +142,26 @@ namespace SHADE
/* Script Serialisation Functions */ /* Script Serialisation Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/// <summary> /// <summary>
/// Generates a JSON string that represents the set of Scripts attached to the /// Performs serialization of all scripts for the specified entity into the
/// specified Entity. /// YAML::Node specified. This node will contain all serialised scripts after
/// calling this function.
/// </summary> /// </summary>
/// <param name="entity"> The Entity to Serialise.</param> /// <param name="entity">The Entity to Serialise.</param>
/// <returns> /// <param name="scriptsNode">
/// String that represents the set of scripts attached to the specified Entity. /// YAML Node that will store the serialised scripts.
/// </returns> /// </param>
std::string SerialiseScripts(EntityID entity) const; /// <return>True if successfully serialised.</return>
bool SerialiseScripts(EntityID entity, YAML::Node& scriptsNode) const;
/// <summary> /// <summary>
/// Loads the specified JSON string and creates a Script for the specified Entity /// Creates scripts and sets fields for the specified Entity based on the specified
/// based on the specified JSON string. /// YAML node.
/// </summary> /// </summary>
/// <param name="entity">The Entity to deserialise a Script on to.</param> /// <param name="entity">The Entity to deserialise a Script on to.</param>
/// <param name="yaml"> /// <param name="scriptsNode">
/// The YAML string that represents the Script to load into the Entity. /// YAML Node that contains the serialised script data.
/// </param> /// </param>
void DeserialiseScript(EntityID entity, const std::string& yaml) const; /// <return>True if successfully deserialised.</return>
bool DeserialiseScripts(EntityID entity, const YAML::Node& scriptsNode) const;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Script Editor Functions */ /* Script Editor Functions */
@ -207,14 +211,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
using CsFuncPtr = void(*)(void); using CsFuncPtr = void(*)(void);
using CsScriptManipFuncPtr = bool(*)(EntityID, const char*); using CsScriptManipFuncPtr = bool(*)(EntityID, const char*);
using CsScriptBasicFuncPtr = void(*)(EntityID); using CsScriptBasicFuncPtr = void(*)(EntityID);
using CsScriptOptionalFuncPtr = void(*)(EntityID, bool); using CsScriptOptionalFuncPtr = void(*)(EntityID, bool);
using CsScriptSerialiseFuncPtr = bool(*)(EntityID, char*, int); using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*);
using CsScriptDeserialiseFuncPtr = bool(*)(EntityID, const char*); using CsScriptDeserialiseYamlFuncPtr = bool(*)(EntityID, const void*);
using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*); using CsScriptEditorFuncPtr = void(*)(EntityID);
using CsScriptEditorFuncPtr = void(*)(EntityID);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constants */ /* Constants */
@ -228,31 +231,29 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
SHDotNetRuntime dotNet { false }; SHDotNetRuntime dotNet { false };
// Function Pointers to CLR Code // Function Pointers to CLR Code
// - Engine Lifecycle // - Engine Lifecycle
CsFuncPtr csEngineInit = nullptr; CsFuncPtr csEngineInit = nullptr;
CsFuncPtr csEngineLoadScripts = nullptr; CsFuncPtr csEngineLoadScripts = nullptr;
CsFuncPtr csEngineUnloadScripts = nullptr; CsFuncPtr csEngineUnloadScripts = nullptr;
CsFuncPtr csEngineReloadScripts = nullptr; CsFuncPtr csEngineReloadScripts = nullptr;
CsFuncPtr csEngineExit = nullptr; CsFuncPtr csEngineExit = nullptr;
// - Scripts Store // - Scripts Store
CsFuncPtr csScriptsFrameSetUp = nullptr; CsFuncPtr csScriptsFrameSetUp = nullptr;
CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; CsFuncPtr csScriptsExecuteFixedUpdate = nullptr;
CsFuncPtr csScriptsExecuteUpdate = nullptr; CsFuncPtr csScriptsExecuteUpdate = nullptr;
CsFuncPtr csScriptsExecuteLateUpdate = nullptr; CsFuncPtr csScriptsExecuteLateUpdate = nullptr;
CsFuncPtr csScriptsFrameCleanUp = nullptr; CsFuncPtr csScriptsFrameCleanUp = nullptr;
CsScriptManipFuncPtr csScriptsAdd = nullptr; CsScriptManipFuncPtr csScriptsAdd = nullptr;
CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr;
CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr; CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr;
CsScriptSerialiseFuncPtr csScriptsSerialise = nullptr; CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr;
CsScriptDeserialiseFuncPtr csScriptDeserialise = nullptr; CsScriptDeserialiseYamlFuncPtr csScriptsDeserialiseYaml = nullptr;
CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr;
CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr;
// - Editor // - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
CsFuncPtr csEditorUndo = nullptr; CsFuncPtr csEditorUndo = nullptr;
CsFuncPtr csEditorRedo = nullptr; CsFuncPtr csEditorRedo = nullptr;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Event Handler Functions */ /* Event Handler Functions */

View File

@ -13,6 +13,8 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Physics/Components/SHRigidBodyComponent.h" #include "Physics/Components/SHRigidBodyComponent.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Scripting/SHScriptEngine.h"
namespace SHADE namespace SHADE
{ {
@ -52,11 +54,13 @@ namespace SHADE
out << YAML::EndSeq; out << YAML::EndSeq;
} }
static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID) static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
{ {
if (!node[EIDNode]) EntityID eid = MAX_EID;
return; if(!node)
EntityID eid = node[EIDNode].as<EntityID>(); return eid;
if (node[EIDNode])
eid = node[EIDNode].as<EntityID>();
std::string name = "Default"; std::string name = "Default";
if (node[EntityNameNode]) if (node[EntityNameNode])
name = node[EntityNameNode].as<std::string>(); name = node[EntityNameNode].as<std::string>();
@ -77,6 +81,10 @@ namespace SHADE
} }
} }
} }
// Deserialise scripts
if (node[ScriptsNode])
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, node[ScriptsNode]);
} }
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
@ -111,7 +119,11 @@ namespace SHADE
{ {
DeserializeEntity(it, (*it), createdEntities); DeserializeEntity(it, (*it), createdEntities);
} }
if(createdEntities.empty())
{
SHLOG_ERROR("Failed to create entities from deserializaiton")
return;
}
//Initialize Entity //Initialize Entity
auto entityVecIt = createdEntities.begin(); auto entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it) for (auto it = entities.begin(); it != entities.end(); ++it)
@ -130,17 +142,19 @@ namespace SHADE
} }
} }
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities) std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept
{ {
YAML::Emitter out; YAML::Emitter out;
YAML::Node node; YAML::Node node;
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
out << YAML::BeginSeq;
for (auto const& eid : entities) for (auto const& eid : entities)
{ {
auto entityNode = sceneGraph.GetNode(eid); auto entityNode = sceneGraph.GetNode(eid);
EmitEntity(entityNode, out); EmitEntity(entityNode, out);
} }
return std::basic_string<char>(out.c_str()); out << YAML::EndSeq;
return std::string(out.c_str());
} }
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
@ -157,7 +171,7 @@ namespace SHADE
node = YAML::Null; node = YAML::Null;
return node; return node;
} }
node.SetStyle(YAML::EmitterStyle::Block); node.SetStyle(YAML::EmitterStyle::Block);
node[EIDNode] = eid; node[EIDNode] = eid;
node[EntityNameNode] = entity->name; node[EntityNameNode] = entity->name;
node[IsActiveNode] = sceneNode->IsActive(); node[IsActiveNode] = sceneNode->IsActive();
@ -179,9 +193,38 @@ namespace SHADE
components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody); components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
} }
node[ComponentsNode] = components; node[ComponentsNode] = components;
YAML::Node scripts;
SHSystemManager::GetSystem<SHScriptEngine>()->SerialiseScripts(eid, scripts);
node[ScriptsNode] = scripts;
return node; return node;
} }
EntityID SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept
{
if(data.empty())
return MAX_EID;
YAML::Node entities = YAML::Load(data.c_str());
EntityID eid{MAX_EID};
std::vector<EntityID> createdEntities;
for(auto it = entities.begin(); it != entities.end(); ++it)
{
eid = DeserializeEntity(it, *it, createdEntities, parentEID);
}
if(createdEntities.empty())
{
SHLOG_ERROR("Failed to create entities from deserializaiton")
return MAX_EID;
}
auto entityVecIt = createdEntities.begin();
for(auto it = entities.begin(); it != entities.end(); ++it)
{
InitializeEntity(*it, *entityVecIt++);
}
return eid;
}
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>
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode) std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
{ {

View File

@ -21,6 +21,7 @@ namespace SHADE
constexpr const char* EIDNode = "EID"; constexpr const char* EIDNode = "EID";
constexpr const char* IsActiveNode = "IsActive"; constexpr const char* IsActiveNode = "IsActive";
constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
constexpr const char* ScriptsNode = "Scripts";
struct SH_API SHSerialization struct SH_API SHSerialization
{ {
@ -28,14 +29,18 @@ namespace SHADE
static void SerializeSceneToFile(std::filesystem::path const& path); static void SerializeSceneToFile(std::filesystem::path const& path);
static std::string SerializeSceneToString(); static std::string SerializeSceneToString();
static void SerializeSceneToEmitter(YAML::Emitter& out); static void SerializeSceneToEmitter(YAML::Emitter& out);
static void DeserializeSceneFromFile(std::filesystem::path const& path); static void DeserializeSceneFromFile(std::filesystem::path const& path);
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities);
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept;
static void SerializeEntityToFile(std::filesystem::path const& path); static void SerializeEntityToFile(std::filesystem::path const& path);
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode); static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
private: private:
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);

View File

@ -0,0 +1,49 @@
#include "SHpch.h"
#include "SHClipboardUtilities.h"
namespace SHADE
{
void SHClipboardUtilities::WriteToClipboard(std::string const& str) noexcept
{
if(str.empty())
return;
HWND const hwnd = GetDesktopWindow();
OpenClipboard(hwnd);
EmptyClipboard();
auto const size = str.size() + 1;
const HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
if(hGlobal)
{
std::memcpy(GlobalLock(hGlobal), str.c_str(), size);
GlobalUnlock(hGlobal);
SetClipboardData(CF_TEXT, hGlobal);
}
else
{
SHLOG_ERROR("Failed to write to clipboard: {}", str.c_str())
}
CloseClipboard();
GlobalFree(hGlobal);
}
std::string const SHClipboardUtilities::GetDataFromClipboard() noexcept
{
HWND const hwnd = GetDesktopWindow();
if(!OpenClipboard(hwnd))
{
SHLOG_ERROR("Failed to open clipboard")
return std::string();
}
if(HANDLE const dataHandle = GetClipboardData(CF_TEXT); dataHandle)
{
std::string data(static_cast<char*>(GlobalLock(dataHandle)));
GlobalUnlock(dataHandle);
CloseClipboard();
return data;
}
CloseClipboard();
return std::string();
}
}

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