Added Copy/Paste of component values, scene name display, editor config #300

Merged
srishamharan merged 5 commits from SP3-4-Editor into main 2023-01-04 01:01:35 +08:00
20 changed files with 487 additions and 246 deletions

4
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

@ -84,34 +84,32 @@ namespace SHADE
editor->selectedEntities.clear(); editor->selectedEntities.clear();
} }
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal); ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
if (ImGui::IsWindowFocused())
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A))
{ {
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A)) SelectAllEntities();
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C))
{
CopySelectedEntities();
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
{
PasteEntities();
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
{
const auto editor = SHSystemManager::GetSystem<SHEditor>();
if (editor->selectedEntities.size() == 1)
{ {
SelectAllEntities(); PasteEntities(editor->selectedEntities.back());
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C))
{
CopySelectedEntities();
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
{
PasteEntities();
}
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
{
const auto editor = SHSystemManager::GetSystem<SHEditor>();
if (editor->selectedEntities.size() == 1)
{
PasteEntities(editor->selectedEntities.back());
}
}
if(ImGui::IsKeyReleased(ImGuiKey_Delete))
{
DeleteSelectedEntities();
} }
} }
if (ImGui::IsKeyReleased(ImGuiKey_Delete))
{
DeleteSelectedEntities();
}
} }
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{ {

View File

@ -19,6 +19,9 @@
#include "Reflection/SHReflectionMetadata.h" #include "Reflection/SHReflectionMetadata.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Physics/Collision/SHCollisionTagMatrix.h" #include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Serialization/SHSerializationHelper.hpp"
#include "Tools/Utilities/SHClipboardUtilities.h"
#include "SHInspectorCommands.h"
namespace SHADE namespace SHADE
{ {
template<typename T> template<typename T>
@ -46,11 +49,12 @@ namespace SHADE
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data())) 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())) 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())) 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

@ -81,131 +81,18 @@ namespace SHADE
if (ImGui::BeginMainMenuBar()) if (ImGui::BeginMainMenuBar())
{ {
if (ImGui::BeginMenu("File")) DrawFileMenu();
{ DrawEditMenu();
if(ImGui::Selectable("New Scene")) DrawScriptsMenu();
{ DrawWindowMenu();
SHSystemManager::GetSystem<SHEditor>()->NewScene(); DrawThemeMenu();
} DrawLayoutMenu();
if(ImGui::Selectable("Save")) DrawApplicationConfig();
{
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();
}
if (ImGui::BeginMenu("Window")) std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())};
{ auto const size = ImGui::CalcTextSize(sceneName.data());
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) ImGui::SetCursorPosX(ImGui::GetWindowWidth() - size.x - ImGui::GetStyle().FramePadding.x);
{ ImGui::Text("%s", sceneName.data());
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();
}
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
@ -272,4 +159,148 @@ namespace SHADE
ImGui::PopStyleVar(3); 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();
}
}
}//namespace SHADE }//namespace SHADE

View File

@ -17,6 +17,15 @@ namespace SHADE
void DrawMainMenuBar() noexcept; void DrawMainMenuBar() noexcept;
void DrawSecondaryBar() const noexcept; void DrawSecondaryBar() const noexcept;
void DrawStatusBar() 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;
float menuBarHeight = 20.0f; float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths; std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar };//class SHEditorMenuBar

View File

