Merge remote-tracking branch 'origin/main' into SP3-2-Physics

This commit is contained in:
Diren D Bharwani 2022-09-27 19:07:27 +08:00
commit cfd387e51c
52 changed files with 9125 additions and 207 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

4993
Assets/racoon.gltf Normal file

File diff suppressed because one or more lines are too long

View File

@ -144,7 +144,7 @@ if %_e%==14 (goto :done) else (goto :tinyddsloader)
:tinyddsloader
echo --------------------tinyddsloader-------------------------
rmdir "Dependencies/tinyddsloader" /S /Q
git clone https://github.com/benikabocha/tinyddsloader.git "Dependencies/tinyddsloader"
git clone https://github.com/SHADE-DP/tinyddsloader.git "Dependencies/tinyddsloader"
:done
echo DONE!

View File

@ -30,11 +30,12 @@ project "SHADE_Application"
externalincludedirs
{
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.tinyddsloader}"
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.VULKAN}/include",
"%{IncludeDir.VMA}/include",
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
"%{IncludeDir.RTTR}/include",
"%{IncludeDir.tinyddsloader}"
}
externalwarnings "Off"
@ -72,8 +73,12 @@ project "SHADE_Application"
filter "configurations:Debug"
symbols "On"
defines {"_DEBUG"}
defines {"_DEBUG", "SHEDITOR"}
filter "configurations:Release"
optimize "On"
defines{"_RELEASE", "SHEDITOR"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE"}

View File

@ -4,7 +4,7 @@
//#define SHEDITOR
#ifdef SHEDITOR
#include "Editor/SHEditor.h"
#include "Editor/SHEditor.hpp"
//#include "Scenes/SBEditorScene.h"
#endif // SHEDITOR
@ -46,14 +46,13 @@ namespace Sandbox
// Set working directory
SHADE::SHFileUtilities::SetWorkDirToExecDir();
SDL_Init(SDL_INIT_EVERYTHING);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
// Create Systems
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
// TODO(Diren): Create Physics System here
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
@ -79,19 +78,18 @@ namespace Sandbox
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
//TODO: REMOVE AFTER PRESENTATION
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.fbx");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
//TODO: REMOVE AFTER PRESENTATION
// Set up graphics system and windows
graphicsSystem->SetWindow(&window);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
//auto [w, h] = window.GetWindowSize();
//SDL_SetWindowSize(sdlWindow, w, h);
SHADE::SHSystemManager::Init();
#ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHADE::SHEditor::Initialise(sdlWindow);
#else
#endif
@ -112,13 +110,9 @@ namespace Sandbox
graphicsSystem->BeginRender();
#ifdef SHEDITOR
SHADE::SHEditor::PreRender();
//SHADE::SHEditor::Render();
SHADE::SHEditor::Update(0.16f);
#endif
#ifdef SHEDITOR
SHADE::SHEditor::Render();
#endif
graphicsSystem->Run(1.0f);
graphicsSystem->EndRender();
@ -131,11 +125,12 @@ namespace Sandbox
{
#ifdef SHEDITOR
SHADE::SHEditor::Exit();
#endif
SHSceneManager::Exit();
SHADE::SHSystemManager::Exit();
SDL_DestroyWindow(sdlWindow);
SDL_Quit();
#endif
SHSceneManager::Exit();
SHADE::SHSystemManager::Exit();
}
}

View File

@ -54,6 +54,9 @@ namespace Sandbox
}
graphicsSystem->BuildMeshBuffers();
//Test Textures
auto textures{ SHADE::SHAssetManager::GetAllTextures() };
// Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();

View File

@ -117,12 +117,24 @@ project "SHADE_Engine"
filter "configurations:Debug"
symbols "On"
defines {"_DEBUG"}
defines {"_DEBUG", "SHEDITOR"}
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"}
--links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
filter "configurations:Release"
optimize "On"
defines{"_RELEASE", "SHEDITOR"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE"}
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",
}
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -1,11 +0,0 @@
#pragma once
#include "tinyddsloader.h"
namespace SHADE
{
struct SHDDSAsset
{
tinyddsloader::DDSFile image;
};
}

View File

@ -21,9 +21,9 @@ namespace SHADE
std::string meshName;
std::vector<SHVec3> vertexPosition;
std::vector<SHVec2> texCoords;
std::vector<SHVec3> vertexTangent;
std::vector<SHVec3> vertexNormal;
std::vector<SHVec2> texCoords;
std::vector<uint32_t> indices;
};
}

View File

@ -0,0 +1,46 @@
#pragma once
#include "tinyddsloader.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include <memory>
namespace SHADE
{
struct SHTextureAsset
{
uint32_t numBytes;
uint32_t width;
uint32_t height;
SHTexture::TextureFormat format;
std::vector<uint32_t> mipOffsets;
SHTexture::PixelChannel const * pixelData;
SHTextureAsset()
: numBytes{ 0 },
width{ 0 },
height{ 0 },
format{ SHTexture::TextureFormat::eUndefined },
pixelData{ nullptr }
{}
SHTextureAsset(SHTextureAsset const& rhs)
: numBytes{ rhs.numBytes },
width{ rhs.width },
height{ rhs.height },
format{ rhs.format },
mipOffsets{ rhs.mipOffsets },
pixelData(rhs.pixelData)
{}
//SHTextureAsset(SHTextureAsset&& rhs)
// : numBytes{ rhs.numBytes },
// width{ rhs.width },
// height{ rhs.height },
// format{ rhs.format },
// mipOffsets{ rhs.mipOffsets },
// pixelData(std::move(rhs.pixelData))
//{}
};
}

View File

