Add Editor Features - Transform Gizmo #105

Merged
srishamharan merged 14 commits from SP3-4-editor_fix into main 2022-10-21 20:58:48 +08:00
74 changed files with 2002 additions and 402 deletions
Showing only changes of commit 5bd5cec9d4 - Show all commits

View File

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

View File

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

View File

@ -9,8 +9,8 @@ Size=1920,1036
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,89
Size=286,971
Pos=0,120
Size=225,940
Collapsed=0
DockId=0x00000004,0
@ -20,23 +20,29 @@ Size=400,400
Collapsed=0
[Window][Inspector]
Pos=1494,24
Size=426,1036
Pos=1686,24
Size=234,1036
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,24
Size=286,63
Size=225,94
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=227,24
Size=1457,1036
Collapsed=0
DockId=0x00000002,0
[Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1492,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=286,1036 Split=Y Selected=0xE096E5AE
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=140,63 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=140,971 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1204,1036 CentralNode=1
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=426,1036 Selected=0xE7039252
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252

View File

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

View File

@ -104,10 +104,10 @@ namespace Sandbox
//TODO: REMOVE AFTER PRESENTATION
//SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
//SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
//SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
//TODO: REMOVE AFTER PRESENTATION
@ -125,6 +125,8 @@ namespace Sandbox
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC();
SHAssetManager::Load();
}
void SBApplication::Update(void)
@ -139,17 +141,10 @@ namespace Sandbox
SHSceneManager::UpdateSceneManager();
#ifdef SHEDITOR
if(editor->editorState == SHEditor::State::PLAY)
#endif
SHSceneManager::SceneUpdate(0.016f);
#ifdef SHEDITOR
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{
editor->PollPicking();
}
#else
SHSystemManager::RunRoutines(false, 0.016f);
#endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking();
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
@ -165,6 +160,7 @@ namespace Sandbox
SHSceneManager::Exit();
SHSystemManager::Exit();
SHAssetManager::Unload();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,6 +21,8 @@
//#==============================================================#
#include <imgui.h>
#include "Serialization/SHSerialization.h"
namespace SHADE
{
@ -181,6 +183,10 @@ namespace SHADE
editor->selectedEntities.clear();
editor->selectedEntities.push_back(eid);
}
if(ImGui::Selectable("Copy"))
{
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
}
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{
SHEntityManager::DestroyEntity(eid);

View File

@ -17,6 +17,8 @@
#include <imgui_internal.h>
#include <rttr/type>
#include "Serialization/SHSerialization.h"
namespace SHADE
{
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -73,7 +75,14 @@ namespace SHADE
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::Selectable("Save"))
{
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
}
if(ImGui::Selectable("Load"))
{
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
}
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Edit"))

View File

@ -54,6 +54,7 @@ namespace SHADE
windowPos = {wndPos.x, wndPos.y};
OnPosChange();
}
isWindowHovered = ImGui::IsWindowHovered();
return result;
}

View File

@ -24,6 +24,7 @@ namespace SHADE
virtual void Update();
virtual void Exit();
bool isOpen;
bool isWindowHovered;
std::string_view windowName;
protected:
virtual bool Begin();
@ -34,5 +35,6 @@ namespace SHADE
ImGuiIO& io;
SHVec2 windowSize;
SHVec2 windowPos;
SHVec2 viewportMousePos;
};//class SHEditorWindow
}//namespace SHADE

View File

@ -2,7 +2,11 @@
#include "SHEditorViewport.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.hpp"
#include "Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
namespace SHADE
{
@ -24,8 +28,27 @@ namespace SHADE
{
DrawMenuBar();
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
//ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
auto const& descriptorSet = gfxSystem->GetPostOffscreenRenderSystem()->GetDescriptorSetGroup()->GetVkHandle()[0];
auto mousePos = ImGui::GetMousePos();
auto cursorPos = ImGui::GetCursorScreenPos();
viewportMousePos = {mousePos.x - cursorPos.x, mousePos.y - cursorPos.y};
gfxSystem->GetMousePickSystem ()->SetViewportMousePos (viewportMousePos);
//if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
//{
// auto eid = gfxSystem->GetMousePickSystem ()->GetPickedEntity();
// if(eid != MAX_EID)
// {
// auto editor = SHSystemManager::GetSystem<SHEditor>();
// editor->selectedEntities.clear();
// editor->selectedEntities.push_back(eid);
// if (const auto hierarchyPanel = SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>())
// {
// hierarchyPanel->SetScrollTo(eid);
// }
// }
//}
ImGui::Image((ImTextureID)descriptorSet, ImGui::GetWindowSize());
}
ImGui::End();
}
@ -39,6 +62,11 @@ namespace SHADE
{
SHEditorWindow::OnResize();
//Get graphics system to resize swapchain image
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto pos = ImGui::GetCursorPos();
//windowCursorPos = {}
gfxSystem->PrepareResize(static_cast<uint32_t>(windowSize.x), static_cast<uint32_t>(windowSize.y));
}
void SHEditorViewport::OnPosChange()

View File

@ -304,10 +304,11 @@ namespace SHADE
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
//auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
auto const& renderers = gfxSystem->GetEditorViewport()->GetRenderers();
SHASSERT(!renderers.empty(), "No Renderers available")
auto renderGraph = renderers[0]->GetRenderGraph();
auto renderGraph = renderers[SHGraphicsConstants::RenderGraphIndices::EDITOR]->GetRenderGraph();
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
@ -336,7 +337,8 @@ namespace SHADE
{
if (auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>())
{
if (!ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
auto viewportWindow = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>();
if (viewportWindow->isWindowHovered && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
EntityID pickedEID = gfxSystem->GetMousePickSystem()->GetPickedEntity();
if(pickedEID == MAX_EID)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -172,7 +172,7 @@ namespace SHADE
// write sampler and image view
auto& [view, sampler, layout] = imageViewsAndSamplers[i];
writeInfo.descImageInfos[i].imageView = view->GetImageView();
writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
writeInfo.descImageInfos[i].sampler = sampler ? sampler->GetVkSampler() : nullptr;
writeInfo.descImageInfos[i].imageLayout = layout;
}
}

View File

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

View File

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

View File

@ -550,10 +550,9 @@ namespace SHADE
}
Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept
Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers/* = false*/) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex, bindings);
return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex, bindings, genImmutableSamplers);
}
Handle<SHVkDescriptorPool> SHVkLogicalDevice::CreateDescriptorPools(const SHVkDescriptorPool::Config& config /*= {}*/) noexcept

View File

@ -186,7 +186,7 @@ namespace SHADE
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
Handle<SHVkFramebuffer> CreateFramebuffer (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept;
Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings, bool genImmutableSamplers = false) noexcept;
Handle<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept;
Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,

View File

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

View File

