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);
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
}

View File

@ -118,7 +118,7 @@ namespace Sandbox
renderable.SetMaterial(customMat);
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.textureIndex", 1);
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f });
transform.SetLocalScale({ 5.0f, 5.0f, 5.0f });
@ -159,7 +159,7 @@ namespace Sandbox
renderableShowcase.SetMaterial(customMat);
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.textureIndex", 1);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.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"}
excludes
{
"%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp",
-- "%{prj.location}/src/Editor/**.cpp",
-- "%{prj.location}/src/Editor/**.h",
-- "%{prj.location}/src/Editor/**.hpp",
}
links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,9 +5,13 @@
//#==============================================================#
#include <functional>
#include "SH_API.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE
{
class SHBaseCommand
class SH_API SHBaseCommand
{
public:
virtual ~SHBaseCommand() = default;
@ -48,4 +52,20 @@ namespace SHADE
T newValue;
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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,6 @@
#include "SHFileSystem.h"
#include "fileapi.h"
#include <filesystem>
#include <cassert>
#include <queue>
namespace SHADE
@ -27,8 +26,11 @@ namespace SHADE
}
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);
@ -37,7 +39,10 @@ namespace SHADE
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());
@ -45,7 +50,11 @@ namespace SHADE
location <<= FOLDER_BIT_ALLOCATE;
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);
return location;
@ -53,7 +62,10 @@ namespace SHADE
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)
{
@ -116,10 +128,11 @@ namespace SHADE
FolderPointer SHFileSystem::CreateFolder(FolderPath path, FolderLocation parent, FolderHandle location, FolderName name) noexcept
{
assert(
CreateDirectoryA(path.c_str(), nullptr),
"Failed to create folder\n"
);
if (!CreateDirectoryA(path.c_str(), nullptr))
{
SHLOG_ERROR("Failed to create folder: {}\n", path);
}
folders[location] = std::make_unique<SHFolder>(location, name);
folders[location]->path = path;

View File

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

View File

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

View File

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

View File

@ -92,7 +92,7 @@ namespace SHADE
//uint32_t minBuffer
if (alignmentSize > 0)
{
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1);
alignedSize = (alignedSize + static_cast<uint32_t>(alignmentSize) - 1) & ~(alignmentSize - 1);
}
return alignedSize;
}
@ -195,6 +195,8 @@ namespace SHADE
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
descIndexingFeature.runtimeDescriptorArray = true;
// Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo
@ -249,6 +251,22 @@ namespace SHADE
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& operator= (SHVkLogicalDevice const& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */

View File

@ -98,6 +98,51 @@ namespace SHADE
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& 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 */
/*-----------------------------------------------------------------------*/

View File

@ -79,6 +79,41 @@ namespace SHADE
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(
VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails,
@ -196,37 +231,7 @@ namespace SHADE
, createFlags {create}
, vmaAllocator {allocator}
{
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. ");
CreateFramebufferImage();
}
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;
}
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
{
vkImage = inVkImage;

View File

@ -108,7 +108,7 @@ namespace SHADE
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
void CreateFramebufferImage (void) noexcept;
public:
/*-----------------------------------------------------------------------*/
@ -137,7 +137,8 @@ namespace SHADE
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) 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 */
/*-----------------------------------------------------------------------*/

View File

@ -6,6 +6,67 @@
namespace SHADE
{
void SHVkImageView::Create(void) noexcept
{
auto parentImageCreateFlags = parentImage->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible
if (imageViewDetails.viewType == vk::ImageViewType::e2DArray)
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{
SHLOG_ERROR("Failed to create image view. Parent image not 2D array compatible. ");
return;
}
}
// Check if its possible for the image view to have different format than parent image
if (imageViewDetails.format != parentImage->GetImageFormat())
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{
SHLOG_ERROR("Failed to create image view. Format for image view not same as image but image not initialized with mutable format bit. ");
return;
}
}
vk::ImageViewCreateInfo viewCreateInfo
{
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parentImage->GetVkImage(),
.viewType = imageViewDetails.viewType,
.format = imageViewDetails.format,
.components
{
.r = vk::ComponentSwizzle::eR,
.g = vk::ComponentSwizzle::eG,
.b = vk::ComponentSwizzle::eB,
.a = vk::ComponentSwizzle::eA,
},
.subresourceRange
{
.aspectMask = imageViewDetails.imageAspectFlags,
.baseMipLevel = imageViewDetails.baseMipLevel,
.levelCount = imageViewDetails.mipLevelCount,
.baseArrayLayer = imageViewDetails.baseArrayLayer,
.layerCount = imageViewDetails.layerCount,
},
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
}
}
/***************************************************************************/
/*!
@ -18,70 +79,12 @@ namespace SHADE
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ }
: parentImage{ parent }
, vkImageView{}
, imageViewDetails{}
, imageViewDetails{createParams}
, logicalDeviceHdl {inLogicalDeviceHdl}
{
auto parentImageCreateFlags = parent->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible
if (createParams.viewType == vk::ImageViewType::e2DArray)
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{
SHLOG_ERROR("Failed to create image view. Parent image not 2D array compatible. ");
return;
}
}
// Check if its possible for the image view to have different format than parent image
if (createParams.format != parent->GetImageFormat())
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{
SHLOG_ERROR("Failed to create image view. Format for image view not same as image but image not initialized with mutable format bit. ");
return;
}
}
vk::ImageViewCreateInfo viewCreateInfo
{
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parent->GetVkImage(),
.viewType = createParams.viewType,
.format = createParams.format,
.components
{
.r = vk::ComponentSwizzle::eR,
.g = vk::ComponentSwizzle::eG,
.b = vk::ComponentSwizzle::eB,
.a = vk::ComponentSwizzle::eA,
},
.subresourceRange
{
.aspectMask = createParams.imageAspectFlags,
.baseMipLevel = createParams.baseMipLevel,
.levelCount = createParams.mipLevelCount,
.baseArrayLayer = createParams.baseArrayLayer,
.layerCount = createParams.layerCount,
},
};
if (auto result = inLogicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
}
// After success, THEN assign variables
parentImage = parent;
imageViewDetails = createParams;
Create();
}
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
{
return parentImage;

View File

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

View File

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

View File

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

View File

@ -67,9 +67,17 @@ namespace SHADE
// Register callback to notify render context upon a window resize
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true);
});
window->RegisterWindowCloseCallback([&](void)
{
renderContext.SetWindowIsDead(true);
}
);
// Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0);
@ -116,8 +124,8 @@ namespace SHADE
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->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
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->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));
// Get render graph from default viewport world renderer
auto worldRenderGraph = resourceManager.Create<SHRenderGraph>();
worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
@ -210,6 +218,15 @@ namespace SHADE
/***************************************************************************/
void SHGraphicsSystem::Run(double) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -249,6 +266,10 @@ namespace SHADE
// Begin recording the command buffer
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());
// Bind all the buffers required for meshes
@ -304,13 +325,6 @@ namespace SHADE
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()
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
// Finalise all batches
for (auto vp : viewports)
for (auto renderer : vp->GetRenderers())
@ -341,10 +358,7 @@ namespace SHADE
{
device->WaitIdle();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
HandleResize();
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
@ -377,6 +391,16 @@ namespace SHADE
/***************************************************************************/
void SHGraphicsSystem::EndRender()
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
@ -387,10 +411,8 @@ namespace SHADE
// If swapchain is incompatible/outdated
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
{
window = wind;
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false)
{}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false)
{}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{
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
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false)
{}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{
auto& renderables = SHComponentManager::GetDense<SHRenderable>();

View File

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

View File

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

View File

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

View File

@ -65,6 +65,7 @@ namespace SHADE
/* 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(void);
/*-----------------------------------------------------------------------------*/
/* Camera Registration */

View File

@ -73,4 +73,16 @@ namespace SHADE
iter->Free();
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);
void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWidth(float w) noexcept;
void SetHeight (float h) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getters */
/*-----------------------------------------------------------------------------*/

