Merge branch 'stabilization/2110' into Prism/DeleteUpdateGemsUI

This commit is contained in:
nggieber
2021-11-09 11:36:32 -08:00
127 changed files with 1364 additions and 700 deletions
+3 -4
View File
@@ -3974,9 +3974,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 +3994,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());
}
-2
View File
@@ -114,9 +114,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
+2 -138
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>
@@ -62,84 +62,6 @@ 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;
@@ -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
@@ -27,7 +27,6 @@ namespace AzQtComponents
setProperty("HasNoWindowDecorations", true);
setAttribute(Qt::WA_ShowWithoutActivating);
setAttribute(Qt::WA_DeleteOnClose);
m_borderRadius = toastConfiguration.m_borderRadius;
if (m_borderRadius > 0)
@@ -31,7 +31,6 @@ namespace AzQtComponents
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(ToastNotification, AZ::SystemAllocator, 0);
ToastNotification(QWidget* parent, const ToastConfiguration& toastConfiguration);
virtual ~ToastNotification();
@@ -73,7 +72,7 @@ namespace AzQtComponents
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZStd::chrono::milliseconds m_fadeDuration;
AZStd::unique_ptr<Ui::ToastNotification> m_ui;
QScopedPointer<Ui::ToastNotification> m_ui;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
} // namespace AzQtComponents
@@ -27,7 +27,6 @@ namespace AzQtComponents
class AZ_QT_COMPONENTS_API ToastConfiguration
{
public:
AZ_CLASS_ALLOCATOR(ToastConfiguration, AZ::SystemAllocator, 0);
ToastConfiguration(ToastType toastType, const QString& title, const QString& description);
bool m_closeOnClick = true;
@@ -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.
@@ -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
@@ -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();
}
@@ -129,7 +129,7 @@ namespace AzToolsFramework
ToastId ToastNotificationsView::CreateToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration)
{
AzQtComponents::ToastNotification* notification = aznew AzQtComponents::ToastNotification(parentWidget(), toastConfiguration);
AzQtComponents::ToastNotification* notification = new AzQtComponents::ToastNotification(this, toastConfiguration);
ToastId toastId = AZ::Entity::MakeId();
m_notifications[toastId] = notification;
@@ -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);
@@ -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);
@@ -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,11 +409,12 @@ 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;
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"));
@@ -427,11 +435,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();
@@ -518,12 +527,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();
@@ -625,11 +635,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();
@@ -674,11 +685,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
@@ -13,6 +13,7 @@
#include <ScreenHeaderWidget.h>
#include <GemCatalog/GemModel.h>
#include <GemCatalog/GemCatalogScreen.h>
#include <GemRepo/GemRepoScreen.h>
#include <ProjectUtils.h>
#include <QDialogButtonBox>
@@ -47,9 +48,14 @@ namespace O3DE::ProjectManager
m_gemCatalogScreen = new GemCatalogScreen(this);
m_stack->addWidget(m_gemCatalogScreen);
m_gemRepoScreen = new GemRepoScreen(this);
m_stack->addWidget(m_gemRepoScreen);
vLayout->addWidget(m_stack);
connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest);
connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, m_gemCatalogScreen, &GemCatalogScreen::Refresh);
// When there are multiple project templates present, we re-gather the gems when changing the selected the project template.
connect(m_newProjectSettingsScreen, &NewProjectSettingsScreen::OnTemplateSelectionChanged, this, [=](int oldIndex, [[maybe_unused]] int newIndex)
@@ -89,6 +95,9 @@ namespace O3DE::ProjectManager
buttons->setObjectName("footer");
vLayout->addWidget(buttons);
m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole);
connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
connect(m_newProjectSettingsScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest);
@@ -100,8 +109,6 @@ namespace O3DE::ProjectManager
Update();
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole);
connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton);
setLayout(vLayout);
}
@@ -122,6 +129,9 @@ namespace O3DE::ProjectManager
// Gather the enabled gems from the default project template when starting the create new project workflow.
ReinitGemCatalogForSelectedTemplate();
// make sure the gem repo has the latest details
m_gemRepoScreen->Reinit();
}
void CreateProjectCtrl::HandleBackButton()
@@ -160,12 +170,21 @@ namespace O3DE::ProjectManager
{
m_header->setSubTitle(tr("Configure project with Gems"));
m_secondaryButton->setVisible(false);
m_primaryButton->setVisible(true);
}
else if (m_stack->currentWidget() == m_gemRepoScreen)
{
m_header->setSubTitle(tr("Gem Repositories"));
m_secondaryButton->setVisible(true);
m_secondaryButton->setText(tr("Back"));
m_primaryButton->setVisible(false);
}
else
{
m_header->setSubTitle(tr("Enter Project Details"));
m_secondaryButton->setVisible(true);
m_secondaryButton->setText(tr("Configure Gems"));
m_primaryButton->setVisible(true);
}
}
@@ -175,6 +194,10 @@ namespace O3DE::ProjectManager
{
HandleSecondaryButton();
}
else if (screen == ProjectManagerScreen::GemRepos)
{
NextScreen();
}
else
{
emit ChangeScreenRequest(screen);
@@ -230,6 +253,12 @@ namespace O3DE::ProjectManager
{
if (m_newProjectSettingsScreen->Validate())
{
if (!m_gemCatalogScreen->GetDownloadController()->IsDownloadQueueEmpty())
{
QMessageBox::critical(this, tr("Gems downloading"), tr("You must wait for gems to finish downloading before continuing."));
return;
}
ProjectInfo projectInfo = m_newProjectSettingsScreen->GetProjectInfo();
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
@@ -23,6 +23,7 @@ namespace O3DE::ProjectManager
QT_FORWARD_DECLARE_CLASS(ScreenHeader)
QT_FORWARD_DECLARE_CLASS(NewProjectSettingsScreen)
QT_FORWARD_DECLARE_CLASS(GemCatalogScreen)
QT_FORWARD_DECLARE_CLASS(GemRepoScreen)
class CreateProjectCtrl
: public ScreenWidget
@@ -64,6 +65,7 @@ namespace O3DE::ProjectManager
NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr;
GemCatalogScreen* m_gemCatalogScreen = nullptr;
GemRepoScreen* m_gemRepoScreen = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -82,12 +82,13 @@ namespace O3DE::ProjectManager
succeeded = false;
}
QString gemName = m_gemNames.front();
m_gemNames.erase(m_gemNames.begin());
emit Done(succeeded);
emit Done(gemName, succeeded);
if (!m_gemNames.empty())
{
emit StartGemDownload(m_gemNames[0]);
emit StartGemDownload(m_gemNames.front());
}
else
{
@@ -58,7 +58,7 @@ namespace O3DE::ProjectManager
signals:
void StartGemDownload(const QString& gemName);
void Done(bool success = true);
void Done(const QString& gemName, bool success = true);
void GemDownloadProgress(int percentage);
private:
@@ -39,6 +39,10 @@ namespace O3DE::ProjectManager
m_tabWidget->addTab(m_engineSettingsScreen, tr("General"));
m_tabWidget->addTab(m_gemRepoScreen, tr("Gem Repositories"));
// when tab changes, notify the current screen so it can refresh
connect(m_tabWidget, &QTabWidget::currentChanged, this, &EngineScreenCtrl::TabChanged);
topBarHLayout->addWidget(m_tabWidget);
vLayout->addWidget(topBarFrameWidget);
@@ -46,6 +50,11 @@ namespace O3DE::ProjectManager
setLayout(vLayout);
}
void EngineScreenCtrl::TabChanged([[maybe_unused]] int index)
{
NotifyCurrentScreen();
}
ProjectManagerScreen EngineScreenCtrl::GetScreenEnum()
{
return ProjectManagerScreen::UpdateProject;
@@ -71,6 +80,15 @@ namespace O3DE::ProjectManager
return false;
}
void EngineScreenCtrl::NotifyCurrentScreen()
{
ScreenWidget* screen = reinterpret_cast<ScreenWidget*>(m_tabWidget->currentWidget());
if (screen)
{
screen->NotifyCurrentScreen();
}
}
void EngineScreenCtrl::GoToScreen(ProjectManagerScreen screen)
{
if (screen == m_engineSettingsScreen->GetScreenEnum())
@@ -30,6 +30,10 @@ namespace O3DE::ProjectManager
bool IsTab() override;
bool ContainsScreen(ProjectManagerScreen screen) override;
void GoToScreen(ProjectManagerScreen screen) override;
void NotifyCurrentScreen() override;
public slots:
void TabChanged(int index);
QTabWidget* m_tabWidget = nullptr;
EngineSettingsScreen* m_engineSettingsScreen = nullptr;
@@ -145,7 +145,7 @@ namespace O3DE::ProjectManager
}
else
{
tagContainer->Update(ConvertFromModelIndices(tagIndices));
tagContainer->Update(GetTagsFromModelIndices(tagIndices));
label->setText(QString("%1 %2").arg(tagIndices.size()).arg(tagIndices.size() == 1 ? singularTitle : pluralTitle));
widget->show();
}
@@ -234,17 +234,23 @@ namespace O3DE::ProjectManager
for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber)
{
QHBoxLayout* nameProgressLayout = new QHBoxLayout();
TagWidget* newTag = new TagWidget(downloadQueue[downloadingGemNumber]);
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(downloadQueue[downloadingGemNumber]));
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);
@@ -255,7 +261,7 @@ namespace O3DE::ProjectManager
}
};
auto downloadEnded = [=](bool /*success*/)
auto downloadEnded = [=](const QString& /*gemName*/, bool /*success*/)
{
update(0); // update the list to remove the gem that has finished
};
@@ -265,15 +271,15 @@ namespace O3DE::ProjectManager
update(0);
}
QStringList CartOverlayWidget::ConvertFromModelIndices(const QVector<QModelIndex>& gems) const
QVector<Tag> CartOverlayWidget::GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const
{
QStringList gemNames;
gemNames.reserve(gems.size());
QVector<Tag> tags;
tags.reserve(gems.size());
for (const QModelIndex& modelIndex : gems)
{
gemNames.push_back(GemModel::GetDisplayName(modelIndex));
tags.push_back({ GemModel::GetDisplayName(modelIndex), GemModel::GetName(modelIndex) });
}
return gemNames;
return tags;
}
CartButton::CartButton(GemModel* gemModel, DownloadController* downloadController, QWidget* parent)
@@ -36,7 +36,7 @@ namespace O3DE::ProjectManager
CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
private:
QStringList ConvertFromModelIndices(const QVector<QModelIndex>& gems) const;
QVector<Tag> GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const;
using GetTagIndicesCallback = AZStd::function<QVector<QModelIndex>()>;
void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices);
@@ -26,6 +26,7 @@
#include <QStandardPaths>
#include <QFileDialog>
#include <QMessageBox>
#include <QHash>
namespace O3DE::ProjectManager
{
@@ -35,6 +36,9 @@ namespace O3DE::ProjectManager
m_gemModel = new GemModel(this);
m_proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
// default to sort by gem name
m_proxyModel->setSortRole(GemModel::RoleName);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0);
vLayout->setSpacing(0);
@@ -48,6 +52,7 @@ namespace O3DE::ProjectManager
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo);
connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked);
connect(m_downloadController, &DownloadController::Done, this, &GemCatalogScreen::OnGemDownloadResult);
QHBoxLayout* hLayout = new QHBoxLayout();
hLayout->setMargin(0);
@@ -57,7 +62,7 @@ namespace O3DE::ProjectManager
m_gemInspector = new GemInspector(m_gemModel, this);
m_gemInspector->setFixedWidth(240);
connect(m_gemInspector, &GemInspector::TagClicked, this, &GemCatalogScreen::SelectGem);
connect(m_gemInspector, &GemInspector::TagClicked, [=](const Tag& tag) { SelectGem(tag.id); });
connect(m_gemInspector, &GemInspector::UpdateGem, this, &GemCatalogScreen::UpdateGem);
connect(m_gemInspector, &GemInspector::UninstallGem, this, &GemCatalogScreen::UninstallGem);
@@ -87,11 +92,20 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::ReinitForProject(const QString& projectPath)
{
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();
m_proxyModel->sort(/*column=*/0);
if (m_filterWidget)
{
@@ -109,8 +123,7 @@ namespace O3DE::ProjectManager
// Select the first entry after everything got correctly sized
QTimer::singleShot(200, [=]{
QModelIndex firstModelIndex = m_gemModel->index(0, 0); // m_gemListView->model()->index(0,0);
//m_gemListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect);
QModelIndex firstModelIndex = m_gemModel->index(0, 0);
m_gemModel->GetSelectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect);
});
}
@@ -150,11 +163,80 @@ namespace O3DE::ProjectManager
{
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
m_gemModel->UpdateGemDependencies();
m_proxyModel->sort(/*column=*/0);
}
}
}
}
void GemCatalogScreen::Refresh()
{
QHash<QString, GemInfo> gemInfoHash;
// create a hash with the gem name as key
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath);
if (allGemInfosResult.IsSuccess())
{
const QVector<GemInfo>& gemInfos = allGemInfosResult.GetValue();
for (const GemInfo& gemInfo : gemInfos)
{
gemInfoHash.insert(gemInfo.m_name, gemInfo);
}
}
// add all the gem repos into the hash
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos();
if (allRepoGemInfosResult.IsSuccess())
{
const QVector<GemInfo>& allRepoGemInfos = allRepoGemInfosResult.GetValue();
for (const GemInfo& gemInfo : allRepoGemInfos)
{
if (!gemInfoHash.contains(gemInfo.m_name))
{
gemInfoHash.insert(gemInfo.m_name, gemInfo);
}
}
}
// remove gems from the model that no longer exist in the hash and are not project dependencies
int i = 0;
while (i < m_gemModel->rowCount())
{
QModelIndex index = m_gemModel->index(i,0);
QString gemName = m_gemModel->GetName(index);
const bool gemFound = gemInfoHash.contains(gemName);
if (!gemFound && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index))
{
m_gemModel->removeRow(i);
}
else
{
if (!gemFound && (m_gemModel->IsAdded(index) || m_gemModel->IsAddedDependency(index)))
{
const QString error = tr("Gem %1 was removed or unregistered, but is still used by the project.").arg(gemName);
AZ_Warning("Project Manager", false, error.toUtf8().constData());
QMessageBox::warning(this, tr("Gem not found"), error.toUtf8().constData());
}
gemInfoHash.remove(gemName);
i++;
}
}
// add all gems remaining in the hash that were not removed
for(auto iter = gemInfoHash.begin(); iter != gemInfoHash.end(); ++iter)
{
m_gemModel->AddGem(iter.value());
}
m_gemModel->UpdateGemDependencies();
m_proxyModel->sort(/*column=*/0);
// temporary, until we can refresh filter counts
m_proxyModel->ResetFilters();
m_filterWidget->ResetAllFilters();
}
void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies)
{
if (m_notificationsEnabled)
@@ -262,20 +344,22 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::FillModel(const QString& projectPath)
{
AZ::Outcome<QVector<GemInfo>, AZStd::string> allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath);
m_projectPath = projectPath;
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath);
if (allGemInfosResult.IsSuccess())
{
// Add all available gems to the model.
const QVector<GemInfo> allGemInfos = allGemInfosResult.GetValue();
const QVector<GemInfo>& allGemInfos = allGemInfosResult.GetValue();
for (const GemInfo& gemInfo : allGemInfos)
{
m_gemModel->AddGem(gemInfo);
}
AZ::Outcome<QVector<GemInfo>, AZStd::string> allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos();
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allRepoGemInfosResult = PythonBindingsInterface::Get()->GetAllGemRepoGemsInfos();
if (allRepoGemInfosResult.IsSuccess())
{
const QVector<GemInfo> allRepoGemInfos = allRepoGemInfosResult.GetValue();
const QVector<GemInfo>& allRepoGemInfos = allRepoGemInfosResult.GetValue();
for (const GemInfo& gemInfo : allRepoGemInfos)
{
// do not add gems that have already been downloaded
@@ -294,10 +378,10 @@ namespace O3DE::ProjectManager
m_notificationsEnabled = false;
// Gather enabled gems for the given project.
auto enabledGemNamesResult = PythonBindingsInterface::Get()->GetEnabledGemNames(projectPath);
const auto& enabledGemNamesResult = PythonBindingsInterface::Get()->GetEnabledGemNames(projectPath);
if (enabledGemNamesResult.IsSuccess())
{
const QVector<AZStd::string> enabledGemNames = enabledGemNamesResult.GetValue();
const QVector<AZStd::string>& enabledGemNames = enabledGemNamesResult.GetValue();
for (const AZStd::string& enabledGemName : enabledGemNames)
{
const QModelIndex modelIndex = m_gemModel->FindIndexByNameString(enabledGemName.c_str());
@@ -357,12 +441,24 @@ namespace O3DE::ProjectManager
for (const QModelIndex& modelIndex : toBeAdded)
{
const QString gemPath = GemModel::GetPath(modelIndex);
const QString& gemPath = GemModel::GetPath(modelIndex);
// make sure any remote gems we added were downloaded successfully
if (GemModel::GetGemOrigin(modelIndex) == GemInfo::Remote && GemModel::GetDownloadStatus(modelIndex) != GemInfo::Downloaded)
{
QMessageBox::critical(
nullptr, "Cannot add gem that isn't downloaded",
tr("Cannot add gem %1 to project because it isn't downloaded yet or failed to download.")
.arg(GemModel::GetDisplayName(modelIndex)));
return EnableDisableGemsResult::Failed;
}
const AZ::Outcome<void, AZStd::string> result = pythonBindings->AddGemToProject(gemPath, projectPath);
if (!result.IsSuccess())
{
QMessageBox::critical(nullptr, "Operation failed",
QString("Cannot add gem %1 to project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
QMessageBox::critical(nullptr, "Failed to add gem to project",
tr("Cannot add gem %1 to project.<br><br>Error:<br>%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
return EnableDisableGemsResult::Failed;
}
@@ -380,8 +476,8 @@ namespace O3DE::ProjectManager
const AZ::Outcome<void, AZStd::string> result = pythonBindings->RemoveGemFromProject(gemPath, projectPath);
if (!result.IsSuccess())
{
QMessageBox::critical(nullptr, "Operation failed",
QString("Cannot remove gem %1 from project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
QMessageBox::critical(nullptr, "Failed to remove gem from project",
tr("Cannot remove gem %1 from project.<br><br>Error:<br>%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str()));
return EnableDisableGemsResult::Failed;
}
@@ -392,23 +488,35 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::HandleOpenGemRepo()
{
QVector<QModelIndex> gemsToBeAdded = m_gemModel->GatherGemsToBeAdded(true);
QVector<QModelIndex> gemsToBeRemoved = m_gemModel->GatherGemsToBeRemoved(true);
emit ChangeScreenRequest(ProjectManagerScreen::GemRepos);
}
if (!gemsToBeAdded.empty() || !gemsToBeRemoved.empty())
void GemCatalogScreen::OnGemDownloadResult(const QString& gemName, bool succeeded)
{
if (succeeded)
{
QMessageBox::StandardButton warningResult = QMessageBox::warning(
nullptr, "Pending Changes",
"There are some unsaved changes to the gem selection,<br> they will be lost if you change screens.<br> Are you sure?",
QMessageBox::No | QMessageBox::Yes);
if (warningResult != QMessageBox::Yes)
// refresh the information for downloaded gems
const AZ::Outcome<QVector<GemInfo>, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath);
if (allGemInfosResult.IsSuccess())
{
return;
// we should find the gem name now in all gem infos
for (const GemInfo& gemInfo : allGemInfosResult.GetValue())
{
if (gemInfo.m_name == gemName)
{
QModelIndex index = m_gemModel->FindIndexByNameString(gemName);
if (index.isValid())
{
m_gemModel->setData(index, GemInfo::Downloaded, GemModel::RoleDownloadStatus);
m_gemModel->setData(index, gemInfo.m_path, GemModel::RolePath);
m_gemModel->setData(index, gemInfo.m_path, GemModel::RoleDirectoryLink);
}
return;
}
}
}
}
emit ChangeScreenRequest(ProjectManagerScreen::GemRepos);
}
ProjectManagerScreen GemCatalogScreen::GetScreenEnum()
@@ -49,6 +49,8 @@ namespace O3DE::ProjectManager
void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies);
void OnAddGemClicked();
void SelectGem(const QString& gemName);
void OnGemDownloadResult(const QString& gemName, bool succeeded = true);
void Refresh();
void UpdateGem(const QModelIndex& modelIndex);
void UninstallGem(const QModelIndex& modelIndex);
@@ -64,7 +66,6 @@ namespace O3DE::ProjectManager
private:
void FillModel(const QString& projectPath);
QModelIndex GetCurrentlySelectedGem();
AZStd::unique_ptr<AzToolsFramework::ToastNotificationsView> m_notificationsView;
@@ -78,5 +79,6 @@ namespace O3DE::ProjectManager
DownloadController* m_downloadController = nullptr;
bool m_notificationsEnabled = true;
QSet<QString> m_gemsToRegisterWithProject;
QString m_projectPath;
};
} // namespace O3DE::ProjectManager
@@ -109,10 +109,10 @@ namespace O3DE::ProjectManager
}
// Depending gems
QStringList dependingGems = m_model->GetDependingGemNames(modelIndex);
if (!dependingGems.isEmpty())
const QVector<Tag>& dependingGemTags = m_model->GetDependingGemTags(modelIndex);
if (!dependingGemTags.isEmpty())
{
m_dependingGems->Update(tr("Depending Gems"), tr("The following Gems will be automatically enabled with this Gem."), dependingGems);
m_dependingGems->Update(tr("Depending Gems"), tr("The following Gems will be automatically enabled with this Gem."), dependingGemTags);
m_dependingGems->show();
}
else
@@ -123,7 +123,8 @@ namespace O3DE::ProjectManager
// Additional information
m_versionLabel->setText(tr("Gem Version: %1").arg(m_model->GetVersion(modelIndex)));
m_lastUpdatedLabel->setText(tr("Last Updated: %1").arg(m_model->GetLastUpdated(modelIndex)));
m_binarySizeLabel->setText(tr("Binary Size: %1 KB").arg(m_model->GetBinarySizeInKB(modelIndex)));
const int binarySize = m_model->GetBinarySizeInKB(modelIndex);
m_binarySizeLabel->setText(tr("Binary Size: %1").arg(binarySize ? tr("%1 KB").arg(binarySize) : tr("Unknown")));
// Update and Uninstall buttons
if (m_model->GetGemOrigin(modelIndex) == GemInfo::Remote && m_model->GetDownloadStatus(modelIndex) == GemInfo::Downloaded)
@@ -45,7 +45,7 @@ namespace O3DE::ProjectManager
inline constexpr static const char* s_textColor = "#DDDDDD";
signals:
void TagClicked(const QString& tag);
void TagClicked(const Tag& tag);
void UpdateGem(const QModelIndex& modelIndex);
void UninstallGem(const QModelIndex& modelIndex);
@@ -18,6 +18,7 @@ namespace O3DE::ProjectManager
: QStandardItemModel(parent)
{
m_selectionModel = new QItemSelectionModel(this, parent);
connect(this, &QAbstractItemModel::rowsAboutToBeRemoved, this, &GemModel::OnRowsAboutToBeRemoved);
}
QItemSelectionModel* GemModel::GetSelectionModel() const
@@ -64,7 +65,6 @@ namespace O3DE::ProjectManager
appendRow(item);
const QModelIndex modelIndex = index(rowCount()-1, 0);
m_nameToIndexMap[gemInfo.m_displayName] = modelIndex;
m_nameToIndexMap[gemInfo.m_name] = modelIndex;
}
@@ -177,18 +177,6 @@ namespace O3DE::ProjectManager
return {};
}
void GemModel::FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames)
{
for (QString& name : inOutGemNames)
{
QModelIndex modelIndex = FindIndexByNameString(name);
if (modelIndex.isValid())
{
name = GetDisplayName(modelIndex);
}
}
}
QStringList GemModel::GetDependingGems(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleDependingGems).toStringList();
@@ -208,16 +196,23 @@ namespace O3DE::ProjectManager
}
}
QStringList GemModel::GetDependingGemNames(const QModelIndex& modelIndex)
QVector<Tag> GemModel::GetDependingGemTags(const QModelIndex& modelIndex)
{
QStringList result = GetDependingGems(modelIndex);
if (result.isEmpty())
QVector<Tag> tags;
QStringList dependingGemNames = GetDependingGems(modelIndex);
tags.reserve(dependingGemNames.size());
for (QString& gemName : dependingGemNames)
{
return {};
const QModelIndex& dependingIndex = FindIndexByNameString(gemName);
if (dependingIndex.isValid())
{
tags.push_back({ GetDisplayName(dependingIndex), GetName(dependingIndex) });
}
}
FindGemDisplayNamesByNameStrings(result);
return result;
return tags;
}
QString GemModel::GetVersion(const QModelIndex& modelIndex)
@@ -372,6 +367,16 @@ namespace O3DE::ProjectManager
gemModel->emit gemStatusChanged(gemName, numChangedDependencies);
}
void GemModel::OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last)
{
for (int i = first; i <= last; ++i)
{
QModelIndex modelIndex = index(i, 0, parent);
const QString& gemName = GetName(modelIndex);
m_nameToIndexMap.remove(gemName);
}
}
void GemModel::SetIsAddedDependency(QAbstractItemModel& model, const QModelIndex& modelIndex, bool isAdded)
{
model.setData(modelIndex, isAdded, RoleIsAddedDependency);
@@ -10,6 +10,7 @@
#if !defined(Q_MOC_RUN)
#include <GemCatalog/GemInfo.h>
#include <TagWidget.h>
#include <QAbstractItemModel>
#include <QStandardItemModel>
#include <QItemSelectionModel>
@@ -26,12 +27,39 @@ namespace O3DE::ProjectManager
explicit GemModel(QObject* parent = nullptr);
QItemSelectionModel* GetSelectionModel() const;
enum UserRole
{
RoleName = Qt::UserRole,
RoleDisplayName,
RoleCreator,
RoleGemOrigin,
RolePlatforms,
RoleSummary,
RoleWasPreviouslyAdded,
RoleWasPreviouslyAddedDependency,
RoleIsAdded,
RoleIsAddedDependency,
RoleDirectoryLink,
RoleDocLink,
RoleDependingGems,
RoleVersion,
RoleLastUpdated,
RoleBinarySize,
RoleFeatures,
RoleTypes,
RolePath,
RoleRequirement,
RoleDownloadStatus,
RoleLicenseText,
RoleLicenseLink
};
void AddGem(const GemInfo& gemInfo);
void Clear();
void UpdateGemDependencies();
QModelIndex FindIndexByNameString(const QString& nameString) const;
QStringList GetDependingGemNames(const QModelIndex& modelIndex);
QVector<Tag> GetDependingGemTags(const QModelIndex& modelIndex);
bool HasDependentGems(const QModelIndex& modelIndex) const;
static QString GetName(const QModelIndex& modelIndex);
@@ -82,38 +110,13 @@ namespace O3DE::ProjectManager
signals:
void gemStatusChanged(const QString& gemName, uint32_t numChangedDependencies);
protected slots:
void OnRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last);
private:
void FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames);
void GetAllDependingGems(const QModelIndex& modelIndex, QSet<QModelIndex>& inOutGems);
QStringList GetDependingGems(const QModelIndex& modelIndex);
enum UserRole
{
RoleName = Qt::UserRole,
RoleDisplayName,
RoleCreator,
RoleGemOrigin,
RolePlatforms,
RoleSummary,
RoleWasPreviouslyAdded,
RoleWasPreviouslyAddedDependency,
RoleIsAdded,
RoleIsAddedDependency,
RoleDirectoryLink,
RoleDocLink,
RoleDependingGems,
RoleVersion,
RoleLastUpdated,
RoleBinarySize,
RoleFeatures,
RoleTypes,
RolePath,
RoleRequirement,
RoleDownloadStatus,
RoleLicenseText,
RoleLicenseLink
};
QHash<QString, QModelIndex> m_nameToIndexMap;
QItemSelectionModel* m_selectionModel = nullptr;
QHash<QString, QSet<QModelIndex>> m_gemDependencyMap;
@@ -86,7 +86,7 @@ namespace O3DE::ProjectManager
}
// Included Gems
m_includedGems->Update(tr("Included Gems"), "", m_model->GetIncludedGemNames(modelIndex));
m_includedGems->Update(tr("Included Gems"), "", m_model->GetIncludedGemTags(modelIndex));
m_mainWidget->adjustSize();
m_mainWidget->show();
@@ -103,17 +103,17 @@ namespace O3DE::ProjectManager
return modelIndex.data(RoleIncludedGems).toStringList();
}
QStringList GemRepoModel::GetIncludedGemNames(const QModelIndex& modelIndex)
QVector<Tag> GemRepoModel::GetIncludedGemTags(const QModelIndex& modelIndex)
{
QStringList gemNames;
QVector<GemInfo> gemInfos = GetIncludedGemInfos(modelIndex);
QVector<Tag> tags;
const QVector<GemInfo>& gemInfos = GetIncludedGemInfos(modelIndex);
tags.reserve(gemInfos.size());
for (const GemInfo& gemInfo : gemInfos)
{
gemNames.append(gemInfo.m_displayName);
tags.append({ gemInfo.m_displayName, gemInfo.m_name });
}
return gemNames;
return tags;
}
QVector<GemInfo> GemRepoModel::GetIncludedGemInfos(const QModelIndex& modelIndex)
@@ -40,7 +40,7 @@ namespace O3DE::ProjectManager
static QString GetPath(const QModelIndex& modelIndex);
static QStringList GetIncludedGemPaths(const QModelIndex& modelIndex);
static QStringList GetIncludedGemNames(const QModelIndex& modelIndex);
static QVector<Tag> GetIncludedGemTags(const QModelIndex& modelIndex);
static QVector<GemInfo> GetIncludedGemInfos(const QModelIndex& modelIndex);
static bool IsEnabled(const QModelIndex& modelIndex);
@@ -52,6 +52,11 @@ namespace O3DE::ProjectManager
Reinit();
}
void GemRepoScreen::NotifyCurrentScreen()
{
Reinit();
}
void GemRepoScreen::Reinit()
{
m_gemRepoModel->clear();
@@ -91,6 +96,7 @@ namespace O3DE::ProjectManager
if (addGemRepoResult)
{
Reinit();
emit OnRefresh();
}
else
{
@@ -116,6 +122,7 @@ namespace O3DE::ProjectManager
if (removeGemRepoResult)
{
Reinit();
emit OnRefresh();
}
else
{
@@ -130,6 +137,7 @@ namespace O3DE::ProjectManager
{
bool refreshResult = PythonBindingsInterface::Get()->RefreshAllGemRepos();
Reinit();
emit OnRefresh();
if (!refreshResult)
{
@@ -146,6 +154,7 @@ namespace O3DE::ProjectManager
if (refreshResult.IsSuccess())
{
Reinit();
emit OnRefresh();
}
else
{
@@ -28,6 +28,7 @@ namespace O3DE::ProjectManager
class GemRepoScreen
: public ScreenWidget
{
Q_OBJECT
public:
explicit GemRepoScreen(QWidget* parent = nullptr);
~GemRepoScreen() = default;
@@ -37,12 +38,18 @@ namespace O3DE::ProjectManager
GemRepoModel* GetGemRepoModel() const { return m_gemRepoModel; }
void NotifyCurrentScreen() override;
signals:
void OnRefresh();
public slots:
void HandleAddRepoButton();
void HandleRemoveRepoButton(const QModelIndex& modelIndex);
void HandleRefreshAllButton();
void HandleRefreshRepoButton(const QModelIndex& modelIndex);
private:
void FillModel();
QFrame* CreateNoReposContent();
@@ -33,14 +33,14 @@ namespace O3DE::ProjectManager
m_layout->addWidget(m_textLabel);
m_tagWidget = new TagContainerWidget();
connect(m_tagWidget, &TagContainerWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); });
connect(m_tagWidget, &TagContainerWidget::TagClicked, this, [=](const Tag& tag){ emit TagClicked(tag); });
m_layout->addWidget(m_tagWidget);
}
void GemsSubWidget::Update(const QString& title, const QString& text, const QStringList& gemNames)
void GemsSubWidget::Update(const QString& title, const QString& text, const QVector<Tag>& tags)
{
m_titleLabel->setText(title);
m_textLabel->setText(text);
m_tagWidget->Update(gemNames);
m_tagWidget->Update(tags);
}
} // namespace O3DE::ProjectManager
@@ -26,10 +26,10 @@ namespace O3DE::ProjectManager
public:
GemsSubWidget(QWidget* parent = nullptr);
void Update(const QString& title, const QString& text, const QStringList& gemNames);
void Update(const QString& title, const QString& text, const QVector<Tag>& tags);
signals:
void TagClicked(const QString& tag);
void TagClicked(const Tag& tag);
private:
QLabel* m_titleLabel = nullptr;
@@ -53,6 +53,8 @@ namespace Platform
#define Py_To_String(obj) pybind11::str(obj).cast<std::string>().c_str()
#define Py_To_String_Optional(dict, key, default_string) dict.contains(key) ? Py_To_String(dict[key]) : default_string
#define Py_To_Int(obj) obj.cast<int>()
#define Py_To_Int_Optional(dict, key, default_int) dict.contains(key) ? Py_To_Int(dict[key]) : default_int
#define QString_To_Py_String(value) pybind11::str(value.toStdString())
#define QString_To_Py_Path(value) m_pathlib.attr("Path")(value.toStdString())
@@ -705,7 +707,9 @@ namespace O3DE::ProjectManager
// optional
gemInfo.m_displayName = Py_To_String_Optional(data, "display_name", gemInfo.m_name);
gemInfo.m_summary = Py_To_String_Optional(data, "summary", "");
gemInfo.m_version = "";
gemInfo.m_version = Py_To_String_Optional(data, "version", gemInfo.m_version);
gemInfo.m_lastUpdatedDate = Py_To_String_Optional(data, "last_updated", gemInfo.m_lastUpdatedDate);
gemInfo.m_binarySizeInKB = Py_To_Int_Optional(data, "binary_size", gemInfo.m_binarySizeInKB);
gemInfo.m_requirement = Py_To_String_Optional(data, "requirements", "");
gemInfo.m_creator = Py_To_String_Optional(data, "origin", "");
gemInfo.m_documentationLink = Py_To_String_Optional(data, "documentation_url", "");
@@ -1175,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)
{
+27 -12
View File
@@ -12,15 +12,16 @@
namespace O3DE::ProjectManager
{
TagWidget::TagWidget(const QString& text, QWidget* parent)
: QLabel(text, parent)
TagWidget::TagWidget(const Tag& tag, QWidget* parent)
: QLabel(tag.text, parent)
, m_tag(tag)
{
setObjectName("TagWidget");
}
void TagWidget::mousePressEvent([[maybe_unused]] QMouseEvent* event)
{
emit(TagClicked(text()));
emit TagClicked(m_tag);
}
TagContainerWidget::TagContainerWidget(QWidget* parent)
@@ -39,20 +40,34 @@ namespace O3DE::ProjectManager
void TagContainerWidget::Update(const QStringList& tags)
{
FlowLayout* flowLayout = static_cast<FlowLayout*>(layout());
Clear();
// remove old tags
foreach (const QString& tag, tags)
{
TagWidget* tagWidget = new TagWidget({tag, tag});
connect(tagWidget, &TagWidget::TagClicked, this, [=](const Tag& clickedTag){ emit TagClicked(clickedTag); });
layout()->addWidget(tagWidget);
}
}
void TagContainerWidget::Update(const QVector<Tag>& tags)
{
Clear();
foreach (const Tag& tag, tags)
{
TagWidget* tagWidget = new TagWidget(tag);
connect(tagWidget, &TagWidget::TagClicked, this, [=](const Tag& clickedTag){ emit TagClicked(clickedTag); });
layout()->addWidget(tagWidget);
}
}
void TagContainerWidget::Clear()
{
QLayoutItem* layoutItem = nullptr;
while ((layoutItem = layout()->takeAt(0)) != nullptr)
{
layoutItem->widget()->deleteLater();
}
foreach (const QString& tag, tags)
{
TagWidget* tagWidget = new TagWidget(tag);
connect(tagWidget, &TagWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); });
flowLayout->addWidget(tagWidget);
}
}
} // namespace O3DE::ProjectManager
+18 -4
View File
@@ -10,12 +10,19 @@
#if !defined(Q_MOC_RUN)
#include <QLabel>
#include <QStringList>
#include <QWidget>
#include <QVector>
#include <QStringList>
#endif
namespace O3DE::ProjectManager
{
struct Tag
{
QString text;
QString id;
};
// Single tag
class TagWidget
: public QLabel
@@ -23,14 +30,17 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
explicit TagWidget(const QString& text, QWidget* parent = nullptr);
explicit TagWidget(const Tag& id, QWidget* parent = nullptr);
~TagWidget() = default;
signals:
void TagClicked(const QString& tag);
void TagClicked(const Tag& tag);
protected:
void mousePressEvent(QMouseEvent* event) override;
private:
Tag m_tag;
};
// Widget containing multiple tags, automatically wrapping based on the size
@@ -43,9 +53,13 @@ namespace O3DE::ProjectManager
explicit TagContainerWidget(QWidget* parent = nullptr);
~TagContainerWidget() = default;
void Update(const QVector<Tag>& tags);
void Update(const QStringList& tags);
signals:
void TagClicked(const QString& tag);
void TagClicked(const Tag& tag);
private:
void Clear();
};
} // namespace O3DE::ProjectManager
@@ -7,6 +7,7 @@
*/
#include <GemCatalog/GemCatalogScreen.h>
#include <GemRepo/GemRepoScreen.h>
#include <ProjectManagerDefs.h>
#include <PythonBindingsInterface.h>
#include <ScreenHeaderWidget.h>
@@ -39,10 +40,10 @@ namespace O3DE::ProjectManager
m_updateSettingsScreen = new UpdateProjectSettingsScreen();
m_gemCatalogScreen = new GemCatalogScreen();
m_gemRepoScreen = new GemRepoScreen(this);
connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, [this](ProjectManagerScreen screen){
emit ChangeScreenRequest(screen);
});
connect(m_gemCatalogScreen, &ScreenWidget::ChangeScreenRequest, this, &UpdateProjectCtrl::OnChangeScreenRequest);
connect(m_gemRepoScreen, &GemRepoScreen::OnRefresh, m_gemCatalogScreen, &GemCatalogScreen::Refresh);
m_stack = new QStackedWidget(this);
m_stack->setObjectName("body");
@@ -69,6 +70,7 @@ namespace O3DE::ProjectManager
m_stack->addWidget(topBarFrameWidget);
m_stack->addWidget(m_gemCatalogScreen);
m_stack->addWidget(m_gemRepoScreen);
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
backNextButtons->setObjectName("footer");
@@ -100,6 +102,22 @@ namespace O3DE::ProjectManager
// Gather the available gems that will be shown in the gem catalog.
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path);
// make sure the gem repo has the latest repo details
m_gemRepoScreen->Reinit();
}
void UpdateProjectCtrl::OnChangeScreenRequest(ProjectManagerScreen screen)
{
if (screen == ProjectManagerScreen::GemRepos)
{
m_stack->setCurrentWidget(m_gemRepoScreen);
Update();
}
else
{
emit ChangeScreenRequest(screen);
}
}
void UpdateProjectCtrl::HandleGemsButton()
@@ -145,6 +163,7 @@ namespace O3DE::ProjectManager
QMessageBox::critical(this, tr("Gems downloading"), tr("You must wait for gems to finish downloading before continuing."));
return;
}
// Enable or disable the gems that got adjusted in the gem catalog and apply them to the given project.
const GemCatalogScreen::EnableDisableGemsResult result = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path);
if (result == GemCatalogScreen::EnableDisableGemsResult::Failed)
@@ -181,18 +200,26 @@ namespace O3DE::ProjectManager
void UpdateProjectCtrl::Update()
{
if (m_stack->currentIndex() == ScreenOrder::Gems)
if (m_stack->currentIndex() == ScreenOrder::GemRepos)
{
m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName()));
m_header->setSubTitle(QString(tr("Gem Repositories")));
m_nextButton->setVisible(false);
}
else if (m_stack->currentIndex() == ScreenOrder::Gems)
{
m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName()));
m_header->setSubTitle(QString(tr("Configure Gems")));
m_nextButton->setText(tr("Save"));
m_nextButton->setVisible(true);
}
else
{
m_header->setTitle("");
m_header->setSubTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.GetProjectDisplayName()));
m_nextButton->setText(tr("Save"));
m_nextButton->setVisible(true);
}
}
@@ -22,9 +22,11 @@ namespace O3DE::ProjectManager
QT_FORWARD_DECLARE_CLASS(ScreenHeader)
QT_FORWARD_DECLARE_CLASS(UpdateProjectSettingsScreen)
QT_FORWARD_DECLARE_CLASS(GemCatalogScreen)
QT_FORWARD_DECLARE_CLASS(GemRepoScreen)
class UpdateProjectCtrl : public ScreenWidget
{
Q_OBJECT
public:
explicit UpdateProjectCtrl(QWidget* parent = nullptr);
~UpdateProjectCtrl() = default;
@@ -37,6 +39,7 @@ namespace O3DE::ProjectManager
void HandleBackButton();
void HandleNextButton();
void HandleGemsButton();
void OnChangeScreenRequest(ProjectManagerScreen screen);
void UpdateCurrentProject(const QString& projectPath);
private:
@@ -47,13 +50,15 @@ namespace O3DE::ProjectManager
enum ScreenOrder
{
Settings,
Gems
Gems,
GemRepos
};
ScreenHeader* m_header = nullptr;
QStackedWidget* m_stack = nullptr;
UpdateProjectSettingsScreen* m_updateSettingsScreen = nullptr;
GemCatalogScreen* m_gemCatalogScreen = nullptr;
GemRepoScreen* m_gemRepoScreen = nullptr;
QPushButton* m_backButton = nullptr;
QPushButton* m_nextButton = nullptr;
@@ -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);