@ -93,6 +93,8 @@ namespace SHADE
SHLOG_CRITICAL("Failed to create ImGui Context") SHLOG_CRITICAL("Failed to create ImGui Context")
} }
} }
editorConfig = &SHConfigurationManager::LoadEditorConfig();
//Add editor windows //Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>(); SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
@ -122,7 +124,7 @@ namespace SHADE
InitBackend(); InitBackend();
SetStyle(Style::SHADE); SetStyle(static_cast<Style>(editorConfig->style));
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
@ -160,26 +162,7 @@ namespace SHADE
RenderUnsavedChangesPrompt(); RenderUnsavedChangesPrompt();
//PollPicking(); //PollPicking();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) ProcessShortcuts();
{
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();
}
Render(); Render();
} }
@ -376,10 +359,14 @@ namespace SHADE
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
SHConfigurationManager::SaveEditorConfig();
} }
void SHEditor::SetStyle(Style style) void SHEditor::SetStyle(Style style)
{ {
editorConfig->style = static_cast<uint32_t>(style);
switch (style) switch (style)
{ {
default: default:
@ -583,6 +570,7 @@ namespace SHADE
SHSceneManager::SetCurrentSceneName(newSceneName); SHSceneManager::SetCurrentSceneName(newSceneName);
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, 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 //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()) if(shWindow->IsUnsavedChanges())
shWindow->ToggleUnsavedChanges(); shWindow->ToggleUnsavedChanges();
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
return true; return true;
} }
return false; return false;
@ -659,6 +647,37 @@ namespace SHADE
LoadScene(SHSceneManager::GetCurrentSceneAssetID()); 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() void SHEditor::NewFrame()
{ {
SDL_Event event; SDL_Event event;
@ -672,6 +691,18 @@ namespace SHADE
ImGuizmo::BeginFrame(); 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 void SHEditor::EditorRoutine::Execute(double dt) noexcept
{ {

View File

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

View File

@ -160,7 +160,7 @@ namespace SHADE
template <typename T, std::size_t N> template <typename T, std::size_t N>
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels, 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) ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
{ {
const ImGuiWindow* const window = ImGui::GetCurrentWindow(); const ImGuiWindow* const window = ImGui::GetCurrentWindow();

View File

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

View File

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

View File

@ -52,15 +52,27 @@ namespace SHADE
SHFileIO::WriteStringToFile(editorConfigPath, out.c_str()); 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 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) for(auto const& property : properties)
{ {
if(node[property.get_name().data()].IsDefined()) if(node[property.get_name().data()].IsDefined())
SHSerializationHelper::InitializeProperty(&editorConfig, property, node[property.get_name().data()]); 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; return editorConfig;
} }
@ -86,4 +98,10 @@ RTTR_REGISTRATION
.property("Starting Scene ID", &SHApplicationConfig::startingSceneID) .property("Starting Scene ID", &SHApplicationConfig::startingSceneID)
.property("Window Size", &SHApplicationConfig::windowSize) .property("Window Size", &SHApplicationConfig::windowSize)
.property("Window Title", &SHApplicationConfig::windowTitle); .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 namespace SHADE
{ {
struct SHApplicationConfig struct SHApplicationConfig
{ {
bool startInFullScreen{ false }; bool startInFullScreen{ false };
@ -19,7 +18,11 @@ namespace SHADE
struct SHEditorConfig struct SHEditorConfig
{ {
bool startMaximized{true};
AssetID workingSceneID{};
SHVec2 windowSize {1920, 1080};
uint32_t style = 0;
RTTR_ENABLE()
}; };
class SH_API SHConfigurationManager class SH_API SHConfigurationManager
@ -33,7 +36,7 @@ namespace SHADE
static SHApplicationConfig applicationConfig; static SHApplicationConfig applicationConfig;
#ifdef SHEDITOR #ifdef SHEDITOR
static void SaveEditorConfig(); static void SaveEditorConfig();
static SHEditorConfig& LoadEditorConfig(); static SHEditorConfig& LoadEditorConfig(WindowData* windowData = nullptr);
static SHEditorConfig editorConfig; static SHEditorConfig editorConfig;
private: private:
static void FetchEditorCameraData(); static void FetchEditorCameraData();

View File

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

View File

@ -104,12 +104,6 @@ namespace SHADE
return node; 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> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path) static 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> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node SerializeComponentToNode(ComponentType* component) static YAML::Node SerializeComponentToNode(ComponentType* component)
{ {
YAML::Node node{}; if constexpr (YAML::HasYAMLConv<ComponentType>())
if (!component) {
return node; if (component)
auto componentType = rttr::type::get<ComponentType>(); {
node = RTTRToNode(*component); auto componentNode = YAML::convert<ComponentType>::encode(*component);
node[IsActive.data()] = component->isActive; componentNode[IsActive.data()] = component->isActive;
return componentNode;
}
}
else
{
if (component)
{
YAML::Node compNode{};
if (!component)
return compNode;
auto componentType = rttr::type::get<ComponentType>();
compNode = RTTRToNode(*component);
compNode[IsActive.data()] = component->isActive;
return compNode;
return node; }
}
} }
template <typename Type> template <typename Type>
@ -192,26 +201,43 @@ namespace SHADE
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> 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)
{ {
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid); if constexpr (YAML::HasYAMLConv<ComponentType>())
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return;
if(componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{ {
if (componentNode[prop.get_name().data()].IsDefined()) 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 false;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return false;
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{ {
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]); if (componentNode[prop.get_name().data()].IsDefined())
{
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
}
} }
} }
return true;
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
@ -227,16 +253,49 @@ namespace SHADE
return componentNode; 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> 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 (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
if (componentsNode.IsNull() && !component) {
return; YAML::Emitter out;
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid); YAML::Node node{};
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>(); node[rttr::type::get<ComponentType>().get_name().data()] = SerializeComponentToNode(component);
YAML::convert<ComponentType>::decode(componentNode, *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> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>

View File

@ -20,6 +20,16 @@ namespace YAML
{ {
using namespace SHADE; 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<> template<>
struct convert<SHVec4> struct convert<SHVec4>
{ {