@ -1,38 +0,0 @@
#include "SHpch.h"
#include "SHDDSLoader.h"
namespace SHADE
{
std::string SHDDSLoader::TinyDDSResultToString(tinyddsloader::Result value)
{
switch (value)
{
case tinyddsloader::Result::ErrorFileOpen:
return "File open err";
case tinyddsloader::Result::ErrorRead:
return "File read err";
case tinyddsloader::Result::ErrorMagicWord:
return "File header magicword err";
case tinyddsloader::Result::ErrorSize:
return "File size err";
case tinyddsloader::Result::ErrorVerify:
return "Pixel format err";
case tinyddsloader::Result::ErrorNotSupported:
return "Unsupported format";
case tinyddsloader::Result::ErrorInvalidData:
return "Invalid data";
default:
return "Unknown";
}
}
void SHDDSLoader::LoadImageAsset(AssetPath path, SHDDSAsset& asset)
{
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
loadResult = asset.image.Load(path.string().c_str());
if (loadResult != tinyddsloader::Result::Success)
{
SHLOG_ERROR("Unable to load DDS file: {} at {}", TinyDDSResultToString(loadResult), path.string());
}
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#define TINYDDSLOADER_IMPLEMENTATION
#include "../SHAssetMacros.h"
#include "../Asset Types/SHDDSAsset.h"
#include "tinyddsloader.h"
#include <vector>
namespace SHADE
{
class SHDDSLoader
{
private:
static std::string TinyDDSResultToString(tinyddsloader::Result value);
public:
static void LoadImageAsset(AssetPath paths, SHDDSAsset& image);
};
}

View File

@ -100,9 +100,7 @@ namespace SHADE
| aiProcess_JoinIdenticalVertices
// join identical vertices/ optimize indexing
| aiProcess_RemoveRedundantMaterials // remove redundant materials
| aiProcess_FindInvalidData
// detect invalid model data, such as invalid normal vectors
| aiProcess_PreTransformVertices // pre-transform all vertices
| aiProcess_FindInvalidData// detect invalid model data, such as invalid normal vectors
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
);

View File

@ -0,0 +1,48 @@
#include "SHpch.h"
#include "SHMeshWriter.h"
#include <fstream>
void SHADE::SHMeshWriter::WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
{
std::ofstream file{path, std::ios::out | std::ios::binary};
if (!file.is_open())
{
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
}
file.write(
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
sizeof(uint32_t)
);
file.write(
reinterpret_cast<const char*>(&(asset.header.indexCount)),
sizeof(uint32_t)
);
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
file.write(
reinterpret_cast<char const*>(asset.vertexPosition.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexTangent.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.vertexNormal.data()),
vertexVec3Byte
);
file.write(
reinterpret_cast<char const*>(asset.texCoords.data()),
vertexVec2Byte
);
file.close();
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "../Asset Types/SHMeshAsset.h"
#include "../SHAssetMacros.h"
namespace SHADE
{
class SHMeshWriter
{
private:
public:
static void WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
};
}

View File

@ -0,0 +1,92 @@
#include "SHpch.h"
#include "SHTextureLoader.h"
namespace SHADE
{
std::string SHTextureLoader::TinyDDSResultToString(tinyddsloader::Result value)
{
switch (value)
{
case tinyddsloader::Result::ErrorFileOpen:
return "File open err";
case tinyddsloader::Result::ErrorRead:
return "File read err";
case tinyddsloader::Result::ErrorMagicWord:
return "File header magic word err";
case tinyddsloader::Result::ErrorSize:
return "File size err";
case tinyddsloader::Result::ErrorVerify:
return "Pixel format err";
case tinyddsloader::Result::ErrorNotSupported:
return "Unsupported format";
case tinyddsloader::Result::ErrorInvalidData:
return "Invalid data";
default:
return "Unknown";
}
}
vk::Format SHTextureLoader::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
{
switch (format)
{
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
return isLinear ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
return vk::Format::eR8G8B8A8Snorm;
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
default:
throw std::runtime_error("Unsupported DDS format.");
}
}
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
{
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
tinyddsloader::DDSFile file;
loadResult = file.Load(path.string().c_str());
if (loadResult != tinyddsloader::Result::Success)
{
SHLOG_ERROR("Unable to load Texture file: {} at {}", TinyDDSResultToString(loadResult), path.string());
}
size_t totalBytes{ 0 };
std::vector<uint32_t> mipOff(file.GetMipCount());
for (auto i{0}; i < file.GetMipCount(); ++i)
{
mipOff.push_back(totalBytes);
totalBytes += file.GetImageData(i, 0)->m_memSlicePitch;
}
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
std::memcpy(pixel, file.GetDDSData(), totalBytes);
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
asset.numBytes = totalBytes;
asset.width = file.GetWidth();
asset.height = file.GetHeight();
asset.format = ddsLoaderToVkFormat(file.GetFormat(), true);
asset.mipOffsets = std::move(mipOff);
asset.pixelData = std::move(pixel);
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#define TINYDDSLOADER_IMPLEMENTATION
#include "../SHAssetMacros.h"
#include "../Asset Types/SHTextureAsset.h"
#include "tinyddsloader.h"
namespace SHADE
{
class SHTextureLoader
{
private:
static std::string TinyDDSResultToString(tinyddsloader::Result value);
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
public:
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
};
}

View File

@ -69,8 +69,11 @@ enum class AssetType : uint8_t
#define SCENE_EXTENSION ".SHADE"
#define PREFAB_EXTENSION ".SHPrefab"
#define MATERIAL_EXTENSION ".SHMat"
#define TEXTURE_EXTENSION ".dds"
#define MESH_EXTENSION ".fbx"
#define TEXTURE_EXTENSION ".shtex"
#define DDS_EXTENSION ".dds"
#define FBX_EXTENSION ".fbx"
#define GLTF_EXTENSION ".gltf"
#define MESH_EXTENSION ".shmesh"
std::string const EXTENSIONS[] = {
AUDIO_EXTENSION,
@ -78,11 +81,14 @@ std::string const EXTENSIONS[] = {
MATERIAL_EXTENSION,
IMAGE_EXTENSION,
TEXTURE_EXTENSION,
DDS_EXTENSION,
MESH_EXTENSION,
SCRIPT_EXTENSION,
SCENE_EXTENSION,
PREFAB_EXTENSION,
AUDIO_WAV_EXTENSION
AUDIO_WAV_EXTENSION,
FBX_EXTENSION,
GLTF_EXTENSION
};
// Error flags

View File

@ -15,7 +15,7 @@
#include "Filesystem/SHFileSystem.h"
#include "Libraries/SHMeshLoader.h"
#include "Libraries/SHDDSLoader.h"
#include "Libraries/SHTextureLoader.h"
namespace SHADE
{
@ -26,7 +26,7 @@ namespace SHADE
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
std::unordered_map<AssetID, SHDDSAsset> SHAssetManager::ddsCollection;
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
/****************************************************************************
* \brief Static function to generate asset ID.
@ -199,7 +199,7 @@ namespace SHADE
{
AssetPath path{ p };
if (path.extension().string() == MESH_EXTENSION)
if (path.extension().string() == GLTF_EXTENSION)
{
LoadGLTF(
{
@ -211,7 +211,7 @@ namespace SHADE
}
);
}
else if (path.extension().string() == TEXTURE_EXTENSION)
else if (path.extension().string() == DDS_EXTENSION)
{
LoadDDS(
{
@ -236,6 +236,17 @@ namespace SHADE
return result;
}
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
{
std::vector<SHTextureAsset> result;
for (auto const& dds : textureCollection)
{
result.push_back(dds.second);
}
return result;
}
/****************************************************************************
* \param Path for meta data file
* \param Path for asset file
@ -294,11 +305,11 @@ namespace SHADE
void SHAssetManager::LoadDDS(SHAsset asset) noexcept
{
SHDDSAsset image;
SHTextureAsset image;
SHDDSLoader::LoadImageAsset(asset.path, image);
SHTextureLoader::LoadImageAsset(asset.path, image);
ddsCollection.emplace(GenerateAssetID(AssetType::DDS), image);
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
}
/****************************************************************************

View File

@ -13,7 +13,7 @@
#include "SHAsset.h"
#include "Asset Types/SHMeshAsset.h"
#include "Asset Types/SHDDSAsset.h"
#include "Asset Types/SHTextureAsset.h"
#include "SH_API.h"
namespace SHADE
@ -73,6 +73,7 @@ namespace SHADE
//TODO: TEMPORARY FOR TESTING GLTF & DDS
static void LoadDataTemp(std::string path) noexcept;
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
private:
/****************************************************************************
@ -127,6 +128,6 @@ namespace SHADE
static std::unordered_map<AssetID, SHAsset> assetRegistry;
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
static std::unordered_map<AssetID, SHDDSAsset> ddsCollection;
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
};
}

View File

@ -0,0 +1,51 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <functional>
namespace SHADE
{
class SHBaseCommand
{
public:
virtual ~SHBaseCommand() = default;
virtual void Execute() {}
virtual void Undo() {}
virtual void Merge(std::shared_ptr<SHBaseCommand>) {}
};//struct SHBaseCommand
template <typename T>
class SHCommand : SHBaseCommand
{
public:
typedef std::function<void(T const&)> SetterFunction;
SHCommand(T const& oldVal, T const& value, SetterFunction setFnc)
: oldValue(oldVal), newValue(value), set(setFnc)
{
}
void Execute() override
{
set(newValue);
}
void Undo() override
{
set(oldValue);
}
void Merge(std::shared_ptr<SHBaseCommand> newCommand) override
{
newValue = std::reinterpret_pointer_cast<SHCommand>(newCommand)->newValue;
}
private:
T oldValue;
T newValue;
SetterFunction set;
};
}//namespace SHADE

View File

@ -0,0 +1,57 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHCommandManager.h"
namespace SHADE
{
SHCommandManager::CommandStack SHCommandManager::undoStack{};
SHCommandManager::CommandStack SHCommandManager::redoStack{};
void SHCommandManager::PerformCommand(CommandPtr commandPtr, bool const& overrideValue)
{
redoStack = CommandStack();
commandPtr->Execute();
if (overrideValue && !undoStack.empty())
{
undoStack.top()->Merge(commandPtr);
}
else
{
undoStack.push(commandPtr);
}
}
void SHCommandManager::UndoCommand()
{
if (undoStack.empty())
return;
undoStack.top()->Undo();
redoStack.push(undoStack.top());
undoStack.pop();
}
void SHCommandManager::RedoCommand()
{
if (redoStack.empty())
return;
redoStack.top()->Execute();
undoStack.push(redoStack.top());
redoStack.pop();
}
std::size_t SHCommandManager::GetUndoStackSize()
{
return undoStack.size();
}
std::size_t SHCommandManager::GetRedoStackSize()
{
return redoStack.size();
}
}//namespace SHADE

View File

@ -0,0 +1,34 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <stack>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHCommand.hpp"
namespace SHADE
{
class SHCommandManager
{
public:
//#==============================================================#
//|| Type Aliases ||
//#==============================================================#
using CommandPtr = std::shared_ptr<SHBaseCommand>;
using CommandStack = std::stack<CommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void UndoCommand();
static void RedoCommand();
static std::size_t GetUndoStackSize();
static std::size_t GetRedoStackSize();
private:
static CommandStack undoStack;
static CommandStack redoStack;
};
}//namespace SHADE

View File

@ -0,0 +1,21 @@
#include "SHpch.h"
#include "SHDragDrop.hpp"
namespace SHADE
{
bool SHDragDrop::hasDragDrop = false;
bool SHDragDrop::BeginSource(ImGuiDragDropFlags const flags)
{ return ImGui::BeginDragDropSource(flags); }
void SHDragDrop::EndSource()
{ ImGui::EndDragDropSource();}
bool SHDragDrop::BeginTarget()
{ return ImGui::BeginDragDropTarget(); }
void SHDragDrop::EndTarget()
{ ImGui::EndDragDropTarget(); hasDragDrop = false;}
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <string_view>
#include <imgui.h>
namespace SHADE
{
//TODO: Convert to RTTR?
constexpr auto DRAG_EID = "DragEID";
constexpr auto DRAG_RESOURCE = "DragResource";
struct SHDragDrop
{
static bool BeginSource(ImGuiDragDropFlags const flags = 0);
/**
* \brief Ends the DragDrop Source. ONLY CALL IF BeginSource returns true
*/
static void EndSource();
template<typename T>
static bool SetPayload(std::string_view const type, T* object, ImGuiCond const cond = 0)
{
hasDragDrop = ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
return hasDragDrop;
}
static bool BeginTarget();
/**
* \brief Ends the DragDrop Target. ONLY CALL IF BeginTarget returns true
*/
static void EndTarget();
template<typename T>
static T* AcceptPayload(std::string_view const type, ImGuiDragDropFlags const flags = 0)
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(type.data(), flags))
return static_cast<T*>(payload->Data);
return nullptr;
}
static bool hasDragDrop;
};
}

View File

@ -0,0 +1,212 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp"
#include "SHHierarchyPanel.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Editor/SHEditor.hpp"
#include "Scene/SHSceneManager.h"
#include "Editor/DragDrop/SHDragDrop.hpp"
#include "Tools/SHException.h"
#include "Editor/IconsMaterialDesign.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
namespace SHADE
{
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHHierarchyPanel::SHHierarchyPanel()
:SHEditorWindow("Hierarchy Panel", ImGuiWindowFlags_MenuBar)
{
}
void SHHierarchyPanel::Init()
{
SHEditorWindow::Init();
}
void SHHierarchyPanel::Update()
{
SHEditorWindow::Update();
isAnyNodeSelected = false;
if (Begin())
{
DrawMenuBar();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
if(const auto root = sceneGraph.GetRoot())
{
auto const& children = root->GetChildren();
for (const auto child : children)
{
RecursivelyDrawEntityNode(child);
}
}
else
{
SHLOG_WARNING("Scene Graph root is null! Unable to render hierarchy.")
}
if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
SHEditor::selectedEntities.clear();
}
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
ImGui::End();
}
}
void SHHierarchyPanel::Exit()
{
SHEditorWindow::Exit();
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHHierarchyPanel::DrawMenuBar() const noexcept
{
if (ImGui::BeginMenuBar())
{
if (ImGui::SmallButton(ICON_MD_ADD))
{
SHEntityManager::CreateEntity();
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Add Entity");
ImGui::EndTooltip();
}
ImGui::EndMenuBar();
}
}
ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* currentNode)
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
//Get node data (Children, eid, selected)
auto& children = currentNode->GetChildren();
EntityID eid = currentNode->GetEntityID();
const bool isSelected = (std::ranges::find(SHEditor::selectedEntities, eid) != SHEditor::selectedEntities.end());
const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow);
//bool highlighted = false;
//if(highlighted)
//{
// ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
//}
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
//Draw Node
bool isNodeOpen = ImGui::TreeNodeEx((void*)eid, nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//Check For Begin Drag
if (SHDragDrop::BeginSource())
{
ImGui::Text("Moving EID: %zu", eid);
SHDragDrop::SetPayload<EntityID>(DRAG_EID, &eid);
SHDragDrop::EndSource();
}
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
{
if (const EntityID* eidPayload = SHDragDrop::AcceptPayload<EntityID>(DRAG_EID)) //If payload is valid
{
EntityID const dropEID = *eidPayload;
if(!sceneGraph.GetChild(dropEID, eid))
sceneGraph.SetParent(dropEID, eid); //Set dropEID parent to eid (belonging to current Node)
SHDragDrop::EndTarget();
}
}
//Context menu
if(ImGui::BeginPopupContextItem(std::to_string(eid).c_str()))
{
if(!isSelected)
{
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{
SHEntityManager::DestroyEntity(eid);
}
if((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
{
sceneGraph.SetParent(currentNode->GetEntityID(), nullptr);
}
ImGui::EndPopup();
}
//Handle node selection
if (ImGui::IsItemHovered())
{
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
if (!isSelected)
{
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}//if not selected
else
{
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
{
auto it = std::ranges::remove(SHEditor::selectedEntities, eid).begin();
}//if mod ctrl is not pressed
else
{
SHEditor::selectedEntities.clear();
SHEditor::selectedEntities.push_back(eid);
}
}//if selected
}//if left mouse button released
}//if item hovered
if (isNodeOpen)
{
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
const float horizontalOffset = 0.0f;
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
vertLineStart.x += horizontalOffset;
ImVec2 vertLineEnd = vertLineStart;
for (const auto child : children)
{
const float horizontalLineSize = 8.0f;
const ImRect childRect = RecursivelyDrawEntityNode(child);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 2);
vertLineEnd.y = midPoint;
}
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 2);
ImGui::TreePop();
}
return nodeRect;
}
void SHHierarchyPanel::CreateChildEntity(EntityID parentEID) const noexcept
{
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
}
}//namespace SHADE

