diff --git a/Source/FicsItCam/UI/FICChangeList.cpp b/Source/FicsItCam/UI/FICChangeList.cpp new file mode 100644 index 0000000..c915abc --- /dev/null +++ b/Source/FicsItCam/UI/FICChangeList.cpp @@ -0,0 +1,64 @@ +#include "FICChangeList.h" + +#include "FICEditorContext.h" + +TArray FFICChange::ChangeStack = TArray(); + +FFICChange_ActiveFrame::FFICChange_ActiveFrame(UFICEditorContext* InEditorContext, int64 InFromFrame, int64 InToFrame) : EditorContext(InEditorContext), FromFrame(InFromFrame), ToFrame(InToFrame) { + if (ToFrame == TNumericLimits::Min()) { + ToFrame = EditorContext->GetCurrentFrame(); + } + if (FromFrame == TNumericLimits::Min()) { + TFunction)> DoChange; + DoChange = [this, &DoChange](TSharedPtr InChange) { + if (InChange) { + if (InChange->ChangeType() == "Group") { + for (TSharedPtr Change : StaticCastSharedPtr(InChange)->Changes) { + if (DoChange(Change)) return true; + } + } else if (InChange->ChangeType() == "ActiveFrame") { + FromFrame = StaticCastSharedPtr(InChange)->ToFrame; + return true; + } + } + return false; + }; + if (!DoChange(EditorContext->ChangeList.PeakChange())) { + FromFrame = EditorContext->GetAnimation()->AnimationStart; + } + } +} + +void FFICChange_ActiveFrame::RedoChange() { + EditorContext->SetCurrentFrame(ToFrame); +} + +void FFICChange_ActiveFrame::UndoChange() { + EditorContext->SetCurrentFrame(FromFrame); +} + +void FFICChangeList::PushChange(TSharedPtr InChange) { + if (Changes.Num() > ChangeIndex+1) Changes.RemoveAt(ChangeIndex+1, Changes.Num() - ChangeIndex - 1); + Changes.Push(InChange); + + if (Changes.Num() > MaxChanges) { + Changes.RemoveAt(0, Changes.Num() - MaxChanges); + } + + ChangeIndex = Changes.Num() - 1; +} + +TSharedPtr FFICChangeList::PushChange() { + if (ChangeIndex >= Changes.Num()-1) return nullptr; + return Changes[++ChangeIndex]; +} + +TSharedPtr FFICChangeList::PopChange() { + if (ChangeIndex < 0) return nullptr; + return Changes[ChangeIndex--]; +} + +TSharedPtr FFICChangeList::PeakChange() { + if (ChangeIndex < 0) return nullptr; + return Changes[ChangeIndex]; +} diff --git a/Source/FicsItCam/UI/FICChangeList.h b/Source/FicsItCam/UI/FICChangeList.h new file mode 100644 index 0000000..89155f6 --- /dev/null +++ b/Source/FicsItCam/UI/FICChangeList.h @@ -0,0 +1,102 @@ +#pragma once + +#include "FICEditorContext.h" +#include "../FICAnimation.h" +#include "../FICEditorAttributeBase.h" + +class FFICChangeList; + +typedef TPair> FChangeStackEntry; + +#define BEGIN_ATTRIB_CHANGE(Attribute) \ + FFICChange::ChangeStack.Push(FChangeStackEntry(Attribute, Attribute->Get())); + +#define END_ATTRIB_CHANGE(ChangeList) { \ + FChangeStackEntry StackEntry = FFICChange::ChangeStack.Pop(); \ + ChangeList->PushChange(MakeShared(StackEntry.Key, StackEntry.Value)); \ + } + +#define BEGIN_QUICK_ATTRIB_CHANGE(Context, Attribute, FromFrame, ToFrame) \ + auto _Change = MakeShared(); \ + _Change->PushChange(MakeShared(Context, FromFrame, ToFrame)); \ + BEGIN_ATTRIB_CHANGE(Attribute) + +#define END_QUICK_ATTRIB_CHANGE(ChangeList) \ + END_ATTRIB_CHANGE(_Change) \ + ChangeList.PushChange(_Change); + +struct FFICChange { + static TArray ChangeStack; + + virtual ~FFICChange() = default; + + virtual void RedoChange() = 0; + virtual void UndoChange() = 0; + virtual FName ChangeType() = 0; +}; + +struct FFICChange_ActiveFrame : public FFICChange { + class UFICEditorContext* EditorContext; + int64 FromFrame; + int64 ToFrame; + + FFICChange_ActiveFrame(class UFICEditorContext* InEditorContext, int64 FromFrame = TNumericLimits::Min(), int64 ToFrame = TNumericLimits::Min()); + + virtual void RedoChange() override; + virtual void UndoChange() override; + virtual FName ChangeType() override { return FName(TEXT("ActiveFrame")); } +}; + +struct FFICChange_Attribute : public FFICChange { + FFICAttribute* Attribute; + TSharedPtr FromAttribute; + TSharedPtr ToAttribute; + + FFICChange_Attribute(FFICAttribute* InAttribute, TSharedPtr InFromAttribute) : Attribute(InAttribute), FromAttribute(InFromAttribute), ToAttribute(Attribute->Get()) {} + + virtual void RedoChange() override { + Attribute->Set(ToAttribute); + } + + virtual void UndoChange() override { + Attribute->Set(FromAttribute); + } + + virtual FName ChangeType() override { + return FName(TEXT("Attribute")); + } +}; + +struct FFICChange_Group : public FFICChange { + TSet> Changes; + + virtual void RedoChange() override { + for (TSharedPtr Change : Changes) Change->RedoChange(); + } + + virtual void UndoChange() override { + for (TSharedPtr Change : Changes) Change->UndoChange(); + } + + virtual FName ChangeType() override { + return FName(TEXT("Group")); + } + + void PushChange(TSharedPtr InChange) { + Changes.Add(InChange); + } +}; + +class FFICChangeList { +private: + TArray> Changes; + int ChangeIndex = -1; + + int MaxChanges = 50; + +public: + void PushChange(TSharedPtr InChange); + TSharedPtr PushChange(); + TSharedPtr PopChange(); + TSharedPtr PeakChange(); +};