@ -25,6 +25,12 @@ namespace SHADE
struct SHGraphicsConstants
{
public:
struct RenderGraphIndices
{
static constexpr uint32_t WORLD = 0;
static constexpr uint32_t EDITOR = 0;
};
struct DescriptorSetIndex
{
/***************************************************************************/

View File

@ -36,11 +36,9 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
#pragma region INIT_EXIT
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
void SHGraphicsSystem::InitBoilerplate(void) noexcept
{
/*-----------------------------------------------------------------------*/
/* BACKEND BOILERPLATE */
@ -51,7 +49,7 @@ namespace SHADE
// Get Physical Device and Construct Logical Device
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
device = SHVkInstance::CreateLogicalDevice({ SHQueueParams(SH_Q_FAM::GRAPHICS, SH_QUEUE_SELECT::DEDICATED), SHQueueParams(SH_Q_FAM::TRANSFER, SH_QUEUE_SELECT::DEDICATED) }, physicalDevice);
// Construct surface
surface = device->CreateSurface(window->GetHWND());
@ -71,7 +69,15 @@ namespace SHADE
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true);
#ifdef SHEDITOR
//PrepareResize(1, 1, SHVec2(0, 0));
#else
PrepareResize(resizeWidth, resizeHeight, SHVec2(0, 0));
#endif
});
window->RegisterWindowCloseCallback([&](void)
@ -106,11 +112,12 @@ namespace SHADE
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
}
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
{
/*-----------------------------------------------------------------------*/
/* MIDDLE END SETUP
/* MIDDLE END SETUP
- Viewports
- Renderer
- Render graph in renderers
@ -118,8 +125,8 @@ namespace SHADE
- Default vertex input state
- Global data
/*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize();
SHGraphicsGlobalData::Init(device);
// Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>();
@ -131,12 +138,12 @@ namespace SHADE
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
worldViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer
worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
{
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
@ -144,44 +151,27 @@ namespace SHADE
// Initialize world render graph
worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Present"}, {}); // no predecessors
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
//First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Present");
gBufferWriteSubpass->AddColorOutput("Scene");
gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL);
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
// We do this to just transition our scene layout to shader read
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
sceneLayoutTransitionSubpass->AddInput("Scene");
// TODO: Use macro to add this node when SH_EDITOR is enabled
auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
// Generate world render graph
worldRenderGraph->Generate();
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
// Create Debug Renderers
/*debugScreenRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugScreenRenderer->SetCamera(screenCamera);
debugWorldRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugWorldRenderer->SetCamera(worldCamera);*/
// Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
@ -198,17 +188,97 @@ namespace SHADE
cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
}
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
{
SHGraphicsGlobalData::Init(device);
InitSceneRenderGraph();
#ifdef SHEDITOR
InitEditorRenderGraph();
#endif
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
}
void SHGraphicsSystem::InitSubsystems(void) noexcept
{
mousePickSystem = resourceManager.Create<SHMousePickSystem>();
std::vector<Handle<SHVkCommandPool>> cmdPools;
cmdPools.reserve(swapchain->GetNumImages());
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
// Register the post offscreen render to the system
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
}
#ifdef SHEDITOR
void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept
{
auto windowDims = window->GetWindowSize();
// Create Default Viewport
editorViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 1.0f));
// Get render graph from viewport editor renderer
editorRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
editorRenderGraph->Init(device, swapchain);
editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
auto imguiNode = editorRenderGraph->AddNode("ImGui Node", { "Present"}, {});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
// Generate world render graph
editorRenderGraph->Generate();
// Add world renderer to default viewport
editorRenderer = editorViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], editorRenderGraph);
editorRenderer->SetCamera(worldCamera);
}
#endif
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
InitBoilerplate();
InitMiddleEnd();
InitSubsystems();
}
void SHGraphicsSystem::Exit(void)
{
}
#pragma endregion INIT_EXIT
#pragma region LIFECYCLE
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
@ -227,12 +297,6 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -328,14 +392,7 @@ namespace SHADE
}
}
}
void SHGraphicsSystem::Exit(void)
{
}
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
@ -400,12 +457,6 @@ namespace SHADE
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
@ -417,9 +468,7 @@ namespace SHADE
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{
HandleResize();
}
}
@ -427,6 +476,10 @@ namespace SHADE
renderContext.AdvanceFrame();
}
#pragma endregion LIFECYCLE
#pragma region ADD_REMOVE_BUILD
Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport)
{
// Create the viewport
@ -537,36 +590,9 @@ namespace SHADE
);
}
void SHGraphicsSystem::HandleResize(void) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(windowDims.first, windowDims.second);
defaultViewport->SetWidth(static_cast<float>(windowDims.first));
defaultViewport->SetHeight(static_cast<float>(windowDims.second));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
}
#pragma endregion ADD_REMOVE
#pragma region ROUTINES
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
@ -638,5 +664,62 @@ namespace SHADE
renderable.ResetChangedFlag();
}
}
#pragma endregion ROUTINES
#pragma region MISC
void SHGraphicsSystem::PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
resizeWidth = newWidth;
resizeHeight = newHeight;
renderContext.SetIsResized(true);
}
void SHGraphicsSystem::HandleResize(void) noexcept
{
device->WaitIdle();
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
graphSemaphores[0].Free();
graphSemaphores[1].Free();
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(resizeWidth, resizeHeight);
editorRenderGraph->HandleResize(windowDims.first, windowDims.second);
mousePickSystem->HandleResize();
postOffscreenRender->HandleResize();
worldViewport->SetWidth(static_cast<float>(resizeWidth));
worldViewport->SetHeight(static_cast<float>(resizeHeight));
worldCamera->SetPerspective(90.0f, static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.0f, 100.0f);
for (auto& semaHandle : graphSemaphores)
semaHandle = device->CreateSemaphore();
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
}
#pragma endregion MISC
}

View File

