Merging latest development
Signed-off-by: kberg-amzn <karlberg@amazon.com>
This commit is contained in:
@@ -77,11 +77,15 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
namespace ApplicationInternal
|
||||
{
|
||||
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
|
||||
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
|
||||
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
|
||||
static constexpr const char* DeprecatedFileIOAliasesRoot = "/O3DE/AzCore/FileIO/DeprecatedAliases";
|
||||
static constexpr const char* DeprecatedFileIOAliasesOldAliasKey = "OldAlias";
|
||||
static constexpr const char* DeprecatedFileIOAliasesNewAliasKey = "NewAlias";
|
||||
}
|
||||
|
||||
Application::Application()
|
||||
@@ -563,6 +567,68 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
struct DeprecatedAliasesKeyVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view,
|
||||
VisitAction action, Type type) override
|
||||
{
|
||||
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = path;
|
||||
}
|
||||
|
||||
// Strip off last path segment from json path and check if is a child element of the array
|
||||
if (AZ::StringFunc::TokenizeLast(path, '/');
|
||||
m_parentArrayPath == path)
|
||||
{
|
||||
m_aliases.emplace_back();
|
||||
}
|
||||
}
|
||||
else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = AZStd::string{};
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
void Visit(AZStd::string_view, AZStd::string_view valueName, Type, AZStd::string_view value) override
|
||||
{
|
||||
if (!m_aliases.empty())
|
||||
{
|
||||
if (valueName == ApplicationInternal::DeprecatedFileIOAliasesOldAliasKey)
|
||||
{
|
||||
m_aliases.back().m_oldAlias = value;
|
||||
}
|
||||
else if (valueName == ApplicationInternal::DeprecatedFileIOAliasesNewAliasKey)
|
||||
{
|
||||
m_aliases.back().m_newAlias = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AliasPair
|
||||
{
|
||||
AZStd::string m_oldAlias;
|
||||
AZStd::string m_newAlias;
|
||||
};
|
||||
AZStd::vector<AliasPair> m_aliases;
|
||||
|
||||
private:
|
||||
AZStd::string m_parentArrayPath;
|
||||
};
|
||||
|
||||
static void CreateUserCache(const AZ::IO::FixedMaxPath& cacheUserPath, AZ::IO::FileIOBase& fileIoBase)
|
||||
{
|
||||
@@ -610,9 +676,8 @@ namespace AzFramework
|
||||
|
||||
void Application::SetFileIOAliases()
|
||||
{
|
||||
if (m_archiveFileIO)
|
||||
if (auto fileIoBase = m_archiveFileIO.get(); fileIoBase)
|
||||
{
|
||||
auto fileIoBase = m_archiveFileIO.get();
|
||||
// Set up the default file aliases based on the settings registry
|
||||
fileIoBase->SetAlias("@engroot@", GetEngineRoot());
|
||||
fileIoBase->SetAlias("@projectroot@", GetEngineRoot());
|
||||
@@ -620,29 +685,20 @@ namespace AzFramework
|
||||
|
||||
{
|
||||
AZ::IO::FixedMaxPath pathAliases;
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@projectcache@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@root@", pathAliases.c_str()); // Deprecated Use @projectplatformcache@
|
||||
fileIoBase->SetAlias("@products@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@engroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@devroot@", pathAliases.c_str()); // Deprecated - Use @engroot@
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
||||
{
|
||||
fileIoBase->SetAlias("@devassets@", pathAliases.c_str()); // Deprecated - Use @projectsourceassets@
|
||||
fileIoBase->SetAlias("@projectroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectsourceassets@", (pathAliases / "Assets").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +719,15 @@ namespace AzFramework
|
||||
}
|
||||
fileIoBase->SetAlias("@log@", projectLogPath.c_str());
|
||||
fileIoBase->CreatePath(projectLogPath.c_str());
|
||||
|
||||
DeprecatedAliasesKeyVisitor visitor;
|
||||
if (m_settingsRegistry->Visit(visitor, ApplicationInternal::DeprecatedFileIOAliasesRoot))
|
||||
{
|
||||
for (const auto& [oldAlias, newAlias] : visitor.m_aliases)
|
||||
{
|
||||
fileIoBase->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ namespace AZ::IO
|
||||
|
||||
if (AZ::IO::FixedMaxPath pathBindRoot; !AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, szBindRoot))
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@assets@");
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@products@");
|
||||
desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String();
|
||||
}
|
||||
else
|
||||
@@ -1807,9 +1807,9 @@ namespace AZ::IO
|
||||
if (m_eRecordFileOpenList != IArchive::RFOM_Disabled)
|
||||
{
|
||||
// we only want to record ASSET access
|
||||
// assets are identified as files that are relative to the resolved @assets@ alias path
|
||||
// assets are identified as files that are relative to the resolved @products@ alias path
|
||||
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
|
||||
const char* aliasValue = fileIoBase->GetAlias("@assets@");
|
||||
const char* aliasValue = fileIoBase->GetAlias("@products@");
|
||||
|
||||
if (AZ::IO::FixedMaxPath resolvedFilePath;
|
||||
fileIoBase->ResolvePath(resolvedFilePath, szFilename)
|
||||
|
||||
@@ -546,6 +546,16 @@ namespace AZ::IO
|
||||
realUnderlyingFileIO->GetAlias(alias);
|
||||
}
|
||||
|
||||
void ArchiveFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
FileIOBase* realUnderlyingFileIO = FileIOBase::GetDirectInstance();
|
||||
if (!realUnderlyingFileIO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
realUnderlyingFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> ArchiveFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
if ((!inOutBuffer) || (bufferLength == 0))
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ::IO
|
||||
IO::Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace AZ::IO
|
||||
{
|
||||
// filter out the stuff which does not match.
|
||||
|
||||
// the problem here is that szDir might be something like "@assets@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@assets@" or "@assets@/levels/mylevel"
|
||||
// the problem here is that szDir might be something like "@products@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@products@" or "@products@/levels/mylevel"
|
||||
// so there's really no way to filter out opening the pack and looking at the files inside.
|
||||
// however, the bind root is not part of the inner zip entry name either
|
||||
// and the ZipDir::FindFile actually expects just the chopped off piece.
|
||||
@@ -202,22 +202,22 @@ namespace AZ::IO
|
||||
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\" <--- mount point
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\" <--- mount point
|
||||
// ~~~~~~~~~~~ Common part
|
||||
// "levels\\*" <---- remainder that is not in common
|
||||
// "" <--- mount point remainder. In this case, we should scan the contents of the pak for the remainder
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// ~~~~~~~~~~~~~~~~~~ common part
|
||||
// "*" <---- remainder that is not in common
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
// example:
|
||||
// "@assets@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "otherlevel\\*" <---- remainder
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace AZ::IO
|
||||
// which means we may search inside the pack.
|
||||
ScanInZip(it->pZip.get(), sourcePathRemainder.Native());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace AZ::IO::Internal
|
||||
}
|
||||
|
||||
AZStd::smatch matches;
|
||||
const AZStd::regex lodRegex("@assets@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
const AZStd::regex lodRegex("@products@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
if (!AZStd::regex_match(szPath, matches, lodRegex) || matches.size() != 3)
|
||||
{
|
||||
// The current file is not a valid LOD file
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace AzFramework
|
||||
|
||||
if (!info.m_relativePath.empty())
|
||||
{
|
||||
const char* devAssetRoot = fileIO->GetAlias("@devassets@");
|
||||
const char* devAssetRoot = fileIO->GetAlias("@projectroot@");
|
||||
if (devAssetRoot)
|
||||
{
|
||||
AZ::Data::AssetStreamInfo streamInfo;
|
||||
|
||||
@@ -133,6 +133,8 @@ namespace AzFramework
|
||||
behaviorContext->Class<BehaviorEntity>("Entity")
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &Internal::BehaviorEntityScriptConstructor)
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "entity")
|
||||
->Constructor()
|
||||
->Constructor<AZ::EntityId>()
|
||||
->Constructor<AZ::Entity*>()
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzFramework
|
||||
|
||||
AZ::IO::Path& gemAbsPath = gemInfo.m_absoluteSourcePaths.emplace_back(value);
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace AzFramework
|
||||
AZStd::vector<AZ::IO::Path> m_absoluteSourcePaths; //!< Where the gem's source path folder are located(as an absolute path)
|
||||
|
||||
static constexpr const char* GetGemAssetFolder() { return "Assets"; }
|
||||
static constexpr const char* GetGemRegistryFolder()
|
||||
{
|
||||
return "Registry";
|
||||
}
|
||||
};
|
||||
|
||||
//! Returns a list of GemInfo of all the gems that are active for the for the specified game project.
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/std/containers/fixed_unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <cctype>
|
||||
|
||||
namespace AZ
|
||||
@@ -292,7 +294,7 @@ namespace AZ
|
||||
void LocalFileIO::CheckInvalidWrite([[maybe_unused]] const char* path)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* assetAliasPath = GetAlias("@products@");
|
||||
if (path && assetAliasPath)
|
||||
{
|
||||
const AZ::IO::PathView pathView(path);
|
||||
@@ -478,17 +480,15 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsAbsolutePath(path))
|
||||
if (AZ::IO::PathView(path).HasRootPath())
|
||||
{
|
||||
size_t pathLen = strlen(path);
|
||||
if (pathLen + 1 < resolvedPathSize)
|
||||
{
|
||||
azstrncpy(resolvedPath, resolvedPathSize, path, pathLen + 1);
|
||||
|
||||
//see if the absolute path uses @assets@ or @root@, if it does lowercase the relative part
|
||||
[[maybe_unused]] bool lowercasePath = LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@assets@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@root@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@projectplatformcache@"));
|
||||
//see if the absolute path matches the resolved value of @products@, if it does lowercase the relative part
|
||||
LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@products@"));
|
||||
|
||||
ToUnixSlashes(resolvedPath, resolvedPathSize);
|
||||
return true;
|
||||
@@ -499,34 +499,39 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
char rootedPathBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
constexpr AZStd::string_view productAssetAlias = "@products@";
|
||||
// Add plus one for the path separator: <alias>/<path>
|
||||
constexpr size_t MaxPathSizeWithProductAssetAlias = AZ::IO::MaxPathLength + productAssetAlias.size() + 1;
|
||||
using RootedPathString = AZStd::fixed_string<MaxPathSizeWithProductAssetAlias>;
|
||||
RootedPathString rootedPathBuffer;
|
||||
const char* rootedPath = path;
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @assets@
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @products@
|
||||
if (path[0] != '@')
|
||||
{
|
||||
if (GetAlias("@assets@"))
|
||||
if (GetAlias("@products@"))
|
||||
{
|
||||
const int rootLength = 9;// strlen("@assets@/")
|
||||
azstrncpy(rootedPathBuffer, AZ_MAX_PATH_LEN, "@assets@/", rootLength);
|
||||
size_t pathLen = strlen(path);
|
||||
size_t rootedPathBufferlength = rootLength + pathLen + 1;// +1 for null terminator
|
||||
if (rootedPathBufferlength > resolvedPathSize)
|
||||
|
||||
if (const size_t requiredSize = productAssetAlias.size() + strlen(path) + 1;
|
||||
requiredSize > rootedPathBuffer.capacity())
|
||||
{
|
||||
AZ_Assert(rootedPathBufferlength < resolvedPathSize, "Constructed path length is wrong:%s", rootedPathBuffer);//path constructed is wrong
|
||||
size_t remainingSize = resolvedPathSize - rootLength - 1;// - 1 for null terminator
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN, path, remainingSize);
|
||||
rootedPathBuffer[resolvedPathSize - 1] = '\0';
|
||||
AZ_Error("FileIO", false, "Prepending the %.*s alias to the input path results in a path longer than the"
|
||||
" AZ::IO::MaxPathLength + the alias size of %zu. The size of the potential failed path is %zu",
|
||||
AZ_STRING_ARG(productAssetAlias), rootedPathBuffer.capacity(), requiredSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN - rootLength, path, pathLen + 1);
|
||||
rootedPathBuffer = RootedPathString::format("%.*s/%s", AZ_STRING_ARG(productAssetAlias), path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertToAbsolutePath(path, rootedPathBuffer, AZ_MAX_PATH_LEN);
|
||||
if (ConvertToAbsolutePath(path, rootedPathBuffer.data(), rootedPathBuffer.capacity()))
|
||||
{
|
||||
// Recalculate the internal string length
|
||||
rootedPathBuffer.resize_no_construct(AZStd::char_traits<char>::length(rootedPathBuffer.data()));
|
||||
}
|
||||
}
|
||||
rootedPath = rootedPathBuffer;
|
||||
rootedPath = rootedPathBuffer.c_str();
|
||||
}
|
||||
|
||||
if (ResolveAliases(rootedPath, resolvedPath, resolvedPathSize))
|
||||
@@ -561,11 +566,57 @@ namespace AZ
|
||||
|
||||
const char* LocalFileIO::GetAlias(const char* key) const
|
||||
{
|
||||
const auto it = m_aliases.find(key);
|
||||
if (it != m_aliases.end())
|
||||
if (const auto it = m_aliases.find(key); it != m_aliases.end())
|
||||
{
|
||||
return it->second.c_str();
|
||||
}
|
||||
else if (const auto deprecatedIt = m_deprecatedAliases.find(key);
|
||||
deprecatedIt != m_deprecatedAliases.end())
|
||||
{
|
||||
AZ_Error("FileIO", false, R"(Alias "%s" is deprecated. Please use alias "%s" instead)",
|
||||
key, deprecatedIt->second.c_str());
|
||||
AZStd::string_view aliasValue = deprecatedIt->second;
|
||||
// Contains the list of aliases resolved so far
|
||||
// If max_size is hit, than an error is logged and nullptr is returned
|
||||
using VisitedAliasSet = AZStd::fixed_unordered_set<AZStd::string_view, 8, 8>;
|
||||
VisitedAliasSet visitedAliasSet;
|
||||
while (aliasValue.starts_with("@"))
|
||||
{
|
||||
if (visitedAliasSet.contains(aliasValue))
|
||||
{
|
||||
AZ_Error("FileIO", false, "Cycle found with for alias %.*s when trying to resolve deprecated alias %s",
|
||||
AZ_STRING_ARG(aliasValue), key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(visitedAliasSet.size() == visitedAliasSet.max_size())
|
||||
{
|
||||
AZ_Error("FileIO", false, "Unable to resolve path to deprecated alias %s within %zu steps",
|
||||
key, visitedAliasSet.max_size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add the current alias value to the visited set
|
||||
visitedAliasSet.emplace(aliasValue);
|
||||
|
||||
// Check if the alias value corresponds to another alias
|
||||
if (auto resolvedIter = m_aliases.find(aliasValue); resolvedIter != m_aliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else if (resolvedIter = m_deprecatedAliases.find(aliasValue);
|
||||
resolvedIter != m_deprecatedAliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return aliasValue.data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -574,6 +625,11 @@ namespace AZ
|
||||
m_aliases.erase(key);
|
||||
}
|
||||
|
||||
void LocalFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
m_deprecatedAliases[oldAlias] = newAlias;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> LocalFileIO::ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const
|
||||
{
|
||||
size_t longestMatch = 0;
|
||||
@@ -675,7 +731,9 @@ namespace AZ
|
||||
: string_view_pair{};
|
||||
|
||||
size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1;
|
||||
AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect");
|
||||
AZ_Assert(path != resolvedPath, "ResolveAliases does not support inplace update of the path");
|
||||
AZ_Assert(resolvedPathSize >= requiredResolvedPathSize, "Resolved path size %llu not large enough. It needs to be %zu",
|
||||
resolvedPathSize, requiredResolvedPathSize);
|
||||
// we assert above, but we also need to properly handle the case when the resolvedPath buffer size
|
||||
// is too small to copy the source into.
|
||||
if (path == resolvedPath || (resolvedPathSize < requiredResolvedPathSize))
|
||||
@@ -699,13 +757,9 @@ namespace AZ
|
||||
resolvedPath[resolvedPathLen] = '\0';
|
||||
|
||||
// If the path started with one of the "asset cache" path aliases, lowercase the path
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* rootAliasPath = GetAlias("@root@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@projectplatformcache@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@products@");
|
||||
|
||||
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
|
||||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
|
||||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
|
||||
const bool lowercasePath = projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath);
|
||||
|
||||
if (lowercasePath)
|
||||
{
|
||||
@@ -822,5 +876,10 @@ namespace AZ
|
||||
|
||||
return pathStr + "/";
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
return AZ::Utils::ConvertToAbsolutePath(path, absolutePath, maxLength);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -71,7 +73,7 @@ namespace AZ
|
||||
|
||||
bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const override;
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const;
|
||||
|
||||
|
||||
private:
|
||||
SystemFile* GetFilePointerFromHandle(HandleType fileHandle);
|
||||
|
||||
@@ -79,7 +81,6 @@ namespace AZ
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const;
|
||||
bool ResolveAliases(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const;
|
||||
bool IsAbsolutePath(const char* path) const;
|
||||
|
||||
bool LowerIfBeginsWith(char* inOutBuffer, AZ::u64 bufferLen, const char* alias) const;
|
||||
|
||||
@@ -91,6 +92,7 @@ namespace AZ
|
||||
AZStd::atomic<HandleType> m_nextHandle;
|
||||
AZStd::unordered_map<HandleType, SystemFile> m_openFiles;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_aliases;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_deprecatedAliases;
|
||||
|
||||
void CheckInvalidWrite(const char* path);
|
||||
};
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace AZ
|
||||
s_IOLog.append(m_name);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
void Append(const char* line)
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u ", m_fileOperation));
|
||||
s_IOLog.append(line);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
~LogCall()
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u End ", m_fileOperation));
|
||||
@@ -251,7 +251,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size request failed. return Error", filePath).c_str());
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
|
||||
size = response.m_size;
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size=%u. return Success", filePath, size).c_str());
|
||||
return ResultCode::Success;
|
||||
@@ -793,6 +793,12 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ClearAlias(alias=%s)", alias?alias:"nullptr").c_str());
|
||||
}
|
||||
|
||||
void NetworkFileIO::SetDeprecatedAlias([[maybe_unused]] AZStd::string_view oldAlias, [[maybe_unused]] AZStd::string_view newAlias)
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::SetDeprecatedAlias(oldAlias=%.*s, newAlias=%.*s)",
|
||||
AZ_STRING_ARG(oldAlias), AZ_STRING_ARG(newAlias)).c_str());
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> NetworkFileIO::ConvertToAlias(char* inOutBuffer, [[maybe_unused]] AZ::u64 bufferLength) const
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ConvertToAlias(inOutBuffer=%s, bufferLength=%u)", inOutBuffer?inOutBuffer:"nullptr", bufferLength).c_str());
|
||||
@@ -927,7 +933,7 @@ namespace AZ
|
||||
{
|
||||
m_cacheLookaheadPos = filePosition - CacheStartFilePosition();
|
||||
}
|
||||
|
||||
|
||||
void RemoteFileCache::SyncCheck()
|
||||
{
|
||||
#ifdef REMOTEFILEIO_SYNC_CHECK
|
||||
@@ -955,7 +961,7 @@ namespace AZ
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle);
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle).c_str());
|
||||
}
|
||||
|
||||
|
||||
if (responce.m_offset != m_filePosition)
|
||||
{
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) failed!!! m_filePosition=%u tell=%u", m_fileHandle, m_filePosition, responce.m_offset);
|
||||
@@ -1028,7 +1034,7 @@ namespace AZ
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Close(fileHandle=%u)", fileHandle).c_str());
|
||||
Result returnValue = NetworkFileIO::Close(fileHandle);
|
||||
|
||||
|
||||
if (returnValue == ResultCode::Success)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
@@ -1160,7 +1166,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Read(fileHandle=%u, buffer=OUT, size=%u, failOnFewerThanSizeBytesRead=%s, bytesRead=OUT)", fileHandle, size, failOnFewerThanSizeBytesRead ? "True" : "False").c_str());
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
|
||||
|
||||
AZ::u64 remainingBytesToRead = size;
|
||||
AZ::u64 bytesReadFromCache = 0;
|
||||
AZ::u64 remainingBytesInCache = cache.RemainingBytes();
|
||||
@@ -1263,7 +1269,7 @@ namespace AZ
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
if (cache.m_cacheLookaheadBuffer.size() && cache.RemainingBytes())
|
||||
{
|
||||
// find out where we are
|
||||
// find out where we are
|
||||
AZ::u64 seekPosition = cache.CacheFilePosition();
|
||||
|
||||
// note, seeks are predicted, and do not ask for a response.
|
||||
@@ -1361,6 +1367,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
if (m_excludedFileIO)
|
||||
{
|
||||
m_excludedFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> RemoteFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
return m_excludedFileIO ? m_excludedFileIO->ConvertToAlias(inOutBuffer, bufferLength) : strlen(inOutBuffer);
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace AZ
|
||||
Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -194,6 +195,7 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingAnd::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingOr::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
@@ -190,6 +191,25 @@ namespace AzFramework
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void InputSystemComponent::Activate()
|
||||
{
|
||||
const auto* settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry)
|
||||
{
|
||||
AZ::u64 value = 0;
|
||||
if (settingsRegistry->Get(value, "/O3DE/InputSystem/MouseMovementSampleRateHertz"))
|
||||
{
|
||||
m_mouseMovementSampleRateHertz = aznumeric_caster(value);
|
||||
}
|
||||
if (settingsRegistry->Get(value, "/O3DE/InputSystem/GamepadsEnabled"))
|
||||
{
|
||||
m_gamepadsEnabled = aznumeric_caster(value);
|
||||
}
|
||||
settingsRegistry->Get(m_keyboardEnabled, "/O3DE/InputSystem/KeyboardEnabled");
|
||||
settingsRegistry->Get(m_motionEnabled, "/O3DE/InputSystem/MotionEnabled");
|
||||
settingsRegistry->Get(m_mouseEnabled, "/O3DE/InputSystem/MouseEnabled");
|
||||
settingsRegistry->Get(m_touchEnabled, "/O3DE/InputSystem/TouchEnabled");
|
||||
settingsRegistry->Get(m_virtualKeyboardEnabled, "/O3DE/InputSystem/VirtualKeyboardEnabled");
|
||||
}
|
||||
|
||||
// Create all enabled input devices
|
||||
CreateEnabledInputDevices();
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Matchmaking/MatchmakingRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! IMatchmakingRequests
|
||||
//! Pure virtual session interface class to abstract the details of session handling from application code.
|
||||
class IMatchmakingRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IMatchmakingRequests, "{BC0B74DA-A448-4F40-9B50-9D73142829D5}");
|
||||
|
||||
IMatchmakingRequests() = default;
|
||||
virtual ~IMatchmakingRequests() = default;
|
||||
|
||||
// Registers a player's acceptance or rejection of a proposed matchmaking.
|
||||
// @param acceptMatchRequest The request of AcceptMatch operation
|
||||
virtual void AcceptMatch(const AcceptMatchRequest& acceptMatchRequest) = 0;
|
||||
|
||||
// Create a game match for a group of players.
|
||||
// @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
// @return A unique identifier for a matchmaking ticket
|
||||
virtual AZStd::string StartMatchmaking(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// Cancels a matchmaking ticket that is currently being processed.
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmaking(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
|
||||
//! IMatchmakingAsyncRequests
|
||||
//! Async version of IMatchmakingRequests
|
||||
class IMatchmakingAsyncRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ISessionAsyncRequests, "{53513480-2D02-493C-B44E-96AA27F42429}");
|
||||
|
||||
IMatchmakingAsyncRequests() = default;
|
||||
virtual ~IMatchmakingAsyncRequests() = default;
|
||||
|
||||
// AcceptMatch Async
|
||||
// @param acceptMatchRequest The request of AcceptMatch operation
|
||||
virtual void AcceptMatchAsync(const AcceptMatchRequest& acceptMatchRequest) = 0;
|
||||
|
||||
// StartMatchmaking Async
|
||||
// @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
virtual void StartMatchmakingAsync(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// StopMatchmaking Async
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmakingAsync(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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/std/string/string.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! MatchmakingAsyncRequestNotifications
|
||||
//! The notifications correspond to matchmaking async requests
|
||||
class MatchmakingAsyncRequestNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
|
||||
virtual void OnAcceptMatchAsyncComplete() = 0;
|
||||
|
||||
// OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
|
||||
// @param matchmakingTicketId The unique identifier for the matchmaking ticket
|
||||
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
|
||||
|
||||
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
virtual void OnStopMatchmakingAsyncComplete() = 0;
|
||||
};
|
||||
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
|
||||
|
||||
//! MatchmakingNotifications
|
||||
//! The matchmaking notifications to listen for performing required operations
|
||||
class MatchAcceptanceNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnMatchAcceptance is fired when DescribeMatchmaking ticket status is REQUIRES_ACCEPTANCE
|
||||
virtual void OnMatchAcceptance() = 0;
|
||||
};
|
||||
using MatchAcceptanceNotificationBus = AZ::EBus<MatchAcceptanceNotifications>;
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Matchmaking/MatchmakingRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void AcceptMatchRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AcceptMatchRequest>()
|
||||
->Version(0)
|
||||
->Field("acceptMatch", &AcceptMatchRequest::m_acceptMatch)
|
||||
->Field("playerIds", &AcceptMatchRequest::m_playerIds)
|
||||
->Field("ticketId", &AcceptMatchRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<AcceptMatchRequest>("AcceptMatchRequest", "The container for AcceptMatch request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_acceptMatch, "AcceptMatch",
|
||||
"Player response to accept or reject match")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_playerIds, "PlayerIds",
|
||||
"A list of unique identifiers for players delivering the response")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartMatchmakingRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<StartMatchmakingRequest>()
|
||||
->Version(0)
|
||||
->Field("ticketId", &StartMatchmakingRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<StartMatchmakingRequest>("StartMatchmakingRequest", "The container for StartMatchmaking request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &StartMatchmakingRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StopMatchmakingRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<StopMatchmakingRequest>()
|
||||
->Version(0)
|
||||
->Field("ticketId", &StopMatchmakingRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<StopMatchmakingRequest>("StopMatchmakingRequest", "The container for StopMatchmaking request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &StopMatchmakingRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! AcceptMatchRequest
|
||||
//! The container for AcceptMatch request parameters.
|
||||
struct AcceptMatchRequest
|
||||
{
|
||||
AZ_RTTI(AcceptMatchRequest, "{AD289D76-CEE2-424F-847E-E62AA83B7D79}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AcceptMatchRequest() = default;
|
||||
virtual ~AcceptMatchRequest() = default;
|
||||
|
||||
// Player response to accept or reject match
|
||||
bool m_acceptMatch;
|
||||
// A list of unique identifiers for players delivering the response
|
||||
AZStd::vector<AZStd::string> m_playerIds;
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
//! StartMatchmakingRequest
|
||||
//! The container for StartMatchmaking request parameters.
|
||||
struct StartMatchmakingRequest
|
||||
{
|
||||
AZ_RTTI(StartMatchmakingRequest, "{70B47776-E8E7-4993-BEC3-5CAEC3D48E47}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
StartMatchmakingRequest() = default;
|
||||
virtual ~StartMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
//! StopMatchmakingRequest
|
||||
//! The container for StopMatchmaking request parameters.
|
||||
struct StopMatchmakingRequest
|
||||
{
|
||||
AZ_RTTI(StopMatchmakingRequest, "{6132E293-65EF-4DC2-A8A0-00269697229D}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
StopMatchmakingRequest() = default;
|
||||
virtual ~StopMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -10,98 +10,11 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzFramework/Session/SessionRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct SessionConfig;
|
||||
|
||||
//! CreateSessionRequest
|
||||
//! The container for CreateSession request parameters.
|
||||
struct CreateSessionRequest
|
||||
{
|
||||
AZ_RTTI(CreateSessionRequest, "{E39C2A45-89C9-4CFB-B337-9734DC798930}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
CreateSessionRequest() = default;
|
||||
virtual ~CreateSessionRequest() = default;
|
||||
|
||||
// A unique identifier for a player or entity creating the session.
|
||||
AZStd::string m_creatorId;
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// A descriptive label that is associated with a session.
|
||||
AZStd::string m_sessionName;
|
||||
|
||||
// The maximum number of players that can be connected simultaneously to the session.
|
||||
uint64_t m_maxPlayer = 0;
|
||||
};
|
||||
|
||||
//! SearchSessionsRequest
|
||||
//! The container for SearchSessions request parameters.
|
||||
struct SearchSessionsRequest
|
||||
{
|
||||
AZ_RTTI(SearchSessionsRequest, "{B49207A8-8549-4ADB-B7D9-D7A4932F9B4B}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SearchSessionsRequest() = default;
|
||||
virtual ~SearchSessionsRequest() = default;
|
||||
|
||||
// String containing the search criteria for the session search. If no filter expression is included, the request returns results
|
||||
// for all active sessions.
|
||||
AZStd::string m_filterExpression;
|
||||
|
||||
// Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
|
||||
AZStd::string m_sortExpression;
|
||||
|
||||
// The maximum number of results to return.
|
||||
uint8_t m_maxResult = 0;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! SearchSessionsResponse
|
||||
//! The container for SearchSession request results.
|
||||
struct SearchSessionsResponse
|
||||
{
|
||||
AZ_RTTI(SearchSessionsResponse, "{F93DE7DC-D381-4E08-8A3B-0B08F7C38714}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SearchSessionsResponse() = default;
|
||||
virtual ~SearchSessionsResponse() = default;
|
||||
|
||||
// A collection of sessions that match the search criteria and sorted in specific order.
|
||||
AZStd::vector<SessionConfig> m_sessionConfigs;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! JoinSessionRequest
|
||||
//! The container for JoinSession request parameters.
|
||||
struct JoinSessionRequest
|
||||
{
|
||||
AZ_RTTI(JoinSessionRequest, "{519769E8-3CDE-4385-A0D7-24DBB3685657}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JoinSessionRequest() = default;
|
||||
virtual ~JoinSessionRequest() = default;
|
||||
|
||||
// A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
// A unique identifier for a player. Player IDs are developer-defined.
|
||||
AZStd::string m_playerId;
|
||||
|
||||
// Developer-defined information related to a player.
|
||||
AZStd::string m_playerData;
|
||||
};
|
||||
|
||||
//! ISessionRequests
|
||||
//! Pure virtual session interface class to abstract the details of session handling from application code.
|
||||
class ISessionRequests
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace AzFramework
|
||||
->Field("terminationTime", &SessionConfig::m_terminationTime)
|
||||
->Field("creatorId", &SessionConfig::m_creatorId)
|
||||
->Field("sessionProperties", &SessionConfig::m_sessionProperties)
|
||||
->Field("matchmakingData", &SessionConfig::m_matchmakingData)
|
||||
->Field("sessionId", &SessionConfig::m_sessionId)
|
||||
->Field("sessionName", &SessionConfig::m_sessionName)
|
||||
->Field("dnsName", &SessionConfig::m_dnsName)
|
||||
@@ -46,6 +47,8 @@ namespace AzFramework
|
||||
"CreatorId", "A unique identifier for a player or entity creating the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionProperties,
|
||||
"SessionProperties", "A collection of custom properties for a session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_matchmakingData,
|
||||
"MatchmakingData", "The matchmaking process information that was used to create the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionId,
|
||||
"SessionId", "A unique identifier for the session.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionName,
|
||||
|
||||
@@ -35,6 +35,9 @@ namespace AzFramework
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// The matchmaking process information that was used to create the session.
|
||||
AZStd::string m_matchmakingData;
|
||||
|
||||
// A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
@@ -41,6 +41,11 @@ namespace AzFramework
|
||||
// OnDestroySessionBegin is fired at the beginning of session termination
|
||||
// @return The result of all OnDestroySessionBegin notifications
|
||||
virtual bool OnDestroySessionBegin() = 0;
|
||||
|
||||
// OnUpdateSessionBegin is fired at the beginning of session update
|
||||
// @param sessionConfig The properties to describe a session
|
||||
// @param updateReason The reason for session update
|
||||
virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0;
|
||||
};
|
||||
using SessionNotificationBus = AZ::EBus<SessionNotifications>;
|
||||
} // namespace AzFramework
|
||||
|
||||
+2
-1
@@ -6,9 +6,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Session/ISessionRequests.h>
|
||||
#include <AzFramework/Session/SessionRequests.h>
|
||||
#include <AzFramework/Session/SessionConfig.h>
|
||||
|
||||
namespace AzFramework
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct SessionConfig;
|
||||
|
||||
//! CreateSessionRequest
|
||||
//! The container for CreateSession request parameters.
|
||||
struct CreateSessionRequest
|
||||
{
|
||||
AZ_RTTI(CreateSessionRequest, "{E39C2A45-89C9-4CFB-B337-9734DC798930}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
CreateSessionRequest() = default;
|
||||
virtual ~CreateSessionRequest() = default;
|
||||
|
||||
// A unique identifier for a player or entity creating the session.
|
||||
AZStd::string m_creatorId;
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// A descriptive label that is associated with a session.
|
||||
AZStd::string m_sessionName;
|
||||
|
||||
// The maximum number of players that can be connected simultaneously to the session.
|
||||
uint64_t m_maxPlayer = 0;
|
||||
};
|
||||
|
||||
//! SearchSessionsRequest
|
||||
//! The container for SearchSessions request parameters.
|
||||
struct SearchSessionsRequest
|
||||
{
|
||||
AZ_RTTI(SearchSessionsRequest, "{B49207A8-8549-4ADB-B7D9-D7A4932F9B4B}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SearchSessionsRequest() = default;
|
||||
virtual ~SearchSessionsRequest() = default;
|
||||
|
||||
// String containing the search criteria for the session search. If no filter expression is included, the request returns results
|
||||
// for all active sessions.
|
||||
AZStd::string m_filterExpression;
|
||||
|
||||
// Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
|
||||
AZStd::string m_sortExpression;
|
||||
|
||||
// The maximum number of results to return.
|
||||
uint8_t m_maxResult = 0;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! SearchSessionsResponse
|
||||
//! The container for SearchSession request results.
|
||||
struct SearchSessionsResponse
|
||||
{
|
||||
AZ_RTTI(SearchSessionsResponse, "{F93DE7DC-D381-4E08-8A3B-0B08F7C38714}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SearchSessionsResponse() = default;
|
||||
virtual ~SearchSessionsResponse() = default;
|
||||
|
||||
// A collection of sessions that match the search criteria and sorted in specific order.
|
||||
AZStd::vector<SessionConfig> m_sessionConfigs;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! JoinSessionRequest
|
||||
//! The container for JoinSession request parameters.
|
||||
struct JoinSessionRequest
|
||||
{
|
||||
AZ_RTTI(JoinSessionRequest, "{519769E8-3CDE-4385-A0D7-24DBB3685657}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JoinSessionRequest() = default;
|
||||
virtual ~JoinSessionRequest() = default;
|
||||
|
||||
// A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
// A unique identifier for a player. Player IDs are developer-defined.
|
||||
AZStd::string m_playerId;
|
||||
|
||||
// Developer-defined information related to a player.
|
||||
AZStd::string m_playerData;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -61,6 +61,10 @@ namespace AzFramework
|
||||
//! be deleted and the spawnable asset to be released. This call is automatically done when
|
||||
//! AssignRootSpawnable is called while a root spawnable is assigned.
|
||||
virtual void ReleaseRootSpawnable() = 0;
|
||||
//! Force processing all SpawnableEntitiesManager requests immediately
|
||||
//! This is useful when loading a different level while SpawnableEntitiesManager still has
|
||||
//! pending requests
|
||||
virtual void ProcessSpawnableQueue() = 0;
|
||||
};
|
||||
|
||||
using RootSpawnableInterface = AZ::Interface<RootSpawnableDefinition>;
|
||||
|
||||
@@ -45,8 +45,7 @@ namespace AzFramework
|
||||
|
||||
void SpawnableSystemComponent::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
{
|
||||
m_entitiesManager.ProcessQueue(
|
||||
SpawnableEntitiesManager::CommandQueuePriority::High | SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
ProcessSpawnableQueue();
|
||||
RootSpawnableNotificationBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
@@ -121,6 +120,12 @@ namespace AzFramework
|
||||
m_rootSpawnableId = AZ::Data::AssetId();
|
||||
}
|
||||
|
||||
void SpawnableSystemComponent::ProcessSpawnableQueue()
|
||||
{
|
||||
m_entitiesManager.ProcessQueue(
|
||||
SpawnableEntitiesManager::CommandQueuePriority::High | SpawnableEntitiesManager::CommandQueuePriority::Regular);
|
||||
}
|
||||
|
||||
void SpawnableSystemComponent::OnRootSpawnableAssigned([[maybe_unused]] AZ::Data::Asset<Spawnable> rootSpawnable,
|
||||
[[maybe_unused]] uint32_t generation)
|
||||
{
|
||||
@@ -161,6 +166,8 @@ namespace AzFramework
|
||||
|
||||
void SpawnableSystemComponent::Deactivate()
|
||||
{
|
||||
ProcessSpawnableQueue();
|
||||
|
||||
m_registryChangeHandler.Disconnect();
|
||||
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
|
||||
@@ -75,6 +75,7 @@ namespace AzFramework
|
||||
|
||||
uint64_t AssignRootSpawnable(AZ::Data::Asset<Spawnable> rootSpawnable) override;
|
||||
void ReleaseRootSpawnable() override;
|
||||
void ProcessSpawnableQueue() override;
|
||||
|
||||
//
|
||||
// RootSpawnbleNotificationBus
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
@@ -17,16 +18,38 @@ namespace AzFramework
|
||||
{
|
||||
namespace SurfaceData
|
||||
{
|
||||
namespace Constants
|
||||
{
|
||||
static const char* s_unassignedTagName = "(unassigned)";
|
||||
}
|
||||
|
||||
struct SurfaceTagWeight
|
||||
{
|
||||
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
|
||||
|
||||
AZ::Crc32 m_surfaceType;
|
||||
float m_weight; //! A Value in the range [0.0f .. 1.0f]
|
||||
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
|
||||
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
|
||||
|
||||
//! Don't call this directly. TerrainDataRequests::Reflect is doing it already.
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
struct SurfaceTagWeightComparator
|
||||
{
|
||||
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
|
||||
{
|
||||
if (!AZ::IsClose(tagWeight1.m_weight, tagWeight2.m_weight))
|
||||
{
|
||||
return tagWeight1.m_weight > tagWeight2.m_weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using OrderedSurfaceTagWeightSet = AZStd::set<SurfaceTagWeight, SurfaceTagWeightComparator>;
|
||||
} //namespace SurfaceData
|
||||
|
||||
namespace Terrain
|
||||
@@ -75,8 +98,28 @@ namespace AzFramework
|
||||
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false,
|
||||
//! otherwise *terrainExistsPtr will be set to true.
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
|
||||
//! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore
|
||||
//! the input Z value.
|
||||
virtual void GetSurfaceWeights(
|
||||
const AZ::Vector3& inPosition,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual void GetSurfaceWeightsFromVector2(
|
||||
const AZ::Vector2& inPosition,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual void GetSurfaceWeightsFromFloats(
|
||||
float x,
|
||||
float y,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
|
||||
//! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats.
|
||||
//! Not available in the behavior context.
|
||||
//! Returns nullptr if the position is inside a hole or outside of the terrain boundaries.
|
||||
|
||||
@@ -533,8 +533,8 @@ namespace AzFramework
|
||||
m_translateCameraInputChannelIds = translateCameraInputChannelIds;
|
||||
}
|
||||
|
||||
PivotCameraInput::PivotCameraInput(const InputChannelId& pivotChannelId)
|
||||
: m_pivotChannelId(pivotChannelId)
|
||||
OrbitCameraInput::OrbitCameraInput(const InputChannelId& orbitChannelId)
|
||||
: m_orbitChannelId(orbitChannelId)
|
||||
{
|
||||
m_pivotFn = []([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
{
|
||||
@@ -542,11 +542,11 @@ namespace AzFramework
|
||||
};
|
||||
}
|
||||
|
||||
bool PivotCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta)
|
||||
bool OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_pivotChannelId)
|
||||
if (input->m_channelId == m_orbitChannelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
@@ -561,13 +561,13 @@ namespace AzFramework
|
||||
|
||||
if (Active())
|
||||
{
|
||||
return m_pivotCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
return m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera PivotCameraInput::StepCamera(
|
||||
Camera OrbitCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
@@ -581,12 +581,12 @@ namespace AzFramework
|
||||
if (Active())
|
||||
{
|
||||
MovePivotDetached(nextCamera, m_pivotFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()));
|
||||
nextCamera = m_pivotCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
if (Ending())
|
||||
{
|
||||
m_pivotCameras.Reset();
|
||||
m_orbitCameras.Reset();
|
||||
|
||||
nextCamera.m_pivot = nextCamera.Translation();
|
||||
nextCamera.m_offset = AZ::Vector3::CreateZero();
|
||||
@@ -595,12 +595,12 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void PivotCameraInput::SetPivotInputChannelId(const InputChannelId& pivotChanneId)
|
||||
void OrbitCameraInput::SetOrbitInputChannelId(const InputChannelId& orbitChanneId)
|
||||
{
|
||||
m_pivotChannelId = pivotChanneId;
|
||||
m_orbitChannelId = orbitChanneId;
|
||||
}
|
||||
|
||||
PivotDollyScrollCameraInput::PivotDollyScrollCameraInput()
|
||||
OrbitDollyScrollCameraInput::OrbitDollyScrollCameraInput()
|
||||
{
|
||||
m_scrollSpeedFn = []() constexpr
|
||||
{
|
||||
@@ -608,7 +608,7 @@ namespace AzFramework
|
||||
};
|
||||
}
|
||||
|
||||
bool PivotDollyScrollCameraInput::HandleEvents(
|
||||
bool OrbitDollyScrollCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
@@ -619,36 +619,45 @@ namespace AzFramework
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
static Camera PivotDolly(const Camera& targetCamera, const float delta)
|
||||
static Camera OrbitDolly(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)
|
||||
// handle case where pivot and offset may be the same to begin with
|
||||
// choose negative y-axis for offset to default to moving the camera backwards from the pivot (standard centered pivot behavior)
|
||||
const auto pivotDirection = [&targetCamera]
|
||||
{
|
||||
nextCamera.m_offset = pivotDirection * minDistance;
|
||||
if (const auto offsetLength = targetCamera.m_offset.GetLength(); AZ::IsCloseMag(offsetLength, 0.0f))
|
||||
{
|
||||
return -AZ::Vector3::CreateAxisY();
|
||||
}
|
||||
else
|
||||
{
|
||||
return targetCamera.m_offset / offsetLength;
|
||||
}
|
||||
}();
|
||||
|
||||
nextCamera.m_offset -= pivotDirection * delta;
|
||||
if (pivotDirection.Dot(nextCamera.m_offset) < 0.0f)
|
||||
{
|
||||
nextCamera.m_offset = pivotDirection * 0.001f;
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
Camera PivotDollyScrollCameraInput::StepCamera(
|
||||
Camera OrbitDollyScrollCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
[[maybe_unused]] const ScreenVector& cursorDelta,
|
||||
const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
const auto nextCamera = PivotDolly(targetCamera, aznumeric_cast<float>(scrollDelta) * m_scrollSpeedFn());
|
||||
const auto nextCamera = OrbitDolly(targetCamera, aznumeric_cast<float>(scrollDelta) * m_scrollSpeedFn());
|
||||
EndActivation();
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
PivotDollyMotionCameraInput::PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId)
|
||||
OrbitDollyMotionCameraInput::OrbitDollyMotionCameraInput(const InputChannelId& dollyChannelId)
|
||||
: m_dollyChannelId(dollyChannelId)
|
||||
{
|
||||
m_motionSpeedFn = []() constexpr
|
||||
@@ -657,28 +666,28 @@ namespace AzFramework
|
||||
};
|
||||
}
|
||||
|
||||
bool PivotDollyMotionCameraInput::HandleEvents(
|
||||
bool OrbitDollyMotionCameraInput::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 PivotDollyMotionCameraInput::StepCamera(
|
||||
Camera OrbitDollyMotionCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
const ScreenVector& cursorDelta,
|
||||
[[maybe_unused]] const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
return PivotDolly(targetCamera, aznumeric_cast<float>(cursorDelta.m_y) * m_motionSpeedFn());
|
||||
return OrbitDolly(targetCamera, aznumeric_cast<float>(cursorDelta.m_y) * m_motionSpeedFn());
|
||||
}
|
||||
|
||||
void PivotDollyMotionCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId)
|
||||
void OrbitDollyMotionCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId)
|
||||
{
|
||||
m_dollyChannelId = dollyChannelId;
|
||||
}
|
||||
|
||||
ScrollTranslationCameraInput::ScrollTranslationCameraInput()
|
||||
LookScrollTranslationCameraInput::LookScrollTranslationCameraInput()
|
||||
{
|
||||
m_scrollSpeedFn = []() constexpr
|
||||
{
|
||||
@@ -686,7 +695,7 @@ namespace AzFramework
|
||||
};
|
||||
}
|
||||
|
||||
bool ScrollTranslationCameraInput::HandleEvents(
|
||||
bool LookScrollTranslationCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
@@ -697,7 +706,7 @@ namespace AzFramework
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera ScrollTranslationCameraInput::StepCamera(
|
||||
Camera LookScrollTranslationCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
[[maybe_unused]] const ScreenVector& cursorDelta,
|
||||
const float scrollDelta,
|
||||
@@ -771,6 +780,73 @@ namespace AzFramework
|
||||
return camera;
|
||||
}
|
||||
|
||||
FocusCameraInput::FocusCameraInput(const InputChannelId& focusChannelId, FocusOffsetFn offsetFn)
|
||||
: m_focusChannelId(focusChannelId)
|
||||
, m_offsetFn(offsetFn)
|
||||
{
|
||||
}
|
||||
|
||||
bool FocusCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_focusChannelId && input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera FocusCameraInput::StepCamera(
|
||||
const Camera& targetCamera,
|
||||
[[maybe_unused]] const ScreenVector& cursorDelta,
|
||||
[[maybe_unused]] float scrollDelta,
|
||||
[[maybe_unused]] float deltaTime)
|
||||
{
|
||||
if (Beginning())
|
||||
{
|
||||
// as the camera starts, record the camera we would like to end up as
|
||||
m_nextCamera.m_offset = m_offsetFn(m_pivotFn().GetDistance(targetCamera.Translation()));
|
||||
const auto angles =
|
||||
EulerAngles(AZ::Matrix3x3::CreateFromMatrix3x4(AZ::Matrix3x4::CreateLookAt(targetCamera.Translation(), m_pivotFn())));
|
||||
m_nextCamera.m_pitch = angles.GetX();
|
||||
m_nextCamera.m_yaw = angles.GetZ();
|
||||
m_nextCamera.m_pivot = targetCamera.m_pivot;
|
||||
}
|
||||
|
||||
// end the behavior when the camera is in alignment
|
||||
if (AZ::IsCloseMag(targetCamera.m_pitch, m_nextCamera.m_pitch) && AZ::IsCloseMag(targetCamera.m_yaw, m_nextCamera.m_yaw))
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
|
||||
return m_nextCamera;
|
||||
}
|
||||
|
||||
void FocusCameraInput::SetPivotFn(PivotFn pivotFn)
|
||||
{
|
||||
m_pivotFn = AZStd::move(pivotFn);
|
||||
}
|
||||
|
||||
void FocusCameraInput::SetFocusInputChannelId(const InputChannelId& focusChannelId)
|
||||
{
|
||||
m_focusChannelId = focusChannelId;
|
||||
}
|
||||
|
||||
bool CustomCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta)
|
||||
{
|
||||
return m_handleEventsFn(*this, event, cursorDelta, scrollDelta);
|
||||
}
|
||||
|
||||
Camera CustomCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime)
|
||||
{
|
||||
return m_stepCameraFn(*this, targetCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize)
|
||||
{
|
||||
const auto& inputChannelId = inputChannel.GetInputChannelId();
|
||||
|
||||
@@ -30,8 +30,11 @@ namespace AzFramework
|
||||
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation);
|
||||
|
||||
//! 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
|
||||
//! The camera's transform and view can be obtained through accessor functions that use the internal
|
||||
//! spherical coordinates to calculate the position and orientation.
|
||||
//! @note Modifying m_pivot directly and leaving m_offset as zero will produce a free look camera effect, giving
|
||||
//! m_offset a value (e.g. in negative Y only) will produce an orbit camera effect, modifying X and Z of m_offset
|
||||
//! will further alter the camera translation in relation to m_pivot so it appears off center.
|
||||
struct Camera
|
||||
{
|
||||
AZ::Vector3 m_pivot = AZ::Vector3::CreateZero(); //!< Pivot point to rotate about (modified in world space).
|
||||
@@ -291,7 +294,7 @@ namespace AzFramework
|
||||
Cameras m_cameras; //!< Represents a collection of camera inputs that together provide a camera controller.
|
||||
|
||||
private:
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/pivot/pan (rotation + translation) - two dimensional.
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/orbit/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).
|
||||
@@ -316,7 +319,7 @@ namespace AzFramework
|
||||
return AZStd::fmod(yaw + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
|
||||
}
|
||||
|
||||
//! A camera input to handle motion deltas that can rotate or pivot the camera.
|
||||
//! A camera input to handle motion deltas that can change the orientation of the camera (update pitch and yaw).
|
||||
class RotateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
@@ -348,15 +351,16 @@ namespace AzFramework
|
||||
//! PanAxes build function that will return a pair of pan axes depending on the camera orientation.
|
||||
using PanAxesFn = AZStd::function<PanAxes(const Camera& camera)>;
|
||||
|
||||
//! PanAxes to use while in 'look' camera behavior (free look).
|
||||
//! PanAxes to use while in 'look' or 'orbit' camera behavior.
|
||||
inline PanAxes LookPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
return { orientation.GetBasisX(), orientation.GetBasisZ() };
|
||||
}
|
||||
|
||||
//! PanAxes to use while in 'pivot' camera behavior.
|
||||
inline PanAxes PivotPan(const Camera& camera)
|
||||
//! Optional PanAxes to use while in 'orbit' camera behavior.
|
||||
//! @note This will move the camera in the local X/Y plane instead of usual X/Z plane.
|
||||
inline PanAxes OrbitPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
@@ -370,14 +374,23 @@ namespace AzFramework
|
||||
return { basisX, basisY };
|
||||
}
|
||||
|
||||
//! TranslationDeltaFn is used by PanCameraInput and TranslateCameraInput
|
||||
//! @note Choose the appropriate function if the behavior should be operating as a free look camera (TranslatePivotLook)
|
||||
//! or an orbit camera (TranslateOffsetOrbit).
|
||||
using TranslationDeltaFn = AZStd::function<void(Camera& camera, const AZ::Vector3& delta)>;
|
||||
|
||||
inline void TranslatePivot(Camera& camera, const AZ::Vector3& delta)
|
||||
//! Update the pivot camera position.
|
||||
//! @note delta will need to have been transformed to world space, e.g. To move the camera right, (1, 0, 0) must
|
||||
//! first be transformed by the orientation of the camera before being applied to m_pivot.
|
||||
inline void TranslatePivotLook(Camera& camera, const AZ::Vector3& delta)
|
||||
{
|
||||
camera.m_pivot += delta;
|
||||
}
|
||||
|
||||
inline void TranslateOffset(Camera& camera, const AZ::Vector3& delta)
|
||||
//! Update the offset camera position.
|
||||
//! @note delta still needs to be transformed to world space (as with TranslatePivotLook) but internally this is undone
|
||||
//! to be performed in local space when being applied to m_offset.
|
||||
inline void TranslateOffsetOrbit(Camera& camera, const AZ::Vector3& delta)
|
||||
{
|
||||
camera.m_offset += camera.View().TransformVector(delta);
|
||||
}
|
||||
@@ -409,7 +422,7 @@ namespace AzFramework
|
||||
//! Axes to use while translating the camera.
|
||||
using TranslationAxesFn = AZStd::function<AZ::Matrix3x3(const Camera& camera)>;
|
||||
|
||||
//! TranslationAxes to use while in 'look' camera behavior (free look).
|
||||
//! TranslationAxes to use while in 'look' or 'orbit' camera behavior.
|
||||
inline AZ::Matrix3x3 LookTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
@@ -421,8 +434,8 @@ namespace AzFramework
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
//! TranslationAxes to use while in 'pivot' camera behavior.
|
||||
inline AZ::Matrix3x3 PivotTranslation(const Camera& camera)
|
||||
//! Optional TranslationAxes to use while in 'orbit' camera behavior.
|
||||
inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
@@ -535,11 +548,11 @@ namespace AzFramework
|
||||
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 pivot distance.
|
||||
class PivotDollyScrollCameraInput : public CameraInput
|
||||
//! A camera input to handle discrete scroll events that can modify the camera offset.
|
||||
class OrbitDollyScrollCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
PivotDollyScrollCameraInput();
|
||||
OrbitDollyScrollCameraInput();
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -548,11 +561,11 @@ namespace AzFramework
|
||||
AZStd::function<float()> m_scrollSpeedFn;
|
||||
};
|
||||
|
||||
//! A camera input to handle motion deltas that can modify the camera pivot distance.
|
||||
class PivotDollyMotionCameraInput : public CameraInput
|
||||
//! A camera input to handle motion deltas that can modify the camera offset.
|
||||
class OrbitDollyMotionCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId);
|
||||
explicit OrbitDollyMotionCameraInput(const InputChannelId& dollyChannelId);
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -569,10 +582,10 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
//! A camera input to handle discrete scroll events that can scroll (translate) the camera along its forward axis.
|
||||
class ScrollTranslationCameraInput : public CameraInput
|
||||
class LookScrollTranslationCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
ScrollTranslationCameraInput();
|
||||
LookScrollTranslationCameraInput();
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
@@ -583,40 +596,96 @@ 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 PivotCameraInput : public CameraInput
|
||||
class OrbitCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
using PivotFn = AZStd::function<AZ::Vector3(const AZ::Vector3& position, const AZ::Vector3& direction)>;
|
||||
|
||||
explicit PivotCameraInput(const InputChannelId& pivotChannelId);
|
||||
explicit OrbitCameraInput(const InputChannelId& orbitChannelId);
|
||||
|
||||
// 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 SetPivotInputChannelId(const InputChannelId& pivotChanneId);
|
||||
void SetOrbitInputChannelId(const InputChannelId& orbitChanneId);
|
||||
|
||||
Cameras m_pivotCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive).
|
||||
Cameras m_orbitCameras; //!< 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 pivot point is calculated.
|
||||
void SetPivotFn(PivotFn pivotFn);
|
||||
|
||||
private:
|
||||
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).
|
||||
InputChannelId m_orbitChannelId; //!< Input channel to begin the orbit camera input.
|
||||
PivotFn m_pivotFn; //!< The pivot position to use for this orbit camera (how is the pivot point calculated/retrieved).
|
||||
};
|
||||
|
||||
inline void PivotCameraInput::SetPivotFn(PivotFn pivotFn)
|
||||
inline void OrbitCameraInput::SetPivotFn(PivotFn pivotFn)
|
||||
{
|
||||
m_pivotFn = AZStd::move(pivotFn);
|
||||
}
|
||||
|
||||
inline bool PivotCameraInput::Exclusive() const
|
||||
inline bool OrbitCameraInput::Exclusive() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Callback to use for FocusCameraInput when a free look camera is being used.
|
||||
//! @note This is when offset is zero.
|
||||
inline AZ::Vector3 FocusLook(float)
|
||||
{
|
||||
return AZ::Vector3::CreateZero();
|
||||
}
|
||||
|
||||
//! Callback to use for FocusCameraInput when a orbit camera is being used.
|
||||
//! @note This is when offset is non zero.
|
||||
inline AZ::Vector3 FocusOrbit(const float length)
|
||||
{
|
||||
return AZ::Vector3::CreateAxisY(-length);
|
||||
}
|
||||
|
||||
using FocusOffsetFn = AZStd::function<AZ::Vector3(float)>;
|
||||
|
||||
//! A focus behavior to align the camera view to the position returned by the pivot function.
|
||||
//! @note This only alters the camera orientation, the translation is unaffected.
|
||||
class FocusCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
using PivotFn = AZStd::function<AZ::Vector3()>;
|
||||
|
||||
FocusCameraInput(const InputChannelId& focusChannelId, FocusOffsetFn offsetFn);
|
||||
|
||||
// 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;
|
||||
|
||||
//! Override the default behavior for how a pivot point is calculated.
|
||||
void SetPivotFn(PivotFn pivotFn);
|
||||
|
||||
void SetFocusInputChannelId(const InputChannelId& focusChannelId);
|
||||
|
||||
private:
|
||||
InputChannelId m_focusChannelId; //!< Input channel to begin the focus camera input.
|
||||
Camera m_nextCamera;
|
||||
PivotFn m_pivotFn;
|
||||
FocusOffsetFn m_offsetFn;
|
||||
};
|
||||
|
||||
//! Provides a CameraInput type that can be implemented without needing to create a new type deriving from CameraInput.
|
||||
//! This can be very useful for specific use cases that are less generally applicable.
|
||||
class CustomCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
// 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;
|
||||
|
||||
//! HandleEvents delegates directly to m_handleEventsFn.
|
||||
AZStd::function<bool(CameraInput&, const InputEvent&, const ScreenVector&, float)> m_handleEventsFn;
|
||||
//! StepCamera delegates directly to m_stepCameraFn.
|
||||
AZStd::function<Camera(CameraInput&, const Camera&, const ScreenVector&, float, float)> m_stepCameraFn;
|
||||
};
|
||||
|
||||
//! Map from a generic InputChannel event to a camera specific InputEvent.
|
||||
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize);
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -167,6 +167,10 @@ set(FILES
|
||||
Logging/MissingAssetLogger.cpp
|
||||
Logging/MissingAssetLogger.h
|
||||
Logging/MissingAssetNotificationBus.h
|
||||
Matchmaking/IMatchmakingRequests.h
|
||||
Matchmaking/MatchmakingRequests.cpp
|
||||
Matchmaking/MatchmakingRequests.h
|
||||
Matchmaking/MatchmakingNotifications.h
|
||||
Scene/Scene.h
|
||||
Scene/Scene.inl
|
||||
Scene/Scene.cpp
|
||||
@@ -181,8 +185,9 @@ set(FILES
|
||||
Script/ScriptRemoteDebugging.cpp
|
||||
Script/ScriptRemoteDebugging.h
|
||||
Session/ISessionHandlingRequests.h
|
||||
Session/ISessionRequests.cpp
|
||||
Session/ISessionRequests.h
|
||||
Session/SessionRequests.cpp
|
||||
Session/SessionRequests.h
|
||||
Session/SessionConfig.cpp
|
||||
Session/SessionConfig.h
|
||||
Session/SessionNotifications.h
|
||||
|
||||
Reference in New Issue
Block a user