View File

@ -0,0 +1,33 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "imgui_internal.h"
#include "ECS_Base/SHECSMacros.h"
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHSceneNode;
constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
class SHHierarchyPanel final : public SHEditorWindow
{
public:
SHHierarchyPanel();
void Init() override;
void Update() override;
void Exit() override;
private:
void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode*);
void CreateChildEntity(EntityID parentEID) const noexcept;
std::string filter;
bool isAnyNodeSelected = false;
};//class SHHierarchyPanel
}//namespace SHADE

View File

@ -0,0 +1,70 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <rttr/type>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/IconsMaterialDesign.h"
#include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp"
namespace SHADE
{
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
static void DrawContextMenu(T* component)
{
if(!component)
return;
rttr::string_view componentName = rttr::type::get<T>().get_name();
if (ImGui::BeginPopupContextItem(componentName.data()))
{
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data()))
{
//SHClipboardUtil::WriteStringToClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT, SHComponentToString(component));
}
if (ImGui::Selectable(std::format("{} Paste {}", ICON_MD_CONTENT_PASTE, componentName.data()).data()))
{
//SHStringToComponent(component, SHClipboardUtil::ReadStringFromClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT));
}
if (ImGui::Selectable(std::format("{} Delete {}", ICON_MD_DELETE, componentName.data()).data()))
{
SHComponentManager::RemoveComponent<T>(component->GetEID());
}
ImGui::EndPopup();
}
}
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
static void DrawComponent(T* component)
{
if (!component)
return;
auto componentType = rttr::type::get(*component);
CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
auto const& properties = componentType.get_properties();
for (auto const& property : properties)
{
auto const& type = property.get_type();
if (type == rttr::type::get<SHVec4>())
{
DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
}
else if (type == rttr::type::get<SHVec3>())
{
DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
}
}
}
else DrawContextMenu(component);
}
}

