@@ -28,6 +28,7 @@
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
#include <AzCore/Module/ModuleManagerBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
|
||||
#include <AzFramework/Asset/SimpleAsset.h>
|
||||
#include <AzFramework/Asset/AssetBundleManifest.h>
|
||||
@@ -295,6 +296,7 @@ namespace AzFramework
|
||||
azrtti_typeid<AZ::ScriptSystemComponent>(),
|
||||
azrtti_typeid<AZ::JobManagerComponent>(),
|
||||
azrtti_typeid<AZ::SliceSystemComponent>(),
|
||||
azrtti_typeid<AZ::TaskGraphSystemComponent>(),
|
||||
|
||||
azrtti_typeid<AzFramework::AssetCatalogComponent>(),
|
||||
azrtti_typeid<AzFramework::CustomAssetTypeComponent>(),
|
||||
@@ -477,14 +479,16 @@ namespace AzFramework
|
||||
newThreadDesc.m_cpuId = AFFINITY_MASK_USERTHREADS;
|
||||
newThreadDesc.m_name = newThreadName;
|
||||
AZStd::binary_semaphore binarySemaphore;
|
||||
AZStd::thread newThread([&workForNewThread, &binarySemaphore, &newThreadName]
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzFramework,
|
||||
"Application::PumpSystemEventLoopWhileDoingWorkInNewThread:ThreadWorker %s", newThreadName);
|
||||
AZStd::thread newThread(
|
||||
newThreadDesc,
|
||||
[&workForNewThread, &binarySemaphore, &newThreadName]
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzFramework,
|
||||
"Application::PumpSystemEventLoopWhileDoingWorkInNewThread:ThreadWorker %s", newThreadName);
|
||||
|
||||
workForNewThread();
|
||||
binarySemaphore.release();
|
||||
}, &newThreadDesc);
|
||||
workForNewThread();
|
||||
binarySemaphore.release();
|
||||
});
|
||||
while (!binarySemaphore.try_acquire_for(eventPumpFrequency))
|
||||
{
|
||||
PumpSystemEventLoopUntilEmpty();
|
||||
|
||||
@@ -1631,7 +1631,20 @@ namespace AZ::IO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
|
||||
ZipDir::InitMethod initType = ZipDir::InitMethod::Default;
|
||||
if (!ZipDir::IsReleaseConfig)
|
||||
{
|
||||
if ((nFlags & INestedArchive::FLAGS_FULL_VALIDATE) != 0)
|
||||
{
|
||||
initType = ZipDir::InitMethod::FullValidation;
|
||||
}
|
||||
else if ((nFlags & INestedArchive::FLAGS_VALIDATE_HEADERS) != 0)
|
||||
{
|
||||
initType = ZipDir::InitMethod::ValidateHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
ZipDir::CacheFactory factory(initType, nFactoryFlags);
|
||||
|
||||
ZipDir::CachePtr cache = factory.New(szFullPath->c_str());
|
||||
if (cache)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Archive/Codec.h>
|
||||
|
||||
namespace AZ::IO
|
||||
@@ -71,6 +73,13 @@ namespace AZ::IO
|
||||
// multiple times
|
||||
FLAGS_DONT_COMPACT = 1 << 5,
|
||||
|
||||
// if this is set, validate header data when opening the archive
|
||||
FLAGS_VALIDATE_HEADERS = 1 << 9,
|
||||
|
||||
// if this is set, validate header data when opening the archive and validate CRCs when decompressing
|
||||
// & reading files.
|
||||
FLAGS_FULL_VALIDATE = 1 << 10,
|
||||
|
||||
// Disable a pak file without unloading it, this flag is used in combination with patches and multiplayer
|
||||
// to ensure that specific paks stay in the position(to keep the same priority) but being disabled
|
||||
// when running multiplayer
|
||||
@@ -128,6 +137,10 @@ namespace AZ::IO
|
||||
// Deletes all files and directories in the archive.
|
||||
virtual int RemoveAll() = 0;
|
||||
|
||||
// Summary:
|
||||
// Lists all the files in the archive.
|
||||
virtual int ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries) = 0;
|
||||
|
||||
// Summary:
|
||||
// Finds the file; you don't have to close the returned handle.
|
||||
// Returns:
|
||||
|
||||
@@ -89,11 +89,51 @@ namespace AZ::IO
|
||||
return m_pCache->RemoveDir(fullPath);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int NestedArchive::RemoveAll()
|
||||
{
|
||||
return m_pCache->RemoveAll();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helper for 'ListAllFiles' to recursively traverse the FileEntryTree and gather all the files
|
||||
void EnumerateFilesRecursive(AZ::IO::Path currentPath, ZipDir::FileEntryTree* currentTree, AZStd::vector<AZ::IO::Path>& fileList)
|
||||
{
|
||||
// Drill down directories first...
|
||||
for (auto dirIter = currentTree->GetDirBegin(); dirIter != currentTree->GetDirEnd(); ++dirIter)
|
||||
{
|
||||
if (ZipDir::FileEntryTree* subTree = currentTree->GetDirEntry(dirIter);
|
||||
subTree != nullptr)
|
||||
{
|
||||
EnumerateFilesRecursive(currentPath / currentTree->GetDirName(dirIter), subTree, fileList);
|
||||
}
|
||||
}
|
||||
|
||||
// Then enumerate the files in current directory...
|
||||
for (auto fileIter = currentTree->GetFileBegin(); fileIter != currentTree->GetFileEnd(); ++fileIter)
|
||||
{
|
||||
fileList.emplace_back(currentPath / currentTree->GetFileName(fileIter));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// lists all files in the archive
|
||||
int NestedArchive::ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries)
|
||||
{
|
||||
AZStd::vector<AZ::IO::Path> filesInArchive;
|
||||
|
||||
ZipDir::FileEntryTree* tree = m_pCache->GetRoot();
|
||||
if (!tree)
|
||||
{
|
||||
return ZipDir::ZD_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
EnumerateFilesRecursive(AZ::IO::Path{ AZ::IO::PosixPathSeparator }, tree, filesInArchive);
|
||||
|
||||
AZStd::swap(outFileEntries, filesInArchive);
|
||||
return ZipDir::ZD_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Adds a new file to the zip or update an existing one
|
||||
// adds a directory (creates several nested directories if needed)
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AZ::IO
|
||||
|
||||
NestedArchive(IArchive* pArchive, AZStd::string_view strBindRoot, ZipDir::CachePtr pCache, uint32_t nFlags = 0);
|
||||
~NestedArchive() override;
|
||||
|
||||
|
||||
auto GetRootFolderHandle() -> Handle override;
|
||||
|
||||
// Adds a new file to the zip or update an existing one
|
||||
@@ -68,6 +68,9 @@ namespace AZ::IO
|
||||
// deletes all files from the archive
|
||||
int RemoveAll() override;
|
||||
|
||||
// lists all the files in the archive
|
||||
int ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries) override;
|
||||
|
||||
// finds the file; you don't have to close the returned handle
|
||||
Handle FindFile(AZStd::string_view szRelativePath) override;
|
||||
|
||||
@@ -79,7 +82,6 @@ namespace AZ::IO
|
||||
|
||||
// returns the full path to the archive file
|
||||
AZ::IO::PathView GetFullPath() const override;
|
||||
ZipDir::Cache* GetCache();
|
||||
|
||||
uint32_t GetFlags() const override;
|
||||
bool SetFlags(uint32_t nFlagsToSet) override;
|
||||
@@ -87,12 +89,15 @@ namespace AZ::IO
|
||||
|
||||
bool SetPackAccessible(bool bAccessible) override;
|
||||
|
||||
ZipDir::Cache* GetCache();
|
||||
|
||||
protected:
|
||||
// returns the pointer to the relative file path to be passed
|
||||
// to the underlying Cache pointer. Uses the given buffer to construct the path.
|
||||
// returns nullptr if the file path is invalid
|
||||
AZ::IO::FixedMaxPathString AdjustPath(AZStd::string_view szRelativePath);
|
||||
|
||||
|
||||
ZipDir::CachePtr m_pCache;
|
||||
// the binding root may be empty string - in this case, the absolute path binding won't work
|
||||
AZ::IO::Path m_strBindRoot;
|
||||
|
||||
@@ -101,10 +101,11 @@ namespace AZ::IO::ZipDir
|
||||
FileEntry* operator -> () { return m_pFileEntry; }
|
||||
FileEntryTransactionAdd(Cache* pCache, AZStd::string_view szRelativePath)
|
||||
: m_pCache(pCache)
|
||||
, m_szRelativePath(AZ::IO::PosixPathSeparator)
|
||||
, m_bCommitted(false)
|
||||
{
|
||||
// Update the cache string pool with the relative path to the file
|
||||
auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath).LexicallyNormal());
|
||||
auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath, AZ::IO::PosixPathSeparator).LexicallyNormal());
|
||||
m_szRelativePath = *pathIt.first;
|
||||
// this is the name of the directory - create it or find it
|
||||
m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath.Native());
|
||||
@@ -740,6 +741,16 @@ namespace AZ::IO::ZipDir
|
||||
{
|
||||
return ZD_ERROR_CORRUPTED_DATA;
|
||||
}
|
||||
if (pFileEntry->bCheckCRCNextRead)
|
||||
{
|
||||
pFileEntry->bCheckCRCNextRead = false;
|
||||
uLong uCRC32 = AZ::Crc32((Bytef*)pUncompressed, nSizeUncompressed);
|
||||
if (uCRC32 != pFileEntry->desc.lCRC32)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_CRC32_CHECK: Uncompressed stream CRC32 check failed");
|
||||
return ZD_ERROR_CRC32_CHECK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Memory/PoolAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzFramework/Archive/Codec.h>
|
||||
#include <AzFramework/Archive/ZipDirStructures.h>
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace AZ::IO::ZipDir
|
||||
// this sets the window size of the blocks of data read from the end of the file to find the Central Directory Record
|
||||
// since normally there are no
|
||||
static constexpr size_t CDRSearchWindowSize = 0x100;
|
||||
CacheFactory::CacheFactory(InitMethodEnum nInitMethod, uint32_t nFlags)
|
||||
CacheFactory::CacheFactory(InitMethod nInitMethod, uint32_t nFlags)
|
||||
{
|
||||
m_nCDREndPos = 0;
|
||||
m_bBuildFileEntryMap = false; // we only need it for validation/debugging
|
||||
@@ -448,7 +448,6 @@ namespace AZ::IO::ZipDir
|
||||
// builds up the m_mapFileEntries
|
||||
bool CacheFactory::BuildFileEntryMap()
|
||||
{
|
||||
|
||||
Seek(m_CDREnd.lCDROffset);
|
||||
|
||||
if (m_CDREnd.lCDRSize == 0)
|
||||
@@ -530,14 +529,6 @@ namespace AZ::IO::ZipDir
|
||||
{
|
||||
// Add this file entry.
|
||||
char* str = reinterpret_cast<char*>(pFileName);
|
||||
for (int i = 0; i < pFile->nFileNameLength; i++)
|
||||
{
|
||||
str[i] = std::tolower(str[i], std::locale());
|
||||
if (str[i] == AZ_WRONG_FILESYSTEM_SEPARATOR)
|
||||
{
|
||||
str[i] = AZ_CORRECT_FILESYSTEM_SEPARATOR;
|
||||
}
|
||||
}
|
||||
str[pFile->nFileNameLength] = 0; // Not standard!, may overwrite signature of the next memory record data in zip.
|
||||
AddFileEntry(str, pFile, extra);
|
||||
}
|
||||
@@ -574,11 +565,7 @@ namespace AZ::IO::ZipDir
|
||||
|
||||
FileEntryBase fileEntry(*pFileHeader, extra);
|
||||
|
||||
// when using encrypted headers we should always initialize data offsets from CDR
|
||||
if ((m_encryptedHeaders != ZipFile::HEADERS_NOT_ENCRYPTED || m_nInitMethod >= ZD_INIT_FULL) && pFileHeader->desc.lSizeCompressed)
|
||||
{
|
||||
InitDataOffset(fileEntry, pFileHeader);
|
||||
}
|
||||
InitDataOffset(fileEntry, pFileHeader);
|
||||
|
||||
if (m_bBuildFileEntryMap)
|
||||
{
|
||||
@@ -606,142 +593,81 @@ namespace AZ::IO::ZipDir
|
||||
{
|
||||
Seek(pFileHeader->lLocalHeaderOffset);
|
||||
|
||||
// read the local file header and the name (for validation) into the buffer
|
||||
AZStd::vector<char>pBuffer;
|
||||
uint32_t nBufferLength = sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength;
|
||||
pBuffer.resize(nBufferLength);
|
||||
Read(&pBuffer[0], nBufferLength);
|
||||
// Read only the LocalFileHeader w/ no additional bytes ('name' or 'extra' fields)
|
||||
AZStd::vector<char> buffer;
|
||||
uint32_t bufferLen = sizeof(ZipFile::LocalFileHeader);
|
||||
buffer.resize_no_construct(bufferLen);
|
||||
Read(buffer.data(), bufferLen);
|
||||
|
||||
// validate the local file header (compare with the CDR file header - they should contain basically the same information)
|
||||
const auto* pLocalFileHeader = reinterpret_cast<const ZipFile::LocalFileHeader*>(&pBuffer[0]);
|
||||
if (pFileHeader->desc != pLocalFileHeader->desc
|
||||
|| pFileHeader->nMethod != pLocalFileHeader->nMethod
|
||||
|| pFileHeader->nFileNameLength != pLocalFileHeader->nFileNameLength
|
||||
// for a tough validation, we can compare the timestamps of the local and central directory entries
|
||||
// but we won't do that for backward compatibility with ZipDir
|
||||
//|| pFileHeader->nLastModDate != pLocalFileHeader->nLastModDate
|
||||
//|| pFileHeader->nLastModTime != pLocalFileHeader->nLastModTime
|
||||
)
|
||||
const auto* localFileHeader = reinterpret_cast<const ZipFile::LocalFileHeader*>(buffer.data());
|
||||
|
||||
// set the correct file data offset...
|
||||
fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) +
|
||||
localFileHeader->nFileNameLength + localFileHeader->nExtraFieldLength;
|
||||
|
||||
fileEntry.nEOFOffset = fileEntry.nFileDataOffset + fileEntry.desc.lSizeCompressed;
|
||||
|
||||
if (m_nInitMethod != ZipDir::InitMethod::Default)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
|
||||
" The local file header descriptor doesn't match the basic parameters declared in the global file header in the file."
|
||||
" The archive content is misconsistent and may be damaged. Please try to repair the archive");
|
||||
return;
|
||||
if (m_nInitMethod == ZipDir::InitMethod::FullValidation)
|
||||
{
|
||||
// Mark the FileEntry to check CRC when the next read occurs
|
||||
fileEntry.bCheckCRCNextRead = true;
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
if (pFileHeader->nLastModDate != localFileHeader->nLastModDate
|
||||
|| pFileHeader->nLastModTime != localFileHeader->nLastModTime)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
|
||||
" The local file header's modification timestamps don't match that of the global file header in the archive."
|
||||
" The archive timestamps are inconsistent and may be damaged. Check the archive file.", m_szFilename.c_str());
|
||||
// don't return here, it may be ok.
|
||||
}
|
||||
|
||||
// Validate data
|
||||
if (pFileHeader->desc != localFileHeader->desc // this checks CRCs and compressed/uncompressed sizes
|
||||
|| pFileHeader->nMethod != localFileHeader->nMethod
|
||||
|| pFileHeader->nFileNameLength != localFileHeader->nFileNameLength)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
|
||||
" The local file header descriptor doesn't match basic parameters declared in the global file header in the file."
|
||||
" The archive content is inconsistent and may be damaged. Please try to repair the archive.", m_szFilename.c_str());
|
||||
// return here because further checks aren't worse than this.
|
||||
return;
|
||||
}
|
||||
|
||||
// Read extra data
|
||||
uint32_t extraDataLen = localFileHeader->nFileNameLength + localFileHeader->nExtraFieldLength;
|
||||
buffer.resize_no_construct(buffer.size() + extraDataLen);
|
||||
Read(buffer.data() + buffer.size(), extraDataLen);
|
||||
|
||||
// Compare local file name with the CDR file name, they should match
|
||||
AZStd::string_view zipFileName{ buffer.data() + sizeof(ZipFile::LocalFileHeader), localFileHeader->nFileNameLength };
|
||||
AZStd::string_view cdrFileName{ reinterpret_cast<const char*>(pFileHeader + 1), pFileHeader->nFileNameLength };
|
||||
if (zipFileName != cdrFileName)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
|
||||
" The file name in the local file header doesn't match the name in the global file header."
|
||||
" The archive content is inconsisten with the directory. Please check the archive.", m_szFilename.c_str());
|
||||
}
|
||||
|
||||
// CDR and local "extra field" lengths may be different, should we compare them if they are equal?
|
||||
|
||||
// make sure it's the same file and the fileEntry structure is properly initialized
|
||||
AZ_Assert(fileEntry.nFileHeaderOffset == pFileHeader->lLocalHeaderOffset,
|
||||
"The file entry header offset doesn't match the file header local offst (%s)", m_szFilename.c_str());
|
||||
|
||||
if (fileEntry.nFileDataOffset >= m_nCDREndPos)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
|
||||
" The global file header declares the file which crosses the boundaries of the archive."
|
||||
" The archive is either corrupted or truncated, please try to repair it", m_szFilename.c_str());
|
||||
}
|
||||
|
||||
// End Validation
|
||||
}
|
||||
|
||||
// now compare the local file name with the one recorded in CDR: they must match.
|
||||
auto CompareNoCase = [](const char lhs, const char rhs) { return std::tolower(lhs, std::locale()) == std::tolower(rhs, std::locale()); };
|
||||
auto zipFileDataBegin = pBuffer.begin() + sizeof(ZipFile::LocalFileHeader);
|
||||
auto zipFileDataEnd = zipFileDataBegin + pFileHeader->nFileNameLength;
|
||||
if (!AZStd::equal(zipFileDataBegin, zipFileDataEnd, reinterpret_cast<const char*>(pFileHeader + 1), CompareNoCase))
|
||||
{
|
||||
// either file name, or the extra field do not match
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
|
||||
" The local file header contains file name which does not match the file name of the global file header."
|
||||
" The archive content is misconsistent with its directory. Please repair the archive");
|
||||
return;
|
||||
}
|
||||
|
||||
fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pLocalFileHeader->nFileNameLength + pLocalFileHeader->nExtraFieldLength;
|
||||
}
|
||||
|
||||
// make sure it's the same file and the fileEntry structure is properly initialized
|
||||
AZ_Assert(fileEntry.nFileHeaderOffset == pFileHeader->lLocalHeaderOffset, "The file entry header offset doesn't match the file header local offst");
|
||||
|
||||
fileEntry.nEOFOffset = fileEntry.nFileDataOffset + fileEntry.desc.lSizeCompressed;
|
||||
|
||||
if (fileEntry.nFileDataOffset >= m_nCDREndPos)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
|
||||
" The global file header declares the file which crosses the boundaries of the archive."
|
||||
" The archive is either corrupted or truncated, please try to repair it");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_nInitMethod >= ZD_INIT_VALIDATE)
|
||||
{
|
||||
Validate(fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// reads the file pointed by the given header and entry (they must be coherent)
|
||||
// and decompresses it; then calculates and validates its CRC32
|
||||
void CacheFactory::Validate(const FileEntryBase& fileEntry)
|
||||
{
|
||||
AZStd::vector<char> pBuffer;
|
||||
// validate the file contents
|
||||
// allocate memory for both the compressed data and uncompressed data
|
||||
pBuffer.resize(fileEntry.desc.lSizeCompressed + fileEntry.desc.lSizeUncompressed);
|
||||
char* pUncompressed = &pBuffer[fileEntry.desc.lSizeCompressed];
|
||||
char* pCompressed = &pBuffer[0];
|
||||
|
||||
AZ_Assert(fileEntry.nFileDataOffset != FileEntry::INVALID_DATA_OFFSET, "File entry has invalid data offset of %" PRIx32, FileEntry::INVALID_DATA_OFFSET);
|
||||
Seek(fileEntry.nFileDataOffset);
|
||||
|
||||
Read(pCompressed, fileEntry.desc.lSizeCompressed);
|
||||
|
||||
size_t nDestSize = fileEntry.desc.lSizeUncompressed;
|
||||
int nError = Z_OK;
|
||||
if (fileEntry.nMethod)
|
||||
{
|
||||
nError = ZipRawUncompress(pUncompressed, &nDestSize, pCompressed, fileEntry.desc.lSizeCompressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(fileEntry.desc.lSizeCompressed == fileEntry.desc.lSizeUncompressed, "Uncompressed file does not have the same commpressed %u and uncompressed file sizes %u",
|
||||
fileEntry.desc.lSizeCompressed, fileEntry.desc.lSizeUncompressed);
|
||||
memcpy(pUncompressed, pCompressed, fileEntry.desc.lSizeUncompressed);
|
||||
}
|
||||
switch (nError)
|
||||
{
|
||||
case Z_OK:
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_NO_MEMORY: ZLib reported out-of-memory error");
|
||||
return;
|
||||
case Z_BUF_ERROR:
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream buffer error");
|
||||
return;
|
||||
case Z_DATA_ERROR:
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream data error");
|
||||
return;
|
||||
default:
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_FAILED: ZLib reported an unexpected unknown error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nDestSize != fileEntry.desc.lSizeUncompressed)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_CORRUPTED_DATA: Uncompressed stream doesn't match the size of uncompressed file stored in the archive file headers");
|
||||
return;
|
||||
}
|
||||
|
||||
uLong uCRC32 = AZ::Crc32((Bytef*)pUncompressed, nDestSize);
|
||||
if (uCRC32 != fileEntry.desc.lCRC32)
|
||||
{
|
||||
AZ_Warning("Archive", false, "ZD_ERROR_CRC32_CHECK: Uncompressed stream CRC32 check failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* CacheFactory::GetFilePath(const char* pFileName, uint16_t nFileNameLength)
|
||||
{
|
||||
static char strResult[AZ_MAX_PATH_LEN];
|
||||
AZ_Assert(nFileNameLength < AZ_MAX_PATH_LEN, "Only filenames shorter than %zu can be copied from filename parameter", AZ_MAX_PATH_LEN);
|
||||
memcpy(strResult, pFileName, nFileNameLength);
|
||||
strResult[nFileNameLength] = 0;
|
||||
for (int i = 0; i < nFileNameLength; i++)
|
||||
{
|
||||
strResult[i] = std::tolower(strResult[i], std::locale{});
|
||||
}
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
// seeks in the file relative to the starting position
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AZ::IO::ZipDir
|
||||
|
||||
// initializes the internal structures
|
||||
// nFlags can have FLAGS_READ_ONLY flag, in this case the object will be opened only for reading
|
||||
CacheFactory(InitMethodEnum nInitMethod, uint32_t nFlags = 0);
|
||||
CacheFactory(InitMethod nInitMethod, uint32_t nFlags = 0);
|
||||
~CacheFactory();
|
||||
|
||||
// the new function creates a new cache
|
||||
@@ -66,28 +66,6 @@ namespace AZ::IO::ZipDir
|
||||
// This function can actually modify strFilePath variable, make sure you use a copy of the real path.
|
||||
void AddFileEntry(char* strFilePath, const ZipFile::CDRFileHeader* pFileHeader, const SExtraZipFileData& extra);// throw (ErrorEnum);
|
||||
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath(const ZipFile::CDRFileHeader* pFileHeader)
|
||||
{
|
||||
return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
|
||||
}
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath(const ZipFile::LocalFileHeader* pFileHeader)
|
||||
{
|
||||
return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
|
||||
}
|
||||
// extracts the file path from the file header with subsequent information
|
||||
// may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
|
||||
// it's the responsibility of the caller to ensure that the file name is in readable valid memory
|
||||
char* GetFilePath(const char* pFileName, uint16_t nFileNameLength);
|
||||
|
||||
// validates (if the init method has the corresponding value) the given file/header
|
||||
void Validate(const FileEntryBase& fileEntry);
|
||||
|
||||
// initializes the actual data offset in the file in the fileEntry structure
|
||||
// searches to the local file header, reads it and calculates the actual offset in the file
|
||||
void InitDataOffset(FileEntryBase& fileEntry, const ZipFile::CDRFileHeader* pFileHeader);
|
||||
@@ -104,7 +82,7 @@ namespace AZ::IO::ZipDir
|
||||
AZStd::string m_szFilename;
|
||||
CZipFile m_fileExt;
|
||||
|
||||
InitMethodEnum m_nInitMethod;
|
||||
InitMethod m_nInitMethod;
|
||||
uint32_t m_nFlags;
|
||||
ZipFile::CDREnd m_CDREnd;
|
||||
|
||||
@@ -129,7 +107,7 @@ namespace AZ::IO::ZipDir
|
||||
ZipFile::CryCustomEncryptionHeader m_headerEncryption;
|
||||
ZipFile::CrySignedCDRHeader m_headerSignature;
|
||||
ZipFile::CryCustomExtendedHeader m_headerExtended;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -68,14 +68,14 @@ namespace AZ::IO::ZipDir
|
||||
{
|
||||
for (FileEntryTree::SubdirMap::iterator it = pTree->GetDirBegin(); it != pTree->GetDirEnd(); ++it)
|
||||
{
|
||||
AddAllFiles(it->second.get(), (AZ::IO::Path(strRoot) / it->first).Native());
|
||||
AddAllFiles(it->second.get(), (AZ::IO::Path(strRoot, AZ::IO::PosixPathSeparator) / it->first).Native());
|
||||
}
|
||||
|
||||
for (FileEntryTree::FileMap::iterator it = pTree->GetFileBegin(); it != pTree->GetFileEnd(); ++it)
|
||||
{
|
||||
FileRecord rec;
|
||||
rec.pFileEntryBase = pTree->GetFileEntry(it);
|
||||
rec.strPath = (AZ::IO::Path(strRoot) / it->first).Native();
|
||||
rec.strPath = (AZ::IO::Path(strRoot, AZ::IO::PosixPathSeparator) / it->first).Native();
|
||||
push_back(rec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,19 +119,28 @@ namespace AZ::IO::ZipDir
|
||||
const char* m_szDescription;
|
||||
};
|
||||
|
||||
#if defined(_RELEASE)
|
||||
inline static constexpr bool IsReleaseConfig{ true };
|
||||
#else
|
||||
inline static constexpr bool IsReleaseConfig{};
|
||||
#endif // _RELEASE
|
||||
|
||||
// possible initialization methods
|
||||
enum InitMethodEnum
|
||||
enum class InitMethod
|
||||
{
|
||||
// initialize as fast as possible, with minimal validation
|
||||
ZD_INIT_FAST,
|
||||
// after initialization, scan through all file headers, precache the actual file data offset values and validate the headers
|
||||
ZD_INIT_FULL,
|
||||
// scan all file headers and try to decompress the data, searching for corrupted files
|
||||
ZD_INIT_VALIDATE_IN_MEMORY,
|
||||
// store archive in memory
|
||||
ZD_INIT_VALIDATE,
|
||||
// maximum level of validation, checks for integrity of the archive
|
||||
ZD_INIT_VALIDATE_MAX = ZD_INIT_VALIDATE
|
||||
// initializes without any sort of extra validation steps
|
||||
Default,
|
||||
|
||||
// initializes with extra validation steps
|
||||
// not available in RELEASE
|
||||
// will check CDR and local headers data match
|
||||
ValidateHeaders,
|
||||
|
||||
// initializes with extra validation steps
|
||||
// not available in RELEASE
|
||||
// will check CDR and local headers data match
|
||||
// will check file data CRC matches (when file is read)
|
||||
FullValidation,
|
||||
};
|
||||
|
||||
// Uncompresses raw (without wrapping) data that is compressed with method 8 (deflated) in the Zip file
|
||||
@@ -184,7 +193,11 @@ namespace AZ::IO::ZipDir
|
||||
// the offset to the start of the next file's header - this
|
||||
// can be used to calculate the available space in zip file
|
||||
uint32_t nEOFOffset{};
|
||||
|
||||
// whether to check the CRC upon the next data read
|
||||
bool bCheckCRCNextRead{};
|
||||
};
|
||||
|
||||
// this is the record about the file in the Zip file.
|
||||
struct FileEntry
|
||||
: FileEntryBase
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/Asset/AssetSeedList.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/Asset/Benchmark/BenchmarkAsset.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Asset/SimpleAsset.h>
|
||||
|
||||
namespace AzFramework
|
||||
@@ -36,4 +37,36 @@ namespace AzFramework
|
||||
|
||||
return "";
|
||||
}
|
||||
void SimpleAssetReferenceBase::Reflect(AZ::ReflectContext *context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SimpleAssetReferenceBase>()
|
||||
->Version(1)
|
||||
->Field("AssetPath", &SimpleAssetReferenceBase::m_assetPath);
|
||||
|
||||
AZ::EditContext* edit = serializeContext->GetEditContext();
|
||||
if (edit)
|
||||
{
|
||||
edit->Class<SimpleAssetReferenceBase>("Asset path", "Asset reference as a project-relative path")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SimpleAssetReferenceBase>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Asset")
|
||||
->Attribute(AZ::Script::Attributes::Module, "asset")
|
||||
->Property("assetPath", &SimpleAssetReferenceBase::GetAssetPath, nullptr)
|
||||
->Property("assetType", &SimpleAssetReferenceBase::GetAssetType, nullptr)
|
||||
->Property("fileFilter", &SimpleAssetReferenceBase::GetFileFilter, nullptr)
|
||||
->Method("SetAssetPath", &SimpleAssetReferenceBase::SetAssetPath)
|
||||
->Attribute(AZ::Script::Attributes::Alias, "set_asset_path")
|
||||
;
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
@@ -74,38 +73,7 @@ namespace AzFramework
|
||||
virtual AZ::Data::AssetType GetAssetType() const = 0;
|
||||
virtual const char* GetFileFilter() const = 0;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SimpleAssetReferenceBase>()
|
||||
->Version(1)
|
||||
->Field("AssetPath", &SimpleAssetReferenceBase::m_assetPath);
|
||||
|
||||
AZ::EditContext* edit = serializeContext->GetEditContext();
|
||||
if (edit)
|
||||
{
|
||||
edit->Class<SimpleAssetReferenceBase>("Asset path", "Asset reference as a project-relative path")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SimpleAssetReferenceBase>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Asset")
|
||||
->Attribute(AZ::Script::Attributes::Module, "asset")
|
||||
->Property("assetPath", &SimpleAssetReferenceBase::GetAssetPath, nullptr)
|
||||
->Property("assetType", &SimpleAssetReferenceBase::GetAssetType, nullptr)
|
||||
->Property("fileFilter", &SimpleAssetReferenceBase::GetFileFilter, nullptr)
|
||||
->Method("SetAssetPath", &SimpleAssetReferenceBase::SetAssetPath)
|
||||
->Attribute(AZ::Script::Attributes::Alias, "set_asset_path")
|
||||
;
|
||||
}
|
||||
}
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
}
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
using EntityContextId = AZ::Uuid;
|
||||
|
||||
@@ -91,15 +91,6 @@ namespace AzFramework
|
||||
*/
|
||||
virtual void DestroyGameEntity(const AZ::EntityId& /*id*/) = 0;
|
||||
|
||||
/**
|
||||
* Destroys an entity only in slice mode (when prefabs are disabled). This request is only added as a stop-gap solution
|
||||
* to prevent the editor from crashing when prefabs are enabled and must only be called through the BehaviorContext binding
|
||||
* for 'DestroyGameEntity'. No code should be written to directly call this method. This will be removed soon.
|
||||
*
|
||||
* @param id The ID of the entity to destroy.
|
||||
*/
|
||||
virtual void DestroyGameEntityOnlyInSliceMode(const AZ::EntityId& /*id*/) = 0;
|
||||
|
||||
/**
|
||||
* Destroys an entity and all of its descendants.
|
||||
* The entity and its descendants are immediately deactivated and will be
|
||||
@@ -108,15 +99,6 @@ namespace AzFramework
|
||||
*/
|
||||
virtual void DestroyGameEntityAndDescendants(const AZ::EntityId& /*id*/) = 0;
|
||||
|
||||
/**
|
||||
* Destroys an entity and its descendants only in slice mode (when prefabs are disabled). This request is only added as a stop-gap
|
||||
* solution to prevent the editor from crashing when prefabs are enabled and must only be called through the BehaviorContext
|
||||
* binding for 'DestroyGameEntityAndDescendants'.No code should be written to directly call this method. This will be removed soon.
|
||||
*
|
||||
* @param id The ID of the entity to destroy.
|
||||
*/
|
||||
virtual void DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId& /*id*/) = 0;
|
||||
|
||||
/**
|
||||
* Activates the game entity.
|
||||
* @param id The ID of the entity to activate.
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
|
||||
|
||||
#include "GameEntityContextComponent.h"
|
||||
|
||||
@@ -47,9 +48,9 @@ namespace AzFramework
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Event("CreateGameEntity", &GameEntityContextRequestBus::Events::CreateGameEntityForBehaviorContext)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Event("DestroyGameEntity", &GameEntityContextRequestBus::Events::DestroyGameEntityOnlyInSliceMode)
|
||||
->Event("DestroyGameEntity", &GameEntityContextRequestBus::Events::DestroyGameEntity)
|
||||
->Event(
|
||||
"DestroyGameEntityAndDescendants", &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendantsOnlyInSliceMode)
|
||||
"DestroyGameEntityAndDescendants", &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants)
|
||||
->Event("ActivateGameEntity", &GameEntityContextRequestBus::Events::ActivateGameEntity)
|
||||
->Event("DeactivateGameEntity", &GameEntityContextRequestBus::Events::DeactivateGameEntity)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::DeactivatesInputEntity, true)
|
||||
@@ -249,23 +250,6 @@ namespace AzFramework
|
||||
DestroyGameEntityInternal(id, false);
|
||||
}
|
||||
|
||||
void GameEntityContextComponent::DestroyGameEntityOnlyInSliceMode(const AZ::EntityId& id)
|
||||
{
|
||||
bool isPrefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (!isPrefabSystemEnabled)
|
||||
{
|
||||
DestroyGameEntityInternal(id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"GameEntityContextComponent", false,
|
||||
"Destroying a game entity is temporarily disabled until the Spawnable system can support this.");
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GameEntityContextComponent::DestroyGameEntityAndDescendantsById
|
||||
//=========================================================================
|
||||
@@ -274,24 +258,6 @@ namespace AzFramework
|
||||
DestroyGameEntityInternal(id, true);
|
||||
}
|
||||
|
||||
|
||||
void GameEntityContextComponent::DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId& id)
|
||||
{
|
||||
bool isPrefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (!isPrefabSystemEnabled)
|
||||
{
|
||||
DestroyGameEntityInternal(id, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"GameEntityContextComponent", false,
|
||||
"Destroying a game entity and its descendants is temporarily disabled until the Spawnable system can support this.");
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// GameEntityContextComponent::DestroyGameEntityInternal
|
||||
//=========================================================================
|
||||
@@ -319,6 +285,28 @@ namespace AzFramework
|
||||
EBUS_EVENT_RESULT(currentEntity, AZ::ComponentApplicationBus, FindEntity, *entityIdIter);
|
||||
if (currentEntity)
|
||||
{
|
||||
bool isPrefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabSystemEnabled)
|
||||
{
|
||||
if (currentEntity->GetSpawnTicketId() > 0)
|
||||
{
|
||||
SpawnableEntitiesDefinition* spawnableEntitiesInterface = SpawnableEntitiesInterface::Get();
|
||||
AZ_Assert(spawnableEntitiesInterface != nullptr, "SpawnableEntitiesInterface is not found.");
|
||||
spawnableEntitiesInterface->RetrieveEntitySpawnTicket(
|
||||
currentEntity->GetSpawnTicketId(),
|
||||
[spawnableEntitiesInterface, currentEntity](EntitySpawnTicket* entitySpawnTicket)
|
||||
{
|
||||
if (entitySpawnTicket != nullptr)
|
||||
{
|
||||
spawnableEntitiesInterface->DespawnEntity(currentEntity->GetId(), *entitySpawnTicket);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentEntity->GetState() == AZ::Entity::State::Active)
|
||||
{
|
||||
// Deactivate the entity, we'll destroy it as soon as it is safe.
|
||||
|
||||
@@ -90,11 +90,6 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GameEntityContextRequestBus
|
||||
void DestroyGameEntityOnlyInSliceMode(const AZ::EntityId&) override;
|
||||
void DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId&) override;
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AzFramework::EntityVisibilityBoundsUnionSystem m_entityVisibilityBoundsUnionSystem;
|
||||
};
|
||||
|
||||
@@ -28,34 +28,10 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId::InputChannelId(const char* name)
|
||||
: m_crc32(name)
|
||||
{
|
||||
memset(m_name, 0, AZ_ARRAY_SIZE(m_name));
|
||||
azstrncpy(m_name, NAME_BUFFER_SIZE, name, MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId::InputChannelId(const InputChannelId& other)
|
||||
: m_crc32(other.m_crc32)
|
||||
{
|
||||
memset(m_name, 0, AZ_ARRAY_SIZE(m_name));
|
||||
azstrcpy(m_name, NAME_BUFFER_SIZE, other.m_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputChannelId& InputChannelId::operator=(const InputChannelId& other)
|
||||
{
|
||||
azstrcpy(m_name, NAME_BUFFER_SIZE, other.m_name);
|
||||
m_crc32 = other.m_crc32;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const char* InputChannelId::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/hash.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
@@ -22,8 +23,7 @@ namespace AzFramework
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
static const int NAME_BUFFER_SIZE = 64;
|
||||
static const int MAX_NAME_LENGTH = NAME_BUFFER_SIZE - 1;
|
||||
static constexpr int MAX_NAME_LENGTH = 64;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
@@ -39,21 +39,28 @@ namespace AzFramework
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
//! \param[in] name Name of the input channel (will be truncated if exceeds MAX_NAME_LENGTH)
|
||||
explicit InputChannelId(const char* name = "");
|
||||
//! \param[in] name Name of the input channel (will be ignored if exceeds MAX_NAME_LENGTH)
|
||||
explicit constexpr InputChannelId(AZStd::string_view name = "")
|
||||
: m_name(name)
|
||||
, m_crc32(name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Copy constructor
|
||||
//! \param[in] other Another instance of the class to copy from
|
||||
InputChannelId(const InputChannelId& other);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Copy assignment operator
|
||||
//! \param[in] other Another instance of the class to copy from
|
||||
InputChannelId& operator=(const InputChannelId& other);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Default destructor
|
||||
constexpr InputChannelId(const InputChannelId& other) = default;
|
||||
constexpr InputChannelId(InputChannelId&& other) = default;
|
||||
constexpr InputChannelId& operator=(const InputChannelId& other)
|
||||
{
|
||||
m_name = other.m_name;
|
||||
m_crc32 = other.m_crc32;
|
||||
return *this;
|
||||
}
|
||||
constexpr InputChannelId& operator=(InputChannelId&& other)
|
||||
{
|
||||
m_name = AZStd::move(other.m_name);
|
||||
m_crc32 = AZStd::move(other.m_crc32);
|
||||
other.m_crc32 = 0;
|
||||
return *this;
|
||||
}
|
||||
~InputChannelId() = default;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -77,7 +84,7 @@ namespace AzFramework
|
||||
private:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
char m_name[NAME_BUFFER_SIZE]; //!< Name of the input channel
|
||||
AZStd::fixed_string<MAX_NAME_LENGTH> m_name; //!< Name of the input channel
|
||||
AZ::Crc32 m_crc32; //!< Crc32 of the input channel
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -28,91 +28,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == IdForIndex0.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::Button::A("gamepad_button_a");
|
||||
const InputChannelId InputDeviceGamepad::Button::B("gamepad_button_b");
|
||||
const InputChannelId InputDeviceGamepad::Button::X("gamepad_button_x");
|
||||
const InputChannelId InputDeviceGamepad::Button::Y("gamepad_button_y");
|
||||
const InputChannelId InputDeviceGamepad::Button::L1("gamepad_button_l1");
|
||||
const InputChannelId InputDeviceGamepad::Button::R1("gamepad_button_r1");
|
||||
const InputChannelId InputDeviceGamepad::Button::L3("gamepad_button_l3");
|
||||
const InputChannelId InputDeviceGamepad::Button::R3("gamepad_button_r3");
|
||||
const InputChannelId InputDeviceGamepad::Button::DU("gamepad_button_d_up");
|
||||
const InputChannelId InputDeviceGamepad::Button::DD("gamepad_button_d_down");
|
||||
const InputChannelId InputDeviceGamepad::Button::DL("gamepad_button_d_left");
|
||||
const InputChannelId InputDeviceGamepad::Button::DR("gamepad_button_d_right");
|
||||
const InputChannelId InputDeviceGamepad::Button::Start("gamepad_button_start");
|
||||
const InputChannelId InputDeviceGamepad::Button::Select("gamepad_button_select");
|
||||
const AZStd::array<InputChannelId, 14> InputDeviceGamepad::Button::All =
|
||||
{{
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L1,
|
||||
R1,
|
||||
L3,
|
||||
R3,
|
||||
DU,
|
||||
DD,
|
||||
DL,
|
||||
DR,
|
||||
Start,
|
||||
Select
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::Trigger::L2("gamepad_trigger_l2");
|
||||
const InputChannelId InputDeviceGamepad::Trigger::R2("gamepad_trigger_r2");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceGamepad::Trigger::All =
|
||||
{{
|
||||
L2,
|
||||
R2
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis2D::L("gamepad_thumbstick_l");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis2D::R("gamepad_thumbstick_r");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceGamepad::ThumbStickAxis2D::All =
|
||||
{{
|
||||
L,
|
||||
R
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::LX("gamepad_thumbstick_l_x");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::LY("gamepad_thumbstick_l_y");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::RX("gamepad_thumbstick_r_x");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickAxis1D::RY("gamepad_thumbstick_r_y");
|
||||
const AZStd::array<InputChannelId, 4> InputDeviceGamepad::ThumbStickAxis1D::All =
|
||||
{{
|
||||
LX,
|
||||
LY,
|
||||
RX,
|
||||
RY
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LU("gamepad_thumbstick_l_up");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LD("gamepad_thumbstick_l_down");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LL("gamepad_thumbstick_l_left");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::LR("gamepad_thumbstick_l_right");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RU("gamepad_thumbstick_r_up");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RD("gamepad_thumbstick_r_down");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RL("gamepad_thumbstick_r_left");
|
||||
const InputChannelId InputDeviceGamepad::ThumbStickDirection::RR("gamepad_thumbstick_r_right");
|
||||
const AZStd::array<InputChannelId, 8> InputDeviceGamepad::ThumbStickDirection::All =
|
||||
{{
|
||||
LU,
|
||||
LD,
|
||||
LL,
|
||||
LR,
|
||||
RU,
|
||||
RD,
|
||||
RL,
|
||||
RR
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceGamepad::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -59,75 +59,115 @@ namespace AzFramework
|
||||
//! All the input channel ids that identify game-pad digital button input
|
||||
struct Button
|
||||
{
|
||||
static const InputChannelId A; //!< The bottom diamond face button
|
||||
static const InputChannelId B; //!< The right diamond face button
|
||||
static const InputChannelId X; //!< The left diamond face button
|
||||
static const InputChannelId Y; //!< The top diamond face button
|
||||
static const InputChannelId L1; //!< The top-left shoulder bumper button
|
||||
static const InputChannelId R1; //!< The top-right shoulder bumper button
|
||||
static const InputChannelId L3; //!< The left thumb-stick click button
|
||||
static const InputChannelId R3; //!< The right thumb-stick click button
|
||||
static const InputChannelId DU; //!< The up directional pad button
|
||||
static const InputChannelId DD; //!< The down directional pad button
|
||||
static const InputChannelId DL; //!< The left directional pad button
|
||||
static const InputChannelId DR; //!< The right directional pad button
|
||||
static const InputChannelId Start; //!< The start/pause/options button
|
||||
static const InputChannelId Select; //!< The select/back button
|
||||
static constexpr inline InputChannelId A{"gamepad_button_a"}; //!< The bottom diamond face button
|
||||
static constexpr inline InputChannelId B{"gamepad_button_b"}; //!< The right diamond face button
|
||||
static constexpr inline InputChannelId X{"gamepad_button_x"}; //!< The left diamond face button
|
||||
static constexpr inline InputChannelId Y{"gamepad_button_y"}; //!< The top diamond face button
|
||||
static constexpr inline InputChannelId L1{"gamepad_button_l1"}; //!< The top-left shoulder bumper button
|
||||
static constexpr inline InputChannelId R1{"gamepad_button_r1"}; //!< The top-right shoulder bumper button
|
||||
static constexpr inline InputChannelId L3{"gamepad_button_l3"}; //!< The left thumb-stick click button
|
||||
static constexpr inline InputChannelId R3{"gamepad_button_r3"}; //!< The right thumb-stick click button
|
||||
static constexpr inline InputChannelId DU{"gamepad_button_d_up"}; //!< The up directional pad button
|
||||
static constexpr inline InputChannelId DD{"gamepad_button_d_down"}; //!< The down directional pad button
|
||||
static constexpr inline InputChannelId DL{"gamepad_button_d_left"}; //!< The left directional pad button
|
||||
static constexpr inline InputChannelId DR{"gamepad_button_d_right"}; //!< The right directional pad button
|
||||
static constexpr inline InputChannelId Start{"gamepad_button_start"}; //!< The start/pause/options button
|
||||
static constexpr inline InputChannelId Select{"gamepad_button_select"}; //!< The select/back button
|
||||
|
||||
//!< All digital game-pad button ids
|
||||
static const AZStd::array<InputChannelId, 14> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L1,
|
||||
R1,
|
||||
L3,
|
||||
R3,
|
||||
DU,
|
||||
DD,
|
||||
DL,
|
||||
DR,
|
||||
Start,
|
||||
Select
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad analog trigger input
|
||||
struct Trigger
|
||||
{
|
||||
static const InputChannelId L2; //!< The bottom-left shoulder trigger
|
||||
static const InputChannelId R2; //!< The bottom-right shoulder trigger
|
||||
static constexpr inline InputChannelId L2{"gamepad_trigger_l2"}; //!< The bottom-left shoulder trigger
|
||||
static constexpr inline InputChannelId R2{"gamepad_trigger_r2"}; //!< The bottom-right shoulder trigger
|
||||
|
||||
//!< All analog game-pad trigger ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
L2,
|
||||
R2
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick 2D axis input
|
||||
struct ThumbStickAxis2D
|
||||
{
|
||||
static const InputChannelId L; //!< The left-hand thumb-stick
|
||||
static const InputChannelId R; //!< The right-hand thumb-stick
|
||||
static constexpr inline InputChannelId L{"gamepad_thumbstick_l"}; //!< The left-hand thumb-stick
|
||||
static constexpr inline InputChannelId R{"gamepad_thumbstick_r"}; //!< The right-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick 2D axis input channel ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
L,
|
||||
R
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick 1D axis input
|
||||
struct ThumbStickAxis1D
|
||||
{
|
||||
static const InputChannelId LX; //!< X-axis of the left-hand thumb-stick
|
||||
static const InputChannelId LY; //!< Y-axis of the left-hand thumb-stick
|
||||
static const InputChannelId RX; //!< X-axis of the right-hand thumb-stick
|
||||
static const InputChannelId RY; //!< Y-axis of the right-hand thumb-stick
|
||||
static constexpr inline InputChannelId LX{"gamepad_thumbstick_l_x"}; //!< X-axis of the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LY{"gamepad_thumbstick_l_y"}; //!< Y-axis of the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RX{"gamepad_thumbstick_r_x"}; //!< X-axis of the right-hand thumb-stick
|
||||
static constexpr inline InputChannelId RY{"gamepad_thumbstick_r_y"}; //!< Y-axis of the right-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick 1D axis input channel ids
|
||||
static const AZStd::array<InputChannelId, 4> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
LX,
|
||||
LY,
|
||||
RX,
|
||||
RY
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! All the input channel ids that identify game-pad thumb-stick directional input
|
||||
struct ThumbStickDirection
|
||||
{
|
||||
static const InputChannelId LU; //!< Up on the left-hand thumb-stick
|
||||
static const InputChannelId LD; //!< Down on the left-hand thumb-stick
|
||||
static const InputChannelId LL; //!< Left on the left-hand thumb-stick
|
||||
static const InputChannelId LR; //!< Right on the left-hand thumb-stick
|
||||
static const InputChannelId RU; //!< Up on the left-hand thumb-stick
|
||||
static const InputChannelId RD; //!< Down on the left-hand thumb-stick
|
||||
static const InputChannelId RL; //!< Left on the left-hand thumb-stick
|
||||
static const InputChannelId RR; //!< Right on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LU{"gamepad_thumbstick_l_up"}; //!< Up on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LD{"gamepad_thumbstick_l_down"}; //!< Down on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LL{"gamepad_thumbstick_l_left"}; //!< Left on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId LR{"gamepad_thumbstick_l_right"}; //!< Right on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RU{"gamepad_thumbstick_r_up"}; //!< Up on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RD{"gamepad_thumbstick_r_down"}; //!< Down on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RL{"gamepad_thumbstick_r_left"}; //!< Left on the left-hand thumb-stick
|
||||
static constexpr inline InputChannelId RR{"gamepad_thumbstick_r_right"}; //!< Right on the left-hand thumb-stick
|
||||
|
||||
//!< All game-pad thumb-stick directional input channel ids
|
||||
static const AZStd::array<InputChannelId, 8> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
LU,
|
||||
LD,
|
||||
LL,
|
||||
LR,
|
||||
RU,
|
||||
RD,
|
||||
RL,
|
||||
RR
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
-273
@@ -24,279 +24,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Alphanumeric Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric0("keyboard_key_alphanumeric_0");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric1("keyboard_key_alphanumeric_1");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric2("keyboard_key_alphanumeric_2");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric3("keyboard_key_alphanumeric_3");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric4("keyboard_key_alphanumeric_4");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric5("keyboard_key_alphanumeric_5");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric6("keyboard_key_alphanumeric_6");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric7("keyboard_key_alphanumeric_7");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric8("keyboard_key_alphanumeric_8");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Alphanumeric9("keyboard_key_alphanumeric_9");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericA("keyboard_key_alphanumeric_A");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericB("keyboard_key_alphanumeric_B");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericC("keyboard_key_alphanumeric_C");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericD("keyboard_key_alphanumeric_D");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericE("keyboard_key_alphanumeric_E");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericF("keyboard_key_alphanumeric_F");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericG("keyboard_key_alphanumeric_G");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericH("keyboard_key_alphanumeric_H");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericI("keyboard_key_alphanumeric_I");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericJ("keyboard_key_alphanumeric_J");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericK("keyboard_key_alphanumeric_K");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericL("keyboard_key_alphanumeric_L");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericM("keyboard_key_alphanumeric_M");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericN("keyboard_key_alphanumeric_N");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericO("keyboard_key_alphanumeric_O");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericP("keyboard_key_alphanumeric_P");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericQ("keyboard_key_alphanumeric_Q");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericR("keyboard_key_alphanumeric_R");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericS("keyboard_key_alphanumeric_S");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericT("keyboard_key_alphanumeric_T");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericU("keyboard_key_alphanumeric_U");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericV("keyboard_key_alphanumeric_V");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericW("keyboard_key_alphanumeric_W");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericX("keyboard_key_alphanumeric_X");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericY("keyboard_key_alphanumeric_Y");
|
||||
const InputChannelId InputDeviceKeyboard::Key::AlphanumericZ("keyboard_key_alphanumeric_Z");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Edit (and escape) Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditBackspace("keyboard_key_edit_backspace");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditCapsLock("keyboard_key_edit_capslock");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditEnter("keyboard_key_edit_enter");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditSpace("keyboard_key_edit_space");
|
||||
const InputChannelId InputDeviceKeyboard::Key::EditTab("keyboard_key_edit_tab");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Escape("keyboard_key_escape");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function01("keyboard_key_function_F01");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function02("keyboard_key_function_F02");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function03("keyboard_key_function_F03");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function04("keyboard_key_function_F04");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function05("keyboard_key_function_F05");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function06("keyboard_key_function_F06");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function07("keyboard_key_function_F07");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function08("keyboard_key_function_F08");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function09("keyboard_key_function_F09");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function10("keyboard_key_function_F10");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function11("keyboard_key_function_F11");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function12("keyboard_key_function_F12");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function13("keyboard_key_function_F13");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function14("keyboard_key_function_F14");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function15("keyboard_key_function_F15");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function16("keyboard_key_function_F16");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function17("keyboard_key_function_F17");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function18("keyboard_key_function_F18");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function19("keyboard_key_function_F19");
|
||||
const InputChannelId InputDeviceKeyboard::Key::Function20("keyboard_key_function_F20");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Modifier Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierAltL("keyboard_key_modifier_alt_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierAltR("keyboard_key_modifier_alt_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierCtrlL("keyboard_key_modifier_ctrl_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierCtrlR("keyboard_key_modifier_ctrl_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierShiftL("keyboard_key_modifier_shift_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierShiftR("keyboard_key_modifier_shift_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierSuperL("keyboard_key_modifier_super_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::ModifierSuperR("keyboard_key_modifier_super_r");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Navigation Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowDown("keyboard_key_navigation_arrow_down");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowLeft("keyboard_key_navigation_arrow_left");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowRight("keyboard_key_navigation_arrow_right");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationArrowUp("keyboard_key_navigation_arrow_up");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationDelete("keyboard_key_navigation_delete");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationEnd("keyboard_key_navigation_end");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationHome("keyboard_key_navigation_home");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationInsert("keyboard_key_navigation_insert");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationPageDown("keyboard_key_navigation_page_down");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NavigationPageUp("keyboard_key_navigation_page_up");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Numpad Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumLock("keyboard_key_num_lock");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad0("keyboard_key_numpad_0");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad1("keyboard_key_numpad_1");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad2("keyboard_key_numpad_2");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad3("keyboard_key_numpad_3");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad4("keyboard_key_numpad_4");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad5("keyboard_key_numpad_5");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad6("keyboard_key_numpad_6");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad7("keyboard_key_numpad_7");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad8("keyboard_key_numpad_8");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPad9("keyboard_key_numpad_9");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadAdd("keyboard_key_numpad_add");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadDecimal("keyboard_key_numpad_decimal");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadDivide("keyboard_key_numpad_divide");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadEnter("keyboard_key_numpad_enter");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadMultiply("keyboard_key_numpad_multiply");
|
||||
const InputChannelId InputDeviceKeyboard::Key::NumPadSubtract("keyboard_key_numpad_subtract");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Punctuation Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationApostrophe("keyboard_key_punctuation_apostrophe");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBackslash("keyboard_key_punctuation_backslash");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBracketL("keyboard_key_punctuation_bracket_l");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationBracketR("keyboard_key_punctuation_bracket_r");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationComma("keyboard_key_punctuation_comma");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationEquals("keyboard_key_punctuation_equals");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationHyphen("keyboard_key_punctuation_hyphen");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationPeriod("keyboard_key_punctuation_period");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationSemicolon("keyboard_key_punctuation_semicolon");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationSlash("keyboard_key_punctuation_slash");
|
||||
const InputChannelId InputDeviceKeyboard::Key::PunctuationTilde("keyboard_key_punctuation_tilde");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Supplementary ISO Key
|
||||
const InputChannelId InputDeviceKeyboard::Key::SupplementaryISO("keyboard_key_supplementary_iso");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Windows System Keys
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemPause("keyboard_key_windows_system_pause");
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemPrint("keyboard_key_windows_system_print");
|
||||
const InputChannelId InputDeviceKeyboard::Key::WindowsSystemScrollLock("keyboard_key_windows_system_scroll_lock");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const AZStd::array<InputChannelId, 112> InputDeviceKeyboard::Key::All =
|
||||
{{
|
||||
// Alphanumeric Keys
|
||||
Alphanumeric0,
|
||||
Alphanumeric1,
|
||||
Alphanumeric2,
|
||||
Alphanumeric3,
|
||||
Alphanumeric4,
|
||||
Alphanumeric5,
|
||||
Alphanumeric6,
|
||||
Alphanumeric7,
|
||||
Alphanumeric8,
|
||||
Alphanumeric9,
|
||||
AlphanumericA,
|
||||
AlphanumericB,
|
||||
AlphanumericC,
|
||||
AlphanumericD,
|
||||
AlphanumericE,
|
||||
AlphanumericF,
|
||||
AlphanumericG,
|
||||
AlphanumericH,
|
||||
AlphanumericI,
|
||||
AlphanumericJ,
|
||||
AlphanumericK,
|
||||
AlphanumericL,
|
||||
AlphanumericM,
|
||||
AlphanumericN,
|
||||
AlphanumericO,
|
||||
AlphanumericP,
|
||||
AlphanumericQ,
|
||||
AlphanumericR,
|
||||
AlphanumericS,
|
||||
AlphanumericT,
|
||||
AlphanumericU,
|
||||
AlphanumericV,
|
||||
AlphanumericW,
|
||||
AlphanumericX,
|
||||
AlphanumericY,
|
||||
AlphanumericZ,
|
||||
|
||||
// Edit (and escape) Keys
|
||||
EditBackspace,
|
||||
EditCapsLock,
|
||||
EditEnter,
|
||||
EditSpace,
|
||||
EditTab,
|
||||
Escape,
|
||||
|
||||
// Function Keys
|
||||
Function01,
|
||||
Function02,
|
||||
Function03,
|
||||
Function04,
|
||||
Function05,
|
||||
Function06,
|
||||
Function07,
|
||||
Function08,
|
||||
Function09,
|
||||
Function10,
|
||||
Function11,
|
||||
Function12,
|
||||
Function13,
|
||||
Function14,
|
||||
Function15,
|
||||
Function16,
|
||||
Function17,
|
||||
Function18,
|
||||
Function19,
|
||||
Function20,
|
||||
|
||||
// Modifier Keys
|
||||
ModifierAltL,
|
||||
ModifierAltR,
|
||||
ModifierCtrlL,
|
||||
ModifierCtrlR,
|
||||
ModifierShiftL,
|
||||
ModifierShiftR,
|
||||
ModifierSuperL,
|
||||
ModifierSuperR,
|
||||
|
||||
// Navigation Keys
|
||||
NavigationArrowDown,
|
||||
NavigationArrowLeft,
|
||||
NavigationArrowRight,
|
||||
NavigationArrowUp,
|
||||
NavigationDelete,
|
||||
NavigationEnd,
|
||||
NavigationHome,
|
||||
NavigationInsert,
|
||||
NavigationPageDown,
|
||||
NavigationPageUp,
|
||||
|
||||
// Numpad Keys
|
||||
NumLock,
|
||||
NumPad0,
|
||||
NumPad1,
|
||||
NumPad2,
|
||||
NumPad3,
|
||||
NumPad4,
|
||||
NumPad5,
|
||||
NumPad6,
|
||||
NumPad7,
|
||||
NumPad8,
|
||||
NumPad9,
|
||||
NumPadAdd,
|
||||
NumPadDecimal,
|
||||
NumPadDivide,
|
||||
NumPadEnter,
|
||||
NumPadMultiply,
|
||||
NumPadSubtract,
|
||||
|
||||
// Punctuation Keys
|
||||
PunctuationApostrophe,
|
||||
PunctuationBackslash,
|
||||
PunctuationBracketL,
|
||||
PunctuationBracketR,
|
||||
PunctuationComma,
|
||||
PunctuationEquals,
|
||||
PunctuationHyphen,
|
||||
PunctuationPeriod,
|
||||
PunctuationSemicolon,
|
||||
PunctuationSlash,
|
||||
PunctuationTilde,
|
||||
|
||||
// Supplementary ISO Key
|
||||
SupplementaryISO,
|
||||
|
||||
// Windows System Keys
|
||||
WindowsSystemPause,
|
||||
WindowsSystemPrint,
|
||||
WindowsSystemScrollLock
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ModifierKeyMask GetCorrespondingModifierKeyMask(const InputChannelId& channelId)
|
||||
{
|
||||
|
||||
+245
-114
@@ -94,137 +94,268 @@ namespace AzFramework
|
||||
struct Key
|
||||
{
|
||||
// Alphanumeric Keys
|
||||
static const InputChannelId Alphanumeric0; //!< The 0 key
|
||||
static const InputChannelId Alphanumeric1; //!< The 1 key
|
||||
static const InputChannelId Alphanumeric2; //!< The 2 key
|
||||
static const InputChannelId Alphanumeric3; //!< The 3 key
|
||||
static const InputChannelId Alphanumeric4; //!< The 4 key
|
||||
static const InputChannelId Alphanumeric5; //!< The 5 key
|
||||
static const InputChannelId Alphanumeric6; //!< The 6 key
|
||||
static const InputChannelId Alphanumeric7; //!< The 7 key
|
||||
static const InputChannelId Alphanumeric8; //!< The 8 key
|
||||
static const InputChannelId Alphanumeric9; //!< The 9 key
|
||||
static const InputChannelId AlphanumericA; //!< The A key
|
||||
static const InputChannelId AlphanumericB; //!< The B key
|
||||
static const InputChannelId AlphanumericC; //!< The C key
|
||||
static const InputChannelId AlphanumericD; //!< The D key
|
||||
static const InputChannelId AlphanumericE; //!< The E key
|
||||
static const InputChannelId AlphanumericF; //!< The F key
|
||||
static const InputChannelId AlphanumericG; //!< The G key
|
||||
static const InputChannelId AlphanumericH; //!< The H key
|
||||
static const InputChannelId AlphanumericI; //!< The I key
|
||||
static const InputChannelId AlphanumericJ; //!< The J key
|
||||
static const InputChannelId AlphanumericK; //!< The K key
|
||||
static const InputChannelId AlphanumericL; //!< The L key
|
||||
static const InputChannelId AlphanumericM; //!< The M key
|
||||
static const InputChannelId AlphanumericN; //!< The N key
|
||||
static const InputChannelId AlphanumericO; //!< The O key
|
||||
static const InputChannelId AlphanumericP; //!< The P key
|
||||
static const InputChannelId AlphanumericQ; //!< The Q key
|
||||
static const InputChannelId AlphanumericR; //!< The R key
|
||||
static const InputChannelId AlphanumericS; //!< The S key
|
||||
static const InputChannelId AlphanumericT; //!< The T key
|
||||
static const InputChannelId AlphanumericU; //!< The U key
|
||||
static const InputChannelId AlphanumericV; //!< The V key
|
||||
static const InputChannelId AlphanumericW; //!< The W key
|
||||
static const InputChannelId AlphanumericX; //!< The X key
|
||||
static const InputChannelId AlphanumericY; //!< The Y key
|
||||
static const InputChannelId AlphanumericZ; //!< The Z key
|
||||
static constexpr inline InputChannelId Alphanumeric0{"keyboard_key_alphanumeric_0"}; //!< The 0 key
|
||||
static constexpr inline InputChannelId Alphanumeric1{"keyboard_key_alphanumeric_1"}; //!< The 1 key
|
||||
static constexpr inline InputChannelId Alphanumeric2{"keyboard_key_alphanumeric_2"}; //!< The 2 key
|
||||
static constexpr inline InputChannelId Alphanumeric3{"keyboard_key_alphanumeric_3"}; //!< The 3 key
|
||||
static constexpr inline InputChannelId Alphanumeric4{"keyboard_key_alphanumeric_4"}; //!< The 4 key
|
||||
static constexpr inline InputChannelId Alphanumeric5{"keyboard_key_alphanumeric_5"}; //!< The 5 key
|
||||
static constexpr inline InputChannelId Alphanumeric6{"keyboard_key_alphanumeric_6"}; //!< The 6 key
|
||||
static constexpr inline InputChannelId Alphanumeric7{"keyboard_key_alphanumeric_7"}; //!< The 7 key
|
||||
static constexpr inline InputChannelId Alphanumeric8{"keyboard_key_alphanumeric_8"}; //!< The 8 key
|
||||
static constexpr inline InputChannelId Alphanumeric9{"keyboard_key_alphanumeric_9"}; //!< The 9 key
|
||||
static constexpr inline InputChannelId AlphanumericA{"keyboard_key_alphanumeric_A"}; //!< The A key
|
||||
static constexpr inline InputChannelId AlphanumericB{"keyboard_key_alphanumeric_B"}; //!< The B key
|
||||
static constexpr inline InputChannelId AlphanumericC{"keyboard_key_alphanumeric_C"}; //!< The C key
|
||||
static constexpr inline InputChannelId AlphanumericD{"keyboard_key_alphanumeric_D"}; //!< The D key
|
||||
static constexpr inline InputChannelId AlphanumericE{"keyboard_key_alphanumeric_E"}; //!< The E key
|
||||
static constexpr inline InputChannelId AlphanumericF{"keyboard_key_alphanumeric_F"}; //!< The F key
|
||||
static constexpr inline InputChannelId AlphanumericG{"keyboard_key_alphanumeric_G"}; //!< The G key
|
||||
static constexpr inline InputChannelId AlphanumericH{"keyboard_key_alphanumeric_H"}; //!< The H key
|
||||
static constexpr inline InputChannelId AlphanumericI{"keyboard_key_alphanumeric_I"}; //!< The I key
|
||||
static constexpr inline InputChannelId AlphanumericJ{"keyboard_key_alphanumeric_J"}; //!< The J key
|
||||
static constexpr inline InputChannelId AlphanumericK{"keyboard_key_alphanumeric_K"}; //!< The K key
|
||||
static constexpr inline InputChannelId AlphanumericL{"keyboard_key_alphanumeric_L"}; //!< The L key
|
||||
static constexpr inline InputChannelId AlphanumericM{"keyboard_key_alphanumeric_M"}; //!< The M key
|
||||
static constexpr inline InputChannelId AlphanumericN{"keyboard_key_alphanumeric_N"}; //!< The N key
|
||||
static constexpr inline InputChannelId AlphanumericO{"keyboard_key_alphanumeric_O"}; //!< The O key
|
||||
static constexpr inline InputChannelId AlphanumericP{"keyboard_key_alphanumeric_P"}; //!< The P key
|
||||
static constexpr inline InputChannelId AlphanumericQ{"keyboard_key_alphanumeric_Q"}; //!< The Q key
|
||||
static constexpr inline InputChannelId AlphanumericR{"keyboard_key_alphanumeric_R"}; //!< The R key
|
||||
static constexpr inline InputChannelId AlphanumericS{"keyboard_key_alphanumeric_S"}; //!< The S key
|
||||
static constexpr inline InputChannelId AlphanumericT{"keyboard_key_alphanumeric_T"}; //!< The T key
|
||||
static constexpr inline InputChannelId AlphanumericU{"keyboard_key_alphanumeric_U"}; //!< The U key
|
||||
static constexpr inline InputChannelId AlphanumericV{"keyboard_key_alphanumeric_V"}; //!< The V key
|
||||
static constexpr inline InputChannelId AlphanumericW{"keyboard_key_alphanumeric_W"}; //!< The W key
|
||||
static constexpr inline InputChannelId AlphanumericX{"keyboard_key_alphanumeric_X"}; //!< The X key
|
||||
static constexpr inline InputChannelId AlphanumericY{"keyboard_key_alphanumeric_Y"}; //!< The Y key
|
||||
static constexpr inline InputChannelId AlphanumericZ{"keyboard_key_alphanumeric_Z"}; //!< The Z key
|
||||
|
||||
// Edit (and escape) Keys
|
||||
static const InputChannelId EditBackspace; //!< The backspace key
|
||||
static const InputChannelId EditCapsLock; //!< The caps lock key
|
||||
static const InputChannelId EditEnter; //!< The enter/return key
|
||||
static const InputChannelId EditSpace; //!< The spacebar key
|
||||
static const InputChannelId EditTab; //!< The tab key
|
||||
static const InputChannelId Escape; //!< The escape key
|
||||
// Edit {and escape} Keys
|
||||
static constexpr inline InputChannelId EditBackspace{"keyboard_key_edit_backspace"}; //!< The backspace key
|
||||
static constexpr inline InputChannelId EditCapsLock{"keyboard_key_edit_capslock"}; //!< The caps lock key
|
||||
static constexpr inline InputChannelId EditEnter{"keyboard_key_edit_enter"}; //!< The enter/return key
|
||||
static constexpr inline InputChannelId EditSpace{"keyboard_key_edit_space"}; //!< The spacebar key
|
||||
static constexpr inline InputChannelId EditTab{"keyboard_key_edit_tab"}; //!< The tab key
|
||||
static constexpr inline InputChannelId Escape{"keyboard_key_escape"}; //!< The escape key
|
||||
|
||||
// Function Keys
|
||||
static const InputChannelId Function01; //!< The F1 key
|
||||
static const InputChannelId Function02; //!< The F2 key
|
||||
static const InputChannelId Function03; //!< The F3 key
|
||||
static const InputChannelId Function04; //!< The F4 key
|
||||
static const InputChannelId Function05; //!< The F5 key
|
||||
static const InputChannelId Function06; //!< The F6 key
|
||||
static const InputChannelId Function07; //!< The F7 key
|
||||
static const InputChannelId Function08; //!< The F8 key
|
||||
static const InputChannelId Function09; //!< The F9 key
|
||||
static const InputChannelId Function10; //!< The F10 key
|
||||
static const InputChannelId Function11; //!< The F11 key
|
||||
static const InputChannelId Function12; //!< The F12 key
|
||||
static const InputChannelId Function13; //!< The F13 key
|
||||
static const InputChannelId Function14; //!< The F14 key
|
||||
static const InputChannelId Function15; //!< The F15 key
|
||||
static const InputChannelId Function16; //!< The F16 key
|
||||
static const InputChannelId Function17; //!< The F17 key
|
||||
static const InputChannelId Function18; //!< The F18 key
|
||||
static const InputChannelId Function19; //!< The F19 key
|
||||
static const InputChannelId Function20; //!< The F20 key
|
||||
static constexpr inline InputChannelId Function01{"keyboard_key_function_F01"}; //!< The F1 key
|
||||
static constexpr inline InputChannelId Function02{"keyboard_key_function_F02"}; //!< The F2 key
|
||||
static constexpr inline InputChannelId Function03{"keyboard_key_function_F03"}; //!< The F3 key
|
||||
static constexpr inline InputChannelId Function04{"keyboard_key_function_F04"}; //!< The F4 key
|
||||
static constexpr inline InputChannelId Function05{"keyboard_key_function_F05"}; //!< The F5 key
|
||||
static constexpr inline InputChannelId Function06{"keyboard_key_function_F06"}; //!< The F6 key
|
||||
static constexpr inline InputChannelId Function07{"keyboard_key_function_F07"}; //!< The F7 key
|
||||
static constexpr inline InputChannelId Function08{"keyboard_key_function_F08"}; //!< The F8 key
|
||||
static constexpr inline InputChannelId Function09{"keyboard_key_function_F09"}; //!< The F9 key
|
||||
static constexpr inline InputChannelId Function10{"keyboard_key_function_F10"}; //!< The F10 key
|
||||
static constexpr inline InputChannelId Function11{"keyboard_key_function_F11"}; //!< The F11 key
|
||||
static constexpr inline InputChannelId Function12{"keyboard_key_function_F12"}; //!< The F12 key
|
||||
static constexpr inline InputChannelId Function13{"keyboard_key_function_F13"}; //!< The F13 key
|
||||
static constexpr inline InputChannelId Function14{"keyboard_key_function_F14"}; //!< The F14 key
|
||||
static constexpr inline InputChannelId Function15{"keyboard_key_function_F15"}; //!< The F15 key
|
||||
static constexpr inline InputChannelId Function16{"keyboard_key_function_F16"}; //!< The F16 key
|
||||
static constexpr inline InputChannelId Function17{"keyboard_key_function_F17"}; //!< The F17 key
|
||||
static constexpr inline InputChannelId Function18{"keyboard_key_function_F18"}; //!< The F18 key
|
||||
static constexpr inline InputChannelId Function19{"keyboard_key_function_F19"}; //!< The F19 key
|
||||
static constexpr inline InputChannelId Function20{"keyboard_key_function_F20"}; //!< The F20 key
|
||||
|
||||
// Modifier Keys
|
||||
static const InputChannelId ModifierAltL; //!< The left alt/option key
|
||||
static const InputChannelId ModifierAltR; //!< The right alt/option key
|
||||
static const InputChannelId ModifierCtrlL; //!< The left control key
|
||||
static const InputChannelId ModifierCtrlR; //!< The right control key
|
||||
static const InputChannelId ModifierShiftL; //!< The left shift key
|
||||
static const InputChannelId ModifierShiftR; //!< The right shift key
|
||||
static const InputChannelId ModifierSuperL; //!< The left super (windows or apple) key
|
||||
static const InputChannelId ModifierSuperR; //!< The right super (windows or apple) key
|
||||
static constexpr inline InputChannelId ModifierAltL{"keyboard_key_modifier_alt_l"}; //!< The left alt/option key
|
||||
static constexpr inline InputChannelId ModifierAltR{"keyboard_key_modifier_alt_r"}; //!< The right alt/option key
|
||||
static constexpr inline InputChannelId ModifierCtrlL{"keyboard_key_modifier_ctrl_l"}; //!< The left control key
|
||||
static constexpr inline InputChannelId ModifierCtrlR{"keyboard_key_modifier_ctrl_r"}; //!< The right control key
|
||||
static constexpr inline InputChannelId ModifierShiftL{"keyboard_key_modifier_shift_l"}; //!< The left shift key
|
||||
static constexpr inline InputChannelId ModifierShiftR{"keyboard_key_modifier_shift_r"}; //!< The right shift key
|
||||
static constexpr inline InputChannelId ModifierSuperL{"keyboard_key_modifier_super_l"}; //!< The left super {windows or apple} key
|
||||
static constexpr inline InputChannelId ModifierSuperR{"keyboard_key_modifier_super_r"}; //!< The right super {windows or apple} key
|
||||
|
||||
// Navigation Keys
|
||||
static const InputChannelId NavigationArrowDown; //!< The down arrow key
|
||||
static const InputChannelId NavigationArrowLeft; //!< The left arrow key
|
||||
static const InputChannelId NavigationArrowRight; //!< The right arrow key
|
||||
static const InputChannelId NavigationArrowUp; //!< The up arrow key
|
||||
static const InputChannelId NavigationDelete; //!< The delete key
|
||||
static const InputChannelId NavigationEnd; //!< The end key
|
||||
static const InputChannelId NavigationHome; //!< The home key
|
||||
static const InputChannelId NavigationInsert; //!< The insert key
|
||||
static const InputChannelId NavigationPageDown; //!< The page down key
|
||||
static const InputChannelId NavigationPageUp; //!< The page up key
|
||||
static constexpr inline InputChannelId NavigationArrowDown{"keyboard_key_navigation_arrow_down"}; //!< The down arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowLeft{"keyboard_key_navigation_arrow_left"}; //!< The left arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowRight{"keyboard_key_navigation_arrow_right"}; //!< The right arrow key
|
||||
static constexpr inline InputChannelId NavigationArrowUp{"keyboard_key_navigation_arrow_up"}; //!< The up arrow key
|
||||
static constexpr inline InputChannelId NavigationDelete{"keyboard_key_navigation_delete"}; //!< The delete key
|
||||
static constexpr inline InputChannelId NavigationEnd{"keyboard_key_navigation_end"}; //!< The end key
|
||||
static constexpr inline InputChannelId NavigationHome{"keyboard_key_navigation_home"}; //!< The home key
|
||||
static constexpr inline InputChannelId NavigationInsert{"keyboard_key_navigation_insert"}; //!< The insert key
|
||||
static constexpr inline InputChannelId NavigationPageDown{"keyboard_key_navigation_page_down"}; //!< The page down key
|
||||
static constexpr inline InputChannelId NavigationPageUp{"keyboard_key_navigation_page_up"}; //!< The page up key
|
||||
|
||||
// Numpad Keys
|
||||
static const InputChannelId NumLock; //!< The num lock key (the clear key on apple keyboards)
|
||||
static const InputChannelId NumPad0; //!< The numpad 0 key
|
||||
static const InputChannelId NumPad1; //!< The numpad 1 key
|
||||
static const InputChannelId NumPad2; //!< The numpad 2 key
|
||||
static const InputChannelId NumPad3; //!< The numpad 3 key
|
||||
static const InputChannelId NumPad4; //!< The numpad 4 key
|
||||
static const InputChannelId NumPad5; //!< The numpad 5 key
|
||||
static const InputChannelId NumPad6; //!< The numpad 6 key
|
||||
static const InputChannelId NumPad7; //!< The numpad 7 key
|
||||
static const InputChannelId NumPad8; //!< The numpad 8 key
|
||||
static const InputChannelId NumPad9; //!< The numpad 9 key
|
||||
static const InputChannelId NumPadAdd; //!< The numpad add key
|
||||
static const InputChannelId NumPadDecimal; //!< The numpad decimal key
|
||||
static const InputChannelId NumPadDivide; //!< The numpad divide key
|
||||
static const InputChannelId NumPadEnter; //!< The numpad enter key
|
||||
static const InputChannelId NumPadMultiply; //!< The numpad multiply key
|
||||
static const InputChannelId NumPadSubtract; //!< The numpad subtract key
|
||||
static constexpr inline InputChannelId NumLock{"keyboard_key_num_lock"}; //!< The num lock key {the clear key on apple keyboards}
|
||||
static constexpr inline InputChannelId NumPad0{"keyboard_key_numpad_0"}; //!< The numpad 0 key
|
||||
static constexpr inline InputChannelId NumPad1{"keyboard_key_numpad_1"}; //!< The numpad 1 key
|
||||
static constexpr inline InputChannelId NumPad2{"keyboard_key_numpad_2"}; //!< The numpad 2 key
|
||||
static constexpr inline InputChannelId NumPad3{"keyboard_key_numpad_3"}; //!< The numpad 3 key
|
||||
static constexpr inline InputChannelId NumPad4{"keyboard_key_numpad_4"}; //!< The numpad 4 key
|
||||
static constexpr inline InputChannelId NumPad5{"keyboard_key_numpad_5"}; //!< The numpad 5 key
|
||||
static constexpr inline InputChannelId NumPad6{"keyboard_key_numpad_6"}; //!< The numpad 6 key
|
||||
static constexpr inline InputChannelId NumPad7{"keyboard_key_numpad_7"}; //!< The numpad 7 key
|
||||
static constexpr inline InputChannelId NumPad8{"keyboard_key_numpad_8"}; //!< The numpad 8 key
|
||||
static constexpr inline InputChannelId NumPad9{"keyboard_key_numpad_9"}; //!< The numpad 9 key
|
||||
static constexpr inline InputChannelId NumPadAdd{"keyboard_key_numpad_add"}; //!< The numpad add key
|
||||
static constexpr inline InputChannelId NumPadDecimal{"keyboard_key_numpad_decimal"}; //!< The numpad decimal key
|
||||
static constexpr inline InputChannelId NumPadDivide{"keyboard_key_numpad_divide"}; //!< The numpad divide key
|
||||
static constexpr inline InputChannelId NumPadEnter{"keyboard_key_numpad_enter"}; //!< The numpad enter key
|
||||
static constexpr inline InputChannelId NumPadMultiply{"keyboard_key_numpad_multiply"}; //!< The numpad multiply key
|
||||
static constexpr inline InputChannelId NumPadSubtract{"keyboard_key_numpad_subtract"}; //!< The numpad subtract key
|
||||
|
||||
// Punctuation Keys
|
||||
static const InputChannelId PunctuationApostrophe; //!< The apostrophe key
|
||||
static const InputChannelId PunctuationBackslash; //!< The backslash key
|
||||
static const InputChannelId PunctuationBracketL; //!< The left bracket key
|
||||
static const InputChannelId PunctuationBracketR; //!< The right bracket key
|
||||
static const InputChannelId PunctuationComma; //!< The comma key
|
||||
static const InputChannelId PunctuationEquals; //!< The equals key
|
||||
static const InputChannelId PunctuationHyphen; //!< The hyphen/underscore key
|
||||
static const InputChannelId PunctuationPeriod; //!< The period key
|
||||
static const InputChannelId PunctuationSemicolon; //!< The semicolon key
|
||||
static const InputChannelId PunctuationSlash; //!< The (forward) slash key
|
||||
static const InputChannelId PunctuationTilde; //!< The tilde/grave key
|
||||
static constexpr inline InputChannelId PunctuationApostrophe{"keyboard_key_punctuation_apostrophe"}; //!< The apostrophe key
|
||||
static constexpr inline InputChannelId PunctuationBackslash{"keyboard_key_punctuation_backslash"}; //!< The backslash key
|
||||
static constexpr inline InputChannelId PunctuationBracketL{"keyboard_key_punctuation_bracket_l"}; //!< The left bracket key
|
||||
static constexpr inline InputChannelId PunctuationBracketR{"keyboard_key_punctuation_bracket_r"}; //!< The right bracket key
|
||||
static constexpr inline InputChannelId PunctuationComma{"keyboard_key_punctuation_comma"}; //!< The comma key
|
||||
static constexpr inline InputChannelId PunctuationEquals{"keyboard_key_punctuation_equals"}; //!< The equals key
|
||||
static constexpr inline InputChannelId PunctuationHyphen{"keyboard_key_punctuation_hyphen"}; //!< The hyphen/underscore key
|
||||
static constexpr inline InputChannelId PunctuationPeriod{"keyboard_key_punctuation_period"}; //!< The period key
|
||||
static constexpr inline InputChannelId PunctuationSemicolon{"keyboard_key_punctuation_semicolon"}; //!< The semicolon key
|
||||
static constexpr inline InputChannelId PunctuationSlash{"keyboard_key_punctuation_slash"}; //!< The {forward} slash key
|
||||
static constexpr inline InputChannelId PunctuationTilde{"keyboard_key_punctuation_tilde"}; //!< The tilde/grave key
|
||||
|
||||
// Supplementary ISO Key
|
||||
static const InputChannelId SupplementaryISO; //!< The supplementary ISO layout key
|
||||
static constexpr inline InputChannelId SupplementaryISO{"keyboard_key_supplementary_iso"}; //!< The supplementary ISO layout key
|
||||
|
||||
// Windows System Keys
|
||||
static const InputChannelId WindowsSystemPause; //!< The windows pause key
|
||||
static const InputChannelId WindowsSystemPrint; //!< The windows print key
|
||||
static const InputChannelId WindowsSystemScrollLock; //!< The windows scroll lock key
|
||||
static constexpr inline InputChannelId WindowsSystemPause{"keyboard_key_windows_system_pause"}; //!< The windows pause key
|
||||
static constexpr inline InputChannelId WindowsSystemPrint{"keyboard_key_windows_system_print"}; //!< The windows print key
|
||||
static constexpr inline InputChannelId WindowsSystemScrollLock{"keyboard_key_windows_system_scroll_lock"}; //!< The windows scroll lock key
|
||||
|
||||
//!< All keyboard key ids
|
||||
static const AZStd::array<InputChannelId, 112> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
// Alphanumeric Keys
|
||||
Alphanumeric0,
|
||||
Alphanumeric1,
|
||||
Alphanumeric2,
|
||||
Alphanumeric3,
|
||||
Alphanumeric4,
|
||||
Alphanumeric5,
|
||||
Alphanumeric6,
|
||||
Alphanumeric7,
|
||||
Alphanumeric8,
|
||||
Alphanumeric9,
|
||||
AlphanumericA,
|
||||
AlphanumericB,
|
||||
AlphanumericC,
|
||||
AlphanumericD,
|
||||
AlphanumericE,
|
||||
AlphanumericF,
|
||||
AlphanumericG,
|
||||
AlphanumericH,
|
||||
AlphanumericI,
|
||||
AlphanumericJ,
|
||||
AlphanumericK,
|
||||
AlphanumericL,
|
||||
AlphanumericM,
|
||||
AlphanumericN,
|
||||
AlphanumericO,
|
||||
AlphanumericP,
|
||||
AlphanumericQ,
|
||||
AlphanumericR,
|
||||
AlphanumericS,
|
||||
AlphanumericT,
|
||||
AlphanumericU,
|
||||
AlphanumericV,
|
||||
AlphanumericW,
|
||||
AlphanumericX,
|
||||
AlphanumericY,
|
||||
AlphanumericZ,
|
||||
|
||||
// Edit (and escape) Keys
|
||||
EditBackspace,
|
||||
EditCapsLock,
|
||||
EditEnter,
|
||||
EditSpace,
|
||||
EditTab,
|
||||
Escape,
|
||||
|
||||
// Function Keys
|
||||
Function01,
|
||||
Function02,
|
||||
Function03,
|
||||
Function04,
|
||||
Function05,
|
||||
Function06,
|
||||
Function07,
|
||||
Function08,
|
||||
Function09,
|
||||
Function10,
|
||||
Function11,
|
||||
Function12,
|
||||
Function13,
|
||||
Function14,
|
||||
Function15,
|
||||
Function16,
|
||||
Function17,
|
||||
Function18,
|
||||
Function19,
|
||||
Function20,
|
||||
|
||||
// Modifier Keys
|
||||
ModifierAltL,
|
||||
ModifierAltR,
|
||||
ModifierCtrlL,
|
||||
ModifierCtrlR,
|
||||
ModifierShiftL,
|
||||
ModifierShiftR,
|
||||
ModifierSuperL,
|
||||
ModifierSuperR,
|
||||
|
||||
// Navigation Keys
|
||||
NavigationArrowDown,
|
||||
NavigationArrowLeft,
|
||||
NavigationArrowRight,
|
||||
NavigationArrowUp,
|
||||
NavigationDelete,
|
||||
NavigationEnd,
|
||||
NavigationHome,
|
||||
NavigationInsert,
|
||||
NavigationPageDown,
|
||||
NavigationPageUp,
|
||||
|
||||
// Numpad Keys
|
||||
NumLock,
|
||||
NumPad0,
|
||||
NumPad1,
|
||||
NumPad2,
|
||||
NumPad3,
|
||||
NumPad4,
|
||||
NumPad5,
|
||||
NumPad6,
|
||||
NumPad7,
|
||||
NumPad8,
|
||||
NumPad9,
|
||||
NumPadAdd,
|
||||
NumPadDecimal,
|
||||
NumPadDivide,
|
||||
NumPadEnter,
|
||||
NumPadMultiply,
|
||||
NumPadSubtract,
|
||||
|
||||
// Punctuation Keys
|
||||
PunctuationApostrophe,
|
||||
PunctuationBackslash,
|
||||
PunctuationBracketL,
|
||||
PunctuationBracketR,
|
||||
PunctuationComma,
|
||||
PunctuationEquals,
|
||||
PunctuationHyphen,
|
||||
PunctuationPeriod,
|
||||
PunctuationSemicolon,
|
||||
PunctuationSlash,
|
||||
PunctuationTilde,
|
||||
|
||||
// Supplementary ISO Key
|
||||
SupplementaryISO,
|
||||
|
||||
// Windows System Keys
|
||||
WindowsSystemPause,
|
||||
WindowsSystemPrint,
|
||||
WindowsSystemScrollLock
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -23,44 +23,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::Acceleration::Gravity("motion_acceleration_gravity");
|
||||
const InputChannelId InputDeviceMotion::Acceleration::Raw("motion_acceleration_raw");
|
||||
const InputChannelId InputDeviceMotion::Acceleration::User("motion_acceleration_user");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMotion::Acceleration::All =
|
||||
{{
|
||||
Gravity,
|
||||
Raw,
|
||||
User
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::RotationRate::Raw("motion_rotation_rate_raw");
|
||||
const InputChannelId InputDeviceMotion::RotationRate::Unbiased("motion_rotation_rate_unbiased");
|
||||
const AZStd::array<InputChannelId, 2> InputDeviceMotion::RotationRate::All =
|
||||
{{
|
||||
Raw,
|
||||
Unbiased
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::MagneticField::North("motion_magnetic_field_north");
|
||||
const InputChannelId InputDeviceMotion::MagneticField::Raw("motion_magnetic_field_raw");
|
||||
const InputChannelId InputDeviceMotion::MagneticField::Unbiased("motion_magnetic_field_unbiased");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMotion::MagneticField::All =
|
||||
{{
|
||||
North,
|
||||
Raw,
|
||||
Unbiased
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMotion::Orientation::Current("motion_orientation_current");
|
||||
const AZStd::array<InputChannelId, 1> InputDeviceMotion::Orientation::All =
|
||||
{{
|
||||
Current
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceMotion::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -44,12 +44,17 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct Acceleration
|
||||
{
|
||||
static const InputChannelId Gravity;
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId User;
|
||||
static constexpr inline InputChannelId Gravity{"motion_acceleration_gravity"};
|
||||
static constexpr inline InputChannelId Raw{"motion_acceleration_raw"};
|
||||
static constexpr inline InputChannelId User{"motion_acceleration_user"};
|
||||
|
||||
//!< All acceleration input channel ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Gravity,
|
||||
Raw,
|
||||
User
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -60,11 +65,15 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct RotationRate
|
||||
{
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId Unbiased;
|
||||
static constexpr inline InputChannelId Raw{"motion_rotation_rate_raw"};
|
||||
static constexpr inline InputChannelId Unbiased{"motion_rotation_rate_unbiased"};
|
||||
|
||||
//!< All rotation rate input channel ids
|
||||
static const AZStd::array<InputChannelId, 2> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Raw,
|
||||
Unbiased
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -75,12 +84,17 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct MagneticField
|
||||
{
|
||||
static const InputChannelId North;
|
||||
static const InputChannelId Raw;
|
||||
static const InputChannelId Unbiased;
|
||||
static constexpr inline InputChannelId North{"motion_magnetic_field_north"};
|
||||
static constexpr inline InputChannelId Raw{"motion_magnetic_field_raw"};
|
||||
static constexpr inline InputChannelId Unbiased{"motion_magnetic_field_unbiased"};
|
||||
|
||||
//!< All magnetic field input channel ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
North,
|
||||
Raw,
|
||||
Unbiased
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -91,10 +105,13 @@ namespace AzFramework
|
||||
//! - InputMotionSensorRequests::SetInputChannelEnabled
|
||||
struct Orientation
|
||||
{
|
||||
static const InputChannelId Current;
|
||||
static constexpr inline InputChannelId Current{"motion_orientation_current"};
|
||||
|
||||
//!< All orientation input channel ids
|
||||
static const AZStd::array<InputChannelId, 1> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Current
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -33,35 +33,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::Button::Left("mouse_button_left");
|
||||
const InputChannelId InputDeviceMouse::Button::Right("mouse_button_right");
|
||||
const InputChannelId InputDeviceMouse::Button::Middle("mouse_button_middle");
|
||||
const InputChannelId InputDeviceMouse::Button::Other1("mouse_button_other1");
|
||||
const InputChannelId InputDeviceMouse::Button::Other2("mouse_button_other2");
|
||||
const AZStd::array<InputChannelId, 5> InputDeviceMouse::Button::All =
|
||||
{{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other1,
|
||||
Other2
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::Movement::X("mouse_delta_x");
|
||||
const InputChannelId InputDeviceMouse::Movement::Y("mouse_delta_y");
|
||||
const InputChannelId InputDeviceMouse::Movement::Z("mouse_delta_z");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceMouse::Movement::All =
|
||||
{{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceMouse::SystemCursorPosition("mouse_system_cursor_position");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceMouse::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -66,14 +66,21 @@ namespace AzFramework
|
||||
//! been implemented for windows simply to provide for backwards compatibility with CryInput.
|
||||
struct Button
|
||||
{
|
||||
static const InputChannelId Left; //!< The left mouse button
|
||||
static const InputChannelId Right; //!< The right mouse button
|
||||
static const InputChannelId Middle; //!< The middle mouse button
|
||||
static const InputChannelId Other1; //!< DEPRECATED: the x1 mouse button
|
||||
static const InputChannelId Other2; //!< DEPRECATED: the x2 mouse button
|
||||
static constexpr inline InputChannelId Left{"mouse_button_left"}; //!< The left mouse button
|
||||
static constexpr inline InputChannelId Right{"mouse_button_right"}; //!< The right mouse button
|
||||
static constexpr inline InputChannelId Middle{"mouse_button_middle"}; //!< The middle mouse button
|
||||
static constexpr inline InputChannelId Other1{"mouse_button_other1"}; //!< DEPRECATED: the x1 mouse button
|
||||
static constexpr inline InputChannelId Other2{"mouse_button_other2"}; //!< DEPRECATED: the x2 mouse button
|
||||
|
||||
//!< All mouse button ids
|
||||
static const AZStd::array<InputChannelId, 5> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other1,
|
||||
Other2
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -82,12 +89,17 @@ namespace AzFramework
|
||||
//! directly correlate to the mouse position (which is queried directly from the system).
|
||||
struct Movement
|
||||
{
|
||||
static const InputChannelId X; //!< Raw horizontal mouse movement over the last frame
|
||||
static const InputChannelId Y; //!< Raw vertical mouse movement over the last frame
|
||||
static const InputChannelId Z; //!< Raw mouse wheel movement over the last frame
|
||||
static constexpr inline InputChannelId X{"mouse_delta_x"}; //!< Raw horizontal mouse movement over the last frame
|
||||
static constexpr inline InputChannelId Y{"mouse_delta_y"}; //!< Raw vertical mouse movement over the last frame
|
||||
static constexpr inline InputChannelId Z{"mouse_delta_z"}; //!< Raw mouse wheel movement over the last frame
|
||||
|
||||
//!< All mouse movement ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -96,7 +108,7 @@ namespace AzFramework
|
||||
//! the system cursor is hidden or visible. When the system cursor has been constrained to
|
||||
//! the active window values will be in the [0.0, 1.0] range, but not when unconstrained.
|
||||
//! See also InputSystemCursorRequests::SetSystemCursorState and GetSystemCursorState.
|
||||
static const InputChannelId SystemCursorPosition;
|
||||
static constexpr inline InputChannelId SystemCursorPosition{"mouse_system_cursor_position"};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
|
||||
@@ -24,31 +24,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceTouch::Touch::Index0("touch_index_0");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index1("touch_index_1");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index2("touch_index_2");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index3("touch_index_3");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index4("touch_index_4");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index5("touch_index_5");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index6("touch_index_6");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index7("touch_index_7");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index8("touch_index_8");
|
||||
const InputChannelId InputDeviceTouch::Touch::Index9("touch_index_9");
|
||||
const AZStd::array<InputChannelId, 10> InputDeviceTouch::Touch::All =
|
||||
{{
|
||||
Index0,
|
||||
Index1,
|
||||
Index2,
|
||||
Index3,
|
||||
Index4,
|
||||
Index5,
|
||||
Index6,
|
||||
Index7,
|
||||
Index8,
|
||||
Index9
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceTouch::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
@@ -38,19 +38,31 @@ namespace AzFramework
|
||||
//! track is arbitrary, but ten seems to be more than sufficient for most game applications.
|
||||
struct Touch
|
||||
{
|
||||
static const InputChannelId Index0; //!< Touch index 0
|
||||
static const InputChannelId Index1; //!< Touch index 1
|
||||
static const InputChannelId Index2; //!< Touch index 2
|
||||
static const InputChannelId Index3; //!< Touch index 3
|
||||
static const InputChannelId Index4; //!< Touch index 4
|
||||
static const InputChannelId Index5; //!< Touch index 5
|
||||
static const InputChannelId Index6; //!< Touch index 6
|
||||
static const InputChannelId Index7; //!< Touch index 7
|
||||
static const InputChannelId Index8; //!< Touch index 8
|
||||
static const InputChannelId Index9; //!< Touch index 9
|
||||
static constexpr inline InputChannelId Index0{"touch_index_0"}; //!< Touch index 0
|
||||
static constexpr inline InputChannelId Index1{"touch_index_1"}; //!< Touch index 1
|
||||
static constexpr inline InputChannelId Index2{"touch_index_2"}; //!< Touch index 2
|
||||
static constexpr inline InputChannelId Index3{"touch_index_3"}; //!< Touch index 3
|
||||
static constexpr inline InputChannelId Index4{"touch_index_4"}; //!< Touch index 4
|
||||
static constexpr inline InputChannelId Index5{"touch_index_5"}; //!< Touch index 5
|
||||
static constexpr inline InputChannelId Index6{"touch_index_6"}; //!< Touch index 6
|
||||
static constexpr inline InputChannelId Index7{"touch_index_7"}; //!< Touch index 7
|
||||
static constexpr inline InputChannelId Index8{"touch_index_8"}; //!< Touch index 8
|
||||
static constexpr inline InputChannelId Index9{"touch_index_9"}; //!< Touch index 9
|
||||
|
||||
//!< All touch input channel ids
|
||||
static const AZStd::array<InputChannelId, 10> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
Index0,
|
||||
Index1,
|
||||
Index2,
|
||||
Index3,
|
||||
Index4,
|
||||
Index5,
|
||||
Index6,
|
||||
Index7,
|
||||
Index8,
|
||||
Index9
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
-11
@@ -23,17 +23,6 @@ namespace AzFramework
|
||||
return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::EditEnter("virtual_keyboard_edit_enter");
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::EditClear("virtual_keyboard_edit_clear");
|
||||
const InputChannelId InputDeviceVirtualKeyboard::Command::NavigationBack("virtual_keyboard_navigation_back");
|
||||
const AZStd::array<InputChannelId, 3> InputDeviceVirtualKeyboard::Command::All =
|
||||
{{
|
||||
EditClear,
|
||||
EditEnter,
|
||||
NavigationBack
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputDeviceVirtualKeyboard::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
|
||||
+9
-4
@@ -39,17 +39,22 @@ namespace AzFramework
|
||||
struct Command
|
||||
{
|
||||
//!< The clear command used to indicate the user wants to clear the active text field
|
||||
static const InputChannelId EditClear;
|
||||
static constexpr inline InputChannelId EditClear{"virtual_keyboard_edit_enter"};
|
||||
|
||||
//!< The enter/return/close command used to indicate the user has finished text editing
|
||||
static const InputChannelId EditEnter;
|
||||
static constexpr inline InputChannelId EditEnter{"virtual_keyboard_edit_clear"};
|
||||
|
||||
//!< The back command used to indicate the user wants to navigate 'backwards'.
|
||||
//!< This is specific to android devices, and does not have an ios equivalent.
|
||||
static const InputChannelId NavigationBack;
|
||||
static constexpr inline InputChannelId NavigationBack{"virtual_keyboard_navigation_back"};
|
||||
|
||||
//!< All virtual keyboard command ids
|
||||
static const AZStd::array<InputChannelId, 3> All;
|
||||
static constexpr inline AZStd::array All
|
||||
{
|
||||
EditClear,
|
||||
EditEnter,
|
||||
NavigationBack
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Logging/MissingAssetNotificationBus.h>
|
||||
|
||||
namespace AzFramework { class LogFile; }
|
||||
|
||||
@@ -593,7 +593,7 @@ namespace AzFramework
|
||||
|
||||
DebugMessage("StartThread: Starting %s", thread.m_desc.m_name);
|
||||
thread.m_join = false;
|
||||
thread.m_thread = AZStd::thread(thread.m_main, &thread.m_desc);
|
||||
thread.m_thread = AZStd::thread(thread.m_desc, thread.m_main);
|
||||
}
|
||||
|
||||
void AssetProcessorConnection::JoinThread(ThreadState& thread, AZStd::condition_variable* wakeUpCondition /* = nullptr */)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzFramework/Physics/Ragdoll.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/SystemBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Script/ScriptContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzFramework/Physics/CollisionBus.h>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzFramework/Physics/Configuration/SystemConfiguration.h>
|
||||
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
|
||||
namespace AzPhysics
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
void SystemInterface::Reflect(AZ::ReflectContext* context)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Material.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionLayers.h>
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzFramework/Physics/PropertyTypes.h>
|
||||
#include <AzFramework/Physics/SystemBus.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace Physics
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include "Utils.h"
|
||||
#include "Material.h"
|
||||
#include "Shape.h"
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzFramework/Physics/AnimationConfiguration.h>
|
||||
#include <AzFramework/Physics/CharacterBus.h>
|
||||
#include <AzFramework/Physics/Character.h>
|
||||
#include <AzFramework/Physics/Ragdoll.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzFramework/Physics/CollisionBus.h>
|
||||
#include <AzFramework/Physics/Components/SimulatedBodyComponentBus.h>
|
||||
#include <AzFramework/Physics/WindBus.h>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
//! Common structures for Render geometry queries
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
@@ -283,8 +283,12 @@ namespace AzFramework
|
||||
: m_payload(rhs.m_payload)
|
||||
, m_id(rhs.m_id)
|
||||
{
|
||||
auto manager = SpawnableEntitiesInterface::Get();
|
||||
AZ_Assert(manager, "SpawnableEntitiesInterface has no implementation.");
|
||||
rhs.m_payload = nullptr;
|
||||
rhs.m_id = 0;
|
||||
AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex);
|
||||
manager->m_entitySpawnTicketMap.insert_or_assign(rhs.m_id, this);
|
||||
}
|
||||
|
||||
EntitySpawnTicket::EntitySpawnTicket(AZ::Data::Asset<Spawnable> spawnable)
|
||||
@@ -294,6 +298,8 @@ namespace AzFramework
|
||||
AZStd::pair<EntitySpawnTicket::Id, void*> result = manager->CreateTicket(AZStd::move(spawnable));
|
||||
m_id = result.first;
|
||||
m_payload = result.second;
|
||||
AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex);
|
||||
manager->m_entitySpawnTicketMap.insert_or_assign(m_id, this);
|
||||
}
|
||||
|
||||
EntitySpawnTicket::~EntitySpawnTicket()
|
||||
@@ -304,6 +310,8 @@ namespace AzFramework
|
||||
AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation.");
|
||||
manager->DestroyTicket(m_payload);
|
||||
m_payload = nullptr;
|
||||
AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex);
|
||||
manager->m_entitySpawnTicketMap.erase(m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
@@ -312,17 +320,23 @@ namespace AzFramework
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
auto manager = SpawnableEntitiesInterface::Get();
|
||||
AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation.");
|
||||
if (m_payload)
|
||||
{
|
||||
auto manager = SpawnableEntitiesInterface::Get();
|
||||
AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation.");
|
||||
manager->DestroyTicket(m_payload);
|
||||
}
|
||||
|
||||
Id previousId = m_id;
|
||||
m_id = rhs.m_id;
|
||||
rhs.m_id = 0;
|
||||
|
||||
m_payload = rhs.m_payload;
|
||||
rhs.m_payload = nullptr;
|
||||
|
||||
AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex);
|
||||
manager->m_entitySpawnTicketMap.erase(previousId);
|
||||
manager->m_entitySpawnTicketMap.insert_or_assign(m_id, this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace AzFramework
|
||||
public:
|
||||
friend class SpawnableEntitiesDefinition;
|
||||
|
||||
using Id = uint64_t;
|
||||
using Id = uint32_t;
|
||||
|
||||
EntitySpawnTicket() = default;
|
||||
EntitySpawnTicket(const EntitySpawnTicket&) = delete;
|
||||
@@ -176,6 +176,7 @@ namespace AzFramework
|
||||
using EntitySpawnCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableConstEntityContainerView)>;
|
||||
using EntityPreInsertionCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableEntityContainerView)>;
|
||||
using EntityDespawnCallback = AZStd::function<void(EntitySpawnTicket::Id)>;
|
||||
using RetrieveEntitySpawnTicketCallback = AZStd::function<void(EntitySpawnTicket*)>;
|
||||
using ReloadSpawnableCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableConstEntityContainerView)>;
|
||||
using ListEntitiesCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableConstEntityContainerView)>;
|
||||
using ListIndicesEntitiesCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableConstIndexEntityContainerView)>;
|
||||
@@ -220,12 +221,21 @@ namespace AzFramework
|
||||
struct DespawnAllEntitiesOptionalArgs final
|
||||
{
|
||||
//! Callback that's called when despawning entities has completed. This can be triggered from a different thread than the one that
|
||||
//! made the function call to despawn. The returned list of entities contains all the newly created entities.
|
||||
//! made the function call to despawn.
|
||||
EntityDespawnCallback m_completionCallback;
|
||||
//! The priority at which this call will be executed.
|
||||
SpawnablePriority m_priority { SpawnablePriority_Default };
|
||||
};
|
||||
|
||||
struct DespawnEntityOptionalArgs final
|
||||
{
|
||||
//! Callback that's called when despawning entity has completed. This can be triggered from a different thread than the one that
|
||||
//! made the function call to despawn.
|
||||
EntityDespawnCallback m_completionCallback;
|
||||
//! The priority at which this call will be executed.
|
||||
SpawnablePriority m_priority{ SpawnablePriority_Default };
|
||||
};
|
||||
|
||||
struct ReloadSpawnableOptionalArgs final
|
||||
{
|
||||
//! Callback that's called when respawning entities has completed. This can be triggered from a different thread than the one that
|
||||
@@ -291,9 +301,17 @@ namespace AzFramework
|
||||
EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) = 0;
|
||||
//! Removes all entities in the provided list from the environment.
|
||||
//! @param ticket The ticket previously used to spawn entities with.
|
||||
//! @param priority The priority at which this call will be executed.
|
||||
//! @param optionalArgs Optional additional arguments, see DespawnAllEntitiesOptionalArgs.
|
||||
virtual void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) = 0;
|
||||
//! Removes the entity with the provided id from the spawned list of entities.
|
||||
//! @param entityId the id of entity to despawn.
|
||||
//! @param ticket The ticket previously used to spawn entities with.
|
||||
//! @param optionalArgs Optional additional arguments, see DespawnEntityOptionalArgs.
|
||||
virtual void DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs = {}) = 0;
|
||||
//! Gets the EntitySpawnTicket associated with the entitySpawnTicketId.
|
||||
//! @param entitySpawnTicketId the id of EntitySpawnTicket to get.
|
||||
//! @param callback The callback to execute upon retrieving the ticket.
|
||||
virtual void RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback) = 0;
|
||||
//! Removes all entities in the provided list from the environment and reconstructs the entities from the provided spawnable.
|
||||
//! @param ticket Holds the information on the entities to reload.
|
||||
//! @param priority The priority at which this call will be executed.
|
||||
@@ -361,6 +379,9 @@ namespace AzFramework
|
||||
{
|
||||
return reinterpret_cast<const T*>(ticket->m_payload);
|
||||
}
|
||||
|
||||
AZStd::unordered_map<EntitySpawnTicket::Id, EntitySpawnTicket*> m_entitySpawnTicketMap;
|
||||
AZStd::recursive_mutex m_entitySpawnTicketMapMutex;
|
||||
};
|
||||
|
||||
using SpawnableEntitiesInterface = AZ::Interface<SpawnableEntitiesDefinition>;
|
||||
|
||||
@@ -85,6 +85,35 @@ namespace AzFramework
|
||||
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs)
|
||||
{
|
||||
AZ_Assert(ticket.IsValid(), "Ticket provided to DespawnEntity hasn't been initialized.");
|
||||
|
||||
DespawnEntityCommand queueEntry;
|
||||
queueEntry.m_ticketId = ticket.GetId();
|
||||
queueEntry.m_entityId = entityId;
|
||||
queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback);
|
||||
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback)
|
||||
{
|
||||
if (entitySpawnTicketId == 0)
|
||||
{
|
||||
AZ_Assert(false, "Ticket id provided to RetrieveEntitySpawnTicket is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::scoped_lock lock(m_entitySpawnTicketMapMutex);
|
||||
auto entitySpawnTicketIterator = m_entitySpawnTicketMap.find(entitySpawnTicketId);
|
||||
if (entitySpawnTicketIterator == m_entitySpawnTicketMap.end())
|
||||
{
|
||||
AZ_Assert(false, "The EntitySpawnTicket corresponding to id '%lu' cannot be found", entitySpawnTicketId);
|
||||
return;
|
||||
}
|
||||
callback(entitySpawnTicketIterator->second);
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::ReloadSpawnable(
|
||||
EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs)
|
||||
{
|
||||
@@ -223,12 +252,13 @@ namespace AzFramework
|
||||
return queue.m_delayed.empty() ? CommandQueueStatus::NoCommandsLeft : CommandQueueStatus::HasCommandsLeft;
|
||||
}
|
||||
|
||||
AZStd::pair<uint64_t, void*> SpawnableEntitiesManager::CreateTicket(AZ::Data::Asset<Spawnable>&& spawnable)
|
||||
AZStd::pair<EntitySpawnTicket::Id, void*> SpawnableEntitiesManager::CreateTicket(AZ::Data::Asset<Spawnable>&& spawnable)
|
||||
{
|
||||
static AZStd::atomic_uint64_t idCounter { 1 };
|
||||
static AZStd::atomic_uint32_t idCounter { 1 };
|
||||
|
||||
auto result = aznew Ticket();
|
||||
result->m_spawnable = AZStd::move(spawnable);
|
||||
|
||||
return AZStd::make_pair<EntitySpawnTicket::Id, void*>(idCounter++, result);
|
||||
}
|
||||
|
||||
@@ -339,6 +369,7 @@ namespace AzFramework
|
||||
// Add to the game context, now the entities are active
|
||||
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
|
||||
{
|
||||
(*it)->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
|
||||
}
|
||||
|
||||
@@ -420,6 +451,7 @@ namespace AzFramework
|
||||
// Add to the game context, now the entities are active
|
||||
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
|
||||
{
|
||||
(*it)->SetSpawnTicketId(request.m_ticketId);
|
||||
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
|
||||
}
|
||||
|
||||
@@ -447,8 +479,10 @@ namespace AzFramework
|
||||
{
|
||||
if (entity != nullptr)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
entity->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId());
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,6 +503,40 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool SpawnableEntitiesManager::ProcessRequest(DespawnEntityCommand& request)
|
||||
{
|
||||
Ticket& ticket = *request.m_ticket;
|
||||
if (request.m_requestId == ticket.m_currentRequestId)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*>& spawnedEntities = request.m_ticket->m_spawnedEntities;
|
||||
for (auto entityIterator = spawnedEntities.begin(); entityIterator != spawnedEntities.end(); ++entityIterator)
|
||||
{
|
||||
if (*entityIterator != nullptr && (*entityIterator)->GetId() == request.m_entityId)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
(*entityIterator)->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, (*entityIterator)->GetId());
|
||||
AZStd::iter_swap(entityIterator, spawnedEntities.rbegin());
|
||||
spawnedEntities.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (request.m_completionCallback)
|
||||
{
|
||||
request.m_completionCallback(request.m_ticketId);
|
||||
}
|
||||
|
||||
ticket.m_currentRequestId++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SpawnableEntitiesManager::ProcessRequest(ReloadSpawnableCommand& request)
|
||||
{
|
||||
Ticket& ticket = *request.m_ticket;
|
||||
@@ -482,8 +550,10 @@ namespace AzFramework
|
||||
{
|
||||
if (entity != nullptr)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
entity->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId());
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,8 +706,10 @@ namespace AzFramework
|
||||
{
|
||||
if (entity != nullptr)
|
||||
{
|
||||
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager.
|
||||
entity->SetSpawnTicketId(0);
|
||||
GameEntityContextRequestBus::Broadcast(
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId());
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
|
||||
}
|
||||
}
|
||||
delete request.m_ticket;
|
||||
|
||||
@@ -57,6 +57,8 @@ namespace AzFramework
|
||||
void SpawnEntities(
|
||||
EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) override;
|
||||
void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) override;
|
||||
void DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs = {}) override;
|
||||
void RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback) override;
|
||||
void ReloadSpawnable(
|
||||
EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs = {}) override;
|
||||
|
||||
@@ -132,6 +134,14 @@ namespace AzFramework
|
||||
EntitySpawnTicket::Id m_ticketId;
|
||||
uint32_t m_requestId;
|
||||
};
|
||||
struct DespawnEntityCommand
|
||||
{
|
||||
EntityDespawnCallback m_completionCallback;
|
||||
Ticket* m_ticket;
|
||||
AZ::EntityId m_entityId;
|
||||
EntitySpawnTicket::Id m_ticketId;
|
||||
uint32_t m_requestId;
|
||||
};
|
||||
struct ReloadSpawnableCommand
|
||||
{
|
||||
AZ::Data::Asset<Spawnable> m_spawnable;
|
||||
@@ -176,8 +186,16 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
using Requests = AZStd::variant<
|
||||
SpawnAllEntitiesCommand, SpawnEntitiesCommand, DespawnAllEntitiesCommand, ReloadSpawnableCommand, ListEntitiesCommand,
|
||||
ListIndicesEntitiesCommand, ClaimEntitiesCommand, BarrierCommand, DestroyTicketCommand>;
|
||||
SpawnAllEntitiesCommand,
|
||||
SpawnEntitiesCommand,
|
||||
DespawnAllEntitiesCommand,
|
||||
DespawnEntityCommand,
|
||||
ReloadSpawnableCommand,
|
||||
ListEntitiesCommand,
|
||||
ListIndicesEntitiesCommand,
|
||||
ClaimEntitiesCommand,
|
||||
BarrierCommand,
|
||||
DestroyTicketCommand>;
|
||||
|
||||
struct Queue
|
||||
{
|
||||
@@ -199,6 +217,7 @@ namespace AzFramework
|
||||
bool ProcessRequest(SpawnAllEntitiesCommand& request);
|
||||
bool ProcessRequest(SpawnEntitiesCommand& request);
|
||||
bool ProcessRequest(DespawnAllEntitiesCommand& request);
|
||||
bool ProcessRequest(DespawnEntityCommand& request);
|
||||
bool ProcessRequest(ReloadSpawnableCommand& request);
|
||||
bool ProcessRequest(ListEntitiesCommand& request);
|
||||
bool ProcessRequest(ListIndicesEntitiesCommand& request);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Spawnable/SpawnableMetaData.h>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/StreamingInstall/StreamingInstallNotifications.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include "StreamingInstall.h"
|
||||
|
||||
namespace AzFramework
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
+1
-1
@@ -319,7 +319,7 @@ namespace AzFramework
|
||||
AZStd::thread_desc td;
|
||||
td.m_name = "TargetManager Thread";
|
||||
td.m_cpuId = AFFINITY_MASK_USERTHREADS;
|
||||
m_threadHandle = AZStd::thread(AZStd::bind(&TargetManagementComponent::TickThread, this), &td);
|
||||
m_threadHandle = AZStd::thread(td, AZStd::bind(&TargetManagementComponent::TickThread, this));
|
||||
}
|
||||
|
||||
void TargetManagementComponent::Deactivate()
|
||||
|
||||
@@ -17,15 +17,6 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
AZ_CVAR(
|
||||
float,
|
||||
ed_cameraSystemDefaultPlaneHeight,
|
||||
34.0f,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The default height of the ground plane to do intersection tests against when orbiting");
|
||||
AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(
|
||||
bool,
|
||||
ed_cameraSystemUseCursor,
|
||||
@@ -135,8 +126,8 @@ namespace AzFramework
|
||||
|
||||
camera.m_pitch = eulerAngles.GetX();
|
||||
camera.m_yaw = eulerAngles.GetZ();
|
||||
// note: m_lookDist is negative so we must invert it here
|
||||
camera.m_lookAt = transform.GetTranslation() + (camera.Rotation().GetBasisY() * -camera.m_lookDist);
|
||||
camera.m_pivot = transform.GetTranslation();
|
||||
camera.m_offset = AZ::Vector3::CreateZero();
|
||||
}
|
||||
|
||||
bool CameraSystem::HandleEvents(const InputEvent& event)
|
||||
@@ -320,14 +311,8 @@ namespace AzFramework
|
||||
nextCamera.m_pitch -= float(cursorDelta.m_y) * rotateSpeed * Invert(m_invertPitchFn());
|
||||
nextCamera.m_yaw -= float(cursorDelta.m_x) * rotateSpeed * Invert(m_invertYawFn());
|
||||
|
||||
const auto clampRotation = [](const float angle)
|
||||
{
|
||||
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
|
||||
};
|
||||
|
||||
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
|
||||
// clamp pitch to be +/-90 degrees
|
||||
nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi);
|
||||
nextCamera.m_yaw = WrapYawRotation(nextCamera.m_yaw);
|
||||
nextCamera.m_pitch = ClampPitchRotation(nextCamera.m_pitch);
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
@@ -337,9 +322,10 @@ namespace AzFramework
|
||||
m_rotateChannelId = rotateChannelId;
|
||||
}
|
||||
|
||||
PanCameraInput::PanCameraInput(const InputChannelId& panChannelId, PanAxesFn panAxesFn)
|
||||
PanCameraInput::PanCameraInput(const InputChannelId& panChannelId, PanAxesFn panAxesFn, TranslationDeltaFn translationDeltaFn)
|
||||
: m_panAxesFn(AZStd::move(panAxesFn))
|
||||
, m_panChannelId(panChannelId)
|
||||
, m_translationDeltaFn(translationDeltaFn)
|
||||
{
|
||||
m_panSpeedFn = []() constexpr
|
||||
{
|
||||
@@ -375,11 +361,11 @@ namespace AzFramework
|
||||
const auto panAxes = m_panAxesFn(nextCamera);
|
||||
|
||||
const float panSpeed = m_panSpeedFn();
|
||||
const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * panSpeed;
|
||||
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * panSpeed;
|
||||
const auto deltaPanX = aznumeric_cast<float>(cursorDelta.m_x) * panAxes.m_horizontalAxis * panSpeed;
|
||||
const auto deltaPanY = aznumeric_cast<float>(cursorDelta.m_y) * panAxes.m_verticalAxis * panSpeed;
|
||||
|
||||
nextCamera.m_lookAt += deltaPanX * Invert(m_invertPanXFn());
|
||||
nextCamera.m_lookAt += deltaPanY * -Invert(m_invertPanYFn());
|
||||
m_translationDeltaFn(nextCamera, deltaPanX * Invert(m_invertPanXFn()));
|
||||
m_translationDeltaFn(nextCamera, deltaPanY * -Invert(m_invertPanYFn()));
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
@@ -426,8 +412,11 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
TranslateCameraInput::TranslateCameraInput(
|
||||
TranslationAxesFn translationAxesFn, const TranslateCameraInputChannelIds& translateCameraInputChannelIds)
|
||||
const TranslateCameraInputChannelIds& translateCameraInputChannelIds,
|
||||
TranslationAxesFn translationAxesFn,
|
||||
TranslationDeltaFn translateDeltaFn)
|
||||
: m_translationAxesFn(AZStd::move(translationAxesFn))
|
||||
, m_translateDeltaFn(AZStd::move(translateDeltaFn))
|
||||
, m_translateCameraInputChannelIds(translateCameraInputChannelIds)
|
||||
{
|
||||
m_translateSpeedFn = []() constexpr
|
||||
@@ -497,32 +486,32 @@ namespace AzFramework
|
||||
|
||||
if ((m_translation & TranslationType::Forward) == TranslationType::Forward)
|
||||
{
|
||||
nextCamera.m_lookAt += axisY * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, axisY * speed * deltaTime);
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Backward) == TranslationType::Backward)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisY * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, -axisY * speed * deltaTime);
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Left) == TranslationType::Left)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisX * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, -axisX * speed * deltaTime);
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Right) == TranslationType::Right)
|
||||
{
|
||||
nextCamera.m_lookAt += axisX * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, axisX * speed * deltaTime);
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Up) == TranslationType::Up)
|
||||
{
|
||||
nextCamera.m_lookAt += axisZ * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, axisZ * speed * deltaTime);
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Down) == TranslationType::Down)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisZ * speed * deltaTime;
|
||||
m_translateDeltaFn(nextCamera, -axisZ * speed * deltaTime);
|
||||
}
|
||||
|
||||
if (Ending())
|
||||
@@ -544,16 +533,20 @@ namespace AzFramework
|
||||
m_translateCameraInputChannelIds = translateCameraInputChannelIds;
|
||||
}
|
||||
|
||||
OrbitCameraInput::OrbitCameraInput(const InputChannelId& orbitChannelId)
|
||||
: m_orbitChannelId(orbitChannelId)
|
||||
PivotCameraInput::PivotCameraInput(const InputChannelId& pivotChannelId)
|
||||
: m_pivotChannelId(pivotChannelId)
|
||||
{
|
||||
m_pivotFn = []([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
{
|
||||
return AZ::Vector3::CreateZero();
|
||||
};
|
||||
}
|
||||
|
||||
bool OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta)
|
||||
bool PivotCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_orbitChannelId)
|
||||
if (input->m_channelId == m_pivotChannelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
@@ -568,85 +561,46 @@ namespace AzFramework
|
||||
|
||||
if (Active())
|
||||
{
|
||||
return m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
return m_pivotCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera OrbitCameraInput::StepCamera(
|
||||
Camera PivotCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
if (Beginning())
|
||||
{
|
||||
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn]
|
||||
{
|
||||
if (lookAtFn)
|
||||
{
|
||||
// pass through the camera's position and look vector for use in the lookAt function
|
||||
if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
|
||||
{
|
||||
// default to internal look at behavior if the look at point matches the camera translation
|
||||
if (targetCamera.m_lookAt.IsClose(*lookAt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
|
||||
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
|
||||
UpdateCameraFromTransform(nextCamera, transform);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (!hasLookAt)
|
||||
{
|
||||
float hit_distance = 0.0f;
|
||||
AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight))
|
||||
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance);
|
||||
|
||||
if (hit_distance > 0.0f)
|
||||
{
|
||||
hit_distance = AZStd::min<float>(hit_distance, ed_cameraSystemMaxOrbitDistance);
|
||||
nextCamera.m_lookDist = -hit_distance;
|
||||
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * hit_distance;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextCamera.m_lookDist = -ed_cameraSystemMinOrbitDistance;
|
||||
nextCamera.m_lookAt =
|
||||
targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * ed_cameraSystemMinOrbitDistance;
|
||||
}
|
||||
}
|
||||
nextCamera.m_pivot = m_pivotFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY());
|
||||
nextCamera.m_offset = nextCamera.View().TransformPoint(targetCamera.Translation());
|
||||
}
|
||||
|
||||
if (Active())
|
||||
{
|
||||
nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
MovePivotDetached(nextCamera, m_pivotFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()));
|
||||
nextCamera = m_pivotCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
if (Ending())
|
||||
{
|
||||
m_orbitCameras.Reset();
|
||||
m_pivotCameras.Reset();
|
||||
|
||||
nextCamera.m_lookAt = nextCamera.Translation();
|
||||
nextCamera.m_lookDist = 0.0f;
|
||||
nextCamera.m_pivot = nextCamera.Translation();
|
||||
nextCamera.m_offset = AZ::Vector3::CreateZero();
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitCameraInput::SetOrbitInputChannelId(const InputChannelId& orbitChanneId)
|
||||
void PivotCameraInput::SetPivotInputChannelId(const InputChannelId& pivotChanneId)
|
||||
{
|
||||
m_orbitChannelId = orbitChanneId;
|
||||
m_pivotChannelId = pivotChanneId;
|
||||
}
|
||||
|
||||
OrbitDollyScrollCameraInput::OrbitDollyScrollCameraInput()
|
||||
PivotDollyScrollCameraInput::PivotDollyScrollCameraInput()
|
||||
{
|
||||
m_scrollSpeedFn = []() constexpr
|
||||
{
|
||||
@@ -654,7 +608,7 @@ namespace AzFramework
|
||||
};
|
||||
}
|
||||
|
||||
bool OrbitDollyScrollCameraInput::HandleEvents(
|
||||
bool PivotDollyScrollCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
@@ -665,46 +619,61 @@ namespace AzFramework
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera OrbitDollyScrollCameraInput::StepCamera(
|
||||
static Camera PivotDolly(const Camera& targetCamera, const float delta)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
const auto pivotDirection = targetCamera.m_offset.GetNormalized();
|
||||
nextCamera.m_offset -= pivotDirection * delta;
|
||||
const auto pivotDot = targetCamera.m_offset.Dot(nextCamera.m_offset);
|
||||
const auto distance = nextCamera.m_offset.GetLength() * AZ::GetSign(pivotDot);
|
||||
|
||||
const auto minDistance = 0.01f;
|
||||
if (distance < minDistance || pivotDot < 0.0f)
|
||||
{
|
||||
nextCamera.m_offset = pivotDirection * minDistance;
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
Camera PivotDollyScrollCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
[[maybe_unused]] const ScreenVector& cursorDelta,
|
||||
const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_scrollSpeedFn(), 0.0f);
|
||||
const auto nextCamera = PivotDolly(targetCamera, aznumeric_cast<float>(scrollDelta) * m_scrollSpeedFn());
|
||||
EndActivation();
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
OrbitDollyCursorMoveCameraInput::OrbitDollyCursorMoveCameraInput(const InputChannelId& dollyChannelId)
|
||||
PivotDollyMotionCameraInput::PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId)
|
||||
: m_dollyChannelId(dollyChannelId)
|
||||
{
|
||||
m_cursorSpeedFn = []() constexpr
|
||||
m_motionSpeedFn = []() constexpr
|
||||
{
|
||||
return 0.01f;
|
||||
};
|
||||
}
|
||||
|
||||
bool OrbitDollyCursorMoveCameraInput::HandleEvents(
|
||||
bool PivotDollyMotionCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta)
|
||||
{
|
||||
HandleActivationEvents(event, m_dollyChannelId, cursorDelta, m_clickDetector, *this);
|
||||
return CameraInputUpdatingAfterMotion(*this);
|
||||
}
|
||||
|
||||
Camera OrbitDollyCursorMoveCameraInput::StepCamera(
|
||||
Camera PivotDollyMotionCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
const ScreenVector& cursorDelta,
|
||||
[[maybe_unused]] const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + float(cursorDelta.m_y) * m_cursorSpeedFn(), 0.0f);
|
||||
return nextCamera;
|
||||
return PivotDolly(targetCamera, aznumeric_cast<float>(cursorDelta.m_y) * m_motionSpeedFn());
|
||||
}
|
||||
|
||||
void OrbitDollyCursorMoveCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId)
|
||||
void PivotDollyMotionCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId)
|
||||
{
|
||||
m_dollyChannelId = dollyChannelId;
|
||||
}
|
||||
@@ -739,7 +708,7 @@ namespace AzFramework
|
||||
const auto translation_basis = LookTranslation(nextCamera);
|
||||
const auto axisY = translation_basis.GetBasisY();
|
||||
|
||||
nextCamera.m_lookAt += axisY * scrollDelta * m_scrollSpeedFn();
|
||||
nextCamera.m_pivot += axisY * scrollDelta * m_scrollSpeedFn();
|
||||
|
||||
EndActivation();
|
||||
|
||||
@@ -790,13 +759,13 @@ namespace AzFramework
|
||||
{
|
||||
const float moveRate = AZStd::exp2(cameraProps.m_translateSmoothnessFn());
|
||||
const float moveTime = AZStd::exp2(-moveRate * deltaTime);
|
||||
camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveTime);
|
||||
camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveTime);
|
||||
camera.m_pivot = targetCamera.m_pivot.Lerp(currentCamera.m_pivot, moveTime);
|
||||
camera.m_offset = targetCamera.m_offset.Lerp(currentCamera.m_offset, moveTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
camera.m_lookDist = targetCamera.m_lookDist;
|
||||
camera.m_lookAt = targetCamera.m_lookAt;
|
||||
camera.m_pivot = targetCamera.m_pivot;
|
||||
camera.m_offset = targetCamera.m_offset;
|
||||
}
|
||||
|
||||
return camera;
|
||||
|
||||
@@ -29,17 +29,15 @@ namespace AzFramework
|
||||
//! @note Order of rotation is Z, Y, X.
|
||||
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation);
|
||||
|
||||
//! A simple camera representation using spherical coordinates as input (pitch, yaw and look distance).
|
||||
//! A simple camera representation using spherical coordinates as input (pitch, yaw, pivot and offset).
|
||||
//! The cameras transform and view can be obtained through accessor functions that use the internal
|
||||
//! spherical coordinates to calculate the position and orientation.
|
||||
struct Camera
|
||||
{
|
||||
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
|
||||
//!< or position of m_lookAt when m_lookDist is greater
|
||||
//!< than zero.
|
||||
float m_yaw{ 0.0 }; //!< Yaw rotation of camera (stored in radians) usually clamped to 0-360 degrees (0-2Pi radians).
|
||||
float m_pitch{ 0.0 }; //!< Pitch rotation of the camera (stored in radians) usually clamped to +/-90 degrees (-Pi/2 - Pi/2 radians).
|
||||
float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
|
||||
AZ::Vector3 m_pivot = AZ::Vector3::CreateZero(); //!< Pivot point to rotate about (modified in world space).
|
||||
AZ::Vector3 m_offset = AZ::Vector3::CreateZero(); //!< Offset relative to pivot (modified in camera space).
|
||||
float m_yaw = 0.0f; //!< Yaw rotation of camera (stored in radians) usually clamped to 0-360 degrees (0-2Pi radians).
|
||||
float m_pitch = 0.0f; //!< Pitch rotation of the camera (stored in radians) usually clamped to +/-90 degrees (-Pi/2 - Pi/2 radians).
|
||||
|
||||
//! View camera transform (V in model-view-projection matrix (MVP)).
|
||||
AZ::Transform View() const;
|
||||
@@ -51,6 +49,15 @@ namespace AzFramework
|
||||
AZ::Vector3 Translation() const;
|
||||
};
|
||||
|
||||
//! Helper to allow the pivot to be positioned without altering the camera's position.
|
||||
inline void MovePivotDetached(Camera& camera, const AZ::Vector3& pivot)
|
||||
{
|
||||
const auto& view = camera.View();
|
||||
const auto delta = view.TransformPoint(pivot) - view.TransformPoint(camera.m_pivot);
|
||||
camera.m_offset -= delta;
|
||||
camera.m_pivot = pivot;
|
||||
}
|
||||
|
||||
inline AZ::Transform Camera::View() const
|
||||
{
|
||||
return Transform().GetInverse();
|
||||
@@ -58,8 +65,8 @@ namespace AzFramework
|
||||
|
||||
inline AZ::Transform Camera::Transform() const
|
||||
{
|
||||
return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) *
|
||||
AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(m_lookDist));
|
||||
return AZ::Transform::CreateTranslation(m_pivot) * AZ::Transform::CreateRotationZ(m_yaw) * AZ::Transform::CreateRotationX(m_pitch) *
|
||||
AZ::Transform::CreateTranslation(m_offset);
|
||||
}
|
||||
|
||||
inline AZ::Matrix3x3 Camera::Rotation() const
|
||||
@@ -279,21 +286,37 @@ namespace AzFramework
|
||||
public:
|
||||
bool HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, float deltaTime);
|
||||
bool HandlingEvents() const
|
||||
{
|
||||
return m_handlingEvents;
|
||||
}
|
||||
bool HandlingEvents() const;
|
||||
|
||||
Cameras m_cameras; //!< Represents a collection of camera inputs that together provide a camera controller.
|
||||
|
||||
private:
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/pivot/pan (rotation + translation) - two dimensional.
|
||||
CursorState m_cursorState; //!< The current and previous position of the cursor (used to calculate movement delta).
|
||||
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
|
||||
bool m_handlingEvents = false; //!< Is the camera system currently handling events (events are consumed and not propagated).
|
||||
};
|
||||
|
||||
//! A camera input to handle motion deltas that can rotate or orbit the camera.
|
||||
inline bool CameraSystem::HandlingEvents() const
|
||||
{
|
||||
return m_handlingEvents;
|
||||
}
|
||||
|
||||
//! Clamps pitch to be +/-90 degrees (-Pi/2, Pi/2).
|
||||
//! @param pitch Pitch angle in radians.
|
||||
inline float ClampPitchRotation(const float pitch)
|
||||
{
|
||||
return AZ::GetClamp(pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi);
|
||||
}
|
||||
|
||||
//! Ensures yaw wraps between 0 and 360 degrees (0, 2Pi).
|
||||
//! @param yaw Yaw angle in radians.
|
||||
inline float WrapYawRotation(const float yaw)
|
||||
{
|
||||
return AZStd::fmod(yaw + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
|
||||
}
|
||||
|
||||
//! A camera input to handle motion deltas that can rotate or pivot the camera.
|
||||
class RotateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -332,8 +355,8 @@ namespace AzFramework
|
||||
return { orientation.GetBasisX(), orientation.GetBasisZ() };
|
||||
}
|
||||
|
||||
//! PanAxes to use while in 'orbit' camera behavior.
|
||||
inline PanAxes OrbitPan(const Camera& camera)
|
||||
//! PanAxes to use while in 'pivot' camera behavior.
|
||||
inline PanAxes PivotPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
@@ -347,11 +370,23 @@ namespace AzFramework
|
||||
return { basisX, basisY };
|
||||
}
|
||||
|
||||
using TranslationDeltaFn = AZStd::function<void(Camera& camera, const AZ::Vector3& delta)>;
|
||||
|
||||
inline void TranslatePivot(Camera& camera, const AZ::Vector3& delta)
|
||||
{
|
||||
camera.m_pivot += delta;
|
||||
}
|
||||
|
||||
inline void TranslateOffset(Camera& camera, const AZ::Vector3& delta)
|
||||
{
|
||||
camera.m_offset += camera.View().TransformVector(delta);
|
||||
}
|
||||
|
||||
//! A camera input to handle motion deltas that can pan the camera (translate in two axes).
|
||||
class PanCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
PanCameraInput(const InputChannelId& panChannelId, PanAxesFn panAxesFn);
|
||||
PanCameraInput(const InputChannelId& panChannelId, PanAxesFn panAxesFn, TranslationDeltaFn translationDeltaFn);
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -365,6 +400,7 @@ namespace AzFramework
|
||||
|
||||
private:
|
||||
PanAxesFn m_panAxesFn; //!< Builder for the particular pan axes (provided in the constructor).
|
||||
TranslationDeltaFn m_translationDeltaFn; //!< How to apply the translation delta to the camera offset or pivot.
|
||||
InputChannelId m_panChannelId; //!< Input channel to begin the pan camera input.
|
||||
ClickDetector m_clickDetector; //!< Used to determine when a sufficient motion delta has occurred after an initial discrete input
|
||||
//!< event has started (press and move event).
|
||||
@@ -385,8 +421,8 @@ namespace AzFramework
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
//! TranslationAxes to use while in 'orbit' camera behavior.
|
||||
inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera)
|
||||
//! TranslationAxes to use while in 'pivot' camera behavior.
|
||||
inline AZ::Matrix3x3 PivotTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
@@ -417,8 +453,10 @@ namespace AzFramework
|
||||
class TranslateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit TranslateCameraInput(
|
||||
TranslationAxesFn translationAxesFn, const TranslateCameraInputChannelIds& translateCameraInputChannelIds);
|
||||
TranslateCameraInput(
|
||||
const TranslateCameraInputChannelIds& translateCameraInputChannelIds,
|
||||
TranslationAxesFn translationAxesFn,
|
||||
TranslationDeltaFn translateDeltaFn);
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -492,15 +530,16 @@ namespace AzFramework
|
||||
|
||||
TranslationType m_translation = TranslationType::Nil; //!< Types of translation the camera input is under.
|
||||
TranslationAxesFn m_translationAxesFn; //!< Builder for translation axes.
|
||||
TranslationDeltaFn m_translateDeltaFn; //!< How to apply the translation delta to the camera offset or pivot.
|
||||
TranslateCameraInputChannelIds m_translateCameraInputChannelIds; //!< Input channel ids that map to internal translation types.
|
||||
bool m_boost = false; //!< Is the translation speed currently being multiplied/scaled upwards.
|
||||
};
|
||||
|
||||
//! A camera input to handle discrete scroll events that can modify the camera look distance.
|
||||
class OrbitDollyScrollCameraInput : public CameraInput
|
||||
//! A camera input to handle discrete scroll events that can modify the camera pivot distance.
|
||||
class PivotDollyScrollCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
OrbitDollyScrollCameraInput();
|
||||
PivotDollyScrollCameraInput();
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -509,11 +548,11 @@ namespace AzFramework
|
||||
AZStd::function<float()> m_scrollSpeedFn;
|
||||
};
|
||||
|
||||
//! A camera input to handle motion deltas that can modify the camera look distance.
|
||||
class OrbitDollyCursorMoveCameraInput : public CameraInput
|
||||
//! A camera input to handle motion deltas that can modify the camera pivot distance.
|
||||
class PivotDollyMotionCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit OrbitDollyCursorMoveCameraInput(const InputChannelId& dollyChannelId);
|
||||
explicit PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId);
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -521,7 +560,7 @@ namespace AzFramework
|
||||
|
||||
void SetDollyInputChannelId(const InputChannelId& dollyChannelId);
|
||||
|
||||
AZStd::function<float()> m_cursorSpeedFn;
|
||||
AZStd::function<float()> m_motionSpeedFn;
|
||||
|
||||
private:
|
||||
InputChannelId m_dollyChannelId; //!< Input channel to begin the dolly cursor camera input.
|
||||
@@ -544,36 +583,36 @@ namespace AzFramework
|
||||
|
||||
//! A camera input that doubles as its own set of camera inputs.
|
||||
//! It is 'exclusive', so does not overlap with other sibling camera inputs - it runs its own set of camera inputs as 'children'.
|
||||
class OrbitCameraInput : public CameraInput
|
||||
class PivotCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>(const AZ::Vector3& position, const AZ::Vector3& direction)>;
|
||||
using PivotFn = AZStd::function<AZ::Vector3(const AZ::Vector3& position, const AZ::Vector3& direction)>;
|
||||
|
||||
explicit OrbitCameraInput(const InputChannelId& orbitChannelId);
|
||||
explicit PivotCameraInput(const InputChannelId& pivotChannelId);
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
bool Exclusive() const override;
|
||||
|
||||
void SetOrbitInputChannelId(const InputChannelId& orbitChanneId);
|
||||
void SetPivotInputChannelId(const InputChannelId& pivotChanneId);
|
||||
|
||||
Cameras m_orbitCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive).
|
||||
Cameras m_pivotCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive).
|
||||
|
||||
//! Override the default behavior for how a look-at point is calculated.
|
||||
void SetLookAtFn(const LookAtFn& lookAtFn);
|
||||
//! Override the default behavior for how a pivot point is calculated.
|
||||
void SetPivotFn(PivotFn pivotFn);
|
||||
|
||||
private:
|
||||
InputChannelId m_orbitChannelId; //!< Input channel to begin the orbit camera input.
|
||||
LookAtFn m_lookAtFn; //!< The look-at behavior to use for this orbit camera (how is the look-at point calculated/retrieved).
|
||||
InputChannelId m_pivotChannelId; //!< Input channel to begin the pivot camera input.
|
||||
PivotFn m_pivotFn; //!< The pivot position to use for this pivot camera (how is the pivot point calculated/retrieved).
|
||||
};
|
||||
|
||||
inline void OrbitCameraInput::SetLookAtFn(const LookAtFn& lookAtFn)
|
||||
inline void PivotCameraInput::SetPivotFn(PivotFn pivotFn)
|
||||
{
|
||||
m_lookAtFn = lookAtFn;
|
||||
m_pivotFn = AZStd::move(pivotFn);
|
||||
}
|
||||
|
||||
inline bool OrbitCameraInput::Exclusive() const
|
||||
inline bool PivotCameraInput::Exclusive() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/RTTI/TypeInfoSimple.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/RTTI/TypeInfoSimple.h>
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -27,7 +26,11 @@ namespace AzFramework
|
||||
AZ_TYPE_INFO(ScreenPoint, "{8472B6C2-527F-44FC-87F8-C226B1A57A97}");
|
||||
ScreenPoint() = default;
|
||||
|
||||
ScreenPoint(int x, int y) : m_x(x), m_y(y) {}
|
||||
ScreenPoint(int x, int y)
|
||||
: m_x(x)
|
||||
, m_y(y)
|
||||
{
|
||||
}
|
||||
|
||||
int m_x; //!< X screen position.
|
||||
int m_y; //!< Y screen position.
|
||||
@@ -42,7 +45,11 @@ namespace AzFramework
|
||||
AZ_TYPE_INFO(ScreenVector, "{1EAA2C62-8FDB-4A28-9FE3-1FA4F1418894}");
|
||||
ScreenVector() = default;
|
||||
|
||||
ScreenVector(int x, int y) : m_x(x), m_y(y) {}
|
||||
ScreenVector(int x, int y)
|
||||
: m_x(x)
|
||||
, m_y(y)
|
||||
{
|
||||
}
|
||||
|
||||
int m_x; //!< X screen delta.
|
||||
int m_y; //!< Y screen delta.
|
||||
@@ -71,14 +78,14 @@ namespace AzFramework
|
||||
|
||||
inline const ScreenPoint operator+(const ScreenPoint& lhs, const ScreenVector& rhs)
|
||||
{
|
||||
ScreenPoint result{lhs};
|
||||
ScreenPoint result{ lhs };
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const ScreenPoint operator-(const ScreenPoint& lhs, const ScreenVector& rhs)
|
||||
{
|
||||
ScreenPoint result{lhs};
|
||||
ScreenPoint result{ lhs };
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
@@ -99,14 +106,14 @@ namespace AzFramework
|
||||
|
||||
inline const ScreenVector operator+(const ScreenVector& lhs, const ScreenVector& rhs)
|
||||
{
|
||||
ScreenVector result{lhs};
|
||||
ScreenVector result{ lhs };
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const ScreenVector operator-(const ScreenVector& lhs, const ScreenVector& rhs)
|
||||
{
|
||||
ScreenVector result{lhs};
|
||||
ScreenVector result{ lhs };
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
@@ -131,23 +138,25 @@ namespace AzFramework
|
||||
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));
|
||||
lhs.m_y = aznumeric_cast<int>(AZStd::lround(aznumeric_cast<float>(lhs.m_y) * rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline const ScreenVector operator*(const ScreenVector& lhs, const float rhs)
|
||||
{
|
||||
ScreenVector 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));
|
||||
}
|
||||
|
||||
inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize)
|
||||
{
|
||||
return ScreenPoint(
|
||||
aznumeric_caster(AZStd::round(screenNDC.GetX() * viewportSize.GetX())),
|
||||
aznumeric_caster(AZStd::round((1.0f - screenNDC.GetY()) * viewportSize.GetY())));
|
||||
}
|
||||
|
||||
inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize)
|
||||
{
|
||||
return AZ::Vector2(aznumeric_cast<float>(screenPoint.m_x), viewportSize.GetY() - aznumeric_cast<float>(screenPoint.m_y)) / viewportSize;
|
||||
}
|
||||
|
||||
//! Return an AZ::Vector2 from a ScreenPoint.
|
||||
inline AZ::Vector2 Vector2FromScreenPoint(const ScreenPoint& screenPoint)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace AzFramework
|
||||
// y-up, z into the screen, x-left
|
||||
//
|
||||
// x -> -x
|
||||
// y -> z
|
||||
// y -> z
|
||||
// z -> y
|
||||
//
|
||||
// the same transform can be used to go to/from z-up - the only difference is the order of
|
||||
@@ -37,15 +37,15 @@ namespace AzFramework
|
||||
// yaw = AZ::Matrix4x4::CreateRotationZ(AZ::DegToRad(180.0f));
|
||||
// conversion = pitch * yaw
|
||||
return AZ::Matrix4x4::CreateFromColumns(
|
||||
AZ::Vector4(-1.0f, 0.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 1.0f, .0f),
|
||||
AZ::Vector4(0.0f, 1.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
AZ::Vector4(-1.0f, 0.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 1.0f, 0.0f), AZ::Vector4(0.0f, 1.0f, 0.0f, 0.0f),
|
||||
AZ::Vector4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
AZ::Matrix4x4 CameraTransform(const CameraState& cameraState)
|
||||
{
|
||||
return AZ::Matrix4x4::CreateFromColumns(
|
||||
AZ::Vector3ToVector4(cameraState.m_side), AZ::Vector3ToVector4(cameraState.m_forward),
|
||||
AZ::Vector3ToVector4(cameraState.m_up), AZ::Vector3ToVector4(cameraState.m_position, 1.0f));
|
||||
AZ::Vector3ToVector4(cameraState.m_side), AZ::Vector3ToVector4(cameraState.m_forward), AZ::Vector3ToVector4(cameraState.m_up),
|
||||
AZ::Vector3ToVector4(cameraState.m_position, 1.0f));
|
||||
}
|
||||
|
||||
AZ::Matrix4x4 CameraView(const CameraState& cameraState)
|
||||
@@ -63,8 +63,7 @@ namespace AzFramework
|
||||
AZ::Matrix4x4 CameraProjection(const CameraState& cameraState)
|
||||
{
|
||||
return AZ::Matrix4x4::CreateProjection(
|
||||
cameraState.VerticalFovRadian(), AspectRatio(cameraState.m_viewportSize), cameraState.m_nearClip,
|
||||
cameraState.m_farClip);
|
||||
cameraState.VerticalFovRadian(), AspectRatio(cameraState.m_viewportSize), cameraState.m_nearClip, cameraState.m_farClip);
|
||||
}
|
||||
|
||||
AZ::Matrix4x4 InverseCameraProjection(const CameraState& cameraState)
|
||||
@@ -93,12 +92,11 @@ namespace AzFramework
|
||||
const auto cameraWorldTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation(
|
||||
AZ::Matrix3x3::CreateFromMatrix4x4(worldFromView), worldFromView.GetTranslation());
|
||||
return AZ::ViewFrustumAttributes(
|
||||
cameraWorldTransform, AspectRatio(cameraState.m_viewportSize), cameraState.m_fovOrZoom,
|
||||
cameraState.m_nearClip, cameraState.m_farClip);
|
||||
cameraWorldTransform, AspectRatio(cameraState.m_viewportSize), cameraState.m_fovOrZoom, cameraState.m_nearClip,
|
||||
cameraState.m_farClip);
|
||||
}
|
||||
|
||||
AZ::Vector3 WorldToScreenNDC(
|
||||
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection)
|
||||
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection)
|
||||
{
|
||||
// transform the world space position to clip space
|
||||
const auto clipSpacePosition = cameraProjection * cameraView * AZ::Vector3ToVector4(worldPosition, 1.0f);
|
||||
@@ -108,25 +106,24 @@ namespace AzFramework
|
||||
return (AZ::Vector4ToVector3(ndcPosition) + AZ::Vector3::CreateOne()) * 0.5f;
|
||||
}
|
||||
|
||||
|
||||
ScreenPoint WorldToScreen(
|
||||
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection,
|
||||
const AZ::Vector3& worldPosition,
|
||||
const AZ::Matrix4x4& cameraView,
|
||||
const AZ::Matrix4x4& cameraProjection,
|
||||
const AZ::Vector2& viewportSize)
|
||||
{
|
||||
const auto ndcNormalizedPosition = WorldToScreenNDC(worldPosition, cameraView, cameraProjection);
|
||||
const auto ndcNormalizedPosition = WorldToScreenNdc(worldPosition, cameraView, cameraProjection);
|
||||
// scale ndc position by screen dimensions to return screen position
|
||||
return ScreenPointFromNDC(ndcNormalizedPosition, viewportSize);
|
||||
return ScreenPointFromNdc(AZ::Vector3ToVector2(ndcNormalizedPosition), viewportSize);
|
||||
}
|
||||
|
||||
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState)
|
||||
{
|
||||
return WorldToScreen(
|
||||
worldPosition, CameraView(cameraState), CameraProjection(cameraState), cameraState.m_viewportSize);
|
||||
return WorldToScreen(worldPosition, CameraView(cameraState), CameraProjection(cameraState), cameraState.m_viewportSize);
|
||||
}
|
||||
|
||||
AZ::Vector3 ScreenNDCToWorld(
|
||||
const AZ::Vector2& normalizedScreenPosition, const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection)
|
||||
AZ::Vector3 ScreenNdcToWorld(
|
||||
const AZ::Vector2& normalizedScreenPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection)
|
||||
{
|
||||
// convert screen space coordinates from <0, 1> to <-1,1> range
|
||||
const auto ndcPosition = normalizedScreenPosition * 2.0f - AZ::Vector2::CreateOne();
|
||||
@@ -142,18 +139,19 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
AZ::Vector3 ScreenToWorld(
|
||||
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize)
|
||||
const ScreenPoint& screenPosition,
|
||||
const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection,
|
||||
const AZ::Vector2& viewportSize)
|
||||
{
|
||||
const auto normalizedScreenPosition = NDCFromScreenPoint(screenPosition, viewportSize);
|
||||
const auto normalizedScreenPosition = NdcFromScreenPoint(screenPosition, viewportSize);
|
||||
|
||||
return ScreenNDCToWorld(normalizedScreenPosition, inverseCameraView, inverseCameraProjection);
|
||||
return ScreenNdcToWorld(normalizedScreenPosition, inverseCameraView, inverseCameraProjection);
|
||||
}
|
||||
|
||||
AZ::Vector3 ScreenToWorld(const ScreenPoint& screenPosition, const CameraState& cameraState)
|
||||
{
|
||||
return ScreenToWorld(
|
||||
screenPosition, InverseCameraView(cameraState), InverseCameraProjection(cameraState),
|
||||
cameraState.m_viewportSize);
|
||||
screenPosition, InverseCameraView(cameraState), InverseCameraProjection(cameraState), cameraState.m_viewportSize);
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -8,26 +8,42 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Frustum;
|
||||
class Matrix4x4;
|
||||
class Vector3;
|
||||
struct ViewFrustumAttributes;
|
||||
} // namespace AZ
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct CameraState;
|
||||
struct ScreenPoint;
|
||||
struct ViewportInfo;
|
||||
|
||||
//! Projects a position in world space to screen space normalized device coordinates for the given camera.
|
||||
AZ::Vector3 WorldToScreenNDC(
|
||||
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection);
|
||||
//! Returns a position in screen space (in the range [0-viewportSize.x, 0-viewportSize.y]) from normalized device
|
||||
//! coordinates (in the range 0.0-1.0).
|
||||
inline ScreenPoint ScreenPointFromNdc(const AZ::Vector2& screenNdc, const AZ::Vector2& viewportSize)
|
||||
{
|
||||
return ScreenPoint(
|
||||
aznumeric_cast<int>(AZStd::lround(screenNdc.GetX() * viewportSize.GetX())),
|
||||
aznumeric_cast<int>(AZStd::lround((1.0f - screenNdc.GetY()) * viewportSize.GetY())));
|
||||
}
|
||||
|
||||
//! Returns a position in normalized device coordinates (in the range [0.0-1.0, 0.0-1.0]) from a
|
||||
//! screen space position (in the range [0-viewportSize.x, 0-viewportSize.y]).
|
||||
inline AZ::Vector2 NdcFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize)
|
||||
{
|
||||
return AZ::Vector2(aznumeric_cast<float>(screenPoint.m_x), viewportSize.GetY() - aznumeric_cast<float>(screenPoint.m_y)) /
|
||||
viewportSize;
|
||||
}
|
||||
|
||||
//! Projects a position in world space to screen space normalized device coordinates for the given camera.
|
||||
AZ::Vector3 WorldToScreenNdc(const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection);
|
||||
|
||||
//! Projects a position in world space to screen space for the given camera.
|
||||
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState);
|
||||
@@ -35,7 +51,9 @@ namespace AzFramework
|
||||
//! Overload of WorldToScreen that accepts camera values that can be precomputed if this function
|
||||
//! is called many times in a loop.
|
||||
ScreenPoint WorldToScreen(
|
||||
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection,
|
||||
const AZ::Vector3& worldPosition,
|
||||
const AZ::Matrix4x4& cameraView,
|
||||
const AZ::Matrix4x4& cameraProjection,
|
||||
const AZ::Vector2& viewportSize);
|
||||
|
||||
//! Unprojects a position in screen space pixel coordinates to world space.
|
||||
@@ -45,14 +63,15 @@ namespace AzFramework
|
||||
//! Overload of ScreenToWorld that accepts camera values that can be precomputed if this function
|
||||
//! is called many times in a loop.
|
||||
AZ::Vector3 ScreenToWorld(
|
||||
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize);
|
||||
const ScreenPoint& screenPosition,
|
||||
const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection,
|
||||
const AZ::Vector2& viewportSize);
|
||||
|
||||
//! Unprojects a position in screen space normalized device coordinates to world space.
|
||||
//! Note: The position returned will be on the near clip plane of the camera in world space.
|
||||
AZ::Vector3 ScreenNDCToWorld(
|
||||
const AZ::Vector2& ndcPosition, const AZ::Matrix4x4& inverseCameraView,
|
||||
const AZ::Matrix4x4& inverseCameraProjection);
|
||||
AZ::Vector3 ScreenNdcToWorld(
|
||||
const AZ::Vector2& ndcPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection);
|
||||
|
||||
//! Returns the camera projection for the current camera state.
|
||||
AZ::Matrix4x4 CameraProjection(const CameraState& cameraState);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
NAMESPACE AZ
|
||||
FILES_CMAKE
|
||||
Tests/frameworktests_files.cmake
|
||||
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Tests
|
||||
@@ -93,6 +94,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
NAME AZ::AzFramework.Tests
|
||||
)
|
||||
|
||||
include(${pal_dir}/platform_specific_test_targets.cmake)
|
||||
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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/XcbApplication.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#include <AzFramework/XcbInterface.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class XcbConnectionManagerImpl
|
||||
: public XcbConnectionManagerBus::Handler
|
||||
{
|
||||
public:
|
||||
XcbConnectionManagerImpl()
|
||||
: m_xcbConnection(xcb_connect(nullptr, nullptr))
|
||||
{
|
||||
AZ_Error("Application", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
XcbConnectionManagerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~XcbConnectionManagerImpl() override
|
||||
{
|
||||
XcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
xcb_connection_t* GetXcbConnection() const override
|
||||
{
|
||||
return m_xcbConnection.get();
|
||||
}
|
||||
|
||||
private:
|
||||
XcbUniquePtr<xcb_connection_t, xcb_disconnect> m_xcbConnection = nullptr;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
XcbApplication::XcbApplication()
|
||||
{
|
||||
LinuxLifecycleEvents::Bus::Handler::BusConnect();
|
||||
m_xcbConnectionManager = AZStd::make_unique<XcbConnectionManagerImpl>();
|
||||
if (XcbConnectionManagerInterface::Get() == nullptr)
|
||||
{
|
||||
XcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
XcbApplication::~XcbApplication()
|
||||
{
|
||||
if (XcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
{
|
||||
XcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
}
|
||||
m_xcbConnectionManager.reset();
|
||||
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void XcbApplication::PumpSystemEventLoopOnce()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
if (auto event = XcbStdFreePtr<xcb_generic_event_t>{xcb_poll_for_event(xcbConnection)})
|
||||
{
|
||||
XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void XcbApplication::PumpSystemEventLoopUntilEmpty()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
while (auto event = XcbStdFreePtr<xcb_generic_event_t>{xcb_poll_for_event(xcbConnection)})
|
||||
{
|
||||
XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AzFramework
|
||||
+7
-13
@@ -5,27 +5,24 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ApplicationLinux_xcb
|
||||
class XcbApplication
|
||||
: public Application::Implementation
|
||||
, public LinuxLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0);
|
||||
ApplicationLinux_xcb();
|
||||
~ApplicationLinux_xcb() override;
|
||||
AZ_CLASS_ALLOCATOR(XcbApplication, AZ::SystemAllocator, 0);
|
||||
XcbApplication();
|
||||
~XcbApplication() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Application::Implementation
|
||||
@@ -33,9 +30,6 @@ namespace AzFramework
|
||||
void PumpSystemEventLoopUntilEmpty() override;
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
|
||||
AZStd::unique_ptr<XcbConnectionManager> m_xcbConnectionManager;
|
||||
};
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbConnectionManager
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(XcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~XcbConnectionManager() = default;
|
||||
|
||||
virtual xcb_connection_t* GetXcbConnection() const = 0;
|
||||
};
|
||||
|
||||
class XcbConnectionManagerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using XcbConnectionManagerBus = AZ::EBus<XcbConnectionManager, XcbConnectionManagerBusTraits>;
|
||||
using XcbConnectionManagerInterface = AZ::Interface<XcbConnectionManager>;
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbEventHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(XcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~XcbEventHandler() = default;
|
||||
|
||||
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
|
||||
};
|
||||
|
||||
class XcbEventHandlerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using XcbEventHandlerBus = AZ::EBus<XcbEventHandler, XcbEventHandlerBusTraits>;
|
||||
} // namespace AzFramework
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
#include <AzFramework/XcbInputDeviceKeyboard.h>
|
||||
|
||||
#define explicit ExplicitIsACXXKeyword
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
XcbInputDeviceKeyboard::XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice)
|
||||
: InputDeviceKeyboard::Implementation(inputDevice)
|
||||
{
|
||||
XcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
auto* interface = AzFramework::XcbConnectionManagerInterface::Get();
|
||||
if (!interface)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB interface not available");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* connection = interface->GetXcbConnection();
|
||||
if (!connection)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB connection not available");
|
||||
return;
|
||||
}
|
||||
|
||||
XcbStdFreePtr<xcb_xkb_use_extension_reply_t> xkbUseExtensionReply{
|
||||
xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr)
|
||||
};
|
||||
if (!xkbUseExtensionReply)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension");
|
||||
return;
|
||||
}
|
||||
if (!xkbUseExtensionReply->supported)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension");
|
||||
return;
|
||||
}
|
||||
|
||||
m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection);
|
||||
|
||||
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
||||
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId));
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
bool XcbInputDeviceKeyboard::IsConnected() const
|
||||
{
|
||||
auto* connection = AzFramework::XcbConnectionManagerInterface::Get()->GetXcbConnection();
|
||||
return connection && !xcb_connection_has_error(connection);
|
||||
}
|
||||
|
||||
bool XcbInputDeviceKeyboard::HasTextEntryStarted() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options)
|
||||
{
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TextEntryStop()
|
||||
{
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::TickInputDevice()
|
||||
{
|
||||
ProcessRawEventQueues();
|
||||
}
|
||||
|
||||
void XcbInputDeviceKeyboard::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->response_type & ~0x80)
|
||||
{
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
auto* keyPress = reinterpret_cast<xcb_key_press_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
auto* keyRelease = reinterpret_cast<xcb_key_release_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] const InputChannelId* XcbInputDeviceKeyboard::InputChannelFromKeyEvent(xcb_keycode_t code) const
|
||||
{
|
||||
const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code);
|
||||
|
||||
switch(keysym)
|
||||
{
|
||||
case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0;
|
||||
case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1;
|
||||
case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2;
|
||||
case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3;
|
||||
case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4;
|
||||
case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5;
|
||||
case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6;
|
||||
case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7;
|
||||
case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8;
|
||||
case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9;
|
||||
case XKB_KEY_A:
|
||||
case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA;
|
||||
case XKB_KEY_B:
|
||||
case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB;
|
||||
case XKB_KEY_C:
|
||||
case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC;
|
||||
case XKB_KEY_D:
|
||||
case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD;
|
||||
case XKB_KEY_E:
|
||||
case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE;
|
||||
case XKB_KEY_F:
|
||||
case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF;
|
||||
case XKB_KEY_G:
|
||||
case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG;
|
||||
case XKB_KEY_H:
|
||||
case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH;
|
||||
case XKB_KEY_I:
|
||||
case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI;
|
||||
case XKB_KEY_J:
|
||||
case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ;
|
||||
case XKB_KEY_K:
|
||||
case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK;
|
||||
case XKB_KEY_L:
|
||||
case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL;
|
||||
case XKB_KEY_M:
|
||||
case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM;
|
||||
case XKB_KEY_N:
|
||||
case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN;
|
||||
case XKB_KEY_O:
|
||||
case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO;
|
||||
case XKB_KEY_P:
|
||||
case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP;
|
||||
case XKB_KEY_Q:
|
||||
case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ;
|
||||
case XKB_KEY_R:
|
||||
case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR;
|
||||
case XKB_KEY_S:
|
||||
case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS;
|
||||
case XKB_KEY_T:
|
||||
case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT;
|
||||
case XKB_KEY_U:
|
||||
case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU;
|
||||
case XKB_KEY_V:
|
||||
case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV;
|
||||
case XKB_KEY_W:
|
||||
case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW;
|
||||
case XKB_KEY_X:
|
||||
case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX;
|
||||
case XKB_KEY_Y:
|
||||
case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY;
|
||||
case XKB_KEY_Z:
|
||||
case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ;
|
||||
case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace;
|
||||
case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock;
|
||||
case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter;
|
||||
case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace;
|
||||
case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab;
|
||||
case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape;
|
||||
case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01;
|
||||
case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02;
|
||||
case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03;
|
||||
case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04;
|
||||
case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05;
|
||||
case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06;
|
||||
case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07;
|
||||
case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08;
|
||||
case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09;
|
||||
case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10;
|
||||
case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11;
|
||||
case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12;
|
||||
case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13;
|
||||
case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14;
|
||||
case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15;
|
||||
case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16;
|
||||
case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17;
|
||||
case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18;
|
||||
case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19;
|
||||
case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20;
|
||||
case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL;
|
||||
case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR;
|
||||
case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL;
|
||||
case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR;
|
||||
case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL;
|
||||
case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR;
|
||||
case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL;
|
||||
case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR;
|
||||
case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown;
|
||||
case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft;
|
||||
case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight;
|
||||
case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp;
|
||||
case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete;
|
||||
case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd;
|
||||
case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome;
|
||||
case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert;
|
||||
case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown;
|
||||
case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp;
|
||||
case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock;
|
||||
case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0;
|
||||
case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1;
|
||||
case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2;
|
||||
case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3;
|
||||
case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4;
|
||||
case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5;
|
||||
case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6;
|
||||
case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7;
|
||||
case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8;
|
||||
case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9;
|
||||
case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd;
|
||||
case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal;
|
||||
case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide;
|
||||
case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter;
|
||||
case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply;
|
||||
case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract;
|
||||
case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe;
|
||||
case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash;
|
||||
case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL;
|
||||
case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR;
|
||||
case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma;
|
||||
case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals;
|
||||
case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen;
|
||||
case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod;
|
||||
case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon;
|
||||
case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash;
|
||||
case XKB_KEY_grave:
|
||||
case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde;
|
||||
case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO;
|
||||
case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause;
|
||||
case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint;
|
||||
case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
#include <AzFramework/XcbInterface.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class XcbInputDeviceKeyboard
|
||||
: public InputDeviceKeyboard::Implementation
|
||||
, public XcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(XcbInputDeviceKeyboard, AZ::SystemAllocator, 0);
|
||||
|
||||
using InputDeviceKeyboard::Implementation::Implementation;
|
||||
XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice);
|
||||
|
||||
bool IsConnected() const override;
|
||||
|
||||
bool HasTextEntryStarted() const override;
|
||||
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override;
|
||||
void TextEntryStop() override;
|
||||
void TickInputDevice() override;
|
||||
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const;
|
||||
|
||||
XcbUniquePtr<xkb_context, xkb_context_unref> m_xkbContext;
|
||||
XcbUniquePtr<xkb_keymap, xkb_keymap_unref> m_xkbKeymap;
|
||||
XcbUniquePtr<xkb_state, xkb_state_unref> m_xkbState;
|
||||
int m_coreDeviceId{-1};
|
||||
bool m_initialized{false};
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
// @brief Wrap a function pointer in a type
|
||||
// This serves as a convenient way to wrap a function pointer in a given
|
||||
// type. That type can then be used in a `unique_ptr` or `shared_ptr`.
|
||||
// Using a type instead of a function pointer by value prevents the need to
|
||||
// copy the pointer when copying the smart poiner.
|
||||
template<auto Callable>
|
||||
struct XcbDeleterFreeFunctionWrapper
|
||||
{
|
||||
using value_type = decltype(Callable);
|
||||
static constexpr value_type s_value = Callable;
|
||||
constexpr operator value_type() const noexcept
|
||||
{
|
||||
return s_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, auto fn>
|
||||
using XcbUniquePtr = AZStd::unique_ptr<T, XcbDeleterFreeFunctionWrapper<fn>>;
|
||||
|
||||
template<typename T>
|
||||
using XcbStdFreePtr = XcbUniquePtr<T, ::free>;
|
||||
} // namespace AzFramework
|
||||
+22
-29
@@ -6,41 +6,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <AzFramework/XcbNativeWindow.h>
|
||||
#include <AzFramework/XcbConnectionManager.h>
|
||||
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
[[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb";
|
||||
[[maybe_unused]] const char XcbErrorWindow[] = "XcbNativeWindow";
|
||||
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
|
||||
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
|
||||
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb()
|
||||
XcbNativeWindow::XcbNativeWindow()
|
||||
: NativeWindow::Implementation()
|
||||
{
|
||||
if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get();
|
||||
xcbConnectionManager != nullptr)
|
||||
{
|
||||
m_xcbConnection = xcbConnectionManager->GetXcbConnection();
|
||||
}
|
||||
AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
|
||||
AZ_Error(XcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb()
|
||||
{
|
||||
}
|
||||
XcbNativeWindow::~XcbNativeWindow() = default;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title,
|
||||
void XcbNativeWindow::InitWindow(const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks)
|
||||
{
|
||||
@@ -98,13 +94,13 @@ namespace AzFramework
|
||||
|
||||
xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString);
|
||||
xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
|
||||
AZ_Error(XcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
|
||||
m_xcbAtomProtocols = replyProtocol->atom;
|
||||
|
||||
const static char* wmDeleteWindowString = "WM_DELETE_WINDOW";
|
||||
xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString);
|
||||
xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
|
||||
AZ_Error(XcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
|
||||
m_xcbAtomDeleteWindow = replyDeleteWindow->atom;
|
||||
|
||||
xcbCheckResult = xcb_change_property_checked(m_xcbConnection,
|
||||
@@ -123,9 +119,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Activate()
|
||||
void XcbNativeWindow::Activate()
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Handler::BusConnect();
|
||||
XcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
if (!m_activated) // nothing to do if window was already activated
|
||||
{
|
||||
@@ -137,7 +133,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Deactivate()
|
||||
void XcbNativeWindow::Deactivate()
|
||||
{
|
||||
if (m_activated) // nothing to do if window was already deactivated
|
||||
{
|
||||
@@ -148,17 +144,17 @@ namespace AzFramework
|
||||
xcb_unmap_window(m_xcbConnection, m_xcbWindow);
|
||||
xcb_flush(m_xcbConnection);
|
||||
}
|
||||
LinuxXcbEventHandlerBus::Handler::BusDisconnect();
|
||||
XcbEventHandlerBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const
|
||||
NativeWindowHandle XcbNativeWindow::GetWindowHandle() const
|
||||
{
|
||||
return reinterpret_cast<NativeWindowHandle>(m_xcbWindow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title)
|
||||
void XcbNativeWindow::SetWindowTitle(const AZStd::string& title)
|
||||
{
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
xcbCheckResult = xcb_change_property(m_xcbConnection,
|
||||
@@ -173,7 +169,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize)
|
||||
void XcbNativeWindow::ResizeClientArea(WindowSize clientAreaSize)
|
||||
{
|
||||
const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height };
|
||||
|
||||
@@ -184,7 +180,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const
|
||||
uint32_t XcbNativeWindow::GetDisplayRefreshRate() const
|
||||
{
|
||||
// [GFX TODO][GHI - 2678]
|
||||
// Using 60 for now until proper support is added
|
||||
@@ -192,7 +188,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie)
|
||||
bool XcbNativeWindow::ValidateXcbResult(xcb_void_cookie_t cookie)
|
||||
{
|
||||
bool result = true;
|
||||
if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie))
|
||||
@@ -204,7 +200,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
void XcbNativeWindow::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
{
|
||||
switch (event->response_type & s_XcbResponseTypeMask)
|
||||
{
|
||||
@@ -233,7 +229,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height)
|
||||
void XcbNativeWindow::WindowSizeChanged(const uint32_t width, const uint32_t height)
|
||||
{
|
||||
if (m_width != width || m_height != height)
|
||||
{
|
||||
@@ -246,7 +242,4 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+9
-10
@@ -5,24 +5,25 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class NativeWindowImpl_Linux_xcb final
|
||||
class XcbNativeWindow final
|
||||
: public NativeWindow::Implementation
|
||||
, public LinuxXcbEventHandlerBus::Handler
|
||||
, public XcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0);
|
||||
NativeWindowImpl_Linux_xcb();
|
||||
~NativeWindowImpl_Linux_xcb() override;
|
||||
AZ_CLASS_ALLOCATOR(XcbNativeWindow, AZ::SystemAllocator, 0);
|
||||
XcbNativeWindow();
|
||||
~XcbNativeWindow() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NativeWindow::Implementation
|
||||
@@ -37,7 +38,7 @@ namespace AzFramework
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LinuxXcbEventHandlerBus::Handler
|
||||
// XcbEventHandlerBus::Handler
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override;
|
||||
|
||||
private:
|
||||
@@ -49,6 +50,4 @@ namespace AzFramework
|
||||
xcb_atom_t m_xcbAtomProtocols;
|
||||
xcb_atom_t m_xcbAtomDeleteWindow;
|
||||
};
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# 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(FILES
|
||||
AzFramework/XcbApplication.cpp
|
||||
AzFramework/XcbApplication.h
|
||||
AzFramework/XcbConnectionManager.h
|
||||
AzFramework/XcbInputDeviceKeyboard.cpp
|
||||
AzFramework/XcbInputDeviceKeyboard.h
|
||||
AzFramework/XcbInterface.h
|
||||
AzFramework/XcbNativeWindow.cpp
|
||||
AzFramework/XcbNativeWindow.h
|
||||
)
|
||||
@@ -12,10 +12,6 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <xcb/xcb.h>
|
||||
#endif // LY_COMPILE_DEFINITIONS
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class LinuxLifecycleEvents
|
||||
@@ -30,54 +26,4 @@ namespace AzFramework
|
||||
|
||||
using Bus = AZ::EBus<LinuxLifecycleEvents>;
|
||||
};
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class LinuxXcbConnectionManager
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LinuxXcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~LinuxXcbConnectionManager() = default;
|
||||
|
||||
virtual xcb_connection_t* GetXcbConnection() const = 0;
|
||||
};
|
||||
|
||||
class LinuxXcbConnectionManagerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using LinuxXcbConnectionManagerBus = AZ::EBus<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
|
||||
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
|
||||
|
||||
class LinuxXcbEventHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~LinuxXcbEventHandler() = default;
|
||||
|
||||
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
|
||||
};
|
||||
|
||||
class LinuxXcbEventHandlerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using LinuxXcbEventHandlerBus = AZ::EBus<LinuxXcbEventHandler, LinuxXcbEventHandlerBusTraits>;
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
} // namespace AzFramework
|
||||
|
||||
+4
-2
@@ -8,7 +8,9 @@
|
||||
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include "Application_Linux_xcb.h"
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbApplication.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
@@ -17,7 +19,7 @@ namespace AzFramework
|
||||
Application::Implementation* Application::Implementation::Create()
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew ApplicationLinux_xcb();
|
||||
return aznew XcbApplication();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include "Application_Linux_xcb.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class LinuxXcbConnectionManagerImpl
|
||||
: public LinuxXcbConnectionManagerBus::Handler
|
||||
{
|
||||
public:
|
||||
LinuxXcbConnectionManagerImpl()
|
||||
{
|
||||
m_xcbConnection = xcb_connect(nullptr, nullptr);
|
||||
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
LinuxXcbConnectionManagerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~LinuxXcbConnectionManagerImpl()
|
||||
{
|
||||
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
xcb_disconnect(m_xcbConnection);
|
||||
}
|
||||
|
||||
xcb_connection_t* GetXcbConnection() const override
|
||||
{
|
||||
return m_xcbConnection;
|
||||
}
|
||||
|
||||
private:
|
||||
xcb_connection_t* m_xcbConnection = nullptr;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::ApplicationLinux_xcb()
|
||||
{
|
||||
LinuxLifecycleEvents::Bus::Handler::BusConnect();
|
||||
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::~ApplicationLinux_xcb()
|
||||
{
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
}
|
||||
m_xcbConnectionManager.reset();
|
||||
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopOnce()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbInputDeviceKeyboard.h>
|
||||
#endif
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice)
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew XcbInputDeviceKeyboard(inputDevice);
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
#else
|
||||
#error "Linux Window Manager not recognized."
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
} // namespace AzFramework
|
||||
-293
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* 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 <AzCore/std/typetraits/integral_constant.h>
|
||||
#include <AzFramework/API/ApplicationAPI_Linux.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
|
||||
#define explicit ExplicitIsACXXKeyword
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class InputDeviceKeyboardXcb
|
||||
: public InputDeviceKeyboard::Implementation
|
||||
, public LinuxXcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(InputDeviceKeyboardXcb, AZ::SystemAllocator, 0);
|
||||
|
||||
using InputDeviceKeyboard::Implementation::Implementation;
|
||||
InputDeviceKeyboardXcb(InputDeviceKeyboard& inputDevice)
|
||||
: InputDeviceKeyboard::Implementation(inputDevice)
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
auto* interface = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
if (!interface)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB interface not available");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* connection = AzFramework::LinuxXcbConnectionManagerInterface::Get()->GetXcbConnection();
|
||||
if (!connection)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "XCB connection not available");
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<xcb_xkb_use_extension_reply_t, DeleterForFreeFn<::std::free>> xkbUseExtensionReply{
|
||||
xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr)
|
||||
};
|
||||
if (!xkbUseExtensionReply)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension");
|
||||
return;
|
||||
}
|
||||
if (!xkbUseExtensionReply->supported)
|
||||
{
|
||||
AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension");
|
||||
return;
|
||||
}
|
||||
|
||||
m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection);
|
||||
|
||||
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
||||
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId));
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
bool IsConnected() const override
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
bool HasTextEntryStarted() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override
|
||||
{
|
||||
}
|
||||
|
||||
void TextEntryStop() override
|
||||
{
|
||||
}
|
||||
|
||||
void TickInputDevice() override
|
||||
{
|
||||
ProcessRawEventQueues();
|
||||
}
|
||||
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override
|
||||
{
|
||||
if (!IsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->response_type & ~0x80)
|
||||
{
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
auto* keyPress = reinterpret_cast<xcb_key_press_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
auto* keyRelease = reinterpret_cast<xcb_key_release_event_t*>(event);
|
||||
|
||||
const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail);
|
||||
if (key)
|
||||
{
|
||||
QueueRawKeyEvent(*key, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const
|
||||
{
|
||||
const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code);
|
||||
|
||||
switch(keysym)
|
||||
{
|
||||
case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0;
|
||||
case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1;
|
||||
case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2;
|
||||
case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3;
|
||||
case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4;
|
||||
case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5;
|
||||
case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6;
|
||||
case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7;
|
||||
case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8;
|
||||
case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9;
|
||||
case XKB_KEY_A:
|
||||
case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA;
|
||||
case XKB_KEY_B:
|
||||
case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB;
|
||||
case XKB_KEY_C:
|
||||
case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC;
|
||||
case XKB_KEY_D:
|
||||
case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD;
|
||||
case XKB_KEY_E:
|
||||
case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE;
|
||||
case XKB_KEY_F:
|
||||
case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF;
|
||||
case XKB_KEY_G:
|
||||
case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG;
|
||||
case XKB_KEY_H:
|
||||
case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH;
|
||||
case XKB_KEY_I:
|
||||
case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI;
|
||||
case XKB_KEY_J:
|
||||
case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ;
|
||||
case XKB_KEY_K:
|
||||
case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK;
|
||||
case XKB_KEY_L:
|
||||
case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL;
|
||||
case XKB_KEY_M:
|
||||
case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM;
|
||||
case XKB_KEY_N:
|
||||
case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN;
|
||||
case XKB_KEY_O:
|
||||
case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO;
|
||||
case XKB_KEY_P:
|
||||
case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP;
|
||||
case XKB_KEY_Q:
|
||||
case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ;
|
||||
case XKB_KEY_R:
|
||||
case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR;
|
||||
case XKB_KEY_S:
|
||||
case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS;
|
||||
case XKB_KEY_T:
|
||||
case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT;
|
||||
case XKB_KEY_U:
|
||||
case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU;
|
||||
case XKB_KEY_V:
|
||||
case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV;
|
||||
case XKB_KEY_W:
|
||||
case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW;
|
||||
case XKB_KEY_X:
|
||||
case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX;
|
||||
case XKB_KEY_Y:
|
||||
case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY;
|
||||
case XKB_KEY_Z:
|
||||
case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ;
|
||||
case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace;
|
||||
case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock;
|
||||
case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter;
|
||||
case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace;
|
||||
case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab;
|
||||
case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape;
|
||||
case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01;
|
||||
case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02;
|
||||
case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03;
|
||||
case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04;
|
||||
case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05;
|
||||
case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06;
|
||||
case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07;
|
||||
case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08;
|
||||
case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09;
|
||||
case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10;
|
||||
case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11;
|
||||
case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12;
|
||||
case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13;
|
||||
case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14;
|
||||
case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15;
|
||||
case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16;
|
||||
case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17;
|
||||
case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18;
|
||||
case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19;
|
||||
case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20;
|
||||
case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL;
|
||||
case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR;
|
||||
case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL;
|
||||
case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR;
|
||||
case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL;
|
||||
case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR;
|
||||
case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL;
|
||||
case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR;
|
||||
case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown;
|
||||
case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft;
|
||||
case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight;
|
||||
case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp;
|
||||
case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete;
|
||||
case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd;
|
||||
case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome;
|
||||
case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert;
|
||||
case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown;
|
||||
case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp;
|
||||
case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock;
|
||||
case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0;
|
||||
case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1;
|
||||
case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2;
|
||||
case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3;
|
||||
case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4;
|
||||
case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5;
|
||||
case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6;
|
||||
case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7;
|
||||
case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8;
|
||||
case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9;
|
||||
case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd;
|
||||
case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal;
|
||||
case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide;
|
||||
case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter;
|
||||
case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply;
|
||||
case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract;
|
||||
case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe;
|
||||
case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash;
|
||||
case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL;
|
||||
case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR;
|
||||
case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma;
|
||||
case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals;
|
||||
case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen;
|
||||
case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod;
|
||||
case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon;
|
||||
case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash;
|
||||
case XKB_KEY_grave:
|
||||
case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde;
|
||||
case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO;
|
||||
case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause;
|
||||
case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint;
|
||||
case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<auto freeFn>
|
||||
using DeleterForFreeFn = AZStd::integral_constant<decltype(freeFn), freeFn>;
|
||||
|
||||
AZStd::unique_ptr<xkb_context, DeleterForFreeFn<xkb_context_unref>> m_xkbContext;
|
||||
AZStd::unique_ptr<xkb_keymap, DeleterForFreeFn<xkb_keymap_unref>> m_xkbKeymap;
|
||||
AZStd::unique_ptr<xkb_state, DeleterForFreeFn<xkb_state_unref>> m_xkbState;
|
||||
int m_coreDeviceId{-1};
|
||||
bool m_initialized{false};
|
||||
};
|
||||
|
||||
InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice)
|
||||
{
|
||||
return aznew InputDeviceKeyboardXcb(inputDevice);
|
||||
}
|
||||
} // namespace AzFramework
|
||||
+4
-3
@@ -6,14 +6,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbNativeWindow.h>
|
||||
#endif
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew NativeWindowImpl_Linux_xcb();
|
||||
return aznew XcbNativeWindow();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
@@ -22,5 +24,4 @@ namespace AzFramework
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
# Only 'xcb' and 'wayland' are recognized
|
||||
if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
|
||||
set(LY_INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
Platform/Common/Xcb
|
||||
)
|
||||
set(LY_FILES_CMAKE
|
||||
Platform/Common/Xcb/azframework_xcb_files.cmake
|
||||
)
|
||||
set(LY_BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::X11::xcb
|
||||
@@ -18,8 +26,6 @@ if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
|
||||
3rdParty::X11::xkbcommon_X11
|
||||
)
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
|
||||
|
||||
elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland")
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND)
|
||||
|
||||
@@ -12,8 +12,6 @@ set(FILES
|
||||
AzFramework/API/ApplicationAPI_Platform.h
|
||||
AzFramework/API/ApplicationAPI_Linux.h
|
||||
AzFramework/Application/Application_Linux.cpp
|
||||
AzFramework/Application/Application_Linux_xcb.h
|
||||
AzFramework/Application/Application_Linux_xcb.cpp
|
||||
AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
|
||||
AzFramework/Process/ProcessWatcher_Linux.cpp
|
||||
AzFramework/Process/ProcessCommon.h
|
||||
@@ -22,10 +20,8 @@ set(FILES
|
||||
../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
|
||||
../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.h
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
|
||||
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_xcb.cpp
|
||||
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Touch/InputDeviceTouch_Unimplemented.cpp
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace UnitTest
|
||||
{
|
||||
constexpr float deltaTime = 0.01666f; // 60fps
|
||||
const bool consumed = m_cameraSystem->HandleEvents(event);
|
||||
m_camera = m_cameraSystem->StepCamera(m_targetCamera, deltaTime);
|
||||
m_targetCamera = m_cameraSystem->StepCamera(m_targetCamera, deltaTime);
|
||||
m_camera = m_targetCamera; // no smoothing
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@@ -45,20 +46,38 @@ namespace UnitTest
|
||||
m_translateCameraInputChannelIds.m_boostChannelId = AzFramework::InputChannelId("keyboard_key_modifier_shift_l");
|
||||
|
||||
m_firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Right);
|
||||
m_firstPersonTranslateCamera =
|
||||
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation, m_translateCameraInputChannelIds);
|
||||
// set rotate speed to be a value that will scale motion delta (pixels moved) by a thousandth.
|
||||
m_firstPersonRotateCamera->m_rotateSpeedFn = []()
|
||||
{
|
||||
return 0.001f;
|
||||
};
|
||||
|
||||
m_orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(m_orbitChannelId);
|
||||
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
|
||||
auto orbitTranslateCamera =
|
||||
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation, m_translateCameraInputChannelIds);
|
||||
m_firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
m_translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot);
|
||||
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
m_pivotCamera = AZStd::make_shared<AzFramework::PivotCameraInput>(m_pivotChannelId);
|
||||
m_pivotCamera->SetPivotFn(
|
||||
[this](const AZ::Vector3&, const AZ::Vector3&)
|
||||
{
|
||||
return m_pivot;
|
||||
});
|
||||
|
||||
auto pivotRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
|
||||
// set rotate speed to be a value that will scale motion delta (pixels moved) by a thousandth.
|
||||
pivotRotateCamera->m_rotateSpeedFn = []()
|
||||
{
|
||||
return 0.001f;
|
||||
};
|
||||
|
||||
auto pivotTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
m_translateCameraInputChannelIds, AzFramework::PivotTranslation, AzFramework::TranslateOffset);
|
||||
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(pivotRotateCamera);
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(pivotTranslateCamera);
|
||||
|
||||
m_cameraSystem->m_cameras.AddCamera(m_firstPersonRotateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(m_firstPersonTranslateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(m_orbitCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(m_pivotCamera);
|
||||
|
||||
// these tests rely on using motion delta, not cursor positions (default is true)
|
||||
AzFramework::ed_cameraSystemUseCursor = false;
|
||||
@@ -68,7 +87,7 @@ namespace UnitTest
|
||||
{
|
||||
AzFramework::ed_cameraSystemUseCursor = true;
|
||||
|
||||
m_orbitCamera.reset();
|
||||
m_pivotCamera.reset();
|
||||
m_firstPersonRotateCamera.reset();
|
||||
m_firstPersonTranslateCamera.reset();
|
||||
|
||||
@@ -78,24 +97,29 @@ namespace UnitTest
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId m_orbitChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l");
|
||||
AzFramework::InputChannelId m_pivotChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l");
|
||||
AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds;
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_firstPersonRotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_firstPersonTranslateCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
|
||||
AZStd::shared_ptr<AzFramework::PivotCameraInput> m_pivotCamera;
|
||||
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;
|
||||
};
|
||||
|
||||
TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents)
|
||||
TEST_F(CameraInputFixture, BeginAndEndPivotCameraInputConsumesCorrectEvents)
|
||||
{
|
||||
// begin orbit camera
|
||||
// begin pivot camera
|
||||
const bool consumed1 = HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceKeyboard::Key::ModifierAltL,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
// begin listening for orbit rotate (click detector) - event is not consumed
|
||||
// begin listening for pivot rotate (click detector) - event is not consumed
|
||||
const bool consumed2 = HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began });
|
||||
// begin orbit rotate (mouse has moved sufficient distance to initiate)
|
||||
// begin pivot rotate (mouse has moved sufficient distance to initiate)
|
||||
const bool consumed3 = HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ 5 });
|
||||
// end orbit (mouse up) - event is not consumed
|
||||
// end pivot (mouse up) - event is not consumed
|
||||
const bool consumed4 = HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Ended });
|
||||
|
||||
@@ -236,29 +260,110 @@ namespace UnitTest
|
||||
EXPECT_TRUE(activationEnded);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, OrbitCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenOrbiting)
|
||||
TEST_F(CameraInputFixture, PivotCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenPivoting)
|
||||
{
|
||||
// create pathological lookAtFn that just returns the same position as the camera
|
||||
m_orbitCamera->SetLookAtFn(
|
||||
m_pivotCamera->SetPivotFn(
|
||||
[](const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
{
|
||||
return position;
|
||||
});
|
||||
|
||||
const auto expectedCameraPosition = AZ::Vector3(10.0f, 10.0f, 10.0f);
|
||||
AzFramework::UpdateCameraFromTransform(
|
||||
m_targetCamera,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 10.0f, 10.0f)));
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), expectedCameraPosition));
|
||||
|
||||
m_camera = m_targetCamera;
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
// verify the camera yaw has not changed and pivot point matches the expected camera position
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_yaw, FloatNear(AZ::DegToRad(90.0f), 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateZero()));
|
||||
EXPECT_THAT(m_camera.m_pivot, IsClose(expectedCameraPosition));
|
||||
}
|
||||
|
||||
// verify the camera yaw has not changed and the look at point
|
||||
// does not match that of the camera translation
|
||||
using ::testing::Eq;
|
||||
using ::testing::Not;
|
||||
EXPECT_THAT(m_camera.m_yaw, Eq(AZ::DegToRad(90.0f)));
|
||||
EXPECT_THAT(m_camera.m_lookAt, Not(IsClose(m_camera.Translation())));
|
||||
TEST_F(CameraInputFixture, FirstPersonRotateCameraInputRotatesYawByNinetyDegreesWithRequiredPixelDelta)
|
||||
{
|
||||
const auto cameraStartingPosition = AZ::Vector3::CreateAxisY(-10.0f);
|
||||
m_targetCamera.m_pivot = cameraStartingPosition;
|
||||
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ PixelMotionDelta });
|
||||
|
||||
const float expectedYaw = AzFramework::WrapYawRotation(-AZ::Constants::HalfPi);
|
||||
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_yaw, FloatNear(expectedYaw, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pivot, IsClose(cameraStartingPosition));
|
||||
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateZero()));
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, FirstPersonRotateCameraInputRotatesPitchByNinetyDegreesWithRequiredPixelDelta)
|
||||
{
|
||||
const auto cameraStartingPosition = AZ::Vector3::CreateAxisY(-10.0f);
|
||||
m_targetCamera.m_pivot = cameraStartingPosition;
|
||||
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Right, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta });
|
||||
|
||||
const float expectedPitch = AzFramework::ClampPitchRotation(-AZ::Constants::HalfPi);
|
||||
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_yaw, FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(expectedPitch, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pivot, IsClose(cameraStartingPosition));
|
||||
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateZero()));
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, PivotRotateCameraInputRotatesPitchOffsetByNinetyDegreesWithRequiredPixelDelta)
|
||||
{
|
||||
const auto cameraStartingPosition = AZ::Vector3::CreateAxisY(-20.0f);
|
||||
m_targetCamera.m_pivot = cameraStartingPosition;
|
||||
|
||||
m_pivot = AZ::Vector3::CreateAxisY(-10.0f);
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta });
|
||||
|
||||
const auto expectedCameraEndingPosition = AZ::Vector3(0.0f, -10.0f, 10.0f);
|
||||
const float expectedPitch = AzFramework::ClampPitchRotation(-AZ::Constants::HalfPi);
|
||||
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_yaw, FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(expectedPitch, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pivot, IsClose(m_pivot));
|
||||
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateAxisY(-10.0f)));
|
||||
EXPECT_THAT(m_camera.Translation(), IsCloseTolerance(expectedCameraEndingPosition, 0.01f));
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, PivotRotateCameraInputRotatesYawOffsetByNinetyDegreesWithRequiredPixelDelta)
|
||||
{
|
||||
const auto cameraStartingPosition = AZ::Vector3(15.0f, -20.0f, 0.0f);
|
||||
m_targetCamera.m_pivot = cameraStartingPosition;
|
||||
|
||||
m_pivot = AZ::Vector3(10.0f, -10.0f, 0.0f);
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ -PixelMotionDelta });
|
||||
|
||||
const auto expectedCameraEndingPosition = AZ::Vector3(20.0f, -5.0f, 0.0f);
|
||||
const float expectedYaw = AzFramework::WrapYawRotation(AZ::Constants::HalfPi);
|
||||
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_yaw, FloatNear(expectedYaw, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(m_camera.m_pivot, IsClose(m_pivot));
|
||||
EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3(5.0f, -10.0f, 0.0f)));
|
||||
EXPECT_THAT(m_camera.Translation(), IsCloseTolerance(expectedCameraEndingPosition, 0.01f));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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 <AzTest/AzTest.h>
|
||||
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
|
||||
@@ -40,6 +40,11 @@ namespace AzFramework
|
||||
|
||||
MOCK_METHOD2(DespawnAllEntities, void(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs));
|
||||
|
||||
MOCK_METHOD3(DespawnEntity, void(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs));
|
||||
|
||||
MOCK_METHOD2(
|
||||
RetrieveEntitySpawnTicket, void(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback));
|
||||
|
||||
MOCK_METHOD3(
|
||||
ReloadSpawnable,
|
||||
void(EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs));
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
ACTION_TEMPLATE(ReturnMalloc,
|
||||
HAS_1_TEMPLATE_PARAMS(typename, T),
|
||||
AND_1_VALUE_PARAMS(p0)) {
|
||||
T* value = static_cast<T*>(malloc(sizeof(T)));
|
||||
*value = T{ p0 };
|
||||
return value;
|
||||
}
|
||||
ACTION_TEMPLATE(ReturnMalloc,
|
||||
HAS_1_TEMPLATE_PARAMS(typename, T),
|
||||
AND_2_VALUE_PARAMS(p0, p1)) {
|
||||
T* value = static_cast<T*>(malloc(sizeof(T)));
|
||||
*value = T{ p0, p1 };
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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 <AzTest/AzTest.h>
|
||||
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 "MockXcbInterface.h"
|
||||
|
||||
// The functions defined in this file will take precedence over those defined
|
||||
// in the real libxcb.so, allowing the test code to use a mock implementation
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// xcb
|
||||
xcb_connection_t* xcb_connect(const char* displayname, int* screenp)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xcb_connect(displayname, screenp);
|
||||
}
|
||||
void xcb_disconnect(xcb_connection_t* c)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xcb_disconnect(c);
|
||||
}
|
||||
xcb_generic_event_t* xcb_poll_for_event(xcb_connection_t* c)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xcb_poll_for_event(c);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// xcb-xkb
|
||||
xcb_xkb_use_extension_cookie_t xcb_xkb_use_extension(xcb_connection_t* c, uint16_t wantedMajor, uint16_t wantedMinor)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xcb_xkb_use_extension(c, wantedMajor, wantedMinor);
|
||||
}
|
||||
xcb_xkb_use_extension_reply_t* xcb_xkb_use_extension_reply(xcb_connection_t* c, xcb_xkb_use_extension_cookie_t cookie, xcb_generic_error_t** e)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xcb_xkb_use_extension_reply(c, cookie, e);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// xkb-x11
|
||||
int32_t xkb_x11_get_core_keyboard_device_id(xcb_connection_t* connection)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_x11_get_core_keyboard_device_id(connection);
|
||||
}
|
||||
struct xkb_keymap* xkb_x11_keymap_new_from_device(struct xkb_context* context, xcb_connection_t* connection, int32_t device_id, enum xkb_keymap_compile_flags flags)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_x11_keymap_new_from_device(context, connection, device_id, flags);
|
||||
}
|
||||
xkb_state* xkb_x11_state_new_from_device(xkb_keymap* keymap, xcb_connection_t* connection, int32_t device_id)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_x11_state_new_from_device(keymap, connection, device_id);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// xkbcommon
|
||||
xkb_context* xkb_context_new(enum xkb_context_flags flags)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_context_new(flags);
|
||||
}
|
||||
void xkb_context_unref(xkb_context *context)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_context_unref(context);
|
||||
}
|
||||
void xkb_keymap_unref(xkb_keymap *keymap)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_keymap_unref(keymap);
|
||||
}
|
||||
void xkb_state_unref(xkb_state *state)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_state_unref(state);
|
||||
}
|
||||
xkb_keysym_t xkb_state_key_get_one_sym(xkb_state *state, xkb_keycode_t key)
|
||||
{
|
||||
return MockXcbInterface::Instance()->xkb_state_key_get_one_sym(state, key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#define explicit ExplicitIsACXXKeyword
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include "Printers.h"
|
||||
|
||||
// xcb / xkb do not provide definitions of these structs, but the tests need some concrete value for them.
|
||||
struct xcb_connection_t
|
||||
{
|
||||
};
|
||||
|
||||
struct xkb_context
|
||||
{
|
||||
};
|
||||
|
||||
struct xkb_keymap
|
||||
{
|
||||
};
|
||||
|
||||
struct xkb_state
|
||||
{
|
||||
};
|
||||
|
||||
class MockXcbInterface
|
||||
{
|
||||
public:
|
||||
MockXcbInterface()
|
||||
{
|
||||
self = this;
|
||||
}
|
||||
MockXcbInterface(const MockXcbInterface&) = delete;
|
||||
MockXcbInterface(MockXcbInterface&&) = delete;
|
||||
MockXcbInterface& operator=(const MockXcbInterface&) = delete;
|
||||
MockXcbInterface& operator=(MockXcbInterface&&) = delete;
|
||||
~MockXcbInterface()
|
||||
{
|
||||
self = nullptr;
|
||||
}
|
||||
|
||||
static MockXcbInterface* Instance() { return self; }
|
||||
|
||||
// xcb
|
||||
MOCK_CONST_METHOD2(xcb_connect, xcb_connection_t*(const char* displayname, int* screenp));
|
||||
MOCK_CONST_METHOD1(xcb_disconnect, void(xcb_connection_t* c));
|
||||
MOCK_CONST_METHOD1(xcb_poll_for_event, xcb_generic_event_t*(xcb_connection_t* c));
|
||||
|
||||
// xcb-xkb
|
||||
MOCK_CONST_METHOD3(xcb_xkb_use_extension, xcb_xkb_use_extension_cookie_t(xcb_connection_t* c, uint16_t wantedMajor, uint16_t wantedMinor));
|
||||
MOCK_CONST_METHOD3(xcb_xkb_use_extension_reply, xcb_xkb_use_extension_reply_t*(xcb_connection_t* c, xcb_xkb_use_extension_cookie_t cookie, xcb_generic_error_t** e));
|
||||
|
||||
// xkb-x11
|
||||
MOCK_CONST_METHOD1(xkb_x11_get_core_keyboard_device_id, int32_t(xcb_connection_t* connection));
|
||||
MOCK_CONST_METHOD4(xkb_x11_keymap_new_from_device, xkb_keymap*(xkb_context* context, xcb_connection_t* connection, int32_t device_id, xkb_keymap_compile_flags flags));
|
||||
MOCK_CONST_METHOD3(xkb_x11_state_new_from_device, xkb_state*(xkb_keymap* keymap, xcb_connection_t* connection, int32_t device_id));
|
||||
|
||||
// xkbcommon
|
||||
MOCK_CONST_METHOD1(xkb_context_new, xkb_context*(xkb_context_flags flags));
|
||||
MOCK_CONST_METHOD1(xkb_context_unref, void(xkb_context* context));
|
||||
MOCK_CONST_METHOD1(xkb_keymap_unref, void(xkb_keymap* keymap));
|
||||
MOCK_CONST_METHOD1(xkb_state_unref, void(xkb_state* state));
|
||||
MOCK_CONST_METHOD2(xkb_state_key_get_one_sym, xkb_keysym_t(xkb_state *state, xkb_keycode_t key));
|
||||
|
||||
private:
|
||||
static inline MockXcbInterface* self = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 <ostream>
|
||||
#include <AzFramework/Input/Channels/InputChannel.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void PrintTo(const InputChannel::State& state, std::ostream* os)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case InputChannel::State::Began:
|
||||
*os << "Began";
|
||||
break;
|
||||
case InputChannel::State::Ended:
|
||||
*os << "Ended";
|
||||
break;
|
||||
case InputChannel::State::Idle:
|
||||
*os << "Idle";
|
||||
break;
|
||||
case InputChannel::State::Updated:
|
||||
*os << "Updated";
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <AzFramework/Input/Channels/InputChannel.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void PrintTo(const InputChannel::State& state, std::ostream* os);
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include <AzFramework/XcbApplication.h>
|
||||
#include <AzFramework/XcbInputDeviceKeyboard.h>
|
||||
#include "MockXcbInterface.h"
|
||||
#include "Actions.h"
|
||||
|
||||
template<typename T>
|
||||
xcb_generic_event_t MakeEvent(T event)
|
||||
{
|
||||
return *reinterpret_cast<xcb_generic_event_t*>(&event);
|
||||
}
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
TEST(XcbInputDeviceKeyboard, InputChannelsUpdateStateFromXcbEvents)
|
||||
{
|
||||
using testing::Return;
|
||||
using testing::Eq;
|
||||
using testing::_;
|
||||
MockXcbInterface interface;
|
||||
|
||||
xcb_connection_t connection{};
|
||||
xkb_context xkbContext{};
|
||||
xkb_keymap xkbKeymap{};
|
||||
xkb_state xkbState{};
|
||||
const int32_t coreDeviceId{1};
|
||||
|
||||
constexpr xcb_keycode_t keycodeForAKey = 38;
|
||||
|
||||
const AZStd::array events
|
||||
{
|
||||
MakeEvent(xcb_key_press_event_t{
|
||||
/*.response_type = */ XCB_KEY_PRESS,
|
||||
/*.detail = */ keycodeForAKey,
|
||||
/*.sequence = */ 0,
|
||||
/*.time = */ 0,
|
||||
/*.root = */ 0,
|
||||
/*.event = */ 0,
|
||||
/*.child = */ 0,
|
||||
/*.root_x = */ 0,
|
||||
/*.root_y = */ 0,
|
||||
/*.event_x = */ 0,
|
||||
/*.event_y = */ 0,
|
||||
/*.state = */ 0,
|
||||
/*.same_screen = */ 0,
|
||||
/*.pad0 = */ 0
|
||||
}),
|
||||
MakeEvent(xcb_key_release_event_t{
|
||||
/*.response_type = */ XCB_KEY_RELEASE,
|
||||
/*.detail = */ keycodeForAKey,
|
||||
/*.sequence = */ 0,
|
||||
/*.time = */ 0,
|
||||
/*.root = */ 0,
|
||||
/*.event = */ 0,
|
||||
/*.child = */ 0,
|
||||
/*.root_x = */ 0,
|
||||
/*.root_y = */ 0,
|
||||
/*.event_x = */ 0,
|
||||
/*.event_y = */ 0,
|
||||
/*.state = */ 0,
|
||||
/*.same_screen = */ 0,
|
||||
/*.pad0 = */ 0
|
||||
}),
|
||||
};
|
||||
|
||||
EXPECT_CALL(interface, xcb_connect(_, _))
|
||||
.WillOnce(Return(&connection));
|
||||
EXPECT_CALL(interface, xcb_disconnect(&connection))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(interface, xkb_context_new(XKB_CONTEXT_NO_FLAGS))
|
||||
.WillOnce(Return(&xkbContext));
|
||||
EXPECT_CALL(interface, xkb_context_unref(&xkbContext))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(interface, xkb_x11_keymap_new_from_device(&xkbContext, &connection, coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS))
|
||||
.WillOnce(Return(&xkbKeymap));
|
||||
EXPECT_CALL(interface, xkb_keymap_unref(&xkbKeymap))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(interface, xkb_x11_state_new_from_device(&xkbKeymap, &connection, coreDeviceId))
|
||||
.WillOnce(Return(&xkbState));
|
||||
EXPECT_CALL(interface, xkb_state_unref(&xkbState))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(interface, xcb_xkb_use_extension(&connection, 1, 0));
|
||||
EXPECT_CALL(interface, xcb_xkb_use_extension_reply(&connection, _, _))
|
||||
.WillOnce(ReturnMalloc<xcb_xkb_use_extension_reply_t>(
|
||||
/* .response_type =*/static_cast<uint8_t>(XCB_XKB_USE_EXTENSION),
|
||||
/* .supported =*/ static_cast<uint8_t>(1))
|
||||
);
|
||||
EXPECT_CALL(interface, xkb_x11_get_core_keyboard_device_id(&connection))
|
||||
.WillRepeatedly(Return(coreDeviceId));
|
||||
|
||||
// Set the expectations for the events that will be generated
|
||||
// nullptr entries represent when the event queue is empty, and will cause
|
||||
// PumpSystemEventLoopUntilEmpty to return
|
||||
// event pointers are freed by the calling code, so we malloc new copies
|
||||
// here
|
||||
EXPECT_CALL(interface, xcb_poll_for_event(&connection))
|
||||
.WillOnce(ReturnMalloc<xcb_generic_event_t>(events[0]))
|
||||
.WillOnce(Return(nullptr))
|
||||
.WillOnce(ReturnMalloc<xcb_generic_event_t>(events[1]))
|
||||
.WillOnce(Return(nullptr))
|
||||
;
|
||||
|
||||
EXPECT_CALL(interface, xkb_state_key_get_one_sym(&xkbState, keycodeForAKey))
|
||||
.WillOnce(Return(XKB_KEY_a))
|
||||
.WillOnce(Return(XKB_KEY_a))
|
||||
;
|
||||
|
||||
Application application;
|
||||
application.Start({}, {});
|
||||
|
||||
const InputChannel* inputChannel = InputChannelRequests::FindInputChannel(InputDeviceKeyboard::Key::AlphanumericA);
|
||||
ASSERT_TRUE(inputChannel);
|
||||
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Idle));
|
||||
|
||||
application.PumpSystemEventLoopUntilEmpty();
|
||||
application.TickSystem();
|
||||
application.Tick();
|
||||
|
||||
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Began));
|
||||
|
||||
application.PumpSystemEventLoopUntilEmpty();
|
||||
application.TickSystem();
|
||||
application.Tick();
|
||||
|
||||
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Ended));
|
||||
|
||||
application.Stop();
|
||||
}
|
||||
} // namespace AzFramework
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# 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(FILES
|
||||
Actions.h
|
||||
Main.cpp
|
||||
MockXcbInterface.cpp
|
||||
MockXcbInterface.h
|
||||
Printers.cpp
|
||||
Printers.h
|
||||
XcbInputDeviceKeyboardTests.cpp
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
|
||||
# This library defines local implementations of all the used xcb functions,
|
||||
# in order to allow tests to run in the absence of a running X server.
|
||||
# These have to be in a separate library, so that the normal AzFramework
|
||||
# tests do not need to set up a mock Xcb interface.
|
||||
ly_add_target(
|
||||
NAME AzFramework.Xcb.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE AZ
|
||||
FILES_CMAKE
|
||||
Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Tests
|
||||
${pal_dir}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzFramework
|
||||
AZ::AzTest
|
||||
AZ::AzTestShared
|
||||
AZ::AzFrameworkTestShared
|
||||
)
|
||||
ly_add_googletest(
|
||||
NAME AZ::AzFramework.Xcb.Tests
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user