Merge remote-tracking branch 'upstream/stabilization/2110' into nvsickle/StabToDevNov21

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-11-11 10:15:11 -08:00
192 changed files with 2090 additions and 1621 deletions
+3 -14
View File
@@ -1361,16 +1361,6 @@ void CCryEditApp::CompileCriticalAssets() const
assetsInQueueNotifcation.BusDisconnect();
CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready."));
// VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others,
// so that by the time we ask for them there is a greater likelihood that they're already good to go.
// these can be loaded later but are still important:
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects");
// some are specifically extra important and will cause issues if missing completely:
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf");
}
bool CCryEditApp::ConnectToAssetProcessor() const
@@ -3974,9 +3964,8 @@ void CCryEditApp::OpenLUAEditor(const char* files)
}
}
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
AZ_Assert(engineRoot != nullptr, "Unable to communicate to AzFramework::ApplicationRequests::Bus");
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
AZ_Assert(!engineRoot.empty(), "Unable to query Engine Path");
AZStd::string_view exePath;
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
@@ -3995,7 +3984,7 @@ void CCryEditApp::OpenLUAEditor(const char* files)
#endif
"%s", argumentQuoteString, aznumeric_cast<int>(exePath.size()), exePath.data(), argumentQuoteString);
AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot);
AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot.c_str());
StartProcessDetached(process.c_str(), processArgs.c_str());
}
-3
View File
@@ -60,7 +60,6 @@ struct IFileUtil
EFILE_TYPE_GEOMETRY,
EFILE_TYPE_TEXTURE,
EFILE_TYPE_SOUND,
EFILE_TYPE_GEOMCACHE,
EFILE_TYPE_LAST,
};
@@ -114,9 +113,7 @@ struct IFileUtil
virtual void ShowInExplorer(const QString& path) = 0;
virtual bool CompileLuaFile(const char* luaFilename) = 0;
virtual bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) = 0;
virtual void EditTextFile(const char* txtFile, int line = 0, ETextFileType fileType = FILE_TYPE_SCRIPT) = 0;
virtual void EditTextureFile(const char* txtureFile, bool bUseGameFolder) = 0;
//! dcc filename calculation and extraction sub-routines
+3 -15
View File
@@ -956,11 +956,7 @@ void CEntityObject::Serialize(CObjectArchive& ar)
QString attachmentType;
xmlNode->getAttr("AttachmentType", attachmentType);
if (attachmentType == "GeomCacheNode")
{
m_attachmentType = eAT_GeomCacheNode;
}
else if (attachmentType == "CharacterBone")
if (attachmentType == "CharacterBone")
{
m_attachmentType = eAT_CharacterBone;
}
@@ -987,11 +983,7 @@ void CEntityObject::Serialize(CObjectArchive& ar)
{
if (m_attachmentType != eAT_Pivot)
{
if (m_attachmentType == eAT_GeomCacheNode)
{
xmlNode->setAttr("AttachmentType", "GeomCacheNode");
}
else if (m_attachmentType == eAT_CharacterBone)
if (m_attachmentType == eAT_CharacterBone)
{
xmlNode->setAttr("AttachmentType", "CharacterBone");
}
@@ -1091,11 +1083,7 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN
objNode->setAttr("ParentId", parentEntity->GetEntityId());
if (m_attachmentType != eAT_Pivot)
{
if (m_attachmentType == eAT_GeomCacheNode)
{
objNode->setAttr("AttachmentType", "GeomCacheNode");
}
else if (m_attachmentType == eAT_CharacterBone)
if (m_attachmentType == eAT_CharacterBone)
{
objNode->setAttr("AttachmentType", "CharacterBone");
}
-1
View File
@@ -131,7 +131,6 @@ public:
enum EAttachmentType
{
eAT_Pivot,
eAT_GeomCacheNode,
eAT_CharacterBone,
};
+1 -1
View File
@@ -608,7 +608,7 @@ bool CObjectManager::AddObject(CBaseObject* obj)
if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj))
{
CEntityObject::EAttachmentType attachType = entityObj->GetAttachType();
if (attachType == CEntityObject::EAttachmentType::eAT_GeomCacheNode || attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
if (attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
{
m_animatedAttachedEntities.insert(entityObj);
}
@@ -13,6 +13,7 @@
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <PostProcess/PostProcessFeatureProcessor.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Name/Name.h>
@@ -47,18 +48,42 @@ namespace TrackView
AZ::Name viewName = AZ::Name("MainCamera");
m_view = AZ::RPI::View::CreateView(viewName, AZ::RPI::View::UsageCamera);
m_renderPipeline->SetDefaultView(m_view);
m_targetView = scene.GetDefaultRenderPipeline()->GetDefaultView();
if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessor>())
{
// This will be set again to mimic the active camera in UpdateView
fp->SetViewAlias(m_view, m_targetView);
}
}
void AtomOutputFrameCapture::DestroyPipeline(AZ::RPI::Scene& scene)
{
if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessor>())
{
// Remove view alias introduced in CreatePipeline and UpdateView
fp->RemoveViewAlias(m_view);
}
scene.RemoveRenderPipeline(m_renderPipeline->GetId());
m_passHierarchy.clear();
m_renderPipeline.reset();
m_view.reset();
m_targetView.reset();
}
void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection)
void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView)
{
if (targetView && targetView != m_targetView)
{
if (AZ::RPI::Scene* scene = SceneFromGameEntityContext())
{
if (AZ::Render::PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessor>())
{
fp->SetViewAlias(m_view, targetView);
m_targetView = targetView;
}
}
}
m_view->SetCameraTransform(cameraTransform);
m_view->SetViewToClipMatrix(cameraProjection);
}
@@ -39,11 +39,12 @@ namespace TrackView
CaptureFinishedCallback captureFinishedCallback);
//! Update the internal view that is associated with the created pipeline.
void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection);
void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView = nullptr);
private:
AZ::RPI::RenderPipelinePtr m_renderPipeline; //!< The internal render pipeline.
AZ::RPI::ViewPtr m_view; //!< The view associated with the render pipeline.
AZ::RPI::ViewPtr m_targetView; //!< The view that this render pipeline will mimic.
AZStd::vector<AZStd::string> m_passHierarchy; //!< Pass hierarchy (includes pipelineName and CopyToSwapChain).
CaptureFinishedCallback m_captureFinishedCallback; //!< Stored callback called from OnCaptureFinished.
@@ -16,6 +16,7 @@
#include <AzCore/Component/ComponentApplication.h>
#include <AzFramework/Windowing/WindowBus.h>
#include <Atom/RPI.Public/ViewProviderBus.h>
// Qt
#include <QAction>
@@ -91,9 +92,12 @@ namespace
static void UpdateAtomOutputFrameCaptureView(TrackView::AtomOutputFrameCapture& atomOutputFrameCapture, const int width, const int height)
{
const AZ::EntityId activeCameraEntityId = TrackView::ActiveCameraEntityId();
AZ::RPI::ViewPtr view = nullptr;
AZ::RPI::ViewProviderBus::EventResult(view, activeCameraEntityId, &AZ::RPI::ViewProvider::GetView);
atomOutputFrameCapture.UpdateView(
TrackView::TransformFromEntityId(activeCameraEntityId),
TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, static_cast<float>(width), static_cast<float>(height)));
TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, aznumeric_cast<float>(width), aznumeric_cast<float>(height)),
view);
}
CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */)
+4 -140
View File
@@ -23,9 +23,9 @@
// AzCore
#include <AzCore/Component/TickBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
// AzQtComponents
#include <AzQtComponents/Utilities/DesktopUtilities.h>
@@ -54,92 +54,14 @@
#include <Shellapi.h>
#endif
bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true };
bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true };
bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true };
bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true };
CAutoRestorePrimaryCDRoot::~CAutoRestorePrimaryCDRoot()
{
QDir::setCurrent(GetIEditor()->GetPrimaryCDFolder());
}
bool CFileUtil::CompileLuaFile(const char* luaFilename)
{
QString luaFile = luaFilename;
if (luaFile.isEmpty())
{
return false;
}
// Check if this file is in Archive.
{
CCryFile file;
if (file.Open(luaFilename, "rb"))
{
// Check if in pack.
if (file.IsInPak())
{
return true;
}
}
}
luaFile = Path::GamePathToFullPath(luaFilename);
// First try compiling script and see if it have any errors.
QString LuaCompiler;
QString CompilerOutput;
// Create the filepath of the lua compiler
QString szExeFileName = qApp->applicationFilePath();
QString exePath = Path::GetPath(szExeFileName);
#if defined(AZ_PLATFORM_WINDOWS)
const char* luaCompiler = "LuaCompiler.exe";
#else
const char* luaCompiler = "lua";
#endif
LuaCompiler = Path::AddPathSlash(exePath) + luaCompiler + " ";
AZStd::string path = luaFile.toUtf8().data();
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, path);
QString finalPath = path.c_str();
finalPath = "\"" + finalPath + "\"";
// Add the name of the Lua file
QString cmdLine = LuaCompiler + finalPath;
// Execute the compiler and capture the output
if (!GetIEditor()->ExecuteConsoleApp(cmdLine, CompilerOutput))
{
QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("Error while executing '%1', make sure the file is in" \
" your Primary CD folder !").arg(luaCompiler));
return false;
}
// Check return string
if (!CompilerOutput.isEmpty())
{
// Errors while compiling file.
// Show output from Lua compiler
if (QMessageBox::critical(QApplication::activeWindow(), QObject::tr("Lua Compiler"),
QObject::tr("Error output from Lua compiler:\r\n%1\r\nDo you want to edit the file ?").arg(CompilerOutput), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
{
int line = 0;
int index = CompilerOutput.indexOf("at line");
if (index >= 0)
{
azsscanf(CompilerOutput.mid(index).toUtf8().data(), "at line %d", &line);
}
// Open the Lua file for editing
EditTextFile(luaFile.toUtf8().data(), line);
}
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const char* pDestinationFilename)
{
@@ -205,7 +127,7 @@ void CFileUtil::EditTextFile(const char* txtFile, int line, IFileUtil::ETextFile
{
QString file = txtFile;
QString fullPathName = Path::GamePathToFullPath(file);
QString fullPathName = Path::GamePathToFullPath(file);
ExtractFile(fullPathName);
QString cmd(fullPathName);
#if defined (AZ_PLATFORM_WINDOWS)
@@ -301,64 +223,6 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
}
}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, const bool bUseGameFolder)
{
QString dosFilepath = PathUtil::ToDosPath(filepath).c_str();
if (bExtractFromPak)
{
ExtractFile(dosFilepath);
}
if (bUseGameFolder)
{
const QString sGameFolder = Path::GetEditingGameDataFolder().c_str();
int nLength = sGameFolder.toUtf8().count();
if (azstrnicmp(filepath, sGameFolder.toUtf8().data(), nLength) != 0)
{
dosFilepath = sGameFolder + '\\' + filepath;
}
dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data()).c_str();
}
const char* engineRoot;
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
const QString fullPath = QString(engineRoot) + '\\' + dosFilepath;
if (gSettings.animEditor.isEmpty())
{
AzQtComponents::ShowFileOnDesktop(fullPath);
}
else
{
if (!QProcess::startDetached(gSettings.animEditor, { fullPath }))
{
CryMessageBox("Can't open the file. You can specify a source editor in Sandbox Preferences or create an association in Windows.", "Cannot open file!", MB_OK | MB_ICONERROR);
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::EditFile(const char* filePath, const bool bExtrackFromPak, const bool bUseGameFolder)
{
QString extension = filePath;
extension.remove(0, extension.lastIndexOf('.'));
if (extension.compare(".ma") == 0)
{
return EditMayaFile(filePath, bExtrackFromPak, bUseGameFolder);
}
else if ((extension.compare(".bspace") == 0) || (extension.compare(".comb") == 0))
{
EditTextFile(filePath, 0, IFileUtil::FILE_TYPE_BSPACE);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::CalculateDccFilename(const QString& assetFilename, QString& dccFilename)
-5
View File
@@ -25,14 +25,9 @@ public:
static void ShowInExplorer(const QString& path);
// Try to compile the given lua file: returns true if compilation succeeded, false on failure.
static bool CompileLuaFile(const char* luaFilename);
static bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr);
static void EditTextFile(const char* txtFile, int line = 0, IFileUtil::ETextFileType fileType = IFileUtil::FILE_TYPE_SCRIPT);
static void EditTextureFile(const char* txtureFile, bool bUseGameFolder);
static bool EditMayaFile(const char* mayaFile, const bool bExtractFromPak, const bool bUseGameFolder);
static bool EditFile(const char* filePath, const bool bExtrackFromPak, const bool bUseGameFolder);
//! dcc filename calculation and extraction sub-routines
static bool CalculateDccFilename(const QString& assetFilename, QString& dccFilename);
-10
View File
@@ -20,21 +20,11 @@ void CFileUtil_impl::ShowInExplorer(const QString& path)
CFileUtil::ShowInExplorer(path);
}
bool CFileUtil_impl::CompileLuaFile(const char* luaFilename)
{
return CFileUtil::CompileLuaFile(luaFilename);
}
bool CFileUtil_impl::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const char* pDestinationFilename)
{
return CFileUtil::ExtractFile(file, bMsgBoxAskForExtraction, pDestinationFilename);
}
void CFileUtil_impl::EditTextFile(const char* txtFile, int line, ETextFileType fileType)
{
CFileUtil::EditTextFile(txtFile, line, fileType);
}
void CFileUtil_impl::EditTextureFile(const char* txtureFile, bool bUseGameFolder)
{
CFileUtil::EditTextureFile(txtureFile, bUseGameFolder);
-2
View File
@@ -36,9 +36,7 @@ public:
void ShowInExplorer(const QString& path) override;
bool CompileLuaFile(const char* luaFilename) override;
bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) override;
void EditTextFile(const char* txtFile, int line = 0, ETextFileType fileType = FILE_TYPE_SCRIPT) override;
void EditTextureFile(const char* txtureFile, bool bUseGameFolder) override;
//! dcc filename calculation and extraction sub-routines
+2 -4
View File
@@ -14,7 +14,6 @@
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for ebus events
#include <AzFramework/API/ApplicationAPI.h>
#include <AzCore/std/string/conversions.h>
#include <AzFramework/IO/LocalFileIO.h>
@@ -175,9 +174,8 @@ namespace Path
//////////////////////////////////////////////////////////////////////////
QString GetEngineRootPath()
{
const char* engineRoot;
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
return QString(engineRoot);
const AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
return QString::fromUtf8(engineRoot.c_str(), static_cast<int>(engineRoot.size()));
}
//////////////////////////////////////////////////////////////////////////
@@ -25,8 +25,6 @@
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
// AzToolsFramework
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
@@ -173,9 +171,6 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
m_pRecentList = pList;
const char* engineRoot;
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
auto projectPath = AZ::Utils::GetProjectPath();
QString gamePath{projectPath.c_str()};
Path::ConvertSlashToBackSlash(gamePath);
@@ -485,16 +485,6 @@ namespace AZ
constexpr bool executeRegDumpCommands = false;
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
// Query for the Executable Path using OS specific functions
CalculateExecutablePath();
// Determine the path to the engine
CalculateEngineRoot();
// If the current platform returns an engaged optional from Utils::GetDefaultAppRootPath(), that is used
// for the application root.
CalculateAppRoot();
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
@@ -614,7 +604,8 @@ namespace AZ
{
AZ_Assert(!m_isStarted, "Component application already started!");
if (m_engineRoot.empty())
using Type = AZ::SettingsRegistryInterface::Type;
if (m_settingsRegistry->GetType(SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder) == Type::NoType)
{
ReportBadEngineRoot();
return nullptr;
@@ -1180,6 +1171,24 @@ namespace AZ
return ReflectionEnvironment::GetReflectionManager() ? ReflectionEnvironment::GetReflectionManager()->GetReflectContext<JsonRegistrationContext>() : nullptr;
}
/// Returns the path to the engine.
const char* ComponentApplication::GetEngineRoot() const
{
static IO::FixedMaxPathString engineRoot;
engineRoot.clear();
m_settingsRegistry->Get(engineRoot, SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
return engineRoot.c_str();
}
const char* ComponentApplication::GetExecutableFolder() const
{
static IO::FixedMaxPathString exeFolder;
exeFolder.clear();
m_settingsRegistry->Get(exeFolder, SettingsRegistryMergeUtils::FilePathKey_BinaryFolder);
return exeFolder.c_str();
}
//=========================================================================
// CreateReflectionManager
//=========================================================================
@@ -1485,27 +1494,6 @@ namespace AZ
}
}
//=========================================================================
// CalculateExecutablePath
//=========================================================================
void ComponentApplication::CalculateExecutablePath()
{
m_exeDirectory = Utils::GetExecutableDirectory();
}
void ComponentApplication::CalculateAppRoot()
{
if (AZStd::optional<AZ::StringFunc::Path::FixedString> appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
{
m_appRoot = AZStd::move(*appRootPath);
}
}
void ComponentApplication::CalculateEngineRoot()
{
m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native();
}
void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath)
{
// No special parsing of the Module Path is done by the Component Application anymore
@@ -221,13 +221,10 @@ namespace AZ
BehaviorContext* GetBehaviorContext() override;
/// Returns the json registration context that has been registered with the app, if there is one.
JsonRegistrationContext* GetJsonRegistrationContext() override;
/// Returns the working root folder that has been registered with the app, if there is one.
/// It's expected that derived applications will implement an application root.
const char* GetAppRoot() const override { return m_appRoot.c_str(); }
/// Returns the path to the engine.
const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
const char* GetEngineRoot() const override;
/// Returns the path to the folder the executable is in.
const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
const char* GetExecutableFolder() const override;
//////////////////////////////////////////////////////////////////////////
/// TickRequestBus
@@ -352,15 +349,6 @@ namespace AZ
/// Adds system components requested by modules and the application to the system entity.
void AddRequiredSystemComponents(AZ::Entity* systemEntity);
/// Calculates the directory the application executable comes from.
void CalculateExecutablePath();
/// Calculates the root directory of the engine.
void CalculateEngineRoot();
/// Deprecated: The term "AppRoot" has no meaning
void CalculateAppRoot();
template<typename Iterator>
static void NormalizePath(Iterator begin, Iterator end, bool doLowercase = true)
{
@@ -388,9 +376,6 @@ namespace AZ
void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
IAllocatorAllocate* m_osAllocator{ nullptr };
EntitySetType m_entities;
AZ::IO::FixedMaxPath m_exeDirectory;
AZ::IO::FixedMaxPath m_engineRoot;
AZ::IO::FixedMaxPath m_appRoot;
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectPathChangedHandler;
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectNameChangedHandler;
@@ -175,10 +175,6 @@ namespace AZ
//! the serializers used by the best-effort json serialization.
virtual class JsonRegistrationContext* GetJsonRegistrationContext() = 0;
//! Gets the name of the working root folder that was registered with the app.
//! @return a pointer to the name of the app's root folder, if a root folder was registered.
virtual const char* GetAppRoot() const = 0;
//! Gets the path of the working engine folder that the app is a part of.
//! @return a pointer to the engine path.
virtual const char* GetEngineRoot() const = 0;
+1 -1
View File
@@ -100,7 +100,7 @@ namespace AZ
void Set(float x, float y, float z);
//! Sets components from an array of 3 floats in xyz order.
void Set(float values[]);
void Set(const float values[]);
//! Indexed access using operator(), just for convenience.
float operator()(int32_t index) const;
@@ -186,7 +186,7 @@ namespace AZ
}
AZ_MATH_INLINE void Vector3::Set(float values[])
AZ_MATH_INLINE void Vector3::Set(const float values[])
{
m_value = Simd::Vec3::LoadImmediate(values[0], values[1], values[2]);
}
@@ -50,7 +50,12 @@ namespace AZ
if (!s_instance)
{
s_instance = Environment::FindVariable<NameDictionary>(NameDictionaryInstanceName);
// Because the NameDictionary allocates memory using the AZ::Allocator and it is created
// in the executable memory space, it's ownership cannot be transferred to other module memory spaces
// Otherwise this could cause the the NameDictionary to be destroyed in static de-init
// after the AZ::Allocators have been destroyed
// Therefore we supply the isTransferOwnership value of false using CreateVariableEx
s_instance = AZ::Environment::CreateVariableEx<NameDictionary>(NameDictionaryInstanceName, true, false);
}
return s_instance.IsConstructed();
@@ -266,7 +266,8 @@ namespace AZ::SettingsRegistryMergeUtils
// Step 3 locate the project root and attempt to find the engine root using the registered engine
// for the project in the project.json file
AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry);
AZ::IO::FixedMaxPath projectRoot;
settingsRegistry.Get(projectRoot.Native(), FilePathKey_ProjectPath);
if (projectRoot.empty())
{
return {};
@@ -668,7 +669,7 @@ namespace AZ::SettingsRegistryMergeUtils
// NOTE: We make the project-path in the BootstrapSettingsRootKey absolute first
AZ::IO::FixedMaxPath projectPath = FindProjectRoot(registry);
if (constexpr auto projectPathKey = FixedValueString(BootstrapSettingsRootKey) + "/project_path";
if ([[maybe_unused]] constexpr auto projectPathKey = FixedValueString(BootstrapSettingsRootKey) + "/project_path";
!projectPath.empty())
{
if (projectPath.IsRelative())
@@ -693,6 +694,7 @@ namespace AZ::SettingsRegistryMergeUtils
R"(Project path isn't set in the Settings Registry at "%.*s".)"
" Project-related filepaths will be set relative to the executable directory\n",
AZ_STRING_ARG(projectPathKey));
projectPath = exePath;
registry.Set(FilePathKey_ProjectPath, exePath.Native());
}
@@ -1427,26 +1427,36 @@ namespace AZ
namespace AssetPath
{
void CalculateBranchToken(const AZStd::string& appRootPath, AZStd::string& token)
namespace Internal
{
// Normalize the token to prepare for CRC32 calculation
AZStd::string normalized = appRootPath;
AZ::u32 CalculateBranchTokenHash(AZStd::string_view engineRootPath)
{
// Normalize the token to prepare for CRC32 calculation
auto NormalizeEnginePath = [](const char element) -> char
{
// Substitute path separators with '_' and lower case
return element == AZ::IO::WindowsPathSeparator || element == AZ::IO::PosixPathSeparator
? '_' : static_cast<char>(std::tolower(element));
};
// Strip out any trailing path separators
AZ::StringFunc::Strip(normalized, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING AZ_WRONG_FILESYSTEM_SEPARATOR_STRING,false, false, true);
// Trim off trailing path separators
engineRootPath = RStrip(engineRootPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
AZ::IO::FixedMaxPathString enginePath;
AZStd::transform(engineRootPath.begin(), engineRootPath.end(),
AZStd::back_inserter(enginePath), AZStd::move(NormalizeEnginePath));
// Lower case always
AZStd::to_lower(normalized.begin(), normalized.end());
// Substitute path separators with '_'
AZStd::replace(normalized.begin(), normalized.end(), '\\', '_');
AZStd::replace(normalized.begin(), normalized.end(), '/', '_');
// Perform the CRC32 calculation
const AZ::Crc32 branchTokenCrc(normalized.c_str(), normalized.size(), true);
char branchToken[12];
azsnprintf(branchToken, AZ_ARRAY_SIZE(branchToken), "0x%08X", static_cast<AZ::u32>(branchTokenCrc));
token = AZStd::string(branchToken);
// Perform the CRC32 calculation
constexpr bool forceLowercase = true;
return static_cast<AZ::u32>(AZ::Crc32(enginePath.c_str(), enginePath.size(), forceLowercase));
}
}
void CalculateBranchToken(AZStd::string_view engineRootPath, AZStd::string& token)
{
token = AZStd::string::format("0x%08X", Internal::CalculateBranchTokenHash(engineRootPath));
}
void CalculateBranchToken(AZStd::string_view engineRootPath, AZ::IO::FixedMaxPathString& token)
{
token = AZ::IO::FixedMaxPathString::format("0x%08X", Internal::CalculateBranchTokenHash(engineRootPath));
}
}
@@ -485,10 +485,11 @@ namespace AZ
//! CalculateBranchToken
/*! Calculate the branch token that is used for asset processor connection negotiations
*
* \param appRootPath - The absolute path of the app root to base the token calculation on
* \param engineRootPath - The absolute path to the engine root to base the token calculation on
* \param token - The result of the branch token calculation
*/
void CalculateBranchToken(const AZStd::string& appRootPath, AZStd::string& token);
void CalculateBranchToken(AZStd::string_view engineRootPath, AZStd::string& token);
void CalculateBranchToken(AZStd::string_view engineRootPath, AZ::IO::FixedMaxPathString& token);
}
//////////////////////////////////////////////////////////////////////////
@@ -41,7 +41,6 @@ namespace UnitTest
MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ());
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
MOCK_CONST_METHOD0(GetAppRoot, const char* ());
MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
@@ -59,7 +59,6 @@ namespace UnitTest
AZ::SerializeContext* GetSerializeContext() override { return nullptr; }
AZ::BehaviorContext* GetBehaviorContext() override { return m_behaviorContext; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
+7 -13
View File
@@ -1060,26 +1060,21 @@ namespace UnitTest
/**
* UserSettingsComponent test
*/
class UserSettingsTestApp
: public ComponentApplication
, public UserSettingsFileLocatorBus::Handler
{
public:
void SetExecutableFolder(const char* path)
{
m_exeDirectory = path;
}
class UserSettingsTestApp
: public ComponentApplication
, public UserSettingsFileLocatorBus::Handler
{
public:
AZStd::string ResolveFilePath(u32 providerId) override
{
AZStd::string filePath;
if (providerId == UserSettings::CT_GLOBAL)
{
filePath = (m_exeDirectory / "GlobalUserSettings.xml").String();
filePath = (AZ::IO::Path(GetTestFolderPath()) / "GlobalUserSettings.xml").Native();
}
else if (providerId == UserSettings::CT_LOCAL)
{
filePath = (m_exeDirectory / "LocalUserSettings.xml").String();
filePath = (AZ::IO::Path(GetTestFolderPath()) / "LocalUserSettings.xml").Native();
}
return filePath;
}
@@ -1117,7 +1112,6 @@ namespace UnitTest
ComponentApplication::Descriptor appDesc;
appDesc.m_memoryBlocksByteSize = 10 * 1024 * 1024;
Entity* systemEntity = app.Create(appDesc);
app.SetExecutableFolder(GetTestFolderPath().c_str());
app.UserSettingsFileLocatorBus::Handler::BusConnect();
// Make sure user settings file does not exist at this point
@@ -1240,7 +1240,6 @@ namespace UnitTest
SerializeContext* GetSerializeContext() override { return m_serializeContext.get(); }
BehaviorContext* GetBehaviorContext() override { return nullptr; }
JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
@@ -67,12 +67,6 @@ namespace AzFramework
/// Make path relative to the provided root.
virtual void MakePathRelative(AZStd::string& /*fullPath*/, const char* /*rootPath*/) {}
/// Gets the engine root path where the modules for the current engine are located.
virtual const char* GetEngineRoot() const { return nullptr; }
/// Retrieves the app root path for the application.
virtual const char* GetAppRoot() const { return nullptr; }
/// Get the Command Line arguments passed in.
virtual const CommandLine* GetCommandLine() { return nullptr; }
@@ -69,6 +69,7 @@
#include <AzCore/Console/Console.h>
#include <AzFramework/Viewport/ViewportBus.h>
#include <GridMate/Memory.h>
#include <AzFramework/Physics/HeightfieldProviderBus.h>
#include "Application.h"
#include <AzFramework/AzFrameworkModule.h>
@@ -224,13 +225,6 @@ namespace AzFramework
}
}
void Application::PreModuleLoad()
{
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
}
void Application::Stop()
{
if (m_isStarted)
@@ -318,6 +312,8 @@ namespace AzFramework
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
AzFramework::Terrain::TerrainDataRequests::Reflect(context);
Physics::HeightfieldProviderRequests::Reflect(context);
Physics::HeightMaterialPoint::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
@@ -394,11 +390,6 @@ namespace AzFramework
outModules.emplace_back(aznew AzFrameworkModule());
}
const char* Application::GetAppRoot() const
{
return m_appRoot.c_str();
}
const char* Application::GetCurrentConfigurationName() const
{
#if defined(_RELEASE)
@@ -434,19 +425,19 @@ namespace AzFramework
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
{
AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
auto fullPath = AZ::IO::FixedMaxPath(GetEngineRoot()) / engineRelativePath;
engineRelativePath = fullPath.String();
}
void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const
{
AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token);
AZ::StringFunc::AssetPath::CalculateBranchToken(GetEngineRoot(), token);
}
////////////////////////////////////////////////////////////////////////////
void Application::MakePathRootRelative(AZStd::string& fullPath)
{
MakePathRelative(fullPath, m_engineRoot.c_str());
MakePathRelative(fullPath, GetEngineRoot());
}
////////////////////////////////////////////////////////////////////////////
@@ -582,30 +573,6 @@ namespace AzFramework
}
}
void Application::SetRootPath(RootPathType type, const char* source)
{
[[maybe_unused]] const size_t sourceLen = strlen(source);
// Copy the source path to the intended root path and correct the path separators as well
switch (type)
{
case RootPathType::AppRoot:
{
AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source);
m_appRoot = AZ::IO::PathView(source).LexicallyNormal();
}
break;
case RootPathType::EngineRoot:
{
AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source);
m_engineRoot = AZ::IO::PathView(source).LexicallyNormal();
}
break;
default:
AZ_Assert(false, "Invalid RootPathType (%d)", static_cast<int>(type));
}
}
struct DeprecatedAliasesKeyVisitor
: AZ::SettingsRegistryInterface::Visitor
{
@@ -95,8 +95,6 @@ namespace AzFramework
//////////////////////////////////////////////////////////////////////////
//! ApplicationRequests::Bus::Handler
const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
const char* GetAppRoot() const override;
void ResolveEnginePath(AZStd::string& engineRelativePath) const override;
void CalculateBranchTokenForEngineRoot(AZStd::string& token) const override;
bool IsPrefabSystemEnabled() const override;
@@ -146,8 +144,6 @@ namespace AzFramework
*/
void SetFileIOAliases();
void PreModuleLoad() override;
//////////////////////////////////////////////////////////////////////////
//! AZ::ComponentApplication
void RegisterCoreComponents() override;
@@ -181,13 +177,7 @@ namespace AzFramework
bool m_ownsConsole = false;
bool m_exitMainLoopRequested = false;
enum class RootPathType
{
AppRoot,
EngineRoot
};
void SetRootPath(RootPathType type, const char* source);
};
} // namespace AzFramework
@@ -0,0 +1,46 @@
/*
* 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 "HeightfieldProviderBus.h"
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace Physics
{
void HeightfieldProviderRequests::Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<Physics::HeightfieldProviderRequestsBus>("HeightfieldProviderRequestsBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Event("GetHeightfieldGridSpacing", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridSpacing)
->Event("GetHeightfieldAabb", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldAabb)
->Event("GetHeightfieldTransform", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldTransform)
->Event("GetMaterialList", &Physics::HeightfieldProviderRequestsBus::Events::GetMaterialList)
->Event("GetHeights", &Physics::HeightfieldProviderRequestsBus::Events::GetHeights)
->Event("GetHeightsAndMaterials", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightsAndMaterials)
->Event("GetHeightfieldMinHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMinHeight)
->Event("GetHeightfieldMaxHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMaxHeight)
->Event("GetHeightfieldGridColumns", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridColumns)
->Event("GetHeightfieldGridRows", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridRows)
;
}
}
void HeightMaterialPoint::Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::HeightMaterialPoint>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
} // namespace Physics
@@ -26,10 +26,25 @@ namespace Physics
struct HeightMaterialPoint
{
HeightMaterialPoint(
float height = 0.0f, QuadMeshType type = QuadMeshType::SubdivideUpperLeftToBottomRight, uint8_t index = 0)
: m_height(height)
, m_quadMeshType(type)
, m_materialIndex(index)
, m_padding(0)
{
}
virtual ~HeightMaterialPoint() = default;
static void Reflect(AZ::ReflectContext* context);
AZ_RTTI(HeightMaterialPoint, "{DF167ED4-24E6-4F7B-8AB7-42622F7DBAD3}");
float m_height{ 0.0f }; //!< Holds the height of this point in the heightfield relative to the heightfield entity location.
QuadMeshType m_quadMeshType{ QuadMeshType::SubdivideUpperLeftToBottomRight }; //!< By default, create two triangles like this |\|, where this point is in the upper left corner.
uint8_t m_materialIndex{ 0 }; //!< The surface material index for the upper left corner of this quad.
uint16_t m_padding{ 0 }; //!< available for future use.
};
//! An interface to provide heightfield values.
@@ -37,6 +52,8 @@ namespace Physics
: public AZ::ComponentBus
{
public:
static void Reflect(AZ::ReflectContext* context);
//! Returns the distance between each height in the map.
//! @return Vector containing Column Spacing, Rows Spacing.
virtual AZ::Vector2 GetHeightfieldGridSpacing() const = 0;
@@ -46,11 +63,27 @@ namespace Physics
//! @param numRows contains the size of the grid in the y direction.
virtual void GetHeightfieldGridSize(int32_t& numColumns, int32_t& numRows) const = 0;
//! Returns the height field gridsize columns.
//! @return the size of the grid in the x direction.
virtual int32_t GetHeightfieldGridColumns() const = 0;
//! Returns the height field gridsize rows.
//! @return the size of the grid in the y direction.
virtual int32_t GetHeightfieldGridRows() const = 0;
//! Returns the height field min and max height bounds.
//! @param minHeightBounds contains the minimum height that the heightfield can contain.
//! @param maxHeightBounds contains the maximum height that the heightfield can contain.
virtual void GetHeightfieldHeightBounds(float& minHeightBounds, float& maxHeightBounds) const = 0;
//! Returns the height field min height bounds.
//! @return the minimum height that the heightfield can contain.
virtual float GetHeightfieldMinHeight() const = 0;
//! Returns the height field max height bounds.
//! @return the maximum height that the heightfield can contain.
virtual float GetHeightfieldMaxHeight() const = 0;
//! Returns the AABB of the heightfield.
//! This is provided separately from the shape AABB because the heightfield might choose to modify the AABB bounds.
//! @return AABB of the heightfield.
@@ -360,6 +360,11 @@ namespace Physics
->Field("MaterialId", &Physics::MaterialId::m_id)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::MaterialId>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
MaterialId MaterialId::Create()
@@ -229,6 +229,7 @@ set(FILES
Physics/Configuration/SystemConfiguration.h
Physics/Configuration/SystemConfiguration.cpp
Physics/HeightfieldProviderBus.h
Physics/HeightfieldProviderBus.cpp
Physics/SimulatedBodies/RigidBody.h
Physics/SimulatedBodies/RigidBody.cpp
Physics/SimulatedBodies/StaticRigidBody.h
@@ -6,6 +6,8 @@
*
*/
#pragma once
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbEventHandler.h>
@@ -14,7 +14,7 @@
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/Asset/AssetUtils.h>
@@ -205,7 +205,7 @@ namespace AzToolsFramework::AssetUtils
return platformConfigFilePathsAdded;
}
AZStd::vector<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
AZStd::vector<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view projectPath,
bool addPlatformConfigs, bool addGemsConfigs, AZ::SettingsRegistryInterface* settingsRegistry)
{
constexpr const char* AssetProcessorGamePlatformConfigFileName = "AssetProcessorGamePlatformConfig.ini";
@@ -232,14 +232,13 @@ namespace AzToolsFramework::AssetUtils
Internal::AddGemConfigFiles(gemInfoList, configFiles);
}
AZ::IO::Path assetRootDir(assetRoot);
assetRootDir /= projectPath;
AZ::IO::Path projectRoot(projectPath);
AZ::IO::Path projectConfigFile = assetRootDir / AssetProcessorGamePlatformConfigFileName;
AZ::IO::Path projectConfigFile = projectRoot / AssetProcessorGamePlatformConfigFileName;
configFiles.push_back(projectConfigFile);
// Add a file entry for the Project AssetProcessor setreg file
projectConfigFile = assetRootDir / AssetProcessorGamePlatformConfigSetreg;
projectConfigFile = projectRoot / AssetProcessorGamePlatformConfigSetreg;
configFiles.push_back(projectConfigFile);
return configFiles;
@@ -251,10 +250,10 @@ namespace AzToolsFramework::AssetUtils
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(relPathFromRoot.c_str(), tokens, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
AZStd::string validatedPath;
AZ::IO::FixedMaxPath validatedPath;
if (rootPath.empty())
{
AzFramework::ApplicationRequests::Bus::BroadcastResult(validatedPath, &AzFramework::ApplicationRequests::GetEngineRoot);
validatedPath = AZ::Utils::GetEnginePath();
}
else
{
@@ -299,10 +298,7 @@ namespace AzToolsFramework::AssetUtils
break;
}
AZStd::string absoluteFilePath;
AZ::StringFunc::Path::ConstructFull(validatedPath.c_str(), element.c_str(), absoluteFilePath);
validatedPath = absoluteFilePath; // go one step deeper.
validatedPath /= element; // go one step deeper.
}
if (success)
@@ -40,7 +40,7 @@ namespace AzToolsFramework::AssetUtils
//! Also note that if the project has any "game project gems", then those will also be inserted last,
//! and thus have a higher priority than the root or non - project gems.
//! Also note that the game project could be in a different location to the engine therefore we need the assetRoot param.
AZStd::vector<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
AZStd::vector<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view projectPath,
bool addPlatformConfigs = true, bool addGemsConfigs = true, AZ::SettingsRegistryInterface* settingsRegistry = nullptr);
//! A utility function which checks the given path starting at the root and updates the relative path to be the actual case correct path.
@@ -20,7 +20,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
AZ_POP_DISABLE_WARNING
AZ_CVAR(
bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null,
bool, ed_useNewAssetBrowserTableView, true, nullptr, AZ::ConsoleFunctorFlags::Null,
"Use the new AssetBrowser TableView for searching assets.");
namespace AzToolsFramework
{
@@ -9,11 +9,11 @@
#include <AzCore/EBus/Results.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <QString>
namespace AzToolsFramework
@@ -113,11 +113,9 @@ namespace AzToolsFramework
if (iconPathToUse.isEmpty())
{
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
AZ_Assert(engineRoot, "Engine Root not initialized");
AZStd::string iconPath = AZStd::string::format("%s%s", engineRoot, DefaultFileIconPath);
iconPathToUse = iconPath.c_str();
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
AZ_Assert(!engineRoot.empty(), "Engine Root not initialized");
iconPathToUse = (engineRoot / DefaultFileIconPath).c_str();
}
m_pixmap.load(iconPathToUse);
@@ -15,6 +15,7 @@
#include <AzCore/std/sort.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Commands/EntityStateCommand.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
@@ -468,6 +469,18 @@ namespace AzToolsFramework
EntityIdList children;
EditorEntityInfoRequestBus::EventResult(children, parentId, &EditorEntityInfoRequestBus::Events::GetChildren);
// If Prefabs are enabled, don't check the order for an invalid parent, just return its children (i.e. the root container entity)
// There will currently always be one root container entity, so there's no order to retrieve
if (!parentId.IsValid())
{
bool isPrefabEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
if (isPrefabEnabled)
{
return children;
}
}
EntityIdList entityChildOrder;
AZ::EntityId sortEntityId = GetEntityIdForSortInfo(parentId);
EditorEntitySortRequestBus::EventResult(entityChildOrder, sortEntityId, &EditorEntitySortRequestBus::Events::GetChildEntityOrderArray);
@@ -11,6 +11,8 @@
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/sort.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
static_assert(sizeof(AZ::u64) == sizeof(AZ::EntityId), "We use AZ::EntityId for Persistent ID, which is a u64 under the hood. These must be the same size otherwise the persistent id will have to be rewritten");
@@ -144,6 +146,12 @@ namespace AzToolsFramework
bool EditorEntitySortComponent::AddChildEntityInternal(const AZ::EntityId& entityId, bool addToBack, EntityOrderArray::iterator insertPosition)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
if (m_ignoreIncomingOrderChanges)
{
return true;
}
auto entityItr = m_childEntityOrderCache.find(entityId);
if (entityItr == m_childEntityOrderCache.end())
{
@@ -198,6 +206,12 @@ namespace AzToolsFramework
bool EditorEntitySortComponent::RemoveChildEntity(const AZ::EntityId& entityId)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
if (m_ignoreIncomingOrderChanges)
{
return true;
}
auto entityItr = m_childEntityOrderCache.find(entityId);
if (entityItr != m_childEntityOrderCache.end())
{
@@ -250,11 +264,30 @@ namespace AzToolsFramework
}
}
void EditorEntitySortComponent::OnPrefabInstancePropagationBegin()
{
m_ignoreIncomingOrderChanges = true;
}
void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
{
m_ignoreIncomingOrderChanges = false;
}
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
{
// mark the order as dirty before sending the ChildEntityOrderArrayUpdated event in order for PrepareSave to be properly handled in the case
// one of the event listeners needs to build the InstanceDataHierarchy
m_entityOrderIsDirty = true;
// Force an immediate update for prefabs, which won't receive PrepareSave
bool isPrefabEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
if (isPrefabEnabled)
{
PrepareSave();
}
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
}
@@ -264,10 +297,20 @@ namespace AzToolsFramework
// This is a special case for certain EditorComponents only!
EditorEntitySortRequestBus::Handler::BusConnect(GetEntityId());
EditorEntityContextNotificationBus::Handler::BusConnect();
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
}
void EditorEntitySortComponent::Activate()
{
// Run the post-serialize handler if prefabs are enabled because PostLoad won't be called automatically
bool isPrefabEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
if (isPrefabEnabled)
{
PostLoad();
}
// Send out that the order for our entity is now updated
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
}
@@ -10,6 +10,7 @@
#include "EditorEntitySortBus.h"
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzToolsFramework
@@ -20,6 +21,7 @@ namespace AzToolsFramework
: public AzToolsFramework::Components::EditorComponentBase
, public EditorEntitySortRequestBus::Handler
, public EditorEntityContextNotificationBus::Handler
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
{
public:
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
@@ -45,6 +47,9 @@ namespace AzToolsFramework
// EditorEntityContextNotificationBus::Handler
void OnEntityStreamLoadSuccess() override;
//////////////////////////////////////////////////////////////////////////
void OnPrefabInstancePropagationBegin() override;
void OnPrefabInstancePropagationEnd() override;
private:
void MarkDirtyAndSendChangedEvent();
bool AddChildEntityInternal(const AZ::EntityId& entityId, bool addToBack, EntityOrderArray::iterator insertPosition);
@@ -106,6 +111,7 @@ namespace AzToolsFramework
EntityOrderCache m_childEntityOrderCache; ///< The map of entity id to index for quick look up
bool m_entityOrderIsDirty = true; ///< This flag indicates our stored serialization order data is out of date and must be rebuilt before serialization occurs
bool m_ignoreIncomingOrderChanges = false; ///< This is set when prefab propagation occurs so that non-authored order changes can be ignored
};
}
} // namespace AzToolsFramework
@@ -175,20 +175,14 @@ namespace AzToolsFramework::Prefab
m_focusedInstance = focusedInstance;
m_focusedTemplateId = focusedInstance->get().GetTemplateId();
AZ::EntityId containerEntityId;
if (focusedInstance->get().GetParentInstance() != AZStd::nullopt)
{
containerEntityId = focusedInstance->get().GetContainerEntityId();
}
else
{
containerEntityId = AZ::EntityId();
}
// Focus on the descendants of the container entity in the Editor, if the interface is initialized.
if (m_focusModeInterface)
{
const AZ::EntityId containerEntityId =
(focusedInstance->get().GetParentInstance() != AZStd::nullopt)
? focusedInstance->get().GetContainerEntityId()
: AZ::EntityId();
m_focusModeInterface->SetFocusRoot(containerEntityId);
}
@@ -1144,6 +1144,10 @@ namespace AzToolsFramework
AZ::EntityId firstEntityIdToDelete = entityIdsNoFocusContainer[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDelete);
if (!commonOwningInstance.has_value())
{
return AZ::Failure(AZStd::string("Cannot delete entities belonging to an invalid instance"));
}
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
// cannot delete an instance from itself.
@@ -6,10 +6,10 @@
*
*/
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <AzFramework/API/ApplicationAPI.h>
namespace AzToolsFramework
{
@@ -68,12 +68,12 @@ namespace AzToolsFramework
SourceControlThumbnail::SourceControlThumbnail(SharedThumbnailKey key)
: Thumbnail(key)
{
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
AZ_Assert(engineRoot, "Engine Root not initialized");
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
AZ_Assert(!engineRoot.empty(), "Engine Root not initialized");
m_writableIconPath = (engineRoot / WRITABLE_ICON_PATH).String();
m_nonWritableIconPath = (engineRoot / NONWRITABLE_ICON_PATH).String();
AzFramework::StringFunc::Path::Join(engineRoot, WRITABLE_ICON_PATH, m_writableIconPath);
AzFramework::StringFunc::Path::Join(engineRoot, NONWRITABLE_ICON_PATH, m_nonWritableIconPath);
BusConnect();
}
@@ -90,8 +90,8 @@ namespace AzToolsFramework
AZ_Assert(sourceControlKey, "Incorrect key type, excpected SourceControlThumbnailKey");
AZStd::string myFileName(sourceControlKey->GetFileName());
AzFramework::StringFunc::Path::Normalize(myFileName);
if (AzFramework::StringFunc::Equal(myFileName.c_str(), filename))
AZ::StringFunc::Path::Normalize(myFileName);
if (AZ::StringFunc::Equal(myFileName.c_str(), filename))
{
Update();
}
@@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Slice/SliceDataFlagsCommand.h>
#include <AzToolsFramework/Slice/SliceMetadataEntityContextBus.h>
@@ -606,6 +607,7 @@ namespace AzToolsFramework
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
AzToolsFramework::GetEntityContextId());
ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
}
EntityPropertyEditor::~EntityPropertyEditor()
@@ -618,7 +620,8 @@ namespace AzToolsFramework
AZ::EntitySystemBus::Handler::BusDisconnect();
EditorEntityContextNotificationBus::Handler::BusDisconnect();
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
for (auto& entityId : m_overrideSelectedEntityIds)
{
DisconnectFromEntityBuses(entityId);
@@ -892,25 +895,51 @@ namespace AzToolsFramework
{
if (!m_prefabsAreEnabled)
{
return m_isLevelEntityEditor ? InspectorLayout::LEVEL : InspectorLayout::ENTITY;
return m_isLevelEntityEditor ? InspectorLayout::Level : InspectorLayout::Entity;
}
// Prefabs layout logic
// If this is the container entity for the root instance, treat it like a level entity.
AZ::EntityId levelContainerEntityId = m_prefabPublicInterface->GetLevelInstanceContainerEntityId();
if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), levelContainerEntityId) != m_selectedEntityIds.end())
{
if (m_selectedEntityIds.size() > 1)
{
return InspectorLayout::INVALID;
return InspectorLayout::Invalid;
}
else
{
return InspectorLayout::LEVEL;
return InspectorLayout::Level;
}
}
else
{
return InspectorLayout::ENTITY;
// If this is the container entity for the currently focused prefab, utilize a separate layout.
if (auto prefabFocusPublicInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
{
AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
EditorEntityContextRequestBus::BroadcastResult(
editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
AZ::EntityId focusedPrefabContainerEntityId =
prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), focusedPrefabContainerEntityId) !=
m_selectedEntityIds.end())
{
if (m_selectedEntityIds.size() > 1)
{
return InspectorLayout::Invalid;
}
else
{
return InspectorLayout::ContainerEntityOfFocusedPrefab;
}
}
}
}
return InspectorLayout::Entity;
}
void EntityPropertyEditor::UpdateEntityDisplay()
@@ -919,7 +948,7 @@ namespace AzToolsFramework
InspectorLayout layout = GetCurrentInspectorLayout();
if (layout == InspectorLayout::LEVEL)
if (!m_prefabsAreEnabled && layout == InspectorLayout::Level)
{
AZStd::string levelName;
AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName);
@@ -961,14 +990,19 @@ namespace AzToolsFramework
InspectorLayout layout = GetCurrentInspectorLayout();
if (layout == InspectorLayout::LEVEL)
if (layout == InspectorLayout::Level)
{
// The Level Inspector should only have a list of selectable components after the
// level entity itself is valid (i.e. "selected").
return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::LevelEntity;
}
if (layout == InspectorLayout::INVALID)
if (layout == InspectorLayout::ContainerEntityOfFocusedPrefab)
{
return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab;
}
if (layout == InspectorLayout::Invalid)
{
return SelectionEntityTypeInfo::Mixed;
}
@@ -1138,7 +1172,8 @@ namespace AzToolsFramework
}
}
bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::LEVEL;
bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::Level;
bool isContainerOfFocusedPrefabLayout = GetCurrentInspectorLayout() == InspectorLayout::ContainerEntityOfFocusedPrefab;
m_gui->m_entityDetailsLabel->setText(entityDetailsLabelText);
m_gui->m_entityDetailsLabel->setVisible(entityDetailsVisible);
@@ -1146,10 +1181,14 @@ namespace AzToolsFramework
m_gui->m_entityNameLabel->setVisible(hasEntitiesDisplayed);
m_gui->m_entityIcon->setVisible(hasEntitiesDisplayed);
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor);
m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_statusLabel->setVisible(
hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_statusComboBox->setVisible(
hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdLabel->setVisible(
hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_entityIdText->setVisible(
hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
bool displayComponentSearchBox = hasEntitiesDisplayed;
if (hasEntitiesDisplayed)
@@ -1157,7 +1196,9 @@ namespace AzToolsFramework
// Build up components to display
SharedComponentArray sharedComponentArray;
BuildSharedComponentArray(sharedComponentArray,
!(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities || selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities));
!(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities ||
selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities) ||
selectionEntityTypeInfo == SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab);
if (sharedComponentArray.size() == 0)
{
@@ -1173,7 +1214,8 @@ namespace AzToolsFramework
UpdateEntityDisplay();
}
m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout);
m_gui->m_darkBox->setVisible(
displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout && !isContainerOfFocusedPrefabLayout);
m_gui->m_entitySearchBox->setVisible(displayComponentSearchBox);
bool displayAddComponentMenu = CanAddComponentsToSelection(selectionEntityTypeInfo);
@@ -354,7 +354,8 @@ namespace AzToolsFramework
OnlyLayerEntities,
OnlyPrefabEntities,
Mixed,
LevelEntity
LevelEntity,
ContainerEntityOfFocusedPrefab
};
/**
* Returns what kinds of entities are in the current selection. This is used because mixed selection
@@ -364,7 +365,7 @@ namespace AzToolsFramework
SelectionEntityTypeInfo GetSelectionEntityTypeInfo(const EntityIdList& selection) const;
/**
* Returns true if a selection matching the passed in selection informatation allows components to be added.
* Returns true if a selection matching the passed in selection information allows components to be added.
*/
bool CanAddComponentsToSelection(const SelectionEntityTypeInfo& selectionEntityTypeInfo) const;
@@ -581,9 +582,10 @@ namespace AzToolsFramework
enum class InspectorLayout
{
ENTITY = 0, // All selected entities are regular entities
LEVEL, // The selected entity is the level prefab container entity
INVALID // Other entities are selected alongside the level prefab container entity
Entity = 0, // All selected entities are regular entities.
Level, // The selected entity is the prefab container entity for the level prefab, or the slice level entity.
ContainerEntityOfFocusedPrefab, // The selected entity is the prefab container entity for the focused prefab.
Invalid // Other entities are selected alongside the level prefab container entity.
};
InspectorLayout GetCurrentInspectorLayout() const;
@@ -28,6 +28,7 @@
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
@@ -1177,8 +1178,10 @@ namespace AzToolsFramework
continue;
}
const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo);
debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax());
if (const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo); bound.IsValid())
{
debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax());
}
}
debugDisplay.DepthTestOn();
@@ -1334,39 +1337,6 @@ namespace AzToolsFramework
EndRecordManipulatorCommand();
});
// surface
translationManipulators->InstallSurfaceManipulatorMouseDownCallback(
[this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action)
{
BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds);
InitializeTranslationLookup(m_entityIdManipulators);
m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(m_entityIdManipulators.m_manipulators->GetLocalTransform());
// [ref 1.]
BeginRecordManipulatorCommand();
});
translationManipulators->InstallSurfaceManipulatorMouseMoveCallback(
[this, prevModifiers, manipulatorEntityIds](const SurfaceManipulator::Action& action) mutable
{
UpdateTranslationManipulator(
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers,
m_transformChangedInternally, m_spaceCluster.m_spaceLock);
});
translationManipulators->InstallSurfaceManipulatorMouseUpCallback(
[this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action)
{
AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast(
&AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged,
manipulatorEntityIds->m_entityIds);
EndRecordManipulatorCommand();
});
// transfer ownership
m_entityIdManipulators.m_manipulators = AZStd::move(translationManipulators);
}
@@ -3604,6 +3574,16 @@ namespace AzToolsFramework
m_selectedEntityIds.clear();
m_selectedEntityIds.reserve(selectedEntityIds.size());
AZStd::copy(selectedEntityIds.begin(), selectedEntityIds.end(), AZStd::inserter(m_selectedEntityIds, m_selectedEntityIds.end()));
// Do not create manipulators for the container entity of the focused prefab.
if (auto prefabFocusPublicInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
{
AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); focusRoot.IsValid())
{
m_selectedEntityIds.erase(focusRoot);
}
}
}
void EditorTransformComponentSelection::OnTransformChanged(
@@ -1116,7 +1116,6 @@ namespace UnitTest
SerializeContext* GetSerializeContext() override { return m_serializeContext.get(); }
BehaviorContext* GetBehaviorContext() override { return nullptr; }
JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
@@ -36,11 +36,6 @@ namespace UnitTest
: public ComponentApplication
{
public:
void SetExecutableFolder(const char* path)
{
m_exeDirectory = path;
}
void SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations) override
{
ComponentApplication::SetSettingsRegistrySpecializations(specializations);
-19
View File
@@ -228,7 +228,6 @@ namespace O3DELauncher
}
}
void CompileCriticalAssets();
void CreateRemoteFileIO();
bool ConnectToAssetProcessor()
@@ -256,29 +255,11 @@ namespace O3DELauncher
{
AZ_TracePrintf("Launcher", "Connected to Asset Processor\n");
CreateRemoteFileIO();
CompileCriticalAssets();
}
return connectedToAssetProcessor;
}
//! Compiles the critical assets that are within the Engine directory of Open 3D Engine
//! This code should be in a centralized location, but doesn't belong in AzFramework
//! since it is specific to how Open 3D Engine projects has assets setup
void CompileCriticalAssets()
{
// VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others,
// so that by the time we ask for them there is a greater likelihood that they're already good to go.
// these can be loaded later but are still important:
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches");
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects");
// some are specifically extra important and will cause issues if missing completely:
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf");
}
//! Remote FileIO to use as a Virtual File System
//! Communication of FileIOBase operations occur through an AssetProcessor connection
void CreateRemoteFileIO()
@@ -346,9 +346,7 @@ namespace AssetBundler
}
// Determine the enabled platforms
const char* appRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot);
m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), appRoot, AZ::Utils::GetProjectPath().c_str());
m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), AZStd::string_view(AZ::Utils::GetProjectPath()));
// Determine which Gems are enabled for the current project
if (!AzFramework::GetGemsInfo(m_gemInfoList, *m_settingsRegistry))
@@ -1401,7 +1401,6 @@ namespace AssetBundler
// If no platform was specified, defaulting to platforms specified in the asset processor config files
AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(
AZStd::string_view{ AZ::Utils::GetEnginePath() },
AZStd::string_view{ AZ::Utils::GetEnginePath() },
AZStd::string_view{ AZ::Utils::GetProjectPath() });
[[maybe_unused]] auto platformsString = AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platformFlags);
@@ -377,7 +377,6 @@ namespace AssetBundler
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view engineRoot,
AZStd::string_view assetRoot,
AZStd::string_view projectPath)
{
auto settingsRegistry = AZ::SettingsRegistry::Get();
@@ -387,7 +386,7 @@ namespace AssetBundler
return AzFramework::PlatformFlags::Platform_NONE;
}
auto configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(engineRoot, assetRoot, projectPath, true, true, settingsRegistry);
auto configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(engineRoot, projectPath, true, true, settingsRegistry);
auto enabledPlatformList = AzToolsFramework::AssetUtils::GetEnabledPlatforms(*settingsRegistry, configFiles);
AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_NONE;
for (const auto& enabledPlatform : enabledPlatformList)
@@ -221,7 +221,6 @@ namespace AssetBundler
//! Please note that the game project could be in a different location to the engine therefore we need the assetRoot param.
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view enginePath,
AZStd::string_view assetRoot,
AZStd::string_view projectPath);
QJsonObject ReadJson(const AZStd::string& filePath);
+8 -8
View File
@@ -67,7 +67,7 @@ namespace AssetBundler
void NormalizePathKeepCase(AZStd::string& /*path*/) override {}
void CalculateBranchTokenForEngineRoot(AZStd::string& /*token*/) const override {}
const char* GetEngineRoot() const override
const char* GetTempDir() const
{
return m_tempDir->GetDirectory();
}
@@ -83,7 +83,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, DISABLED_TestFilePath_StartsWithAFileSeparator_Valid)
{
AZ::IO::Path relFilePath = "Foo/foo.xml";
AZ::IO::Path absoluteFilePath = AZ::IO::PathView(GetEngineRoot()).RootPath();
AZ::IO::Path absoluteFilePath = AZ::IO::PathView(GetTempDir()).RootPath();
absoluteFilePath /= relFilePath;
absoluteFilePath = absoluteFilePath.LexicallyNormal();
@@ -95,7 +95,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, TestFilePath_RelativePath_Valid)
{
AZ::IO::Path relFilePath = "Foo\\foo.xml";
AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
FilePath filePath(relFilePath.Native());
EXPECT_EQ(AZ::IO::PathView{ filePath.AbsolutePath() }, absoluteFilePath);
}
@@ -107,8 +107,8 @@ namespace AssetBundler
AZ::IO::Path relFilePath = "Foo\\Foo.xml";
AZ::IO::Path wrongCaseRelFilePath = "Foo\\foo.xml";
AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
AZ::IO::FileIOBase::GetInstance()->Open(correctAbsoluteFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath, fileHandle);
@@ -121,7 +121,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, TestFilePath_NoFileExists_NoError_valid)
{
AZ::IO::Path relFilePath = "Foo\\Foo.xml";
AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
FilePath filePath(absoluteFilePath.Native(), true, false);
EXPECT_TRUE(filePath.IsValid());
@@ -132,8 +132,8 @@ namespace AssetBundler
{
AZStd::string relFilePath = "Foo\\Foo.xml";
AZStd::string wrongCaseRelFilePath = "Foo\\foo.xml";
AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
AZ::IO::FileIOBase::GetInstance()->Open(correctAbsoluteFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath, fileHandle);
@@ -16,6 +16,7 @@
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/Utils/Utils.h>
#include <source/utils/utils.h>
#include <source/utils/applicationManager.h>
@@ -84,10 +85,9 @@ namespace AssetBundler
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
ASSERT_TRUE(engineRoot) << "Unable to locate engine root.\n";
AzFramework::StringFunc::Path::Join(engineRoot, RelativeTestFolder, m_data->m_testEngineRoot);
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
ASSERT_TRUE(!engineRoot.empty()) << "Unable to locate engine root.\n";
m_data->m_testEngineRoot = (engineRoot / RelativeTestFolder).String();
m_data->m_localFileIO = aznew AZ::IO::LocalFileIO();
m_data->m_priorFileIO = AZ::IO::FileIOBase::GetInstance();
@@ -150,7 +150,8 @@ namespace AssetBundler
EXPECT_EQ(0, gemsNameMap.size());
AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot.c_str(), m_data->m_testEngineRoot.c_str(), DummyProjectName);
const auto testProjectPath = AZ::IO::Path(m_data->m_testEngineRoot) / DummyProjectName;
AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot, testProjectPath.Native());
AzFramework::PlatformFlags hostPlatformFlag = AzFramework::PlatformHelper::GetPlatformFlag(AzToolsFramework::AssetSystem::GetHostAssetPlatform());
AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ANDROID | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag;
ASSERT_EQ(platformFlags, expectedFlags);
@@ -699,7 +699,6 @@ namespace AssetBuilderSDK
// XML files may contain generic data (avoid this in new builders - use a custom extension!)
static const char* xmlExtensions = ".xml";
static const char* geomCacheExtensions = ".cax";
static const char* skeletonExtensions = ".chr";
static AZ::Data::AssetType unknownAssetType = AZ::Data::AssetType::CreateNull();
@@ -710,7 +709,6 @@ namespace AssetBuilderSDK
static AZ::Data::AssetType textureMipsAssetType("{3918728C-D3CA-4D9E-813E-A5ED20C6821E}");
static AZ::Data::AssetType skinnedMeshLodsAssetType("{58E5824F-C27B-46FD-AD48-865BA41B7A51}");
static AZ::Data::AssetType staticMeshLodsAssetType("{9AAE4926-CB6A-4C60-9948-A1A22F51DB23}");
static AZ::Data::AssetType geomCacheAssetType("{EBC96071-E960-41B6-B3E3-328F515AE5DA}");
static AZ::Data::AssetType skeletonAssetType("{60161B46-21F0-4396-A4F0-F2CCF0664CDE}");
static AZ::Data::AssetType entityIconAssetType("{3436C30E-E2C5-4C3B-A7B9-66C94A28701B}");
@@ -822,11 +820,6 @@ namespace AssetBuilderSDK
return skinnedMeshAssetType;
}
if (AzFramework::StringFunc::Find(geomCacheExtensions, extension.c_str()) != AZStd::string::npos)
{
return geomCacheAssetType;
}
if (AzFramework::StringFunc::Find(skeletonExtensions, extension.c_str()) != AZStd::string::npos)
{
return skeletonAssetType;
@@ -52,11 +52,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BadPlatform)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_badplatform");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -67,11 +68,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoPlatform)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noplatform");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -81,11 +83,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoScanFolders)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noscans");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -95,11 +98,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BrokenRecognizers)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_recognizers");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -109,11 +113,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
// verify the data.
@@ -322,12 +327,13 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
AssetUtilities::ComputeProjectName(EmptyDummyProjectName, true);
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_EQ(config.GetScanFolderCount(), 3); // the two, and then the one that has the same data as prior but different identifier.
@@ -356,11 +362,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular_platform_scanfolder");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_EQ(config.GetScanFolderCount(), 5);
@@ -402,13 +409,14 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
config.AddScanFolder(ScanFolderInfo("blahblah", "Blah ScanFolder", "sf2", true, true), true);
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_TRUE(config.IsFileExcluded("blahblah/$tmp_01.test"));
@@ -429,11 +437,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
#endif
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -520,12 +529,13 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides)
using namespace AzToolsFramework::AssetSystem;
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / DummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), DummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -627,11 +637,12 @@ TEST_F(PlatformConfigurationUnitTests, ReadCheckServer_FromConfig_Valid)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -676,11 +687,12 @@ TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes_AssetImporterExtension
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_metadata");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_TRUE(config.MetaDataFileTypesCount() == 2);
@@ -749,7 +749,7 @@ namespace AssetProcessor
}
AZStd::vector<AZ::IO::Path> configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(absoluteSystemRoot.toUtf8().constData(),
absoluteAssetRoot.toUtf8().constData(), projectPath.toUtf8().constData(),
projectPath.toUtf8().constData(),
addPlatformConfigs, addGemsConfigs && !noGemScanFolders, settingsRegistry);
// First Merge all Engine, Gem and Project specific AssetProcessor*Config.setreg/.inifiles
@@ -41,9 +41,11 @@ namespace O3DE::ProjectManager
void DownloadController::AddGemDownload(const QString& gemName)
{
m_gemNames.push_back(gemName);
emit GemDownloadAdded(gemName);
if (m_gemNames.size() == 1)
{
m_worker->SetGemToDownload(m_gemNames[0], false);
m_worker->SetGemToDownload(m_gemNames.front(), false);
m_workerThread.start();
}
}
@@ -62,6 +64,7 @@ namespace O3DE::ProjectManager
else
{
m_gemNames.erase(findResult);
emit GemDownloadRemoved(gemName);
}
}
}
@@ -69,7 +72,7 @@ namespace O3DE::ProjectManager
void DownloadController::UpdateUIProgress(int progress)
{
m_lastProgress = progress;
emit GemDownloadProgress(progress);
emit GemDownloadProgress(m_gemNames.front(), progress);
}
void DownloadController::HandleResults(const QString& result)
@@ -59,7 +59,9 @@ namespace O3DE::ProjectManager
signals:
void StartGemDownload(const QString& gemName);
void Done(const QString& gemName, bool success = true);
void GemDownloadProgress(int percentage);
void GemDownloadAdded(const QString& gemName);
void GemDownloadRemoved(const QString& gemName);
void GemDownloadProgress(const QString& gemName, int percentage);
private:
DownloadWorker* m_worker;
@@ -30,6 +30,7 @@ namespace O3DE::ProjectManager
m_layout->setMargin(5);
m_layout->setAlignment(Qt::AlignTop);
setLayout(m_layout);
setMinimumHeight(400);
QHBoxLayout* hLayout = new QHBoxLayout();
@@ -119,6 +120,12 @@ namespace O3DE::ProjectManager
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
}
CartOverlayWidget::~CartOverlayWidget()
{
// disconnect from all download controller signals
disconnect(m_downloadController, nullptr, this, nullptr);
}
void CartOverlayWidget::CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices)
{
QWidget* widget = new QWidget();
@@ -162,13 +169,13 @@ namespace O3DE::ProjectManager
void CartOverlayWidget::CreateDownloadSection()
{
QWidget* widget = new QWidget();
widget->setFixedWidth(s_width);
m_layout->addWidget(widget);
m_downloadSectionWidget = new QWidget();
m_downloadSectionWidget->setFixedWidth(s_width);
m_layout->addWidget(m_downloadSectionWidget);
QVBoxLayout* layout = new QVBoxLayout();
layout->setAlignment(Qt::AlignTop);
widget->setLayout(layout);
m_downloadSectionWidget->setLayout(layout);
QLabel* titleLabel = new QLabel();
titleLabel->setObjectName("GemCatalogCartOverlaySectionLabel");
@@ -187,88 +194,121 @@ namespace O3DE::ProjectManager
QLabel* processingQueueLabel = new QLabel("Processing Queue");
gemDownloadLayout->addWidget(processingQueueLabel);
QWidget* downloadingItemWidget = new QWidget();
downloadingItemWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG");
gemDownloadLayout->addWidget(downloadingItemWidget);
m_downloadingListWidget = new QWidget();
m_downloadingListWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG");
gemDownloadLayout->addWidget(m_downloadingListWidget);
QVBoxLayout* downloadingItemLayout = new QVBoxLayout();
downloadingItemLayout->setAlignment(Qt::AlignTop);
downloadingItemWidget->setLayout(downloadingItemLayout);
m_downloadingListWidget->setLayout(downloadingItemLayout);
auto update = [=](int downloadProgress)
QLabel* downloadsInProgessLabel = new QLabel("");
downloadsInProgessLabel->setObjectName("NumDownloadsInProgressLabel");
downloadingItemLayout->addWidget(downloadsInProgessLabel);
if (m_downloadController->IsDownloadQueueEmpty())
{
if (m_downloadController->IsDownloadQueueEmpty())
{
widget->hide();
}
else
{
widget->setUpdatesEnabled(false);
// remove items
QLayoutItem* layoutItem = nullptr;
while ((layoutItem = downloadingItemLayout->takeAt(0)) != nullptr)
{
if (layoutItem->layout())
{
// Gem info row
QLayoutItem* rowLayoutItem = nullptr;
while ((rowLayoutItem = layoutItem->layout()->takeAt(0)) != nullptr)
{
rowLayoutItem->widget()->deleteLater();
}
layoutItem->layout()->deleteLater();
}
if (layoutItem->widget())
{
layoutItem->widget()->deleteLater();
}
}
// Setup gem download rows
const AZStd::vector<QString>& downloadQueue = m_downloadController->GetDownloadQueue();
QLabel* downloadsInProgessLabel = new QLabel("");
downloadsInProgessLabel->setText(
QString("%1 %2").arg(downloadQueue.size()).arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress...")));
downloadingItemLayout->addWidget(downloadsInProgessLabel);
for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber)
{
QHBoxLayout* nameProgressLayout = new QHBoxLayout();
const QString& gemName = downloadQueue[downloadingGemNumber];
TagWidget* newTag = new TagWidget({gemName, gemName});
nameProgressLayout->addWidget(newTag);
QLabel* progress = new QLabel(downloadingGemNumber == 0? QString("%1%").arg(downloadProgress) : tr("Queued"));
nameProgressLayout->addWidget(progress);
QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
nameProgressLayout->addSpacerItem(spacer);
QLabel* cancelText = new QLabel(QString("<a href=\"%1\">Cancel</a>").arg(gemName));
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText);
downloadingItemLayout->addLayout(nameProgressLayout);
QProgressBar* downloadProgessBar = new QProgressBar();
downloadingItemLayout->addWidget(downloadProgessBar);
downloadProgessBar->setValue(downloadingGemNumber == 0 ? downloadProgress : 0);
}
widget->setUpdatesEnabled(true);
widget->show();
}
};
auto downloadEnded = [=](const QString& /*gemName*/, bool /*success*/)
m_downloadSectionWidget->hide();
}
else
{
update(0); // update the list to remove the gem that has finished
};
// Setup gem download rows for gems that are already in the queue
const AZStd::vector<QString>& downloadQueue = m_downloadController->GetDownloadQueue();
for (const QString& gemName : downloadQueue)
{
GemDownloadAdded(gemName);
}
}
// connect to download controller data changed
connect(m_downloadController, &DownloadController::GemDownloadProgress, this, update);
connect(m_downloadController, &DownloadController::Done, this, downloadEnded);
update(0);
connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &CartOverlayWidget::GemDownloadAdded);
connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &CartOverlayWidget::GemDownloadRemoved);
connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &CartOverlayWidget::GemDownloadProgress);
connect(m_downloadController, &DownloadController::Done, this, &CartOverlayWidget::GemDownloadComplete);
}
void CartOverlayWidget::GemDownloadAdded(const QString& gemName)
{
// Containing widget for the current download item
QWidget* newGemDownloadWidget = new QWidget();
newGemDownloadWidget->setObjectName(gemName);
QVBoxLayout* downloadingGemLayout = new QVBoxLayout(newGemDownloadWidget);
newGemDownloadWidget->setLayout(downloadingGemLayout);
// Gem name, progress string, cancel
QHBoxLayout* nameProgressLayout = new QHBoxLayout(newGemDownloadWidget);
TagWidget* newTag = new TagWidget({gemName, gemName}, newGemDownloadWidget);
nameProgressLayout->addWidget(newTag);
QLabel* progress = new QLabel(tr("Queued"), newGemDownloadWidget);
progress->setObjectName("DownloadProgressLabel");
nameProgressLayout->addWidget(progress);
nameProgressLayout->addStretch();
QLabel* cancelText = new QLabel(tr("<a href=\"%1\">Cancel</a>").arg(gemName), newGemDownloadWidget);
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText);
downloadingGemLayout->addLayout(nameProgressLayout);
// Progress bar
QProgressBar* downloadProgessBar = new QProgressBar(newGemDownloadWidget);
downloadProgessBar->setObjectName("DownloadProgressBar");
downloadingGemLayout->addWidget(downloadProgessBar);
downloadProgessBar->setValue(0);
m_downloadingListWidget->layout()->addWidget(newGemDownloadWidget);
const AZStd::vector<QString>& downloadQueue = m_downloadController->GetDownloadQueue();
QLabel* numDownloads = m_downloadingListWidget->findChild<QLabel*>("NumDownloadsInProgressLabel");
numDownloads->setText(QString("%1 %2")
.arg(downloadQueue.size())
.arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress...")));
m_downloadingListWidget->show();
}
void CartOverlayWidget::GemDownloadRemoved(const QString& gemName)
{
QWidget* gemToRemove = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToRemove)
{
gemToRemove->deleteLater();
}
if (m_downloadController->IsDownloadQueueEmpty())
{
m_downloadSectionWidget->hide();
}
else
{
size_t downloadQueueSize = m_downloadController->GetDownloadQueue().size();
QLabel* numDownloads = m_downloadingListWidget->findChild<QLabel*>("NumDownloadsInProgressLabel");
numDownloads->setText(QString("%1 %2")
.arg(downloadQueueSize)
.arg(downloadQueueSize == 1 ? tr("download in progress...") : tr("downloads in progress...")));
}
}
void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int percentage)
{
QWidget* gemToUpdate = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToUpdate)
{
QLabel* progressLabel = gemToUpdate->findChild<QLabel*>("DownloadProgressLabel");
if (progressLabel)
{
progressLabel->setText(QString("%1%").arg(percentage));
}
QProgressBar* progressBar = gemToUpdate->findChild<QProgressBar*>("DownloadProgressBar");
if (progressBar)
{
progressBar->setValue(percentage);
}
}
}
void CartOverlayWidget::GemDownloadComplete(const QString& gemName, bool /*success*/)
{
GemDownloadRemoved(gemName); // update the list to remove the gem that has finished
}
QVector<Tag> CartOverlayWidget::GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const
@@ -34,6 +34,13 @@ namespace O3DE::ProjectManager
public:
CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
~CartOverlayWidget();
public slots:
void GemDownloadAdded(const QString& gemName);
void GemDownloadRemoved(const QString& gemName);
void GemDownloadProgress(const QString& gemName, int percentage);
void GemDownloadComplete(const QString& gemName, bool success);
private:
QVector<Tag> GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const;
@@ -47,6 +54,9 @@ namespace O3DE::ProjectManager
GemModel* m_gemModel = nullptr;
DownloadController* m_downloadController = nullptr;
QWidget* m_downloadSectionWidget = nullptr;
QWidget* m_downloadingListWidget = nullptr;
inline constexpr static int s_width = 240;
};
@@ -90,6 +90,13 @@ namespace O3DE::ProjectManager
m_projectPath = projectPath;
m_gemModel->Clear();
m_gemsToRegisterWithProject.clear();
if (m_filterWidget)
{
// disconnect so we don't update the status filter for every gem we add
disconnect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
}
FillModel(projectPath);
m_proxyModel->ResetFilters();
@@ -251,6 +258,7 @@ namespace O3DE::ProjectManager
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
{
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
GemModel::SetDownloadStatus(*m_proxyModel, m_proxyModel->mapFromSource(modelIndex), GemInfo::DownloadStatus::Downloading);
}
}
@@ -221,7 +221,6 @@ namespace O3DE::ProjectManager
ResetGemStatusFilter();
ResetGemOriginFilter();
ResetTypeFilter();
ResetPlatformFilter();
ResetFeatureFilter();
}
@@ -1179,6 +1179,7 @@ namespace O3DE::ProjectManager
QString_To_Py_String(gemName), // gem name
pybind11::none(), // destination path
false, // skip auto register
false, // force
pybind11::cpp_function(
[this, gemProgressCallback](int progress)
{
@@ -39,7 +39,6 @@ namespace PythonBindingsExample
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect();
// prepare the Python binding gem(s)
CalculateExecutablePath();
Start(Descriptor());
AZ::SerializeContext* context;
@@ -368,7 +368,6 @@ namespace AZ::SceneAPI::Containers
MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ());
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
MOCK_CONST_METHOD0(GetAppRoot, const char*());
MOCK_CONST_METHOD0(GetEngineRoot, const char*());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
@@ -202,8 +202,6 @@ namespace AZ
bool skipSystem = commandLine->HasSwitch("skipsystem");
bool isDryRun = commandLine->HasSwitch("dryrun");
const char* appRoot = const_cast<const Application&>(application).GetAppRoot();
PathDocumentContainer documents;
bool result = true;
const AZStd::string& filePath = application.GetConfigFilePath();
@@ -230,7 +228,7 @@ namespace AZ
}
auto callback =
[&result, skipGems, skipSystem, &configurationName, sourceGameFolder, &appRoot, &documents, &convertSettings, &verifySettings]
[&result, skipGems, skipSystem, &configurationName, sourceGameFolder, &documents, &convertSettings, &verifySettings]
(void* classPtr, const Uuid& classId, SerializeContext* context)
{
if (classId == azrtti_typeid<AZ::ComponentApplication::Descriptor>())
@@ -238,7 +236,7 @@ namespace AZ
if (!skipSystem)
{
result = ConvertSystemSettings(documents, *reinterpret_cast<AZ::ComponentApplication::Descriptor*>(classPtr),
configurationName, sourceGameFolder, appRoot) && result;
configurationName, sourceGameFolder) && result;
}
// Cleanup the Serialized Element to allow any classes within the element's hierarchy to delete
@@ -443,7 +441,7 @@ namespace AZ
}
bool Converter::ConvertSystemSettings(PathDocumentContainer& documents, const ComponentApplication::Descriptor& descriptor,
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder, [[maybe_unused]] const AZStd::string& applicationRoot)
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder)
{
AZ::IO::FixedMaxPath memoryFilePath{ projectFolder };
memoryFilePath /= "Registry";
+1 -1
View File
@@ -43,7 +43,7 @@ namespace AZ
using PathDocumentContainer = AZStd::vector<PathDocumentPair>;
static bool ConvertSystemSettings(PathDocumentContainer& documents, const ComponentApplication::Descriptor& descriptor,
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder, const AZStd::string& applicationRoot);
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder);
static bool ConvertSystemComponents(PathDocumentContainer& documents, const Entity& entity,
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder,
const JsonSerializerSettings& convertSettings, const JsonDeserializerSettings& verifySettings);