From 78ca464c6537823445e2683f05455051be0bdbc1 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sat, 12 Nov 2022 18:22:45 +0800 Subject: [PATCH] Editor now uses separate stacks; 1 set of stacks when in play and another set of stacks otherwise. CommandStack now uses SHDeque --- .../src/Editor/Command/SHCommandManager.cpp | 77 ++++++++++++++----- .../src/Editor/Command/SHCommandManager.h | 13 +++- .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 4 +- SHADE_Engine/src/Tools/SHDeque.h | 69 +++++++++++++++++ 4 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 SHADE_Engine/src/Tools/SHDeque.h diff --git a/SHADE_Engine/src/Editor/Command/SHCommandManager.cpp b/SHADE_Engine/src/Editor/Command/SHCommandManager.cpp index 3c0ee5dd..b86f9247 100644 --- a/SHADE_Engine/src/Editor/Command/SHCommandManager.cpp +++ b/SHADE_Engine/src/Editor/Command/SHCommandManager.cpp @@ -10,63 +10,102 @@ namespace SHADE { - SHCommandManager::CommandStack SHCommandManager::undoStack{}; - SHCommandManager::CommandStack SHCommandManager::redoStack{}; + + SHCommandManager::CommandStack SHCommandManager::undoStack(defaultStackSize); + SHCommandManager::CommandStack SHCommandManager::redoStack(defaultStackSize); + SHCommandManager::CommandStack SHCommandManager::secondaryUndoStack(defaultStackSize); + SHCommandManager::CommandStack SHCommandManager::secondaryRedoStack(defaultStackSize); + + SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack); + SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack); void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue) { - redoStack = CommandStack(); + *pCurrRedoStack = CommandStack(defaultStackSize); commandPtr->Execute(); - if (overrideValue && !undoStack.empty()) + if (overrideValue && !pCurrUndoStack->Empty()) { - undoStack.top()->Merge(commandPtr); + pCurrUndoStack->Top()->Merge(commandPtr); } else { - undoStack.push(commandPtr); + pCurrUndoStack->Push(commandPtr); } } void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr) { - undoStack.push(commandPtr); + pCurrUndoStack->Push(commandPtr); } void SHCommandManager::UndoCommand() { - if (undoStack.empty()) + if (pCurrUndoStack->Empty()) return; - undoStack.top()->Undo(); - redoStack.push(undoStack.top()); - undoStack.pop(); + pCurrUndoStack->Top()->Undo(); + pCurrRedoStack->Push(pCurrUndoStack->Top()); + pCurrUndoStack->Pop(); } void SHCommandManager::RedoCommand() { - if (redoStack.empty()) + if (pCurrRedoStack->Empty()) return; - redoStack.top()->Execute(); - undoStack.push(redoStack.top()); - redoStack.pop(); + pCurrRedoStack->Top()->Execute(); + pCurrUndoStack->Push(pCurrRedoStack->Top()); + pCurrRedoStack->Pop(); } std::size_t SHCommandManager::GetUndoStackSize() { - return undoStack.size(); + return pCurrUndoStack->Size(); } std::size_t SHCommandManager::GetRedoStackSize() { - return redoStack.size(); + return pCurrRedoStack->Size(); } void SHCommandManager::PopLatestCommandFromRedoStack() { - redoStack.pop(); + pCurrRedoStack->Pop(); } void SHCommandManager::PopLatestCommandFromUndoStack() { - undoStack.pop(); + pCurrUndoStack->Pop(); } + + void SHCommandManager::SwapStacks() + { + if (pCurrUndoStack == &undoStack) + { + pCurrUndoStack = &secondaryUndoStack; + } + else + { + secondaryUndoStack.Clear(); + pCurrUndoStack = &undoStack; + } + + if (pCurrRedoStack == &redoStack) + { + pCurrRedoStack = &secondaryRedoStack; + } + else + { + secondaryRedoStack.Clear(); + pCurrRedoStack = &redoStack; + } + } + + void SHCommandManager::ClearAll() + { + undoStack.Clear(); + redoStack.Clear(); + + secondaryUndoStack.Clear(); + secondaryRedoStack.Clear(); + } + }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/Command/SHCommandManager.h b/SHADE_Engine/src/Editor/Command/SHCommandManager.h index a514c464..178347b5 100644 --- a/SHADE_Engine/src/Editor/Command/SHCommandManager.h +++ b/SHADE_Engine/src/Editor/Command/SHCommandManager.h @@ -10,6 +10,7 @@ //#==============================================================# #include "SHCommand.hpp" #include "SH_API.h" +#include "Tools/SHDeque.h" namespace SHADE { @@ -22,7 +23,8 @@ namespace SHADE using BaseCommandPtr = std::shared_ptr; template using SHCommandPtr = std::shared_ptr>; - using CommandStack = std::stack; + using CommandStack = SHDeque; + using CommandStackPtr = CommandStack*; static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false); static void RegisterCommand(BaseCommandPtr commandPtr); @@ -34,8 +36,17 @@ namespace SHADE static void PopLatestCommandFromRedoStack(); static void PopLatestCommandFromUndoStack(); + static void SwapStacks(); + static void ClearAll(); + + static constexpr CommandStack::SizeType defaultStackSize = 100; private: + static CommandStackPtr pCurrUndoStack; + static CommandStackPtr pCurrRedoStack; + static CommandStack undoStack; + static CommandStack secondaryUndoStack; static CommandStack redoStack; + static CommandStack secondaryRedoStack; }; }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index cfb36cd0..fdde55e1 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -228,7 +228,7 @@ namespace SHADE .previousState = editor->editorState }; editor->editorState = SHEditor::State::PLAY; - + SHCommandManager::SwapStacks(); SHEventManager::BroadcastEvent(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT); } } @@ -253,7 +253,7 @@ namespace SHADE .previousState = editor->editorState }; editor->editorState = SHEditor::State::STOP; - + SHCommandManager::SwapStacks(); SHEventManager::BroadcastEvent(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT); editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID()); } diff --git a/SHADE_Engine/src/Tools/SHDeque.h b/SHADE_Engine/src/Tools/SHDeque.h new file mode 100644 index 00000000..99df910a --- /dev/null +++ b/SHADE_Engine/src/Tools/SHDeque.h @@ -0,0 +1,69 @@ +#pragma once +#pragma once + +#include "SH_API.h" +#include + +namespace SHADE +{ + template + class SH_API SHDeque + { + public: + using ValueType = T; + using Pointer = T*; + using ValueRef = T&; + using ValueConstRef = T const&; + using SizeType = uint32_t; + using ContainerType = std::deque; + using ContainerTypeConstRef = std::deque; + + SHDeque(SizeType n) : max_size(n) {} + + ContainerTypeConstRef const& GetDeque() const + { + return deque; + } + + void Push(ValueConstRef obj) + { + if (deque.size() < max_size) + deque.push_front(std::move(obj)); + else + { + deque.pop_back(); + deque.push_front(std::move(obj)); + } + } + + bool Empty() + { + return deque.empty(); + } + + void Pop() + { + deque.pop_front(); + } + + ValueConstRef Top() + { + return deque.front(); + } + + SizeType Size() const noexcept + { + return deque.size(); + } + + void Clear() + { + deque.clear(); + } + + private: + int max_size; + ContainerType deque{}; + + }; +} \ No newline at end of file