Integrating up through commit 90f050496
This commit is contained in:
@@ -107,15 +107,9 @@ namespace AZ
|
||||
result = ContinueLoading(&id, azrtti_typeid<AssetId>(), it->value, context);
|
||||
if (!id.m_guid.IsNull())
|
||||
{
|
||||
if (instance->Create(id))
|
||||
{
|
||||
result.Combine(context.Report(result, "Successfully created Asset<T>."));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Combine(context.Report(JSR::Tasks::Convert, JSR::Outcomes::Unknown,
|
||||
"The asset id was successfully read, but creating an Asset<T> instance from it failed."));
|
||||
}
|
||||
*instance = Asset<AssetData>(id, instance->GetType());
|
||||
|
||||
result.Combine(context.Report(result, "Successfully created Asset<T> with id."));
|
||||
}
|
||||
else if (result.GetProcessing() == JSR::Processing::Completed)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <AzCore/Module/ModuleManager.h>
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
#include <AzCore/Driller/Driller.h>
|
||||
@@ -434,6 +435,7 @@ namespace AZ
|
||||
|
||||
// Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
|
||||
|
||||
@@ -888,17 +890,19 @@ namespace AZ
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry,
|
||||
AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
|
||||
// In development builds apply the developer registry and the command line to allow early overrides. This will
|
||||
// In development builds apply the o3de registry and the command line to allow early overrides. This will
|
||||
// allow developers to override things like default paths or Asset Processor connection settings. Any additional
|
||||
// values will be replaced by later loads, so this step will happen again at the end of loading.
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_UserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
|
||||
#endif
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
#if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_UserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
|
||||
#endif
|
||||
}
|
||||
@@ -1455,6 +1459,8 @@ namespace AZ
|
||||
PolygonPrismReflect(context);
|
||||
// reflect name dictionary.
|
||||
Name::Reflect(context);
|
||||
// reflect path
|
||||
IO::PathReflection::Reflect(context);
|
||||
|
||||
// reflect the SettingsRegistryInterface, SettignsRegistryImpl and the global Settings Registry
|
||||
// instance (AZ::SettingsRegistry::Get()) into the Behavior Context
|
||||
|
||||
@@ -96,6 +96,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
Entity::~Entity()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Entity::Reset()
|
||||
{
|
||||
AZ_Assert(m_state != State::Activating && m_state != State::Deactivating && m_state != State::Initializing, "Unsafe to delete an entity during its state transition.");
|
||||
if (m_state == State::Active)
|
||||
@@ -116,6 +121,8 @@ namespace AZ
|
||||
delete *it;
|
||||
}
|
||||
|
||||
m_components.clear();
|
||||
|
||||
if (m_state == State::Init)
|
||||
{
|
||||
EBUS_EVENT(EntitySystemBus, OnEntityDestroyed, m_id);
|
||||
@@ -751,6 +758,8 @@ namespace AZ
|
||||
->Field("IsRuntimeActive", &Entity::m_isRuntimeActiveByDefault)
|
||||
;
|
||||
|
||||
serializeContext->RegisterGenericType<AZStd::unordered_map<AZStd::string, AZ::Component*>>();
|
||||
|
||||
serializeContext->Class<EntityId>()
|
||||
->Version(1, &EntityIdConverter)
|
||||
->Field("id", &EntityId::m_id);
|
||||
|
||||
@@ -118,6 +118,9 @@ namespace AZ
|
||||
//! If the entity is in a transition state, this function asserts.
|
||||
virtual ~Entity();
|
||||
|
||||
//! Resets the state to default
|
||||
void Reset();
|
||||
|
||||
//! Gets the ID of the entity.
|
||||
//! @return The ID of the entity.
|
||||
EntityId GetId() const { return m_id; }
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/EntityIdSerializer.h>
|
||||
#include <AzCore/Component/EntitySerializer.h>
|
||||
@@ -62,11 +63,17 @@ namespace AZ
|
||||
}
|
||||
|
||||
{
|
||||
AZStd::unordered_map<AZStd::string, AZ::Component*> componentMap;
|
||||
JSR::ResultCode componentLoadResult =
|
||||
ContinueLoadingFromJsonObjectField(&entityInstance->m_components,
|
||||
azrtti_typeid<decltype(entityInstance->m_components)>(),
|
||||
ContinueLoadingFromJsonObjectField(&componentMap,
|
||||
azrtti_typeid<decltype(componentMap)>(),
|
||||
inputValue, "Components", context);
|
||||
|
||||
for (auto& [componentKey, component] : componentMap)
|
||||
{
|
||||
entityInstance->m_components.emplace_back(component);
|
||||
}
|
||||
|
||||
result.Combine(componentLoadResult);
|
||||
}
|
||||
|
||||
@@ -145,9 +152,21 @@ namespace AZ
|
||||
const AZ::Entity::ComponentArrayType* defaultComponents =
|
||||
defaultEntityInstance ? &defaultEntityInstance->m_components : nullptr;
|
||||
|
||||
AZStd::unordered_map<AZStd::string, AZ::Component*> componentMap;
|
||||
AZStd::unordered_map<AZStd::string, AZ::Component*> defaultComponentMap;
|
||||
|
||||
ConvertComponentVectorToMap(*components, componentMap);
|
||||
|
||||
if (defaultComponents)
|
||||
{
|
||||
ConvertComponentVectorToMap(*defaultComponents, defaultComponentMap);
|
||||
}
|
||||
|
||||
JSR::ResultCode resultComponents =
|
||||
ContinueStoringToJsonObjectField(outputValue, "Components",
|
||||
components, defaultComponents, azrtti_typeid<decltype(entityInstance->m_components)>(), context);
|
||||
&componentMap,
|
||||
defaultComponents ? &defaultComponentMap : nullptr,
|
||||
azrtti_typeid<decltype(componentMap)>(), context);
|
||||
|
||||
result.Combine(resultComponents);
|
||||
}
|
||||
@@ -183,4 +202,16 @@ namespace AZ
|
||||
result.GetProcessing() == JSR::Processing::Halted ? "Successfully stored Entity information." :
|
||||
"Failed to store Entity information.");
|
||||
}
|
||||
|
||||
void JsonEntitySerializer::ConvertComponentVectorToMap(const AZ::Entity::ComponentArrayType& components,
|
||||
AZStd::unordered_map<AZStd::string, AZ::Component*>& componentMapOut)
|
||||
{
|
||||
for (AZ::Component* component : components)
|
||||
{
|
||||
if (component)
|
||||
{
|
||||
componentMapOut.emplace(AZStd::string::format("Component_[%llu]", component->GetId()), component);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,9 @@ namespace AZ
|
||||
|
||||
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context) override;
|
||||
|
||||
private:
|
||||
void ConvertComponentVectorToMap(const AZ::Entity::ComponentArrayType& components,
|
||||
AZStd::unordered_map<AZStd::string, AZ::Component*>& componentMapOut);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZStd::string Console::AutoCompleteCommand(const char* command)
|
||||
AZStd::string Console::AutoCompleteCommand(const char* command, AZStd::vector<AZStd::string>* matches)
|
||||
{
|
||||
const size_t commandLength = strlen(command);
|
||||
|
||||
@@ -219,6 +219,10 @@ namespace AZ
|
||||
{
|
||||
AZLOG_INFO("- %s : %s\n", curr->m_name, curr->m_desc);
|
||||
commandSubset.push_back(curr->m_name);
|
||||
if (matches)
|
||||
{
|
||||
matches->push_back(curr->m_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +287,12 @@ namespace AZ
|
||||
AZ_Assert(false, "Mismatched console functor types registered under the same name");
|
||||
return;
|
||||
}
|
||||
|
||||
// Discard duplicate functors if the 'DontDuplicate' flag has been set
|
||||
if ((front->GetFlags() & ConsoleFunctorFlags::DontDuplicate) != ConsoleFunctorFlags::Null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_commands[lowerName].emplace_back(functor);
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
void ExecuteCommandLine(const AZ::CommandLine& commandLine) override;
|
||||
bool HasCommand(const char* command) override;
|
||||
ConsoleFunctorBase* FindCommand(const char* command) override;
|
||||
AZStd::string AutoCompleteCommand(const char* command) override;
|
||||
AZStd::string AutoCompleteCommand(const char* command, AZStd::vector<AZStd::string>* matches = nullptr) override;
|
||||
void VisitRegisteredFunctors(const FunctorVisitor& visitor) override;
|
||||
void RegisterFunctor(ConsoleFunctorBase* functor) override;
|
||||
void UnregisterFunctor(ConsoleFunctorBase* functor) override;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <AzCore/Console/IConsoleTypes.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -103,10 +104,13 @@ namespace AZ
|
||||
//! @return non-null pointer to the console command if found
|
||||
virtual ConsoleFunctorBase* FindCommand(const char* command) = 0;
|
||||
|
||||
//! Prints all commands of which the input is a prefix.
|
||||
//! @param command the prefix string to dump all matching commands for
|
||||
//! @return boolean true on success, false otherwise
|
||||
virtual AZStd::string AutoCompleteCommand(const char* command) = 0;
|
||||
//! Finds all commands where the input command is a prefix and returns
|
||||
//! the longest matching substring prefix the results have in common.
|
||||
//! @param command The prefix string to find all matching commands for.
|
||||
//! @param matches The list of all commands that match the input prefix.
|
||||
//! @return The longest matching substring prefix the results have in common.
|
||||
virtual AZStd::string AutoCompleteCommand(const char* command,
|
||||
AZStd::vector<AZStd::string>* matches = nullptr) = 0;
|
||||
|
||||
//! Retrieves the value of the requested cvar.
|
||||
//! @param command the name of the cvar to find and retrieve the current value of
|
||||
@@ -233,7 +237,7 @@ static constexpr AZ::ThreadSafety ConsoleThreadSafety<_TYPE, std::enable_if_t<st
|
||||
//! @param _FLAGS a set of AzFramework::ConsoleFunctorFlags used to mutate behaviour
|
||||
//! @param _DESC a description of the cvar
|
||||
#define AZ_CONSOLEFREEFUNC_3(_FUNCTION, _FLAGS, _DESC) \
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
|
||||
//! Implements a console functor for a non-member function.
|
||||
//!
|
||||
@@ -243,6 +247,6 @@ static constexpr AZ::ThreadSafety ConsoleThreadSafety<_TYPE, std::enable_if_t<st
|
||||
//! @param _FLAGS a set of AzFramework::ConsoleFunctorFlags used to mutate behaviour
|
||||
//! @param _DESC a description of the cvar
|
||||
#define AZ_CONSOLEFREEFUNC_4(_NAME, _FUNCTION, _FLAGS, _DESC) \
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
|
||||
|
||||
#define AZ_CONSOLEFREEFUNC(...) AZ_MACRO_SPECIALIZE(AZ_CONSOLEFREEFUNC_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace AZ
|
||||
, IsDeprecated = (1 << 5) // Command is deprecated, show a warning when invoked
|
||||
, NeedsReload = (1 << 6) // Level should be reloaded after executing this command
|
||||
, AllowClientSet = (1 << 7) // Allow clients to modify this cvar even in release (this alters the cvar for all connected servers and clients, be VERY careful enabling this flag)
|
||||
, DontDuplicate = (1 << 8) // Discard functors with the same name as another that has already been registered instead of duplicating them (which is the default behavior)
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(ConsoleFunctorFlags);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
// Explicit instantations of our support Path classes
|
||||
namespace AZ::IO
|
||||
@@ -53,4 +54,13 @@ namespace AZ::IO
|
||||
const PathIterator<Path>& rhs);
|
||||
template bool operator!=<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
|
||||
const PathIterator<FixedMaxPath>& rhs);
|
||||
|
||||
void PathReflection::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AZ::IO::Path>()
|
||||
->Field("m_path", &AZ::IO::Path::m_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +300,7 @@ namespace AZ::IO
|
||||
using const_iterator = const PathIterator<BasicPath>;
|
||||
using iterator = const_iterator;
|
||||
friend PathIterator<BasicPath>;
|
||||
friend struct PathReflection;
|
||||
|
||||
// constructors and destructor
|
||||
constexpr BasicPath() = default;
|
||||
@@ -631,6 +632,11 @@ namespace AZ::IO
|
||||
constexpr BasicPath<StringType> operator/(const BasicPath<StringType>& lhs, const typename BasicPath<StringType>::value_type* rhs);
|
||||
}
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(AZ::IO::Path, "{88E0A40F-3085-4CAB-8B11-EF5A2659C71A}");
|
||||
}
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
//! Path iterator that allows traversal of the path elements
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace AZStd
|
||||
struct hash;
|
||||
}
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
//! Path Constants
|
||||
@@ -56,6 +61,11 @@ namespace AZ::IO
|
||||
// It depends on the path type
|
||||
template <typename PathType>
|
||||
class PathIterator;
|
||||
|
||||
struct PathReflection
|
||||
{
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
}
|
||||
|
||||
namespace AZStd
|
||||
|
||||
@@ -68,9 +68,11 @@ namespace AZ
|
||||
|
||||
bool useAllHardware = true;
|
||||
settingsRegistry->Get(useAllHardware, "/Amazon/AzCore/Streamer/UseAllHardware");
|
||||
bool reportHardware = true;
|
||||
settingsRegistry->Get(reportHardware, "/Amazon/AzCore/Streamer/ReportHardware");
|
||||
|
||||
AZ::IO::HardwareInformation hardwareInfo;
|
||||
if (!AZ::IO::CollectIoHardwareInformation(hardwareInfo, useAllHardware))
|
||||
if (!AZ::IO::CollectIoHardwareInformation(hardwareInfo, useAllHardware, reportHardware))
|
||||
{
|
||||
AZ_Assert(false, "Unable to collect information on available IO hardware.");
|
||||
return CreateSimpleStreamerStack();
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace AZ::IO
|
||||
AZStd::string m_profile{"Default"};
|
||||
size_t m_maxPhysicalSectorSize{ AZCORE_GLOBAL_NEW_ALIGNMENT };
|
||||
size_t m_maxLogicalSectorSize{ AZCORE_GLOBAL_NEW_ALIGNMENT };
|
||||
size_t m_maxPageSize{ 0 };
|
||||
size_t m_maxTransfer{ 0 };
|
||||
size_t m_maxPageSize{ AZCORE_GLOBAL_NEW_ALIGNMENT };
|
||||
size_t m_maxTransfer{ AZCORE_GLOBAL_NEW_ALIGNMENT };
|
||||
};
|
||||
|
||||
class IStreamerStackConfig
|
||||
@@ -73,7 +73,8 @@ namespace AZ::IO
|
||||
//! @param includeAllHardware Includes all available hardware that can be used by AZ::IO::Streamer. If set to false
|
||||
//! only hardware is listed that is known to be used. This may be more performant, but can result is file
|
||||
//! requests failing if they use an previously unknown path.
|
||||
extern bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware);
|
||||
//! @param reportHardware If true, hardware information will be printed to the log if available.
|
||||
extern bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware, bool reportHardware);
|
||||
extern void ReflectNative(ReflectContext* context);
|
||||
|
||||
//! Constant used to denote "file not found" in StreamStackEntry processing.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <AzCore/Math/ColorSerializer.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/TransformSerializer.h>
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
#include <AzCore/Math/Matrix3x4.h>
|
||||
#include <AzCore/Math/Matrix4x4.h>
|
||||
@@ -370,6 +371,7 @@ namespace AZ
|
||||
context.Serializer<JsonVector3Serializer>()->HandlesType<Vector3>();
|
||||
context.Serializer<JsonVector4Serializer>()->HandlesType<Vector4>();
|
||||
context.Serializer<JsonQuaternionSerializer>()->HandlesType<Quaternion>();
|
||||
context.Serializer<JsonTransformSerializer>()->HandlesType<Transform>();
|
||||
}
|
||||
|
||||
void MathReflect(ReflectContext* context)
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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 <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/TransformSerializer.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JsonTransformSerializer, AZ::SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result JsonTransformSerializer::Load(
|
||||
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
if (azrtti_typeid<AZ::Transform>() != outputValueTypeId)
|
||||
{
|
||||
return context.Report(
|
||||
JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
|
||||
"Unable to deserialize Transform from json because the outputValueTypeId isn't a Transform type.");
|
||||
}
|
||||
|
||||
AZ::Transform* transformInstance = reinterpret_cast<AZ::Transform*>(outputValue);
|
||||
AZ_Assert(transformInstance, "Output value for JsonTransformSerializer can't be null.");
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::ReadField);
|
||||
|
||||
{
|
||||
AZ::Vector3 translation = transformInstance->GetTranslation();
|
||||
|
||||
JSR::ResultCode loadResult = ContinueLoadingFromJsonObjectField(
|
||||
&translation, azrtti_typeid<decltype(translation)>(), inputValue, TranslationTag, context);
|
||||
|
||||
result.Combine(loadResult);
|
||||
|
||||
transformInstance->SetTranslation(translation);
|
||||
}
|
||||
|
||||
{
|
||||
AZ::Quaternion rotation = transformInstance->GetRotation();
|
||||
|
||||
JSR::ResultCode loadResult =
|
||||
ContinueLoadingFromJsonObjectField(&rotation, azrtti_typeid<decltype(rotation)>(), inputValue, RotationTag, context);
|
||||
|
||||
result.Combine(loadResult);
|
||||
|
||||
transformInstance->SetRotation(rotation);
|
||||
}
|
||||
|
||||
{
|
||||
// Scale is transitioning to a single uniform scale value, but since it's still internally represented as a Vector3,
|
||||
// we need to pick one number to use for load/store operations.
|
||||
float scale = transformInstance->GetScale().GetMaxElement();
|
||||
|
||||
JSR::ResultCode loadResult =
|
||||
ContinueLoadingFromJsonObjectField(&scale, azrtti_typeid<decltype(scale)>(), inputValue, ScaleTag, context);
|
||||
|
||||
result.Combine(loadResult);
|
||||
|
||||
transformInstance->SetScale(AZ::Vector3(scale));
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Transform information."
|
||||
: "Failed to load Transform information.");
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result JsonTransformSerializer::Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
if (azrtti_typeid<AZ::Transform>() != valueTypeId)
|
||||
{
|
||||
return context.Report(
|
||||
JSR::Tasks::WriteValue, JSR::Outcomes::Unsupported,
|
||||
"Unable to Serialize Transform to json because the valueTypeId isn't a Transform type.");
|
||||
}
|
||||
|
||||
const AZ::Transform* transformInstance = reinterpret_cast<const AZ::Transform*>(inputValue);
|
||||
AZ_Assert(transformInstance, "Input value for JsonTransformSerializer can't be null.");
|
||||
const AZ::Transform* defaultTransformInstance = reinterpret_cast<const AZ::Transform*>(defaultValue);
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subPathName(context, TranslationTag);
|
||||
const AZ::Vector3 translation = transformInstance->GetTranslation();
|
||||
const AZ::Vector3 defaultTranslation = defaultTransformInstance ? defaultTransformInstance->GetTranslation() : AZ::Vector3();
|
||||
|
||||
JSR::ResultCode storeResult = ContinueStoringToJsonObjectField(
|
||||
outputValue, TranslationTag, &translation, defaultTransformInstance ? &defaultTranslation : nullptr,
|
||||
azrtti_typeid<decltype(translation)>(), context);
|
||||
|
||||
result.Combine(storeResult);
|
||||
}
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subPathName(context, RotationTag);
|
||||
const AZ::Quaternion rotation = transformInstance->GetRotation();
|
||||
const AZ::Quaternion defaultRotation = defaultTransformInstance ? defaultTransformInstance->GetRotation() : AZ::Quaternion();
|
||||
|
||||
JSR::ResultCode storeResult = ContinueStoringToJsonObjectField(
|
||||
outputValue, RotationTag, &rotation, defaultTransformInstance ? &defaultRotation : nullptr,
|
||||
azrtti_typeid<decltype(rotation)>(), context);
|
||||
|
||||
result.Combine(storeResult);
|
||||
}
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subPathName(context, ScaleTag);
|
||||
|
||||
// Scale is transitioning to a single uniform scale value, but since it's still internally represented as a Vector3,
|
||||
// we need to pick one number to use for load/store operations.
|
||||
float scale = transformInstance->GetScale().GetMaxElement();
|
||||
float defaultScale = defaultTransformInstance ? defaultTransformInstance->GetScale().GetMaxElement() : 0.0f;
|
||||
|
||||
JSR::ResultCode storeResult = ContinueStoringToJsonObjectField(
|
||||
outputValue, ScaleTag, &scale, defaultTransformInstance ? &defaultScale : nullptr, azrtti_typeid<decltype(scale)>(),
|
||||
context);
|
||||
|
||||
result.Combine(storeResult);
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored Transform information."
|
||||
: "Failed to store Transform information.");
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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/Serialization/Json/BaseJsonSerializer.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class JsonTransformSerializer : public BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(JsonTransformSerializer, "{51C321B8-9214-4E85-AA5C-B720428A3B17}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
JsonSerializationResult::Result Load(
|
||||
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
JsonDeserializerContext& context) override;
|
||||
|
||||
JsonSerializationResult::Result Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context) override;
|
||||
|
||||
private:
|
||||
// Note: These need to be defined as "const char[]" instead of "const char*" so that they can be implicitly converted
|
||||
// to a rapidjson::GenericStringRef<>. (This also lets rapidjson get the string length at compile time)
|
||||
static inline constexpr const char TranslationTag[] = "Translation";
|
||||
static inline constexpr const char RotationTag[] = "Rotation";
|
||||
static inline constexpr const char ScaleTag[] = "Scale";
|
||||
};
|
||||
|
||||
} // namespace AZ
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <AzCore/std/any.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -195,7 +196,9 @@ namespace AZ
|
||||
context.GetSerializeContext()->FindClassData(classElement.m_typeId);
|
||||
if (!elementClassData)
|
||||
{
|
||||
return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, "Failed to retrieve serialization information.");
|
||||
return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
|
||||
AZStd::string::format("Failed to retrieve serialization information for type %s.",
|
||||
classElement.m_typeId.ToString<AZStd::fixed_string<AZ::Uuid::MaxStringBuffer>>().c_str()));
|
||||
}
|
||||
if (!elementClassData->m_azRtti)
|
||||
{
|
||||
|
||||
@@ -709,7 +709,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
}
|
||||
|
||||
void MergeSettingsToRegistry_UserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
void MergeSettingsToRegistry_ProjectUserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
|
||||
{
|
||||
// Unlike other paths, the path can't be overwritten by the dev settings because that would create a circular dependency.
|
||||
@@ -721,6 +721,16 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
}
|
||||
|
||||
void MergeSettingsToRegistry_O3deUserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
|
||||
{
|
||||
if (AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory(); !o3deUserPath.empty())
|
||||
{
|
||||
o3deUserPath /= SettingsRegistryInterface::RegistryFolder;
|
||||
registry.MergeSettingsFolder(o3deUserPath.Native(), specializations, platform, "", scratchBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands)
|
||||
{
|
||||
// Iterate over all the command line options in order to parse the --regset and --regremove
|
||||
|
||||
@@ -171,7 +171,14 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
|
||||
//! Adds the development settings added by individual users of the project to the Settings Registry.
|
||||
//! Note that this function is only called in development builds and is compiled out in release builds.
|
||||
void MergeSettingsToRegistry_UserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
void MergeSettingsToRegistry_ProjectUserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
|
||||
|
||||
//! Adds the user settings from the users home directory of "~/.o3de/Registry"
|
||||
//! '~' corresponds to %USERPROFILE% on Windows and $HOME on Unix-like platforms(Linux, Mac)
|
||||
//! Note that this function is only called in development builds and is compiled out in release builds.
|
||||
//! It is merged before the command line settings are merged so that the command line always takes precedence
|
||||
void MergeSettingsToRegistry_O3deUserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
|
||||
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
|
||||
|
||||
//! Adds the settings set through the command line to the Settings Registry. This will also execute any Settings
|
||||
|
||||
@@ -42,6 +42,30 @@ namespace AZ::Utils
|
||||
return result.m_pathStored;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetExecutableDirectory()
|
||||
{
|
||||
AZ::IO::FixedMaxPathString executableDirectory;
|
||||
if(GetExecutableDirectory(executableDirectory.data(), executableDirectory.capacity())
|
||||
== ExecutablePathResult::Success)
|
||||
{
|
||||
// Updated the size field within the fixed string by using char_traits to calculate the string length
|
||||
executableDirectory.resize_no_construct(AZStd::char_traits<char>::length(executableDirectory.data()));
|
||||
}
|
||||
|
||||
return executableDirectory;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
{
|
||||
AZ::IO::FixedMaxPath o3deManifestPath = GetO3deManifestDirectory();
|
||||
if (!o3deManifestPath.empty())
|
||||
{
|
||||
o3deManifestPath /= "o3de_manifest.json";
|
||||
}
|
||||
|
||||
return o3deManifestPath.Native();
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEnginePath()
|
||||
{
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
|
||||
|
||||
@@ -76,6 +76,9 @@ namespace AZ
|
||||
//! @returns a result object that indicates if the executable directory was able to be stored within the buffer
|
||||
ExecutablePathResult GetExecutableDirectory(char* exeStorageBuffer, size_t exeStorageSize);
|
||||
|
||||
//! Retrieves the full path of the directroy containing the executable
|
||||
AZ::IO::FixedMaxPathString GetExecutableDirectory();
|
||||
|
||||
//! Retrieves the full path to the engine from settings registry
|
||||
AZ::IO::FixedMaxPathString GetEnginePath();
|
||||
|
||||
@@ -85,6 +88,9 @@ namespace AZ
|
||||
//! Retrieves the project name from the settings registry
|
||||
AZ::SettingsRegistryInterface::FixedValueString GetProjectName();
|
||||
|
||||
//! Retrieves the full directory to the O3DE manifest directory, i.e. "<userhome>/.o3de"
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory();
|
||||
|
||||
//! Retrieves the full path where the manifest file lives, i.e. "<userhome>/.o3de/o3de_manifest.json"
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath();
|
||||
|
||||
|
||||
@@ -332,6 +332,8 @@ set(FILES
|
||||
Math/Transform.cpp
|
||||
Math/Transform.h
|
||||
Math/Transform.inl
|
||||
Math/TransformSerializer.cpp
|
||||
Math/TransformSerializer.h
|
||||
Math/Uuid.cpp
|
||||
Math/Uuid.h
|
||||
Math/UuidSerializer.h
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AZStd
|
||||
* therefore an empty class in C++ has size of 1 byte.
|
||||
* From the C++20 draft chapter 10, note 5
|
||||
* "[Note: Complete objects of class type have nonzero size. Base class subobjects and "
|
||||
* "members declared with the no_unique_address attribute ([dcl.attr.nouniqueaddr]) are not so constrained. —end note]"
|
||||
* "members declared with the no_unique_address attribute ([dcl.attr.nouniqueaddr]) are not so constrained. -end note]"
|
||||
* The Index template parameter is used to disambiguate a compressed pair containing multiple elements of the same types
|
||||
* This is used to allow multiple inheritance from 2 of the same types underlying elements
|
||||
*/
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace AZStd
|
||||
* \page Setup AZSTD Setup
|
||||
*
|
||||
* After you have the AZStd code, you need to make sure you project has add the include path to the folder where AZStd was installed. All AZStd include files are using based on
|
||||
* AZStd parent folder. For instance all includes are like this \e AZStd/base.h,"AZCore/std/containers/vector,h",etc. We use use the AZStd to avoid name collisions with other
|
||||
* AZStd parent folder. For instance all includes are like this \e AZStd/base.h,"AzCore/std/containers/vector,h",etc. We use use the AZStd to avoid name collisions with other
|
||||
* stl implementations and make it obvious where the included file comes from.
|
||||
* If you decide to use the default allocator (AZStd::allocator) you will need to implement AZStd::Default_Alloc and AZStd::Default_Free functions otherwise you should
|
||||
* use your own allocator.
|
||||
|
||||
+2
-1
@@ -15,7 +15,8 @@
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, [[maybe_unused]] bool includeAllHardware)
|
||||
bool CollectIoHardwareInformation(
|
||||
HardwareInformation& info, [[maybe_unused]] bool includeAllHardware, [[maybe_unused]] bool reportHardware)
|
||||
{
|
||||
// The numbers below are based on common defaults from a local hardware survey.
|
||||
info.m_maxPageSize = 4096;
|
||||
|
||||
+2
-3
@@ -14,9 +14,8 @@
|
||||
|
||||
namespace AZ::Utils
|
||||
{
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace AZ::Utils
|
||||
} // namespace AZ::Utils
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace AZ
|
||||
|
||||
void NativeErrorMessageBox(const char*, const char*) {}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
if (const char* homePath = std::getenv("HOME"); homePath != nullptr)
|
||||
{
|
||||
@@ -33,7 +33,6 @@ namespace AZ
|
||||
if (!path.empty())
|
||||
{
|
||||
path /= ".o3de";
|
||||
path /= "o3de_manifest.json";
|
||||
}
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
+3
-1
@@ -31,6 +31,7 @@ namespace AZ::IO
|
||||
options.m_enableUnbufferedReads = m_enableUnbufferedReads;
|
||||
options.m_enableSharing = m_enableFileSharing;
|
||||
options.m_hasSeekPenalty = drive.m_hasSeekPenalty;
|
||||
options.m_minimalReporting = m_minimalReporting;
|
||||
|
||||
AZStd::vector<AZStd::string_view> drivePaths(drive.m_paths.begin(), drive.m_paths.end());
|
||||
AZ_Assert(!drive.m_paths.empty(), "Expected at least one drive path.");
|
||||
@@ -59,7 +60,8 @@ namespace AZ::IO
|
||||
->Field("MaxMetaDataCache", &WindowsStorageDriveConfig::m_maxMetaDataCache)
|
||||
->Field("Overcommit", &WindowsStorageDriveConfig::m_overcommit)
|
||||
->Field("EnableFileSharing", &WindowsStorageDriveConfig::m_enableFileSharing)
|
||||
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads);
|
||||
->Field("EnableUnbufferedReads", &WindowsStorageDriveConfig::m_enableUnbufferedReads)
|
||||
->Field("MinimalReporting", &WindowsStorageDriveConfig::m_minimalReporting);
|
||||
}
|
||||
}
|
||||
} // namespace AZ::IO
|
||||
|
||||
@@ -34,5 +34,6 @@ namespace AZ::IO
|
||||
AZ::u32 m_overcommit{ 8 };
|
||||
bool m_enableFileSharing{ false };
|
||||
bool m_enableUnbufferedReads{ true };
|
||||
bool m_minimalReporting{ false };
|
||||
};
|
||||
} // namespace AZ::IO
|
||||
|
||||
+11
-13
@@ -41,6 +41,7 @@ namespace AZ::IO
|
||||
: m_hasSeekPenalty(true)
|
||||
, m_enableUnbufferedReads(true)
|
||||
, m_enableSharing(false)
|
||||
, m_minimalReporting(false)
|
||||
{}
|
||||
|
||||
//
|
||||
@@ -102,7 +103,10 @@ namespace AZ::IO
|
||||
m_name += m_drivePaths[i].substr(0, m_drivePaths[i].length()-1);
|
||||
}
|
||||
m_name += ')';
|
||||
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
|
||||
if (!m_constructionOptions.m_minimalReporting)
|
||||
{
|
||||
AZ_Printf("Streamer", "%s created.\n", m_name.c_str());
|
||||
}
|
||||
|
||||
if (m_physicalSectorSize == 0)
|
||||
{
|
||||
@@ -160,7 +164,10 @@ namespace AZ::IO
|
||||
::CloseHandle(file);
|
||||
}
|
||||
}
|
||||
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
|
||||
if (!m_constructionOptions.m_minimalReporting)
|
||||
{
|
||||
AZ_Printf("Streamer", "%s destroyed.\n", m_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void StorageDriveWin::PrepareRequest(FileRequest* request)
|
||||
@@ -483,7 +490,7 @@ namespace AZ::IO
|
||||
// Remove any alertable IO completion notifications that could be queued by the IO Manager.
|
||||
if (!::SetFileCompletionNotificationModes(file, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
|
||||
{
|
||||
AZ_Printf("StorageDriveWin", "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
|
||||
AZ_Warning("StorageDriveWin", false, "Failed to remove alertable IO completion notifications. (Error: %u)\n", ::GetLastError());
|
||||
}
|
||||
|
||||
if (m_fileCache_handles[cacheIndex] != INVALID_HANDLE_VALUE)
|
||||
@@ -651,15 +658,6 @@ namespace AZ::IO
|
||||
#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO
|
||||
}
|
||||
|
||||
// Keep this, it helps to see the critical info about every read.
|
||||
//AZ_Printf("StorageDriveWin", "FileRead: addr: 0x%p size: %zu offs: %zu alloc: %s direct: %.2f%% '%s'\n",
|
||||
// data->m_output,
|
||||
// data->m_size,
|
||||
// data->m_offset,
|
||||
// (isAligned) ? "Yes" : "No",
|
||||
// m_directReadsPercentageStat.GetAverage() * 100.0,
|
||||
// data->m_path.GetRelativePath());
|
||||
|
||||
FileReadStatus& readStatus = m_readSlots_statusInfo[readSlot];
|
||||
LPOVERLAPPED overlapped = &readStatus.m_overlapped;
|
||||
overlapped->Offset = aznumeric_caster(readOffs);
|
||||
@@ -678,7 +676,7 @@ namespace AZ::IO
|
||||
DWORD error = ::GetLastError();
|
||||
if (error != ERROR_IO_PENDING)
|
||||
{
|
||||
AZ_Printf("StorageDriveWin", "::ReadFile failed with error: %u\n", error);
|
||||
AZ_Warning("StorageDriveWin", false, "::ReadFile failed with error: %u\n", error);
|
||||
|
||||
m_context->GetStreamerThreadSynchronizer().DestroyEventHandle(overlapped->hEvent);
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace AZ::IO
|
||||
//! while in use by AZ::IO::Streamer. File sharing can negatively impact performance and is recommended for
|
||||
//! development only.
|
||||
u8 m_enableSharing : 1;
|
||||
//! If true, only information that's explicitly requested or issues are reported. If false, status information
|
||||
//! such as when drives are created and destroyed is reported as well.
|
||||
u8 m_minimalReporting : 1;
|
||||
};
|
||||
|
||||
//! Creates an instance of a storage device that's optimized for use on Windows.
|
||||
|
||||
+107
-62
@@ -34,7 +34,7 @@ namespace AZ::IO
|
||||
return value;
|
||||
}
|
||||
|
||||
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName)
|
||||
static void CollectIoAdaptor(HANDLE deviceHandle, DriveInformation& info, const char* driveName, bool reportHardware)
|
||||
{
|
||||
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -71,17 +71,21 @@ namespace AZ::IO
|
||||
|
||||
DWORD pageSize = NextPowerOfTwo(adapterDescriptor.MaximumTransferLength / adapterDescriptor.MaximumPhysicalPages);
|
||||
|
||||
AZ_Printf("Streamer",
|
||||
"Adapter for drive '%s':\n"
|
||||
" Bus: %s %i.%i\n"
|
||||
" Max transfer: %.3f kb\n"
|
||||
" Page size: %i kb for %i pages\n"
|
||||
" Supports queuing: %s\n",
|
||||
driveName,
|
||||
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
|
||||
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
|
||||
pageSize, adapterDescriptor.MaximumPhysicalPages,
|
||||
adapterDescriptor.CommandQueueing ? "Yes" : "No");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
"Adapter for drive '%s':\n"
|
||||
" Bus: %s %i.%i\n"
|
||||
" Max transfer: %.3f kb\n"
|
||||
" Page size: %i kb for %i pages\n"
|
||||
" Supports queuing: %s\n",
|
||||
driveName,
|
||||
info.m_profile.c_str(), adapterDescriptor.BusMajorVersion, adapterDescriptor.BusMinorVersion,
|
||||
(1.0f / 1024.0f) * adapterDescriptor.MaximumTransferLength,
|
||||
pageSize, adapterDescriptor.MaximumPhysicalPages,
|
||||
adapterDescriptor.CommandQueueing ? "Yes" : "No");
|
||||
}
|
||||
|
||||
info.m_maxTransfer = adapterDescriptor.MaximumTransferLength;
|
||||
info.m_pageSize = pageSize;
|
||||
@@ -89,7 +93,7 @@ namespace AZ::IO
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void AppendDriveTypeToProfile(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
// Check for support for the TRIM command. This command is exclusively used by SSD drives so can be used to
|
||||
// tell the difference between SSD and HDD. Since these are the only 2 types supported right now, no further
|
||||
@@ -105,18 +109,24 @@ namespace AZ::IO
|
||||
&trimDescriptor, sizeof(trimDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_profile += trimDescriptor.TrimEnabled ? "_SSD" : "_HDD";
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type: %s\n",
|
||||
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
|
||||
if (reportHardware)
|
||||
{
|
||||
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type: %s\n",
|
||||
trimDescriptor.TrimEnabled ? "SSD" : "HDD");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
" Drive type couldn't be determined.");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", " Drive type couldn't be determined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectAlignmentRequirements(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -129,15 +139,19 @@ namespace AZ::IO
|
||||
{
|
||||
information.m_physicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerPhysicalSector);
|
||||
information.m_logicalSectorSize = aznumeric_caster(alignmentDescriptor.BytesPerLogicalSector);
|
||||
AZ_Printf("Streamer",
|
||||
" Physical sector size: %i bytes\n"
|
||||
" Logical sector size: %i bytes\n",
|
||||
alignmentDescriptor.BytesPerPhysicalSector,
|
||||
alignmentDescriptor.BytesPerLogicalSector);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
" Physical sector size: %i bytes\n"
|
||||
" Logical sector size: %i bytes\n",
|
||||
alignmentDescriptor.BytesPerPhysicalSector,
|
||||
alignmentDescriptor.BytesPerLogicalSector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName)
|
||||
static void CollectDriveInfo(HANDLE deviceHandle, const char* driveName, bool reportHardware)
|
||||
{
|
||||
STORAGE_DEVICE_DESCRIPTOR sizeRequest{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -154,21 +168,24 @@ namespace AZ::IO
|
||||
if (::DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
|
||||
buffer.get(), header->Size, &bytesReturned, nullptr))
|
||||
{
|
||||
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
|
||||
AZ_Printf("Streamer",
|
||||
"Drive info for '%s':\n"
|
||||
" Id: %s%s%s%s%s\n",
|
||||
driveName,
|
||||
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
|
||||
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
|
||||
if (reportHardware)
|
||||
{
|
||||
auto deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.get());
|
||||
AZ_Printf("Streamer",
|
||||
"Drive info for '%s':\n"
|
||||
" Id: %s%s%s%s%s\n",
|
||||
driveName,
|
||||
deviceDescriptor->VendorIdOffset != 0 ? buffer.get() + deviceDescriptor->VendorIdOffset : "",
|
||||
deviceDescriptor->VendorIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? buffer.get() + deviceDescriptor->ProductIdOffset : "",
|
||||
deviceDescriptor->ProductIdOffset != 0 ? " " : "",
|
||||
deviceDescriptor->ProductRevisionOffset != 0 ? buffer.get() + deviceDescriptor->ProductRevisionOffset : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectDriveIoCapability(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
STORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR capabilityDescriptor{};
|
||||
STORAGE_PROPERTY_QUERY query{};
|
||||
@@ -180,15 +197,19 @@ namespace AZ::IO
|
||||
&capabilityDescriptor, sizeof(capabilityDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_ioChannelCount = aznumeric_caster(capabilityDescriptor.LunMaxIoCount);
|
||||
AZ_Printf("Streamer",
|
||||
" Max IO count (LUN): %i\n"
|
||||
" Max IO count (Adapter): %i\n",
|
||||
capabilityDescriptor.LunMaxIoCount,
|
||||
capabilityDescriptor.AdapterMaxIoCount);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer",
|
||||
" Max IO count (LUN): %i\n"
|
||||
" Max IO count (Adapter): %i\n",
|
||||
capabilityDescriptor.LunMaxIoCount,
|
||||
capabilityDescriptor.AdapterMaxIoCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information)
|
||||
static void CollectDriveSeekPenalty(HANDLE deviceHandle, DriveInformation& information, bool reportHardware)
|
||||
{
|
||||
DWORD bytesReturned = 0;
|
||||
|
||||
@@ -201,9 +222,12 @@ namespace AZ::IO
|
||||
&seekPenaltyDescriptor, sizeof(seekPenaltyDescriptor), &bytesReturned, nullptr))
|
||||
{
|
||||
information.m_hasSeekPenalty = seekPenaltyDescriptor.IncursSeekPenalty ? true : false;
|
||||
AZ_Printf("Streamer",
|
||||
" Has seek penalty: %s\n",
|
||||
information.m_hasSeekPenalty ? "Yes" : "No");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
" Has seek penalty: %s\n",
|
||||
information.m_hasSeekPenalty ? "Yes" : "No");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -267,7 +291,7 @@ namespace AZ::IO
|
||||
return visitor.m_found;
|
||||
}
|
||||
|
||||
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives)
|
||||
static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives, bool reportHardware)
|
||||
{
|
||||
char drives[512];
|
||||
if (::GetLogicalDriveStrings(sizeof(drives) - 1, drives))
|
||||
@@ -286,7 +310,10 @@ namespace AZ::IO
|
||||
{
|
||||
if (!addAllDrives && !IsDriveUsed(driveIt))
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
|
||||
}
|
||||
while (*driveIt++);
|
||||
continue;
|
||||
}
|
||||
@@ -311,14 +338,14 @@ namespace AZ::IO
|
||||
DriveInformation driveInformation;
|
||||
driveInformation.m_paths.emplace_back(driveIt);
|
||||
|
||||
CollectIoAdaptor(deviceHandle, driveInformation, driveIt);
|
||||
CollectIoAdaptor(deviceHandle, driveInformation, driveIt, reportHardware);
|
||||
if (driveInformation.m_supportsQueuing)
|
||||
{
|
||||
CollectDriveInfo(deviceHandle, driveIt);
|
||||
AppendDriveTypeToProfile(deviceHandle, driveInformation);
|
||||
CollectDriveIoCapability(deviceHandle, driveInformation);
|
||||
CollectDriveSeekPenalty(deviceHandle, driveInformation);
|
||||
CollectAlignmentRequirements(deviceHandle, driveInformation);
|
||||
CollectDriveInfo(deviceHandle, driveIt, reportHardware);
|
||||
AppendDriveTypeToProfile(deviceHandle, driveInformation, reportHardware);
|
||||
CollectDriveIoCapability(deviceHandle, driveInformation, reportHardware);
|
||||
CollectDriveSeekPenalty(deviceHandle, driveInformation, reportHardware);
|
||||
CollectAlignmentRequirements(deviceHandle, driveInformation, reportHardware);
|
||||
|
||||
hardwareInfo.m_maxPhysicalSectorSize =
|
||||
AZStd::max(hardwareInfo.m_maxPhysicalSectorSize, driveInformation.m_physicalSectorSize);
|
||||
@@ -329,24 +356,39 @@ namespace AZ::IO
|
||||
|
||||
driveMappings.insert({ storageDeviceNumber.DeviceNumber, AZStd::move(driveInformation) });
|
||||
|
||||
AZ_Printf("Streamer", "\n");
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Skipping drive '%s' because device does not support queuing requests.\n", driveIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
|
||||
driveIt, driveInformationEntry->second.m_paths[0].c_str());
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Drive '%s' is on the same storage drive as '%s'.\n",
|
||||
driveIt, driveInformationEntry->second.m_paths[0].c_str());
|
||||
}
|
||||
driveInformationEntry->second.m_paths.emplace_back(driveIt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer",
|
||||
"Skipping drive '%s' because device is not registered with OS as a storage device.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf(
|
||||
"Streamer", "Skipping drive '%s' because device is not registered with OS as a storage device.\n",
|
||||
driveIt);
|
||||
}
|
||||
}
|
||||
::CloseHandle(deviceHandle);
|
||||
}
|
||||
@@ -358,7 +400,10 @@ namespace AZ::IO
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
|
||||
if (reportHardware)
|
||||
{
|
||||
AZ_Printf("Streamer", "Skipping drive '%s', as it the type of drive is not supported.\n", driveIt);
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next drive string. GetLogicalDriveStrings fills the target buffer with null-terminated strings, for instance
|
||||
@@ -384,9 +429,9 @@ namespace AZ::IO
|
||||
}
|
||||
}
|
||||
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware)
|
||||
bool CollectIoHardwareInformation(HardwareInformation& info, bool includeAllHardware, bool reportHardware)
|
||||
{
|
||||
if (!CollectHardwareInfo(info, includeAllHardware))
|
||||
if (!CollectHardwareInfo(info, includeAllHardware, reportHardware))
|
||||
{
|
||||
// The numbers below are based on common defaults from a local hardware survey.
|
||||
info.m_maxPageSize = 4096;
|
||||
|
||||
@@ -22,20 +22,18 @@ namespace AZ::Utils
|
||||
::MessageBox(0, message, title, MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
AZ::IO::FixedMaxPathString GetO3deManifestDirectory()
|
||||
{
|
||||
char userProfileBuffer[AZ::IO::MaxPathLength] = {0};
|
||||
char userProfileBuffer[AZ::IO::MaxPathLength]{};
|
||||
size_t variableSize = 0;
|
||||
auto err = getenv_s(&variableSize, userProfileBuffer, AZ::IO::MaxPathLength, "USERPROFILE");
|
||||
if (!err)
|
||||
{
|
||||
AZ::IO::FixedMaxPath path{userProfileBuffer};
|
||||
AZ::IO::FixedMaxPath path{ userProfileBuffer };
|
||||
path /= ".o3de";
|
||||
path /= "o3de_manifest.json";
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace AZ::Utils
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AZ::Utils
|
||||
|
||||
const char* src = [appSupportDir UTF8String];
|
||||
const size_t srcLen = strlen(src);
|
||||
if (srcLen > MaxPathLength - 1)
|
||||
if (srcLen > AZ::IO::MaxPathLength - 1)
|
||||
{
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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 <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/TransformSerializer.h>
|
||||
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
|
||||
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
|
||||
|
||||
namespace JsonSerializationTests
|
||||
{
|
||||
class JsonTransformSerializerTestDescription : public JsonSerializerConformityTestDescriptor<AZ::Transform>
|
||||
{
|
||||
public:
|
||||
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
|
||||
{
|
||||
return AZStd::make_shared<AZ::JsonTransformSerializer>();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<AZ::Transform> CreateDefaultInstance() override
|
||||
{
|
||||
return AZStd::make_shared<AZ::Transform>(AZ::Transform::CreateIdentity());
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<AZ::Transform> CreatePartialDefaultInstance() override
|
||||
{
|
||||
return AZStd::make_shared<AZ::Transform>(AZ::Transform::CreateTranslation(AZ::Vector3(1.0f, 2.0f, 3.0f)));
|
||||
}
|
||||
|
||||
AZStd::string_view GetJsonForPartialDefaultInstance() override
|
||||
{
|
||||
return "{ \"Translation\" : [ 1.0, 2.0, 3.0 ] }";
|
||||
}
|
||||
|
||||
|
||||
AZStd::shared_ptr<AZ::Transform> CreateFullySetInstance() override
|
||||
{
|
||||
return AZStd::make_shared<AZ::Transform>(
|
||||
AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), AZ::Vector3(9.0f));
|
||||
}
|
||||
|
||||
AZStd::string_view GetJsonForFullySetInstance() override
|
||||
{
|
||||
return "{ \"Translation\" : [ 1.0, 2.0, 3.0 ], \"Rotation\" : [ 0.25, 0.5, 0.75, 1.0 ], \"Scale\" : 9.0 }";
|
||||
}
|
||||
|
||||
void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
|
||||
{
|
||||
features.EnableJsonType(rapidjson::kObjectType);
|
||||
features.m_supportsPartialInitialization = true;
|
||||
features.m_supportsInjection = false;
|
||||
features.m_requiresTypeIdLookups = true;
|
||||
}
|
||||
|
||||
bool AreEqual(const AZ::Transform& lhs, const AZ::Transform& rhs) override
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
using JsonTransformSerializerConformityTestTypes = ::testing::Types<JsonTransformSerializerTestDescription>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(JsonTransformSerializer, JsonSerializerConformityTests, JsonTransformSerializerConformityTestTypes);
|
||||
|
||||
class JsonTransformSerializerTests
|
||||
: public BaseJsonSerializerFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
BaseJsonSerializerFixture::SetUp();
|
||||
m_transformSerializer = AZStd::make_unique<AZ::JsonTransformSerializer>();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_transformSerializer.reset();
|
||||
BaseJsonSerializerFixture::TearDown();
|
||||
}
|
||||
|
||||
protected:
|
||||
AZStd::unique_ptr<AZ::JsonTransformSerializer> m_transformSerializer;
|
||||
};
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithAllValuesSetCorrectly)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform(
|
||||
AZ::Vector3(2.25f, 3.5f, 4.75f),
|
||||
AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f),
|
||||
AZ::Vector3(5.5f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Rotation": [ 0.25, 0.5, 0.75, 1.0 ], "Scale": 5.5 })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::Success);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithDefaultTranslation)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform =
|
||||
AZ::Transform::CreateFromQuaternion(AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f));
|
||||
expectedTransform.SetScale(AZ::Vector3(5.5f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Rotation": [ 0.25, 0.5, 0.75, 1.0 ], "Scale": 5.5 })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithDefaultRotation)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform = AZ::Transform::CreateTranslation(AZ::Vector3(2.25f, 3.5f, 4.75f));
|
||||
expectedTransform.SetScale(AZ::Vector3(5.5f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Scale": 5.5 })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithDefaultScale)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform =
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), AZ::Vector3(2.25f, 3.5f, 4.75f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Rotation": [ 0.25, 0.5, 0.75, 1.0 ] })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithOnlyTranslation)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform = AZ::Transform::CreateTranslation(AZ::Vector3(2.25f, 3.5f, 4.75f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ] })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithOnlyRotation)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform = AZ::Transform::CreateFromQuaternion(AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Rotation": [ 0.25, 0.5, 0.75, 1.0 ] })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithOnlyScale)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform = AZ::Transform::CreateScale(AZ::Vector3(5.5f));
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({ "Scale" : 5.5 })");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::PartialDefaults);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
|
||||
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithAllDefaults)
|
||||
{
|
||||
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform expectedTransform = AZ::Transform::CreateIdentity();
|
||||
|
||||
rapidjson::Document json;
|
||||
json.Parse(R"({})");
|
||||
|
||||
ResultCode result =
|
||||
m_transformSerializer->Load(&testTransform, azrtti_typeid<decltype(testTransform)>(), json, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::DefaultsUsed);
|
||||
EXPECT_EQ(testTransform, expectedTransform);
|
||||
}
|
||||
} // namespace JsonSerializationTests
|
||||
@@ -123,6 +123,7 @@ set(FILES
|
||||
Serialization/Json/TestCases_Pointers.h
|
||||
Serialization/Json/TestCases_Pointers.cpp
|
||||
Serialization/Json/TestCases_TypeId.cpp
|
||||
Serialization/Json/TransformSerializerTests.cpp
|
||||
Serialization/Json/TupleSerializerTests.cpp
|
||||
Serialization/Json/UnorderedSetSerializerTests.cpp
|
||||
Serialization/Json/UuidSerializerTests.cpp
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace AzFramework
|
||||
|
||||
/// Execute a function in a new thread and pump the system event loop at the specified frequency until the thread returns.
|
||||
virtual void PumpSystemEventLoopWhileDoingWorkInNewThread(const AZStd::chrono::milliseconds& /*eventPumpFrequency*/,
|
||||
const AZStd::function<void()>& /*workForNewThread*/,
|
||||
const char* /*newThreadName*/) {}
|
||||
const AZStd::function<void()>& /*workForNewThread*/,
|
||||
const char* /*newThreadName*/) {}
|
||||
|
||||
/// Run the main loop until ExitMainLoop is called.
|
||||
virtual void RunMainLoop() {}
|
||||
@@ -114,6 +114,21 @@ namespace AzFramework
|
||||
/// Calculate the branch token from the current application's engine root
|
||||
virtual void CalculateBranchTokenForEngineRoot(AZStd::string& token) const = 0;
|
||||
|
||||
/// Returns true if Prefab System is enabled, false if Legacy Slice System is enabled
|
||||
virtual bool IsPrefabSystemEnabled() const { return true; }
|
||||
|
||||
/// Returns true if the additional work in progress Prefab features are enabled, false otherwise
|
||||
virtual bool ArePrefabWipFeaturesEnabled() const { return false; }
|
||||
|
||||
/// Sets whether or not the Prefab System should be enabled. The application will need to be restarted when this changes
|
||||
virtual void SetPrefabSystemEnabled([[maybe_unused]] bool enable) {}
|
||||
|
||||
/// Returns true if Prefab System is enabled for use with levels, false if legacy level system is enabled (level.pak)
|
||||
virtual bool IsPrefabSystemForLevelsEnabled() const { return false; }
|
||||
|
||||
/// Returns true if code should assert when the Legacy Slice System is used
|
||||
virtual bool ShouldAssertForLegacySlicesUsage() const { return false; }
|
||||
|
||||
/*!
|
||||
* Returns a Type Uuid of the component for the given componentId and entityId.
|
||||
* if no component matches the entity and component Id pair, a Null Uuid is returned
|
||||
|
||||
@@ -89,6 +89,10 @@ namespace AzFramework
|
||||
{
|
||||
namespace ApplicationInternal
|
||||
{
|
||||
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
|
||||
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
|
||||
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
|
||||
|
||||
// A Helper function that can load an app descriptor from file.
|
||||
AZ::Outcome<AZStd::unique_ptr<AZ::ComponentApplication::Descriptor>, AZStd::string> LoadDescriptorFromFilePath(const char* appDescriptorFilePath, AZ::SerializeContext& serializeContext)
|
||||
{
|
||||
@@ -411,9 +415,10 @@ namespace AzFramework
|
||||
// UserSettingsFileLocatorBus
|
||||
AZStd::string Application::ResolveFilePath([[maybe_unused]] AZ::u32 providerId)
|
||||
{
|
||||
AZStd::string result;
|
||||
AzFramework::StringFunc::Path::Join(GetEngineRoot(), "UserSettings.xml", result, /*bCaseInsenitive*/false);
|
||||
return result;
|
||||
AZ::IO::Path userSettingsPath;
|
||||
m_settingsRegistry->Get(userSettingsPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
userSettingsPath /= "UserSettings.xml";
|
||||
return userSettingsPath.Native();
|
||||
}
|
||||
|
||||
AZ::Component* Application::EnsureComponentAdded(AZ::Entity* systemEntity, const AZ::Uuid& typeId)
|
||||
@@ -779,4 +784,47 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::IsPrefabSystemEnabled() const
|
||||
{
|
||||
bool value = true;
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->Get(value, ApplicationInternal::s_prefabSystemKey);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool Application::ArePrefabWipFeaturesEnabled() const
|
||||
{
|
||||
bool value = false;
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->Get(value, ApplicationInternal::s_prefabWipSystemKey);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void Application::SetPrefabSystemEnabled(bool enable)
|
||||
{
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->Set(ApplicationInternal::s_prefabSystemKey, enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::IsPrefabSystemForLevelsEnabled() const
|
||||
{
|
||||
return IsPrefabSystemEnabled();
|
||||
}
|
||||
|
||||
bool Application::ShouldAssertForLegacySlicesUsage() const
|
||||
{
|
||||
bool value = false;
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->Get(value, ApplicationInternal::s_legacySlicesAssertKey);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -104,6 +104,11 @@ namespace AzFramework
|
||||
const char* GetAppRoot() const override;
|
||||
void ResolveEnginePath(AZStd::string& engineRelativePath) const override;
|
||||
void CalculateBranchTokenForEngineRoot(AZStd::string& token) const override;
|
||||
bool IsPrefabSystemEnabled() const override;
|
||||
bool ArePrefabWipFeaturesEnabled() const override;
|
||||
void SetPrefabSystemEnabled(bool enable) override;
|
||||
bool IsPrefabSystemForLevelsEnabled() const override;
|
||||
bool ShouldAssertForLegacySlicesUsage() const override;
|
||||
|
||||
#pragma push_macro("GetCommandLine")
|
||||
#undef GetCommandLine
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Asset/AssetBundleManifest.h>
|
||||
#include <AzFramework/Asset/AssetRegistry.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
@@ -1506,35 +1507,48 @@ namespace AZ::IO
|
||||
|
||||
auto bundleManifest = GetBundleManifest(desc.pZip);
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog;
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
if (bundleManifest)
|
||||
{
|
||||
bundleCatalog = GetBundleCatalog(desc.pZip, bundleManifest->GetCatalogName());
|
||||
}
|
||||
|
||||
if (addLevels)
|
||||
{
|
||||
// Note that manifest version two and above will contain level directory information inside them
|
||||
// otherwise we will fallback to scanning the archive for levels.
|
||||
if (bundleManifest && bundleManifest->GetBundleVersion() >= 2)
|
||||
{
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
levelDirs = bundleManifest->GetLevelDirectories();
|
||||
}
|
||||
else
|
||||
if (usePrefabSystemForLevels)
|
||||
{
|
||||
m_arrZips.insert(revItZip.base(), desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
|
||||
if (addLevels)
|
||||
{
|
||||
levelDirs = ScanForLevels(desc.pZip);
|
||||
// Note that manifest version two and above will contain level directory information inside them
|
||||
// otherwise we will fallback to scanning the archive for levels.
|
||||
if (bundleManifest && bundleManifest->GetBundleVersion() >= 2)
|
||||
{
|
||||
levelDirs = bundleManifest->GetLevelDirectories();
|
||||
}
|
||||
else
|
||||
{
|
||||
levelDirs = ScanForLevels(desc.pZip);
|
||||
}
|
||||
}
|
||||
|
||||
if (!levelDirs.empty())
|
||||
{
|
||||
desc.m_containsLevelPak = true;
|
||||
}
|
||||
|
||||
m_arrZips.insert(revItZip.base(), desc);
|
||||
|
||||
m_levelOpenEvent.Signal(levelDirs);
|
||||
}
|
||||
|
||||
if (!levelDirs.empty())
|
||||
{
|
||||
desc.m_containsLevelPak = true;
|
||||
}
|
||||
|
||||
m_arrZips.insert(revItZip.base(), desc);
|
||||
|
||||
m_levelOpenEvent.Signal(levelDirs);
|
||||
AZ::IO::ArchiveNotificationBus::Broadcast([](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName,
|
||||
AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest, const char* nextBundle, AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog)
|
||||
{
|
||||
@@ -1555,10 +1569,13 @@ namespace AZ::IO
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
AZStd::unique_lock lock(m_csZips);
|
||||
for (auto it = m_arrZips.begin(); it != m_arrZips.end();)
|
||||
{
|
||||
bool needRescan = false;
|
||||
if (azstricmp(szZipPath->c_str(), it->GetFullPath()) == 0)
|
||||
{
|
||||
// this is the pack with the given name - remove it, and if possible it will be deleted
|
||||
@@ -1571,16 +1588,25 @@ namespace AZ::IO
|
||||
archiveNotifications->BundleClosed(bundleName);
|
||||
}, it->GetFullPath());
|
||||
|
||||
if (it->m_containsLevelPak)
|
||||
if (usePrefabSystemForLevels)
|
||||
{
|
||||
needRescan = true;
|
||||
it = m_arrZips.erase(it);
|
||||
}
|
||||
|
||||
it = m_arrZips.erase(it);
|
||||
|
||||
if (needRescan)
|
||||
else
|
||||
{
|
||||
m_levelCloseEvent.Signal(szZipPath->Native());
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
bool needRescan = false;
|
||||
if (it->m_containsLevelPak)
|
||||
{
|
||||
needRescan = true;
|
||||
}
|
||||
|
||||
it = m_arrZips.erase(it);
|
||||
|
||||
if (needRescan)
|
||||
{
|
||||
m_levelCloseEvent.Signal(szZipPath->Native());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -120,6 +120,8 @@ namespace AZ::IO
|
||||
{
|
||||
AZ::IO::Path m_pathBindRoot; // the zip binding root
|
||||
AZStd::string strFileName; // the zip file name (with path) - very useful for debugging so please don't remove
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
bool m_containsLevelPak = false; // indicates whether this archive has level.pak inside it or not
|
||||
|
||||
const char* GetFullPath() const { return pZip->GetFilePath(); }
|
||||
@@ -199,6 +201,7 @@ namespace AZ::IO
|
||||
|
||||
bool IsInstalledToHDD(AZStd::string_view acFilePath = 0) const override;
|
||||
|
||||
// [LYN-2376] Remove 'addLevels' parameter once legacy slice support is removed
|
||||
bool OpenPack(AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
|
||||
bool OpenPack(AZStd::string_view szBindRoot, AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override;
|
||||
// after this call, the file will be unlocked and closed, and its contents won't be used to search for files
|
||||
@@ -300,7 +303,8 @@ namespace AZ::IO
|
||||
|
||||
EStreamSourceMediaType GetFileMediaType(AZStd::string_view szName) const override;
|
||||
|
||||
auto GetLevelPackOpenEvent()->LevelPackOpenEvent* override;
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
auto GetLevelPackOpenEvent() -> LevelPackOpenEvent* override;
|
||||
auto GetLevelPackCloseEvent()->LevelPackCloseEvent* override;
|
||||
|
||||
|
||||
@@ -336,6 +340,8 @@ namespace AZ::IO
|
||||
//! Return the Manifest from a bundle, if it exists
|
||||
AZStd::shared_ptr<AzFramework::AssetBundleManifest> GetBundleManifest(ZipDir::CachePtr pZip);
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> GetBundleCatalog(ZipDir::CachePtr pZip, const AZStd::string& catalogName);
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
AZStd::vector<AZStd::string> ScanForLevels(ZipDir::CachePtr pZip);
|
||||
|
||||
mutable AZStd::shared_mutex m_csOpenFiles;
|
||||
@@ -362,6 +368,8 @@ namespace AZ::IO
|
||||
RecordedFilesSet m_recordedFilesSet;
|
||||
|
||||
AZStd::intrusive_ptr<IResourceList> m_pEngineStartupResourceList;
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
AZStd::intrusive_ptr<IResourceList> m_pLevelResourceList;
|
||||
AZStd::intrusive_ptr<IResourceList> m_pNextLevelResourceList;
|
||||
|
||||
@@ -378,6 +386,8 @@ namespace AZ::IO
|
||||
AZStd::fixed_string<128> m_sLocalizationRoot;
|
||||
|
||||
AZStd::set<uint32_t, AZStd::less<>, AZ::OSStdAllocator> m_filesCachedOnHDD;
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
LevelPackOpenEvent m_levelOpenEvent;
|
||||
LevelPackCloseEvent m_levelCloseEvent;
|
||||
};
|
||||
|
||||
@@ -17,17 +17,28 @@
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
#include <AzFramework/Archive/ZipDirFind.h>
|
||||
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
bool AZStdStringLessCaseInsensitive::operator()(AZStd::string_view left, AZStd::string_view right) const
|
||||
{
|
||||
// If one or both strings are 0-length, return true if the left side is smaller, false if they're equal or left is larger.
|
||||
size_t compareLength = (AZStd::min)(left.size(), right.size());
|
||||
if (compareLength == 0)
|
||||
{
|
||||
return left.size() < right.size();
|
||||
}
|
||||
|
||||
// They're both non-zero, so compare the strings up until the length of the shorter string.
|
||||
int compareResult = azstrnicmp(left.data(), right.data(), compareLength);
|
||||
|
||||
// If both strings are equal for the number of characters compared, return true if the left side is shorter, false if
|
||||
// they're equal or left is longer.
|
||||
if (compareResult == 0)
|
||||
{
|
||||
return left.size() < right.size();
|
||||
}
|
||||
|
||||
// Return true if the left side should come first alphabetically, false if the right side should.
|
||||
return compareResult < 0;
|
||||
}
|
||||
|
||||
@@ -124,7 +135,8 @@ namespace AZ::IO
|
||||
fileDesc.tAccess = fileDesc.tWrite;
|
||||
fileDesc.tCreate = fileDesc.tWrite;
|
||||
}
|
||||
m_mapFiles.emplace(AZStd::move(fullFilePath), fileDesc);
|
||||
[[maybe_unused]] auto result = m_mapFiles.emplace(AZStd::move(fullFilePath), fileDesc);
|
||||
AZ_Assert(result.second, "Failed to insert FindData entry for %s", fullFilePath.c_str());
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace Camera
|
||||
{
|
||||
//! Stores camera configuration values that describe the camera's view frustum.
|
||||
struct Configuration
|
||||
{
|
||||
float m_fovRadians = 0.f;
|
||||
@@ -25,114 +26,83 @@ namespace Camera
|
||||
float m_frustumHeight = 0.f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this bus to send messages to a camera component on an entity
|
||||
* If you create your own camera you should implement this bus
|
||||
* Call like this:
|
||||
* Camera::CameraRequestBus::Event(cameraEntityId, &Camera::CameraRequestBus::Events::SetFov, newFov);
|
||||
*/
|
||||
//! Use this bus to send messages to a camera component on an entity
|
||||
//! If you create your own camera you should implement this bus
|
||||
//! Call like this:
|
||||
//! Camera::CameraRequestBus::Event(cameraEntityId, &Camera::CameraRequestBus::Events::SetFov, newFov);
|
||||
class CameraComponentRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
virtual ~CameraComponentRequests() = default;
|
||||
/**
|
||||
* Gets the camera's field of view in degrees
|
||||
* @return The camera's field of view in degrees
|
||||
*/
|
||||
//! Gets the camera's field of view in degrees
|
||||
//! @return The camera's field of view in degrees
|
||||
virtual float GetFov()
|
||||
{
|
||||
AZ_WarningOnce("CameraBus", false, "GetFov is deprecated. Please use GetFovDegrees or GetFovRadians.");
|
||||
return GetFovDegrees();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the camera's field of view in degrees
|
||||
* @return The camera's field of view in degrees
|
||||
*/
|
||||
//! Gets the camera's field of view in degrees
|
||||
//! @return The camera's field of view in degrees
|
||||
virtual float GetFovDegrees() = 0;
|
||||
|
||||
/**
|
||||
* Gets the camera's field of view in radians
|
||||
* @return The camera's field of view in radians
|
||||
*/
|
||||
//! Gets the camera's field of view in radians
|
||||
//! @return The camera's field of view in radians
|
||||
virtual float GetFovRadians() = 0;
|
||||
|
||||
/**
|
||||
* Gets the camera's distance from the near clip plane in meters
|
||||
* @return The camera's distance from the near clip plane in meters
|
||||
*/
|
||||
//! Gets the camera's distance from the near clip plane in meters
|
||||
//! @return The camera's distance from the near clip plane in meters
|
||||
virtual float GetNearClipDistance() = 0;
|
||||
|
||||
/**
|
||||
* Gets the camera's distance from the far clip plane in meters
|
||||
* @return The camera's distance from the far clip plane in meters
|
||||
*/
|
||||
//! Gets the camera's distance from the far clip plane in meters
|
||||
//! @return The camera's distance from the far clip plane in meters
|
||||
virtual float GetFarClipDistance() = 0;
|
||||
|
||||
/**
|
||||
* Gets the camera frustum's width
|
||||
* @return The camera frustum's width
|
||||
*/
|
||||
//! Gets the camera frustum's width
|
||||
//! @return The camera frustum's width
|
||||
virtual float GetFrustumWidth() = 0;
|
||||
|
||||
/**
|
||||
* Gets the camera frustum's height
|
||||
* @return The camera frustum's height
|
||||
*/
|
||||
//! Gets the camera frustum's height
|
||||
//! @return The camera frustum's height
|
||||
virtual float GetFrustumHeight() = 0;
|
||||
|
||||
/**
|
||||
* Sets the camera's field of view in degrees between 0 < fov < 180 degrees
|
||||
* @param fov The camera frustum's new field of view in degrees
|
||||
*/
|
||||
//! Sets the camera's field of view in degrees between 0 < fov < 180 degrees
|
||||
//! @param fov The camera frustum's new field of view in degrees
|
||||
virtual void SetFov(float fov)
|
||||
{
|
||||
AZ_WarningOnce("CameraBus", false, "SetFov is deprecated. Please use SetFovDegrees or SetFovRadians.");
|
||||
SetFovDegrees(fov);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera's field of view in degrees between 0 < fov < 180 degrees
|
||||
* @param fov The camera frustum's new field of view in degrees
|
||||
*/
|
||||
//! Sets the camera's field of view in degrees between 0 < fov < 180 degrees
|
||||
//! @param fov The camera frustum's new field of view in degrees
|
||||
virtual void SetFovDegrees(float fovInDegrees) = 0;
|
||||
|
||||
/**
|
||||
* Sets the camera's field of view in radians between 0 < fov < pi radians
|
||||
* @param fov The camera frustum's new field of view in radians
|
||||
*/
|
||||
//! Sets the camera's field of view in radians between 0 < fov < pi radians
|
||||
//! @param fov The camera frustum's new field of view in radians
|
||||
virtual void SetFovRadians(float fovInRadians) = 0;
|
||||
|
||||
/**
|
||||
* Sets the near clip plane to a given distance from the camera in meters. Should be small, but greater than 0
|
||||
* @param nearClipDistance The camera frustum's new near clip plane distance from camera
|
||||
*/
|
||||
//! Sets the near clip plane to a given distance from the camera in meters. Should be small, but greater than 0
|
||||
//! @param nearClipDistance The camera frustum's new near clip plane distance from camera
|
||||
virtual void SetNearClipDistance(float nearClipDistance) = 0;
|
||||
|
||||
/**
|
||||
* Sets the far clip plane to a given distance from the camera in meters.
|
||||
* @param farClipDistance The camera frustum's new far clip plane distance from camera
|
||||
*/
|
||||
//! Sets the far clip plane to a given distance from the camera in meters.
|
||||
//! @param farClipDistance The camera frustum's new far clip plane distance from camera
|
||||
virtual void SetFarClipDistance(float farClipDistance) = 0;
|
||||
|
||||
/**
|
||||
* Sets the camera frustum's width
|
||||
* @param width The camera frustum's new width
|
||||
*/
|
||||
//! Sets the camera frustum's width
|
||||
//! @param width The camera frustum's new width
|
||||
virtual void SetFrustumWidth(float width) = 0;
|
||||
|
||||
/**
|
||||
* Sets the camera frustum's height
|
||||
* @param height The camera frustum's new height
|
||||
*/
|
||||
//! Sets the camera frustum's height
|
||||
//! @param height The camera frustum's new height
|
||||
virtual void SetFrustumHeight(float height) = 0;
|
||||
|
||||
/**
|
||||
* Makes the camera the active view
|
||||
*/
|
||||
//! Makes the camera the active view
|
||||
virtual void MakeActiveView() = 0;
|
||||
|
||||
//! Get the camera frustum's aggregate configuration
|
||||
virtual Configuration GetCameraConfiguration()
|
||||
{
|
||||
return Configuration
|
||||
@@ -147,14 +117,11 @@ namespace Camera
|
||||
};
|
||||
using CameraRequestBus = AZ::EBus<CameraComponentRequests>;
|
||||
|
||||
/**
|
||||
* Use this broadcast bus to gather a list of all active cameras
|
||||
* If you create your own camera you should handle this bus
|
||||
* Call like this:
|
||||
*
|
||||
* AZ::EBusAggregateResults<AZ::EntityId> results;
|
||||
* Camera::CameraBus::BroadcastResult(results, &Camera::CameraRequests::GetCameras);
|
||||
*/
|
||||
//! Use this broadcast bus to gather a list of all active cameras
|
||||
//! If you create your own camera you should handle this bus
|
||||
//! Call like this:
|
||||
//! AZ::EBusAggregateResults<AZ::EntityId> results;
|
||||
//! Camera::CameraBus::BroadcastResult(results, &Camera::CameraRequests::GetCameras);
|
||||
class CameraRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
@@ -166,18 +133,14 @@ namespace Camera
|
||||
};
|
||||
using CameraBus = AZ::EBus<CameraRequests>;
|
||||
|
||||
/**
|
||||
* Use this system broadcast for things like getting the active camera
|
||||
*/
|
||||
//! Use this system broadcast for things like getting the active camera
|
||||
class CameraSystemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
virtual ~CameraSystemRequests() = default;
|
||||
|
||||
/**
|
||||
* returns the camera being used by the active view
|
||||
*/
|
||||
//! returns the camera being used by the active view
|
||||
virtual AZ::EntityId GetActiveCamera() = 0;
|
||||
};
|
||||
using CameraSystemRequestBus = AZ::EBus<CameraSystemRequests>;
|
||||
@@ -198,13 +161,11 @@ namespace Camera
|
||||
};
|
||||
using ActiveCameraRequestBus = AZ::EBus<ActiveCameraRequests>;
|
||||
|
||||
/**
|
||||
* Handle this bus if you want to know when cameras are added or removed during edit or run time
|
||||
* You will get an OnCameraAdded event for each camera that is already active
|
||||
* If you create your own camera you should call this bus on activation/deactivation
|
||||
* Connect to the bus like this
|
||||
* Camera::CameraNotificationBus::Handler::Connect()
|
||||
*/
|
||||
//! Handle this bus if you want to know when cameras are added or removed during edit or run time
|
||||
//! You will get an OnCameraAdded event for each camera that is already active
|
||||
//! If you create your own camera you should call this bus on activation/deactivation
|
||||
//! Connect to the bus like this
|
||||
//! Camera::CameraNotificationBus::Handler::Connect()
|
||||
class CameraNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
@@ -223,28 +184,33 @@ namespace Camera
|
||||
{
|
||||
handler->OnCameraAdded(cameraId);
|
||||
}
|
||||
|
||||
AZ::EntityId activeView;
|
||||
CameraSystemRequestBus::BroadcastResult(activeView, &CameraSystemRequestBus::Events::GetActiveCamera);
|
||||
if (activeView.IsValid())
|
||||
{
|
||||
handler->OnActiveViewChanged(activeView);
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* If the camera is active when a handler connects to the bus,
|
||||
* then OnCameraAdded() is immediately dispatched.
|
||||
*/
|
||||
//! If the camera is active when a handler connects to the bus,
|
||||
//! then OnCameraAdded() is immediately dispatched.
|
||||
template<class Bus>
|
||||
using ConnectionPolicy = CameraNotificationConnectionPolicy<Bus>;
|
||||
|
||||
virtual ~CameraNotifications() = default;
|
||||
|
||||
/**
|
||||
* Called whenever a camera entity is added
|
||||
* @param cameraId The id of the camera added
|
||||
*/
|
||||
virtual void OnCameraAdded(const AZ::EntityId& cameraId) = 0;
|
||||
//! Called whenever a camera entity is added
|
||||
//! @param cameraId The id of the camera added
|
||||
virtual void OnCameraAdded(const AZ::EntityId& /*cameraId*/) {}
|
||||
|
||||
/**
|
||||
* Called whenever a camera entity is removed
|
||||
* @param cameraId The id of the camera removed
|
||||
*/
|
||||
virtual void OnCameraRemoved(const AZ::EntityId& cameraId) = 0;
|
||||
//! Called whenever a camera entity is removed
|
||||
//! @param cameraId The id of the camera removed
|
||||
virtual void OnCameraRemoved(const AZ::EntityId& /*cameraId*/) {}
|
||||
|
||||
//! Called whenever the active camera entity changes
|
||||
//! @param cameraId The id of the newly activated camera
|
||||
virtual void OnActiveViewChanged(const AZ::EntityId&) {}
|
||||
};
|
||||
using CameraNotificationBus = AZ::EBus<CameraNotifications>;
|
||||
|
||||
|
||||
@@ -44,10 +44,7 @@ namespace AzFramework
|
||||
incompatible.push_back(AZ_CRC_CE("LookAtService"));
|
||||
incompatible.push_back(AZ_CRC_CE("SequenceService"));
|
||||
incompatible.push_back(AZ_CRC_CE("ClothMeshService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXColliderService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXTriggerService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXJointService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXShapeColliderService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXCharacterControllerService"));
|
||||
incompatible.push_back(AZ_CRC_CE("PhysXRagdollService"));
|
||||
incompatible.push_back(AZ_CRC_CE("WhiteBoxService"));
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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 <AzFramework/Engine/Engine.h>
|
||||
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
namespace Engine
|
||||
{
|
||||
AZ::IO::FixedMaxPath FindEngineRoot(AZStd::string_view searchPath)
|
||||
{
|
||||
// File to locate
|
||||
const char engineRootMarker[] = "engine.json";
|
||||
|
||||
AZ::IO::FixedMaxPath currentSearchPath{searchPath};
|
||||
if (currentSearchPath.empty())
|
||||
{
|
||||
char executablePath[AZ_MAX_PATH_LEN];
|
||||
AZ::Utils::GetExecutablePathReturnType result = AZ::Utils::GetExecutablePath(executablePath, AZ_MAX_PATH_LEN);
|
||||
currentSearchPath = executablePath;
|
||||
}
|
||||
do
|
||||
{
|
||||
currentSearchPath = currentSearchPath.ParentPath();
|
||||
if (AZ::IO::SystemFile::Exists((currentSearchPath / engineRootMarker).c_str()))
|
||||
{
|
||||
return currentSearchPath;
|
||||
}
|
||||
} while (currentSearchPath.ParentPath() != currentSearchPath);
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
} // AzFramework
|
||||
|
||||
@@ -100,9 +100,9 @@ namespace AzFramework
|
||||
//! @param idRemapTable if remapIds is true, the provided table is filled with a map of original ids to new ids
|
||||
//! @param filterDesc any ObjectStream::LoadFlags
|
||||
//! @return whether or not the root slice was successfully loaded from the provided stream
|
||||
virtual bool LoadFromStream(AZ::IO::GenericStream& stream, bool remapIds,
|
||||
bool LoadFromStream(AZ::IO::GenericStream& stream, bool remapIds,
|
||||
EntityIdToEntityIdMap* idRemapTable = nullptr,
|
||||
const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor());
|
||||
const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor()) override;
|
||||
|
||||
//! Executes the post-add actions for the provided list of entities, like connecting to required ebuses.
|
||||
//! @param entities The entities to perform the post-add actions for.
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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 <AzFramework/Physics/World.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzFramework/Physics/Casts.h>
|
||||
#include <AzFramework/Physics/CollisionBus.h>
|
||||
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
/// This structure is used only for reflecting type vector<RayCastHit> to
|
||||
/// serialize and behavior context. It's not used in the API anywhere
|
||||
struct RaycastHitArray
|
||||
{
|
||||
AZ_TYPE_INFO(RaycastHitArray, "{BAFCC4E7-A06B-4909-B2AE-C89D9E84FE4E}");
|
||||
AZStd::vector<Physics::RayCastHit> m_hitArray;
|
||||
};
|
||||
|
||||
AZStd::vector<AZStd::pair<AzPhysics::CollisionGroup, AZStd::string>> PopulateCollisionGroups()
|
||||
{
|
||||
AZStd::vector<AZStd::pair<AzPhysics::CollisionGroup, AZStd::string>> elems;
|
||||
const AzPhysics::CollisionConfiguration& configuration = AZ::Interface<Physics::CollisionRequests>::Get()->GetCollisionConfiguration();
|
||||
for (const AzPhysics::CollisionGroups::Preset& preset : configuration.m_collisionGroups.GetPresets())
|
||||
{
|
||||
elems.push_back({ AzPhysics::CollisionGroup(preset.m_name), preset.m_name });
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
void RayCastHit::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<RayCastRequest>()
|
||||
->Field("Distance", &RayCastRequest::m_distance)
|
||||
->Field("Start", &RayCastRequest::m_start)
|
||||
->Field("Direction", &RayCastRequest::m_direction)
|
||||
->Field("Collision", &RayCastRequest::m_collisionGroup)
|
||||
->Field("QueryType", &RayCastRequest::m_queryType)
|
||||
->Field("MaxResults", &RayCastRequest::m_maxResults)
|
||||
;
|
||||
|
||||
serializeContext->Class<RayCastHit>()
|
||||
->Field("Distance", &RayCastHit::m_distance)
|
||||
->Field("Position", &RayCastHit::m_position)
|
||||
->Field("Normal", &RayCastHit::m_normal)
|
||||
;
|
||||
|
||||
serializeContext->Class<RaycastHitArray>()
|
||||
->Field("HitArray", &RaycastHitArray::m_hitArray)
|
||||
;
|
||||
|
||||
if (auto editContext = azrtti_cast<AZ::EditContext*>(serializeContext->GetEditContext()))
|
||||
{
|
||||
editContext->Enum<QueryType>("Query Type", "Object types to include in the query")
|
||||
->Value("Static", QueryType::Static)
|
||||
->Value("Dynamic", QueryType::Dynamic)
|
||||
->Value("Static and Dynamic", QueryType::StaticAndDynamic)
|
||||
;
|
||||
|
||||
editContext->Class<RayCastRequest>("RayCast Request", "Parameters for raycast")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_start, "Start", "Start position of the raycast")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_distance, "Distance", "Length of the raycast")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_direction, "Direction", "Direction of the raycast")
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &RayCastRequest::m_collisionGroup, "Collision Group", "The layers to include in the query")
|
||||
->Attribute(AZ::Edit::Attributes::EnumValues, &PopulateCollisionGroups)
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &RayCastRequest::m_queryType, "Query Type", "Object types to include in the query")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_maxResults, "Max results", "The Maximum results for this request to return, this is limited by the value set in WorldConfiguration")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<RayCastRequest>("RayCastRequest")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Distance", BehaviorValueProperty(&RayCastRequest::m_distance))
|
||||
->Property("Start", BehaviorValueProperty(&RayCastRequest::m_start))
|
||||
->Property("Direction", BehaviorValueProperty(&RayCastRequest::m_direction))
|
||||
->Property("Collision", BehaviorValueProperty(&RayCastRequest::m_collisionGroup))
|
||||
// Until enum class support for behavior context is done, expose this as an int
|
||||
->Property("QueryType", [](const RayCastRequest& self) { return static_cast<int>(self.m_queryType); },
|
||||
[](RayCastRequest& self, int newQueryType) { self.m_queryType = QueryType(newQueryType); })
|
||||
->Property("MaxResults", BehaviorValueProperty(&RayCastRequest::m_maxResults))
|
||||
;
|
||||
|
||||
behaviorContext->Class<RayCastHit>("RayCastHit")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Distance", BehaviorValueProperty(&RayCastHit::m_distance))
|
||||
->Property("Position", BehaviorValueProperty(&RayCastHit::m_position))
|
||||
->Property("Normal", BehaviorValueProperty(&RayCastHit::m_normal))
|
||||
->Property("EntityId", [](RayCastHit& result) { return result.m_body != nullptr ? result.m_body->GetEntityId() : AZ::EntityId(); }, nullptr)
|
||||
;
|
||||
|
||||
behaviorContext->Class<RaycastHitArray>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Property("HitArray", BehaviorValueProperty(&RaycastHitArray::m_hitArray))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Physics
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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 <functional>
|
||||
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
#include <AzFramework/Physics/Material.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class WorldBody;
|
||||
class Shape;
|
||||
class ShapeConfiguration;
|
||||
|
||||
/// Enum to specify the hit type returned by the filter callback.
|
||||
enum QueryHitType
|
||||
{
|
||||
None, ///< The hit should not be reported.
|
||||
Touch, ///< The hit should be reported but it should not block the query
|
||||
Block ///< The hit should be reported and it should block the query
|
||||
};
|
||||
|
||||
/// Callback used for directed scene queries: RayCasts and ShapeCasts
|
||||
using FilterCallback = AZStd::function<QueryHitType(const Physics::WorldBody* body, const Physics::Shape* shape)>;
|
||||
|
||||
/// Enum to specify which shapes are included in the query.
|
||||
enum class QueryType : int
|
||||
{
|
||||
Static, ///< Only test against static shapes
|
||||
Dynamic, ///< Only test against dynamic shapes
|
||||
StaticAndDynamic ///< Test against both static and dynamic shapes
|
||||
};
|
||||
|
||||
//! Scene query and geometry query behavior flags.
|
||||
//!
|
||||
//! HitFlags are used for 3 different purposes:
|
||||
//!
|
||||
//! 1) To request hit fields to be filled in by scene queries (such as hit position, normal, face index or UVs).
|
||||
//! 2) Once query is completed, to indicate which fields are valid (note that a query may produce more valid fields than requested).
|
||||
//! 3) To specify additional options for the narrow phase and mid-phase intersection routines.
|
||||
enum class HitFlags : AZ::u16
|
||||
{
|
||||
Position = (1 << 0), //!< "position" member of the hit is valid
|
||||
Normal = (1 << 1), //!< "normal" member of the hit is valid
|
||||
UV = (1 << 3), //!< "u" and "v" barycentric coordinates of the hit are valid. Not applicable to ShapeCast queries.
|
||||
//! Performance hint flag for ShapeCasts when it is known upfront there's no initial overlap.
|
||||
//! NOTE: using this flag may cause undefined results if shapes are initially overlapping.
|
||||
AssumeNoInitialOverlap = (1 << 4),
|
||||
MeshMultiple = (1 << 5), //!< Report all hits for meshes rather than just the first. Not applicable to ShapeCast queries.
|
||||
//! Report any first hit for meshes. If neither MeshMultiple nor MeshAny is specified,
|
||||
//! a single closest hit will be reported for meshes.
|
||||
MeshAny = (1 << 6),
|
||||
//! Report hits with back faces of mesh triangles. Also report hits for raycast
|
||||
//! originating on mesh surface and facing away from the surface normal. Not applicable to ShapeCast queries.
|
||||
MeshBothSides = (1 << 7),
|
||||
PreciseSweep = (1 << 8), //!< Use more accurate but slower narrow phase sweep tests.
|
||||
MTD = (1 << 9), //!< Report the minimum translation depth, normal and contact point.
|
||||
FaceIndex = (1 << 10), //!< "face index" member of the hit is valid. Required to get the per-face material data.
|
||||
Default = Position | Normal | FaceIndex
|
||||
};
|
||||
|
||||
/// Casts a ray from a starting pose along a direction returning objects that intersected with the ray.
|
||||
struct RayCastRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(RayCastRequest, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(RayCastRequest, "{53EAD088-A391-48F1-8370-2A1DBA31512F}");
|
||||
|
||||
float m_distance = 500.0f; ///< The distance along m_dir direction.
|
||||
AZ::Vector3 m_start = AZ::Vector3::CreateZero(); ///< World space point where ray starts from.
|
||||
AZ::Vector3 m_direction = AZ::Vector3::CreateZero(); ///< World space direction (normalized).
|
||||
AzPhysics::CollisionGroup m_collisionGroup = AzPhysics::CollisionGroup::All; ///< The layers to include in the query
|
||||
FilterCallback m_filterCallback = nullptr; ///< Hit filtering function
|
||||
QueryType m_queryType = QueryType::StaticAndDynamic; ///< Object types to include in the query
|
||||
HitFlags m_hitFlags = HitFlags::Default; ///< Query behavior flags
|
||||
AZ::u64 m_maxResults = 32; ///< The Maximum results for this request to return, this is limited by the value set in WorldConfiguration
|
||||
};
|
||||
|
||||
/// Sweeps a shape from a starting pose along a direction returning objects that intersected with the shape.
|
||||
struct ShapeCastRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(ShapeCastRequest, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(ShapeCastRequest, "{52F6C536-92F6-4C05-983D-0A74800AE56D}");
|
||||
|
||||
float m_distance = 500.0f; /// The distance to cast along m_dir direction.
|
||||
AZ::Transform m_start = AZ::Transform::CreateIdentity(); ///< World space start position. Assumes only rotation + translation (no scaling).
|
||||
AZ::Vector3 m_direction = AZ::Vector3::CreateZero(); ///< World space direction (Should be normalized)
|
||||
ShapeConfiguration* m_shapeConfiguration = nullptr; ///< Shape information.
|
||||
AzPhysics::CollisionGroup m_collisionGroup = AzPhysics::CollisionGroup::All; ///< Collision filter for the query.
|
||||
FilterCallback m_filterCallback = nullptr; ///< Hit filtering function
|
||||
QueryType m_queryType = QueryType::StaticAndDynamic; ///< Object types to include in the query
|
||||
HitFlags m_hitFlags = HitFlags::Default; ///< Query behavior flags
|
||||
AZ::u64 m_maxResults = 32; ///< The Maximum results for this request to return, this is limited by the value set in WorldConfiguration
|
||||
};
|
||||
|
||||
/// Callback used for undirected scene queries: Overlaps
|
||||
using OverlapFilterCallback = AZStd::function<bool(const Physics::WorldBody* body, const Physics::Shape* shape)>;
|
||||
|
||||
/// Searches a region enclosed by a specified shape for any overlapping objects in the scene.
|
||||
struct OverlapRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(OverlapRequest, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(OverlapRequest, "{3DC986C2-316B-4C54-A0A6-8ABBB8ABCC4A}");
|
||||
|
||||
AZ::Transform m_pose = AZ::Transform::CreateIdentity(); ///< Initial shape pose
|
||||
ShapeConfiguration* m_shapeConfiguration = nullptr; ///< Shape information.
|
||||
AzPhysics::CollisionGroup m_collisionGroup = AzPhysics::CollisionGroup::All; ///< Collision filter for the query.
|
||||
OverlapFilterCallback m_filterCallback = nullptr; ///< Hit filtering function
|
||||
QueryType m_queryType = QueryType::StaticAndDynamic; ///< Object types to include in the query
|
||||
AZ::u64 m_maxResults = 32; ///< The Maximum results for this request to return, this is limited by the value set in WorldConfiguration
|
||||
};
|
||||
|
||||
/// Structure used to store the result from either a raycast or a shape cast.
|
||||
struct RayCastHit
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(RayCastHit, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(RayCastHit, "{A46CBEA6-6B92-4809-9363-9DDF0F74F296}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
inline operator bool() const { return m_body != nullptr; }
|
||||
|
||||
float m_distance = 0.0f; ///< The distance along the cast at which the hit occurred as given by Dot(m_normal, startPoint) - Dot(m_normal, m_point).
|
||||
AZ::Vector3 m_position = AZ::Vector3::CreateZero(); ///< The position of the hit in world space
|
||||
AZ::Vector3 m_normal = AZ::Vector3::CreateZero(); ///< The normal of the surface hit
|
||||
WorldBody* m_body = nullptr; ///< World body that was hit.
|
||||
Shape* m_shape = nullptr; ///< The shape on the body that was hit
|
||||
Material* m_material = nullptr; ///< The material on the shape (or face) that was hit
|
||||
};
|
||||
|
||||
/// Overlap hit.
|
||||
struct OverlapHit
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(OverlapHit, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(OverlapHit, "{7A7201B9-67B5-438B-B4EB-F3EEBB78C617}");
|
||||
|
||||
inline operator bool() const { return m_body != nullptr; }
|
||||
|
||||
WorldBody* m_body = nullptr; ///< World body that was hit.
|
||||
Shape* m_shape = nullptr; ///< The shape on the body that was hit
|
||||
Material* m_material = nullptr; ///< The material on the shape (or face) that was hit
|
||||
};
|
||||
|
||||
/// Bitwise operators for HitFlags
|
||||
inline HitFlags operator|(HitFlags lhs, HitFlags rhs)
|
||||
{
|
||||
return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) | static_cast<AZ::u16>(rhs));
|
||||
}
|
||||
|
||||
inline HitFlags operator&(HitFlags lhs, HitFlags rhs)
|
||||
{
|
||||
return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) & static_cast<AZ::u16>(rhs));
|
||||
}
|
||||
} // namespace Physics
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(Physics::QueryType, "{0E0E56A8-73A8-40B4-B438-B19FC852E3C0}");
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<CharacterConfiguration>()
|
||||
serializeContext->Class<CharacterConfiguration, AzPhysics::SimulatedBodyConfiguration>()
|
||||
->Version(2)
|
||||
->Field("CollisionLayer", &CharacterConfiguration::m_collisionLayer)
|
||||
->Field("CollisionGroupId", &CharacterConfiguration::m_collisionGroupId)
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionLayers.h>
|
||||
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
@@ -59,11 +59,11 @@ namespace Physics
|
||||
|
||||
/// Information required to create the basic physics representation of a character.
|
||||
class CharacterConfiguration
|
||||
: public WorldBodyConfiguration
|
||||
: public AzPhysics::SimulatedBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}");
|
||||
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
|
||||
|
||||
virtual ~CharacterConfiguration() = default;
|
||||
|
||||
@@ -84,11 +84,11 @@ namespace Physics
|
||||
/// all-purpose character controller implementation. This class just abstracts some common functionality amongst
|
||||
/// typical characters, and is take-it-or-leave it style; useful as a starting point or reference.
|
||||
class Character
|
||||
: public WorldBody
|
||||
: public AzPhysics::SimulatedBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", WorldBody);
|
||||
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
|
||||
|
||||
~Character() override = default;
|
||||
|
||||
|
||||
@@ -36,7 +36,33 @@ namespace AzFramework
|
||||
public:
|
||||
virtual ~CharacterPhysicsDataNotifications() = default;
|
||||
|
||||
virtual void OnRagdollConfigurationReady() = 0;
|
||||
virtual void OnRagdollConfigurationReady(const Physics::RagdollConfiguration& ragdollConfiguration) = 0;
|
||||
|
||||
//! When connecting to this bus, if the ragdoll configuration is ready
|
||||
//! it will immediately send an OnRagdollConfigurationReady event.
|
||||
template<class Bus>
|
||||
struct ConnectionPolicy
|
||||
: public AZ::EBusConnectionPolicy<Bus>
|
||||
{
|
||||
static void Connect(
|
||||
typename Bus::BusPtr& busPtr,
|
||||
typename Bus::Context& context,
|
||||
typename Bus::HandlerNode& handler,
|
||||
typename Bus::Context::ConnectLockGuard& connectLock,
|
||||
const typename Bus::BusIdType& id = 0)
|
||||
{
|
||||
AZ::EBusConnectionPolicy<Bus>::Connect(busPtr, context, handler, connectLock, id);
|
||||
|
||||
bool ragdollConfigValid = false;
|
||||
Physics::RagdollConfiguration ragdollConfiguration;
|
||||
CharacterPhysicsDataRequestBus::EventResult(ragdollConfigValid, id,
|
||||
&CharacterPhysicsDataRequests::GetRagdollConfiguration, ragdollConfiguration);
|
||||
if (ragdollConfigValid)
|
||||
{
|
||||
handler->OnRagdollConfigurationReady(ragdollConfiguration);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
using CharacterPhysicsDataNotificationBus = AZ::EBus<CharacterPhysicsDataNotifications>;
|
||||
|
||||
@@ -264,63 +264,5 @@ namespace Physics
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool RigidBodyVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
|
||||
{
|
||||
if (classElement.GetVersion() <= 1)
|
||||
{
|
||||
const int elementIndex = classElement.FindElement(AZ_CRC("Centre of mass offset", 0x1e569a45));
|
||||
|
||||
if (elementIndex >= 0)
|
||||
{
|
||||
AZ::Vector3 existingCenterOfMassOffset;
|
||||
AZ::SerializeContext::DataElementNode& centerOfMassElement = classElement.GetSubElement(elementIndex);
|
||||
const bool found = centerOfMassElement.GetData<AZ::Vector3>(existingCenterOfMassOffset);
|
||||
|
||||
if (found && !existingCenterOfMassOffset.IsZero())
|
||||
{
|
||||
// An existing center of mass (COM) offset value was specified for this rigid body.
|
||||
// Version 2 includes a new m_computeCenterOfMass boolean flag to specify the automatic calculation of COM.
|
||||
// In this case set m_computeCenterOfMass to false so that the existing center of mass offset value is utilized correctly.
|
||||
const int idx = classElement.AddElement<bool>(context, "Compute COM");
|
||||
if (idx != -1)
|
||||
{
|
||||
if (!classElement.GetSubElement(idx).SetData<bool>(context, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classElement.GetVersion() <= 2)
|
||||
{
|
||||
const int elementIndex = classElement.FindElement(AZ_CRC("Mass", 0x6c035b66));
|
||||
|
||||
if (elementIndex >= 0)
|
||||
{
|
||||
float existingMass = 0;
|
||||
AZ::SerializeContext::DataElementNode& massElement = classElement.GetSubElement(elementIndex);
|
||||
const bool found = massElement.GetData<float>(existingMass);
|
||||
|
||||
if (found && existingMass > 0)
|
||||
{
|
||||
// Keeping the existing mass and disabling auto-compute of the mass for this rigid body.
|
||||
// Version 3 includes a new m_computeMass boolean flag to specify the automatic calculation of mass.
|
||||
const int idx = classElement.AddElement<bool>(context, "Compute Mass");
|
||||
if (idx != -1)
|
||||
{
|
||||
if (!classElement.GetSubElement(idx).SetData<bool>(context, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace ClassConverters
|
||||
} // namespace Physics
|
||||
|
||||
@@ -22,6 +22,6 @@ namespace Physics
|
||||
bool MaterialLibraryAssetConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
|
||||
bool ColliderConfigurationConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
|
||||
bool MaterialSelectionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
|
||||
bool RigidBodyVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
|
||||
|
||||
} // namespace ClassConverters
|
||||
} // namespace Physics
|
||||
} // namespace Physics
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(TriggerEvent, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(Contact, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(CollisionEvent, AZ::SystemAllocator, 0);
|
||||
|
||||
/*static*/ void TriggerEvent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<TriggerEvent>()
|
||||
->Version(2)
|
||||
->Field("Type", &TriggerEvent::m_type)
|
||||
->Field("TriggerBodyHandle", &TriggerEvent::m_triggerBodyHandle)
|
||||
->Field("OtherBodyHandle", &TriggerEvent::m_otherBodyHandle)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<TriggerEvent>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("GetTriggerEntityId", &TriggerEvent::GetTriggerEntityId)
|
||||
->Method("GetOtherEntityId", &TriggerEvent::GetOtherEntityId)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId TriggerEvent::GetTriggerEntityId() const
|
||||
{
|
||||
if (m_triggerBody)
|
||||
{
|
||||
return m_triggerBody->GetEntityId();
|
||||
}
|
||||
return AZ::EntityId();
|
||||
}
|
||||
|
||||
AZ::EntityId TriggerEvent::GetOtherEntityId() const
|
||||
{
|
||||
if (m_otherBody)
|
||||
{
|
||||
return m_otherBody->GetEntityId();
|
||||
}
|
||||
return AZ::EntityId();
|
||||
}
|
||||
|
||||
/*static*/ void Contact::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<Contact>()
|
||||
->Version(1)
|
||||
->Field("Position", &Contact::m_position)
|
||||
->Field("Normal", &Contact::m_normal)
|
||||
->Field("Impulse", &Contact::m_impulse)
|
||||
->Field("Separation", &Contact::m_separation)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<Contact>("Contact")
|
||||
->Property("Position", BehaviorValueProperty(&Contact::m_position))
|
||||
->Property("Normal", BehaviorValueProperty(&Contact::m_normal))
|
||||
->Property("Impulse", BehaviorValueProperty(&Contact::m_impulse))
|
||||
->Property("Separation", BehaviorValueProperty(&Contact::m_separation))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void CollisionEvent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
Contact::Reflect(context);
|
||||
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<CollisionEvent>()
|
||||
->Version(3)
|
||||
->Field("Type", &CollisionEvent::m_type)
|
||||
->Field("Contacts", &CollisionEvent::m_contacts)
|
||||
->Field("BodyHandle1", &CollisionEvent::m_bodyHandle1)
|
||||
->Field("BodyHandle2", &CollisionEvent::m_bodyHandle2)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<CollisionEvent>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Property("Contacts", BehaviorValueProperty(&CollisionEvent::m_contacts))
|
||||
->Method("GetBody1EntityId", &CollisionEvent::GetBody1EntityId)
|
||||
->Method("GetBody2EntityId", &CollisionEvent::GetBody2EntityId)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId CollisionEvent::GetBody1EntityId() const
|
||||
{
|
||||
if (m_body1)
|
||||
{
|
||||
return m_body1->GetEntityId();
|
||||
}
|
||||
return AZ::EntityId();
|
||||
}
|
||||
|
||||
AZ::EntityId CollisionEvent::GetBody2EntityId() const
|
||||
{
|
||||
if (m_body2)
|
||||
{
|
||||
return m_body2->GetEntityId();
|
||||
}
|
||||
return AZ::EntityId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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/Component/EntityId.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class Shape;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
|
||||
//! Trigger event raised when an object enters/exits a trigger shape.
|
||||
struct TriggerEvent
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_TYPE_INFO(TriggerEvent, "{7A0851A3-2CBD-4A03-85D5-1C40221E7F61}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
enum class Type : AZ::u8
|
||||
{
|
||||
Enter,
|
||||
Exit
|
||||
};
|
||||
|
||||
Type m_type; //! The type of trigger event.
|
||||
SimulatedBodyHandle m_triggerBodyHandle = AzPhysics::InvalidSimulatedBodyHandle; //!< Handle to the trigger body
|
||||
SimulatedBody* m_triggerBody = nullptr; //!< The trigger body
|
||||
Physics::Shape* m_triggerShape = nullptr; //!< The trigger shape
|
||||
SimulatedBodyHandle m_otherBodyHandle = AzPhysics::InvalidSimulatedBodyHandle; //!< Handle to the body that entered the trigger
|
||||
SimulatedBody* m_otherBody = nullptr; //!< The other body that entered the trigger
|
||||
Physics::Shape* m_otherShape = nullptr; //!< The other shape that entered the trigger
|
||||
|
||||
private:
|
||||
// helpers for reflecting to behaviour context
|
||||
AZ::EntityId GetTriggerEntityId() const;
|
||||
AZ::EntityId GetOtherEntityId() const;
|
||||
};
|
||||
using TriggerEventList = AZStd::vector<TriggerEvent>;
|
||||
|
||||
//! Stores information about the contacts between two overlapping shapes.
|
||||
struct Contact
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_TYPE_INFO(Contact, "{D7439508-ED10-4395-9D48-1FC3D7815361}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZ::Vector3 m_position; //!< The position of the contact
|
||||
AZ::Vector3 m_normal; //!< The normal of the contact
|
||||
AZ::Vector3 m_impulse; //!< The impulse force applied to separate the bodies
|
||||
AZ::u32 m_internalFaceIndex01 = 0; //!< Internal face index of the first shape
|
||||
AZ::u32 m_internalFaceIndex02 = 0; //!< Internal face index of the second shape
|
||||
float m_separation = 0.0f; //!< The separation
|
||||
};
|
||||
|
||||
//! A collision event raised when two objects, neither of which can be triggers, overlap.
|
||||
struct CollisionEvent
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_TYPE_INFO(CollisionEvent, "{7602AA36-792C-4BDC-BDF8-AA16792151A3}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
enum class Type : AZ::u8
|
||||
{
|
||||
Begin,
|
||||
Persist,
|
||||
End
|
||||
};
|
||||
Type m_type; //! The Type of collision event.
|
||||
SimulatedBodyHandle m_bodyHandle1 = AzPhysics::InvalidSimulatedBodyHandle; //!< Handle to the first body
|
||||
SimulatedBody* m_body1 = nullptr; //! The first body
|
||||
Physics::Shape* m_shape1 = nullptr; //!< The shape on the first body
|
||||
SimulatedBodyHandle m_bodyHandle2 = AzPhysics::InvalidSimulatedBodyHandle; //!< Handle to the second body
|
||||
SimulatedBody* m_body2 = nullptr; //! The second body
|
||||
Physics::Shape* m_shape2 = nullptr; //!< The shape on the second body
|
||||
AZStd::vector<Contact> m_contacts; //!< The contacts between the two shapes
|
||||
|
||||
private:
|
||||
// helpers for reflecting to behaviour context
|
||||
AZ::EntityId GetBody1EntityId() const;
|
||||
AZ::EntityId GetBody2EntityId() const;
|
||||
};
|
||||
using CollisionEventList = AZStd::vector<CollisionEvent>;
|
||||
}
|
||||
@@ -60,8 +60,6 @@ namespace Physics
|
||||
|
||||
/// Creates a new collision group preset with corresponding groupName.
|
||||
virtual void CreateCollisionGroup(const AZStd::string& groupName, const AzPhysics::CollisionGroup& group) = 0;
|
||||
|
||||
virtual AzPhysics::CollisionConfiguration GetCollisionConfiguration() = 0;
|
||||
};
|
||||
|
||||
/// Collision requests bus traits. Singleton pattern.
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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/Component/ComponentBus.h>
|
||||
#include <AzFramework/Physics/WorldEventhandler.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
/// CollisionNotifications
|
||||
/// Bus interface for receiving collision events from a Physics::World
|
||||
///
|
||||
/// The bus is addressed by EntityId. Body1 inside collisionEvent will correspond
|
||||
/// to the eEntity id subscribed to. Body2 will always be the other body colliding with the entity.
|
||||
class CollisionNotifications
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
// Ebus Traits. ID'd on body1 entity Id
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
static const bool EnableEventQueue = true;
|
||||
using BusIdType = AZ::EntityId;
|
||||
|
||||
virtual ~CollisionNotifications() {}
|
||||
|
||||
/// Dispatched when two shapes start colliding.
|
||||
virtual void OnCollisionBegin(const CollisionEvent& /*collisionEvent*/) {}
|
||||
|
||||
/// Dispatched when two shapes continue colliding.
|
||||
virtual void OnCollisionPersist(const CollisionEvent& /*collisionEvent*/) {}
|
||||
|
||||
/// Dispatched when two shapes stop colliding.
|
||||
virtual void OnCollisionEnd(const CollisionEvent& /*collisionEvent*/) {}
|
||||
};
|
||||
|
||||
/// Bus to service the PhysX Trigger Area Component event group.
|
||||
using CollisionNotificationBus = AZ::EBus<CollisionNotifications>;
|
||||
} // namespace PhysX
|
||||
@@ -13,6 +13,14 @@
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/EBus/OrderedEvent.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
@@ -42,6 +50,14 @@ namespace AzPhysics
|
||||
//! Event triggers at the end of the SystemInterface::Simulate call.
|
||||
using OnPostsimulateEvent = AZ::Event<>;
|
||||
|
||||
//! Event trigger when a Scene is added to the simulation.
|
||||
//! When triggered will send the handle to the new Scene.
|
||||
using OnSceneAddedEvent = AZ::Event<AzPhysics::SceneHandle>;
|
||||
|
||||
//! Event trigger when a Scene is removed from the simulation.
|
||||
//! When triggered will send the handle to the old Scene (after this call, the Handle will be invalid).
|
||||
using OnSceneRemovedEvent = AZ::Event<AzPhysics::SceneHandle>;
|
||||
|
||||
//! Event that triggers when the default material library changes.
|
||||
//! When triggered the event will send the Asset Id of the new material library.
|
||||
using OnDefaultMaterialLibraryChangedEvent = AZ::Event<const AZ::Data::AssetId&>;
|
||||
@@ -50,4 +66,80 @@ namespace AzPhysics
|
||||
//! When triggered the event will send the new default scene configuration.
|
||||
using OnDefaultSceneConfigurationChangedEvent = AZ::Event<const SceneConfiguration*>;
|
||||
}
|
||||
|
||||
namespace SceneEvents
|
||||
{
|
||||
//! Event that triggers when a new config is set on a scene.
|
||||
//! When triggered the event will send a handle to the Scene that triggered the event and the new configuration.
|
||||
using OnSceneConfigurationChanged = AZ::Event<AzPhysics::SceneHandle, const AzPhysics::SceneConfiguration&>;
|
||||
|
||||
//! Event that triggers when a Simulated body has been added to a scene.
|
||||
//! When triggered the event will send a handle to the Scene that triggered the event and a handle to the new simulated body.
|
||||
using OnSimulationBodyAdded = AZ::Event<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle>;
|
||||
|
||||
//! Event that triggers when a Simulated body has been removed from a scene.
|
||||
//! When triggered the event will send a handle to the Scene that triggered the event and a handle to the removed simulated body (after this call, the Handle will be invalid).
|
||||
using OnSimulationBodyRemoved = AZ::Event<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle>;
|
||||
|
||||
//! Event that triggers when a Simulated body has its simulation enabled.
|
||||
//! When triggered the event will send a handle to the Scene that triggered the event and a handle to the affected simulated body.
|
||||
using OnSimulationBodySimulationEnabled = AZ::Event<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle>;
|
||||
|
||||
//! Event that triggers when a Simulated body has its simulation disabled.
|
||||
//! When triggered the event will send a handle to the Scene that triggered the event and a handle to the affected simulated body.
|
||||
using OnSimulationBodySimulationDisabled = AZ::Event<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle>;
|
||||
|
||||
//! Enum for use with the OnSceneSimulationStartEvent and OnSceneSimulationFinishEvent AZ::OrderedEvent calls.
|
||||
//! Higher values are called before lower values.
|
||||
enum class PhysicsStartFinishSimulationPriority : int32_t
|
||||
{
|
||||
Default = 0, //!< All other systems (Game code).
|
||||
Audio = 1000, //!< Audio systems (occlusion).
|
||||
Scripting = 2000, //!< Scripting systems (script canvas).
|
||||
Components = 3000, //!< C++ components (force region).
|
||||
Animation = 4000, //!< Animation system (ragdolls).
|
||||
Physics = 5000 //!< The physics system itself
|
||||
};
|
||||
|
||||
//! Event triggers at the beginning of the Scene::StartSimulation call.
|
||||
//! This will not trigger if the scene if not Enabled (Scene::IsEnabled() returns true).
|
||||
//! When triggered the event will send a handle to the Scene that triggers the event and the delta time in seconds used to step this update.
|
||||
//! @note This may fire multiple times per frame.
|
||||
using OnSceneSimulationStartEvent = AZ::OrderedEvent<AzPhysics::SceneHandle, float>;
|
||||
using OnSceneSimulationStartHandler = AZ::OrderedEventHandler<AzPhysics::SceneHandle, float>;
|
||||
|
||||
//! Event triggers at the End of the Scene::FinishSimulation call.
|
||||
//! This will not trigger if the scene if not Enabled (Scene::IsEnabled() returns true).
|
||||
//! When triggered the event will send a handle to the Scene that triggers the event and the delta time in seconds used to step this update.
|
||||
//! @note This may fire multiple times per frame.
|
||||
using OnSceneSimulationFinishEvent = AZ::OrderedEvent<AzPhysics::SceneHandle, float>;
|
||||
using OnSceneSimulationFinishHandler = AZ::OrderedEventHandler<AzPhysics::SceneHandle, float>;
|
||||
|
||||
//! Event triggers during the Scene::FinishSimulation call before the OnSceneSimulationFinishEvent for a scene
|
||||
//! and only if the SceneConfiguration::m_enableActiveActors is true.
|
||||
//! This will not trigger if the scene is not Enabled (Scene::IsEnabled() must return true to trigger).
|
||||
//! When triggered, the event will send a handle of the Scene that triggered the event and a list of SimulatedBodyHandles that were updated in this tick.
|
||||
//! @note There may be a performance penalty for enabling the Active Actor Notification.
|
||||
using OnSceneActiveSimulatedBodiesEvent = AZ::Event<AzPhysics::SceneHandle, const AzPhysics::SimulatedBodyHandleList&>;
|
||||
|
||||
//! Event triggers with an ordered list of all the collision Begin/Persist/End events that happened during a single sub simulation step.
|
||||
//! When triggered the event will send a handle to the Scene that triggers the event and the list of collision events that occurred.
|
||||
//! @note The event will trigger at the end of the Scene::FinishSimulation call and only if collision events were generated and will be
|
||||
//! triggered before the OnSceneSimulationFinishEvent, SimulatedBodyEvents::OnCollisionBegin, SimulatedBodyEvents::OnCollisionPersist, and SimulatedBodyEvents::OnCollisionEnd.
|
||||
//! This may fire multiple times per frame.
|
||||
//! The CollisionEventList is only valid for the duration of the callback.
|
||||
using OnSceneCollisionsEvent = AZ::Event<AzPhysics::SceneHandle, const AzPhysics::CollisionEventList&>;
|
||||
|
||||
//! Event triggers with an ordered list of all the trigger Enter/Exit events that happened during single sub simulation step.
|
||||
//! When triggered the event will send a handle to the Scene that triggers the event and the list of trigger events that occurred.
|
||||
//! @note The event will trigger at the end of the Scene::FinishSimulation call and only if trigger events were generated and will be
|
||||
//! triggered before the OnSceneSimulationFinishEvent, SimulatedBodyEvents::OnTriggerEnter and SimulatedBodyEvents::OnTriggerExit.
|
||||
//! This may fire multiple times per frame.
|
||||
//! The TriggerEventList is only valid for the duration of the callback.
|
||||
using OnSceneTriggersEvent = AZ::Event<AzPhysics::SceneHandle, const AzPhysics::TriggerEventList&>;
|
||||
|
||||
//! Event trigger when the gravity has been changed on the scene.
|
||||
//! When triggered the event will send a handle to the Scene that triggers the event and the new gravity vector.
|
||||
using OnSceneGravityChangedEvent = AZ::Event<AzPhysics::SceneHandle, const AZ::Vector3&>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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 <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <AzFramework/Physics/CollisionBus.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SceneQueryRequest, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(RayCastRequest, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(ShapeCastRequest, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(OverlapRequest, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SceneQueryHit, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SceneQueryHits, AZ::SystemAllocator, 0);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
AZStd::vector<AZStd::pair<CollisionGroup, AZStd::string>> PopulateCollisionGroups()
|
||||
{
|
||||
AZStd::vector<AZStd::pair<CollisionGroup, AZStd::string>> elems;
|
||||
const CollisionConfiguration& configuration = AZ::Interface<AzPhysics::SystemInterface>::Get()->GetConfiguration()->m_collisionConfig;
|
||||
for (const CollisionGroups::Preset& preset : configuration.m_collisionGroups.GetPresets())
|
||||
{
|
||||
elems.push_back({ CollisionGroup(preset.m_name), preset.m_name });
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneQuery
|
||||
{
|
||||
/*static*/ void ReflectSceneQueryObjects(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
if (auto* editContext = azrtti_cast<AZ::EditContext*>(serializeContext->GetEditContext()))
|
||||
{
|
||||
editContext->Enum<QueryType>("Query Type Flags", "Object types to include in the query")
|
||||
->Value("Static", QueryType::Static)
|
||||
->Value("Dynamic", QueryType::Dynamic)
|
||||
->Value("Static and Dynamic", QueryType::StaticAndDynamic)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
SceneQueryRequest::Reflect(context);
|
||||
RayCastRequest::Reflect(context);
|
||||
ShapeCastRequest::Reflect(context);
|
||||
OverlapRequest::Reflect(context);
|
||||
SceneQueryHits::Reflect(context);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void SceneQueryRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SceneQueryRequest>()
|
||||
->Field("MaxResults", &SceneQueryRequest::m_maxResults)
|
||||
->Field("CollisionGroup", &SceneQueryRequest::m_collisionGroup)
|
||||
->Field("QueryType", &SceneQueryRequest::m_queryType)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<SceneQueryRequest>("Scene Query Request", "Parameters for scene queries")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &SceneQueryRequest::m_collisionGroup, "Collision Group", "The layers to include in the query")
|
||||
->Attribute(AZ::Edit::Attributes::EnumValues, &Internal::PopulateCollisionGroups)
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &SceneQueryRequest::m_queryType, "Query Type", "Object types to include in the query")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneQueryRequest::m_maxResults, "Max results", "The Maximum results for this request to return, this is limited by the value set in Physics Configuration")
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void RayCastRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<RayCastRequest, SceneQueryRequest>()
|
||||
->Field("Distance", &RayCastRequest::m_distance)
|
||||
->Field("Start", &RayCastRequest::m_start)
|
||||
->Field("Direction", &RayCastRequest::m_direction)
|
||||
->Field("HitFlags", &RayCastRequest::m_hitFlags)
|
||||
->Field("ReportMultipleHits", &RayCastRequest::m_reportMultipleHits)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<RayCastRequest>("RayCast Request", "Parameters for raycast")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_start, "Start", "Start position of the raycast")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_distance, "Distance", "Length of the raycast")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RayCastRequest::m_direction, "Direction", "Direction of the raycast")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<RayCastRequest>("RayCastRequest")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Distance", BehaviorValueProperty(&RayCastRequest::m_distance))
|
||||
->Property("Start", BehaviorValueProperty(&RayCastRequest::m_start))
|
||||
->Property("Direction", BehaviorValueProperty(&RayCastRequest::m_direction))
|
||||
->Property("Collision", BehaviorValueProperty(&RayCastRequest::m_collisionGroup))
|
||||
// Until enum class support for behavior context is done, expose this as an int
|
||||
->Property("QueryType", [](const RayCastRequest& self) { return static_cast<int>(self.m_queryType); },
|
||||
[](RayCastRequest& self, int newQueryType) { self.m_queryType = SceneQuery::QueryType(newQueryType); })
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void ShapeCastRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<ShapeCastRequest, SceneQueryRequest>()
|
||||
->Field("Distance", &ShapeCastRequest::m_distance)
|
||||
->Field("Start", &ShapeCastRequest::m_start)
|
||||
->Field("Direction", &ShapeCastRequest::m_direction)
|
||||
->Field("ShapeConfiguration", &ShapeCastRequest::m_shapeConfiguration)
|
||||
->Field("HitFlags", &ShapeCastRequest::m_hitFlags)
|
||||
->Field("ReportMultipleHits", &ShapeCastRequest::m_reportMultipleHits)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShapeCastRequestHelpers
|
||||
{
|
||||
ShapeCastRequest CreateSphereCastRequest(float radius,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType /*= SceneQuery::QueryType::StaticAndDynamic*/,
|
||||
CollisionGroup collisionGroup /*= CollisionGroup::All*/,
|
||||
SceneQuery::FilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::ShapeCastRequest request;
|
||||
request.m_distance = distance;
|
||||
request.m_start = startPose;
|
||||
request.m_direction = direction;
|
||||
request.m_shapeConfiguration = AZStd::make_shared<Physics::SphereShapeConfiguration>(radius);
|
||||
request.m_queryType = queryType;
|
||||
request.m_collisionGroup = collisionGroup;
|
||||
request.m_filterCallback = filterCallback;
|
||||
return request;
|
||||
}
|
||||
|
||||
ShapeCastRequest CreateBoxCastRequest(const AZ::Vector3& boxDimensions,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType /*= SceneQuery::QueryType::StaticAndDynamic*/,
|
||||
CollisionGroup collisionGroup /*= CollisionGroup::All*/,
|
||||
SceneQuery::FilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::ShapeCastRequest request;
|
||||
request.m_distance = distance;
|
||||
request.m_start = startPose;
|
||||
request.m_direction = direction;
|
||||
request.m_shapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(boxDimensions);
|
||||
request.m_queryType = queryType;
|
||||
request.m_collisionGroup = collisionGroup;
|
||||
request.m_filterCallback = filterCallback;
|
||||
return request;
|
||||
}
|
||||
|
||||
ShapeCastRequest CreateCapsuleCastRequest(float capsuleRadius, float capsuleHeight,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType /*= SceneQuery::QueryType::StaticAndDynamic*/,
|
||||
CollisionGroup collisionGroup /*= CollisionGroup::All*/,
|
||||
SceneQuery::FilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::ShapeCastRequest request;
|
||||
request.m_distance = distance;
|
||||
request.m_start = startPose;
|
||||
request.m_direction = direction;
|
||||
request.m_shapeConfiguration = AZStd::make_shared<Physics::CapsuleShapeConfiguration>(capsuleHeight, capsuleRadius);
|
||||
request.m_queryType = queryType;
|
||||
request.m_collisionGroup = collisionGroup;
|
||||
request.m_filterCallback = filterCallback;
|
||||
return request;
|
||||
}
|
||||
|
||||
} // namespace ShapeCastRequestHelpers
|
||||
|
||||
/*static*/ void OverlapRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<OverlapRequest, SceneQueryRequest>()
|
||||
->Field("Pose", &OverlapRequest::m_pose)
|
||||
->Field("ShapeConfiguration", &OverlapRequest::m_shapeConfiguration)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OverlapRequestHelpers
|
||||
{
|
||||
OverlapRequest CreateSphereOverlapRequest(float radius, const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::OverlapRequest overlapRequest;
|
||||
overlapRequest.m_pose = pose;
|
||||
overlapRequest.m_shapeConfiguration = AZStd::make_shared<Physics::SphereShapeConfiguration>(radius);
|
||||
overlapRequest.m_filterCallback = filterCallback;
|
||||
return overlapRequest;
|
||||
}
|
||||
|
||||
OverlapRequest CreateBoxOverlapRequest(const AZ::Vector3& dimensions, const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::OverlapRequest overlapRequest;
|
||||
overlapRequest.m_pose = pose;
|
||||
overlapRequest.m_shapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(dimensions);
|
||||
overlapRequest.m_filterCallback = filterCallback;
|
||||
return overlapRequest;
|
||||
}
|
||||
|
||||
OverlapRequest CreateCapsuleOverlapRequest(float height, float radius, const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback /*= nullptr*/)
|
||||
{
|
||||
AzPhysics::OverlapRequest overlapRequest;
|
||||
overlapRequest.m_pose = pose;
|
||||
overlapRequest.m_shapeConfiguration = AZStd::make_shared<Physics::CapsuleShapeConfiguration>(height, radius);
|
||||
overlapRequest.m_filterCallback = filterCallback;
|
||||
return overlapRequest;
|
||||
}
|
||||
|
||||
} // namespace OverlapRequestHelpers
|
||||
|
||||
/*static*/ void SceneQueryHit::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SceneQueryHit>()
|
||||
->Field("Distance", &SceneQueryHit::m_distance)
|
||||
->Field("Position", &SceneQueryHit::m_position)
|
||||
->Field("Normal", &SceneQueryHit::m_normal)
|
||||
->Field("BodyHandle", &SceneQueryHit::m_bodyHandle)
|
||||
->Field("EntityId", &SceneQueryHit::m_entityId)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SceneQueryHit>("SceneQueryHit")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Distance", BehaviorValueProperty(&SceneQueryHit::m_distance))
|
||||
->Property("Position", BehaviorValueProperty(&SceneQueryHit::m_position))
|
||||
->Property("Normal", BehaviorValueProperty(&SceneQueryHit::m_normal))
|
||||
->Property("BodyHandle", BehaviorValueProperty(&SceneQueryHit::m_bodyHandle))
|
||||
->Property("EntityId", BehaviorValueProperty(&SceneQueryHit::m_entityId))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void SceneQueryHits::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
SceneQueryHit::Reflect(context);
|
||||
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SceneQueryHits>()
|
||||
->Field("HitArray", &SceneQueryHits::m_hits)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SceneQueryHits>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Property("HitArray", BehaviorValueProperty(&SceneQueryHits::m_hits))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Physics
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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/Transform.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class Material;
|
||||
class Shape;
|
||||
class ShapeConfiguration;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
struct SceneQueryHit;
|
||||
struct SceneQueryHits;
|
||||
using SceneQueryHitsList = AZStd::vector<SceneQueryHits>;
|
||||
|
||||
namespace SceneQuery
|
||||
{
|
||||
//! Enum to specify the hit type returned by the filter callback.
|
||||
enum class QueryHitType : AZ::u8
|
||||
{
|
||||
None, //!< The hit should not be reported.
|
||||
Touch, //!< The hit should be reported but it should not block the query
|
||||
Block //!< The hit should be reported and it should block the query
|
||||
};
|
||||
|
||||
//! Enum to specify which shapes are included in the query.
|
||||
enum class QueryType : AZ::u8
|
||||
{
|
||||
Static, //!< Only test against static shapes
|
||||
Dynamic, //!< Only test against dynamic shapes
|
||||
StaticAndDynamic //!< Test against both static and dynamic shapes
|
||||
};
|
||||
|
||||
//! Scene query and geometry query behavior flags.
|
||||
//!
|
||||
//! HitFlags are used for 3 different purposes:
|
||||
//!
|
||||
//! 1) To request hit fields to be filled in by scene queries (such as hit position, normal, face index or UVs).
|
||||
//! 2) Once query is completed, to indicate which fields are valid (note that a query may produce more valid fields than requested).
|
||||
//! 3) To specify additional options for the narrow phase and mid-phase intersection routines.
|
||||
enum class HitFlags : AZ::u16
|
||||
{
|
||||
Position = (1 << 0), //!< "position" member of the hit is valid
|
||||
Normal = (1 << 1), //!< "normal" member of the hit is valid
|
||||
UV = (1 << 3), //!< "u" and "v" barycentric coordinates of the hit are valid. Not applicable to ShapeCast queries.
|
||||
//! Performance hint flag for ShapeCasts when it is known upfront there's no initial overlap.
|
||||
//! NOTE: using this flag may cause undefined results if shapes are initially overlapping.
|
||||
AssumeNoInitialOverlap = (1 << 4),
|
||||
MeshMultiple = (1 << 5), //!< Report all hits for meshes rather than just the first. Not applicable to ShapeCast queries.
|
||||
//! Report any first hit for meshes. If neither MeshMultiple nor MeshAny is specified,
|
||||
//! a single closest hit will be reported for meshes.
|
||||
MeshAny = (1 << 6),
|
||||
//! Report hits with back faces of mesh triangles. Also report hits for raycast
|
||||
//! originating on mesh surface and facing away from the surface normal. Not applicable to ShapeCast queries.
|
||||
MeshBothSides = (1 << 7),
|
||||
PreciseSweep = (1 << 8), //!< Use more accurate but slower narrow phase sweep tests.
|
||||
MTD = (1 << 9), //!< Report the minimum translation depth, normal and contact point.
|
||||
FaceIndex = (1 << 10), //!< "face index" member of the hit is valid. Required to get the per-face material data.
|
||||
Default = Position | Normal | FaceIndex
|
||||
};
|
||||
|
||||
//! Bitwise operators for HitFlags
|
||||
inline HitFlags operator|(HitFlags lhs, HitFlags rhs)
|
||||
{
|
||||
return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) | static_cast<AZ::u16>(rhs));
|
||||
}
|
||||
|
||||
inline HitFlags operator&(HitFlags lhs, HitFlags rhs)
|
||||
{
|
||||
return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) & static_cast<AZ::u16>(rhs));
|
||||
}
|
||||
|
||||
//! Flag used to mark which members are valid in a SceneQueryHit object.
|
||||
//! Example: if SceneQueryHit::m_resultFlags & ResultFlags::Distance is true,
|
||||
//! then the SceneQueryHit::m_distance member would have a valid value.
|
||||
enum ResultFlags : AZ::u8
|
||||
{
|
||||
Invalid = 0,
|
||||
|
||||
Distance = (1 << 0),
|
||||
BodyHandle = (1 << 1),
|
||||
EntityId = (1 << 2),
|
||||
Shape = (1 << 3),
|
||||
Material = (1 << 4),
|
||||
Position = (1 << 5),
|
||||
Normal = (1 << 6)
|
||||
};
|
||||
//! Bitwise operators for ResultFlags
|
||||
inline ResultFlags operator|(ResultFlags lhs, ResultFlags rhs)
|
||||
{
|
||||
return static_cast<ResultFlags>(static_cast<AZ::u8>(lhs) | static_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
inline ResultFlags operator|=(ResultFlags& lhs, ResultFlags rhs)
|
||||
{
|
||||
return (lhs = (lhs | rhs));
|
||||
}
|
||||
|
||||
inline ResultFlags operator&(ResultFlags lhs, ResultFlags rhs)
|
||||
{
|
||||
return static_cast<ResultFlags>(static_cast<AZ::u8>(lhs) & static_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
//! Callback used for directed scene queries: RayCasts and ShapeCasts
|
||||
using FilterCallback = AZStd::function<QueryHitType(const SimulatedBody* body, const Physics::Shape* shape)>;
|
||||
|
||||
//! Callback used for undirected scene queries: Overlaps
|
||||
using OverlapFilterCallback = AZStd::function<bool(const SimulatedBody* body, const Physics::Shape* shape)>;
|
||||
|
||||
//! Callback for unbounded world queries. These are queries which don't require
|
||||
//! building the entire result vector, and so saves memory for very large numbers of hits.
|
||||
//! Called with '{ hit }' repeatedly until there are no more hits, then called with '{}', then never called again.
|
||||
//! Returns 'true' to continue processing more hits, or 'false' otherwise. If the function ever returns
|
||||
//! 'false', it is unspecified if the finalizing call '{}' occurs.
|
||||
using UnboundedOverlapHitCallback = AZStd::function<bool(AZStd::optional<SceneQueryHit>&&)>;
|
||||
|
||||
using AsyncRequestId = int;
|
||||
using AsyncCallback = AZStd::function<void(AsyncRequestId requestId, SceneQueryHits hits)>;
|
||||
using AsyncBatchCallback = AZStd::function<void(AsyncRequestId requestId, SceneQueryHitsList hits)>;
|
||||
|
||||
//! Helper used to reflect all required objects in PhysicsSceneQuery.h
|
||||
void ReflectSceneQueryObjects(AZ::ReflectContext* context);
|
||||
|
||||
} // namespace SceneQuery
|
||||
|
||||
//! Base Scene Query request.
|
||||
//! Not valid to be used with Scene::QueryScene functions
|
||||
struct SceneQueryRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(SceneQueryRequest, "{76ECAB7D-42BA-461F-82E6-DCED8E1BDCB9}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
virtual ~SceneQueryRequest() = default;
|
||||
|
||||
AZ::u64 m_maxResults = 32; //!< The Maximum results for this request to return, this is limited by the value set in the SceneConfiguration
|
||||
CollisionGroup m_collisionGroup = CollisionGroup::All; //!< Collision filter for the query.
|
||||
SceneQuery::QueryType m_queryType = SceneQuery::QueryType::StaticAndDynamic; //!< Object types to include in the query
|
||||
};
|
||||
using SceneQueryRequests = AZStd::vector<AZStd::shared_ptr<SceneQueryRequest>>;
|
||||
|
||||
//! Casts a ray from a starting pose along a direction returning objects that intersected with the ray.
|
||||
struct RayCastRequest :
|
||||
public SceneQueryRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(RayCastRequest, "{53EAD088-A391-48F1-8370-2A1DBA31512F}", SceneQueryRequest);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
float m_distance = 500.0f; //!< The distance to cast along the direction.
|
||||
AZ::Vector3 m_start = AZ::Vector3::CreateZero(); //!< World space point where ray starts from.
|
||||
AZ::Vector3 m_direction = AZ::Vector3::CreateZero(); //!< World space direction (Should be normalized)
|
||||
SceneQuery::HitFlags m_hitFlags = SceneQuery::HitFlags::Default; //!< Query behavior flags
|
||||
SceneQuery::FilterCallback m_filterCallback = nullptr; //!< Hit filtering function
|
||||
bool m_reportMultipleHits = false; //!< flag to have the cast stop after the first hit or return all hits along the query.
|
||||
};
|
||||
|
||||
//! Sweeps a shape from a starting pose along a direction returning objects that intersected with the shape.
|
||||
struct ShapeCastRequest :
|
||||
public SceneQueryRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(ShapeCastRequest, "{52F6C536-92F6-4C05-983D-0A74800AE56D}", SceneQueryRequest);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
float m_distance = 500.0f; //! The distance to cast along the direction.
|
||||
AZ::Transform m_start = AZ::Transform::CreateIdentity(); //!< World space start position. Assumes only rotation + translation (no scaling).
|
||||
AZ::Vector3 m_direction = AZ::Vector3::CreateZero(); //!< World space direction (Should be normalized)
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfiguration; //!< Shape information.
|
||||
SceneQuery::HitFlags m_hitFlags = SceneQuery::HitFlags::Default; //!< Query behavior flags
|
||||
SceneQuery::FilterCallback m_filterCallback = nullptr; //!< Hit filtering function
|
||||
bool m_reportMultipleHits = false; //!< flag to have the cast stop after the first hit or return all hits along the query.
|
||||
};
|
||||
|
||||
namespace ShapeCastRequestHelpers
|
||||
{
|
||||
//! Helper to create a ShapeCastRequest with a SphereShapeConfiguration as its shape configuration.
|
||||
ShapeCastRequest CreateSphereCastRequest(float radius,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType = SceneQuery::QueryType::StaticAndDynamic,
|
||||
CollisionGroup collisionGroup = CollisionGroup::All,
|
||||
SceneQuery::FilterCallback filterCallback = nullptr);
|
||||
|
||||
//! Helper to create a ShapeCastRequest with a BoxShapeConfiguration as its shape configuration.
|
||||
ShapeCastRequest CreateBoxCastRequest(const AZ::Vector3& boxDimensions,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType = SceneQuery::QueryType::StaticAndDynamic,
|
||||
CollisionGroup collisionGroup = CollisionGroup::All,
|
||||
SceneQuery::FilterCallback filterCallback = nullptr);
|
||||
|
||||
//! Helper to create a ShapeCastRequest with a CapsuleShapeConfiguration as its shape configuration.
|
||||
ShapeCastRequest CreateCapsuleCastRequest(float capsuleRadius, float capsuleHeight,
|
||||
const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType = SceneQuery::QueryType::StaticAndDynamic,
|
||||
CollisionGroup collisionGroup = CollisionGroup::All,
|
||||
SceneQuery::FilterCallback filterCallback = nullptr);
|
||||
|
||||
} // namespace ShapeCastRequestHelpers
|
||||
|
||||
//! Searches a region enclosed by a specified shape for any overlapping objects in the scene.
|
||||
struct OverlapRequest :
|
||||
public SceneQueryRequest
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(OverlapRequest, "{3DC986C2-316B-4C54-A0A6-8ABBB8ABCC4A}", SceneQueryRequest);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZ::Transform m_pose = AZ::Transform::CreateIdentity(); //!< Initial shape pose
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfiguration; //!< Shape information.
|
||||
SceneQuery::OverlapFilterCallback m_filterCallback = nullptr; //!< Hit filtering function
|
||||
SceneQuery::UnboundedOverlapHitCallback m_unboundedOverlapHitCallback = nullptr; //!< When not nullptr the request will perform an unbounded overlap query.
|
||||
};
|
||||
|
||||
namespace OverlapRequestHelpers
|
||||
{
|
||||
//! Helper to create a OverlapRequest with a SphereShapeConfiguration as its shape configuration.
|
||||
OverlapRequest CreateSphereOverlapRequest(float radius,const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback = nullptr);
|
||||
|
||||
//! Helper to create a OverlapRequest with a BoxShapeConfiguration as its shape configuration.
|
||||
OverlapRequest CreateBoxOverlapRequest(const AZ::Vector3& dimensions, const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback = nullptr);
|
||||
|
||||
//! Helper to create a OverlapRequest with a CapsuleShapeConfiguration as its shape configuration.
|
||||
OverlapRequest CreateCapsuleOverlapRequest(float height, float radius, const AZ::Transform& pose,
|
||||
SceneQuery::OverlapFilterCallback filterCallback = nullptr);
|
||||
|
||||
} // namespace OverlapRequestHelpers
|
||||
|
||||
//! Structure that contains information of an individual hit related to a SceneQuery.
|
||||
struct SceneQueryHit
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_TYPE_INFO(SceneQueryHit, "{7A7201B9-67B5-438B-B4EB-F3EEBB78C617}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
virtual ~SceneQueryHit() = default;
|
||||
|
||||
explicit operator bool() const { return IsValid(); }
|
||||
bool IsValid() const { return m_resultFlags != SceneQuery::ResultFlags::Invalid; }
|
||||
|
||||
//! Flags used to determine what members are valid.
|
||||
//! If the flag is true, the member will have a valid value.
|
||||
SceneQuery::ResultFlags m_resultFlags = SceneQuery::ResultFlags::Invalid;
|
||||
|
||||
//! The distance along the cast at which the hit occurred as given by Dot(m_normal, startPoint) - Dot(m_normal, m_position).
|
||||
//! Valid if SceneQuery::ResultFlags::Distance is set.
|
||||
float m_distance = 0.0f;
|
||||
//! Handler to the simulated body that was hit.
|
||||
//! Valid if SceneQuery::ResultFlags::BodyHandle is set.
|
||||
AzPhysics::SimulatedBodyHandle m_bodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
//! The Entity Id of the body that was hit.
|
||||
//! Valid if SceneQuery::ResultFlags::EntityId is set.
|
||||
AZ::EntityId m_entityId;
|
||||
//! The shape on the body that was hit.
|
||||
//! Valid if SceneQuery::ResultFlags::Shape is set.
|
||||
Physics::Shape* m_shape = nullptr;
|
||||
//! The material on the shape (or face) that was hit.
|
||||
//! Valid if SceneQuery::ResultFlags::Material is set.
|
||||
Physics::Material* m_material = nullptr;
|
||||
//! The position of the hit in world space.
|
||||
//! Valid if SceneQuery::ResultFlags::Position is set.
|
||||
AZ::Vector3 m_position = AZ::Vector3::CreateZero();
|
||||
//! The normal of the surface hit.
|
||||
//! Valid if SceneQuery::ResultFlags::Normal is set.
|
||||
AZ::Vector3 m_normal = AZ::Vector3::CreateZero();
|
||||
};
|
||||
|
||||
//! Structure that contains all hits related to a SceneQuery.
|
||||
struct SceneQueryHits
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_TYPE_INFO(SceneQueryHits, "{BAFCC4E7-A06B-4909-B2AE-C89D9E84FE4E}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
explicit operator bool() const { return !m_hits.empty(); }
|
||||
|
||||
AZStd::vector<SceneQueryHit> m_hits;
|
||||
};
|
||||
}
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(AzPhysics::SceneQuery::QueryType, "{0E0E56A8-73A8-40B4-B438-B19FC852E3C0}");
|
||||
AZ_TYPE_INFO_SPECIALIZE(AzPhysics::SceneQuery::ResultFlags, "{E081DB48-CFC8-4480-BB69-AA5BFC8C5FEE}");
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyAutomation.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SimulatedBody, AZ::SystemAllocator, 0);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
template<class Event, class Function>
|
||||
Event* GetEvent(AZ::EntityId entityid, Function getEventFunc)
|
||||
{
|
||||
auto* physicsSystem = AZ::Interface<SystemInterface>::Get();
|
||||
auto* sceneInterface = AZ::Interface<SceneInterface>::Get();
|
||||
if (physicsSystem != nullptr && sceneInterface != nullptr)
|
||||
{
|
||||
auto [sceneHandle, bodyHandle] = physicsSystem->FindAttachedBodyHandleFromEntityId(entityid);
|
||||
if (SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle))
|
||||
{
|
||||
auto func = AZStd::bind(getEventFunc, body);
|
||||
return func();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void SimulatedBody::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
Automation::SimulatedBodyCollisionAutomationHandler::Reflect(context);
|
||||
Automation::SimulatedBodyTriggerAutomationHandler::Reflect(context);
|
||||
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AzPhysics::SimulatedBody>()
|
||||
->Version(1)
|
||||
->Field("SceneOwner", &SimulatedBody::m_sceneOwner)
|
||||
->Field("BodyHandle", &SimulatedBody::m_bodyHandle)
|
||||
;
|
||||
}
|
||||
|
||||
// reflect the collision and trigger AZ::Events
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
const AZStd::vector<AZStd::string> collisionEventParams = {
|
||||
"Simulated Body Handle",
|
||||
"Collision Event"
|
||||
};
|
||||
|
||||
const AZ::BehaviorAzEventDescription onCollisionBeginEventDescription =
|
||||
{
|
||||
"On Collision Begin event",
|
||||
collisionEventParams // Parameters
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription onCollisionPersistDescription =
|
||||
{
|
||||
"On Collision Persist event",
|
||||
collisionEventParams // Parameters
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription onCollisionEndEventDescription =
|
||||
{
|
||||
"On Collision End event",
|
||||
collisionEventParams // Parameters
|
||||
};
|
||||
|
||||
const AZStd::vector<AZStd::string> triggerEventParams = {
|
||||
"Simulated Body Handle",
|
||||
"Trigger Event"
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription onTriggerEnterDescription =
|
||||
{
|
||||
"On Trigger Enter event",
|
||||
triggerEventParams // Parameters
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription onTriggerExitDescription =
|
||||
{
|
||||
"On Trigger Exit event",
|
||||
triggerEventParams // Parameters
|
||||
};
|
||||
|
||||
const auto getOnCollisionBegin = [](AZ::EntityId id) -> SimulatedBodyEvents::OnCollisionBegin*
|
||||
{
|
||||
return Internal::GetEvent<SimulatedBodyEvents::OnCollisionBegin>(id, &SimulatedBody::GetOnCollisionBeginEvent);
|
||||
};
|
||||
const auto getOnCollisionPersist = [](AZ::EntityId id) -> SimulatedBodyEvents::OnCollisionPersist*
|
||||
{
|
||||
return Internal::GetEvent<SimulatedBodyEvents::OnCollisionPersist>(id, &SimulatedBody::GetOnCollisionPersistEvent);
|
||||
};
|
||||
const auto getOnCollisionEnd = [](AZ::EntityId id) -> SimulatedBodyEvents::OnCollisionEnd*
|
||||
{
|
||||
return Internal::GetEvent<SimulatedBodyEvents::OnCollisionEnd>(id, &SimulatedBody::GetOnCollisionEndEvent);
|
||||
};
|
||||
const auto getOnTriggerEnter = [](AZ::EntityId id) -> SimulatedBodyEvents::OnTriggerEnter*
|
||||
{
|
||||
return Internal::GetEvent<SimulatedBodyEvents::OnTriggerEnter>(id, &SimulatedBody::GetOnTriggerEnterEvent);
|
||||
};
|
||||
const auto getOnTriggerExit = [](AZ::EntityId id) -> SimulatedBodyEvents::OnTriggerExit*
|
||||
{
|
||||
return Internal::GetEvent<SimulatedBodyEvents::OnTriggerExit>(id, &SimulatedBody::GetOnTriggerExitEvent);
|
||||
};
|
||||
|
||||
behaviorContext->Class<SimulatedBody>("SimulatedBody")
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Physics")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Method("GetOnCollisionBeginEvent", getOnCollisionBegin)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(onCollisionBeginEventDescription))
|
||||
->Method("GetOnCollisionPersistEvent", getOnCollisionPersist)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(onCollisionPersistDescription))
|
||||
->Method("GetOnCollisionEndEvent", getOnCollisionEnd)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(onCollisionEndEventDescription))
|
||||
->Method("GetOnTriggerEnterEvent", getOnTriggerEnter)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(onTriggerEnterDescription))
|
||||
->Method("GetOnTriggerExitEvent", getOnTriggerExit)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move(onTriggerExitDescription))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatedBody::ProcessCollisionEvent(const CollisionEvent& collision) const
|
||||
{
|
||||
switch (collision.m_type)
|
||||
{
|
||||
case CollisionEvent::Type::Begin:
|
||||
m_collisionBeginEvent.Signal(m_bodyHandle, collision);
|
||||
break;
|
||||
case CollisionEvent::Type::Persist:
|
||||
m_collisionPersistEvent.Signal(m_bodyHandle, collision);
|
||||
break;
|
||||
case CollisionEvent::Type::End:
|
||||
m_collisionEndEvent.Signal(m_bodyHandle, collision);
|
||||
break;
|
||||
default:
|
||||
AZ_Warning("Physics", false, "[SimulatedBody::ProcessCollisionEvent] Unexpected collison type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatedBody::ProcessTriggerEvent(const TriggerEvent& trigger) const
|
||||
{
|
||||
switch (trigger.m_type)
|
||||
{
|
||||
case AzPhysics::TriggerEvent::Type::Enter:
|
||||
m_triggerEnterEvent.Signal(m_bodyHandle, trigger);
|
||||
break;
|
||||
case AzPhysics::TriggerEvent::Type::Exit:
|
||||
m_triggerExitEvent.Signal(m_bodyHandle, trigger);
|
||||
break;
|
||||
default:
|
||||
AZ_Warning("Physics", false, "[SimulatedBody::ProcessTriggerEvent] Unexpected trigger type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Scene* SimulatedBody::GetScene()
|
||||
{
|
||||
if (auto* physicsSystem = AZ::Interface<SystemInterface>::Get())
|
||||
{
|
||||
return physicsSystem->GetScene(m_sceneOwner);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SimulatedBodyEvents::OnCollisionBegin* SimulatedBody::GetOnCollisionBeginEvent()
|
||||
{
|
||||
return &m_collisionBeginEvent;
|
||||
}
|
||||
|
||||
SimulatedBodyEvents::OnCollisionPersist* SimulatedBody::GetOnCollisionPersistEvent()
|
||||
{
|
||||
return &m_collisionPersistEvent;
|
||||
}
|
||||
|
||||
SimulatedBodyEvents::OnCollisionEnd* SimulatedBody::GetOnCollisionEndEvent()
|
||||
{
|
||||
return &m_collisionEndEvent;
|
||||
}
|
||||
|
||||
SimulatedBodyEvents::OnTriggerEnter* SimulatedBody::GetOnTriggerEnterEvent()
|
||||
{
|
||||
return &m_triggerEnterEvent;
|
||||
}
|
||||
|
||||
SimulatedBodyEvents::OnTriggerExit* SimulatedBody::GetOnTriggerExitEvent()
|
||||
{
|
||||
return &m_triggerExitEvent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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/Aabb.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
namespace Automation
|
||||
{
|
||||
class SimulatedBodyCollisionAutomationHandler;
|
||||
class SimulatedBodyTriggerAutomationHandler;
|
||||
}
|
||||
class Scene;
|
||||
struct CollisionEvent;
|
||||
struct TriggerEvent;
|
||||
|
||||
//! Base class for all Simulated bodies in Physics.
|
||||
struct SimulatedBody
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::SimulatedBody, "{BCC37A4F-1C05-4660-9E41-0CCF2D5E7175}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
virtual ~SimulatedBody() = default;
|
||||
|
||||
//! The current Scene the simulated body is contained.
|
||||
SceneHandle m_sceneOwner = AzPhysics::InvalidSceneHandle;
|
||||
|
||||
//! The handle to this simulated body
|
||||
SimulatedBodyHandle m_bodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
|
||||
//! Flag to determine if the body is part of the simulation.
|
||||
//! When true the body will be affected by any forces, collisions, and found with scene queries.
|
||||
bool m_simulating = true;
|
||||
|
||||
//! Helper functions for setting user data.
|
||||
//! @param userData Can be a pointer to any type as internally will be cast to a void*. Object lifetime not managed by the SimulatedBody.
|
||||
template<typename T>
|
||||
void SetUserData(T* userData);
|
||||
//! Helper functions for getting the set user data.
|
||||
//! @return Will return a void* to the user data set.
|
||||
void* GetUserData()
|
||||
{
|
||||
return m_customUserData;
|
||||
}
|
||||
|
||||
//! Perform a ray cast on this Simulated Body.
|
||||
//! @param request The request to make.
|
||||
//! @return Returns the closest hit, if any, against this simulated body.
|
||||
virtual AzPhysics::SceneQueryHit RayCast(const RayCastRequest& request) = 0;
|
||||
|
||||
//! Helper to direct the CollisionEvent to the correct handler.
|
||||
//! Will invoke the OnCollisionBegin or OnCollisionPersist or OnCollisionEnd event.
|
||||
//! @param collision The collision data to be routed.
|
||||
void ProcessCollisionEvent(const CollisionEvent& collision) const;
|
||||
|
||||
//! Helper to direct the TriggerEvent to the correct handler.
|
||||
//! Will invoke the OnTriggerEnter or OnTriggerExitevent event.
|
||||
//! @param trigger The trigger data to be routed.
|
||||
void ProcessTriggerEvent(const TriggerEvent& trigger) const;
|
||||
|
||||
//! Helpers to register a handler for Collision events on this Simulated body.
|
||||
//! OnCollisionBegin is when two bodies start to collide.
|
||||
//! OnCollisionPersist is when two bodies continue to collide.
|
||||
//! OnCollisionEnd is when two bodies stop colliding.
|
||||
void RegisterOnCollisionBeginHandler(SimulatedBodyEvents::OnCollisionBegin::Handler& handler);
|
||||
//! see RegisterOnCollisionBeginHandler
|
||||
void RegisterOnCollisionPersistHandler(SimulatedBodyEvents::OnCollisionPersist::Handler& handler);
|
||||
//! see RegisterOnCollisionBeginHandler
|
||||
void RegisterOnCollisionEndHandler(SimulatedBodyEvents::OnCollisionEnd::Handler& handler);
|
||||
|
||||
//! Helpers to register a handler for Trigger Events on this Simulated body.
|
||||
//! OnTriggerEnter is when a body enters a trigger.
|
||||
//! OnTriggerExit is when a body leaves a trigger.
|
||||
void RegisterOnTriggerEnterHandler(SimulatedBodyEvents::OnTriggerEnter::Handler& handler);
|
||||
//! see RegisterOnTriggerEnterHandler
|
||||
void RegisterOnTriggerExitHandler(SimulatedBodyEvents::OnTriggerExit::Handler& handler);
|
||||
|
||||
virtual AZ::Crc32 GetNativeType() const = 0;
|
||||
virtual void* GetNativePointer() const = 0;
|
||||
|
||||
//! Helper to get the scene this body is attached too.
|
||||
//! @return Returns a pointer to the scene.
|
||||
virtual Scene* GetScene();
|
||||
|
||||
// Temporary until LYN-438 work is complete - from old WorldBody Class
|
||||
virtual AZ::EntityId GetEntityId() const = 0;
|
||||
virtual AZ::Transform GetTransform() const = 0;
|
||||
virtual void SetTransform(const AZ::Transform& transform) = 0;
|
||||
virtual AZ::Vector3 GetPosition() const = 0;
|
||||
virtual AZ::Quaternion GetOrientation() const = 0;
|
||||
virtual AZ::Aabb GetAabb() const = 0;
|
||||
|
||||
private:
|
||||
friend class Automation::SimulatedBodyCollisionAutomationHandler;
|
||||
friend class Automation::SimulatedBodyTriggerAutomationHandler;
|
||||
|
||||
SimulatedBodyEvents::OnCollisionBegin m_collisionBeginEvent;
|
||||
SimulatedBodyEvents::OnCollisionPersist m_collisionPersistEvent;
|
||||
SimulatedBodyEvents::OnCollisionEnd m_collisionEndEvent;
|
||||
SimulatedBodyEvents::OnTriggerEnter m_triggerEnterEvent;
|
||||
SimulatedBodyEvents::OnTriggerExit m_triggerExitEvent;
|
||||
|
||||
void* m_customUserData = nullptr;
|
||||
|
||||
// helpers for reflecting to behavior context
|
||||
SimulatedBodyEvents::OnCollisionBegin* GetOnCollisionBeginEvent();
|
||||
SimulatedBodyEvents::OnCollisionPersist* GetOnCollisionPersistEvent();
|
||||
SimulatedBodyEvents::OnCollisionEnd* GetOnCollisionEndEvent();
|
||||
SimulatedBodyEvents::OnTriggerEnter* GetOnTriggerEnterEvent();
|
||||
SimulatedBodyEvents::OnTriggerExit* GetOnTriggerExitEvent();
|
||||
};
|
||||
//! Alias for a list of non owning weak pointers to SimulatedBody objects.
|
||||
using SimulatedBodyList = AZStd::vector<SimulatedBody*>;
|
||||
|
||||
template<typename T>
|
||||
void SimulatedBody::SetUserData(T* userData)
|
||||
{
|
||||
m_customUserData = static_cast<void*>(userData);
|
||||
}
|
||||
|
||||
inline void SimulatedBody::RegisterOnCollisionBeginHandler(SimulatedBodyEvents::OnCollisionBegin::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_collisionBeginEvent);
|
||||
}
|
||||
|
||||
inline void SimulatedBody::RegisterOnCollisionPersistHandler(SimulatedBodyEvents::OnCollisionPersist::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_collisionPersistEvent);
|
||||
}
|
||||
|
||||
inline void SimulatedBody::RegisterOnCollisionEndHandler(SimulatedBodyEvents::OnCollisionEnd::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_collisionEndEvent);
|
||||
}
|
||||
|
||||
inline void SimulatedBody::RegisterOnTriggerEnterHandler(SimulatedBodyEvents::OnTriggerEnter::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_triggerEnterEvent);
|
||||
}
|
||||
|
||||
inline void SimulatedBody::RegisterOnTriggerExitHandler(SimulatedBodyEvents::OnTriggerExit::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_triggerExitEvent);
|
||||
}
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Common/PhysicsSimulatedBodyAutomation.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace AzPhysics::Automation
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SimulatedBodyCollisionAutomationHandler, AZ::SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SimulatedBodyTriggerAutomationHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
/*static*/ void SimulatedBodyCollisionAutomationHandler::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<AzPhysics::Automation::AutomationCollisionNotificationsBus>("CollisionNotificationBus")
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Physics")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
||||
->Handler<SimulatedBodyCollisionAutomationHandler>()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
SimulatedBodyCollisionAutomationHandler::SimulatedBodyCollisionAutomationHandler()
|
||||
{
|
||||
m_collisionBeginHandler = SimulatedBodyEvents::OnCollisionBegin::Handler(
|
||||
[this]([[maybe_unused]] SimulatedBodyHandle bodyHandle,
|
||||
const CollisionEvent& event)
|
||||
{
|
||||
OnCollisionBeginEvent(event);
|
||||
});
|
||||
m_collisionPersistHandler = SimulatedBodyEvents::OnCollisionPersist::Handler(
|
||||
[this]([[maybe_unused]] SimulatedBodyHandle bodyHandle,
|
||||
const CollisionEvent& event)
|
||||
{
|
||||
OnCollisionPersistEvent(event);
|
||||
});
|
||||
m_collisionEndHandler = SimulatedBodyEvents::OnCollisionEnd::Handler(
|
||||
[this]([[maybe_unused]] SimulatedBodyHandle bodyHandle,
|
||||
const CollisionEvent& event)
|
||||
{
|
||||
OnCollisionEndEvent(event);
|
||||
});
|
||||
|
||||
SetEvent(&SimulatedBodyCollisionAutomationHandler::OnCollisionBegin, "OnCollisionBegin");
|
||||
SetEvent(&SimulatedBodyCollisionAutomationHandler::OnCollisionPersist, "OnCollisionPersist");
|
||||
SetEvent(&SimulatedBodyCollisionAutomationHandler::OnCollisionEnd, "OnCollisionEnd");
|
||||
}
|
||||
|
||||
void SimulatedBodyCollisionAutomationHandler::Disconnect()
|
||||
{
|
||||
m_collisionBeginHandler.Disconnect();
|
||||
m_collisionPersistHandler.Disconnect();
|
||||
m_collisionEndHandler.Disconnect();
|
||||
}
|
||||
|
||||
bool SimulatedBodyCollisionAutomationHandler::Connect(AZ::BehaviorValueParameter* id /*= nullptr*/)
|
||||
{
|
||||
if (id && id->ConvertTo<typename AZ::EntityId>())
|
||||
{
|
||||
m_connectedEntityId = *id->GetAsUnsafe<typename AZ::EntityId>();
|
||||
auto* physicsSystem = AZ::Interface<SystemInterface>::Get();
|
||||
auto* sceneInterface = AZ::Interface<SceneInterface>::Get();
|
||||
if (physicsSystem != nullptr && sceneInterface != nullptr)
|
||||
{
|
||||
auto [sceneHandle, bodyHandle] = physicsSystem->FindAttachedBodyHandleFromEntityId(m_connectedEntityId);
|
||||
if (SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle))
|
||||
{
|
||||
bool connected = false;
|
||||
if (auto* collisionBeginEvent = body->GetOnCollisionBeginEvent())
|
||||
{
|
||||
m_collisionBeginHandler.Connect(*collisionBeginEvent);
|
||||
connected = true;
|
||||
}
|
||||
if (auto* collisionPersistEvent = body->GetOnCollisionPersistEvent())
|
||||
{
|
||||
m_collisionPersistHandler.Connect(*collisionPersistEvent);
|
||||
connected = true;
|
||||
}
|
||||
if (auto* collisionEndEvent = body->GetOnCollisionEndEvent())
|
||||
{
|
||||
m_collisionEndHandler.Connect(*collisionEndEvent);
|
||||
connected = true;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SimulatedBodyCollisionAutomationHandler::IsConnected()
|
||||
{
|
||||
return m_collisionBeginHandler.IsConnected() || m_collisionPersistHandler.IsConnected() || m_collisionEndHandler.IsConnected();
|
||||
}
|
||||
|
||||
bool SimulatedBodyCollisionAutomationHandler::IsConnectedId(AZ::BehaviorValueParameter* id)
|
||||
{
|
||||
if (id && id->ConvertTo<typename AZ::EntityId>())
|
||||
{
|
||||
return m_connectedEntityId == *id->GetAsUnsafe<typename AZ::EntityId>() && IsConnected();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int SimulatedBodyCollisionAutomationHandler::GetFunctionIndex(const char* functionName) const
|
||||
{
|
||||
if (azstricmp(functionName, "OnCollisionBegin") == 0)
|
||||
{
|
||||
return FN_OnCollisionBegin;
|
||||
}
|
||||
if (azstricmp(functionName, "OnCollisionPersist") == 0)
|
||||
{
|
||||
return FN_OnCollisionPersist;
|
||||
}
|
||||
if (azstricmp(functionName, "OnCollisionEnd") == 0)
|
||||
{
|
||||
return FN_OnCollisionEnd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SimulatedBodyCollisionAutomationHandler::OnCollisionBeginEvent(const CollisionEvent& event)
|
||||
{
|
||||
Call(FN_OnCollisionBegin, event.m_body2->GetEntityId(), event.m_contacts); //send m_body2 entity id as that is the other body involved in the collision.
|
||||
}
|
||||
|
||||
void SimulatedBodyCollisionAutomationHandler::OnCollisionPersistEvent(const CollisionEvent& event)
|
||||
{
|
||||
Call(FN_OnCollisionPersist, event.m_body2->GetEntityId(), event.m_contacts); //send m_body2 entity id as that is the other body involved in the collision.
|
||||
}
|
||||
|
||||
void SimulatedBodyCollisionAutomationHandler::OnCollisionEndEvent(const CollisionEvent& event)
|
||||
{
|
||||
Call(FN_OnCollisionEnd, event.m_body2->GetEntityId()); //send m_body2 entity id as that is the other body involved in the collision.
|
||||
}
|
||||
|
||||
/*static*/ void SimulatedBodyTriggerAutomationHandler::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<AzPhysics::Automation::AutomationTriggerNotificationsBus>("TriggerNotificationBus")
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Physics")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
||||
->Handler<SimulatedBodyTriggerAutomationHandler>()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
SimulatedBodyTriggerAutomationHandler::SimulatedBodyTriggerAutomationHandler()
|
||||
{
|
||||
m_triggerEnterHandler = SimulatedBodyEvents::OnTriggerEnter::Handler(
|
||||
[this]([[maybe_unused]] SimulatedBodyHandle bodyHandle,
|
||||
const TriggerEvent& event)
|
||||
{
|
||||
OnTriggerEnterEvent(event);
|
||||
});
|
||||
m_triggerExitHandler = SimulatedBodyEvents::OnTriggerExit::Handler(
|
||||
[this]([[maybe_unused]] SimulatedBodyHandle bodyHandle,
|
||||
const TriggerEvent& event)
|
||||
{
|
||||
OnTriggerExitEvent(event);
|
||||
});
|
||||
|
||||
SetEvent(&SimulatedBodyTriggerAutomationHandler::OnTriggerEnter, "OnTriggerEnter");
|
||||
SetEvent(&SimulatedBodyTriggerAutomationHandler::OnTriggerExit, "OnTriggerExit");
|
||||
}
|
||||
|
||||
void SimulatedBodyTriggerAutomationHandler::Disconnect()
|
||||
{
|
||||
m_triggerEnterHandler.Disconnect();
|
||||
m_triggerExitHandler.Disconnect();
|
||||
}
|
||||
|
||||
bool SimulatedBodyTriggerAutomationHandler::Connect(AZ::BehaviorValueParameter* id /*= nullptr*/)
|
||||
{
|
||||
if (id && id->ConvertTo<typename AZ::EntityId>())
|
||||
{
|
||||
m_connectedEntityId = *id->GetAsUnsafe<typename AZ::EntityId>();
|
||||
auto* physicsSystem = AZ::Interface<SystemInterface>::Get();
|
||||
auto* sceneInterface = AZ::Interface<SceneInterface>::Get();
|
||||
if (physicsSystem != nullptr && sceneInterface != nullptr)
|
||||
{
|
||||
auto [sceneHandle, bodyHandle] = physicsSystem->FindAttachedBodyHandleFromEntityId(m_connectedEntityId);
|
||||
if (SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle))
|
||||
{
|
||||
bool connected = false;
|
||||
if (auto* triggerEnterEvent = body->GetOnTriggerEnterEvent())
|
||||
{
|
||||
m_triggerEnterHandler.Connect(*triggerEnterEvent);
|
||||
connected = true;
|
||||
}
|
||||
if (auto* triggerExitEvent = body->GetOnTriggerExitEvent())
|
||||
{
|
||||
m_triggerExitHandler.Connect(*triggerExitEvent);
|
||||
connected = true;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SimulatedBodyTriggerAutomationHandler::IsConnected()
|
||||
{
|
||||
return m_triggerEnterHandler.IsConnected() || m_triggerExitHandler.IsConnected();
|
||||
}
|
||||
|
||||
bool SimulatedBodyTriggerAutomationHandler::IsConnectedId(AZ::BehaviorValueParameter* id)
|
||||
{
|
||||
if (id && id->ConvertTo<typename AZ::EntityId>())
|
||||
{
|
||||
return m_connectedEntityId == *id->GetAsUnsafe<typename AZ::EntityId>() && IsConnected();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int SimulatedBodyTriggerAutomationHandler::GetFunctionIndex(const char* functionName) const
|
||||
{
|
||||
if (azstricmp(functionName, "OnTriggerEnter") == 0)
|
||||
{
|
||||
return FN_OnTriggerEnter;
|
||||
}
|
||||
if (azstricmp(functionName, "OnTriggerExit") == 0)
|
||||
{
|
||||
return FN_OnTriggerExit;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SimulatedBodyTriggerAutomationHandler::OnTriggerEnterEvent(const TriggerEvent& event)
|
||||
{
|
||||
Call(FN_OnTriggerEnter, event.m_otherBody->GetEntityId());
|
||||
}
|
||||
|
||||
void SimulatedBodyTriggerAutomationHandler::OnTriggerExitEvent(const TriggerEvent& event)
|
||||
{
|
||||
Call(FN_OnTriggerExit, event.m_otherBody->GetEntityId());
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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/Component/ComponentBus.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
struct BehaviorValueParameter;
|
||||
}
|
||||
|
||||
namespace AzPhysics::Automation
|
||||
{
|
||||
//! Buses to expose Collision and Trigger event to Automation
|
||||
//! @{
|
||||
class AutomationCollisionNotifications
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
virtual ~AutomationCollisionNotifications() = default;
|
||||
virtual void OnCollisionBegin(AZ::EntityId entityId, const AZStd::vector<AzPhysics::Contact>& contacts) = 0;
|
||||
virtual void OnCollisionPersist(AZ::EntityId entityId, const AZStd::vector<AzPhysics::Contact>& contacts) = 0;
|
||||
virtual void OnCollisionEnd(AZ::EntityId entityId) = 0;
|
||||
};
|
||||
using AutomationCollisionNotificationsBus = AZ::EBus<AutomationCollisionNotifications>;
|
||||
|
||||
class AutomationTriggerNotifications
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
virtual ~AutomationTriggerNotifications() = default;
|
||||
virtual void OnTriggerEnter(AZ::EntityId entityId) = 0;
|
||||
virtual void OnTriggerExit(AZ::EntityId entityId) = 0;
|
||||
};
|
||||
using AutomationTriggerNotificationsBus = AZ::EBus<AutomationTriggerNotifications>;
|
||||
//! @}
|
||||
|
||||
//! Collision Event Handler for Automation
|
||||
//! @note this class is not using the usual AZ_EBUS_BEHAVIOR_BINDER macro as the signature
|
||||
//! needs to be changed for script canvas.
|
||||
class SimulatedBodyCollisionAutomationHandler
|
||||
: public AutomationCollisionNotificationsBus::Handler
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::Automation::SimulatedBodyCollisionAutomationHandler, "{B0493CB7-9D20-44E1-B744-1419E54CAF67}", AZ::BehaviorEBusHandler);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SimulatedBodyCollisionAutomationHandler();
|
||||
|
||||
using EventFunctionsParameterPack = AZStd::Internal::pack_traits_arg_sequence<
|
||||
decltype(&SimulatedBodyCollisionAutomationHandler::OnCollisionBegin),
|
||||
decltype(&SimulatedBodyCollisionAutomationHandler::OnCollisionPersist),
|
||||
decltype(&SimulatedBodyCollisionAutomationHandler::OnCollisionEnd)
|
||||
>;
|
||||
private:
|
||||
// AutomationCollisionNotificationsBus::Handler Interface
|
||||
void OnCollisionBegin([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const AZStd::vector<AzPhysics::Contact>& contacts) override {}
|
||||
void OnCollisionPersist([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const AZStd::vector<AzPhysics::Contact>& contacts) override {}
|
||||
void OnCollisionEnd([[maybe_unused]] AZ::EntityId entityId) override {}
|
||||
|
||||
enum
|
||||
{
|
||||
FN_OnCollisionBegin,
|
||||
FN_OnCollisionPersist,
|
||||
FN_OnCollisionEnd,
|
||||
FN_MAX
|
||||
};
|
||||
|
||||
// AZ::BehaviorEBusHandler interface
|
||||
void Disconnect() override;
|
||||
bool Connect(AZ::BehaviorValueParameter* id = nullptr) override;
|
||||
bool IsConnected() override;
|
||||
bool IsConnectedId(AZ::BehaviorValueParameter* id) override;
|
||||
int GetFunctionIndex(const char* functionName) const override;
|
||||
|
||||
void OnCollisionBeginEvent(const CollisionEvent& event);
|
||||
void OnCollisionPersistEvent(const CollisionEvent& event);
|
||||
void OnCollisionEndEvent(const CollisionEvent& event);
|
||||
|
||||
AZ::EntityId m_connectedEntityId;
|
||||
SimulatedBodyEvents::OnCollisionBegin::Handler m_collisionBeginHandler;
|
||||
SimulatedBodyEvents::OnCollisionPersist::Handler m_collisionPersistHandler;
|
||||
SimulatedBodyEvents::OnCollisionEnd::Handler m_collisionEndHandler;
|
||||
};
|
||||
|
||||
//! Trigger Event Handler for Automation
|
||||
//! @note this class is not using the usual AZ_EBUS_BEHAVIOR_BINDER macro as the signature
|
||||
//! needs to be changed for script canvas.
|
||||
class SimulatedBodyTriggerAutomationHandler
|
||||
: public AutomationTriggerNotificationsBus::Handler
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::Automation::SimulatedBodyTriggerAutomationHandler, "{0BFA757E-F270-40D7-8543-B21260A987D0}", AZ::BehaviorEBusHandler);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SimulatedBodyTriggerAutomationHandler();
|
||||
|
||||
using EventFunctionsParameterPack = AZStd::Internal::pack_traits_arg_sequence<
|
||||
decltype(&SimulatedBodyTriggerAutomationHandler::OnTriggerEnter),
|
||||
decltype(&SimulatedBodyTriggerAutomationHandler::OnTriggerExit)
|
||||
>;
|
||||
private:
|
||||
// AutomationTriggerNotificationsBus::Handler Interface
|
||||
void OnTriggerEnter([[maybe_unused]] AZ::EntityId entityId) override {}
|
||||
void OnTriggerExit([[maybe_unused]] AZ::EntityId entityId) override {}
|
||||
|
||||
enum
|
||||
{
|
||||
FN_OnTriggerEnter,
|
||||
FN_OnTriggerExit,
|
||||
FN_MAX
|
||||
};
|
||||
|
||||
// AZ::BehaviorEBusHandler interface
|
||||
void Disconnect() override;
|
||||
bool Connect(AZ::BehaviorValueParameter* id = nullptr) override;
|
||||
bool IsConnected() override;
|
||||
bool IsConnectedId(AZ::BehaviorValueParameter* id) override;
|
||||
int GetFunctionIndex(const char* functionName) const override;
|
||||
|
||||
void OnTriggerEnterEvent(const TriggerEvent& event);
|
||||
void OnTriggerExitEvent(const TriggerEvent& event);
|
||||
|
||||
AZ::EntityId m_connectedEntityId;
|
||||
SimulatedBodyEvents::OnTriggerEnter::Handler m_triggerEnterHandler;
|
||||
SimulatedBodyEvents::OnTriggerExit::Handler m_triggerExitHandler;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
|
||||
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
namespace SimulatedBodyEvents
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
//helper to register a handler
|
||||
template<typename Handler, class Function>
|
||||
void RegisterHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
Handler& handler, Function registerFunc)
|
||||
{
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
if (AzPhysics::SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle))
|
||||
{
|
||||
auto func = AZStd::bind(registerFunc, body, AZStd::placeholders::_1);
|
||||
func(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterOnCollisionBeginHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionBegin::Handler& handler)
|
||||
{
|
||||
Internal::RegisterHandler(sceneHandle, bodyHandle, handler, &SimulatedBody::RegisterOnCollisionBeginHandler);
|
||||
}
|
||||
|
||||
void RegisterOnCollisionPersistHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionPersist::Handler& handler)
|
||||
{
|
||||
Internal::RegisterHandler(sceneHandle, bodyHandle, handler, &SimulatedBody::RegisterOnCollisionPersistHandler);
|
||||
}
|
||||
|
||||
void RegisterOnCollisionEndHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionEnd::Handler& handler)
|
||||
{
|
||||
Internal::RegisterHandler(sceneHandle, bodyHandle, handler, &SimulatedBody::RegisterOnCollisionEndHandler);
|
||||
}
|
||||
|
||||
void RegisterOnTriggerEnterHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnTriggerEnter::Handler& handler)
|
||||
{
|
||||
Internal::RegisterHandler(sceneHandle, bodyHandle, handler, &SimulatedBody::RegisterOnTriggerEnterHandler);
|
||||
}
|
||||
|
||||
void RegisterOnTriggerExitHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnTriggerExit::Handler& handler)
|
||||
{
|
||||
Internal::RegisterHandler(sceneHandle, bodyHandle, handler, &SimulatedBody::RegisterOnTriggerExitHandler);
|
||||
}
|
||||
} // namespace SimulatedBodyEvents
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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/EBus/Event.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct CollisionEvent;
|
||||
struct TriggerEvent;
|
||||
|
||||
namespace SimulatedBodyEvents
|
||||
{
|
||||
//! Collision Events for Simulated bodies.
|
||||
//! OnCollisionBegin is when two bodies start to collide. Will always be triggered before OnCollisionPersist and OnCollisionEnd.
|
||||
//! OnCollisionPersist is when two bodies continue to collide. Can only be triggered after OnCollisionBegin and before OnCollisionEnd.
|
||||
//! OnCollisionEnd is when two bodies stop colliding. Will always be triggered after OnCollisionBegin and OnCollisionPersist.
|
||||
//! The SimulatedBodyHandle passed in the event will match CollisionEvent::m_bodyHandle1, CollisionEvent::m_bodyHandle2 will be the other body involved.
|
||||
//! @note The CollisionEvent is only valid for the duration of the callback.
|
||||
//! This may fire multiple times per frame.
|
||||
using OnCollisionBegin = AZ::Event<SimulatedBodyHandle, const CollisionEvent&>;
|
||||
|
||||
//! see OnCollisionBegin
|
||||
using OnCollisionPersist = AZ::Event<SimulatedBodyHandle, const CollisionEvent&>;
|
||||
|
||||
//! see OnCollisionBegin
|
||||
using OnCollisionEnd = AZ::Event<SimulatedBodyHandle, const CollisionEvent&>;
|
||||
|
||||
//! Trigger Events for Simulated bodies.
|
||||
//! OnTriggerEnter is when a body enters a trigger.
|
||||
//! OnTriggerExit is when a body leaves a trigger. Will only be triggered after OnTriggerEnter.
|
||||
//! These events will be triggered on both the trigger body and the body that entered/exited the trigger.
|
||||
//! The SimulatedBodyHandle passed will be the body that the handler is registered to, which can be the Trigger or Other body.
|
||||
//! @note The TriggerEvent is only valid for the duration of the callback.
|
||||
//! This may fire multiple times per frame.
|
||||
using OnTriggerEnter = AZ::Event<SimulatedBodyHandle, const TriggerEvent&>;
|
||||
|
||||
//! see OnTriggerEnter
|
||||
using OnTriggerExit = AZ::Event<SimulatedBodyHandle, const TriggerEvent&>;
|
||||
|
||||
//! Helper to register a Collision Event handler.
|
||||
//! @param sceneHandle A handle to the scene that owns the simulated body.
|
||||
//! @param bodyHandle A handle to the simulated body.
|
||||
//! @param handler The handle to register.
|
||||
void RegisterOnCollisionBeginHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionBegin::Handler& handler);
|
||||
|
||||
//! see RegisterOnCollisionBeginHandler
|
||||
void RegisterOnCollisionPersistHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionPersist::Handler& handler);
|
||||
|
||||
//! see RegisterOnCollisionBeginHandler
|
||||
void RegisterOnCollisionEndHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnCollisionEnd::Handler& handler);
|
||||
|
||||
//! Helper to register a Trigger Event handler.
|
||||
//! @param sceneHandle A handle to the scene that owns the simulated body.
|
||||
//! @param bodyHandle A handle to the simulated body.
|
||||
//! @param handler The handle to register.
|
||||
void RegisterOnTriggerEnterHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnTriggerEnter::Handler& handler);
|
||||
|
||||
//! see RegisterOnTriggerEnterHandler
|
||||
void RegisterOnTriggerExitHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle,
|
||||
OnTriggerExit::Handler& handler);
|
||||
} // namespace SimulatedBodyEvents
|
||||
}
|
||||
@@ -11,33 +11,121 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/std/tuple.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ColliderConfiguration;
|
||||
class Shape;
|
||||
class ShapeConfiguration;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
using SceneIndex = AZ::s8;
|
||||
//! Default Scene Names and Crc32
|
||||
static constexpr const char* DefaultPhysicsSceneName = "DefaultScene";
|
||||
static constexpr const AZ::Crc32 DefaultPhysicsSceneId = AZ_CRC_CE(DefaultPhysicsSceneName);
|
||||
static constexpr const char* EditorPhysicsSceneName = "EditorScene";
|
||||
static constexpr const AZ::Crc32 EditorPhysicsSceneId = AZ_CRC_CE(EditorPhysicsSceneName);
|
||||
|
||||
//! A handle to a Scene within the physics simulation.
|
||||
//! A SceneHandle is a tuple of a Crc of the scenes name and the index in the Scene list.
|
||||
using SceneHandle = AZStd::tuple<AZ::Crc32, SceneIndex>;
|
||||
|
||||
//! Default gravity.
|
||||
static const AZ::Vector3 DefaultGravity = AZ::Vector3(0.0f, 0.0f, -9.81f);
|
||||
|
||||
//! Helper for retrieving the values from the SceneHandle tuple.
|
||||
//! Example usage
|
||||
//! @code{ .cpp }
|
||||
//! SceneHandle someHandle;
|
||||
//! AZ::Crc32 handleCrc = AZStd::get<SceneHandleValues::Crc>(someHandle);
|
||||
//! SceneIndex index = AZStd::get<SceneHandleValues::Index>(someHandle);
|
||||
//! const AZ::Crc32 handleCrc = AZStd::get<HandleTypeIndex::Crc>(someHandle);
|
||||
//! const SceneIndex index = AZStd::get<HandleTypeIndex::Index>(someHandle);
|
||||
//! @endcode
|
||||
enum SceneHandleValues
|
||||
enum HandleTypeIndex
|
||||
{
|
||||
Crc = 0,
|
||||
Index
|
||||
};
|
||||
|
||||
using SceneIndex = AZ::s8;
|
||||
using SimulatedBodyIndex = AZ::s32;
|
||||
static_assert(std::is_signed<SceneIndex>::value
|
||||
&& std::is_signed<SimulatedBodyIndex>::value, "SceneIndex and SimulatedBodyIndex must be signed integers.");
|
||||
|
||||
|
||||
//! A handle to a Scene within the physics simulation.
|
||||
//! A SceneHandle is a tuple of a Crc of the scenes name and the index in the Scene list.
|
||||
using SceneHandle = AZStd::tuple<AZ::Crc32, SceneIndex>;
|
||||
static constexpr SceneHandle InvalidSceneHandle = { AZ::Crc32(), -1 };
|
||||
|
||||
//! Ease of use type for referencing a List of SceneHandle objects.
|
||||
using SceneHandleList = AZStd::vector<SceneHandle>;
|
||||
|
||||
//! A handle to a Simulated body within a physics scene.
|
||||
//! A SimulatedBodyHandle is a tuple of a Crc of the scene's name and the index in the SimulatedBody list.
|
||||
using SimulatedBodyHandle = AZStd::tuple<AZ::Crc32, SimulatedBodyIndex>;
|
||||
static constexpr SimulatedBodyHandle InvalidSimulatedBodyHandle = { AZ::Crc32(), -1 };
|
||||
using SimulatedBodyHandleList = AZStd::vector<SimulatedBodyHandle>;
|
||||
|
||||
//! Helper used for pairing the ShapeConfiguration and ColliderConfiguration together which is used when creating a Simulated Body.
|
||||
using ShapeColliderPair = AZStd::pair<Physics::ColliderConfiguration*, Physics::ShapeConfiguration*>;
|
||||
|
||||
//! Flags used to specifying which properties of a body to compute.
|
||||
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
|
||||
};
|
||||
//! 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));
|
||||
}
|
||||
|
||||
//! Variant to allow support for the system to either create the Shape(s) or use the provide Shape(s) that have been created externally.
|
||||
//! Can be one of the following.
|
||||
//! @code{ .cpp }
|
||||
//! // A ShapeColliderPair, which contains a ColliderConfiguration and ShapeConfiguration.
|
||||
//! AzPhysics::StaticRigidBodyConfiguration staticRigidBodyConfig;
|
||||
//! staticRigidBodyConfig.m_colliderAndShapeData = AzPhysics::ShapeColliderPair(&colliderConfig, &shapeConfig);
|
||||
//!
|
||||
//! // A pointer to a Physics::Shape. The Simulated Body will take ownership of the pointer.
|
||||
//! AZStd::shared_ptr<Physics::Shape> shapePtr /*Created through other means*/;
|
||||
//! AzPhysics::StaticRigidBodyConfiguration staticRigidBodyConfig;
|
||||
//! staticRigidBodyConfig.m_colliderAndShapeData = shapePtr;
|
||||
//!
|
||||
//! // A list of ShapeColliderPairs.
|
||||
//! AZStd::vector<AzPhysics::ShapeColliderPair> shapeColliderPairList;
|
||||
//! shapeColliderPairList.emplace_back(&colliderConfig, &shapeConfig); //add as many configs as required.
|
||||
//! AzPhysics::StaticRigidBodyConfiguration staticRigidBodyConfig;
|
||||
//! staticRigidBodyConfig.m_colliderAndShapeData = shapeColliderPairList;
|
||||
//!
|
||||
//! // A list of Physics::Shape pointers. The Simulated Body will take ownership of these pointers.
|
||||
//! AZStd::vector<AZStd::shared_ptr<Physics::Shape>> shapePtrList;
|
||||
//! shapePtrList.emplace_back(/*Shape created through other means*/);
|
||||
//! AzPhysics::StaticRigidBodyConfiguration staticRigidBodyConfig;
|
||||
//! staticRigidBodyConfig.m_colliderAndShapeData = shapePtrList;
|
||||
//! @endcode
|
||||
using ShapeVariantData = AZStd::variant<
|
||||
AZStd::monostate,
|
||||
ShapeColliderPair,
|
||||
AZStd::shared_ptr<Physics::Shape>,
|
||||
AZStd::vector<ShapeColliderPair>,
|
||||
AZStd::vector<AZStd::shared_ptr<Physics::Shape>>>;
|
||||
}
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
// Visibility functions.
|
||||
AZ::Crc32 GetPropertyVisibility(AZ::u16 flags, RigidBodyConfiguration::PropertyVisibility property)
|
||||
{
|
||||
return (flags & property) != 0 ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
void SetPropertyVisibility(AZ::u16 flags, RigidBodyConfiguration::PropertyVisibility property, bool isVisible)
|
||||
{
|
||||
if (isVisible)
|
||||
{
|
||||
flags |= property;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags &= ~property;
|
||||
}
|
||||
}
|
||||
|
||||
bool RigidBodyVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
|
||||
{
|
||||
if (classElement.GetVersion() <= 1)
|
||||
{
|
||||
const int elementIndex = classElement.FindElement(AZ_CRC("Centre of mass offset", 0x1e569a45));
|
||||
|
||||
if (elementIndex >= 0)
|
||||
{
|
||||
AZ::Vector3 existingCenterOfMassOffset;
|
||||
AZ::SerializeContext::DataElementNode& centerOfMassElement = classElement.GetSubElement(elementIndex);
|
||||
const bool found = centerOfMassElement.GetData<AZ::Vector3>(existingCenterOfMassOffset);
|
||||
|
||||
if (found && !existingCenterOfMassOffset.IsZero())
|
||||
{
|
||||
// An existing center of mass (COM) offset value was specified for this rigid body.
|
||||
// Version 2 includes a new m_computeCenterOfMass boolean flag to specify the automatic calculation of COM.
|
||||
// In this case set m_computeCenterOfMass to false so that the existing center of mass offset value is utilized correctly.
|
||||
const int idx = classElement.AddElement<bool>(context, "Compute COM");
|
||||
if (idx != -1)
|
||||
{
|
||||
if (!classElement.GetSubElement(idx).SetData<bool>(context, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classElement.GetVersion() <= 2)
|
||||
{
|
||||
const int elementIndex = classElement.FindElement(AZ_CRC("Mass", 0x6c035b66));
|
||||
|
||||
if (elementIndex >= 0)
|
||||
{
|
||||
float existingMass = 0;
|
||||
AZ::SerializeContext::DataElementNode& massElement = classElement.GetSubElement(elementIndex);
|
||||
const bool found = massElement.GetData<float>(existingMass);
|
||||
|
||||
if (found && existingMass > 0)
|
||||
{
|
||||
// Keeping the existing mass and disabling auto-compute of the mass for this rigid body.
|
||||
// Version 3 includes a new m_computeMass boolean flag to specify the automatic calculation of mass.
|
||||
const int idx = classElement.AddElement<bool>(context, "Compute Mass");
|
||||
if (idx != -1)
|
||||
{
|
||||
if (!classElement.GetSubElement(idx).SetData<bool>(context, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classElement.GetVersion() <= 3)
|
||||
{
|
||||
classElement.RemoveElementByName(AZ_CRC_CE("Property Visibility Flags"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_CLASS_ALLOCATOR_IMPL(RigidBodyConfiguration, AZ::SystemAllocator, 0);
|
||||
|
||||
void RigidBodyConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<RigidBodyConfiguration, AzPhysics::SimulatedBodyConfiguration>()
|
||||
->Version(4, &Internal::RigidBodyVersionConverter)
|
||||
->Field("Initial linear velocity", &RigidBodyConfiguration::m_initialLinearVelocity)
|
||||
->Field("Initial angular velocity", &RigidBodyConfiguration::m_initialAngularVelocity)
|
||||
->Field("Linear damping", &RigidBodyConfiguration::m_linearDamping)
|
||||
->Field("Angular damping", &RigidBodyConfiguration::m_angularDamping)
|
||||
->Field("Sleep threshold", &RigidBodyConfiguration::m_sleepMinEnergy)
|
||||
->Field("Start Asleep", &RigidBodyConfiguration::m_startAsleep)
|
||||
->Field("Interpolate Motion", &RigidBodyConfiguration::m_interpolateMotion)
|
||||
->Field("Gravity Enabled", &RigidBodyConfiguration::m_gravityEnabled)
|
||||
->Field("Simulated", &RigidBodyConfiguration::m_simulated)
|
||||
->Field("Kinematic", &RigidBodyConfiguration::m_kinematic)
|
||||
->Field("CCD Enabled", &RigidBodyConfiguration::m_ccdEnabled)
|
||||
->Field("Compute Mass", &RigidBodyConfiguration::m_computeMass)
|
||||
->Field("Mass", &RigidBodyConfiguration::m_mass)
|
||||
->Field("Compute COM", &RigidBodyConfiguration::m_computeCenterOfMass)
|
||||
->Field("Centre of mass offset", &RigidBodyConfiguration::m_centerOfMassOffset)
|
||||
->Field("Compute inertia", &RigidBodyConfiguration::m_computeInertiaTensor)
|
||||
->Field("Inertia tensor", &RigidBodyConfiguration::m_inertiaTensor)
|
||||
->Field("Maximum Angular Velocity", &RigidBodyConfiguration::m_maxAngularVelocity)
|
||||
->Field("Include All Shapes In Mass", &RigidBodyConfiguration::m_includeAllShapesInMassCalculation)
|
||||
->Field("CCD Min Advance", &RigidBodyConfiguration::m_ccdMinAdvanceCoefficient)
|
||||
->Field("CCD Friction", &RigidBodyConfiguration::m_ccdFrictionEnabled)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
MassComputeFlags RigidBodyConfiguration::GetMassComputeFlags() const
|
||||
{
|
||||
MassComputeFlags flags = MassComputeFlags::NONE;
|
||||
|
||||
if (m_computeCenterOfMass)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_COM;
|
||||
}
|
||||
|
||||
if (m_computeInertiaTensor)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_INERTIA;
|
||||
}
|
||||
|
||||
if (m_computeMass)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_MASS;
|
||||
}
|
||||
|
||||
if (m_includeAllShapesInMassCalculation)
|
||||
{
|
||||
flags = flags | MassComputeFlags::INCLUDE_ALL_SHAPES;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void RigidBodyConfiguration::SetMassComputeFlags(MassComputeFlags flags)
|
||||
{
|
||||
m_computeCenterOfMass = MassComputeFlags::COMPUTE_COM == (flags & MassComputeFlags::COMPUTE_COM);
|
||||
m_computeInertiaTensor = MassComputeFlags::COMPUTE_INERTIA == (flags & MassComputeFlags::COMPUTE_INERTIA);
|
||||
m_computeMass = MassComputeFlags::COMPUTE_MASS == (flags & MassComputeFlags::COMPUTE_MASS);
|
||||
m_includeAllShapesInMassCalculation =
|
||||
MassComputeFlags::INCLUDE_ALL_SHAPES == (flags & MassComputeFlags::INCLUDE_ALL_SHAPES);
|
||||
}
|
||||
|
||||
bool RigidBodyConfiguration::IsCCDEnabled() const
|
||||
{
|
||||
return m_ccdEnabled;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInitialVelocitiesVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::InitialVelocities);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInertiaSettingsVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::InertiaProperties);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInertiaVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & RigidBodyConfiguration::PropertyVisibility::InertiaProperties) != 0) && !m_computeInertiaTensor;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetCoMVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & RigidBodyConfiguration::PropertyVisibility::InertiaProperties) != 0) && !m_computeCenterOfMass;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetMassVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & RigidBodyConfiguration::PropertyVisibility::InertiaProperties) != 0) && !m_computeMass;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetDampingVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::Damping);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetSleepOptionsVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::SleepOptions);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInterpolationVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::Interpolation);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetGravityVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::Gravity);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetKinematicVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::Kinematic);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetCCDVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::ContinuousCollisionDetection);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetMaxVelocitiesVisibility() const
|
||||
{
|
||||
return Internal::GetPropertyVisibility(m_propertyVisibilityFlags, RigidBodyConfiguration::PropertyVisibility::MaxVelocities);
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
//! Configuration used to Add Rigid bodies to a Scene.
|
||||
struct RigidBodyConfiguration
|
||||
: public AzPhysics::SimulatedBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(RigidBodyConfiguration, "{ACFA8900-8530-4744-AF00-AA533C868A8E}", AzPhysics::SimulatedBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
RigidBodyConfiguration() = default;
|
||||
|
||||
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 = 1.0f;
|
||||
AZ::Matrix3x3 m_inertiaTensor = AZ::Matrix3x3::CreateIdentity();
|
||||
float m_linearDamping = 0.05f;
|
||||
float m_angularDamping = 0.15f;
|
||||
float m_sleepMinEnergy = 0.005f;
|
||||
float m_maxAngularVelocity = 100.0f;
|
||||
|
||||
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;
|
||||
|
||||
//! Variant to support multiple having the system creating the Shape(s) or just providing the Shape(s) that have been created externally.
|
||||
//! See ShapeVariantData for more information.
|
||||
ShapeVariantData m_colliderAndShapeData;
|
||||
|
||||
//Visibility helpers for use in the Editor when reflected. RagdollNodeConfiguration also uses these.
|
||||
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.
|
||||
};
|
||||
|
||||
AZ::Crc32 GetInitialVelocitiesVisibility() const;
|
||||
AZ::Crc32 GetInertiaSettingsVisibility() const;
|
||||
AZ::Crc32 GetInertiaVisibility() const;
|
||||
AZ::Crc32 GetMassVisibility() const;
|
||||
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;
|
||||
|
||||
AZ::u16 m_propertyVisibilityFlags = (std::numeric_limits<AZ::u16>::max)();
|
||||
};
|
||||
}
|
||||
+55
-9
@@ -13,6 +13,7 @@
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
@@ -21,16 +22,47 @@ namespace AzPhysics
|
||||
|
||||
/*static*/ void SceneConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
Physics::WorldConfiguration::Reflect(context);
|
||||
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SceneConfiguration>()
|
||||
->Version(1)
|
||||
->Field("LegacyConfig", &SceneConfiguration::m_legacyConfiguration)
|
||||
->Field("LegacyId", &SceneConfiguration::m_legacyId)
|
||||
->Version(2)
|
||||
->Field("Name", &SceneConfiguration::m_sceneName)
|
||||
->Field("WorldBounds", &SceneConfiguration::m_worldBounds)
|
||||
->Field("Gravity", &SceneConfiguration::m_gravity)
|
||||
->Field("EnableCcd", &SceneConfiguration::m_enableCcd)
|
||||
->Field("MaxCcdPasses", &SceneConfiguration::m_maxCcdPasses)
|
||||
->Field("EnableCcdResweep", &SceneConfiguration::m_enableCcdResweep)
|
||||
->Field("EnableActiveActors", &SceneConfiguration::m_enableActiveActors)
|
||||
->Field("EnablePcm", &SceneConfiguration::m_enablePcm)
|
||||
->Field("BounceThresholdVelocity", &SceneConfiguration::m_bounceThresholdVelocity)
|
||||
;
|
||||
|
||||
if (auto* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<SceneConfiguration>("Scene Configuration", "Default scene configuration")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_worldBounds, "World Bounds", "World bounds")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_gravity, "Gravity", "Gravity")
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Continuous Collision Detection")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_enableCcd, "Enable CCD", "Enabled continuous collision detection in the world")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_maxCcdPasses,
|
||||
"Max CCD Passes", "Maximum number of continuous collision detection passes")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &SceneConfiguration::GetCcdVisibility)
|
||||
->Attribute(AZ::Edit::Attributes::Min, 1u)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_enableCcdResweep,
|
||||
"Enable CCD Resweep", "Enable a more accurate but more expensive continuous collision detection method")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &SceneConfiguration::GetCcdVisibility)
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "") // end previous group by starting new unnamed expanded group
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_enablePcm, "Persistent Contact Manifold", "Enabled the persistent contact manifold narrow-phase algorithm")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_bounceThresholdVelocity,
|
||||
"Bounce Threshold Velocity", "Relative velocity below which colliding objects will not bounce")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.01f)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,14 +73,28 @@ namespace AzPhysics
|
||||
|
||||
bool SceneConfiguration::operator==(const SceneConfiguration& other) const
|
||||
{
|
||||
return m_legacyId == other.m_legacyId
|
||||
&& m_sceneName == other.m_sceneName
|
||||
&& m_legacyConfiguration == other.m_legacyConfiguration
|
||||
;
|
||||
return m_sceneName == other.m_sceneName
|
||||
&& m_enableCcd == other.m_enableCcd
|
||||
&& m_enableCcdResweep == other.m_enableCcdResweep
|
||||
&& m_enableActiveActors == other.m_enableActiveActors
|
||||
&& m_enablePcm == other.m_enablePcm
|
||||
&& m_kinematicFiltering == other.m_kinematicFiltering
|
||||
&& m_kinematicStaticFiltering == other.m_kinematicStaticFiltering
|
||||
&& m_customUserData == other.m_customUserData
|
||||
&& m_maxCcdPasses == other.m_maxCcdPasses
|
||||
&& AZ::IsClose(m_bounceThresholdVelocity, other.m_bounceThresholdVelocity)
|
||||
&& m_gravity.IsClose(other.m_gravity)
|
||||
&& m_worldBounds == other.m_worldBounds
|
||||
;
|
||||
}
|
||||
|
||||
bool SceneConfiguration::operator!=(const SceneConfiguration& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
AZ::Crc32 SceneConfiguration::GetCcdVisibility() const
|
||||
{
|
||||
return m_enableCcd ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#include <AzFramework/Physics/World.h> //this will be removed with LYN-438.
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -33,14 +35,28 @@ namespace AzPhysics
|
||||
|
||||
static SceneConfiguration CreateDefault();
|
||||
|
||||
// Legacy members Will be removed and replaced with LYN-438 work.
|
||||
Physics::WorldConfiguration m_legacyConfiguration;
|
||||
AZ::Crc32 m_legacyId; //use SceneConfiguration::m_SceneName instead
|
||||
AZStd::string m_sceneName; //!< Name given to the scene.
|
||||
|
||||
AZStd::string m_sceneName = "DefaultScene"; //!< Name given to the scene.
|
||||
AZ::Aabb m_worldBounds = AZ::Aabb::CreateFromMinMax(-AZ::Vector3(1000.f, 1000.f, 1000.f), AZ::Vector3(1000.f, 1000.f, 1000.f));
|
||||
AZ::Vector3 m_gravity = AzPhysics::DefaultGravity;
|
||||
void* m_customUserData = nullptr;
|
||||
bool m_enableCcd = false; //!< Enables continuous collision detection in the world.
|
||||
AZ::u32 m_maxCcdPasses = 1; //!< Maximum number of continuous collision detection passes.
|
||||
bool m_enableCcdResweep = true; //!< Use a more accurate but more expensive continuous collision detection method.
|
||||
|
||||
//! Enables reporting of changed Simulated bodies on the OnSceneActiveSimulatedBodiesEvent event.
|
||||
//! @note There may be a performance penalty for enabling the Active Actor Notification.
|
||||
bool m_enableActiveActors = false;
|
||||
bool m_enablePcm = true; //!< Enables the persistent contact manifold algorithm to be used as the narrow phase algorithm.
|
||||
bool m_kinematicFiltering = true; //!< Enables filtering between kinematic/kinematic objects.
|
||||
bool m_kinematicStaticFiltering = true; //!< Enables filtering between kinematic/static objects.
|
||||
float m_bounceThresholdVelocity = 2.0f; //!< Relative velocity below which colliding objects will not bounce.
|
||||
|
||||
bool operator==(const SceneConfiguration& other) const;
|
||||
bool operator!=(const SceneConfiguration& other) const;
|
||||
|
||||
private:
|
||||
AZ::Crc32 GetCcdVisibility() const;
|
||||
};
|
||||
|
||||
//! Alias for a list of SceneConfiguration objects, used for the creation of multiple Scenes at once.
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
bool DeprecateWorldBodyConfiguration(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
|
||||
{
|
||||
// WorldBodyConfiguration on serialized the name so capture that.
|
||||
AZStd::string name = "";
|
||||
classElement.GetChildData(AZ::Crc32("name"), name);
|
||||
//convert to the new class
|
||||
classElement.Convert<SimulatedBodyConfiguration>(context);
|
||||
//add the captured name
|
||||
classElement.AddElementWithData(context, "name", name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SimulatedBodyConfiguration, AZ::SystemAllocator, 0);
|
||||
|
||||
void SimulatedBodyConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->ClassDeprecate("WorldBodyConfiguration", "{6EEB377C-DC60-4E10-AF12-9626C0763B2D}", &Internal::DeprecateWorldBodyConfiguration);
|
||||
serializeContext->Class<SimulatedBodyConfiguration>()
|
||||
->Version(1)
|
||||
->Field("name", &SimulatedBodyConfiguration::m_debugName)
|
||||
->Field("position", &SimulatedBodyConfiguration::m_position)
|
||||
->Field("orientation", &SimulatedBodyConfiguration::m_orientation)
|
||||
->Field("scale", &SimulatedBodyConfiguration::m_scale)
|
||||
->Field("entityId", &SimulatedBodyConfiguration::m_entityId)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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/Component/EntityId.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
//! Base Class of all Physics Bodies that will be simulated.
|
||||
struct SimulatedBodyConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SimulatedBodyConfiguration() = default;
|
||||
virtual ~SimulatedBodyConfiguration() = default;
|
||||
|
||||
// Basic initial settings.
|
||||
AZ::Vector3 m_position = AZ::Vector3::CreateZero();
|
||||
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity();
|
||||
AZ::Vector3 m_scale = AZ::Vector3::CreateOne();
|
||||
|
||||
// Entity/object association.
|
||||
AZ::EntityId m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId);
|
||||
void* m_customUserData = nullptr;
|
||||
|
||||
// For debugging/tracking purposes only.
|
||||
AZStd::string m_debugName;
|
||||
};
|
||||
|
||||
//! Alias for a list of non owning weak pointers to SceneConfiguration objects.
|
||||
//! Used for the creation of multiple SimulatedBodies at once with Scene::AddSimulatedBodies.
|
||||
using SimulatedBodyConfigurationList = AZStd::vector<SimulatedBodyConfiguration*>;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(StaticRigidBodyConfiguration, AZ::SystemAllocator, 0);
|
||||
|
||||
void StaticRigidBodyConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<StaticRigidBodyConfiguration, SimulatedBodyConfiguration>()
|
||||
->Version(1)
|
||||
->Field("ColliderAndShapeData", &StaticRigidBodyConfiguration::m_colliderAndShapeData);
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ShapeConfiguration;
|
||||
class ColliderConfiguration;
|
||||
class Shape;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct StaticRigidBodyConfiguration : public SimulatedBodyConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(StaticRigidBodyConfiguration, "{E68A14C0-21DC-4FC7-9AD0-04BB9D972004}", SimulatedBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
StaticRigidBodyConfiguration() = default;
|
||||
virtual ~StaticRigidBodyConfiguration() = default;
|
||||
|
||||
//! Variant to support multiple having the system creating the Shape(s) or just providing the Shape(s) that have been created externally.
|
||||
//! See ShapeVariantData for more information.
|
||||
ShapeVariantData m_colliderAndShapeData;
|
||||
};
|
||||
}
|
||||
+48
-2
@@ -13,17 +13,24 @@
|
||||
#include <AzFramework/Physics/Configuration/SystemConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const float TimestepMin = 0.001f; //1000fps
|
||||
const float TimestepMax = 0.05f; //20fps
|
||||
}
|
||||
|
||||
AZ_CLASS_ALLOCATOR_IMPL(SystemConfiguration, AZ::SystemAllocator, 0);
|
||||
|
||||
/*static*/ void SystemConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SystemConfiguration>()
|
||||
serializeContext->Class<AzPhysics::SystemConfiguration>()
|
||||
->Version(2)
|
||||
->Field("AutoManageSimulationUpdate", &SystemConfiguration::m_autoManageSimulationUpdate)
|
||||
->Field("MaxTimestep", &SystemConfiguration::m_maxTimestep)
|
||||
@@ -33,6 +40,34 @@ namespace AzPhysics
|
||||
->Field("OverlapBufferSize", &SystemConfiguration::m_overlapBufferSize)
|
||||
->Field("CollisionConfig", &SystemConfiguration::m_collisionConfig)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<AzPhysics::SystemConfiguration>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemConfiguration::m_maxTimestep, "Max Time Step (sec)", "Max time step in seconds")
|
||||
->Attribute(AZ::Edit::Attributes::Min, TimestepMin)
|
||||
->Attribute(AZ::Edit::Attributes::Max, TimestepMax)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &SystemConfiguration::OnMaxTimeStepChanged)//need to clamp m_fixedTimeStep if this value changes
|
||||
->Attribute(AZ::Edit::Attributes::Decimals, 8)
|
||||
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 8)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemConfiguration::m_fixedTimestep, "Fixed Time Step (sec)", "Fixed time step in seconds. Limited by 'Max Time Step'")
|
||||
->Attribute(AZ::Edit::Attributes::Min, TimestepMin)
|
||||
->Attribute(AZ::Edit::Attributes::Max, &SystemConfiguration::GetFixedTimeStepMax)
|
||||
->Attribute(AZ::Edit::Attributes::Decimals, 8)
|
||||
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 8)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemConfiguration::m_raycastBufferSize,
|
||||
"Raycast Buffer Size", "Maximum number of hits from a raycast")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 1u)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemConfiguration::m_shapecastBufferSize,
|
||||
"Shapecast Buffer Size", "Maximum number of hits from a shapecast")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 1u)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemConfiguration::m_overlapBufferSize,
|
||||
"Overlap Query Buffer Size", "Maximum number of hits from a overlap query")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 1u)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +87,15 @@ namespace AzPhysics
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
AZ::u32 SystemConfiguration::OnMaxTimeStepChanged()
|
||||
{
|
||||
m_fixedTimestep = AZStd::GetMin(m_fixedTimestep, GetFixedTimeStepMax()); //since m_maxTimeStep has changed, m_fixedTimeStep might be larger then the max.
|
||||
return AZ::Edit::PropertyRefreshLevels::AttributesAndValues;
|
||||
}
|
||||
|
||||
float SystemConfiguration::GetFixedTimeStepMax() const
|
||||
{
|
||||
return m_maxTimestep;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace AzPhysics
|
||||
struct SystemConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(SystemConfiguration, "{24697CAF-AC00-443D-9C27-28D58734A84C}");
|
||||
AZ_RTTI(AzPhysics::SystemConfiguration, "{24697CAF-AC00-443D-9C27-28D58734A84C}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SystemConfiguration() = default;
|
||||
@@ -51,5 +51,10 @@ namespace AzPhysics
|
||||
|
||||
bool operator==(const SystemConfiguration& other) const;
|
||||
bool operator!=(const SystemConfiguration& other) const;
|
||||
|
||||
private:
|
||||
// helpers for edit context
|
||||
AZ::u32 OnMaxTimeStepChanged();
|
||||
float GetFixedTimeStepMax() const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
@@ -43,10 +47,10 @@ namespace Physics
|
||||
AZ_CLASS_ALLOCATOR(Joint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Joint, "{405F517C-E986-4ACB-9606-D5D080DDE987}");
|
||||
|
||||
virtual Physics::WorldBody* GetParentBody() const = 0;
|
||||
virtual Physics::WorldBody* GetChildBody() const = 0;
|
||||
virtual void SetParentBody(Physics::WorldBody* parentBody) = 0;
|
||||
virtual void SetChildBody(Physics::WorldBody* childBody) = 0;
|
||||
virtual AzPhysics::SimulatedBody* GetParentBody() const = 0;
|
||||
virtual AzPhysics::SimulatedBody* GetChildBody() const = 0;
|
||||
virtual void SetParentBody(AzPhysics::SimulatedBody* parentBody) = 0;
|
||||
virtual void SetChildBody(AzPhysics::SimulatedBody* childBody) = 0;
|
||||
virtual const AZStd::string& GetName() const = 0;
|
||||
virtual void SetName(const AZStd::string& name) = 0;
|
||||
virtual const AZ::Crc32 GetNativeType() const = 0;
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MaterialConfiguration>()
|
||||
serializeContext->Class<Physics::MaterialConfiguration>()
|
||||
->Version(3, &VersionConverter)
|
||||
->Field("SurfaceType", &MaterialConfiguration::m_surfaceType)
|
||||
->Field("DynamicFriction", &MaterialConfiguration::m_dynamicFriction)
|
||||
@@ -88,7 +88,7 @@ namespace Physics
|
||||
{
|
||||
AZStd::unordered_set<AZStd::string> forbiddenSurfaceTypeNames;
|
||||
forbiddenSurfaceTypeNames.insert("Default");
|
||||
editContext->Class<MaterialConfiguration>("", "")
|
||||
editContext->Class<Physics::MaterialConfiguration>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "Physics Material")
|
||||
->DataElement(MaterialConfiguration::s_configLineEdit, &MaterialConfiguration::m_surfaceType, "Surface type", "Game surface type") // Uses ConfigStringLineEditCtrl in PhysX gem.
|
||||
->Attribute(AZ::Edit::Attributes::MaxLength, 64)
|
||||
@@ -168,7 +168,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MaterialLibraryAsset, AZ::Data::AssetData>()
|
||||
serializeContext->Class<Physics::MaterialLibraryAsset, AZ::Data::AssetData>()
|
||||
->Version(2, &ClassConverters::MaterialLibraryAssetConverter)
|
||||
->Attribute(AZ::Edit::Attributes::EnableForAssetEditor, true)
|
||||
->EventHandler<MaterialLibraryAssetEventHandler>()
|
||||
@@ -178,7 +178,7 @@ namespace Physics
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<MaterialLibraryAsset>("", "")
|
||||
editContext->Class<Physics::MaterialLibraryAsset>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialLibraryAsset::m_materialLibrary, "Physics Materials", "List of physics materials")
|
||||
@@ -196,7 +196,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MaterialLibraryAssetReflectionWrapper>()
|
||||
serializeContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>()
|
||||
->Version(1)
|
||||
->Field("Asset", &MaterialLibraryAssetReflectionWrapper::m_asset)
|
||||
;
|
||||
@@ -204,7 +204,7 @@ namespace Physics
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<MaterialLibraryAssetReflectionWrapper>("", "")
|
||||
editContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
@@ -223,7 +223,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<DefaultMaterialLibraryAssetReflectionWrapper>()
|
||||
serializeContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>()
|
||||
->Version(1)
|
||||
->Field("Asset", &DefaultMaterialLibraryAssetReflectionWrapper::m_asset)
|
||||
;
|
||||
@@ -231,7 +231,7 @@ namespace Physics
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<DefaultMaterialLibraryAssetReflectionWrapper>("", "")
|
||||
editContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
@@ -250,7 +250,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MaterialFromAssetConfiguration>()
|
||||
serializeContext->Class<Physics::MaterialFromAssetConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Configuration", &MaterialFromAssetConfiguration::m_configuration)
|
||||
->Field("UID", &MaterialFromAssetConfiguration::m_id)
|
||||
@@ -259,7 +259,7 @@ namespace Physics
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<MaterialFromAssetConfiguration>("", "")
|
||||
editContext->Class<Physics::MaterialFromAssetConfiguration>("", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialFromAssetConfiguration::m_configuration, "Physics Material", "Physics Material properties")
|
||||
@@ -369,7 +369,7 @@ namespace Physics
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<MaterialSelection>()
|
||||
serializeContext->Class<Physics::MaterialSelection>()
|
||||
->Version(2, &ClassConverters::MaterialSelectionConverter)
|
||||
->EventHandler<MaterialSelectionEventHandler>()
|
||||
->Field("Material", &MaterialSelection::m_materialLibrary)
|
||||
@@ -378,7 +378,7 @@ namespace Physics
|
||||
|
||||
if (auto editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<MaterialSelection>("Physics Material", "Select physics material library and which materials to use for the object")
|
||||
editContext->Class<Physics::MaterialSelection>("Physics Material", "Select physics material library and which materials to use for the object")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialLibrary, "Library", "Physics material library to use for this object")
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Material, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Material, "{44636CEA-46DD-4D4A-B1EF-5ED6DEA7F714}");
|
||||
AZ_RTTI(Physics::Material, "{44636CEA-46DD-4D4A-B1EF-5ED6DEA7F714}");
|
||||
|
||||
/// Enumeration that determines how two materials properties are combined when
|
||||
/// processing collisions.
|
||||
@@ -102,7 +102,7 @@ namespace Physics
|
||||
class MaterialConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(MaterialConfiguration, "{8807CAA1-AD08-4238-8FDB-2154ADD084A1}");
|
||||
AZ_TYPE_INFO(Physics::MaterialConfiguration, "{8807CAA1-AD08-4238-8FDB-2154ADD084A1}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialId, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(MaterialId, "{744CCE6C-9F69-4E2F-B950-DAB8514F870B}");
|
||||
AZ_TYPE_INFO(Physics::MaterialId, "{744CCE6C-9F69-4E2F-B950-DAB8514F870B}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static MaterialId Create();
|
||||
@@ -160,7 +160,7 @@ namespace Physics
|
||||
class MaterialFromAssetConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(MaterialFromAssetConfiguration, "{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}");
|
||||
AZ_TYPE_INFO(Physics::MaterialFromAssetConfiguration, "{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialLibraryAsset, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(MaterialLibraryAsset, "{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}", AZ::Data::AssetData);
|
||||
AZ_RTTI(Physics::MaterialLibraryAsset, "{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}", AZ::Data::AssetData);
|
||||
|
||||
MaterialLibraryAsset() = default;
|
||||
virtual ~MaterialLibraryAsset() = default;
|
||||
@@ -231,7 +231,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(MaterialLibraryAssetReflectionWrapper, "{3D2EF5DF-EFD0-47EB-B88F-3E6FE1FEE5B0}");
|
||||
AZ_TYPE_INFO(Physics::MaterialLibraryAssetReflectionWrapper, "{3D2EF5DF-EFD0-47EB-B88F-3E6FE1FEE5B0}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
|
||||
@@ -243,7 +243,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(DefaultMaterialLibraryAssetReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
|
||||
AZ_TYPE_INFO(Physics::DefaultMaterialLibraryAssetReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
|
||||
@@ -263,7 +263,7 @@ namespace Physics
|
||||
friend class MaterialSelectionEventHandler;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MaterialSelection, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(MaterialSelection, "{F571AFF4-C4BB-4590-A204-D11D9EEABBC4}");
|
||||
AZ_TYPE_INFO(Physics::MaterialSelection, "{F571AFF4-C4BB-4590-A204-D11D9EEABBC4}");
|
||||
|
||||
using SlotsArray = AZStd::vector<AZStd::string>;
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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 <AzFramework/Physics/PhysicsScene.h>
|
||||
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(Scene, AZ::SystemAllocator, 0);
|
||||
|
||||
/*static*/ void Scene::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
const auto getOnGravityChange = [](const AZStd::string& sceneName) -> SceneEvents::OnSceneGravityChangedEvent*
|
||||
{
|
||||
if (auto* physicsSystem = AZ::Interface<SystemInterface>::Get())
|
||||
{
|
||||
SceneHandle sceneHandle = physicsSystem->GetSceneHandle(sceneName);
|
||||
if (sceneHandle != AzPhysics::InvalidSceneHandle)
|
||||
{
|
||||
if (Scene* scene = physicsSystem->GetScene(sceneHandle))
|
||||
{
|
||||
return scene->GetOnGravityChangedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription gravityChangedEventDescription =
|
||||
{
|
||||
"On Gravity Changed event",
|
||||
{
|
||||
"Scene Handle",
|
||||
"Gravity Vector"
|
||||
} // Parameters
|
||||
};
|
||||
|
||||
behaviorContext->Class<Scene>("PhysicsScene")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Physics")
|
||||
->Method("GetOnGravityChangeEvent", getOnGravityChange)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, gravityChangedEventDescription)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
Scene::Scene(const SceneConfiguration& config)
|
||||
: m_id(config.m_sceneName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const AZ::Crc32& Scene::GetId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
SceneEvents::OnSceneGravityChangedEvent* Scene::GetOnGravityChangedEvent()
|
||||
{
|
||||
return &m_sceneGravityChangedEvent;
|
||||
}
|
||||
} // namespace AzPhysics
|
||||
@@ -12,21 +12,232 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <AzFramework/Physics/World.h> // Temporary until LYN-438 work is complete
|
||||
#include <AzFramework/Physics/Common/PhysicsEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SceneConfiguration;
|
||||
|
||||
//! Interface to access a Physics Scene with a SceneHandle.
|
||||
class SceneInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(SceneInterface, "{912CE8D1-7E3E-496F-B7BE-D17F8B30C228}");
|
||||
|
||||
SceneInterface() = default;
|
||||
virtual ~SceneInterface() = default;
|
||||
AZ_DISABLE_COPY_MOVE(SceneInterface);
|
||||
|
||||
//! Returns a Scene Handle connected to the given scene name.
|
||||
//! @param sceneName The name of the scene to look up.
|
||||
//! @returns Will return a SceneHandle to a Scene connected with the given name, otherwise will return InvalidSceneHandle.
|
||||
virtual SceneHandle GetSceneHandle(const AZStd::string& sceneName) = 0;
|
||||
|
||||
//! Start the simulation process.
|
||||
//! As an example, this is a good place to trigger and queue any long running work in separate threads.
|
||||
//! @param sceneHandle The SceneHandle of the scene to use.
|
||||
//! @param deltatime The time in seconds to step the simulation for.
|
||||
virtual void StartSimulation(SceneHandle sceneHandle, float deltatime) = 0;
|
||||
|
||||
//! Complete the simulation process.
|
||||
//! As an example, this is a good place to wait for any work to complete that was triggered in StartSimulation, or swap buffers if double buffering.
|
||||
//! @param sceneHandle The SceneHandle of the scene to use.
|
||||
virtual void FinishSimulation(SceneHandle sceneHandle) = 0;
|
||||
|
||||
//! Enable or Disable this Scene's Simulation tick.
|
||||
//! Default is Enabled.
|
||||
//! @param sceneHandle The SceneHandle of the scene to use.
|
||||
//! @param enable When true the Scene will execute its simulation tick when StartSimulation is called. When false, StartSimulation will not execute.
|
||||
virtual void SetEnabled(SceneHandle sceneHandle, bool enable) = 0;
|
||||
|
||||
//! Check if this Scene is currently Enabled.
|
||||
//! @param sceneHandle The SceneHandle of the scene to use.
|
||||
//! @return When true the Scene is enabled and will execute its simulation tick when StartSimulation is called. When false,
|
||||
//! StartSimulation will not execute or the SceneHandle is invalid.
|
||||
virtual bool IsEnabled(SceneHandle sceneHandle) const = 0;
|
||||
|
||||
//! Add a simulated body to the Scene.
|
||||
//! @param sceneHandle A handle to the scene to add the requested simulated body.
|
||||
//! @param simulatedBodyConfig The config of the simulated body.
|
||||
//! @return Returns a handle to the created Simulated body. Will return AzPhyiscs::InvalidSimulatedBodyHandle if it fails.
|
||||
virtual SimulatedBodyHandle AddSimulatedBody(SceneHandle sceneHandle, const SimulatedBodyConfiguration* simulatedBodyConfig) = 0;
|
||||
|
||||
//! Add a set of simulated bodied to the Scene.
|
||||
//! @param sceneHandle A handle to the scene to Add the simulated bodies to.
|
||||
//! @param simulatedBodyConfigs The list of simulated body configs.
|
||||
//! @return Returns a list of handles to the created Simulated bodies. Will be in the same order as supplied in simulatedBodyConfigs.
|
||||
//! If the scene handle is invalid, this will return an empty list. If one fails, that index will be set to AzPhyiscs::InvalidSimulatedBodyHandle.
|
||||
virtual SimulatedBodyHandleList AddSimulatedBodies(SceneHandle sceneHandle, const SimulatedBodyConfigurationList& simulatedBodyConfigs) = 0;
|
||||
|
||||
//! Get the Raw pointer to the requested simulated body.
|
||||
//! @param sceneHandle A handle to the scene to get the simulated bodies from.
|
||||
//! @param bodyHandle A handle to the simulated body to retrieve the raw pointer.
|
||||
//! @return A raw pointer to the Simulated body. If the either handle is invalid this will return null.
|
||||
virtual SimulatedBody* GetSimulatedBodyFromHandle(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Get the Raw pointer to the set of requested simulated bodies.
|
||||
//! @param sceneHandle A handle to the scene to get the simulated bodies from.
|
||||
//! @param bodyHandles A list of simulated body handles to retrieve the raw pointers.
|
||||
//! @return A list of raw pointers to the Simulated bodies requested. If the scene handle is invalid this will return an empty list.
|
||||
//! If a simulated body handle is invalid, that index in the list will be null.
|
||||
virtual SimulatedBodyList GetSimulatedBodiesFromHandle(SceneHandle sceneHandle, const SimulatedBodyHandleList& bodyHandles) = 0;
|
||||
|
||||
//! Remove a simulated body from the Scene.z
|
||||
//! @param sceneHandle A handle to the scene to remove the requested simulated body.
|
||||
//! @param bodyHandle A handle to the simulated body being removed.
|
||||
virtual void RemoveSimulatedBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Remove a list of simulated bodies from the Scene.
|
||||
//! @param sceneHandle A handle to the scene to remove the simulated bodies from.
|
||||
//! @param bodyHandles A list of simulated body handles to be removed.
|
||||
virtual void RemoveSimulatedBodies(SceneHandle sceneHandle, const SimulatedBodyHandleList& bodyHandles) = 0;
|
||||
|
||||
//! Enable / Disable simulation of the requested body. By default all bodies added are enabled.
|
||||
//! Disabling simulation the body will no longer be affected by any forces, collisions, or found with scene queries.
|
||||
//! @param sceneHandle A handle to the scene to enable / disable the requested simulated body.
|
||||
//! @param bodyHandle The handle of the simulated body to enable / disable.
|
||||
virtual void EnableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
virtual void DisableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Make a blocking query into the scene.
|
||||
//! @param sceneHandle A handle to the scene to make the scene query with.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @return Returns a structure that contains a list of Hits. Depending on flags set in the request, this may only contain 1 result.
|
||||
virtual SceneQueryHits QueryScene(SceneHandle sceneHandle, const SceneQueryRequest* request) = 0;
|
||||
|
||||
//! Make many blocking queries into the scene.
|
||||
//! @param sceneHandle A handle to the scene to make the scene query with.
|
||||
//! @param requests A list of requests to make. Each entry should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @return Returns a list of SceneQueryHits. Will be in the same order as supplied in SceneQueryRequests.
|
||||
virtual SceneQueryHitsList QuerySceneBatch(SceneHandle sceneHandle, const SceneQueryRequests& requests) = 0;
|
||||
|
||||
//! Make a non-blocking query into the scene.
|
||||
//! @param sceneHandle A handle to the scene to make the scene query with.
|
||||
//! @param requestId A user defined value to identify the request when the callback is called.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @param callback The callback to trigger when the request is complete.
|
||||
//! @return Returns If the request was queued successfully. If returns false, the callback will never be called.
|
||||
[[nodiscard]] virtual bool QuerySceneAsync(SceneHandle sceneHandle, SceneQuery::AsyncRequestId requestId,
|
||||
const SceneQueryRequest* request, SceneQuery::AsyncCallback callback) = 0;
|
||||
|
||||
//! Make a non-blocking query into the scene.
|
||||
//! @param sceneHandle A handle to the scene to make the scene query with.
|
||||
//! @param requestId A user defined valid to identify the request when the callback is called.
|
||||
//! @param requests A list of requests to make. Each entry should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @param callback The callback to trigger when all the request are complete.
|
||||
//! @return Returns If the request was queued successfully. If returns false, the callback will never be called.
|
||||
[[nodiscard]] virtual bool QuerySceneAsyncBatch(SceneHandle sceneHandle, SceneQuery::AsyncRequestId requestId,
|
||||
const SceneQueryRequests& requests, SceneQuery::AsyncBatchCallback callback) = 0;
|
||||
|
||||
//! Registers a pair of simulated bodies for which collisions should be suppressed.
|
||||
//! Making multiple requests with the same pair result are dropped. To remove the suppression call UnsuppressCollisionEvents with the pair.
|
||||
//! The order of the bodies do not matter, {body0, body1} collision pair is equal to {body1, body0}.
|
||||
//! @param sceneHandle A handle to the scene to register the collision pair with.
|
||||
//! @param bodyHandleA A handle to a simulated body.
|
||||
//! @param bodyHandleB A handle to a simulated body.
|
||||
virtual void SuppressCollisionEvents(SceneHandle sceneHandle,
|
||||
const SimulatedBodyHandle& bodyHandleA,
|
||||
const SimulatedBodyHandle& bodyHandleB) = 0;
|
||||
|
||||
//! Unregisters a pair of simulated bodies for which collisions should be suppressed.
|
||||
//! Making multiple requests with the same pair result are dropped. To add a suppression call SuppressCollisionEvents with the pair.
|
||||
//! The order of the bodies do not matter, {body0, body1} collision pair is equal to {body1, body0}.
|
||||
//! @param sceneHandle A handle to the scene to unregister the collision pair with.
|
||||
//! @param bodyHandleA A handle to a simulated body.
|
||||
//! @param bodyHandleB A handle to a simulated body.
|
||||
virtual void UnsuppressCollisionEvents(SceneHandle sceneHandle,
|
||||
const SimulatedBodyHandle& bodyHandleA,
|
||||
const SimulatedBodyHandle& bodyHandleB) = 0;
|
||||
|
||||
//! Set the Gravity of the given Scene.
|
||||
//! @param sceneHandle A handle to the scene to set the gravity vector of.
|
||||
//! @Param The new gravity vector to be used in the Scene
|
||||
virtual void SetGravity(SceneHandle sceneHandle, const AZ::Vector3& gravity) = 0;
|
||||
|
||||
//! Get the Gravity of the given Scene.
|
||||
//! @param sceneHandle A handle to the scene to get the gravity vector of.
|
||||
//! @return A Vector3 of the gravity used in the Scene, will return a Zero Vector if sceneHandle is invalid or not found.
|
||||
virtual AZ::Vector3 GetGravity(SceneHandle sceneHandle) const = 0;
|
||||
|
||||
//! Register a handler to receive an event when the SceneConfiguration changes.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneConfigurationChangedEventHandler(SceneHandle sceneHandle, SceneEvents::OnSceneConfigurationChanged::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body is added to the Scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSimulationBodyAddedHandler(SceneHandle sceneHandle, SceneEvents::OnSimulationBodyAdded::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body is removed from the Scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSimulationBodyRemovedHandler(SceneHandle sceneHandle, SceneEvents::OnSimulationBodyRemoved::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body has its simulation enabled in the Scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! This will only trigger if the simulated body was disabled, when first added to a scene SceneEvents::OnAnySimulationBodyCreated will trigger instead.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSimulationBodySimulationEnabledHandler(SceneHandle sceneHandle, SceneEvents::OnSimulationBodySimulationEnabled::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body has its simulation disabled in the Scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSimulationBodySimulationDisabledHandler(SceneHandle sceneHandle, SceneEvents::OnSimulationBodySimulationDisabled::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when Scene::StartSimulation is called.
|
||||
//! @note This may fire multiple times per frame.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneSimulationStartHandler(SceneHandle sceneHandle, SceneEvents::OnSceneSimulationStartHandler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event when Scene::FinishSimulation is called.
|
||||
//! @note This may fire multiple times per frame.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneSimulationFinishHandler(SceneHandle sceneHandle, SceneEvents::OnSceneSimulationFinishHandler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive an event with a list of SimulatedBodyHandles that updated this scene tick.
|
||||
//! @note This will fire after the OnSceneSimulationStartEvent and before the OnSceneSimulationFinishEvent when SceneConfiguration::m_enableActiveActors is true.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneActiveSimulatedBodiesHandler(SceneHandle sceneHandle, SceneEvents::OnSceneActiveSimulatedBodiesEvent::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive all collision events in the scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneCollisionEventHandler(SceneHandle sceneHandle, SceneEvents::OnSceneCollisionsEvent::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive all trigger events in the scene.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneTriggersEventHandler(SceneHandle sceneHandle, SceneEvents::OnSceneTriggersEvent::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler to receive a notification when the Scene's gravity has changed.
|
||||
//! @param sceneHandle A handle to the scene to register the event with.
|
||||
//! @param handler The handler to receive the event.
|
||||
virtual void RegisterSceneGravityChangedEvent(SceneHandle sceneHandle, SceneEvents::OnSceneGravityChangedEvent::Handler& handler) = 0;
|
||||
};
|
||||
|
||||
//! Interface of a Physics Scene
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(Scene, "{52BD8163-BDC4-4B09-ABB2-11DD1F601FFD}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
Scene() = default;
|
||||
explicit Scene(const SceneConfiguration& config);
|
||||
virtual ~Scene() = default;
|
||||
|
||||
//! Get the Id of the Scene.
|
||||
//! @return The Crc32 of the scene.
|
||||
const AZ::Crc32& GetId() const;
|
||||
|
||||
//! Start the simulation process.
|
||||
//! As an example, this is a good place to trigger and queue any long running work in separate threads.
|
||||
//! @param deltatime The time in seconds to run the simulation for.
|
||||
@@ -39,7 +250,7 @@ namespace AzPhysics
|
||||
//! Enable or Disable this Scene's Simulation tick.
|
||||
//! Default is Enabled.
|
||||
//! @param enable When true the Scene will execute its simulation tick when StartSimulation is called. When false, StartSimulation will not execute.
|
||||
virtual void Enable(bool enable) = 0;
|
||||
virtual void SetEnabled(bool enable) = 0;
|
||||
|
||||
//! Check if this Scene is currently Enabled.
|
||||
//! @return When true the Scene is enabled and will execute its simulation tick when StartSimulation is called. When false, StartSimulation will not execute.
|
||||
@@ -53,8 +264,217 @@ namespace AzPhysics
|
||||
//! @param config The new configuration to apply.
|
||||
virtual void UpdateConfiguration(const SceneConfiguration& config) = 0;
|
||||
|
||||
// Temporary until LYN-438 work is complete
|
||||
virtual AZStd::shared_ptr<Physics::World> GetLegacyWorld() const = 0;
|
||||
//! Add a simulated body to the Scene.
|
||||
//! @param simulatedBodyConfig The config of the simulated body.
|
||||
//! @return Returns a handle to the created Simulated body. Will return AzPhyiscs::InvalidSimulatedBodyHandle if it fails.
|
||||
virtual SimulatedBodyHandle AddSimulatedBody(const SimulatedBodyConfiguration* simulatedBodyConfig) = 0;
|
||||
|
||||
//! Add a set of simulated bodied to the Scene.
|
||||
//! @param simulatedBodyConfigs The list of simulated body configs.
|
||||
//! @return Returns a list of handles to the created Simulated bodies. Will be in the same order as supplied in simulatedBodyConfigs.
|
||||
//! If one fails, that index will be set to AzPhyiscs::InvalidSimulatedBodyHandle.
|
||||
virtual SimulatedBodyHandleList AddSimulatedBodies(const SimulatedBodyConfigurationList& simulatedBodyConfigs) = 0;
|
||||
|
||||
//! Get the Raw pointer to the requested simulated body.
|
||||
//! @param bodyHandle A handle to the simulated body to retrieve the raw pointer for.
|
||||
//! @return A raw pointer to the Simulated body. If the handle is invalid this will return null.
|
||||
virtual SimulatedBody* GetSimulatedBodyFromHandle(SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Get the Raw pointer to the set of requested simulated bodies.
|
||||
//! @param bodyHandles A list of simulated body handles to retrieve the raw pointers for.
|
||||
//! @return A list of raw pointers to the Simulated bodies requested. If a simulated body handle is invalid, that index in the list will be null.
|
||||
virtual SimulatedBodyList GetSimulatedBodiesFromHandle(const SimulatedBodyHandleList& bodyHandles) = 0;
|
||||
|
||||
//! Remove a simulated body from the Scene.
|
||||
//! @param bodyHandle A handle to the simulated body being removed.
|
||||
virtual void RemoveSimulatedBody(SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Remove a list of simulated bodies from the Scene.
|
||||
//! @param bodyHandles A list of simulated body handles to be removed.
|
||||
virtual void RemoveSimulatedBodies(const SimulatedBodyHandleList& bodyHandles) = 0;
|
||||
|
||||
//! Enable / Disable simulation of the requested body. By default all bodies added are enabled.
|
||||
//! Disabling simulation the body will no longer be affected by any forces, collisions, or found with scene queries.
|
||||
//! @param bodyHandle The handle of the simulated body to enable / disable.
|
||||
virtual void EnableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
|
||||
virtual void DisableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Make a blocking query into the scene.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @return Returns a structure that contains a list of Hits. Depending on flags set in the request, this may only contain 1 result.
|
||||
virtual SceneQueryHits QueryScene(const SceneQueryRequest* request) = 0;
|
||||
|
||||
//! Make many blocking queries into the scene.
|
||||
//! @param requests A list of requests to make. Each entry should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @return Returns a list of SceneQueryHits. Will be in the same order as supplied in SceneQueryRequests.
|
||||
virtual SceneQueryHitsList QuerySceneBatch(const SceneQueryRequests& requests) = 0;
|
||||
|
||||
//! Make a non-blocking query into the scene.
|
||||
//! @param requestId A user defined valid to identify the request when the callback is called.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @param callback The callback to trigger when the request is complete.
|
||||
//! @return Returns if the request was queued successfully. If returns false, the callback will never be called.
|
||||
[[nodiscard]] virtual bool QuerySceneAsync(SceneQuery::AsyncRequestId requestId,
|
||||
const SceneQueryRequest* request, SceneQuery::AsyncCallback callback) = 0;
|
||||
|
||||
//! Make a non-blocking query into the scene.
|
||||
//! @param requestId A user defined valid to identify the request when the callback is called.
|
||||
//! @param requests A list of requests to make. Each entry should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @param callback The callback to trigger when all the request are complete.
|
||||
//! @return Returns If the request was queued successfully. If returns false, the callback will never be called.
|
||||
[[nodiscard]] virtual bool QuerySceneAsyncBatch(SceneQuery::AsyncRequestId requestId,
|
||||
const SceneQueryRequests& requests, SceneQuery::AsyncBatchCallback callback) = 0;
|
||||
|
||||
//! Registers a pair of simulated bodies for which collisions should be suppressed.
|
||||
//! Making multiple requests with the same pair result are dropped. To remove the suppression call UnsuppressCollisionEvents with the pair.
|
||||
//! The order of the bodies do not matter, {body0, body1} collision pair is equal to {body1, body0}.
|
||||
//! @param bodyHandleA A handle to a simulated body.
|
||||
//! @param bodyHandleB A handle to a simulated body.
|
||||
virtual void SuppressCollisionEvents(
|
||||
const SimulatedBodyHandle& bodyHandleA,
|
||||
const SimulatedBodyHandle& bodyHandleB) = 0;
|
||||
|
||||
//! Unregisters a pair of simulated bodies for which collisions should be suppressed.
|
||||
//! Making multiple requests with the same pair result are dropped. To add a suppression call SuppressCollisionEvents with the pair.
|
||||
//! The order of the bodies do not matter, {body0, body1} collision pair is equal to {body1, body0}.
|
||||
//! @param bodyHandleA A handle to a simulated body.
|
||||
//! @param bodyHandleB A handle to a simulated body.
|
||||
virtual void UnsuppressCollisionEvents(
|
||||
const SimulatedBodyHandle& bodyHandleA,
|
||||
const SimulatedBodyHandle& bodyHandleB) = 0;
|
||||
|
||||
//! Set the Gravity of the Scene.
|
||||
//! @Param The new gravity vector to be used in the Scene
|
||||
virtual void SetGravity(const AZ::Vector3& gravity) = 0;
|
||||
|
||||
//! Get the Gravity of the Scene.
|
||||
//! @return A Vector3 of the gravity used in the Scene.
|
||||
virtual AZ::Vector3 GetGravity() const = 0;
|
||||
|
||||
//! Get the native pointer for a scene. Should be used with caution as it allows direct access to the lower level physics simulation.
|
||||
//! @return A pointer to the underlying implementation of a scene if there is one.
|
||||
virtual void* GetNativePointer() const = 0;
|
||||
|
||||
//! Register a handler to receive an event when the SceneConfiguration changes.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneConfigurationChangedEventHandler(SceneEvents::OnSceneConfigurationChanged::Handler& handler);
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body is added to the Scene.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSimulationBodyAddedHandler(SceneEvents::OnSimulationBodyAdded::Handler& handler);
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body is removed from the Scene.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSimulationBodyRemovedHandler(SceneEvents::OnSimulationBodyRemoved::Handler& handler);
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body has its simulation enabled in the Scene.
|
||||
//! This will only trigger if the simulated body was disabled, when first added to a scene SceneEvents::OnAnySimulationBodyCreated will trigger instead.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSimulationBodySimulationEnabledHandler(SceneEvents::OnSimulationBodySimulationEnabled::Handler& handler);
|
||||
|
||||
//! Register a handler to receive an event when a Simulated body has its simulation disabled in the Scene.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSimulationBodySimulationDisabledHandler(SceneEvents::OnSimulationBodySimulationDisabled::Handler& handler);
|
||||
|
||||
//! Register a handler to receive an event when Scene::StartSimulation is called.
|
||||
//! @note This may fire multiple times per frame.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneSimulationStartHandler(SceneEvents::OnSceneSimulationStartHandler& handler);
|
||||
|
||||
//! Register a handler to receive an event when Scene::FinishSimulation is called.
|
||||
//! @note This may fire multiple times per frame.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneSimulationFinishHandler(SceneEvents::OnSceneSimulationFinishHandler& handler);
|
||||
|
||||
//! Register a handler to receive an event with a list of SimulatedBodyHandles that updated this scene tick.
|
||||
//! @note This will fire after the OnSceneSimulationStartEvent and before the OnSceneSimulationFinishEvent when SceneConfiguration::m_enableActiveActors is true.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneActiveSimulatedBodiesHandler(SceneEvents::OnSceneActiveSimulatedBodiesEvent::Handler& handler);
|
||||
|
||||
//! Register a handler to receive all collision events in the scene.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneCollisionEventHandler(SceneEvents::OnSceneCollisionsEvent::Handler& handler);
|
||||
|
||||
//! Register a handler to receive all trigger events in the scene.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneTriggersEventHandler(SceneEvents::OnSceneTriggersEvent::Handler& handler);
|
||||
|
||||
//! Register a handler to receive a notification when the Scene's gravity has changed.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneGravityChangedEvent(SceneEvents::OnSceneGravityChangedEvent::Handler& handler);
|
||||
|
||||
protected:
|
||||
SceneEvents::OnSceneConfigurationChanged m_configChangeEvent;
|
||||
SceneEvents::OnSimulationBodyAdded m_simulatedBodyAddedEvent;
|
||||
SceneEvents::OnSimulationBodyRemoved m_simulatedBodyRemovedEvent;
|
||||
SceneEvents::OnSimulationBodySimulationEnabled m_simulatedBodySimulationEnabledEvent;
|
||||
SceneEvents::OnSimulationBodySimulationDisabled m_simulatedBodySimulationDisabledEvent;
|
||||
SceneEvents::OnSceneSimulationStartEvent m_sceneSimuationStartEvent;
|
||||
SceneEvents::OnSceneSimulationFinishEvent m_sceneSimuationFinishEvent;
|
||||
SceneEvents::OnSceneActiveSimulatedBodiesEvent m_sceneActiveSimulatedBodies;
|
||||
SceneEvents::OnSceneCollisionsEvent m_sceneCollisionEvent;
|
||||
SceneEvents::OnSceneTriggersEvent m_sceneTriggerEvent;
|
||||
SceneEvents::OnSceneGravityChangedEvent m_sceneGravityChangedEvent;
|
||||
private:
|
||||
// helper for behaviour context
|
||||
SceneEvents::OnSceneGravityChangedEvent* GetOnGravityChangedEvent();
|
||||
|
||||
AZ::Crc32 m_id;
|
||||
};
|
||||
using SceneList = AZStd::vector<Scene*>;
|
||||
using SceneList = AZStd::vector<AZStd::unique_ptr<Scene>>;
|
||||
|
||||
inline void Scene::RegisterSceneConfigurationChangedEventHandler(SceneEvents::OnSceneConfigurationChanged::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_configChangeEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSimulationBodyAddedHandler(SceneEvents::OnSimulationBodyAdded::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_simulatedBodyAddedEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSimulationBodyRemovedHandler(SceneEvents::OnSimulationBodyRemoved::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_simulatedBodyRemovedEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSimulationBodySimulationEnabledHandler(SceneEvents::OnSimulationBodySimulationEnabled::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_simulatedBodySimulationEnabledEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSimulationBodySimulationDisabledHandler(SceneEvents::OnSimulationBodySimulationDisabled::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_simulatedBodySimulationDisabledEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneSimulationStartHandler(SceneEvents::OnSceneSimulationStartHandler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneSimuationStartEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneSimulationFinishHandler(SceneEvents::OnSceneSimulationFinishHandler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneSimuationFinishEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneActiveSimulatedBodiesHandler(SceneEvents::OnSceneActiveSimulatedBodiesEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneActiveSimulatedBodies);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneCollisionEventHandler(SceneEvents::OnSceneCollisionsEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneCollisionEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneTriggersEventHandler(SceneEvents::OnSceneTriggersEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneTriggerEvent);
|
||||
}
|
||||
|
||||
inline void Scene::RegisterSceneGravityChangedEvent(SceneEvents::OnSceneGravityChangedEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_sceneGravityChangedEvent);
|
||||
}
|
||||
} // namespace AzPhysics
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* 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 <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
void SystemInterface::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
const auto getOnPresimulateEvent = []()->SystemEvents::OnPresimulateEvent*
|
||||
{
|
||||
if (auto* physicsSystem = AZ::Interface<SystemInterface>::Get())
|
||||
{
|
||||
return &physicsSystem->m_preSimulateEvent;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription presimulateEventDescription =
|
||||
{
|
||||
"Presimulate event",
|
||||
{"Tick time"} // Parameters
|
||||
};
|
||||
|
||||
const auto getOnPostsimulateEvent = []() -> SystemEvents::OnPostsimulateEvent*
|
||||
{
|
||||
if (auto* physicsSystem = AZ::Interface<SystemInterface>::Get())
|
||||
{
|
||||
return &physicsSystem->m_postSimulateEvent;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
const AZ::BehaviorAzEventDescription postsimulateEventDescription =
|
||||
{
|
||||
"Postsimulate event",
|
||||
{} // Parameters
|
||||
};
|
||||
|
||||
behaviorContext->Class<SystemInterface>("System Interface")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Method("GetOnPresimulateEvent", getOnPresimulateEvent)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, presimulateEventDescription)
|
||||
->Method("GetOnPostsimulateEvent", getOnPostsimulateEvent)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, postsimulateEventDescription)
|
||||
;
|
||||
}
|
||||
}
|
||||
} // namespace AzPhysics
|
||||
@@ -35,6 +35,8 @@ namespace AzPhysics
|
||||
virtual ~SystemInterface() = default;
|
||||
AZ_DISABLE_COPY_MOVE(SystemInterface);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
//! Initialize the Physics system with the given configuration.
|
||||
//! @param config Contains the configuration options
|
||||
virtual void Initialize(const SystemConfiguration* config) = 0;
|
||||
@@ -83,6 +85,11 @@ namespace AzPhysics
|
||||
//! @return Returns a list of SceneHandle objects for each created Scene. Order will be the same as the SceneConfigurationList provided.
|
||||
virtual SceneHandleList AddScenes(const SceneConfigurationList& configs) = 0;
|
||||
|
||||
//! Returns a Scene Handle connected to the given scene name.
|
||||
//! @param sceneName The name of the scene to look up.
|
||||
//! @returns Will return a SceneHandle to a Scene connected with the given name, otherwise will return InvalidSceneHandle.
|
||||
virtual SceneHandle GetSceneHandle(const AZStd::string& sceneName) = 0;
|
||||
|
||||
//! Get the Scene of the requested SceneHandle.
|
||||
//! @param handle The SceneHandle of the requested scene.
|
||||
//! @return Returns a SceneInterface pointer if found, otherwise nullptr.
|
||||
@@ -108,6 +115,12 @@ namespace AzPhysics
|
||||
//! Removes All Scenes.
|
||||
virtual void RemoveAllScenes() = 0;
|
||||
|
||||
//! Helper to find the SceneHandle and SimulatedBodyHandle of a body related to the requested EntityId.
|
||||
//! @note This will search all scenes and maybe slow if there are many Scenes.
|
||||
//! @param entityId The entity to search for.
|
||||
//! @return Will return a AZStd::pair of SceneHandle and SimulatedBodyHandle of the requested entityid, otherwise will return AzPhysics::InvalidSceneHandle, AzPhysics::SimulatedBodyHandle.
|
||||
virtual AZStd::pair<SceneHandle, SimulatedBodyHandle> FindAttachedBodyHandleFromEntityId(AZ::EntityId entityId) = 0;
|
||||
|
||||
//! Get the current SystemConfiguration used to initialize the Physics system.
|
||||
virtual const SystemConfiguration* GetConfiguration() const = 0;
|
||||
|
||||
@@ -147,6 +160,12 @@ namespace AzPhysics
|
||||
//! Register to receive notifications when the Physics System simulation ends.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterPostSimulateEvent(SystemEvents::OnPostsimulateEvent::Handler& handler) { handler.Connect(m_postSimulateEvent); }
|
||||
//! Register to receive notifications when the a new Scene is added to the simulation.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneAddedEvent(SystemEvents::OnSceneAddedEvent::Handler& handler) { handler.Connect(m_sceneAddedEvent); }
|
||||
//! Register to receive notifications when the a Scene is removed from the simulation.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSceneRemovedEvent(SystemEvents::OnSceneAddedEvent::Handler& handler) { handler.Connect(m_sceneRemovedEvent); }
|
||||
//! Register to receive notifications when the SystemConfiguration changes.
|
||||
//! @param handler The handler to receive the event.
|
||||
void RegisterSystemConfigurationChangedEvent(SystemEvents::OnConfigurationChangedEvent::Handler& handler) { handler.Connect(m_configChangeEvent); }
|
||||
@@ -163,6 +182,8 @@ namespace AzPhysics
|
||||
SystemEvents::OnShutdownEvent m_shutdownEvent;
|
||||
SystemEvents::OnPresimulateEvent m_preSimulateEvent;
|
||||
SystemEvents::OnPostsimulateEvent m_postSimulateEvent;
|
||||
SystemEvents::OnSceneAddedEvent m_sceneAddedEvent;
|
||||
SystemEvents::OnSceneRemovedEvent m_sceneRemovedEvent;
|
||||
SystemEvents::OnConfigurationChangedEvent m_configChangeEvent;
|
||||
SystemEvents::OnDefaultMaterialLibraryChangedEvent m_onDefaultMaterialLibraryChangedEvent;
|
||||
SystemEvents::OnDefaultSceneConfigurationChangedEvent m_onDefaultSceneConfigurationChangedEvent;
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace Physics
|
||||
RagdollNodeConfiguration::RagdollNodeConfiguration()
|
||||
{
|
||||
m_propertyVisibilityFlags =
|
||||
PropertyVisibility::InertiaProperties |
|
||||
PropertyVisibility::Damping |
|
||||
PropertyVisibility::SleepOptions |
|
||||
PropertyVisibility::Interpolation |
|
||||
PropertyVisibility::Gravity |
|
||||
PropertyVisibility::ContinuousCollisionDetection |
|
||||
PropertyVisibility::MaxVelocities;
|
||||
RigidBodyConfiguration::PropertyVisibility::InertiaProperties |
|
||||
RigidBodyConfiguration::PropertyVisibility::Damping |
|
||||
RigidBodyConfiguration::PropertyVisibility::SleepOptions |
|
||||
RigidBodyConfiguration::PropertyVisibility::Interpolation |
|
||||
RigidBodyConfiguration::PropertyVisibility::Gravity |
|
||||
RigidBodyConfiguration::PropertyVisibility::ContinuousCollisionDetection |
|
||||
RigidBodyConfiguration::PropertyVisibility::MaxVelocities;
|
||||
}
|
||||
|
||||
void RagdollNodeConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
@@ -57,7 +57,7 @@ namespace Physics
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<RagdollConfiguration, WorldBodyConfiguration>()
|
||||
serializeContext->Class<RagdollConfiguration, AzPhysics::SimulatedBodyConfiguration>()
|
||||
->Version(2, &ClassConverters::RagdollConfigConverter)
|
||||
->Field("nodes", &RagdollConfiguration::m_nodes)
|
||||
->Field("colliders", &RagdollConfiguration::m_colliders)
|
||||
@@ -103,4 +103,4 @@ namespace Physics
|
||||
m_nodes.erase(m_nodes.begin() + configIndex.GetValue());
|
||||
}
|
||||
}
|
||||
} // namespace Physics
|
||||
} // namespace Physics
|
||||
|
||||
@@ -15,19 +15,21 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/Physics/Character.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
#include <AzFramework/Physics/RigidBody.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/RagdollPhysicsBus.h>
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class RagdollNodeConfiguration
|
||||
: public RigidBodyConfiguration
|
||||
: public AzPhysics::RigidBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RagdollNodeConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RagdollNodeConfiguration, "{A1796586-85AB-496E-93C9-C5841F03B1AD}", RigidBodyConfiguration);
|
||||
AZ_RTTI(RagdollNodeConfiguration, "{A1796586-85AB-496E-93C9-C5841F03B1AD}", AzPhysics::RigidBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
RagdollNodeConfiguration();
|
||||
@@ -37,11 +39,11 @@ namespace Physics
|
||||
};
|
||||
|
||||
class RagdollConfiguration
|
||||
: public WorldBodyConfiguration
|
||||
: public AzPhysics::SimulatedBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RagdollConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RagdollConfiguration, "{7C96D332-61D8-4C58-A2BF-707716D38D14}", WorldBodyConfiguration);
|
||||
AZ_RTTI(RagdollConfiguration, "{7C96D332-61D8-4C58-A2BF-707716D38D14}", AzPhysics::SimulatedBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
RagdollConfiguration() = default;
|
||||
@@ -58,25 +60,26 @@ namespace Physics
|
||||
|
||||
/// Represents a single rigid part of a ragdoll.
|
||||
class RagdollNode
|
||||
: public WorldBody
|
||||
: public AzPhysics::SimulatedBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RagdollNode, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RagdollNode, "{226D02B7-6138-4F6B-9870-DE5A1C3C5077}", WorldBody);
|
||||
AZ_RTTI(RagdollNode, "{226D02B7-6138-4F6B-9870-DE5A1C3C5077}", AzPhysics::SimulatedBody);
|
||||
|
||||
virtual RigidBody& GetRigidBody() = 0;
|
||||
virtual AzPhysics::RigidBody& GetRigidBody() = 0;
|
||||
virtual ~RagdollNode() = default;
|
||||
|
||||
virtual const AZStd::shared_ptr<Physics::Joint>& GetJoint() const = 0;
|
||||
virtual bool IsSimulating() const = 0;
|
||||
};
|
||||
|
||||
/// A hierarchical collection of rigid bodies connected by joints typically used to physically simulate a character.
|
||||
class Ragdoll
|
||||
: public WorldBody
|
||||
: public AzPhysics::SimulatedBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Ragdoll, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", WorldBody);
|
||||
AZ_RTTI(Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", AzPhysics::SimulatedBody);
|
||||
virtual ~Ragdoll() = default;
|
||||
|
||||
/// Inserts the ragdoll into the physics simulation.
|
||||
@@ -131,8 +134,5 @@ namespace Physics
|
||||
|
||||
/// Returns the number of ragdoll nodes in the ragdoll.
|
||||
virtual size_t GetNumNodes() const = 0;
|
||||
|
||||
/// Returns the id of the world the ragdoll exists in.
|
||||
virtual AZ::Crc32 GetWorldId() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/RigidBody.h>
|
||||
#include <AzFramework/Physics/ClassConverters.h>
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
float DefaultRigidBodyConfiguration::m_mass = 1.f;
|
||||
bool DefaultRigidBodyConfiguration::m_computeInertiaTensor = false;
|
||||
float DefaultRigidBodyConfiguration::m_linearDamping = 0.05f;
|
||||
float DefaultRigidBodyConfiguration::m_angularDamping = 0.15f;
|
||||
float DefaultRigidBodyConfiguration::m_sleepMinEnergy = 0.5f;
|
||||
float DefaultRigidBodyConfiguration::m_maxAngularVelocity = 100.0f;
|
||||
|
||||
void RigidBodyConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<RigidBodyConfiguration, WorldBodyConfiguration>()
|
||||
->Version(3, &ClassConverters::RigidBodyVersionConverter)
|
||||
->Field("Initial linear velocity", &Physics::RigidBodyConfiguration::m_initialLinearVelocity)
|
||||
->Field("Initial angular velocity", &Physics::RigidBodyConfiguration::m_initialAngularVelocity)
|
||||
->Field("Linear damping", &Physics::RigidBodyConfiguration::m_linearDamping)
|
||||
->Field("Angular damping", &Physics::RigidBodyConfiguration::m_angularDamping)
|
||||
->Field("Sleep threshold", &Physics::RigidBodyConfiguration::m_sleepMinEnergy)
|
||||
->Field("Start Asleep", &Physics::RigidBodyConfiguration::m_startAsleep)
|
||||
->Field("Interpolate Motion", &Physics::RigidBodyConfiguration::m_interpolateMotion)
|
||||
->Field("Gravity Enabled", &Physics::RigidBodyConfiguration::m_gravityEnabled)
|
||||
->Field("Simulated", &Physics::RigidBodyConfiguration::m_simulated)
|
||||
->Field("Kinematic", &Physics::RigidBodyConfiguration::m_kinematic)
|
||||
->Field("CCD Enabled", &Physics::RigidBodyConfiguration::m_ccdEnabled)
|
||||
->Field("Compute Mass", &Physics::RigidBodyConfiguration::m_computeMass)
|
||||
->Field("Mass", &Physics::RigidBodyConfiguration::m_mass)
|
||||
->Field("Compute COM", &Physics::RigidBodyConfiguration::m_computeCenterOfMass)
|
||||
->Field("Centre of mass offset", &RigidBodyConfiguration::m_centerOfMassOffset)
|
||||
->Field("Compute inertia", &RigidBodyConfiguration::m_computeInertiaTensor)
|
||||
->Field("Inertia tensor", &RigidBodyConfiguration::m_inertiaTensor)
|
||||
->Field("Property Visibility Flags", &RigidBodyConfiguration::m_propertyVisibilityFlags)
|
||||
->Field("Maximum Angular Velocity", &RigidBodyConfiguration::m_maxAngularVelocity)
|
||||
->Field("Include All Shapes In Mass", &RigidBodyConfiguration::m_includeAllShapesInMassCalculation)
|
||||
->Field("CCD Min Advance", &RigidBodyConfiguration::m_ccdMinAdvanceCoefficient)
|
||||
->Field("CCD Friction", &RigidBodyConfiguration::m_ccdFrictionEnabled)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetPropertyVisibility(PropertyVisibility property) const
|
||||
{
|
||||
return (m_propertyVisibilityFlags & property) != 0 ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
void RigidBodyConfiguration::SetPropertyVisibility(PropertyVisibility property, bool isVisible)
|
||||
{
|
||||
if (isVisible)
|
||||
{
|
||||
m_propertyVisibilityFlags |= property;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_propertyVisibilityFlags &= ~property;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInitialVelocitiesVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::InitialVelocities);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInertiaSettingsVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::InertiaProperties);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInertiaVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & PropertyVisibility::InertiaProperties) != 0) && !m_computeInertiaTensor;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetCoMVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & PropertyVisibility::InertiaProperties) != 0) && !m_computeCenterOfMass;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetMassVisibility() const
|
||||
{
|
||||
bool visible = ((m_propertyVisibilityFlags & PropertyVisibility::InertiaProperties) != 0) && !m_computeMass;
|
||||
return visible ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetDampingVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::Damping);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetSleepOptionsVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::SleepOptions);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetInterpolationVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::Interpolation);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetGravityVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::Gravity);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetKinematicVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::Kinematic);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetCCDVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::ContinuousCollisionDetection);
|
||||
}
|
||||
|
||||
AZ::Crc32 RigidBodyConfiguration::GetMaxVelocitiesVisibility() const
|
||||
{
|
||||
return GetPropertyVisibility(PropertyVisibility::MaxVelocities);
|
||||
}
|
||||
|
||||
Physics::MassComputeFlags RigidBodyConfiguration::GetMassComputeFlags() const
|
||||
{
|
||||
using Physics::MassComputeFlags;
|
||||
|
||||
MassComputeFlags flags = MassComputeFlags::NONE;
|
||||
|
||||
if (m_computeCenterOfMass)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_COM;
|
||||
}
|
||||
|
||||
if (m_computeInertiaTensor)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_INERTIA;
|
||||
}
|
||||
|
||||
if (m_computeMass)
|
||||
{
|
||||
flags = flags | MassComputeFlags::COMPUTE_MASS;
|
||||
}
|
||||
|
||||
if (m_includeAllShapesInMassCalculation)
|
||||
{
|
||||
flags = flags | MassComputeFlags::INCLUDE_ALL_SHAPES;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void RigidBodyConfiguration::SetMassComputeFlags(MassComputeFlags flags)
|
||||
{
|
||||
using Physics::MassComputeFlags;
|
||||
m_computeCenterOfMass = MassComputeFlags::COMPUTE_COM == (flags & MassComputeFlags::COMPUTE_COM);
|
||||
m_computeInertiaTensor = MassComputeFlags::COMPUTE_INERTIA == (flags & MassComputeFlags::COMPUTE_INERTIA);
|
||||
m_computeMass = MassComputeFlags::COMPUTE_MASS == (flags & MassComputeFlags::COMPUTE_MASS);
|
||||
m_includeAllShapesInMassCalculation =
|
||||
MassComputeFlags::INCLUDE_ALL_SHAPES == (flags & MassComputeFlags::INCLUDE_ALL_SHAPES);
|
||||
}
|
||||
|
||||
bool RigidBodyConfiguration::IsCCDEnabled() const
|
||||
{
|
||||
return m_ccdEnabled;
|
||||
}
|
||||
|
||||
RigidBody::RigidBody(const RigidBodyConfiguration& settings)
|
||||
: WorldBody(settings)
|
||||
{
|
||||
}
|
||||
} // namespace Physics
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
// LUMBERYARD_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
|
||||
@@ -13,12 +13,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzFramework/Physics/Casts.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct RigidBody;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class RigidBody;
|
||||
|
||||
class RigidBodyRequests
|
||||
: public AZ::ComponentBus
|
||||
@@ -69,9 +74,9 @@ namespace Physics
|
||||
virtual void SetSimulationEnabled(bool enabled) = 0;
|
||||
|
||||
virtual AZ::Aabb GetAabb() const = 0;
|
||||
virtual Physics::RigidBody* GetRigidBody() = 0;
|
||||
virtual AzPhysics::RigidBody* GetRigidBody() = 0;
|
||||
|
||||
virtual Physics::RayCastHit RayCast(const Physics::RayCastRequest& request) = 0;
|
||||
virtual AzPhysics::SceneQueryHit RayCast(const AzPhysics::RayCastRequest& request) = 0;
|
||||
};
|
||||
|
||||
using RigidBodyRequestBus = AZ::EBus<RigidBodyRequests>;
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* 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 "ScriptCanvasPhysicsUtils.h"
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
namespace ReflectionUtils
|
||||
{
|
||||
CollisionNotificationBusBehaviorHandler::CollisionNotificationBusBehaviorHandler()
|
||||
{
|
||||
m_events.resize(FN_MAX);
|
||||
SetEvent(&CollisionNotificationBusBehaviorHandler::OnCollisionBeginDummy, "OnCollisionBegin");
|
||||
SetEvent(&CollisionNotificationBusBehaviorHandler::OnCollisionPersistDummy, "OnCollisionPersist");
|
||||
SetEvent(&CollisionNotificationBusBehaviorHandler::OnCollisionEndDummy, "OnCollisionEnd");
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<Physics::Contact>()
|
||||
->Version(1)
|
||||
->Field("Position", &Physics::Contact::m_position)
|
||||
->Field("Normal", &Physics::Contact::m_normal)
|
||||
->Field("Impulse", &Physics::Contact::m_impulse)
|
||||
->Field("Separation", &Physics::Contact::m_separation)
|
||||
;
|
||||
|
||||
serializeContext->Class<Physics::CollisionEvent>()
|
||||
->Field("Contacts", &Physics::CollisionEvent::m_contacts)
|
||||
;
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<Physics::Contact>("Contact")
|
||||
->Property("Position", BehaviorValueProperty(&Physics::Contact::m_position))
|
||||
->Property("Normal", BehaviorValueProperty(&Physics::Contact::m_normal))
|
||||
->Property("Impulse", BehaviorValueProperty(&Physics::Contact::m_impulse))
|
||||
->Property("Separation", BehaviorValueProperty(&Physics::Contact::m_separation))
|
||||
;
|
||||
|
||||
behaviorContext->Class<Physics::CollisionEvent>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Property("Contacts", BehaviorValueProperty(&Physics::CollisionEvent::m_contacts))
|
||||
;
|
||||
|
||||
behaviorContext->EBus<Physics::CollisionNotificationBus>("CollisionNotificationBus")
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Handler<CollisionNotificationBusBehaviorHandler>()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::Disconnect()
|
||||
{
|
||||
BusDisconnect();
|
||||
}
|
||||
|
||||
bool CollisionNotificationBusBehaviorHandler::Connect(AZ::BehaviorValueParameter* id)
|
||||
{
|
||||
return AZ::Internal::EBusConnector<CollisionNotificationBusBehaviorHandler>::Connect(this, id);
|
||||
}
|
||||
|
||||
bool CollisionNotificationBusBehaviorHandler::IsConnected()
|
||||
{
|
||||
return AZ::Internal::EBusConnector<CollisionNotificationBusBehaviorHandler>::IsConnected(this);
|
||||
}
|
||||
|
||||
bool CollisionNotificationBusBehaviorHandler::IsConnectedId(AZ::BehaviorValueParameter* id)
|
||||
{
|
||||
return AZ::Internal::EBusConnector<CollisionNotificationBusBehaviorHandler>::IsConnectedId(this, id);
|
||||
}
|
||||
|
||||
int CollisionNotificationBusBehaviorHandler::GetFunctionIndex(const char* functionName) const
|
||||
{
|
||||
if (strcmp(functionName, "OnCollisionBegin") == 0) return FN_OnCollisionBegin;
|
||||
if (strcmp(functionName, "OnCollisionPersist") == 0) return FN_OnCollisionPersist;
|
||||
if (strcmp(functionName, "OnCollisionEnd") == 0) return FN_OnCollisionEnd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionBeginDummy(AZ::EntityId /*entityId*/, const AZStd::vector<Contact>& /*contacts*/)
|
||||
{
|
||||
// This is never invoked, and only used for type deduction when calling SetEvent
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionPersistDummy(AZ::EntityId /*entityId*/, const AZStd::vector<Contact>& /*contacts*/)
|
||||
{
|
||||
// This is never invoked, and only used for type deduction when calling SetEvent
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionEndDummy(AZ::EntityId /*entityId*/)
|
||||
{
|
||||
// This is never invoked, and only used for type deduction when calling SetEvent
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionBegin(const CollisionEvent& collisionEvent)
|
||||
{
|
||||
Call(FN_OnCollisionBegin, collisionEvent.m_body2->GetEntityId(), collisionEvent.m_contacts);
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionPersist(const CollisionEvent& collisionEvent)
|
||||
{
|
||||
Call(FN_OnCollisionPersist, collisionEvent.m_body2->GetEntityId(), collisionEvent.m_contacts);
|
||||
}
|
||||
|
||||
void CollisionNotificationBusBehaviorHandler::OnCollisionEnd(const CollisionEvent& collisionEvent)
|
||||
{
|
||||
Call(FN_OnCollisionEnd, collisionEvent.m_body2->GetEntityId());
|
||||
}
|
||||
|
||||
void WorldNotificationBusBehaviorHandler::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<WorldNotificationBus>("WorldNotificationBus")
|
||||
->Handler<WorldNotificationBusBehaviorHandler>()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldNotificationBusBehaviorHandler::OnPrePhysicsTick(float deltaTime)
|
||||
{
|
||||
Call(FN_OnPrePhysicsTick, deltaTime);
|
||||
}
|
||||
|
||||
void WorldNotificationBusBehaviorHandler::OnPrePhysicsSubtick(float fixedDeltaTime)
|
||||
{
|
||||
Call(FN_OnPrePhysicsSubtick, fixedDeltaTime);
|
||||
}
|
||||
|
||||
void WorldNotificationBusBehaviorHandler::OnPostPhysicsSubtick(float fixedDeltaTime)
|
||||
{
|
||||
Call(FN_OnPostPhysicsSubtick, fixedDeltaTime);
|
||||
}
|
||||
|
||||
void WorldNotificationBusBehaviorHandler::OnPostPhysicsTick(float deltaTime)
|
||||
{
|
||||
Call(FN_OnPostPhysicsTick, deltaTime);
|
||||
}
|
||||
|
||||
int WorldNotificationBusBehaviorHandler::GetPhysicsTickOrder()
|
||||
{
|
||||
int order = WorldNotifications::Scripting;
|
||||
CallResult(order, FN_GetPhysicsTickOrder);
|
||||
return order;
|
||||
}
|
||||
} // namespace ReflectionUtils
|
||||
} // namespace Physics
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/TriggerBus.h>
|
||||
#include <AzFramework/Physics/CollisionNotificationBus.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzFramework/Physics/World.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
namespace ReflectionUtils
|
||||
{
|
||||
/// Behavior handler which forwards CollisionNotificationBus events to script canvas.
|
||||
/// Note this class is not using the usual AZ_EBUS_BEHAVIOR_BINDER macro as the signature
|
||||
/// needs to be changed for script canvas
|
||||
class CollisionNotificationBusBehaviorHandler
|
||||
: public CollisionNotificationBus::Handler
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(CollisionNotificationBusBehaviorHandler, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(CollisionNotificationBusBehaviorHandler, "{A28ACB8F-3429-4F92-88DB-481ACF90EF21}", AZ::BehaviorEBusHandler);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
CollisionNotificationBusBehaviorHandler();
|
||||
|
||||
// Script Canvas Signature
|
||||
void OnCollisionBeginDummy(AZ::EntityId entityId, const AZStd::vector<Contact>& contacts);
|
||||
void OnCollisionPersistDummy(AZ::EntityId entityId, const AZStd::vector<Contact>& contacts);
|
||||
void OnCollisionEndDummy(AZ::EntityId entityId);
|
||||
|
||||
using EventFunctionsParameterPack = AZStd::Internal::pack_traits_arg_sequence
|
||||
<
|
||||
decltype(&CollisionNotificationBusBehaviorHandler::OnCollisionBeginDummy),
|
||||
decltype(&CollisionNotificationBusBehaviorHandler::OnCollisionPersistDummy),
|
||||
decltype(&CollisionNotificationBusBehaviorHandler::OnCollisionEndDummy)
|
||||
>;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
FN_OnCollisionBegin,
|
||||
FN_OnCollisionPersist,
|
||||
FN_OnCollisionEnd,
|
||||
FN_MAX
|
||||
};
|
||||
|
||||
// AZ::BehaviorEBusHandler
|
||||
void Disconnect() override;
|
||||
bool Connect(AZ::BehaviorValueParameter* id = nullptr) override;
|
||||
bool IsConnected() override;
|
||||
bool IsConnectedId(AZ::BehaviorValueParameter* id) override;
|
||||
int GetFunctionIndex(const char* functionName) const override;
|
||||
|
||||
|
||||
// CollisionNotificationBus
|
||||
void OnCollisionBegin(const CollisionEvent& triggerEvent) override;
|
||||
void OnCollisionPersist(const CollisionEvent& triggerEvent) override;
|
||||
void OnCollisionEnd(const CollisionEvent& triggerEvent) override;
|
||||
};
|
||||
|
||||
class WorldNotificationBusBehaviorHandler
|
||||
: public WorldNotificationBus::Handler
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
AZ_EBUS_BEHAVIOR_BINDER(WorldNotificationBusBehaviorHandler, "{D8B108B8-9126-4C66-B857-377BA5DB3062}", AZ::SystemAllocator
|
||||
, OnPrePhysicsTick
|
||||
, OnPrePhysicsSubtick
|
||||
, OnPostPhysicsSubtick
|
||||
, OnPostPhysicsTick
|
||||
, GetPhysicsTickOrder
|
||||
);
|
||||
|
||||
// WorldNotificationBus ...
|
||||
void OnPrePhysicsTick(float deltaTime) override;
|
||||
void OnPrePhysicsSubtick(float fixedDeltaTime) override;
|
||||
void OnPostPhysicsSubtick(float fixedDeltaTime) override;
|
||||
void OnPostPhysicsTick(float deltaTime) override;
|
||||
int GetPhysicsTickOrder() override;
|
||||
};
|
||||
} // namespace ReflectionUtils
|
||||
} // namespace Physics
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <AzFramework/Physics/Material.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionLayers.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -83,7 +84,6 @@ namespace Physics
|
||||
using ShapeConfigurationList = AZStd::vector<ShapeConfigurationPair>;
|
||||
|
||||
struct RayCastRequest;
|
||||
struct RayCastHit;
|
||||
|
||||
class Shape
|
||||
{
|
||||
@@ -121,11 +121,11 @@ namespace Physics
|
||||
//! Raycast against this shape.
|
||||
//! @param request Ray parameters in world space.
|
||||
//! @param worldTransform World transform of this shape.
|
||||
virtual Physics::RayCastHit RayCast(const Physics::RayCastRequest& worldSpaceRequest, const AZ::Transform& worldTransform) = 0;
|
||||
virtual AzPhysics::SceneQueryHit RayCast(const AzPhysics::RayCastRequest& worldSpaceRequest, const AZ::Transform& worldTransform) = 0;
|
||||
|
||||
//! Raycast against this shape using local coordinates.
|
||||
//! @param request Ray parameters in local space.
|
||||
virtual Physics::RayCastHit RayCastLocal(const Physics::RayCastRequest& localSpaceRequest) = 0;
|
||||
virtual AzPhysics::SceneQueryHit RayCastLocal(const AzPhysics::RayCastRequest& localSpaceRequest) = 0;
|
||||
|
||||
//! Retrieve this shape AABB.
|
||||
//! @param worldTransform World transform of this shape.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(RigidBody, AZ::SystemAllocator, 0);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ShapeConfiguration;
|
||||
class Shape;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
//! Dynamic rigid body.
|
||||
struct RigidBody
|
||||
: public SimulatedBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::RigidBody, "{156E459F-7BB7-4B4E-ADA0-2130D96B7E80}", AzPhysics::SimulatedBody);
|
||||
|
||||
RigidBody() = default;
|
||||
|
||||
virtual void AddShape(AZStd::shared_ptr<Physics::Shape> shape) = 0;
|
||||
virtual void RemoveShape(AZStd::shared_ptr<Physics::Shape> shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Physics::Shape> GetShape([[maybe_unused]]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;
|
||||
};
|
||||
|
||||
} // namespace AzPhysics
|
||||
+10
-14
@@ -10,26 +10,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Physics/World.h>
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/StaticRigidBody.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace Physics
|
||||
namespace AzPhysics
|
||||
{
|
||||
void WorldBodyConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
AZ_CLASS_ALLOCATOR_IMPL(StaticRigidBody, AZ::SystemAllocator, 0);
|
||||
|
||||
/*static*/ void StaticRigidBody::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<WorldBodyConfiguration>()
|
||||
serializeContext->Class<StaticRigidBody, SimulatedBody>()
|
||||
->Version(1)
|
||||
->Field("name", &WorldBodyConfiguration::m_debugName)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldBody::SetUserData(void* userData)
|
||||
{
|
||||
m_customUserData = userData;
|
||||
}
|
||||
} // namespace Physics
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ShapeConfiguration;
|
||||
class ColliderConfiguration;
|
||||
class Shape;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
//! Static rigid body.
|
||||
struct StaticRigidBody
|
||||
: public SimulatedBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(StaticRigidBody, "{13A677BB-7085-4EDB-BCC8-306548238692}", SimulatedBody);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
//Legacy API - may change with LYN-438
|
||||
virtual void AddShape(const AZStd::shared_ptr<Physics::Shape>& shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Physics::Shape> GetShape([[maybe_unused]]AZ::u32 index) { return nullptr; }
|
||||
};
|
||||
}
|
||||
@@ -16,33 +16,31 @@
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Asset/GenericAssetHandler.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
struct RigidBodyConfiguration;
|
||||
struct RigidBody;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class World;
|
||||
class WorldBody;
|
||||
class RigidBody;
|
||||
class RigidBodyStatic;
|
||||
class Shape;
|
||||
class Material;
|
||||
class MaterialSelection;
|
||||
class MaterialConfiguration;
|
||||
class MaterialLibraryAsset;
|
||||
class WorldBodyConfiguration;
|
||||
class RigidBodyConfiguration;
|
||||
class ColliderConfiguration;
|
||||
class ShapeConfiguration;
|
||||
class JointLimitConfiguration;
|
||||
class Joint;
|
||||
struct RayCastRequest;
|
||||
struct RayCastResult;
|
||||
struct ShapeCastRequest;
|
||||
struct ShapeCastResult;
|
||||
class CharacterConfiguration;
|
||||
class Character;
|
||||
|
||||
@@ -71,9 +69,9 @@ namespace Physics
|
||||
/// Settings structure provided to DebugDrawPhysics to drive debug drawing behavior.
|
||||
struct DebugDrawSettings
|
||||
{
|
||||
using DebugDrawLineCallback = AZStd::function<void(const DebugDrawVertex& from, const DebugDrawVertex& to, const AZStd::shared_ptr<WorldBody>& body, float thickness, void* udata)>;
|
||||
using DebugDrawTriangleCallback = AZStd::function<void(const DebugDrawVertex& a, const DebugDrawVertex& b, const DebugDrawVertex& c, const AZStd::shared_ptr<WorldBody>& body, void* udata)>;
|
||||
using DebugDrawTriangleBatchCallback = AZStd::function<void(const DebugDrawVertex* verts, AZ::u32 numVerts, const AZ::u32* indices, AZ::u32 numIndices, const AZStd::shared_ptr<WorldBody>& body, void* udata)>;
|
||||
using DebugDrawLineCallback = AZStd::function<void(const DebugDrawVertex& from, const DebugDrawVertex& to, const AZStd::shared_ptr<AzPhysics::SimulatedBody>& body, float thickness, void* udata)>;
|
||||
using DebugDrawTriangleCallback = AZStd::function<void(const DebugDrawVertex& a, const DebugDrawVertex& b, const DebugDrawVertex& c, const AZStd::shared_ptr<AzPhysics::SimulatedBody>& body, void* udata)>;
|
||||
using DebugDrawTriangleBatchCallback = AZStd::function<void(const DebugDrawVertex* verts, AZ::u32 numVerts, const AZ::u32* indices, AZ::u32 numIndices, const AZStd::shared_ptr<AzPhysics::SimulatedBody>& body, void* udata)>;
|
||||
|
||||
DebugDrawLineCallback m_drawLineCB; ///< Required user callback for line drawing.
|
||||
DebugDrawTriangleBatchCallback m_drawTriBatchCB; ///< User callback for triangle batch drawing. Required if \ref m_isWireframe is false.
|
||||
@@ -84,8 +82,8 @@ namespace Physics
|
||||
bool m_drawBodyTransforms = false; ///< If enabled, draws transform axes for each body.
|
||||
void* m_udata = nullptr; ///< Platform specific and/or gem specific optional user data pointer.
|
||||
|
||||
void DrawLine(const DebugDrawVertex& from, const DebugDrawVertex& to, const AZStd::shared_ptr<WorldBody>& body, float thickness = 1.0f) { m_drawLineCB(from, to, body, thickness, m_udata); }
|
||||
void DrawTriangleBatch(const DebugDrawVertex* verts, AZ::u32 numVerts, const AZ::u32* indices, AZ::u32 numIndices, const AZStd::shared_ptr<WorldBody>& body) { m_drawTriBatchCB(verts, numVerts, indices, numIndices, body, m_udata); }
|
||||
void DrawLine(const DebugDrawVertex& from, const DebugDrawVertex& to, const AZStd::shared_ptr<AzPhysics::SimulatedBody>& body, float thickness = 1.0f) { m_drawLineCB(from, to, body, thickness, m_udata); }
|
||||
void DrawTriangleBatch(const DebugDrawVertex* verts, AZ::u32 numVerts, const AZ::u32* indices, AZ::u32 numIndices, const AZStd::shared_ptr<AzPhysics::SimulatedBody>& body) { m_drawTriBatchCB(verts, numVerts, indices, numIndices, body, m_udata); }
|
||||
};
|
||||
|
||||
/// An interface to get the default physics world for systems that do not support multiple worlds.
|
||||
@@ -95,8 +93,8 @@ namespace Physics
|
||||
public:
|
||||
using MutexType = AZStd::mutex;
|
||||
|
||||
/// Returns the Default world managed by a relevant system.
|
||||
virtual AZStd::shared_ptr<World> GetDefaultWorld() = 0;
|
||||
//! Returns a handle to the Default Scene managed by a relevant system.
|
||||
virtual AzPhysics::SceneHandle GetDefaultSceneHandle() const = 0;
|
||||
};
|
||||
|
||||
typedef AZ::EBus<DefaultWorldRequests> DefaultWorldBus;
|
||||
@@ -108,8 +106,8 @@ namespace Physics
|
||||
public:
|
||||
using MutexType = AZStd::mutex;
|
||||
|
||||
/// Returns the Editor world managed editor system component.
|
||||
virtual AZStd::shared_ptr<World> GetEditorWorld() = 0;
|
||||
//! Returns a handle to the Editor Scene managed by editor system component.
|
||||
virtual AzPhysics::SceneHandle GetEditorSceneHandle() const = 0;
|
||||
};
|
||||
using EditorWorldBus = AZ::EBus<EditorWorldRequests>;
|
||||
|
||||
@@ -142,8 +140,6 @@ namespace Physics
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// General Physics
|
||||
|
||||
virtual AZStd::unique_ptr<RigidBodyStatic> CreateStaticRigidBody(const WorldBodyConfiguration& configuration) = 0;
|
||||
virtual AZStd::unique_ptr<RigidBody> CreateRigidBody(const RigidBodyConfiguration& configuration) = 0;
|
||||
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
|
||||
|
||||
/// Adds an appropriate collider component to the entity based on the provided shape configuration.
|
||||
@@ -177,7 +173,7 @@ namespace Physics
|
||||
virtual AZStd::vector<AZ::TypeId> GetSupportedJointTypes() = 0;
|
||||
virtual AZStd::shared_ptr<JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType) = 0;
|
||||
virtual AZStd::shared_ptr<Joint> CreateJoint(const AZStd::shared_ptr<JointLimitConfiguration>& configuration,
|
||||
Physics::WorldBody* parentBody, Physics::WorldBody* childBody) = 0;
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody) = 0;
|
||||
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
|
||||
/// @param configuration The joint configuration to generate visualization data for.
|
||||
/// @param parentRotation The rotation of the joint's parent body (in the same frame as childRotation).
|
||||
@@ -272,11 +268,7 @@ namespace Physics
|
||||
/// Creates the physics representation used to handle basic character interactions (also known as a character
|
||||
/// controller).
|
||||
virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig,
|
||||
const ShapeConfiguration& shapeConfig, World& world) = 0;
|
||||
|
||||
/// Performs any updates related to character controllers which are per-world and not per-character, such as
|
||||
/// computing character-character interactions.
|
||||
virtual void UpdateCharacters(World& world, float deltaTime) = 0;
|
||||
const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0;
|
||||
};
|
||||
|
||||
typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus;
|
||||
@@ -301,16 +293,4 @@ namespace Physics
|
||||
|
||||
typedef AZ::EBus<SystemDebugRequests> SystemDebugRequestBus;
|
||||
|
||||
class SystemNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
virtual ~SystemNotifications() {}
|
||||
|
||||
virtual void OnWorldCreated(World* /*world*/) {};
|
||||
virtual void OnPreWorldDestroy(World* /*world*/) {};
|
||||
};
|
||||
|
||||
using SystemNotificationBus = AZ::EBus<SystemNotifications>;
|
||||
|
||||
} // namespace Physics
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user