diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py index 254224a2f8..4265dd6fc9 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py @@ -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) diff --git a/Code/Editor/BaseLibrary.cpp b/Code/Editor/BaseLibrary.cpp deleted file mode 100644 index 15742bd254..0000000000 --- a/Code/Editor/BaseLibrary.cpp +++ /dev/null @@ -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 -#include - -////////////////////////////////////////////////////////////////////////// -// 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 > temp; - for (unsigned int i = 0; i < m_items.size(); i++) - { - if (i == newLocation) - { - temp.push_back(_smart_ptr(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(item)); - } - m_items = temp; -} -//CONFETTI END - -#include diff --git a/Code/Editor/BaseLibrary.h b/Code/Editor/BaseLibrary.h deleted file mode 100644 index 55079d3fde..0000000000 --- a/Code/Editor/BaseLibrary.h +++ /dev/null @@ -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 -#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 -{ - 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(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 > m_items; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_BASELIBRARY_H diff --git a/Code/Editor/BaseLibraryItem.cpp b/Code/Editor/BaseLibraryItem.cpp deleted file mode 100644 index e3788bc3e4..0000000000 --- a/Code/Editor/BaseLibraryItem.cpp +++ /dev/null @@ -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 - -//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(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(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); - } -} diff --git a/Code/Editor/BaseLibraryItem.h b/Code/Editor/BaseLibraryItem.h deleted file mode 100644 index 53cf0add2b..0000000000 --- a/Code/Editor/BaseLibraryItem.h +++ /dev/null @@ -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 - -class CBaseLibrary; - -////////////////////////////////////////////////////////////////////////// -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -/** Base class for all items contained in BaseLibraray. -*/ -class EDITOR_CORE_API CBaseLibraryItem - : public TRefCountBase -{ - 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 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 diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp deleted file mode 100644 index 0e51a5238c..0000000000 --- a/Code/Editor/BaseLibraryManager.cpp +++ /dev/null @@ -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 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 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 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 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(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 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(FindItemByName(fullName)); - if (!pOldItem) - { - AZStd::lock_guard 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(FindItemByName(fullName)); - if (!pOldItem) - { - AZStd::lock_guard 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 lock(m_itemsNameMapMutex); - auto findIter = m_itemsNameMap.find(pItem->GetFullName()); - if (findIter != m_itemsNameMap.end()) - { - _smart_ptr 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(&m_itemsNameMap); - } - else - { - return new CDataBaseItemEnumerator(&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 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; -} diff --git a/Code/Editor/BaseLibraryManager.h b/Code/Editor/BaseLibraryManager.h deleted file mode 100644 index 118c7ef1f0..0000000000 --- a/Code/Editor/BaseLibraryManager.h +++ /dev/null @@ -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 -#include - -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(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 > m_libs; - - // There is always one current level library. - TSmartPtr m_pLevelLibrary; - - // GUID to item map. - typedef std::map, guid_less_predicate> ItemsGUIDMap; - ItemsGUIDMap m_itemsGuidMap; - - // Case insensitive name to items map. - typedef std::map, stl::less_stricmp> ItemsNameMap; - ItemsNameMap m_itemsNameMap; - AZStd::mutex m_itemsNameMapMutex; - - std::vector m_listeners; - - // Currently selected item. - _smart_ptr m_pSelectedItem; - _smart_ptr m_pSelectedParent; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -////////////////////////////////////////////////////////////////////////// -template -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 diff --git a/Code/Editor/EditorPreferencesPageAWS.cpp b/Code/Editor/EditorPreferencesPageAWS.cpp index 68a9d6889f..9279dce7bc 100644 --- a/Code/Editor/EditorPreferencesPageAWS.cpp +++ b/Code/Editor/EditorPreferencesPageAWS.cpp @@ -28,7 +28,7 @@ void CEditorPreferencesPage_AWS::Reflect(AZ::SerializeContext& serialize) if (editContext) { editContext->Class("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 O3DE to send information about your use of AWS Core Gem to AWS", ""); editContext->Class("AWS Preferences", "AWS Preferences") diff --git a/Code/Editor/ErrorRecorder.cpp b/Code/Editor/ErrorRecorder.cpp index 999dab323c..253e103527 100644 --- a/Code/Editor/ErrorRecorder.cpp +++ b/Code/Editor/ErrorRecorder.cpp @@ -7,7 +7,6 @@ */ #include "EditorDefs.h" #include "ErrorRecorder.h" -#include "BaseLibraryItem.h" #include "Include/IErrorReport.h" diff --git a/Code/Editor/ErrorRecorder.h b/Code/Editor/ErrorRecorder.h index e4b3706a16..beacc3f0e5 100644 --- a/Code/Editor/ErrorRecorder.h +++ b/Code/Editor/ErrorRecorder.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 diff --git a/Code/Editor/ErrorReport.cpp b/Code/Editor/ErrorReport.cpp index 4fd7d41a96..f93ea7606d 100644 --- a/Code/Editor/ErrorReport.cpp +++ b/Code/Editor/ErrorReport.cpp @@ -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) { diff --git a/Code/Editor/ErrorReport.h b/Code/Editor/ErrorReport.h index 3b9a860301..98d230e383 100644 --- a/Code/Editor/ErrorReport.h +++ b/Code/Editor/ErrorReport.h @@ -17,8 +17,11 @@ // forward declarations. class CParticleItem; -#include "BaseLibraryItem.h" +#include +#include + #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 pObject; - //! Library Item that caused this error. - _smart_ptr 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 m_pObject; - _smart_ptr m_pItem; CParticleItem* m_pParticle; QString m_currentFilename; }; diff --git a/Code/Editor/ErrorReportDialog.cpp b/Code/Editor/ErrorReportDialog.cpp index 2d551d6c8b..bbeede79ef 100644 --- a/Code/Editor/ErrorReportDialog.cpp +++ b/Code/Editor/ErrorReportDialog.cpp @@ -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"); } } diff --git a/Code/Editor/ErrorReportTableModel.cpp b/Code/Editor/ErrorReportTableModel.cpp index f5dce1a86d..923991bb62 100644 --- a/Code/Editor/ErrorReportTableModel.cpp +++ b/Code/Editor/ErrorReportTableModel.cpp @@ -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(); } diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h index d2d4998187..c91ca62c5e 100644 --- a/Code/Editor/IEditor.h +++ b/Code/Editor/IEditor.h @@ -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. diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 0846cf8a9e..38006c6fca 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -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; diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index d99b8ae802..7867912941 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -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; } diff --git a/Code/Editor/Include/IBaseLibraryManager.h b/Code/Editor/Include/IBaseLibraryManager.h deleted file mode 100644 index 4116b573fa..0000000000 --- a/Code/Editor/Include/IBaseLibraryManager.h +++ /dev/null @@ -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 -#include "Include/IDataBaseItem.h" -#include "Include/IDataBaseLibrary.h" -#include "Include/IDataBaseManager.h" -#include "Util/TRefCountBase.h" - -class CBaseLibraryItem; -class CBaseLibrary; - -struct IBaseLibraryManager - : public TRefCountBase - , 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 diff --git a/Code/Editor/Include/IDataBaseItem.h b/Code/Editor/Include/IDataBaseItem.h deleted file mode 100644 index 6be5f49c2d..0000000000 --- a/Code/Editor/Include/IDataBaseItem.h +++ /dev/null @@ -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 -#include - -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 diff --git a/Code/Editor/Include/IDataBaseLibrary.h b/Code/Editor/Include/IDataBaseLibrary.h deleted file mode 100644 index 75437d93e2..0000000000 --- a/Code/Editor/Include/IDataBaseLibrary.h +++ /dev/null @@ -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 diff --git a/Code/Editor/Include/IDataBaseManager.h b/Code/Editor/Include/IDataBaseManager.h deleted file mode 100644 index 3d701d51fc..0000000000 --- a/Code/Editor/Include/IDataBaseManager.h +++ /dev/null @@ -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 - -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 diff --git a/Code/Editor/Include/IEditorMaterial.h b/Code/Editor/Include/IEditorMaterial.h deleted file mode 100644 index 329b0ae53f..0000000000 --- a/Code/Editor/Include/IEditorMaterial.h +++ /dev/null @@ -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 - -struct IEditorMaterial - : public CBaseLibraryItem -{ - virtual int GetFlags() const = 0; - virtual IMaterial* GetMatInfo(bool bUseExistingEngineMaterial = false) = 0; - virtual void DisableHighlightForFrame() = 0; -}; diff --git a/Code/Editor/Include/IEditorMaterialManager.h b/Code/Editor/Include/IEditorMaterialManager.h deleted file mode 100644 index 6f71c5ddd1..0000000000 --- a/Code/Editor/Include/IEditorMaterialManager.h +++ /dev/null @@ -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 - - -struct IEditorMaterialManager -{ - virtual void GotoMaterial(IMaterial* pMaterial) = 0; -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H diff --git a/Code/Editor/Include/IErrorReport.h b/Code/Editor/Include/IErrorReport.h index 7bf00d6973..c409dbc7dd 100644 --- a/Code/Editor/Include/IErrorReport.h +++ b/Code/Editor/Include/IErrorReport.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; }; diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 590f98e6d7..aaee34c2c6 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -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 )); diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index c3e379bccc..c6b7e4ce2d 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -27,6 +27,7 @@ #define CLASS_ENVIRONMENT_LIGHT "EnvironmentLight" class CEntityObject; +class CSelectionGroup; class QMenu; /*! diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index fc1014ad03..fa576fa983 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -13,6 +13,8 @@ #include "ErrorReport.h" #include +#include + class CErrorRecord; struct IObjectManager; diff --git a/Code/Editor/TrackView/TrackViewSequence.h b/Code/Editor/TrackView/TrackViewSequence.h index a392ad00f9..8f686af0cb 100644 --- a/Code/Editor/TrackView/TrackViewSequence.h +++ b/Code/Editor/TrackView/TrackViewSequence.h @@ -11,6 +11,7 @@ #define CRYINCLUDE_EDITOR_TRACKVIEW_TRACKVIEWSEQUENCE_H #pragma once +#include #include "IMovieSystem.h" #include diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.cpp b/Code/Editor/TrackView/TrackViewSequenceManager.cpp index d7c1e3c709..515af4df38 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.cpp +++ b/Code/Editor/TrackView/TrackViewSequenceManager.cpp @@ -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 { diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.h b/Code/Editor/TrackView/TrackViewSequenceManager.h index 1474323dc6..6c65a7f1a9 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.h +++ b/Code/Editor/TrackView/TrackViewSequenceManager.h @@ -13,13 +13,11 @@ #include "TrackViewSequence.h" -#include "IDataBaseManager.h" #include 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; diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index a71df6a9cd..1b0e5a4d93 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -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; diff --git a/Code/Editor/editor_core_files.cmake b/Code/Editor/editor_core_files.cmake index 53dd8d79a5..1f0a5a3618 100644 --- a/Code/Editor/editor_core_files.cmake +++ b/Code/Editor/editor_core_files.cmake @@ -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 diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index c81a326aff..59a1a91647 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -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 diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index dc9c7b4538..66197ae8fc 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -164,6 +165,8 @@ namespace AzFramework public: friend class SpawnableEntitiesDefinition; + AZ_CLASS_ALLOCATOR(AzFramework::EntitySpawnTicket, AZ::SystemAllocator, 0); + using Id = uint32_t; EntitySpawnTicket() = default; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 37570caec7..3406057fca 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -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; diff --git a/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp index 0dc00f81dd..50365ff2ff 100644 --- a/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp +++ b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp @@ -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(reflection)) { - serializeContext->Class(); + serializeContext->Class() + ->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(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(managerInterface); @@ -147,22 +158,43 @@ namespace UnitTest { auto entry = AZStd::make_unique(); entry->AddComponent(aznew SourceSpawnableComponent()); + entry->SetId(AZ::EntityId(EntityIdStartId + i)); entities.push_back(AZStd::move(entry)); } } - AZ::Data::Asset CreateTargetSpawnable(size_t numElements) + AZ::Data::Asset 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(); - entry->AddComponent(aznew TargetSpawnableComponent()); - entities.push_back(AZStd::move(entry)); + for (size_t i = 0; i < numElements; ++i) + { + auto entry = AZStd::make_unique(); + 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(); + entry->AddComponent(aznew TargetSpawnableComponent()); + entities.push_back(AZStd::move(entry)); + } } return AZ::Data::Asset(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(); 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = false; + AZ::Data::Asset 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = false; + AZ::Data::Asset 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 target = CreateTargetSpawnable(4); + constexpr bool requiresMatchingEntityIds = true; + AZ::Data::Asset 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 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) {}; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp index 8ef69c4b56..8daa183b80 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/ElidingLabel.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include 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) diff --git a/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h b/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h index 4915fb9cab..23ea87cd1c 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h +++ b/Code/Framework/AzTest/AzTest/Platform/Mac/AzTest_Traits_Mac.h @@ -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, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b91a0aac93..418d176daa 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -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; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp index 5bea383630..3b2f78ef2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSnapping.cpp @@ -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); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 490a151925..03d62dff0a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -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::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(nullptr, AZ::EntityId()); + } + } + + return AZStd::pair(instance, instance->GetEntityId(relativeAliasPath.Filename().Native())); + } + + AZStd::pair 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(nullptr, AZ::EntityId()); } } - return instance->GetEntityId(relativeAliasPath.Filename().Native()); + return AZStd::pair(instance, instance->GetEntityId(relativeAliasPath.Filename().Native())); } AZStd::vector Instance::GetNestedInstanceAliases(TemplateId templateId) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h index 25971093cd..b63eca309a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h @@ -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&& 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 GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath); + AZStd::pair GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const; /** diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp index dfba1d54ba..9488b68ee8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp @@ -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& instance, EntityList& hierarchyEntities) + void EditorInfoRemover::GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities) { - instance->GetAllEntitiesInHierarchy( + instance.GetAllEntitiesInHierarchy( [&hierarchyEntities](const AZStd::unique_ptr& 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(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& 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& 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 diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h index dc10952733..dbad58d2f5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h @@ -43,7 +43,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils using RemoveEditorInfoResult = AZ::Outcome; RemoveEditorInfoResult RemoveEditorInfo( - PrefabDom& prefab, + PrefabDocument& prefab, AZ::SerializeContext* serializeContext, PrefabProcessorContext& prefabProcessorContext); @@ -51,8 +51,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils protected: using EntityList = AZStd::vector; - static void GetEntitiesFromInstance( - AZStd::unique_ptr& instance, EntityList& hierarchyEntities); + static void GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities); static bool ReadComponentAttribute( AZ::Component* component, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h new file mode 100644 index 0000000000..9ab1f9bbd1 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h @@ -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 +#include +#include +#include +#include +#include + +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; + + LinkStore m_source; + LinkStore m_target; + uint32_t m_tag; + AzFramework::Spawnable::EntityAliasType m_aliasType; + EntityAliasSpawnableLoadBehavior m_loadBehavior; + }; +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp index 553ad8ece4..dc5cd299b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp @@ -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()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp index 7a54950c47..40cd52cac8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp @@ -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& 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 entity) + AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities(); + instance.DetachAllEntitiesInHierarchy( + [&entities, &context](AZStd::unique_ptr 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 diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h index 253321f8e7..39a94c86b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.h @@ -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 }; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp new file mode 100644 index 0000000000..04fdea30d2 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp @@ -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 +#include +#include + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + PrefabDocument::PrefabDocument(AZStd::string name) + : m_name(AZStd::move(name)) + , m_instance(AZStd::make_unique()) + { + 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& 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 diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h new file mode 100644 index 0000000000..215daf7f71 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h @@ -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 +#include +#include +#include +#include +#include +#include + +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 + void ListEntitiesWithComponentType(const AZStd::function& callback) const; + void ListEntitiesWithComponentType( + AZ::TypeId componentType, const AZStd::function& 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 m_instance; + AZStd::string m_name; + mutable bool m_isDirty{ false }; + }; +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils + +#include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl new file mode 100644 index 0000000000..37b1f1c127 --- /dev/null +++ b/Code/Framework/AzToolsFramework/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 + void PrefabDocument::ListEntitiesWithComponentType(const AZStd::function& callback) const + { + ListEntitiesWithComponentType(azrtti_typeid(), callback); + } +} // namespace AzToolsFramework::Prefab::PrefabConversionUtils diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp index efef0f53de..12625712b7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp @@ -7,8 +7,10 @@ */ #include +#include #include #include +#include #include #include @@ -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& 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& callback) const + void PrefabProcessorContext::ListPrefabs(const AZStd::function& 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& 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(&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(&target->m_spawnable, loadBehavior), alias.m_tag, sourceIndex, targetIndex, + AZ::Data::Asset(target->m_spawnable.GetId(), azrtti_typeid()), 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); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h index d35a09a574..d07761271b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h @@ -21,60 +21,12 @@ #include #include #include +#include +#include #include 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; - - 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& callback); - virtual void ListPrefabs(const AZStd::function& callback) const; + virtual bool AddPrefab(PrefabDocument&& document); + virtual void ListPrefabs(const AZStd::function& callback); + virtual void ListPrefabs(const AZStd::function& 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; + using PrefabNames = AZStd::unordered_set; + using PrefabContainer = AZStd::vector; using SpawnableEntityAliasStore = AZStd::vector; 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; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp index 5e552aad3f..4f007f509e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include #include +#include 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 - AZStd::unique_ptr CloneEntity(AZ::EntityId entityId, T& source) + AZStd::unique_ptr 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 ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source) + AZStd::unique_ptr 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(entityId), source.GetTemplateSourcePath().c_str()); + instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%.*s' for replacing.", + aznumeric_cast(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(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::MakeId(), entityData->get().GetName()); return instance->ReplaceEntity(AZStd::move(placeholder), alias); } - AZStd::unique_ptr 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(entityId)); - - AZStd::unique_ptr original = AZStd::move(source.GetEntities()[index]); - AZ_Assert( - original, "SpawnbleUtils were unable to locate entity with id %zu in Spawnable for replacing.", - aznumeric_cast(entityId)); - - source.GetEntities()[index] = AZStd::make_unique(original->GetId(), original->GetName()); - - return original; - } - - template AZStd::pair, 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, 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::MakeId()), AzFramework::Spawnable::EntityAliasType::Additional); + return ResultPair(AZStd::make_unique(), 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(entityId), AzFramework::Spawnable::EntityAliasType::Merge); + return ResultPair(AZStd::make_unique(), AzFramework::Spawnable::EntityAliasType::Merge); default: AZ_Assert( false, "Invalid PrefabProcessorContext::EntityAliasType type (%i) provided.", aznumeric_cast(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(AZStd::move(sourcePrefabName), AZStd::move(alias)); - store.m_target.emplace(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(entityId)); - return nullptr; - } - } - else - { - AZ_Assert(false, "Entity with id %llu was not found in the source prefab.", static_cast(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(source, entityId); - store.m_target.emplace(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(entityId)); - return nullptr; - } - } - uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable) { auto begin = spawnable.GetEntities().begin(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h index ea8a49857e..53d007c0c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include 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::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); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index bb2d2851ca..e895456151 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -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); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 4f952a3edc..7f877facb6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -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(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 diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 79a87391b4..2c60ca914c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -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 diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 2c25cc9222..05c07afecd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -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 diff --git a/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp b/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp new file mode 100644 index 0000000000..2a1254f2e9 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/AzToolsFrameworkTestHelpersTest.cpp @@ -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 + +#include +#include + +namespace UnitTest +{ + class AzToolsFrameworkTestHelpersFixture : public AllocatorsTestFixture + { + public: + void SetUp() override + { + AllocatorsTestFixture::SetUp(); + + m_rootWidget = AZStd::make_unique(); + 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(); + 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 m_rootWidget; + AZStd::unique_ptr m_mouseMoveDetector; + }; + + struct MouseMoveParams + { + QSize m_widgetSize; + QPoint m_widgetPosition; + QPoint m_localCursorPosition; + QPoint m_cursorDelta; + }; + + class MouseMoveAzToolsFrameworkTestHelperFixture + : public AzToolsFrameworkTestHelpersFixture + , public ::testing::WithParamInterface + { + }; + + 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 diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp index ecbbe10c39..ba0c3a4838 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp @@ -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(); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp index b8ce3c7c42..0d75227e38 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/SpawnableRemoveEditorInfoTestFixture.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -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 convertedInstance(aznew Instance()); - ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom)); - - convertedInstance->DetachAllEntitiesInHierarchy( + prefab.GetInstance().DetachAllEntitiesInHierarchy( [this](AZStd::unique_ptr entity) { m_runtimeEntities.emplace_back(entity.release()); diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index 9a1f61ab56..2631a84325 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -12,6 +12,7 @@ set(FILES AssetFileInfoListComparison.cpp AssetSeedManager.cpp AssetSystemMocks.h + AzToolsFrameworkTestHelpersTest.cpp BoundsTestComponent.cpp BoundsTestComponent.h ComponentAdapterTests.cpp diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h index 8d7fe068c2..3ebe7d8e44 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Test_Traits_Mac.h @@ -8,4 +8,4 @@ #pragma once -#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false +#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true diff --git a/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h b/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h index d7b1f32461..2cacfb0d34 100644 --- a/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h +++ b/Gems/AWSCore/Code/Platform/Linux/AWSCore_Traits_Linux.h @@ -7,4 +7,4 @@ */ #pragma once -#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 0 +#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 1 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli index f658dd13da..ba06dada74 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli @@ -17,7 +17,7 @@ struct VSInput struct VSDepthOutput { - float4 m_position : SV_Position; + precise float4 m_position : SV_Position; }; VSDepthOutput DepthPassVS(VSInput IN) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl index 9aa169beea..e3237e59a2 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl @@ -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) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader index 781d7e26e5..1f04570625 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant index 668dc28ca0..a359556df6 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant index 77bb341839..7a90c7f352 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant index 117f993f28..4cbb76954d 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp index de49c4ff50..a72d90fc94 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp @@ -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")); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h index 6c3017fe33..a828fe4b96 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h @@ -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; diff --git a/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake b/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake index 419331db3b..4645eb9444 100644 --- a/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake +++ b/Gems/Atom/RHI/Code/Platform/Mac/AtomRHITests_traits_mac.cmake @@ -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) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index af91615283..352ffb6486 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -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( diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index 2a6baed411..a797523bc0 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -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::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 LoadInstanceFromPrefab(const PrefabDom& prefab) - { - using namespace AzToolsFramework::Prefab; - - // convert Prefab DOM into Prefab Instance. - AZStd::unique_ptr 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& 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 sourceInstance = LoadInstanceFromPrefab(prefab); - if (!sourceInstance) - { - return; - } - - AZStd::string uniqueName = prefabName; + AZStd::string uniqueName = prefab.GetName(); uniqueName += ".network.spawnable"; auto serializer = [serializationFormat](AZStd::vector& output, const ProcessedObjectStore& object) -> bool { @@ -127,15 +107,16 @@ namespace Multiplayer ProcessedObjectStore::Create(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 netEntityToInstanceMap; AZStd::vector 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(); @@ -193,18 +174,12 @@ namespace Multiplayer AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName); auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent(); 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 diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h index 0fd3529db7..ef8912467d 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h @@ -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; }; diff --git a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp index 42a817987e..aef13fbfe2 100644 --- a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp +++ b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp @@ -57,6 +57,7 @@ namespace UnitTest TEST_F(PrefabProcessingTestFixture, NetworkPrefabProcessor_ProcessPrefabTwoEntities_NetEntityGoesToNetSpawnable) { using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext; + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument; AZStd::vector 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; diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp index f4cdd01889..1151c0ffff 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp @@ -73,6 +73,7 @@ namespace PhysX::Utils::Characters physx::PxMaterial* pxMaterial = static_cast(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() diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp index 6107226783..71464501ba 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp @@ -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& jobProducts) + AzToolsFramework::Prefab::PrefabDom&& rootDom, AZStd::vector& 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; } diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h index 9ebdd690f5..73ef6b0426 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h @@ -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& jobProducts); protected: diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp index 2ed05b4dfe..5ee23a9e3c 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp @@ -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); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp index d62ebb9c3a..fbacfd8c32 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.cpp @@ -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; diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h index 6e8e176145..1770e48dfa 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilder.h @@ -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; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 750097b428..f8f867d7e3 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -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 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() diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h index ca381445ea..b86df2d9c2 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h @@ -121,7 +121,7 @@ namespace ScriptCanvasEditor void UpdateName(); //===================================================================== - void UpdatePropertyDisplay(const SourceHandle& sourceHandle); + void UpdatePropertyDisplay(); //===================================================================== void BuildGameEntityData(); diff --git a/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg b/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg new file mode 100644 index 0000000000..ac0c854b19 --- /dev/null +++ b/Gems/Terrain/Registry/Platform/Mac/AssetProcessorPlatformConfig.setreg @@ -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" + } + } + } + } +} diff --git a/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp index b386f17cab..c7c0ef5d3d 100644 --- a/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp +++ b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp @@ -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. diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 109ae75f38..f7bc2721ae 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -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) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 570c553444..51f89d7829 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -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') diff --git a/scripts/build/Platform/Mac/build_config.json b/scripts/build/Platform/Mac/build_config.json index 6ba264cdb2..6147f70f0c 100644 --- a/scripts/build/Platform/Mac/build_config.json +++ b/scripts/build/Platform/Mac/build_config.json @@ -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" } }, diff --git a/scripts/build/Platform/Mac/build_mac.sh b/scripts/build/Platform/Mac/build_mac.sh index 2ea5eeab8a..d6a66fc6c6 100755 --- a/scripts/build/Platform/Mac/build_mac.sh +++ b/scripts/build/Platform/Mac/build_mac.sh @@ -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 diff --git a/scripts/build/Platform/Mac/test_mac.sh b/scripts/build/Platform/Mac/test_mac.sh index e398de3061..46dffab84d 100755 --- a/scripts/build/Platform/Mac/test_mac.sh +++ b/scripts/build/Platform/Mac/test_mac.sh @@ -19,8 +19,9 @@ fi pushd $OUTPUT_DIRECTORY # Find the CTEST_RUN_FLAGS from the CMakeCache.txt file, then replace the $ 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]/$/${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/$/${CONFIGURATION}} # Run ctest echo [ci_build] ctest ${CTEST_RUN_FLAGS} ${CTEST_OPTIONS} diff --git a/scripts/ctest/CMakeLists.txt b/scripts/ctest/CMakeLists.txt index 98ea21e938..064d27a9cf 100644 --- a/scripts/ctest/CMakeLists.txt +++ b/scripts/ctest/CMakeLists.txt @@ -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 $ + TEST_LIBRARY pytest + ) +endif() \ No newline at end of file diff --git a/scripts/ctest/ctest_driver_test.py b/scripts/ctest/ctest_driver_test.py index 82d92ce098..b9a7283b25 100755 --- a/scripts/ctest/ctest_driver_test.py +++ b/scripts/ctest/ctest_driver_test.py @@ -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))