SP3-2 Cleaned Up Physics System #85

Merged
direnbharwani merged 11 commits from SP3-2-Physics into main 2022-10-13 18:32:25 +08:00
59 changed files with 972 additions and 244 deletions
Showing only changes of commit 877507284e - Show all commits

View File

@ -145,6 +145,9 @@ namespace Sandbox
SHADE::SHSystemManager::RunRoutines(false, 0.016f); SHADE::SHSystemManager::RunRoutines(false, 0.016f);
} }
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
} }

View File

@ -118,7 +118,7 @@ namespace Sandbox
renderable.SetMaterial(customMat); renderable.SetMaterial(customMat);
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f }); transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f });
transform.SetLocalScale({ 5.0f, 5.0f, 5.0f }); transform.SetLocalScale({ 5.0f, 5.0f, 5.0f });
@ -159,7 +159,7 @@ namespace Sandbox
renderableShowcase.SetMaterial(customMat); renderableShowcase.SetMaterial(customMat);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });

View File

@ -163,8 +163,8 @@ project "SHADE_Engine"
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
excludes excludes
{ {
"%{prj.location}/src/Editor/**.cpp", -- "%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h", -- "%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp", -- "%{prj.location}/src/Editor/**.hpp",
} }
links{"fmodstudio_vc.lib", "fmod_vc.lib"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -17,7 +17,8 @@ namespace SHADE
SHTexture::PixelChannel const * pixelData; SHTexture::PixelChannel const * pixelData;
SHTextureAsset() SHTextureAsset()
: numBytes{ 0 }, : compiled{ false },
numBytes{ 0 },
width{ 0 }, width{ 0 },
height{ 0 }, height{ 0 },
format{ SHTexture::TextureFormat::eUndefined }, format{ SHTexture::TextureFormat::eUndefined },
@ -25,7 +26,8 @@ namespace SHADE
{} {}
SHTextureAsset(SHTextureAsset const& rhs) SHTextureAsset(SHTextureAsset const& rhs)
: numBytes{ rhs.numBytes }, : compiled{ false },
numBytes{ rhs.numBytes },
width{ rhs.width }, width{ rhs.width },
height{ rhs.height }, height{ rhs.height },
format{ rhs.format }, format{ rhs.format },

View File

@ -91,8 +91,8 @@ namespace SHADE
} }
} }
result.header.vertexCount = result.vertexPosition.size(); result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
result.header.indexCount = result.indices.size(); result.header.indexCount = static_cast<uint32_t>(result.indices.size());
result.header.meshName = mesh.mName.C_Str(); result.header.meshName = mesh.mName.C_Str();
return result; return result;

View File

@ -83,10 +83,10 @@ namespace SHADE
std::vector<uint32_t> mipOff(file.GetMipCount()); std::vector<uint32_t> mipOff(file.GetMipCount());
for (auto i{0}; i < file.GetMipCount(); ++i) for (size_t i{0}; i < file.GetMipCount(); ++i)
{ {
mipOff[i] = totalBytes; mipOff[i] = static_cast<uint32_t>(totalBytes);
totalBytes += file.GetImageData(i, 0)->m_memSlicePitch; totalBytes += file.GetImageData(static_cast<uint32_t>(i), 0)->m_memSlicePitch;
} }
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes]; SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
@ -94,7 +94,7 @@ namespace SHADE
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData())); //pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
asset.compiled = false; asset.compiled = false;
asset.numBytes = totalBytes; asset.numBytes = static_cast<uint32_t>(totalBytes);
asset.width = file.GetWidth(); asset.width = file.GetWidth();
asset.height = file.GetHeight(); asset.height = file.GetHeight();
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true); asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);

View File

@ -72,12 +72,13 @@ namespace SHADE
AssetType type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string().c_str()); AssetType type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string().c_str());
std::string folder; std::string folder;
switch (type) //TODO Implement asset type generation
{ //switch (type)
default: //{
//TODO:ASSERT UNSUPPORTED FILE TYPE //default:
return std::filesystem::path(); // //TODO:ASSERT UNSUPPORTED FILE TYPE
} // return std::filesystem::path();
//}
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string()); return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
} }
@ -108,12 +109,13 @@ namespace SHADE
meta.type = type; meta.type = type;
std::string folder; std::string folder;
switch (type) //TODO implement folder choosing
{ //switch (type)
default: //{
folder = ""; //default:
break; // folder = "";
} // break;
//}
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) }; AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
SHAssetMetaHandler::WriteMetaData(meta); SHAssetMetaHandler::WriteMetaData(meta);

View File

@ -122,7 +122,7 @@ namespace SHADE
break; break;
default: default:
void; break;
} }
metaFile.close(); metaFile.close();

View File

@ -5,9 +5,13 @@
//#==============================================================# //#==============================================================#
#include <functional> #include <functional>
#include "SH_API.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE namespace SHADE
{ {
class SHBaseCommand class SH_API SHBaseCommand
{ {
public: public:
virtual ~SHBaseCommand() = default; virtual ~SHBaseCommand() = default;
@ -48,4 +52,20 @@ namespace SHADE
T newValue; T newValue;
SetterFunction set; SetterFunction set;
}; };
class SH_API SHCLICommand : SHBaseCommand
{
public:
SHCLICommand() = default;
void Execute() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RedoScriptInspectorChanges();
}
void Undo() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->UndoScriptInspectorChanges();
}
};
}//namespace SHADE }//namespace SHADE

View File

@ -27,6 +27,11 @@ namespace SHADE
} }
} }
void SHCommandManager::RegisterCommand(CommandPtr commandPtr)
{
undoStack.push(commandPtr);
}
void SHCommandManager::UndoCommand() void SHCommandManager::UndoCommand()
{ {
if (undoStack.empty()) if (undoStack.empty())

View File

@ -9,10 +9,11 @@
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "SHCommand.hpp" #include "SHCommand.hpp"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
class SHCommandManager class SH_API SHCommandManager
{ {
public: public:
//#==============================================================# //#==============================================================#
@ -22,6 +23,7 @@ namespace SHADE
using CommandStack = std::stack<CommandPtr>; using CommandStack = std::stack<CommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false); static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(CommandPtr commandPtr);
static void UndoCommand(); static void UndoCommand();
static void RedoCommand(); static void RedoCommand();
static std::size_t GetUndoStackSize(); static std::size_t GetUndoStackSize();

View File

@ -18,6 +18,8 @@
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "AudioSystem/SHAudioSystem.h" #include "AudioSystem/SHAudioSystem.h"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
namespace SHADE namespace SHADE
{ {
@ -70,23 +72,28 @@ namespace SHADE
{ {
DrawComponent(renderableComponent); DrawComponent(renderableComponent);
} }
if(auto testComponent = SHComponentManager::GetComponent_s<SHComponent_ENUM>(eid)) if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
{ {
DrawComponent(testComponent); DrawComponent(colliderComponent);
} }
if(auto rigidbodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
DrawComponent(rigidbodyComponent);
}
ImGui::Separator();
// Render Scripts
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RenderScriptsInInspector(eid);
ImGui::Separator(); ImGui::Separator();
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
{ {
DrawAddComponentButton<SHTransformComponent>(eid); DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid); DrawAddComponentButton<SHRenderable>(eid);
DrawAddComponentButton<SHComponent_ENUM>(eid); DrawAddComponentButton<SHColliderComponent>(eid);
DrawAddComponentButton<SHRigidBodyComponent>(eid);
ImGui::EndMenu(); ImGui::EndMenu();
} }
// Render Scripts
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RenderScriptsInInspector(eid);
} }
ImGui::End(); ImGui::End();
} }

