@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user