View File

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

View File

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

View File

@ -36,6 +36,7 @@ namespace SHADE
uint32_t currentFrame;
bool isResized{ false };
bool windowIsDead {false};
public:
SHRenderContext(void) noexcept;
@ -51,12 +52,15 @@ namespace SHADE
bool WaitForFence (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& GetFrameData (uint32_t index) noexcept;
uint32_t GetCurrentFrame (void) const noexcept;
bool GetResized (void) noexcept;
bool GetResizeAndReset (void) noexcept;
bool GetWindowIsDead (void) const noexcept;
};
}

View File

@ -149,7 +149,7 @@ namespace SHADE
{
texOrder.emplace_back(job.TextureHandle);
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();

View File

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

View File

@ -46,7 +46,7 @@ namespace SHADE
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{
w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
w = swapchainHdl->GetSwapchainImage(0)->GetHeight();
h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format;
}
@ -465,9 +465,6 @@ namespace SHADE
// better way to manage these
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)
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
{
if (nodeIndexing.contains(nodeName))

View File

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

View File

@ -3,6 +3,7 @@
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.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 CreateFramebuffer(void) noexcept;
void HandleResize (void) noexcept;
public:
/*-----------------------------------------------------------------------*/

View File

@ -2,9 +2,11 @@
#include "SHRenderGraphResource.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkImageView.h"
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
: resourceType{ type }
: logicalDevice {logicalDevice}
, swapchain{ swapchain }
, resourceType{ type }
, resourceFormat{ format }
, images{}
, imageViews{}
@ -52,10 +56,10 @@ namespace SHADE
, resourceName{ name }
{
// 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;
vk::ImageUsageFlags usage = {};
imageAspectFlags = vk::ImageAspectFlags{};
usage = {};
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType)
@ -142,6 +146,7 @@ namespace SHADE
, width{ rhs.width }
, height{ rhs.height }
, mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
{
}
@ -172,6 +177,7 @@ namespace SHADE
width = rhs.width;
height = rhs.height;
mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
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 */
/*-----------------------------------------------------------------------*/
// for creation/recreation
Handle<SHVkLogicalDevice> logicalDevice;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource
std::string resourceName;
@ -47,6 +53,14 @@ namespace SHADE
//! Number of mipmap levels
uint8_t mipLevels;
//! image aspect flags
vk::ImageAspectFlags imageAspectFlags;
//! usage flags
vk::ImageUsageFlags usage = {};
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
@ -56,6 +70,8 @@ namespace SHADE
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
friend class SHRenderGraphNode;
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
: logicalDeviceHdl {inLogicalDeviceHdl}
, numAttDescs {static_cast<uint32_t>(vkDescriptions.size())}
, vkSubpassDescriptions{}
, vkSubpassDeps{}
, clearColors{}
, vkAttachmentDescriptions{}
{
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{
@ -42,7 +45,6 @@ namespace SHADE
vk::RenderPassCreateInfo renderPassCreateInfo{};
std::vector<vk::SubpassDependency> subpassDeps;
// For validating the depth ref
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);
};
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
vkAttachmentDescriptions[i] = vkDescriptions[i];
uint32_t subpassIndex = 0;
if (!subpasses.empty())
{
for (auto& subpass : subpasses)
{
subpassDescriptions.emplace_back();
auto& spDesc = subpassDescriptions.back();
vkSubpassDescriptions.emplace_back();
auto& spDesc = vkSubpassDescriptions.back();
spDesc.pColorAttachments = subpass.colorRefs.data();
spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size());
@ -88,18 +93,18 @@ namespace SHADE
};
// Push a new dependency
subpassDeps.push_back(dependency);
vkSubpassDeps.push_back(dependency);
++subpassIndex;
}
// Renderpass create info for render pass creation
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(subpassDeps.size());
renderPassCreateInfo.pDependencies = subpassDeps.data();
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();
}
// No subpasses passed in, create a default one.
@ -172,6 +177,8 @@ namespace SHADE
: logicalDeviceHdl{ inLogicalDeviceHdl }
, numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) }
, clearColors{}
, vkSubpassDescriptions{ }
, vkSubpassDeps{ }
{
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}} };
}
subpassDescriptions.resize (spDescs.size());
for (uint32_t i = 0; i < subpassDescriptions.size(); ++i)
{
subpassDescriptions[i] = spDescs[i];
}
vkAttachmentDescriptions.resize(vkDescriptions.size());
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
vkAttachmentDescriptions[i] = vkDescriptions[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{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size());
renderPassCreateInfo.pDependencies = spDeps.data();
@ -210,8 +223,11 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept
: vkRenderpass {rhs.vkRenderpass}
, logicalDeviceHdl {rhs.logicalDeviceHdl}
, subpassDescriptions {std::move (rhs.subpassDescriptions)}
, clearColors {std::move (rhs.clearColors)}
, vkSubpassDescriptions{ std::move(rhs.vkSubpassDescriptions) }
, vkSubpassDeps{ std::move(rhs.vkSubpassDeps) }
, clearColors{ std::move(rhs.clearColors) }
, vkAttachmentDescriptions{ std::move(rhs.vkAttachmentDescriptions) }
, numAttDescs{rhs.numAttDescs}
{
rhs.vkRenderpass = VK_NULL_HANDLE;
}
@ -224,8 +240,11 @@ namespace SHADE
vkRenderpass = rhs.vkRenderpass;
logicalDeviceHdl = rhs.logicalDeviceHdl;
subpassDescriptions = std::move(rhs.subpassDescriptions);
vkSubpassDescriptions = std::move(rhs.vkSubpassDescriptions);
vkSubpassDeps = std::move(rhs.vkSubpassDeps);
clearColors = std::move(rhs.clearColors);
vkAttachmentDescriptions = std::move(rhs.vkAttachmentDescriptions);
numAttDescs = std::move(rhs.numAttDescs);
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
{
return vkRenderpass;

View File

@ -29,7 +29,13 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! 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
std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors;
@ -49,6 +55,8 @@ namespace SHADE
SHVkRenderpass(SHVkRenderpass&& rhs) noexcept;
SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/

View File

@ -272,6 +272,17 @@ namespace SHADE
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)
{
auto window = windowMap.GetWindow(hwnd);
@ -307,6 +318,8 @@ namespace SHADE
case WM_CREATE:
OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam));
break;
case WM_CLOSE:
case WM_DESTROY:
OnDestroy();
return 0;
@ -362,8 +375,17 @@ namespace SHADE
}
void SHADE::SHWindow::OnClose()
{
for (const auto& callbackFn : windowCloseCallbacks | std::views::values)
{
callbackFn();
}
}
void SHWindow::OnDestroy()
{
OnClose();
this->Destroy();
}
@ -375,6 +397,14 @@ namespace SHADE
{
wndData.width = static_cast<unsigned>(size.cx);
wndData.height = static_cast<unsigned>(size.cy);
if (type == SIZE_MINIMIZED)
{
wndData.isMinimised = true;
}
else
wndData.isMinimised = false;
for (auto const& entry : windowResizeCallbacks)
{
entry.second(static_cast<uint32_t>(wndData.width), static_cast<uint32_t>(wndData.height));

View File

@ -18,7 +18,7 @@ namespace SHADE
};
struct WindowData
{
{
unsigned x = 0;
unsigned y = 0;
@ -42,7 +42,7 @@ namespace SHADE
bool closable = true;
bool minimizable = true;
bool maximizable = true;
//bool canFullscreen = true;
@ -56,11 +56,13 @@ namespace SHADE
bool shadowEnabled = true;
bool isVisible = true;
bool isFullscreen = false;
bool modal = false;
bool isMinimised = false;
std::wstring title = L"SHADE ENGINE";
std::wstring name = L"SHADEEngineApp";
@ -73,6 +75,7 @@ namespace SHADE
public:
using SHVec2 = std::pair<uint32_t, uint32_t>;
typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn;
typedef std::function<void(void)> WindowCloseCallbackFn;
typedef uint16_t CALLBACKID;
SHWindow();
@ -103,7 +106,7 @@ namespace SHADE
void SetMousePosition(unsigned x, unsigned y);
//unsigned GetBGColor();
void SetBGColor(unsigned color);
void Minimize();
@ -123,6 +126,9 @@ namespace SHADE
CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn);
void UnregisterWindowSizeCallback(CALLBACKID const& callbackid);
CALLBACKID RegisterWindowCloseCallback(WindowCloseCallbackFn);
void UnregisterWindowCloseCallback(CALLBACKID const& callbackid);
bool IsMinimized() const { return wndData.isMinimised; }
protected:
static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@ -154,10 +160,13 @@ namespace SHADE
HFONT font;
std::unordered_map<CALLBACKID, WindowResizeCallbackFn> windowResizeCallbacks;
std::unordered_map<CALLBACKID, WindowCloseCallbackFn> windowCloseCallbacks;
CALLBACKID windowResizeCallbackCount{};
CALLBACKID windowCloseCallbackCount{};
//TODO: Shift to events abstraction
void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct);
void OnClose();
void OnDestroy();
//void OnFileDrop(HDROP drop);
void OnSize(UINT msg, UINT type, SIZE size);

View File

@ -390,6 +390,13 @@ RTTR_REGISTRATION
using namespace SHADE;
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")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )

View File

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

View File

@ -118,7 +118,7 @@ namespace SHADE
/// <param name="handle">Handle to the resource object.</param>
/// <returns>Read-only reference to the resource object.</returns>
template<typename T>
const T& Get(Handle<T> handle) const;
const T& Get(Handle<T> handle) const;
private:
/*-----------------------------------------------------------------------------*/

View File

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

View File

@ -153,6 +153,16 @@ namespace SHADE
csEditorRenderScripts(entity);
}
void SHScriptEngine::UndoScriptInspectorChanges() const
{
csEditorUndo();
}
void SHScriptEngine::RedoScriptInspectorChanges() const
{
csEditorRedo();
}
/*-----------------------------------------------------------------------------------*/
/* Static Utility Functions */
/*-----------------------------------------------------------------------------------*/
@ -400,6 +410,18 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".Editor",
"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()