View File

@ -2,7 +2,6 @@
#include "SHFileSystem.h" #include "SHFileSystem.h"
#include "fileapi.h" #include "fileapi.h"
#include <filesystem> #include <filesystem>
#include <cassert>
#include <queue> #include <queue>
namespace SHADE namespace SHADE
@ -28,7 +27,10 @@ namespace SHADE
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size()); auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
assert(count < FOLDER_MAX_COUNT, "Max subfolders reached\n"); if (count >= FOLDER_MAX_COUNT)
{
SHLOG_ERROR("Max subfolder reached: {}\n", name);
}
auto const location = static_cast<FolderLocation>(count); auto const location = static_cast<FolderLocation>(count);
@ -37,7 +39,10 @@ namespace SHADE
return location; return location;
} }
assert(folders.contains(here), "Folder creation location does not exist/invalid\n"); if (!folders.contains(here))
{
SHLOG_ERROR("Folder creation location does not exist/invalid: {}\n", here);
}
auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size()); auto const count = static_cast<FolderCounter>(folders[here]->subFolders.size());
@ -45,7 +50,11 @@ namespace SHADE
location <<= FOLDER_BIT_ALLOCATE; location <<= FOLDER_BIT_ALLOCATE;
location |= count; location |= count;
assert(count < FOLDER_MAX_COUNT, "Max subfolders reached\n"); if (count >= FOLDER_MAX_COUNT)
{
SHLOG_ERROR("Max subfolder reached: {}\n", name);
}
CreateFolder(folders[0]->path, here, location, name); CreateFolder(folders[0]->path, here, location, name);
return location; return location;
@ -53,7 +62,10 @@ namespace SHADE
bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept bool SHFileSystem::DeleteFolder(FolderPointer location) noexcept
{ {
assert(folders.contains(location->id), "Delete target does not exist/invalid.\n"); if (!folders.contains(location->id))
{
SHLOG_ERROR("Delete target does not exist/invalid: {}\n", location->name);
}
for (auto const& subFolder : folders[location->id]->subFolders) for (auto const& subFolder : folders[location->id]->subFolders)
{ {
@ -116,10 +128,11 @@ namespace SHADE
FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept
{ {
assert(
CreateDirectoryA(path.c_str(), nullptr), if (!CreateDirectoryA(path.c_str(), nullptr))
"Failed to create folder\n" {
); SHLOG_ERROR("Failed to create folder: {}\n", path);
}
folders[location] = std::make_unique<SHFolder>(location, name); folders[location] = std::make_unique<SHFolder>(location, name);
folders[location]->path = path; folders[location]->path = path;

View File

@ -24,7 +24,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer::~SHVkCommandBuffer(void) noexcept SHVkCommandBuffer::~SHVkCommandBuffer(void) noexcept
{ {
if (vkCommandBuffer) if (vkCommandBuffer && parentPool)
parentPool->GetLogicalDevice()->GetVkLogicalDevice().freeCommandBuffers(parentPool->GetVkCommandPool(), commandBufferCount, &vkCommandBuffer); parentPool->GetLogicalDevice()->GetVkLogicalDevice().freeCommandBuffers(parentPool->GetVkCommandPool(), commandBufferCount, &vkCommandBuffer);
} }

View File

@ -102,8 +102,6 @@ namespace SHADE
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
transient = rhs.transient; transient = rhs.transient;
static_cast<ISelfHandle<SHVkCommandPool>&>(*this) = static_cast<ISelfHandle<SHVkCommandPool>&>(rhs);
rhs.vkCommandPool = VK_NULL_HANDLE; rhs.vkCommandPool = VK_NULL_HANDLE;
return *this; return *this;

View File

@ -208,7 +208,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set // to index a set
uint32_t setIndex = setIndexing[bsHash]; uint32_t setIndex = setIndexing[set];
// to index a write for a binding // to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
@ -233,7 +233,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set // to index a set
uint32_t setIndex = setIndexing[bsHash]; uint32_t setIndex = setIndexing[set];
// to index a write for a binding // to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; uint32_t writeInfoIndex = updater.writeHashMap[bsHash];

View File

@ -92,7 +92,7 @@ namespace SHADE
//uint32_t minBuffer //uint32_t minBuffer
if (alignmentSize > 0) if (alignmentSize > 0)
{ {
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1); alignedSize = (alignedSize + static_cast<uint32_t>(alignmentSize) - 1) & ~(alignmentSize - 1);
} }
return alignedSize; return alignedSize;
} }
@ -195,6 +195,8 @@ namespace SHADE
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{}; vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true; descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
descIndexingFeature.runtimeDescriptorArray = true;
// Prepare to create the device // Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo vk::DeviceCreateInfo deviceCreateInfo
@ -249,6 +251,22 @@ namespace SHADE
vkLogicalDevice.destroy(nullptr); vkLogicalDevice.destroy(nullptr);
} }
SHVkLogicalDevice& SHVkLogicalDevice::operator=(SHVkLogicalDevice&& rhs) noexcept
{
if (this == &rhs)
return *this;
vkLogicalDevice = std::move (rhs.vkLogicalDevice);
queueFamilyIndices = std::move (rhs.queueFamilyIndices);
vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
rhs.vkLogicalDevice = VK_NULL_HANDLE;
return *this;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -115,7 +115,7 @@ namespace SHADE
~SHVkLogicalDevice (void) noexcept; ~SHVkLogicalDevice (void) noexcept;
SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */ /* PUBLIC MEMBER VARIABLES */

View File

@ -98,6 +98,51 @@ namespace SHADE
return *this; return *this;
} }
void SHVkFramebuffer::HandleResize(Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept
{
width = inWidth;
height = inHeight;
for (auto& attachment : attachments)
{
// Not sure if its an error to pass in diff dimension images.
if (attachment->GetParentImage()->GetWidth() != (*attachments.begin())->GetParentImage()->GetWidth() || attachment->GetParentImage()->GetHeight() != (*attachments.begin())->GetParentImage()->GetHeight())
{
SHLOG_ERROR("Dimensions of images not same as each other. Cannot create framebuffer.");
return;
}
}
std::vector<vk::ImageView> vkAttachments(attachments.size());
uint32_t i = 0;
for(auto const& attachment : attachments)
{
vkAttachments[i] = attachment->GetImageView();
++i;
}
vk::FramebufferCreateInfo createInfo
{
.renderPass = renderpassHdl->GetVkRenderpass(),
.attachmentCount = static_cast<uint32_t>(vkAttachments.size()),
.pAttachments = vkAttachments.data(),
.width = width,
.height = height,
.layers = 1 // TODO: Find out why this is 1
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createFramebuffer(&createInfo, nullptr, &vkFramebuffer); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create framebuffer. ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created framebuffer. ");
}
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -37,6 +37,8 @@ namespace SHADE
SHVkFramebuffer(SHVkFramebuffer&& rhs) noexcept; SHVkFramebuffer(SHVkFramebuffer&& rhs) noexcept;
SHVkFramebuffer& operator=(SHVkFramebuffer&& rhs) noexcept; SHVkFramebuffer& operator=(SHVkFramebuffer&& rhs) noexcept;
void HandleResize (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -79,6 +79,41 @@ namespace SHADE
vmaUnmapMemory(*vmaAllocator, stagingAlloc); vmaUnmapMemory(*vmaAllocator, stagingAlloc);
} }
void SHVkImage::CreateFramebufferImage(void) noexcept
{
vk::ImageCreateInfo imageCreateInfo{};
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
}
SHVkImage::SHVkImage( SHVkImage::SHVkImage(
VmaAllocator const* allocator, VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
@ -196,37 +231,7 @@ namespace SHADE
, createFlags {create} , createFlags {create}
, vmaAllocator {allocator} , vmaAllocator {allocator}
{ {
vk::ImageCreateInfo imageCreateInfo{}; CreateFramebufferImage();
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
} }
Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept
@ -288,6 +293,16 @@ namespace SHADE
barrier.subresourceRange.layerCount = layerCount; barrier.subresourceRange.layerCount = layerCount;
} }
void SHVkImage::HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept
{
vmaDestroyImage(*vmaAllocator, vkImage, alloc);
width = newWidth;
height = newHeight;
CreateFramebufferImage();
}
void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept
{ {
vkImage = inVkImage; vkImage = inVkImage;

View File

@ -108,7 +108,7 @@ namespace SHADE
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept; void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
void CreateFramebufferImage (void) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -137,6 +137,7 @@ namespace SHADE
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept; Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept; void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */

View File

@ -6,27 +6,13 @@
namespace SHADE namespace SHADE
{ {
/***************************************************************************/
/*!
\brief void SHVkImageView::Create(void) noexcept
Non-default ctor. Initializes image view with image that it is a view of.
\param parent
Parent image the view is a view of.
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ }
, vkImageView{}
, imageViewDetails{}
, logicalDeviceHdl {inLogicalDeviceHdl}
{ {
auto parentImageCreateFlags = parent->GetImageeCreateFlags(); auto parentImageCreateFlags = parentImage->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible // 2D array image type means parent image must be 2D array compatible
if (createParams.viewType == vk::ImageViewType::e2DArray) if (imageViewDetails.viewType == vk::ImageViewType::e2DArray)
{ {
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible)) if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{ {
@ -36,7 +22,7 @@ namespace SHADE
} }
// Check if its possible for the image view to have different format than parent image // Check if its possible for the image view to have different format than parent image
if (createParams.format != parent->GetImageFormat()) if (imageViewDetails.format != parentImage->GetImageFormat())
{ {
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat)) if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{ {
@ -49,9 +35,9 @@ namespace SHADE
vk::ImageViewCreateInfo viewCreateInfo vk::ImageViewCreateInfo viewCreateInfo
{ {
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information .pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parent->GetVkImage(), .image = parentImage->GetVkImage(),
.viewType = createParams.viewType, .viewType = imageViewDetails.viewType,
.format = createParams.format, .format = imageViewDetails.format,
.components .components
{ {
.r = vk::ComponentSwizzle::eR, .r = vk::ComponentSwizzle::eR,
@ -61,15 +47,15 @@ namespace SHADE
}, },
.subresourceRange .subresourceRange
{ {
.aspectMask = createParams.imageAspectFlags, .aspectMask = imageViewDetails.imageAspectFlags,
.baseMipLevel = createParams.baseMipLevel, .baseMipLevel = imageViewDetails.baseMipLevel,
.levelCount = createParams.mipLevelCount, .levelCount = imageViewDetails.mipLevelCount,
.baseArrayLayer = createParams.baseArrayLayer, .baseArrayLayer = imageViewDetails.baseArrayLayer,
.layerCount = createParams.layerCount, .layerCount = imageViewDetails.layerCount,
}, },
}; };
if (auto result = inLogicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess) if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{ {
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! "); SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return; return;
@ -79,9 +65,26 @@ namespace SHADE
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. "); SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
} }
// After success, THEN assign variables }
parentImage = parent;
imageViewDetails = createParams; /***************************************************************************/
/*!
\brief
Non-default ctor. Initializes image view with image that it is a view of.
\param parent
Parent image the view is a view of.
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ parent }
, vkImageView{}
, imageViewDetails{createParams}
, logicalDeviceHdl {inLogicalDeviceHdl}
{
Create();
} }
SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept
@ -94,6 +97,17 @@ namespace SHADE
} }
void SHVkImageView::ViewNewImage(Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
{
imageViewDetails = createParams;
parentImage = parent;
if (vkImageView)
logicalDeviceHdl->GetVkLogicalDevice().destroyImageView(vkImageView, nullptr);
Create();
}
Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept
{ {
return parentImage; return parentImage;

View File

@ -25,12 +25,17 @@ namespace SHADE
//! Logical Device needed for creation and destruction //! Logical Device needed for creation and destruction
Handle<SHVkLogicalDevice> logicalDeviceHdl; Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Create new image view
void Create (void) noexcept;
public: public:
SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept; SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
~SHVkImageView(void) noexcept; ~SHVkImageView(void) noexcept;
SHVkImageView(SHVkImageView&& rhs) noexcept; SHVkImageView(SHVkImageView&& rhs) noexcept;
SHVkImageView& operator=(SHVkImageView&& rhs) noexcept; SHVkImageView& operator=(SHVkImageView&& rhs) noexcept;
void ViewNewImage (Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -249,7 +249,7 @@ namespace SHADE
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
singleMatPropSize = SHADER_INFO->GetBytesRequired(); singleMatPropSize = SHADER_INFO->GetBytesRequired();
singleMatPropAlignedSize = device->PadSSBOSize(singleMatPropSize); singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize; matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
if (matPropsDataSize < matPropTotalBytes) if (matPropsDataSize < matPropTotalBytes)
{ {
@ -386,7 +386,7 @@ namespace SHADE
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
bufferList, bufferList,
0, matPropsDataSize 0, static_cast<uint32_t>(matPropsDataSize)
); );
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
( (

View File

@ -69,7 +69,7 @@ namespace SHADE
SHMatrix inverseViewMatrix; SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix; SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix; SHMatrix inverseVpMatrix;
bool isDirty; bool isDirty = true;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -67,9 +67,17 @@ namespace SHADE
// Register callback to notify render context upon a window resize // Register callback to notify render context upon a window resize
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{ {
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true); renderContext.SetIsResized(true);
}); });
window->RegisterWindowCloseCallback([&](void)
{
renderContext.SetWindowIsDead(true);
}
);
// Create graphics queue // Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0); graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0); transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0);
@ -116,8 +124,8 @@ namespace SHADE
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f); screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
worldCamera = resourceManager.Create<SHCamera>(); worldCamera = resourceManager.Create<SHCamera>();
//worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f)); worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f); worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
@ -125,7 +133,7 @@ namespace SHADE
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f)); defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer // Get render graph from default viewport world renderer
auto worldRenderGraph = resourceManager.Create<SHRenderGraph>(); worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()}; std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i) for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
@ -210,6 +218,15 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::Run(double) noexcept void SHGraphicsSystem::Run(double) noexcept
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame // Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData(); auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame(); uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -249,6 +266,10 @@ namespace SHADE
// Begin recording the command buffer // Begin recording the command buffer
currentCmdBuffer->BeginRecording(); currentCmdBuffer->BeginRecording();
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout()); currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
@ -304,13 +325,6 @@ namespace SHADE
void SHGraphicsSystem::Exit(void) void SHGraphicsSystem::Exit(void)
{ {
renderContext.Destroy();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
SHVkInstance::Destroy();
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -328,6 +342,9 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::BeginRender() void SHGraphicsSystem::BeginRender()
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
// Finalise all batches // Finalise all batches
for (auto vp : viewports) for (auto vp : viewports)
for (auto renderer : vp->GetRenderers()) for (auto renderer : vp->GetRenderers())
@ -341,10 +358,7 @@ namespace SHADE
{ {
device->WaitIdle(); device->WaitIdle();
// Resize the swapchain HandleResize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
} }
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
@ -377,6 +391,16 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHGraphicsSystem::EndRender() void SHGraphicsSystem::EndRender()
{ {
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData(); auto& currFrameData = renderContext.GetCurrentFrameData();
@ -387,10 +411,8 @@ namespace SHADE
// If swapchain is incompatible/outdated // If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{ {
auto windowDims = window->GetWindowSize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize(); HandleResize();
} }
} }
@ -509,25 +531,79 @@ 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 void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{ {
window = wind; window = wind;
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false)
{}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender(); reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false)
{}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt); reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt);
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - EndRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::EndRoutine::EndRoutine()
: SHSystemRoutine("Graphics System Frame Clean Up", false)
{}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender(); reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
} }
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false)
{}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{ {
auto& renderables = SHComponentManager::GetDense<SHRenderable>(); auto& renderables = SHComponentManager::GetDense<SHRenderable>();

View File

@ -69,21 +69,25 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine class SH_API BeginRoutine final : public SHSystemRoutine
{ {
public: public:
BeginRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API RenderRoutine final : public SHSystemRoutine class SH_API RenderRoutine final : public SHSystemRoutine
{ {
public: public:
RenderRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API EndRoutine final : public SHSystemRoutine class SH_API EndRoutine final : public SHSystemRoutine
{ {
public: public:
EndRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{ {
public: public:
BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
@ -246,6 +250,9 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void BuildTextures(); void BuildTextures();
void HandleResize(void) noexcept;
void AwaitGraphicsExecution();
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters */ /* Setters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -279,7 +286,6 @@ namespace SHADE
Handle<SHVkQueue> transferQueue; Handle<SHVkQueue> transferQueue;
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool; Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandPool> transferCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer; Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer; Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext; SHRenderContext renderContext;
@ -314,5 +320,7 @@ namespace SHADE
// Temp Materials // Temp Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHRenderGraph> worldRenderGraph;
}; };
} }

View File

@ -63,7 +63,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory; std::unique_ptr<char> propMemory;
Byte propMemorySize; Byte propMemorySize = 0;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -49,6 +49,14 @@ namespace SHADE
cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA); cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA);
} }
SHRenderer::~SHRenderer(void)
{
//for (auto& cmdBuffer : commandBuffers)
//{
// cmdBuffer.Free();
//}
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Camera Registration */ /* Camera Registration */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -65,6 +65,7 @@ namespace SHADE
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph); SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph);
~SHRenderer(void);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Camera Registration */ /* Camera Registration */

View File

@ -73,4 +73,16 @@ namespace SHADE
iter->Free(); iter->Free();
renderers.erase(iter); renderers.erase(iter);
} }
void SHViewport::SetWidth(float w) noexcept
{
viewport.width = w;
}
void SHViewport::SetHeight(float h) noexcept
{
viewport.height = h;
}
} }

