Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
20 changed files with 517 additions and 270 deletions
Showing only changes of commit d7fa40776a - Show all commits

4
.gitignore vendored
View File

@ -364,3 +364,7 @@ MigrationBackup/
*.filters
Assets/Editor/Layouts/UserLayout.ini
JSON/Schemas/Catalog/
Assets/Editor/Editor.SHConfig

View File

@ -67,6 +67,9 @@ namespace Sandbox
SHFileUtilities::SetWorkDirToExecDir();
WindowData wndData{};
auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
#if SHEDITOR
auto& editorConfig = SHConfigurationManager::LoadEditorConfig(&wndData);
#endif
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
// Create Systems
@ -156,8 +159,11 @@ namespace Sandbox
SHSystemManager::Init();
#if SHEDITOR
SHSceneManager::InitSceneManager<SBMainScene>(editorConfig.workingSceneID);
#else
SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
#endif
SHFrameRateController::UpdateFRC();
// Link up SHDebugDraw

View File

@ -18,11 +18,17 @@ namespace SHADE
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
bool SHCommandManager::failedExecution(false);
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
{
*pCurrRedoStack = CommandStack(defaultStackSize);
commandPtr->Execute();
if(failedExecution)
{
failedExecution = false;
return;
}
*pCurrRedoStack = CommandStack(defaultStackSize);
if (overrideValue && !pCurrUndoStack->Empty())
{
pCurrUndoStack->Top()->Merge(commandPtr);
@ -68,11 +74,13 @@ namespace SHADE
void SHCommandManager::PopLatestCommandFromRedoStack()
{
if(!pCurrRedoStack->Empty())
pCurrRedoStack->Pop();
}
void SHCommandManager::PopLatestCommandFromUndoStack()
{
if(!pCurrUndoStack->Empty())
pCurrUndoStack->Pop();
}

View File

@ -39,6 +39,7 @@ namespace SHADE
static void SwapStacks();
static void ClearAll();
static bool failedExecution;
static constexpr CommandStack::SizeType defaultStackSize = 100;
private:
static CommandStackPtr pCurrUndoStack;

View File

@ -84,8 +84,7 @@ namespace SHADE
editor->selectedEntities.clear();
}
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
if (ImGui::IsWindowFocused())
{
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A))
{
SelectAllEntities();
@ -106,11 +105,10 @@ namespace SHADE
PasteEntities(editor->selectedEntities.back());
}
}
if(ImGui::IsKeyReleased(ImGuiKey_Delete))
if (ImGui::IsKeyReleased(ImGuiKey_Delete))
{
DeleteSelectedEntities();
}
}
}
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))

View File

