Merge branch 'development' of https://github.com/o3de/o3de into jckand/EditorPrefabTests
Signed-off-by: jckand-amzn <82226555+jckand-amzn@users.noreply.github.com>
This commit is contained in:
+7
-1
@@ -97,7 +97,13 @@ def AssetBrowser_SearchFiltering():
|
||||
# 3) Type the name of an asset in the search bar and make sure it is filtered to and selectable
|
||||
asset_browser = editor_window.findChild(QtWidgets.QDockWidget, "Asset Browser")
|
||||
search_bar = asset_browser.findChild(QtWidgets.QLineEdit, "textSearch")
|
||||
search_bar.setText("cedar.fbx")
|
||||
|
||||
# Add a small pause when typing in the search bar in order to check that the entries are updated properly
|
||||
search_bar.setText("Cedar.f")
|
||||
general.idle_wait(0.5)
|
||||
search_bar.setText("Cedar.fbx")
|
||||
general.idle_wait(0.5)
|
||||
|
||||
asset_browser_tree = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTreeViewWidget")
|
||||
asset_browser_table = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTableViewWidget")
|
||||
found = await pyside_utils.wait_for_condition(lambda: pyside_utils.find_child_by_pattern(asset_browser_table, "cedar.fbx"), 5.0)
|
||||
|
||||
@@ -1,232 +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 "BaseLibrary.h"
|
||||
#include "BaseLibraryItem.h"
|
||||
#include "Include/IBaseLibraryManager.h"
|
||||
#include <Util/PathUtil.h>
|
||||
#include <IFileUtil.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CBaseLibrary implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseLibrary::CBaseLibrary(IBaseLibraryManager* pManager)
|
||||
: m_pManager(pManager)
|
||||
, m_bModified(false)
|
||||
, m_bLevelLib(false)
|
||||
, m_bNewLibrary(true)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseLibrary::~CBaseLibrary()
|
||||
{
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IBaseLibraryManager* CBaseLibrary::GetManager()
|
||||
{
|
||||
return m_pManager;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibrary::RemoveAllItems()
|
||||
{
|
||||
AddRef();
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
// Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call.
|
||||
m_pManager->UnregisterItem(m_items[i]);
|
||||
// Clear library item.
|
||||
m_items[i]->m_library = nullptr;
|
||||
}
|
||||
m_items.clear();
|
||||
Release();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibrary::SetName(const QString& name)
|
||||
{
|
||||
//the fullname of the items in the library will be changed due to library's name change
|
||||
//so we need unregistered them and register them after their name changed.
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
m_pManager->UnregisterItem(m_items[i]);
|
||||
}
|
||||
|
||||
m_name = name;
|
||||
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
m_pManager->RegisterItem(m_items[i]);
|
||||
}
|
||||
|
||||
SetModified();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const QString& CBaseLibrary::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CBaseLibrary::Save()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CBaseLibrary::Load(const QString& filename)
|
||||
{
|
||||
m_filename = filename;
|
||||
SetModified(false);
|
||||
m_bNewLibrary = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibrary::SetModified(bool bModified)
|
||||
{
|
||||
if (bModified != m_bModified)
|
||||
{
|
||||
m_bModified = bModified;
|
||||
emit Modified(bModified);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibrary::AddItem(IDataBaseItem* item, bool bRegister)
|
||||
{
|
||||
|
||||
CBaseLibraryItem* pLibItem = (CBaseLibraryItem*)item;
|
||||
// Check if item is already assigned to this library.
|
||||
if (pLibItem->m_library != this)
|
||||
{
|
||||
pLibItem->m_library = this;
|
||||
m_items.push_back(pLibItem);
|
||||
SetModified();
|
||||
if (bRegister)
|
||||
{
|
||||
m_pManager->RegisterItem(pLibItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibrary::GetItem(int index)
|
||||
{
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return m_items[index];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibrary::RemoveItem(IDataBaseItem* item)
|
||||
{
|
||||
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (m_items[i] == item)
|
||||
{
|
||||
// Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call.
|
||||
m_pManager->UnregisterItem(m_items[i]);
|
||||
m_items.erase(m_items.begin() + i);
|
||||
SetModified();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibrary::FindItem(const QString& name)
|
||||
{
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (QString::compare(m_items[i]->GetName(), name, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return m_items[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const
|
||||
{
|
||||
IEditor* pEditor = GetIEditor();
|
||||
IFileUtil* pFileUtil = pEditor ? pEditor->GetFileUtil() : nullptr;
|
||||
if (pFileUtil)
|
||||
{
|
||||
return pFileUtil->CheckoutFile(fullPathName.toUtf8().data(), nullptr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary)
|
||||
{
|
||||
assert(name != nullptr);
|
||||
if (name == nullptr)
|
||||
{
|
||||
CryFatalError("The library you are attempting to save has no name specified.");
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fileName(GetFilename());
|
||||
if (fileName.isEmpty() && !saveEmptyLibrary)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fileName = Path::GamePathToFullPath(fileName);
|
||||
|
||||
XmlNodeRef root = GetIEditor()->GetSystem()->CreateXmlNode(name);
|
||||
Serialize(root, false);
|
||||
bool bRes = XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), root, fileName.toUtf8().data());
|
||||
if (m_bNewLibrary)
|
||||
{
|
||||
AddLibraryToSourceControl(fileName);
|
||||
m_bNewLibrary = false;
|
||||
}
|
||||
if (!bRes)
|
||||
{
|
||||
QByteArray filenameUtf8 = fileName.toUtf8();
|
||||
AZStd::string strMessage = AZStd::string::format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data());
|
||||
CryMessageBox(strMessage.c_str(), "Saving Error", MB_OK | MB_ICONWARNING);
|
||||
}
|
||||
return bRes;
|
||||
}
|
||||
|
||||
//CONFETTI BEGIN
|
||||
void CBaseLibrary::ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation)
|
||||
{
|
||||
std::vector<_smart_ptr<CBaseLibraryItem> > temp;
|
||||
for (unsigned int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (i == newLocation)
|
||||
{
|
||||
temp.push_back(_smart_ptr<CBaseLibraryItem>(item));
|
||||
}
|
||||
if (m_items[i] != item)
|
||||
{
|
||||
temp.push_back(m_items[i]);
|
||||
}
|
||||
}
|
||||
// If newLocation is greater than the original size, append the item to end of the list
|
||||
if (newLocation >= m_items.size())
|
||||
{
|
||||
temp.push_back(_smart_ptr<CBaseLibraryItem>(item));
|
||||
}
|
||||
m_items = temp;
|
||||
}
|
||||
//CONFETTI END
|
||||
|
||||
#include <moc_BaseLibrary.cpp>
|
||||
@@ -1,129 +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_BASELIBRARY_H
|
||||
#define CRYINCLUDE_EDITOR_BASELIBRARY_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Include/IDataBaseLibrary.h"
|
||||
#include "Include/IBaseLibraryManager.h"
|
||||
#include "Include/EditorCoreAPI.h"
|
||||
#include "Util/TRefCountBase.h"
|
||||
|
||||
#include <QObject>
|
||||
#endif
|
||||
|
||||
// Ensure we don't try to dllimport when moc includes us
|
||||
#if defined(Q_MOC_BUILD) && !defined(EDITOR_CORE)
|
||||
#define EDITOR_CORE
|
||||
#endif
|
||||
|
||||
/** This a base class for all Libraries used by Editor.
|
||||
*/
|
||||
class EDITOR_CORE_API CBaseLibrary
|
||||
: public QObject
|
||||
, public TRefCountBase<IDataBaseLibrary>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CBaseLibrary(IBaseLibraryManager* pManager);
|
||||
~CBaseLibrary();
|
||||
|
||||
//! Set library name.
|
||||
virtual void SetName(const QString& name);
|
||||
//! Get library name.
|
||||
const QString& GetName() const override;
|
||||
|
||||
//! Set new filename for this library.
|
||||
virtual bool SetFilename(const QString& filename, [[maybe_unused]] bool checkForUnique = true) { m_filename = filename.toLower(); return true; };
|
||||
const QString& GetFilename() const override { return m_filename; };
|
||||
|
||||
bool Save() override = 0;
|
||||
bool Load(const QString& filename) override = 0;
|
||||
void Serialize(XmlNodeRef& node, bool bLoading) override = 0;
|
||||
|
||||
//! Mark library as modified.
|
||||
void SetModified(bool bModified = true) override;
|
||||
//! Check if library was modified.
|
||||
bool IsModified() const override { return m_bModified; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Working with items.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Add a new prototype to library.
|
||||
void AddItem(IDataBaseItem* item, bool bRegister = true) override;
|
||||
//! Get number of known prototypes.
|
||||
int GetItemCount() const override { return static_cast<int>(m_items.size()); }
|
||||
//! Get prototype by index.
|
||||
IDataBaseItem* GetItem(int index) override;
|
||||
|
||||
//! Delete item by pointer of item.
|
||||
void RemoveItem(IDataBaseItem* item) override;
|
||||
|
||||
//! Delete all items from library.
|
||||
void RemoveAllItems() override;
|
||||
|
||||
//! Find library item by name.
|
||||
//! Using linear search.
|
||||
IDataBaseItem* FindItem(const QString& name) override;
|
||||
|
||||
//! Check if this library is local level library.
|
||||
bool IsLevelLibrary() const override { return m_bLevelLib; };
|
||||
|
||||
//! Set library to be level library.
|
||||
void SetLevelLibrary(bool bEnable) override { m_bLevelLib = bEnable; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Return manager for this library.
|
||||
IBaseLibraryManager* GetManager() override;
|
||||
|
||||
// Saves the library with the main tag defined by the parameter name
|
||||
bool SaveLibrary(const char* name, bool saveEmptyLibrary = false);
|
||||
|
||||
//CONFETTI BEGIN
|
||||
// Used to change the library item order
|
||||
void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) override;
|
||||
//CONFETTI END
|
||||
|
||||
signals:
|
||||
void Modified(bool bModified);
|
||||
|
||||
private:
|
||||
// Add the library to the source control
|
||||
bool AddLibraryToSourceControl(const QString& fullPathName) const;
|
||||
|
||||
protected:
|
||||
|
||||
//! Name of the library.
|
||||
QString m_name;
|
||||
//! Filename of the library.
|
||||
QString m_filename;
|
||||
|
||||
//! Flag set when library was modified.
|
||||
bool m_bModified;
|
||||
|
||||
// Flag set when the library is just created and it's not yet saved for the first time.
|
||||
bool m_bNewLibrary;
|
||||
|
||||
//! Level library is saved within the level .ly file and is local for this level.
|
||||
bool m_bLevelLib;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Manager.
|
||||
IBaseLibraryManager* m_pManager;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
// Array of all our library items.
|
||||
std::vector<_smart_ptr<CBaseLibraryItem> > m_items;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_BASELIBRARY_H
|
||||
@@ -1,261 +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 "BaseLibraryItem.h"
|
||||
#include "BaseLibrary.h"
|
||||
#include "BaseLibraryManager.h"
|
||||
#include "Undo/IUndoObject.h"
|
||||
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
|
||||
//undo object for multi-changes inside library item. such as set all variables to default values.
|
||||
//For example: change particle emitter shape will lead to multiple variable changes
|
||||
class CUndoBaseLibraryItem
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
CUndoBaseLibraryItem(IBaseLibraryManager *libMgr, CBaseLibraryItem* libItem, bool ignoreChild)
|
||||
: m_libMgr(libMgr)
|
||||
{
|
||||
assert(libItem);
|
||||
assert(libMgr);
|
||||
|
||||
m_itemPath = libItem->GetFullName();
|
||||
|
||||
//serialize the lib item to undo
|
||||
m_undoCtx.node = GetIEditor()->GetSystem()->CreateXmlNode("Undo");
|
||||
m_undoCtx.bIgnoreChilds = ignoreChild;
|
||||
m_undoCtx.bLoading = false; //saving
|
||||
m_undoCtx.bUniqName = false; //don't generate new name
|
||||
m_undoCtx.bCopyPaste = true; //so it won't override guid
|
||||
m_undoCtx.bUndo = true;
|
||||
libItem->Serialize(m_undoCtx);
|
||||
|
||||
//evaluate size
|
||||
XmlString xmlStr = m_undoCtx.node->getXML();
|
||||
m_size = sizeof(CUndoBaseLibraryItem);
|
||||
m_size += static_cast<int>(xmlStr.GetAllocatedMemory());
|
||||
m_size += m_itemPath.length();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
int GetSize() override
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void Undo(bool bUndo) override
|
||||
{
|
||||
//find the libItem
|
||||
IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath);
|
||||
if (libItem == nullptr)
|
||||
{
|
||||
//the undo stack is not reliable any more..
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//save for redo
|
||||
if (bUndo)
|
||||
{
|
||||
m_redoCtx.node = GetIEditor()->GetSystem()->CreateXmlNode("Redo");
|
||||
m_redoCtx.bIgnoreChilds = m_undoCtx.bIgnoreChilds;
|
||||
m_redoCtx.bLoading = false; //saving
|
||||
m_redoCtx.bUniqName = false;
|
||||
m_redoCtx.bCopyPaste = true;
|
||||
m_redoCtx.bUndo = true;
|
||||
libItem->Serialize(m_redoCtx);
|
||||
|
||||
XmlString xmlStr = m_redoCtx.node->getXML();
|
||||
m_size += static_cast<int>(xmlStr.GetAllocatedMemory());
|
||||
}
|
||||
|
||||
//load previous saved data
|
||||
m_undoCtx.bLoading = true;
|
||||
libItem->Serialize(m_undoCtx);
|
||||
}
|
||||
|
||||
void Redo() override
|
||||
{
|
||||
//find the libItem
|
||||
IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath);
|
||||
if (libItem == nullptr || m_redoCtx.node == nullptr)
|
||||
{
|
||||
//the undo stack is not reliable any more..
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_redoCtx.bLoading = true;
|
||||
libItem->Serialize(m_redoCtx);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_itemPath;
|
||||
IDataBaseItem::SerializeContext m_undoCtx; //saved before operation
|
||||
IDataBaseItem::SerializeContext m_redoCtx; //saved after operation so used for redo
|
||||
IBaseLibraryManager* m_libMgr;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CBaseLibraryItem implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseLibraryItem::CBaseLibraryItem()
|
||||
{
|
||||
m_library = nullptr;
|
||||
GenerateId();
|
||||
m_bModified = false;
|
||||
}
|
||||
|
||||
CBaseLibraryItem::~CBaseLibraryItem()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryItem::GetFullName() const
|
||||
{
|
||||
QString name;
|
||||
if (m_library)
|
||||
{
|
||||
name = m_library->GetName() + ".";
|
||||
}
|
||||
name += m_name;
|
||||
return name;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryItem::GetGroupName()
|
||||
{
|
||||
QString str = GetName();
|
||||
int p = str.lastIndexOf('.');
|
||||
if (p >= 0)
|
||||
{
|
||||
return str.mid(0, p);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryItem::GetShortName()
|
||||
{
|
||||
QString str = GetName();
|
||||
int p = str.lastIndexOf('.');
|
||||
if (p >= 0)
|
||||
{
|
||||
return str.mid(p + 1);
|
||||
}
|
||||
p = str.lastIndexOf('/');
|
||||
if (p >= 0)
|
||||
{
|
||||
return str.mid(p + 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryItem::SetName(const QString& name)
|
||||
{
|
||||
assert(m_library);
|
||||
if (name == m_name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString oldName = GetFullName();
|
||||
m_name = name;
|
||||
((CBaseLibraryManager*)m_library->GetManager())->OnRenameItem(this, oldName);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const QString& CBaseLibraryItem::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryItem::GenerateId()
|
||||
{
|
||||
GUID guid = AZ::Uuid::CreateRandom();
|
||||
SetGUID(guid);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryItem::SetGUID(REFGUID guid)
|
||||
{
|
||||
if (m_library)
|
||||
{
|
||||
((CBaseLibraryManager*)m_library->GetManager())->RegisterItem(this, guid);
|
||||
}
|
||||
m_guid = guid;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryItem::Serialize(SerializeContext& ctx)
|
||||
{
|
||||
assert(m_library);
|
||||
|
||||
XmlNodeRef node = ctx.node;
|
||||
if (ctx.bLoading)
|
||||
{
|
||||
QString name = m_name;
|
||||
// Loading
|
||||
node->getAttr("Name", name);
|
||||
|
||||
if (!ctx.bUniqName)
|
||||
{
|
||||
SetName(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetName(GetLibrary()->GetManager()->MakeUniqueItemName(name));
|
||||
}
|
||||
|
||||
if (!ctx.bCopyPaste)
|
||||
{
|
||||
GUID guid;
|
||||
if (node->getAttr("Id", guid))
|
||||
{
|
||||
SetGUID(guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
node->setAttr("Name", m_name.toUtf8().data());
|
||||
node->setAttr("Id", m_guid);
|
||||
node->setAttr("Library", GetLibrary()->GetName().toUtf8().data());
|
||||
}
|
||||
m_bModified = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryItem::GetLibrary() const
|
||||
{
|
||||
return m_library;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryItem::SetLibrary(CBaseLibrary* pLibrary)
|
||||
{
|
||||
m_library = pLibrary;
|
||||
}
|
||||
|
||||
//! Mark library as modified.
|
||||
void CBaseLibraryItem::SetModified(bool bModified)
|
||||
{
|
||||
m_bModified = bModified;
|
||||
if (m_bModified && m_library != nullptr)
|
||||
{
|
||||
m_library->SetModified(bModified);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +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_BASELIBRARYITEM_H
|
||||
#define CRYINCLUDE_EDITOR_BASELIBRARYITEM_H
|
||||
#pragma once
|
||||
|
||||
#include "Include/IDataBaseItem.h"
|
||||
#include "BaseLibrary.h"
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
class CBaseLibrary;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
/** Base class for all items contained in BaseLibraray.
|
||||
*/
|
||||
class EDITOR_CORE_API CBaseLibraryItem
|
||||
: public TRefCountBase<IDataBaseItem>
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
CBaseLibraryItem();
|
||||
~CBaseLibraryItem();
|
||||
|
||||
//! Set item name.
|
||||
//! Its virtual, in case you want to override it in derrived item.
|
||||
virtual void SetName(const QString& name);
|
||||
//! Get item name.
|
||||
const QString& GetName() const;
|
||||
|
||||
//! Get full item name, including name of library.
|
||||
//! Name formed by adding dot after name of library
|
||||
//! eg. library Pickup and item PickupRL form full item name: "Pickups.PickupRL".
|
||||
QString GetFullName() const;
|
||||
|
||||
//! Get only nameof group from prototype.
|
||||
QString GetGroupName();
|
||||
//! Get short name of prototype without group.
|
||||
QString GetShortName();
|
||||
|
||||
//! Return Library this item are contained in.
|
||||
//! Item can only be at one library.
|
||||
IDataBaseLibrary* GetLibrary() const;
|
||||
void SetLibrary(CBaseLibrary* pLibrary);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Serialize library item to archive.
|
||||
virtual void Serialize(SerializeContext& ctx);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Generate new unique id for this item.
|
||||
void GenerateId();
|
||||
//! Returns GUID of this material.
|
||||
const GUID& GetGUID() const { return m_guid; }
|
||||
|
||||
//! Mark library as modified.
|
||||
void SetModified(bool bModified = true);
|
||||
//! Check if library was modified.
|
||||
bool IsModified() const { return m_bModified; };
|
||||
|
||||
//! Returns true if the item is registered, otherwise false
|
||||
bool IsRegistered() const { return m_bRegistered; };
|
||||
|
||||
//! Validate item for errors.
|
||||
virtual void Validate() {};
|
||||
|
||||
//! Get number of sub childs.
|
||||
virtual int GetChildCount() const { return 0; }
|
||||
//! Get sub child by index.
|
||||
virtual CBaseLibraryItem* GetChild([[maybe_unused]] int index) const { return nullptr; }
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Gathers resources by this item.
|
||||
virtual void GatherUsedResources([[maybe_unused]] CUsedResources& resources) {};
|
||||
|
||||
//! Get if stored item is enabled
|
||||
virtual bool GetIsEnabled() { return true; };
|
||||
|
||||
|
||||
int IsParticleItem = -1;
|
||||
protected:
|
||||
void SetGUID(REFGUID guid);
|
||||
friend class CBaseLibrary;
|
||||
friend class CBaseLibraryManager;
|
||||
// Name of this prototype.
|
||||
QString m_name;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
//! Reference to prototype library who contains this prototype.
|
||||
_smart_ptr<CBaseLibrary> m_library;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
//! Every base library item have unique id.
|
||||
GUID m_guid;
|
||||
// True when item modified by editor.
|
||||
bool m_bModified;
|
||||
// True when item registered in manager.
|
||||
bool m_bRegistered = false;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CBaseLibraryItem*);
|
||||
|
||||
TYPEDEF_AUTOPTR(CBaseLibraryItem);
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_BASELIBRARYITEM_H
|
||||
@@ -1,822 +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 "BaseLibraryManager.h"
|
||||
|
||||
// Editor
|
||||
#include "BaseLibraryItem.h"
|
||||
#include "ErrorReport.h"
|
||||
#include "Undo/IUndoObject.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CBaseLibraryManager implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseLibraryManager::CBaseLibraryManager()
|
||||
{
|
||||
m_bUniqNameMap = false;
|
||||
m_bUniqGuidMap = true;
|
||||
GetIEditor()->RegisterNotifyListener(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseLibraryManager::~CBaseLibraryManager()
|
||||
{
|
||||
ClearAll();
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::ClearAll()
|
||||
{
|
||||
// Delete all items from all libraries.
|
||||
for (int i = 0; i < m_libs.size(); i++)
|
||||
{
|
||||
m_libs[i]->RemoveAllItems();
|
||||
}
|
||||
|
||||
// if we will not copy maps locally then destructors of the elements of
|
||||
// the map will operate on the already invalid map object
|
||||
// see:
|
||||
// CBaseLibraryManager::UnregisterItem()
|
||||
// CBaseLibraryManager::DeleteItem()
|
||||
// CMaterial::~CMaterial()
|
||||
|
||||
ItemsGUIDMap itemsGuidMap;
|
||||
ItemsNameMap itemsNameMap;
|
||||
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_itemsNameMapMutex);
|
||||
std::swap(itemsGuidMap, m_itemsGuidMap);
|
||||
std::swap(itemsNameMap, m_itemsNameMap);
|
||||
|
||||
m_libs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryManager::FindLibrary(const QString& library)
|
||||
{
|
||||
const int index = FindLibraryIndex(library);
|
||||
return index == -1 ? nullptr : m_libs[index];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CBaseLibraryManager::FindLibraryIndex(const QString& library)
|
||||
{
|
||||
QString lib = library;
|
||||
lib.replace('\\', '/');
|
||||
for (int i = 0; i < m_libs.size(); i++)
|
||||
{
|
||||
QString _lib = m_libs[i]->GetFilename();
|
||||
_lib.replace('\\', '/');
|
||||
if (QString::compare(lib, m_libs[i]->GetName(), Qt::CaseInsensitive) == 0 || QString::compare(lib, _lib, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::FindItem(REFGUID guid) const
|
||||
{
|
||||
CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, nullptr);
|
||||
return pMtl;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::SplitFullItemName(const QString& fullItemName, QString& libraryName, QString& itemName)
|
||||
{
|
||||
int p;
|
||||
p = fullItemName.indexOf('.');
|
||||
if (p < 0 || !QString::compare(fullItemName.mid(p + 1), "mtl", Qt::CaseInsensitive))
|
||||
{
|
||||
libraryName = "";
|
||||
itemName = fullItemName;
|
||||
return;
|
||||
}
|
||||
libraryName = fullItemName.mid(0, p);
|
||||
itemName = fullItemName.mid(p + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::FindItemByName(const QString& fullItemName)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_itemsNameMapMutex);
|
||||
return stl::find_in_map(m_itemsNameMap, fullItemName, nullptr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::LoadItemByName(const QString& fullItemName)
|
||||
{
|
||||
QString libraryName, itemName;
|
||||
SplitFullItemName(fullItemName, libraryName, itemName);
|
||||
|
||||
if (!FindLibrary(libraryName))
|
||||
{
|
||||
LoadLibrary(MakeFilename(libraryName));
|
||||
}
|
||||
|
||||
return FindItemByName(fullItemName);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::FindItemByName(const char* fullItemName)
|
||||
{
|
||||
return FindItemByName(QString(fullItemName));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::LoadItemByName(const char* fullItemName)
|
||||
{
|
||||
return LoadItemByName(QString(fullItemName));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::CreateItem(IDataBaseLibrary* pLibrary)
|
||||
{
|
||||
assert(pLibrary);
|
||||
|
||||
// Add item to this library.
|
||||
TSmartPtr<CBaseLibraryItem> pItem = MakeNewItem();
|
||||
pLibrary->AddItem(pItem);
|
||||
return pItem;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::DeleteItem(IDataBaseItem* pItem)
|
||||
{
|
||||
assert(pItem);
|
||||
|
||||
UnregisterItem((CBaseLibraryItem*)pItem);
|
||||
if (pItem->GetLibrary())
|
||||
{
|
||||
pItem->GetLibrary()->RemoveItem(pItem);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryManager::LoadLibrary(const QString& inFilename, [[maybe_unused]] bool bReload)
|
||||
{
|
||||
if (auto lib = FindLibrary(inFilename))
|
||||
{
|
||||
return lib;
|
||||
}
|
||||
|
||||
TSmartPtr<CBaseLibrary> pLib = MakeNewLibrary();
|
||||
if (!pLib->Load(MakeFilename(inFilename)))
|
||||
{
|
||||
Error(QObject::tr("Failed to Load Item Library: %1").arg(inFilename).toUtf8().data());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_libs.push_back(pLib);
|
||||
return pLib;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CBaseLibraryManager::GetModifiedLibraryCount() const
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < m_libs.size(); i++)
|
||||
{
|
||||
if (m_libs[i]->IsModified())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryManager::AddLibrary(const QString& library, bool bIsLevelLibrary, bool bIsLoading)
|
||||
{
|
||||
// Make a filename from name of library.
|
||||
QString filename = library;
|
||||
|
||||
if (filename.indexOf(".xml") == -1) // if its already a filename, we don't do anything
|
||||
{
|
||||
filename.replace(' ', '_');
|
||||
if (!bIsLevelLibrary)
|
||||
{
|
||||
filename = MakeFilename(library);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if its the level library it gets saved in the level and should not be concatenated with any other file name
|
||||
filename = filename + ".xml";
|
||||
}
|
||||
}
|
||||
|
||||
IDataBaseLibrary* pBaseLib = FindLibrary(library); //library name
|
||||
if (!pBaseLib)
|
||||
{
|
||||
pBaseLib = FindLibrary(filename); //library file name
|
||||
}
|
||||
if (pBaseLib)
|
||||
{
|
||||
return pBaseLib;
|
||||
}
|
||||
|
||||
CBaseLibrary* lib = MakeNewLibrary();
|
||||
lib->SetName(library);
|
||||
lib->SetLevelLibrary(bIsLevelLibrary);
|
||||
lib->SetFilename(filename, !bIsLoading);
|
||||
// set modified to true, so even empty particle libraries get saved
|
||||
lib->SetModified(true);
|
||||
|
||||
m_libs.push_back(lib);
|
||||
return lib;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryManager::MakeFilename(const QString& library)
|
||||
{
|
||||
QString filename = library;
|
||||
filename.replace(' ', '_');
|
||||
filename.replace(".xml", "");
|
||||
|
||||
// make it contain the canonical libs path:
|
||||
Path::ConvertBackSlashToSlash(filename);
|
||||
|
||||
QString LibsPath(GetLibsPath());
|
||||
Path::ConvertBackSlashToSlash(LibsPath);
|
||||
|
||||
if (filename.left(LibsPath.length()).compare(LibsPath, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
filename = filename.mid(LibsPath.length());
|
||||
}
|
||||
|
||||
return LibsPath + filename + ".xml";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CBaseLibraryManager::IsUniqueFilename(const QString& library)
|
||||
{
|
||||
QString resultPath = MakeFilename(library);
|
||||
CCryFile xmlFile;
|
||||
// If we can find a file for the path
|
||||
return !xmlFile.Open(resultPath.toUtf8().data(), "rb");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::DeleteLibrary(const QString& library, bool forceDeleteLevel)
|
||||
{
|
||||
for (int i = 0; i < m_libs.size(); i++)
|
||||
{
|
||||
if (QString::compare(library, m_libs[i]->GetName(), Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
CBaseLibrary* pLibrary = m_libs[i];
|
||||
// Check if not level library, they cannot be deleted.
|
||||
if (!pLibrary->IsLevelLibrary() || forceDeleteLevel)
|
||||
{
|
||||
for (int j = 0; j < pLibrary->GetItemCount(); j++)
|
||||
{
|
||||
UnregisterItem((CBaseLibraryItem*)pLibrary->GetItem(j));
|
||||
}
|
||||
pLibrary->RemoveAllItems();
|
||||
|
||||
if (pLibrary->IsLevelLibrary())
|
||||
{
|
||||
m_pLevelLibrary = nullptr;
|
||||
}
|
||||
m_libs.erase(m_libs.begin() + i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryManager::GetLibrary(int index) const
|
||||
{
|
||||
assert(index >= 0 && index < m_libs.size());
|
||||
return m_libs[index];
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseLibrary* CBaseLibraryManager::GetLevelLibrary() const
|
||||
{
|
||||
IDataBaseLibrary* pLevelLib = nullptr;
|
||||
|
||||
for (int i = 0; i < GetLibraryCount(); i++)
|
||||
{
|
||||
if (GetLibrary(i)->IsLevelLibrary())
|
||||
{
|
||||
pLevelLib = GetLibrary(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return pLevelLib;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::SaveAllLibs()
|
||||
{
|
||||
for (int i = 0; i < GetLibraryCount(); i++)
|
||||
{
|
||||
// Check if library is modified.
|
||||
IDataBaseLibrary* pLibrary = GetLibrary(i);
|
||||
|
||||
//Level library is saved when the level is saved
|
||||
if (pLibrary->IsLevelLibrary())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pLibrary->IsModified())
|
||||
{
|
||||
if (pLibrary->Save())
|
||||
{
|
||||
pLibrary->SetModified(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::Serialize(XmlNodeRef& node, bool bLoading)
|
||||
{
|
||||
static const char* const LEVEL_LIBRARY_TAG = "LevelLibrary";
|
||||
|
||||
QString rootNodeName = GetRootNodeName();
|
||||
if (bLoading)
|
||||
{
|
||||
XmlNodeRef libs = node->findChild(rootNodeName.toUtf8().data());
|
||||
if (libs)
|
||||
{
|
||||
for (int i = 0; i < libs->getChildCount(); i++)
|
||||
{
|
||||
// Load only library name.
|
||||
XmlNodeRef libNode = libs->getChild(i);
|
||||
if (strcmp(libNode->getTag(), LEVEL_LIBRARY_TAG) == 0)
|
||||
{
|
||||
if (!m_pLevelLibrary)
|
||||
{
|
||||
QString libName;
|
||||
libNode->getAttr("Name", libName);
|
||||
m_pLevelLibrary = static_cast<CBaseLibrary*>(AddLibrary(libName, true));
|
||||
}
|
||||
m_pLevelLibrary->Serialize(libNode, bLoading);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString libName;
|
||||
if (libNode->getAttr("Name", libName))
|
||||
{
|
||||
// Load this library.
|
||||
if (!FindLibrary(libName))
|
||||
{
|
||||
LoadLibrary(MakeFilename(libName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save all libraries.
|
||||
XmlNodeRef libs = node->newChild(rootNodeName.toUtf8().data());
|
||||
for (int i = 0; i < GetLibraryCount(); i++)
|
||||
{
|
||||
IDataBaseLibrary* pLib = GetLibrary(i);
|
||||
if (pLib->IsLevelLibrary())
|
||||
{
|
||||
// Level libraries are saved in in level.
|
||||
XmlNodeRef libNode = libs->newChild(LEVEL_LIBRARY_TAG);
|
||||
pLib->Serialize(libNode, bLoading);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save only library name.
|
||||
XmlNodeRef libNode = libs->newChild("Library");
|
||||
libNode->setAttr("Name", pLib->GetName().toUtf8().data());
|
||||
}
|
||||
}
|
||||
SaveAllLibs();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QString& libName)
|
||||
{
|
||||
// unlikely we'll ever encounter more than 16
|
||||
std::vector<AZStd::string> possibleDuplicates;
|
||||
possibleDuplicates.reserve(16);
|
||||
|
||||
// search for strings in the database that might have a similar name (ignore case)
|
||||
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
|
||||
for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
|
||||
{
|
||||
//Check if the item is in the target library first.
|
||||
IDataBaseLibrary* itemLibrary = pItem->GetLibrary();
|
||||
QString itemLibraryName;
|
||||
if (itemLibrary)
|
||||
{
|
||||
itemLibraryName = itemLibrary->GetName();
|
||||
}
|
||||
|
||||
// Item is not in the library so there cannot be a naming conflict.
|
||||
if (!libName.isEmpty() && !itemLibraryName.isEmpty() && itemLibraryName != libName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString& name = pItem->GetName();
|
||||
if (name.startsWith(srcName, Qt::CaseInsensitive))
|
||||
{
|
||||
possibleDuplicates.push_back(AZStd::string(name.toUtf8().data()));
|
||||
}
|
||||
}
|
||||
pEnum->Release();
|
||||
|
||||
if (possibleDuplicates.empty())
|
||||
{
|
||||
return srcName;
|
||||
}
|
||||
|
||||
std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const AZStd::string& strOne, const AZStd::string& strTwo)
|
||||
{
|
||||
// I can assume size sorting since if the length is different, either one of the two strings doesn't
|
||||
// closely match the string we are trying to duplicate, or it's a bigger number (X1 vs X10)
|
||||
if (strOne.size() != strTwo.size())
|
||||
{
|
||||
return strOne.size() < strTwo.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return azstricmp(strOne.c_str(), strTwo.c_str()) < 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
int num = 0;
|
||||
QString returnValue = srcName;
|
||||
while (num < possibleDuplicates.size() && QString::compare(possibleDuplicates[num].c_str(), returnValue, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
returnValue = QStringLiteral("%1%2%3").arg(srcName).arg("_").arg(num);
|
||||
++num;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::Validate()
|
||||
{
|
||||
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
|
||||
for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
|
||||
{
|
||||
pItem->Validate();
|
||||
}
|
||||
pEnum->Release();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid)
|
||||
{
|
||||
assert(pItem);
|
||||
|
||||
bool bNotify = false;
|
||||
|
||||
if (m_bUniqGuidMap)
|
||||
{
|
||||
REFGUID oldGuid = pItem->GetGUID();
|
||||
if (!GuidUtil::IsEmpty(oldGuid))
|
||||
{
|
||||
m_itemsGuidMap.erase(oldGuid);
|
||||
}
|
||||
if (GuidUtil::IsEmpty(newGuid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, nullptr);
|
||||
if (!pOldItem)
|
||||
{
|
||||
pItem->m_guid = newGuid;
|
||||
m_itemsGuidMap[newGuid] = pItem;
|
||||
pItem->m_bRegistered = true;
|
||||
bNotify = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pOldItem != pItem)
|
||||
{
|
||||
ReportDuplicateItem(pItem, pOldItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bUniqNameMap)
|
||||
{
|
||||
QString fullName = pItem->GetFullName();
|
||||
if (!pItem->GetName().isEmpty())
|
||||
{
|
||||
CBaseLibraryItem* pOldItem = static_cast<CBaseLibraryItem*>(FindItemByName(fullName));
|
||||
if (!pOldItem)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_itemsNameMapMutex);
|
||||
m_itemsNameMap[fullName] = pItem;
|
||||
pItem->m_bRegistered = true;
|
||||
bNotify = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pOldItem != pItem)
|
||||
{
|
||||
ReportDuplicateItem(pItem, pOldItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify listeners.
|
||||
if (bNotify)
|
||||
{
|
||||
NotifyItemEvent(pItem, EDB_ITEM_EVENT_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem)
|
||||
{
|
||||
assert(pItem);
|
||||
|
||||
bool bNotify = false;
|
||||
|
||||
if (m_bUniqGuidMap)
|
||||
{
|
||||
if (GuidUtil::IsEmpty(pItem->GetGUID()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), nullptr);
|
||||
if (!pOldItem)
|
||||
{
|
||||
m_itemsGuidMap[pItem->GetGUID()] = pItem;
|
||||
pItem->m_bRegistered = true;
|
||||
bNotify = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pOldItem != pItem)
|
||||
{
|
||||
ReportDuplicateItem(pItem, pOldItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bUniqNameMap)
|
||||
{
|
||||
QString fullName = pItem->GetFullName();
|
||||
if (!fullName.isEmpty())
|
||||
{
|
||||
CBaseLibraryItem* pOldItem = static_cast<CBaseLibraryItem*>(FindItemByName(fullName));
|
||||
if (!pOldItem)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_itemsNameMapMutex);
|
||||
m_itemsNameMap[fullName] = pItem;
|
||||
pItem->m_bRegistered = true;
|
||||
bNotify = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pOldItem != pItem)
|
||||
{
|
||||
ReportDuplicateItem(pItem, pOldItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify listeners.
|
||||
if (bNotify)
|
||||
{
|
||||
NotifyItemEvent(pItem, EDB_ITEM_EVENT_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::SetRegisteredFlag(CBaseLibraryItem* pItem, bool bFlag)
|
||||
{
|
||||
pItem->m_bRegistered = bFlag;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem)
|
||||
{
|
||||
QString sLibName;
|
||||
if (pOldItem->GetLibrary())
|
||||
{
|
||||
sLibName = pOldItem->GetLibrary()->GetName();
|
||||
}
|
||||
CErrorRecord err;
|
||||
err.pItem = pItem;
|
||||
err.error = QStringLiteral("Item %1 with duplicate GUID to loaded item %2 ignored").arg(pItem->GetFullName(), pOldItem->GetFullName());
|
||||
GetIEditor()->GetErrorReport()->ReportError(err);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::UnregisterItem(CBaseLibraryItem* pItem)
|
||||
{
|
||||
// Notify listeners.
|
||||
NotifyItemEvent(pItem, EDB_ITEM_EVENT_DELETE);
|
||||
|
||||
if (!pItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bUniqGuidMap)
|
||||
{
|
||||
m_itemsGuidMap.erase(pItem->GetGUID());
|
||||
}
|
||||
if (m_bUniqNameMap && !pItem->GetFullName().isEmpty())
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_itemsNameMapMutex);
|
||||
auto findIter = m_itemsNameMap.find(pItem->GetFullName());
|
||||
if (findIter != m_itemsNameMap.end())
|
||||
{
|
||||
_smart_ptr<CBaseLibraryItem> item = findIter->second;
|
||||
m_itemsNameMap.erase(findIter);
|
||||
}
|
||||
}
|
||||
|
||||
pItem->m_bRegistered = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString CBaseLibraryManager::MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName)
|
||||
{
|
||||
assert(pLibrary);
|
||||
QString name = pLibrary->GetName() + ".";
|
||||
if (!group.isEmpty())
|
||||
{
|
||||
name += group + ".";
|
||||
}
|
||||
name += itemName;
|
||||
return name;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::GatherUsedResources(CUsedResources& resources)
|
||||
{
|
||||
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
|
||||
for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
|
||||
{
|
||||
pItem->GatherUsedResources(resources);
|
||||
}
|
||||
pEnum->Release();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItemEnumerator* CBaseLibraryManager::GetItemEnumerator()
|
||||
{
|
||||
if (m_bUniqNameMap)
|
||||
{
|
||||
return new CDataBaseItemEnumerator<ItemsNameMap>(&m_itemsNameMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CDataBaseItemEnumerator<ItemsGUIDMap>(&m_itemsGuidMap);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case eNotify_OnBeginNewScene:
|
||||
SetSelectedItem(nullptr);
|
||||
ClearAll();
|
||||
break;
|
||||
case eNotify_OnBeginSceneOpen:
|
||||
SetSelectedItem(nullptr);
|
||||
ClearAll();
|
||||
break;
|
||||
case eNotify_OnCloseScene:
|
||||
SetSelectedItem(nullptr);
|
||||
ClearAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName)
|
||||
{
|
||||
m_itemsNameMapMutex.lock();
|
||||
if (!oldName.isEmpty())
|
||||
{
|
||||
m_itemsNameMap.erase(oldName);
|
||||
}
|
||||
if (!pItem->GetFullName().isEmpty())
|
||||
{
|
||||
m_itemsNameMap[pItem->GetFullName()] = pItem;
|
||||
}
|
||||
m_itemsNameMapMutex.unlock();
|
||||
|
||||
OnItemChanged(pItem);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::AddListener(IDataBaseManagerListener* pListener)
|
||||
{
|
||||
stl::push_back_unique(m_listeners, pListener);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::RemoveListener(IDataBaseManagerListener* pListener)
|
||||
{
|
||||
stl::find_and_erase(m_listeners, pListener);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::NotifyItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event)
|
||||
{
|
||||
// Notify listeners.
|
||||
if (!m_listeners.empty())
|
||||
{
|
||||
for (int i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
m_listeners[i]->OnDataBaseItemEvent(pItem, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::OnItemChanged(IDataBaseItem* pItem)
|
||||
{
|
||||
NotifyItemEvent(pItem, EDB_ITEM_EVENT_CHANGED);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh)
|
||||
{
|
||||
NotifyItemEvent(pItem, bRefresh ? EDB_ITEM_EVENT_UPDATE_PROPERTIES
|
||||
: EDB_ITEM_EVENT_UPDATE_PROPERTIES_NO_EDITOR_REFRESH);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CBaseLibraryManager::SetSelectedItem(IDataBaseItem* pItem)
|
||||
{
|
||||
if (m_pSelectedItem == pItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_pSelectedItem = (CBaseLibraryItem*)pItem;
|
||||
NotifyItemEvent(m_pSelectedItem, EDB_ITEM_EVENT_SELECTED);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::GetSelectedItem() const
|
||||
{
|
||||
return m_pSelectedItem;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IDataBaseItem* CBaseLibraryManager::GetSelectedParentItem() const
|
||||
{
|
||||
return m_pSelectedParent;
|
||||
}
|
||||
|
||||
void CBaseLibraryManager::ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation)
|
||||
{
|
||||
if (!lib || newLocation >= m_libs.size() || lib == m_libs[newLocation])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_libs.size(); i++)
|
||||
{
|
||||
if (lib == m_libs[i])
|
||||
{
|
||||
_smart_ptr<CBaseLibrary> curLib = m_libs[i];
|
||||
m_libs.erase(m_libs.begin() + i);
|
||||
m_libs.insert(m_libs.begin() + newLocation, curLib);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CBaseLibraryManager::SetLibraryName(CBaseLibrary* lib, const QString& name)
|
||||
{
|
||||
// SetFilename will validate if the name is duplicate with exist libraries.
|
||||
if (lib->SetFilename(MakeFilename(name)))
|
||||
{
|
||||
lib->SetName(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,226 +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_BASELIBRARYMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_BASELIBRARYMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "Include/IBaseLibraryManager.h"
|
||||
#include "Include/IDataBaseItem.h"
|
||||
#include "Include/IDataBaseLibrary.h"
|
||||
#include "Include/IDataBaseManager.h"
|
||||
#include "Util/TRefCountBase.h"
|
||||
#include "Util/GuidUtil.h"
|
||||
#include "BaseLibrary.h"
|
||||
#include "Util/smartptr.h"
|
||||
#include <EditorDefs.h>
|
||||
#include <QtUtil.h>
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
/** Manages all Libraries and Items.
|
||||
*/
|
||||
class SANDBOX_API CBaseLibraryManager
|
||||
: public IBaseLibraryManager
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
CBaseLibraryManager();
|
||||
~CBaseLibraryManager();
|
||||
|
||||
//! Clear all libraries.
|
||||
void ClearAll() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IDocListener implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Library items.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Make a new item in specified library.
|
||||
IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) override;
|
||||
//! Delete item from library and manager.
|
||||
void DeleteItem(IDataBaseItem* pItem) override;
|
||||
|
||||
//! Find Item by its GUID.
|
||||
IDataBaseItem* FindItem(REFGUID guid) const override;
|
||||
IDataBaseItem* FindItemByName(const QString& fullItemName) override;
|
||||
IDataBaseItem* LoadItemByName(const QString& fullItemName) override;
|
||||
virtual IDataBaseItem* FindItemByName(const char* fullItemName);
|
||||
virtual IDataBaseItem* LoadItemByName(const char* fullItemName);
|
||||
|
||||
IDataBaseItemEnumerator* GetItemEnumerator() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set item currently selected.
|
||||
void SetSelectedItem(IDataBaseItem* pItem) override;
|
||||
// Get currently selected item.
|
||||
IDataBaseItem* GetSelectedItem() const override;
|
||||
IDataBaseItem* GetSelectedParentItem() const override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Libraries.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Add Item library.
|
||||
IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override;
|
||||
void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override;
|
||||
//! Get number of libraries.
|
||||
int GetLibraryCount() const override { return static_cast<int>(m_libs.size()); };
|
||||
//! Get number of modified libraries.
|
||||
int GetModifiedLibraryCount() const override;
|
||||
|
||||
//! Get Item library by index.
|
||||
IDataBaseLibrary* GetLibrary(int index) const override;
|
||||
|
||||
//! Get Level Item library.
|
||||
IDataBaseLibrary* GetLevelLibrary() const override;
|
||||
|
||||
//! Find Items Library by name.
|
||||
IDataBaseLibrary* FindLibrary(const QString& library) override;
|
||||
|
||||
//! Find Items Library's index by name.
|
||||
int FindLibraryIndex(const QString& library) override;
|
||||
|
||||
//! Load Items library.
|
||||
IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) override;
|
||||
|
||||
//! Save all modified libraries.
|
||||
void SaveAllLibs() override;
|
||||
|
||||
//! Serialize property manager.
|
||||
void Serialize(XmlNodeRef& node, bool bLoading) override;
|
||||
|
||||
//! Export items to game.
|
||||
void Export([[maybe_unused]] XmlNodeRef& node) override {};
|
||||
|
||||
//! Returns unique name base on input name.
|
||||
QString MakeUniqueItemName(const QString& name, const QString& libName = "") override;
|
||||
QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) override;
|
||||
|
||||
//! Root node where this library will be saved.
|
||||
QString GetRootNodeName() override = 0;
|
||||
//! Path to libraries in this manager.
|
||||
QString GetLibsPath() override = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Validate library items for errors.
|
||||
void Validate() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void GatherUsedResources(CUsedResources& resources) override;
|
||||
|
||||
void AddListener(IDataBaseManagerListener* pListener) override;
|
||||
void RemoveListener(IDataBaseManagerListener* pListener) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) override;
|
||||
void RegisterItem(CBaseLibraryItem* pItem) override;
|
||||
void UnregisterItem(CBaseLibraryItem* pItem) override;
|
||||
|
||||
// Only Used internally.
|
||||
void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) override;
|
||||
|
||||
// Called by items to indicated that they have been modified.
|
||||
// Sends item changed event to listeners.
|
||||
void OnItemChanged(IDataBaseItem* pItem) override;
|
||||
void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) override;
|
||||
|
||||
QString MakeFilename(const QString& library);
|
||||
bool IsUniqueFilename(const QString& library) override;
|
||||
|
||||
//CONFETTI BEGIN
|
||||
// Used to change the library item order
|
||||
void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) override;
|
||||
|
||||
bool SetLibraryName(CBaseLibrary* lib, const QString& name) override;
|
||||
|
||||
protected:
|
||||
void SplitFullItemName(const QString& fullItemName, QString& libraryName, QString& itemName);
|
||||
void NotifyItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event);
|
||||
void SetRegisteredFlag(CBaseLibraryItem* pItem, bool bFlag);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Must be overriden.
|
||||
//! Makes a new Item.
|
||||
virtual CBaseLibraryItem* MakeNewItem() = 0;
|
||||
virtual CBaseLibrary* MakeNewLibrary() = 0;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem);
|
||||
|
||||
protected:
|
||||
bool m_bUniqGuidMap;
|
||||
bool m_bUniqNameMap;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
//! Array of all loaded entity items libraries.
|
||||
std::vector<_smart_ptr<CBaseLibrary> > m_libs;
|
||||
|
||||
// There is always one current level library.
|
||||
TSmartPtr<CBaseLibrary> m_pLevelLibrary;
|
||||
|
||||
// GUID to item map.
|
||||
typedef std::map<GUID, _smart_ptr<CBaseLibraryItem>, guid_less_predicate> ItemsGUIDMap;
|
||||
ItemsGUIDMap m_itemsGuidMap;
|
||||
|
||||
// Case insensitive name to items map.
|
||||
typedef std::map<QString, _smart_ptr<CBaseLibraryItem>, stl::less_stricmp<QString>> ItemsNameMap;
|
||||
ItemsNameMap m_itemsNameMap;
|
||||
AZStd::mutex m_itemsNameMapMutex;
|
||||
|
||||
std::vector<IDataBaseManagerListener*> m_listeners;
|
||||
|
||||
// Currently selected item.
|
||||
_smart_ptr<CBaseLibraryItem> m_pSelectedItem;
|
||||
_smart_ptr<CBaseLibraryItem> m_pSelectedParent;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class TMap>
|
||||
class CDataBaseItemEnumerator
|
||||
: public IDataBaseItemEnumerator
|
||||
{
|
||||
TMap* m_pMap;
|
||||
typename TMap::iterator m_iterator;
|
||||
|
||||
public:
|
||||
CDataBaseItemEnumerator(TMap* pMap)
|
||||
{
|
||||
assert(pMap);
|
||||
m_pMap = pMap;
|
||||
m_iterator = m_pMap->begin();
|
||||
}
|
||||
void Release() override { delete this; };
|
||||
IDataBaseItem* GetFirst() override
|
||||
{
|
||||
m_iterator = m_pMap->begin();
|
||||
if (m_iterator == m_pMap->end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_iterator->second;
|
||||
}
|
||||
IDataBaseItem* GetNext() override
|
||||
{
|
||||
if (m_iterator != m_pMap->end())
|
||||
{
|
||||
m_iterator++;
|
||||
}
|
||||
if (m_iterator == m_pMap->end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_iterator->second;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_BASELIBRARYMANAGER_H
|
||||
@@ -28,7 +28,7 @@ void CEditorPreferencesPage_AWS::Reflect(AZ::SerializeContext& serialize)
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<UsageOptions>("Options", "")
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &UsageOptions::m_awsAttributionEnabled, "Allow O3DE to send information about your use of AWS Core Gem to AWS",
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &UsageOptions::m_awsAttributionEnabled, "Allow <a href=\"https://aws.amazon.com/privacy/\">O3DE</a> to send information about your use of AWS Core Gem to AWS",
|
||||
"");
|
||||
|
||||
editContext->Class<CEditorPreferencesPage_AWS>("AWS Preferences", "AWS Preferences")
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
#include "EditorDefs.h"
|
||||
#include "ErrorRecorder.h"
|
||||
#include "BaseLibraryItem.h"
|
||||
#include "Include/IErrorReport.h"
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define CRYINCLUDE_EDITOR_CORE_ERRORRECORDER_H
|
||||
#pragma once
|
||||
|
||||
#include "Include/EditorCoreAPI.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Automatic class to record and display error.
|
||||
class EDITOR_CORE_API CErrorsRecorder
|
||||
|
||||
@@ -67,24 +67,6 @@ QString CErrorRecord::GetErrorText() const
|
||||
{
|
||||
str += QString("\t ");
|
||||
}
|
||||
if (pItem)
|
||||
{
|
||||
switch (pItem->GetType())
|
||||
{
|
||||
case EDB_TYPE_MATERIAL:
|
||||
str += QString("\t Material=\"");
|
||||
break;
|
||||
case EDB_TYPE_PARTICLE:
|
||||
str += QString("\t Particle=\"");
|
||||
break;
|
||||
case EDB_TYPE_MUSIC:
|
||||
str += QString("\t Music=\"");
|
||||
break;
|
||||
default:
|
||||
str += QString("\t Item=\"");
|
||||
}
|
||||
str += pItem->GetFullName() + "\"";
|
||||
}
|
||||
if (pObject)
|
||||
{
|
||||
str += QString("\t Object=\"") + pObject->GetName() + "\"";
|
||||
@@ -101,7 +83,6 @@ CErrorReport::CErrorReport()
|
||||
m_bImmediateMode = true;
|
||||
m_bShowErrors = true;
|
||||
m_pObject = nullptr;
|
||||
m_pItem = nullptr;
|
||||
m_pParticle = nullptr;
|
||||
}
|
||||
|
||||
@@ -140,10 +121,6 @@ void CErrorReport::ReportError(CErrorRecord& err)
|
||||
{
|
||||
err.pObject = m_pObject;
|
||||
}
|
||||
else if (err.pItem == nullptr && m_pItem != nullptr)
|
||||
{
|
||||
err.pItem = m_pItem;
|
||||
}
|
||||
m_errors.push_back(err);
|
||||
}
|
||||
bNoRecurse = false;
|
||||
@@ -255,12 +232,6 @@ void CErrorReport::SetCurrentValidatorObject(CBaseObject* pObject)
|
||||
m_pObject = pObject;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CErrorReport::SetCurrentValidatorItem(CBaseLibraryItem* pItem)
|
||||
{
|
||||
m_pItem = pItem;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CErrorReport::SetCurrentFile(const QString& file)
|
||||
{
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
// forward declarations.
|
||||
class CParticleItem;
|
||||
|
||||
#include "BaseLibraryItem.h"
|
||||
#include <CryCommon/IValidator.h>
|
||||
#include <CryCommon/smartptr.h>
|
||||
|
||||
#include "Objects/BaseObject.h"
|
||||
#include "Include/EditorCoreAPI.h"
|
||||
#include "Include/IErrorReport.h"
|
||||
#include "ErrorRecorder.h"
|
||||
|
||||
@@ -56,16 +59,13 @@ public:
|
||||
int count;
|
||||
//! Object that caused this error.
|
||||
_smart_ptr<CBaseObject> pObject;
|
||||
//! Library Item that caused this error.
|
||||
_smart_ptr<CBaseLibraryItem> pItem;
|
||||
int flags;
|
||||
|
||||
CErrorRecord(CBaseObject* object, ESeverity _severity, const QString& _error, int _flags = 0, int _count = 0,
|
||||
CBaseLibraryItem* item = 0, EValidatorModule _module = VALIDATOR_MODULE_EDITOR)
|
||||
EValidatorModule _module = VALIDATOR_MODULE_EDITOR)
|
||||
: severity(_severity)
|
||||
, module(_module)
|
||||
, pObject(object)
|
||||
, pItem(item)
|
||||
, flags(_flags)
|
||||
, count(_count)
|
||||
, error(_error)
|
||||
@@ -77,7 +77,6 @@ public:
|
||||
severity = ESEVERITY_WARNING;
|
||||
module = VALIDATOR_MODULE_EDITOR;
|
||||
pObject = 0;
|
||||
pItem = 0;
|
||||
flags = 0;
|
||||
count = 0;
|
||||
}
|
||||
@@ -116,8 +115,6 @@ public:
|
||||
|
||||
//! Assign current Object to which new reported warnings are assigned.
|
||||
void SetCurrentValidatorObject(CBaseObject* pObject);
|
||||
//! Assign current Item to which new reported warnings are assigned.
|
||||
void SetCurrentValidatorItem(CBaseLibraryItem* pItem);
|
||||
//! Assign current filename.
|
||||
void SetCurrentFile(const QString& file);
|
||||
|
||||
@@ -127,7 +124,6 @@ private:
|
||||
bool m_bImmediateMode;
|
||||
bool m_bShowErrors;
|
||||
_smart_ptr<CBaseObject> m_pObject;
|
||||
_smart_ptr<CBaseLibraryItem> m_pItem;
|
||||
CParticleItem* m_pParticle;
|
||||
QString m_currentFilename;
|
||||
};
|
||||
|
||||
@@ -362,10 +362,6 @@ void CErrorReportDialog::CopyToClipboard()
|
||||
{
|
||||
str += QString::fromLatin1(" [Object: %1]").arg(pRecord->pObject->GetName());
|
||||
}
|
||||
if (pRecord->pItem)
|
||||
{
|
||||
str += QString::fromLatin1(" [Material: %1]").arg(pRecord->pItem->GetName());
|
||||
}
|
||||
str += QString::fromLatin1("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,11 +149,7 @@ QVariant CErrorReportTableModel::data(const CErrorRecord& record, int column, in
|
||||
case ColumnFile:
|
||||
return record.file;
|
||||
case ColumnObject:
|
||||
if (record.pItem)
|
||||
{
|
||||
return record.pItem->GetFullName();
|
||||
}
|
||||
else if (record.pObject)
|
||||
if (record.pObject)
|
||||
{
|
||||
return record.pObject->GetName();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ class CMusicManager;
|
||||
struct IEditorParticleManager;
|
||||
class CEAXPresetManager;
|
||||
class CErrorReport;
|
||||
class CBaseLibraryItem;
|
||||
class ICommandManager;
|
||||
class CEditorCommandManager;
|
||||
class CHyperGraphManager;
|
||||
@@ -52,9 +51,7 @@ class CConsoleSynchronization;
|
||||
class CUIEnumsDatabase;
|
||||
struct ISourceControl;
|
||||
struct IEditorClassFactory;
|
||||
struct IDataBaseItem;
|
||||
struct ITransformManipulator;
|
||||
struct IDataBaseManager;
|
||||
class IFacialEditor;
|
||||
class CDialog;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
@@ -82,8 +79,6 @@ struct IEventLoopHook;
|
||||
struct IErrorReport; // Vladimir@conffx
|
||||
struct IFileUtil; // Vladimir@conffx
|
||||
struct IEditorLog; // Vladimir@conffx
|
||||
struct IEditorMaterialManager; // Vladimir@conffx
|
||||
struct IBaseLibraryManager; // Vladimir@conffx
|
||||
struct IImageUtil; // Vladimir@conffx
|
||||
struct IEditorParticleUtils; // Leroy@conffx
|
||||
struct ILogFile; // Vladimir@conffx
|
||||
@@ -519,10 +514,6 @@ struct IEditor
|
||||
//! Get access to object manager.
|
||||
virtual struct IObjectManager* GetObjectManager() = 0;
|
||||
virtual CSettingsManager* GetSettingsManager() = 0;
|
||||
//! Get DB manager that own items of specified type.
|
||||
virtual IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) = 0;
|
||||
virtual IBaseLibraryManager* GetMaterialManagerLibrary() = 0; // Vladimir@conffx
|
||||
virtual IEditorMaterialManager* GetIEditorMaterialManager() = 0; // Vladimir@Conffx
|
||||
//! Returns IconManager.
|
||||
virtual IIconManager* GetIconManager() = 0;
|
||||
//! Get Music Manager.
|
||||
|
||||
@@ -892,11 +892,6 @@ void CEditorImpl::CloseView(const GUID& classId)
|
||||
}
|
||||
}
|
||||
|
||||
IDataBaseManager* CEditorImpl::GetDBItemManager([[maybe_unused]] EDataBaseItemType itemType)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CEditorImpl::SelectColor(QColor& color, QWidget* parent)
|
||||
{
|
||||
const AZ::Color c = AzQtComponents::fromQColor(color);
|
||||
@@ -1624,18 +1619,6 @@ SEditorSettings* CEditorImpl::GetEditorSettings()
|
||||
return &gSettings;
|
||||
}
|
||||
|
||||
// Vladimir@Conffx
|
||||
IBaseLibraryManager* CEditorImpl::GetMaterialManagerLibrary()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Vladimir@Conffx
|
||||
IEditorMaterialManager* CEditorImpl::GetIEditorMaterialManager()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IImageUtil* CEditorImpl::GetImageUtil()
|
||||
{
|
||||
return m_pImageUtil;
|
||||
|
||||
@@ -157,7 +157,6 @@ public:
|
||||
void LockSelection(bool bLock) override;
|
||||
bool IsSelectionLocked() override;
|
||||
|
||||
IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) override;
|
||||
CMusicManager* GetMusicManager() override { return m_pMusicManager; };
|
||||
|
||||
IEditorFileMonitor* GetFileMonitor() override;
|
||||
@@ -294,8 +293,6 @@ public:
|
||||
void RegisterObjectContextMenuExtension(TContextMenuExtensionFunc func) override;
|
||||
|
||||
SSystemGlobalEnvironment* GetEnv() override;
|
||||
IBaseLibraryManager* GetMaterialManagerLibrary() override; // Vladimir@Conffx
|
||||
IEditorMaterialManager* GetIEditorMaterialManager() override; // Vladimir@Conffx
|
||||
IImageUtil* GetImageUtil() override; // Vladimir@conffx
|
||||
SEditorSettings* GetEditorSettings() override;
|
||||
ILogFile* GetLogFile() override { return m_pLogFile; }
|
||||
|
||||
@@ -1,143 +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_INCLUDE_IBASELIBRARYMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IBASELIBRARYMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include <IEditor.h>
|
||||
#include "Include/IDataBaseItem.h"
|
||||
#include "Include/IDataBaseLibrary.h"
|
||||
#include "Include/IDataBaseManager.h"
|
||||
#include "Util/TRefCountBase.h"
|
||||
|
||||
class CBaseLibraryItem;
|
||||
class CBaseLibrary;
|
||||
|
||||
struct IBaseLibraryManager
|
||||
: public TRefCountBase<IDataBaseManager>
|
||||
, public IEditorNotifyListener
|
||||
{
|
||||
//! Clear all libraries.
|
||||
virtual void ClearAll() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IDocListener implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Library items.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Make a new item in specified library.
|
||||
virtual IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) = 0;
|
||||
//! Delete item from library and manager.
|
||||
virtual void DeleteItem(IDataBaseItem* pItem) = 0;
|
||||
|
||||
//! Find Item by its GUID.
|
||||
virtual IDataBaseItem* FindItem(REFGUID guid) const = 0;
|
||||
virtual IDataBaseItem* FindItemByName(const QString& fullItemName) = 0;
|
||||
virtual IDataBaseItem* LoadItemByName(const QString& fullItemName) = 0;
|
||||
|
||||
virtual IDataBaseItemEnumerator* GetItemEnumerator() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set item currently selected.
|
||||
virtual void SetSelectedItem(IDataBaseItem* pItem) = 0;
|
||||
// Get currently selected item.
|
||||
virtual IDataBaseItem* GetSelectedItem() const = 0;
|
||||
virtual IDataBaseItem* GetSelectedParentItem() const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Libraries.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Add Item library.
|
||||
virtual IDataBaseLibrary* AddLibrary(const QString& library, bool isLevelLibrary = false, bool bIsLoading = true) = 0;
|
||||
virtual void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) = 0;
|
||||
//! Get number of libraries.
|
||||
virtual int GetLibraryCount() const = 0;
|
||||
//! Get number of modified libraries.
|
||||
virtual int GetModifiedLibraryCount() const = 0;
|
||||
|
||||
//! Get Item library by index.
|
||||
virtual IDataBaseLibrary* GetLibrary(int index) const = 0;
|
||||
|
||||
//! Get Level Item library.
|
||||
virtual IDataBaseLibrary* GetLevelLibrary() const = 0;
|
||||
|
||||
//! Find Items Library by name.
|
||||
virtual IDataBaseLibrary* FindLibrary(const QString& library) = 0;
|
||||
|
||||
//! Find the Library's index by name.
|
||||
virtual int FindLibraryIndex(const QString& library) = 0;
|
||||
|
||||
//! Load Items library.
|
||||
#ifdef LoadLibrary
|
||||
#undef LoadLibrary
|
||||
#endif
|
||||
virtual IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) = 0;
|
||||
|
||||
//! Save all modified libraries.
|
||||
virtual void SaveAllLibs() = 0;
|
||||
|
||||
//! Serialize property manager.
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0;
|
||||
|
||||
//! Export items to game.
|
||||
virtual void Export(XmlNodeRef& node) = 0;
|
||||
|
||||
//! Returns unique name base on input name.
|
||||
// Vera@conffx, add LibName parameter so we could make an unique name depends on input library.
|
||||
// Arguments:
|
||||
// - name: name of the item
|
||||
// - libName: The library of the item. Given the library name, the function will return a unique name in the library
|
||||
// Default value "": The function will ignore the library name and return a unique name in the manager
|
||||
virtual QString MakeUniqueItemName(const QString& name, const QString& libName = "") = 0;
|
||||
virtual QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) = 0;
|
||||
|
||||
//! Root node where this library will be saved.
|
||||
virtual QString GetRootNodeName() = 0;
|
||||
//! Path to libraries in this manager.
|
||||
virtual QString GetLibsPath() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Validate library items for errors.
|
||||
virtual void Validate() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void GatherUsedResources(CUsedResources& resources) = 0;
|
||||
|
||||
virtual void AddListener(IDataBaseManagerListener* pListener) = 0;
|
||||
virtual void RemoveListener(IDataBaseManagerListener* pListener) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) = 0;
|
||||
virtual void RegisterItem(CBaseLibraryItem* pItem) = 0;
|
||||
virtual void UnregisterItem(CBaseLibraryItem* pItem) = 0;
|
||||
|
||||
// Only Used internally.
|
||||
virtual void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) = 0;
|
||||
|
||||
// Called by items to indicated that they have been modified.
|
||||
// Sends item changed event to listeners.
|
||||
virtual void OnItemChanged(IDataBaseItem* pItem) = 0;
|
||||
virtual void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) = 0;
|
||||
|
||||
//CONFETTI BEGIN
|
||||
// Used to change the library item order
|
||||
virtual void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) = 0;
|
||||
// simplifies the library renaming process
|
||||
virtual bool SetLibraryName(CBaseLibrary* lib, const QString& name) = 0;
|
||||
|
||||
|
||||
//Check if the file name is unique.
|
||||
//Params: library: library name. NOT the file path.
|
||||
virtual bool IsUniqueFilename(const QString& library) = 0;
|
||||
//CONFETTI END
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IBASELIBRARYMANAGER_H
|
||||
@@ -1,92 +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_INCLUDE_IDATABASEITEM_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASEITEM_H
|
||||
#pragma once
|
||||
|
||||
#include <qwindowdefs.h>
|
||||
#include <IEditor.h>
|
||||
|
||||
struct IDataBaseLibrary;
|
||||
class CUsedResources;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** Base class for all items contained in BaseLibraray.
|
||||
*/
|
||||
struct IDataBaseItem
|
||||
{
|
||||
struct SerializeContext
|
||||
{
|
||||
XmlNodeRef node;
|
||||
bool bUndo;
|
||||
bool bLoading;
|
||||
bool bCopyPaste;
|
||||
bool bIgnoreChilds;
|
||||
bool bUniqName;
|
||||
SerializeContext()
|
||||
: node(0)
|
||||
, bLoading(false)
|
||||
, bCopyPaste(false)
|
||||
, bIgnoreChilds(false)
|
||||
, bUniqName(false)
|
||||
, bUndo(false) {};
|
||||
SerializeContext(XmlNodeRef _node, bool bLoad)
|
||||
: node(_node)
|
||||
, bLoading(bLoad)
|
||||
, bCopyPaste(false)
|
||||
, bIgnoreChilds(false)
|
||||
, bUniqName(false)
|
||||
, bUndo(false) {};
|
||||
SerializeContext(const SerializeContext& ctx)
|
||||
: node(ctx.node)
|
||||
, bLoading(ctx.bLoading)
|
||||
, bCopyPaste(ctx.bCopyPaste)
|
||||
, bIgnoreChilds(ctx.bIgnoreChilds)
|
||||
, bUniqName(ctx.bUniqName)
|
||||
, bUndo(ctx.bUndo) {};
|
||||
};
|
||||
|
||||
virtual EDataBaseItemType GetType() const = 0;
|
||||
|
||||
//! Return Library this item are contained in.
|
||||
//! Item can only be at one library.
|
||||
virtual IDataBaseLibrary* GetLibrary() const = 0;
|
||||
|
||||
//! Change item name.
|
||||
virtual void SetName(const QString& name) = 0;
|
||||
//! Get item name.
|
||||
virtual const QString& GetName() const = 0;
|
||||
|
||||
//! Get full item name, including name of library.
|
||||
//! Name formed by adding dot after name of library
|
||||
//! eg. library Pickup and item PickupRL form full item name: "Pickups.PickupRL".
|
||||
virtual QString GetFullName() const = 0;
|
||||
|
||||
//! Get only nameof group from prototype.
|
||||
virtual QString GetGroupName() = 0;
|
||||
//! Get short name of prototype without group.
|
||||
virtual QString GetShortName() = 0;
|
||||
|
||||
//! Serialize library item to archive.
|
||||
virtual void Serialize(SerializeContext& ctx) = 0;
|
||||
|
||||
//! Generate new unique id for this item.
|
||||
virtual void GenerateId() = 0;
|
||||
//! Returns GUID of this material.
|
||||
virtual const GUID& GetGUID() const = 0;
|
||||
|
||||
//! Validate item for errors.
|
||||
virtual void Validate() {};
|
||||
|
||||
//! Gathers resources by this item.
|
||||
virtual void GatherUsedResources([[maybe_unused]] CUsedResources& resources) {};
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASEITEM_H
|
||||
@@ -1,118 +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_INCLUDE_IDATABASELIBRARY_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASELIBRARY_H
|
||||
#pragma once
|
||||
|
||||
|
||||
struct IDataBaseManager;
|
||||
struct IDataBaseItem;
|
||||
|
||||
class QString;
|
||||
class XmlNodeRef;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Description:
|
||||
// Interface to access specific library of editor data base.
|
||||
// Ex. Archetype library, Material Library.
|
||||
// See Also:
|
||||
// IDataBaseItem,IDataBaseManager
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IDataBaseLibrary
|
||||
{
|
||||
// Description:
|
||||
// Return IDataBaseManager interface to the manager for items stored in this library.
|
||||
virtual IDataBaseManager* GetManager() = 0;
|
||||
|
||||
// Description:
|
||||
// Return library name.
|
||||
virtual const QString& GetName() const = 0;
|
||||
|
||||
// Description:
|
||||
// Return filename where this library is stored.
|
||||
virtual const QString& GetFilename() const = 0;
|
||||
|
||||
// Description:
|
||||
// Save contents of library to file.
|
||||
virtual bool Save() = 0;
|
||||
|
||||
// Description:
|
||||
// Load library from file.
|
||||
// Arguments:
|
||||
// filename - Full specified library filename (relative to root game folder).
|
||||
virtual bool Load(const QString& filename) = 0;
|
||||
|
||||
// Description:
|
||||
// Serialize library parameters and items to/from XML node.
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0;
|
||||
|
||||
// Description:
|
||||
// Marks library as modified, indicates that some item in library was modified.
|
||||
virtual void SetModified(bool bModified = true) = 0;
|
||||
|
||||
// Description:
|
||||
// Check if library parameters or any items where modified.
|
||||
// If any item was modified library may need saving before closing editor.
|
||||
virtual bool IsModified() const = 0;
|
||||
|
||||
// Description:
|
||||
// Check if this library is not shared and internal to current level.
|
||||
virtual bool IsLevelLibrary() const = 0;
|
||||
|
||||
// Description:
|
||||
// Make this library accessible only from current Level. (not shared)
|
||||
virtual void SetLevelLibrary(bool bEnable) = 0;
|
||||
|
||||
// Description:
|
||||
// Associate a new item with the library.
|
||||
// Watch out if item was already in another library.
|
||||
virtual void AddItem(IDataBaseItem* pItem, bool bRegister = true) = 0;
|
||||
|
||||
// Description:
|
||||
// Return number of items in library.
|
||||
virtual int GetItemCount() const = 0;
|
||||
|
||||
// Description:
|
||||
// Get item by index.
|
||||
// See Also:
|
||||
// GetItemCount
|
||||
// Arguments:
|
||||
// index - Index from 0 to GetItemCount()
|
||||
virtual IDataBaseItem* GetItem(int index) = 0;
|
||||
|
||||
// Description:
|
||||
// Remove item from library, does not destroy item,
|
||||
// only unliks it from this library, to delete item use IDataBaseManager.
|
||||
// See Also:
|
||||
// AddItem
|
||||
virtual void RemoveItem(IDataBaseItem* item) = 0;
|
||||
|
||||
// Description:
|
||||
// Remove all items from library, does not destroy items,
|
||||
// only unliks them from this library, to delete item use IDataBaseManager.
|
||||
// See Also:
|
||||
// RemoveItem,AddItem
|
||||
virtual void RemoveAllItems() = 0;
|
||||
|
||||
// Description:
|
||||
// Find item in library by name.
|
||||
// This function usually uses linear search so it is not particularry fast.
|
||||
// See Also:
|
||||
// GetItem
|
||||
virtual IDataBaseItem* FindItem(const QString& name) = 0;
|
||||
|
||||
|
||||
//CONFETTI BEGIN
|
||||
// Used to change the library item order
|
||||
virtual void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) = 0;
|
||||
//CONFETTI END
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASELIBRARY_H
|
||||
@@ -1,134 +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_INCLUDE_IDATABASEMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_INCLUDE_IDATABASEMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
struct IDataBaseItem;
|
||||
struct IDataBaseLibrary;
|
||||
class CUsedResources;
|
||||
|
||||
enum EDataBaseItemEvent
|
||||
{
|
||||
EDB_ITEM_EVENT_ADD,
|
||||
EDB_ITEM_EVENT_DELETE,
|
||||
EDB_ITEM_EVENT_CHANGED,
|
||||
EDB_ITEM_EVENT_SELECTED,
|
||||
EDB_ITEM_EVENT_UPDATE_PROPERTIES,
|
||||
EDB_ITEM_EVENT_UPDATE_PROPERTIES_NO_EDITOR_REFRESH
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Description:
|
||||
// Callback class to intercept item creation and deletion events.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IDataBaseManagerListener
|
||||
{
|
||||
virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Description:
|
||||
// his interface is used to enumerate al items registered to the database manager.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IDataBaseItemEnumerator
|
||||
{
|
||||
virtual ~IDataBaseItemEnumerator() = default;
|
||||
|
||||
virtual void Release() = 0;
|
||||
virtual IDataBaseItem* GetFirst() = 0;
|
||||
virtual IDataBaseItem* GetNext() = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Interface to the collection of all items or specific type
|
||||
// in data base libraries.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IDataBaseManager
|
||||
{
|
||||
//! Clear all libraries.
|
||||
virtual void ClearAll() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Library items.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Make a new item in specified library.
|
||||
virtual IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) = 0;
|
||||
//! Delete item from library and manager.
|
||||
virtual void DeleteItem(IDataBaseItem* pItem) = 0;
|
||||
|
||||
//! Find Item by its GUID.
|
||||
virtual IDataBaseItem* FindItem(REFGUID guid) const = 0;
|
||||
virtual IDataBaseItem* FindItemByName(const QString& fullItemName) = 0;
|
||||
|
||||
virtual IDataBaseItemEnumerator* GetItemEnumerator() = 0;
|
||||
|
||||
// Select one item in DB.
|
||||
virtual void SetSelectedItem(IDataBaseItem* pItem) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Libraries.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Add Item library. Set isLevelLibrary to true if its the "level" library which gets saved inside the level
|
||||
virtual IDataBaseLibrary* AddLibrary(const QString& library, bool isLevelLibrary = false, bool bIsLoading = true) = 0;
|
||||
virtual void DeleteLibrary(const QString& library, bool forceDeleteLibrary = false) = 0;
|
||||
//! Get number of libraries.
|
||||
virtual int GetLibraryCount() const = 0;
|
||||
//! Get Item library by index.
|
||||
virtual IDataBaseLibrary* GetLibrary(int index) const = 0;
|
||||
|
||||
//! Find Items Library by name.
|
||||
virtual IDataBaseLibrary* FindLibrary(const QString& library) = 0;
|
||||
|
||||
//! Load Items library.
|
||||
#ifdef LoadLibrary
|
||||
#undef LoadLibrary
|
||||
#endif
|
||||
virtual IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) = 0;
|
||||
|
||||
//! Save all modified libraries.
|
||||
virtual void SaveAllLibs() = 0;
|
||||
|
||||
//! Serialize property manager.
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0;
|
||||
|
||||
//! Export items to game.
|
||||
virtual void Export([[maybe_unused]] XmlNodeRef& node) {};
|
||||
|
||||
//! Returns unique name base on input name.
|
||||
virtual QString MakeUniqueItemName(const QString& name, const QString& libName = "") = 0;
|
||||
virtual QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) = 0;
|
||||
|
||||
//! Root node where this library will be saved.
|
||||
virtual QString GetRootNodeName() = 0;
|
||||
//! Path to libraries in this manager.
|
||||
virtual QString GetLibsPath() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Validate library items for errors.
|
||||
virtual void Validate() = 0;
|
||||
|
||||
// Description:
|
||||
// Collects names of all resource files used by managed items.
|
||||
// Arguments:
|
||||
// resources - Structure where all filenames are collected.
|
||||
virtual void GatherUsedResources(CUsedResources& resources) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Register listeners.
|
||||
virtual void AddListener(IDataBaseManagerListener* pListener) = 0;
|
||||
virtual void RemoveListener(IDataBaseManagerListener* pListener) = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_INCLUDE_IDATABASEMANAGER_H
|
||||
@@ -1,20 +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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "BaseLibraryItem.h"
|
||||
#include <IMaterial.h>
|
||||
|
||||
struct IEditorMaterial
|
||||
: public CBaseLibraryItem
|
||||
{
|
||||
virtual int GetFlags() const = 0;
|
||||
virtual IMaterial* GetMatInfo(bool bUseExistingEngineMaterial = false) = 0;
|
||||
virtual void DisableHighlightForFrame() = 0;
|
||||
};
|
||||
@@ -1,21 +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_MATERIAL_IEDITORMATERIALMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_MATERIAL_IEDITORMATERIALMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include <Include/IBaseLibraryManager.h>
|
||||
#include <IMaterial.h>
|
||||
|
||||
|
||||
struct IEditorMaterialManager
|
||||
{
|
||||
virtual void GotoMaterial(IMaterial* pMaterial) = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H
|
||||
@@ -14,7 +14,6 @@
|
||||
// forward declarations.
|
||||
class CParticleItem;
|
||||
class CBaseObject;
|
||||
class CBaseLibraryItem;
|
||||
class CErrorRecord;
|
||||
class QString;
|
||||
|
||||
@@ -52,9 +51,6 @@ struct IErrorReport
|
||||
//! Assign current Object to which new reported warnings are assigned.
|
||||
virtual void SetCurrentValidatorObject(CBaseObject* pObject) = 0;
|
||||
|
||||
//! Assign current Item to which new reported warnings are assigned.
|
||||
virtual void SetCurrentValidatorItem(CBaseLibraryItem* pItem) = 0;
|
||||
|
||||
//! Assign current filename.
|
||||
virtual void SetCurrentFile(const QString& file) = 0;
|
||||
};
|
||||
|
||||
@@ -85,9 +85,6 @@ public:
|
||||
MOCK_METHOD0(IsSelectionLocked, bool());
|
||||
MOCK_METHOD0(GetObjectManager, struct IObjectManager* ());
|
||||
MOCK_METHOD0(GetSettingsManager, CSettingsManager* ());
|
||||
MOCK_METHOD1(GetDBItemManager, IDataBaseManager* (EDataBaseItemType));
|
||||
MOCK_METHOD0(GetMaterialManagerLibrary, IBaseLibraryManager* ());
|
||||
MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ());
|
||||
MOCK_METHOD0(GetIconManager, IIconManager* ());
|
||||
MOCK_METHOD0(GetMusicManager, CMusicManager* ());
|
||||
MOCK_METHOD2(GetTerrainElevation, float(float , float ));
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define CLASS_ENVIRONMENT_LIGHT "EnvironmentLight"
|
||||
|
||||
class CEntityObject;
|
||||
class CSelectionGroup;
|
||||
class QMenu;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "ErrorReport.h"
|
||||
#include <AzCore/std/containers/set.h>
|
||||
|
||||
#include <CryCommon/IXml.h>
|
||||
|
||||
class CErrorRecord;
|
||||
struct IObjectManager;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define CRYINCLUDE_EDITOR_TRACKVIEW_TRACKVIEWSEQUENCE_H
|
||||
#pragma once
|
||||
|
||||
#include <IEditor.h>
|
||||
#include "IMovieSystem.h"
|
||||
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
|
||||
@@ -408,20 +408,6 @@ void CTrackViewSequenceManager::OnSequenceRemoved(CTrackViewSequence* sequence)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void CTrackViewSequenceManager::OnDataBaseItemEvent([[maybe_unused]] IDataBaseItem* pItem, EDataBaseItemEvent event)
|
||||
{
|
||||
if (event != EDataBaseItemEvent::EDB_ITEM_EVENT_ADD)
|
||||
{
|
||||
const size_t numSequences = m_sequences.size();
|
||||
|
||||
for (size_t i = 0; i < numSequences; ++i)
|
||||
{
|
||||
m_sequences[i]->UpdateDynamicParams();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
CTrackViewAnimNodeBundle CTrackViewSequenceManager::GetAllRelatedAnimNodes(const AZ::EntityId entityId) const
|
||||
{
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
|
||||
|
||||
#include "TrackViewSequence.h"
|
||||
#include "IDataBaseManager.h"
|
||||
|
||||
#include <AzCore/Component/EntityBus.h>
|
||||
|
||||
class CTrackViewSequenceManager
|
||||
: public IEditorNotifyListener
|
||||
, public IDataBaseManagerListener
|
||||
, public ITrackViewSequenceManager
|
||||
, public AZ::EntitySystemBus::Handler
|
||||
{
|
||||
@@ -65,8 +63,6 @@ private:
|
||||
void OnSequenceAdded(CTrackViewSequence* pSequence);
|
||||
void OnSequenceRemoved(CTrackViewSequence* pSequence);
|
||||
|
||||
void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) override;
|
||||
|
||||
// AZ::EntitySystemBus
|
||||
void OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) override;
|
||||
void OnEntityDestruction(const AZ::EntityId& entityId) override;
|
||||
|
||||
@@ -46,7 +46,6 @@ struct HitContext;
|
||||
struct IRenderListener;
|
||||
class CImageEx;
|
||||
class QMenu;
|
||||
struct IDataBaseItem;
|
||||
|
||||
/** Type of viewport.
|
||||
*/
|
||||
@@ -230,8 +229,6 @@ public:
|
||||
// Drag and drop support on viewports.
|
||||
// To be overrided in derived classes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual bool CanDrop([[maybe_unused]] const QPoint& point, [[maybe_unused]] IDataBaseItem* pItem) { return false; };
|
||||
virtual void Drop([[maybe_unused]] const QPoint& point, [[maybe_unused]] IDataBaseItem* pItem) {};
|
||||
virtual void SetGlobalDropCallback(DropCallback dropCallback, void* dropCallbackCustom)
|
||||
{
|
||||
m_dropCallback = dropCallback;
|
||||
|
||||
@@ -7,17 +7,12 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
BaseLibrary.h
|
||||
BaseLibraryItem.h
|
||||
UsedResources.h
|
||||
UIEnumsDatabase.h
|
||||
Include/EditorCoreAPI.cpp
|
||||
Include/IErrorReport.h
|
||||
Include/IBaseLibraryManager.h
|
||||
Include/IFileUtil.h
|
||||
Include/EditorCoreAPI.h
|
||||
Include/IEditorMaterial.h
|
||||
Include/IEditorMaterialManager.h
|
||||
Include/IImageUtil.h
|
||||
Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.qrc
|
||||
Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp
|
||||
@@ -35,8 +30,6 @@ set(FILES
|
||||
Controls/QBitmapPreviewDialogImp.h
|
||||
Controls/QToolTipWidget.h
|
||||
Controls/QToolTipWidget.cpp
|
||||
BaseLibraryItem.cpp
|
||||
BaseLibrary.cpp
|
||||
UsedResources.cpp
|
||||
UIEnumsDatabase.cpp
|
||||
LyViewPaneNames.h
|
||||
|
||||
@@ -271,9 +271,6 @@ set(FILES
|
||||
Include/HitContext.h
|
||||
Include/ICommandManager.h
|
||||
Include/IConsoleConnectivity.h
|
||||
Include/IDataBaseItem.h
|
||||
Include/IDataBaseLibrary.h
|
||||
Include/IDataBaseManager.h
|
||||
Include/IDisplayViewport.h
|
||||
Include/IEditorClassFactory.h
|
||||
Include/IEventLoopHook.h
|
||||
@@ -369,9 +366,6 @@ set(FILES
|
||||
ActionManager.h
|
||||
ShortcutDispatcher.cpp
|
||||
ShortcutDispatcher.h
|
||||
BaseLibraryManager.cpp
|
||||
BaseLibraryItem.h
|
||||
BaseLibraryManager.h
|
||||
CheckOutDialog.cpp
|
||||
CheckOutDialog.h
|
||||
CheckOutDialog.ui
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
@@ -164,6 +165,8 @@ namespace AzFramework
|
||||
public:
|
||||
friend class SpawnableEntitiesDefinition;
|
||||
|
||||
AZ_CLASS_ALLOCATOR(AzFramework::EntitySpawnTicket, AZ::SystemAllocator, 0);
|
||||
|
||||
using Id = uint32_t;
|
||||
|
||||
EntitySpawnTicket() = default;
|
||||
|
||||
@@ -499,12 +499,8 @@ namespace AzFramework
|
||||
for (auto it = newEntitiesBegin; it != newEntitiesEnd; ++it)
|
||||
{
|
||||
AZ::Entity* clone = (*it);
|
||||
// The entity component framework doesn't handle entities without TransformComponent safely.
|
||||
if (!clone->GetComponents().empty())
|
||||
{
|
||||
clone->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
|
||||
}
|
||||
clone->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, clone);
|
||||
}
|
||||
|
||||
// Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context.
|
||||
@@ -636,12 +632,8 @@ namespace AzFramework
|
||||
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
|
||||
{
|
||||
AZ::Entity* clone = (*it);
|
||||
// The entity component framework doesn't handle entities without TransformComponent safely.
|
||||
if (!clone->GetComponents().empty())
|
||||
{
|
||||
clone->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
|
||||
}
|
||||
clone->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
|
||||
}
|
||||
|
||||
if (request.m_completionCallback)
|
||||
@@ -668,7 +660,7 @@ namespace AzFramework
|
||||
{
|
||||
if (entity != nullptr)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
// Setting it to 0 is needed to avoid the infinite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
entity->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
|
||||
@@ -702,7 +694,7 @@ namespace AzFramework
|
||||
{
|
||||
if (*entityIterator != nullptr && (*entityIterator)->GetId() == request.m_entityId)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
// Setting it to 0 is needed to avoid the infinite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
(*entityIterator)->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, (*entityIterator)->GetId());
|
||||
@@ -949,11 +941,6 @@ namespace AzFramework
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Entities without components wouldn't have been send to the GameEntityContext.
|
||||
delete entity;
|
||||
}
|
||||
}
|
||||
delete request.m_ticket;
|
||||
|
||||
|
||||
@@ -77,6 +77,12 @@ namespace UnitTest
|
||||
public:
|
||||
AZ_COMPONENT(TargetSpawnableComponent, "{B4041561-63A7-4E1E-80F1-78C08D497960}");
|
||||
|
||||
TargetSpawnableComponent() = default;
|
||||
explicit TargetSpawnableComponent(AZ::EntityId parent)
|
||||
: m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void Activate() override {}
|
||||
void Deactivate() override {}
|
||||
|
||||
@@ -84,14 +90,19 @@ namespace UnitTest
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
|
||||
{
|
||||
serializeContext->Class<TargetSpawnableComponent, AZ::Component>();
|
||||
serializeContext->Class<TargetSpawnableComponent, AZ::Component>()
|
||||
->Field("Parent", &TargetSpawnableComponent::m_parent);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId m_parent;
|
||||
};
|
||||
|
||||
class SpawnableEntitiesManagerTest : public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
constexpr static AZ::u64 EntityIdStartId = 40;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsFixture::SetUp();
|
||||
@@ -111,7 +122,7 @@ namespace UnitTest
|
||||
m_spawnable = aznew AzFramework::Spawnable(
|
||||
AZ::Data::AssetId::CreateString("{EB2E8A2B-F253-4A90-BBF4-55F2EED786B8}:0"), AZ::Data::AssetData::AssetStatus::Ready);
|
||||
m_spawnableAsset = new AZ::Data::Asset<AzFramework::Spawnable>(m_spawnable, AZ::Data::AssetLoadBehavior::Default);
|
||||
m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset);
|
||||
m_ticket = aznew AzFramework::EntitySpawnTicket(*m_spawnableAsset);
|
||||
|
||||
auto managerInterface = AzFramework::SpawnableEntitiesInterface::Get();
|
||||
m_manager = azrtti_cast<AzFramework::SpawnableEntitiesManager*>(managerInterface);
|
||||
@@ -147,22 +158,43 @@ namespace UnitTest
|
||||
{
|
||||
auto entry = AZStd::make_unique<AZ::Entity>();
|
||||
entry->AddComponent(aznew SourceSpawnableComponent());
|
||||
entry->SetId(AZ::EntityId(EntityIdStartId + i));
|
||||
entities.push_back(AZStd::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> CreateTargetSpawnable(size_t numElements)
|
||||
AZ::Data::Asset<AzFramework::Spawnable> CreateTargetSpawnable(size_t numElements, bool requiresMatchingEntityIds)
|
||||
{
|
||||
auto target = aznew AzFramework::Spawnable(
|
||||
AZ::Data::AssetId(AZ::Uuid("{716CD8C3-0BA8-4F32-B579-0EC7C967796F}")), AZ::Data::AssetData::AssetStatus::Ready);
|
||||
|
||||
AzFramework::Spawnable::EntityList& entities = target->GetEntities();
|
||||
entities.reserve(numElements);
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
if (requiresMatchingEntityIds)
|
||||
{
|
||||
auto entry = AZStd::make_unique<AZ::Entity>();
|
||||
entry->AddComponent(aznew TargetSpawnableComponent());
|
||||
entities.push_back(AZStd::move(entry));
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
auto entry = AZStd::make_unique<AZ::Entity>();
|
||||
if (i != 0)
|
||||
{
|
||||
entry->AddComponent(aznew TargetSpawnableComponent(AZ::EntityId(EntityIdStartId + i - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->AddComponent(aznew TargetSpawnableComponent());
|
||||
}
|
||||
entry->SetId(AZ::EntityId(EntityIdStartId + i));
|
||||
entities.push_back(AZStd::move(entry));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
auto entry = AZStd::make_unique<AZ::Entity>();
|
||||
entry->AddComponent(aznew TargetSpawnableComponent());
|
||||
entities.push_back(AZStd::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Data::Asset<AzFramework::Spawnable>(target, AZ::Data::AssetLoadBehavior::NoLoad);
|
||||
@@ -212,6 +244,38 @@ namespace UnitTest
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DoParentEntityIdsMatch(AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
if (entities.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::Entity* previous = nullptr;
|
||||
for (const AZ::Entity* entity : entities)
|
||||
{
|
||||
if (entity)
|
||||
{
|
||||
if (previous)
|
||||
{
|
||||
if (TargetSpawnableComponent* link = entity->FindComponent<TargetSpawnableComponent>(); link != nullptr)
|
||||
{
|
||||
if (link->m_parent != previous->GetId())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
previous = entity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsEveryOtherEntityAReplacement(AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
bool onAlternative = true;
|
||||
@@ -516,7 +580,7 @@ namespace UnitTest
|
||||
// Make sure we start with a fresh ticket each time, or else each iteration through this loop would continue to build up
|
||||
// more and more entities.
|
||||
delete m_ticket;
|
||||
m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset);
|
||||
m_ticket = aznew AzFramework::EntitySpawnTicket(*m_spawnableAsset);
|
||||
|
||||
constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
@@ -599,7 +663,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = true;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace,
|
||||
@@ -608,11 +673,13 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allReplaced = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allReplaced](
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allReplaced, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allReplaced = AreAllEntitiesReplaced(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -621,6 +688,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(4, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allReplaced);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllAliasesWithAdditional_SourceAndTargetComponentsMerged)
|
||||
@@ -628,7 +696,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = false;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional,
|
||||
@@ -637,11 +706,13 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allAdded = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allAdded](
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allAdded, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allAdded = IsEveryOtherEntityAReplacement(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -650,6 +721,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(8, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allAdded);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_AllAliasesWithMerge_SourceAndTargetComponentsMerged)
|
||||
@@ -657,7 +729,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = true;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge,
|
||||
@@ -666,11 +739,13 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allMerged = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allMerged](
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allMerged, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allMerged = AreAllMerged(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -679,6 +754,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(4, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allMerged);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1095,7 +1171,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = true;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace, Spawnable::EntityAliasType::Replace,
|
||||
@@ -1106,11 +1183,13 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allReplaced = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allReplaced](
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allReplaced, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allReplaced = AreAllEntitiesReplaced(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -1119,6 +1198,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(4, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allReplaced);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllAliasesWithAdditional_SourceAndTargetComponentsMerged)
|
||||
@@ -1126,7 +1206,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = false;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional, Spawnable::EntityAliasType::Additional,
|
||||
@@ -1137,12 +1218,14 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allAdded = false;
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback =
|
||||
[&spawnedEntitiesCount, &allAdded](
|
||||
[&spawnedEntitiesCount, &allAdded, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allAdded = IsEveryOtherEntityAReplacement(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -1151,6 +1234,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(8, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allAdded);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, SpawnEntities_AllAliasesWithMerge_SourceAndTargetComponentsMerged)
|
||||
@@ -1158,7 +1242,8 @@ namespace UnitTest
|
||||
using namespace AzFramework;
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4);
|
||||
constexpr bool requiresMatchingEntityIds = true;
|
||||
AZ::Data::Asset<Spawnable> target = CreateTargetSpawnable(4, requiresMatchingEntityIds);
|
||||
InsertEntityAliases<4>(
|
||||
{ 0, 1, 2, 3 }, { 0, 1, 2, 3 },
|
||||
{ Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge, Spawnable::EntityAliasType::Merge,
|
||||
@@ -1169,11 +1254,13 @@ namespace UnitTest
|
||||
|
||||
size_t spawnedEntitiesCount = 0;
|
||||
bool allMerged = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allMerged](
|
||||
bool allEntityIdsPatched = false;
|
||||
auto callback = [&spawnedEntitiesCount, &allMerged, &allEntityIdsPatched](
|
||||
AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
|
||||
{
|
||||
spawnedEntitiesCount += entities.size();
|
||||
allMerged = AreAllMerged(entities);
|
||||
allEntityIdsPatched = DoParentEntityIdsMatch(entities);
|
||||
};
|
||||
AzFramework::SpawnEntitiesOptionalArgs optionalArgs;
|
||||
optionalArgs.m_completionCallback = AZStd::move(callback);
|
||||
@@ -1182,6 +1269,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(4, spawnedEntitiesCount);
|
||||
EXPECT_TRUE(allMerged);
|
||||
EXPECT_TRUE(allEntityIdsPatched);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1302,6 +1390,36 @@ namespace UnitTest
|
||||
// ClaimEntities
|
||||
//
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, ClaimEntities_Call_AllEntitiesWereClaimedAndNotDeleted)
|
||||
{
|
||||
static constexpr size_t NumEntities = 4;
|
||||
FillSpawnable(NumEntities);
|
||||
|
||||
AZStd::vector<AZ::Entity*> claimedEntities;
|
||||
auto callback = [&claimedEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView container)
|
||||
{
|
||||
for (AZ::Entity* entity : container)
|
||||
{
|
||||
claimedEntities.push_back(entity);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
AzFramework::EntitySpawnTicket ticket(*m_spawnableAsset);
|
||||
m_manager->SpawnAllEntities(ticket);
|
||||
m_manager->ClaimEntities(ticket, AZStd::move(callback));
|
||||
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
EXPECT_EQ(NumEntities, claimedEntities.size());
|
||||
|
||||
// If these calls fail it means that the ticket has still deleted the entities, so they weren't properly claimed.
|
||||
for (AZ::Entity* entity : claimedEntities)
|
||||
{
|
||||
delete entity;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SpawnableEntitiesManagerTest, ClaimEntities_DeleteTicketBeforeCall_NoCrash)
|
||||
{
|
||||
auto callback = [](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView) {};
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
|
||||
namespace AzQtComponents
|
||||
{
|
||||
@@ -35,6 +37,7 @@ namespace AzQtComponents
|
||||
|
||||
m_text = text;
|
||||
m_metricsLabel->setText(m_text);
|
||||
|
||||
m_elidedText.clear();
|
||||
elide();
|
||||
updateGeometry();
|
||||
@@ -65,7 +68,62 @@ namespace AzQtComponents
|
||||
void ElidingLabel::elide()
|
||||
{
|
||||
ensurePolished();
|
||||
m_elidedText = fontMetrics().elidedText(m_text, m_elideMode, TextRect().width());
|
||||
|
||||
if (Qt::mightBeRichText(m_text))
|
||||
{
|
||||
// If RichText tags are elided using fontMetrics.elidedText(), they will break.
|
||||
// A TextDocument is used to produce elided text that takes this into account.
|
||||
const QString ellipsis("...");
|
||||
const int maxLineWidth = TextRect().width();
|
||||
|
||||
QTextDocument doc;
|
||||
doc.setHtml(m_text);
|
||||
doc.setDefaultFont(font());
|
||||
doc.setDocumentMargin(0.0);
|
||||
|
||||
// Turn off wrapping so the document uses a single line.
|
||||
QTextOption option = doc.defaultTextOption();
|
||||
option.setWrapMode(QTextOption::WrapMode::NoWrap);
|
||||
doc.setDefaultTextOption(option);
|
||||
doc.adjustSize();
|
||||
|
||||
if (doc.size().width() <= maxLineWidth)
|
||||
{
|
||||
m_elidedText = m_text;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTextCursor textCursor(&doc);
|
||||
textCursor.movePosition(QTextCursor::End);
|
||||
|
||||
int ellipsisWidth = 0;
|
||||
|
||||
// At the moment only ElideRight and ElideNone are ever used. This will need expanding if other elision modes are used.
|
||||
if (m_elideMode == Qt::ElideRight)
|
||||
{
|
||||
ellipsisWidth = fontMetrics().horizontalAdvance(ellipsis);
|
||||
}
|
||||
|
||||
// Move the cursor back until the text fits or the start of the text is reached.
|
||||
while (doc.size().width() + ellipsisWidth > maxLineWidth && !textCursor.atStart())
|
||||
{
|
||||
textCursor.deletePreviousChar();
|
||||
doc.adjustSize();
|
||||
}
|
||||
|
||||
if (m_elideMode == Qt::ElideRight)
|
||||
{
|
||||
textCursor.insertText(ellipsis);
|
||||
}
|
||||
|
||||
m_elidedText = doc.toHtml();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_elidedText = fontMetrics().elidedText(m_text, m_elideMode, TextRect().width());
|
||||
}
|
||||
|
||||
QLabel::setText(m_elidedText);
|
||||
|
||||
if (m_elidedText != m_text)
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_ASSET_MANAGER_FLOOD_TEST true
|
||||
#define AZ_TRAIT_DISABLE_ASSETCONTAINERDISABLETEST true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_DLL_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_MODULE_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_TESTS true
|
||||
|
||||
// Golden perline gradiant values for random seed 7878 for this platform
|
||||
#define AZ_TRAIT_UNIT_TEST_PERLINE_GRADIANT_GOLDEN_VALUES_7878 0.5000f, 0.5456f, 0.5138f, 0.4801f, \
|
||||
0.4174f, 0.4942f, 0.5493f, 0.5431f, \
|
||||
0.4984f, 0.5204f, 0.5526f, 0.5840f, \
|
||||
0.5251f, 0.5029f, 0.6153f, 0.5802f,
|
||||
#define AZ_TRAIT_UNIT_TEST_PERLINE_GRADIANT_GOLDEN_VALUES_7878 0.5000f, 0.5276f, 0.5341f, 0.4801f, \
|
||||
0.5220f, 0.5162f, 0.4828f, 0.5431f, \
|
||||
0.4799f, 0.4486f, 0.5054f, 0.4129f, \
|
||||
0.6023f, 0.5029f, 0.4529f, 0.4428f,
|
||||
|
||||
+2
-2
@@ -415,8 +415,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
// Construct the runtime entities and products
|
||||
bool readyToCreateRootSpawnable = m_playInEditorData.m_assetsCache.IsActivated();
|
||||
if (!readyToCreateRootSpawnable &&
|
||||
!m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor))
|
||||
if (!readyToCreateRootSpawnable && !m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor))
|
||||
|
||||
{
|
||||
AZ_Error("Prefab", false, "Failed to create a prefab processing stack from key '%.*s'.", AZ_STRING_ARG(Prefab::PrefabConversionUtils::PlayInEditor));
|
||||
return;
|
||||
|
||||
@@ -184,6 +184,10 @@ namespace AzToolsFramework
|
||||
const float halfGridSquareCount = float(gridSquareCount) * 0.5f;
|
||||
const float halfGridSize = halfGridSquareCount * squareSize;
|
||||
const float fadeLineLength = cl_viewportFadeLineDistanceScale * squareSize;
|
||||
|
||||
// ensure AuxGeomDraw::OpacityType::Translucent render state is set
|
||||
debugDisplay.SetAlpha(0.5f);
|
||||
|
||||
for (size_t lineIndex = 0; lineIndex <= gridSquareCount; ++lineIndex)
|
||||
{
|
||||
const float lineOffset = -halfGridSize + (lineIndex * squareSize);
|
||||
|
||||
@@ -142,14 +142,14 @@ namespace AzToolsFramework
|
||||
return m_templateSourcePath;
|
||||
}
|
||||
|
||||
void Instance::SetTemplateSourcePath(AZ::IO::PathView sourcePath)
|
||||
void Instance::SetTemplateSourcePath(AZ::IO::Path sourcePath)
|
||||
{
|
||||
m_templateSourcePath = sourcePath;
|
||||
m_templateSourcePath = AZStd::move(sourcePath);
|
||||
}
|
||||
|
||||
void Instance::SetContainerEntityName(AZStd::string_view containerName)
|
||||
void Instance::SetContainerEntityName(AZStd::string containerName)
|
||||
{
|
||||
m_containerEntity->SetName(containerName);
|
||||
m_containerEntity->SetName(AZStd::move(containerName));
|
||||
}
|
||||
|
||||
bool Instance::AddEntity(AZ::Entity& entity)
|
||||
@@ -608,6 +608,31 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZ::EntityId Instance::GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const
|
||||
{
|
||||
return GetInstanceAndEntityIdFromAliasPath(relativeAliasPath).second;
|
||||
}
|
||||
|
||||
AZStd::pair<Instance*, AZ::EntityId> Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath)
|
||||
{
|
||||
Instance* instance = this;
|
||||
AliasPathView path = relativeAliasPath.ParentPath();
|
||||
for (auto it : path)
|
||||
{
|
||||
InstanceOptionalReference child = instance->FindNestedInstance(it.Native());
|
||||
if (child.has_value())
|
||||
{
|
||||
instance = &(child->get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZStd::pair<Instance*, AZ::EntityId>(nullptr, AZ::EntityId());
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::pair<Instance*, AZ::EntityId>(instance, instance->GetEntityId(relativeAliasPath.Filename().Native()));
|
||||
}
|
||||
|
||||
AZStd::pair<const Instance*, AZ::EntityId> Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const
|
||||
{
|
||||
const Instance* instance = this;
|
||||
AliasPathView path = relativeAliasPath.ParentPath();
|
||||
@@ -620,11 +645,11 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZ::EntityId();
|
||||
return AZStd::pair<const Instance*, AZ::EntityId>(nullptr, AZ::EntityId());
|
||||
}
|
||||
}
|
||||
|
||||
return instance->GetEntityId(relativeAliasPath.Filename().Native());
|
||||
return AZStd::pair<const Instance*, AZ::EntityId>(instance, instance->GetEntityId(relativeAliasPath.Filename().Native()));
|
||||
}
|
||||
|
||||
AZStd::vector<InstanceAlias> Instance::GetNestedInstanceAliases(TemplateId templateId) const
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace AzToolsFramework
|
||||
void SetTemplateId(TemplateId templateId);
|
||||
|
||||
const AZ::IO::Path& GetTemplateSourcePath() const;
|
||||
void SetTemplateSourcePath(AZ::IO::PathView sourcePath);
|
||||
void SetContainerEntityName(AZStd::string_view containerName);
|
||||
void SetTemplateSourcePath(AZ::IO::Path sourcePath);
|
||||
void SetContainerEntityName(AZStd::string containerName);
|
||||
|
||||
bool AddEntity(AZ::Entity& entity);
|
||||
bool AddEntity(AZStd::unique_ptr<AZ::Entity>&& entity);
|
||||
@@ -169,6 +169,13 @@ namespace AzToolsFramework
|
||||
* @return entityId, invalid ID if not found
|
||||
*/
|
||||
AZ::EntityId GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const;
|
||||
/**
|
||||
* Retrieves the instance pointer and entity id from an alias path that's relative to this instance.
|
||||
*
|
||||
* @return A pair with the Instance and entity id. The Instance is set to null and entityId is set to invalid if not found.
|
||||
*/
|
||||
AZStd::pair<Instance*, AZ::EntityId> GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath);
|
||||
AZStd::pair<const Instance*, AZ::EntityId> GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+9
-38
@@ -37,13 +37,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
|
||||
prefabProcessorContext.ListPrefabs(
|
||||
[this, &serializeContext, &prefabProcessorContext]([[maybe_unused]] AZStd::string_view prefabName, PrefabDom& prefab)
|
||||
[this, &serializeContext, &prefabProcessorContext](PrefabDocument& prefab)
|
||||
{
|
||||
auto result = RemoveEditorInfo(prefab, serializeContext, prefabProcessorContext);
|
||||
if (!result)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false, "Converting to runtime Prefab '%.*s' failed, Error: %s .", AZ_STRING_ARG(prefabName),
|
||||
"Prefab", false, "Converting to runtime Prefab '%s' failed, Error: %s .", prefab.GetName().c_str(),
|
||||
result.GetError().c_str());
|
||||
return;
|
||||
}
|
||||
@@ -58,10 +58,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInfoRemover::GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities)
|
||||
void EditorInfoRemover::GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities)
|
||||
{
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
instance.GetAllEntitiesInHierarchy(
|
||||
[&hierarchyEntities](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
hierarchyEntities.emplace_back(entity.get());
|
||||
@@ -498,7 +497,7 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
|
||||
EditorInfoRemover::RemoveEditorInfoResult EditorInfoRemover::RemoveEditorInfo(
|
||||
PrefabDom& prefab,
|
||||
PrefabDocument& prefab,
|
||||
AZ::SerializeContext* serializeContext,
|
||||
PrefabProcessorContext& prefabProcessorContext)
|
||||
{
|
||||
@@ -510,28 +509,10 @@ exportComponent, prefabProcessorContext);
|
||||
|
||||
m_componentRequirementsValidator.SetPlatformTags(prefabProcessorContext.GetPlatformTags());
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> instance(aznew Instance());
|
||||
if (!Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*instance, prefab,
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
AZStd::string errorMessage("Failed to Load Prefab Instance from given Prefab Dom during Removal of Editor Info.");
|
||||
if (sourceReference.has_value() &&
|
||||
sourceReference->get().IsString() &&
|
||||
sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source));
|
||||
}
|
||||
|
||||
return AZ::Failure(errorMessage);
|
||||
}
|
||||
|
||||
// grab all nested entities from the Instance as source entities.
|
||||
Instance& sourceInstance = prefab.GetInstance();
|
||||
EntityList sourceEntities;
|
||||
GetEntitiesFromInstance(instance, sourceEntities);
|
||||
GetEntitiesFromInstance(sourceInstance, sourceEntities);
|
||||
|
||||
EntityList exportEntities;
|
||||
|
||||
@@ -597,7 +578,7 @@ exportComponent, prefabProcessorContext);
|
||||
exportEntitiesMap.emplace(entity->GetId(), entity);
|
||||
}
|
||||
);
|
||||
instance->RemoveNestedEntities(
|
||||
sourceInstance.RemoveNestedEntities(
|
||||
[&exportEntitiesMap](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
return exportEntitiesMap.find(entity->GetId()) == exportEntitiesMap.end();
|
||||
@@ -605,7 +586,7 @@ exportComponent, prefabProcessorContext);
|
||||
);
|
||||
|
||||
// replace entities of instance with exported ones.
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
sourceInstance.GetAllEntitiesInHierarchy(
|
||||
[&exportEntitiesMap](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
auto entityId = entity->GetId();
|
||||
@@ -614,16 +595,6 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
);
|
||||
|
||||
// save the final result in the target Prefab DOM.
|
||||
PrefabDom filteredPrefab;
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format(
|
||||
"Saving exported Prefab Instance within a Prefab Dom failed.")
|
||||
);
|
||||
}
|
||||
prefab.Swap(filteredPrefab);
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
+2
-3
@@ -43,7 +43,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
using RemoveEditorInfoResult = AZ::Outcome<void, AZStd::string>;
|
||||
RemoveEditorInfoResult RemoveEditorInfo(
|
||||
PrefabDom& prefab,
|
||||
PrefabDocument& prefab,
|
||||
AZ::SerializeContext* serializeContext,
|
||||
PrefabProcessorContext& prefabProcessorContext);
|
||||
|
||||
@@ -51,8 +51,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
protected:
|
||||
using EntityList = AZStd::vector<AZ::Entity*>;
|
||||
static void GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities);
|
||||
static void GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities);
|
||||
|
||||
static bool ReadComponentAttribute(
|
||||
AZ::Component* component,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
enum class EntityAliasType : uint8_t
|
||||
{
|
||||
Disable, //!< No alias is added.
|
||||
OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned.
|
||||
//!< The original entity will be left in the spawnable and a copy is returned.
|
||||
Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original
|
||||
//!< entity is returned and a blank entity is left.
|
||||
Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id.
|
||||
//!< An empty entity will be returned.
|
||||
Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added
|
||||
//!< components may no conflict with the entities already in the root entity.
|
||||
};
|
||||
|
||||
enum class EntityAliasSpawnableLoadBehavior : uint8_t
|
||||
{
|
||||
NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller.
|
||||
QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset
|
||||
//!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow
|
||||
//!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler.
|
||||
DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity
|
||||
//!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable.
|
||||
};
|
||||
|
||||
struct EntityAliasSpawnableLink
|
||||
{
|
||||
EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index);
|
||||
|
||||
AzFramework::Spawnable& m_spawnable;
|
||||
AZ::EntityId m_index;
|
||||
};
|
||||
|
||||
struct EntityAliasPrefabLink
|
||||
{
|
||||
EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias);
|
||||
|
||||
AZStd::string m_prefabName;
|
||||
AzToolsFramework::Prefab::AliasPath m_alias;
|
||||
};
|
||||
|
||||
struct EntityAliasStore
|
||||
{
|
||||
using LinkStore = AZStd::variant<AZStd::monostate, EntityAliasSpawnableLink, EntityAliasPrefabLink>;
|
||||
|
||||
LinkStore m_source;
|
||||
LinkStore m_target;
|
||||
uint32_t m_tag;
|
||||
AzFramework::Spawnable::EntityAliasType m_aliasType;
|
||||
EntityAliasSpawnableLoadBehavior m_loadBehavior;
|
||||
};
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
+3
-3
@@ -112,9 +112,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
// Use a random uuid as this is only a temporary source.
|
||||
PrefabConversionUtils::PrefabProcessorContext context(AZ::Uuid::CreateRandom());
|
||||
PrefabDom copy;
|
||||
copy.CopyFrom(templateReference->get().GetPrefabDom(), copy.GetAllocator(), false);
|
||||
context.AddPrefab(spawnableName, AZStd::move(copy));
|
||||
PrefabDocument document(spawnableName);
|
||||
document.SetPrefabDom(templateReference->get().GetPrefabDom());
|
||||
context.AddPrefab(AZStd::move(document));
|
||||
m_converter.ProcessPrefab(context);
|
||||
|
||||
if (!context.HasCompletedSuccessfully() || context.GetProcessedObjects().empty())
|
||||
|
||||
+28
-39
@@ -25,9 +25,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
AZ::DataStream::StreamType serializationFormat = m_serializationFormat == SerializationFormats::Binary ?
|
||||
AZ::DataStream::StreamType::ST_BINARY : AZ::DataStream::StreamType::ST_XML;
|
||||
context.ListPrefabs([&context, serializationFormat](AZStd::string_view prefabName, PrefabDom& prefab)
|
||||
context.ListPrefabs([&context, serializationFormat](PrefabDocument& prefab)
|
||||
{
|
||||
ProcessPrefab(context, prefabName, prefab, serializationFormat);
|
||||
ProcessPrefab(context, prefab, serializationFormat);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,12 +45,12 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab,
|
||||
void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::SpawnableUtils;
|
||||
|
||||
AZStd::string uniqueName = prefabName;
|
||||
AZStd::string uniqueName = prefab.GetName();
|
||||
uniqueName += AzFramework::Spawnable::DotFileExtension;
|
||||
|
||||
auto serializer = [serializationFormat](AZStd::vector<uint8_t>& output, const ProcessedObjectStore& object) -> bool
|
||||
@@ -64,45 +64,34 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
AZStd::move(uniqueName), context.GetSourceUuid(), AZStd::move(serializer));
|
||||
AZ_Assert(spawnable, "Failed to create a new spawnable.");
|
||||
|
||||
Instance instance;
|
||||
if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(
|
||||
instance, prefab, object.GetReferencedAssets(),
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is
|
||||
// going to be used to create clones of the entities.
|
||||
{
|
||||
// Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are
|
||||
// moved from the instance as they'd otherwise can't be found.
|
||||
context.ResolveSpawnableEntityAliases(prefabName, *spawnable, instance);
|
||||
Instance& instance = prefab.GetInstance();
|
||||
// Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are
|
||||
// moved from the instance as they'd otherwise can't be found.
|
||||
context.ResolveSpawnableEntityAliases(prefab.GetName(), *spawnable, instance);
|
||||
|
||||
AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities();
|
||||
instance.DetachAllEntitiesInHierarchy(
|
||||
[&entities, &context](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities();
|
||||
instance.DetachAllEntitiesInHierarchy(
|
||||
[&entities, &context](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
{
|
||||
if (entity)
|
||||
{
|
||||
if (entity)
|
||||
entity->InvalidateDependencies();
|
||||
AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails();
|
||||
if (evaluation.IsSuccess())
|
||||
{
|
||||
entity->InvalidateDependencies();
|
||||
AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails();
|
||||
if (evaluation.IsSuccess())
|
||||
{
|
||||
entities.emplace_back(AZStd::move(entity));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s",
|
||||
entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str());
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
entities.emplace_back(AZStd::move(entity));
|
||||
}
|
||||
});
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s",
|
||||
entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str());
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable);
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName));
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable);
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
+1
-2
@@ -40,8 +40,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
protected:
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat);
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab, AZ::DataStream::StreamType serializationFormat);
|
||||
|
||||
SerializationFormats m_serializationFormat{ SerializationFormats::Binary };
|
||||
};
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
PrefabDocument::PrefabDocument(AZStd::string name)
|
||||
: m_name(AZStd::move(name))
|
||||
, m_instance(AZStd::make_unique<AzToolsFramework::Prefab::Instance>())
|
||||
{
|
||||
m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name);
|
||||
}
|
||||
|
||||
bool PrefabDocument::SetPrefabDom(const PrefabDom& prefab)
|
||||
{
|
||||
if (ConstructInstanceFromPrefabDom(prefab))
|
||||
{
|
||||
constexpr bool copyConstStrings = true;
|
||||
m_dom.CopyFrom(prefab, m_dom.GetAllocator(), copyConstStrings);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabDocument::SetPrefabDom(PrefabDom&& prefab)
|
||||
{
|
||||
if (ConstructInstanceFromPrefabDom(prefab))
|
||||
{
|
||||
m_dom = AZStd::move(prefab);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::string& PrefabDocument::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const PrefabDom& PrefabDocument::GetDom() const
|
||||
{
|
||||
if (m_isDirty)
|
||||
{
|
||||
m_isDirty = !PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
|
||||
}
|
||||
return m_dom;
|
||||
}
|
||||
|
||||
PrefabDom&& PrefabDocument::TakeDom()
|
||||
{
|
||||
if (m_isDirty)
|
||||
{
|
||||
[[maybe_unused]] bool storedSuccessfully = PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
|
||||
AZ_Assert(storedSuccessfully, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
|
||||
m_isDirty = false;
|
||||
}
|
||||
// After the PrefabDom is moved an empty PrefabDom is left behind. This should be reflected in the Instance,
|
||||
// so reset it so it's empty as well.
|
||||
m_instance->Reset();
|
||||
m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name);
|
||||
return AZStd::move(m_dom);
|
||||
}
|
||||
|
||||
void PrefabDocument::ListEntitiesWithComponentType(
|
||||
AZ::TypeId componentType, const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const
|
||||
{
|
||||
m_instance->GetAllEntitiesInHierarchyConst(
|
||||
[this, &componentType, &callback](const AZ::Entity& entity) -> bool
|
||||
{
|
||||
if (entity.FindComponent(componentType))
|
||||
{
|
||||
return callback(m_instance->GetAliasPathRelativeToInstance(entity.GetId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AZ::Entity* PrefabDocument::CreateEntityAlias(
|
||||
PrefabDocument& source,
|
||||
AzToolsFramework::Prefab::AliasPathView entity,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
auto&& [sourceInstance, entityId] = source.m_instance->GetInstanceAndEntityIdFromAliasPath(entity);
|
||||
if (sourceInstance != nullptr && entityId.IsValid())
|
||||
{
|
||||
return SpawnableUtils::CreateEntityAlias(
|
||||
source.m_name, *sourceInstance, m_name, *m_instance, entityId, aliasType, loadBehavior, tag, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance()
|
||||
{
|
||||
// Assume that changes will be made to the instance.
|
||||
m_isDirty = true;
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
const AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance() const
|
||||
{
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
bool PrefabDocument::ConstructInstanceFromPrefabDom(const PrefabDom& prefab)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
m_instance->Reset();
|
||||
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*m_instance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
AZStd::string_view sourceName = m_name;
|
||||
PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
sourceName = AZStd::string_view(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
}
|
||||
AZ_Error(
|
||||
"PrefabDocument", false, "Failed to construct Prefab instance from given PrefabDOM '%.*s'.", AZ_STRING_ARG(sourceName));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
|
||||
class PrefabDocument final
|
||||
{
|
||||
public:
|
||||
explicit PrefabDocument(AZStd::string name);
|
||||
PrefabDocument(const PrefabDocument&) = delete;
|
||||
PrefabDocument(PrefabDocument&&) = default;
|
||||
|
||||
PrefabDocument& operator=(const PrefabDocument&) = delete;
|
||||
PrefabDocument& operator=(PrefabDocument&&) = default;
|
||||
|
||||
bool SetPrefabDom(const PrefabDom& prefab);
|
||||
bool SetPrefabDom(PrefabDom&& prefab);
|
||||
|
||||
const AZStd::string& GetName() const;
|
||||
const PrefabDom& GetDom() const;
|
||||
PrefabDom&& TakeDom();
|
||||
|
||||
template<typename Component>
|
||||
void ListEntitiesWithComponentType(const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const;
|
||||
void ListEntitiesWithComponentType(
|
||||
AZ::TypeId componentType, const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const;
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
PrefabDocument& source,
|
||||
AzToolsFramework::Prefab::AliasPathView entity,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
|
||||
// Where possible, prefer functions directly on the PrefabDocument Instead of using the Instance.
|
||||
AzToolsFramework::Prefab::Instance& GetInstance();
|
||||
const AzToolsFramework::Prefab::Instance& GetInstance() const;
|
||||
|
||||
private:
|
||||
bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab);
|
||||
|
||||
mutable PrefabDom m_dom;
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> m_instance;
|
||||
AZStd::string m_name;
|
||||
mutable bool m_isDirty{ false };
|
||||
};
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl>
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
template<typename Component>
|
||||
void PrefabDocument::ListEntitiesWithComponentType(const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const
|
||||
{
|
||||
ListEntitiesWithComponentType(azrtti_typeid<Component>(), callback);
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
+57
-15
@@ -7,8 +7,10 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Component/EntityUtils.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
|
||||
@@ -30,27 +32,42 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
: m_sourceUuid(sourceUuid)
|
||||
{}
|
||||
|
||||
bool PrefabProcessorContext::AddPrefab(AZStd::string prefabName, PrefabDom prefab)
|
||||
bool PrefabProcessorContext::AddPrefab(PrefabDocument&& document)
|
||||
{
|
||||
auto result = m_prefabs.emplace(AZStd::move(prefabName), AZStd::move(prefab));
|
||||
return result.second;
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, PrefabDom&)>& callback)
|
||||
{
|
||||
m_isIterating = true;
|
||||
for (auto& it : m_prefabs)
|
||||
AZStd::string name = document.GetName();
|
||||
if (!m_prefabNames.contains(name))
|
||||
{
|
||||
callback(it.first, it.second);
|
||||
m_prefabNames.emplace(AZStd::move(name));
|
||||
// If currently iterating add to pending queue to avoid invalidating the container that's being iterated over.
|
||||
PrefabContainer& container = m_isIterating ? m_pendingPrefabAdditions : m_prefabs;
|
||||
container.push_back(AZStd::move(document));
|
||||
return true;
|
||||
}
|
||||
m_isIterating = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, const PrefabDom&)>& callback) const
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(PrefabDocument&)>& callback)
|
||||
{
|
||||
for (const auto& it : m_prefabs)
|
||||
// Enable iterating state so the prefab container doesn't get invalided. Enabling this flag will cause new prefabs
|
||||
// to be stored in a temporary buffer that can be moved into the regular prefab container after iterating.
|
||||
m_isIterating = true;
|
||||
for (PrefabDocument& document : m_prefabs)
|
||||
{
|
||||
callback(it.first, it.second);
|
||||
callback(document);
|
||||
}
|
||||
|
||||
m_isIterating = false;
|
||||
m_prefabs.insert(
|
||||
m_prefabs.end(), AZStd::make_move_iterator(m_pendingPrefabAdditions.begin()),
|
||||
AZStd::make_move_iterator(m_pendingPrefabAdditions.end()));
|
||||
m_pendingPrefabAdditions.clear();
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(const PrefabDocument&)>& callback) const
|
||||
{
|
||||
for (const PrefabDocument& document : m_prefabs)
|
||||
{
|
||||
callback(document);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +149,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
// Resolve prefab links into spawnable links for the provided spawnable.
|
||||
for (EntityAliasStore& entityAlias : m_entityAliases)
|
||||
{
|
||||
auto sourcePrefab = AZStd::get_if<EntityAliasPrefabLink>(&entityAlias.m_source);
|
||||
@@ -224,11 +242,35 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
it = aliasVisitors.emplace(source->m_spawnable.GetId(), AZStd::move(visitor)).first;
|
||||
}
|
||||
it->second.AddAlias(
|
||||
AZ::Data::Asset<AzFramework::Spawnable>(&target->m_spawnable, loadBehavior), alias.m_tag, sourceIndex, targetIndex,
|
||||
AZ::Data::Asset<AzFramework::Spawnable>(target->m_spawnable.GetId(), azrtti_typeid<AzFramework::Spawnable>()), alias.m_tag,
|
||||
sourceIndex, targetIndex,
|
||||
alias.m_aliasType, alias.m_loadBehavior == EntityAliasSpawnableLoadBehavior::QueueLoad);
|
||||
|
||||
// Register the dependency between the two spawnables.
|
||||
RegisterProductAssetDependency(source->m_spawnable.GetId(), target->m_spawnable.GetId(), loadBehavior);
|
||||
|
||||
// Patch up all entity ids so the alias points to the same entity id if needed.
|
||||
switch (alias.m_aliasType)
|
||||
{
|
||||
case AzFramework::Spawnable::EntityAliasType::Original:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Disable:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Replace:
|
||||
break; // Requires entity id for alias in source and target spawnable matches.
|
||||
case AzFramework::Spawnable::EntityAliasType::Additional:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Merge:
|
||||
break; // Requires entity id for alias in source and target spawnable matches.
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
auto entityIdMapper = [source, target](const AZ::EntityId& originalId, bool /*isEntityId*/) -> AZ::EntityId
|
||||
{
|
||||
return originalId == target->m_index ? source->m_index : originalId;
|
||||
};
|
||||
AZ::EntityUtils::ReplaceEntityIdsAndEntityRefs(&target->m_spawnable, entityIdMapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-55
@@ -21,60 +21,12 @@
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
enum class EntityAliasType : uint8_t
|
||||
{
|
||||
Disable, //!< No alias is added.
|
||||
OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned.
|
||||
//!< The original entity will be left in the spawnable and a copy is returned.
|
||||
Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original
|
||||
//!< entity is returned and a blank entity is left.
|
||||
Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id.
|
||||
//!< An empty entity will be returned.
|
||||
Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added
|
||||
//!< components may no conflict with the entities already in the root entity.
|
||||
};
|
||||
|
||||
enum class EntityAliasSpawnableLoadBehavior : uint8_t
|
||||
{
|
||||
NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller.
|
||||
QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset
|
||||
//!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow
|
||||
//!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler.
|
||||
DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity
|
||||
//!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable.
|
||||
};
|
||||
|
||||
struct EntityAliasSpawnableLink
|
||||
{
|
||||
EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index);
|
||||
|
||||
AzFramework::Spawnable& m_spawnable;
|
||||
AZ::EntityId m_index;
|
||||
};
|
||||
|
||||
struct EntityAliasPrefabLink
|
||||
{
|
||||
EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias);
|
||||
|
||||
AZStd::string m_prefabName;
|
||||
AzToolsFramework::Prefab::AliasPath m_alias;
|
||||
};
|
||||
|
||||
struct EntityAliasStore
|
||||
{
|
||||
using LinkStore = AZStd::variant<AZStd::monostate, EntityAliasSpawnableLink, EntityAliasPrefabLink>;
|
||||
|
||||
LinkStore m_source;
|
||||
LinkStore m_target;
|
||||
uint32_t m_tag;
|
||||
AzFramework::Spawnable::EntityAliasType m_aliasType;
|
||||
EntityAliasSpawnableLoadBehavior m_loadBehavior;
|
||||
};
|
||||
|
||||
struct AssetDependencyInfo
|
||||
{
|
||||
AZ::Data::AssetId m_assetId;
|
||||
@@ -93,9 +45,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
explicit PrefabProcessorContext(const AZ::Uuid& sourceUuid);
|
||||
virtual ~PrefabProcessorContext() = default;
|
||||
|
||||
virtual bool AddPrefab(AZStd::string prefabName, PrefabDom prefab);
|
||||
virtual void ListPrefabs(const AZStd::function<void(AZStd::string_view, PrefabDom&)>& callback);
|
||||
virtual void ListPrefabs(const AZStd::function<void(AZStd::string_view, const PrefabDom&)>& callback) const;
|
||||
virtual bool AddPrefab(PrefabDocument&& document);
|
||||
virtual void ListPrefabs(const AZStd::function<void(PrefabDocument&)>& callback);
|
||||
virtual void ListPrefabs(const AZStd::function<void(const PrefabDocument&)>& callback) const;
|
||||
virtual bool HasPrefabs() const;
|
||||
|
||||
virtual bool RegisterSpawnableProductAssetDependency(
|
||||
@@ -128,12 +80,15 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
virtual void ErrorEncountered();
|
||||
|
||||
protected:
|
||||
using NamedPrefabContainer = AZStd::unordered_map<AZStd::string, PrefabDom>;
|
||||
using PrefabNames = AZStd::unordered_set<AZStd::string>;
|
||||
using PrefabContainer = AZStd::vector<PrefabDocument>;
|
||||
using SpawnableEntityAliasStore = AZStd::vector<EntityAliasStore>;
|
||||
|
||||
AZ::Data::AssetLoadBehavior ToAssetLoadBehavior(EntityAliasSpawnableLoadBehavior loadBehavior) const;
|
||||
|
||||
NamedPrefabContainer m_prefabs;
|
||||
PrefabContainer m_prefabs;
|
||||
PrefabContainer m_pendingPrefabAdditions;
|
||||
PrefabNames m_prefabNames;
|
||||
SpawnableEntityAliasStore m_entityAliases;
|
||||
ProcessedObjectStoreContainer m_products;
|
||||
ProductAssetDependencyContainer m_registeredProductAssetDependencies;
|
||||
|
||||
+43
-110
@@ -16,10 +16,12 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
{
|
||||
@@ -52,14 +54,32 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
return result;
|
||||
}
|
||||
|
||||
const AZ::Entity* FindEntity(AZ::EntityId entityId, const AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
const AZ::Entity* result = nullptr;
|
||||
source.GetConstEntities(
|
||||
[&result, entityId](const AZ::Entity& entity)
|
||||
{
|
||||
if (entity.GetId() != entityId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = &entity;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
AZ::Entity* FindEntity(AZ::EntityId entityId, AzFramework::Spawnable& source)
|
||||
{
|
||||
uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source);
|
||||
return index != InvalidEntityIndex ? source.GetEntities()[index].get() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
AZStd::unique_ptr<AZ::Entity> CloneEntity(AZ::EntityId entityId, T& source)
|
||||
AZStd::unique_ptr<AZ::Entity> CloneEntity(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
AZ::Entity* target = Internal::FindEntity(entityId, source);
|
||||
AZ_Assert(
|
||||
@@ -74,41 +94,30 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
return clone;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source)
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(
|
||||
AZ::EntityId entityId,
|
||||
[[maybe_unused]] AZStd::string_view sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
auto&& [instance, alias] = source.FindInstanceAndAlias(entityId);
|
||||
AZ_Assert(
|
||||
instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%s' for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId), source.GetTemplateSourcePath().c_str());
|
||||
instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%.*s' for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId), AZ_STRING_ARG(sourcePrefabName));
|
||||
|
||||
EntityOptionalReference entityData = instance->GetEntity(alias);
|
||||
AZ_Assert(
|
||||
entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%s' for replacing.",
|
||||
AZ_STRING_ARG(alias), source.GetTemplateSourcePath().c_str());
|
||||
auto placeholder = AZStd::make_unique<AZ::Entity>(entityData->get().GetId(), entityData->get().GetName());
|
||||
entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%.*s' for replacing.",
|
||||
AZ_STRING_ARG(alias), AZ_STRING_ARG(sourcePrefabName));
|
||||
// A new entity id can be used for the placeholder as `ReplaceEntity` will swap the entity ids.
|
||||
auto placeholder = AZStd::make_unique<AZ::Entity>(AZ::Entity::MakeId(), entityData->get().GetName());
|
||||
return instance->ReplaceEntity(AZStd::move(placeholder), alias);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzFramework::Spawnable& source)
|
||||
{
|
||||
uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source);
|
||||
AZ_Assert(
|
||||
index != InvalidEntityIndex, "SpawnbleUtils were unable to locate entity alias with id %zu in Spawnable for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId));
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> original = AZStd::move(source.GetEntities()[index]);
|
||||
AZ_Assert(
|
||||
original, "SpawnbleUtils were unable to locate entity with id %zu in Spawnable for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId));
|
||||
|
||||
source.GetEntities()[index] = AZStd::make_unique<AZ::Entity>(original->GetId(), original->GetName());
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
AZStd::pair<AZStd::unique_ptr<AZ::Entity>, AzFramework::Spawnable::EntityAliasType> ApplyAlias(
|
||||
Source& source, AZ::EntityId entityId, AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType)
|
||||
AZStd::string_view sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType)
|
||||
{
|
||||
namespace PCU = AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
using ResultPair = AZStd::pair<AZStd::unique_ptr<AZ::Entity>, AzFramework::Spawnable::EntityAliasType>;
|
||||
@@ -121,12 +130,13 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
case PCU::EntityAliasType::OptionalReplace:
|
||||
return ResultPair(CloneEntity(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
case PCU::EntityAliasType::Replace:
|
||||
return ResultPair(ReplaceEntityWithPlaceholder(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
return ResultPair(
|
||||
ReplaceEntityWithPlaceholder(entityId, sourcePrefabName, source),
|
||||
AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
case PCU::EntityAliasType::Additional:
|
||||
ResultPair(AZStd::make_unique<AZ::Entity>(AZ::Entity::MakeId()), AzFramework::Spawnable::EntityAliasType::Additional);
|
||||
return ResultPair(AZStd::make_unique<AZ::Entity>(), AzFramework::Spawnable::EntityAliasType::Additional);
|
||||
case PCU::EntityAliasType::Merge:
|
||||
// Use the same entity id as the original entity so at runtime the entity ids can be verified to match.
|
||||
ResultPair(AZStd::make_unique<AZ::Entity>(entityId), AzFramework::Spawnable::EntityAliasType::Merge);
|
||||
return ResultPair(AZStd::make_unique<AZ::Entity>(), AzFramework::Spawnable::EntityAliasType::Merge);
|
||||
default:
|
||||
AZ_Assert(
|
||||
false, "Invalid PrefabProcessorContext::EntityAliasType type (%i) provided.", aznumeric_cast<uint64_t>(aliasType));
|
||||
@@ -182,7 +192,8 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
AliasPath alias = source.GetAliasPathRelativeToInstance(entityId);
|
||||
if (!alias.empty())
|
||||
{
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
auto&& [replacement, storedAliasType] =
|
||||
Internal::ApplyAlias(sourcePrefabName, source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
@@ -212,84 +223,6 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AZStd::string sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
|
||||
AliasPath alias = source.GetAliasPathRelativeToInstance(entityId);
|
||||
if (!alias.empty())
|
||||
{
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
target.GetEntities().push_back(AZStd::move(replacement));
|
||||
|
||||
EntityAliasStore store;
|
||||
store.m_aliasType = storedAliasType;
|
||||
store.m_source.emplace<EntityAliasPrefabLink>(AZStd::move(sourcePrefabName), AZStd::move(alias));
|
||||
store.m_target.emplace<EntityAliasSpawnableLink>(target, result->GetId());
|
||||
store.m_tag = tag;
|
||||
store.m_loadBehavior = loadBehavior;
|
||||
context.RegisterSpawnableEntityAlias(AZStd::move(store));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Entity with id %llu was not found in the source prefab.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AzFramework::Spawnable& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
target.GetEntities().push_back(AZStd::move(replacement));
|
||||
|
||||
EntityAliasStore store;
|
||||
store.m_aliasType = storedAliasType;
|
||||
store.m_source.emplace<EntityAliasSpawnableLink>(source, entityId);
|
||||
store.m_target.emplace<EntityAliasSpawnableLink>(target, result->GetId());
|
||||
store.m_tag = tag;
|
||||
store.m_loadBehavior = loadBehavior;
|
||||
context.RegisterSpawnableEntityAlias(AZStd::move(store));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable)
|
||||
{
|
||||
auto begin = spawnable.GetEntities().begin();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <AzCore/std/limits.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -24,6 +24,11 @@ namespace AzToolsFramework::Prefab
|
||||
class Instance;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
{
|
||||
static constexpr uint32_t InvalidEntityIndex = AZStd::numeric_limits<uint32_t>::max();
|
||||
@@ -41,24 +46,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AZStd::string sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AzFramework::Spawnable& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
|
||||
|
||||
uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable);
|
||||
|
||||
void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable);
|
||||
|
||||
+1
@@ -421,6 +421,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
QString label{ text };
|
||||
m_nameLabel->setText(label);
|
||||
m_nameLabel->setOpenExternalLinks(true);
|
||||
m_nameLabel->setVisible(!label.isEmpty());
|
||||
// setting the stretches to 0 in case of an empty label really hides the label (i.e. even the reserved space)
|
||||
m_mainLayout->setStretch(0, label.isEmpty() ? 0 : LabelColumnStretch);
|
||||
|
||||
+24
-5
@@ -30,8 +30,7 @@ namespace UnitTest
|
||||
void MousePressAndMove(
|
||||
QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton)
|
||||
{
|
||||
QPoint position = widget->mapToGlobal(initialPositionWidget);
|
||||
QTest::mousePress(widget, mouseButton, Qt::NoModifier, position);
|
||||
QTest::mousePress(widget, mouseButton, Qt::NoModifier, initialPositionWidget);
|
||||
|
||||
MouseMove(widget, initialPositionWidget, mouseDelta, mouseButton);
|
||||
}
|
||||
@@ -45,14 +44,15 @@ namespace UnitTest
|
||||
// - https://lists.qt-project.org/pipermail/development/2019-July/036873.html
|
||||
void MouseMove(QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton)
|
||||
{
|
||||
QPoint nextPosition = widget->mapToGlobal(initialPositionWidget + mouseDelta);
|
||||
const QPoint nextLocalPosition = initialPositionWidget + mouseDelta;
|
||||
const QPoint nextGlobalPosition = widget->mapToGlobal(nextLocalPosition);
|
||||
|
||||
// ^1 To ensure a mouse move event is fired we must call the test mouse move function
|
||||
// and also send a mouse move event that matches. Each on their own do not appear to
|
||||
// work - please see the links above for more context.
|
||||
QTest::mouseMove(widget, nextPosition);
|
||||
QTest::mouseMove(widget, nextLocalPosition);
|
||||
QMouseEvent mouseMoveEvent(
|
||||
QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), Qt::NoButton, mouseButton, Qt::NoModifier);
|
||||
QEvent::MouseMove, QPointF(nextLocalPosition), QPointF(nextGlobalPosition), Qt::NoButton, mouseButton, Qt::NoModifier);
|
||||
QApplication::sendEvent(widget, &mouseMoveEvent);
|
||||
}
|
||||
|
||||
@@ -157,6 +157,23 @@ namespace UnitTest
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
MouseMoveDetector::MouseMoveDetector(QWidget* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool MouseMoveDetector::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (const auto eventType = event->type(); eventType == QEvent::Type::MouseMove)
|
||||
{
|
||||
auto mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
m_mouseGlobalPosition = mouseEvent->globalPos();
|
||||
m_mouseLocalPosition = mouseEvent->pos();
|
||||
}
|
||||
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void TestEditorActions::Connect()
|
||||
{
|
||||
using AzToolsFramework::GetEntityContextId;
|
||||
@@ -571,3 +588,5 @@ namespace UnitTest
|
||||
sliceAssets.clear();
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
#include <moc_AzToolsFrameworkTestHelpers.cpp>
|
||||
|
||||
+20
-1
@@ -111,10 +111,29 @@ namespace UnitTest
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FocusInteractionWidget(QWidget* parent = nullptr) : QWidget(parent) {}
|
||||
FocusInteractionWidget(QWidget* parent = nullptr)
|
||||
: QWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
};
|
||||
|
||||
/// Records mouse move events and stores the local and global position of the cursor.
|
||||
/// @note To use, install as an event filter for the widget being interacted with
|
||||
/// e.g. m_testWidget->installEventFilter(&m_mouseMoveDetector);
|
||||
class MouseMoveDetector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MouseMoveDetector(QWidget* parent = nullptr);
|
||||
|
||||
bool eventFilter([[maybe_unused]] QObject* watched, QEvent* event) override;
|
||||
|
||||
QPoint m_mouseGlobalPosition;
|
||||
QPoint m_mouseLocalPosition;
|
||||
};
|
||||
|
||||
/// Stores actions registered for either normal mode (regular viewport) editing and
|
||||
/// component mode editing.
|
||||
class TestEditorActions
|
||||
|
||||
@@ -723,6 +723,7 @@ set(FILES
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/UiEditorOnlyEntityHandler.cpp
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.h
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.cpp
|
||||
Prefab/Spawnable/EntityAliasTypes.h
|
||||
Prefab/Spawnable/InMemorySpawnableAssetContainer.h
|
||||
Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp
|
||||
Prefab/Spawnable/PrefabCatchmentProcessor.h
|
||||
@@ -730,6 +731,9 @@ set(FILES
|
||||
Prefab/Spawnable/PrefabConversionPipeline.h
|
||||
Prefab/Spawnable/PrefabConversionPipeline.cpp
|
||||
Prefab/Spawnable/PrefabConverterStackProfileNames.h
|
||||
Prefab/Spawnable/PrefabDocument.h
|
||||
Prefab/Spawnable/PrefabDocument.inl
|
||||
Prefab/Spawnable/PrefabDocument.cpp
|
||||
Prefab/Spawnable/ProcesedObjectStore.h
|
||||
Prefab/Spawnable/ProcesedObjectStore.cpp
|
||||
Prefab/Spawnable/PrefabProcessor.h
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class AzToolsFrameworkTestHelpersFixture : public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsTestFixture::SetUp();
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(0, 0);
|
||||
m_rootWidget->setMouseTracking(true);
|
||||
m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner
|
||||
|
||||
m_mouseMoveDetector = AZStd::make_unique<MouseMoveDetector>();
|
||||
m_rootWidget->installEventFilter(m_mouseMoveDetector.get());
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_rootWidget->removeEventFilter(m_mouseMoveDetector.get());
|
||||
m_rootWidget.reset();
|
||||
m_mouseMoveDetector.reset();
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<QWidget> m_rootWidget;
|
||||
AZStd::unique_ptr<MouseMoveDetector> m_mouseMoveDetector;
|
||||
};
|
||||
|
||||
struct MouseMoveParams
|
||||
{
|
||||
QSize m_widgetSize;
|
||||
QPoint m_widgetPosition;
|
||||
QPoint m_localCursorPosition;
|
||||
QPoint m_cursorDelta;
|
||||
};
|
||||
|
||||
class MouseMoveAzToolsFrameworkTestHelperFixture
|
||||
: public AzToolsFrameworkTestHelpersFixture
|
||||
, public ::testing::WithParamInterface<MouseMoveParams>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(MouseMoveAzToolsFrameworkTestHelperFixture, MouseMoveCorrectlyTransformsCursorPositionInGlobalAndLocalSpace)
|
||||
{
|
||||
// given
|
||||
const MouseMoveParams mouseMoveParams = GetParam();
|
||||
m_rootWidget->move(mouseMoveParams.m_widgetPosition);
|
||||
m_rootWidget->setFixedSize(mouseMoveParams.m_widgetSize);
|
||||
|
||||
// when
|
||||
MouseMove(m_rootWidget.get(), mouseMoveParams.m_localCursorPosition, mouseMoveParams.m_cursorDelta);
|
||||
|
||||
// then
|
||||
const QPoint mouseLocalPosition = m_mouseMoveDetector->m_mouseLocalPosition;
|
||||
const QPoint mouseLocalPositionFromGlobal = m_rootWidget->mapFromGlobal(m_mouseMoveDetector->m_mouseGlobalPosition);
|
||||
const QPoint expectedPosition = mouseMoveParams.m_localCursorPosition + mouseMoveParams.m_cursorDelta;
|
||||
|
||||
using ::testing::Eq;
|
||||
EXPECT_THAT(mouseLocalPosition.x(), Eq(expectedPosition.x()));
|
||||
EXPECT_THAT(mouseLocalPosition.y(), Eq(expectedPosition.y()));
|
||||
EXPECT_THAT(mouseLocalPositionFromGlobal.x(), Eq(expectedPosition.x()));
|
||||
EXPECT_THAT(mouseLocalPositionFromGlobal.y(), Eq(expectedPosition.y()));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
All,
|
||||
MouseMoveAzToolsFrameworkTestHelperFixture,
|
||||
testing::Values(
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(0, 0), QPoint(0, 0), QPoint(10, 10) },
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(100, 100), QPoint(0, 0), QPoint(10, 10) },
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(20, 20), QPoint(50, 50), QPoint(20, 20) }));
|
||||
} // namespace UnitTest
|
||||
+5
-4
@@ -25,7 +25,7 @@ namespace Benchmark
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spwanableCounter = 0; spwanableCounter < spawnAllEntitiesCallCount; spwanableCounter++)
|
||||
@@ -62,7 +62,7 @@ namespace Benchmark
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
@@ -93,15 +93,16 @@ namespace Benchmark
|
||||
|
||||
SetUpSpawnableAsset(entityCountInSpawnable);
|
||||
|
||||
auto spawner = AzFramework::SpawnableEntitiesInterface::Get();
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spawnCallCounter = 0; spawnCallCounter < spawnCallCount; spawnCallCounter++)
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
spawner->SpawnAllEntities(*m_spawnTicket);
|
||||
}
|
||||
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
|
||||
+5
-5
@@ -9,6 +9,7 @@
|
||||
#include <Prefab/SpawnableRemoveEditorInfoTestFixture.h>
|
||||
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorOnlyEntityComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorOnlyEntityComponentBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
@@ -201,15 +202,14 @@ namespace UnitTest
|
||||
{
|
||||
ConvertSourceEntitiesToPrefab();
|
||||
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument prefab("Test");
|
||||
prefab.SetPrefabDom(m_prefabDom);
|
||||
const bool actualResult =
|
||||
m_editorInfoRemover.RemoveEditorInfo(m_prefabDom, m_serializeContext, m_prefabProcessorContext).IsSuccess();
|
||||
m_editorInfoRemover.RemoveEditorInfo(prefab, m_serializeContext, m_prefabProcessorContext).IsSuccess();
|
||||
|
||||
EXPECT_EQ(expectedResult, actualResult);
|
||||
|
||||
AZStd::unique_ptr<Instance> convertedInstance(aznew Instance());
|
||||
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom));
|
||||
|
||||
convertedInstance->DetachAllEntitiesInHierarchy(
|
||||
prefab.GetInstance().DetachAllEntitiesInHierarchy(
|
||||
[this](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
{
|
||||
m_runtimeEntities.emplace_back(entity.release());
|
||||
|
||||
@@ -12,6 +12,7 @@ set(FILES
|
||||
AssetFileInfoListComparison.cpp
|
||||
AssetSeedManager.cpp
|
||||
AssetSystemMocks.h
|
||||
AzToolsFrameworkTestHelpersTest.cpp
|
||||
BoundsTestComponent.cpp
|
||||
BoundsTestComponent.h
|
||||
ComponentAdapterTests.cpp
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 0
|
||||
#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 1
|
||||
|
||||
@@ -17,7 +17,7 @@ struct VSInput
|
||||
|
||||
struct VSDepthOutput
|
||||
{
|
||||
float4 m_position : SV_Position;
|
||||
precise float4 m_position : SV_Position;
|
||||
};
|
||||
|
||||
VSDepthOutput DepthPassVS(VSInput IN)
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex);
|
||||
float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb);
|
||||
float4 albedo = PassSrg::m_albedo.Load(screenCoords, sampleIndex);
|
||||
float probeIrradianceBlendWeight = PassSrg::m_downsampledProbeIrradiance.Load(probeIrradianceCoords, sampleIndex).a;
|
||||
float probeIrradianceBlendWeight = saturate(PassSrg::m_downsampledProbeIrradiance.Load(probeIrradianceCoords, sampleIndex).a);
|
||||
|
||||
float3 diffuse = float3(0.0f, 0.0f, 0.0f);
|
||||
if (probeIrradianceBlendWeight > 0.0f)
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+18
-4
@@ -102,8 +102,17 @@ namespace AZ
|
||||
|
||||
void DiffuseProbeGrid::SetProbeSpacing(const AZ::Vector3& probeSpacing)
|
||||
{
|
||||
// remove previous spacing from the render extents
|
||||
m_renderExtents -= m_probeSpacing;
|
||||
|
||||
// update probe spacing
|
||||
m_probeSpacing = probeSpacing;
|
||||
|
||||
// expand the extents by one probe spacing unit in order to blend properly around the edges of the volume
|
||||
m_renderExtents += m_probeSpacing;
|
||||
|
||||
m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f);
|
||||
|
||||
// recompute the number of probes since the spacing changed
|
||||
UpdateProbeCount();
|
||||
|
||||
@@ -128,7 +137,8 @@ namespace AZ
|
||||
void DiffuseProbeGrid::SetTransform(const AZ::Transform& transform)
|
||||
{
|
||||
m_transform = transform;
|
||||
m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_extents / 2.0f);
|
||||
|
||||
m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f);
|
||||
|
||||
// probes need to be relocated since the grid position changed
|
||||
m_remainingRelocationIterations = DefaultNumRelocationIterations;
|
||||
@@ -144,11 +154,15 @@ namespace AZ
|
||||
void DiffuseProbeGrid::SetExtents(const AZ::Vector3& extents)
|
||||
{
|
||||
m_extents = extents;
|
||||
m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_extents / 2.0f);
|
||||
|
||||
// recompute the number of probes since the extents changed
|
||||
UpdateProbeCount();
|
||||
|
||||
// expand the extents by one probe spacing unit in order to blend properly around the edges of the volume
|
||||
m_renderExtents = m_extents + m_probeSpacing;
|
||||
|
||||
m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f);
|
||||
|
||||
// probes need to be relocated since the grid extents changed
|
||||
m_remainingRelocationIterations = DefaultNumRelocationIterations;
|
||||
|
||||
@@ -700,11 +714,11 @@ namespace AZ
|
||||
RHI::ShaderInputImageIndex imageIndex;
|
||||
|
||||
constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_modelToWorld"));
|
||||
AZ::Matrix3x4 modelToWorld = AZ::Matrix3x4::CreateFromTransform(m_transform) * AZ::Matrix3x4::CreateScale(m_extents);
|
||||
AZ::Matrix3x4 modelToWorld = AZ::Matrix3x4::CreateFromTransform(m_transform) * AZ::Matrix3x4::CreateScale(m_renderExtents);
|
||||
m_renderObjectSrg->SetConstant(constantIndex, modelToWorld);
|
||||
|
||||
constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_modelToWorldInverse"));
|
||||
AZ::Matrix3x4 modelToWorldInverse = AZ::Matrix3x4::CreateFromTransform(m_transform).GetInverseFull();
|
||||
AZ::Matrix3x4 modelToWorldInverse = modelToWorld.GetInverseFull();
|
||||
m_renderObjectSrg->SetConstant(constantIndex, modelToWorldInverse);
|
||||
|
||||
constantIndex = srgLayout->FindShaderInputConstantIndex(Name("m_obbHalfLengths"));
|
||||
|
||||
@@ -183,11 +183,14 @@ namespace AZ
|
||||
// extents of the probe grid
|
||||
AZ::Vector3 m_extents = AZ::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// expanded extents for rendering the volume
|
||||
AZ::Vector3 m_renderExtents = AZ::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// probe grid OBB (world space), built from transform and extents
|
||||
AZ::Obb m_obbWs;
|
||||
|
||||
// per-axis spacing of probes in the grid
|
||||
AZ::Vector3 m_probeSpacing;
|
||||
AZ::Vector3 m_probeSpacing = AZ::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// per-axis number of probes in the grid
|
||||
uint32_t m_probeCountX = 0;
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
#
|
||||
#
|
||||
|
||||
set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_TEST TRUE)
|
||||
set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_TEST FALSE)
|
||||
set(ATOM_RHI_TRAIT_BUILD_SUPPORTS_EDIT TRUE)
|
||||
set(PAL_TRAIT_BUILD_RENDERDOC_SUPPORTED FALSE)
|
||||
|
||||
@@ -348,14 +348,7 @@ namespace AZ::AtomBridge
|
||||
void AtomDebugDisplayViewportInterface::SetAlpha(float a)
|
||||
{
|
||||
m_rendState.m_color.SetA(a);
|
||||
if (a < 1.0f)
|
||||
{
|
||||
m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent;
|
||||
}
|
||||
m_rendState.m_opacityType = a < 1.0f ? AZ::RPI::AuxGeomDraw::OpacityType::Translucent : AZ::RPI::AuxGeomDraw::OpacityType::Opaque;
|
||||
}
|
||||
|
||||
void AtomDebugDisplayViewportInterface::DrawQuad(
|
||||
|
||||
@@ -20,11 +20,10 @@
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor;
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore;
|
||||
|
||||
void NetworkPrefabProcessor::Process(PrefabProcessorContext& context)
|
||||
void NetworkPrefabProcessor::Process(AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument;
|
||||
|
||||
IMultiplayerTools* mpTools = AZ::Interface<IMultiplayerTools>::Get();
|
||||
if (mpTools)
|
||||
{
|
||||
@@ -33,11 +32,17 @@ namespace Multiplayer
|
||||
|
||||
AZ::DataStream::StreamType serializationFormat = GetAzSerializationFormat();
|
||||
|
||||
context.ListPrefabs([&context, serializationFormat](AZStd::string_view prefabName, PrefabDom& prefab) {
|
||||
ProcessPrefab(context, prefabName, prefab, serializationFormat);
|
||||
});
|
||||
bool networkPrefabsAdded = false;
|
||||
context.ListPrefabs(
|
||||
[&networkPrefabsAdded, &context, serializationFormat](PrefabDocument& prefab)
|
||||
{
|
||||
if (ProcessPrefab(context, prefab, serializationFormat))
|
||||
{
|
||||
networkPrefabsAdded = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (mpTools && !context.GetProcessedObjects().empty())
|
||||
if (mpTools && networkPrefabsAdded)
|
||||
{
|
||||
mpTools->SetDidProcessNetworkPrefabs(true);
|
||||
}
|
||||
@@ -59,28 +64,6 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
static AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> LoadInstanceFromPrefab(const PrefabDom& prefab)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> sourceInstance(aznew Instance());
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
AZStd::string errorMessage("NetworkPrefabProcessor: Failed to Load Prefab Instance from given Prefab Dom.");
|
||||
if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source));
|
||||
}
|
||||
AZ_Error("NetworkPrefabProcessor", false, errorMessage.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
return sourceInstance;
|
||||
}
|
||||
|
||||
static void GatherNetEntities(
|
||||
AzToolsFramework::Prefab::Instance* instance,
|
||||
AZStd::unordered_map<AZ::Entity*, AzToolsFramework::Prefab::Instance*>& entityToInstanceMap,
|
||||
@@ -103,18 +86,15 @@ namespace Multiplayer
|
||||
});
|
||||
}
|
||||
|
||||
void NetworkPrefabProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, AZ::DataStream::StreamType serializationFormat)
|
||||
bool NetworkPrefabProcessor::ProcessPrefab(
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat)
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore;
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> sourceInstance = LoadInstanceFromPrefab(prefab);
|
||||
if (!sourceInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string uniqueName = prefabName;
|
||||
AZStd::string uniqueName = prefab.GetName();
|
||||
uniqueName += ".network.spawnable";
|
||||
|
||||
auto serializer = [serializationFormat](AZStd::vector<uint8_t>& output, const ProcessedObjectStore& object) -> bool {
|
||||
@@ -127,15 +107,16 @@ namespace Multiplayer
|
||||
ProcessedObjectStore::Create<AzFramework::Spawnable>(uniqueName, context.GetSourceUuid(), AZStd::move(serializer));
|
||||
auto& netSpawnableEntities = networkSpawnable->GetEntities();
|
||||
|
||||
Instance& sourceInstance = prefab.GetInstance();
|
||||
// Grab all net entities with their corresponding Instances to handle nested prefabs correctly
|
||||
AZStd::unordered_map<AZ::Entity*, AzToolsFramework::Prefab::Instance*> netEntityToInstanceMap;
|
||||
AZStd::vector<AZ::Entity*> prefabNetEntities;
|
||||
GatherNetEntities(sourceInstance.get(), netEntityToInstanceMap, prefabNetEntities);
|
||||
GatherNetEntities(&sourceInstance, netEntityToInstanceMap, prefabNetEntities);
|
||||
|
||||
if (prefabNetEntities.empty())
|
||||
{
|
||||
// No networked entities in the prefab, no need to do anything in this processor.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sort the entities prior to processing. The entities will end up in the net spawnable in this order.
|
||||
@@ -182,7 +163,7 @@ namespace Multiplayer
|
||||
|
||||
// Add net spawnable asset holder to the prefab root
|
||||
{
|
||||
EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity();
|
||||
EntityOptionalReference containerEntityRef = sourceInstance.GetContainerEntity();
|
||||
if (containerEntityRef.has_value())
|
||||
{
|
||||
auto* networkSpawnableHolderComponent = containerEntityRef.value().get().CreateComponent<NetworkSpawnableHolderComponent>();
|
||||
@@ -193,18 +174,12 @@ namespace Multiplayer
|
||||
AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName);
|
||||
auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent<NetworkSpawnableHolderComponent>();
|
||||
networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset);
|
||||
sourceInstance->AddEntity(*networkSpawnableHolderEntity);
|
||||
sourceInstance.AddEntity(*networkSpawnableHolderEntity);
|
||||
}
|
||||
}
|
||||
|
||||
// save the final result in the target Prefab DOM.
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab))
|
||||
{
|
||||
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ::DataStream::StreamType NetworkPrefabProcessor::GetAzSerializationFormat() const
|
||||
|
||||
@@ -14,23 +14,23 @@
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
class PrefabDocument;
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor;
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext;
|
||||
using AzToolsFramework::Prefab::PrefabDom;
|
||||
|
||||
class NetworkPrefabProcessor : public PrefabProcessor
|
||||
class NetworkPrefabProcessor : public AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Multiplayer::NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor);
|
||||
AZ_RTTI(
|
||||
Multiplayer::NetworkPrefabProcessor,
|
||||
"{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}",
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor);
|
||||
|
||||
~NetworkPrefabProcessor() override = default;
|
||||
|
||||
void Process(PrefabProcessorContext& context) override;
|
||||
void Process(AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context) override;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
@@ -44,7 +44,10 @@ namespace Multiplayer
|
||||
AZ::DataStream::StreamType GetAzSerializationFormat() const;
|
||||
|
||||
protected:
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab, AZ::DataStream::StreamType serializationFormat);
|
||||
static bool ProcessPrefab(
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat);
|
||||
|
||||
SerializationFormats m_serializationFormat = SerializationFormats::Binary;
|
||||
};
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace UnitTest
|
||||
TEST_F(PrefabProcessingTestFixture, NetworkPrefabProcessor_ProcessPrefabTwoEntities_NetEntityGoesToNetSpawnable)
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext;
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument;
|
||||
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
|
||||
@@ -74,7 +75,9 @@ namespace UnitTest
|
||||
// Add the prefab into the Prefab Processor Context
|
||||
const AZStd::string prefabName = "testPrefab";
|
||||
PrefabProcessorContext prefabProcessorContext{AZ::Uuid::CreateRandom()};
|
||||
prefabProcessorContext.AddPrefab(prefabName, AZStd::move(prefabDom));
|
||||
PrefabDocument document(prefabName);
|
||||
ASSERT_TRUE(document.SetPrefabDom(AZStd::move(prefabDom)));
|
||||
prefabProcessorContext.AddPrefab(AZStd::move(document));
|
||||
|
||||
// Request NetworkPrefabProcessor to process the prefab
|
||||
Multiplayer::NetworkPrefabProcessor processor;
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace PhysX::Utils::Characters
|
||||
physx::PxMaterial* pxMaterial = static_cast<physx::PxMaterial*>(materials.front()->GetNativePointer());
|
||||
|
||||
controllerDesc.material = pxMaterial;
|
||||
controllerDesc.position = PxMathConvertExtended(characterConfig.m_position);
|
||||
controllerDesc.slopeLimit = cosf(AZ::DegToRad(characterConfig.m_maximumSlopeAngle));
|
||||
controllerDesc.stepOffset = characterConfig.m_stepHeight;
|
||||
controllerDesc.upDirection = characterConfig.m_upDirection.IsZero()
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace AZ::Prefab
|
||||
|
||||
bool PrefabBuilderComponent::ProcessPrefab(
|
||||
const AZ::PlatformTagSet& platformTags, const char* filePath, AZ::IO::PathView tempDirPath, const AZ::Uuid& sourceFileUuid,
|
||||
AzToolsFramework::Prefab::PrefabDom& mutableRootDom, AZStd::vector<AssetBuilderSDK::JobProduct>& jobProducts)
|
||||
AzToolsFramework::Prefab::PrefabDom&& rootDom, AZStd::vector<AssetBuilderSDK::JobProduct>& jobProducts)
|
||||
{
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext context(sourceFileUuid);
|
||||
AZStd::string rootPrefabName;
|
||||
@@ -247,7 +247,9 @@ namespace AZ::Prefab
|
||||
filePath);
|
||||
return false;
|
||||
}
|
||||
context.AddPrefab(AZStd::move(rootPrefabName), AZStd::move(mutableRootDom));
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument rootDocument(AZStd::move(rootPrefabName));
|
||||
rootDocument.SetPrefabDom(AZStd::move(rootDom));
|
||||
context.AddPrefab(AZStd::move(rootDocument));
|
||||
|
||||
context.SetPlatformTags(AZStd::move(platformTags));
|
||||
|
||||
@@ -319,8 +321,8 @@ namespace AZ::Prefab
|
||||
});
|
||||
|
||||
if (ProcessPrefab(
|
||||
platformTags, request.m_fullPath.c_str(), request.m_tempDirPath.c_str(), request.m_sourceFileUUID, mutableRootDom,
|
||||
response.m_outputProducts))
|
||||
platformTags, request.m_fullPath.c_str(), request.m_tempDirPath.c_str(), request.m_sourceFileUUID,
|
||||
AZStd::move(mutableRootDom), response.m_outputProducts))
|
||||
{
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace AZ::Prefab
|
||||
const AzToolsFramework::Prefab::PrefabDom& genericDocument);
|
||||
bool ProcessPrefab(
|
||||
const AZ::PlatformTagSet& platformTags, const char* filePath, AZ::IO::PathView tempDirPath, const AZ::Uuid& sourceFileUuid,
|
||||
AzToolsFramework::Prefab::PrefabDom& mutableRootDom,
|
||||
AzToolsFramework::Prefab::PrefabDom&& rootDom,
|
||||
AZStd::vector<AssetBuilderSDK::JobProduct>& jobProducts);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -106,7 +106,8 @@ namespace UnitTest
|
||||
AzToolsFramework::Prefab::PrefabDom prefabDom;
|
||||
prefabDom.CopyFrom(prefabSystemComponentInterface->FindTemplateDom(parentInstance->GetTemplateId()), prefabDom.GetAllocator(), false);
|
||||
|
||||
ASSERT_TRUE(prefabBuilderComponent.ProcessPrefab({AZ::Crc32("pc")}, "parent.prefab", "unused", AZ::Uuid(), prefabDom, jobProducts));
|
||||
ASSERT_TRUE(prefabBuilderComponent.ProcessPrefab(
|
||||
{ AZ::Crc32("pc") }, "parent.prefab", "unused", AZ::Uuid(), AZStd::move(prefabDom), jobProducts));
|
||||
|
||||
ASSERT_EQ(jobProducts.size(), 1);
|
||||
ASSERT_EQ(jobProducts[0].m_dependencies.size(), 1);
|
||||
|
||||
@@ -246,6 +246,16 @@ namespace ScriptCanvasBuilder
|
||||
}
|
||||
}
|
||||
|
||||
void BuildVariableOverrides::SetHandlesToDescription()
|
||||
{
|
||||
m_source = m_source.Describe();
|
||||
|
||||
for (auto& dependency : m_dependencies)
|
||||
{
|
||||
dependency.SetHandlesToDescription();
|
||||
}
|
||||
}
|
||||
|
||||
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& buildOverrides)
|
||||
{
|
||||
ScriptCanvas::RuntimeDataOverrides runtimeOverrides;
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace ScriptCanvasBuilder
|
||||
// use this to initialize the new data, and make sure they have a editor graph variable for proper editor display
|
||||
void PopulateFromParsedResults(ScriptCanvas::Grammar::AbstractCodeModelConstPtr abstractCodeModel, const ScriptCanvas::VariableData& variables);
|
||||
|
||||
void SetHandlesToDescription();
|
||||
|
||||
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
|
||||
ScriptCanvasEditor::SourceHandle m_source;
|
||||
|
||||
|
||||
@@ -245,13 +245,13 @@ namespace ScriptCanvasEditor
|
||||
void EditorScriptCanvasComponent::OpenEditor([[maybe_unused]] const AZ::Data::AssetId& assetId, const AZ::Data::AssetType&)
|
||||
{
|
||||
AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
|
||||
|
||||
|
||||
AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
|
||||
|
||||
|
||||
if (m_sourceHandle.IsDescriptionValid())
|
||||
{
|
||||
GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
|
||||
|
||||
|
||||
if (!openOutcome)
|
||||
{
|
||||
AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
|
||||
@@ -261,7 +261,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntityIds;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
|
||||
// Going to bypass the multiple selected entities flow for right now.
|
||||
if (selectedEntityIds.size() == 1)
|
||||
{
|
||||
@@ -279,7 +279,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void EditorScriptCanvasComponent::InitializeSource(const SourceHandle& sourceHandle)
|
||||
{
|
||||
m_sourceHandle = sourceHandle;
|
||||
m_sourceHandle = sourceHandle.Describe();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -345,6 +345,7 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
|
||||
m_variableOverrides = parseOutcome.TakeValue();
|
||||
m_variableOverrides.SetHandlesToDescription();
|
||||
m_runtimeDataIsValid = true;
|
||||
}
|
||||
|
||||
@@ -373,13 +374,7 @@ namespace ScriptCanvasEditor
|
||||
void EditorScriptCanvasComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
m_sourceHandle = SourceHandle(nullptr, assetId.m_guid, {});
|
||||
|
||||
auto completeAsset = CompleteDescription(m_sourceHandle);
|
||||
if (completeAsset)
|
||||
{
|
||||
m_sourceHandle = *completeAsset;
|
||||
}
|
||||
|
||||
CompleteDescriptionInPlace(m_sourceHandle);
|
||||
OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged);
|
||||
SetName(m_sourceHandle.Path().Filename().Native());
|
||||
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
|
||||
@@ -399,7 +394,7 @@ namespace ScriptCanvasEditor
|
||||
OnScriptCanvasAssetChanged(SourceChangeDescription::SelectionChanged);
|
||||
return AZ::Edit::PropertyRefreshLevels::EntireTree;
|
||||
}
|
||||
|
||||
|
||||
void EditorScriptCanvasComponent::OnScriptCanvasAssetChanged(SourceChangeDescription changeDescription)
|
||||
{
|
||||
ScriptCanvas::GraphIdentifier newIdentifier = GetGraphIdentifier();
|
||||
@@ -417,20 +412,11 @@ namespace ScriptCanvasEditor
|
||||
ClearVariables();
|
||||
}
|
||||
|
||||
m_sourceHandle = m_previousHandle;
|
||||
|
||||
if (m_sourceHandle.IsDescriptionValid())
|
||||
{
|
||||
if (!m_sourceHandle.Get())
|
||||
{
|
||||
if (auto loaded = LoadFromFile(m_sourceHandle.Path().c_str()); loaded.IsSuccess())
|
||||
{
|
||||
m_sourceHandle = SourceHandle(loaded.TakeValue(), m_sourceHandle.Id(), m_sourceHandle.Path().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_sourceHandle.Get())
|
||||
{
|
||||
UpdatePropertyDisplay(m_sourceHandle);
|
||||
}
|
||||
UpdatePropertyDisplay();
|
||||
}
|
||||
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
@@ -492,14 +478,11 @@ namespace ScriptCanvasEditor
|
||||
return ScriptCanvas::GraphIdentifier(m_sourceHandle.Id(), 0);
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::UpdatePropertyDisplay(const SourceHandle& sourceHandle)
|
||||
void EditorScriptCanvasComponent::UpdatePropertyDisplay()
|
||||
{
|
||||
if (sourceHandle.IsGraphValid())
|
||||
{
|
||||
BuildGameEntityData();
|
||||
UpdateName();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
}
|
||||
BuildGameEntityData();
|
||||
UpdateName();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::ClearVariables()
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@ namespace ScriptCanvasEditor
|
||||
void UpdateName();
|
||||
|
||||
//=====================================================================
|
||||
void UpdatePropertyDisplay(const SourceHandle& sourceHandle);
|
||||
void UpdatePropertyDisplay();
|
||||
//=====================================================================
|
||||
|
||||
void BuildGameEntityData();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"AssetProcessor": {
|
||||
"Settings": {
|
||||
// The terrain shader doesn't work on mac due to unbounded arrays, so disable problematic materials and material types
|
||||
// in the terrain gem to prevent dependencies from failing.
|
||||
"Exclude Terrain DefaultPbrTerrain.material": {
|
||||
"pattern": "^Materials/Terrain/DefaultPbrTerrain.material"
|
||||
},
|
||||
"Exclude Terrain PbrTerrain.materialtype": {
|
||||
"pattern": "^Materials/Terrain/PbrTerrain.materialtype"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ namespace Vegetation
|
||||
// Create the EntitySpawnTicket here. This pointer is going to get handed off to the vegetation system as opaque instance data,
|
||||
// where it will be tracked and held onto for the lifetime of the vegetation instance. The vegetation system will pass it back
|
||||
// in to DestroyInstance at the end of the lifetime, so that's the one place where we will delete the ticket pointers.
|
||||
AzFramework::EntitySpawnTicket* ticket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
AzFramework::EntitySpawnTicket* ticket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
if (ticket->IsValid())
|
||||
{
|
||||
// Track the ticket that we've created.
|
||||
|
||||
@@ -24,7 +24,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform
|
||||
ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af)
|
||||
ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-linux TARGETS TIFF PACKAGE_HASH 2377f48b2ebc2d1628d9f65186c881544c92891312abe478a20d10b85877409a)
|
||||
ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97)
|
||||
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4)
|
||||
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-linux TARGETS AWSNativeSDK PACKAGE_HASH f30b6969c6732a7c1a23a59d205a150633a7f219dcb60d837b543888d2c63ea1)
|
||||
ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0)
|
||||
ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-linux TARGETS PhysX PACKAGE_HASH fa72365df409376aef02d1763194dc91d255bdfcb4e8febcfbb64d23a3e50b96)
|
||||
ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-linux TARGETS mcpp PACKAGE_HASH df7a998d0bc3fedf44b5bdebaf69ddad6033355b71a590e8642445ec77bc6c41)
|
||||
|
||||
Vendored
+5
-3
@@ -38,7 +38,7 @@ def pipelineParameters = [
|
||||
booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME')
|
||||
]
|
||||
|
||||
def palSh(cmd, lbl = '', winSlashReplacement = true) {
|
||||
def palSh(cmd, lbl = '', winSlashReplacement = true, winCharReplacement = true) {
|
||||
if (env.IS_UNIX) {
|
||||
sh label: lbl,
|
||||
script: cmd
|
||||
@@ -46,7 +46,9 @@ def palSh(cmd, lbl = '', winSlashReplacement = true) {
|
||||
if (winSlashReplacement) {
|
||||
cmd = cmd.replace('/','\\')
|
||||
}
|
||||
cmd = cmd.replace('%', '%%')
|
||||
if (winCharReplacement) {
|
||||
cmd = cmd.replace('%', '%%')
|
||||
}
|
||||
bat label: lbl,
|
||||
script: cmd
|
||||
}
|
||||
@@ -262,7 +264,7 @@ def CheckoutRepo(boolean disableSubmodules = false) {
|
||||
commitDateFmt = '%%cI'
|
||||
if (env.IS_UNIX) commitDateFmt = '%cI'
|
||||
|
||||
palSh("git show -s --format=${commitDateFmt} ${env.CHANGE_ID} > commitdate", 'Getting commit date')
|
||||
palSh("git show -s --format=${commitDateFmt} ${env.CHANGE_ID} > commitdate", 'Getting commit date', winSlashReplacement=true, winCharReplacement=false)
|
||||
env.CHANGE_DATE = readFile file: 'commitdate'
|
||||
env.CHANGE_DATE = env.CHANGE_DATE.trim()
|
||||
palRm('commitdate')
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
],
|
||||
"steps": [
|
||||
"profile",
|
||||
"asset_profile"
|
||||
"asset_profile",
|
||||
"test_profile"
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
@@ -89,6 +90,22 @@
|
||||
"ASSET_PROCESSOR_PLATFORMS": "mac"
|
||||
}
|
||||
},
|
||||
"test_profile": {
|
||||
"TAGS": [
|
||||
"daily-pipeline-metrics",
|
||||
"weekly-build-metrics"
|
||||
],
|
||||
"COMMAND": "build_test_mac.sh",
|
||||
"PARAMETERS": {
|
||||
"CONFIGURATION": "profile",
|
||||
"OUTPUT_DIRECTORY": "build/mac",
|
||||
"CMAKE_OPTIONS": "-G Xcode",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "ALL_BUILD",
|
||||
"CTEST_OPTIONS": "-L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error",
|
||||
"TEST_RESULTS": "False"
|
||||
}
|
||||
},
|
||||
"periodic_test_profile": {
|
||||
"TAGS": [
|
||||
"nightly-incremental",
|
||||
@@ -102,7 +119,7 @@
|
||||
"CMAKE_OPTIONS": "-G Xcode",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "TEST_SUITE_periodic",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_periodic)\"",
|
||||
"CTEST_OPTIONS": "-L (SUITE_periodic)",
|
||||
"TEST_RESULTS": "False"
|
||||
}
|
||||
},
|
||||
@@ -119,7 +136,7 @@
|
||||
"CMAKE_OPTIONS": "-G Xcode",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "TEST_SUITE_benchmark",
|
||||
"CTEST_OPTIONS": "-L \"(SUITE_benchmark)\"",
|
||||
"CTEST_OPTIONS": "-L (SUITE_benchmark)",
|
||||
"TEST_RESULTS": "False"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@ if [[ ! -z "$RUN_CONFIGURE" ]]; then
|
||||
echo "${CONFIGURE_CMD}" > ${LAST_CONFIGURE_CMD_FILE}
|
||||
fi
|
||||
|
||||
echo [ci_build] cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS}
|
||||
cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS}
|
||||
echo [ci_build] cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(/usr/sbin/sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS}
|
||||
cmake --build . --target ${CMAKE_TARGET} --config ${CONFIGURATION} -j $(/usr/sbin/sysctl -n hw.ncpu) -- ${CMAKE_NATIVE_BUILD_ARGS}
|
||||
|
||||
popd
|
||||
|
||||
@@ -19,8 +19,9 @@ fi
|
||||
pushd $OUTPUT_DIRECTORY
|
||||
|
||||
# Find the CTEST_RUN_FLAGS from the CMakeCache.txt file, then replace the $<CONFIG> with the current configuration
|
||||
IFS='=' read -ra CTEST_RUN_FLAGS <<< $(cmake -N -LA . | grep "CTEST_RUN_FLAGS:STRING")
|
||||
CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS[1]/$<CONFIG>/${CONFIGURATION}}
|
||||
CTEST_RUN_FLAGS=$(cmake -N -LA . | grep "CTEST_RUN_FLAGS:STRING")
|
||||
CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS/CTEST_RUN_FLAGS:STRING=/}
|
||||
CTEST_RUN_FLAGS=${CTEST_RUN_FLAGS/$<CONFIG>/${CONFIGURATION}}
|
||||
|
||||
# Run ctest
|
||||
echo [ci_build] ctest ${CTEST_RUN_FLAGS} ${CTEST_OPTIONS}
|
||||
|
||||
@@ -17,7 +17,7 @@ endif()
|
||||
# Tests
|
||||
################################################################################
|
||||
|
||||
if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED)
|
||||
if(PAL_TRAIT_TEST_PYTEST_SUPPORTED)
|
||||
foreach(suite_name ${LY_TEST_GLOBAL_KNOWN_SUITE_NAMES})
|
||||
ly_add_pytest(
|
||||
NAME pytest_sanity_${suite_name}_no_gpu
|
||||
@@ -32,16 +32,16 @@ if(PAL_TRAIT_TEST_LYTESTTOOLS_SUPPORTED)
|
||||
TEST_REQUIRES gpu
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# add a custom test which makes sure that the test filtering works!
|
||||
|
||||
ly_add_test(
|
||||
NAME cli_test_driver
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_COMMAND ${LY_PYTHON_CMD} ${CMAKE_CURRENT_LIST_DIR}/ctest_driver_test.py
|
||||
-x ${CMAKE_CTEST_COMMAND}
|
||||
--build-path ${CMAKE_BINARY_DIR}
|
||||
TEST_LIBRARY pytest
|
||||
)
|
||||
# add a custom test which makes sure that the test filtering works!
|
||||
ly_add_test(
|
||||
NAME cli_test_driver
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_COMMAND ${LY_PYTHON_CMD} ${CMAKE_CURRENT_LIST_DIR}/ctest_driver_test.py
|
||||
-x ${CMAKE_CTEST_COMMAND}
|
||||
--build-path ${CMAKE_BINARY_DIR}
|
||||
--config $<CONFIG>
|
||||
TEST_LIBRARY pytest
|
||||
)
|
||||
|
||||
endif()
|
||||
@@ -15,10 +15,10 @@ import sys
|
||||
import argparse
|
||||
from ctest_driver import SUITES_AND_DESCRIPTIONS
|
||||
|
||||
def main(build_path, ctest_executable):
|
||||
def main(build_path, ctest_executable, config):
|
||||
script_folder = os.path.dirname(__file__)
|
||||
# -N prevents tests from running, just lists them:
|
||||
base_args = [sys.executable, os.path.join(script_folder,'ctest_driver.py'), "--build-path", build_path, '-N']
|
||||
base_args = [sys.executable, os.path.join(script_folder,'ctest_driver.py'), "--build-path", build_path, "--config", config, '-N']
|
||||
if ctest_executable:
|
||||
base_args.append("--ctest-executable")
|
||||
base_args.append(ctest_executable)
|
||||
@@ -77,7 +77,10 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-b', '--build-path',
|
||||
required=True,
|
||||
help="Path to a CMake build folder (generated by running cmake)")
|
||||
parser.add_argument('-c', '--config',
|
||||
required=True,
|
||||
help="Configuration to run")
|
||||
args = parser.parse_args()
|
||||
sys.exit(main(args.build_path, args.ctest_executable))
|
||||
sys.exit(main(args.build_path, args.ctest_executable, args.config))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user