View File

@ -0,0 +1,73 @@
#include "SHpch.h"
#include "SHEditorInspector.h"
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Editor/SHEditor.hpp"
#include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp"
#include "SHEditorComponentView.hpp"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
namespace SHADE
{
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
void DrawAddComponentButton(EntityID const& eid)
{
if(!SHComponentManager::HasComponent<ComponentType>(eid) && ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()))
{
SHComponentManager::AddComponent<ComponentType>(eid);
}
}
SHEditorInspector::SHEditorInspector()
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
{
}
void SHEditorInspector::Init()
{
SHEditorWindow::Init();
}
void SHEditorInspector::Update()
{
SHEditorWindow::Update();
if (Begin())
{
if (!SHEditor::selectedEntities.empty())
{
EntityID const& eid = SHEditor::selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
ImGui::SameLine();
ImGui::InputText("##EntityName", &entity->name);
if (auto transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
DrawComponent(transformComponent);
}
ImGui::Separator();
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
{
DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid);
ImGui::EndMenu();
}
}
ImGui::End();
}
}
void SHEditorInspector::Exit()
{
SHEditorWindow::Exit();
}
}

View File

@ -0,0 +1,30 @@
#pragma once
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <rttr/type>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHComponent;
class SHEditorInspector final : public SHEditorWindow
{
public:
SHEditorInspector();
void Init() override;
void Update() override;
void Exit() override;
private:
};
}