@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
#include "../Textures/SHTextureLibrary.h"
#include "../Textures/SHVkSamplerCache.h"
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
namespace SHADE
{
@ -66,6 +67,16 @@ namespace SHADE
/***********************************************************************************/
class SH_API SHGraphicsSystem : public SHSystem
{
private:
void InitBoilerplate (void) noexcept;
void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept;
#ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept;
#endif
public:
class SH_API BeginRoutine final : public SHSystemRoutine
{
@ -251,6 +262,7 @@ namespace SHADE
/***************************************************************************/
void BuildTextures();
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept;
void AwaitGraphicsExecution();
@ -262,20 +274,25 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Getters (Temporary) */
/*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> GetDevice() const { return device; }
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
Handle<SHViewport> GetDefaultViewport() const {return defaultViewport;}
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
Handle<SHVkLogicalDevice> GetDevice() const { return device; }
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
Handle<SHViewport> GetDefaultViewport() const {return worldViewport;}
#ifdef SHEDITOR
Handle<SHViewport> GetEditorViewport () const {return editorViewport;};
#endif
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
@ -296,13 +313,19 @@ namespace SHADE
SHWindow* window = nullptr;
// Middle End Resources
ResourceManager resourceManager;
ResourceManager resourceManager;
SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary;
SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache;
// Viewports
Handle<SHViewport> defaultViewport; // Whole screen
#ifdef SHEDITOR
Handle<SHViewport> editorViewport;
Handle<SHRenderer> editorRenderer;
Handle<SHRenderGraph> editorRenderGraph;
#endif
Handle<SHViewport> worldViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers
@ -327,5 +350,9 @@ namespace SHADE
// Sub systems
Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
uint32_t resizeWidth;
uint32_t resizeHeight;
};
}

View File

@ -6,11 +6,16 @@
#include "Graphics/Synchronization/SHVkFence.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
namespace SHADE
{
void SHMousePickSystem::Init(Handle<SHVkLogicalDevice> logicalDevice, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept
void SHMousePickSystem::Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept
{
logicalDevice = device;
pickedEID = MAX_EID;
// Create command buffers
for (auto& pool : cmdPools)
{
@ -20,13 +25,7 @@ namespace SHADE
// assign the attachment
entityIDAttachment = eidAttachment;
// Create the fence
afterCopyFence = logicalDevice->CreateFence();
uint32_t bufferSize = entityIDAttachment->GetWidth() * eidAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
// Create the buffer
imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
HandleResize();
}
void SHMousePickSystem::Run(Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept
@ -54,13 +53,36 @@ namespace SHADE
// wait for the copy to be done
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
int mouseX = 0, mouseY = 0;
SHInputManager::GetMouseWindowPosition(&mouseX, &mouseY);
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(mouseY * entityIDAttachment->GetWidth() + mouseX);
}
}
void SHMousePickSystem::HandleResize(void) noexcept
{
if (afterCopyFence)
{
afterCopyFence->Reset();
afterCopyFence.Free();
}
if (imageDataDstBuffer)
imageDataDstBuffer.Free();
// Create the fence
afterCopyFence = logicalDevice->CreateFence();
uint32_t bufferSize = entityIDAttachment->GetWidth() * entityIDAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
// Create the buffer
imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
}
void SHMousePickSystem::SetViewportMousePos(SHVec2 vpMousePos) noexcept
{
viewportMousePos = vpMousePos;
}
EntityID SHMousePickSystem::GetPickedEntity(void) const noexcept
{
return pickedEID;

View File

@ -13,10 +13,13 @@ namespace SHADE
class SHVkFence;
class SHVkQueue;
class SHVkBuffer;
class SHViewport;
class SHMousePickSystem
{
private:
Handle<SHVkLogicalDevice> logicalDevice;
//! Handle to the render graph resource that will contain the entity IDs
Handle<SHRenderGraphResource> entityIDAttachment;
@ -30,17 +33,24 @@ namespace SHADE
Handle<SHVkBuffer> imageDataDstBuffer;
//! eid picked from screen
EntityID pickedEID = MAX_EID;
EntityID pickedEID;
//! mouse position relative to the viewport window displaying the world
SHVec2 viewportMousePos;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init(Handle<SHVkLogicalDevice> logicalDevice, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept;
void Init(Handle<SHVkLogicalDevice> device, std::span<Handle<SHVkCommandPool>> cmdPools, Handle<SHRenderGraphResource> eidAttachment) noexcept;
void Run (Handle<SHVkQueue> queue, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
void SetViewportMousePos (SHVec2 vpMousePos) noexcept;
EntityID GetPickedEntity (void) const noexcept;
};

View File

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

View File

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

View File

@ -75,12 +75,15 @@ namespace SHADE
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
if (camera)
{
cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
}
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,10 +45,10 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: logicalDevice {logicalDevice}
, swapchain{ swapchain }
, resourceType{ type }
, resourceTypeFlags{ }
, resourceFormat{ format }
, images{}
, imageViews{}
@ -58,52 +58,10 @@ namespace SHADE
, resourceName{ name }
{
// If the resource type is an arbitrary image and not swapchain image
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)
{
imageAspectFlags = vk::ImageAspectFlags{};
usage = usageFlags;
resourceTypeFlags |= static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT);
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType)
{
case SH_ATT_DESC_TYPE::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break;
case SH_ATT_DESC_TYPE::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break;
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break;
}
// The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
// just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
}
else // if swapchain image resource
{
// Prepare image view details
SHImageViewDetails viewDetails
{
@ -126,6 +84,65 @@ namespace SHADE
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
}
}
else // if swapchain image resource
{
imageAspectFlags = vk::ImageAspectFlags{};
usage = usageFlags;
for (auto& type : typeFlags)
{
// store the flags
resourceTypeFlags |= static_cast<uint32_t>(type);
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (type)
{
case SH_ATT_DESC_TYPE_FLAGS::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::INPUT:
usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
{
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
return;
}
}
}
// The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
// just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
}
}
/***************************************************************************/
@ -141,7 +158,7 @@ namespace SHADE
/***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
: resourceName{ std::move(rhs.resourceName) }
, resourceType{ std::move(rhs.resourceType) }
, resourceTypeFlags{ std::move(rhs.resourceTypeFlags) }
, images{ std::move(rhs.images) }
, imageViews{ std::move(rhs.imageViews) }
, resourceFormat{ std::move(rhs.resourceFormat) }
@ -149,6 +166,7 @@ namespace SHADE
, height{ rhs.height }
, mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
, swapchain {rhs.swapchain}
{
}
@ -172,7 +190,7 @@ namespace SHADE
return *this;
resourceName = std::move(rhs.resourceName);
resourceType = std::move(rhs.resourceType);
resourceTypeFlags = std::move(rhs.resourceTypeFlags);
images = std::move(rhs.images);
imageViews = std::move(rhs.imageViews);
resourceFormat = std::move(rhs.resourceFormat);
@ -180,6 +198,7 @@ namespace SHADE
height = rhs.height;
mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
swapchain = rhs.swapchain;
return *this;
}
@ -202,7 +221,7 @@ namespace SHADE
width = newWidth;
height = newHeight;
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
if ((resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0)
{
// prepare image view details
SHImageViewDetails viewDetails
@ -299,4 +318,9 @@ namespace SHADE
return height;
}
Handle<SHVkImageView> SHRenderGraphResource::GetImageView(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
{
return imageViews [index];
}
}

View File

@ -16,6 +16,8 @@ namespace SHADE
class SHVkCommandBuffer;
class SHVkBuffer;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
class SH_API SHRenderGraphResource
{
private:
@ -32,7 +34,7 @@ namespace SHADE
std::string resourceName;
//! Used for initializing image layouts
SH_ATT_DESC_TYPE resourceType;
SHRenderGraphResourceFlags resourceTypeFlags;
//! The resource itself (this is a vector because if the resource happens
//! to be a swapchain image, then we need however many frames in flight).
@ -67,7 +69,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept;
@ -82,9 +84,10 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Format GetResourceFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept;
vk::Format GetResourceFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept;
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;

View File

@ -23,7 +23,7 @@ namespace SHADE
*/
/***************************************************************************/
SHSubpass::SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
: resourceAttachmentMapping{ mapping }
, ptrToResources{ resources }
, parentNode{ parent }
@ -55,6 +55,8 @@ namespace SHADE
, inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, ptrToResources{ rhs.ptrToResources }
, descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) }
{
}
@ -83,6 +85,8 @@ namespace SHADE
inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
ptrToResources = rhs.ptrToResources;
descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
return *this;
}
@ -120,18 +124,18 @@ namespace SHADE
*/
/***************************************************************************/
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType) noexcept
{
vk::ImageLayout imageLayout;
switch (attachmentDescriptionType)
{
case SH_ATT_DESC_TYPE::DEPTH:
case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
break;
case SH_ATT_DESC_TYPE::STENCIL:
case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
break;
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
break;
default:

View File

@ -62,7 +62,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -71,7 +71,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
// Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddInput(std::string resourceToReference) noexcept;
// Runtime functions

View File

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

View File

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

View File

@ -59,9 +59,9 @@ namespace SHADE
SparseSet();
~SparseSet() = default;
// Disallow moving or copying
SparseSet(const SparseSet&) = delete;
SparseSet(SparseSet&&) = delete;
//// Disallow moving or copying
//SparseSet(const SparseSet&) = delete;
//SparseSet(SparseSet&&) = delete;
/*-----------------------------------------------------------------------------*/
/* Usage Functions */

View File

@ -115,7 +115,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*---------------------------------------------------------------------------------*/
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const
std::string SHScriptEngine::SerialiseScripts(EntityID entity) const
{
// Create buffer needed to store serialised script data
constexpr int BUFFER_SIZE = 10240;
@ -124,7 +124,7 @@ namespace SHADE
// Attempt to serialise the script
std::string result;
if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE))
if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE))
{
result = std::string(buffer.get());
}
@ -140,9 +140,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const
void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const
{
csScriptDeserialise(entity.GetEID(), yaml.c_str());
csScriptDeserialise(entity, yaml.c_str());
}
/*-----------------------------------------------------------------------------------*/