View File

@ -171,6 +171,14 @@ namespace SHADE
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
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 */
@ -243,9 +251,8 @@ namespace SHADE
CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr;
// - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
// Delegates
/*ECS::EntityEvent::Delegate onEntityCreate;
ECS::EntityEvent::Delegate onEntityDestroy;*/
CsFuncPtr csEditorUndo = nullptr;
CsFuncPtr csEditorRedo = nullptr;
/*-----------------------------------------------------------------------------*/
/* Event Handler Functions */

View File

@ -30,7 +30,8 @@ project "SHADE_Managed"
"%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}",
"%{IncludeDir.yamlcpp}",
"%{IncludeDir.RTTR}/include",
"%{IncludeDir.RTTR}/include",
"%{IncludeDir.dotnet}\\include",
"%{wks.location}/SHADE_Engine/src"
}
@ -85,3 +86,8 @@ project "SHADE_Managed"
optimize "On"
defines{"_RELEASE"}
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
\par email: kahwei.tng\@digipen.edu
\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.
Note: This file is written in C++17/CLI.
@ -16,6 +16,8 @@ of DigiPen Institute of Technology is prohibited.
#include "SHpch.h"
// Primary Header
#include "Editor/Editor.hxx"
// STL Includes
#include <memory>
// External Dependencies
#include "Editor/SHEditorUI.h"
// Project Headers
@ -25,6 +27,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Utility/Debug.hxx"
#include "Serialisation/ReflectionUtilities.hxx"
#include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/Command/SHCommand.hpp"
// Using Directives
using namespace System;
@ -48,9 +52,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \
field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \
} \
/// <summary>
@ -69,9 +75,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \
field->SetValue(object, Convert::ToCLI(val)); \
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \
} \
} \
@ -105,26 +113,43 @@ namespace SHADE
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.RenderScriptsInInspector")
}
void Editor::RenderScriptAddButton(Entity entity)
{
// Get list of Scripts
auto scriptTypes = ScriptStore::GetAvailableScriptList();
void Editor::RenderScriptAddButton(Entity entity)
{
// Get list of Scripts
auto scriptTypes = ScriptStore::GetAvailableScriptList();
// Define pop up
if (SHEditorUI::BeginMenu("Add Script", ICON_MD_LIBRARY_ADD))
{
for each (Type ^ type in scriptTypes)
{
if (SHEditorUI::Selectable(Convert::ToNative(type->Name)))
{
// Add the script
ScriptStore::AddScriptViaName(entity, type->Name);
}
}
// Define pop up
if (SHEditorUI::BeginMenu("Add Script", ICON_MD_LIBRARY_ADD))
{
for each (Type ^ type in scriptTypes)
{
if (SHEditorUI::Selectable(Convert::ToNative(type->Name)))
{
// Add the script
ScriptStore::AddScriptViaName(entity, type->Name);
}
}
SHEditorUI::EndMenu();
}
}
SHEditorUI::EndMenu();
}
}
/*---------------------------------------------------------------------------------*/
/* 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 */
@ -192,9 +217,11 @@ namespace SHADE
}
int val = safe_cast<int>(field->GetValue(object));
int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames))
{
field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal);
}
}
else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2)
@ -210,9 +237,11 @@ namespace SHADE
// Actual Field
std::string val = Convert::ToNative(stringVal);
std::string oldVal = val;
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), 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
#include "Engine/Entity.hxx"
#include "Scripts/Script.hxx"
#include "UndoRedoStack.hxx"
namespace SHADE
{
@ -36,15 +37,26 @@ namespace SHADE
/// rendering code.
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
static void RenderScriptsInInspector(Entity entity);
/// <summary>
/// Renders a dropdown button that allows for the addition of PlushieScripts
/// onto the specified Entity.
/// </summary>
/// <param name="entity">The Entity to add PlushieScripts to.</param>
static void RenderScriptAddButton(Entity entity);
static void RenderScriptsInInspector(Entity entity);
/// <summary>
/// Renders a dropdown button that allows for the addition of PlushieScripts
/// onto the specified Entity.
/// </summary>
/// <param name="entity">The Entity to add PlushieScripts to.</param>
static void RenderScriptAddButton(Entity entity);
/*-----------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*-----------------------------------------------------------------------------*/
static void Undo();
static void Redo();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
static UndoRedoStack actionStack;
private:
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
@ -73,5 +85,6 @@ namespace SHADE
/// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
};
}

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>();
};
}