git mv Code\Sandbox\Editor Code/Editor
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_EDITORCORE_UNDO_IUNDOMANAGERLISTENER_H
|
||||
#define CRYINCLUDE_EDITORCORE_UNDO_IUNDOMANAGERLISTENER_H
|
||||
#pragma once
|
||||
|
||||
struct IUndoManagerListener
|
||||
{
|
||||
virtual void BeginUndoTransaction() {}
|
||||
virtual void EndUndoTransaction() {}
|
||||
virtual void BeginRestoreTransaction() {}
|
||||
virtual void EndRestoreTransaction() {}
|
||||
virtual void SignalNumUndoRedo([[maybe_unused]] const unsigned int& numUndo, [[maybe_unused]] const unsigned int& numRedo){}
|
||||
virtual void UndoStackFlushed() {}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCORE_UNDO_IUNDOMANAGERLISTENER_H
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Interface for implementation of IUndo objects.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UNDO_IUNDOOBJECT_H
|
||||
#define CRYINCLUDE_EDITOR_UNDO_IUNDOOBJECT_H
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
//! IUndoObject is a interface of general Undo object.
|
||||
struct IUndoObject
|
||||
{
|
||||
// Virtual destructor.
|
||||
virtual ~IUndoObject() {};
|
||||
|
||||
//! Called to delete undo object.
|
||||
virtual void Release() { delete this; };
|
||||
//! Return size of this Undo object.
|
||||
virtual int GetSize() = 0;
|
||||
//! Return description of this Undo object.
|
||||
virtual QString GetDescription() = 0;
|
||||
|
||||
//! Undo this object.
|
||||
//! @param bUndo If true this operation called in response to Undo operation.
|
||||
virtual void Undo(bool bUndo = true) = 0;
|
||||
|
||||
//! Redo undone changes on object.
|
||||
virtual void Redo() = 0;
|
||||
|
||||
// Returns the name of undo object
|
||||
virtual QString GetObjectName(){ return QString(); };
|
||||
|
||||
// Returns the name of related editor object.
|
||||
// Ex: For a undo action which would modify value for var "Emitter Strength" of emitter "Level.example",
|
||||
// this function will return emitter name "Level.example" - Vera, Confetti
|
||||
virtual QString GetEditorObjectName() { return QString(); };
|
||||
|
||||
virtual bool IsChanged([[maybe_unused]] unsigned int& compareValue) const { return false; }
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UNDO_IUNDOOBJECT_H
|
||||
@@ -0,0 +1,839 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Undo.h"
|
||||
|
||||
#include "Settings.h"
|
||||
#include "IUndoManagerListener.h"
|
||||
#include "Objects/ObjectManager.h"
|
||||
#include <Include/ILogFile.h>
|
||||
#include <list>
|
||||
|
||||
#include <QString>
|
||||
#include "QtUtilWin.h"
|
||||
|
||||
#define UNDOREDO_BUTTON_POPUP_TEXT_WIDTH 81
|
||||
#define UNDOREDO_MULTIPLE_OBJECTS_TEXT " (Multiple Objects)"
|
||||
|
||||
|
||||
//! CSuperUndo objects groups together a block of UndoStepto to allow them to be Undo by single operation.
|
||||
class CSuperUndoStep
|
||||
: public CUndoStep
|
||||
{
|
||||
public:
|
||||
//! Add new undo object to undo step.
|
||||
void AddUndoStep(CUndoStep* step)
|
||||
{
|
||||
m_undoSteps.push_back(step);
|
||||
}
|
||||
virtual int GetSize() const
|
||||
{
|
||||
int size = 0;
|
||||
for (int i = 0; i < m_undoSteps.size(); i++)
|
||||
{
|
||||
size += m_undoSteps[i]->GetSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
virtual bool IsEmpty() const
|
||||
{
|
||||
return m_undoSteps.empty();
|
||||
}
|
||||
virtual void Undo(bool bUndo)
|
||||
{
|
||||
for (int i = m_undoSteps.size() - 1; i >= 0; i--)
|
||||
{
|
||||
m_undoSteps[i]->Undo(bUndo);
|
||||
}
|
||||
}
|
||||
virtual void Redo()
|
||||
{
|
||||
for (int i = 0; i < m_undoSteps.size(); i++)
|
||||
{
|
||||
m_undoSteps[i]->Redo();
|
||||
}
|
||||
}
|
||||
|
||||
// to get memory statistics
|
||||
void GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
for (int i = 0; i < m_undoSteps.size(); i++)
|
||||
{
|
||||
m_undoSteps[i]->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
pSizer->Add(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
//! Undo steps included in this step.
|
||||
std::vector<CUndoStep*> m_undoSteps;
|
||||
};
|
||||
|
||||
// Helper class for CUndoManager that monitors the Asset Manager and suspends undo recording while the Asset Manager
|
||||
// is processing asset loading events. The events are processed non-deterministically, so they could accidentally get captured
|
||||
// within an undo recording block.
|
||||
class AssetManagerUndoInterruptor
|
||||
: public AZ::Data::AssetManagerNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AssetManagerUndoInterruptor()
|
||||
{
|
||||
AZ::Data::AssetManagerNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~AssetManagerUndoInterruptor() override
|
||||
{
|
||||
AZ::Data::AssetManagerNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void OnAssetEventsDispatchBegin() override
|
||||
{
|
||||
GetIEditor()->GetUndoManager()->Suspend();
|
||||
}
|
||||
|
||||
void OnAssetEventsDispatchEnd() override
|
||||
{
|
||||
GetIEditor()->GetUndoManager()->Resume();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CUndoManager::CUndoManager()
|
||||
{
|
||||
m_bRecording = false;
|
||||
m_bSuperRecording = false;
|
||||
|
||||
m_currentUndo = 0;
|
||||
m_superUndo = 0;
|
||||
m_assetManagerUndoInterruptor = new AssetManagerUndoInterruptor();
|
||||
|
||||
m_suspendCount = 0;
|
||||
|
||||
m_bUndoing = false;
|
||||
m_bRedoing = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CUndoManager::~CUndoManager()
|
||||
{
|
||||
|
||||
m_bRecording = false;
|
||||
ClearRedoStack();
|
||||
ClearUndoStack();
|
||||
|
||||
delete m_superUndo;
|
||||
delete m_currentUndo;
|
||||
delete m_assetManagerUndoInterruptor;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Begin()
|
||||
{
|
||||
//CryLog( "<Undo> Begin SuspendCount=%d",m_suspendCount );
|
||||
//if (m_bSuperRecording)
|
||||
//CLogFile::FormatLine( "<Undo> Begin (Inside SuperSuper)" );
|
||||
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 CUndoStep;
|
||||
|
||||
m_bRecording = true;
|
||||
//CLogFile::WriteLine( "<Undo> Begin OK" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::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" );
|
||||
}
|
||||
|
||||
// This function is used below to decide if an operation should force a save or not. This currently
|
||||
// prevents selecting an entity, either from the outliner or both the old and new viewports.
|
||||
static bool ShouldPersist(const QString& name)
|
||||
{
|
||||
return name != "Select Object(s)" && name != "Select Entity" && name != "Box Select Entities";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Accept(const QString& 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())
|
||||
{
|
||||
const bool persist = ShouldPersist(name);
|
||||
if (persist)
|
||||
{
|
||||
GetIEditor()->SetModifiedFlag();
|
||||
}
|
||||
|
||||
// If accepting new undo object, must clear all redo stack.
|
||||
ClearRedoStack();
|
||||
|
||||
m_currentUndo->SetName(name);
|
||||
if (m_bSuperRecording)
|
||||
{
|
||||
m_superUndo->AddUndoStep(m_currentUndo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal recording.
|
||||
// Keep max undo steps.
|
||||
while (m_undoStack.size() && (m_undoStack.size() >= GetIEditor()->GetEditorSettings()->undoLevels || GetDatabaseSize() > 100 * 1024 * 1024))
|
||||
{
|
||||
delete m_undoStack.front();
|
||||
m_undoStack.pop_front();
|
||||
}
|
||||
m_undoStack.push_back(m_currentUndo);
|
||||
}
|
||||
//CLogFile::FormatLine( "Undo Object Accepted (Undo:%d,Redo:%d, Size=%dKb)",m_undoStack.size(),m_redoStack.size(),GetDatabaseSize()/1024 );
|
||||
|
||||
// If undo accepted, document modified.
|
||||
if (persist)
|
||||
{
|
||||
GetIEditor()->SetModifiedFlag();
|
||||
}
|
||||
|
||||
if (name.compare("Select Object(s)", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
}
|
||||
else if (name.compare("Move Selection", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
}
|
||||
else if (name.compare("SubObject Select", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
}
|
||||
else if (name.compare("Manipulator Drag", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no any object was recorded, Cancel undo operation.
|
||||
Cancel();
|
||||
}
|
||||
|
||||
m_bRecording = false;
|
||||
m_currentUndo = 0;
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
|
||||
//CLogFile::WriteLine( "<Undo> Accept OK" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::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);
|
||||
//GetIEditor()->GetLogFile()->FormatLine( "Undo Object Canceled (Undo:%d,Redo:%d)",m_undoStack.size(),m_redoStack.size() );
|
||||
}
|
||||
|
||||
delete m_currentUndo;
|
||||
m_currentUndo = 0;
|
||||
//CLogFile::WriteLine( "<Undo> Cancel OK" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Redo(int numSteps)
|
||||
{
|
||||
GetIEditor()->Notify(eNotify_OnBeginUndoRedo);
|
||||
|
||||
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bRecording || m_bSuperRecording)
|
||||
{
|
||||
GetIEditor()->GetLogFile()->FormatLine("Cannot Redo while Recording");
|
||||
return;
|
||||
}
|
||||
|
||||
m_bRedoing = true;
|
||||
BeginUndoTransaction();
|
||||
m_bRedoing = false;
|
||||
|
||||
if (!m_redoStack.empty())
|
||||
{
|
||||
Suspend();
|
||||
while (numSteps-- > 0 && !m_redoStack.empty() && !m_bClearRedoStackQueued)
|
||||
{
|
||||
m_bRedoing = true;
|
||||
CUndoStep* redo = m_redoStack.back();
|
||||
redo->Redo();
|
||||
m_redoStack.pop_back();
|
||||
// Push undo object to redo stack.
|
||||
m_undoStack.push_back(redo);
|
||||
m_bRedoing = false;
|
||||
}
|
||||
Resume();
|
||||
}
|
||||
if (m_suspendCount == 0)
|
||||
{
|
||||
GetIEditor()->UpdateViews(eUpdateObjects);
|
||||
}
|
||||
GetIEditor()->GetLogFile()->FormatLine("Redo (Undo:%d,Redo:%d)", m_undoStack.size(), m_redoStack.size());
|
||||
GetIEditor()->GetObjectManager()->InvalidateVisibleList();
|
||||
|
||||
m_bRedoing = true;
|
||||
EndUndoTransaction();
|
||||
SignalNumUndoRedoToListeners();
|
||||
m_bRedoing = false;
|
||||
|
||||
GetIEditor()->Notify(eNotify_OnEndUndoRedo);
|
||||
|
||||
if (m_bClearRedoStackQueued)
|
||||
{
|
||||
ClearRedoStack();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Undo(int numSteps)
|
||||
{
|
||||
GetIEditor()->Notify(eNotify_OnBeginUndoRedo);
|
||||
|
||||
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bRecording || m_bSuperRecording)
|
||||
{
|
||||
GetIEditor()->GetLogFile()->FormatLine("Cannot Undo while Recording");
|
||||
return;
|
||||
}
|
||||
|
||||
m_bUndoing = true;
|
||||
BeginUndoTransaction();
|
||||
m_bUndoing = false;
|
||||
|
||||
if (!m_undoStack.empty())
|
||||
{
|
||||
Suspend();
|
||||
while (numSteps-- > 0 && !m_undoStack.empty())
|
||||
{
|
||||
m_bUndoing = true;
|
||||
CUndoStep* undo = m_undoStack.back();
|
||||
undo->Undo(true);
|
||||
m_undoStack.pop_back();
|
||||
// Push undo object to redo stack.
|
||||
m_redoStack.push_back(undo);
|
||||
m_bUndoing = false;
|
||||
}
|
||||
Resume();
|
||||
}
|
||||
// Update viewports.
|
||||
if (m_suspendCount == 0)
|
||||
{
|
||||
GetIEditor()->UpdateViews(eUpdateObjects);
|
||||
}
|
||||
GetIEditor()->GetLogFile()->FormatLine("Undo (Undo:%d,Redo:%d)", m_undoStack.size(), m_redoStack.size());
|
||||
GetIEditor()->GetObjectManager()->InvalidateVisibleList();
|
||||
|
||||
m_bUndoing = true;
|
||||
EndUndoTransaction();
|
||||
SignalNumUndoRedoToListeners();
|
||||
m_bUndoing = false;
|
||||
|
||||
GetIEditor()->Notify(eNotify_OnEndUndoRedo);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::RecordUndo(IUndoObject* 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 CUndoManager::ClearRedoStack()
|
||||
{
|
||||
if (m_bRedoing)
|
||||
{
|
||||
m_bClearRedoStackQueued = true;
|
||||
return;
|
||||
}
|
||||
m_bClearRedoStackQueued = false;
|
||||
|
||||
for (std::list<CUndoStep*>::iterator it = m_redoStack.begin(); it != m_redoStack.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_redoStack.clear();
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::ClearUndoStack()
|
||||
{
|
||||
for (std::list<CUndoStep*>::iterator it = m_undoStack.begin(); it != m_undoStack.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_undoStack.clear();
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::ClearUndoStack(int num)
|
||||
{
|
||||
int i = num;
|
||||
while (i > 0 && !m_undoStack.empty())
|
||||
{
|
||||
delete m_undoStack.front();
|
||||
m_undoStack.pop_front();
|
||||
i--;
|
||||
}
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::ClearRedoStack(int num)
|
||||
{
|
||||
int i = num;
|
||||
while (i > 0 && !m_redoStack.empty())
|
||||
{
|
||||
delete m_redoStack.back();
|
||||
m_redoStack.pop_back();
|
||||
i--;
|
||||
}
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CUndoManager::IsHaveRedo() const
|
||||
{
|
||||
return !m_redoStack.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CUndoManager::IsHaveUndo() const
|
||||
{
|
||||
return !m_undoStack.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Suspend()
|
||||
{
|
||||
m_suspendCount++;
|
||||
//CLogFile::FormatLine( "<Undo> Suspend %d",m_suspendCount );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Resume()
|
||||
{
|
||||
assert(m_suspendCount >= 0);
|
||||
if (m_suspendCount > 0)
|
||||
{
|
||||
m_suspendCount--;
|
||||
}
|
||||
//CLogFile::FormatLine( "<Undo> Resume %d",m_suspendCount );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::SuperBegin()
|
||||
{
|
||||
//CLogFile::FormatLine( "<Undo> SuperBegin (SuspendCount%d)",m_suspendCount );
|
||||
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_bSuperRecording = true;
|
||||
m_superUndo = new CSuperUndoStep;
|
||||
//CLogFile::WriteLine( "<Undo> SuperBegin OK" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::SuperAccept(const QString& name)
|
||||
{
|
||||
//CLogFile::WriteLine( "<Undo> SupperAccept" );
|
||||
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_bSuperRecording)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_superUndo != 0);
|
||||
|
||||
if (m_bRecording)
|
||||
{
|
||||
Accept(name);
|
||||
}
|
||||
|
||||
if (!m_superUndo->IsEmpty())
|
||||
{
|
||||
m_superUndo->SetName(name);
|
||||
// Keep max undo steps.
|
||||
while (m_undoStack.size() && (m_undoStack.size() >= GetIEditor()->GetEditorSettings()->undoLevels || GetDatabaseSize() > 100 * 1024 * 1024))
|
||||
{
|
||||
delete m_undoStack.front();
|
||||
m_undoStack.pop_front();
|
||||
}
|
||||
m_undoStack.push_back(m_superUndo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no any object was recorded, Cancel undo operation.
|
||||
SuperCancel();
|
||||
}
|
||||
|
||||
//CLogFile::FormatLine( "Undo Object Accepted (Undo:%d,Redo:%d)",m_undoStack.size(),m_redoStack.size() );
|
||||
m_bSuperRecording = false;
|
||||
m_superUndo = 0;
|
||||
//CLogFile::WriteLine( "<Undo> SupperAccept OK" );
|
||||
|
||||
SignalNumUndoRedoToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::SuperCancel()
|
||||
{
|
||||
//CLogFile::WriteLine( "<Undo> SuperCancel" );
|
||||
if (m_bUndoing || m_bRedoing) // If Undoing or redoing now, ignore this calls.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_bSuperRecording)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_superUndo != 0);
|
||||
|
||||
if (m_bRecording)
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
|
||||
Suspend();
|
||||
//! Undo all changes already made.
|
||||
m_superUndo->Undo(false); // Undo not by Undo command (no need to store Redo)
|
||||
Resume();
|
||||
|
||||
m_bSuperRecording = false;
|
||||
delete m_superUndo;
|
||||
m_superUndo = 0;
|
||||
//CLogFile::WriteLine( "<Undo> SuperCancel OK" );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CUndoManager::GetUndoStackLen() const
|
||||
{
|
||||
return m_undoStack.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CUndoManager::GetRedoStackLen() const
|
||||
{
|
||||
return m_redoStack.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
std::vector<QString> CUndoManager::GetUndoStackNames() const
|
||||
{
|
||||
std::vector<QString> undos(m_undoStack.size());
|
||||
int i = 0;
|
||||
QString text;
|
||||
|
||||
for (auto it = m_undoStack.begin(); it != m_undoStack.end(); it++)
|
||||
{
|
||||
QString objNames = (*it)->GetObjectNames();
|
||||
text = (*it)->GetName() + objNames;
|
||||
if (text.length() > UNDOREDO_BUTTON_POPUP_TEXT_WIDTH)
|
||||
{
|
||||
undos[i++] = (*it)->GetName() + UNDOREDO_MULTIPLE_OBJECTS_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
undos[i++] = (*it)->GetName() + (objNames.isEmpty() ? "" : " (" + objNames + ")");
|
||||
}
|
||||
}
|
||||
|
||||
return undos;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
std::vector<QString> CUndoManager::GetRedoStackNames() const
|
||||
{
|
||||
std::vector<QString> redos(m_redoStack.size());
|
||||
int i = 0;
|
||||
QString text;
|
||||
|
||||
for (auto it = m_redoStack.begin(); it != m_redoStack.end(); it++)
|
||||
{
|
||||
text = (*it)->GetName() + (*it)->GetObjectNames();
|
||||
if (text.length() > UNDOREDO_BUTTON_POPUP_TEXT_WIDTH)
|
||||
{
|
||||
redos[i++] = (*it)->GetName() + UNDOREDO_MULTIPLE_OBJECTS_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
redos[i++] = (*it)->GetName() + " (" + (*it)->GetObjectNames() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
return redos;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CUndoManager::GetDatabaseSize()
|
||||
{
|
||||
int size = 0;
|
||||
{
|
||||
for (std::list<CUndoStep*>::iterator it = m_undoStack.begin(); it != m_undoStack.end(); it++)
|
||||
{
|
||||
size += (*it)->GetSize();
|
||||
}
|
||||
}
|
||||
{
|
||||
for (std::list<CUndoStep*>::iterator it = m_redoStack.begin(); it != m_redoStack.end(); it++)
|
||||
{
|
||||
size += (*it)->GetSize();
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::Flush()
|
||||
{
|
||||
m_bRecording = false;
|
||||
ClearRedoStack();
|
||||
ClearUndoStack();
|
||||
|
||||
delete m_superUndo;
|
||||
delete m_currentUndo;
|
||||
m_superUndo = 0;
|
||||
m_currentUndo = 0;
|
||||
|
||||
SignalUndoFlushedToListeners();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CUndoStep* CUndoManager::GetNextUndo()
|
||||
{
|
||||
if (!m_undoStack.empty())
|
||||
{
|
||||
return m_undoStack.back();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CUndoStep* CUndoManager::GetNextRedo()
|
||||
{
|
||||
if (!m_redoStack.empty())
|
||||
{
|
||||
return m_redoStack.back();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CUndoManager::SetMaxUndoStep(int steps)
|
||||
{
|
||||
GetIEditor()->GetEditorSettings()->undoLevels = steps;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CUndoManager::GetMaxUndoStep() const
|
||||
{
|
||||
return GetIEditor()->GetEditorSettings()->undoLevels;
|
||||
}
|
||||
|
||||
void CUndoManager::GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
if (m_currentUndo)
|
||||
{
|
||||
m_currentUndo->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
if (m_superUndo)
|
||||
{
|
||||
m_superUndo->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
for (std::list<CUndoStep*>::const_iterator it = m_undoStack.begin(); it != m_undoStack.end(); it++)
|
||||
{
|
||||
(*it)->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
for (std::list<CUndoStep*>::const_iterator it = m_redoStack.begin(); it != m_redoStack.end(); it++)
|
||||
{
|
||||
(*it)->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
pSizer->Add(*this);
|
||||
}
|
||||
|
||||
void CUndoManager::AddListener(IUndoManagerListener* pListener)
|
||||
{
|
||||
stl::push_back_unique(m_listeners, pListener);
|
||||
}
|
||||
|
||||
void CUndoManager::RemoveListener(IUndoManagerListener* pListener)
|
||||
{
|
||||
stl::find_and_erase(m_listeners, pListener);
|
||||
}
|
||||
|
||||
void CUndoManager::BeginUndoTransaction()
|
||||
{
|
||||
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
|
||||
{
|
||||
(*iter)->BeginUndoTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoManager::EndUndoTransaction()
|
||||
{
|
||||
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
|
||||
{
|
||||
(*iter)->EndUndoTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoManager::BeginRestoreTransaction()
|
||||
{
|
||||
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
|
||||
{
|
||||
(*iter)->BeginRestoreTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoManager::EndRestoreTransaction()
|
||||
{
|
||||
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
|
||||
{
|
||||
(*iter)->EndRestoreTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoManager::SignalNumUndoRedoToListeners()
|
||||
{
|
||||
for (IUndoManagerListener* listener : m_listeners)
|
||||
{
|
||||
listener->SignalNumUndoRedo(m_undoStack.size(), m_redoStack.size());
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoManager::SignalUndoFlushedToListeners()
|
||||
{
|
||||
for (IUndoManagerListener* listener : m_listeners)
|
||||
{
|
||||
listener->UndoStackFlushed();
|
||||
}
|
||||
}
|
||||
|
||||
bool CUndoManager::IsUndoRecording() const
|
||||
{
|
||||
return (m_bRecording || m_bSuperRecording) && m_suspendCount == 0;
|
||||
}
|
||||
|
||||
bool CUndoManager::IsUndoSuspended() const
|
||||
{
|
||||
return m_suspendCount != 0;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCORE_UNDO_UNDO_H
|
||||
#define CRYINCLUDE_EDITORCORE_UNDO_UNDO_H
|
||||
#pragma once
|
||||
|
||||
#include "IUndoManagerListener.h"
|
||||
#include "CrySizer.h" // ICrySizer
|
||||
#include "IUndoObject.h"
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
|
||||
struct IUndoObject;
|
||||
class CSuperUndoStep;
|
||||
class AssetManagerUndoInterruptor;
|
||||
|
||||
//! CUndo is a collection of IUndoObjects instances that forms single undo step.
|
||||
class CUndoStep
|
||||
{
|
||||
public:
|
||||
CUndoStep() {};
|
||||
virtual ~CUndoStep() { ClearObjects(); }
|
||||
|
||||
//! Set undo object name.
|
||||
void SetName(const QString& name) { m_name = name; };
|
||||
//! Get undo object name.
|
||||
const QString& GetName() { return m_name; };
|
||||
|
||||
//! Add new undo object to undo step.
|
||||
void AddUndoObject(IUndoObject* o)
|
||||
{
|
||||
m_undoObjects.push_back(o);
|
||||
}
|
||||
void ClearObjects()
|
||||
{
|
||||
int i;
|
||||
// Release all undo objects.
|
||||
std::vector<IUndoObject*> undoObjects = m_undoObjects;
|
||||
m_undoObjects.clear();
|
||||
|
||||
for (i = 0; i < undoObjects.size(); i++)
|
||||
{
|
||||
undoObjects[i]->Release();
|
||||
}
|
||||
};
|
||||
virtual int GetSize() const
|
||||
{
|
||||
int size = 0;
|
||||
for (int i = 0; i < m_undoObjects.size(); i++)
|
||||
{
|
||||
size += m_undoObjects[i]->GetSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
// Confetti: Get the size of m_undoObjects
|
||||
virtual int GetCount() const
|
||||
{
|
||||
return m_undoObjects.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();
|
||||
}
|
||||
}
|
||||
|
||||
// to get memory statistics
|
||||
void GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
size_t nThisSize = sizeof(*this);
|
||||
|
||||
for (int i = 0; i < m_undoObjects.size(); i++)
|
||||
{
|
||||
nThisSize += m_undoObjects[i]->GetSize();
|
||||
}
|
||||
|
||||
pSizer->Add(m_name);
|
||||
pSizer->Add(this, nThisSize);
|
||||
}
|
||||
|
||||
// get undo object at index i
|
||||
IUndoObject* GetUndoObject(int i = 0)
|
||||
{
|
||||
if (i < m_undoObjects.size())
|
||||
{
|
||||
return m_undoObjects[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QString GetObjectNames()
|
||||
{
|
||||
QString objNamesStr("");
|
||||
std::vector<QString> objNames;
|
||||
|
||||
bool bFirst = true;
|
||||
for (int i = 0; i < m_undoObjects.size(); ++i)
|
||||
{
|
||||
if (!m_undoObjects[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_undoObjects[i]->GetObjectName() == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stl::find(objNames, m_undoObjects[i]->GetObjectName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bFirst == false)
|
||||
{
|
||||
objNamesStr += ",";
|
||||
}
|
||||
else
|
||||
{
|
||||
bFirst = false;
|
||||
}
|
||||
|
||||
objNamesStr += m_undoObjects[i]->GetObjectName();
|
||||
|
||||
objNames.push_back(m_undoObjects[i]->GetObjectName());
|
||||
}
|
||||
|
||||
return objNamesStr;
|
||||
};
|
||||
|
||||
private: // ------------------------------------------------------
|
||||
|
||||
friend class CUndoManager;
|
||||
QString m_name;
|
||||
// Undo objects registered for this step.
|
||||
std::vector<IUndoObject*> m_undoObjects;
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
/*!
|
||||
* CUndoManager is keeping and operating on CUndo class instances.
|
||||
*/
|
||||
class EDITOR_CORE_API CUndoManager
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
CUndoManager();
|
||||
~CUndoManager();
|
||||
|
||||
//! Begin operation requiring undo.
|
||||
//! Undo manager enters holding state.
|
||||
void Begin();
|
||||
//! Restore all undo objects registered since last Begin call.
|
||||
//! @param bUndo if true all Undo object registered up to this point will be undone.
|
||||
void Restore(bool bUndo);
|
||||
//! Accept changes and registers an undo object with the undo manager.
|
||||
//! This will allow the user to undo the operation.
|
||||
void Accept(const QString& name);
|
||||
//! Cancel changes and restore undo objects.
|
||||
void Cancel();
|
||||
|
||||
//! Normally this is NOT needed but in special cases this can be useful.
|
||||
//! This allows to group a set of Begin()/Accept() sequences to be undone in one operation.
|
||||
void SuperBegin();
|
||||
//! When a SuperBegin() used, this method is used to Accept.
|
||||
//! This leaves the undo database in its modified state and registers the IUndoObjects with the undo system.
|
||||
//! This will allow the user to undo the operation.
|
||||
void SuperAccept(const QString& name);
|
||||
//! Cancel changes and restore undo objects.
|
||||
void SuperCancel();
|
||||
|
||||
//! Temporarily suspends recording of undo.
|
||||
void Suspend();
|
||||
//! Resume recording if was suspended.
|
||||
void Resume();
|
||||
|
||||
// Undo last operation.
|
||||
void Undo(int numSteps = 1);
|
||||
|
||||
// Undo a specific operation
|
||||
void Reset(const QString& name);
|
||||
|
||||
//! Redo last undo.
|
||||
void Redo(int numSteps = 1);
|
||||
|
||||
//! Check if undo information is recording now.
|
||||
bool IsUndoRecording() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool IsUndoSuspended() const;
|
||||
|
||||
//! Put new undo object, must be called between Begin and Accept/Cancel methods.
|
||||
void RecordUndo(IUndoObject* obj);
|
||||
|
||||
bool IsHaveUndo() const;
|
||||
bool IsHaveRedo() const;
|
||||
|
||||
void SetMaxUndoStep(int steps);
|
||||
int GetMaxUndoStep() const;
|
||||
|
||||
//! Returns length of undo stack.
|
||||
int GetUndoStackLen() const;
|
||||
//! Returns length of redo stack.
|
||||
int GetRedoStackLen() const;
|
||||
|
||||
//! Retreves array of undo objects names.
|
||||
std::vector<QString> GetUndoStackNames() const;
|
||||
//! Retreves array of redo objects names.
|
||||
std::vector<QString> GetRedoStackNames() const;
|
||||
|
||||
//! Get size of current Undo and redo database size.
|
||||
int GetDatabaseSize();
|
||||
|
||||
//! Completly flush all Undo and redo buffers.
|
||||
//! Must be done on level reloads or global Fetch operation.
|
||||
void Flush();
|
||||
|
||||
//! Get Next Undo Item and Next Redo Item -- Vera, Confetti
|
||||
CUndoStep* GetNextUndo();
|
||||
CUndoStep* GetNextRedo();
|
||||
|
||||
|
||||
void ClearRedoStack();
|
||||
void ClearUndoStack();
|
||||
|
||||
void ClearUndoStack(int num);
|
||||
void ClearRedoStack(int num);
|
||||
|
||||
// to get memory statistics
|
||||
void GetMemoryUsage(ICrySizer* pSizer);
|
||||
|
||||
void AddListener(IUndoManagerListener* pListener);
|
||||
void RemoveListener(IUndoManagerListener* pListener);
|
||||
|
||||
int GetSuspendCount() { return m_suspendCount; }
|
||||
|
||||
private: // ---------------------------------------------------------------
|
||||
|
||||
void BeginUndoTransaction();
|
||||
void EndUndoTransaction();
|
||||
void BeginRestoreTransaction();
|
||||
void EndRestoreTransaction();
|
||||
void SignalNumUndoRedoToListeners();
|
||||
void SignalUndoFlushedToListeners();
|
||||
|
||||
bool m_bRecording;
|
||||
bool m_bSuperRecording;
|
||||
int m_suspendCount;
|
||||
|
||||
bool m_bUndoing;
|
||||
bool m_bRedoing;
|
||||
|
||||
bool m_bClearRedoStackQueued;
|
||||
|
||||
CUndoStep* m_currentUndo;
|
||||
//! Undo step object created by SuperBegin.
|
||||
CSuperUndoStep* m_superUndo;
|
||||
|
||||
AssetManagerUndoInterruptor* m_assetManagerUndoInterruptor;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
std::list<CUndoStep*> m_undoStack;
|
||||
std::list<CUndoStep*> m_redoStack;
|
||||
|
||||
std::vector<IUndoManagerListener*> m_listeners;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
class CScopedSuspendUndo
|
||||
{
|
||||
public:
|
||||
CScopedSuspendUndo() { GetIEditor()->SuspendUndo(); }
|
||||
~CScopedSuspendUndo() { GetIEditor()->ResumeUndo(); }
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCORE_UNDO_UNDO_H
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_EDITOR_UNDO_UNDOVARIABLECHANGE_H
|
||||
#define CRYINCLUDE_EDITOR_UNDO_UNDOVARIABLECHANGE_H
|
||||
#pragma once
|
||||
|
||||
#include "IUndoObject.h"
|
||||
|
||||
#include "Util/Variable.h"
|
||||
|
||||
class CAttributeItem;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo object for Variable in property control..
|
||||
class CUndoVariableChange
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
CUndoVariableChange(IVariable* var, const char* undoDescription, const char* editorObjfullname = 0)
|
||||
{
|
||||
// Stores the current state of this object.
|
||||
assert(var != 0);
|
||||
m_undoDescription = undoDescription;
|
||||
m_var = var;
|
||||
m_undo = m_var->Clone(false);
|
||||
m_EditorObjFullName = editorObjfullname;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int GetSize()
|
||||
{
|
||||
int size = sizeof(*this);
|
||||
//if (m_var)
|
||||
//size += m_var->GetSize();
|
||||
if (m_undo)
|
||||
{
|
||||
size += m_undo->GetSize();
|
||||
}
|
||||
if (m_redo)
|
||||
{
|
||||
size += m_redo->GetSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
virtual QString GetDescription()
|
||||
{
|
||||
return m_undoDescription;
|
||||
}
|
||||
|
||||
virtual void Undo(bool bUndo)
|
||||
{
|
||||
if (bUndo)
|
||||
{
|
||||
m_redo = m_var->Clone(false);
|
||||
}
|
||||
m_var->CopyValue(m_undo);
|
||||
}
|
||||
|
||||
virtual void Redo()
|
||||
{
|
||||
if (m_redo)
|
||||
{
|
||||
m_var->CopyValue(m_redo);
|
||||
}
|
||||
}
|
||||
|
||||
virtual QString GetEditorObjectName()
|
||||
{
|
||||
return m_EditorObjFullName;
|
||||
};
|
||||
|
||||
void SetEditorObjName(const char* fullname)
|
||||
{
|
||||
m_EditorObjFullName = fullname;
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_undoDescription;
|
||||
QString m_EditorObjFullName; // Add related editor object name so we can track undo by editor object
|
||||
TSmartPtr<IVariable> m_undo;
|
||||
TSmartPtr<IVariable> m_redo;
|
||||
TSmartPtr<IVariable> m_var;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Confetti Start
|
||||
// This undoobject class is responsible for recording varialeundo action reqiure QTUI reaction.
|
||||
// This class will store a CAttributeView. Editor plugin is responsible for deal with QTUI actions.
|
||||
class CUndoQTUIVariableChange
|
||||
: public CUndoVariableChange
|
||||
{
|
||||
public:
|
||||
CUndoQTUIVariableChange(IVariable* var, CAttributeItem* widget, const char* undoDescription, const char* editorObjfullname = 0)
|
||||
: CUndoVariableChange(var, undoDescription, editorObjfullname)
|
||||
{
|
||||
// Stores the current state of this object.
|
||||
m_uiWidget = widget;
|
||||
}
|
||||
|
||||
CAttributeItem* getWidget() const
|
||||
{
|
||||
return m_uiWidget;
|
||||
}
|
||||
|
||||
private:
|
||||
CAttributeItem* m_uiWidget;
|
||||
};
|
||||
// Confetti End
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UNDO_UNDO_H
|
||||
Reference in New Issue
Block a user