View File

@ -0,0 +1,130 @@
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <imgui_internal.h>
#include <rttr/type>
#include "Editor/SHEditor.hpp"
namespace SHADE
{
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
constexpr ImGuiWindowFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode;
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHEditorMenuBar::SHEditorMenuBar()
:SHEditorWindow("SHEditorMenuBar", editorMenuBarFlags | ImGuiWindowFlags_NoBackground)
{
}
void SHEditorMenuBar::Init()
{
SHEditorWindow::Init();
}
void SHEditorMenuBar::Update()
{
SHEditorWindow::Update();
DrawMainMenuBar();
DrawSecondaryBar();
DrawStatusBar();
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHEditorMenuBar::DrawMainMenuBar() noexcept
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { ImVec2(0.0f, 0.0f) });
if (Begin())
{
ImGui::PopStyleVar(3);
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("File"))
{
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Edit"))
{
ImGui::BeginDisabled(!SHCommandManager::GetUndoStackSize());
if(ImGui::Button(std::format("{} Undo", ICON_MD_UNDO).data()))
{
SHCommandManager::UndoCommand();
}
ImGui::EndDisabled();
ImGui::BeginDisabled(!SHCommandManager::GetRedoStackSize());
if(ImGui::Button(std::format("{} Redo", ICON_MD_REDO).data()))
{
SHCommandManager::RedoCommand();
}
ImGui::EndDisabled();
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Theme"))
{
auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
auto values = styles.get_values();
for (auto style : values)
{
if(ImGui::Selectable(style.to_string().c_str()))
{
SHEditor::SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
const ImGuiID dockspace_id = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspaceFlags);
ImGui::End();
}
}
void SHEditorMenuBar::DrawSecondaryBar() const noexcept
{
}
void SHEditorMenuBar::DrawStatusBar() const noexcept
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { ImVec2(0.0f, 0.0f) });
if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags))
{
ImGui::Text("Entity count: ");
ImGui::End();
}
ImGui::PopStyleVar(3);
}
}//namespace SHADE

View File

@ -0,0 +1,22 @@
#pragma once
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Editor/EditorWindow/SHEditorWindow.h"
namespace SHADE
{
class SHEditorMenuBar final : public SHEditorWindow
{
public:
SHEditorMenuBar();
virtual void Init() override;
virtual void Update() override;
private:
void DrawMainMenuBar() noexcept;
void DrawSecondaryBar() const noexcept;
void DrawStatusBar() const noexcept;
float menuBarHeight = 20.0f;
};//class SHEditorMenuBar
}//namespace SHADE

View File

@ -0,0 +1,46 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SHEditorWindow.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
namespace SHADE
{
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags)
: isOpen(true), windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
{
}
void SHEditorWindow::Init()
{
}
void SHEditorWindow::Update()
{
}
void SHEditorWindow::Exit()
{
}
//#==============================================================#
//|| Protected Member Functions ||
//#==============================================================#
bool SHEditorWindow::Begin()
{
return ImGui::Begin(windowName.data(), &isOpen, windowFlags);
}
}//namespace SHADE

View File

@ -0,0 +1,31 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <string>
//#==============================================================#
//|| Forward Declarations ||
//#==============================================================#
struct ImGuiIO;
typedef int ImGuiWindowFlags;
namespace SHADE
{
class SHEditorWindow
{
public:
SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags);
virtual ~SHEditorWindow() = default;
virtual void Init();
virtual void Update();
virtual void Exit();
bool isOpen = false;
std::string_view windowName;
protected:
virtual bool Begin();
ImGuiWindowFlags windowFlags = 0;
ImGuiIO& io;
};//class SHEditorWindow
}//namespace SHADE

View File

