Files
o3de/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

450 lines
11 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "UiAnimUndoManager.h"
#include "UiAnimUndoObject.h"
#include "Undo/IUndoManagerListener.h"
#include <list>
// UI Editor
#include "EditorCommon.h"
#include <QUndoCommand>
UiAnimUndoManager* UiAnimUndoManager::s_instance = nullptr;
//! UiAnimUndoStep is a collection of UiAnimUndoObjects instances that forms a single undo step.
class UiAnimUndoStep
: public QUndoCommand
{
public:
UiAnimUndoStep()
: m_hasDoneUndo(false) {};
virtual ~UiAnimUndoStep() { ClearObjects(); }
//! Set undo object name.
void SetName(const AZStd::string& name) { m_name = name; };
//! Get undo object name.
const AZStd::string& GetName() { return m_name; };
//! Add new undo object to undo step.
void AddUndoObject(UiAnimUndoObject* o)
{
m_undoObjects.push_back(o);
}
void ClearObjects()
{
int i;
// Release all undo objects.
for (i = 0; i < m_undoObjects.size(); i++)
{
m_undoObjects[i]->Release();
}
m_undoObjects.clear();
};
virtual int GetSize() const
{
int size = 0;
for (int i = 0; i < m_undoObjects.size(); i++)
{
size += m_undoObjects[i]->GetSize();
}
return size;
}
virtual bool IsEmpty() const { return m_undoObjects.empty(); };
virtual void Undo(bool bUndo)
{
for (int i = m_undoObjects.size() - 1; i >= 0; i--)
{
m_undoObjects[i]->Undo(bUndo);
}
}
virtual void Redo()
{
for (int i = 0; i < m_undoObjects.size(); i++)
{
m_undoObjects[i]->Redo();
}
}
// Add to Qt undo stack
void Push(UndoStack* undoStack)
{
setText(m_name.c_str());
undoStack->push(this);
}
private: // ------------------------------------------------------
// these are called from the Qt undo system
void undo() override
{
UiAnimUndoManager::Get()->UndoStep(this);
m_hasDoneUndo = true;
}
void redo() override
{
// Qt automatically calls redo when a command is added to the Qt undo stack
// We are emulating the CUndo behavior so we ingore that first redo
if (m_hasDoneUndo)
{
UiAnimUndoManager::Get()->RedoStep(this);
}
}
bool m_hasDoneUndo;
friend class UiAnimUndoManager;
AZStd::string m_name;
// Undo objects registered for this step.
std::vector<UiAnimUndoObject*> m_undoObjects;
};
//////////////////////////////////////////////////////////////////////////
UiAnimUndoManager::UiAnimUndoManager()
{
m_bRecording = false;
m_currentUndo = 0;
m_suspendCount = 0;
m_bUndoing = false;
m_bRedoing = false;
s_instance = this;
}
//////////////////////////////////////////////////////////////////////////
UiAnimUndoManager::~UiAnimUndoManager()
{
m_bRecording = false;
delete m_currentUndo;
s_instance = nullptr;
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Begin()
{
//CryLog( "<Undo> Begin SuspendCount=%d",m_suspendCount );
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
// assert( m_bRecording == false );
if (m_bRecording)
{
//CLogFile::WriteLine( "<Undo> Begin (already recording)" );
// Not cancel, just combine.
return;
}
// Begin Creates a new undo object.
m_currentUndo = new UiAnimUndoStep;
m_bRecording = true;
//CLogFile::WriteLine( "<Undo> Begin OK" );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Restore(bool bUndo)
{
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
if (m_currentUndo)
{
BeginRestoreTransaction();
Suspend();
if (bUndo && m_currentUndo)
{
m_currentUndo->Undo(false); // Undo not by Undo command (no need to store Redo)
}
Resume();
if (m_currentUndo)
{
m_currentUndo->ClearObjects();
}
EndRestoreTransaction();
}
//CryLog( "Restore Undo" );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Accept(const AZStd::string& name)
{
//CryLog( "<Undo> Accept, Suspend Count=%d",m_suspendCount );
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
if (!m_bRecording)
{
//CLogFile::WriteLine( "<Undo> Accept (Not recording)" );
return;
}
if (!m_currentUndo->IsEmpty())
{
m_currentUndo->SetName(name);
{
// push this undo stap on the Ui Editor undo stack
m_currentUndo->Push(m_uiUndoStack);
}
}
else
{
// If no any object was recorded, Cancel undo operation.
Cancel();
}
m_bRecording = false;
m_currentUndo = 0;
//CLogFile::WriteLine( "<Undo> Accept OK" );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Cancel()
{
//CryLog( "<Undo> Cancel" );
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
if (!m_bRecording)
{
return;
}
assert(m_currentUndo != 0);
m_bRecording = false;
if (!m_currentUndo->IsEmpty())
{
// Restore all objects to the state they was at Begin call and throws out all undo objects.
Restore(true);
}
delete m_currentUndo;
m_currentUndo = 0;
//CLogFile::WriteLine( "<Undo> Cancel OK" );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Redo()
{
// this is called when using the Redo menu/toolbar actions in the
// UI Animation Editor. Just use the UI Editor redo
m_uiUndoStack->redo();
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Undo()
{
// this is called when using the undo menu/toolbar actions in the
// UI Animation Editor. Just use the UI Editor undo
m_uiUndoStack->undo();
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::RedoStep(UiAnimUndoStep* step)
{
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
if (m_bRecording)
{
// GetIEditor()->GetLogFile()->FormatLine("Cannot Redo while Recording");
return;
}
m_bRedoing = true;
BeginUndoTransaction();
m_bRedoing = false;
Suspend();
m_bRedoing = true;
step->Redo();
m_bRedoing = false;
Resume();
// if (m_suspendCount == 0)
// GetIEditor()->UpdateViews(eUpdateObjects);
m_bRedoing = true;
EndUndoTransaction();
m_bRedoing = false;
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::UndoStep(UiAnimUndoStep* step)
{
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
return;
}
if (m_bRecording)
{
// GetIEditor()->GetLogFile()->FormatLine("Cannot Undo while Recording");
return;
}
m_bUndoing = true;
BeginUndoTransaction();
m_bUndoing = false;
Suspend();
m_bUndoing = true;
step->Undo(true);
m_bUndoing = false;
Resume();
// Update viewports.
// if (m_suspendCount == 0)
// GetIEditor()->UpdateViews(eUpdateObjects);
m_bUndoing = true;
EndUndoTransaction();
m_bUndoing = false;
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::RecordUndo(UiAnimUndoObject* obj)
{
//CryLog( "<Undo> RecordUndo Name=%s",obj->GetDescription() );
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
{
//CLogFile::WriteLine( "<Undo> RecordUndo (Undoing or Redoing)" );
obj->Release();
return;
}
if (m_bRecording && (m_suspendCount == 0))
{
assert(m_currentUndo != 0);
m_currentUndo->AddUndoObject(obj);
//CLogFile::FormatLine( "Undo Object Added: %s",obj->GetDescription() );
}
else
{
//CLogFile::WriteLine( "<Undo> RecordUndo (Not Recording)" );
// Ignore this object.
obj->Release();
}
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Suspend()
{
m_suspendCount++;
//CLogFile::FormatLine( "<Undo> Suspend %d",m_suspendCount );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Resume()
{
assert(m_suspendCount >= 0);
if (m_suspendCount > 0)
{
m_suspendCount--;
}
//CLogFile::FormatLine( "<Undo> Resume %d",m_suspendCount );
}
//////////////////////////////////////////////////////////////////////////
void UiAnimUndoManager::Flush()
{
m_bRecording = false;
delete m_currentUndo;
m_currentUndo = 0;
}
void UiAnimUndoManager::AddListener(IUndoManagerListener* pListener)
{
stl::push_back_unique(m_listeners, pListener);
}
void UiAnimUndoManager::RemoveListener(IUndoManagerListener* pListener)
{
stl::find_and_erase(m_listeners, pListener);
}
void UiAnimUndoManager::BeginUndoTransaction()
{
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->BeginUndoTransaction();
}
}
void UiAnimUndoManager::EndUndoTransaction()
{
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->EndUndoTransaction();
}
}
void UiAnimUndoManager::BeginRestoreTransaction()
{
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->BeginRestoreTransaction();
}
}
void UiAnimUndoManager::EndRestoreTransaction()
{
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->EndRestoreTransaction();
}
}
bool UiAnimUndoManager::IsUndoRecording() const
{
return (m_bRecording) && m_suspendCount == 0;
}
bool UiAnimUndoManager::IsUndoSuspended() const
{
return m_suspendCount != 0;
}
void UiAnimUndoManager::SetActiveUndoStack(UndoStack* undoStack)
{
m_uiUndoStack = undoStack;
}
UndoStack* UiAnimUndoManager::GetActiveUndoStack() const
{
return m_uiUndoStack;
}
UiAnimUndoManager* UiAnimUndoManager::Get()
{
return s_instance;
}