@ -18,6 +18,9 @@
#include "Physics/Interface/SHColliderComponent.h"
#include "Reflection/SHReflectionMetadata.h"
#include "Resource/SHResourceManager.h"
#include "Serialization/SHSerializationHelper.hpp"
#include "Tools/Utilities/SHClipboardUtilities.h"
#include "SHInspectorCommands.h"
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
namespace SHADE
{
@ -46,11 +49,12 @@ namespace SHADE
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data()))
{
//SHClipboardUtil::WriteStringToClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT, SHComponentToString(component));
SHClipboardUtilities::WriteToClipboard(SHSerializationHelper::SerializeComponentToString<T>(component->GetEID()));
}
if (ImGui::Selectable(std::format("{} Paste {}", ICON_MD_CONTENT_PASTE, componentName.data()).data()))
{
//SHStringToComponent(component, SHClipboardUtil::ReadStringFromClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT));
//SHSerializationHelper::DeserializeComponentFromString<T>(SHClipboardUtilities::GetDataFromClipboard(), component->GetEID());
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>( std::make_shared<SHPasteComponentCommand<T>>(component->GetEID(), SHClipboardUtilities::GetDataFromClipboard())));
}
if (ImGui::Selectable(std::format("{} Delete {}", ICON_MD_DELETE, componentName.data()).data()))
{

View File

@ -0,0 +1,27 @@
#pragma once
#include "Editor/Command/SHCommand.hpp"
namespace SHADE
{
template<typename T>
class SHPasteComponentCommand final : SHBaseCommand
{
public:
struct Data
{
EntityID eid;
std::string oldComponentData;
std::string newComponentData;
};
SHPasteComponentCommand(EntityID eid, std::string const& newComponentData);
void Execute() override;
void Undo() override;
private:
Data data;
};
}
#include "SHInspectorCommands.hpp"

View File

@ -0,0 +1,26 @@
#pragma once
#include "SHInspectorCommands.h"
namespace SHADE
{
template<typename T>
SHPasteComponentCommand<T>::SHPasteComponentCommand(EntityID eid, std::string const& newComponentData)
:data(eid, {}, newComponentData)
{
data.oldComponentData = SHSerializationHelper::SerializeComponentToString<T>(eid);
}
template<typename T>
void SHPasteComponentCommand<T>::Execute()
{
bool result = SHSerializationHelper::DeserializeComponentFromString<T>(data.newComponentData, data.eid);
if(!result)
SHCommandManager::failedExecution = true;
}
template<typename T>
void SHPasteComponentCommand<T>::Undo()
{
SHSerializationHelper::DeserializeComponentFromString<T>(data.oldComponentData, data.eid);
}
}

View File

@ -82,155 +82,19 @@ namespace SHADE
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::Selectable("New Scene"))
{
SHSystemManager::GetSystem<SHEditor>()->NewScene();
}
if(ImGui::Selectable("Save"))
{
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
}
if(ImGui::Selectable("Load"))
{
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
}
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("Scripts"))
{
if (ImGui::Selectable("Generate Visual Studio Project"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile();
}
if (ImGui::Selectable("Open Visual Studio Project"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->OpenSolution();
}
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
if (ImGui::Selectable("Build Scripts - Debug"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(true, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
if (ImGui::Selectable("Build Scripts - Release"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(false, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
ImGui::EndDisabled();
ImGui::EndMenu();
}
DrawFileMenu();
DrawEditMenu();
DrawScriptsMenu();
DrawWindowMenu();
DrawThemeMenu();
DrawLayoutMenu();
DrawApplicationConfig();
DrawPhysicsSettings();
if (ImGui::BeginMenu("Window"))
{
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
if (window.get() != this)
ImGui::Checkbox(window->windowName.data(), &window->isOpen);
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Theme"))
{
const 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()))
{
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
editor->SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Layout"))
{
for(auto const& entry : layoutPaths)
{
if(ImGui::Selectable(entry.stem().string().c_str()))
{
ImGui::LoadIniSettingsFromDisk(entry.string().c_str());
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Application Config"))
{
auto& appConfig = SHConfigurationManager::applicationConfig;
ImGui::InputText("Window Title", &appConfig.windowTitle);
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
if(ImGui::BeginCombo("Starting Scne", sceneAsset ? sceneAsset->name.data() : ""))
{
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
for(auto const& scene : scenes)
{
if(ImGui::Selectable(scene.name.data()))
{
appConfig.startingSceneID = scene.id;
}
}
ImGui::EndCombo();
}
if (ImGui::Button("Save"))
{
SHConfigurationManager::SaveApplicationConfig();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Physics Settings"))
{
if (auto* physicsDebugDraw = SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>())
{
bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS);
if (ImGui::Checkbox("Draw Colliders", &drawColliders))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders);
bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS);
if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints);
bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS);
if (ImGui::Checkbox("Draw Rays", &drawRays))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
bool drawBroadphase = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::BROADPHASE);
if (ImGui::Checkbox("Draw Broadphase", &drawBroadphase))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::BROADPHASE, drawBroadphase);
}
ImGui::EndMenu();
}
std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())};
auto const size = ImGui::CalcTextSize(sceneName.data());
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - size.x - ImGui::GetStyle().FramePadding.x);
ImGui::Text("%s", sceneName.data());
ImGui::EndMainMenuBar();
}
@ -297,4 +161,176 @@ namespace SHADE
ImGui::PopStyleVar(3);
}
void SHEditorMenuBar::DrawFileMenu() noexcept
{
if (ImGui::BeginMenu("File"))
{
if (ImGui::Selectable("New Scene"))
{
SHSystemManager::GetSystem<SHEditor>()->NewScene();
}
if (ImGui::Selectable("Save"))
{
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
}
if (ImGui::Selectable("Load"))
{
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
}
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawEditMenu() noexcept
{
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();
}
}
void SHEditorMenuBar::DrawScriptsMenu() noexcept
{
if (ImGui::BeginMenu("Scripts"))
{
if (ImGui::Selectable("Generate Visual Studio Project"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile();
}
if (ImGui::Selectable("Open Visual Studio Project"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->OpenSolution();
}
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
if (ImGui::Selectable("Build Scripts - Debug"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(true, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
if (ImGui::Selectable("Build Scripts - Release"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(false, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
}
ImGui::EndDisabled();
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawWindowMenu() noexcept
{
if (ImGui::BeginMenu("Window"))
{
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{
if (window.get() != this)
ImGui::Checkbox(window->windowName.data(), &window->isOpen);
}
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawThemeMenu() noexcept
{
if (ImGui::BeginMenu("Theme"))
{
const 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()))
{
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
editor->SetStyle(style.convert<SHEditor::Style>());
}
}
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawLayoutMenu() noexcept
{
if (ImGui::BeginMenu("Layout"))
{
for (auto const& entry : layoutPaths)
{
if (ImGui::Selectable(entry.stem().string().c_str()))
{
ImGui::LoadIniSettingsFromDisk(entry.string().c_str());
}
}
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawApplicationConfig() noexcept
{
if (ImGui::BeginMenu("Application Config"))
{
auto& appConfig = SHConfigurationManager::applicationConfig;
ImGui::InputText("Window Title", &appConfig.windowTitle);
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
if (ImGui::BeginCombo("Starting Scene", sceneAsset ? sceneAsset->name.data() : ""))
{
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
for (auto const& scene : scenes)
{
if (ImGui::Selectable(scene.name.data()))
{
appConfig.startingSceneID = scene.id;
}
}
ImGui::EndCombo();
}
if (ImGui::Button("Save"))
{
SHConfigurationManager::SaveApplicationConfig();
}
ImGui::EndMenu();
}
}
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
{
if (ImGui::BeginMenu("Physics Settings"))
{
if (auto* physicsDebugDraw = SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>())
{
bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS);
if (ImGui::Checkbox("Draw Colliders", &drawColliders))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders);
bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS);
if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints);
bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS);
if (ImGui::Checkbox("Draw Rays", &drawRays))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
bool drawBroadphase = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::BROADPHASE);
if (ImGui::Checkbox("Draw Broadphase", &drawBroadphase))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::BROADPHASE, drawBroadphase);
}
ImGui::EndMenu();
}
}
}//namespace SHADE

View File

@ -17,6 +17,16 @@ namespace SHADE
void DrawMainMenuBar() noexcept;
void DrawSecondaryBar() const noexcept;
void DrawStatusBar() const noexcept;
void DrawFileMenu() noexcept;
void DrawEditMenu() noexcept;
void DrawScriptsMenu() noexcept;
void DrawWindowMenu() noexcept;
void DrawThemeMenu() noexcept;
void DrawLayoutMenu() noexcept;
void DrawApplicationConfig() noexcept;
void DrawPhysicsSettings() noexcept;
float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar

View File

@ -94,6 +94,8 @@ namespace SHADE
}
}
editorConfig = &SHConfigurationManager::LoadEditorConfig();
//Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
@ -122,7 +124,7 @@ namespace SHADE
InitBackend();
SetStyle(Style::SHADE);
SetStyle(static_cast<Style>(editorConfig->style));
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
@ -160,26 +162,7 @@ namespace SHADE
RenderUnsavedChangesPrompt();
//PollPicking();
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();
}
if(ImGui::IsKeyReleased(ImGuiKey_F5))
{
Play();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
{
Pause();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
{
Stop();
}
ProcessShortcuts();
Render();
}
@ -376,10 +359,14 @@ namespace SHADE
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
SHConfigurationManager::SaveEditorConfig();
}
void SHEditor::SetStyle(Style style)
{
editorConfig->style = static_cast<uint32_t>(style);
switch (style)
{
default:
@ -583,6 +570,7 @@ namespace SHADE
SHSceneManager::SetCurrentSceneName(newSceneName);
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
}
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
@ -591,7 +579,7 @@ namespace SHADE
{
if(shWindow->IsUnsavedChanges())
shWindow->ToggleUnsavedChanges();
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
return true;
}
return false;
@ -659,6 +647,37 @@ namespace SHADE
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
}
void SHEditor::ProcessShortcuts()
{
if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
{
if(ImGui::IsKeyReleased(ImGuiKey_S))
{
SaveScene();
}
}
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();
}
if (ImGui::IsKeyReleased(ImGuiKey_F5))
{
Play();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
{
Pause();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
{
Stop();
}
}
void SHEditor::NewFrame()
{
SDL_Event event;
@ -672,6 +691,18 @@ namespace SHADE
ImGuizmo::BeginFrame();
}
void SHEditor::SetSHWindow(SHWindow* inWindow)
{
shWindow = inWindow;
shWindow->RegisterWindowSizeCallback([&](uint32_t width, uint32_t height)
{
if(width > 0 && height > 0)
{
auto [width, height] = shWindow->GetWindowSize();
editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) };
}
});
}
void SHEditor::EditorRoutine::Execute(double dt) noexcept
{

View File

@ -20,6 +20,7 @@
#include "Events/SHEventDefines.h"
#include "Events/SHEvent.h"
#include "Graphics/Windowing/SHWindow.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
//#==============================================================#
//|| Library Includes ||
@ -108,7 +109,7 @@ namespace SHADE
void InitBackend();
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
void SetSHWindow(SHWindow* inWindow){shWindow = inWindow;}
void SetSHWindow(SHWindow* inWindow);
void PollPicking();
@ -122,11 +123,15 @@ namespace SHADE
void Pause();
void Stop();
void ProcessShortcuts();
// List of selected entities
std::vector<EntityID> selectedEntities;
State editorState = State::STOP;
SHEditorConfig* editorConfig;
private:
/**
* @brief Start new frame for editor

View File

@ -160,7 +160,7 @@ namespace SHADE
template <typename T, std::size_t N>
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "%.3f", T valueMin = T(), T valueMax = T(),
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();

View File

@ -115,6 +115,11 @@ namespace SHADE
SetFocus(wndHWND);
}
if(!wndData.isFullscreen && wndData.isMaximised)
{
Maximize();
}
if (!wndData.icoPath.empty())
{
//HICON hIcon = ::LoadIcon(nullptr, MAKEINTRESOURCE(wndData.icoPath.c_str()));
@ -208,10 +213,12 @@ namespace SHADE
if (!IsZoomed(wndHWND))
{
ShowWindow(wndHWND, SW_MAXIMIZE);
wndData.isMaximised = true;
}
else
{
ShowWindow(wndHWND, SW_RESTORE);
wndData.isMaximised = false;
}
}
@ -428,7 +435,9 @@ namespace SHADE
wndData.isMinimised = true;
}
else
{
wndData.isMinimised = false;
}
for (auto const& entry : windowResizeCallbacks)
{

View File

@ -64,6 +64,8 @@ namespace SHADE
bool isMinimised = false;
bool isMaximised = true;
std::wstring title = L"SHADE ENGINE";
std::wstring name = L"SHADEEngineApp";

View File

@ -52,15 +52,27 @@ namespace SHADE
SHFileIO::WriteStringToFile(editorConfigPath, out.c_str());
}
SHEditorConfig& SHConfigurationManager::LoadEditorConfig()
SHEditorConfig& SHConfigurationManager::LoadEditorConfig(WindowData* windowData)
{
if (!std::filesystem::exists(editorConfigPath))
{
SaveApplicationConfig();
return editorConfig;
}
auto const node = YAML::Load(SHFileIO::GetStringFromFile(editorConfigPath));
auto properties = rttr::type::get<SHApplicationConfig>().get_properties();
auto properties = rttr::type::get<SHEditorConfig>().get_properties();
for(auto const& property : properties)
{
if(node[property.get_name().data()].IsDefined())
SHSerializationHelper::InitializeProperty(&editorConfig, property, node[property.get_name().data()]);
}
if(windowData)
{
windowData->isMaximised = editorConfig.startMaximized;
windowData->width = static_cast<uint32_t>(editorConfig.windowSize.x);
windowData->height = static_cast<uint32_t>(editorConfig.windowSize.y);
}
return editorConfig;
}
@ -86,4 +98,10 @@ RTTR_REGISTRATION
.property("Starting Scene ID", &SHApplicationConfig::startingSceneID)
.property("Window Size", &SHApplicationConfig::windowSize)
.property("Window Title", &SHApplicationConfig::windowTitle);
registration::class_<SHEditorConfig>("Editor Config")
.property("Start Maximized", &SHEditorConfig::startMaximized)
.property("Working Scene ID", &SHEditorConfig::workingSceneID)
.property("Window Size", &SHEditorConfig::windowSize)
.property("Style", &SHEditorConfig::style);
}

View File

@ -7,7 +7,6 @@
namespace SHADE
{
struct SHApplicationConfig
{
bool startInFullScreen{ false };
@ -19,7 +18,11 @@ namespace SHADE
struct SHEditorConfig
{
bool startMaximized{true};
AssetID workingSceneID{};
SHVec2 windowSize {1920, 1080};
uint32_t style = 0;
RTTR_ENABLE()
};
class SH_API SHConfigurationManager
@ -33,7 +36,7 @@ namespace SHADE
static SHApplicationConfig applicationConfig;
#ifdef SHEDITOR
static void SaveEditorConfig();
static SHEditorConfig& LoadEditorConfig();
static SHEditorConfig& LoadEditorConfig(WindowData* windowData = nullptr);
static SHEditorConfig editorConfig;
private:
static void FetchEditorCameraData();

View File

@ -171,24 +171,14 @@ namespace SHADE
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
{
if (const ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
{
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(component);
}
}
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void AddConvComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
{
YAML::Node node{};
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
{
auto componentNode = YAML::convert<ComponentType>::encode(*component);
componentNode[IsActive.data()] = component->isActive;
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = componentNode;
node = SHSerializationHelper::SerializeComponentToNode(component);
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = node;
}
}
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
{
YAML::Node node;
@ -211,15 +201,15 @@ namespace SHADE
AddComponentToComponentNode<SHTransformComponent>(components, eid);
AddComponentToComponentNode<SHCameraComponent>(components, eid);
AddComponentToComponentNode<SHCameraArmComponent>(components, eid);
AddConvComponentToComponentNode<SHRenderable>(components, eid);
AddComponentToComponentNode<SHRenderable>(components, eid);
AddComponentToComponentNode<SHLightComponent>(components, eid);
AddComponentToComponentNode<SHRigidBodyComponent>(components, eid);
AddConvComponentToComponentNode<SHColliderComponent>(components, eid);
AddComponentToComponentNode<SHColliderComponent>(components, eid);
AddComponentToComponentNode<SHCanvasComponent>(components, eid);
AddComponentToComponentNode<SHButtonComponent>(components, eid);
AddConvComponentToComponentNode<SHTextRenderableComponent>(components, eid);
AddComponentToComponentNode<SHTextRenderableComponent>(components, eid);
node[ComponentsNode] = components;
@ -351,12 +341,12 @@ namespace SHADE
SHSerializationHelper::InitializeComponentFromNode<SHCameraComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHCameraArmComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid);
SHSerializationHelper::ConvertNodeToComponent<SHRenderable>(componentsNode, eid);
SHSerializationHelper::ConvertNodeToComponent<SHColliderComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHRenderable>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHColliderComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid);
SHSerializationHelper::ConvertNodeToComponent<SHTextRenderableComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHTextRenderableComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHLightComponent>(componentsNode, eid);
}
}

View File

@ -104,12 +104,6 @@ namespace SHADE
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static std::string SerializeComponentToString(ComponentType* component)
{
return std::string();
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
{
@ -118,14 +112,29 @@ namespace SHADE
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node SerializeComponentToNode(ComponentType* component)
{
YAML::Node node{};
if constexpr (YAML::HasYAMLConv<ComponentType>())
{
if (component)
{
auto componentNode = YAML::convert<ComponentType>::encode(*component);
componentNode[IsActive.data()] = component->isActive;
return componentNode;
}
}
else
{
if (component)
{
YAML::Node compNode{};
if (!component)
return node;
return compNode;
auto componentType = rttr::type::get<ComponentType>();
node = RTTRToNode(*component);
node[IsActive.data()] = component->isActive;
compNode = RTTRToNode(*component);
compNode[IsActive.data()] = component->isActive;
return compNode;
return node;
}
}
}
template <typename Type>
@ -192,16 +201,31 @@ namespace SHADE
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
static bool InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
{
if constexpr (YAML::HasYAMLConv<ComponentType>())
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() || !component)
return false;
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid);
if (componentNode.IsNull() || !componentNode.IsDefined())
return false;
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
YAML::convert<ComponentType>::decode(componentNode, *component);
return true;
}
else
{
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
return false;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return;
if(componentNode[IsActive.data()].IsDefined())
return false;
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
auto properties = rttrType.get_properties();
@ -213,6 +237,8 @@ namespace SHADE
}
}
}
return true;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node GetComponentNode(YAML::Node const& componentsNode, EntityID const& eid)
@ -227,16 +253,49 @@ namespace SHADE
return componentNode;
}
//template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
//static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
//{
// if constexpr (YAML::HasYAMLConv<ComponentType>())
// {
// if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
// {
// auto componentNode = YAML::convert<ComponentType>::encode(*component);
// componentNode[IsActive.data()] = component->isActive;
// componentsNode[rttr::type::get<ComponentType>().get_name().data()] = componentNode;
// }
// }
// else
// {
// if (const ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
// {
// componentsNode[rttr::type::get<ComponentType>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(component);
// }
// }
//}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid)
static std::string SerializeComponentToString(EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid);
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
YAML::convert<ComponentType>::decode(componentNode, *component);
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
{
YAML::Emitter out;
YAML::Node node{};
node[rttr::type::get<ComponentType>().get_name().data()] = SerializeComponentToNode(component);
out << node;
return out.c_str();
}
return std::string();
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static bool DeserializeComponentFromString(std::string data, EntityID const& eid)
{
YAML::Node node = YAML::Load(data);
return InitializeComponentFromNode<ComponentType>(node, eid);
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>

View File

@ -18,6 +18,16 @@ namespace YAML
{
using namespace SHADE;
template<typename T>
struct HasYAMLConv : std::false_type{};
template<>
struct HasYAMLConv<SHColliderComponent> : std::true_type {};
template<>
struct HasYAMLConv<SHRenderable> : std::true_type {};
template<>
struct HasYAMLConv<SHTextRenderableComponent> : std::true_type {};
template<>
struct convert<SHVec4>
{