View File

@ -62,6 +62,12 @@ namespace SHADE
Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph); Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph);
void RemoveRenderer(Handle<SHRenderer> renderer); void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWidth(float w) noexcept;
void SetHeight (float h) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getters */ /* Getters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -196,12 +196,12 @@ namespace SHADE
static SHMeshData meshData = Cube(); static SHMeshData meshData = Cube();
return meshLibrary.AddMesh return meshLibrary.AddMesh
( (
meshData.VertexPositions.size(), static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(), meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(), meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(), meshData.VertexTangents.data(),
meshData.VertexNormals.data(), meshData.VertexNormals.data(),
meshData.Indices.size(), static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data() meshData.Indices.data()
); );
} }
@ -211,12 +211,12 @@ namespace SHADE
static SHMeshData meshData = Cube(); static SHMeshData meshData = Cube();
return gfxSystem.AddMesh return gfxSystem.AddMesh
( (
meshData.VertexPositions.size(), static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(), meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(), meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(), meshData.VertexTangents.data(),
meshData.VertexNormals.data(), meshData.VertexNormals.data(),
meshData.Indices.size(), static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data() meshData.Indices.data()
); );
} }

View File

@ -168,6 +168,11 @@ namespace SHADE
isResized = resized; isResized = resized;
} }
void SHRenderContext::SetWindowIsDead(bool dead) noexcept
{
windowIsDead = dead;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -197,6 +202,11 @@ namespace SHADE
return currentFrame; return currentFrame;
} }
bool SHRenderContext::GetResized(void) noexcept
{
return isResized;
}
bool SHRenderContext::GetResizeAndReset(void) noexcept bool SHRenderContext::GetResizeAndReset(void) noexcept
{ {
bool b = isResized; bool b = isResized;
@ -204,4 +214,9 @@ namespace SHADE
return b; return b;
} }
bool SHRenderContext::GetWindowIsDead(void) const noexcept
{
return windowIsDead;
}
} }

View File

@ -36,6 +36,7 @@ namespace SHADE
uint32_t currentFrame; uint32_t currentFrame;
bool isResized{ false }; bool isResized{ false };
bool windowIsDead {false};
public: public:
SHRenderContext(void) noexcept; SHRenderContext(void) noexcept;
@ -52,11 +53,14 @@ namespace SHADE
void ResetFence (void) noexcept; void ResetFence (void) noexcept;
void SetIsResized (bool resized) noexcept; void SetIsResized (bool resized) noexcept;
void SetWindowIsDead (bool dead) noexcept;
SHPerFrameData& GetCurrentFrameData(void) noexcept; SHPerFrameData& GetCurrentFrameData(void) noexcept;
SHPerFrameData& GetFrameData (uint32_t index) noexcept; SHPerFrameData& GetFrameData (uint32_t index) noexcept;
uint32_t GetCurrentFrame (void) const noexcept; uint32_t GetCurrentFrame (void) const noexcept;
bool GetResized (void) noexcept;
bool GetResizeAndReset (void) noexcept; bool GetResizeAndReset (void) noexcept;
bool GetWindowIsDead (void) const noexcept;
}; };
} }

View File

@ -149,7 +149,7 @@ namespace SHADE
{ {
texOrder.emplace_back(job.TextureHandle); texOrder.emplace_back(job.TextureHandle);
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal)); combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
job.TextureHandle->TextureArrayIndex = texOrder.size() - 1; job.TextureHandle->TextureArrayIndex = static_cast<uint32_t>(texOrder.size()) - 1U;
} }
addJobs.clear(); addJobs.clear();

View File

@ -37,7 +37,7 @@ namespace SHADE
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
class SHVkSampler; class SHVkSampler;
class SHTextureAsset; struct SHTextureAsset;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */

View File

@ -46,7 +46,7 @@ namespace SHADE
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{ {
w = swapchainHdl->GetSwapchainImage(0)->GetWidth(); w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
w = swapchainHdl->GetSwapchainImage(0)->GetHeight(); h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format; format = swapchainHdl->GetSurfaceFormatKHR().format;
} }
@ -465,9 +465,6 @@ namespace SHADE
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
{ {
// TODO: DON'T HARDCODE THIS
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
for (auto& node : nodes) for (auto& node : nodes)
node->Execute(cmdBuffer, descPool, frameIndex); node->Execute(cmdBuffer, descPool, frameIndex);
} }
@ -480,6 +477,18 @@ namespace SHADE
} }
} }
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
// resize resources
for (auto& [name, resource]: graphResources)
resource->HandleResize(newWidth, newHeight);
for (auto& node : nodes)
{
node->HandleResize();
}
}
Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept
{ {
if (nodeIndexing.contains(nodeName)) if (nodeIndexing.contains(nodeName))

View File

@ -80,6 +80,7 @@ namespace SHADE
void Generate (void) noexcept; void Generate (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept; void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */

View File

@ -3,6 +3,7 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "SHSubpass.h" #include "SHSubpass.h"
@ -56,6 +57,33 @@ namespace SHADE
} }
} }
void SHRenderGraphNode::HandleResize(void) noexcept
{
renderpass->HandleResize();
for (uint32_t i = 0; i < framebuffers.size(); ++i)
{
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
for (uint32_t j = 0; j < attResources.size(); ++j)
{
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::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
if (fbWidth > attResources[j]->width)
fbWidth = attResources[j]->width;
if (fbHeight > attResources[j]->height)
fbHeight = attResources[j]->height;
}
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
}
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -81,6 +81,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void CreateRenderpass(void) noexcept; void CreateRenderpass(void) noexcept;
void CreateFramebuffer(void) noexcept; void CreateFramebuffer(void) noexcept;
void HandleResize (void) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -2,9 +2,11 @@
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkImageView.h"
namespace SHADE namespace SHADE
{ {
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -42,7 +44,9 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept
: resourceType{ type } : logicalDevice {logicalDevice}
, swapchain{ swapchain }
, resourceType{ type }
, resourceFormat{ format } , resourceFormat{ format }
, images{} , images{}
, imageViews{} , imageViews{}
@ -52,10 +56,10 @@ namespace SHADE
, resourceName{ name } , resourceName{ name }
{ {
// If the resource type is an arbitrary image and not swapchain image // If the resource type is an arbitrary image and not swapchain image
if (type != SH_ATT_DESC_TYPE::COLOR_PRESENT) if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
{ {
vk::ImageAspectFlags imageAspectFlags; imageAspectFlags = vk::ImageAspectFlags{};
vk::ImageUsageFlags usage = {}; usage = {};
// Check the resource type and set image usage flags and image aspect flags accordingly // Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType) switch (resourceType)
@ -142,6 +146,7 @@ namespace SHADE
, width{ rhs.width } , width{ rhs.width }
, height{ rhs.height } , height{ rhs.height }
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
{ {
} }
@ -172,6 +177,7 @@ namespace SHADE
width = rhs.width; width = rhs.width;
height = rhs.height; height = rhs.height;
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
return *this; return *this;
} }
@ -189,4 +195,51 @@ namespace SHADE
} }
void SHRenderGraphResource::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
width = newWidth;
height = newHeight;
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
{
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
for (uint32_t i = 0; i < images.size(); ++i)
{
images[i]->HandleResizeFramebufferImage(width, height);
imageViews[i]->ViewNewImage(images[i], viewDetails);
}
}
else
{
// Prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.mipLevelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
{
images[i] = swapchain->GetSwapchainImage(i);
imageViews[i]->ViewNewImage(images[i], viewDetails);
}
}
}
} }

