Merge branch 'development' into redcode/crythread-2nd-pass
Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com>
This commit is contained in:
@@ -45,7 +45,7 @@ int CAutoDirectoryRestoreFileDialog::exec()
|
||||
foreach(const QString&fileName, selectedFiles())
|
||||
{
|
||||
QFileInfo info(fileName);
|
||||
if (!CryStringUtils::IsValidFileName(info.fileName().toStdString().c_str()))
|
||||
if (!AZ::StringFunc::Path::IsValid(info.fileName().toStdString().c_str()))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Please select a valid file name (standard English alphanumeric characters only)"));
|
||||
problem = true;
|
||||
|
||||
@@ -30,30 +30,6 @@ void HeapCheck::Check([[maybe_unused]] const char* file, [[maybe_unused]] int li
|
||||
_ASSERTE(_CrtCheckMemory());
|
||||
#endif
|
||||
|
||||
/*
|
||||
int heapstatus = _heapchk();
|
||||
switch( heapstatus )
|
||||
{
|
||||
case _HEAPOK:
|
||||
break;
|
||||
case _HEAPEMPTY:
|
||||
break;
|
||||
case _HEAPBADBEGIN:
|
||||
{
|
||||
CString str;
|
||||
str.Format( "Bad Start of Heap, at file %s line:%d",file,line );
|
||||
MessageBox( nullptr,str,"Heap Check",MB_OK );
|
||||
}
|
||||
break;
|
||||
case _HEAPBADNODE:
|
||||
{
|
||||
CString str;
|
||||
str.Format( "Bad Node in Heap, at file %s line:%d",file,line );
|
||||
MessageBox( nullptr,str,"Heap Check",MB_OK );
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <IXml.h>
|
||||
#include "Util/FileUtil.h"
|
||||
#include <Cry_Color.h>
|
||||
#include <CryCommon/ISystem.h>
|
||||
|
||||
//! Typedef for quaternion.
|
||||
//typedef CryQuat Quat;
|
||||
|
||||
@@ -264,7 +264,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
|
||||
}
|
||||
|
||||
bool failedToLaunch = true;
|
||||
QByteArray textureEditorPath = gSettings.textureEditor.toUtf8();
|
||||
const QString& textureEditorPath = gSettings.textureEditor;
|
||||
|
||||
// Give the user a warning if they don't have a texture editor configured
|
||||
if (textureEditorPath.isEmpty())
|
||||
@@ -278,8 +278,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
|
||||
// Use the Win32 API calls to open the right editor; the OS knows how to do this even better than
|
||||
// Qt does.
|
||||
QString fullTexturePathFixedForWindows = QString(fullTexturePath.data()).replace('/', '\\');
|
||||
QByteArray fullTexturePathFixedForWindowsUtf8 = fullTexturePathFixedForWindows.toUtf8();
|
||||
HINSTANCE hInst = ShellExecute(nullptr, "open", textureEditorPath.data(), fullTexturePathFixedForWindowsUtf8.data(), nullptr, SW_SHOWNORMAL);
|
||||
HINSTANCE hInst = ShellExecuteW(nullptr, L"open", textureEditorPath.toStdWString().c_str(), fullTexturePathFixedForWindows.toStdWString().c_str(), nullptr, SW_SHOWNORMAL);
|
||||
failedToLaunch = ((DWORD_PTR)hInst <= 32);
|
||||
#elif defined(AZ_PLATFORM_MAC)
|
||||
failedToLaunch = QProcess::execute(QString("/usr/bin/open"), {"-a", gSettings.textureEditor, QString(fullTexturePath.data()) }) != 0;
|
||||
@@ -298,7 +297,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, const bool bUseGameFolder)
|
||||
{
|
||||
QString dosFilepath = QtUtil::ToQString(PathUtil::ToDosPath(filepath));
|
||||
QString dosFilepath = PathUtil::ToDosPath(filepath).c_str();
|
||||
if (bExtractFromPak)
|
||||
{
|
||||
ExtractFile(dosFilepath);
|
||||
@@ -313,7 +312,7 @@ bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, c
|
||||
dosFilepath = sGameFolder + '\\' + filepath;
|
||||
}
|
||||
|
||||
dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data());
|
||||
dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data()).c_str();
|
||||
}
|
||||
|
||||
const char* engineRoot;
|
||||
@@ -1304,7 +1303,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory
|
||||
// all with the same names and all with the same files names inside. If you would make a depth-first search
|
||||
// you could end up with the files from the deepest folder in ALL your folders.
|
||||
|
||||
std::vector<string> ignoredPatterns;
|
||||
std::vector<AZStd::string> ignoredPatterns;
|
||||
StringHelpers::Split(ignoreFilesAndFolders, "|", false, ignoredPatterns);
|
||||
|
||||
QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
|
||||
@@ -1330,7 +1329,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory
|
||||
const QString fileName = QFileInfo(filePath).fileName();
|
||||
|
||||
bool ignored = false;
|
||||
for (const string& ignoredFile : ignoredPatterns)
|
||||
for (const AZStd::string& ignoredFile : ignoredPatterns)
|
||||
{
|
||||
if (StringHelpers::CompareIgnoreCase(fileName.toStdString().c_str(), ignoredFile.c_str()) == 0)
|
||||
{
|
||||
@@ -2159,13 +2158,14 @@ uint32 CFileUtil::GetAttributes(const char* filename, bool bUseSourceControl /*=
|
||||
return SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK;
|
||||
}
|
||||
|
||||
DWORD dwAttrib = ::GetFileAttributes(file.GetAdjustedFilename());
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES)
|
||||
|
||||
const char* adjustedFile = file.GetAdjustedFilename();
|
||||
if (!AZ::IO::SystemFile::Exists(adjustedFile))
|
||||
{
|
||||
return SCC_FILE_ATTRIBUTE_INVALID;
|
||||
}
|
||||
|
||||
if (dwAttrib & FILE_ATTRIBUTE_READONLY)
|
||||
if (!AZ::IO::SystemFile::IsWritable(adjustedFile))
|
||||
{
|
||||
return SCC_FILE_ATTRIBUTE_NORMAL | SCC_FILE_ATTRIBUTE_READONLY;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include "../Include/SandboxAPI.h"
|
||||
#include <QString>
|
||||
#include <QFileInfo>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
// Helper class to handle Redo/Undo on set of Xml nodes
|
||||
struct IXmlUndoEventHandler
|
||||
{
|
||||
virtual bool SaveToXml(XmlNodeRef& xmlNode) = 0;
|
||||
virtual bool LoadFromXml(const XmlNodeRef& xmlNode) = 0;
|
||||
virtual bool ReloadFromXml(const XmlNodeRef& xmlNode) = 0;
|
||||
};
|
||||
|
||||
struct IXmlHistoryEventListener
|
||||
{
|
||||
enum EHistoryEventType
|
||||
{
|
||||
eHET_HistoryDeleted,
|
||||
eHET_HistoryCleared,
|
||||
eHET_HistorySaved,
|
||||
|
||||
eHET_VersionChanged,
|
||||
eHET_VersionAdded,
|
||||
|
||||
eHET_HistoryInvalidate,
|
||||
|
||||
eHET_HistoryGroupChanged,
|
||||
eHET_HistoryGroupAdded,
|
||||
eHET_HistoryGroupRemoved,
|
||||
};
|
||||
virtual void OnEvent(EHistoryEventType event, void* pData = nullptr) = 0;
|
||||
};
|
||||
|
||||
struct IXmlHistoryView
|
||||
{
|
||||
virtual bool LoadXml(int typeId, const XmlNodeRef& xmlNode, IXmlUndoEventHandler*& pUndoEventHandler, uint32 userindex) = 0;
|
||||
virtual void UnloadXml(int typeId) = 0;
|
||||
};
|
||||
|
||||
struct IXmlHistoryManager
|
||||
{
|
||||
// Undo/Redo
|
||||
virtual bool Undo() = 0;
|
||||
virtual bool Redo() = 0;
|
||||
virtual bool Goto(int historyNum) = 0;
|
||||
virtual void RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc) = 0;
|
||||
virtual void UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId = 0, bool destoryForever = false) = 0;
|
||||
virtual void RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId) = 0;
|
||||
|
||||
virtual void RegisterEventListener(IXmlHistoryEventListener* pEventListener) = 0;
|
||||
virtual void UnregisterEventListener(IXmlHistoryEventListener* pEventListener) = 0;
|
||||
|
||||
// History
|
||||
virtual void ClearHistory(bool flagAsSaved = false) = 0;
|
||||
virtual int GetVersionCount() const = 0;
|
||||
virtual const string& GetVersionDesc(int number) const = 0;
|
||||
virtual int GetCurrentVersionNumber() const = 0;
|
||||
|
||||
// Views
|
||||
virtual void RegisterView(IXmlHistoryView* pView) = 0;
|
||||
virtual void UnregisterView(IXmlHistoryView* pView) = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H
|
||||
@@ -24,8 +24,7 @@ bool CImageASC::Save(const QString& fileName, const CFloatImage& image)
|
||||
uint32 height = image.GetHeight();
|
||||
float* pixels = image.GetData();
|
||||
|
||||
string fileHeader;
|
||||
fileHeader.Format(
|
||||
AZStd::string fileHeader = AZStd::string::format(
|
||||
// Number of columns and rows in the data
|
||||
"ncols %d\n"
|
||||
"nrows %d\n"
|
||||
|
||||
@@ -399,8 +399,8 @@ bool CImageTIF::SaveRAW(const QString& fileName, const void* pData, int width, i
|
||||
|
||||
if (preset && preset[0])
|
||||
{
|
||||
string tiffphotoshopdata, valueheader;
|
||||
string presetkeyvalue = string("/preset=") + string(preset);
|
||||
AZStd::string tiffphotoshopdata, valueheader;
|
||||
AZStd::string presetkeyvalue = AZStd::string("/preset=") + AZStd::string(preset);
|
||||
|
||||
valueheader.push_back('\x1C');
|
||||
valueheader.push_back('\x02');
|
||||
@@ -472,7 +472,7 @@ const char* CImageTIF::GetPreset(const QString& fileName)
|
||||
libtiffDummyWriteProc, libtiffDummySeekProc,
|
||||
libtiffDummyCloseProc, libtiffDummySizeProc, libtiffDummyMapFileProc, libtiffDummyUnmapFileProc);
|
||||
|
||||
string strReturn;
|
||||
AZStd::string strReturn;
|
||||
char* preset = nullptr;
|
||||
int size;
|
||||
if (tif)
|
||||
|
||||
@@ -86,8 +86,7 @@ bool CImageUtil::SavePGM(const QString& fileName, const CImageEx& image)
|
||||
uint32* pixels = image.GetData();
|
||||
|
||||
// Create the file header.
|
||||
string fileHeader;
|
||||
fileHeader.Format(
|
||||
AZStd::string fileHeader = AZStd::string::format(
|
||||
// P2 = PGM header for ASCII output. (P5 is PGM header for binary output)
|
||||
"P2\n"
|
||||
// width and height of the image
|
||||
|
||||
@@ -15,24 +15,21 @@
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for ebus events
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace
|
||||
{
|
||||
string g_currentModName; // folder name only!
|
||||
}
|
||||
|
||||
namespace Path
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SplitPath(const QString& rstrFullPathFilename, QString& rstrDriveLetter, QString& rstrDirectory, QString& rstrFilename, QString& rstrExtension)
|
||||
{
|
||||
string strFullPathString(rstrFullPathFilename.toUtf8().data());
|
||||
string strDriveLetter;
|
||||
string strDirectory;
|
||||
string strFilename;
|
||||
string strExtension;
|
||||
AZStd::string strFullPathString(rstrFullPathFilename.toUtf8().data());
|
||||
AZStd::string strDriveLetter;
|
||||
AZStd::string strDirectory;
|
||||
AZStd::string strFilename;
|
||||
AZStd::string strExtension;
|
||||
|
||||
char* szPath((char*)strFullPathString.c_str());
|
||||
char* pchLastPosition(szPath);
|
||||
@@ -81,16 +78,16 @@ namespace Path
|
||||
strFilename.assign(pchLastPosition, pchCurrentPosition);
|
||||
}
|
||||
|
||||
rstrDriveLetter = strDriveLetter;
|
||||
rstrDirectory = strDirectory;
|
||||
rstrFilename = strFilename;
|
||||
rstrExtension = strExtension;
|
||||
rstrDriveLetter = strDriveLetter.c_str();
|
||||
rstrDirectory = strDirectory.c_str();
|
||||
rstrFilename = strFilename.c_str();
|
||||
rstrExtension = strExtension.c_str();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void GetDirectoryQueue(const QString& rstrSourceDirectory, QStringList& rcstrDirectoryTree)
|
||||
{
|
||||
string strCurrentDirectoryName;
|
||||
string strSourceDirectory(rstrSourceDirectory.toUtf8().data());
|
||||
AZStd::string strCurrentDirectoryName;
|
||||
AZStd::string strSourceDirectory(rstrSourceDirectory.toUtf8().data());
|
||||
const char* szSourceDirectory(strSourceDirectory.c_str());
|
||||
const char* pchCurrentPosition(szSourceDirectory);
|
||||
const char* pchLastPosition(szSourceDirectory);
|
||||
@@ -207,14 +204,7 @@ namespace Path
|
||||
|
||||
bool IsFolder(const char* pPath)
|
||||
{
|
||||
DWORD attrs = GetFileAttributes(pPath);
|
||||
|
||||
if (attrs == FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return AZ::IO::FileIOBase::GetInstance()->IsDirectory(pPath);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -255,16 +245,16 @@ namespace Path
|
||||
/// Get the data folder
|
||||
AZStd::string GetEditingGameDataFolder()
|
||||
{
|
||||
// query the editor root. The bus exists in case we want tools to be able to override this.
|
||||
// Define here the mod name
|
||||
static AZ::IO::FixedMaxPathString s_currentModName;
|
||||
|
||||
|
||||
if (g_currentModName.empty())
|
||||
if (s_currentModName.empty())
|
||||
{
|
||||
return GetGameAssetsFolder();
|
||||
}
|
||||
AZStd::string str(GetGameAssetsFolder());
|
||||
str += "Mods\\";
|
||||
str += g_currentModName;
|
||||
str += s_currentModName.c_str();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -93,7 +93,7 @@ namespace Path
|
||||
#endif
|
||||
file = path_buffer;
|
||||
}
|
||||
inline void Split(const string& filepath, string& path, string& file)
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
@@ -101,12 +101,12 @@ namespace Path
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath, drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
|
||||
#else
|
||||
_splitpath(filepath, drive, dir, fname, ext);
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath(path_buffer, 0, 0, fname, ext);
|
||||
@@ -137,7 +137,7 @@ namespace Path
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
inline void Split(const string& filepath, string& path, string& filename, string& fext)
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
@@ -145,10 +145,10 @@ namespace Path
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath, drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
#else
|
||||
_splitpath(filepath, drive, dir, fname, ext);
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
#endif
|
||||
path = path_buffer;
|
||||
@@ -230,7 +230,7 @@ namespace Path
|
||||
}
|
||||
|
||||
template<size_t size>
|
||||
inline bool EndsWithSlash(CryStackStringT<char, size>* path)
|
||||
inline bool EndsWithSlash(AZStd::fixed_string<size>* path)
|
||||
{
|
||||
if ((!path) || (path->empty()))
|
||||
{
|
||||
@@ -271,7 +271,7 @@ namespace Path
|
||||
}
|
||||
|
||||
template<size_t size>
|
||||
inline void AddBackslash(CryStackStringT<char, size>* path)
|
||||
inline void AddBackslash(AZStd::fixed_string<size>* path)
|
||||
{
|
||||
if (path->empty())
|
||||
{
|
||||
@@ -284,7 +284,7 @@ namespace Path
|
||||
}
|
||||
|
||||
template<size_t size>
|
||||
inline void AddSlash(CryStackStringT<char, size>* path)
|
||||
inline void AddSlash(AZStd::fixed_string<size>* path)
|
||||
{
|
||||
if (path->empty())
|
||||
{
|
||||
@@ -357,7 +357,7 @@ namespace Path
|
||||
{
|
||||
return CaselessPaths(GetRelativePath(path, true));
|
||||
}
|
||||
inline string FullPathToGamePath(const char* path)
|
||||
inline AZStd::string FullPathToGamePath(const char* path)
|
||||
{
|
||||
return CaselessPaths(GetRelativePath(path, true)).toUtf8().data();
|
||||
}
|
||||
@@ -394,7 +394,7 @@ namespace Path
|
||||
inline QString GetAudioLocalizationFolder(bool returnAbsolutePath)
|
||||
{
|
||||
// Omit the trailing slash!
|
||||
QString sLocalizationFolder(QString(PathUtil::GetLocalizationFolder()).left(static_cast<int>(PathUtil::GetLocalizationFolder().size()) - 1));
|
||||
QString sLocalizationFolder(QString(PathUtil::GetLocalizationFolder().c_str()).left(static_cast<int>(PathUtil::GetLocalizationFolder().size()) - 1));
|
||||
|
||||
if (!sLocalizationFolder.isEmpty())
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,210 +11,18 @@
|
||||
#define CRYINCLUDE_CRYCOMMONTOOLS_STRINGHELPERS_H
|
||||
#pragma once
|
||||
|
||||
#include <CryString.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace StringHelpers
|
||||
{
|
||||
// compares two strings to see if they are the same or different, case sensitive
|
||||
// returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
|
||||
int Compare(const string& str0, const string& str1);
|
||||
int Compare(const wstring& str0, const wstring& str1);
|
||||
|
||||
// compares two strings to see if they are the same or different, case is ignored
|
||||
// returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
|
||||
int CompareIgnoreCase(const string& str0, const string& str1);
|
||||
int CompareIgnoreCase(const wstring& str0, const wstring& str1);
|
||||
int CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1);
|
||||
int CompareIgnoreCase(const AZStd::wstring& str0, const AZStd::wstring& str1);
|
||||
|
||||
void Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector<AZStd::string>& outParts);
|
||||
void Split(const AZStd::wstring& str, const AZStd::wstring& separator, bool bReturnEmptyPartsToo, std::vector<AZStd::wstring>& outParts);
|
||||
|
||||
// compares two strings to see if they are the same, case senstive
|
||||
// returns true if they are the same or false if they are different
|
||||
bool Equals(const string& str0, const string& str1);
|
||||
bool Equals(const wstring& str0, const wstring& str1);
|
||||
|
||||
// compares two strings to see if they are the same, case is ignored
|
||||
// returns true if they are the same or false if they are different
|
||||
bool EqualsIgnoreCase(const string& str0, const string& str1);
|
||||
bool EqualsIgnoreCase(const wstring& str0, const wstring& str1);
|
||||
|
||||
// checks to see if a string starts with a specified string, case sensitive
|
||||
// returns true if the string does start with a specified string or false if it does not
|
||||
bool StartsWith(const string& str, const string& pattern);
|
||||
bool StartsWith(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string starts with a specified string, case is ignored
|
||||
// returns true if the string does start with a specified string or false if it does not
|
||||
bool StartsWithIgnoreCase(const string& str, const string& pattern);
|
||||
bool StartsWithIgnoreCase(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string ends with a specified string, case sensitive
|
||||
// returns true if the string does end with a specified string or false if it does not
|
||||
bool EndsWith(const string& str, const string& pattern);
|
||||
bool EndsWith(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string ends with a specified string, case is ignored
|
||||
// returns true if the string does end with a specified string or false if it does not
|
||||
bool EndsWithIgnoreCase(const string& str, const string& pattern);
|
||||
bool EndsWithIgnoreCase(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string contains a specified string, case sensitive
|
||||
// returns true if the string does contain the specified string or false if it does not
|
||||
bool Contains(const string& str, const string& pattern);
|
||||
bool Contains(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string contains a specified string, case is ignored
|
||||
// returns true if the string does contain the specified string or false if it does not
|
||||
bool ContainsIgnoreCase(const string& str, const string& pattern);
|
||||
bool ContainsIgnoreCase(const wstring& str, const wstring& pattern);
|
||||
|
||||
// checks to see if a string contains a wildcard string pattern, case sensitive
|
||||
// returns true if the string does match the wildcard string pattern or false if it does not
|
||||
bool MatchesWildcards(const string& str, const string& wildcards);
|
||||
bool MatchesWildcards(const wstring& str, const wstring& wildcards);
|
||||
|
||||
// checks to see if a string contains a wildcard string pattern, case is ignored
|
||||
// returns true if the string does match the wildcard string pattern or false if it does not
|
||||
bool MatchesWildcardsIgnoreCase(const string& str, const string& wildcards);
|
||||
bool MatchesWildcardsIgnoreCase(const wstring& str, const wstring& wildcards);
|
||||
|
||||
bool MatchesWildcardsIgnoreCaseExt(const string& str, const string& wildcards, std::vector<string>& wildcardMatches);
|
||||
bool MatchesWildcardsIgnoreCaseExt(const wstring& str, const wstring& wildcards, std::vector<wstring>& wildcardMatches);
|
||||
|
||||
string TrimLeft(const string& s);
|
||||
wstring TrimLeft(const wstring& s);
|
||||
|
||||
string TrimRight(const string& s);
|
||||
wstring TrimRight(const wstring& s);
|
||||
|
||||
string Trim(const string& s);
|
||||
wstring Trim(const wstring& s);
|
||||
|
||||
string RemoveDuplicateSpaces(const string& s);
|
||||
wstring RemoveDuplicateSpaces(const wstring& s);
|
||||
|
||||
// converts a string with upper case characters to be all lower case
|
||||
// returns the string in all lower case
|
||||
string MakeLowerCase(const string& s);
|
||||
wstring MakeLowerCase(const wstring& s);
|
||||
|
||||
// converts a string with lower case characters to be all upper case
|
||||
// returns the string in all upper case
|
||||
string MakeUpperCase(const string& s);
|
||||
wstring MakeUpperCase(const wstring& s);
|
||||
|
||||
// replace a specified character in a string with a specified replacement character
|
||||
// returns string with specified character replaced
|
||||
string Replace(const string& s, char oldChar, char newChar);
|
||||
wstring Replace(const wstring& s, wchar_t oldChar, wchar_t newChar);
|
||||
|
||||
void ConvertStringByRef(string& out, const string& in);
|
||||
void ConvertStringByRef(wstring& out, const string& in);
|
||||
void ConvertStringByRef(string& out, const wstring& in);
|
||||
void ConvertStringByRef(wstring& out, const wstring& in);
|
||||
|
||||
template <typename O, typename I>
|
||||
O ConvertString(const I& in)
|
||||
{
|
||||
O out;
|
||||
ConvertStringByRef(out, in);
|
||||
return out;
|
||||
}
|
||||
|
||||
void Split(const string& str, const string& separator, bool bReturnEmptyPartsToo, std::vector<string>& outParts);
|
||||
void Split(const wstring& str, const wstring& separator, bool bReturnEmptyPartsToo, std::vector<wstring>& outParts);
|
||||
|
||||
void SplitByAnyOf(const string& str, const string& separators, bool bReturnEmptyPartsToo, std::vector<string>& outParts);
|
||||
void SplitByAnyOf(const wstring& str, const wstring& separators, bool bReturnEmptyPartsToo, std::vector<wstring>& outParts);
|
||||
|
||||
string FormatVA(const char* const format, va_list parg);
|
||||
wstring FormatVA(const wchar_t* const format, va_list parg);
|
||||
|
||||
inline string Format(const char* const format, ...)
|
||||
{
|
||||
if ((format == 0) || (format[0] == 0))
|
||||
{
|
||||
return string();
|
||||
}
|
||||
va_list parg;
|
||||
va_start(parg, format);
|
||||
const string result = FormatVA(format, parg);
|
||||
va_end(parg);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline wstring Format(const wchar_t* const format, ...)
|
||||
{
|
||||
if ((format == 0) || (format[0] == 0))
|
||||
{
|
||||
return wstring();
|
||||
}
|
||||
va_list parg;
|
||||
va_start(parg, format);
|
||||
const wstring result = FormatVA(format, parg);
|
||||
va_end(parg);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SafeCopy(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc);
|
||||
void SafeCopy(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc);
|
||||
|
||||
void SafeCopyPadZeros(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc);
|
||||
void SafeCopyPadZeros(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ASCII
|
||||
// ANSI (system default Windows ANSI code page)
|
||||
// UTF-8
|
||||
// UTF-16
|
||||
|
||||
// ASCII -> UTF-16
|
||||
|
||||
bool Utf16ContainsAsciiOnly(const wchar_t* wstr);
|
||||
string ConvertAsciiUtf16ToAscii(const wchar_t* wstr);
|
||||
wstring ConvertAsciiToUtf16(const char* str);
|
||||
|
||||
// UTF-8 <-> UTF-16
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
wstring ConvertUtf8ToUtf16(const char* str);
|
||||
string ConvertUtf16ToUtf8(const wchar_t* wstr);
|
||||
|
||||
inline string ConvertUtfToUtf8(const char* str)
|
||||
{
|
||||
return string(str);
|
||||
}
|
||||
|
||||
inline string ConvertUtfToUtf8(const wchar_t* wstr)
|
||||
{
|
||||
return ConvertUtf16ToUtf8(wstr);
|
||||
}
|
||||
|
||||
inline wstring ConvertUtfToUtf16(const char* str)
|
||||
{
|
||||
return ConvertUtf8ToUtf16(str);
|
||||
}
|
||||
|
||||
inline wstring ConvertUtfToUtf16(const wchar_t* wstr)
|
||||
{
|
||||
return wstring(wstr);
|
||||
}
|
||||
|
||||
// ANSI <-> UTF-8, UTF-16
|
||||
|
||||
wstring ConvertAnsiToUtf16(const char* str);
|
||||
string ConvertUtf16ToAnsi(const wchar_t* wstr, char badChar);
|
||||
|
||||
inline string ConvertAnsiToUtf8(const char* str)
|
||||
{
|
||||
return ConvertUtf16ToUtf8(ConvertAnsiToUtf16(str).c_str());
|
||||
}
|
||||
inline string ConvertUtf8ToAnsi(const char* str, char badChar)
|
||||
{
|
||||
return ConvertUtf16ToAnsi(ConvertUtf8ToUtf16(str).c_str(), badChar);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ANSI -> ASCII
|
||||
string ConvertAnsiToAscii(const char* str, char badChar);
|
||||
}
|
||||
#endif // CRYINCLUDE_CRYCOMMONTOOLS_STRINGHELPERS_H
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Utility class to help in STL algorithms on containers with
|
||||
// CStrings when intending to use case insensitive searches or sorting for
|
||||
// example.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
Utility class to help in STL algorithms on containers with CStrings
|
||||
when intending to use case insensitive searches or sorting for example.
|
||||
|
||||
e.g.
|
||||
std::vector< CString > v;
|
||||
...
|
||||
std::sort( v.begin(), v.end(), CStringNoCasePredicate::LessThan() );
|
||||
std::find_if( v.begin(), v.end(), CStringNoCasePredicate::Equal( stringImLookingFor ) );
|
||||
*/
|
||||
class CStringNoCasePredicate
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct Equal
|
||||
{
|
||||
Equal(const QString& referenceString)
|
||||
: m_referenceString(referenceString)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator() (const QString& arg) const
|
||||
{
|
||||
return (m_referenceString.compare(arg, Qt::CaseInsensitive) == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
const QString& m_referenceString;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct LessThan
|
||||
{
|
||||
bool operator() (const QString& arg1, const QString& arg2) const
|
||||
{
|
||||
return (arg1.CompareNoCase(arg2) < 0);
|
||||
}
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H
|
||||
@@ -1,875 +0,0 @@
|
||||
/*
|
||||
* 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 "EditorDefs.h"
|
||||
|
||||
#include "XmlHistoryManager.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistory::SXmlHistory(CXmlHistoryManager* pManager, const XmlNodeRef& xmlBaseVersion, uint32 typeId)
|
||||
: m_pManager(pManager)
|
||||
, m_typeId(typeId)
|
||||
, m_DeletedVersion(-1)
|
||||
, m_SavedVersion(-1)
|
||||
{
|
||||
int newVersionNumber = m_pManager->GetCurrentVersionNumber() + (m_pManager->IsPreparedForNextVersion() ? 1 : 0);
|
||||
m_xmlVersionList[ newVersionNumber ] = xmlBaseVersion;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SXmlHistory::AddToHistory(const XmlNodeRef& newXmlVersion)
|
||||
{
|
||||
int newVersionNumber = m_pManager->IncrementVersion(this);
|
||||
m_xmlVersionList[ newVersionNumber ] = newXmlVersion;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const XmlNodeRef& SXmlHistory::Undo(bool* bVersionExist)
|
||||
{
|
||||
m_pManager->Undo();
|
||||
return GetCurrentVersion(bVersionExist);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const XmlNodeRef& SXmlHistory::Redo()
|
||||
{
|
||||
m_pManager->Redo();
|
||||
return GetCurrentVersion();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const XmlNodeRef& SXmlHistory::GetCurrentVersion(bool* bVersionExist, int* iVersionNumber) const
|
||||
{
|
||||
int currentVersion = m_pManager->GetCurrentVersionNumber();
|
||||
|
||||
TXmlVersionMap::const_iterator it = m_xmlVersionList.begin();
|
||||
TXmlVersionMap::const_iterator previt = m_xmlVersionList.begin();
|
||||
while (it != m_xmlVersionList.end())
|
||||
{
|
||||
if (it->first > currentVersion)
|
||||
{
|
||||
break;
|
||||
}
|
||||
previt = it;
|
||||
++it;
|
||||
}
|
||||
|
||||
if (bVersionExist)
|
||||
{
|
||||
*bVersionExist = currentVersion >= m_xmlVersionList.begin()->first;
|
||||
}
|
||||
if (iVersionNumber)
|
||||
{
|
||||
*iVersionNumber = previt->first;
|
||||
}
|
||||
|
||||
return previt->second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool SXmlHistory::IsModified() const
|
||||
{
|
||||
int currVersion;
|
||||
GetCurrentVersion(nullptr, &currVersion);
|
||||
return m_SavedVersion != currVersion;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SXmlHistory::FlagAsDeleted()
|
||||
{
|
||||
assert(m_pManager->IsPreparedForNextVersion());
|
||||
m_DeletedVersion = m_pManager->GetCurrentVersionNumber() + 1;
|
||||
m_SavedVersion = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SXmlHistory::FlagAsSaved()
|
||||
{
|
||||
if (Exist())
|
||||
{
|
||||
int currVersion;
|
||||
GetCurrentVersion(nullptr, &currVersion);
|
||||
m_SavedVersion = currVersion;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool SXmlHistory::Exist() const
|
||||
{
|
||||
// int currentVersion = m_pManager->GetCurrentVersionNumber();
|
||||
// bool deleted = m_DeletedVersion != -1 && currentVersion >= m_DeletedVersion;
|
||||
// bool exist = currentVersion >= m_xmlVersionList.begin()->first;
|
||||
// return !deleted && exist;
|
||||
int currentVersion = m_pManager->GetCurrentVersionNumber();
|
||||
return currentVersion >= m_xmlVersionList.begin()->first && (m_DeletedVersion == -1 || currentVersion < m_DeletedVersion);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SXmlHistory::ClearRedo()
|
||||
{
|
||||
int currentVersion = m_pManager->GetCurrentVersionNumber();
|
||||
if (m_DeletedVersion > currentVersion + (m_pManager->IsPreparedForNextVersion() ? 1 : 0))
|
||||
{
|
||||
m_DeletedVersion = -1;
|
||||
}
|
||||
TXmlVersionMap::iterator it = m_xmlVersionList.begin();
|
||||
for (; it != m_xmlVersionList.end(); ++it)
|
||||
{
|
||||
if (it->first > currentVersion)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it != m_xmlVersionList.end())
|
||||
{
|
||||
++it;
|
||||
while (it != m_xmlVersionList.end())
|
||||
{
|
||||
m_xmlVersionList.erase(it++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SXmlHistory::ClearHistory(bool flagAsSaved)
|
||||
{
|
||||
bool wasModified = !flagAsSaved && IsModified();
|
||||
m_DeletedVersion = Exist() ? -1 : 0;
|
||||
ClearRedo();
|
||||
XmlNodeRef latest = m_xmlVersionList.rbegin()->second;
|
||||
m_xmlVersionList.clear();
|
||||
m_xmlVersionList[ 0 ] = latest;
|
||||
m_SavedVersion = wasModified ? -1 : 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistoryGroup::SXmlHistoryGroup(CXmlHistoryManager* pManager, uint32 typeId)
|
||||
: m_pManager(pManager)
|
||||
, m_typeId(typeId)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistory* SXmlHistoryGroup::GetHistory(int index) const
|
||||
{
|
||||
THistoryList::const_iterator it = m_List.begin();
|
||||
while (index > 0 && it != m_List.end())
|
||||
{
|
||||
++it;
|
||||
if ((*it)->Exist())
|
||||
{
|
||||
--index;
|
||||
}
|
||||
}
|
||||
return it != m_List.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int SXmlHistoryGroup::GetHistoryCount() const
|
||||
{
|
||||
int count = 0;
|
||||
for (THistoryList::const_iterator it = m_List.begin(); it != m_List.end(); ++it)
|
||||
{
|
||||
if ((*it)->Exist())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistory* SXmlHistoryGroup::GetHistoryByTypeId(uint32 typeId, int index /*= 0*/) const
|
||||
{
|
||||
for (int i = 0; i < GetHistoryCount(); ++i)
|
||||
{
|
||||
SXmlHistory* pHistory = GetHistory(i);
|
||||
if (pHistory->GetTypeId() == typeId)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
if (index == -1)
|
||||
{
|
||||
return pHistory;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int SXmlHistoryGroup::GetHistoryCountByTypeId(uint32 typeId) const
|
||||
{
|
||||
int res = 0;
|
||||
for (int i = 0; i < GetHistoryCount(); ++i)
|
||||
{
|
||||
if (GetHistory(i)->GetTypeId() == typeId)
|
||||
{
|
||||
res++;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int SXmlHistoryGroup::CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion)
|
||||
{
|
||||
if (m_pManager)
|
||||
{
|
||||
m_List.push_back(m_pManager->CreateXmlHistory(typeId, xmlBaseVersion));
|
||||
return m_List.size() - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int SXmlHistoryGroup::GetHistoryIndex(const SXmlHistory* pHistory) const
|
||||
{
|
||||
int index = 0;
|
||||
for (THistoryList::const_iterator it = m_List.begin(); it != m_List.end(); ++it)
|
||||
{
|
||||
if (*it == pHistory)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
CXmlHistoryManager::CXmlHistoryManager()
|
||||
: m_CurrentVersion(0)
|
||||
, m_LatestVersion(0)
|
||||
, m_pExclusiveListener(nullptr)
|
||||
, m_RecordNextVersion(false)
|
||||
, m_pExActiveGroup(nullptr)
|
||||
, m_bIsActiveGroupEx(false)
|
||||
{
|
||||
m_pNullGroup = new SXmlHistoryGroup(this, (uint32) - 1);
|
||||
}
|
||||
|
||||
CXmlHistoryManager::~CXmlHistoryManager()
|
||||
{
|
||||
delete m_pNullGroup;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlHistoryManager::Undo()
|
||||
{
|
||||
if (m_CurrentVersion > 0)
|
||||
{
|
||||
int prevVersion = m_CurrentVersion;
|
||||
const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup();
|
||||
m_CurrentVersion--;
|
||||
ReloadCurrentVersion(pPrevCurrGroup, prevVersion);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlHistoryManager::Redo()
|
||||
{
|
||||
if (m_CurrentVersion < m_LatestVersion)
|
||||
{
|
||||
int prevVersion = m_CurrentVersion;
|
||||
const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup();
|
||||
m_CurrentVersion++;
|
||||
ReloadCurrentVersion(pPrevCurrGroup, prevVersion);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlHistoryManager::Goto(int historyNum)
|
||||
{
|
||||
if (historyNum >= 0 && historyNum <= m_LatestVersion)
|
||||
{
|
||||
int prevVersion = m_CurrentVersion;
|
||||
const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup();
|
||||
m_CurrentVersion = historyNum;
|
||||
ReloadCurrentVersion(pPrevCurrGroup, prevVersion);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc)
|
||||
{
|
||||
ClearRedo();
|
||||
SXmlHistory* pChangedXml = m_UndoEventHandlerMap[ pEventHandler ].CurrentData;
|
||||
assert(pChangedXml);
|
||||
|
||||
XmlNodeRef newData = gEnv->pSystem->CreateXmlNode();
|
||||
#if !defined(NDEBUG)
|
||||
bool bRes =
|
||||
#endif
|
||||
pEventHandler->SaveToXml(newData);
|
||||
assert(bRes);
|
||||
|
||||
TXmlHistotyGroupPtrList activeGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups;
|
||||
|
||||
pChangedXml->AddToHistory(newData);
|
||||
m_UndoEventHandlerMap[ pEventHandler ].HistoryData[ m_CurrentVersion ] = pChangedXml;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].HistoryDescription = desc;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo = false;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups = activeGroups;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = false;
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionAdded);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId /*= 0*/, bool destoryForever /*= false*/)
|
||||
{
|
||||
if (destoryForever)
|
||||
{
|
||||
UnregisterUndoEventHandler(pEventHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InvalidHandlerMap[typeId] = pEventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId)
|
||||
{
|
||||
TInvalidUndoEventListener::iterator it = m_InvalidHandlerMap.find(typeId);
|
||||
if (it != m_InvalidHandlerMap.end())
|
||||
{
|
||||
IXmlUndoEventHandler* pLastHandler = it->second;
|
||||
TUndoEventHandlerMap::iterator lastit = m_UndoEventHandlerMap.find(pLastHandler);
|
||||
if (lastit != m_UndoEventHandlerMap.end())
|
||||
{
|
||||
m_UndoEventHandlerMap[pEventHandler] = lastit->second;
|
||||
m_UndoEventHandlerMap.erase(lastit);
|
||||
}
|
||||
m_InvalidHandlerMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RegisterEventListener(IXmlHistoryEventListener* pEventListener)
|
||||
{
|
||||
stl::push_back_unique(m_EventListener, pEventListener);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::UnregisterEventListener(IXmlHistoryEventListener* pEventListener)
|
||||
{
|
||||
m_EventListener.remove(pEventListener);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::PrepareForNextVersion()
|
||||
{
|
||||
assert(!m_RecordNextVersion);
|
||||
m_RecordNextVersion = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RecordNextVersion(SXmlHistory* pHistory, XmlNodeRef newData, const char* undoDesc /*= nullptr*/)
|
||||
{
|
||||
assert(m_RecordNextVersion);
|
||||
RegisterUndoEventHandler(this, pHistory);
|
||||
m_newHistoryData = newData;
|
||||
RecordUndo(this, undoDesc ? undoDesc : "<UNDEFINED>");
|
||||
m_RecordNextVersion = false;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = true;
|
||||
UnregisterUndoEventHandler(this);
|
||||
SetActiveGroupInt(GetActiveGroup());
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryInvalidate);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlHistoryManager::SaveToXml(XmlNodeRef& xmlNode)
|
||||
{
|
||||
assert(m_newHistoryData);
|
||||
xmlNode = m_newHistoryData;
|
||||
return true;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::ClearHistory(bool flagAsSaved)
|
||||
{
|
||||
TXmlHistotyGroupPtrList activeGropus = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups;
|
||||
for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it)
|
||||
{
|
||||
it->ClearHistory(flagAsSaved);
|
||||
}
|
||||
|
||||
SetActiveGroup(nullptr);
|
||||
|
||||
m_CurrentVersion = 0;
|
||||
m_LatestVersion = 0;
|
||||
|
||||
m_UndoEventHandlerMap.clear();
|
||||
m_HistoryInfoMap.clear();
|
||||
|
||||
m_HistoryInfoMap[ 0 ].HistoryDescription = "New History";
|
||||
m_HistoryInfoMap[ 0 ].ActiveGroups = activeGropus;
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryCleared);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
const string& CXmlHistoryManager::GetVersionDesc(int number) const
|
||||
{
|
||||
THistoryInfoMap::const_iterator it = m_HistoryInfoMap.find(number);
|
||||
if (it != m_HistoryInfoMap.end())
|
||||
{
|
||||
return it->second.HistoryDescription;
|
||||
}
|
||||
|
||||
static string undef("UNDEFINED");
|
||||
return undef;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RegisterView(IXmlHistoryView* pView)
|
||||
{
|
||||
stl::push_back_unique(m_Views, pView);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::UnregisterView(IXmlHistoryView* pView)
|
||||
{
|
||||
m_Views.remove(pView);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistoryGroup* CXmlHistoryManager::CreateXmlGroup(uint32 typeId)
|
||||
{
|
||||
m_Groups.push_back(SXmlHistoryGroup(this, typeId));
|
||||
return &(*m_Groups.rbegin());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::AddXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc /*= nullptr*/)
|
||||
{
|
||||
RecordUndoInternal(undoDesc ? undoDesc : "New XML Group added");
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups.push_back(pGroup);
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupAdded, (void*)pGroup);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RemoveXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc /*= nullptr*/)
|
||||
{
|
||||
bool unload = m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup == pGroup;
|
||||
RecordUndoInternal(undoDesc ? undoDesc : "XML Group deleted");
|
||||
TXmlHistotyGroupPtrList& list = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups;
|
||||
stl::find_and_erase(list, pGroup);
|
||||
if (unload)
|
||||
{
|
||||
SetActiveGroupInt(nullptr);
|
||||
}
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup = m_pNullGroup;
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupRemoved, (void*)pGroup);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::SetActiveGroup(const SXmlHistoryGroup* pGroup, const char* displayName /*= nullptr*/, const TGroupIndexMap& groupIndex /*= TGroupIndexMap()*/, bool setExternal /*= false*/)
|
||||
{
|
||||
TGroupIndexMap userIndex;
|
||||
const SXmlHistoryGroup* pActiveGroup = GetActiveGroup(userIndex);
|
||||
if (pGroup != pActiveGroup || userIndex != groupIndex || setExternal)
|
||||
{
|
||||
const bool isEx = m_CurrentVersion != m_LatestVersion || setExternal;
|
||||
m_pExActiveGroup = const_cast<SXmlHistoryGroup*>(pGroup);
|
||||
m_ExCurrentIndex = groupIndex;
|
||||
m_bIsActiveGroupEx = true;
|
||||
SetActiveGroupInt(pGroup, displayName, !isEx, groupIndex);
|
||||
m_bIsActiveGroupEx = isEx;
|
||||
}
|
||||
}
|
||||
|
||||
void CXmlHistoryManager::SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const char* displayName /*= nullptr*/, bool bRecordNullUndo /*= false*/, const TGroupIndexMap& groupIndex /*= TGroupIndexMap()*/)
|
||||
{
|
||||
UnloadInt();
|
||||
|
||||
TEventHandlerList eventHandler;
|
||||
string undoDesc;
|
||||
|
||||
if (pGroup)
|
||||
{
|
||||
for (TViews::iterator it = m_Views.begin(); it != m_Views.end(); ++it)
|
||||
{
|
||||
IXmlHistoryView* pView = *it;
|
||||
|
||||
std::map<uint32, int> userIndexCount;
|
||||
|
||||
for (SXmlHistoryGroup::THistoryList::const_iterator history = pGroup->m_List.begin(); history != pGroup->m_List.end(); ++history)
|
||||
{
|
||||
std::map<uint32, int>::iterator it2 = userIndexCount.find((*history)->GetTypeId());
|
||||
if (it2 == userIndexCount.end())
|
||||
{
|
||||
userIndexCount[ (*history)->GetTypeId() ] = 0;
|
||||
}
|
||||
uint32 userindex = userIndexCount[ (*history)->GetTypeId() ];
|
||||
IXmlUndoEventHandler* pEventHandler = nullptr;
|
||||
TGroupIndexMap::const_iterator indexIter = groupIndex.find((*history)->GetTypeId());
|
||||
if (indexIter == groupIndex.end() || indexIter->second == userindex)
|
||||
{
|
||||
if ((*history)->Exist())
|
||||
{
|
||||
if (pView->LoadXml((*history)->GetTypeId(), (*history)->GetCurrentVersion(), pEventHandler, userindex))
|
||||
{
|
||||
if (pEventHandler)
|
||||
{
|
||||
m_UndoHandlerViewMap[ pEventHandler ] = pView;
|
||||
RegisterUndoEventHandler(pEventHandler, *history);
|
||||
eventHandler.push_back(pEventHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((*history)->Exist())
|
||||
{
|
||||
userIndexCount[ (*history)->GetTypeId() ]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
undoDesc.Format("Changed View to \"%s\"", displayName ? displayName : "UNDEFINED");
|
||||
}
|
||||
else
|
||||
{
|
||||
undoDesc = "Unloaded Views";
|
||||
for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it)
|
||||
{
|
||||
eventHandler.push_back(it->first);
|
||||
}
|
||||
pGroup = m_pNullGroup;
|
||||
}
|
||||
|
||||
if (bRecordNullUndo)
|
||||
{
|
||||
RecordNullUndo(eventHandler, undoDesc.c_str());
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup = pGroup;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].CurrUserIndex = groupIndex;
|
||||
}
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupChanged);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
const SXmlHistoryGroup* CXmlHistoryManager::GetActiveGroup() const
|
||||
{
|
||||
TGroupIndexMap userIndex;
|
||||
return GetActiveGroup(userIndex);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
const SXmlHistoryGroup* CXmlHistoryManager::GetActiveGroup(TGroupIndexMap& currUserIndex /*out*/) const
|
||||
{
|
||||
if (m_bIsActiveGroupEx)
|
||||
{
|
||||
currUserIndex = m_ExCurrentIndex;
|
||||
return m_pExActiveGroup;
|
||||
}
|
||||
|
||||
int currVersion = m_CurrentVersion;
|
||||
do
|
||||
{
|
||||
THistoryInfoMap::const_iterator it = m_HistoryInfoMap.find(currVersion);
|
||||
if (it != m_HistoryInfoMap.end())
|
||||
{
|
||||
const SXmlHistoryGroup* pGroup = it->second.CurrGroup;
|
||||
if (it != m_HistoryInfoMap.end() && pGroup)
|
||||
{
|
||||
currUserIndex = it->second.CurrUserIndex;
|
||||
return pGroup == m_pNullGroup ? nullptr : pGroup;
|
||||
}
|
||||
}
|
||||
currVersion--;
|
||||
} while (currVersion >= 0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistory* CXmlHistoryManager::CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion)
|
||||
{
|
||||
m_XmlHistoryList.push_back(SXmlHistory(this, xmlBaseVersion, typeId));
|
||||
return &(*m_XmlHistoryList.rbegin());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::DeleteXmlHistory(const SXmlHistory* pXmlHistry)
|
||||
{
|
||||
for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it)
|
||||
{
|
||||
if (&(*it) == pXmlHistry)
|
||||
{
|
||||
m_XmlHistoryList.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::UnloadInt()
|
||||
{
|
||||
for (TViews::iterator it = m_Views.begin(); it != m_Views.end(); ++it)
|
||||
{
|
||||
IXmlHistoryView* pView = *it;
|
||||
pView->UnloadXml(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
template< class T >
|
||||
void ClearAfterVersion(T& container, int version)
|
||||
{
|
||||
auto foundit = container.end();
|
||||
do
|
||||
{
|
||||
auto it = container.find(version);
|
||||
if (it != container.end())
|
||||
{
|
||||
foundit = it;
|
||||
break;
|
||||
}
|
||||
version--;
|
||||
} while (version >= 0);
|
||||
if (foundit != container.end())
|
||||
{
|
||||
for (auto it = ++foundit; it != container.end(); )
|
||||
{
|
||||
container.erase(it++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CXmlHistoryManager::ClearRedo()
|
||||
{
|
||||
ClearAfterVersion(m_HistoryInfoMap, m_CurrentVersion);
|
||||
for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it)
|
||||
{
|
||||
ClearAfterVersion(it->second.HistoryData, m_CurrentVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::DeleteAll()
|
||||
{
|
||||
ClearHistory();
|
||||
m_Groups.clear();
|
||||
m_UndoEventHandlerMap.clear();
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryDeleted);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::FlagHistoryAsSaved()
|
||||
{
|
||||
for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it)
|
||||
{
|
||||
it->FlagAsSaved();
|
||||
}
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistorySaved);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RecordNullUndo(const TEventHandlerList& eventHandler, const char* desc, bool isNull /*= true*/)
|
||||
{
|
||||
TXmlHistotyGroupPtrList activeGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups;
|
||||
|
||||
// if current version is already null undo, overwrite it instead of create a new version
|
||||
if (m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo && isNull)
|
||||
{
|
||||
assert(m_CurrentVersion);
|
||||
m_CurrentVersion--;
|
||||
}
|
||||
|
||||
ClearRedo();
|
||||
IncrementVersion();
|
||||
|
||||
for (TEventHandlerList::const_iterator it = eventHandler.begin(); it != eventHandler.end(); ++it)
|
||||
{
|
||||
SXmlHistory* pChangedXml = m_UndoEventHandlerMap[ *it ].CurrentData;
|
||||
m_UndoEventHandlerMap[ *it ].HistoryData[ m_CurrentVersion ] = pChangedXml;
|
||||
}
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].HistoryDescription = desc;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo = isNull;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups = activeGroups;
|
||||
m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = false;
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionAdded);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::ReloadCurrentVersion(const SXmlHistoryGroup* pPrevGroup, int prevVersion)
|
||||
{
|
||||
m_bIsActiveGroupEx = false;
|
||||
const SXmlHistoryGroup* pActiveGroup = GetActiveGroup();
|
||||
|
||||
bool bInvalidated = false;
|
||||
int start = min(prevVersion, m_CurrentVersion);
|
||||
int end = max(prevVersion, m_CurrentVersion);
|
||||
for (int i = start; i <= end; ++i)
|
||||
{
|
||||
if (m_HistoryInfoMap[i].HistoryInvalidated)
|
||||
{
|
||||
bInvalidated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bInvalidated && pPrevGroup == pActiveGroup)
|
||||
{
|
||||
for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it)
|
||||
{
|
||||
IXmlUndoEventHandler* pEventHandler = it->first;
|
||||
if (!IsEventHandlerValid(pEventHandler))
|
||||
{
|
||||
assert(false);
|
||||
continue;
|
||||
}
|
||||
SXmlHistory* pXmlHistory = GetLatestHistory(m_UndoEventHandlerMap[ pEventHandler ]); /*m_UndoEventHandlerMap[ pEventHandler ].HistoryData[ m_CurrentVersion ];*/
|
||||
if (pXmlHistory)
|
||||
{
|
||||
if (pXmlHistory->Exist())
|
||||
{
|
||||
pEventHandler->ReloadFromXml(pXmlHistory->GetCurrentVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionChanged);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActiveGroupInt(pActiveGroup);
|
||||
}
|
||||
|
||||
if (bInvalidated)
|
||||
{
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryInvalidate);
|
||||
}
|
||||
|
||||
TXmlHistotyGroupPtrList oldActiveGroups = m_HistoryInfoMap[ prevVersion ].ActiveGroups;
|
||||
TXmlHistotyGroupPtrList newActiveGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups;
|
||||
|
||||
RemoveListFromList(newActiveGroups, oldActiveGroups);
|
||||
RemoveListFromList(oldActiveGroups, m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups);
|
||||
|
||||
for (TXmlHistotyGroupPtrList::iterator it = newActiveGroups.begin(); it != newActiveGroups.end(); ++it)
|
||||
{
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupAdded, (void*) *it);
|
||||
}
|
||||
|
||||
for (TXmlHistotyGroupPtrList::iterator it = oldActiveGroups.begin(); it != oldActiveGroups.end(); ++it)
|
||||
{
|
||||
NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupRemoved, (void*) *it);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RemoveListFromList(TXmlHistotyGroupPtrList& list, const TXmlHistotyGroupPtrList& removeList)
|
||||
{
|
||||
for (TXmlHistotyGroupPtrList::const_iterator rit = removeList.begin(); rit != removeList.end(); ++rit)
|
||||
{
|
||||
for (TXmlHistotyGroupPtrList::iterator it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
if (*it == *rit)
|
||||
{
|
||||
list.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
SXmlHistory* CXmlHistoryManager::GetLatestHistory(SUndoEventHandlerData& eventHandlerData)
|
||||
{
|
||||
int currVersion = m_CurrentVersion;
|
||||
do
|
||||
{
|
||||
THistoryVersionMap::iterator it = eventHandlerData.HistoryData.find(currVersion);
|
||||
if (it != eventHandlerData.HistoryData.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
currVersion--;
|
||||
} while (currVersion >= 0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::NotifyUndoEventListener(IXmlHistoryEventListener::EHistoryEventType event, void* pData)
|
||||
{
|
||||
if (m_pExclusiveListener)
|
||||
{
|
||||
m_pExclusiveListener->OnEvent(event, pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TEventListener::iterator it = m_EventListener.begin(); it != m_EventListener.end(); ++it)
|
||||
{
|
||||
(*it)->OnEvent(event, pData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int CXmlHistoryManager::IncrementVersion([[maybe_unused]] SXmlHistory* pXmlHistry)
|
||||
{
|
||||
for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it)
|
||||
{
|
||||
it->ClearRedo();
|
||||
}
|
||||
return IncrementVersion();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int CXmlHistoryManager::IncrementVersion()
|
||||
{
|
||||
m_CurrentVersion++;
|
||||
m_LatestVersion = m_CurrentVersion;
|
||||
return m_CurrentVersion;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RegisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler, SXmlHistory* pXmlData)
|
||||
{
|
||||
m_UndoEventHandlerMap[ pEventHandler ].CurrentData = pXmlData;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::UnregisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler)
|
||||
{
|
||||
TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.find(pEventHandler);
|
||||
if (it != m_UndoEventHandlerMap.end())
|
||||
{
|
||||
m_UndoEventHandlerMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CXmlHistoryManager::RecordUndoInternal(const char* desc)
|
||||
{
|
||||
TEventHandlerList eventHandler;
|
||||
for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it)
|
||||
{
|
||||
eventHandler.push_back(it->first);
|
||||
}
|
||||
RecordNullUndo(eventHandler, desc, false);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlHistoryManager::IsEventHandlerValid(IXmlUndoEventHandler* pEventHandler)
|
||||
{
|
||||
for (TInvalidUndoEventListener::iterator it = m_InvalidHandlerMap.begin(); it != m_InvalidHandlerMap.end(); ++it)
|
||||
{
|
||||
if (it->second == pEventHandler)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "IXmlHistoryManager.h"
|
||||
|
||||
class CXmlHistoryManager;
|
||||
|
||||
struct SXmlHistory
|
||||
{
|
||||
public:
|
||||
SXmlHistory(CXmlHistoryManager* pManager, const XmlNodeRef& xmlBaseVersion, uint32 typeId);
|
||||
|
||||
void AddToHistory(const XmlNodeRef& newXmlVersion);
|
||||
|
||||
const XmlNodeRef& Undo(bool* bVersionExist = nullptr);
|
||||
const XmlNodeRef& Redo();
|
||||
const XmlNodeRef& GetCurrentVersion(bool* bVersionExist = nullptr, int* iVersionNumber = nullptr) const;
|
||||
bool IsModified() const;
|
||||
uint32 GetTypeId() const {return m_typeId; }
|
||||
void FlagAsDeleted();
|
||||
void FlagAsSaved();
|
||||
bool Exist() const;
|
||||
|
||||
private:
|
||||
friend class CXmlHistoryManager;
|
||||
|
||||
void ClearRedo();
|
||||
void ClearHistory(bool flagAsSaved);
|
||||
|
||||
private:
|
||||
CXmlHistoryManager* m_pManager;
|
||||
uint32 m_typeId;
|
||||
int m_DeletedVersion;
|
||||
int m_SavedVersion;
|
||||
|
||||
typedef std::map< int, XmlNodeRef > TXmlVersionMap;
|
||||
TXmlVersionMap m_xmlVersionList;
|
||||
};
|
||||
|
||||
|
||||
struct SXmlHistoryGroup
|
||||
{
|
||||
SXmlHistoryGroup(CXmlHistoryManager* pManager, uint32 typeId);
|
||||
|
||||
SXmlHistory* GetHistory(int index) const;
|
||||
int GetHistoryCount() const;
|
||||
|
||||
SXmlHistory* GetHistoryByTypeId(uint32 typeId, int index = 0) const;
|
||||
int GetHistoryCountByTypeId(uint32 typeId) const;
|
||||
|
||||
int CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion);
|
||||
uint32 GetTypeId() const {return m_typeId; }
|
||||
|
||||
int GetHistoryIndex(const SXmlHistory* pHistory) const;
|
||||
|
||||
private:
|
||||
friend class CXmlHistoryManager;
|
||||
CXmlHistoryManager* m_pManager;
|
||||
uint32 m_typeId;
|
||||
|
||||
typedef std::list< SXmlHistory* > THistoryList;
|
||||
THistoryList m_List;
|
||||
};
|
||||
|
||||
typedef std::map<uint32, int> TGroupIndexMap;
|
||||
|
||||
|
||||
class CXmlHistoryManager
|
||||
: public IXmlHistoryManager
|
||||
, public IXmlUndoEventHandler
|
||||
{
|
||||
public:
|
||||
CXmlHistoryManager();
|
||||
~CXmlHistoryManager();
|
||||
|
||||
// Undo/Redo
|
||||
bool Undo();
|
||||
bool Redo();
|
||||
bool Goto(int historyNum);
|
||||
void RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc);
|
||||
void UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId = 0, bool destoryForever = false);
|
||||
void RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId);
|
||||
|
||||
void PrepareForNextVersion();
|
||||
void RecordNextVersion(SXmlHistory* pHistory, XmlNodeRef newData, const char* undoDesc = nullptr);
|
||||
bool IsPreparedForNextVersion() const {return m_RecordNextVersion; }
|
||||
|
||||
void RegisterEventListener(IXmlHistoryEventListener* pEventListener);
|
||||
void UnregisterEventListener(IXmlHistoryEventListener* pEventListener);
|
||||
void SetExclusiveListener(IXmlHistoryEventListener* pEventListener) { m_pExclusiveListener = pEventListener; }
|
||||
|
||||
// History
|
||||
void ClearHistory(bool flagAsSaved = false);
|
||||
int GetVersionCount() const { return m_LatestVersion; }
|
||||
const string& GetVersionDesc(int number) const;
|
||||
int GetCurrentVersionNumber() const { return m_CurrentVersion; }
|
||||
|
||||
// Views
|
||||
void RegisterView(IXmlHistoryView* pView);
|
||||
void UnregisterView(IXmlHistoryView* pView);
|
||||
|
||||
// Xml History Groups
|
||||
SXmlHistoryGroup* CreateXmlGroup(uint32 typeId);
|
||||
void SetActiveGroup(const SXmlHistoryGroup* pGroup, const char* displayName = nullptr, const TGroupIndexMap& groupIndex = TGroupIndexMap(), bool setExternal = false);
|
||||
const SXmlHistoryGroup* GetActiveGroup() const;
|
||||
const SXmlHistoryGroup* GetActiveGroup(TGroupIndexMap& currUserIndex /*out*/) const;
|
||||
void AddXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc = nullptr);
|
||||
void RemoveXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc = nullptr);
|
||||
|
||||
void DeleteAll();
|
||||
|
||||
void FlagHistoryAsSaved();
|
||||
|
||||
virtual bool SaveToXml(XmlNodeRef& xmlNode);
|
||||
virtual bool LoadFromXml([[maybe_unused]] const XmlNodeRef& xmlNode) { return false; };
|
||||
virtual bool ReloadFromXml([[maybe_unused]] const XmlNodeRef& xmlNode) { return false; };
|
||||
|
||||
private:
|
||||
typedef std::list< SXmlHistory > TXmlHistoryList;
|
||||
TXmlHistoryList m_XmlHistoryList;
|
||||
int m_CurrentVersion;
|
||||
int m_LatestVersion;
|
||||
SXmlHistoryGroup* m_pNullGroup; // hack for unload view ...
|
||||
XmlNodeRef m_newHistoryData;
|
||||
bool m_RecordNextVersion;
|
||||
bool m_bIsActiveGroupEx;
|
||||
SXmlHistoryGroup* m_pExActiveGroup;
|
||||
TGroupIndexMap m_ExCurrentIndex;
|
||||
|
||||
typedef std::list< SXmlHistoryGroup > TXmlHistotyGroupList;
|
||||
TXmlHistotyGroupList m_Groups;
|
||||
|
||||
// event listener
|
||||
typedef std::list< IXmlHistoryEventListener* > TEventListener;
|
||||
TEventListener m_EventListener;
|
||||
IXmlHistoryEventListener* m_pExclusiveListener;
|
||||
|
||||
// views
|
||||
typedef std::list< IXmlHistoryView* > TViews;
|
||||
TViews m_Views;
|
||||
|
||||
typedef std::list< const SXmlHistoryGroup* > TXmlHistotyGroupPtrList;
|
||||
// history
|
||||
struct SHistoryInfo
|
||||
{
|
||||
SHistoryInfo()
|
||||
: IsNullUndo(false)
|
||||
, CurrGroup(nullptr)
|
||||
, HistoryInvalidated(false) {}
|
||||
|
||||
const SXmlHistoryGroup* CurrGroup;
|
||||
TGroupIndexMap CurrUserIndex;
|
||||
string HistoryDescription;
|
||||
bool IsNullUndo;
|
||||
bool HistoryInvalidated;
|
||||
TXmlHistotyGroupPtrList ActiveGroups;
|
||||
};
|
||||
typedef std::map< int, SHistoryInfo > THistoryInfoMap;
|
||||
THistoryInfoMap m_HistoryInfoMap;
|
||||
|
||||
// undo event handler
|
||||
typedef std::map< int, SXmlHistory* > THistoryVersionMap;
|
||||
struct SUndoEventHandlerData
|
||||
{
|
||||
SUndoEventHandlerData()
|
||||
: CurrentData(nullptr) {}
|
||||
|
||||
SXmlHistory* CurrentData;
|
||||
THistoryVersionMap HistoryData;
|
||||
};
|
||||
typedef std::map< IXmlUndoEventHandler*, SUndoEventHandlerData > TUndoEventHandlerMap;
|
||||
TUndoEventHandlerMap m_UndoEventHandlerMap;
|
||||
|
||||
typedef std::map< IXmlUndoEventHandler*, IXmlHistoryView* > TUndoHandlerViewMap;
|
||||
TUndoHandlerViewMap m_UndoHandlerViewMap;
|
||||
|
||||
typedef std::map< uint32, IXmlUndoEventHandler* > TInvalidUndoEventListener;
|
||||
TInvalidUndoEventListener m_InvalidHandlerMap;
|
||||
|
||||
private:
|
||||
friend struct SXmlHistory;
|
||||
friend struct SXmlHistoryGroup;
|
||||
|
||||
int IncrementVersion(SXmlHistory* pXmlHistry);
|
||||
int IncrementVersion();
|
||||
SXmlHistory* CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion);
|
||||
void DeleteXmlHistory(const SXmlHistory* pXmlHistry);
|
||||
|
||||
void RegisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler, SXmlHistory* pXmlData);
|
||||
void UnregisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler);
|
||||
typedef std::list< IXmlUndoEventHandler* > TEventHandlerList;
|
||||
void RecordNullUndo(const TEventHandlerList& eventHandler, const char* desc, bool isNull = true);
|
||||
void ReloadCurrentVersion(const SXmlHistoryGroup* pPrevGroup, int prevVersion);
|
||||
SXmlHistory* GetLatestHistory(SUndoEventHandlerData& eventHandlerData);
|
||||
void NotifyUndoEventListener(IXmlHistoryEventListener::EHistoryEventType event, void* pData = nullptr);
|
||||
|
||||
void SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const char* displayName = nullptr, bool bRecordNullUndo = false, const TGroupIndexMap& groupIndex = TGroupIndexMap());
|
||||
void UnloadInt();
|
||||
void ClearRedo();
|
||||
|
||||
void RecordUndoInternal(const char* desc);
|
||||
void RemoveListFromList(TXmlHistotyGroupPtrList& list, const TXmlHistotyGroupPtrList& removeList);
|
||||
|
||||
bool IsEventHandlerValid(IXmlUndoEventHandler* pEventHandler);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H
|
||||
Reference in New Issue
Block a user