Merge branch 'aws-lumberyard:development' into SerializeContextToolsConvertHandleAnyValidation

This commit is contained in:
lumberyard-employee-dm
2021-06-17 20:29:08 -05:00
committed by GitHub
2639 changed files with 258816 additions and 150125 deletions
+4 -1
View File
@@ -140,7 +140,10 @@ typedef uint8 byte;
#define STDMETHODCALLTYPE
#endif
#define _ALIGN(num) __attribute__ ((aligned(num)))
#define _ALIGN(num) \
__attribute__ ((aligned(num))) \
AZ_POP_DISABLE_WARNING
#define _PACK __attribute__ ((packed))
// Safe memory freeing
+2 -4
View File
@@ -282,11 +282,9 @@ struct TIntTraits
static const size_t nPOS_BITS
= sizeof(T) * 8 - bSIGNED;
static const T nMIN
= bSIGNED ? T (T(1) << (T(sizeof(T) * 8 - 1))) : T(0);
static const T nMIN = std::numeric_limits<T>::min();
static const T nMAX
= ~nMIN;
static const T nMAX = std::numeric_limits<T>::max();
};
template<uint S>
+3 -3
View File
@@ -125,7 +125,7 @@ enum ESystemConfigPlatform
{
CONFIG_INVALID_PLATFORM = 0,
CONFIG_PC = 1,
CONFIG_OSX_GL = 2,
CONFIG_MAC = 2,
CONFIG_OSX_METAL = 3,
CONFIG_ANDROID = 4,
CONFIG_IOS = 5,
@@ -1154,13 +1154,13 @@ struct DiskOperationInfo
return *this;
}
DiskOperationInfo& operator - (const DiskOperationInfo& rv)
DiskOperationInfo operator - (const DiskOperationInfo& rv)
{
DiskOperationInfo res(*this);
return res -= rv;
}
DiskOperationInfo& operator + (const DiskOperationInfo& rv)
DiskOperationInfo operator + (const DiskOperationInfo& rv)
{
DiskOperationInfo res(*this);
return res += rv;
+4 -1
View File
@@ -104,7 +104,10 @@ typedef float FLOAT;
#define STDMETHODCALLTYPE
#endif
#define _ALIGN(num) __attribute__ ((aligned(num)))
#define _ALIGN(num) \
__attribute__ ((aligned(num))) \
AZ_POP_DISABLE_WARNING
#define _PACK __attribute__ ((packed))
// Safe memory freeing
+1 -2
View File
@@ -11,7 +11,6 @@
*/
#pragma once
#include <IRenderer.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Color.h>
@@ -84,7 +83,7 @@ public: // types
//! If this is not passed then the defaults below are used
struct TextOptions
{
IFFont* font; //!< default is "default"
AZStd::string fontName; //!< default is "default"
unsigned int effectIndex; //!< default is 0
AZ::Vector3 color; //!< default is (1,1,1)
HAlign horizontalAlignment; //!< default is HAlign::Left
@@ -137,5 +137,6 @@ enum class AnimParamType
Invalid = static_cast<int>(0xFFFFFFFF)
};
static const int OLD_APARAM_USER = 100;
#endif // CRYINCLUDE_CRYCOMMON_MAESTRO_TYPES_ANIMPARAMTYPE_H
+1 -1
View File
@@ -67,7 +67,7 @@ struct CryPakMock
MOCK_METHOD1(PoolMalloc, void*(size_t size));
MOCK_METHOD1(PoolFree, void(void* p));
MOCK_METHOD3(PoolAllocMemoryBlock, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> (size_t nSize, const char* sUsage, size_t nAlign));
MOCK_METHOD3(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, uint32_t nFlags, bool bAllOwUseFileSystem));
MOCK_METHOD2(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, AZ::IO::IArchive::EFileSearchType));
MOCK_METHOD1(FindNext, AZ::IO::ArchiveFileIterator(AZ::IO::ArchiveFileIterator handle));
MOCK_METHOD1(FindClose, bool(AZ::IO::ArchiveFileIterator));
MOCK_METHOD1(GetModificationTime, AZ::IO::IArchive::FileTime(AZ::IO::HandleType f));
+3 -1
View File
@@ -111,7 +111,9 @@ int64 CryGetTicksPerSec();
}
#endif
#define _MS_ALIGN(num) __declspec(align(num))
#define _MS_ALIGN(num) \
AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") \
__declspec(align(num))
#define DEFINE_ALIGNED_DATA(type, name, alignment) _declspec(align(alignment)) type name;
#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) static _declspec(align(alignment)) type name;
+3 -1
View File
@@ -93,7 +93,9 @@ int64 CryGetTicksPerSec();
}
#endif
#define _MS_ALIGN(num) __declspec(align(num))
#define _MS_ALIGN(num) \
AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") \
__declspec(align(num))
#define DEFINE_ALIGNED_DATA(type, name, alignment) _declspec(align(alignment)) type name;
#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) static _declspec(align(alignment)) type name;
+2 -2
View File
@@ -733,12 +733,12 @@ enum ETriState
// Fallback for Alignment macro of GCC/CLANG (must be after the class definition)
#if !defined(_ALIGN)
#define _ALIGN(num)
#define _ALIGN(num) AZ_POP_DISABLE_WARNING
#endif
// Fallback for Alignment macro of MSVC (must be before the class definition)
#if !defined(_MS_ALIGN)
#define _MS_ALIGN(num)
#define _MS_ALIGN(num) AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option")
#endif
#if defined(WIN32) || defined(WIN64)
@@ -1,14 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// If you make changes in ICryPak.h, make changes here, to dirty the PCH.
#include "CrySystem_precompiled.h"
+1 -1
View File
@@ -561,7 +561,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
if (pex)
{
MINIDUMP_TYPE mdumpValue;
MINIDUMP_TYPE mdumpValue = MiniDumpNormal;
bool bDump = true;
switch (g_cvars.sys_dump_type)
{
@@ -306,8 +306,9 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder)
AZStd::unordered_set<AZStd::string> pakList;
bool allowFileSystem = true;
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), 0, allowFileSystem);
const bool allowFileSystem = true;
const uint32_t skipPakFiles = 1;
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly);
if (handle)
{
@@ -320,7 +321,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder)
{
if (AZ::StringFunc::Equal(handle.m_filename.data(), LevelPakName))
{
// level folder contain pak files like 'level.pak'
// level folder contain pak files like 'level.pak'
// which we only want to load during level loading.
continue;
}
@@ -351,7 +352,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder)
PopulateLevels(search, folder, pPak, modFolder, false);
// Load levels outside of the bundles to maintain backward compatibility.
PopulateLevels(search, folder, pPak, modFolder, true);
}
void CLevelSystem::PopulateLevels(
@@ -360,7 +361,7 @@ void CLevelSystem::PopulateLevels(
{
// allow this find first to actually touch the file system
// (causes small overhead but with minimal amount of levels this should only be around 150ms on actual DVD Emu)
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(), 0, fromFileSystemOnly);
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly);
if (handle)
{
@@ -973,7 +974,7 @@ void CLevelSystem::UnloadLevel()
m_lastLevelName.clear();
SAFE_RELEASE(m_pCurrentLevel);
// Force Lua garbage collection (may no longer be needed now the legacy renderer has been removed).
// Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event).
EBUS_EVENT(AZ::ScriptSystemRequestBus, GarbageCollect);
@@ -36,8 +36,8 @@ namespace LegacyLevelSystem
//------------------------------------------------------------------------
static void LoadLevel(const AZ::ConsoleCommandContainer& arguments)
{
AZ_Error("SpawnableLevelSystem", arguments.empty(), "LoadLevel requires a level file name to be provided.");
AZ_Error("SpawnableLevelSystem", arguments.size() > 1, "LoadLevel requires a single level file name to be provided.");
AZ_Error("SpawnableLevelSystem", !arguments.empty(), "LoadLevel requires a level file name to be provided.");
AZ_Error("SpawnableLevelSystem", arguments.size() == 1, "LoadLevel requires a single level file name to be provided.");
if (!arguments.empty() && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
{
+51 -55
View File
@@ -26,6 +26,7 @@
#include <AzFramework/IO/FileOperations.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/Path/Path.h>
#ifdef WIN32
#include <time.h>
@@ -88,7 +89,6 @@ CLog::CLog(ISystem* pSystem)
m_nMainThreadId = CryGetCurrentThreadId();
m_logFileHandle = AZ::IO::InvalidHandle;
#if defined(KEEP_LOG_FILE_OPEN)
m_bFirstLine = true;
#endif
@@ -162,35 +162,6 @@ void CLog::RegisterConsoleVariables()
REGISTER_COMMAND("log_flush", &LogFlushFile, 0, "Flush the log file");
#endif
}
/*
//testbed
{
int iSave0 = m_pLogVerbosity->GetIVal();
int iSave1 = m_pLogFileVerbosity->GetIVal();
for(int i=0;i<=4;++i)
{
m_pLogVerbosity->Set(i);
m_pLogFileVerbosity->Set(i);
LogWithType(eAlways,"CLog selftest: Verbosity=%d FileVerbosity=%d",m_pLogVerbosity->GetIVal(),m_pLogFileVerbosity->GetIVal());
LogWithType(eAlways,"--------------");
LogWithType(eError,"eError");
LogWithType(eWarning,"eWarning");
LogWithType(eMessage,"eMessage");
LogWithType(eInput,"eInput");
LogWithType(eInputResponse,"eInputResponse");
LogWarning("LogWarning()");
LogError("LogError()");
LogWithType(eAlways,"--------------");
}
m_pLogVerbosity->Set(iSave0);
m_pLogFileVerbosity->Set(iSave1);
}
*/
#undef DEFAULT_VERBOSITY
}
@@ -210,7 +181,7 @@ CLog::~CLog()
UnregisterConsoleVariables();
CloseLogFile(true);
CloseLogFile();
}
void CLog::UnregisterConsoleVariables()
@@ -224,31 +195,36 @@ void CLog::UnregisterConsoleVariables()
}
//////////////////////////////////////////////////////////////////////////
void CLog::CloseLogFile([[maybe_unused]] bool forceClose)
void CLog::CloseLogFile()
{
if (m_logFileHandle != AZ::IO::InvalidHandle)
{
AZ::IO::FileIOBase::GetDirectInstance()->Close(m_logFileHandle);
m_logFileHandle = AZ::IO::InvalidHandle;
}
m_logFileHandle.Close();
}
//////////////////////////////////////////////////////////////////////////
AZ::IO::HandleType CLog::OpenLogFile(const char* filename, const char* mode)
bool CLog::OpenLogFile(const char* filename, int mode)
{
using namespace AZ::IO;
AZ_Assert(m_logFileHandle == AZ::IO::InvalidHandle, "Attempt to open log file when one is already open. This would lead to a handle leak.");
if ((!filename) || (filename[0] == 0))
if (m_logFileHandle.IsOpen())
{
return m_logFileHandle;
// Can only AZ_Assert if a file is open, otherwise the AZ_Assert
// would eventually lead to OpenLogFile being opened up again
AZ_Assert(false, "Attempt to open log file when one is already open. This would lead to a handle leak.");
return false;
}
if (filename == nullptr || filename[0] == '\0')
{
return false;
}
// it is assumed that @log@ points at the appropriate place (so for apple, to the user profile dir)
AZ::IO::FileIOBase::GetDirectInstance()->Open(filename, AZ::IO::GetOpenModeFromStringMode(mode), m_logFileHandle);
AZ::IO::FileIOBase* fileSystem = AZ::IO::FileIOBase::GetDirectInstance();
if (AZ::IO::FixedMaxPath logFilePath; fileSystem->ReplaceAlias(logFilePath, filename))
{
logFilePath = logFilePath.LexicallyNormal();
m_logFileHandle.Open(logFilePath.c_str(), mode);
}
if (m_logFileHandle != AZ::IO::InvalidHandle)
if (m_logFileHandle.IsOpen())
{
#if defined(KEEP_LOG_FILE_OPEN)
m_bFirstLine = true;
@@ -257,11 +233,11 @@ AZ::IO::HandleType CLog::OpenLogFile(const char* filename, const char* mode)
else
{
#if defined(LINUX) || defined(APPLE)
syslog(LOG_NOTICE, "Failed to open log file [%s], mode [%s]", filename, mode);
syslog(LOG_NOTICE, "Failed to open log file [%s], mode [%d]", filename, mode);
#endif
}
return m_logFileHandle;
return m_logFileHandle.IsOpen();
}
//////////////////////////////////////////////////////////////////////////
@@ -1114,12 +1090,15 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
if (logToFile)
{
if (m_logFileHandle == AZ::IO::InvalidHandle)
if (!m_logFileHandle.IsOpen())
{
OpenLogFile(m_szFilename, "w+t");
constexpr auto openMode = AZ::IO::SystemFile::OpenMode::SF_OPEN_APPEND
| AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE
| AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY;
OpenLogFile(m_szFilename, openMode);
}
if (m_logFileHandle != AZ::IO::InvalidHandle)
if (m_logFileHandle.IsOpen())
{
#if defined(KEEP_LOG_FILE_OPEN)
if (m_bFirstLine)
@@ -1130,9 +1109,9 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
if (bAdd)
{
// if adding to a prior line erase the \n at the end.
AZ::IO::FileIOBase::GetDirectInstance()->Seek(m_logFileHandle, -2, AZ::IO::SeekType::SeekFromEnd);
m_logFileHandle.Seek(-2, AZ::IO::SystemFile::SeekMode::SF_SEEK_END);
}
AZ::IO::FPutS(tempString.c_str(), m_logFileHandle);
m_logFileHandle.Write(tempString.c_str(), tempString.size());
#if !defined(KEEP_LOG_FILE_OPEN)
CloseLogFile();
#endif
@@ -1383,6 +1362,23 @@ bool CLog::SetFileName(const char* fileNameOrAbsolutePath, bool backupLogs)
CreateBackupFile();
AZ::IO::FileIOBase* fileSystem = AZ::IO::FileIOBase::GetDirectInstance();
AZ::IO::FixedMaxPath newLogFilePath;
if (fileSystem->ReplaceAlias(newLogFilePath, m_szFilename))
{
newLogFilePath = newLogFilePath.LexicallyNormal();
}
if (m_logFileHandle.IsOpen() && newLogFilePath != m_logFileHandle.Name())
{
constexpr auto openMode = AZ::IO::SystemFile::OpenMode::SF_OPEN_APPEND
| AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE
| AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY;
if(AZ::IO::SystemFile newLogFile; newLogFile.Open(m_szFilename, openMode))
{
m_logFileHandle = AZStd::move(newLogFile);
}
}
return true;
}
@@ -1537,9 +1533,9 @@ const char* CLog::GetModuleFilter()
void CLog::FlushAndClose()
{
#if defined(KEEP_LOG_FILE_OPEN)
if (m_logFileHandle)
if (m_logFileHandle.IsOpen())
{
CloseLogFile(true);
CloseLogFile();
}
#endif
}
+7 -11
View File
@@ -137,8 +137,8 @@ private: // -------------------------------------------------------------------
void LogStringToConsole(const char* szString, ELogType logType, bool bAdd) {}
#endif // !defined(EXCLUDE_NORMAL_LOG)
AZ::IO::HandleType OpenLogFile(const char* filename, const char* mode);
void CloseLogFile(bool force = false);
bool OpenLogFile(const char* filename, int mode);
void CloseLogFile();
// will format the message into m_szTemp
void FormatMessage(const char* szCommand, ...) PRINTF_PARAMS(2, 3);
@@ -152,15 +152,11 @@ private: // -------------------------------------------------------------------
virtual const char* GetAssetScopeString();
#endif
ISystem* m_pSystem; //
float m_fLastLoadingUpdateTime; // for non-frequent streamingEngine update
//char m_szTemp[MAX_TEMP_LENGTH_SIZE]; //
char m_szFilename[MAX_FILENAME_SIZE]; // can be with path
mutable char m_sBackupFilename[MAX_FILENAME_SIZE]; // can be with path
AZ::IO::HandleType m_logFileHandle;
CryStackStringT<char, 32> m_LogMode; //mode m_pLogFile has been opened with
AZ::IO::HandleType m_errFileHandle;
int m_nErrCount;
ISystem* m_pSystem; //
float m_fLastLoadingUpdateTime; // for non-frequent streamingEngine update
char m_szFilename[MAX_FILENAME_SIZE]; // can be with path
mutable char m_sBackupFilename[MAX_FILENAME_SIZE]; // can be with path
AZ::IO::SystemFile m_logFileHandle;
bool m_backupLogs;
+1 -1
View File
@@ -66,7 +66,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
if (pSystem && !pSystem->IsQuitting())
{
LRESULT result;
LRESULT result = 0;
bool bAny = false;
for (std::vector<IWindowMessageHandler*>::const_iterator it = pSystem->m_windowMessageHandlers.begin(); it != pSystem->m_windowMessageHandlers.end(); ++it)
{
+1 -1
View File
@@ -729,7 +729,7 @@ protected: // -------------------------------------------------------------
CCmdLine* m_pCmdLine;
string m_currentLanguageAudio;
string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg
string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_android.cfg or system_windows_pc.cfg
std::vector< std::pair<CTimeValue, float> > m_updateTimes;
+4 -9
View File
@@ -634,7 +634,7 @@ ICVar* CSystem::attachVariable (const char* szVarName, int* pContainer, const ch
IConsole* pConsole = GetIConsole();
ICVar* pOldVar = pConsole->GetCVar (szVarName);
int nDefault;
int nDefault = 0;
if (pOldVar)
{
nDefault = pOldVar->GetIVal();
@@ -864,11 +864,6 @@ bool CSystem::InitShine([[maybe_unused]] const SSystemInitParams& initParams)
EBUS_EVENT(UiSystemBus, InitializeSystem);
if (!m_env.pLyShine)
{
AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "LYShine System did not initialize correctly. Please check that the LyShine gem is enabled for this project in *_dependencies.cmake.");
return false;
}
return true;
}
@@ -1213,7 +1208,7 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
{
assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
AZ_Warning(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
R"(This typically done by setting he "assets" field in the bootstrap.cfg for within a .setreg file)""\n"
R"(This typically done by setting the "assets" field within a .setreg file)""\n"
R"(A fallback of %s will be used.)",
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
assetPlatform.c_str());
@@ -2022,8 +2017,8 @@ void CSystem::CreateSystemVars()
REGISTER_CVAR2("sys_streaming_in_blocks", &g_cvars.sys_streaming_in_blocks, 1, VF_NULL,
"Streaming of large files happens in blocks");
#if (defined(WIN32) || defined(WIN64)) && !defined(_RELEASE)
REGISTER_CVAR2("sys_float_exceptions", &g_cvars.sys_float_exceptions, 3, 0, "Use or not use floating point exceptions.");
#if (defined(WIN32) || defined(WIN64)) && defined(_DEBUG)
REGISTER_CVAR2("sys_float_exceptions", &g_cvars.sys_float_exceptions, 2, 0, "Use or not use floating point exceptions.");
#else // Float exceptions by default disabled for console builds.
REGISTER_CVAR2("sys_float_exceptions", &g_cvars.sys_float_exceptions, 0, 0, "Use or not use floating point exceptions.");
#endif
@@ -75,6 +75,5 @@ set(FILES
ViewSystem/View.h
ViewSystem/ViewSystem.cpp
ViewSystem/ViewSystem.h
CrySystem_precompiled.cpp
WindowsErrorReporting.cpp
)
@@ -76,7 +76,7 @@ namespace AZ
template <typename Type>
friend struct AZStd::IntrusivePtrCountPolicy;
template <typename Type>
template<typename Type>
friend class InstanceDatabase;
// Pointer to the InstanceDatabase that owns this instance. Will be null if the InstanceData object
@@ -46,14 +46,22 @@ namespace AZ
*/
using CreateFunction = AZStd::function<Instance<Type>(AssetData*)>;
using CreateFunctionWithParam = AZStd::function<Instance<Type>(AssetData*, const AZStd::any* param)>;
/**
* Deletion takes an asset as input and transfers ownership to the method.
*/
using DeleteFunction = AZStd::function<void(Type*)>;
/// [Required] The function to use when creating an instance.
/// The system will assert if no creation function is provided.
CreateFunction m_createFunction;
/// A function to use when creating an instance.
/// The system will assert if both @m_createFunction and @m_createFunctionWithParam
/// creation functions are invalid.
CreateFunction m_createFunction = nullptr;
/// A function with an additional custom param to use when creating an instance.
/// The system will assert if both @m_createFunction and @m_createFunctionWithParam
/// creation functions are invalid.
CreateFunctionWithParam m_createFunctionWithParam = nullptr;
/// [Optional] The function to use when deleting an instance.
DeleteFunction m_deleteFunction = [](Type* t) { delete t; };
@@ -156,28 +164,14 @@ namespace AZ
* Use this function when creating an InstanceDatabase that will handle concrete classes of @ref Type.
* \param assetType - All instances will be based on subclasses of this asset type.
* \param handler - An InstanceHandler that creates instances of @ref assetType assets.
* \param checkAssetIds - If true, it will be validated that "instance->m_assetId == asset.GetId()"
*/
static void Create(const AssetType& assetType, const InstanceHandler<Type>& handler);
/**
* Create the InstanceDatabase with no handlers. Individual handlers must be added using @ref AddHandler().
* Use this function when creating an InstanceDatabase that will handle subclasses of @ref Type.
* \param assetType - All instances will be based on subclasses of this asset type.
*/
static void Create(const AssetType& assetType);
static void Create(const AssetType& assetType, const InstanceHandler<Type>& handler, bool checkAssetIds = true);
static void Destroy();
static bool IsReady();
static InstanceDatabase& Instance();
/**
* Add an InstanceHandler that will create instances for assets of type @ref assetType.
*/
void AddHandler(const AssetType& assetType, const InstanceHandler<Type>& handler);
void AddHandler(const AssetType& assetType, typename InstanceHandler<Type>::CreateFunction createFunction);
void RemoveHandler(const AssetType& assetType);
/**
* Attempts to find an instance associated with the provided id. If the instance exists, it
* is returned. If no instance is found, nullptr is returned. If is safe to call this from
@@ -205,18 +199,20 @@ namespace AZ
* when acquiring an instance.
* @return Returns a smart pointer to the instance, which was either found or created.
*/
Data::Instance<Type> FindOrCreate(const InstanceId& id, const Asset<AssetData>& asset);
Data::Instance<Type> FindOrCreate(const InstanceId& id, const Asset<AssetData>& asset, const AZStd::any* param = nullptr);
//! Calls the above FindOrCreate using an InstanceId created from the asset
Data::Instance<Type> FindOrCreate(const Asset<AssetData>& asset);
Data::Instance<Type> FindOrCreate(const Asset<AssetData>& asset, const AZStd::any* param = nullptr);
//! Calls FindOrCreate using a random InstanceId
Data::Instance<Type> Create(const Asset<AssetData>& asset);
Data::Instance<Type> Create(const Asset<AssetData>& asset, const AZStd::any* param = nullptr);
private:
InstanceDatabase(const AssetType& assetType);
~InstanceDatabase();
bool m_checkAssetIds = true;
//useAssetTypeAsKeyForHandlers;
static const char* GetEnvironmentName();
// Utility function called by InstanceData to remove the instance from the database.
@@ -224,11 +220,7 @@ namespace AZ
void ValidateSameAsset(InstanceData* instance, const Data::Asset<AssetData>& asset) const;
// Performs a thread-safe search for the InstanceHandler for a given asset type.
bool FindHandler(const AssetType& assetType, InstanceHandler<Type>& handlerOut);
mutable AZStd::shared_mutex m_handlersMutex;
AZStd::unordered_map<AssetType, InstanceHandler<Type>> m_handlers;
InstanceHandler<Type> m_instanceHandler;
// m_database uses a recursive_mutex instead of a shared_mutex because it's possible to recursively
// create or destroy instances on the same thread while in the midst of creating or destroying an instance.
@@ -241,10 +233,11 @@ namespace AZ
static EnvironmentVariable<InstanceDatabase*> ms_instance;
};
template <typename Type>
EnvironmentVariable<InstanceDatabase<Type>*> InstanceDatabase<Type>::ms_instance = nullptr;
template<typename Type>
EnvironmentVariable<InstanceDatabase<Type>*>
InstanceDatabase<Type>::ms_instance = nullptr;
template <typename Type>
template<typename Type>
InstanceDatabase<Type>::~InstanceDatabase()
{
#ifdef AZ_DEBUG_BUILD
@@ -261,52 +254,7 @@ namespace AZ
"AZ::Data::%s still has active references.", Type::GetDatabaseName());
}
template <typename Type>
void InstanceDatabase<Type>::AddHandler(const AssetType& assetType, const InstanceHandler<Type>& handler)
{
AZ_Assert(handler.m_createFunction, "You are required to provide a create function to InstanceDatabase.");
AZStd::unique_lock<AZStd::shared_mutex> lock(m_handlersMutex);
auto result = m_handlers.emplace(assetType, handler);
AZ_Assert(result.second, "An InstanceHandler already exists for this AssetType");
}
template <typename Type>
void InstanceDatabase<Type>::AddHandler(const AssetType& assetType, typename InstanceHandler<Type>::CreateFunction createFunction)
{
InstanceHandler<Type> instanceHandler;
instanceHandler.m_createFunction = createFunction;
AddHandler(assetType, instanceHandler);
}
template <typename Type>
void InstanceDatabase<Type>::RemoveHandler(const AssetType& assetType)
{
AZStd::unique_lock<AZStd::shared_mutex> lock(m_handlersMutex);
m_handlers.erase(assetType);
}
template <typename Type>
bool InstanceDatabase<Type>::FindHandler(const AssetType& assetType, InstanceHandler<Type>& handlerOut)
{
AZStd::shared_lock<AZStd::shared_mutex> lock(m_handlersMutex);
auto handlerIter = m_handlers.find(assetType);
if (handlerIter != m_handlers.end())
{
// Since the handler is just a couple pointers, we copy the handler so we can
// release the lock right away.
handlerOut = handlerIter->second;
return true;
}
else
{
return false;
}
}
template <typename Type>
template<typename Type>
Data::Instance<Type> InstanceDatabase<Type>::Find(const InstanceId& id) const
{
AZStd::scoped_lock<AZStd::recursive_mutex> lock(m_databaseMutex);
@@ -318,8 +266,9 @@ namespace AZ
return nullptr;
}
template <typename Type>
Data::Instance<Type> InstanceDatabase<Type>::FindOrCreate(const InstanceId& id, const Asset<AssetData>& asset)
template<typename Type>
Data::Instance<Type> InstanceDatabase<Type>::FindOrCreate(
const InstanceId& id, const Asset<AssetData>& asset, const AZStd::any* param)
{
if (!id.IsValid())
{
@@ -358,24 +307,6 @@ namespace AZ
}
}
if (!azrtti_istypeof(m_baseAssetType, assetLocal.Get()))
{
InstanceHandler<Type> instanceHandler;
// If a handler was incorrectly registered for an unrelated asset type, this is the
// first chance we have to discover that fact, because up until now all we had was two
// TypeIds.
if (FindHandler(assetLocal.GetType(), instanceHandler))
{
AZ_Assert(false, "An InstanceHandler was added for asset type %s which is not a subclass of the base asset type %s.",
assetLocal.GetType().ToString<AZStd::string>().data(),
m_baseAssetType.ToString<AZStd::string>().data()
);
return nullptr;
}
}
// Take a lock to guard the insertion. Note that this will not guard against recursive insertions on the same thread.
AZStd::scoped_lock<AZStd::recursive_mutex> lock(m_databaseMutex);
@@ -390,48 +321,46 @@ namespace AZ
}
// Emplace a new instance and return it.
InstanceHandler<Type> instanceHandler;
if (FindHandler(assetLocal.GetType(), instanceHandler))
// It's possible for the m_createFunction call to recursively trigger another FindOrCreate call, so be aware that
// the contents of m_database may change within this call.
Data::Instance<Type> instance = nullptr;
if (!param)
{
// It's possible for the m_createFunction call to recursively trigger another FindOrCreate call, so be aware that
// the contents of m_database may change within this call.
Data::Instance<Type> instance = instanceHandler.m_createFunction(assetLocal.Get());
if (instance)
{
AZ_Assert(m_database.find(id) == m_database.end(),
"Instance creation for asset id %s resulted in a recursive creation of that asset, which was unexpected. "
"This asset might be erroneously referencing itself as a dependent asset.", id.ToString<AZStd::string>().c_str());
instance->m_id = id;
instance->m_parentDatabase = this;
instance->m_assetId = assetLocal.GetId();
instance->m_assetType = assetLocal.GetType();
m_database.emplace(id, instance.get());
}
return AZStd::move(instance);
instance = m_instanceHandler.m_createFunction(assetLocal.Get());
}
else
{
AZ_Warning(
"InstanceDatabase", false,
"No InstanceHandler found for asset type %s", assetLocal.GetType().ToString<AZStd::string>().data());
return nullptr;
instance = m_instanceHandler.m_createFunctionWithParam(assetLocal.Get(), param);
}
if (instance)
{
AZ_Assert(m_database.find(id) == m_database.end(),
"Instance creation for asset id %s resulted in a recursive creation of that asset, which was unexpected. "
"This asset might be erroneously referencing itself as a dependent asset.", id.ToString<AZStd::string>().c_str());
instance->m_id = id;
instance->m_parentDatabase = this;
instance->m_assetId = assetLocal.GetId();
instance->m_assetType = assetLocal.GetType();
m_database.emplace(id, instance.get());
}
return AZStd::move(instance);
}
template <typename Type>
Data::Instance<Type> InstanceDatabase<Type>::FindOrCreate(const Asset<AssetData>& asset)
template<typename Type>
Data::Instance<Type> InstanceDatabase<Type>::FindOrCreate(const Asset<AssetData>& asset, const AZStd::any* param)
{
return FindOrCreate(Data::InstanceId::CreateFromAssetId(asset.GetId()), asset);
return FindOrCreate(Data::InstanceId::CreateFromAssetId(asset.GetId()), asset, param);
}
template <typename Type>
Data::Instance<Type> InstanceDatabase<Type>::Create(const Asset<AssetData>& asset)
template<typename Type>
Data::Instance<Type> InstanceDatabase<Type>::Create(const Asset<AssetData>& asset, const AZStd::any* param)
{
return FindOrCreate(Data::InstanceId::CreateRandom(), asset);
return FindOrCreate(Data::InstanceId::CreateRandom(), asset, param);
}
template <typename Type>
template<typename Type>
void InstanceDatabase<Type>::ReleaseInstance(InstanceData* instance, const InstanceId& instanceId)
{
AZStd::scoped_lock<AZStd::recursive_mutex> lock(m_databaseMutex);
@@ -447,22 +376,13 @@ namespace AZ
instance->m_useCount.compare_exchange_strong(expectedRefCount, -1))
{
m_database.erase(instance->GetId());
InstanceHandler<Type> instanceHandler;
if (FindHandler(instance->GetAssetType(), instanceHandler))
{
instanceHandler.m_deleteFunction(static_cast<Type*>(instance));
}
else
{
AZ_Assert(false,
"Cannot delete Instance. No InstanceHandler found for asset type %s", instance->GetAssetType().ToString<AZStd::string>().data());
}
m_instanceHandler.m_deleteFunction(static_cast<Type*>(instance));
}
}
template <typename Type>
void InstanceDatabase<Type>::ValidateSameAsset(InstanceData* instance, const Data::Asset<AssetData>& asset) const
template<typename Type>
void InstanceDatabase<Type>::ValidateSameAsset(
InstanceData* instance, const Data::Asset<AssetData>& asset) const
{
/**
* The following validation layer is disabled in release, but is designed to catch a couple related edge cases
@@ -476,46 +396,47 @@ namespace AZ
*/
#if defined (AZ_DEBUG_BUILD)
AZ_Error("InstanceDatabase", instance->m_assetId == asset.GetId(),
"InstanceDatabase::FindOrCreate found the requested instance, but a different asset was used to create it. "
"Instances of a specific id should be acquired using the same asset. Either make sure the instance id "
"is actually unique, or that you are using the same asset each time for that particular id.");
if (m_checkAssetIds)
{
AZ_Error(
"InstanceDatabase", (instance->m_assetId == asset.GetId()),
"InstanceDatabase::FindOrCreate found the requested instance, but a different asset was used to create it. "
"Instances of a specific id should be acquired using the same asset. Either make sure the instance id "
"is actually unique, or that you are using the same asset each time for that particular id.");
}
#else
AZ_UNUSED(instance);
AZ_UNUSED(asset);
#endif
}
template <typename Type>
template<typename Type>
InstanceDatabase<Type>::InstanceDatabase(const AssetType& assetType)
: m_baseAssetType(assetType)
{
}
template <typename Type>
void InstanceDatabase<Type>::Create(const AssetType& assetType)
template<typename Type>
void InstanceDatabase<Type>::Create(const AssetType& assetType, const InstanceHandler<Type>& handler, bool checkAssetIds)
{
AZ_Assert(!ms_instance || !ms_instance.Get(), "InstanceDatabase already created!");
if (!ms_instance)
{
ms_instance = Environment::CreateVariable<InstanceDatabase*>(GetEnvironmentName());
ms_instance = Environment::CreateVariable<InstanceDatabase<Type>*>(GetEnvironmentName());
}
if (!ms_instance.Get())
{
ms_instance.Set(aznew InstanceDatabase<Type>(assetType));
}
AZ_Assert(handler.m_createFunction || handler.m_createFunctionWithParam, "At least one create function must be valid");
ms_instance.Get()->m_instanceHandler = handler;
ms_instance.Get()->m_checkAssetIds = checkAssetIds;
}
template <typename Type>
void InstanceDatabase<Type>::Create(const AssetType& assetType, const InstanceHandler<Type>& handler)
{
Create(assetType);
Instance().AddHandler(assetType, handler);
}
template <typename Type>
template<typename Type>
void InstanceDatabase<Type>::Destroy()
{
AZ_Assert(ms_instance, "InstanceDatabase not created!");
@@ -523,7 +444,7 @@ namespace AZ
*ms_instance = nullptr;
}
template <typename Type>
template<typename Type>
bool InstanceDatabase<Type>::IsReady()
{
if (!ms_instance)
@@ -534,7 +455,7 @@ namespace AZ
return ms_instance && *ms_instance;
}
template <typename Type>
template<typename Type>
InstanceDatabase<Type>& InstanceDatabase<Type>::Instance()
{
if (!ms_instance)
@@ -546,10 +467,12 @@ namespace AZ
return *(*ms_instance);
}
template <typename Type>
template<typename Type>
const char* InstanceDatabase<Type>::GetEnvironmentName()
{
static_assert(HasInstanceDatabaseName<Type>::value, "All classes used as instances in an InstanceDatabase need to define AZ_INSTANCE_DATA in the class.");
static_assert(
HasInstanceDatabaseName<Type>::value,
"All classes used as instances in an InstanceDatabase need to define AZ_INSTANCE_DATA in the class.");
return Type::GetDatabaseName();
}
}
@@ -34,8 +34,7 @@ namespace UnitTest
static const AssetId s_assetId3{ Uuid("{D9CDAB04-D206-431E-BDC0-1DD615D56197}") };
// test asset type
class TestAssetType
: public AssetData
class TestAssetType : public AssetData
{
public:
AZ_CLASS_ALLOCATOR(TestAssetType, AZ::SystemAllocator, 0);
@@ -47,30 +46,30 @@ namespace UnitTest
}
};
class TestInstanceA
: public InstanceData
class TestInstanceA : public InstanceData
{
public:
AZ_INSTANCE_DATA(TestInstanceA, "{65CBF1C8-F65F-4A84-8A11-B510BC435DB0}");
AZ_CLASS_ALLOCATOR(TestInstanceA, AZ::SystemAllocator, 0);
TestInstanceA(TestAssetType* asset)
: m_asset{asset, AZ::Data::AssetLoadBehavior::Default}
{}
: m_asset{ asset, AZ::Data::AssetLoadBehavior::Default }
{
}
Asset<TestAssetType> m_asset;
};
class TestInstanceB
: public InstanceData
class TestInstanceB : public InstanceData
{
public:
AZ_INSTANCE_DATA(TestInstanceB, "{4ED0A8BF-7800-44B2-AC73-2CB759C61C37}");
AZ_CLASS_ALLOCATOR(TestInstanceB, AZ::SystemAllocator, 0);
TestInstanceB(TestAssetType* asset)
: m_asset{asset, AZ::Data::AssetLoadBehavior::Default }
{}
: m_asset{ asset, AZ::Data::AssetLoadBehavior::Default }
{
}
~TestInstanceB()
{
@@ -86,8 +85,7 @@ namespace UnitTest
// test asset handler
template<typename AssetDataT>
class MyAssetHandler
: public AssetHandler
class MyAssetHandler : public AssetHandler
{
public:
AZ_CLASS_ALLOCATOR(MyAssetHandler, AZ::SystemAllocator, 0);
@@ -120,13 +118,12 @@ namespace UnitTest
}
};
class InstanceDatabaseTest
: public AllocatorsFixture
class InstanceDatabaseTest : public AllocatorsFixture
{
protected:
MyAssetHandler<TestAssetType>* m_assetHandler;
public:
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
@@ -200,7 +197,7 @@ namespace UnitTest
AZStd::vector<Uuid> guids;
AZStd::vector<Asset<TestAssetType>> assets;
for (size_t i = 0; i < assetIdCount; ++i)
{
Uuid guid = Uuid::CreateRandom();
@@ -211,7 +208,6 @@ namespace UnitTest
assets.emplace_back(assetManager.CreateAsset<TestAssetType>(guid, AZ::Data::AssetLoadBehavior::Default));
}
AZStd::vector<AZStd::thread> threads;
AZStd::mutex mutex;
AZStd::atomic<int> threadCount((int)threadCountMax);
@@ -232,27 +228,29 @@ namespace UnitTest
for (size_t i = 0; i < threadCountMax; ++i)
{
threads.emplace_back([&instanceManager, &threadCount, &cv, &guids, &assets, &durationSeconds]()
{
AZ::Debug::Timer timer;
timer.Stamp();
while(timer.GetDeltaTimeInSeconds() < durationSeconds)
threads.emplace_back(
[&instanceManager, &threadCount, &cv, &guids, &assets, &durationSeconds]()
{
const size_t index = rand() % guids.size();
const Uuid uuid = guids[index];
const InstanceId instanceId{uuid};
const AssetId assetId{uuid};
AZ::Debug::Timer timer;
timer.Stamp();
Instance<TestInstanceA> instance = instanceManager.FindOrCreate(instanceId, Asset<TestAssetType>(assetId, azrtti_typeid<TestAssetType>()));
EXPECT_NE(instance, nullptr);
EXPECT_EQ(instance->GetId(), instanceId);
EXPECT_EQ(instance->m_asset, assets[index]);
}
while (timer.GetDeltaTimeInSeconds() < durationSeconds)
{
const size_t index = rand() % guids.size();
const Uuid uuid = guids[index];
const InstanceId instanceId{ uuid };
const AssetId assetId{ uuid };
threadCount--;
cv.notify_one();
});
Instance<TestInstanceA> instance =
instanceManager.FindOrCreate(instanceId, Asset<TestAssetType>(assetId, azrtti_typeid<TestAssetType>()));
EXPECT_NE(instance, nullptr);
EXPECT_EQ(instance->GetId(), instanceId);
EXPECT_EQ(instance->m_asset, assets[index]);
}
threadCount--;
cv.notify_one();
});
}
bool timedOut = false;
@@ -261,7 +259,9 @@ namespace UnitTest
while (threadCount > 0 && !timedOut)
{
AZStd::unique_lock<AZStd::mutex> lock(mutex);
timedOut = (AZStd::cv_status::timeout == cv.wait_until(lock, AZStd::chrono::system_clock::now() + AZStd::chrono::seconds(durationSeconds * 2)));
timedOut =
(AZStd::cv_status::timeout ==
cv.wait_until(lock, AZStd::chrono::system_clock::now() + AZStd::chrono::seconds(durationSeconds * 2)));
}
EXPECT_TRUE(threadCount == 0) << "One or more threads appear to be deadlocked at " << timer.GetDeltaTimeInSeconds() << " seconds";
@@ -280,8 +280,8 @@ namespace UnitTest
TEST_F(InstanceDatabaseTest, ParallelInstanceCreate)
{
// This is the original test scenario from when InstanceDatabase was first implemented
// threads, AssetIds, seconds
ParallelInstanceCreateHelper( 8, 100, 5 );
// threads, AssetIds, seconds
ParallelInstanceCreateHelper(8, 100, 5);
// This value is checked in as 1 so this test doesn't take too much time, but can be increased locally to soak the test.
const size_t attempts = 1;
@@ -291,10 +291,10 @@ namespace UnitTest
printf("Attempt %zu of %zu... \n", i, attempts);
// The idea behind this series of tests is that there are two threads sharing one Instance, and both threads try to
// create or release that instance at the same time.
// create or release that instance at the same time.
// At the time, this set of scenarios has something like a 10% failure rate.
const size_t duration = 2;
// threads, AssetIds, seconds
// threads, AssetIds, seconds
ParallelInstanceCreateHelper(2, 1, duration);
ParallelInstanceCreateHelper(4, 1, duration);
ParallelInstanceCreateHelper(8, 1, duration);
@@ -306,7 +306,7 @@ namespace UnitTest
// Here we try a bunch of different threadCount:assetCount ratios to be thorough
const size_t duration = 2;
// threads, AssetIds, seconds
// threads, AssetIds, seconds
ParallelInstanceCreateHelper(2, 1, duration);
ParallelInstanceCreateHelper(4, 1, duration);
ParallelInstanceCreateHelper(4, 2, duration);
@@ -328,7 +328,10 @@ namespace UnitTest
// Tests whether the deleter actually calls delete properly without
// a parent database.
instance->m_onDeleteCallback = [this, &m_deleted] () { m_deleted = true; };
instance->m_onDeleteCallback = [this, &m_deleted]()
{
m_deleted = true;
};
}
EXPECT_TRUE(m_deleted);
@@ -386,242 +389,4 @@ namespace UnitTest
InstanceDatabase<TestInstanceB>::Destroy();
}
class InstanceDatabaseTestWithMultipleSubclasses
: public AllocatorsFixture
{
protected:
// We have "BaseAsset" with subclasses "FooAsset" and "BarAsset",
// and corresponding "BaseInstance" with subclasses "FooInstance" and "BarInstance".
// There is one "InstanceDatabse<BaseInstance>" that can create instances of both subtypes.
class BaseAsset
: public AssetData
{
public:
AZ_CLASS_ALLOCATOR(BaseAsset, AZ::SystemAllocator, 0);
AZ_RTTI(FooAsset, "{35B443A6-D8ED-4C3C-A3F0-D642251F0AA5}", AssetData);
BaseAsset()
{
m_status = AssetStatus::Ready;
}
};
class BaseInstance
: public InstanceData
{
public:
AZ_INSTANCE_DATA(BaseInstance, "{EFEC3406-2CB7-462E-A676-C22177E143E6}");
AZ_CLASS_ALLOCATOR(BaseInstance, AZ::SystemAllocator, 0);
BaseInstance(BaseAsset* asset)
: m_asset{ asset, AZ::Data::AssetLoadBehavior::Default }
{}
Asset<BaseAsset> m_asset;
};
class FooAsset
: public BaseAsset
{
public:
AZ_CLASS_ALLOCATOR(FooAsset, AZ::SystemAllocator, 0);
AZ_RTTI(FooAsset, "{74BAE278-3DCA-4ADD-807E-2A6873F9EA3C}", BaseAsset);
};
class BarAsset
: public BaseAsset
{
public:
AZ_CLASS_ALLOCATOR(BarAsset, AZ::SystemAllocator, 0);
AZ_RTTI(FooAsset, "{2BCD66F5-768B-4569-9FC2-DE92ABC9C0BF}", BaseAsset);
};
class FooInstance
: public BaseInstance
{
public:
AZ_RTTI(FooInstance, "{B5487509-5518-4591-AC96-03E623A584B7}", BaseInstance);
AZ_CLASS_ALLOCATOR(FooInstance, AZ::SystemAllocator, 0);
FooInstance(BaseAsset* asset)
: BaseInstance(asset)
{
EXPECT_TRUE(azrtti_typeid<FooAsset>() == asset->GetType());
}
};
class BarInstance
: public BaseInstance
{
public:
AZ_RTTI(BarInstance, "{CE9C844A-625D-4899-B7DB-8127D4618D25}", BaseInstance);
AZ_CLASS_ALLOCATOR(BarInstance, AZ::SystemAllocator, 0);
BarInstance(BaseAsset* asset)
: BaseInstance(asset)
{
EXPECT_TRUE(azrtti_typeid<BarAsset>() == asset->GetType());
}
};
MyAssetHandler<FooAsset> m_fooAssetHandler;
MyAssetHandler<BarAsset> m_barAssetHandler;
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
AllocatorInstance<PoolAllocator>::Create();
AllocatorInstance<ThreadPoolAllocator>::Create();
// create the asset database
{
AssetManager::Descriptor desc;
AssetManager::Create(desc);
}
// create the instance database
{
InstanceDatabase<BaseInstance>::Create(azrtti_typeid<BaseAsset>());
InstanceHandler<BaseInstance> fooHandler;
fooHandler.m_createFunction = [](AssetData* assetData)
{
EXPECT_TRUE(azrtti_istypeof<FooAsset>(assetData));
return aznew FooInstance(static_cast<FooAsset*>(assetData));
};
InstanceDatabase<BaseInstance>::Instance().AddHandler(azrtti_typeid<FooAsset>(), fooHandler);
// Using a different overload of AddHandler()
InstanceDatabase<BaseInstance>::Instance().AddHandler(azrtti_typeid<BarAsset>(), [](AssetData* assetData)
{
EXPECT_TRUE(azrtti_istypeof<BarAsset>(assetData));
return aznew BarInstance(static_cast<BarAsset*>(assetData));
});
}
AssetManager::Instance().RegisterHandler(&m_fooAssetHandler, AzTypeInfo<FooAsset>::Uuid());
AssetManager::Instance().RegisterHandler(&m_barAssetHandler, AzTypeInfo<BarAsset>::Uuid());
}
void TearDown() override
{
AssetManager::Instance().UnregisterHandler(&m_fooAssetHandler);
AssetManager::Instance().UnregisterHandler(&m_barAssetHandler);
AssetManager::Destroy();
InstanceDatabase<BaseInstance>::Destroy();
AllocatorInstance<ThreadPoolAllocator>::Destroy();
AllocatorInstance<PoolAllocator>::Destroy();
AllocatorsFixture::TearDown();
}
};
TEST_F(InstanceDatabaseTestWithMultipleSubclasses, InstanceCreate)
{
auto& assetManager = AssetManager::Instance();
auto& instanceDatabase = InstanceDatabase<BaseInstance>::Instance();
Asset<FooAsset> fooAsset = assetManager.CreateAsset<FooAsset>(s_assetId0, AZ::Data::AssetLoadBehavior::Default);
Asset<BarAsset> barAsset = assetManager.CreateAsset<BarAsset>(s_assetId1, AZ::Data::AssetLoadBehavior::Default);
// Run the creation tests on 'A' first.
Instance<BaseInstance> fooInstanceA = instanceDatabase.Find(s_instanceId0);
EXPECT_EQ(fooInstanceA, nullptr);
Instance<BaseInstance> barInstanceA = instanceDatabase.Find(s_instanceId1);
EXPECT_EQ(barInstanceA, nullptr);
fooInstanceA = instanceDatabase.FindOrCreate(s_instanceId0, fooAsset);
EXPECT_NE(fooInstanceA, nullptr);
EXPECT_EQ(fooInstanceA->m_asset, fooAsset);
EXPECT_TRUE(azrtti_typeid<FooInstance>() == fooInstanceA->RTTI_GetType());
EXPECT_EQ(fooInstanceA, instanceDatabase.Find(s_instanceId0));
barInstanceA = instanceDatabase.FindOrCreate(s_instanceId1, barAsset);
EXPECT_NE(barInstanceA, nullptr);
EXPECT_EQ(barInstanceA->m_asset, barAsset);
EXPECT_TRUE(azrtti_typeid<BarInstance>() == barInstanceA->RTTI_GetType());
EXPECT_EQ(barInstanceA, instanceDatabase.Find(s_instanceId1));
// Run the same test on 'B' to make sure it works independently.
Instance<BaseInstance> fooInstanceB = instanceDatabase.Find(s_instanceId2);
EXPECT_EQ(fooInstanceB, nullptr);
Instance<BaseInstance> barInstanceB = instanceDatabase.Find(s_instanceId3);
EXPECT_EQ(barInstanceB, nullptr);
fooInstanceB = instanceDatabase.FindOrCreate(s_instanceId2, fooAsset);
EXPECT_NE(fooInstanceB, nullptr);
EXPECT_EQ(fooInstanceB->m_asset, fooAsset);
EXPECT_TRUE(azrtti_typeid<FooInstance>() == fooInstanceB->RTTI_GetType());
EXPECT_EQ(fooInstanceB, instanceDatabase.Find(s_instanceId2));
barInstanceB = instanceDatabase.FindOrCreate(s_instanceId3, barAsset);
EXPECT_NE(barInstanceB, nullptr);
EXPECT_EQ(barInstanceB->m_asset, barAsset);
EXPECT_TRUE(azrtti_typeid<BarInstance>() == barInstanceB->RTTI_GetType());
EXPECT_EQ(barInstanceB, instanceDatabase.Find(s_instanceId3));
// Make sure the instances are unique
EXPECT_NE(fooInstanceA, fooInstanceB);
EXPECT_NE(barInstanceA, barInstanceB);
}
TEST_F(InstanceDatabaseTestWithMultipleSubclasses, TestError_AddHandler_AssetTypeIsNotSubclass)
{
MyAssetHandler<TestAssetType> testAssetHandler;
AssetManager::Instance().RegisterHandler(&testAssetHandler, azrtti_typeid<TestAssetType>());
// Register an instance handler with an unrelated asset type. This can't actually
// check the AssetType yet because all it has are AssetType GUIDs, no actual data.
{
InstanceHandler<BaseInstance> instanceHandler;
instanceHandler.m_createFunction = [](AssetData* assetData)
{
return aznew BaseInstance(static_cast<BaseAsset*>(assetData));
};
AssetType unrelatedAssetType = azrtti_typeid<TestAssetType>();
InstanceDatabase<BaseInstance>::Instance().AddHandler(unrelatedAssetType, instanceHandler);
}
// Try to use the unrelated handler. This is where we'll actually get an error.
{
AZ_TEST_START_ASSERTTEST;
Asset<TestAssetType> testAsset = AssetManager::Instance().CreateAsset<TestAssetType>(s_assetId0, AZ::Data::AssetLoadBehavior::Default);
EXPECT_EQ(nullptr, InstanceDatabase<BaseInstance>::Instance().FindOrCreate(s_instanceId0, testAsset));
AZ_TEST_STOP_ASSERTTEST(1);
}
AssetManager::Instance().UnregisterHandler(&testAssetHandler);
}
TEST_F(InstanceDatabaseTestWithMultipleSubclasses, TestError_AddHandler_AlreadyExists)
{
InstanceHandler<BaseInstance> instanceHandler;
instanceHandler.m_createFunction = [](AssetData*)
{
return nullptr; // Doesn't matter
};
AZ_TEST_START_ASSERTTEST;
// The SetUp() function already registered a handler for FooAsset so this should fail
InstanceDatabase<BaseInstance>::Instance().AddHandler(azrtti_typeid<FooAsset>(), instanceHandler);
InstanceDatabase<BaseInstance>::Instance().AddHandler(azrtti_typeid<FooAsset>(), [](AssetData*) { return nullptr; });
AZ_TEST_STOP_ASSERTTEST(2);
}
}
} // namespace UnitTest
-2
View File
@@ -9,8 +9,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
cmake_minimum_required(VERSION 3.0)
ly_add_target(
NAME AzAutoGen HEADERONLY
NAMESPACE AZ
@@ -77,6 +77,27 @@
#endif // defined(AZ_ENABLE_DEBUG_TOOLS)
#include <AzCore/Module/Environment.h>
#include <AzCore/std/string/conversions.h>
static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
{
if (arguments.empty())
{
return;
}
const auto entityIdStr = AZStd::string(arguments.front());
const auto entityIdValue = AZStd::stoull(entityIdStr);
AZStd::string entityName;
AZ::ComponentApplicationBus::BroadcastResult(
entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, AZ::EntityId(entityIdValue));
AZ_Printf("Entity Debug", "EntityId: %" PRIu64 ", Entity Name: %s", entityIdValue, entityName.c_str());
}
AZ_CONSOLEFREEFUNC(
PrintEntityName, AZ::ConsoleFunctorFlags::Null, "Parameter: EntityId value, Prints the name of the entity to the console");
namespace AZ
{
@@ -1260,7 +1281,7 @@ namespace AZ
// So auto load is turned off if option "AutoLoad" key is bool that is false
if (valueName == "AutoLoad" && !value)
{
// Strip off the AutoLoead entry from the path
// Strip off the AutoLoad entry from the path
auto autoLoadKey = AZ::StringFunc::TokenizeLast(path, "/");
if (!autoLoadKey)
{
@@ -1330,7 +1351,7 @@ namespace AZ
{
auto CompareDynamicModuleDescriptor = [&dynamicLibraryPath](const DynamicModuleDescriptor& entry)
{
return entry.m_dynamicLibraryPath.contains(dynamicLibraryPath);
return AZ::IO::PathView(entry.m_dynamicLibraryPath).Stem() == AZ::IO::PathView(dynamicLibraryPath).Stem();
};
if (auto moduleIter = AZStd::find_if(gemModules.begin(), gemModules.end(), CompareDynamicModuleDescriptor);
moduleIter == gemModules.end())
@@ -172,78 +172,10 @@ namespace AZ
//! Rotation modifiers
//! @{
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation in the world.
//! The origin of the axes is the entity's position in world space.
//! @param eulerAnglesRadians A three-dimensional vector, containing Euler angles in radians, to rotate the entity by.
virtual void SetRotation([[maybe_unused]] const AZ::Vector3& eulerAnglesRadians) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's X axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The X coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationX([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's Y axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Y coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationY([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's Z axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Z coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationZ([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotationQuaternion()
//! Sets the entity's rotation in the world in quaternion notation.
//! The origin of the axes is the entity's position in world space.
//! @param quaternion A quaternion that represents the rotation to use for the entity.
virtual void SetRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {}
//! @deprecated Use RotateAroundLocalX()
//! Rotates the entity around the world's X axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the X axis.
virtual void RotateByX([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use RotateAroundLocalY()
//! Rotates the entity around the world's Y axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Y axis.
virtual void RotateByY([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use RotateAroundLocalZ()
//! Rotates the entity around the world's Z axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Z axis.
virtual void RotateByZ([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation in the world in Euler angles rotation in radians.
//! @return A three-dimensional vector, containing Euler angles in radians, that represents the entity's rotation.
virtual AZ::Vector3 GetRotationEulerRadians() { return AZ::Vector3(FLT_MAX); }
//! @deprecated Use GetLocalRotationQuaternion()
//! Gets the entity's rotation in the world in quaternion format.
//! @return A quaternion that represents the entity's rotation in world space.
virtual AZ::Quaternion GetRotationQuaternion() { return AZ::Quaternion::CreateZero(); }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's X axis.
//! @return The Euler angle in radians by which the the entity is rotated around the X axis in world space.
virtual float GetRotationX() { return FLT_MAX; }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's Y axis.
//! @return The Euler angle in radians by which the the entity is rotated around the Y axis in world space.
virtual float GetRotationY() { return FLT_MAX; }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's Z axis.
//! @return The Euler angle in radians by which the the entity is rotated around the Z axis in world space.
virtual float GetRotationZ() { return FLT_MAX; }
virtual void SetWorldRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {}
//! Get angles in radian for each principle axis around which the world transform is
//! rotated in the order of z-axis and y-axis and then x-axis.
@@ -287,18 +219,11 @@ namespace AZ
//! Scale modifiers
//! @{
//! Set local scale of the transform.
//! @param scale The new scale to set.
virtual void SetLocalScale([[maybe_unused]] const AZ::Vector3& scale) {}
//! Get the scale value in local space.
//! @deprecated GetLocalScale is deprecated, and is left only to allow migration of legacy vector scale.
//! Get the legacy vector scale value in local space.
//! @return The scale value in local space.
virtual AZ::Vector3 GetLocalScale() { return AZ::Vector3(FLT_MAX); }
//! Get the scale value in world space.
//! @return The scale value in world space.
virtual AZ::Vector3 GetWorldScale() { return AZ::Vector3(FLT_MAX); }
//! Set the uniform scale value in local space.
virtual void SetLocalUniformScale([[maybe_unused]] float scale) {}
@@ -95,6 +95,12 @@ namespace AZ::IO
constexpr int Compare(AZStd::string_view pathString) const noexcept;
constexpr int Compare(const value_type* pathString) const noexcept;
// Extension for fixed strings
//! extension: fixed string types with MaxPathLength capacity
//! Returns a new instance of an AZStd::fixed_string with capacity of MaxPathLength
//! made from the internal string
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const noexcept;
// decomposition
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
//! "/O3DE/foo/bar/name.txt"
@@ -915,6 +915,11 @@ namespace AZ::IO
return compare_string_view(path);
}
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathString() const noexcept
{
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
}
// decomposition
constexpr auto PathView::RootName() const -> PathView
{
+39 -21
View File
@@ -30,7 +30,7 @@ namespace Platform
using FileHandleType = SystemFile::FileHandleType;
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode);
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode);
SystemFile::SizeType Tell(FileHandleType handle, const SystemFile* systemFile);
bool Eof(FileHandleType handle, const SystemFile* systemFile);
AZ::u64 ModificationTime(FileHandleType handle, const SystemFile* systemFile);
@@ -68,9 +68,8 @@ void SystemFile::CreatePath(const char* fileName)
}
SystemFile::SystemFile()
: m_handle{ AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE }
{
m_fileName[0] = '\0';
m_handle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
}
SystemFile::~SystemFile()
@@ -81,6 +80,25 @@ SystemFile::~SystemFile()
}
}
SystemFile::SystemFile(SystemFile&& other)
: SystemFile{}
{
AZStd::swap(m_fileName, other.m_fileName);
AZStd::swap(m_handle, other.m_handle);
}
SystemFile& SystemFile::operator=(SystemFile&& other)
{
// Close the current file and take over the SystemFile handle and filename
Close();
m_fileName = AZStd::move(other.m_fileName);
m_handle = AZStd::move(other.m_handle);
other.m_fileName = {};
other.m_handle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
return *this;
}
bool SystemFile::Open(const char* fileName, int mode, int platformFlags)
{
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Open - %s", fileName);
@@ -88,42 +106,42 @@ bool SystemFile::Open(const char* fileName, int mode, int platformFlags)
if (fileName) // If we reopen the file we are allowed to have NULL file name
{
if (strlen(fileName) > AZ_ARRAY_SIZE(m_fileName) - 1)
if (strlen(fileName) > m_fileName.max_size())
{
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, 0);
return false;
}
// store the filename
azsnprintf(m_fileName, AZ_ARRAY_SIZE(m_fileName), "%s", fileName);
m_fileName = fileName;
}
if (FileIOBus::HasHandlers())
{
bool isOpen = false;
bool isHandled = false;
EBUS_EVENT_RESULT(isHandled, FileIOBus, OnOpen, *this, m_fileName, mode, platformFlags, isOpen);
EBUS_EVENT_RESULT(isHandled, FileIOBus, OnOpen, *this, m_fileName.c_str(), mode, platformFlags, isOpen);
if (isHandled)
{
return isOpen;
}
}
AZ_Assert(!IsOpen(), "This file (%s) is already open!", m_fileName);
AZ_Assert(!IsOpen(), "This file (%s) is already open!", m_fileName.c_str());
return PlatformOpen(mode, platformFlags);
}
bool SystemFile::ReOpen(int mode, int platformFlags)
{
AZ_Assert(strlen(m_fileName) > 0, "Missing filename. You must call open first!");
AZ_Assert(!m_fileName.empty(), "Missing filename. You must call open first!");
return Open(0, mode, platformFlags);
}
void SystemFile::Close()
{
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Close - %s", m_fileName);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Close - %s", m_fileName);
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Close - %s", m_fileName.c_str());
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Close - %s", m_fileName.c_str());
if (FileIOBus::HasHandlers())
{
@@ -138,9 +156,9 @@ void SystemFile::Close()
PlatformClose();
}
void SystemFile::Seek(SizeType offset, SeekMode mode)
void SystemFile::Seek(SeekSizeType offset, SeekMode mode)
{
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Seek - %s:%i", m_fileName, offset);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Seek - %s:%i", m_fileName.c_str(), offset);
if (FileIOBus::HasHandlers())
{
@@ -167,15 +185,15 @@ bool SystemFile::Eof()
AZ::u64 SystemFile::ModificationTime()
{
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::ModTime - %s", m_fileName);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::ModTime - %s", m_fileName.c_str());
return Platform::ModificationTime(m_handle, this);
}
SystemFile::SizeType SystemFile::Read(SizeType byteSize, void* buffer)
{
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Read - %s:%i", m_fileName, byteSize);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Read - %s:%i", m_fileName, byteSize);
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Read - %s:%i", m_fileName.c_str(), byteSize);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Read - %s:%i", m_fileName.c_str(), byteSize);
if (FileIOBus::HasHandlers())
{
@@ -193,8 +211,8 @@ SystemFile::SizeType SystemFile::Read(SizeType byteSize, void* buffer)
SystemFile::SizeType SystemFile::Write(const void* buffer, SizeType byteSize)
{
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Write - %s:%i", m_fileName, byteSize);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Write - %s:%i", m_fileName, byteSize);
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Write - %s:%i", m_fileName.c_str(), byteSize);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Write - %s:%i", m_fileName.c_str(), byteSize);
if (FileIOBus::HasHandlers())
{
@@ -212,14 +230,14 @@ SystemFile::SizeType SystemFile::Write(const void* buffer, SizeType byteSize)
void SystemFile::Flush()
{
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Flush - %s", m_fileName);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Flush - %s", m_fileName.c_str());
Platform::Flush(m_handle, this);
}
SystemFile::SizeType SystemFile::Length() const
{
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Length - %s", m_fileName);
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Length - %s", m_fileName.c_str());
return Platform::Length(m_handle, this);
}
@@ -379,9 +397,9 @@ namespace
HasPosixEnumOption(PermissionModeFlags::Write);
#undef HasPosixEnumOption
}
}
FileDescriptorRedirector::FileDescriptorRedirector(int sourceFileDescriptor)
: m_sourceFileDescriptor(sourceFileDescriptor)
{
+13 -8
View File
@@ -12,10 +12,11 @@
#pragma once
#include <AzCore/base.h>
#include <AzCore/std/function/function_fwd.h>
#include <AzCore/std/string/string.h>
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/IO/SystemFile_Platform.h>
#include <AzCore/std/function/function_fwd.h>
#include <AzCore/std/string/fixed_string.h>
// Establish a consistent size that works across platforms. It's actually larger than this
// on platforms we support, but this is a good least common denominator
@@ -51,11 +52,15 @@ namespace AZ
};
using SizeType = AZ::IO::Internal::SizeType;
using SeekSizeType = AZ::IO::Internal::SeekSizeType;
using FileHandleType = AZ::IO::Internal::FileHandleType;
SystemFile();
~SystemFile();
SystemFile(SystemFile&&);
SystemFile& operator=(SystemFile&&);
/**
* Opens a file.
* \param fileName full file name including path
@@ -69,7 +74,7 @@ namespace AZ
/// Closes a file, if file already close it has no effect.
void Close();
/// Seek in current file.
void Seek(SizeType offset, SeekMode mode);
void Seek(SeekSizeType offset, SeekMode mode);
/// Get the cursor position in the current file.
SizeType Tell();
/// Is the cursor at the end of the file?
@@ -87,7 +92,7 @@ namespace AZ
/// Return disc offset if possible, otherwise 0
SizeType DiskOffset() const;
/// Return file name or NULL if file is not open.
AZ_FORCE_INLINE const char* Name() const { return m_fileName; }
AZ_FORCE_INLINE const char* Name() const { return m_fileName.c_str(); }
bool IsOpen() const;
/// Return native handle to the file.
@@ -124,12 +129,12 @@ namespace AZ
private:
static void CreatePath(const char * fileName);
bool PlatformOpen(int mode, int platformFlags);
void PlatformClose();
FileHandleType m_handle;
char m_fileName[AZ_MAX_PATH_LEN];
FileHandleType m_handle;
AZ::IO::FixedMaxPathString m_fileName;
};
/**
+1 -1
View File
@@ -227,7 +227,7 @@ namespace AZ
// the min and max of each part and sum them to get the min and max co-ordinate of the transformed box. For a given new axis,
// the coefficients for what proportion of each original axis is rotated onto that new axis are the same as the components we
// would get by performing the inverse rotation on the new axis, so we need to take the conjugate to get the inverse rotation.
axisCoeffs = transform.GetScale() * (transform.GetRotation().GetConjugate().TransformVector(axis));
axisCoeffs = transform.GetUniformScale() * (transform.GetRotation().GetConjugate().TransformVector(axis));
a = axisCoeffs * m_min;
b = axisCoeffs * m_max;
@@ -292,8 +292,13 @@ namespace AZ
const typename VecType::FloatType cmp2 = VecType::AndNot(cmp0, cmp1);
// -1/x
// this step is calculated for all values of x, but only used if x > Sqrt(2) + 1
// in order to avoid a division by zero, detect if xabs is zero here and replace it with an arbitrary value
// if xabs does equal zero, the value here doesn't matter because the result will be thrown away
typename VecType::FloatType xabsSafe =
VecType::Add(xabs, VecType::And(VecType::CmpEq(xabs, VecType::ZeroFloat()), FastLoadConstant<VecType>(Simd::g_vec1111)));
const typename VecType::FloatType y0 = VecType::And(cmp0, FastLoadConstant<VecType>(Simd::g_HalfPi));
typename VecType::FloatType x0 = VecType::Div(FastLoadConstant<VecType>(Simd::g_vec1111), xabs);
typename VecType::FloatType x0 = VecType::Div(FastLoadConstant<VecType>(Simd::g_vec1111), xabsSafe);
x0 = VecType::Xor(x0, VecType::CastToFloat(FastLoadConstant<VecType>(Simd::g_negateMask)));
const typename VecType::FloatType y1 = VecType::And(cmp2, FastLoadConstant<VecType>(Simd::g_QuarterPi));
@@ -368,8 +373,12 @@ namespace AZ
typename VecType::FloatType offset = VecType::And(x_lt_0, offset1);
// the result of this part of the computation is thrown away if x equals 0,
// but if x does equal 0, it will cause a division by zero
// so replace zero by an arbitrary value here in that case
typename VecType::FloatType xSafe = VecType::Add(x, VecType::And(x_eq_0, FastLoadConstant<VecType>(Simd::g_vec1111)));
const typename VecType::FloatType atan_mask = VecType::Not(VecType::Or(x_eq_0, y_eq_0));
const typename VecType::FloatType atan_arg = VecType::Div(y, x);
const typename VecType::FloatType atan_arg = VecType::Div(y, xSafe);
typename VecType::FloatType atan_result = VecType::Atan(atan_arg);
atan_result = VecType::Add(atan_result, offset);
atan_result = VecType::AndNot(pio2_mask, atan_result);
@@ -471,6 +471,7 @@ namespace AZ
AZ_MATH_INLINE Vec2::FloatType Vec2::Reciprocal(FloatArgType value)
{
value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f);
return Sse::Reciprocal(value);
}
@@ -513,6 +514,7 @@ namespace AZ
AZ_MATH_INLINE Vec2::FloatType Vec2::SqrtInv(FloatArgType value)
{
value = Sse::ReplaceFourth(Sse::ReplaceThird(value, 1.0f), 1.0f);
return Sse::SqrtInv(value);
}
@@ -507,6 +507,7 @@ namespace AZ
AZ_MATH_INLINE Vec3::FloatType Vec3::Reciprocal(FloatArgType value)
{
value = Sse::ReplaceFourth(value, 1.0f);
return Sse::Reciprocal(value);
}
@@ -549,6 +550,7 @@ namespace AZ
AZ_MATH_INLINE Vec3::FloatType Vec3::SqrtInv(FloatArgType value)
{
value = Sse::ReplaceFourth(value, 1.0f);
return Sse::SqrtInv(value);
}
+1 -1
View File
@@ -154,7 +154,7 @@ namespace AZ
return Obb::CreateFromPositionRotationAndHalfLengths(
transform.TransformPoint(obb.GetPosition()),
transform.GetRotation() * obb.GetRotation(),
transform.GetScale() * obb.GetHalfLengths()
transform.GetUniformScale() * obb.GetHalfLengths()
);
}
}
+40 -19
View File
@@ -130,8 +130,8 @@ namespace AZ
const Transform* transform = reinterpret_cast<const Transform*>(classPtr);
float data[NumFloats];
transform->GetRotation().StoreToFloat4(data);
transform->GetScale().StoreToFloat3(&data[4]);
transform->GetTranslation().StoreToFloat3(&data[7]);
data[4] = transform->GetUniformScale();
transform->GetTranslation().StoreToFloat3(&data[5]);
for (int i = 0; i < NumFloats; i++)
{
@@ -159,8 +159,8 @@ namespace AZ
size_t TransformSerializer::TextToData(const char* text, unsigned int textVersion, IO::GenericStream& stream, bool isDataBigEndian)
{
const size_t dataBufferSize = AZStd::max(NumFloatsVersion0, NumFloats);
const size_t numElements = textVersion < 1 ? NumFloatsVersion0 : NumFloats;
const size_t dataBufferSize = AZStd::max(AZStd::max(NumFloatsVersion1, NumFloatsVersion0), NumFloats);
const size_t numElements = textVersion < 1 ? NumFloatsVersion0 : (textVersion == 1 ? NumFloatsVersion1 : NumFloats);
size_t nextNumberIndex = 0;
AZStd::array<float, dataBufferSize> data;
@@ -201,7 +201,34 @@ namespace AZ
return true;
}
// otherwise load as a separate rotation, scale and translation
// version 1 had a quaternion rotation, vector3 scale and vector3 translation
else if (version == 1)
{
float data[NumFloatsVersion1];
if (stream.GetLength() < sizeof(data))
{
return false;
}
stream.Read(sizeof(data), reinterpret_cast<void*>(data));
for (unsigned int i = 0; i < AZ_ARRAY_SIZE(data); ++i)
{
AZ_SERIALIZE_SWAP_ENDIAN(data[i], isDataBigEndian);
}
Quaternion rotation = Quaternion::CreateFromFloat4(data);
Vector3 vectorScale = Vector3::CreateFromFloat3(&data[4]);
Vector3 translation = Vector3::CreateFromFloat3(&data[7]);
float uniformScale = vectorScale.GetMaxElement();
*reinterpret_cast<Transform*>(classPtr) =
Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateUniformScale(uniformScale);
return true;
}
// otherwise load as a quaternion rotation, float scale and vector3 translation
float data[NumFloats];
if (stream.GetLength() < sizeof(data))
{
@@ -216,11 +243,11 @@ namespace AZ
}
Quaternion rotation = Quaternion::CreateFromFloat4(data);
Vector3 scale = Vector3::CreateFromFloat3(&data[4]);
Vector3 translation = Vector3::CreateFromFloat3(&data[7]);
float scale = data[4];
Vector3 translation = Vector3::CreateFromFloat3(&data[5]);
*reinterpret_cast<Transform*>(classPtr) =
Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateScale(scale);
Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateUniformScale(scale);
return true;
}
@@ -237,7 +264,7 @@ namespace AZ
if (serializeContext)
{
serializeContext->Class<Transform>()
->Version(1)
->Version(2)
->Serializer<TransformSerializer>();
}
@@ -250,7 +277,7 @@ namespace AZ
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::TransformDefaultConstructor)->
Constructor<const Vector3&, const Quaternion&, const Vector3&>()->
Constructor<const Vector3&, const Quaternion&, float>()->
Method("GetBasis", &Transform::GetBasis)->
Method("GetBasisX", &Transform::GetBasisX)->
Method("GetBasisY", &Transform::GetBasisY)->
@@ -283,15 +310,10 @@ namespace AZ
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("GetRotation", &Transform::GetRotation)->
Method<void (Transform::*)(const Quaternion&)>("SetRotation", &Transform::SetRotation)->
Method("GetScale", &Transform::GetScale)->
Method("GetUniformScale", &Transform::GetUniformScale)->
Method("SetScale", &Transform::SetScale)->
Method("SetUniformScale", &Transform::SetUniformScale)->
Method("ExtractScale", &Transform::ExtractScale)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("ExtractUniformScale", &Transform::ExtractUniformScale)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("MultiplyByScale", &Transform::MultiplyByScale)->
Method("MultiplyByUniformScale", &Transform::MultiplyByUniformScale)->
Method("GetInverse", &Transform::GetInverse)->
Method("Invert", &Transform::Invert)->
@@ -310,7 +332,6 @@ namespace AZ
Method("CreateFromQuaternionAndTranslation", &Transform::CreateFromQuaternionAndTranslation)->
Method("CreateFromMatrix3x3", &Transform::CreateFromMatrix3x3)->
Method("CreateFromMatrix3x3AndTranslation", &Transform::CreateFromMatrix3x3AndTranslation)->
Method("CreateScale", &Transform::CreateScale)->
Method("CreateUniformScale", &Transform::CreateUniformScale)->
Method("CreateTranslation", &Transform::CreateTranslation)->
Method("ConstructFromValuesNumeric", &Internal::ConstructTransformFromValues);
@@ -321,7 +342,7 @@ namespace AZ
{
Transform result;
Matrix3x3 tmp = value;
result.m_scale = tmp.ExtractScale();
result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x3(tmp);
result.m_translation = Vector3::CreateZero();
return result;
@@ -331,7 +352,7 @@ namespace AZ
{
Transform result;
Matrix3x3 tmp = value;
result.m_scale = tmp.ExtractScale();
result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x3(tmp);
result.m_translation = p;
return result;
@@ -341,7 +362,7 @@ namespace AZ
{
Transform result;
Matrix3x4 tmp = value;
result.m_scale = tmp.ExtractScale();
result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x4(tmp);
result.m_translation = value.GetTranslation();
return result;
+17 -16
View File
@@ -25,10 +25,13 @@ namespace AZ
: public SerializeContext::IDataSerializer
{
public:
// number of floats in the serialized representation, 4 for rotation, 3 for scale and 3 for translation
static constexpr int NumFloats = 10;
// number of floats in the serialized representation, 4 for rotation, 1 for scale and 3 for translation
static constexpr int NumFloats = 8;
// number of floats in the old format, which stored a 3x4 matrix
// number of floats in version 1, which used 4 for rotation, 3 for scale and 3 for translation
static constexpr int NumFloatsVersion1 = 10;
// number of floats in version 0, which stored a 3x4 matrix
static constexpr int NumFloatsVersion0 = 12;
size_t Save(const void* classPtr, IO::GenericStream& stream, bool isDataBigEndian) override;
@@ -45,7 +48,7 @@ namespace AZ
static constexpr float MaxTransformScale = 1e9f;
//! @}
//! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation.
//! The basic transformation class, represented using a quaternion rotation, float scale and vector translation.
//! By design, cannot represent skew transformations.
class Transform
{
@@ -63,7 +66,7 @@ namespace AZ
Transform() = default;
//! Construct a transform from components.
Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
Transform(const Vector3& translation, const Quaternion& rotation, float scale);
//! Creates an identity transform.
static Transform CreateIdentity();
@@ -82,16 +85,20 @@ namespace AZ
static Transform CreateFromQuaternionAndTranslation(const class Quaternion& q, const Vector3& p);
//! Constructs from a Matrix3x3, translation is set to zero.
//! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
//! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x3(const class Matrix3x3& value);
//! Constructs from a Matrix3x3, translation is set to zero.
//! Constructs from a Matrix3x3 and translation Vector3.
//! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
//! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x3AndTranslation(const class Matrix3x3& value, const Vector3& p);
//! Constructs from a Matrix3x4.
//! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
//! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x4(const Matrix3x4& value);
//! Sets the transform to apply scale only, no rotation or translation.
static Transform CreateScale(const AZ::Vector3& scale);
//! Sets the transform to apply (uniform) scale only, no rotation or translation.
static Transform CreateUniformScale(const float scale);
@@ -122,18 +129,12 @@ namespace AZ
const Quaternion& GetRotation() const;
void SetRotation(const Quaternion& rotation);
Vector3 GetScale() const;
float GetUniformScale() const;
void SetScale(const Vector3& v);
void SetUniformScale(const float scale);
//! Sets the transform's scale to a unit value and returns the previous scale value.
Vector3 ExtractScale();
//! Sets the transform's scale to a unit value and returns the previous scale value.
float ExtractUniformScale();
void MultiplyByScale(const AZ::Vector3& scale);
void MultiplyByUniformScale(float scale);
Transform operator*(const Transform& rhs) const;
@@ -168,7 +169,7 @@ namespace AZ
private:
Quaternion m_rotation;
Vector3 m_scale;
float m_scale;
Vector3 m_translation;
};
+21 -58
View File
@@ -12,7 +12,7 @@
namespace AZ
{
AZ_MATH_INLINE Transform::Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale)
AZ_MATH_INLINE Transform::Transform(const Vector3& translation, const Quaternion& rotation, float scale)
: m_translation(translation)
, m_rotation(rotation)
, m_scale(scale)
@@ -25,7 +25,7 @@ namespace AZ
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = Vector3::CreateOne();
result.m_scale = 1.0f;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -49,7 +49,7 @@ namespace AZ
{
Transform result;
result.m_rotation = q;
result.m_scale = Vector3::CreateOne();
result.m_scale = 1.0f;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -58,26 +58,16 @@ namespace AZ
{
Transform result;
result.m_rotation = q;
result.m_scale = Vector3::CreateOne();
result.m_scale = 1.0f;
result.m_translation = p;
return result;
}
AZ_MATH_INLINE Transform Transform::CreateScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "CreateScale is deprecated, please use CreateUniformScale instead.");
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = scale;
result.m_translation = Vector3::CreateZero();
return result;
}
AZ_MATH_INLINE Transform Transform::CreateUniformScale(float scale)
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = Vector3(scale);
result.m_scale = scale;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -86,7 +76,7 @@ namespace AZ
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = Vector3::CreateOne();
result.m_scale = 1.0f;
result.m_translation = translation;
return result;
}
@@ -114,17 +104,17 @@ namespace AZ
AZ_MATH_INLINE Vector3 Transform::GetBasisX() const
{
return m_rotation.TransformVector(Vector3::CreateAxisX(m_scale.GetX()));
return m_rotation.TransformVector(Vector3::CreateAxisX(m_scale));
}
AZ_MATH_INLINE Vector3 Transform::GetBasisY() const
{
return m_rotation.TransformVector(Vector3::CreateAxisY(m_scale.GetY()));
return m_rotation.TransformVector(Vector3::CreateAxisY(m_scale));
}
AZ_MATH_INLINE Vector3 Transform::GetBasisZ() const
{
return m_rotation.TransformVector(Vector3::CreateAxisZ(m_scale.GetZ()));
return m_rotation.TransformVector(Vector3::CreateAxisZ(m_scale));
}
AZ_MATH_INLINE void Transform::GetBasisAndTranslation(Vector3* basisX, Vector3* basisY, Vector3* basisZ, Vector3* pos) const
@@ -160,49 +150,23 @@ namespace AZ
m_rotation = rotation;
}
AZ_MATH_INLINE Vector3 Transform::GetScale() const
{
AZ_WarningOnce("Transform", false, "GetScale is deprecated, please use GetUniformScale instead.");
return m_scale;
}
AZ_MATH_INLINE float Transform::GetUniformScale() const
{
return m_scale.GetMaxElement();
}
AZ_MATH_INLINE void Transform::SetScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "SetScale is deprecated, please use SetUniformScale instead.");
m_scale = scale;
return m_scale;
}
AZ_MATH_INLINE void Transform::SetUniformScale(const float scale)
{
m_scale = Vector3(scale);
}
AZ_MATH_INLINE Vector3 Transform::ExtractScale()
{
AZ_WarningOnce("Transform", false, "ExtractScale is deprecated, please use ExtractUniformScale instead.");
const Vector3 scale = m_scale;
m_scale = Vector3::CreateOne();
return scale;
m_scale = scale;
}
AZ_MATH_INLINE float Transform::ExtractUniformScale()
{
const float scale = m_scale.GetMaxElement();
m_scale = Vector3::CreateOne();
const float scale = m_scale;
m_scale = 1.0f;
return scale;
}
AZ_MATH_INLINE void Transform::MultiplyByScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "MultiplyByScale is deprecated, please use MultiplyByUniformScale instead.");
m_scale *= scale;
}
AZ_MATH_INLINE void Transform::MultiplyByUniformScale(float scale)
{
m_scale *= scale;
@@ -240,10 +204,9 @@ namespace AZ
AZ_MATH_INLINE Transform Transform::GetInverse() const
{
// note - need to be careful about how to calculate inverse when there is non-uniform scale
Transform out;
out.m_rotation = m_rotation.GetConjugate();
out.m_scale = m_scale.GetReciprocal();
out.m_scale = 1.0f / m_scale;
out.m_translation = -out.m_scale * (out.m_rotation.TransformVector(m_translation));
return out;
}
@@ -255,27 +218,27 @@ namespace AZ
AZ_MATH_INLINE bool Transform::IsOrthogonal(float tolerance) const
{
return m_scale.IsClose(Vector3::CreateOne(), tolerance);
return AZ::IsClose(m_scale, 1.0f, tolerance);
}
AZ_MATH_INLINE Transform Transform::GetOrthogonalized() const
{
Transform result;
result.m_rotation = m_rotation;
result.m_scale = Vector3::CreateOne();
result.m_scale = 1.0f;
result.m_translation = m_translation;
return result;
}
AZ_MATH_INLINE void Transform::Orthogonalize()
{
m_scale = Vector3::CreateOne();
m_scale = 1.0f;
}
AZ_MATH_INLINE bool Transform::IsClose(const Transform& rhs, float tolerance) const
{
return m_rotation.IsClose(rhs.m_rotation, tolerance)
&& m_scale.IsClose(rhs.m_scale, tolerance)
&& AZ::IsClose(m_scale, rhs.m_scale, tolerance)
&& m_translation.IsClose(rhs.m_translation, tolerance);
}
@@ -304,21 +267,21 @@ namespace AZ
AZ_MATH_INLINE void Transform::SetFromEulerDegrees(const Vector3& eulerDegrees)
{
m_translation = Vector3::CreateZero();
m_scale = Vector3::CreateOne();
m_scale = 1.0f;
m_rotation.SetFromEulerDegrees(eulerDegrees);
}
AZ_MATH_INLINE void Transform::SetFromEulerRadians(const Vector3& eulerRadians)
{
m_translation = Vector3::CreateZero();
m_scale = Vector3::CreateOne();
m_scale = 1.0f;
m_rotation.SetFromEulerRadians(eulerRadians);
}
AZ_MATH_INLINE bool Transform::IsFinite() const
{
return m_rotation.IsFinite()
&& m_scale.IsFinite()
&& AZ::IsFiniteFloat(m_scale)
&& m_translation.IsFinite();
}
@@ -67,7 +67,7 @@ namespace AZ
result.Combine(loadResult);
transformInstance->SetScale(AZ::Vector3(scale));
transformInstance->SetUniformScale(scale);
}
return context.Report(
@@ -512,7 +512,7 @@ namespace AZ
// Load DLLs specified in the application descriptor
for (const auto& moduleDescriptor : modules)
{
// For each module that is loaded, attempt to set the module's folder as a path for dependent module resolution
// For each module that is loaded, attempt to set the module's folder as a path for dependent module resolution
moduleSearchPathHelper.SetModuleSearchPath(moduleDescriptor);
LoadModuleOutcome result = LoadDynamicModule(moduleDescriptor.m_dynamicLibraryPath.c_str(), lastStepToPerform, maintainReferences);
+12 -2
View File
@@ -96,7 +96,12 @@
#endif
/// Aligns a declaration.
# define AZ_ALIGN(_decl, _alignment) __declspec(align(_alignment)) _decl
# define AZ_ALIGN(_decl, _alignment) \
AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") \
__declspec(align(_alignment)) \
_decl \
AZ_POP_DISABLE_WARNING
/// Return the alignment of a type. This if for internal use only (use AZStd::alignment_of<>())
# define AZ_INTERNAL_ALIGNMENT_OF(_type) __alignof(_type)
/// Pointer will be aliased.
@@ -123,7 +128,12 @@
# define AZ_FORCE_INLINE inline
/// Aligns a declaration.
# define AZ_ALIGN(_decl, _alignment) _decl __attribute__((aligned(_alignment)))
# define AZ_ALIGN(_decl, _alignment) \
AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") \
_decl \
__attribute__((aligned(_alignment)))
AZ_POP_DISABLE_WARNING
/// Return the alignment of a type. This if for internal use only (use AZStd::alignment_of<>())
# define AZ_INTERNAL_ALIGNMENT_OF(_type) __alignof__(_type)
/// Pointer will be aliased.
@@ -19,7 +19,7 @@ namespace AZ
{
inline namespace PlatformDefaults
{
static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient };
static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformAndroid, PlatformIOS, PlatformMac, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient };
const char* PlatformIdToPalFolder(AZ::PlatformId platform)
{
@@ -31,11 +31,11 @@ namespace AZ
{
case AZ::PC:
return "PC";
case AZ::ES3:
case AZ::ANDROID_ID:
return "Android";
case AZ::IOS:
return "iOS";
case AZ::OSX:
case AZ::MAC_ID:
return "Mac";
case AZ::PROVO:
return "Provo";
@@ -66,11 +66,11 @@ namespace AZ
}
else if (osPlatform == PlatformCodeNameMac)
{
return PlatformOSX;
return PlatformMac;
}
else if (osPlatform == PlatformCodeNameAndroid)
{
return PlatformES3;
return PlatformAndroid;
}
else if (osPlatform == PlatformCodeNameiOS)
{
@@ -207,13 +207,13 @@ namespace AZ
platformCodes.emplace_back(PlatformCodeNameWindows);
platformCodes.emplace_back(PlatformCodeNameLinux);
break;
case PlatformId::ES3:
case PlatformId::ANDROID_ID:
platformCodes.emplace_back(PlatformCodeNameAndroid);
break;
case PlatformId::IOS:
platformCodes.emplace_back(PlatformCodeNameiOS);
break;
case PlatformId::OSX:
case PlatformId::MAC_ID:
platformCodes.emplace_back(PlatformCodeNameMac);
break;
case PlatformId::PROVO:
@@ -27,9 +27,9 @@ namespace AZ
inline namespace PlatformDefaults
{
constexpr char PlatformPC[] = "pc";
constexpr char PlatformES3[] = "es3";
constexpr char PlatformAndroid[] = "android";
constexpr char PlatformIOS[] = "ios";
constexpr char PlatformOSX[] = "osx_gl";
constexpr char PlatformMac[] = "mac";
constexpr char PlatformProvo[] = "provo";
constexpr char PlatformSalem[] = "salem";
constexpr char PlatformJasper[] = "jasper";
@@ -54,9 +54,9 @@ namespace AZ
AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int,
(Invalid, -1),
PC,
ES3,
ANDROID_ID,
IOS,
OSX,
MAC_ID,
PROVO,
SALEM,
JASPER,
@@ -73,9 +73,9 @@ namespace AZ
{
Platform_NONE = 0x00,
Platform_PC = 1 << PlatformId::PC,
Platform_ES3 = 1 << PlatformId::ES3,
Platform_ANDROID = 1 << PlatformId::ANDROID_ID,
Platform_IOS = 1 << PlatformId::IOS,
Platform_OSX = 1 << PlatformId::OSX,
Platform_MAC = 1 << PlatformId::MAC_ID,
Platform_PROVO = 1 << PlatformId::PROVO,
Platform_SALEM = 1 << PlatformId::SALEM,
Platform_JASPER = 1 << PlatformId::JASPER,
@@ -87,7 +87,7 @@ namespace AZ
// A special platform that will always correspond to all non-server platforms, even if new ones are added
Platform_ALL_CLIENT = 1ULL << 31,
AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER,
AllNamedPlatforms = Platform_PC | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER,
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags);
@@ -28,8 +28,8 @@ namespace AZ
return "Android64";
case PlatformID::PLATFORM_APPLE_IOS:
return "iOS";
case PlatformID::PLATFORM_APPLE_OSX:
return "OSX";
case PlatformID::PLATFORM_APPLE_MAC:
return "Mac";
#if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
case PlatformID::PLATFORM_##PUBLICNAME:\
@@ -23,7 +23,7 @@ namespace AZ
PLATFORM_WINDOWS_64,
PLATFORM_LINUX_64,
PLATFORM_APPLE_IOS,
PLATFORM_APPLE_OSX,
PLATFORM_APPLE_MAC,
PLATFORM_ANDROID_64, // ARMv8 / 64-bit
#if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
@@ -161,7 +161,56 @@ namespace AZ
return "A pair is an fixed size collection of two elements.";
}
};
template<typename T>
void GetTypeNamesFold(AZStd::vector<AZStd::string>& result, AZ::BehaviorContext& context)
{
result.push_back(OnDemandPrettyName<T>::Get(context));
};
template<typename... T>
void GetTypeNames(AZStd::vector<AZStd::string>& result, AZ::BehaviorContext& context)
{
(GetTypeNamesFold<T>(result, context), ...);
};
template<typename T>
void GetTypeNamesFold(AZStd::string& result, AZ::BehaviorContext& context)
{
if (!result.empty())
{
result += ", ";
}
result += OnDemandPrettyName<T>::Get(context);
};
template<typename... T>
void GetTypeNames(AZStd::string& result, AZ::BehaviorContext& context)
{
(GetTypeNamesFold<T>(result, context), ...);
};
template<typename... T>
struct OnDemandPrettyName<AZStd::tuple<T...>>
{
static AZStd::string Get(AZ::BehaviorContext& context)
{
AZStd::string typeNames;
GetTypeNames<T...>(typeNames, context);
return AZStd::string::format("Tuple<%s>", typeNames.c_str());
}
};
template<typename... T>
struct OnDemandToolTip<AZStd::tuple<T...>>
{
static AZStd::string Get(AZ::BehaviorContext&)
{
return "A tuple is an fixed size collection of any number of any type of element.";
}
};
template<class Key, class MappedType, class Hasher, class EqualKey, class Allocator>
struct OnDemandPrettyName< AZStd::unordered_map<Key, MappedType, Hasher, EqualKey, Allocator> >
{
@@ -813,20 +813,27 @@ namespace AZ
{
using ContainerType = AZStd::tuple<T...>;
template<size_t Index>
static void ReflectUnpackMethodFold(BehaviorContext::ClassBuilder<ContainerType>& builder)
template<typename Targ, size_t Index>
static void ReflectUnpackMethodFold(BehaviorContext::ClassBuilder<ContainerType>& builder, const AZStd::vector<AZStd::string>& typeNames)
{
const AZStd::string methodName = AZStd::string::format("Get%zu", Index);
builder->Method(methodName.data(), [](ContainerType& value) { return AZStd::get<Index>(value); })
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
builder->Method(methodName.data(), [](ContainerType& thisPointer) { return AZStd::get<Index>(thisPointer); })
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
->Attribute(AZ::ScriptCanvasAttributes::TupleGetFunctionIndex, Index)
;
builder->Property
( AZStd::string::format("element_%zu_%s", Index, typeNames[Index].c_str()).c_str()
, [](ContainerType& thisPointer) { return AZStd::get<Index>(thisPointer); }
, [](ContainerType& thisPointer, const Targ& element) { AZStd::get<Index>(thisPointer) = element; });
}
template<size_t... Indices>
template<typename... Targ, size_t... Indices>
static void ReflectUnpackMethods(BehaviorContext::ClassBuilder<ContainerType>& builder, AZStd::index_sequence<Indices...>)
{
(ReflectUnpackMethodFold<Indices>(builder), ...);
AZStd::vector<AZStd::string> typeNames;
ScriptCanvasOnDemandReflection::GetTypeNames<T...>(typeNames, *builder.m_context);
(ReflectUnpackMethodFold<Targ, Indices>(builder, typeNames), ...);
}
static void Reflect(ReflectContext* context)
@@ -851,9 +858,10 @@ namespace AZ
->Attribute(AZ::ScriptCanvasAttributes::TupleConstructorFunction, constructorHolder)
;
ReflectUnpackMethods(builder, AZStd::make_index_sequence<sizeof...(T)>{});
ReflectUnpackMethods<T...>(builder, AZStd::make_index_sequence<sizeof...(T)>{});
builder->Method("GetSize", []() { return AZStd::tuple_size<ContainerType>::value; })
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
;
}
}
@@ -274,7 +274,7 @@ namespace AZ
{
using Callable = AZStd::conditional_t<AZStd::function_traits<Invocable>::value, AZStd::function<typename AZStd::function_traits<Invocable>::function_type>, Invocable>;
public:
AZ_RTTI((AttributeInvocable<Invocable>, "{60D5804F-9AF4-4EB1-8F5A-62AFB4883F9D}"), AZ::Attribute);
AZ_RTTI((AttributeInvocable<Invocable>, "{60D5804F-9AF4-4EB1-8F5A-62AFB4883F9D}", Invocable), AZ::Attribute);
AZ_CLASS_ALLOCATOR(AttributeInvocable<Invocable>, SystemAllocator, 0);
template<typename CallableType>
explicit AttributeInvocable(CallableType&& invocable)
+13 -8
View File
@@ -150,8 +150,13 @@ namespace AZ
// also needs to be an overload for every version because they all represent overloads for different non-types.
namespace AzGenericTypeInfo
{
template<typename...>
constexpr bool false_v = false;
/// Needs to match declared parameter type.
template <template <typename...> class> constexpr bool false_v1 = false;
template <template <AZStd::size_t...> class> constexpr bool false_v2 = false;
template <template <typename, AZStd::size_t> class> constexpr bool false_v3 = false;
template <template <typename, typename, AZStd::size_t> class> constexpr bool false_v4 = false;
template <template <typename, typename, typename, AZStd::size_t> class> constexpr bool false_v5 = false;
template <template <typename, AZStd::size_t, typename> class> constexpr bool false_v6 = false;
template<typename T>
inline const AZ::TypeId& Uuid()
@@ -162,7 +167,7 @@ namespace AZ
template<template<typename...> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v1<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -170,7 +175,7 @@ namespace AZ
template<template<AZStd::size_t...> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v2<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -178,7 +183,7 @@ namespace AZ
template<template<typename, AZStd::size_t> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v3<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -186,7 +191,7 @@ namespace AZ
template<template<typename, typename, AZStd::size_t> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v4<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -194,7 +199,7 @@ namespace AZ
template<template<typename, typename, typename, AZStd::size_t> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v5<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -202,7 +207,7 @@ namespace AZ
template<template<typename, AZStd::size_t, typename> class T>
inline const AZ::TypeId& Uuid()
{
static_assert(false_v<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static_assert(false_v6<T>, "Missing specialization for this template. Make sure it's registered for type info support.");
static const AZ::TypeId s_uuid = AZ::TypeId::CreateNull();
return s_uuid;
}
@@ -937,7 +937,7 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection)
->Enum<static_cast<int>(PlatformID::PLATFORM_LINUX_64)>("Linux")
->Enum<static_cast<int>(PlatformID::PLATFORM_ANDROID_64)>("Android64")
->Enum<static_cast<int>(PlatformID::PLATFORM_APPLE_IOS)>("iOS")
->Enum<static_cast<int>(PlatformID::PLATFORM_APPLE_OSX)>("OSX")
->Enum<static_cast<int>(PlatformID::PLATFORM_APPLE_MAC)>("Mac")
#if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
->Enum<static_cast<int>(PlatformID::PLATFORM_##PUBLICNAME)>(#CodeName)
@@ -127,13 +127,14 @@ namespace AZ
*/
class EditContext
{
public:
/// @cond EXCLUDE_DOCS
class ClassBuilder;
class EnumBuilder;
using ClassInfo = ClassBuilder; ///< @deprecated Use EditContext::ClassBuilder
using EnumInfo = EnumBuilder; ///< @deprecated Use EditContext::EnumBuilder
/// @endcond
public:
AZ_CLASS_ALLOCATOR(EditContext, SystemAllocator, 0);
/**
@@ -186,6 +187,7 @@ namespace AZ
* look at the unit tests and example to see use cases.
*
*/
public:
class ClassBuilder
{
friend EditContext;
@@ -399,6 +401,7 @@ namespace AZ
EnumBuilder* Value(const char* name, E value);
};
private:
typedef AZStd::list<Edit::ClassData> ClassDataListType;
typedef AZStd::unordered_map<AZ::Uuid, Edit::ElementData> EnumDataMapType;
@@ -123,6 +123,7 @@ namespace AZ
const static AZ::Crc32 NameLabelOverride = AZ_CRC("NameLabelOverride", 0x9ff79cab);
const static AZ::Crc32 AssetPickerTitle = AZ_CRC_CE("AssetPickerTitle");
const static AZ::Crc32 HideProductFilesInAssetPicker = AZ_CRC_CE("HideProductFilesInAssetPicker");
const static AZ::Crc32 ChildNameLabelOverride = AZ_CRC("ChildNameLabelOverride", 0x73dd2909);
//! Container attribute that is used to override labels for its elements given the index of the element
const static AZ::Crc32 IndexedChildNameLabelOverride = AZ_CRC("IndexedChildNameLabelOverride", 0x5f313ac2);
@@ -28,7 +28,13 @@ namespace AZ
{
namespace IdUtils
{
template<typename IdType>
/**
* \param AllowDuplicates - If true allows the same id to be registered multiple times,
with the newer value overwriting the stored value. If false, duplicates are not allowed and
the first stored value is kept.The default is false.
*/
template<typename IdType, bool AllowDuplicates = false>
struct Remapper
{
/**
@@ -138,14 +144,18 @@ namespace AZ
* \param context - The serialize context for enumerating the @classPtr elements
*/
template<typename T, typename MapType>
static void GenerateNewIdsAndFixRefs(T* object, MapType& newIdMap, AZ::SerializeContext* context = nullptr)
static void GenerateNewIdsAndFixRefs(
T* object, MapType& newIdMap, AZ::SerializeContext* context = nullptr)
{
if (!context)
{
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (!context)
{
AZ_Error("Serialization", false, "No serialize context provided! Failed to get component application default serialize context! ComponentApp is not started or input serialize context should not be null!");
AZ_Error(
"Serialization", false,
"No serialize context provided! Failed to get component application default serialize context! ComponentApp is "
"not started or input serialize context should not be null!");
return;
}
}
@@ -156,8 +166,16 @@ namespace AZ
{
if (idGenerator)
{
auto it = newIdMap.emplace(originalId, idGenerator());
return it.first->second;
if constexpr(AllowDuplicates)
{
auto it = newIdMap.insert_or_assign(originalId, idGenerator());
return it.first->second;
}
else
{
auto it = newIdMap.emplace(originalId, idGenerator());
return it.first->second;
}
}
return originalId;
}
@@ -30,8 +30,10 @@ namespace AZ
bool m_isModifiedContainer;
};
template<typename IdType>
unsigned int Remapper<IdType>::RemapIds(void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType>::IdMapper& mapper, AZ::SerializeContext* context, bool replaceId)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::RemapIds(
void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType, AllowDuplicates>::IdMapper& mapper,
AZ::SerializeContext* context, bool replaceId)
{
if (!context)
{
@@ -152,16 +154,18 @@ namespace AZ
return replaced;
}
template<typename IdType>
unsigned int Remapper<IdType>::ReplaceIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const IdMapper& mapper, AZ::SerializeContext* context /*= nullptr*/)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::ReplaceIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const IdMapper& mapper, AZ::SerializeContext* context /*= nullptr*/)
{
unsigned int replaced = RemapIds(classPtr, classUuid, mapper, context, true);
replaced += RemapIds(classPtr, classUuid, mapper, context, false);
return replaced;
}
template<typename IdType>
unsigned int Remapper<IdType>::RemapIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType>::IdReplacer& mapper, AZ::SerializeContext* context)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::RemapIdsAndIdRefs(
void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType, AllowDuplicates>::IdReplacer& mapper,
AZ::SerializeContext* context)
{
if (!context)
{
@@ -24,7 +24,12 @@
#include <AzCore/Serialization/Json/StringSerializer.h>
#include <AzCore/Serialization/Json/TupleSerializer.h>
#include <AzCore/Serialization/Json/UnorderedSetSerializer.h>
#include <AzCore/Serialization/Json/UnsupportedTypesSerializer.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/any.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/tuple.h>
#include <AzCore/std/utils.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/containers/forward_list.h>
@@ -33,12 +38,11 @@
#include <AzCore/std/containers/set.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/intrusive_ptr.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/tuple.h>
#include <AzCore/std/utils.h>
namespace AZ
{
@@ -98,6 +102,13 @@ namespace AZ
jsonContext->Serializer<JsonArraySerializer>()
->HandlesType<AZStd::array>();
jsonContext->Serializer<JsonAnySerializer>()
->HandlesType<AZStd::any>();
jsonContext->Serializer<JsonVariantSerializer>()
->HandlesType<AZStd::variant>();
jsonContext->Serializer<JsonOptionalSerializer>()
->HandlesType<AZStd::optional>();
MathReflect(jsonContext);
}
else if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(reflectContext))
@@ -33,34 +33,31 @@ namespace AZ
, m_serializerIter(serializerMapIter)
{}
JsonRegistrationContext::SerializerBuilder* JsonRegistrationContext::SerializerBuilder::HandlesTypeId(const Uuid& uuid)
JsonRegistrationContext::SerializerBuilder* JsonRegistrationContext::SerializerBuilder::HandlesTypeId(
const Uuid& uuid, bool overwriteExisting)
{
if (!m_context->IsRemovingReflection())
{
auto serializer = m_serializerIter->second.get();
if (uuid.IsNull())
{
AZ_Error("Serialization", false,
"Could not register Json serializer %s. Its Uuid is null.",
serializer->RTTI_GetTypeName()
);
AZ_Assert(false, "Could not register Json serializer %s. Its Uuid is null.", serializer->RTTI_GetTypeName());
return this;
}
auto serializerIter = m_context->m_handledTypesMap.find(uuid);
if (serializerIter == m_context->m_handledTypesMap.end())
if (!overwriteExisting)
{
m_context->m_handledTypesMap.emplace(uuid, serializer);
return this;
auto emplaceResult = m_context->m_handledTypesMap.try_emplace(uuid, serializer);
AZ_Assert(
emplaceResult.second,
"Couldn't register Json serializer %s. Another serializer (%s) has already been registered for the same Uuid (%s).",
serializer->RTTI_GetTypeName(), emplaceResult.first->second->RTTI_GetTypeName(),
uuid.ToString<AZStd::string>().c_str());
}
else
{
m_context->m_handledTypesMap.insert_or_assign(uuid, serializer);
}
AZ_Error("Serialization", false,
"Couldn't register Json serializer %s. Another serializer (%s) has already been registered for the same Uuid (%s).",
serializer->RTTI_GetTypeName(),
serializerIter->second->RTTI_GetTypeName(),
serializerIter->first.ToString<OSString>().c_str()
);
}
else
{
@@ -63,52 +63,50 @@ namespace AZ
SerializerBuilder* operator->();
template <typename T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template <template<typename...> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template<template<AZStd::size_t...> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template<template<typename, AZStd::size_t> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template<template<typename, typename, AZStd::size_t> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template<template<typename, typename, typename, AZStd::size_t> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
template<template<typename, AZStd::size_t, typename> class T>
SerializerBuilder* HandlesType()
SerializerBuilder* HandlesType(bool overwriteExisting = false)
{
return HandlesTypeId(azrtti_typeid<T>());
return HandlesTypeId(azrtti_typeid<T>(), overwriteExisting);
}
protected:
struct Placeholder { AZ_TYPE_INFO(PlaceHolder, "{4425191C-F497-411A-A7C3-52928E720B0A}"); };
SerializerBuilder(JsonRegistrationContext* context, SerializerMap::const_iterator serializerMapIter);
SerializerBuilder* HandlesTypeId(const AZ::Uuid& uuid);
SerializerBuilder* HandlesTypeId(const AZ::Uuid& uuid, bool overwriteExisting);
JsonRegistrationContext* m_context = nullptr;
SerializerMap::const_iterator m_serializerIter;
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/UnsupportedTypesSerializer.h>
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(JsonUnsupportedTypesSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonAnySerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonVariantSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonOptionalSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonUnsupportedTypesSerializer::Load(void*, const Uuid&, const rapidjson::Value&,
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Invalid, GetMessage());
}
JsonSerializationResult::Result JsonUnsupportedTypesSerializer::Store(rapidjson::Value&, const void*, const void*, const Uuid&,
JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::Invalid, GetMessage());
}
AZStd::string_view JsonAnySerializer::GetMessage() const
{
return "The Json Serialization doesn't support AZStd::any by design. The Json Serialization attempts to minimize the use of $type, "
"in particular the guid version, but no way has yet been found to use AZStd::any without explicitly and always requiring "
"one.";
}
AZStd::string_view JsonVariantSerializer::GetMessage() const
{
return "The Json Serialization doesn't support AZStd::variant by design. The Json Serialization attempts to minimize the use of "
"$type, in particular the guid version. While combinations of AZStd::variant can be constructed that don't require a $type, "
"this cannot be guaranteed in general.";
}
AZStd::string_view JsonOptionalSerializer::GetMessage() const
{
return "The Json Serialization doesn't support AZStd::optional by design. No JSON format has yet been found that wasn't deemed too "
"complex or overly verbose.";
}
} // namespace AZ
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/std/string/string_view.h>
namespace AZ
{
class JsonUnsupportedTypesSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonUnsupportedTypesSerializer, "{AFCC76B9-1F28-429D-8B4E-020BFD95ADAC}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(
void* outputValue,
const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(
rapidjson::Value& outputValue,
const void* inputValue,
const void* defaultValue,
const Uuid& valueTypeId,
JsonSerializerContext& context) override;
protected:
virtual AZStd::string_view GetMessage() const = 0;
};
class JsonAnySerializer : public JsonUnsupportedTypesSerializer
{
public:
AZ_RTTI(JsonAnySerializer, "{699A0864-C4E2-4266-8141-99793C76870F}", JsonUnsupportedTypesSerializer);
AZ_CLASS_ALLOCATOR_DECL;
protected:
AZStd::string_view GetMessage() const override;
};
class JsonVariantSerializer : public JsonUnsupportedTypesSerializer
{
public:
AZ_RTTI(JsonVariantSerializer, "{08F8E746-F8A4-4E83-8902-713E90F3F498}", JsonUnsupportedTypesSerializer);
AZ_CLASS_ALLOCATOR_DECL;
protected:
AZStd::string_view GetMessage() const override;
};
class JsonOptionalSerializer : public JsonUnsupportedTypesSerializer
{
public:
AZ_RTTI(JsonOptionalSerializer, "{F8AF1C95-BD1B-44D2-9B4A-F5726133A104}", JsonUnsupportedTypesSerializer);
AZ_CLASS_ALLOCATOR_DECL;
protected:
AZStd::string_view GetMessage() const override;
};
} // namespace AZ
@@ -101,6 +101,9 @@ namespace AZ
class SerializeContext
: public ReflectContext
{
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
public:
/// @cond EXCLUDE_DOCS
friend class EditContext;
class ClassBuilder;
@@ -108,9 +111,6 @@ namespace AZ
/// @endcond
class EnumBuilder;
static const unsigned int VersionClassDeprecated = (unsigned int)-1;
public:
class ClassData;
struct EnumerateInstanceCallContext;
struct ClassElement;
@@ -1131,6 +1131,7 @@ namespace AZ
* ->Version(3,&MyVersionConverter)
* ->Field("data",&MyStruct::m_data);
*/
public:
class ClassBuilder
{
friend class SerializeContext;
@@ -1330,7 +1331,8 @@ namespace AZ
AZStd::vector<AttributeSharedPair, AZStdFunctorAllocator>* m_currentAttributes = nullptr;
};
EditContext* m_editContext; ///< Pointer to optional edit context.
private:
EditContext* m_editContext; ///< Pointer to optional edit context.
UuidToClassMap m_uuidMap; ///< Map for all class in this serialize context
AZStd::unordered_multimap<AZ::Crc32, AZ::Uuid> m_classNameToUuid; /// Map all class names to their uuid
AZStd::unordered_multimap<Uuid, GenericClassInfo*> m_uuidGenericMap; ///< Uuid to ClassData map of reflected classes with GenericTypeInfo
@@ -88,6 +88,35 @@ namespace AZ::Internal
m_enginePaths.emplace_back(EngineInfo{AZ::IO::FixedMaxPath{value}.LexicallyNormal(), {}});
}
AZ::SettingsRegistryInterface::VisitResponse Traverse(
[[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName,
AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type type) override
{
auto response = AZ::SettingsRegistryInterface::VisitResponse::Continue;
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
{
if (type == AZ::SettingsRegistryInterface::Type::Array)
{
if (valueName.compare("engines") != 0)
{
response = AZ::SettingsRegistryInterface::VisitResponse::Skip;
}
}
}
else if (action == AZ::SettingsRegistryInterface::VisitAction::Value)
{
if (type == AZ::SettingsRegistryInterface::Type::String)
{
if (valueName.compare("path") != 0)
{
response = AZ::SettingsRegistryInterface::VisitResponse::Skip;
}
}
}
return response;
}
AZStd::vector<EngineInfo> m_enginePaths{};
};
@@ -612,6 +641,8 @@ namespace AZ::SettingsRegistryMergeUtils
}
else
{
// Set the default ProjectUserPath to the <engine-root>/user directory
registry.Set(FilePathKey_ProjectUserPath, (engineRoot / "user").LexicallyNormal().Native());
AZ_TracePrintf("SettingsRegistryMergeUtils",
R"(Project path isn't set in the Settings Registry at "%.*s". Project-related filepaths will not be set)" "\n",
aznumeric_cast<int>(projectPathKey.size()), projectPathKey.data());
@@ -971,6 +971,10 @@ namespace AZ
*/
void RestoreCachedInstances();
/// Returns data flags for use when instantiating an instance of this slice.
/// These data flags include those harvested from the entire slice ancestry.
const DataFlagsPerEntity& GetDataFlagsForInstances() const;
protected:
//////////////////////////////////////////////////////////////////////////
@@ -1004,9 +1008,6 @@ namespace AZ
DataFlagsPerEntity* GetCorrectBundleOfDataFlags(EntityId entityId);
const DataFlagsPerEntity* GetCorrectBundleOfDataFlags(EntityId entityId) const;
/// Returns data flags for use when instantiating an instance of this slice.
/// These data flags include those harvested from the entire slice ancestry.
const DataFlagsPerEntity& GetDataFlagsForInstances() const;
void BuildDataFlagsForInstances();
/**
@@ -175,4 +175,11 @@ namespace AZ::Utils
path /= ".o3de";
return path.Native();
}
AZ::IO::FixedMaxPathString GetO3deLogsDirectory()
{
AZ::IO::FixedMaxPath path = GetO3deManifestDirectory();
path /= "Logs";
return path.Native();
}
}
+5 -1
View File
@@ -97,6 +97,9 @@ namespace AZ
//! Retrieves the full path where the manifest file lives, i.e. "<userhome>/.o3de/o3de_manifest.json"
AZ::IO::FixedMaxPathString GetEngineManifestPath();
//! Retrieves the full directory to the O3DE logs directory, i.e. "<userhome>/.o3de/Logs"
AZ::IO::FixedMaxPathString GetO3deLogsDirectory();
//! Retrieves the App root path to use on the current platform
//! If the optional is not engaged the AppRootPath should be calculated based
//! on the location of the bootstrap.cfg file
@@ -113,7 +116,8 @@ namespace AZ
//! Save a string to a file. Otherwise returns a failure with error message.
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
//! Read a file into a string. Returns a failure with error message if the content could not be loaded.
//! Read a file into a string. Returns a failure with error message if the content could not be loaded or if
//! the file size is larger than the max file size provided.
template<typename Container = AZStd::string>
AZ::Outcome<Container, AZStd::string> ReadFile(AZStd::string_view filePath, size_t maxFileSize = DefaultMaxFileSize);
}
@@ -544,6 +544,8 @@ set(FILES
Serialization/Json/TupleSerializer.cpp
Serialization/Json/UnorderedSetSerializer.h
Serialization/Json/UnorderedSetSerializer.cpp
Serialization/Json/UnsupportedTypesSerializer.h
Serialization/Json/UnsupportedTypesSerializer.cpp
Serialization/std/VariantReflection.inl
Settings/CommandLine.cpp
Settings/CommandLine.h
+4
View File
@@ -21,11 +21,15 @@ namespace AZStd
using std::asin;
using std::atan;
using std::atan2;
using std::ceil;
using std::cos;
using std::exp2;
using std::floor;
using std::fmod;
using std::pow;
using std::round;
using std::sin;
using std::sqrt;
using std::tan;
using std::trunc;
} // namespace AZStd
@@ -101,7 +101,7 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
}
bool isApkFile = AZ::Android::Utils::IsApkPath(m_fileName);
bool isApkFile = AZ::Android::Utils::IsApkPath(m_fileName.c_str());
if (createPath)
{
@@ -111,19 +111,19 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
return false;
}
CreatePath(m_fileName);
CreatePath(m_fileName.c_str());
}
int errorCode = 0;
if (isApkFile)
{
AZ::u64 size = 0;
m_handle = AZ::Android::APKFileHandler::Open(m_fileName, openMode, size);
m_handle = AZ::Android::APKFileHandler::Open(m_fileName.c_str(), openMode, size);
errorCode = EACCES; // general error when a file can't be opened from inside the APK
}
else
{
m_handle = fopen(m_fileName, openMode);
m_handle = fopen(m_fileName.c_str(), openMode);
errorCode = errno;
}
@@ -233,7 +233,7 @@ namespace Platform
}
}
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
@@ -15,6 +15,9 @@
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <AzCore/std/typetraits/underlying_type.h>
namespace AZ
{
@@ -23,6 +26,7 @@ namespace AZ
namespace Internal
{
using SizeType = AZ::u64;
using SeekSizeType = AZ::s64;
using FileHandleType = FILE*;
}
@@ -37,7 +41,7 @@ namespace AZ
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
@@ -14,6 +14,9 @@
#include <sys/syslimits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <AzCore/std/typetraits/underlying_type.h>
namespace AZ
{
@@ -22,9 +25,10 @@ namespace AZ
namespace Internal
{
using SizeType = AZ::u64;
using SeekSizeType = AZ::s64;
using FileHandleType = int;
}
namespace PosixInternal
{
enum class OpenFlags : int
@@ -36,7 +40,7 @@ namespace AZ
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
@@ -13,6 +13,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <AzCore/std/typetraits/underlying_type.h>
namespace AZ
{
@@ -21,6 +24,7 @@ namespace AZ
namespace Internal
{
using SizeType = AZ::u64;
using SeekSizeType = AZ::s64;
using FileHandleType = int;
}
@@ -35,7 +39,7 @@ namespace AZ
#else
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
#endif
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
@@ -13,9 +13,10 @@
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
#include <dlfcn.h>
#include <libgen.h>
@@ -61,10 +62,11 @@ namespace AZ
// If it doesn't attempt to append the path to the executable path
if (!AZ::IO::SystemFile::Exists(fullFilePath.c_str()))
{
auto candidatePath = Platform::GetModulePath() / fullFilePath;
AZ::IO::FixedMaxPath candidatePath = Platform::GetModulePath() / fullFilePath;
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
{
fullFilePath = candidatePath;
m_fileName.assign(candidatePath.Native().c_str(), candidatePath.Native().size());
return;
}
}
@@ -74,19 +76,26 @@ namespace AZ
{
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
if(AZ::IO::FixedMaxPath projectModulePath;
if (AZ::IO::FixedMaxPath projectModulePath;
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
{
projectModulePath /= fullFilePath;
if (AZ::IO::SystemFile::Exists(projectModulePath.c_str()))
{
fullFilePath = projectModulePath;
m_fileName.assign(projectModulePath.c_str(), projectModulePath.Native().size());
}
}
}
}
m_fileName = AZStd::string_view{fullFilePath.Native()};
else
{
// The module does exist (in 'cwd'), but still needs to be an absolute path for the module to be loaded.
AZStd::optional<AZ::IO::FixedMaxPathString> absPathOptional = AZ::Utils::ConvertToAbsolutePath(m_fileName);
if (absPathOptional.has_value())
{
m_fileName.assign(absPathOptional->c_str(), absPathOptional->size());
}
}
}
~DynamicModuleHandleUnixLike() override
@@ -86,9 +86,9 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
if (createPath)
{
CreatePath(m_fileName);
CreatePath(m_fileName.c_str());
}
m_handle = open(m_fileName, desiredAccess, permissions);
m_handle = open(m_fileName.c_str(), desiredAccess, permissions);
if (m_handle == PlatformSpecificInvalidHandle)
{
@@ -119,7 +119,7 @@ namespace Platform
{
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
@@ -209,19 +209,19 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
if (createPath)
{
CreatePath(m_fileName);
CreatePath(m_fileName.c_str());
}
# ifdef _UNICODE
wchar_t fileNameW[AZ_MAX_PATH_LEN];
size_t numCharsConverted;
m_handle = INVALID_HANDLE_VALUE;
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName.c_str(), AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
{
m_handle = CreateFileW(fileNameW, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
}
# else //!_UNICODE
m_handle = CreateFile(m_fileName, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
m_handle = CreateFile(m_fileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
# endif // !_UNICODE
if (m_handle == INVALID_HANDLE_VALUE)
@@ -261,7 +261,7 @@ namespace Platform
{
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
{
if (handle != PlatformSpecificInvalidHandle)
{
@@ -13,6 +13,9 @@
#include <fcntl.h>
#include <corecrt_io.h>
#include <sys/stat.h>
#include <AzCore/std/typetraits/underlying_type.h>
namespace AZ
{
@@ -21,6 +24,7 @@ namespace AZ
namespace Internal
{
using SizeType = AZ::u64;
using SeekSizeType = AZ::s64;
using FileHandleType = void*;
}
@@ -31,7 +35,7 @@ namespace AZ
Append = _O_APPEND, // Moves the file pointer to the end of the file before every write operation.
Create = _O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
Temporary = _O_TEMPORARY, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
Exclusive = _O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Exclusive = _O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
Truncate = _O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
// Note: The TRUNC flag destroys the contents of the specified file.
@@ -24,9 +24,9 @@ namespace AZ
: public DynamicModuleHandle
{
public:
AZ_CLASS_ALLOCATOR(DynamicModuleHandleWindows, OSAllocator, 0)
AZ_CLASS_ALLOCATOR(DynamicModuleHandleWindows, OSAllocator, 0);
DynamicModuleHandleWindows(const char* fullFileName)
DynamicModuleHandleWindows(const char* fullFileName)
: DynamicModuleHandle(fullFileName)
, m_handle(nullptr)
{
@@ -52,6 +52,7 @@ namespace AZ
if (AZ::IO::SystemFile::Exists(candidatePath.c_str()))
{
m_fileName.assign(candidatePath.Native().c_str(), candidatePath.Native().size());
return;
}
}
}
@@ -65,7 +66,7 @@ namespace AZ
// Therefore an existence check is needed
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
if(AZ::IO::FixedMaxPath projectModulePath;
if (AZ::IO::FixedMaxPath projectModulePath;
settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath))
{
projectModulePath /= AZStd::string_view(m_fileName);
@@ -76,6 +77,15 @@ namespace AZ
}
}
}
else
{
// The module does exist (in 'cwd'), but still needs to be an absolute path for the module to be loaded.
AZStd::optional<AZ::IO::FixedMaxPathString> absPathOptional = AZ::Utils::ConvertToAbsolutePath(m_fileName);
if (absPathOptional.has_value())
{
m_fileName.assign(absPathOptional->c_str(), absPathOptional->size());
}
}
}
~DynamicModuleHandleWindows() override
@@ -13,5 +13,5 @@
namespace AZ
{
static const PlatformID g_currentPlatform = PlatformID::PLATFORM_APPLE_OSX;
static const PlatformID g_currentPlatform = PlatformID::PLATFORM_APPLE_MAC;
}
+8 -8
View File
@@ -1914,7 +1914,7 @@ namespace UnitTest
TEST_F(String, StringView_CompareIsConstexpr)
{
using TypeParam = char;
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
{
return "HelloWorld";
};
@@ -1922,7 +1922,7 @@ namespace UnitTest
{
return "HelloPearl";
};
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
constexpr basic_string_view<TypeParam> lhsView(compileTimeString1);
constexpr basic_string_view<TypeParam> rhsView(compileTimeString2);
@@ -1937,11 +1937,11 @@ namespace UnitTest
TEST_F(String, StringView_CompareOperatorsAreConstexpr)
{
using TypeParam = char;
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
auto TestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
{
return "HelloWorld";
};
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
constexpr const TypeParam* compileTimeString1 = TestMakeCompileTimeString1();
constexpr basic_string_view<TypeParam> compareView(compileTimeString1);
static_assert(compareView == "HelloWorld", "string_view operator== comparison has failed");
static_assert(compareView != "MadWorld", "string_view operator!= comparison has failed");
@@ -1955,7 +1955,7 @@ namespace UnitTest
{
auto swap_test_func = []() constexpr -> basic_string_view<TypeParam>
{
constexpr auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
constexpr auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
{
if constexpr (AZStd::is_same_v<TypeParam, char>)
{
@@ -1977,7 +1977,7 @@ namespace UnitTest
return L"InuWorld";
}
};
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
basic_string_view<TypeParam> lhsView(compileTimeString1);
basic_string_view<TypeParam> rhsView(compileTimeString2);
@@ -2001,7 +2001,7 @@ namespace UnitTest
TYPED_TEST(BasicStringViewConstexprFixture, HashString_FunctionIsConstexpr)
{
auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
{
if constexpr (AZStd::is_same_v<TypeParam, char>)
{
@@ -2012,7 +2012,7 @@ namespace UnitTest
return L"HelloWorld";
}
};
constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
constexpr basic_string_view<TypeParam> hashView(compileTimeString1);
constexpr size_t compileHash = AZStd::hash<basic_string_view<TypeParam>>{}(hashView);
static_assert(compileHash != 0, "Hash of \"HelloWorld\" should not be 0");
@@ -68,7 +68,7 @@ namespace AZ
return os
<< "translation: " << transform.GetTranslation()
<< " rotation: " << transform.GetRotation()
<< " scale: " << transform.GetScale();
<< " scale: " << transform.GetUniformScale();
}
std::ostream& operator<<(std::ostream& os, const Color& color)
+2 -1
View File
@@ -395,7 +395,8 @@ namespace UnitTest
}
else
{
int result1, result2;
int result1 = 0;
int result2 = 0;
Job* job1 = aznew FibonacciJob2(m_n - 1, &result1, m_context);
Job* job2 = aznew FibonacciJob2(m_n - 2, &result2, m_context);
StartAsChild(job1);
@@ -59,7 +59,7 @@ namespace UnitTest
TEST(MATH_Matrix4x4, TestCreateFrom)
{
float testFloats[] =
float thisTestFloats[] =
{
1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
@@ -67,20 +67,20 @@ namespace UnitTest
13.0f, 14.0f, 15.0f, 16.0f
};
float testFloatMtx[16];
Matrix4x4 m1 = Matrix4x4::CreateFromRowMajorFloat16(testFloats);
Matrix4x4 m1 = Matrix4x4::CreateFromRowMajorFloat16(thisTestFloats);
AZ_TEST_ASSERT(m1.GetRow(0) == Vector4(1.0f, 2.0f, 3.0f, 4.0f));
AZ_TEST_ASSERT(m1.GetRow(1) == Vector4(5.0f, 6.0f, 7.0f, 8.0f));
AZ_TEST_ASSERT(m1.GetRow(2) == Vector4(9.0f, 10.0f, 11.0f, 12.0f));
AZ_TEST_ASSERT(m1.GetRow(3) == Vector4(13.0f, 14.0f, 15.0f, 16.0f));
m1.StoreToRowMajorFloat16(testFloatMtx);
AZ_TEST_ASSERT(memcmp(testFloatMtx, testFloats, sizeof(testFloatMtx)) == 0);
m1 = Matrix4x4::CreateFromColumnMajorFloat16(testFloats);
AZ_TEST_ASSERT(memcmp(testFloatMtx, thisTestFloats, sizeof(testFloatMtx)) == 0);
m1 = Matrix4x4::CreateFromColumnMajorFloat16(thisTestFloats);
AZ_TEST_ASSERT(m1.GetRow(0) == Vector4(1.0f, 5.0f, 9.0f, 13.0f));
AZ_TEST_ASSERT(m1.GetRow(1) == Vector4(2.0f, 6.0f, 10.0f, 14.0f));
AZ_TEST_ASSERT(m1.GetRow(2) == Vector4(3.0f, 7.0f, 11.0f, 15.0f));
AZ_TEST_ASSERT(m1.GetRow(3) == Vector4(4.0f, 8.0f, 12.0f, 16.0f));
m1.StoreToColumnMajorFloat16(testFloatMtx);
AZ_TEST_ASSERT(memcmp(testFloatMtx, testFloats, sizeof(testFloatMtx)) == 0);
AZ_TEST_ASSERT(memcmp(testFloatMtx, thisTestFloats, sizeof(testFloatMtx)) == 0);
}
TEST(MATH_Matrix4x4, TestCreateFromMatrix3x4)
+12 -12
View File
@@ -119,10 +119,10 @@ namespace UnitTest
TEST(MATH_Obb, Contains)
{
const Vector3 position(1.0f, 2.0f, 3.0f);
const Quaternion rotation = Quaternion::CreateRotationZ(DegToRad(30.0f));
const Vector3 halfLengths(2.0f, 1.0f, 2.5f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
const Vector3 testPosition(1.0f, 2.0f, 3.0f);
const Quaternion testRotation = Quaternion::CreateRotationZ(DegToRad(30.0f));
const Vector3 testHalfLengths(2.0f, 1.0f, 2.5f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
// test some pairs of points which should be just either side of the Obb boundary
EXPECT_TRUE(obb.Contains(Vector3(1.35f, 3.35f, 3.5f)));
EXPECT_FALSE(obb.Contains(Vector3(1.35f, 3.4f, 3.5f)));
@@ -134,10 +134,10 @@ namespace UnitTest
TEST(MATH_Obb, GetDistance)
{
const Vector3 position(5.0f, 3.0f, 2.0f);
const Quaternion rotation = Quaternion::CreateRotationX(DegToRad(60.0f));
const Vector3 halfLengths(0.5f, 2.0f, 1.5f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
const Vector3 testPosition(5.0f, 3.0f, 2.0f);
const Quaternion testRotation = Quaternion::CreateRotationX(DegToRad(60.0f));
const Vector3 testHalfLengths(0.5f, 2.0f, 1.5f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
EXPECT_NEAR(obb.GetDistance(Vector3(5.3f, 3.2f, 1.8f)), 0.0f, 1e-3f);
EXPECT_NEAR(obb.GetDistance(Vector3(5.1f, 1.1f, 3.7f)), 0.9955f, 1e-3f);
EXPECT_NEAR(obb.GetDistance(Vector3(4.7f, 4.5f, 4.2f)), 0.6553f, 1e-3f);
@@ -146,10 +146,10 @@ namespace UnitTest
TEST(MATH_Obb, GetDistanceSq)
{
const Vector3 position(1.0f, 4.0f, 3.0f);
const Quaternion rotation = Quaternion::CreateRotationY(DegToRad(45.0f));
const Vector3 halfLengths(1.5f, 3.0f, 1.0f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
const Vector3 testPosition(1.0f, 4.0f, 3.0f);
const Quaternion testRotation = Quaternion::CreateRotationY(DegToRad(45.0f));
const Vector3 testHalfLengths(1.5f, 3.0f, 1.0f);
const Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(testPosition, testRotation, testHalfLengths);
EXPECT_NEAR(obb.GetDistanceSq(Vector3(1.1f, 4.3f, 2.7f)), 0.0f, 1e-3f);
EXPECT_NEAR(obb.GetDistanceSq(Vector3(-0.7f, 3.5f, 2.0f)), 0.8266f, 1e-3f);
EXPECT_NEAR(obb.GetDistanceSq(Vector3(2.4f, 0.5f, 1.5f)), 0.5532f, 1e-3f);
@@ -2010,6 +2010,28 @@ TEST_F(SerializeBasicTest, BasicTypeTest_Succeed)
}
/*
This test will dynamic cast (azrtti_cast) between incompatible types, which should always result in nullptr.
If this test fails, the RTTI declaration for the relevant type is incorrect.
*/
TEST_F(Serialization, AttributeRTTI)
{
{
AttributeInvocable<AZStd::function<AZStd::string(AZStd::string)>> fn([](AZStd::string x) { return x + x; });
Attribute* fnDownCast = &fn;
auto fnUpCast = azrtti_cast<AttributeInvocable<AZStd::function<int(int)>>*>(fnDownCast);
EXPECT_EQ(fnUpCast, nullptr);
}
{
AttributeFunction<AZStd::string(AZStd::string)> fn([](AZStd::string x) { return x + x; });
Attribute* fnDownCast = &fn;
auto fnUpCast = azrtti_cast<AttributeFunction<int(int)>*>(fnDownCast);
EXPECT_EQ(fnUpCast, nullptr);
}
}
/*
* Deprecation
*/
@@ -95,6 +95,20 @@ namespace JsonSerializationTests
}
};
class SerializerWithOneDuplicatedTypeWithOverride
: public JsonSerializerTemplatedMock<SerializerWithOneDuplicatedTypeWithOverride>
{
public:
AZ_RTTI(SerializerWithOneDuplicatedTypeWithOverride, "{4218D591-E578-499B-B578-ACA70C9944AB}", BaseJsonSerializer);
~SerializerWithOneDuplicatedTypeWithOverride() override = default;
static void Reflect(AZ::JsonRegistrationContext* context)
{
context->Serializer<SerializerWithOneDuplicatedTypeWithOverride>()
->HandlesType<bool>(true);
}
};
// Attempts to register the same type twice
class SerializerWithTwoSameTypes
: public JsonSerializerTemplatedMock<SerializerWithTwoSameTypes>
@@ -271,13 +285,29 @@ namespace JsonSerializationTests
EXPECT_EQ(1, m_jsonRegistrationContext->GetRegisteredSerializers().size());
AZ::BaseJsonSerializer* mockSerializer = m_jsonRegistrationContext->GetSerializerForType(azrtti_typeid<bool>());
EXPECT_NE(mockSerializer, nullptr);
ASSERT_NE(mockSerializer, nullptr);
EXPECT_EQ(AZ::AzTypeInfo<SerializerWithOneType>::Uuid(), mockSerializer->RTTI_GetType());
SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get());
SerializerWithOneDuplicatedType::Unreflect(m_jsonRegistrationContext.get());
}
TEST_F(JsonRegistrationContextTests, OverwriteRegisterSameUuidWithMultipleSerializers_Succeeds)
{
EXPECT_NE(AZ::AzTypeInfo<SerializerWithOneDuplicatedTypeWithOverride>::Uuid(), AZ::AzTypeInfo<SerializerWithOneType>::Uuid());
SerializerWithOneType::Reflect(m_jsonRegistrationContext.get());
SerializerWithOneDuplicatedTypeWithOverride::Reflect(m_jsonRegistrationContext.get());
EXPECT_EQ(1, m_jsonRegistrationContext->GetRegisteredSerializers().size());
AZ::BaseJsonSerializer* mockSerializer = m_jsonRegistrationContext->GetSerializerForType(azrtti_typeid<bool>());
ASSERT_NE(mockSerializer, nullptr);
EXPECT_EQ(AZ::AzTypeInfo<SerializerWithOneDuplicatedTypeWithOverride>::Uuid(), mockSerializer->RTTI_GetType());
SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get());
SerializerWithOneDuplicatedTypeWithOverride::Unreflect(m_jsonRegistrationContext.get());
}
TEST_F(JsonRegistrationContextTests, RegisterSameUuidWithSameSerializers_Fails)
{
AZ_TEST_START_ASSERTTEST;
@@ -44,7 +44,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr<AZ::Transform> CreateFullySetInstance() override
{
return AZStd::make_shared<AZ::Transform>(
AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), AZ::Vector3(9.0f));
AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), 9.0f);
}
AZStd::string_view GetJsonForFullySetInstance() override
@@ -95,7 +95,7 @@ namespace JsonSerializationTests
AZ::Transform expectedTransform(
AZ::Vector3(2.25f, 3.5f, 4.75f),
AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f),
AZ::Vector3(5.5f));
5.5f);
rapidjson::Document json;
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Rotation": [ 0.25, 0.5, 0.75, 1.0 ], "Scale": 5.5 })");
@@ -0,0 +1,142 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Serialization/Json/UnsupportedTypesSerializer.h>
#include <AzCore/std/any.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/containers/variant.h>
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
namespace JsonSerializationTests
{
struct AnyInfo
{
using Type = AZStd::any;
using Serializer = AZ::JsonAnySerializer;
};
struct VariantInfo
{
using Type = AZStd::variant<AZStd::monostate, int, double>;
using Serializer = AZ::JsonVariantSerializer;
};
struct OptionalInfo
{
using Type = AZStd::optional<int>;
using Serializer = AZ::JsonVariantSerializer;
};
template<typename Info>
class JsonUnsupportedTypesSerializerTests : public BaseJsonSerializerFixture
{
public:
using Type = typename Info::Type;
using Serializer = typename Info::Serializer;
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
this->m_serializer = AZStd::make_unique<Serializer>();
}
void TearDown() override
{
this->m_serializer.reset();
BaseJsonSerializerFixture::TearDown();
}
protected:
AZStd::unique_ptr<Serializer> m_serializer;
Type m_instance{};
};
using UnsupportedTypesTestTypes = ::testing::Types<AnyInfo, VariantInfo, OptionalInfo>;
TYPED_TEST_CASE(JsonUnsupportedTypesSerializerTests, UnsupportedTypesTestTypes);
TYPED_TEST(JsonUnsupportedTypesSerializerTests, Load_CallDirectly_ReportsIssueAndHalts)
{
namespace JSR = AZ::JsonSerializationResult;
bool hasMessage = false;
auto callback = [&hasMessage](AZStd::string_view message, JSR::ResultCode result, AZStd::string_view) -> JSR::ResultCode
{
hasMessage = !message.empty();
return result;
};
this->m_jsonDeserializationContext->PushReporter(AZStd::move(callback));
JSR::Result result = this->m_serializer->Load(
&this->m_instance, azrtti_typeid(this->m_instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext);
this->m_jsonDeserializationContext->PopReporter();
EXPECT_EQ(JSR::Processing::Halted, result.GetResultCode().GetProcessing());
EXPECT_TRUE(hasMessage);
}
TYPED_TEST(JsonUnsupportedTypesSerializerTests, Load_CallThroughFrontEnd_ReportsIssueAndHalts)
{
namespace JSR = AZ::JsonSerializationResult;
bool hasMessage = false;
auto callback = [&hasMessage](AZStd::string_view message, JSR::ResultCode result, AZStd::string_view) -> JSR::ResultCode
{
hasMessage = !message.empty();
return result;
};
this->m_deserializationSettings->m_reporting = AZStd::move(callback);
JSR::ResultCode result = AZ::JsonSerialization::Load(this->m_instance, *this->m_jsonDocument, *this->m_deserializationSettings);
EXPECT_EQ(JSR::Processing::Halted, result.GetProcessing());
EXPECT_TRUE(hasMessage);
}
TYPED_TEST(JsonUnsupportedTypesSerializerTests, Save_CallDirectly_ReportsIssueAndHalts)
{
namespace JSR = AZ::JsonSerializationResult;
bool hasMessage = false;
auto callback = [&hasMessage](AZStd::string_view message, JSR::ResultCode result, AZStd::string_view) -> JSR::ResultCode
{
hasMessage = !message.empty();
return result;
};
this->m_jsonSerializationContext->PushReporter(AZStd::move(callback));
JSR::Result result = this->m_serializer->Store(
*this->m_jsonDocument, &this->m_instance, nullptr, azrtti_typeid(this->m_instance), *this->m_jsonSerializationContext);
this->m_jsonSerializationContext->PopReporter();
EXPECT_EQ(JSR::Processing::Halted, result.GetResultCode().GetProcessing());
EXPECT_TRUE(hasMessage);
}
TYPED_TEST(JsonUnsupportedTypesSerializerTests, Save_CallThroughFrontEnd_ReportsIssueAndHalts)
{
namespace JSR = AZ::JsonSerializationResult;
bool hasMessage = false;
auto callback = [&hasMessage](AZStd::string_view message, JSR::ResultCode result, AZStd::string_view) -> JSR::ResultCode
{
hasMessage = !message.empty();
return result;
};
this->m_serializationSettings->m_reporting = AZStd::move(callback);
JSR::ResultCode result = AZ::JsonSerialization::Store(
*this->m_jsonDocument, this->m_jsonDocument->GetAllocator(), this->m_instance, *this->m_serializationSettings);
EXPECT_EQ(JSR::Processing::Halted, result.GetProcessing());
EXPECT_TRUE(hasMessage);
}
} // namespace JsonSerializationTests
@@ -372,15 +372,15 @@ mac_remote_filesystem=0
-- We need to know this before we establish VFS because different platform assets
-- are stored in different root folders in the cache. These correspond to the names
-- In the asset processor config file. This value also controls what config file is read
-- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_es3.cfg)
-- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_android.cfg)
-- by default, pc assets (in the 'pc' folder) are used, with RC being fed 'pc' as the platform
-- by default on console we use the default assets=pc for better iteration times
-- we should turn on console specific assets only when in release and/or testing assets and/or loading performance
-- that way most people will not need to have 3 different caches taking up disk space
assets = pc
android_assets = es3
android_assets = android
ios_assets = ios
mac_assets = osx_gl
mac_assets = mac
-- Add the IP address of your console to the white list that will connect to the asset processor here
-- You can list addresses or CIDR's. CIDR's are helpful if you are using DHCP. A CIDR looks like an ip address with
@@ -438,9 +438,9 @@ mac_wait_for_connect=0
ConfigFileParams::SettingsKeyValuePair{"/ios_remote_filesystem", AZ::s64{0}},
ConfigFileParams::SettingsKeyValuePair{"/mac_remote_filesystem", AZ::s64{0}},
ConfigFileParams::SettingsKeyValuePair{"/assets", AZStd::string_view{"pc"}},
ConfigFileParams::SettingsKeyValuePair{"/android_assets", AZStd::string_view{"es3"}},
ConfigFileParams::SettingsKeyValuePair{"/android_assets", AZStd::string_view{"android"}},
ConfigFileParams::SettingsKeyValuePair{"/ios_assets", AZStd::string_view{"ios"}},
ConfigFileParams::SettingsKeyValuePair{"/mac_assets", AZStd::string_view{"osx_gl"}},
ConfigFileParams::SettingsKeyValuePair{"/mac_assets", AZStd::string_view{"mac"}},
ConfigFileParams::SettingsKeyValuePair{"/connect_to_remote", AZ::s64{0}},
ConfigFileParams::SettingsKeyValuePair{"/windows_connect_to_remote", AZ::s64{1}},
ConfigFileParams::SettingsKeyValuePair{"/android_connect_to_remote", AZ::s64{0}},
@@ -478,20 +478,20 @@ test_asset_processor_tag = test_value
[Platform pc]
tags=tools,renderer,dx12,vulkan
[Platform es3]
[Platform android]
tags=android,mobile,renderer,vulkan ; With Comments at the end
[Platform ios]
tags=mobile,renderer,metal
[Platform osx_gl]
[Platform mac]
tags=tools,renderer,metal)"
, AZStd::fixed_vector<ConfigFileParams::SettingsKeyValuePair, 20>{
ConfigFileParams::SettingsKeyValuePair{"/test_asset_processor_tag", AZStd::string_view{"test_value"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform pc/tags", AZStd::string_view{"tools,renderer,dx12,vulkan"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform es3/tags", AZStd::string_view{"android,mobile,renderer,vulkan"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform android/tags", AZStd::string_view{"android,mobile,renderer,vulkan"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform ios/tags", AZStd::string_view{"mobile,renderer,metal"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform osx_gl/tags", AZStd::string_view{"tools,renderer,metal"}},
ConfigFileParams::SettingsKeyValuePair{"/Platform mac/tags", AZStd::string_view{"tools,renderer,metal"}},
}}
)
);
@@ -128,6 +128,7 @@ set(FILES
Serialization/Json/TransformSerializerTests.cpp
Serialization/Json/TupleSerializerTests.cpp
Serialization/Json/UnorderedSetSerializerTests.cpp
Serialization/Json/UnsupportedTypesSerializerTests.cpp
Serialization/Json/UuidSerializerTests.cpp
Math/AabbTests.cpp
Math/ColorTests.cpp
@@ -711,8 +711,8 @@ namespace AzFramework
}
}
AZ::IO::FixedMaxPath projectUserPath;
if (m_settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
if (AZ::IO::FixedMaxPath projectUserPath;
m_settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
{
fileIoBase->SetAlias("@user@", projectUserPath.c_str());
AZ::IO::FixedMaxPath projectLogPath = projectUserPath / "log";
@@ -721,6 +721,15 @@ namespace AzFramework
CreateUserCache(projectUserPath, *fileIoBase);
}
else
{
AZ::IO::FixedMaxPath fallbackLogPath = GetEngineRoot();
fallbackLogPath /= "user";
fileIoBase->SetAlias("@user@", fallbackLogPath.c_str());
fallbackLogPath /= "log";
fileIoBase->SetAlias("@log@", fallbackLogPath.c_str());
fileIoBase->CreatePath(fallbackLogPath.c_str());
}
}
}
@@ -1290,7 +1290,7 @@ namespace AZ::IO
//////////////////////////////////////////////////////////////////////////
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, [[maybe_unused]] uint32_t nPathFlags, bool bAllowUseFileSystem)
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, EFileSearchType searchType)
{
auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pDir);
if (!szFullPath)
@@ -1299,8 +1299,26 @@ namespace AZ::IO
return {};
}
bool bScanZips{};
bool bAllowUseFileSystem{};
switch (searchType)
{
case IArchive::eFileSearchType_AllowInZipsOnly:
bAllowUseFileSystem = false;
bScanZips = true;
break;
case IArchive::eFileSearchType_AllowOnDiskAndInZips:
bAllowUseFileSystem = true;
bScanZips = true;
break;
case IArchive::eFileSearchType_AllowOnDiskOnly:
bAllowUseFileSystem = true;
bScanZips = false;
break;
}
AZStd::intrusive_ptr<AZ::IO::FindData> pFindData = new AZ::IO::FindData();
pFindData->Scan(this, szFullPath->Native(), bAllowUseFileSystem);
pFindData->Scan(this, szFullPath->Native(), bAllowUseFileSystem, bScanZips);
return pFindData->Fetch();
}
@@ -1676,18 +1694,16 @@ namespace AZ::IO
return true;
}
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, 0, true); fileIterator)
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, IArchive::eFileSearchType_AllowOnDiskOnly); fileIterator)
{
AZStd::vector<AZStd::string> files;
do
{
if (AZStd::wildcard_match(pWildcardIn, fileIterator.m_filename))
{
AZStd::string foundFilename{ fileIterator.m_filename };
AZStd::to_lower(foundFilename.begin(), foundFilename.end());
files.emplace_back(AZStd::move(foundFilename));
}
} while (fileIterator = FindNext(fileIterator));
AZStd::string foundFilename{ fileIterator.m_filename };
AZStd::to_lower(foundFilename.begin(), foundFilename.end());
files.emplace_back(AZStd::move(foundFilename));
}
while (fileIterator = FindNext(fileIterator));
// Open files in alphabet order.
AZStd::sort(files.begin(), files.end());
@@ -2008,13 +2024,12 @@ namespace AZ::IO
// if no bind root is specified, compute one:
strBindRoot = !bindRoot.empty() ? bindRoot : szFullPath->ParentPath().Native();
// Check if archive file disk exist on disk or inside of pak.
bool bFileExists = IsFileExist(szFullPath->Native());
if (!bFileExists && (nFactoryFlags & ZipDir::CacheFactory::FLAGS_READ_ONLY))
// Check if archive file disk exist on disk.
const bool pakOnDisk = FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
if (!pakOnDisk && (nFactoryFlags & ZipDir::CacheFactory::FLAGS_READ_ONLY))
{
// Archive file not found.
AZ_TracePrintf("Archive", "Cannot open Archive file %s\n", szFullPath->c_str());
AZ_TracePrintf("Archive", "Archive file %s does not exist\n", szFullPath->c_str());
return nullptr;
}
@@ -2492,8 +2507,6 @@ namespace AZ::IO
void Archive::FindCompressionInfo(bool& found, AZ::IO::CompressionInfo& info, const AZStd::string_view filename)
{
constexpr uint32_t s_compressionTag = static_cast<uint32_t>('Z') << 24 | static_cast<uint32_t>('C') << 16 | static_cast<uint32_t>('R') << 8 | static_cast<uint32_t>('Y');
if (!found)
{
auto correctedFilename = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(filename);
@@ -2519,7 +2532,6 @@ namespace AZ::IO
found = true;
info.m_archiveFilename.InitFromRelativePath(archive->GetFilePath());
info.m_compressionTag.m_code = s_compressionTag;
info.m_offset = pFileData->GetFileDataOffset();
info.m_compressedSize = entry->desc.lSizeCompressed;
info.m_uncompressedSize = entry->desc.lSizeUncompressed;
@@ -2539,9 +2551,8 @@ namespace AZ::IO
break;
}
info.m_decompressor = [&s_compressionTag]([[maybe_unused]] const AZ::IO::CompressionInfo& info, const void* compressed, size_t compressedSize, void* uncompressed, size_t uncompressedBufferSize)->bool
info.m_decompressor = []([[maybe_unused]] const AZ::IO::CompressionInfo& info, const void* compressed, size_t compressedSize, void* uncompressed, size_t uncompressedBufferSize)->bool
{
AZ_Assert(info.m_compressionTag.m_code == s_compressionTag, "Provided compression info isn't supported by this decompressor.");
size_t nSizeUncompressed = uncompressedBufferSize;
return ZipDir::ZipRawUncompress(uncompressed, &nSizeUncompressed, compressed, compressedSize) == 0;
};
@@ -234,7 +234,7 @@ namespace AZ::IO
uint64_t FTell(AZ::IO::HandleType handle) override;
int FFlush(AZ::IO::HandleType handle) override;
int FClose(AZ::IO::HandleType handle) override;
AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, uint32_t nPathFlags = 0, bool bAllOwUseFileSystem = false) override;
AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) override;
AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override;
bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override;
int FEof(AZ::IO::HandleType handle) override;
@@ -50,6 +50,7 @@ namespace AZ::IO
, tWrite{ writeTime }
{
}
ArchiveFileIterator::ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc)
: m_findData{ findData }
, m_filename{ filename }
@@ -76,7 +77,7 @@ namespace AZ::IO
return m_findData && m_lastFetchValid;
}
void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS)
void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS, bool bScanZips)
{
// get the priority into local variable to avoid it changing in the course of
// this function execution
@@ -86,12 +87,18 @@ namespace AZ::IO
{
// first, find the file system files
ScanFS(archive, szDir);
ScanZips(archive, szDir);
if (bScanZips)
{
ScanZips(archive, szDir);
}
}
else
{
// first, find the zip files
ScanZips(archive, szDir);
if (bScanZips)
{
ScanZips(archive, szDir);
}
if (bAllowUseFS || nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly)
{
ScanFS(archive, szDir);
@@ -108,36 +115,33 @@ namespace AZ::IO
AZ::StringFunc::Path::GetFullPath(directory.c_str(), searchDirectory);
AZ::StringFunc::Path::GetFullFileName(directory.c_str(), pattern);
}
AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), [&](const char* filePath) -> bool
{
AZ::IO::FileDesc fileDesc;
AZStd::string fullFilePath;
AZ::StringFunc::Path::GetFullFileName(filePath, fullFilePath);
AZ::IO::ArchiveFileIterator fileIterator;
fileIterator.m_filename = AZ::IO::PathView(filePath).Filename().Native();
fileIterator.m_fileDesc.nAttrib = {};
if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath))
{
fileDesc.nAttrib = fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory;
fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory;
m_fileStack.emplace_back(AZStd::move(fileIterator));
}
else
{
if (AZ::IO::FileIOBase::GetDirectInstance()->IsReadOnly(filePath))
{
fileDesc.nAttrib = fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly;
fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly;
}
AZ::u64 fileSize = 0;
AZ::IO::FileIOBase::GetDirectInstance()->Size(filePath, fileSize);
fileDesc.nSize = fileSize;
fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath);
fileIterator.m_fileDesc.nSize = fileSize;
fileIterator.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath);
// These times are not supported by our file interface
fileDesc.tAccess = fileDesc.tWrite;
fileDesc.tCreate = fileDesc.tWrite;
fileIterator.m_fileDesc.tAccess = fileIterator.m_fileDesc.tWrite;
fileIterator.m_fileDesc.tCreate = fileIterator.m_fileDesc.tWrite;
m_fileStack.emplace_back(AZStd::move(fileIterator));
}
[[maybe_unused]] auto result = m_mapFiles.emplace(AZStd::move(fullFilePath), fileDesc);
AZ_Assert(result.second, "Failed to insert FindData entry for %s", fullFilePath.c_str());
return true;
});
}
@@ -167,7 +171,7 @@ namespace AZ::IO
fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive;
fileDesc.nSize = fileEntry->desc.lSizeUncompressed;
fileDesc.tWrite = fileEntry->GetModificationTime();
m_mapFiles.emplace(fname, fileDesc);
m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc });
}
ZipDir::FindDir findDirectoryEntry(zipCache);
@@ -180,7 +184,7 @@ namespace AZ::IO
}
AZ::IO::FileDesc fileDesc;
fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory;
m_mapFiles.emplace(fname, fileDesc);
m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc });
}
};
@@ -249,7 +253,7 @@ namespace AZ::IO
if (!bindRootIter->empty() && AZStd::wildcard_match(sourcePathRemainder.Native(), bindRootIter->Native()))
{
AZ::IO::FileDesc fileDesc{ AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory };
m_mapFiles.emplace(bindRootIter->Native(), fileDesc);
m_fileStack.emplace_back(AZ::IO::ArchiveFileIterator{ this, bindRootIter->Native(), fileDesc });
}
}
else
@@ -265,20 +269,19 @@ namespace AZ::IO
AZ::IO::ArchiveFileIterator FindData::Fetch()
{
AZ::IO::ArchiveFileIterator fileIterator;
fileIterator.m_findData = this;
if (m_mapFiles.empty())
if (m_fileStack.empty())
{
return fileIterator;
AZ::IO::ArchiveFileIterator emptyFileIterator;
emptyFileIterator.m_lastFetchValid = false;
emptyFileIterator.m_findData = this;
return emptyFileIterator;
}
auto pakFileIter = m_mapFiles.begin();
fileIterator.m_filename = pakFileIter->first;
fileIterator.m_fileDesc = pakFileIter->second;
fileIterator.m_lastFetchValid = true;
// Remove Fetched item from the FindData map so that the iteration continues
m_mapFiles.erase(pakFileIter);
AZ::IO::ArchiveFileIterator fileIterator{ m_fileStack.back() };
fileIterator.m_lastFetchValid = true;
fileIterator.m_findData = this;
m_fileStack.pop_back();
return fileIterator;
}
}
@@ -15,7 +15,6 @@
#include <AzCore/std/smart_ptr/intrusive_base.h>
#include <AzCore/std/string/fixed_string.h>
namespace AZ::IO
{
struct IArchive;
@@ -74,13 +73,13 @@ namespace AZ::IO
AZ_CLASS_ALLOCATOR(FindData, AZ::SystemAllocator, 0);
FindData() = default;
AZ::IO::ArchiveFileIterator Fetch();
void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false);
void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false, bool bScanZips = true);
protected:
void ScanFS(IArchive* archive, AZStd::string_view path);
void ScanZips(IArchive* archive, AZStd::string_view path);
using FileMap = AZStd::map<AZStd::string, AZ::IO::FileDesc, AZStdStringLessCaseInsensitive>;
FileMap m_mapFiles;
using FileStack = AZStd::vector<ArchiveFileIterator>;
FileStack m_fileStack;
};
}
@@ -197,6 +197,13 @@ namespace AZ::IO
eInMemoryPakLocale_PAK,
};
enum EFileSearchType
{
eFileSearchType_AllowInZipsOnly = 0,
eFileSearchType_AllowOnDiskAndInZips,
eFileSearchType_AllowOnDiskOnly
};
using SignedFileSize = int64_t;
virtual ~IArchive() = default;
@@ -315,7 +322,7 @@ namespace AZ::IO
// Arguments:
// nFlags is a combination of EPathResolutionRules flags.
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, uint32_t nFlags = 0, bool bAllowUseFileSystem = false) = 0;
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0;
virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0;
virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0;
//returns file modification time
@@ -308,6 +308,56 @@ namespace AzFramework
}
}
//---------------------------------------------------------------------
GenerateRelativeSourcePathRequest::GenerateRelativeSourcePathRequest(const AZ::OSString& sourcePath)
{
AZ_Assert(!sourcePath.empty(), "GenerateRelativeSourcePathRequest: asset path is empty");
m_sourcePath = sourcePath;
}
unsigned int GenerateRelativeSourcePathRequest::GetMessageType() const
{
return MessageType;
}
void GenerateRelativeSourcePathRequest::Reflect(AZ::ReflectContext* context)
{
auto serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<GenerateRelativeSourcePathRequest, BaseAssetProcessorMessage>()
->Version(1)
->Field("SourcePath", &GenerateRelativeSourcePathRequest::m_sourcePath);
}
}
//---------------------------------------------------------------------
GenerateRelativeSourcePathResponse::GenerateRelativeSourcePathResponse(
bool resolved, const AZ::OSString& relativeSourcePath, const AZ::OSString& rootFolder)
{
m_relativeSourcePath = relativeSourcePath;
m_resolved = resolved;
m_rootFolder = rootFolder;
}
unsigned int GenerateRelativeSourcePathResponse::GetMessageType() const
{
return GenerateRelativeSourcePathRequest::MessageType;
}
void GenerateRelativeSourcePathResponse::Reflect(AZ::ReflectContext* context)
{
auto serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<GenerateRelativeSourcePathResponse, BaseAssetProcessorMessage>()
->Version(1)
->Field("RelativeSourcePath", &GenerateRelativeSourcePathResponse::m_relativeSourcePath)
->Field("RootFolder", &GenerateRelativeSourcePathResponse::m_rootFolder)
->Field("Resolved", &GenerateRelativeSourcePathResponse::m_resolved);
}
}
//---------------------------------------------------------------------
GetFullSourcePathFromRelativeProductPathRequest::GetFullSourcePathFromRelativeProductPathRequest(const AZ::OSString& relativeProductPath)
{
@@ -166,7 +166,7 @@ namespace AzFramework
{
public:
AZ_CLASS_ALLOCATOR(RequestEscalateAsset, AZ::OSAllocator, 0);
AZ_RTTI(RequestAssetStatus, "{E95C5422-5F00-478B-A984-C041DE70484F}", BaseAssetProcessorMessage);
AZ_RTTI(RequestEscalateAsset, "{E95C5422-5F00-478B-A984-C041DE70484F}", BaseAssetProcessorMessage);
static void Reflect(AZ::ReflectContext* context);
static constexpr unsigned int MessageType = AZ_CRC("AssetSystem::RequestEscalateAsset", 0x1894d94e);
@@ -288,6 +288,45 @@ namespace AzFramework
bool m_resolved;
};
//////////////////////////////////////////////////////////////////////////
class GenerateRelativeSourcePathRequest : public BaseAssetProcessorMessage
{
public:
AZ_CLASS_ALLOCATOR(GenerateRelativeSourcePathRequest, AZ::OSAllocator, 0);
AZ_RTTI(GenerateRelativeSourcePathRequest, "{B3865033-F5A3-4749-8147-7B1AB04D5F6D}",
BaseAssetProcessorMessage);
static void Reflect(AZ::ReflectContext* context);
// For people that are debugging the network messages and just see MessageType as a value,
// the CRC value below is 739777771 (0x2C181CEB)
static constexpr unsigned int MessageType =
AZ_CRC_CE("AssetSystem::GenerateRelativeSourcePathRequest");
GenerateRelativeSourcePathRequest() = default;
GenerateRelativeSourcePathRequest(const AZ::OSString& sourcePath);
unsigned int GetMessageType() const override;
AZ::OSString m_sourcePath;
};
class GenerateRelativeSourcePathResponse : public BaseAssetProcessorMessage
{
public:
AZ_CLASS_ALLOCATOR(GenerateRelativeSourcePathResponse, AZ::OSAllocator, 0);
AZ_RTTI(GenerateRelativeSourcePathResponse, "{938D33DB-C8F6-4FA4-BC81-2F139A9BE1D7}",
BaseAssetProcessorMessage);
static void Reflect(AZ::ReflectContext* context);
GenerateRelativeSourcePathResponse() = default;
GenerateRelativeSourcePathResponse(
bool resolved, const AZ::OSString& relativeSourcePath, const AZ::OSString& rootFolder);
unsigned int GetMessageType() const override;
AZ::OSString m_relativeSourcePath;
AZ::OSString m_rootFolder; ///< This is the folder it was found in (the watched/scanned folder, such as gems /assets/ folder)
bool m_resolved;
};
//////////////////////////////////////////////////////////////////////////
class GetFullSourcePathFromRelativeProductPathRequest
: public BaseAssetProcessorMessage
@@ -202,6 +202,7 @@ namespace AzFramework
// Requests
GetUnresolvedDependencyCountsRequest::Reflect(context);
GetRelativeProductPathFromFullSourceOrProductPathRequest::Reflect(context);
GenerateRelativeSourcePathRequest::Reflect(context);
GetFullSourcePathFromRelativeProductPathRequest::Reflect(context);
SourceAssetInfoRequest::Reflect(context);
AssetInfoRequest::Reflect(context);
@@ -234,6 +235,7 @@ namespace AzFramework
// Responses
GetUnresolvedDependencyCountsResponse::Reflect(context);
GetRelativeProductPathFromFullSourceOrProductPathResponse::Reflect(context);
GenerateRelativeSourcePathResponse::Reflect(context);
GetFullSourcePathFromRelativeProductPathResponse::Reflect(context);
SourceAssetInfoResponse::Reflect(context);
AssetInfoResponse::Reflect(context);
@@ -1,22 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzFramework
{
@@ -64,15 +64,13 @@ namespace AzFramework
the EditContext. TController can friend itself to the editor component to make this work if required.
*/
template<typename TController, typename TConfiguration = AZ::ComponentConfig>
class ComponentAdapter
: public AZ::Component
class ComponentAdapter : public AZ::Component
{
public:
AZ_RTTI((ComponentAdapter, "{644A9187-4FDB-42C1-9D59-DD75304B551A}", TController, TConfiguration), AZ::Component);
ComponentAdapter() = default;
ComponentAdapter(const TConfiguration& configuration);
explicit ComponentAdapter(const TConfiguration& configuration);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
@@ -85,7 +83,6 @@ namespace AzFramework
void Deactivate() override;
protected:
static void Reflect(AZ::ReflectContext* context);
// AZ::Component overrides ...
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Components/ComponentAdapterHelpers.h>
@@ -32,10 +32,12 @@ namespace AzFramework
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
// clang-format off
serializeContext->Class<ComponentAdapter, Component>()
->Version(1)
->Field("Controller", &ComponentAdapter::m_controller)
;
// clang-format on
}
}
@@ -66,9 +68,6 @@ namespace AzFramework
GetDependentServicesHelper<TController>(services, typename AZ::HasComponentDependentServices<TController>::type());
}
//////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
template<typename TController, typename TConfiguration>
void ComponentAdapter<TController, TConfiguration>::Init()
{
@@ -78,7 +77,7 @@ namespace AzFramework
template<typename TController, typename TConfiguration>
void ComponentAdapter<TController, TConfiguration>::Activate()
{
m_controller.Activate(GetEntityId());
ComponentActivateHelper<TController>::Activate(m_controller, AZ::EntityComponentIdPair(GetEntityId(), GetId()));
}
template<typename TController, typename TConfiguration>
@@ -13,6 +13,7 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Component/EntityBus.h>
namespace AzFramework
{
@@ -27,18 +28,43 @@ namespace AzFramework
template<typename T, typename = void>
struct ComponentInitHelper
{
static void Init(T& common)
static void Init([[maybe_unused]] T& controller)
{
AZ_UNUSED(common);
}
};
template<typename T>
struct ComponentInitHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Init())>>
{
static void Init(T& common)
static void Init(T& controller)
{
common.Init();
controller.Init();
}
};
template<typename T, typename = void>
struct ComponentActivateHelper
{
static void Activate([[maybe_unused]] T& controller, [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair)
{
}
};
template<typename T>
struct ComponentActivateHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Activate(AZ::EntityId()))>>
{
static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair)
{
controller.Activate(entityComponentIdPair.GetEntityId());
}
};
template<typename T>
struct ComponentActivateHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Activate(AZ::EntityComponentIdPair()))>>
{
static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair)
{
controller.Activate(entityComponentIdPair);
}
};
@@ -327,99 +327,13 @@ namespace AzFramework
return localZ;
}
void TransformComponent::SetRotation(const AZ::Vector3& eulerAnglesRadian)
void TransformComponent::SetWorldRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ_Warning("TransformComponent", false, "SetRotation is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::ConvertEulerRadiansToQuaternion(eulerAnglesRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ_Warning("TransformComponent", false, "SetRotationQuaternion is deprecated, please use SetLocalRotationQuaternion");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(quaternion);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationX(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationX is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationX(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationY(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationY is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationY(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationZ(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationZ is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationZ(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::RotateByX(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByX is deprecated, please use RotateAroundLocalX");
RotateAroundLocalX(eulerAngleRadian);
}
void TransformComponent::RotateByY(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByY is deprecated, please use RotateAroundLocalY");
RotateAroundLocalY(eulerAngleRadian);
}
void TransformComponent::RotateByZ(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByZ is deprecated, please use RotateAroundLocalZ");
RotateAroundLocalZ(eulerAngleRadian);
}
AZ::Vector3 TransformComponent::GetRotationEulerRadians()
{
AZ_Warning("TransformComponent", false, "GetRotationEulerRadians is deprecated, please use GetWorldRotation");
return m_worldTM.GetRotation().GetEulerRadians();
}
AZ::Quaternion TransformComponent::GetRotationQuaternion()
{
AZ_Warning("TransformComponent", false, "GetRotationQuaternion is deprecated, please use GetWorldRotationQuaternion");
return m_worldTM.GetRotation();
}
float TransformComponent::GetRotationX()
{
AZ_Warning("TransformComponent", false, "GetRotationX is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetX();
}
float TransformComponent::GetRotationY()
{
AZ_Warning("TransformComponent", false, "GetRotationY is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetY();
}
float TransformComponent::GetRotationZ()
{
AZ_Warning("TransformComponent", false, "GetRotationZ is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetZ();
}
AZ::Vector3 TransformComponent::GetWorldRotation()
{
return m_worldTM.GetRotation().GetEulerRadians();
@@ -492,21 +406,10 @@ namespace AzFramework
return m_localTM.GetRotation();
}
void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
{
AZ::Transform newLocalTM = m_localTM;
newLocalTM.SetScale(scale);
SetLocalTM(newLocalTM);
}
AZ::Vector3 TransformComponent::GetLocalScale()
{
return m_localTM.GetScale();
}
AZ::Vector3 TransformComponent::GetWorldScale()
{
return m_worldTM.GetScale();
AZ_WarningOnce("TransformComponent", false, "GetLocalScale is deprecated, please use GetLocalUniformScale instead");
return AZ::Vector3(m_localTM.GetUniformScale());
}
void TransformComponent::SetLocalUniformScale(float scale)
@@ -830,45 +733,7 @@ namespace AzFramework
->Event("GetLocalX", &AZ::TransformBus::Events::GetLocalX)
->Event("GetLocalY", &AZ::TransformBus::Events::GetLocalY)
->Event("GetLocalZ", &AZ::TransformBus::Events::GetLocalZ)
->Event("RotateByX", &AZ::TransformBus::Events::RotateByX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("RotateByY", &AZ::TransformBus::Events::RotateByY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("RotateByZ", &AZ::TransformBus::Events::RotateByZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetEulerRotation", &AZ::TransformBus::Events::SetRotation)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationQuaternion", &AZ::TransformBus::Events::SetRotationQuaternion)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationX", &AZ::TransformBus::Events::SetRotationX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationY", &AZ::TransformBus::Events::SetRotationY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationZ", &AZ::TransformBus::Events::SetRotationZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetEulerRotation", &AZ::TransformBus::Events::GetRotationEulerRadians)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationQuaternion", &AZ::TransformBus::Events::GetRotationQuaternion)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationX", &AZ::TransformBus::Events::GetRotationX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationY", &AZ::TransformBus::Events::GetRotationY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationZ", &AZ::TransformBus::Events::GetRotationZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetWorldRotationQuaternion", &AZ::TransformBus::Events::SetWorldRotationQuaternion)
->Event("GetWorldRotation", &AZ::TransformBus::Events::GetWorldRotation)
->Event("GetWorldRotationQuaternion", &AZ::TransformBus::Events::GetWorldRotationQuaternion)
->Event("SetLocalRotation", &AZ::TransformBus::Events::SetLocalRotation)
@@ -880,11 +745,11 @@ namespace AzFramework
->Event("GetLocalRotationQuaternion", &AZ::TransformBus::Events::GetLocalRotationQuaternion)
->Attribute("Rotation", AZ::Edit::Attributes::PropertyRotation)
->VirtualProperty("Rotation", "GetLocalRotationQuaternion", "SetLocalRotationQuaternion")
->Event("SetLocalScale", &AZ::TransformBus::Events::SetLocalScale)
->Event("GetLocalScale", &AZ::TransformBus::Events::GetLocalScale)
->Attribute("Scale", AZ::Edit::Attributes::PropertyScale)
->VirtualProperty("Scale", "GetLocalScale", "SetLocalScale")
->Event("GetWorldScale", &AZ::TransformBus::Events::GetWorldScale)
->Event("SetLocalUniformScale", &AZ::TransformBus::Events::SetLocalUniformScale)
->Event("GetLocalUniformScale", &AZ::TransformBus::Events::GetLocalUniformScale)
->VirtualProperty("Uniform Scale", "GetLocalUniformScale", "SetLocalUniformScale")
->Event("GetChildren", &AZ::TransformBus::Events::GetChildren)
->Event("GetAllDescendants", &AZ::TransformBus::Events::GetAllDescendants)
->Event("GetEntityAndAllDescendants", &AZ::TransformBus::Events::GetEntityAndAllDescendants)

Some files were not shown because too many files have changed in this diff Show More