Merge branch 'main' into non-uniform-scale-visibility
This commit is contained in:
@@ -82,9 +82,6 @@
|
||||
|
||||
static const char* s_azFrameworkWarningWindow = "AzFramework";
|
||||
|
||||
static const char* s_engineConfigFileName = "engine.json";
|
||||
static const char* s_engineConfigEngineVersionKey = "LumberyardVersion";
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
namespace ApplicationInternal
|
||||
@@ -264,24 +261,8 @@ namespace AzFramework
|
||||
|
||||
void Application::PreModuleLoad()
|
||||
{
|
||||
// Calculate the engine root by reading the engine.json file
|
||||
AZStd::string engineJsonPath = AZStd::string_view{ m_engineRoot };
|
||||
engineJsonPath += s_engineConfigFileName;
|
||||
AzFramework::StringFunc::Path::Normalize(engineJsonPath);
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
auto readJsonResult = AzFramework::FileFunc::ReadJsonFile(engineJsonPath, &localFileIO);
|
||||
|
||||
if (readJsonResult.IsSuccess())
|
||||
{
|
||||
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
|
||||
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is any problem reading the engine.json file, then default to engine root to the app root
|
||||
AZ_Warning(s_azFrameworkWarningWindow, false, "Unable to read engine.json file '%s' (%s). Defaulting the engine root to '%s'", engineJsonPath.c_str(), readJsonResult.GetError().c_str(), m_appRoot.c_str());
|
||||
SetRootPath(RootPathType::EngineRoot, m_appRoot.c_str());
|
||||
}
|
||||
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
|
||||
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -504,13 +485,13 @@ namespace AzFramework
|
||||
|
||||
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
|
||||
{
|
||||
AZStd::string fullPath = AZStd::string(m_engineRoot) + AZStd::string(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING) + engineRelativePath;
|
||||
engineRelativePath = fullPath;
|
||||
AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
|
||||
engineRelativePath = fullPath.String();
|
||||
}
|
||||
|
||||
void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const
|
||||
{
|
||||
AzFramework::StringFunc::AssetPath::CalculateBranchToken(AZStd::string(m_engineRoot), token);
|
||||
AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -648,37 +629,21 @@ namespace AzFramework
|
||||
|
||||
void Application::SetRootPath(RootPathType type, const char* source)
|
||||
{
|
||||
size_t sourceLen = strlen(source);
|
||||
|
||||
constexpr AZStd::string_view pathSeparators{ AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR };
|
||||
// Determine if we need to append a trailing path separator
|
||||
bool appendTrailingPathSep = sourceLen > 0 && pathSeparators.find_first_of(source[sourceLen - 1]) == AZStd::string_view::npos;
|
||||
const size_t sourceLen = strlen(source);
|
||||
|
||||
// Copy the source path to the intended root path and correct the path separators as well
|
||||
switch (type)
|
||||
{
|
||||
case RootPathType::AppRoot:
|
||||
{
|
||||
AZ_Assert(sourceLen < m_appRoot.max_size(), "String overflow for App Root: %s", source);
|
||||
m_appRoot = source;
|
||||
|
||||
AZStd::replace(std::begin(m_appRoot), std::end(m_appRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
if (appendTrailingPathSep)
|
||||
{
|
||||
m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
}
|
||||
AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source);
|
||||
m_appRoot = AZ::IO::PathView(source).LexicallyNormal();
|
||||
}
|
||||
break;
|
||||
case RootPathType::EngineRoot:
|
||||
{
|
||||
AZ_Assert(sourceLen < m_engineRoot.max_size(), "String overflow for Engine Root: %s", source);
|
||||
m_engineRoot = source;
|
||||
|
||||
AZStd::replace(std::begin(m_engineRoot), std::end(m_engineRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
if (appendTrailingPathSep)
|
||||
{
|
||||
m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
}
|
||||
AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source);
|
||||
m_engineRoot = AZ::IO::PathView(source).LexicallyNormal();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1188,8 +1188,8 @@ namespace AZ::IO
|
||||
if (az_archive_verbosity)
|
||||
{
|
||||
char fileNameBuffer[AZ_MAX_PATH_LEN];
|
||||
const char* fileName = AZ::IO::FileIOBase::GetDirectInstance()->GetFilename(fileHandle, fileNameBuffer, AZ_ARRAY_SIZE(fileNameBuffer))
|
||||
? fileNameBuffer : "unknown";
|
||||
[[maybe_unused]] const char* fileName = AZ::IO::FileIOBase::GetDirectInstance()->GetFilename(fileHandle, fileNameBuffer,
|
||||
AZ_ARRAY_SIZE(fileNameBuffer)) ? fileNameBuffer : "unknown";
|
||||
AZ_TracePrintf("Archive", R"(Perf Warning: First call to read file "%s" made from multiple threads concurrently)" "\n",
|
||||
fileName);
|
||||
}
|
||||
@@ -1914,7 +1914,6 @@ namespace AZ::IO
|
||||
AZ::IO::StackString pathStr{ szPathIn };
|
||||
// Determine if there is a period ('.') after the last slash to determine if the path contains a file.
|
||||
// This used to be a strchr on the whole path which could contain a period in a path, such as network domain paths (domain.user).
|
||||
bool bPathContainsFile = false;
|
||||
size_t findDotFromPos = pathStr.rfind(AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
if (findDotFromPos == AZ::IO::StackString::npos)
|
||||
{
|
||||
@@ -2046,7 +2045,6 @@ namespace AZ::IO
|
||||
|
||||
uint8_t pMem[dwChunkSize];
|
||||
|
||||
uint32_t dwSize = 0;
|
||||
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (!fileIO)
|
||||
@@ -2453,11 +2451,13 @@ namespace AZ::IO
|
||||
ArchiveLocationPriority Archive::GetPakPriority() const
|
||||
{
|
||||
int pakPriority = aznumeric_cast<int>(ArchiveVars{}.nPriority);
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
|
||||
{
|
||||
AZ::GetValueResult getCvarResult = console->GetCvarValue("sys_PakPriority", pakPriority);
|
||||
AZ_Error("Archive", getCvarResult == AZ::GetValueResult::Success, "Lookup of 'sys_PakPriority console variable failed with error %s", AZ::GetEnumString(getCvarResult));
|
||||
}
|
||||
#endif
|
||||
return static_cast<ArchiveLocationPriority>(pakPriority);
|
||||
}
|
||||
|
||||
@@ -2580,10 +2580,6 @@ namespace AZ::IO
|
||||
return static_cast<EStreamSourceMediaType>(0);
|
||||
}
|
||||
|
||||
ZipDir::CachePtr pZip;
|
||||
uint32_t archFlags;
|
||||
ZipDir::FileEntry* pFileEntry = FindPakFileEntry(szFullPath->Native(), archFlags, &pZip, false);
|
||||
|
||||
enum StreamMediaType : int32_t
|
||||
{
|
||||
TypeUnknown = 0,
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AZ::IO::Internal
|
||||
static bool IsIgnored(const char* szPath);
|
||||
|
||||
// Do not report missing LOD files if no CGF files depend on them
|
||||
// Do not report missing .cgfm files since they're not actually created and used in Lumberyard
|
||||
// Do not report missing .cgfm files since they're not actually created and used in Open 3D Engine
|
||||
// This checking prevents our missing dependency scanner from having a lot of false positives on these files
|
||||
static bool IgnoreCGFDependencies(const char* szPath);
|
||||
|
||||
|
||||
@@ -831,7 +831,7 @@ namespace AZ::IO::ZipDir
|
||||
//arrFiles.SortByFileOffset();
|
||||
size_t nSizeCDR = arrFiles.GetStats().nSizeCDR;
|
||||
void* pCDR = m_allocator->Allocate(nSizeCDR, alignof(uint8_t), 0, "Cache::WriteCDR");
|
||||
size_t nSizeCDRSerialized = arrFiles.MakeZipCDR(m_lCDROffset, pCDR);
|
||||
[[maybe_unused]] size_t nSizeCDRSerialized = arrFiles.MakeZipCDR(m_lCDROffset, pCDR);
|
||||
AZ_Assert(nSizeCDRSerialized == nSizeCDR, "Serialized CDR size %zu does not match size in memory %zu", nSizeCDRSerialized, nSizeCDR);
|
||||
if (m_encryptedHeaders == ZipFile::HEADERS_ENCRYPTED_TEA)
|
||||
{
|
||||
|
||||
@@ -343,7 +343,6 @@ namespace AZ::IO::ZipDir
|
||||
{
|
||||
AZ::IO::HandleType realFileHandle = m_fileHandle;
|
||||
size_t nFileSize = ~0;
|
||||
int64_t offset = 0;
|
||||
|
||||
AZ::u64 fileSize = 0;
|
||||
if (!m_fileIOBase->Size(realFileHandle, fileSize))
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace AZ
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
// Class to describe metadata about an AssetBundle in Lumberyard
|
||||
// Class to describe metadata about an AssetBundle in Open 3D Engine
|
||||
class AssetBundleManifest
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -617,9 +617,9 @@ namespace AzFramework
|
||||
// won't free the mutex until the load is complete.
|
||||
// So instead, queue the notification until the next tick, so that it doesn't occur within the AssetCatalogRequestBus mutex, and also
|
||||
// so that the entire AssetCatalog initialization is complete.
|
||||
AZ::TickBus::QueueFunction([catalogRegistryFile]()
|
||||
AZ::TickBus::QueueFunction([catalogRegistryString = AZStd::string(catalogRegistryFile)]()
|
||||
{
|
||||
AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryFile);
|
||||
AssetCatalogEventBus::Broadcast(&AssetCatalogEventBus::Events::OnCatalogLoaded, catalogRegistryString.c_str());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,7 +1014,6 @@ namespace AzFramework
|
||||
behaviorContext->Constant("EditorTransformComponentTypeId", BehaviorConstant(AZ::EditorTransformComponentTypeId));
|
||||
|
||||
behaviorContext->Class<AZ::TransformConfig>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &AZ::TransformConfigConstructor)
|
||||
->Enum<(int)AZ::TransformConfig::ParentActivationTransformMode::MaintainOriginalRelativeTransform>("MaintainOriginalRelativeTransform")
|
||||
->Enum<(int)AZ::TransformConfig::ParentActivationTransformMode::MaintainCurrentWorldTransform>("MaintainCurrentWorldTransform")
|
||||
|
||||
@@ -167,8 +167,6 @@ namespace AzFramework
|
||||
|
||||
for (auto && bound : m_bounds)
|
||||
{
|
||||
bool satisfies = false;
|
||||
|
||||
if (bound.m_comparison == Comp::TwiddleWakka)
|
||||
{
|
||||
// Lower bound
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace AzFramework
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<BehaviorComponentId>("ComponentId")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Constructor()
|
||||
->Method("IsValid", &BehaviorComponentId::IsValid)
|
||||
@@ -136,7 +135,6 @@ namespace AzFramework
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<BehaviorEntity>("Entity")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &Internal::BehaviorEntityScriptConstructor)
|
||||
->Constructor()
|
||||
|
||||
@@ -597,9 +597,9 @@ namespace AZ
|
||||
{
|
||||
// here we are making sure that the buffer being passed in has enough space to include the alias in it.
|
||||
// we are trying to find the LONGEST match, meaning of the following two examples, the second should 'win'
|
||||
// File: g:/lumberyard/dev/files/morefiles/blah.xml
|
||||
// Alias1 links to 'g:/lumberyard/dev/'
|
||||
// Alias2 links to 'g:/lumberyard/dev/files/morefiles'
|
||||
// File: g:/O3DE/dev/files/morefiles/blah.xml
|
||||
// Alias1 links to 'g:/O3DE/dev/'
|
||||
// Alias2 links to 'g:/O3DE/dev/files/morefiles'
|
||||
// so returning Alias2 is preferred as it is more specific, even though alias1 includes it.
|
||||
// note that its not possible for this to be matched if the string is shorter than the length of the alias itself so we skip
|
||||
// strings that are shorter than the alias's mapped path without checking.
|
||||
|
||||
@@ -643,8 +643,6 @@ namespace AZ
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
bool bSourceExcluded = false;
|
||||
bool bDestinationExcluded = false;
|
||||
|
||||
//else both are remote so just issue the remote copy command
|
||||
AzFramework::AssetSystem::FileCopyRequest request(sourceFilePath, destinationFilePath);
|
||||
@@ -697,8 +695,6 @@ namespace AZ
|
||||
}
|
||||
|
||||
//we are going to access shared memory so lock and copy the results into our memory
|
||||
bool bSourceExcluded = false;
|
||||
bool bDestinationExcluded = false;
|
||||
|
||||
//if the source and destination are the same, shortcut
|
||||
if (!strcmp(sourceFilePath, destinationFilePath))
|
||||
|
||||
@@ -126,19 +126,22 @@ namespace AzFramework
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
|
||||
else
|
||||
{
|
||||
FlushCache(args.m_path);
|
||||
if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
|
||||
{
|
||||
FlushCache(args.m_path);
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
|
||||
{
|
||||
FlushEntireCache();
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
|
||||
{
|
||||
Report(args);
|
||||
}
|
||||
StreamStackEntry::QueueRequest(request);
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
|
||||
{
|
||||
FlushEntireCache();
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
|
||||
{
|
||||
Report(args);
|
||||
}
|
||||
StreamStackEntry::QueueRequest(request);
|
||||
}, request->GetCommand());
|
||||
}
|
||||
|
||||
|
||||
@@ -130,13 +130,11 @@ namespace AzFramework
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<InputSystemNotificationBus>("InputSystemNotificationBus")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Input")
|
||||
->Handler<InputSystemNotificationBusBehaviorHandler>()
|
||||
;
|
||||
|
||||
behaviorContext->EBus<InputSystemRequestBus>("InputSystemRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Input")
|
||||
->Event("RecreateEnabledInputDevices", &InputSystemRequestBus::Events::RecreateEnabledInputDevices)
|
||||
;
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace AzFramework
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->EBus<NetBindingHandlerBus>("NetBindingHandlerBus")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::Preview)
|
||||
->Event("IsEntityBoundToNetwork", &NetBindingHandlerBus::Events::IsEntityBoundToNetwork)
|
||||
->Event("IsEntityAuthoritative", &NetBindingHandlerBus::Events::IsEntityAuthoritative)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Physics
|
||||
behaviorContext->EBus<Physics::CollisionFilteringRequestBus>("CollisionFilteringBus")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::Preview)
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Event("SetCollisionLayer", &Physics::CollisionFilteringRequestBus::Events::SetCollisionLayer)
|
||||
->Event("GetCollisionLayerName", &Physics::CollisionFilteringRequestBus::Events::GetCollisionLayerName)
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace Physics
|
||||
MaterialId m_id;
|
||||
};
|
||||
|
||||
/// An asset that holds a list of materials to be edited and assigned in Lumberyard Editor
|
||||
/// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor
|
||||
/// ======================================================================================
|
||||
///
|
||||
/// Use Asset Editor to create a MaterialLibraryAsset and add materials to it.\n
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ShapeConfiguration;
|
||||
class World;
|
||||
class Shape;
|
||||
|
||||
/// Default values used for initializing RigidBodySettings.
|
||||
/// These can be modified by Physics Implementation gems. // O3DE_DEPRECATED(LY-114472) - DefaultRigidBodyConfiguration values are not shared across modules.
|
||||
// Use RigidBodyConfiguration default values.
|
||||
struct DefaultRigidBodyConfiguration
|
||||
{
|
||||
static float m_mass;
|
||||
static bool m_computeInertiaTensor;
|
||||
static float m_linearDamping;
|
||||
static float m_angularDamping;
|
||||
static float m_sleepMinEnergy;
|
||||
static float m_maxAngularVelocity;
|
||||
};
|
||||
|
||||
enum class MassComputeFlags : AZ::u8
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
//! Flags indicating whether a certain mass property should be auto-computed or not.
|
||||
COMPUTE_MASS = 1,
|
||||
COMPUTE_INERTIA = 1 << 1,
|
||||
COMPUTE_COM = 1 << 2,
|
||||
|
||||
//! If set, non-simulated shapes will also be included in the mass properties calculation.
|
||||
INCLUDE_ALL_SHAPES = 1 << 3,
|
||||
|
||||
DEFAULT = COMPUTE_COM | COMPUTE_INERTIA | COMPUTE_MASS
|
||||
};
|
||||
|
||||
class RigidBodyConfiguration
|
||||
: public WorldBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RigidBodyConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBodyConfiguration, "{ACFA8900-8530-4744-AF00-AA533C868A8E}", WorldBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
enum PropertyVisibility : AZ::u16
|
||||
{
|
||||
InitialVelocities = 1 << 0, ///< Whether the initial linear and angular velocities are visible.
|
||||
InertiaProperties = 1 << 1, ///< Whether the whole category of inertia properties (mass, compute inertia,
|
||||
///< inertia tensor etc) is visible.
|
||||
Damping = 1 << 2, ///< Whether linear and angular damping are visible.
|
||||
SleepOptions = 1 << 3, ///< Whether the sleep threshold and start asleep options are visible.
|
||||
Interpolation = 1 << 4, ///< Whether the interpolation option is visible.
|
||||
Gravity = 1 << 5, ///< Whether the effected by gravity option is visible.
|
||||
Kinematic = 1 << 6, ///< Whether the option to make the body kinematic is visible.
|
||||
ContinuousCollisionDetection = 1 << 7, ///< Whether the option to enable continuous collision detection is visible.
|
||||
MaxVelocities = 1 << 8 ///< Whether upper limits on velocities are visible.
|
||||
};
|
||||
|
||||
RigidBodyConfiguration() = default;
|
||||
RigidBodyConfiguration(const RigidBodyConfiguration& settings) = default;
|
||||
|
||||
// Visibility functions.
|
||||
AZ::Crc32 GetPropertyVisibility(PropertyVisibility property) const;
|
||||
void SetPropertyVisibility(PropertyVisibility property, bool isVisible);
|
||||
|
||||
AZ::Crc32 GetInitialVelocitiesVisibility() const;
|
||||
/// Returns whether the whole category of inertia settings (mass, inertia, center of mass offset etc) is visible.
|
||||
AZ::Crc32 GetInertiaSettingsVisibility() const;
|
||||
/// Returns whether the individual inertia tensor field is visible or is hidden because the compute inertia option is selected.
|
||||
AZ::Crc32 GetInertiaVisibility() const;
|
||||
/// Returns whether the mass field is visible or is hidden because compute mass option is selected.
|
||||
AZ::Crc32 GetMassVisibility() const;
|
||||
/// Returns whether the individual centre of mass offset field is visible or is hidden because compute CoM option is selected.
|
||||
AZ::Crc32 GetCoMVisibility() const;
|
||||
AZ::Crc32 GetDampingVisibility() const;
|
||||
AZ::Crc32 GetSleepOptionsVisibility() const;
|
||||
AZ::Crc32 GetInterpolationVisibility() const;
|
||||
AZ::Crc32 GetGravityVisibility() const;
|
||||
AZ::Crc32 GetKinematicVisibility() const;
|
||||
AZ::Crc32 GetCCDVisibility() const;
|
||||
AZ::Crc32 GetMaxVelocitiesVisibility() const;
|
||||
MassComputeFlags GetMassComputeFlags() const;
|
||||
void SetMassComputeFlags(MassComputeFlags flags);
|
||||
|
||||
bool IsCCDEnabled() const;
|
||||
|
||||
// Basic initial settings.
|
||||
AZ::Vector3 m_initialLinearVelocity = AZ::Vector3::CreateZero();
|
||||
AZ::Vector3 m_initialAngularVelocity = AZ::Vector3::CreateZero();
|
||||
AZ::Vector3 m_centerOfMassOffset = AZ::Vector3::CreateZero();
|
||||
|
||||
// Simulation parameters.
|
||||
float m_mass = DefaultRigidBodyConfiguration::m_mass;
|
||||
AZ::Matrix3x3 m_inertiaTensor = AZ::Matrix3x3::CreateIdentity();
|
||||
float m_linearDamping = DefaultRigidBodyConfiguration::m_linearDamping;
|
||||
float m_angularDamping = DefaultRigidBodyConfiguration::m_angularDamping;
|
||||
float m_sleepMinEnergy = DefaultRigidBodyConfiguration::m_sleepMinEnergy;
|
||||
float m_maxAngularVelocity = DefaultRigidBodyConfiguration::m_maxAngularVelocity;
|
||||
|
||||
// Visibility settings.
|
||||
AZ::u16 m_propertyVisibilityFlags = (std::numeric_limits<AZ::u16>::max)();
|
||||
|
||||
bool m_startAsleep = false;
|
||||
bool m_interpolateMotion = false;
|
||||
bool m_gravityEnabled = true;
|
||||
bool m_simulated = true;
|
||||
bool m_kinematic = false;
|
||||
bool m_ccdEnabled = false; ///< Whether continuous collision detection is enabled.
|
||||
float m_ccdMinAdvanceCoefficient = 0.15f; ///< Coefficient affecting how granularly time is subdivided in CCD.
|
||||
bool m_ccdFrictionEnabled = false; ///< Whether friction is applied when resolving CCD collisions.
|
||||
|
||||
bool m_computeCenterOfMass = true;
|
||||
bool m_computeInertiaTensor = true;
|
||||
bool m_computeMass = true;
|
||||
|
||||
//! If set, non-simulated shapes will also be included in the mass properties calculation.
|
||||
bool m_includeAllShapesInMassCalculation = false;
|
||||
};
|
||||
|
||||
/// Dynamic rigid body.
|
||||
class RigidBody
|
||||
: public WorldBody
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(RigidBody, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBody, "{156E459F-7BB7-4B4E-ADA0-2130D96B7E80}", WorldBody);
|
||||
|
||||
public:
|
||||
RigidBody() = default;
|
||||
explicit RigidBody(const RigidBodyConfiguration& settings);
|
||||
|
||||
|
||||
virtual void AddShape(AZStd::shared_ptr<Shape> shape) = 0;
|
||||
virtual void RemoveShape(AZStd::shared_ptr<Shape> shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Shape> GetShape(AZ::u32 /*index*/) { return nullptr; }
|
||||
|
||||
virtual AZ::Vector3 GetCenterOfMassWorld() const = 0;
|
||||
virtual AZ::Vector3 GetCenterOfMassLocal() const = 0;
|
||||
|
||||
virtual AZ::Matrix3x3 GetInverseInertiaWorld() const = 0;
|
||||
virtual AZ::Matrix3x3 GetInverseInertiaLocal() const = 0;
|
||||
|
||||
virtual float GetMass() const = 0;
|
||||
virtual float GetInverseMass() const = 0;
|
||||
virtual void SetMass(float mass) = 0;
|
||||
virtual void SetCenterOfMassOffset(const AZ::Vector3& comOffset) = 0;
|
||||
|
||||
/// Retrieves the velocity at center of mass; only linear velocity, no rotational velocity contribution.
|
||||
virtual AZ::Vector3 GetLinearVelocity() const = 0;
|
||||
virtual void SetLinearVelocity(const AZ::Vector3& velocity) = 0;
|
||||
virtual AZ::Vector3 GetAngularVelocity() const = 0;
|
||||
virtual void SetAngularVelocity(const AZ::Vector3& angularVelocity) = 0;
|
||||
virtual AZ::Vector3 GetLinearVelocityAtWorldPoint(const AZ::Vector3& worldPoint) = 0;
|
||||
virtual void ApplyLinearImpulse(const AZ::Vector3& impulse) = 0;
|
||||
virtual void ApplyLinearImpulseAtWorldPoint(const AZ::Vector3& impulse, const AZ::Vector3& worldPoint) = 0;
|
||||
virtual void ApplyAngularImpulse(const AZ::Vector3& angularImpulse) = 0;
|
||||
|
||||
virtual float GetLinearDamping() const = 0;
|
||||
virtual void SetLinearDamping(float damping) = 0;
|
||||
virtual float GetAngularDamping() const = 0;
|
||||
virtual void SetAngularDamping(float damping) = 0;
|
||||
|
||||
virtual bool IsAwake() const = 0;
|
||||
virtual void ForceAsleep() = 0;
|
||||
virtual void ForceAwake() = 0;
|
||||
virtual float GetSleepThreshold() const = 0;
|
||||
virtual void SetSleepThreshold(float threshold) = 0;
|
||||
|
||||
virtual bool IsKinematic() const = 0;
|
||||
virtual void SetKinematic(bool kinematic) = 0;
|
||||
virtual void SetKinematicTarget(const AZ::Transform& targetPosition) = 0;
|
||||
|
||||
virtual bool IsGravityEnabled() const = 0;
|
||||
virtual void SetGravityEnabled(bool enabled) = 0;
|
||||
virtual void SetSimulationEnabled(bool enabled) = 0;
|
||||
virtual void SetCCDEnabled(bool enabled) = 0;
|
||||
|
||||
//! Recalculates mass, inertia and center of mass based on the flags passed.
|
||||
//! @param flags MassComputeFlags specifying which properties should be recomputed.
|
||||
//! @param centerOfMassOffsetOverride Optional override of the center of mass. Note: This parameter will be ignored if COMPUTE_COM is passed in flags.
|
||||
//! @param inertiaTensorOverride Optional override of the inertia. Note: This parameter will be ignored if COMPUTE_INERTIA is passed in flags.
|
||||
//! @param massOverride Optional override of the mass. Note: This parameter will be ignored if COMPUTE_MASS is passed in flags.
|
||||
virtual void UpdateMassProperties(MassComputeFlags flags = MassComputeFlags::DEFAULT,
|
||||
const AZ::Vector3* centerOfMassOffsetOverride = nullptr,
|
||||
const AZ::Matrix3x3* inertiaTensorOverride = nullptr,
|
||||
const float* massOverride = nullptr) = 0;
|
||||
};
|
||||
|
||||
/// Bitwise operators for MassComputeFlags
|
||||
inline MassComputeFlags operator|(MassComputeFlags lhs, MassComputeFlags rhs)
|
||||
{
|
||||
return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) | aznumeric_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
inline MassComputeFlags operator&(MassComputeFlags lhs, MassComputeFlags rhs)
|
||||
{
|
||||
return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) & aznumeric_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
/// Static rigid body.
|
||||
class RigidBodyStatic
|
||||
: public WorldBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RigidBodyStatic, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBodyStatic, "{13A677BB-7085-4EDB-BCC8-306548238692}", WorldBody);
|
||||
|
||||
virtual void AddShape(const AZStd::shared_ptr<Shape>& shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Shape> GetShape(AZ::u32 /*index*/) { return nullptr; }
|
||||
};
|
||||
} // namespace Physics
|
||||
@@ -93,9 +93,9 @@ namespace AzFramework
|
||||
"DataSet31","DataSet32"
|
||||
};
|
||||
|
||||
if (s_chunkIndex > AZ_ARRAY_SIZE(s_nameArray) && AZ_ARRAY_SIZE(s_nameArray) >= 0)
|
||||
if ((s_chunkIndex >= AZ_ARRAY_SIZE(s_nameArray)) && (AZ_ARRAY_SIZE(s_nameArray) >= 0))
|
||||
{
|
||||
s_chunkIndex = s_chunkIndex%AZ_ARRAY_SIZE(s_nameArray);
|
||||
s_chunkIndex = s_chunkIndex % AZ_ARRAY_SIZE(s_nameArray);
|
||||
}
|
||||
|
||||
return s_nameArray[s_chunkIndex++];
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CameraInput.h"
|
||||
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Math/Plane.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void CameraSystem::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& cursor_motion = AZStd::get_if<CursorMotionEvent>(&event))
|
||||
{
|
||||
m_currentCursorPosition = cursor_motion->m_position;
|
||||
}
|
||||
else if (const auto& scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
m_scrollDelta = scroll->m_delta;
|
||||
}
|
||||
|
||||
m_cameras.HandleEvents(event);
|
||||
}
|
||||
|
||||
Camera CameraSystem::StepCamera(const Camera& targetCamera, float deltaTime)
|
||||
{
|
||||
const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value()
|
||||
? m_currentCursorPosition.value() - m_lastCursorPosition.value()
|
||||
: ScreenVector(0, 0);
|
||||
|
||||
if (m_currentCursorPosition.has_value())
|
||||
{
|
||||
m_lastCursorPosition = m_currentCursorPosition;
|
||||
}
|
||||
|
||||
const auto nextCamera = m_cameras.StepCamera(targetCamera, cursorDelta, m_scrollDelta, deltaTime);
|
||||
|
||||
m_scrollDelta = 0.0f;
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void Cameras::AddCamera(AZStd::shared_ptr<CameraInput> camera_input)
|
||||
{
|
||||
m_idleCameraInputs.push_back(AZStd::move(camera_input));
|
||||
}
|
||||
|
||||
void Cameras::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
for (auto& camera_input : m_activeCameraInputs)
|
||||
{
|
||||
camera_input->HandleEvents(event);
|
||||
}
|
||||
|
||||
for (auto& camera_input : m_idleCameraInputs)
|
||||
{
|
||||
camera_input->HandleEvents(event);
|
||||
}
|
||||
}
|
||||
|
||||
Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime)
|
||||
{
|
||||
for (int i = 0; i < m_idleCameraInputs.size();)
|
||||
{
|
||||
auto& camera_input = m_idleCameraInputs[i];
|
||||
const bool can_begin = camera_input->Beginning() &&
|
||||
std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
|
||||
[](const auto& input) { return !input->Exclusive(); }) &&
|
||||
(!camera_input->Exclusive() || (camera_input->Exclusive() && m_activeCameraInputs.empty()));
|
||||
if (can_begin)
|
||||
{
|
||||
m_activeCameraInputs.push_back(camera_input);
|
||||
using AZStd::swap;
|
||||
swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]);
|
||||
m_idleCameraInputs.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// accumulate
|
||||
Camera nextCamera = targetCamera;
|
||||
for (auto& camera_input : m_activeCameraInputs)
|
||||
{
|
||||
nextCamera = camera_input->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_activeCameraInputs.size();)
|
||||
{
|
||||
auto& camera_input = m_activeCameraInputs[i];
|
||||
if (camera_input->Ending())
|
||||
{
|
||||
camera_input->ClearActivation();
|
||||
m_idleCameraInputs.push_back(camera_input);
|
||||
using AZStd::swap;
|
||||
swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
|
||||
m_activeCameraInputs.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
camera_input->ContinueActivation();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void Cameras::Reset()
|
||||
{
|
||||
for (int i = 0; i < m_activeCameraInputs.size();)
|
||||
{
|
||||
m_activeCameraInputs[i]->Reset();
|
||||
m_idleCameraInputs.push_back(m_activeCameraInputs[i]);
|
||||
m_activeCameraInputs[i] = m_activeCameraInputs[m_activeCameraInputs.size() - 1];
|
||||
m_activeCameraInputs.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void RotateCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_channelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera RotateCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
nextCamera.m_pitch += float(cursorDelta.m_y) * m_props.m_rotateSpeed;
|
||||
nextCamera.m_yaw += float(cursorDelta.m_x) * m_props.m_rotateSpeed;
|
||||
|
||||
auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoOverPi, AZ::Constants::TwoOverPi); };
|
||||
|
||||
nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw);
|
||||
// clamp pitch to be +-90 degrees
|
||||
nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::Pi * 0.5f, AZ::Constants::Pi * 0.5f);
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void PanCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceMouse::Button::Middle)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera PanCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
const auto pan_axes = m_panAxesFn(nextCamera);
|
||||
|
||||
const auto delta_pan_x = float(cursorDelta.m_x) * pan_axes.m_horizontalAxis * m_props.m_panSpeed;
|
||||
const auto delta_pan_y = float(cursorDelta.m_y) * pan_axes.m_verticalAxis * m_props.m_panSpeed;
|
||||
|
||||
const auto inv = [](const bool invert) {
|
||||
constexpr float Dir[] = {1.0f, -1.0f};
|
||||
return Dir[static_cast<int>(invert)];
|
||||
};
|
||||
|
||||
nextCamera.m_lookAt += delta_pan_x * inv(m_props.m_panInvertX);
|
||||
nextCamera.m_lookAt += delta_pan_y * -inv(m_props.m_panInvertY);
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
TranslateCameraInput::TranslationType TranslateCameraInput::translationFromKey(InputChannelId channelId)
|
||||
{
|
||||
// note: remove hard-coded InputDevice keys
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericW)
|
||||
{
|
||||
return TranslationType::Forward;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericS)
|
||||
{
|
||||
return TranslationType::Backward;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericA)
|
||||
{
|
||||
return TranslationType::Left;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericD)
|
||||
{
|
||||
return TranslationType::Right;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericQ)
|
||||
{
|
||||
return TranslationType::Down;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericE)
|
||||
{
|
||||
return TranslationType::Up;
|
||||
}
|
||||
|
||||
return TranslationType::Nil;
|
||||
}
|
||||
|
||||
void TranslateCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Updated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_translation |= translationFromKey(input->m_channelId);
|
||||
if (m_translation != TranslationType::Nil)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
|
||||
{
|
||||
m_boost = true;
|
||||
}
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
m_translation ^= translationFromKey(input->m_channelId);
|
||||
if (m_translation == TranslationType::Nil)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
|
||||
{
|
||||
m_boost = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera TranslateCameraInput::StepCamera(
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
|
||||
const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
const auto translation_basis = m_translationAxesFn(nextCamera);
|
||||
const auto axisX = translation_basis.GetBasisX();
|
||||
const auto axisY = translation_basis.GetBasisY();
|
||||
const auto axisZ = translation_basis.GetBasisZ();
|
||||
|
||||
const float speed = [boost = m_boost, props = m_props]() {
|
||||
return props.m_translateSpeed * (boost ? props.m_boostMultiplier : 1.0f);
|
||||
}();
|
||||
|
||||
if ((m_translation & TranslationType::Forward) == TranslationType::Forward)
|
||||
{
|
||||
nextCamera.m_lookAt += axisY * speed * deltaTime;
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Backward) == TranslationType::Backward)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisY * speed * deltaTime;
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Left) == TranslationType::Left)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisX * speed * deltaTime;
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Right) == TranslationType::Right)
|
||||
{
|
||||
nextCamera.m_lookAt += axisX * speed * deltaTime;
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Up) == TranslationType::Up)
|
||||
{
|
||||
nextCamera.m_lookAt += axisZ * speed * deltaTime;
|
||||
}
|
||||
|
||||
if ((m_translation & TranslationType::Down) == TranslationType::Down)
|
||||
{
|
||||
nextCamera.m_lookAt -= axisZ * speed * deltaTime;
|
||||
}
|
||||
|
||||
if (Ending())
|
||||
{
|
||||
m_translation = TranslationType::Nil;
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void TranslateCameraInput::ResetImpl()
|
||||
{
|
||||
m_translation = TranslationType::Nil;
|
||||
m_boost = false;
|
||||
}
|
||||
|
||||
void OrbitCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierAltL)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Updated)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (Active())
|
||||
{
|
||||
m_orbitCameras.HandleEvents(event);
|
||||
}
|
||||
}
|
||||
|
||||
Camera OrbitCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
if (Beginning())
|
||||
{
|
||||
float hit_distance = 0.0f;
|
||||
if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateZero())
|
||||
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY() * m_props.m_maxOrbitDistance, hit_distance))
|
||||
{
|
||||
nextCamera.m_lookDist = -hit_distance;
|
||||
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * hit_distance;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextCamera.m_lookDist = -m_props.m_defaultOrbitDistance;
|
||||
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * m_props.m_defaultOrbitDistance;
|
||||
}
|
||||
}
|
||||
|
||||
if (Active())
|
||||
{
|
||||
// todo: need to return nested cameras to idle state when ending
|
||||
nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
if (Ending())
|
||||
{
|
||||
m_orbitCameras.Reset();
|
||||
|
||||
nextCamera.m_lookAt = nextCamera.Translation();
|
||||
nextCamera.m_lookDist = 0.0f;
|
||||
}
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitDollyScrollCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
}
|
||||
|
||||
Camera OrbitDollyScrollCameraInput::StepCamera(
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
|
||||
[[maybe_unused]] float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_props.m_dollySpeed, 0.0f);
|
||||
EndActivation();
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitDollyCursorMoveCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceMouse::Button::Right)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera OrbitDollyCursorMoveCameraInput::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_props.m_dollySpeed, 0.0f);
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void ScrollTranslationCameraInput::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
}
|
||||
|
||||
Camera ScrollTranslationCameraInput::StepCamera(
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
const auto translation_basis = LookTranslation(nextCamera);
|
||||
const auto axisY = translation_basis.GetBasisY();
|
||||
|
||||
nextCamera.m_lookAt += axisY * scrollDelta * m_props.m_translateSpeed;
|
||||
|
||||
EndActivation();
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, const float deltaTime)
|
||||
{
|
||||
const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
|
||||
// keep yaw in 0 - 360 range
|
||||
float target_yaw = clamp_rotation(targetCamera.m_yaw);
|
||||
const float current_yaw = clamp_rotation(currentCamera.m_yaw);
|
||||
|
||||
auto sign = [](const float value) { return static_cast<float>((0.0f < value) - (value < 0.0f)); };
|
||||
|
||||
// ensure smooth transition when moving across 0 - 360 boundary
|
||||
const float yaw_delta = target_yaw - current_yaw;
|
||||
if (std::abs(yaw_delta) >= AZ::Constants::Pi)
|
||||
{
|
||||
target_yaw -= AZ::Constants::TwoPi * sign(yaw_delta);
|
||||
}
|
||||
|
||||
Camera camera;
|
||||
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
|
||||
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
|
||||
const float lookRate = std::exp2(props.m_lookSmoothness);
|
||||
const float lookT = std::exp2(-lookRate * deltaTime);
|
||||
camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT);
|
||||
camera.m_yaw = AZ::Lerp(target_yaw, current_yaw, lookT);
|
||||
const float moveRate = std::exp2(props.m_moveSmoothness);
|
||||
const float moveT = std::exp2(-moveRate * deltaTime);
|
||||
camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT);
|
||||
camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveT);
|
||||
return camera;
|
||||
}
|
||||
|
||||
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize)
|
||||
{
|
||||
const auto& inputChannelId = inputChannel.GetInputChannelId();
|
||||
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
|
||||
|
||||
if (inputChannelId == InputDeviceMouse::SystemCursorPosition)
|
||||
{
|
||||
AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero();
|
||||
InputSystemCursorRequestBus::EventResult(
|
||||
systemCursorPositionNormalized, inputDeviceId, &InputSystemCursorRequestBus::Events::GetSystemCursorPositionNormalized);
|
||||
|
||||
return CursorMotionEvent{ScreenPoint(
|
||||
systemCursorPositionNormalized.GetX() * windowSize.m_width, systemCursorPositionNormalized.GetY() * windowSize.m_height)};
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
return ScrollEvent{inputChannel.GetValue()};
|
||||
}
|
||||
else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
|
||||
}
|
||||
|
||||
return AZStd::monostate{};
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzFramework/Input/Channels/InputChannel.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct WindowSize;
|
||||
|
||||
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};
|
||||
float m_pitch{0.0};
|
||||
float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
|
||||
|
||||
//! View camera transform (v in MVP).
|
||||
AZ::Transform View() const;
|
||||
//! World camera transform.
|
||||
AZ::Transform Transform() const;
|
||||
//! World rotation.
|
||||
AZ::Matrix3x3 Rotation() const;
|
||||
//! World translation.
|
||||
AZ::Vector3 Translation() const;
|
||||
};
|
||||
|
||||
inline AZ::Transform Camera::View() const
|
||||
{
|
||||
return Transform().GetInverse();
|
||||
}
|
||||
|
||||
inline AZ::Transform Camera::Transform() const
|
||||
{
|
||||
return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationX(m_pitch) *
|
||||
AZ::Transform::CreateRotationZ(m_yaw) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist));
|
||||
}
|
||||
|
||||
inline AZ::Matrix3x3 Camera::Rotation() const
|
||||
{
|
||||
return AZ::Matrix3x3::CreateFromQuaternion(Transform().GetRotation());
|
||||
}
|
||||
|
||||
inline AZ::Vector3 Camera::Translation() const
|
||||
{
|
||||
return Transform().GetTranslation();
|
||||
}
|
||||
|
||||
struct CursorMotionEvent
|
||||
{
|
||||
ScreenPoint m_position;
|
||||
};
|
||||
|
||||
struct ScrollEvent
|
||||
{
|
||||
float m_delta;
|
||||
};
|
||||
|
||||
struct DiscreteInputEvent
|
||||
{
|
||||
InputChannelId m_channelId; //!< Channel type. (e.g. Keyboard key, mouse button or other device input).
|
||||
InputChannel::State m_state; //!< Channel state. (e.g. Begin/update/end event).
|
||||
};
|
||||
|
||||
using InputEvent = AZStd::variant<AZStd::monostate, CursorMotionEvent, ScrollEvent, DiscreteInputEvent>;
|
||||
|
||||
class CameraInput
|
||||
{
|
||||
public:
|
||||
enum class Activation
|
||||
{
|
||||
Idle,
|
||||
Begin,
|
||||
Active,
|
||||
End
|
||||
};
|
||||
|
||||
virtual ~CameraInput() = default;
|
||||
|
||||
bool Beginning() const
|
||||
{
|
||||
return m_activation == Activation::Begin;
|
||||
}
|
||||
|
||||
bool Ending() const
|
||||
{
|
||||
return m_activation == Activation::End;
|
||||
}
|
||||
|
||||
bool Idle() const
|
||||
{
|
||||
return m_activation == Activation::Idle;
|
||||
}
|
||||
|
||||
bool Active() const
|
||||
{
|
||||
return m_activation == Activation::Active;
|
||||
}
|
||||
|
||||
void BeginActivation()
|
||||
{
|
||||
m_activation = Activation::Begin;
|
||||
}
|
||||
|
||||
void EndActivation()
|
||||
{
|
||||
m_activation = Activation::End;
|
||||
}
|
||||
|
||||
void ContinueActivation()
|
||||
{
|
||||
m_activation = Activation::Active;
|
||||
}
|
||||
|
||||
void ClearActivation()
|
||||
{
|
||||
m_activation = Activation::Idle;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ClearActivation();
|
||||
ResetImpl();
|
||||
}
|
||||
|
||||
virtual void HandleEvents(const InputEvent& event) = 0;
|
||||
virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0;
|
||||
|
||||
virtual bool Exclusive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void ResetImpl()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Activation m_activation = Activation::Idle;
|
||||
};
|
||||
|
||||
struct SmoothProps
|
||||
{
|
||||
float m_lookSmoothness = 5.0f;
|
||||
float m_moveSmoothness = 5.0f;
|
||||
};
|
||||
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, float deltaTime);
|
||||
|
||||
class Cameras
|
||||
{
|
||||
public:
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
void HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_activeCameraInputs;
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_idleCameraInputs;
|
||||
};
|
||||
|
||||
class CameraSystem
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, float deltaTime);
|
||||
|
||||
Cameras m_cameras;
|
||||
|
||||
private:
|
||||
float m_scrollDelta = 0.0f;
|
||||
AZStd::optional<ScreenPoint> m_lastCursorPosition;
|
||||
AZStd::optional<ScreenPoint> m_currentCursorPosition;
|
||||
};
|
||||
|
||||
class RotateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit RotateCameraInput(const InputChannelId channelId)
|
||||
: m_channelId(channelId)
|
||||
{
|
||||
}
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
InputChannelId m_channelId;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_rotateSpeed = 0.005f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
struct PanAxes
|
||||
{
|
||||
AZ::Vector3 m_horizontalAxis;
|
||||
AZ::Vector3 m_verticalAxis;
|
||||
};
|
||||
|
||||
using PanAxesFn = AZStd::function<PanAxes(const Camera& camera)>;
|
||||
|
||||
inline PanAxes LookPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
return {orientation.GetBasisX(), orientation.GetBasisZ()};
|
||||
}
|
||||
|
||||
inline PanAxes OrbitPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
const auto basisX = orientation.GetBasisX();
|
||||
const auto basisY = [&orientation] {
|
||||
const auto forward = orientation.GetBasisY();
|
||||
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
|
||||
}();
|
||||
|
||||
return {basisX, basisY};
|
||||
}
|
||||
|
||||
class PanCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit PanCameraInput(PanAxesFn panAxesFn)
|
||||
: m_panAxesFn(AZStd::move(panAxesFn))
|
||||
{
|
||||
}
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_panSpeed = 0.01f;
|
||||
bool m_panInvertX = true;
|
||||
bool m_panInvertY = true;
|
||||
} m_props;
|
||||
|
||||
private:
|
||||
PanAxesFn m_panAxesFn;
|
||||
};
|
||||
|
||||
using TranslationAxesFn = AZStd::function<AZ::Matrix3x3(const Camera& camera)>;
|
||||
|
||||
inline AZ::Matrix3x3 LookTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
const auto basisX = orientation.GetBasisX();
|
||||
const auto basisY = orientation.GetBasisY();
|
||||
const auto basisZ = AZ::Vector3::CreateAxisZ();
|
||||
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
const auto basisX = orientation.GetBasisX();
|
||||
const auto basisY = [&orientation] {
|
||||
const auto forward = orientation.GetBasisY();
|
||||
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
|
||||
}();
|
||||
const auto basisZ = AZ::Vector3::CreateAxisZ();
|
||||
|
||||
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
|
||||
}
|
||||
|
||||
class TranslateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit TranslateCameraInput(TranslationAxesFn translationAxesFn)
|
||||
: m_translationAxesFn(AZStd::move(translationAxesFn))
|
||||
{
|
||||
}
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
void ResetImpl() override;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_translateSpeed = 10.0f;
|
||||
float m_boostMultiplier = 3.0f;
|
||||
} m_props;
|
||||
|
||||
private:
|
||||
enum class TranslationType
|
||||
{
|
||||
// clang-format off
|
||||
Nil = 0,
|
||||
Forward = 1 << 0,
|
||||
Backward = 1 << 1,
|
||||
Left = 1 << 2,
|
||||
Right = 1 << 3,
|
||||
Up = 1 << 4,
|
||||
Down = 1 << 5,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
friend TranslationType operator|(const TranslationType lhs, const TranslationType rhs)
|
||||
{
|
||||
return static_cast<TranslationType>(
|
||||
static_cast<std::underlying_type_t<TranslationType>>(lhs) | static_cast<std::underlying_type_t<TranslationType>>(rhs));
|
||||
}
|
||||
|
||||
friend TranslationType& operator|=(TranslationType& lhs, const TranslationType rhs)
|
||||
{
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend TranslationType operator^(const TranslationType lhs, const TranslationType rhs)
|
||||
{
|
||||
return static_cast<TranslationType>(
|
||||
static_cast<std::underlying_type_t<TranslationType>>(lhs) ^ static_cast<std::underlying_type_t<TranslationType>>(rhs));
|
||||
}
|
||||
|
||||
friend TranslationType& operator^=(TranslationType& lhs, const TranslationType rhs)
|
||||
{
|
||||
lhs = lhs ^ rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend TranslationType operator&(const TranslationType lhs, const TranslationType rhs)
|
||||
{
|
||||
return static_cast<TranslationType>(
|
||||
static_cast<std::underlying_type_t<TranslationType>>(lhs) & static_cast<std::underlying_type_t<TranslationType>>(rhs));
|
||||
}
|
||||
|
||||
friend TranslationType& operator&=(TranslationType& lhs, const TranslationType rhs)
|
||||
{
|
||||
lhs = lhs & rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
static TranslationType translationFromKey(InputChannelId channelId);
|
||||
|
||||
TranslationType m_translation = TranslationType::Nil;
|
||||
TranslationAxesFn m_translationAxesFn;
|
||||
bool m_boost = false;
|
||||
};
|
||||
|
||||
class OrbitDollyScrollCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_dollySpeed = 0.2f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
class OrbitDollyCursorMoveCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_dollySpeed = 0.1f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
class ScrollTranslationCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_translateSpeed = 0.2f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
class OrbitCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
bool Exclusive() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Cameras m_orbitCameras;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_defaultOrbitDistance = 15.0f;
|
||||
float m_maxOrbitDistance = 100.0f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize);
|
||||
} // namespace AzFramework
|
||||
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Viewport/ViewportId.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
@@ -60,17 +61,18 @@ namespace AzFramework
|
||||
{
|
||||
//! The viewport ID this event was dispatched to.
|
||||
ViewportId m_viewportId;
|
||||
//! The native window handle for the application.
|
||||
NativeWindowHandle m_windowHandle;
|
||||
//! The input channel data for this event.
|
||||
const AzFramework::InputChannel& m_inputChannel;
|
||||
//! The priority this event was dispatched at.
|
||||
ViewportControllerPriority m_priority;
|
||||
|
||||
ViewportControllerInputEvent(
|
||||
ViewportId viewportId,
|
||||
const AzFramework::InputChannel& inputChannel,
|
||||
ViewportControllerPriority priority = ViewportControllerPriority::DispatchToAllPriorities
|
||||
)
|
||||
ViewportId viewportId, NativeWindowHandle windowHandle, const AzFramework::InputChannel& inputChannel,
|
||||
ViewportControllerPriority priority = ViewportControllerPriority::DispatchToAllPriorities)
|
||||
: m_viewportId(viewportId)
|
||||
, m_windowHandle(windowHandle)
|
||||
, m_inputChannel(inputChannel)
|
||||
, m_priority(priority)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace AzFramework
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<BoundsRequestBus>("BoundsRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
|
||||
->Event("GetWorldBounds", &BoundsRequestBus::Events::GetWorldBounds)
|
||||
->Event("GetLocalBounds", &BoundsRequestBus::Events::GetLocalBounds);
|
||||
}
|
||||
|
||||
+2
-2
@@ -84,7 +84,7 @@ namespace AzFramework
|
||||
{
|
||||
if (IVisibilitySystem* visibilitySystem = AZ::Interface<IVisibilitySystem>::Get())
|
||||
{
|
||||
visibilitySystem->RemoveEntry(instance_it->second.m_visibilityEntry);
|
||||
visibilitySystem->GetDefaultVisibilityScene()->RemoveEntry(instance_it->second.m_visibilityEntry);
|
||||
m_entityVisibilityBoundsUnionInstanceMapping.erase(instance_it);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace AzFramework
|
||||
if (visibilitySystem && !worldEntityBoundsUnion.IsClose(instance.m_visibilityEntry.m_boundingVolume))
|
||||
{
|
||||
instance.m_visibilityEntry.m_boundingVolume = worldEntityBoundsUnion;
|
||||
visibilitySystem->InsertOrUpdateEntry(instance.m_visibilityEntry);
|
||||
visibilitySystem->GetDefaultVisibilityScene()->InsertOrUpdateEntry(instance.m_visibilityEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace AzFramework
|
||||
m_octreeDebug.Clear();
|
||||
m_visibleEntityIds.clear();
|
||||
|
||||
visSystem->Enumerate(
|
||||
visSystem->GetDefaultVisibilityScene()->Enumerate(
|
||||
viewFrustum,
|
||||
[&viewFrustum, &visibleEntityIdsOut = m_visibleEntityIds,
|
||||
&octreeDebug = m_octreeDebug](const AzFramework::IVisibilitySystem::NodeData& nodeData)
|
||||
&octreeDebug = m_octreeDebug](const AzFramework::IVisibilityScene::NodeData& nodeData)
|
||||
{
|
||||
if (ed_visibility_showDebug)
|
||||
{
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Math/Sphere.h>
|
||||
#include <AzCore/Math/Frustum.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
@@ -35,7 +37,6 @@ namespace AzFramework
|
||||
{
|
||||
TYPE_None = 0,
|
||||
TYPE_Entity = 1 << 0, // All entities
|
||||
TYPE_NetEntity = 1 << 1, // NetBound entities
|
||||
TYPE_RPI_Cullable = 1 << 2 // Cullable by the render system
|
||||
};
|
||||
|
||||
@@ -46,12 +47,15 @@ namespace AzFramework
|
||||
TypeFlags m_typeFlags = TYPE_None;
|
||||
};
|
||||
|
||||
//! @class IVisibilitySystem
|
||||
//! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries.
|
||||
class IVisibilitySystem
|
||||
//! @class IVisibilityScene
|
||||
//! @brief This is the interface for managing objects and visibility queries for a given scene.
|
||||
class IVisibilityScene
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}");
|
||||
AZ_RTTI(IVisibilityScene, "{822BC414-3CE3-40B4-A9A2-A42EA5B9499F}");
|
||||
|
||||
IVisibilityScene() = default;
|
||||
virtual ~IVisibilityScene() = default;
|
||||
|
||||
struct NodeData
|
||||
{
|
||||
@@ -60,8 +64,8 @@ namespace AzFramework
|
||||
};
|
||||
using EnumerateCallback = AZStd::function<void(const NodeData&)>;
|
||||
|
||||
IVisibilitySystem() = default;
|
||||
virtual ~IVisibilitySystem() = default;
|
||||
//! Get the unique scene name, used to look up the scene in the IVisibilitySystem. Duplicate names will assert on creation.
|
||||
virtual const AZ::Name& GetName() const = 0;
|
||||
|
||||
//! Insert or update an entry within the visibility system.
|
||||
//! This encompasses the following three scenarios:
|
||||
@@ -69,11 +73,11 @@ namespace AzFramework
|
||||
// 2. A previously added entry moves to a new position within its current node in the spatial hash.
|
||||
// 3. A previously added entry moves to a new node in the spatial hash.
|
||||
// (causing it to be removed from its original node and added to its new node)
|
||||
//! @param visibilityEntry data for the object being added to the visibility system
|
||||
//! @param visibilityEntry data for the object being added/updated
|
||||
virtual void InsertOrUpdateEntry(VisibilityEntry& visibilityEntry) = 0;
|
||||
|
||||
//! Removes an entry from the visibility system.
|
||||
//! @param visibilityEntry data for the object being added to the visibility system
|
||||
//! @param visibilityEntry data for the object being removed
|
||||
virtual void RemoveEntry(VisibilityEntry& visibilityEntry) = 0;
|
||||
|
||||
//! Intersects an axis aligned bounding box against the visibility system.
|
||||
@@ -100,6 +104,34 @@ namespace AzFramework
|
||||
|
||||
//! Return the number of VisibilityEntries that have been added to the system
|
||||
virtual uint32_t GetEntryCount() const = 0;
|
||||
};
|
||||
|
||||
//! @class IVisibilitySystem
|
||||
//! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries.
|
||||
class IVisibilitySystem
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}");
|
||||
|
||||
IVisibilitySystem() = default;
|
||||
virtual ~IVisibilitySystem() = default;
|
||||
|
||||
//! Return the default IVisibilityScene for entities.
|
||||
virtual IVisibilityScene* GetDefaultVisibilityScene() = 0;
|
||||
|
||||
//! Create a new IVisibilityScene that is uniquely identified by the scene name.
|
||||
virtual IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) = 0;
|
||||
|
||||
//! Destroy the visibility scene.
|
||||
//! This does not destroy the entities that are a part of the scene, only the visibility scene.
|
||||
//! This will set the visScene to nullptr
|
||||
virtual void DestroyVisibilityScene(IVisibilityScene* visScene) = 0;
|
||||
|
||||
//! Find the IVisibilityScene that is identified by sceneName.
|
||||
virtual IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) = 0;
|
||||
|
||||
//! Logs stats about the visibility system to the console.
|
||||
virtual void DumpStats(const AZ::ConsoleCommandContainer& arguments) = 0;
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(IVisibilitySystem);
|
||||
};
|
||||
@@ -113,6 +145,4 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
};
|
||||
using IVisibilitySystemRequestBus = AZ::EBus<IVisibilitySystem, IVisibilitySystemRequests>;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the octreeSystemComponent will degenerate to a quadtree split along the X/Y plane");
|
||||
AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the visibility octrees will degenerate to a quadtree split along the X/Y plane");
|
||||
AZ_CVAR(float, bg_octreeMaxWorldExtents, 16384.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum supported world size by the world octreeSystemComponent");
|
||||
AZ_CVAR(uint32_t, bg_octreeNodeMaxEntries, 64, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of entries to allow in any node before forcing a split");
|
||||
AZ_CVAR(uint32_t, bg_octreeNodeMinEntries, 32, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of entries to allow in a node resulting from a merge operation");
|
||||
@@ -67,9 +67,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Insert(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeSystemComponent");
|
||||
AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeScene");
|
||||
|
||||
// If this is not a leaf node, try to insert into the child nodes
|
||||
if (m_children != nullptr)
|
||||
@@ -80,7 +80,7 @@ namespace AzFramework
|
||||
{
|
||||
if (AZ::ShapeIntersection::Contains(m_children[child].m_bounds, boundingVolume))
|
||||
{
|
||||
return m_children[child].Insert(octreeSystemComponent, entry);
|
||||
return m_children[child].Insert(octreeScene, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,8 +90,8 @@ namespace AzFramework
|
||||
if ((m_children == nullptr) && (m_entries.size() >= bg_octreeNodeMaxEntries))
|
||||
{
|
||||
// If we're not already split, and our entry list gets too large, split this node
|
||||
Split(octreeSystemComponent);
|
||||
Insert(octreeSystemComponent, entry);
|
||||
Split(octreeScene);
|
||||
Insert(octreeScene, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Update(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == this, "Update invoked for an entry bound to a different OctreeNode");
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
// Remove the entry from our current node, since it is no longer contained
|
||||
Remove(octreeSystemComponent, entry);
|
||||
Remove(octreeScene, entry);
|
||||
|
||||
// Traverse up our ancestor nodes to find the first node that fully contains the entry
|
||||
// This strategy assumes an entry will typically move a small distance relative to the total world
|
||||
@@ -125,14 +125,14 @@ namespace AzFramework
|
||||
{
|
||||
if (AZ::ShapeIntersection::Contains(insertCheck->m_bounds, boundingVolume))
|
||||
{
|
||||
return insertCheck->Insert(octreeSystemComponent, entry);
|
||||
return insertCheck->Insert(octreeScene, entry);
|
||||
}
|
||||
insertCheck = insertCheck->m_parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Remove(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == this, "Remove invoked for an entry bound to a different OctreeNode");
|
||||
AZ_Assert(m_entries[entry->m_internalNodeIndex] == entry, "Visibility entry data is corrupt");
|
||||
@@ -150,29 +150,30 @@ namespace AzFramework
|
||||
|
||||
if (m_parent != nullptr)
|
||||
{
|
||||
m_parent->TryMerge(octreeSystemComponent);
|
||||
m_parent->TryMerge(octreeScene);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(aabb, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(sphere, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(frustum, callback);
|
||||
}
|
||||
|
||||
void OctreeNode::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
|
||||
void OctreeNode::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
// Invoke the callback for the current node
|
||||
if (!m_entries.empty())
|
||||
@@ -191,6 +192,7 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AZStd::vector<VisibilityEntry*>& OctreeNode::GetEntries() const
|
||||
{
|
||||
return m_entries;
|
||||
@@ -209,7 +211,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::TryMerge(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::TryMerge(OctreeScene& octreeScene)
|
||||
{
|
||||
if (IsLeaf())
|
||||
{
|
||||
@@ -222,7 +224,7 @@ namespace AzFramework
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
for (uint32_t child = 0; child < childCount; ++child)
|
||||
{
|
||||
m_children[child].TryMerge(octreeSystemComponent);
|
||||
m_children[child].TryMerge(octreeScene);
|
||||
if (!m_children[child].IsLeaf())
|
||||
{
|
||||
return;
|
||||
@@ -232,13 +234,13 @@ namespace AzFramework
|
||||
|
||||
if (potentialNodeCount <= bg_octreeNodeMinEntries)
|
||||
{
|
||||
Merge(octreeSystemComponent);
|
||||
Merge(octreeScene);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZ_Assert(AZ::ShapeIntersection::Overlaps(boundingVolume, m_bounds), "EnumerateHelper invoked on an octreeSystemComponent node that is not within the bounding volume");
|
||||
|
||||
@@ -263,11 +265,11 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Split(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::Split(OctreeScene& octreeScene)
|
||||
{
|
||||
AZ_Assert(m_children == nullptr, "Split invoked on an octreeSystemComponent node that has already been split");
|
||||
m_childNodeIndex = octreeSystemComponent.AllocateChildNodes();
|
||||
m_children = octreeSystemComponent.GetChildNodesAtIndex(m_childNodeIndex);
|
||||
AZ_Assert(m_children == nullptr, "Split invoked on an octreeScene node that has already been split");
|
||||
m_childNodeIndex = octreeScene.AllocateChildNodes();
|
||||
m_children = octreeScene.GetChildNodesAtIndex(m_childNodeIndex);
|
||||
|
||||
// Set child split planes and bounding volumes
|
||||
{
|
||||
@@ -308,14 +310,14 @@ namespace AzFramework
|
||||
{
|
||||
entry->m_internalNode = nullptr;
|
||||
entry->m_internalNodeIndex = 0;
|
||||
Insert(octreeSystemComponent, entry);
|
||||
Insert(octreeScene, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Merge(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::Merge(OctreeScene& octreeScene)
|
||||
{
|
||||
AZ_Assert(m_children != nullptr, "Merge invoked on an octreeSystemComponent node that does not have children");
|
||||
AZ_Assert(m_children != nullptr, "Merge invoked on an octreeScene node that does not have children");
|
||||
|
||||
// Move all child entries to our own entry set
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
@@ -330,46 +332,20 @@ namespace AzFramework
|
||||
m_children[child].m_entries.clear();
|
||||
}
|
||||
|
||||
octreeSystemComponent.ReleaseChildNodes(m_childNodeIndex);
|
||||
octreeScene.ReleaseChildNodes(m_childNodeIndex);
|
||||
m_childNodeIndex = InvalidChildNodeIndex;
|
||||
m_children = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
OctreeScene::OctreeScene(const AZ::Name& sceneName)
|
||||
: m_sceneName(sceneName)
|
||||
, m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents)))
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<OctreeSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
AZ_Assert(!sceneName.IsEmpty(), "sceneName must be a valid string");
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
OctreeScene::~OctreeScene()
|
||||
{
|
||||
provided.push_back(AZ_CRC_CE("VisibilityService"));
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC_CE("VisibilityService"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::OctreeSystemComponent()
|
||||
: m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents)))
|
||||
{
|
||||
AZ::Interface<IVisibilitySystem>::Register(this);
|
||||
IVisibilitySystemRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::~OctreeSystemComponent()
|
||||
{
|
||||
IVisibilitySystemRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IVisibilitySystem>::Unregister(this);
|
||||
for (auto page : m_nodeCache)
|
||||
{
|
||||
delete page;
|
||||
@@ -378,21 +354,14 @@ namespace AzFramework
|
||||
m_nodeCache.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Activate()
|
||||
const AZ::Name& OctreeScene::GetName() const
|
||||
{
|
||||
;
|
||||
return m_sceneName;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Deactivate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::InsertOrUpdateEntry(VisibilityEntry& entry)
|
||||
void OctreeScene::InsertOrUpdateEntry(VisibilityEntry& entry)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
if (entry.m_internalNode != nullptr)
|
||||
{
|
||||
static_cast<OctreeNode*>(entry.m_internalNode)->Update(*this, &entry);
|
||||
@@ -405,8 +374,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::RemoveEntry(VisibilityEntry& entry)
|
||||
void OctreeScene::RemoveEntry(VisibilityEntry& entry)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
if (entry.m_internalNode)
|
||||
{
|
||||
static_cast<OctreeNode*>(entry.m_internalNode)->Remove(*this, &entry);
|
||||
@@ -415,70 +385,71 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(aabb, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(sphere, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(frustum, callback);
|
||||
}
|
||||
|
||||
void OctreeSystemComponent::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
|
||||
void OctreeScene::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.EnumerateNoCull(callback);
|
||||
}
|
||||
|
||||
uint32_t OctreeSystemComponent::GetEntryCount() const
|
||||
|
||||
uint32_t OctreeScene::GetEntryCount() const
|
||||
{
|
||||
return m_entryCount;
|
||||
}
|
||||
|
||||
OctreeNode& OctreeSystemComponent::GetRoot()
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
uint32_t OctreeSystemComponent::GetNodeCount() const
|
||||
uint32_t OctreeScene::GetNodeCount() const
|
||||
{
|
||||
return m_nodeCount;
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetFreeNodeCount() const
|
||||
uint32_t OctreeScene::GetFreeNodeCount() const
|
||||
{
|
||||
// Each entry represents GetChildNodeCount() nodes
|
||||
return aznumeric_cast<uint32_t>(m_freeOctreeNodes.size() * GetChildNodeCount());
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetPageCount() const
|
||||
uint32_t OctreeScene::GetPageCount() const
|
||||
{
|
||||
return aznumeric_cast<uint32_t>(m_nodeCache.size());
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetChildNodeCount() const
|
||||
uint32_t OctreeScene::GetChildNodeCount() const
|
||||
{
|
||||
return AzFramework::GetChildNodeCount();
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
void OctreeScene::DumpStats()
|
||||
{
|
||||
AZ_TracePrintf("Console", "OctreeNode::EntryCount = %u", GetEntryCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::NodeCount = %u", GetNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::FreeNodeCount = %u", GetFreeNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::PageCount = %u", GetPageCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::ChildNodeCount = %u", GetChildNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::EntryCount = %u", GetName().GetCStr(), GetEntryCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::NodeCount = %u", GetName().GetCStr(), GetNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::FreeNodeCount = %u", GetName().GetCStr(), GetFreeNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::PageCount = %u", GetName().GetCStr(), GetPageCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::ChildNodeCount = %u", GetName().GetCStr(), GetChildNodeCount());
|
||||
}
|
||||
|
||||
|
||||
@@ -496,7 +467,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::AllocateChildNodes()
|
||||
uint32_t OctreeScene::AllocateChildNodes()
|
||||
{
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
m_nodeCount += childCount;
|
||||
@@ -540,18 +511,124 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::ReleaseChildNodes(uint32_t nodeIndex)
|
||||
void OctreeScene::ReleaseChildNodes(uint32_t nodeIndex)
|
||||
{
|
||||
m_nodeCount -= GetChildNodeCount();
|
||||
m_freeOctreeNodes.push(nodeIndex);
|
||||
}
|
||||
|
||||
|
||||
OctreeNode* OctreeSystemComponent::GetChildNodesAtIndex(uint32_t nodeIndex) const
|
||||
OctreeNode* OctreeScene::GetChildNodesAtIndex(uint32_t nodeIndex) const
|
||||
{
|
||||
uint32_t childPage;
|
||||
uint32_t childOffset;
|
||||
ExtractPageAndOffsetFromIndex(nodeIndex, childPage, childOffset);
|
||||
return &(*m_nodeCache[childPage])[childOffset];
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<OctreeSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("OctreeService"));
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("OctreeService"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::OctreeSystemComponent()
|
||||
{
|
||||
AZ::Interface<IVisibilitySystem>::Register(this);
|
||||
IVisibilitySystemRequestBus::Handler::BusConnect();
|
||||
|
||||
m_defaultScene = aznew OctreeScene(AZ::Name("DefaultVisibilityScene"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::~OctreeSystemComponent()
|
||||
{
|
||||
AZ_Assert(m_scenes.empty(), "All IVisibilityScenes must be destroyed before shutdown");
|
||||
|
||||
delete m_defaultScene;
|
||||
|
||||
IVisibilitySystemRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IVisibilitySystem>::Unregister(this);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Activate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Deactivate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::GetDefaultVisibilityScene()
|
||||
{
|
||||
return m_defaultScene;
|
||||
}
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::CreateVisibilityScene(const AZ::Name& sceneName)
|
||||
{
|
||||
AZ_Assert(FindVisibilityScene(sceneName) == nullptr, "Scene with same name already created!");
|
||||
OctreeScene* newScene = aznew OctreeScene(sceneName);
|
||||
m_scenes.push_back(newScene);
|
||||
return newScene;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DestroyVisibilityScene(IVisibilityScene* visScene)
|
||||
{
|
||||
for (auto iter = m_scenes.begin(); iter != m_scenes.end(); ++iter)
|
||||
{
|
||||
if (*iter == visScene)
|
||||
{
|
||||
delete visScene;
|
||||
m_scenes.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
AZ_Assert(false, "visScene[\"%s\"] not found in the OctreeSystemComponent", visScene->GetName().GetCStr());
|
||||
}
|
||||
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::FindVisibilityScene(const AZ::Name& sceneName)
|
||||
{
|
||||
for (OctreeScene* scene : m_scenes)
|
||||
{
|
||||
if(scene->GetName() == sceneName)
|
||||
{
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
for (OctreeScene* scene : m_scenes)
|
||||
{
|
||||
AZ_TracePrintf("Console", "============================================");
|
||||
scene->DumpStats();
|
||||
}
|
||||
AZ_TracePrintf("Console", "============================================");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
#include <AzFramework/Visibility/IVisibilitySystem.h>
|
||||
#include <AzCore/Math/Plane.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/std/containers/stack.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class OctreeSystemComponent;
|
||||
class OctreeScene;
|
||||
|
||||
//! An internal node within the tree.
|
||||
//! It contains all objects that are *fully contained* by the node, if an object spans multiple child nodes that object will be stored in the parent.
|
||||
@@ -40,25 +41,25 @@ namespace AzFramework
|
||||
OctreeNode& operator=(OctreeNode&& rhs);
|
||||
|
||||
//! Inserts a VisibilityEntry into this OctreeNode, potentially triggering a split.
|
||||
void Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Insert(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Updates a VisibilityEntry that is currently bound to this OctreeNode.
|
||||
//! The provided entry must be bound to this node, but may no longer be bound to this node upon function exit.
|
||||
void Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Update(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Removes a VisibilityEntry from this OctreeNode.
|
||||
//! The provided entry must be bound to this node.
|
||||
void Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Remove(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Recursively enumerates any OctreeNodes and their children that intersect the provided bounding volume.
|
||||
//! @{
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
//! @}
|
||||
|
||||
//! Recursively enumerate *all* OctreeNodes that have any entries in them (without any culling).
|
||||
void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
|
||||
//! Returns the set of entries bound to this node.
|
||||
const AZStd::vector<VisibilityEntry*>& GetEntries() const;
|
||||
@@ -71,13 +72,13 @@ namespace AzFramework
|
||||
|
||||
private:
|
||||
|
||||
void TryMerge(OctreeSystemComponent& octreeSystemComponent);
|
||||
void TryMerge(OctreeScene& octreeScene);
|
||||
|
||||
template <typename T>
|
||||
void EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
|
||||
void Split(OctreeSystemComponent& octreeSystemComponent);
|
||||
void Merge(OctreeSystemComponent& octreeSystemComponent);
|
||||
void Split(OctreeScene& octreeScene);
|
||||
void Merge(OctreeScene& octreeScene);
|
||||
|
||||
// The page is stored in the upper 16-bits of the child node index, the offset into the page is the lower 16-bits
|
||||
// This gives us a maximum of 65,536 pages and 65,536 nodes per page, for a total of 2^32 - 1 total pages (-1 reserved for the invalid index)
|
||||
@@ -90,60 +91,47 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
//! Implementation of the visibility system interface.
|
||||
//! This uses a simple adaptive octreeSystemComponent to support partitioning an object set and efficiently running gathers and visibility queries.
|
||||
class OctreeSystemComponent
|
||||
: public AZ::Component
|
||||
, public IVisibilitySystemRequestBus::Handler
|
||||
//! This uses a simple adaptive octree to support partitioning an object set for a specific scene and efficiently running gathers and visibility queries.
|
||||
class OctreeScene
|
||||
: public IVisibilityScene
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(OctreeScene, "{A88E4D86-11F1-4E3F-A91A-66DE99502B93}");
|
||||
AZ_CLASS_ALLOCATOR(OctreeScene, AZ::SystemAllocator, 0);
|
||||
AZ_DISABLE_COPY_MOVE(OctreeScene);
|
||||
|
||||
AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}");
|
||||
explicit OctreeScene(const AZ::Name& sceneName);
|
||||
virtual ~OctreeScene();
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
|
||||
OctreeSystemComponent();
|
||||
virtual ~OctreeSystemComponent();
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
//! IVisibilitySystem overrides.
|
||||
//! IVisibilityScene overrides.
|
||||
//! @{
|
||||
const AZ::Name& GetName() const override;
|
||||
void InsertOrUpdateEntry(VisibilityEntry& entry) override;
|
||||
void RemoveEntry(VisibilityEntry& entry) override;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
uint32_t GetEntryCount() const override;
|
||||
//! @}
|
||||
|
||||
//! Returns the OctreeSystemComponent's root node.
|
||||
OctreeNode& GetRoot();
|
||||
|
||||
//! OctreeSystemComponent stats
|
||||
//! Stats
|
||||
//! @{
|
||||
uint32_t GetNodeCount() const;
|
||||
uint32_t GetFreeNodeCount() const;
|
||||
uint32_t GetPageCount() const;
|
||||
uint32_t GetChildNodeCount() const;
|
||||
void DumpStats(const AZ::ConsoleCommandContainer& arguments);
|
||||
void DumpStats();
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t AllocateChildNodes();
|
||||
void ReleaseChildNodes(uint32_t nodeIndex);
|
||||
OctreeNode* GetChildNodesAtIndex(uint32_t nodeIndex) const;
|
||||
|
||||
// Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats'
|
||||
AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window");
|
||||
mutable AZStd::shared_mutex m_sharedMutex;
|
||||
|
||||
AZ::Name m_sceneName; //< The uniquely identifying name for the visibility scene.
|
||||
OctreeNode m_root; //< The root node for the octreeSystemComponent.
|
||||
|
||||
uint32_t m_entryCount = 0; //< Metric tracking the number of entries inserted into the octreeSystemComponent.
|
||||
@@ -158,4 +146,47 @@ namespace AzFramework
|
||||
|
||||
friend class OctreeNode; // For access to the node allocator methods
|
||||
};
|
||||
|
||||
//! Implementation of the visibility system interface.
|
||||
//! This manages creating, destroying, and finding the underlying octrees that are associated with specific scenes
|
||||
class OctreeSystemComponent
|
||||
: public AZ::Component
|
||||
, public IVisibilitySystemRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}");
|
||||
|
||||
// Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats'
|
||||
AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
|
||||
OctreeSystemComponent();
|
||||
virtual ~OctreeSystemComponent();
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
//! IVisibilitySystem overrides
|
||||
//! @{
|
||||
IVisibilityScene* GetDefaultVisibilityScene() override;
|
||||
IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) override;
|
||||
void DestroyVisibilityScene(IVisibilityScene* visScene) override;
|
||||
IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) override;
|
||||
void DumpStats(const AZ::ConsoleCommandContainer& arguments) override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
//! The default scene used for most entities (e.g. gameplay, networking)
|
||||
OctreeScene* m_defaultScene = nullptr;
|
||||
|
||||
//! Other scenes (e.g. each rendering scene) are stored here and looked up by name.
|
||||
AZStd::vector<OctreeScene*> m_scenes; //using a vector<> here because we'll generally have a small number of scenes
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ set(FILES
|
||||
Viewport/ScreenGeometry.cpp
|
||||
Viewport/CameraState.h
|
||||
Viewport/CameraState.cpp
|
||||
Viewport/CameraInput.h
|
||||
Viewport/CameraInput.cpp
|
||||
Viewport/DisplayContextRequestBus.h
|
||||
Entity/BehaviorEntity.cpp
|
||||
Entity/BehaviorEntity.h
|
||||
@@ -426,4 +428,7 @@ set(FILES
|
||||
Visibility/EntityVisibilityBoundsUnionSystem.cpp
|
||||
Visibility/EntityVisibilityQuery.h
|
||||
Visibility/EntityVisibilityQuery.cpp
|
||||
Dependency/Dependency.h
|
||||
Dependency/Dependency.inl
|
||||
Dependency/Version.h
|
||||
)
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
#include <AzCore/Android/APKFileHandler.h>
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/IOUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
#include <android/api-level.h>
|
||||
|
||||
#if __ANDROID_API__ == 19
|
||||
// The following were apparently introduced in API 21, however in earlier versions of the
|
||||
// The following were apparently introduced in API 21, however in earlier versions of the
|
||||
// platform specific headers they were defines. In the move to unified headers, the following
|
||||
// defines were removed from stat.h
|
||||
#ifndef stat64
|
||||
@@ -52,7 +53,7 @@ namespace AZ
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(resolvedPath))
|
||||
{
|
||||
return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath));
|
||||
return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath).c_str());
|
||||
}
|
||||
|
||||
struct stat result;
|
||||
@@ -108,7 +109,7 @@ namespace AZ
|
||||
|
||||
if (isInAPK)
|
||||
{
|
||||
AZ::OSString strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
AZ::IO::FixedMaxPath strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
|
||||
char tempBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
|
||||
|
||||
+1
@@ -290,6 +290,7 @@ namespace AzFramework
|
||||
UpdateSystemCursorVisibility();
|
||||
const bool shouldBeDisabled = (m_systemCursorState == SystemCursorState::ConstrainedAndHidden) ||
|
||||
(m_systemCursorState == SystemCursorState::ConstrainedAndVisible);
|
||||
|
||||
if (!shouldBeDisabled)
|
||||
{
|
||||
DestroyDisabledSystemCursorEventTap();
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ namespace AzFramework
|
||||
{
|
||||
AZStd::string GetPersistentName()
|
||||
{
|
||||
AZStd::string persistentName = "Lumberyard";
|
||||
AZStd::string persistentName = "Open 3D Engine";
|
||||
|
||||
char procPath[AZ_MAX_PATH_LEN];
|
||||
AZ::Utils::GetExecutablePathReturnType ret = AZ::Utils::GetExecutablePath(procPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ namespace AzFramework
|
||||
bool m_isInBorderlessWindowFullScreenState = false; //!< Was a borderless window used to enter full screen state?
|
||||
};
|
||||
|
||||
const char* NativeWindowImpl_Win32::s_defaultClassName = "LumberyardWin32Class";
|
||||
const char* NativeWindowImpl_Win32::s_defaultClassName = "O3DEWin32Class";
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
{
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ namespace AzFramework
|
||||
//!
|
||||
//! return another vector relative to the specified display orientation, and such that the
|
||||
//! +y axis points out the back of the screen and z+ axis points out the top of the device.
|
||||
//! This flipping of axes is to match Lumberyard's z-up and left-handed coordinate system.
|
||||
//! This flipping of axes is to match Open 3D Engine's z-up and left-handed coordinate system.
|
||||
//!
|
||||
//! \param[in] x The x component of the vector to be aligned
|
||||
//! \param[in] y The y component of the vector to be aligned
|
||||
|
||||
Reference in New Issue
Block a user