View File

@ -148,7 +148,7 @@ namespace SHADE
/// <returns>
/// String that represents the set of scripts attached to the specified Entity.
/// </returns>
std::string SerialiseScripts(const SHEntity& entity) const;
std::string SerialiseScripts(EntityID entity) const;
/// <summary>
/// Loads the specified JSON string and creates a Script for the specified Entity
/// based on the specified JSON string.
@ -157,7 +157,7 @@ namespace SHADE
/// <param name="yaml">
/// The YAML string that represents the Script to load into the Entity.
/// </param>
void DeserialiseScript(const SHEntity& entity, const std::string& yaml) const;
void DeserialiseScript(EntityID entity, const std::string& yaml) const;
/*-----------------------------------------------------------------------------*/
/* Script Editor Functions */

View File

@ -0,0 +1,220 @@
#include "SHpch.h"
#include "SHSerializationHelper.hpp"
#include "SHSerialization.h"
#include <yaml-cpp/yaml.h>
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
#include "Tools/SHException.h"
#include "Assets/SHAssetManager.h"
#include <fstream>
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Physics/Components/SHRigidBodyComponent.h"
namespace SHADE
{
void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path)
{
YAML::Emitter out;
SerializeSceneToEmitter(out);
std::ofstream file(path.c_str());
if (file.good())
{
file << out.c_str();
file.close();
}
}
std::string SHSerialization::SerializeSceneToString()
{
YAML::Emitter out;
SerializeSceneToEmitter(out);
return std::basic_string<char>(out.c_str());
}
void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out)
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto root = sceneGraph.GetRoot();
SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node.");
auto const& children = root->GetChildren();
out << YAML::BeginSeq;
auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
sceneGraph.Traverse(pred);
//out << SerializeEntityToNode(child);
out << YAML::EndSeq;
}
static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
{
if (!node[EIDNode])
return;
EntityID eid = node[EIDNode].as<EntityID>();
std::string name = "Default";
if (node[EntityNameNode])
name = node[EntityNameNode].as<std::string>();
//Compile component IDs
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
createdEntities.push_back(eid);
if (node[NumberOfChildrenNode])
{
if(const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
{
++it;
for (int i = 0; i < numOfChildren; ++i)
{
DeserializeEntity(it, (*it), createdEntities, eid);
if((i + 1) < numOfChildren)
++it;
}
}
}
}
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
{
//TODO:Shift to using XQ's FileIO
std::ifstream iFile;
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string fileContent = "";
try
{
// Open file
// Read file's buffer contents into streams
iFile.open(path);
std::stringstream fileStream;
fileStream << iFile.rdbuf();
fileContent = fileStream.str();
// Close file handler
iFile.close();
}
catch (std::ifstream::failure e)
{
SHLOG_ERROR("Could not read file");
}
YAML::Node entities = YAML::Load(fileContent);
std::vector<EntityID> createdEntities{};
//Create Entities
for (auto it = entities.begin(); it != entities.end(); ++it)
{
DeserializeEntity(it, (*it), createdEntities);
}
//Initialize Entity
auto entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
InitializeEntity(*it, *entityVecIt++);
}
}
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
{
out << SerializeEntityToNode(entityNode);
auto const& children = entityNode->GetChildren();
for(auto const& child : children)
{
EmitEntity(child, out);
}
}
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities)
{
YAML::Emitter out;
YAML::Node node;
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for (auto const& eid : entities)
{
auto entityNode = sceneGraph.GetNode(eid);
EmitEntity(entityNode, out);
}
return std::basic_string<char>(out.c_str());
}
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
{
}
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
{
YAML::Node node;
auto eid = sceneNode->GetEntityID();
auto entity = SHEntityManager::GetEntityByID(eid);
if (!sceneNode || !entity)
{
node = YAML::Null;
return node;
}
node.SetStyle(YAML::EmitterStyle::Block);
node[EIDNode] = eid;
node[EntityNameNode] = entity->name;
node[IsActiveNode] = sceneNode->IsActive();
auto const& children = sceneNode->GetChildren();
node[NumberOfChildrenNode] = children.size();
YAML::Node components;
if (const auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
components[rttr::type::get<SHTransformComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform);
}
if (const auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(eid))
{
components[rttr::type::get<SHRenderable>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable);
}
if (const auto rigidbody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
}
node[ComponentsNode] = components;
return node;
}
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
{
if (componentNode[rttr::type::get<ComponentType>().get_name().data()])
return { SHFamilyID<SHComponent>::GetID<ComponentType>() };
else
return std::nullopt;
}
std::vector<ComponentTypeID> SHSerialization::GetComponentIDList(YAML::Node const& componentsNode)
{
std::vector<ComponentTypeID> componentIDList;
auto id = GetComponentID<SHTransformComponent>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
id = GetComponentID<SHRenderable>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
id = GetComponentID<SHRigidBodyComponent>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
return componentIDList;
}
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
{
auto const componentsNode = entityNode[ComponentsNode];
if (!componentsNode)
return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "SH_API.h"
#include <string>
#include <filesystem>
#include <ECS_Base/Components/SHComponent.h>
namespace YAML
{
class Emitter;
class Node;
}
namespace SHADE
{
class SHSceneNode;
constexpr const char* ComponentsNode = "Components";
constexpr const char* EntityNameNode = "Name";
constexpr const char* EIDNode = "EID";
constexpr const char* IsActiveNode = "IsActive";
constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
struct SH_API SHSerialization
{
//TODO: change paths to resource ID
static void SerializeSceneToFile(std::filesystem::path const& path);
static std::string SerializeSceneToString();
static void SerializeSceneToEmitter(YAML::Emitter& out);
static void DeserializeSceneFromFile(std::filesystem::path const& path);
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities);
static void SerializeEntityToFile(std::filesystem::path const& path);
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
private:
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
};
}