View File

@ -20,6 +20,12 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// for creation/recreation
Handle<SHVkLogicalDevice> logicalDevice;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource //! Name of the resource
std::string resourceName; std::string resourceName;
@ -47,6 +53,14 @@ namespace SHADE
//! Number of mipmap levels //! Number of mipmap levels
uint8_t mipLevels; uint8_t mipLevels;
//! image aspect flags
vk::ImageAspectFlags imageAspectFlags;
//! usage flags
vk::ImageUsageFlags usage = {};
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
@ -56,6 +70,8 @@ namespace SHADE
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
}; };

View File

@ -30,7 +30,10 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept SHVkRenderpass::SHVkRenderpass(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
: logicalDeviceHdl {inLogicalDeviceHdl} : logicalDeviceHdl {inLogicalDeviceHdl}
, numAttDescs {static_cast<uint32_t>(vkDescriptions.size())} , numAttDescs {static_cast<uint32_t>(vkDescriptions.size())}
, vkSubpassDescriptions{}
, vkSubpassDeps{}
, clearColors{} , clearColors{}
, vkAttachmentDescriptions{}
{ {
for (uint32_t i = 0; i < vkDescriptions.size(); ++i) for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{ {
@ -42,7 +45,6 @@ namespace SHADE
vk::RenderPassCreateInfo renderPassCreateInfo{}; vk::RenderPassCreateInfo renderPassCreateInfo{};
std::vector<vk::SubpassDependency> subpassDeps;
// For validating the depth ref // For validating the depth ref
auto isValidDepthRef = [&](vk::AttachmentReference const& depthRef) -> bool auto isValidDepthRef = [&](vk::AttachmentReference const& depthRef) -> bool
@ -50,13 +52,16 @@ namespace SHADE
return !(depthRef.attachment == static_cast<uint32_t> (-1) && depthRef.layout == vk::ImageLayout::eUndefined); return !(depthRef.attachment == static_cast<uint32_t> (-1) && depthRef.layout == vk::ImageLayout::eUndefined);
}; };
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
vkAttachmentDescriptions[i] = vkDescriptions[i];
uint32_t subpassIndex = 0; uint32_t subpassIndex = 0;
if (!subpasses.empty()) if (!subpasses.empty())
{ {
for (auto& subpass : subpasses) for (auto& subpass : subpasses)
{ {
subpassDescriptions.emplace_back(); vkSubpassDescriptions.emplace_back();
auto& spDesc = subpassDescriptions.back(); auto& spDesc = vkSubpassDescriptions.back();
spDesc.pColorAttachments = subpass.colorRefs.data(); spDesc.pColorAttachments = subpass.colorRefs.data();
spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size()); spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size());
@ -88,18 +93,18 @@ namespace SHADE
}; };
// Push a new dependency // Push a new dependency
subpassDeps.push_back(dependency); vkSubpassDeps.push_back(dependency);
++subpassIndex; ++subpassIndex;
} }
// Renderpass create info for render pass creation // Renderpass create info for render pass creation
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size()); renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkAttachmentDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data(); renderPassCreateInfo.pAttachments = vkAttachmentDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size()); renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data(); renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(subpassDeps.size()); renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(vkSubpassDeps.size());
renderPassCreateInfo.pDependencies = subpassDeps.data(); renderPassCreateInfo.pDependencies = vkSubpassDeps.data();
} }
// No subpasses passed in, create a default one. // No subpasses passed in, create a default one.
@ -172,6 +177,8 @@ namespace SHADE
: logicalDeviceHdl{ inLogicalDeviceHdl } : logicalDeviceHdl{ inLogicalDeviceHdl }
, numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) } , numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) }
, clearColors{} , clearColors{}
, vkSubpassDescriptions{ }
, vkSubpassDeps{ }
{ {
for (uint32_t i = 0; i < vkDescriptions.size(); ++i) for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{ {
@ -181,18 +188,24 @@ namespace SHADE
clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
} }
subpassDescriptions.resize (spDescs.size()); vkAttachmentDescriptions.resize(vkDescriptions.size());
for (uint32_t i = 0; i < subpassDescriptions.size(); ++i) for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{ vkAttachmentDescriptions[i] = vkDescriptions[i];
subpassDescriptions[i] = spDescs[i];
} vkSubpassDescriptions.resize (spDescs.size());
for (uint32_t i = 0; i < vkSubpassDescriptions.size(); ++i)
vkSubpassDescriptions[i] = spDescs[i];
vkSubpassDeps.resize(spDeps.size());
for (uint32_t i = 0; i < vkSubpassDeps.size(); ++i)
vkSubpassDeps[i] = spDeps[i];
vk::RenderPassCreateInfo renderPassCreateInfo{}; vk::RenderPassCreateInfo renderPassCreateInfo{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size()); renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data(); renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size()); renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data(); renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size()); renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size());
renderPassCreateInfo.pDependencies = spDeps.data(); renderPassCreateInfo.pDependencies = spDeps.data();
@ -210,8 +223,11 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept
: vkRenderpass {rhs.vkRenderpass} : vkRenderpass {rhs.vkRenderpass}
, logicalDeviceHdl {rhs.logicalDeviceHdl} , logicalDeviceHdl {rhs.logicalDeviceHdl}
, subpassDescriptions {std::move (rhs.subpassDescriptions)} , vkSubpassDescriptions{ std::move(rhs.vkSubpassDescriptions) }
, vkSubpassDeps{ std::move(rhs.vkSubpassDeps) }
, clearColors{ std::move(rhs.clearColors) } , clearColors{ std::move(rhs.clearColors) }
, vkAttachmentDescriptions{ std::move(rhs.vkAttachmentDescriptions) }
, numAttDescs{rhs.numAttDescs}
{ {
rhs.vkRenderpass = VK_NULL_HANDLE; rhs.vkRenderpass = VK_NULL_HANDLE;
} }
@ -224,8 +240,11 @@ namespace SHADE
vkRenderpass = rhs.vkRenderpass; vkRenderpass = rhs.vkRenderpass;
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
subpassDescriptions = std::move(rhs.subpassDescriptions); vkSubpassDescriptions = std::move(rhs.vkSubpassDescriptions);
vkSubpassDeps = std::move(rhs.vkSubpassDeps);
clearColors = std::move(rhs.clearColors); clearColors = std::move(rhs.clearColors);
vkAttachmentDescriptions = std::move(rhs.vkAttachmentDescriptions);
numAttDescs = std::move(rhs.numAttDescs);
rhs.vkRenderpass = VK_NULL_HANDLE; rhs.vkRenderpass = VK_NULL_HANDLE;
@ -238,6 +257,31 @@ namespace SHADE
} }
void SHVkRenderpass::HandleResize(void) noexcept
{
logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr);
vk::RenderPassCreateInfo renderPassCreateInfo{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkAttachmentDescriptions.size());
renderPassCreateInfo.pAttachments = vkAttachmentDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(vkSubpassDeps.size());
renderPassCreateInfo.pDependencies = vkSubpassDeps.data();
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createRenderPass(&renderPassCreateInfo, nullptr, &vkRenderpass); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create Renderpass. ");
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created Renderpass. ");
}
}
vk::RenderPass SHVkRenderpass::GetVkRenderpass(void) const noexcept vk::RenderPass SHVkRenderpass::GetVkRenderpass(void) const noexcept
{ {
return vkRenderpass; return vkRenderpass;

View File

@ -29,7 +29,13 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDeviceHdl; Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Container of subpass information used to construct subpasses //! Container of subpass information used to construct subpasses
std::vector<vk::SubpassDescription> subpassDescriptions; std::vector<vk::SubpassDescription> vkSubpassDescriptions;
//! Container of subpass dependencies used to create renderpass
std::vector<vk::SubpassDependency> vkSubpassDeps;
//! Attachment descriptions
std::vector<vk::AttachmentDescription> vkAttachmentDescriptions;
//! Clear colors for the color and depth //! Clear colors for the color and depth
std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors; std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors;
@ -49,6 +55,8 @@ namespace SHADE
SHVkRenderpass(SHVkRenderpass&& rhs) noexcept; SHVkRenderpass(SHVkRenderpass&& rhs) noexcept;
SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept; SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -272,6 +272,17 @@ namespace SHADE
windowResizeCallbacks.erase(callbackid); windowResizeCallbacks.erase(callbackid);
} }
SHWindow::CALLBACKID SHWindow::RegisterWindowCloseCallback(WindowCloseCallbackFn windowCloseCallback)
{
windowCloseCallbacks.try_emplace(windowResizeCallbackCount, windowCloseCallback);
return windowCloseCallbackCount++;
}
void SHWindow::UnregisterWindowCloseCallback(CALLBACKID const& callbackid)
{
windowCloseCallbacks.erase(callbackid);
}
LRESULT SHWindow::WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) LRESULT SHWindow::WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{ {
auto window = windowMap.GetWindow(hwnd); auto window = windowMap.GetWindow(hwnd);
@ -307,6 +318,8 @@ namespace SHADE
case WM_CREATE: case WM_CREATE:
OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam)); OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam));
break; break;
case WM_CLOSE:
case WM_DESTROY: case WM_DESTROY:
OnDestroy(); OnDestroy();
return 0; return 0;
@ -362,8 +375,17 @@ namespace SHADE
} }
void SHADE::SHWindow::OnClose()
{
for (const auto& callbackFn : windowCloseCallbacks | std::views::values)
{
callbackFn();
}
}
void SHWindow::OnDestroy() void SHWindow::OnDestroy()
{ {
OnClose();
this->Destroy(); this->Destroy();
} }
@ -375,6 +397,14 @@ namespace SHADE
{ {
wndData.width = static_cast<unsigned>(size.cx); wndData.width = static_cast<unsigned>(size.cx);
wndData.height = static_cast<unsigned>(size.cy); wndData.height = static_cast<unsigned>(size.cy);
if (type == SIZE_MINIMIZED)
{
wndData.isMinimised = true;
}
else
wndData.isMinimised = false;
for (auto const& entry : windowResizeCallbacks) for (auto const& entry : windowResizeCallbacks)
{ {
entry.second(static_cast<uint32_t>(wndData.width), static_cast<uint32_t>(wndData.height)); entry.second(static_cast<uint32_t>(wndData.width), static_cast<uint32_t>(wndData.height));

View File

@ -61,6 +61,8 @@ namespace SHADE
bool modal = false; bool modal = false;
bool isMinimised = false;
std::wstring title = L"SHADE ENGINE"; std::wstring title = L"SHADE ENGINE";
std::wstring name = L"SHADEEngineApp"; std::wstring name = L"SHADEEngineApp";
@ -73,6 +75,7 @@ namespace SHADE
public: public:
using SHVec2 = std::pair<uint32_t, uint32_t>; using SHVec2 = std::pair<uint32_t, uint32_t>;
typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn; typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn;
typedef std::function<void(void)> WindowCloseCallbackFn;
typedef uint16_t CALLBACKID; typedef uint16_t CALLBACKID;
SHWindow(); SHWindow();
@ -123,6 +126,9 @@ namespace SHADE
CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn); CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn);
void UnregisterWindowSizeCallback(CALLBACKID const& callbackid); void UnregisterWindowSizeCallback(CALLBACKID const& callbackid);
CALLBACKID RegisterWindowCloseCallback(WindowCloseCallbackFn);
void UnregisterWindowCloseCallback(CALLBACKID const& callbackid);
bool IsMinimized() const { return wndData.isMinimised; }
protected: protected:
static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@ -154,10 +160,13 @@ namespace SHADE
HFONT font; HFONT font;
std::unordered_map<CALLBACKID, WindowResizeCallbackFn> windowResizeCallbacks; std::unordered_map<CALLBACKID, WindowResizeCallbackFn> windowResizeCallbacks;
std::unordered_map<CALLBACKID, WindowCloseCallbackFn> windowCloseCallbacks;
CALLBACKID windowResizeCallbackCount{}; CALLBACKID windowResizeCallbackCount{};
CALLBACKID windowCloseCallbackCount{};
//TODO: Shift to events abstraction //TODO: Shift to events abstraction
void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct); void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct);
void OnClose();
void OnDestroy(); void OnDestroy();
//void OnFileDrop(HDROP drop); //void OnFileDrop(HDROP drop);
void OnSize(UINT msg, UINT type, SIZE size); void OnSize(UINT msg, UINT type, SIZE size);