@ -0,0 +1,4 @@
#pragma once
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
#include "Inspector/SHEditorInspector.h" //Inspector

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +1,125 @@
//#==============================================================#
//|| PCH Include ||
//#==============================================================#
#include "SHpch.h"
#include "SHEditor.h"
#include <imgui.h>
#include "IconsMaterialDesign.h"
#include "DragDrop/SHDragDrop.hpp"
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Tools/SHLogger.h"
#include "Tools/SHException.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/Instance/SHVkInstance.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
//IMGUI Backend includes
#include "SHEditor.hpp"
#include "SHEditorWidgets.hpp"
//#==============================================================#
//|| Editor Window Includes ||
//#==============================================================#
#include "EditorWindow/SHEditorWindowIncludes.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <SDL.h>
#include <rttr/registration>
//#==============================================================#
//|| ImGui Backend Includes ||
//#==============================================================#
#include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h>
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::enumeration<SHEditor::Style>("Style")
(
value("SHADE", SHEditor::Style::SHADE),
value("DARK", SHEditor::Style::DARK),
value("LIGHT", SHEditor::Style::LIGHT),
value("CLASSIC", SHEditor::Style::CLASSIC)
);
}
namespace SHADE
{
//#==============================================================#
//|| Initialise static members ||
//#==============================================================#
Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
SHEditor::EditorWindowMap SHEditor::editorWindows{};
SHEditor::EditorWindowID SHEditor::windowCount{};
std::vector<EntityID> SHEditor::selectedEntities;
void SHEditor::Initialise(SDL_Window* sdlWindow)
//#==============================================================#
//|| Public Member Functions ||
//#==============================================================#
void SHEditor::Initialise(SDL_Window* const sdlWindow)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
if(auto context = ImGui::CreateContext())
{
if(context == nullptr)
{
SHLOG_CRITICAL("Failed to create ImGui Context")
}
}
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
ImGui_ImplSDL2_InitForVulkan(sdlWindow);
InitFonts();
InitBackend(sdlWindow);
auto* gfxSystem = reinterpret_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SetStyle(Style::SHADE);
//Add editor windows
CreateEditorWindow<SHEditorMenuBar>();
CreateEditorWindow<SHHierarchyPanel>();
CreateEditorWindow<SHEditorInspector>();
ImGui_ImplVulkan_InitInfo initInfo{};
initInfo.Instance = SHVkInstance::GetVkInstance();
initInfo.PhysicalDevice = gfxSystem->GetPhysicalDevice()->GetVkPhysicalDevice();
initInfo.Device = gfxSystem->GetDevice()->GetVkLogicalDevice();
initInfo.Queue = gfxSystem->GetQueue()->GetVkQueue();
initInfo.DescriptorPool = gfxSystem->GetDescriptorPool()->GetVkHandle();
initInfo.MinImageCount = initInfo.ImageCount = gfxSystem->GetSwapchain()->GetNumImages();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
/*auto renderPass = gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetRenderpass();
ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass());*/
imguiCommandBuffer->BeginRecording();
ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer());
imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({imguiCommandBuffer}, {}, {}, vk::PipelineStageFlagBits::eNone, {});
ImGui_ImplVulkan_DestroyFontUploadObjects();
/*gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});*/
//ImGuiIO& io = ImGui::GetIO();
//int w, h;
//SDL_GetWindowSize(sdlWindow, &w, &h);
//io.DisplaySize = { static_cast<float>(w),static_cast<float>(h)};
SHLOG_INFO("Successfully initialised SHADE Engine Editor")
}
void SHEditor::PreRender()
void SHEditor::Update(float const dt)
{
(void)dt;
NewFrame();
ImGui::ShowDemoWindow();
ImGui::Begin("Your mom");
if (ImGui::Button("OP"))
for (const auto& window : editorWindows | std::views::values)
{
std::cout << "HEHEHEOHEIOHIEOH\n";
window->Update();
}
ImGui::End();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{
SHCommandManager::RedoCommand();
}
else if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
{
SHCommandManager::UndoCommand();
}
Render();
}
void SHEditor::Render()
@ -87,6 +133,18 @@ namespace SHADE
}
}
void SHEditor::InitFonts() noexcept
{
ImGuiIO& io = ImGui::GetIO();
ImFont* mainFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path
static const ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
ImFont* UIFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges); //TODO: Change to config based assets path
io.Fonts->Build();
}
void SHEditor::Exit()
{
ImGui_ImplVulkan_Shutdown();
@ -94,19 +152,164 @@ namespace SHADE
ImGui::DestroyContext();
}
void SHEditor::InitBackend()
void SHEditor::SetStyle(Style style)
{
switch (style)
{
default:
case Style::SHADE:
{
ImGuiStyle& imStyle = ImGui::GetStyle();
ImVec4* colors = imStyle.Colors;
colors[ImGuiCol_Text] = ImVec4(0.706f, 0.729f, 0.757f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.172f, 0.184f, 0.203f, 1.f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f);
colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f);
colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_TitleBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TitleBgCollapsed] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_MenuBarBg] = ImVec4(0.129f, 0.141f, 0.157f, 1.f);
colors[ImGuiCol_ScrollbarBg] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_CheckMark] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f);
colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.15f, 0.15f, 0.15f, 0.54f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f);
colors[ImGuiCol_Separator] = colors[ImGuiCol_MenuBarBg];
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f);
colors[ImGuiCol_Tab] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.14f, 0.14f, 0.14f, 0.8f);
colors[ImGuiCol_TabUnfocused] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_TabUnfocusedActive] = colors[ImGuiCol_WindowBg];
colors[ImGuiCol_DockingPreview] = ImVec4(0.627f, 0.239f, 0.761f, 1.00f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.855f, 0.6f, 0.941f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.73f, 0.73f, 0.73f, 0.7f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.141f, 0.141f, 0.141f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = colors[ImGuiCol_NavHighlight];
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.2f, 0.2f, 0.2f, 0.65f);
imStyle.WindowPadding = ImVec2(8.00f, 8.00f);
imStyle.FramePadding = ImVec2(5.00f, 2.00f);
imStyle.CellPadding = ImVec2(6.00f, 8.00f);
imStyle.ItemSpacing = ImVec2(6.00f, 6.00f);
imStyle.ItemInnerSpacing = ImVec2(6.00f, 6.00f);
imStyle.TouchExtraPadding = ImVec2(0.00f, 0.00f);
imStyle.IndentSpacing = 25;
imStyle.ScrollbarSize = 15;
imStyle.GrabMinSize = 10;
imStyle.WindowBorderSize = 0.6f;
imStyle.ChildBorderSize = 1;
imStyle.PopupBorderSize = 1;
imStyle.FrameBorderSize = 1;
imStyle.TabBorderSize = 1;
imStyle.WindowRounding = 7;
imStyle.ChildRounding = 4;
imStyle.FrameRounding = 3;
imStyle.PopupRounding = 4;
imStyle.ScrollbarRounding = 9;
imStyle.GrabRounding = 3;
imStyle.LogSliderDeadzone = 4;
imStyle.TabRounding = 4;
imStyle.WindowMenuButtonPosition = ImGuiDir_None;
}
break;
case Style::DARK: ImGui::StyleColorsDark(); break;
case Style::LIGHT: ImGui::StyleColorsLight(); break;
case Style::CLASSIC: ImGui::StyleColorsClassic(); break;
}
}
//#==============================================================#
//|| Private Member Functions ||
//#==============================================================#
void SHEditor::InitBackend(SDL_Window* sdlWindow)
{
if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to perform SDL initialisation for Vulkan")
}
const auto* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
ImGui_ImplVulkan_InitInfo initInfo{};
initInfo.Instance = SHVkInstance::GetVkInstance();
initInfo.PhysicalDevice = gfxSystem->GetPhysicalDevice()->GetVkPhysicalDevice();
initInfo.Device = gfxSystem->GetDevice()->GetVkLogicalDevice();
initInfo.Queue = gfxSystem->GetQueue()->GetVkQueue();
initInfo.DescriptorPool = gfxSystem->GetDescriptorPool()->GetVkHandle();
initInfo.MinImageCount = initInfo.ImageCount = gfxSystem->GetSwapchain()->GetNumImages();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
SHASSERT(!renderers.empty(), "No Renderers available")
auto renderGraph = renderers[0]->GetRenderGraph();
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to initialise Vulkan backend")
}
imguiCommandBuffer->BeginRecording();
if(ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer()) == false)
{
SHLOG_CRITICAL("Editor backend initialisation; Failed to create fonts texture for Vulkan backend")
}
imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {});
ImGui_ImplVulkan_DestroyFontUploadObjects();
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});
}
void SHEditor::NewFrame()
{
SDL_Event event;
while (SDL_PollEvent(&event) != 0)
{
ImGui_ImplSDL2_ProcessEvent(&event);
}
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
void SHEditor::EndFrame()
{
}
}
}//namespace SHADE