View File

@ -0,0 +1,204 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
#include <yaml-cpp/yaml.h>
#include <rttr/registration>
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
namespace SHADE
{
struct SHSerializationHelper
{
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static std::string SerializeComponentToString(ComponentType* component)
{
return std::string();
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
{
}
static YAML::Node RTTRToNode(const rttr::variant& var)
{
YAML::Node node;
auto varType = var.get_type();
if (varType == rttr::type::get<SHVec4>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec4>().x;
node["Y"] = var.convert<SHVec4>().y;
node["Z"] = var.convert<SHVec4>().z;
node["W"] = var.convert<SHVec4>().w;
}
else if (varType == rttr::type::get<SHVec3>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
node["Z"] = var.convert<SHVec3>().z;
}
else if (varType == rttr::type::get<SHVec2>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
}
else if (varType.is_arithmetic())
{
bool ok = false;
if (varType == rttr::type::get<bool>())
node = var.to_bool();
else if (varType == rttr::type::get<int8_t>())
node = var.to_int8(&ok);
else if (varType == rttr::type::get<int16_t>())
node = var.to_int16(&ok);
else if (varType == rttr::type::get<int32_t>())
node = var.to_int32(&ok);
else if (varType == rttr::type::get<int64_t>())
node = var.to_int64(&ok);
else if (varType == rttr::type::get<uint8_t>())
node = var.to_uint8(&ok);
else if (varType == rttr::type::get<uint16_t>())
node = var.to_uint16(&ok);
else if (varType == rttr::type::get<uint32_t>())
node = var.to_uint32(&ok);
else if (varType == rttr::type::get<uint64_t>())
node = var.to_uint64(&ok);
else if (varType == rttr::type::get<float>())
node = var.to_float(&ok);
else if (varType == rttr::type::get<double>())
node = var.to_double(&ok);
//else if (varType == rttr::type::get<char>()) //same as uint8_t
// node = var.to_uint8();
}
else if (varType.is_enumeration())
{
bool ok = false;
auto result = var.to_string(&ok);
if (ok)
{
node = var.to_string();
}
else
{
ok = false;
auto value = var.to_uint64(&ok);
if (ok)
node = value;
else
node = YAML::Null;
}
}
else
{
auto properties = var.get_type().get_properties();
for (auto property : properties)
{
node[property.get_name().data()] = RTTRToNode(property.get_value(var));
}
}
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node SerializeComponentToNode(ComponentType* component)
{
YAML::Node node{};
if (!component)
return node;
auto componentType = rttr::type::get<ComponentType>();
node = RTTRToNode(*component);
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode)
{
auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>())
{
SHVec4 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>(), propertyNode["W"].as<float>() };
prop.set_value(component, vec);
}
else if (propType == rttr::type::get<SHVec3>())
{
SHVec3 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>() };
prop.set_value(component, vec);
}
else if (propType == rttr::type::get<SHVec2>())
{
SHVec2 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>() };
prop.set_value(component, vec);
}
else if (propType.is_arithmetic())
{
bool ok = false;
if (propType == rttr::type::get<bool>())
prop.set_value(component, propertyNode.as<bool>());
else if (propType == rttr::type::get<int8_t>())
prop.set_value(component, propertyNode.as<int8_t>());
else if (propType == rttr::type::get<int16_t>())
prop.set_value(component, propertyNode.as<int16_t>());
else if (propType == rttr::type::get<int32_t>())
prop.set_value(component, propertyNode.as<int32_t>());
else if (propType == rttr::type::get<int64_t>())
prop.set_value(component, propertyNode.as<int64_t>());
else if (propType == rttr::type::get<uint8_t>())
prop.set_value(component, propertyNode.as<uint8_t>());
else if (propType == rttr::type::get<uint16_t>())
prop.set_value(component, propertyNode.as<uint16_t>());
else if (propType == rttr::type::get<uint32_t>())
prop.set_value(component, propertyNode.as<uint32_t>());
else if (propType == rttr::type::get<uint64_t>())
prop.set_value(component, propertyNode.as<uint64_t>());
else if (propType == rttr::type::get<float>())
prop.set_value(component, propertyNode.as<float>());
else if (propType == rttr::type::get<double>())
prop.set_value(component, propertyNode.as<double>());
}
else if (propType.is_enumeration())
{
auto enumAlign = prop.get_enumeration();
prop.set_value(component, enumAlign.name_to_value(propertyNode.as<std::string>()));
}
else
{
auto properties = propType.get_properties();
for (auto property : properties)
{
InitializeProperty(component, property, propertyNode[property.get_name().data()]);
}
}
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (componentsNode.IsNull())
return;
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{
if (componentNode[prop.get_name().data()])
{
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
}
}
}
};
}

View File

@ -29,6 +29,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/Command/SHCommand.hpp"
#include "TooltipAttribute.hxx"
// Using Directives
using namespace System;
@ -48,17 +49,17 @@ using namespace System::Collections::Generic;
/// <param name="MANAGED_TYPE">The managed type of the object to edit.</param>
/// <param name="NATIVE_TYPE">The native type of the object to edit.</param>
/// <param name="FUNC">The SHEditorUI:: function to use for editing.</param>
#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC) \
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \
field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \
} \
#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC) \
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered))\
{ \
field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \
} \
/// <summary>
/// Macro expansion that is used in renderFieldInInspector() to check the type of a field
/// named "field" against the specified type and if it matches, retrieves the value of
@ -76,7 +77,7 @@ using namespace System::Collections::Generic;
{ \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered)) \
{ \
field->SetValue(object, Convert::ToCLI(val)); \
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \
@ -196,6 +197,8 @@ namespace SHADE
}
void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object)
{
bool isHovered = false;
if RENDER_FIELD (Int16, int, InputInt)
else if RENDER_FIELD (Int32, int, InputInt)
else if RENDER_FIELD (Int64, int, InputInt)
@ -244,6 +247,15 @@ namespace SHADE
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
}
}
// Check if the field has a specific attribute
TooltipAttribute^ toolTip = hasAttribute<TooltipAttribute^>(field);
if (toolTip && isHovered)
{
SHEditorUI::BeginTooltip();
SHEditorUI::Text(Convert::ToNative(toolTip->Description));
SHEditorUI::EndTooltip();
}
}
void Editor::renderScriptContextMenu(Entity entity, Script^ script)
@ -274,4 +286,24 @@ namespace SHADE
SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCLICommand>()));
}
generic<typename Attribute>
Attribute Editor::hasAttribute(System::Reflection::FieldInfo^ field)
{
array<System::Object^>^ attributes = field->GetCustomAttributes(true);
for each (System::Object^ attrib in attributes)
{
try
{
Attribute attribute = safe_cast<Attribute>(attrib);
if (attribute != nullptr)
return attribute;
}
catch (System::InvalidCastException^)
{
continue;
}
}
// Failed to find
return Attribute{};
}
}