View File

@ -390,6 +390,13 @@ RTTR_REGISTRATION
using namespace SHADE; using namespace SHADE;
using namespace rttr; using namespace rttr;
registration::enumeration<SHRigidBodyComponent::Type>("RigidBody Type")
(
value("Static", SHRigidBodyComponent::Type::STATIC),
value("Dynamic", SHRigidBodyComponent::Type::DYNAMIC),
value("Kinematic", SHRigidBodyComponent::Type::KINEMATIC)
);
registration::class_<SHRigidBodyComponent>("RigidBody Component") registration::class_<SHRigidBodyComponent>("RigidBody Component")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType ) .property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass ) .property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )

View File

@ -8,9 +8,9 @@ namespace SHADE
ResourceManager::~ResourceManager() ResourceManager::~ResourceManager()
{ {
// Delete all resources libraries // Delete all resources libraries
for (const auto& deleter : deleters) for (auto iter = deleters.rbegin(); iter != deleters.rend(); ++iter)
{ {
deleter(); (*iter)();
} }
deleters.clear(); deleters.clear();
} }

View File

@ -90,10 +90,15 @@ namespace SHADE
#endif #endif
// Go through the map and release all the nodes // Go through the map and release all the nodes
for (auto* node : entityNodeMap | std::views::values) for (auto*& node : entityNodeMap | std::views::values)
ReleaseNode(node); {
delete node;
node = nullptr;
}
delete root; entityNodeMap.clear();
//delete root;
#ifdef _DEBUG #ifdef _DEBUG
SHLOG_INFO("Scene Graph Destroyed Successfully!") SHLOG_INFO("Scene Graph Destroyed Successfully!")