View File

@ -1,29 +0,0 @@
#pragma once
#include "SH_API.h"
#include <SDL.h>
#include "Resource/Handle.h"
namespace SHADE
{
class SHVkCommandBuffer;
class SHVkCommandPool;
class SH_API SHEditor
{
public:
static void Initialise(SDL_Window* sdlWindow);
static void PreRender();
static void Render();
static void Exit();
private:
static void InitBackend();
static void NewFrame();
static void EndFrame();
static Handle<SHVkCommandPool> imguiCommandPool;
static Handle<SHVkCommandBuffer> imguiCommandBuffer;
};
}

View File

@ -0,0 +1,168 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <vector>
#include <unordered_map>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "SH_API.h"
#include "ECS_Base/SHECSMacros.h"
#include "Resource/Handle.h"
#include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLogger.h"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <SDL_video.h>
namespace SHADE
{
//#==============================================================#
//|| Forward Declarations ||
//#==============================================================#
class SHVkCommandBuffer;
class SHVkCommandPool;
/**
* @brief SHEditor static class contains editor variables and implementation of editor functions.
*
*/
class SH_API SHEditor
{
public:
//#==============================================================#
//|| Type Aliases ||
//#==============================================================#
using EditorWindowID = uint8_t;
using EditorWindowPtr = std::unique_ptr<SHEditorWindow>;
using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>;
/**
* @brief Style options
*
*/
enum class Style : uint8_t
{
SHADE,
DARK,
LIGHT,
CLASSIC
};
/**
* @brief Initialise the editor
*
* @param sdlWindow pointer to SDL_Window object created in application
*/
static void Initialise(SDL_Window* sdlWindow);
/**
* @brief Update the editor and add to ImGui DrawList
*
* @param dt Delta-time of the frame
*/
static void Update(float dt);
/**
* @brief Safely shutdown the editor
*
*/
static void Exit();
/**
* @brief Set the Style for the editor
*
* @param style Desired style
*/
static void SetStyle(Style style);
/**
* @brief Get ID for the Editor Window Type
*
* @tparam T Type of Editor Window
* @return EditorWindowID ID of Editor Window Type
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static EditorWindowID GetEditorWindowID()
{
static EditorWindowID id;
static bool idCreated = false;
if (!idCreated)
{
id = windowCount++;
idCreated = true;
}
return id;
}
/**
* @brief Get pointer to the Editor Window
*
* @tparam T Type of editor window to retrieve
* @return T* Pointer to the editor window
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static T* GetEditorWindow()
{
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
}
// List of selected entities
static std::vector<EntityID> selectedEntities;
private:
/**
* @brief Initialise Backend for ImGui (SDL and Vulkan backend)
*
* @param sdlWindow Pointer to SDL_Window
*/
static void InitBackend(SDL_Window* sdlWindow);
/**
* @brief Start new frame for editor
*
*/
static void NewFrame();
/**
* @brief Perform ImGui and ImGui Backend Render
*
*/
static void Render();
/**
* @brief Create an Editor Window
*
* @tparam T Type of Editor Window to create
*/
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
static void CreateEditorWindow()
{
static bool isCreated = false;
if (!isCreated)
{
editorWindows[GetEditorWindowID<T>()] = std::make_unique<T>();
isCreated = true;
}
else
{
SHLOG_WARNING("Attempt to create duplicate of Editor window type")
}
}
static void InitFonts() noexcept;
// Handle to command pool used for ImGui Vulkan Backend
static Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend
static Handle<SHVkCommandBuffer> imguiCommandBuffer;
// Number of windows; used for Editor Window ID Generation
static EditorWindowID windowCount;
// Map of Editor Windows
static EditorWindowMap editorWindows;
};//class SHEditor
}//namespace SHADE

View File

@ -0,0 +1,187 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <functional>
#include <string>
#include <iterator>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Math/SHMath.h"
#include "Command/SHCommandManager.h"
#include "SHImGuiHelpers.hpp"
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui.h>
#include <imgui_internal.h>
#include <misc/cpp/imgui_stdlib.h>
#include <rttr/type.h>
namespace SHADE
{
//#==============================================================#
//|| Custom Widgets ||
//#==============================================================#
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImGuiID id = window->GetID("##Splitter");
ImRect bb;
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
}
template <typename T, std::size_t N>
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
ImGuiSliderFlags flags = 0)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiContext& g = *GImGui;
bool valueChanged = false;
ImGui::BeginGroup();
ImGui::PushID(fieldLabel.c_str());
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str());
ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i)
{
ImGui::PushID(static_cast<int>(i));
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
ImGui::SetNextItemWidth(80.0f);
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
const ImVec2 min = ImGui::GetItemRectMin();
const ImVec2 max = ImGui::GetItemRectMax();
const float spacing = g.Style.FrameRounding;
const float halfSpacing = spacing / 2;
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
ImGuiColors::colors[i], 4);
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
ImGui::PopID();
ImGui::PopItemWidth();
}
ImGui::EndColumns();
ImGui::PopID();
ImGui::EndGroup();
return valueChanged;
}
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec2 values = get();
bool changed = false;
if (DragN<float, 2>(fieldLabel, componentLabels, {&values.x, &values.y}, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
}
if (changed)
{
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
else if(ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
}
return changed;
}
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec3 values = get();
bool changed = false;
if (DragN<float, 3>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z}, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
}
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
else if(ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
}
return changed;
}
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec4 values = get();
bool changed = false;
if (DragN<float, 4>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z, &values.w}, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
}
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
else if(ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
}
return changed;
}
//#==============================================================#
//|| Widget Extensions ||
//#==============================================================#
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
{
bool value = get();
if (ImGui::Checkbox(label.c_str(), &value))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
return true;
}
return false;
}
template<typename T>
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
{
T type = get();
for (size_t i = 0; i < listTypes.size(); i++)
{
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
}
ImGui::SameLine();
}
return true;
}
}//namespace SHADE

View File