View File

@ -23,7 +23,7 @@ namespace SHADE
/// <summary>
/// Static class for Editor-related functions
/// </summary>
public ref class Editor abstract sealed
private ref class Editor abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
@ -48,7 +48,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Undoes the last script inspector change if there is any.
/// </summary>
static void Undo();
/// <summary>
/// Redoes the last script inspector change if there is any.
/// </summary>
static void Redo();
private:
@ -86,5 +92,7 @@ namespace SHADE
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
generic<typename Attribute> where Attribute : System::Attribute
static Attribute hasAttribute(System::Reflection::FieldInfo^ field);
};
}

View File

@ -1,27 +1,34 @@
/************************************************************************************//*!
\file SerializeFieldAttribute.cxx
\file TooltipAttribute.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 5, 2021
\brief Contains the definition of the functions of the managed SerializeField
Attribute class.
\date Oct 18, 2022
\brief Contains the definition of the functions of the managed Tooltip Attribute
class.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "SerializeFieldAttribute.hxx"
#include "TooltipAttribute.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
System::String^ TooltipAttribute::Description::get()
{
return desc;
}
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SerializeField::SerializeField()
TooltipAttribute::TooltipAttribute(System::String^ description)
: desc { description }
{}
}

View File

@ -0,0 +1,53 @@
/************************************************************************************//*!
\file TooltipAttribute.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 18, 2022
\brief Contains the definition of the managed Tooltip Attribute class with
the declaration of functions for working with it.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
namespace SHADE
{
/// <summary>
/// Simple attribute to mark that a field in a Script should be serialised.
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class TooltipAttribute : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Description that is to be shown in the Tooltip.
/// </summary>
property System::String^ Description
{
System::String^ get();
}
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Constructor for a Tooltip attribute that fills in the description.
/// </summary>
/// <param name="description">Text to be shown when a field is hovered.</param>
TooltipAttribute(System::String^ description);
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
System::String^ desc;
};
}

View File

@ -0,0 +1,102 @@
/************************************************************************************//*!
\file Input.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 16, 2022
\brief Contains the definition of the managed Input static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "Input.hxx"
#include "Utility/Convert.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
Vector3 Input::MousePosition::get()
{
int x, y;
SHInputManager::GetMouseWindowPosition(&x, &y);
return Vector3(static_cast<float>(x), static_cast<float>(y), 0.0f);
}
int Input::MouseScrollDelta::get()
{
return SHInputManager::GetMouseWheelVerticalDelta();
}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
bool Input::GetKey(KeyCode key)
{
return SHInputManager::GetKey(static_cast<SHInputManager::SH_KEYCODE>(key));
}
bool Input::GetKeyDown(KeyCode key)
{
return SHInputManager::GetKeyDown(static_cast<SHInputManager::SH_KEYCODE>(key));
}
bool Input::GetKeyUp(KeyCode key)
{
return SHInputManager::GetKeyUp(static_cast<SHInputManager::SH_KEYCODE>(key));
}
bool Input::GetMouseButton(MouseCode mouseButton)
{
return SHInputManager::GetKey(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
}
bool Input::GetMouseButtonDown(MouseCode mouseButton)
{
return SHInputManager::GetKeyDown(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
}
bool Input::GetMouseButtonUp(MouseCode mouseButton)
{
return SHInputManager::GetKeyUp(static_cast<SHInputManager::SH_KEYCODE>(mouseButton));
}
/*---------------------------------------------------------------------------------*/
/* Cursor Functions */
/*---------------------------------------------------------------------------------*/
void Input::SetMousePosition(Vector2 pos)
{
SHInputManager::SetMouseWindowPosition
(
static_cast<int>(pos.x),
static_cast<int>(pos.y)
);
}
/*---------------------------------------------------------------------------------*/
/* Time Functions */
/*---------------------------------------------------------------------------------*/
double Input::GetKeyHeldTime(KeyCode key)
{
return SHInputManager::GetKeyHeldTime(static_cast<SHInputManager::SH_KEYCODE>(key));
}
double Input::GetKeyReleasedTime(KeyCode key)
{
return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
}
double Input::GetMouseHeldTime(MouseCode key)
{
return SHInputManager::GetKeyHeldTime(static_cast<SHInputManager::SH_KEYCODE>(key));
}
double Input::GetMouseReleasedTime(MouseCode key)
{
return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
}
}

View File