View File

@ -153,6 +153,16 @@ namespace SHADE
csEditorRenderScripts(entity); csEditorRenderScripts(entity);
} }
void SHScriptEngine::UndoScriptInspectorChanges() const
{
csEditorUndo();
}
void SHScriptEngine::RedoScriptInspectorChanges() const
{
csEditorRedo();
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -400,6 +410,18 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".Editor", DEFAULT_CSHARP_NAMESPACE + ".Editor",
"RenderScriptsInInspector" "RenderScriptsInInspector"
); );
csEditorUndo = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Editor",
"Undo"
);
csEditorRedo = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Editor",
"Redo"
);
} }
void SHScriptEngine::registerEvents() void SHScriptEngine::registerEvents()

View File

@ -171,6 +171,14 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
void RenderScriptsInInspector(EntityID entity) const; void RenderScriptsInInspector(EntityID entity) const;
/// <summary>
/// Performs an undo for script inspector changes if it exists.
/// </summary>
void UndoScriptInspectorChanges() const;
/// <summary>
/// Performs a redo for script inspector changes if it exists.
/// </summary>
void RedoScriptInspectorChanges() const;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
@ -243,9 +251,8 @@ namespace SHADE
CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr; CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr;
// - Editor // - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
// Delegates CsFuncPtr csEditorUndo = nullptr;
/*ECS::EntityEvent::Delegate onEntityCreate; CsFuncPtr csEditorRedo = nullptr;
ECS::EntityEvent::Delegate onEntityDestroy;*/
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Event Handler Functions */ /* Event Handler Functions */

View File