@ -0,0 +1,69 @@
#pragma once
//#==============================================================#
//|| STL Includes ||
//#==============================================================#
#include <string>
//#==============================================================#
//|| SHADE Includes ||
//#==============================================================#
#include "Math/SHMath.h"
//#==============================================================#
//|| SHADE-ImGui Math Conversions ||
//#==============================================================#
#ifndef SH_IM_MATH
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const SHADE::SHVec2& vec) {x = vec.x; y = vec.y;} \
operator SHADE::SHVec2() const {return SHADE::SHVec2(x,y);}
#define IM_VEC3_CLASS_EXTRA \
ImVec3(const SHADE::SHVec3& vec) {x = vec.x; y = vec.y; z = vec.z;} \
operator SHADE::SHVec3() const {return SHADE::SHVec3(x,y,z);}
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const SHADE::SHVec4& vec) {x = vec.x; y = vec.y; z = vec.z; w = vec.w;} \
operator SHADE::SHVec4() const {return SHADE::SHVec4(x,y,z,w);}
#endif
#define IMGUI_DEFINE_MATH_OPERATORS
//#==============================================================#
//|| Library Includes ||
//#==============================================================#
#include <imgui_internal.h>
#include <imgui.h>
namespace SHADE
{
namespace ImGuiColors
{
constexpr ImVec4 red = {1.0f, 0.0f, 0.0f, 1.f};
constexpr ImVec4 green = {0.0f, 1.0f, 0.0f, 1.f};
constexpr ImVec4 blue = {0.0f, 0.0f, 1.0f, 1.f};
constexpr ImVec4 white = {1.0f, 1.0f, 1.0f, 1.f};
constexpr ImU32 colors[] = {
0xBB0000FF, // red
0xBB00FF00, // green
0xBBFF0000, // blue
0xBBFFFFFF, // white
};
}
static void PushMultiItemsWidthsAndLabels(const std::vector<std::string>& labels, float wFull)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImGuiStyle& style = GImGui->Style;
if (wFull <= 0.0f)
wFull = ImGui::GetContentRegionAvail().x;
const auto size = labels.size();
const float w_item_one =
ImMax(1.0f, (wFull - (static_cast<float>(size) - 1.0f) * (style.ItemInnerSpacing.x * 2.0f)) / static_cast<float>(
size)) -
style.ItemInnerSpacing.x;
for (int i = 0; i < size; i++)
window->DC.ItemWidthStack.push_back(w_item_one - ImGui::CalcTextSize(labels[i].c_str()).x);
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
}
} //namespace SHADE

View File

@ -135,11 +135,13 @@ namespace SHADE
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
//worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", "Normals",*/ "Present" }, {}); // no predecessors
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Present" }, {}); // no predecessors
//First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
//gBufferWriteSubpass->AddColorOutput("Scene");
gBufferWriteSubpass->AddColorOutput("Present");
//writeSubpass->AddColorOutput("Normals");

View File

@ -202,6 +202,7 @@ namespace SHADE
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
Handle<SHViewport> GetDefaultViewport() const {return defaultViewport;}
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }

View File

@ -284,6 +284,7 @@ namespace SHADE
SHRenderGraph(SHRenderGraph&& rhs) noexcept;
SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/

View File

@ -1,6 +1,8 @@
#include "SHPch.h"
#include "SHWindowMap.h"
#include "SHWindow.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Input/SHInputManagerSystem.h"
namespace SHADE
@ -339,6 +341,14 @@ namespace SHADE
OnPosChange(reinterpret_cast<LPWINDOWPOS>(lparam));
break;
}
case WM_MOUSEWHEEL:
{
if (auto im = SHSystemManager::GetSystem<SHInputManagerSystem>())
{
im->PollWheelVerticalDelta(wparam);
}
break;
}
default:
return ::DefWindowProc(hwnd, msg, wparam, lparam);
}

View File

@ -12,6 +12,7 @@
#pragma once
//#include <Xinput.h>
//#include "../../SHADE_Managed/src/SHpch.h"
#include "SH_API.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHFixedSystemRoutine.h"

View File

@ -144,4 +144,15 @@ namespace SHADE
updateQueue.push({ UpdateCommandType::WORLD_SCALE, newWorldScale });
}
} // namespace SHADE
} // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::class_<SHTransformComponent>("Transform Component")
.property("Translate", &SHTransformComponent::GetLocalPosition, &SHTransformComponent::SetLocalPosition)
.property("Rotate", &SHTransformComponent::GetLocalRotation, select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation))
.property("Scale", &SHTransformComponent::GetLocalScale, &SHTransformComponent::SetLocalScale);
}

View File

@ -12,6 +12,7 @@
#include <queue>
#include <rttr/registration>
// Project Headers
#include "SH_API.h"
#include "ECS_Base/Components/SHComponent.h"
@ -116,6 +117,8 @@ namespace SHADE
SHTransform world;
UpdateQueue updateQueue;
RTTR_ENABLE()
};

View File

@ -66,27 +66,23 @@ namespace SHADE
for (const auto* child : node->GetChildren())
{
const bool HAS_TRANSFORM = SHComponentManager::HasComponent<SHTransformComponent>(child->GetEntityID());
if (!HAS_TRANSFORM)
continue;
auto* childTransform = SHComponentManager::GetComponent<SHTransformComponent>(child->GetEntityID());
// Only update if node in hierarchy and component are both active
const bool IS_NODE_ACTIVE = child->IsActive();
if (IS_NODE_ACTIVE && childTransform->isActive)
auto* childTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(child->GetEntityID());
if (childTransform)
{
if (childTransform->dirty || HAS_PARENT_CHANGED)
UpdateTransform(*childTransform, NODE_TRANSFORM);
// Only update if node in hierarchy and component are both active
const bool IS_NODE_ACTIVE = child->IsActive();
if (IS_NODE_ACTIVE && childTransform->isActive)
{
if (childTransform->dirty || HAS_PARENT_CHANGED)
UpdateTransform(*childTransform, NODE_TRANSFORM);
}
}
UpdateEntity(child);
// Clear dirty flag after all children are updated
childTransform->dirty = false;
if (childTransform)
childTransform->dirty = false;
}
}
@ -144,8 +140,8 @@ namespace SHADE
tf.world.ComputeTRS();
// Transpose TRS to column major
tf.local.trs.Transpose();
tf.world.trs.Transpose();
//tf.local.trs.Transpose();
//tf.world.trs.Transpose();
}
} // namespace SHADE

View File

@ -7,7 +7,8 @@ workspace "SHADE"
configurations
{
"Debug",
"Release"
"Release",
"Publish"
}
flags