Merging last dev

Signed-off-by: Gene Walters <genewalt@amazon.com>
This commit is contained in:
Gene Walters
2021-11-19 23:12:59 -08:00
2657 changed files with 249197 additions and 30535 deletions
@@ -67,12 +67,6 @@ namespace AzFramework
/// Make path relative to the provided root.
virtual void MakePathRelative(AZStd::string& /*fullPath*/, const char* /*rootPath*/) {}
/// Gets the engine root path where the modules for the current engine are located.
virtual const char* GetEngineRoot() const { return nullptr; }
/// Retrieves the app root path for the application.
virtual const char* GetAppRoot() const { return nullptr; }
/// Get the Command Line arguments passed in.
virtual const CommandLine* GetCommandLine() { return nullptr; }
@@ -69,6 +69,7 @@
#include <AzCore/Console/Console.h>
#include <AzFramework/Viewport/ViewportBus.h>
#include <GridMate/Memory.h>
#include <AzFramework/Physics/HeightfieldProviderBus.h>
#include "Application.h"
#include <AzFramework/AzFrameworkModule.h>
@@ -224,13 +225,6 @@ namespace AzFramework
}
}
void Application::PreModuleLoad()
{
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
}
void Application::Stop()
{
if (m_isStarted)
@@ -318,6 +312,8 @@ namespace AzFramework
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
AzFramework::Terrain::TerrainDataRequests::Reflect(context);
Physics::HeightfieldProviderRequests::Reflect(context);
Physics::HeightMaterialPoint::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
@@ -394,11 +390,6 @@ namespace AzFramework
outModules.emplace_back(aznew AzFrameworkModule());
}
const char* Application::GetAppRoot() const
{
return m_appRoot.c_str();
}
const char* Application::GetCurrentConfigurationName() const
{
#if defined(_RELEASE)
@@ -434,19 +425,19 @@ namespace AzFramework
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
{
AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
auto fullPath = AZ::IO::FixedMaxPath(GetEngineRoot()) / engineRelativePath;
engineRelativePath = fullPath.String();
}
void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const
{
AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token);
AZ::StringFunc::AssetPath::CalculateBranchToken(GetEngineRoot(), token);
}
////////////////////////////////////////////////////////////////////////////
void Application::MakePathRootRelative(AZStd::string& fullPath)
{
MakePathRelative(fullPath, m_engineRoot.c_str());
MakePathRelative(fullPath, GetEngineRoot());
}
////////////////////////////////////////////////////////////////////////////
@@ -562,11 +553,9 @@ namespace AzFramework
////////////////////////////////////////////////////////////////////////////
AZ_CVAR(float, t_frameTimeOverride, 0.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "If > 0, overrides the application delta frame-time with the provided value");
void Application::Tick(float deltaOverride /*= -1.f*/)
void Application::Tick()
{
ComponentApplication::Tick((t_frameTimeOverride > 0.0f) ? t_frameTimeOverride : deltaOverride);
ComponentApplication::Tick();
}
////////////////////////////////////////////////////////////////////////////
@@ -582,30 +571,6 @@ namespace AzFramework
}
}
void Application::SetRootPath(RootPathType type, const char* source)
{
[[maybe_unused]] const size_t sourceLen = strlen(source);
// Copy the source path to the intended root path and correct the path separators as well
switch (type)
{
case RootPathType::AppRoot:
{
AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source);
m_appRoot = AZ::IO::PathView(source).LexicallyNormal();
}
break;
case RootPathType::EngineRoot:
{
AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source);
m_engineRoot = AZ::IO::PathView(source).LexicallyNormal();
}
break;
default:
AZ_Assert(false, "Invalid RootPathType (%d)", static_cast<int>(type));
}
}
struct DeprecatedAliasesKeyVisitor
: AZ::SettingsRegistryInterface::Visitor
{
@@ -87,7 +87,7 @@ namespace AzFramework
*/
virtual void Stop();
void Tick(float deltaOverride = -1.f) override;
void Tick() override;
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
@@ -95,8 +95,6 @@ namespace AzFramework
//////////////////////////////////////////////////////////////////////////
//! ApplicationRequests::Bus::Handler
const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
const char* GetAppRoot() const override;
void ResolveEnginePath(AZStd::string& engineRelativePath) const override;
void CalculateBranchTokenForEngineRoot(AZStd::string& token) const override;
bool IsPrefabSystemEnabled() const override;
@@ -146,8 +144,6 @@ namespace AzFramework
*/
void SetFileIOAliases();
void PreModuleLoad() override;
//////////////////////////////////////////////////////////////////////////
//! AZ::ComponentApplication
void RegisterCoreComponents() override;
@@ -181,13 +177,7 @@ namespace AzFramework
bool m_ownsConsole = false;
bool m_exitMainLoopRequested = false;
enum class RootPathType
{
AppRoot,
EngineRoot
};
void SetRootPath(RootPathType type, const char* source);
};
} // namespace AzFramework
@@ -34,7 +34,6 @@
#include <AzFramework/Archive/Archive.h>
#include <AzFramework/Archive/NestedArchive.h>
#include <AzFramework/Archive/ArchiveBus.h>
#include <AzFramework/Archive/ArchiveVars.h>
#include <AzFramework/Archive/MissingFileReport.h>
#include <AzFramework/Archive/ZipDirFind.h>
#include <AzFramework/Archive/ZipDirCacheFactory.h>
@@ -43,8 +42,10 @@
namespace AZ::IO
{
AZ_CVAR(int, sys_PakPriority, aznumeric_cast<int>(ArchiveVars{}.nPriority), nullptr, AZ::ConsoleFunctorFlags::Null,
"If set to 1, tells Archive to try to open the file in pak first, then go to file system");
AZ_CVAR(int, sys_PakPriority, aznumeric_cast<int>(ArchiveVars{}.m_fileSearchPriority), nullptr, AZ::ConsoleFunctorFlags::Null,
"If set to 0, tells Archive to try to open the file on the file system first othewise check mounted paks.\n"
"If set to 1, tells Archive to try to open the file in pak first, then go to file system.\n"
"If set to 2, tells the Archive to only open files from the pak");
AZ_CVAR(int, sys_PakMessageInvalidFileAccess, ArchiveVars{}.nMessageInvalidFileAccess, nullptr, AZ::ConsoleFunctorFlags::Null,
"Message Box synchronous file access when in game");
@@ -437,9 +438,9 @@ namespace AZ::IO
//////////////////////////////////////////////////////////////////////////
bool Archive::IsFileExist(AZStd::string_view sFilename, EFileSearchLocation fileLocation)
bool Archive::IsFileExist(AZStd::string_view sFilename, FileSearchLocation fileLocation)
{
const AZ::IO::ArchiveLocationPriority nVarPakPriority = GetPakPriority();
const AZ::IO::FileSearchPriority nVarPakPriority = GetPakPriority();
auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(sFilename);
if (!szFullPath)
@@ -450,25 +451,25 @@ namespace AZ::IO
switch(fileLocation)
{
case IArchive::eFileLocation_Any:
case FileSearchLocation::Any:
// Search for file based on pak priority
switch (nVarPakPriority)
{
case ArchiveLocationPriority::ePakPriorityFileFirst:
case FileSearchPriority::FileFirst:
return FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str()) || FindPakFileEntry(szFullPath->Native());
case ArchiveLocationPriority::ePakPriorityPakFirst:
case FileSearchPriority::PakFirst:
return FindPakFileEntry(szFullPath->Native()) || IO::FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
case ArchiveLocationPriority::ePakPriorityPakOnly:
case FileSearchPriority::PakOnly:
return FindPakFileEntry(szFullPath->Native());
default:
AZ_Assert(false, "PakPriority %d doesn't match a value in the ArchiveLocationPriority enum",
AZ_Assert(false, "PakPriority %d doesn't match a value in the FileSearchPriority enum",
aznumeric_cast<int>(nVarPakPriority));
}
break;
case IArchive::eFileLocation_InPak:
case FileSearchLocation::InPak:
return FindPakFileEntry(szFullPath->Native());
case IArchive::eFileLocation_OnDisk:
if (nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly)
case FileSearchLocation::OnDisk:
if (nVarPakPriority != FileSearchPriority::PakOnly)
{
return FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
}
@@ -485,7 +486,7 @@ namespace AZ::IO
//////////////////////////////////////////////////////////////////////////
bool Archive::IsFolder(AZStd::string_view sPath)
{
AZStd::fixed_string<AZ::IO::MaxPathLength > filePath{ sPath };
AZ::IO::FixedMaxPath filePath{ sPath };
return AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath.c_str());
}
@@ -515,7 +516,7 @@ namespace AZ::IO
// get the priority into local variable to avoid it changing in the course of
// this function execution (?)
const ArchiveLocationPriority nVarPakPriority = GetPakPriority();
const FileSearchPriority nVarPakPriority = GetPakPriority();
AZ::IO::OpenMode nOSFlags = AZ::IO::GetOpenModeFromStringMode(szMode);
@@ -628,17 +629,17 @@ namespace AZ::IO
switch (nVarPakPriority)
{
case ArchiveLocationPriority::ePakPriorityFileFirst:
case FileSearchPriority::FileFirst:
{
AZ::IO::HandleType fileHandle = OpenFromFileSystem();
return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromArchive();
}
case ArchiveLocationPriority::ePakPriorityPakFirst:
case FileSearchPriority::PakFirst:
{
AZ::IO::HandleType fileHandle = OpenFromArchive();
return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromFileSystem();
}
case ArchiveLocationPriority::ePakPriorityPakOnly:
case FileSearchPriority::PakOnly:
{
return OpenFromArchive();
}
@@ -810,7 +811,7 @@ namespace AZ::IO
return 0;
}
if (GetPakPriority() == ArchiveLocationPriority::ePakPriorityFileFirst) // if the file system files have priority now..
if (GetPakPriority() == FileSearchPriority::FileFirst) // if the file system files have priority now..
{
IArchive::SignedFileSize nFileSize = GetFileSizeOnDisk(fullPath->Native());
if (nFileSize != IArchive::FILE_NOT_PRESENT)
@@ -825,7 +826,7 @@ namespace AZ::IO
return pFileEntry->desc.lSizeUncompressed;
}
if (bAllowUseFileSystem || GetPakPriority() == ArchiveLocationPriority::ePakPriorityPakFirst) // if the archive files had more priority, we didn't attempt fopen before- try it now
if (bAllowUseFileSystem || GetPakPriority() == FileSearchPriority::PakFirst) // if the archive files had more priority, we didn't attempt fopen before- try it now
{
IArchive::SignedFileSize nFileSize = GetFileSizeOnDisk(fullPath->Native());
if (nFileSize != IArchive::FILE_NOT_PRESENT)
@@ -1023,7 +1024,7 @@ namespace AZ::IO
//////////////////////////////////////////////////////////////////////////
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, EFileSearchType searchType)
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, FileSearchLocation searchType)
{
auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pDir);
if (!szFullPath)
@@ -1036,18 +1037,21 @@ namespace AZ::IO
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;
case FileSearchLocation::InPak:
bAllowUseFileSystem = false;
bScanZips = true;
break;
case FileSearchLocation::Any:
bAllowUseFileSystem = true;
bScanZips = true;
break;
case FileSearchLocation::OnDisk:
bAllowUseFileSystem = true;
bScanZips = false;
break;
default:
AZ_Assert(false, "Invalid search location value supplied");
break;
}
AZStd::intrusive_ptr pFindData = aznew AZ::IO::FindData();
@@ -1218,7 +1222,7 @@ namespace AZ::IO
else
{
// [LYN-2376] Remove once legacy slice support is removed
AZStd::vector<AZStd::string> levelDirs;
AZStd::vector<AZ::IO::Path> levelDirs;
if (addLevels)
{
@@ -1241,6 +1245,10 @@ namespace AZ::IO
m_arrZips.insert(revItZip.base(), desc);
// This lock is for m_arrZips.
// Unlock it now because the modification is complete, and events responding to this signal
// will attempt to lock the same mutex, causing the application to lock up.
lock.unlock();
m_levelOpenEvent.Signal(levelDirs);
}
@@ -1376,7 +1384,7 @@ namespace AZ::IO
return true;
}
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, IArchive::eFileSearchType_AllowOnDiskOnly); fileIterator)
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, FileSearchLocation::OnDisk); fileIterator)
{
AZStd::vector<AZ::IO::FixedMaxPath> files;
do
@@ -1951,15 +1959,15 @@ namespace AZ::IO
}
// gets the current archive priority
ArchiveLocationPriority Archive::GetPakPriority() const
FileSearchPriority Archive::GetPakPriority() const
{
int pakPriority = aznumeric_cast<int>(ArchiveVars{}.nPriority);
FileSearchPriority pakPriority = ArchiveVars{}.m_fileSearchPriority;
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
{
[[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sys_PakPriority", pakPriority);
[[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sys_PakPriority", reinterpret_cast<int&>(pakPriority));
AZ_Error("Archive", getCvarResult == AZ::GetValueResult::Success, "Lookup of 'sys_PakPriority console variable failed with error %s", AZ::GetEnumString(getCvarResult));
}
return static_cast<ArchiveLocationPriority>(pakPriority);
return pakPriority;
}
//////////////////////////////////////////////////////////////////////////
@@ -2026,13 +2034,13 @@ namespace AZ::IO
switch (GetPakPriority())
{
case ArchiveLocationPriority::ePakPriorityFileFirst:
case FileSearchPriority::FileFirst:
info.m_conflictResolution = AZ::IO::ConflictResolution::PreferFile;
break;
case ArchiveLocationPriority::ePakPriorityPakFirst:
case FileSearchPriority::PakFirst:
info.m_conflictResolution = AZ::IO::ConflictResolution::PreferArchive;
break;
case ArchiveLocationPriority::ePakPriorityPakOnly:
case FileSearchPriority::PakOnly:
info.m_conflictResolution = AZ::IO::ConflictResolution::UseArchiveOnly;
break;
}
@@ -2143,13 +2151,13 @@ namespace AZ::IO
return manifestInfo;
}
AZStd::vector<AZStd::string> Archive::ScanForLevels(ZipDir::CachePtr pZip)
AZStd::vector<AZ::IO::Path> Archive::ScanForLevels(ZipDir::CachePtr pZip)
{
AZStd::queue<AZStd::string> scanDirs;
AZStd::vector<AZStd::string> levelDirs;
AZStd::string currentDir = "levels";
AZStd::string currentDirPattern;
AZStd::string currentFilePattern;
AZStd::queue<AZ::IO::Path> scanDirs;
AZStd::vector<AZ::IO::Path> levelDirs;
AZ::IO::Path currentDir = "levels";
AZ::IO::Path currentDirPattern;
AZ::IO::Path currentFilePattern;
ZipDir::FindDir findDir(pZip);
findDir.FindFirst(currentDir.c_str());
@@ -2167,11 +2175,10 @@ namespace AZ::IO
scanDirs.pop();
}
currentDirPattern = currentDir + AZ_FILESYSTEM_SEPARATOR_WILDCARD;
currentFilePattern = currentDir + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "level.pak";
currentDirPattern = currentDir / "*";
currentFilePattern = currentDir / "level.pak";
ZipDir::FileEntry* fileEntry = findFile.FindExact(currentFilePattern.c_str());
if (fileEntry)
if (ZipDir::FileEntry* fileEntry = findFile.FindExact(currentFilePattern); fileEntry)
{
levelDirs.emplace_back(currentDir);
continue;
@@ -2179,9 +2186,7 @@ namespace AZ::IO
for (findDir.FindFirst(currentDirPattern.c_str()); findDir.GetDirEntry(); findDir.FindNext())
{
AZStd::string_view dirName = findDir.GetDirName();
AZStd::string dirToAdd = AZStd::string::format("%s/%.*s", currentDir.data(), aznumeric_cast<int>(dirName.size()), dirName.data());
scanDirs.push(dirToAdd);
scanDirs.push(currentDir / findDir.GetDirName());
}
} while (!scanDirs.empty());
@@ -207,7 +207,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, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) override;
AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, FileSearchLocation searchType = FileSearchLocation::InPak) override;
AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override;
bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override;
int FEof(AZ::IO::HandleType handle) override;
@@ -219,7 +219,7 @@ namespace AZ::IO
bool RemoveDir(AZStd::string_view pName) override; // remove directory from FS (if supported)
bool IsAbsPath(AZStd::string_view pPath) override;
bool IsFileExist(AZStd::string_view sFilename, EFileSearchLocation fileLocation = eFileLocation_Any) override;
bool IsFileExist(AZStd::string_view sFilename, FileSearchLocation fileLocation = FileSearchLocation::Any) override;
bool IsFolder(AZStd::string_view sPath) override;
IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) override;
@@ -255,7 +255,7 @@ namespace AZ::IO
bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) override;
// gets the current archive priority
ArchiveLocationPriority GetPakPriority() const override;
FileSearchPriority GetPakPriority() const override;
uint64_t GetFileOffsetOnMedia(AZStd::string_view szName) const override;
@@ -305,7 +305,7 @@ namespace AZ::IO
AZStd::shared_ptr<AzFramework::AssetRegistry> GetBundleCatalog(ZipDir::CachePtr pZip, const AZStd::string& catalogName);
// [LYN-2376] Remove once legacy slice support is removed
AZStd::vector<AZStd::string> ScanForLevels(ZipDir::CachePtr pZip);
AZStd::vector<AZ::IO::Path> ScanForLevels(ZipDir::CachePtr pZip);
mutable AZStd::shared_mutex m_csOpenFiles;
ZipPseudoFileArray m_arrOpenFiles;
@@ -169,7 +169,7 @@ namespace AZ::IO
size = m_archive->FGetSize(filePath, true);
if (!size)
{
return m_archive->IsFileExist(filePath, IArchive::eFileLocation_Any) ? IO::ResultCode::Success : IO::ResultCode::Error;
return m_archive->IsFileExist(filePath, FileSearchLocation::Any) ? IO::ResultCode::Success : IO::ResultCode::Error;
}
return IO::ResultCode::Success;
@@ -78,9 +78,9 @@ namespace AZ::IO
{
// get the priority into local variable to avoid it changing in the course of
// this function execution
ArchiveLocationPriority nVarPakPriority = archive->GetPakPriority();
FileSearchPriority nVarPakPriority = archive->GetPakPriority();
if (nVarPakPriority == ArchiveLocationPriority::ePakPriorityFileFirst)
if (nVarPakPriority == FileSearchPriority::FileFirst)
{
// first, find the file system files
ScanFS(archive, szDir);
@@ -96,7 +96,7 @@ namespace AZ::IO
{
ScanZips(archive, szDir);
}
if (bAllowUseFS || nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly)
if (bAllowUseFS || nVarPakPriority != FileSearchPriority::PakOnly)
{
ScanFS(archive, szDir);
}
@@ -0,0 +1,24 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/Archive/ArchiveVars.h>
namespace AZ::IO
{
FileSearchPriority GetDefaultFileSearchPriority()
{
#if defined(LY_ARCHIVE_FILE_SEARCH_MODE)
return FileSearchPriority{ LY_ARCHIVE_FILE_SEARCH_MODE };
#else
return FileSearchPriority{ !ArchiveVars::IsReleaseConfig
? FileSearchPriority::FileFirst
: FileSearchPriority::PakOnly };
#endif
}
}
@@ -13,13 +13,24 @@
namespace AZ::IO
{
enum class ArchiveLocationPriority
enum class FileSearchPriority
{
ePakPriorityFileFirst = 0,
ePakPriorityPakFirst = 1,
ePakPriorityPakOnly = 2
FileFirst,
PakFirst,
PakOnly
};
//file location enum used in isFileExist to control where the archive system looks for the file.
enum class FileSearchLocation
{
Any,
OnDisk,
InPak
};
FileSearchPriority GetDefaultFileSearchPriority();
// variables that control behavior of the Archive subsystem
struct ArchiveVars
{
@@ -28,8 +39,6 @@ namespace AZ::IO
#else
inline static constexpr bool IsReleaseConfig{};
#endif
public:
int nReadSlice{};
int nSaveTotalResourceList{};
int nSaveFastloadResourceList{};
@@ -42,9 +51,7 @@ namespace AZ::IO
int nLoadCache{};
int nLoadModePaks{};
int nStreamCache{ STREAM_CACHE_DEFAULT };
ArchiveLocationPriority nPriority{ IsReleaseConfig
? ArchiveLocationPriority::ePakPriorityPakOnly
: ArchiveLocationPriority::ePakPriorityFileFirst }; // Which file location to favor (loose vs. pak files)
FileSearchPriority m_fileSearchPriority{ GetDefaultFileSearchPriority()};
int nMessageInvalidFileAccess{};
int nLogInvalidFileAccess{ IsReleaseConfig ? 0 : 1 };
int nDisableNonLevelRelatedPaks{ 1 };
@@ -18,13 +18,13 @@
#include <AzCore/std/string/fixed_string.h>
#include <AzFramework/Archive/ArchiveFindData.h>
#include <AzFramework/Archive/ArchiveVars.h>
enum EStreamSourceMediaType : int32_t;
namespace AZ::IO
{
enum class ArchiveLocationPriority;
enum class FileSearchPriority;
struct IResourceList;
struct INestedArchive;
struct IArchive;
@@ -114,14 +114,6 @@ namespace AZ::IO
RFOM_NextLevel // used for level2level loading
};
//file location enum used in isFileExist to control where the archive system looks for the file.
enum EFileSearchLocation
{
eFileLocation_Any = 0,
eFileLocation_OnDisk,
eFileLocation_InPak,
};
enum EInMemoryArchiveLocation
{
eInMemoryPakLocale_Unload = 0,
@@ -130,12 +122,6 @@ namespace AZ::IO
eInMemoryPakLocale_PAK,
};
enum EFileSearchType
{
eFileSearchType_AllowInZipsOnly = 0,
eFileSearchType_AllowOnDiskAndInZips,
eFileSearchType_AllowOnDiskOnly
};
using SignedFileSize = int64_t;
@@ -213,7 +199,7 @@ namespace AZ::IO
virtual AZStd::intrusive_ptr<AZ::IO::MemoryBlock> PoolAllocMemoryBlock(size_t nSize, const char* sUsage, size_t nAlign = 1) = 0;
// Arguments:
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0;
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, FileSearchLocation searchType = FileSearchLocation::InPak) = 0;
virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0;
virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0;
//returns file modification time
@@ -221,7 +207,7 @@ namespace AZ::IO
// Description:
// Checks if specified file exist in filesystem.
virtual bool IsFileExist(AZStd::string_view sFilename, EFileSearchLocation = eFileLocation_Any) = 0;
virtual bool IsFileExist(AZStd::string_view sFilename, FileSearchLocation = FileSearchLocation::Any) = 0;
// Checks if path is a folder
virtual bool IsFolder(AZStd::string_view sPath) = 0;
@@ -283,7 +269,7 @@ namespace AZ::IO
virtual bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) = 0;
// gets the current pak priority
virtual ArchiveLocationPriority GetPakPriority() const = 0;
virtual FileSearchPriority GetPakPriority() const = 0;
// Summary:
// Return offset in archive file (ideally has to return offset on DVD) for streaming requests sorting
@@ -295,7 +281,7 @@ namespace AZ::IO
// Event sent when a archive file is opened that contains a level.pak
// @param const AZStd::vector<AZStd::string>& - Array of directories containing level.pak files
using LevelPackOpenEvent = AZ::Event<const AZStd::vector<AZStd::string>&>;
using LevelPackOpenEvent = AZ::Event<const AZStd::vector<AZ::IO::Path>&>;
virtual auto GetLevelPackOpenEvent()->LevelPackOpenEvent* = 0;
// Event sent when a archive contains a level.pak is closed
// @param const AZStd::string_view - Name of the pak file that was closed
@@ -7,23 +7,153 @@
*/
#include <AzFramework/Asset/AssetBundleManifest.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/ObjectStream.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzFramework
{
const int AssetBundleManifest::CurrentBundleVersion = 2;
// Redirects writing of the AssetBundleManifest to an older version if the bundle version
// is not set to the current version
static void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement);
static bool BundleManifestVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement);
const int AssetBundleManifest::CurrentBundleVersion = 3;
const char AssetBundleManifest::s_manifestFileName[] = "manifest.xml";
AssetBundleManifest::AssetBundleManifest() = default;
AssetBundleManifest::~AssetBundleManifest() = default;
void AssetBundleManifest::ReflectSerialize(AZ::SerializeContext* serializeContext)
{
if (serializeContext)
{
serializeContext->Class<AssetBundleManifest>()
->Version(2)
->Version(CurrentBundleVersion, &BundleManifestVersionConverter)
->Attribute(AZ::SerializeContextAttributes::ObjectStreamWriteElementOverride, &OldBundleManifestWriter)
->Field("BundleVersion", &AssetBundleManifest::m_bundleVersion)
->Field("CatalogName", &AssetBundleManifest::m_catalogName)
->Field("DependentBundleNames", &AssetBundleManifest::m_depedendentBundleNames)
->Field("DependentBundleNames", &AssetBundleManifest::m_dependentBundleNames)
->Field("LevelNames", &AssetBundleManifest::m_levelDirs);
// Make sure the AZStd::vector<AZStd::string> type is reflected so that it can be read
// using DataElement::GetChildData
serializeContext->RegisterGenericType<AZStd::vector<AZStd::string>>();
}
}
bool BundleManifestVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement)
{
if (rootElement.GetVersion() < 3)
{
static constexpr AZ::u32 levelNamesCrc = AZ_CRC_CE("LevelNames");
AZStd::vector<AZ::IO::Path> newLevelDirs;
if (AZStd::vector<AZStd::string> oldLevelNames; rootElement.GetChildData(levelNamesCrc, oldLevelNames))
{
newLevelDirs.insert(newLevelDirs.end(),
AZStd::make_move_iterator(oldLevelNames.begin()), AZStd::make_move_iterator(oldLevelNames.end()));
}
else
{
AZ_Error("AssetBundleManifest", false, R"(Unable to read "levelNames" from AssetBundleManifest version %u )",
rootElement.GetVersion());
}
rootElement.RemoveElementByName(levelNamesCrc);
rootElement.AddElementWithData(context, "LevelNames", newLevelDirs);
}
return true;
}
void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement)
{
// Copy the AssetBundleManifest current version instance to the AssetBundleManifest V2 instance
auto assetBundleManifestCurrent = reinterpret_cast<const AssetBundleManifest*>(bundleManifestPointer);
if (assetBundleManifestCurrent->GetBundleVersion() <= 2)
{
auto serializeContext = const_cast<AZ::SerializeContext*>(callContext.m_context);
struct AssetBundleManifestV2
{
// Use the same ClassName and typeid as the AssetBundleManifest
AZ_TYPE_INFO(AssetBundleManifest, azrtti_typeid<AssetBundleManifest>());
AZStd::string m_catalogName;
AZStd::vector<AZStd::string> m_dependentBundleNames;
AZStd::vector<AZStd::string> m_levelDirs;
int m_bundleVersion{};
};
auto ReflectAssetBundleManifestV2 = [](AZ::SerializeContext* serializeContext)
{
serializeContext->Class<AssetBundleManifestV2>()
->Version(2)
->Field("BundleVersion", &AssetBundleManifestV2::m_bundleVersion)
->Field("CatalogName", &AssetBundleManifestV2::m_catalogName)
->Field("DependentBundleNames", &AssetBundleManifestV2::m_dependentBundleNames)
->Field("LevelNames", &AssetBundleManifestV2::m_levelDirs);
};
// Unreflect the AssetBundleManifest class at the version since it shares the same typeid
// as the older version and Reflect the V2 AssetBundlerManifest
serializeContext->EnableRemoveReflection();
AssetBundleManifest::ReflectSerialize(serializeContext);
serializeContext->DisableRemoveReflection();
ReflectAssetBundleManifestV2(serializeContext);
// Use the Current AssetBundleManifest instance to make a Version 2 AssetBundleManifest
AssetBundleManifestV2 assetBundleManifestV2;
assetBundleManifestV2.m_catalogName = assetBundleManifestCurrent->GetCatalogName();
assetBundleManifestV2.m_dependentBundleNames = assetBundleManifestCurrent->GetDependentBundleNames();
assetBundleManifestV2.m_bundleVersion = assetBundleManifestCurrent->GetBundleVersion();
for (const AZ::IO::Path& levelDir : assetBundleManifestCurrent->GetLevelDirectories())
{
assetBundleManifestV2.m_levelDirs.emplace_back(levelDir.Native());
}
const AZ::TypeId& assetBundlerManifestTypeId = azrtti_typeid<AssetBundleManifestV2>();
const auto assetBundleManifestV2ClassData = serializeContext->FindClassData(assetBundlerManifestTypeId);
// Create an AssetBundleManifest Version 2 Class Eleemnt
// It will copy over the name and nameCrc values of the current AssetBundleManifestelemnt
auto CreateAssetBundleManifestV2ClassElement = [&assetBundlerManifestTypeId](
const AZ::SerializeContext::ClassElement* currentVersionElement) -> AZ::SerializeContext::ClassElement
{
AZ::SerializeContext::ClassElement v2ClassElement;
// Copy over the name of he current
if (currentVersionElement)
{
v2ClassElement.m_name = currentVersionElement->m_name;
v2ClassElement.m_nameCrc = currentVersionElement->m_nameCrc;
}
v2ClassElement.m_dataSize = sizeof(AssetBundleManifest);
v2ClassElement.m_azRtti = AZ::GetRttiHelper<AssetBundleManifestV2>();
v2ClassElement.m_genericClassInfo = nullptr;
v2ClassElement.m_typeId = assetBundlerManifestTypeId;
v2ClassElement.m_editData = nullptr;
v2ClassElement.m_attributeOwnership = AZ::SerializeContext::ClassElement::AttributeOwnership::Self;
return v2ClassElement;
};
const auto assetBundleManifestV2ClassElement = CreateAssetBundleManifestV2ClassElement(assetBundleManifestClassElement);
serializeContext->EnumerateInstanceConst(&callContext, &assetBundleManifestV2, assetBundlerManifestTypeId,
assetBundleManifestV2ClassData, assetBundleManifestClassElement ? &assetBundleManifestV2ClassElement : nullptr);
// Unreflect the V2 AssetBundleManifest and Re-reflect the AssetBundleManifest class at the current version
serializeContext->EnableRemoveReflection();
ReflectAssetBundleManifestV2(serializeContext);
serializeContext->DisableRemoveReflection();
AssetBundleManifest::ReflectSerialize(serializeContext);
}
}
const AZStd::vector<AZ::IO::Path>& AssetBundleManifest::GetLevelDirectories() const
{
return m_levelDirs;
}
void AssetBundleManifest::SetLevelsDirectory(const AZStd::vector<AZ::IO::Path>& levelDirs)
{
m_levelDirs = levelDirs;
}
} // namespace AzFramework
@@ -8,6 +8,7 @@
#pragma once
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/std/string/string.h>
@@ -27,7 +28,8 @@ namespace AzFramework
AZ_TYPE_INFO(AssetBundleManifest, "{8628A669-7B19-4C48-A7CB-F670CC9586FD}");
AZ_CLASS_ALLOCATOR(AssetBundleManifest, AZ::SystemAllocator, 0);
AssetBundleManifest() = default;
AssetBundleManifest();
~AssetBundleManifest();
static void ReflectSerialize(AZ::SerializeContext* serializeContext);
@@ -35,21 +37,21 @@ namespace AzFramework
// of files within the AssetBundle in order to update the Asset Registry at runtime when
// loading the bundle
const AZStd::string& GetCatalogName() const { return m_catalogName; }
AZStd::vector<AZStd::string> GetDependentBundleNames() const { return m_depedendentBundleNames; }
AZStd::vector<AZStd::string> GetLevelDirectories() const { return m_levelDirs; }
AZStd::vector<AZStd::string> GetDependentBundleNames() const { return m_dependentBundleNames; }
const AZStd::vector<AZ::IO::Path>& GetLevelDirectories() const;
int GetBundleVersion() const { return m_bundleVersion; }
void SetCatalogName(const AZStd::string& catalogName) { m_catalogName = catalogName; }
void SetBundleVersion(int bundleVersion) { m_bundleVersion = bundleVersion; }
void SetDependentBundleNames(const AZStd::vector<AZStd::string>& dependentBundleNames) { m_depedendentBundleNames = dependentBundleNames; }
void SetLevelsDirectory(const AZStd::vector<AZStd::string>& levelDirs) { m_levelDirs = levelDirs; }
void SetDependentBundleNames(const AZStd::vector<AZStd::string>& dependentBundleNames) { m_dependentBundleNames = dependentBundleNames; }
void SetLevelsDirectory(const AZStd::vector<AZ::IO::Path>& levelDirs);
static const char s_manifestFileName[];
static const int CurrentBundleVersion;
private:
private:
AZStd::string m_catalogName;
AZStd::vector<AZStd::string> m_depedendentBundleNames;
AZStd::vector<AZStd::string> m_levelDirs;
AZStd::vector<AZStd::string> m_dependentBundleNames;
AZStd::vector<AZ::IO::Path> m_levelDirs;
int m_bundleVersion = CurrentBundleVersion;
};
@@ -1186,7 +1186,7 @@ namespace AzFramework
}
bool AssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs)
bool AssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs)
{
if (bundleVersion > AzFramework::AssetBundleManifest::CurrentBundleVersion || bundleVersion < 0)
{
@@ -67,7 +67,7 @@ namespace AzFramework
bool InsertDeltaCatalogBefore(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog, AZStd::shared_ptr<AzFramework::AssetRegistry> afterDeltaCatalog) override;
bool RemoveDeltaCatalog(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog) override;
static bool SaveAssetBundleManifest(const char* assetBundleManifestFile, AzFramework::AssetBundleManifest* bundleManifest);
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs) override;
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs) override;
bool CreateDeltaCatalog(const AZStd::vector<AZStd::string>& files, const AZStd::string& filePath) override;
void AddExtension(const char* extension) override;
@@ -534,7 +534,7 @@ namespace AzFramework
void TransformComponent::SetParentImpl(AZ::EntityId parentId, bool isKeepWorldTM)
{
if (parentId == GetEntityId())
if (GetEntity() && parentId == GetEntityId())
{
AZ_Warning("TransformComponent", false, "An entity can not be set as its own parent.");
return;
@@ -76,9 +76,12 @@ namespace AzFramework
virtual void DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) { (void)pos; (void)dir; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) { (void)center; (void)axis; (void)radius; (void)height; }
virtual void DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded = true) { (void)center; (void)axis; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCylinderNoEnds(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) { (void)center; (void)axis; (void)radius; (void)height; }
virtual void DrawSolidCylinderNoEnds(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded = true) { (void)center; (void)axis; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float heightStraightSection) { (void)center; (void)axis; (void)radius; (void)heightStraightSection; }
virtual void DrawWireSphere(const AZ::Vector3& pos, float radius) { (void)pos; (void)radius; }
virtual void DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) { (void)pos; (void)radius; }
virtual void DrawWireHemisphere(const AZ::Vector3& pos, const AZ::Vector3& axis, float radius) { (void)pos; (void)axis; (void)radius; }
virtual void DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) { (void)pos; (void)dir; (void)radius; }
virtual void DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded = true) { (void)pos; (void)radius; (void)drawShaded; }
virtual void DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) { (void)pos; (void)dir; (void)radius; }
@@ -0,0 +1,46 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "HeightfieldProviderBus.h"
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace Physics
{
void HeightfieldProviderRequests::Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<Physics::HeightfieldProviderRequestsBus>("HeightfieldProviderRequestsBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Event("GetHeightfieldGridSpacing", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridSpacing)
->Event("GetHeightfieldAabb", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldAabb)
->Event("GetHeightfieldTransform", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldTransform)
->Event("GetMaterialList", &Physics::HeightfieldProviderRequestsBus::Events::GetMaterialList)
->Event("GetHeights", &Physics::HeightfieldProviderRequestsBus::Events::GetHeights)
->Event("GetHeightsAndMaterials", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightsAndMaterials)
->Event("GetHeightfieldMinHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMinHeight)
->Event("GetHeightfieldMaxHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMaxHeight)
->Event("GetHeightfieldGridColumns", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridColumns)
->Event("GetHeightfieldGridRows", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridRows)
;
}
}
void HeightMaterialPoint::Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::HeightMaterialPoint>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
} // namespace Physics
@@ -26,10 +26,25 @@ namespace Physics
struct HeightMaterialPoint
{
HeightMaterialPoint(
float height = 0.0f, QuadMeshType type = QuadMeshType::SubdivideUpperLeftToBottomRight, uint8_t index = 0)
: m_height(height)
, m_quadMeshType(type)
, m_materialIndex(index)
, m_padding(0)
{
}
virtual ~HeightMaterialPoint() = default;
static void Reflect(AZ::ReflectContext* context);
AZ_RTTI(HeightMaterialPoint, "{DF167ED4-24E6-4F7B-8AB7-42622F7DBAD3}");
float m_height{ 0.0f }; //!< Holds the height of this point in the heightfield relative to the heightfield entity location.
QuadMeshType m_quadMeshType{ QuadMeshType::SubdivideUpperLeftToBottomRight }; //!< By default, create two triangles like this |\|, where this point is in the upper left corner.
uint8_t m_materialIndex{ 0 }; //!< The surface material index for the upper left corner of this quad.
uint16_t m_padding{ 0 }; //!< available for future use.
};
//! An interface to provide heightfield values.
@@ -37,6 +52,8 @@ namespace Physics
: public AZ::ComponentBus
{
public:
static void Reflect(AZ::ReflectContext* context);
//! Returns the distance between each height in the map.
//! @return Vector containing Column Spacing, Rows Spacing.
virtual AZ::Vector2 GetHeightfieldGridSpacing() const = 0;
@@ -46,11 +63,27 @@ namespace Physics
//! @param numRows contains the size of the grid in the y direction.
virtual void GetHeightfieldGridSize(int32_t& numColumns, int32_t& numRows) const = 0;
//! Returns the height field gridsize columns.
//! @return the size of the grid in the x direction.
virtual int32_t GetHeightfieldGridColumns() const = 0;
//! Returns the height field gridsize rows.
//! @return the size of the grid in the y direction.
virtual int32_t GetHeightfieldGridRows() const = 0;
//! Returns the height field min and max height bounds.
//! @param minHeightBounds contains the minimum height that the heightfield can contain.
//! @param maxHeightBounds contains the maximum height that the heightfield can contain.
virtual void GetHeightfieldHeightBounds(float& minHeightBounds, float& maxHeightBounds) const = 0;
//! Returns the height field min height bounds.
//! @return the minimum height that the heightfield can contain.
virtual float GetHeightfieldMinHeight() const = 0;
//! Returns the height field max height bounds.
//! @return the maximum height that the heightfield can contain.
virtual float GetHeightfieldMaxHeight() const = 0;
//! Returns the AABB of the heightfield.
//! This is provided separately from the shape AABB because the heightfield might choose to modify the AABB bounds.
//! @return AABB of the heightfield.
@@ -360,6 +360,11 @@ namespace Physics
->Field("MaterialId", &Physics::MaterialId::m_id)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::MaterialId>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
MaterialId MaterialId::Create()
@@ -94,27 +94,27 @@ namespace AzFramework
float y;
float z;
// 2.4 Factor as RzRyRx
if (orientation.GetElement(2, 0) < 1.0f)
// 2.5 Factor as RzRxRy
if (orientation.GetElement(2, 1) < 1.0f)
{
if (orientation.GetElement(2, 0) > -1.0f)
if (orientation.GetElement(2, 1) > -1.0f)
{
x = AZStd::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2));
y = AZStd::asin(-orientation.GetElement(2, 0));
z = AZStd::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0));
x = AZStd::asin(orientation.GetElement(2, 1));
y = AZStd::atan2(-orientation.GetElement(2, 0), orientation.GetElement(2, 2));
z = AZStd::atan2(-orientation.GetElement(0, 1), orientation.GetElement(1, 1));
}
else
{
x = 0.0f;
y = AZ::Constants::Pi * 0.5f;
z = -AZStd::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1));
x = -AZ::Constants::Pi * 0.5f;
y = 0.0f;
z = -AZStd::atan2(orientation.GetElement(0, 2), orientation.GetElement(0, 0));
}
}
else
{
x = 0.0f;
y = -AZ::Constants::Pi * 0.5f;
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
x = AZ::Constants::Pi * 0.5f;
y = 0.0f;
z = AZStd::atan2(orientation.GetElement(0, 2), orientation.GetElement(0, 0));
}
return { x, y, z };
@@ -122,14 +122,36 @@ namespace AzFramework
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
{
const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform));
UpdateCameraFromTranslationAndRotation(
camera, transform.GetTranslation(), AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform)));
}
void UpdateCameraFromTranslationAndRotation(Camera& camera, const AZ::Vector3& translation, const AZ::Vector3& eulerAngles)
{
camera.m_pitch = eulerAngles.GetX();
camera.m_yaw = eulerAngles.GetZ();
camera.m_pivot = transform.GetTranslation();
camera.m_pivot = translation;
camera.m_offset = AZ::Vector3::CreateZero();
}
float SmoothValueTime(const float smoothness, float deltaTime)
{
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
const float rate = AZStd::exp2(smoothness);
return AZStd::exp2(-rate * deltaTime);
}
float SmoothValue(const float target, const float current, const float time)
{
return AZ::Lerp(target, current, time);
}
float SmoothValue(const float target, const float current, const float smoothness, const float deltaTime)
{
return SmoothValue(target, current, SmoothValueTime(smoothness, deltaTime));
}
bool CameraSystem::HandleEvents(const InputEvent& event)
{
if (const auto& cursor = AZStd::get_if<CursorEvent>(&event))
@@ -291,6 +313,11 @@ namespace AzFramework
{
return false;
};
m_constrainPitch = []() constexpr
{
return true;
};
}
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta)
@@ -312,7 +339,10 @@ namespace AzFramework
nextCamera.m_yaw -= float(cursorDelta.m_x) * rotateSpeed * Invert(m_invertYawFn());
nextCamera.m_yaw = WrapYawRotation(nextCamera.m_yaw);
nextCamera.m_pitch = ClampPitchRotation(nextCamera.m_pitch);
if (m_constrainPitch())
{
nextCamera.m_pitch = ClampPitchRotation(nextCamera.m_pitch);
}
return nextCamera;
}
@@ -726,14 +756,14 @@ namespace AzFramework
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const CameraProps& cameraProps, const float deltaTime)
{
const auto clamp_rotation = [](const float angle)
const auto clampRotation = [](const float angle)
{
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
};
// keep yaw in 0 - 360 range
float targetYaw = clamp_rotation(targetCamera.m_yaw);
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
float targetYaw = clampRotation(targetCamera.m_yaw);
const float currentYaw = clampRotation(currentCamera.m_yaw);
// return the sign of the float input (-1, 0, 1)
const auto sign = [](const float value)
@@ -742,21 +772,17 @@ namespace AzFramework
};
// ensure smooth transition when moving across 0 - 360 boundary
const float yawDelta = targetYaw - currentYaw;
if (AZStd::abs(yawDelta) >= AZ::Constants::Pi)
if (const float yawDelta = targetYaw - currentYaw; AZStd::abs(yawDelta) >= AZ::Constants::Pi)
{
targetYaw -= AZ::Constants::TwoPi * sign(yawDelta);
}
Camera camera;
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
if (cameraProps.m_rotateSmoothingEnabledFn())
{
const float lookRate = AZStd::exp2(cameraProps.m_rotateSmoothnessFn());
const float lookTime = AZStd::exp2(-lookRate * deltaTime);
camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookTime);
camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookTime);
const float lookTime = SmoothValueTime(cameraProps.m_rotateSmoothnessFn(), deltaTime);
camera.m_pitch = SmoothValue(targetCamera.m_pitch, currentCamera.m_pitch, lookTime);
camera.m_yaw = SmoothValue(targetYaw, currentYaw, lookTime);
}
else
{
@@ -766,8 +792,7 @@ namespace AzFramework
if (cameraProps.m_translateSmoothingEnabledFn())
{
const float moveRate = AZStd::exp2(cameraProps.m_translateSmoothnessFn());
const float moveTime = AZStd::exp2(-moveRate * deltaTime);
const float moveTime = SmoothValueTime(cameraProps.m_rotateSmoothnessFn(), deltaTime);
camera.m_pivot = targetCamera.m_pivot.Lerp(currentCamera.m_pivot, moveTime);
camera.m_offset = targetCamera.m_offset.Lerp(currentCamera.m_offset, moveTime);
}
@@ -85,6 +85,19 @@ namespace AzFramework
//! Extracts Euler angles (orientation) and translation from the transform and writes the values to the camera.
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform);
//! Writes the translation value and Euler angles to the camera.
void UpdateCameraFromTranslationAndRotation(Camera& camera, const AZ::Vector3& translation, const AZ::Vector3& eulerAngles);
//! Returns the time ('t') input value to use with SmoothValue.
//! Useful if it is to be reused for multiple calls to SmoothValue.
float SmoothValueTime(float smoothness, float deltaTime);
// Smoothly interpolate a value from current to target according to a smoothing parameter.
float SmoothValue(float target, float current, float smoothness, float deltaTime);
// Overload of SmoothValue that takes time ('t') value directly.
float SmoothValue(float target, float current, float time);
//! Generic motion type.
template<typename MotionTag>
struct MotionEvent
@@ -334,6 +347,7 @@ namespace AzFramework
AZStd::function<float()> m_rotateSpeedFn;
AZStd::function<bool()> m_invertPitchFn;
AZStd::function<bool()> m_invertYawFn;
AZStd::function<bool()> m_constrainPitch;
private:
InputChannelId m_rotateChannelId; //!< Input channel to begin the rotate camera input.
@@ -8,18 +8,18 @@
#include "CameraState.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzFramework
{
void SetCameraClippingVolume(
AzFramework::CameraState& cameraState, const float nearPlane, const float farPlane, const float fovRad)
AzFramework::CameraState& cameraState, const float nearPlane, const float farPlane, const float verticalFovRad)
{
cameraState.m_nearClip = nearPlane;
cameraState.m_farClip = farPlane;
cameraState.m_fovOrZoom = fovRad;
cameraState.m_fovOrZoom = verticalFovRad;
}
void SetCameraTransform(CameraState& cameraState, const AZ::Transform& transform)
@@ -35,20 +35,34 @@ namespace AzFramework
SetCameraClippingVolume(cameraState, 0.1f, 1000.0f, AZ::DegToRad(60.0f));
}
AzFramework::CameraState CreateDefaultCamera(
const AZ::Transform& transform, const AZ::Vector2& viewportSize)
CameraState CreateCamera(
const AZ::Transform& transform,
const float nearPlane,
const float farPlane,
const float verticalFovRad,
const AZ::Vector2& viewportSize)
{
AzFramework::CameraState cameraState;
SetDefaultCameraClippingVolume(cameraState);
SetCameraTransform(cameraState, transform);
SetCameraClippingVolume(cameraState, nearPlane, farPlane, verticalFovRad);
cameraState.m_viewportSize = viewportSize;
return cameraState;
}
AzFramework::CameraState CreateIdentityDefaultCamera(
const AZ::Vector3& position, const AZ::Vector2& viewportSize)
AzFramework::CameraState CreateDefaultCamera(const AZ::Transform& transform, const AZ::Vector2& viewportSize)
{
AzFramework::CameraState cameraState;
SetCameraTransform(cameraState, transform);
SetDefaultCameraClippingVolume(cameraState);
cameraState.m_viewportSize = viewportSize;
return cameraState;
}
AzFramework::CameraState CreateIdentityDefaultCamera(const AZ::Vector3& position, const AZ::Vector2& viewportSize)
{
return CreateDefaultCamera(AZ::Transform::CreateTranslation(position), viewportSize);
}
@@ -89,15 +103,15 @@ namespace AzFramework
void CameraState::Reflect(AZ::SerializeContext& serializeContext)
{
serializeContext.Class<CameraState>()->
Field("Position", &CameraState::m_position)->
Field("Forward", &CameraState::m_forward)->
Field("Side", &CameraState::m_side)->
Field("Up", &CameraState::m_up)->
Field("ViewportSize", &CameraState::m_viewportSize)->
Field("NearClip", &CameraState::m_nearClip)->
Field("FarClip", &CameraState::m_farClip)->
Field("FovZoom", &CameraState::m_fovOrZoom)->
Field("Ortho", &CameraState::m_orthographic);
serializeContext.Class<CameraState>()
->Field("Position", &CameraState::m_position)
->Field("Forward", &CameraState::m_forward)
->Field("Side", &CameraState::m_side)
->Field("Up", &CameraState::m_up)
->Field("ViewportSize", &CameraState::m_viewportSize)
->Field("NearClip", &CameraState::m_nearClip)
->Field("FarClip", &CameraState::m_farClip)
->Field("FovZoom", &CameraState::m_fovOrZoom)
->Field("Ortho", &CameraState::m_orthographic);
}
} // namespace AzFramework
@@ -40,10 +40,14 @@ namespace AzFramework
AZ::Vector2 m_viewportSize = AZ::Vector2::CreateZero(); //!< Dimensions of the viewport.
float m_nearClip = 0.01f; //!< Near clip plane of the camera.
float m_farClip = 100.0f; //!< Far clip plane of the camera.
float m_fovOrZoom = 0.0f; //!< Fov or zoom of camera depending on if it is using orthographic projection or not.
float m_fovOrZoom = 0.0f; //!< Vertical fov or zoom of camera depending on if it is using orthographic projection or not.
bool m_orthographic = false; //!< Is the camera using orthographic projection or not.
};
//! Create a camera at the given transform, specifying the near and far clip planes as well as the fov with a specific viewport size.
CameraState CreateCamera(
const AZ::Transform& transform, float nearPlane, float farPlane, float verticalFovRad, const AZ::Vector2& viewportSize);
//! Create a camera at the given transform with a specific viewport size.
//! @note The near/far clip planes and fov are sensible default values - please
//! use SetCameraClippingVolume to override them.
@@ -60,7 +64,7 @@ namespace AzFramework
CameraState CreateCameraFromWorldFromViewMatrix(const AZ::Matrix4x4& worldFromView, const AZ::Vector2& viewportSize);
//! Override the default near/far clipping planes and fov of the camera.
void SetCameraClippingVolume(CameraState& cameraState, float nearPlane, float farPlane, float fovRad);
void SetCameraClippingVolume(CameraState& cameraState, float nearPlane, float farPlane, float verticalFovRad);
//! Override the default near/far clipping planes and fov of the camera by inferring them the specified right handed transform into clip space.
void SetCameraClippingVolumeFromPerspectiveFovMatrixRH(CameraState& cameraState, const AZ::Matrix4x4& clipFromView);
@@ -24,11 +24,12 @@ namespace AzFramework
ClickDetector::ClickOutcome ClickDetector::DetectClick(const ClickEvent clickEvent, const ScreenVector& cursorDelta)
{
m_moveAccumulator += ScreenVectorLength(cursorDelta);
const auto previousDetectionState = m_detectionState;
if (previousDetectionState == DetectionState::WaitingForMove)
{
// only allow the action to begin if the mouse has been moved a small amount
m_moveAccumulator += ScreenVectorLength(cursorDelta);
if (m_moveAccumulator > m_deadZone)
{
m_detectionState = DetectionState::Moved;
@@ -43,7 +44,7 @@ namespace AzFramework
using FloatingPointSeconds = AZStd::chrono::duration<float, AZStd::chrono::seconds::period>;
const auto diff = now - m_tryBeginTime.value();
if (FloatingPointSeconds(diff).count() < m_doubleClickInterval)
if (FloatingPointSeconds(diff).count() < m_doubleClickInterval && m_moveAccumulator < m_deadZone)
{
return ClickOutcome::Nil;
}
@@ -15,6 +15,10 @@
namespace AzFramework
{
//! Default value to use for detecting if the mouse has moved far enough after a mouse down to no longer
//! register a click when a mouse up occurs.
inline constexpr float DefaultMouseMoveDeadZone = 2.0f;
struct ScreenVector;
//! Utility class to help detect different types of mouse click (mouse down and up with
@@ -66,7 +70,7 @@ namespace AzFramework
};
float m_moveAccumulator = 0.0f; //!< How far the mouse has moved after mouse down.
float m_deadZone = 2.0f; //!< How far to move before a click is cancelled (when Move will fire).
float m_deadZone = DefaultMouseMoveDeadZone; //!< How far to move before a click is cancelled (when Move will fire).
float m_doubleClickInterval = 0.4f; //!< Default double click interval, can be overridden.
DetectionState m_detectionState; //!< Internal state of ClickDetector.
//! Mouse down time (happens each mouse down, helps with double click handling).
@@ -24,6 +24,10 @@ namespace AzFramework
serializeContext->Class<ScreenVector>()->
Field("X", &ScreenVector::m_x)->
Field("Y", &ScreenVector::m_y);
serializeContext->Class<ScreenSize>()->
Field("Width", &ScreenSize::m_width)->
Field("Height", &ScreenSize::m_height);
}
}
} // namespace AzFramework
@@ -26,7 +26,7 @@ namespace AzFramework
AZ_TYPE_INFO(ScreenPoint, "{8472B6C2-527F-44FC-87F8-C226B1A57A97}");
ScreenPoint() = default;
ScreenPoint(int x, int y)
constexpr ScreenPoint(int x, int y)
: m_x(x)
, m_y(y)
{
@@ -45,7 +45,7 @@ namespace AzFramework
AZ_TYPE_INFO(ScreenVector, "{1EAA2C62-8FDB-4A28-9FE3-1FA4F1418894}");
ScreenVector() = default;
ScreenVector(int x, int y)
constexpr ScreenVector(int x, int y)
: m_x(x)
, m_y(y)
{
@@ -55,6 +55,22 @@ namespace AzFramework
int m_y; //!< Y screen delta.
};
//! A wrapper around a screen width and height.
struct ScreenSize
{
AZ_TYPE_INFO(ScreenSize, "{26D28916-6E8E-44B8-83F9-C44BCDA370E2}");
ScreenSize() = default;
constexpr ScreenSize(int width, int height)
: m_width(width)
, m_height(height)
{
}
int m_width; //!< Screen size width.
int m_height; //!< Screen size height.
};
void ScreenGeometryReflect(AZ::ReflectContext* context);
inline const ScreenVector operator-(const ScreenPoint& lhs, const ScreenPoint& rhs)
@@ -138,6 +154,16 @@ namespace AzFramework
return !operator==(lhs, rhs);
}
inline const bool operator==(const ScreenSize& lhs, const ScreenSize& rhs)
{
return lhs.m_width == rhs.m_width && lhs.m_height == rhs.m_height;
}
inline const bool operator!=(const ScreenSize& lhs, const ScreenSize& rhs)
{
return !operator==(lhs, rhs);
}
inline ScreenVector& operator*=(ScreenVector& lhs, const float rhs)
{
lhs.m_x = aznumeric_cast<int>(AZStd::lround(aznumeric_cast<float>(lhs.m_x) * rhs));
@@ -152,6 +178,20 @@ namespace AzFramework
return result;
}
inline ScreenSize& operator*=(ScreenSize& lhs, const float rhs)
{
lhs.m_width = aznumeric_cast<int>(AZStd::lround(aznumeric_cast<float>(lhs.m_width) * rhs));
lhs.m_height = aznumeric_cast<int>(AZStd::lround(aznumeric_cast<float>(lhs.m_height) * rhs));
return lhs;
}
inline const ScreenSize operator*(const ScreenSize& lhs, const float rhs)
{
ScreenSize result{ lhs };
result *= rhs;
return result;
}
inline float ScreenVectorLength(const ScreenVector& screenVector)
{
return aznumeric_cast<float>(AZStd::sqrt(screenVector.m_x * screenVector.m_x + screenVector.m_y * screenVector.m_y));
@@ -168,4 +208,28 @@ namespace AzFramework
{
return AZ::Vector2(aznumeric_cast<float>(screenVector.m_x), aznumeric_cast<float>(screenVector.m_y));
}
//! Return an AZ::Vector2 from a ScreenSize.
inline AZ::Vector2 Vector2FromScreenSize(const ScreenSize& screenSize)
{
return AZ::Vector2(aznumeric_cast<float>(screenSize.m_width), aznumeric_cast<float>(screenSize.m_height));
}
//! Return a ScreenPoint from an AZ::Vector2.
inline ScreenPoint ScreenPointFromVector2(const AZ::Vector2& vector2)
{
return ScreenPoint(aznumeric_cast<int>(AZStd::lround(vector2.GetX())), aznumeric_cast<int>(AZStd::lround(vector2.GetY())));
}
//! Return a ScreenVector from an AZ::Vector2.
inline ScreenVector ScreenVectorFromVector2(const AZ::Vector2& vector2)
{
return ScreenVector(aznumeric_cast<int>(AZStd::lround(vector2.GetX())), aznumeric_cast<int>(AZStd::lround(vector2.GetY())));
}
//! Return a ScreenSize from an AZ::Vector2.
inline ScreenSize ScreenSizeFromVector2(const AZ::Vector2& vector2)
{
return ScreenSize(aznumeric_cast<int>(AZStd::lround(vector2.GetX())), aznumeric_cast<int>(AZStd::lround(vector2.GetY())));
}
} // namespace AzFramework
@@ -10,6 +10,7 @@
#include <AzCore/Math/Frustum.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Math/Vector4.h>
#include <AzCore/Math/VectorConversions.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
@@ -112,9 +113,8 @@ namespace AzFramework
const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize)
{
const auto ndcNormalizedPosition = WorldToScreenNdc(worldPosition, cameraView, cameraProjection);
// scale ndc position by screen dimensions to return screen position
return ScreenPointFromNdc(AZ::Vector3ToVector2(ndcNormalizedPosition), viewportSize);
return ScreenPointFromNdc(AZ::Vector3ToVector2(WorldToScreenNdc(worldPosition, cameraView, cameraProjection)), viewportSize);
}
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState)
@@ -144,9 +144,7 @@ namespace AzFramework
const AZ::Matrix4x4& inverseCameraProjection,
const AZ::Vector2& viewportSize)
{
const auto normalizedScreenPosition = NdcFromScreenPoint(screenPosition, viewportSize);
return ScreenNdcToWorld(normalizedScreenPosition, inverseCameraView, inverseCameraProjection);
return ScreenNdcToWorld(NdcFromScreenPoint(screenPosition, viewportSize), inverseCameraView, inverseCameraProjection);
}
AZ::Vector3 ScreenToWorld(const ScreenPoint& screenPosition, const CameraState& cameraState)
@@ -21,6 +21,7 @@ set(FILES
Archive/ArchiveFindData.cpp
Archive/ArchiveFindData.h
Archive/ArchiveVars.h
Archive/ArchiveVars.cpp
Archive/Codec.h
Archive/IArchive.h
Archive/INestedArchive.h
@@ -78,6 +79,7 @@ set(FILES
CommandLine/CommandLine.h
CommandLine/CommandRegistrationBus.h
Debug/DebugCameraBus.h
feature_options.cmake
Viewport/ViewportBus.h
Viewport/ViewportBus.cpp
Viewport/ViewportColors.h
@@ -229,6 +231,7 @@ set(FILES
Physics/Configuration/SystemConfiguration.h
Physics/Configuration/SystemConfiguration.cpp
Physics/HeightfieldProviderBus.h
Physics/HeightfieldProviderBus.cpp
Physics/SimulatedBodies/RigidBody.h
Physics/SimulatedBodies/RigidBody.cpp
Physics/SimulatedBodies/StaticRigidBody.h
@@ -0,0 +1,13 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(LY_ARCHIVE_FILE_SEARCH_MODE "" CACHE STRING "Set the default file search mode to locate non-Pak files within the Archive System\n\
Valid values are:\n\
0 = Search FileSystem first, before searching within mounted Paks (default in debug/profile)\n\
1 = Search mounted Paks first, before searching FileSystem\n\
2 = Search only mounted Paks (default in release)\n")
@@ -6,6 +6,7 @@
#
#
include(AzFramework/feature_options.cmake)
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common)
@@ -33,6 +34,14 @@ ly_add_target(
3rdParty::lz4
)
set(LY_SEARCH_MODE_DEFINE $<$<BOOL:"${LY_ARCHIVE_FILE_SEARCH_MODE}">:LY_ARCHIVE_FILE_SEARCH_MODE=${LY_ARCHIVE_FILE_SEARCH_MODE}>)
ly_add_source_properties(
SOURCES
AzFramework/Archive/ArchiveVars.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ${LY_SEARCH_MODE_DEFINE})
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME})
@@ -6,6 +6,8 @@
*
*/
#pragma once
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbEventHandler.h>
@@ -273,7 +273,7 @@ namespace UnitTest
// Also enable extra verbosity in the AZ::IO::Archive code
CVarIntValueScope previousLocationPriority{ *console, "sys_pakPriority" };
CVarIntValueScope oldArchiveVerbosity{ *console, "az_archive_verbosity" };
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::ArchiveLocationPriority::ePakPriorityPakOnly)) });
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::FileSearchPriority::PakOnly)) });
console->PerformCommand("az_archive_verbosity", { "1" });
// ---- Archive FGetCachedFileDataTests (these leverage Archive CachedFile mechanism for caching data ---
@@ -459,7 +459,7 @@ namespace UnitTest
// Once the archive has been deleted it should no longer be searched
CVarIntValueScope previousLocationPriority{ *console, "sys_pakPriority" };
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::ArchiveLocationPriority::ePakPriorityPakOnly)) });
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::FileSearchPriority::PakOnly)) });
handle = archive->FindFirst("levels\\*");
EXPECT_FALSE(static_cast<bool>(handle));
@@ -785,7 +785,7 @@ namespace UnitTest
EXPECT_TRUE(archive->OpenPack("@usercache@", realNameBuf));
EXPECT_TRUE(archive->IsFileExist("@usercache@/foundit.dat"));
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
EXPECT_FALSE(archive->IsFileExist("@usercache@/notfoundit.dat"));
EXPECT_TRUE(archive->ClosePack(realNameBuf));
@@ -793,7 +793,7 @@ namespace UnitTest
EXPECT_TRUE(archive->OpenPack("@products@", realNameBuf));
EXPECT_TRUE(archive->IsFileExist("@products@/foundit.dat"));
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous location!
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat"));
EXPECT_TRUE(archive->ClosePack(realNameBuf));
@@ -802,8 +802,8 @@ namespace UnitTest
EXPECT_TRUE(archive->IsFileExist("@products@/mystuff/foundit.dat"));
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat")); // do not find it in the previous locations!
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous locations!
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat")); // non-existent file
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/notfoundit.dat")); // non-existent file
EXPECT_TRUE(archive->ClosePack(realNameBuf));
@@ -104,9 +104,10 @@ namespace UnitTest
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
AZ::Vector3 m_pivot = AZ::Vector3::CreateZero();
//! This is approximately Pi/2 * 1000 - this can be used to rotate the camera 90 degrees (pitch or yaw based
//! on vertical or horizontal motion) as the rotate speed function is set to be 1/1000.
inline static const int PixelMotionDelta = 1570;
// this is approximately Pi/2 * 1000 - this can be used to rotate the camera 90 degrees (pitch or yaw based
// on vertical or horizontal motion) as the rotate speed function is set to be 1/1000.
inline static const int PixelMotionDelta90Degrees = 1570;
inline static const int PixelMotionDelta135Degrees = 2356;
};
TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents)
@@ -292,7 +293,7 @@ namespace UnitTest
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ PixelMotionDelta });
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ PixelMotionDelta90Degrees });
const float expectedYaw = AzFramework::WrapYawRotation(-AZ::Constants::HalfPi);
@@ -310,7 +311,7 @@ namespace UnitTest
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta });
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta90Degrees });
const float expectedPitch = AzFramework::ClampPitchRotation(-AZ::Constants::HalfPi);
@@ -331,7 +332,7 @@ namespace UnitTest
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta });
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta90Degrees });
const auto expectedCameraEndingPosition = AZ::Vector3(0.0f, -10.0f, 10.0f);
const float expectedPitch = AzFramework::ClampPitchRotation(-AZ::Constants::HalfPi);
@@ -354,7 +355,7 @@ namespace UnitTest
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ -PixelMotionDelta });
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ -PixelMotionDelta90Degrees });
const auto expectedCameraEndingPosition = AZ::Vector3(20.0f, -5.0f, 0.0f);
const float expectedYaw = AzFramework::WrapYawRotation(AZ::Constants::HalfPi);
@@ -366,4 +367,42 @@ namespace UnitTest
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3(5.0f, -10.0f, 0.0f)));
EXPECT_THAT(m_camera.Translation(), IsCloseTolerance(expectedCameraEndingPosition, 0.01f));
}
TEST_F(CameraInputFixture, CameraPitchCanNotBeMovedPastNinetyDegreesWhenConstrained)
{
const auto cameraStartingPosition = AZ::Vector3(15.0f, -20.0f, 0.0f);
m_targetCamera.m_pivot = cameraStartingPosition;
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
// pitch by 135.0 degrees
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ -PixelMotionDelta135Degrees });
// clamped to 90.0 degrees
const float expectedPitch = AZ::DegToRad(90.0f);
using ::testing::FloatNear;
EXPECT_THAT(m_camera.m_pitch, FloatNear(expectedPitch, 0.001f));
}
TEST_F(CameraInputFixture, CameraPitchCanBeMovedPastNinetyDegreesWhenUnconstrained)
{
m_firstPersonRotateCamera->m_constrainPitch = []
{
return false;
};
const auto cameraStartingPosition = AZ::Vector3(15.0f, -20.0f, 0.0f);
m_targetCamera.m_pivot = cameraStartingPosition;
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
// pitch by 135.0 degrees
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ -PixelMotionDelta135Degrees });
const float expectedPitch = AZ::DegToRad(135.0f);
using ::testing::FloatNear;
EXPECT_THAT(m_camera.m_pitch, FloatNear(expectedPitch, 0.001f));
}
} // namespace UnitTest
@@ -11,6 +11,7 @@
#include <AzFramework/Viewport/CameraState.h>
#include <AZTestShared/Math/MathTestHelpers.h>
#include <AzCore/Math/SimdMath.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Math/Matrix4x4.h>
namespace UnitTest
@@ -51,22 +52,6 @@ namespace UnitTest
{
};
// Taken from Atom::MatrixUtils for testing purposes, this can be removed if MakePerspectiveFovMatrixRH makes it into AZ
static AZ::Matrix4x4 MakePerspectiveMatrixRH(float fovY, float aspectRatio, float nearClip, float farClip)
{
float sinFov, cosFov;
AZ::SinCos(0.5f * fovY, sinFov, cosFov);
float yScale = cosFov / sinFov; //cot(fovY/2)
float xScale = yScale / aspectRatio;
AZ::Matrix4x4 out;
out.SetRow(0, xScale, 0.f, 0.f, 0.f );
out.SetRow(1, 0.f, yScale, 0.f, 0.f );
out.SetRow(2, 0.f, 0.f, farClip / (nearClip - farClip), nearClip*farClip / (nearClip - farClip) );
out.SetRow(3, 0.f, 0.f, -1.f, 0.f );
return out;
}
TEST_P(Translation, Permutation)
{
// Given a position
@@ -176,7 +161,8 @@ namespace UnitTest
{
auto [fovY, aspectRatio, nearClip, farClip] = GetParam();
AZ::Matrix4x4 clipFromView = MakePerspectiveMatrixRH(fovY, aspectRatio, nearClip, farClip);
AZ::Matrix4x4 clipFromView;
MakePerspectiveFovMatrixRH(clipFromView, fovY, aspectRatio, nearClip, farClip);
AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(m_cameraState, clipFromView);
@@ -144,12 +144,45 @@ namespace UnitTest
{
using ::testing::Eq;
const ClickDetector::ClickOutcome downOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome upOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(50, 50));
const ClickDetector::ClickOutcome downOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome upOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(50, 50));
EXPECT_THAT(downOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(upOutcome, Eq(ClickDetector::ClickOutcome::Release));
}
//! note: ClickDetector does not explicitly return double clicks but if one occurs the ClickOutcome will be Nil
TEST_F(ClickDetectorFixture, DoubleClickIsRegisteredIfMouseDeltaHasMovedLessThanDeadzoneInClickInterval)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome firstDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome firstUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(firstDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(firstUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
EXPECT_THAT(secondDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(secondUpOutcome, Eq(ClickDetector::ClickOutcome::Nil));
}
TEST_F(ClickDetectorFixture, DoubleClickIsNotRegisteredIfMouseDeltaHasMovedMoreThanDeadzoneInClickInterval)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome firstDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome firstUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(10, 10));
const ClickDetector::ClickOutcome secondUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(firstDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(firstUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
EXPECT_THAT(secondDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(secondUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
}
} // namespace UnitTest
@@ -8,12 +8,13 @@
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Viewport/CursorState.h>
#include <Tests/Utils/Printers.h>
namespace UnitTest
{
using AzFramework::CursorState;
using AzFramework::ScreenVector;
using AzFramework::ScreenPoint;
using AzFramework::ScreenVector;
class CursorStateFixture : public ::testing::Test
{
@@ -0,0 +1,32 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "Printers.h"
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <ostream>
#include <string>
namespace AzFramework
{
void PrintTo(const ScreenPoint& screenPoint, std::ostream* os)
{
*os << "(x: " << screenPoint.m_x << ", y: " << screenPoint.m_y << ")";
}
void PrintTo(const ScreenVector& screenVector, std::ostream* os)
{
*os << "(x: " << screenVector.m_x << ", y: " << screenVector.m_y << ")";
}
void PrintTo(const ScreenSize& screenSize, std::ostream* os)
{
*os << "(width: " << screenSize.m_width << ", height: " << screenSize.m_height << ")";
}
} // namespace AzFramework
@@ -0,0 +1,20 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <iosfwd>
namespace AzFramework
{
struct ScreenPoint;
struct ScreenVector;
struct ScreenSize;
void PrintTo(const ScreenPoint& screenPoint, std::ostream* os);
void PrintTo(const ScreenVector& screenVector, std::ostream* os);
void PrintTo(const ScreenSize& screenSize, std::ostream* os);
} // namespace AzFramework
@@ -11,5 +11,7 @@ set(FILES
Mocks/MockWindowRequests.h
Utils/Utils.h
Utils/Utils.cpp
Utils/Printers.h
Utils/Printers.cpp
FrameworkApplicationFixture.h
)