@ -31,6 +31,7 @@ project "SHADE_Managed"
"%{IncludeDir.imnodes}", "%{IncludeDir.imnodes}",
"%{IncludeDir.yamlcpp}", "%{IncludeDir.yamlcpp}",
"%{IncludeDir.RTTR}/include", "%{IncludeDir.RTTR}/include",
"%{IncludeDir.dotnet}\\include",
"%{wks.location}/SHADE_Engine/src" "%{wks.location}/SHADE_Engine/src"
} }
@ -85,3 +86,8 @@ project "SHADE_Managed"
optimize "On" optimize "On"
defines{"_RELEASE"} defines{"_RELEASE"}
links{"librttr_core.lib"} links{"librttr_core.lib"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE"}
links{"librttr_core.lib"}

View File

@ -3,7 +3,7 @@
\author Tng Kah Wei, kahwei.tng, 390009620 \author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu \par email: kahwei.tng\@digipen.edu
\date Sep 27, 2022 \date Sep 27, 2022
\brief Contains the definition of the functions for the ScriptStore managed \brief Contains the definition of the functions for the Editor managed
static class. static class.
Note: This file is written in C++17/CLI. Note: This file is written in C++17/CLI.
@ -16,6 +16,8 @@ of DigiPen Institute of Technology is prohibited.
#include "SHpch.h" #include "SHpch.h"
// Primary Header // Primary Header
#include "Editor/Editor.hxx" #include "Editor/Editor.hxx"
// STL Includes
#include <memory>
// External Dependencies // External Dependencies
#include "Editor/SHEditorUI.h" #include "Editor/SHEditorUI.h"
// Project Headers // Project Headers
@ -25,6 +27,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "Serialisation/ReflectionUtilities.hxx" #include "Serialisation/ReflectionUtilities.hxx"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/Command/SHCommand.hpp"
// Using Directives // Using Directives
using namespace System; using namespace System;
@ -48,9 +52,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \ (field->FieldType == MANAGED_TYPE::typeid) \
{ \ { \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \ NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \ if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \ { \
field->SetValue(object, val); \ field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \ } \
} \ } \
/// <summary> /// <summary>
@ -69,9 +75,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \ (field->FieldType == MANAGED_TYPE::typeid) \
{ \ { \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \ 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)) \
{ \ { \
field->SetValue(object, Convert::ToCLI(val)); \ field->SetValue(object, Convert::ToCLI(val)); \
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \
} \ } \
} \ } \
@ -126,6 +134,23 @@ namespace SHADE
} }
} }
/*---------------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*---------------------------------------------------------------------------------*/
void Editor::Undo()
{
SAFE_NATIVE_CALL_BEGIN
actionStack.Undo();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.Undo")
}
void Editor::Redo()
{
SAFE_NATIVE_CALL_BEGIN
actionStack.Redo();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.Redo")
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -192,9 +217,11 @@ namespace SHADE
} }
int val = safe_cast<int>(field->GetValue(object)); int val = safe_cast<int>(field->GetValue(object));
int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames)) if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames))
{ {
field->SetValue(object, val); field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal);
} }
} }
else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2) else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2)
@ -210,9 +237,11 @@ namespace SHADE
// Actual Field // Actual Field
std::string val = Convert::ToNative(stringVal); std::string val = Convert::ToNative(stringVal);
std::string oldVal = val;
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val)) if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val))
{ {
field->SetValue(object, Convert::ToCLI(val)); field->SetValue(object, Convert::ToCLI(val));
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
} }
} }
} }
@ -231,4 +260,18 @@ namespace SHADE
} }
} }
void Editor::registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData)
{
// Create command and add it into the undo stack
UndoRedoStack::Command cmd;
cmd.Field = field;
cmd.Object = object;
cmd.NewData = newData;
cmd.OldData = oldData;
actionStack.Add(cmd);
// Inform the C++ Undo-Redo stack
SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCLICommand>()));
}
} }

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Engine/Entity.hxx" #include "Engine/Entity.hxx"
#include "Scripts/Script.hxx" #include "Scripts/Script.hxx"
#include "UndoRedoStack.hxx"
namespace SHADE namespace SHADE
{ {
@ -44,7 +45,18 @@ namespace SHADE
/// <param name="entity">The Entity to add PlushieScripts to.</param> /// <param name="entity">The Entity to add PlushieScripts to.</param>
static void RenderScriptAddButton(Entity entity); static void RenderScriptAddButton(Entity entity);
/*-----------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*-----------------------------------------------------------------------------*/
static void Undo();
static void Redo();
private: private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
static UndoRedoStack actionStack;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -73,5 +85,6 @@ namespace SHADE
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param> /// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script); static void renderScriptContextMenu(Entity entity, Script^ script);
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
}; };
} }

View File

@ -0,0 +1,69 @@
/************************************************************************************//*!
\file UndoRedoStack.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 29, 2022
\brief Contains the definition of the functions for the UndoRedoStack managed
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.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "UndoRedoStack.hxx"
// External Dependencies
#include "Editor/SHEditorUI.h"
// Project Headers
namespace SHADE
{
bool UndoRedoStack::UndoActionPresent::get()
{
return commandStack->Count > 0 && latestActionIndex >= 0;
}
bool UndoRedoStack::RedoActionPresent::get()
{
return latestActionIndex >= 0 && latestActionIndex < commandStack->Count - 1;
}
void UndoRedoStack::Add(Command command)
{
// Erase any other actions ahead of the current action
if (latestActionIndex >= 0 && latestActionIndex < commandStack->Count - 1)
{
commandStack->RemoveRange(latestActionIndex, commandStack->Count - latestActionIndex);
}
// Add the command
commandStack->Add(command);
// Set the latest command
latestActionIndex = commandStack->Count - 1;
}
void UndoRedoStack::Undo()
{
if (!UndoActionPresent)
return;
Command cmd = commandStack[latestActionIndex];
cmd.Field->SetValue(cmd.Object, cmd.OldData);
--latestActionIndex;
}
void UndoRedoStack::Redo()
{
if (!RedoActionPresent)
return;
Command cmd = commandStack[latestActionIndex];
cmd.Field->SetValue(cmd.Object, cmd.NewData);
++latestActionIndex;
}
}

View File

@ -0,0 +1,75 @@
/************************************************************************************//*!
\file UndoRedoStack.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 29, 2022
\brief Contains the definition of the managed UndoRedoStack 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
namespace SHADE
{
/// <summary>
/// Class that is able to store a stack of actions that can be done and redone.
/// </summary>
private ref class UndoRedoStack sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Command for the stack that represents a data modification.
/// </summary>
value struct Command
{
public:
System::Object^ Object;
System::Reflection::FieldInfo^ Field;
System::Object^ NewData;
System::Object^ OldData;
};
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// True if there is an undoable action in the stack.
/// </summary>
property bool UndoActionPresent { bool get(); }
/// <summary>
/// True if there is a redoable action in the stack.
/// </summary>
property bool RedoActionPresent { bool get(); }
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Adds a command onto the stack.
/// </summary>
/// <param name="command"></param>
void Add(Command command);
/// <summary>
/// Undos the last added command if it exists.
/// </summary>
void Undo();
/// <summary>
/// Redoes the last undo-ed command if it exists.
/// </summary>
void Redo();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
int latestActionIndex = -1;
System::Collections::Generic::List<Command>^ commandStack = gcnew System::Collections::Generic::List<Command>();
};
}