@ -0,0 +1,325 @@
/************************************************************************************//*!
\file Input.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 16, 2022
\brief Contains the definition of the managed Input static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
#include "Input/SHInputManager.h"
#include "Math/Vector2.hxx"
#include "Math/Vector3.hxx"
namespace SHADE
{
/// <summary>
/// Static class responsible for providing access to Input-related functionality.
/// </summary>
public ref class Input abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Represents the available supported keycodes that can be passed into the
/// key-based Input functions.
/// </summary>
enum class KeyCode : int
{
Space = static_cast<int>(SHInputManager::SH_KEYCODE::SPACE),
//Apostrophe = static_cast<int>(SHInputManager::SH_KEYCODE::APOSTROPHE),
Comma = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_COMMA),
Minus = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_MINUS),
Period = static_cast<int>(SHInputManager::SH_KEYCODE::OEM_PERIOD),
//Slash = static_cast<int>(SHInputManager::SH_KEYCODE::SLASH),
Key0 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_0),
Key1 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_1),
Key2 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_2),
Key3 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_3),
Key4 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_4),
Key5 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_5),
Key6 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_6),
Key7 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_7),
Key8 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_8),
Key9 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMBER_9),
//Semicolon = static_cast<int>(SHInputManager::SH_KEYCODE::SEMICOLON),
//Equal = static_cast<int>(SHInputManager::SH_KEYCODE::EQUAL),
A = static_cast<int>(SHInputManager::SH_KEYCODE::A),
B = static_cast<int>(SHInputManager::SH_KEYCODE::B),
C = static_cast<int>(SHInputManager::SH_KEYCODE::C),
D = static_cast<int>(SHInputManager::SH_KEYCODE::D),
E = static_cast<int>(SHInputManager::SH_KEYCODE::E),
F = static_cast<int>(SHInputManager::SH_KEYCODE::F),
G = static_cast<int>(SHInputManager::SH_KEYCODE::G),
H = static_cast<int>(SHInputManager::SH_KEYCODE::H),
I = static_cast<int>(SHInputManager::SH_KEYCODE::I),
J = static_cast<int>(SHInputManager::SH_KEYCODE::J),
K = static_cast<int>(SHInputManager::SH_KEYCODE::K),
L = static_cast<int>(SHInputManager::SH_KEYCODE::L),
M = static_cast<int>(SHInputManager::SH_KEYCODE::M),
N = static_cast<int>(SHInputManager::SH_KEYCODE::N),
O = static_cast<int>(SHInputManager::SH_KEYCODE::O),
P = static_cast<int>(SHInputManager::SH_KEYCODE::P),
Q = static_cast<int>(SHInputManager::SH_KEYCODE::Q),
R = static_cast<int>(SHInputManager::SH_KEYCODE::R),
S = static_cast<int>(SHInputManager::SH_KEYCODE::S),
T = static_cast<int>(SHInputManager::SH_KEYCODE::T),
U = static_cast<int>(SHInputManager::SH_KEYCODE::U),
V = static_cast<int>(SHInputManager::SH_KEYCODE::V),
W = static_cast<int>(SHInputManager::SH_KEYCODE::W),
X = static_cast<int>(SHInputManager::SH_KEYCODE::X),
Y = static_cast<int>(SHInputManager::SH_KEYCODE::Y),
Z = static_cast<int>(SHInputManager::SH_KEYCODE::Z),
//LeftBracket = static_cast<int>(SHInputManager::SH_KEYCODE::LEFTBRACKET),
//BackSlash = static_cast<int>(SHInputManager::SH_KEYCODE::BACKSLASH),
//RightBracket = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHTBRACKET),
//GraveAccent = static_cast<int>(SHInputManager::SH_KEYCODE::GRAVEACCENT),
//WORLD1 = static_cast<int>(SHInputManager::SH_KEYCODE::WORLD1),
//WORLD2 = static_cast<int>(SHInputManager::SH_KEYCODE::WORLD2),
/* Function keys */
Escape = static_cast<int>(SHInputManager::SH_KEYCODE::ESCAPE),
Enter = static_cast<int>(SHInputManager::SH_KEYCODE::ENTER),
Tab = static_cast<int>(SHInputManager::SH_KEYCODE::TAB),
Backspace = static_cast<int>(SHInputManager::SH_KEYCODE::BACKSPACE),
Insert = static_cast<int>(SHInputManager::SH_KEYCODE::INSERT),
Delete = static_cast<int>(SHInputManager::SH_KEYCODE::DEL),
Right = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ARROW),
Left = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ARROW),
Down = static_cast<int>(SHInputManager::SH_KEYCODE::DOWN_ARROW),
Up = static_cast<int>(SHInputManager::SH_KEYCODE::UP_ARROW),
PageUp = static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_UP),
PageDown = static_cast<int>(SHInputManager::SH_KEYCODE::PAGE_DOWN),
Home = static_cast<int>(SHInputManager::SH_KEYCODE::HOME),
End = static_cast<int>(SHInputManager::SH_KEYCODE::END),
CapsLock = static_cast<int>(SHInputManager::SH_KEYCODE::CAPS_LOCK),
ScrollLock = static_cast<int>(SHInputManager::SH_KEYCODE::SCROLL_LOCK),
NumLock = static_cast<int>(SHInputManager::SH_KEYCODE::NUM_LOCK),
PrintScreen = static_cast<int>(SHInputManager::SH_KEYCODE::PRINT_SCREEN),
Pause = static_cast<int>(SHInputManager::SH_KEYCODE::PAUSE),
F1 = static_cast<int>(SHInputManager::SH_KEYCODE::F1),
F2 = static_cast<int>(SHInputManager::SH_KEYCODE::F2),
F3 = static_cast<int>(SHInputManager::SH_KEYCODE::F3),
F4 = static_cast<int>(SHInputManager::SH_KEYCODE::F4),
F5 = static_cast<int>(SHInputManager::SH_KEYCODE::F5),
F6 = static_cast<int>(SHInputManager::SH_KEYCODE::F6),
F7 = static_cast<int>(SHInputManager::SH_KEYCODE::F7),
F8 = static_cast<int>(SHInputManager::SH_KEYCODE::F8),
F9 = static_cast<int>(SHInputManager::SH_KEYCODE::F9),
F10 = static_cast<int>(SHInputManager::SH_KEYCODE::F10),
F11 = static_cast<int>(SHInputManager::SH_KEYCODE::F11),
F12 = static_cast<int>(SHInputManager::SH_KEYCODE::F12),
F13 = static_cast<int>(SHInputManager::SH_KEYCODE::F13),
F14 = static_cast<int>(SHInputManager::SH_KEYCODE::F14),
F15 = static_cast<int>(SHInputManager::SH_KEYCODE::F15),
F16 = static_cast<int>(SHInputManager::SH_KEYCODE::F16),
F17 = static_cast<int>(SHInputManager::SH_KEYCODE::F17),
F18 = static_cast<int>(SHInputManager::SH_KEYCODE::F18),
F19 = static_cast<int>(SHInputManager::SH_KEYCODE::F19),
F20 = static_cast<int>(SHInputManager::SH_KEYCODE::F20),
F21 = static_cast<int>(SHInputManager::SH_KEYCODE::F21),
F22 = static_cast<int>(SHInputManager::SH_KEYCODE::F22),
F23 = static_cast<int>(SHInputManager::SH_KEYCODE::F23),
F24 = static_cast<int>(SHInputManager::SH_KEYCODE::F24),
/* Keypad */
KeyPad0 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_0),
KeyPad1 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_1),
KeyPad2 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_2),
KeyPad3 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_3),
KeyPad4 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_4),
KeyPad5 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_5),
KeyPad6 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_6),
KeyPad7 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_7),
KeyPad8 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_8),
KeyPad9 = static_cast<int>(SHInputManager::SH_KEYCODE::NUMPAD_9),
//KeyPadDecimal = static_cast<int>(SHInputManager::SH_KEYCODE::KPDECIMAL),
//KeyPadDivide = static_cast<int>(SHInputManager::SH_KEYCODE::KPDIVIDE),
//KeyPadMultiply = static_cast<int>(SHInputManager::SH_KEYCODE::KPMULTIPLY),
//KeyPadSubtract = static_cast<int>(SHInputManager::SH_KEYCODE::KPSUBTRACT),
//KeyPadAdd = static_cast<int>(SHInputManager::SH_KEYCODE::KPADD),
//KeyPadEnter = static_cast<int>(SHInputManager::SH_KEYCODE::KPENTER),
//KeyPadEqual = static_cast<int>(SHInputManager::SH_KEYCODE::KEYPAD),
Shift = static_cast<int>(SHInputManager::SH_KEYCODE::SHIFT),
LeftControl = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_CTRL),
LeftAlt = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_ALT),
LeftSuper = static_cast<int>(SHInputManager::SH_KEYCODE::LEFT_WINDOWS),
RightShift = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_SHIFT),
RightControl = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_CTRL),
RightAlt = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_ALT),
RightSuper = static_cast<int>(SHInputManager::SH_KEYCODE::RIGHT_WINDOWS),
/* Gamepad */
JoystickA = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_A),
JoystickB = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_B),
JoystickX = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_X),
JoystickY = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_Y),
JoystickLeftBumper = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFTSHOULDER),
JoystickRightBumper = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHTSHOULDER),
JoystickLeftTrigger = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFTTRIGGER),
JoystickRightTrigger = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHTTRIGGER),
JoystickDPadUp = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_UP),
JoystickDPadDown = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_DOWN),
JoystickDPadLeft = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_LEFT),
JoystickDPadRight = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_DPAD_RIGHT),
JoystickMenu = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_MENU),
JoystickView = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_VIEW),
JoystickLeftStick = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_LEFT_THUMBSTICK_BUTTON),
JoystickRightStick = static_cast<int>(SHInputManager::SH_KEYCODE::GAMEPAD_RIGHT_THUMBSTICK_BUTTON),
/* Unity Gamepad Mappings */
JoystickButton0 = JoystickA,
JoystickButton1 = JoystickB,
JoystickButton2 = JoystickX,
JoystickButton3 = JoystickY,
JoystickButton4 = JoystickLeftBumper,
JoystickButton5 = JoystickRightBumper,
JoystickButton6 = JoystickView,
JoystickButton7 = JoystickMenu,
JoystickButton8 = JoystickLeftStick,
JoystickButton9 = JoystickRightStick
};
/// <summary>
/// Represents the available supported mouse keycodes that can be passed into the
/// mouse-button-based Input functions.
/// </summary>
enum class MouseCode : int
{
LeftButton = static_cast<int>(SHInputManager::SH_KEYCODE::LMB),
RightButton = static_cast<int>(SHInputManager::SH_KEYCODE::RMB),
MiddleButton = static_cast<int>(SHInputManager::SH_KEYCODE::MMB),
Button3 = static_cast<int>(SHInputManager::SH_KEYCODE::XMB1),
Button4 = static_cast<int>(SHInputManager::SH_KEYCODE::XMB2)
};
/*-----------------------------------------------------------------------------*/
/* Properites */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Mouse position in screen coordinates relative to the top left of the window.
/// This value is a Vector3 for compatibility with functions that have Vector3
/// arguments. The z component of the Vector3 is always 0
/// </summary>
static property Vector3 MousePosition
{
Vector3 get();
}
/// <summary>
/// Amnount of vertical mouse scroll in this frame.
/// </summary>
static property int MouseScrollDelta
{
int get();
}
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Checks if a specified key is being held down.
/// This will also be true if GetKeyDown() is true.
/// </summary>
/// <param name="key">KeyCode of the key to check.</param>
/// <returns>True while the user holds down the key specified.</returns>
static bool GetKey(KeyCode key);
/// <summary>
/// Checks if a specified key is pressed and was not pressed before.
/// </summary>
/// <param name="key">KeyCode of the key to check.</param>
/// <returns>
/// True during the frame the user starts pressing down the key specified.
/// </returns>
static bool GetKeyDown(KeyCode key);
/// <summary>
/// Checks if a specified key is no longer pressed pressed and was pressed
/// before.
/// </summary>
/// <param name="key">KeyCode of the key to check.</param>
/// <returns>
/// True during the frame the user releases the key identified by name.
/// </returns>
static bool GetKeyUp(KeyCode key);
/// <summary>
/// Checks if a specified mouse button is being held down.
/// This will also be true if GetMouseButtonDown() is true.
/// </summary>
/// <param name="mouseButton">MouseCode of the mouse button to check.</param>
/// <returns>True while the user holds down the mouse button specified.</returns>
static bool GetMouseButton(MouseCode mouseButton);
/// <summary>
/// Checks if a specified mouse button is pressed and was not pressed before.
/// </summary>
/// <param name="mouseButton">MouseCode of the mouse button to check.</param>
/// <returns>
/// True during the frame the user pressed the given mouse button.
/// </returns>
static bool GetMouseButtonDown(MouseCode mouseButton);
/// <summary>
/// Checks if a specified mouse button is no longer pressed and was pressed
/// before.
/// </summary>
/// <param name="mouseButton">MouseCode of the mouse button to check.</param>
/// <returns>
/// True during the frame the user releases the given mouse button.
/// </returns>
static bool GetMouseButtonUp(MouseCode mouseButton);
/*-----------------------------------------------------------------------------*/
/* Cursor Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Sets the position of the mouse cursor relative to the top left corner of the
/// window.
/// </summary>
/// <param name="pos">
/// Position of the mouse in window pixel coordinates to set.
/// </param>
static void SetMousePosition(Vector2 pos);
/*-----------------------------------------------------------------------------*/
/* Timing Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Retrieves the duration that the specified key has been held or was last held
/// for.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns>
static double GetKeyHeldTime(KeyCode key);
/// <summary>
/// Retrieves the duration that the specified key has not been held or was last
/// not been held for.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns>
static double GetKeyReleasedTime(KeyCode key);
/// <summary>
/// Retrieves the duration that the specified key has been held or was last held
/// for.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns>
static double GetMouseHeldTime(MouseCode mouseButton);
/// <summary>
/// Retrieves the duration that the specified key has not been held or was last
/// not been held for.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns>
static double GetMouseReleasedTime(MouseCode mouseButton);
};
}

View File

@ -21,15 +21,6 @@ namespace SHADE
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class SerializeField : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Default Constructor
/// </summary>
SerializeField();
};
{};
}

View File

@ -3,8 +3,12 @@ using System;
public class RaccoonShowcase : Script
{
public double RotateSpeed = 1.0;
public Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
[SerializeField]
[Tooltip("Speed of the rotation in radians per second.")]
private double RotateSpeed = 1.0;
[SerializeField]
[Tooltip("Speed of the scaling in radians per second around each axis.")]
private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
private Transform Transform;
private double rotation = 0.0;
private Vector3 scale = Vector3.Zero;

View File

@ -3,7 +3,9 @@ using System;
public class RaccoonSpin : Script
{
public double RotateSpeed = 1.0;
[SerializeField]
[Tooltip("Speed of the rotation in radians per second.")]
private double RotateSpeed = 1.0;
private double rotation = 0.0;
private Transform Transform;
public RaccoonSpin(GameObject gameObj) : base(gameObj) { }