Merge branch 'main' into SpawnablePriorityQueue

This commit is contained in:
AMZN-koppersr
2021-06-01 09:57:27 -07:00
581 changed files with 13617 additions and 12612 deletions
@@ -406,21 +406,10 @@ namespace AzFramework
return m_localTM.GetRotation();
}
void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
{
AZ::Transform newLocalTM = m_localTM;
newLocalTM.SetScale(scale);
SetLocalTM(newLocalTM);
}
AZ::Vector3 TransformComponent::GetLocalScale()
{
return m_localTM.GetScale();
}
AZ::Vector3 TransformComponent::GetWorldScale()
{
return m_worldTM.GetScale();
AZ_WarningOnce("TransformComponent", false, "GetLocalScale is deprecated, please use GetLocalUniformScale instead");
return AZ::Vector3(m_localTM.GetUniformScale());
}
void TransformComponent::SetLocalUniformScale(float scale)
@@ -756,11 +745,11 @@ namespace AzFramework
->Event("GetLocalRotationQuaternion", &AZ::TransformBus::Events::GetLocalRotationQuaternion)
->Attribute("Rotation", AZ::Edit::Attributes::PropertyRotation)
->VirtualProperty("Rotation", "GetLocalRotationQuaternion", "SetLocalRotationQuaternion")
->Event("SetLocalScale", &AZ::TransformBus::Events::SetLocalScale)
->Event("GetLocalScale", &AZ::TransformBus::Events::GetLocalScale)
->Attribute("Scale", AZ::Edit::Attributes::PropertyScale)
->VirtualProperty("Scale", "GetLocalScale", "SetLocalScale")
->Event("GetWorldScale", &AZ::TransformBus::Events::GetWorldScale)
->Event("SetLocalUniformScale", &AZ::TransformBus::Events::SetLocalUniformScale)
->Event("GetLocalUniformScale", &AZ::TransformBus::Events::GetLocalUniformScale)
->VirtualProperty("Uniform Scale", "GetLocalUniformScale", "SetLocalUniformScale")
->Event("GetChildren", &AZ::TransformBus::Events::GetChildren)
->Event("GetAllDescendants", &AZ::TransformBus::Events::GetAllDescendants)
->Event("GetEntityAndAllDescendants", &AZ::TransformBus::Events::GetEntityAndAllDescendants)
@@ -128,9 +128,7 @@ namespace AzFramework
AZ::Quaternion GetLocalRotationQuaternion() override;
// Scale Modifiers
void SetLocalScale(const AZ::Vector3& scale) override;
AZ::Vector3 GetLocalScale() override;
AZ::Vector3 GetWorldScale() override;
void SetLocalUniformScale(float scale) override;
float GetLocalUniformScale() override;
@@ -259,11 +259,18 @@ namespace Physics
if (success)
{
success = success && dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
success = success && (dataElement.FindElement(AZ_CRC("MaterialId", 0x9360e002)) < 0);
success = success && dataElement.AddElementWithData(context, "MaterialIds", AZStd::vector<Physics::MaterialId> { materialId });
}
}
if (success && dataElement.GetVersion() <= 2)
{
dataElement.RemoveElementByName(AZ_CRC_CE("Material"));
success = success && (dataElement.FindElement(AZ_CRC_CE("Material")) < 0);
}
return success;
}
} // namespace ClassConverters
@@ -58,9 +58,18 @@ namespace AzPhysics
//! 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.
//! Event that triggers when the 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&>;
using OnMaterialLibraryChangedEvent = AZ::Event<const AZ::Data::AssetId&>;
enum class MaterialLibraryLoadErrorType : uint8_t
{
InvalidId,
ErrorLoading
};
//! Event that triggers when the default material library has loaded with errors.
using OnMaterialLibraryLoadErrorEvent = AZ::Event<MaterialLibraryLoadErrorType>;
//! Event that triggers when the default scene configuration changes.
//! When triggered the event will send the new default scene configuration.
@@ -18,6 +18,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/limits.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
@@ -68,6 +69,22 @@ namespace AzPhysics
return m_customUserData;
}
//! Helper functions for setting frame ID.
//! @param frameId Optionally set frame ID for the systems moving the actors back in time.
void SetFrameId(uint32_t frameId)
{
m_frameId = frameId;
}
//! Helper functions for getting the set frame ID.
//! @return Will return the frame ID.
uint32_t GetFrameId() const
{
return m_frameId;
}
static constexpr uint32_t UndefinedFrameId = AZStd::numeric_limits<uint32_t>::max();
//! 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.
@@ -126,6 +143,7 @@ namespace AzPhysics
SimulatedBodyEvents::OnTriggerExit m_triggerExitEvent;
void* m_customUserData = nullptr;
uint32_t m_frameId = UndefinedFrameId;
// helpers for reflecting to behavior context
SimulatedBodyEvents::OnCollisionBegin* GetOnCollisionBeginEvent();
@@ -39,6 +39,8 @@ namespace AzPhysics
->Field("ShapecastBufferSize", &SystemConfiguration::m_shapecastBufferSize)
->Field("OverlapBufferSize", &SystemConfiguration::m_overlapBufferSize)
->Field("CollisionConfig", &SystemConfiguration::m_collisionConfig)
->Field("DefaultMaterial", &SystemConfiguration::m_defaultMaterialConfiguration)
->Field("MaterialLibrary", &SystemConfiguration::m_materialLibraryAsset)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -79,7 +81,9 @@ namespace AzPhysics
m_overlapBufferSize == other.m_overlapBufferSize &&
AZ::IsClose(m_maxTimestep, other.m_maxTimestep) &&
AZ::IsClose(m_fixedTimestep, other.m_fixedTimestep) &&
m_collisionConfig == other.m_collisionConfig
m_collisionConfig == other.m_collisionConfig &&
m_defaultMaterialConfiguration == other.m_defaultMaterialConfiguration &&
m_materialLibraryAsset == other.m_materialLibraryAsset
;
}
@@ -13,6 +13,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
#include <AzFramework/Physics/Material.h>
namespace AZ
{
@@ -45,6 +46,9 @@ namespace AzPhysics
//! Each Physics Scene uses this as a base and will override as needed.
CollisionConfiguration m_collisionConfig;
Physics::MaterialConfiguration m_defaultMaterialConfiguration; //!< Default material parameters for the project.
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibraryAsset = AZ::Data::AssetLoadBehavior::NoLoad; //!< Material Library exposed by the system component SystemBus API.
//! Controls whether the Physics System will self register to the TickBus and call StartSimulation / FinishSimulation on each Scene.
//! Disable this to manually control Physics Scene simulation logic.
bool m_autoManageSimulationUpdate = true;
@@ -49,10 +49,7 @@ namespace Physics
{
materialSelection->SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
}
if (materialSelection->IsDefaultMaterialLibraryAsset())
{
materialSelection->SyncSelectionToMaterialLibrary();
}
materialSelection->SyncSelectionToMaterialLibrary();
}
};
@@ -122,6 +119,24 @@ namespace Physics
}
}
bool MaterialConfiguration::operator==(const MaterialConfiguration& other) const
{
return m_surfaceType == other.m_surfaceType &&
AZ::IsClose(m_dynamicFriction, other.m_dynamicFriction) &&
AZ::IsClose(m_staticFriction, other.m_staticFriction) &&
AZ::IsClose(m_restitution, other.m_restitution) &&
AZ::IsClose(m_density, other.m_density) &&
m_restitutionCombine == other.m_restitutionCombine &&
m_frictionCombine == other.m_frictionCombine &&
m_debugColor == other.m_debugColor
;
}
bool MaterialConfiguration::operator!=(const MaterialConfiguration& other) const
{
return !(*this == other);
}
AZ::Color MaterialConfiguration::GenerateDebugColor(const char* materialName)
{
static const AZ::Color colors[] =
@@ -191,51 +206,25 @@ namespace Physics
//////////////////////////////////////////////////////////////////////////
void MaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>()
->Version(1)
->Field("Asset", &MaterialLibraryAssetReflectionWrapper::m_asset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>("", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialLibraryAssetReflectionWrapper::m_asset, "Physics Material Library", "Physics Material Library")
->Attribute("EditButton", "")
;
}
}
}
//////////////////////////////////////////////////////////////////////////
void DefaultMaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
void MaterialInfoReflectionWrapper::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>()
serializeContext->Class<Physics::MaterialInfoReflectionWrapper>()
->Version(1)
->Field("Asset", &DefaultMaterialLibraryAssetReflectionWrapper::m_asset)
->Field("DefaultMaterial", &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration)
->Field("Asset", &MaterialInfoReflectionWrapper::m_materialLibraryAsset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>("", "")
editContext->Class<Physics::MaterialInfoReflectionWrapper>("Physics Materials", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &DefaultMaterialLibraryAssetReflectionWrapper::m_asset, "Default Physics Material Library", "Library to use by default")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration, "Default Physics Material", "Material used by default")
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_materialLibraryAsset, "Physics Material Library", "Library to use for the project")
->Attribute(AZ::Edit::Attributes::AllowClearAsset, false)
->Attribute("EditButton", "")
;
@@ -269,6 +258,17 @@ namespace Physics
}
}
bool MaterialFromAssetConfiguration::operator==(const MaterialFromAssetConfiguration& other) const
{
return m_configuration == other.m_configuration &&
m_id == other.m_id;
}
bool MaterialFromAssetConfiguration::operator!=(const MaterialFromAssetConfiguration& other) const
{
return !(*this == other);
}
//////////////////////////////////////////////////////////////////////////
bool MaterialLibraryAsset::GetDataForMaterialId(const MaterialId& materialId, MaterialFromAssetConfiguration& configuration) const
@@ -370,9 +370,8 @@ namespace Physics
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<Physics::MaterialSelection>()
->Version(2, &ClassConverters::MaterialSelectionConverter)
->Version(3, &ClassConverters::MaterialSelectionConverter)
->EventHandler<MaterialSelectionEventHandler>()
->Field("Material", &MaterialSelection::m_materialLibrary)
->Field("MaterialIds", &MaterialSelection::m_materialIdsAssignedToSlots)
;
@@ -381,14 +380,8 @@ namespace Physics
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")
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
->Attribute("EditButton", "")
->Attribute("EditDescription", "Open in Asset Editor")
->Attribute(AZ::Edit::Attributes::DefaultAsset, &MaterialSelection::GetDefaultMaterialLibraryId)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &MaterialSelection::OnMaterialLibraryChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialIdsAssignedToSlots, "Mesh Surfaces", "Specify which Physics Material to use for each element of this object")
->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryAssetId)
->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryId)
->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &MaterialSelection::GetMaterialSlotLabel)
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->ElementAttribute(AZ::Edit::Attributes::ReadOnly, &MaterialSelection::AreMaterialSlotsReadOnly)
@@ -398,12 +391,6 @@ namespace Physics
}
}
AZ::u32 MaterialSelection::OnMaterialLibraryChanged()
{
SyncSelectionToMaterialLibrary();
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
AZStd::string MaterialSelection::GetMaterialSlotLabel(int index)
{
if (index < m_materialSlots.size())
@@ -425,28 +412,9 @@ namespace Physics
}
}
AZ::Data::AssetId MaterialSelection::GetMaterialLibraryAssetId() const
void MaterialSelection::OnMaterialLibraryChanged([[maybe_unused]] const AZ::Data::AssetId& defaultMaterialLibraryId)
{
return GetMaterialLibraryAsset().GetId();
}
const Physics::MaterialLibraryAsset* MaterialSelection::GetMaterialLibraryAssetData() const
{
return GetMaterialLibraryAsset().Get();
}
const AZStd::string& MaterialSelection::GetMaterialLibraryAssetHint() const
{
return m_materialLibrary.GetHint();
}
void MaterialSelection::OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId)
{
AZ_UNUSED(defaultMaterialLibraryId);
if (IsDefaultMaterialLibraryAsset())
{
OnMaterialLibraryChanged();
}
SyncSelectionToMaterialLibrary();
}
void MaterialSelection::SetSlotsReadOnly(bool readOnly)
@@ -454,45 +422,6 @@ namespace Physics
m_slotsReadOnly = readOnly;
}
bool MaterialSelection::IsMaterialLibraryValid() const
{
if (GetMaterialLibraryAssetId().IsValid())
{
auto materialAsset = LoadAsset();
const auto& materialsData = materialAsset.Get()->GetMaterialsData();
if (materialsData.size() != 0)
{
return true;
}
}
return false;
}
bool MaterialSelection::GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const
{
if (IsMaterialLibraryValid())
{
auto materialAsset = LoadAsset();
if (materialAsset.Get())
{
return materialAsset.Get()->GetDataForMaterialId(materialId, configuration);
}
}
return false;
}
void MaterialSelection::SetMaterialLibrary(const AZ::Data::AssetId& assetId)
{
m_materialLibrary = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(assetId, m_materialLibrary.GetAutoLoadBehavior());
m_materialLibrary.BlockUntilLoadComplete();
}
void MaterialSelection::ResetToDefaultMaterialLibrary()
{
m_materialLibrary = {};
}
void MaterialSelection::SetMaterialSlots(const SlotsArray& slots)
{
if (slots.empty())
@@ -533,74 +462,45 @@ namespace Physics
m_materialIdsAssignedToSlots[slotIndex] = materialId;
}
AZ::Data::Asset<Physics::MaterialLibraryAsset> MaterialSelection::LoadAsset() const
{
AZ::Data::Asset<MaterialLibraryAsset> asset = AZ::Data::AssetManager::Instance()
.GetAsset<Physics::MaterialLibraryAsset>(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
return asset;
}
void MaterialSelection::SyncSelectionToMaterialLibrary()
{
if (GetMaterialLibraryAssetId().IsValid())
auto* materialLibrary = GetMaterialLibrary().Get();
if (!materialLibrary)
{
auto materialLibraryAsset = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
return;
}
materialLibraryAsset.BlockUntilLoadComplete();
// We try to check whether existing selection matches any materials in the newly assigned library and do one of the following:
// 1. If previous MaterialId is invalid for this material library, and it is not the Default material, we set it to the Default material from the library.
// 2. If it's valid, or it is the Default material, we don't change it (useful when user accidentally re-assigns the same library: previous selection won't go away).
if (materialLibraryAsset.Get())
for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
{
// Leave nulls (default) unchanged.
if (materialId.IsNull())
{
for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
{
if (!materialLibraryAsset.Get()->HasDataForMaterialId(materialId)
&& !materialId.IsNull()) // Null materialId is the Default material.
{
materialId = MaterialId();
}
}
continue;
}
else
// If the material id is not present in the library anymore, set it to default
if (!materialLibrary->HasDataForMaterialId(materialId))
{
AZ_Warning("PhysX", false, "MaterialSelection: invalid material library");
materialId = MaterialId();
}
}
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibraryAsset() const
{
if (IsDefaultMaterialLibraryAsset())
{
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& defaultMaterialLibrary = GetDefaultMaterialLibrary();
return defaultMaterialLibrary;
}
return m_materialLibrary;
}
bool MaterialSelection::IsDefaultMaterialLibraryAsset() const
{
return !m_materialLibrary.GetId().IsValid();
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetDefaultMaterialLibrary()
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibrary()
{
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
return physicsSystem->GetDefaultMaterialLibrary();
if (const auto* physicsConfiguration = physicsSystem->GetConfiguration())
{
return physicsConfiguration->m_materialLibraryAsset;
}
}
return s_invalidMaterialLibrary;
}
const AZ::Data::AssetId& MaterialSelection::GetDefaultMaterialLibraryId()
const AZ::Data::AssetId& MaterialSelection::GetMaterialLibraryId()
{
return GetDefaultMaterialLibrary().GetId();
return GetMaterialLibrary().GetId();
}
bool MaterialSelection::AreMaterialSlotsReadOnly() const
@@ -29,7 +29,6 @@ namespace Physics
/// =========================
/// This is the interface to the wrapper around native material type (such as PxMaterial in PhysX gem)
/// that stores extra metadata, like Surface Type name.
/// To see more details about PhysX implementation please refer to PhysX::Material class
///
/// Usage example
/// -------------------------
@@ -37,14 +36,7 @@ namespace Physics
///
/// Physics::MaterialConfiguration materialProperties;
/// AZStd::shared_ptr<Physics::Material> newMaterial = AZ::Interface<Physics::System>::Get()->CreateMaterial(materialProperties);
///
/// To get PxMaterial use GetNativePointer function
///
/// physx::PxMaterial* material = static_cast<physx::PxMaterial*>(newMaterial->GetNativePointer());
///
/// You can use retrieved PxMaterial pointer on its own, provided you increment its reference count.
/// If this class goes out of scope, the PxMaterial pointer will be valid, but its userData
/// will be cleaned up to point to nullptr.
///
class Material
{
public:
@@ -63,9 +55,9 @@ namespace Physics
/// Returns AZ::Crc32 of the surface name.
virtual AZ::Crc32 GetSurfaceType() const = 0;
virtual void SetSurfaceType(AZ::Crc32 surfaceType) = 0;
virtual const AZStd::string& GetSurfaceTypeName() const = 0;
virtual void SetSurfaceTypeName(const AZStd::string& surfaceTypeName) = 0;
virtual float GetDynamicFriction() const = 0;
virtual void SetDynamicFriction(float dynamicFriction) = 0;
@@ -85,6 +77,9 @@ namespace Physics
virtual float GetDensity() const = 0;
virtual void SetDensity(float density) = 0;
virtual AZ::Color GetDebugColor() const = 0;
virtual void SetDebugColor(const AZ::Color& debugColor) = 0;
/// If the name of this material matches the name of one of the CrySurface types, it will return its CrySurface Id.\n
/// If there's no match it will return default CrySurface Id.\n
/// CrySurface types are defined in libs/materialeffects/surfacetypes.xml
@@ -122,6 +117,10 @@ namespace Physics
Material::CombineMode m_frictionCombine = Material::CombineMode::Average;
AZ::Color m_debugColor = AZ::Colors::White;
bool operator==(const MaterialConfiguration& other) const;
bool operator!=(const MaterialConfiguration& other) const;
private:
static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
static AZ::Color GenerateDebugColor(const char* materialName);
@@ -147,6 +146,7 @@ namespace Physics
static MaterialId FromUUID(const AZ::Uuid& uuid);
bool IsNull() const { return m_id.IsNull(); }
bool operator==(const MaterialId& other) const { return m_id == other.m_id; }
bool operator!=(const MaterialId& other) const { return !(*this == other); }
const AZ::Uuid& GetUuid() const { return m_id; }
private:
@@ -166,6 +166,9 @@ namespace Physics
MaterialConfiguration m_configuration;
MaterialId m_id;
bool operator==(const MaterialFromAssetConfiguration& other) const;
bool operator!=(const MaterialFromAssetConfiguration& other) const;
};
/// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor
@@ -222,40 +225,27 @@ namespace Physics
AZStd::vector<MaterialFromAssetConfiguration> m_materialLibrary;
};
/// The class is used to expose a MaterialLibraryAsset to Edit Context
/// The class is used to expose a default material and material library asset to Edit Context
/// =======================================================================
///
/// Since AZ::Data::Asset doesn't reflect the data to EditContext
/// we have to have a wrapper doing it.
class MaterialLibraryAssetReflectionWrapper
class MaterialInfoReflectionWrapper
{
public:
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::MaterialLibraryAssetReflectionWrapper, "{3D2EF5DF-EFD0-47EB-B88F-3E6FE1FEE5B0}");
AZ_CLASS_ALLOCATOR(MaterialInfoReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::MaterialInfoReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
static void Reflect(AZ::ReflectContext* context);
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
Physics::MaterialConfiguration m_defaultMaterialConfiguration;
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibraryAsset =
AZ::Data::AssetLoadBehavior::NoLoad;
};
/// Customized material library for use as default material library
class DefaultMaterialLibraryAssetReflectionWrapper : public Physics::MaterialLibraryAssetReflectionWrapper
{
public:
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::DefaultMaterialLibraryAssetReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
static void Reflect(AZ::ReflectContext* context);
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
AZ::Data::AssetLoadBehavior::NoLoad;
};
/// The class is used to store a MaterialLibraryAsset and a vector of MaterialIds selected from the library
/// The class is used to store a vector of MaterialIds selected from the library
/// =======================================================================
///
/// This class is used to store a reference to the library asset and user's
/// selection of the materials from this library.\n
/// It also reflects UI controls for assigning MaterialLibraryAsset and selecting a material from it.
/// This class is used to store the user's selection of the materials from this library.
/// You can reflect this class in EditorContext to provide UI for selecting materials
/// on any custom component or QWidget.
class MaterialSelection
@@ -269,27 +259,6 @@ namespace Physics
static void Reflect(AZ::ReflectContext* context);
/// Returns whether MaterialLibraryAsset assigned to this selection exists and valid. Attempts to load
/// the library if it's not loaded yet.
/// @return true if MaterialLibraryAsset has a valid AssetId, loaded and isn't empty
bool IsMaterialLibraryValid() const;
/// Looks up MaterialLibraryAsset for MaterialFromAssetConfiguration with MaterialId that is stored intrenally.
/// @param configuration contains material data if there is a material selected by user
/// and if it exists in the MaterialLibraryAsset
/// @param materialId MaterialId to retrieve MaterialFromAssetConfiguration for
/// @return true if lookup was successful.
bool GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const;
/// Sets and loads MaterialLibraryAsset with specified AssetId.
/// It is used to construct MaterialSelection at runtime.
/// It is not a typical use case and mostly needed to convert legacy entities and auto-generate material libraries
/// @param assetId AssetId to create MaterialLibraryAsset with
void SetMaterialLibrary(const AZ::Data::AssetId& assetId);
/// Sets the material library to none, this will cause to use the project-wide default material library
void ResetToDefaultMaterialLibrary();
/// Sets an array of material slots to pick MaterialIds for. Having multiple slots is required for assigning multiple materials on a mesh
/// or heightfield object. SlotsArray can be empty and in this case Default slot will be created.
/// @param slots Array of names for slots. Can be empty, in this case Default slot will be created
@@ -298,48 +267,34 @@ namespace Physics
/// Returns a list of MaterialId that were assigned for each corresponding slot.
const AZStd::vector<Physics::MaterialId>& GetMaterialIdsAssignedToSlots() const;
/// Sets the MaterialId from MaterialLibraryAsset as the selected material at a specific slotIndex.
/// @param materialId MaterialId that user selected from the MaterialLibraryAsset
/// @param slotIndex index of the slot to set MaterialId for
/// Sets the MaterialId as the selected material at a specific slotIndex.
/// @param materialId MaterialId that user selected
/// @param slotIndex Index of the slot to set the MaterialId
void SetMaterialId(const Physics::MaterialId& materialId, int slotIndex = 0);
/// Returns the material library asset id.
AZ::Data::AssetId GetMaterialLibraryAssetId() const;
/// Returns the material id assigned to this selection at a specific slotIndex.
/// @param slotIndex index of the slot to retrieve MaterialId for
/// @param slotIndex Index of the slot to retrieve the MaterialId
Physics::MaterialId GetMaterialId(int slotIndex = 0) const;
/// Returns the material library asset.
const Physics::MaterialLibraryAsset* GetMaterialLibraryAssetData() const;
/// Returns the material library asset hint(UI display string)
const AZStd::string& GetMaterialLibraryAssetHint() const;
/// Called when the material library has changed
void OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
void OnMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
/// Set if the material slots are editable in the edit context
void SetSlotsReadOnly(bool readOnly);
private:
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibrary { AZ::Data::AssetLoadBehavior::NoLoad };
AZStd::vector<Physics::MaterialId> m_materialIdsAssignedToSlots;
SlotsArray m_materialSlots;
bool m_slotsReadOnly = false;
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibraryAsset() const;
AZ::Data::Asset<Physics::MaterialLibraryAsset> LoadAsset() const;
bool IsDefaultMaterialLibraryAsset() const;
void SyncSelectionToMaterialLibrary();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary();
static const AZ::Data::AssetId& GetDefaultMaterialLibraryId();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibrary();
static const AZ::Data::AssetId& GetMaterialLibraryId();
bool AreMaterialSlotsReadOnly() const;
// EditorContext callbacks
AZ::u32 OnMaterialLibraryChanged();
AZStd::string GetMaterialSlotLabel(int index);
};
@@ -25,21 +25,26 @@ namespace Physics
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // Implemented by sole owner of materials, e.g. class MaterialManager in PhysX gem.
/// Get default material
/// Get default material.
virtual AZStd::shared_ptr<Physics::Material> GetGenericDefaultMaterial() = 0;
/// Returns weak pointers to physics materials.
/// Connect to PhysicsMaterialNotifications::MaterialsReleased to be informed when material pointers are deleted by owner.
virtual void GetMaterials(const MaterialSelection& materialSelection
, AZStd::vector<AZStd::weak_ptr<Physics::Material>>& outMaterials) = 0;
, AZStd::vector<AZStd::shared_ptr<Physics::Material>>& outMaterials) = 0;
/// Returns a weak pointer to physics material with the given id.
virtual AZStd::shared_ptr<Physics::Material> GetMaterialById(Physics::MaterialId id) = 0;
/// Returns a weak pointer to physics material with the given name.
virtual AZStd::weak_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) = 0;
virtual AZStd::shared_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) = 0;
/// Returns index of the first selected material in MaterialSelection's material library.
/// A MaterialSelection can contain multiple material selections.
/// Returned index is 0-based where 0 is the Default material, and materials from the material library are 1 and onwards.
virtual AZ::u32 GetFirstSelectedMaterialIndex(const MaterialSelection& materialSelection) = 0;
/// Updates the material selection from the physics asset or sets it to default if there's no asset provided.
/// @param shapeConfiguration The shape information that contains the physics asset.
/// @param materialSelection The material selection to update.
virtual void UpdateMaterialSelectionFromPhysicsAsset(
const ShapeConfiguration& shapeConfiguration,
MaterialSelection& materialSelection) = 0;
};
using PhysicsMaterialRequestBus = AZ::EBus<PhysicsMaterialRequests>;
@@ -130,13 +130,6 @@ namespace AzPhysics
//! @param forceReinitialization Flag to force a reinitialization of the physics system. Default false.
virtual void UpdateConfiguration(const SystemConfiguration* newConfig, bool forceReinitialization = false) = 0;
//! Update the default material library.
//! @param materialLibrary The new material library asset to use.
virtual void UpdateDefaultMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary) = 0;
//! Accessor to get the current Material Library. This is also available in the PhysXSystemConfiguration.
virtual const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary() const = 0;
//! Update the current default scene configuration.
//! This is the configuration used to to create scenes without a custom configuration.
//! @param sceneConfiguration The new configuration to apply.
@@ -169,9 +162,12 @@ namespace AzPhysics
//! 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); }
//! Register a handler to receive an event when the default material library changes.
//! Register a handler to receive an event when the material library changes.
//! @param handler The handler to receive the event.
void RegisterOnDefaultMaterialLibraryChangedEventHandler(SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onDefaultMaterialLibraryChangedEvent); }
void RegisterOnMaterialLibraryChangedEventHandler(SystemEvents::OnMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryChangedEvent); }
//! Register a handler to receive an event when the material library fails to load on startup.
//! @param handler The handler to receive the event.
void RegisterOnMaterialLibraryLoadErrorEventHandler(SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryLoadErrorEvent); }
//! Register a handler to receive an event when the default SceneConfiguration changes.
//! @param handler The handler to receive the event.
void RegisterOnDefaultSceneConfigurationChangedEventHandler(SystemEvents::OnDefaultSceneConfigurationChangedEvent::Handler& handler) { handler.Connect(m_onDefaultSceneConfigurationChangedEvent); }
@@ -185,7 +181,8 @@ namespace AzPhysics
SystemEvents::OnSceneAddedEvent m_sceneAddedEvent;
SystemEvents::OnSceneRemovedEvent m_sceneRemovedEvent;
SystemEvents::OnConfigurationChangedEvent m_configChangeEvent;
SystemEvents::OnDefaultMaterialLibraryChangedEvent m_onDefaultMaterialLibraryChangedEvent;
SystemEvents::OnMaterialLibraryChangedEvent m_onMaterialLibraryChangedEvent;
SystemEvents::OnMaterialLibraryLoadErrorEvent m_onMaterialLibraryLoadErrorEvent;
SystemEvents::OnDefaultSceneConfigurationChangedEvent m_onDefaultSceneConfigurationChangedEvent;
};
} // namespace AzPhysics
@@ -17,6 +17,21 @@
namespace Physics
{
namespace Internal
{
bool ShapeConfigurationVersionConverter(
[[maybe_unused]] AZ::SerializeContext& context,
AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() <= 1)
{
classElement.RemoveElementByName(AZ_CRC_CE("UseMaterialsFromAsset"));
}
return true;
}
}
void ShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
@@ -166,10 +181,9 @@ namespace Physics
->RegisterGenericType<AZStd::shared_ptr<PhysicsAssetShapeConfiguration>>();
serializeContext->Class<PhysicsAssetShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Version(2, &Internal::ShapeConfigurationVersionConverter)
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
@@ -182,7 +196,6 @@ namespace Physics
->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_assetScale, "Asset Scale", "The scale of the asset shape")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset, "Physics Materials from Mesh", "Auto-set physics materials using Mesh's material surfaces names")
;
}
}
@@ -140,7 +140,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
bool m_useMaterialsFromAsset = true;
bool m_useMaterialsFromAsset = false; // Not reflected or exposed to the user until there is a way to auto-match mesh's materials with physics materials
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
@@ -142,24 +142,12 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
//////////////////////////////////////////////////////////////////////////
//// Physics Materials
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
virtual AZStd::shared_ptr<Material> GetDefaultMaterial() = 0;
virtual AZStd::vector<AZStd::shared_ptr<Material>> CreateMaterialsFromLibrary(const Physics::MaterialSelection& materialSelection) = 0;
/// Updates the collider material selection from the physics asset or sets it to default if there's no asset provided.
/// @param shapeConfiguration The shape information
/// @param colliderConfiguration The collider information
virtual bool UpdateMaterialSelection(const Physics::ShapeConfiguration& shapeConfiguration,
Physics::ColliderConfiguration& colliderConfiguration) = 0;
//////////////////////////////////////////////////////////////////////////
//// Joints
@@ -119,8 +119,7 @@ namespace Physics
AzPhysics::SceneConfiguration::Reflect(context);
MaterialConfiguration::Reflect(context);
MaterialLibraryAsset::Reflect(context);
MaterialLibraryAssetReflectionWrapper::Reflect(context);
DefaultMaterialLibraryAssetReflectionWrapper::Reflect(context);
MaterialInfoReflectionWrapper::Reflect(context);
JointLimitConfiguration::Reflect(context);
AzPhysics::SimulatedBodyConfiguration::Reflect(context);
AzPhysics::RigidBodyConfiguration::Reflect(context);
@@ -12,6 +12,7 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzFramework/Entity/EntityContextBus.h>
#include <AzFramework/Render/GeometryIntersectionStructures.h>
namespace AzFramework
@@ -35,12 +36,12 @@ namespace AzFramework
AzFramework::EntityContextId m_contextId;
};
//! Interface for intersection requests, implement this interface for making your component
//! render geometry intersectable.
//! Interface for intersection requests.
//! Implement this interface to make your component 'intersectable'.
class IntersectionRequests
: public AZ::EBusTraits
{
//! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus
//! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus
//! so it updates the internal data of the entities
template<class Bus>
struct IntersectionRequestsConnectionPolicy
@@ -10,6 +10,7 @@
*
*/
#include <AzCore/Casting/lossy_cast.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/std/string/string.h>
#include <AzFramework/Spawnable/Spawnable.h>
@@ -88,4 +89,10 @@ namespace AzFramework
{
extensions.push_back(Spawnable::FileExtension);
}
uint32_t SpawnableAssetHandler::BuildSubId(AZStd::string_view id)
{
AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size());
return azlossy_caster(subIdHash.GetHash());
}
} // namespace AzFramework
@@ -47,6 +47,7 @@ namespace AzFramework
const char* GetGroup() const override;
const char* GetBrowserIcon() const override;
void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
static uint32_t BuildSubId(AZStd::string_view id);
protected:
LoadResult LoadAssetData(
@@ -29,7 +29,7 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 6.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -37,7 +37,6 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -144,7 +143,7 @@ namespace AzFramework
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
}
return {x, y, z};
return { x, y, z };
}
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
@@ -179,7 +178,7 @@ namespace AzFramework
{
const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime);
m_motionDelta = ScreenVector{0, 0};
m_motionDelta = ScreenVector{ 0, 0 };
m_scrollDelta = 0.0f;
return nextCamera;
@@ -213,7 +212,10 @@ namespace AzFramework
auto& cameraInput = m_idleCameraInputs[i];
const bool canBegin = cameraInput->Beginning() &&
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
[](const auto& input) { return !input->Exclusive(); }) &&
[](const auto& input)
{
return !input->Exclusive();
}) &&
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
if (canBegin)
@@ -231,7 +233,8 @@ namespace AzFramework
const Camera nextCamera = AZStd::accumulate(
AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera,
[cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) {
[cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera)
{
acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime);
return acc;
});
@@ -284,7 +287,8 @@ namespace AzFramework
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
const ClickDetector::ClickEvent clickEvent = [&event, this] {
const ClickDetector::ClickEvent clickEvent = [&event, this]
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == m_rotateChannelId)
@@ -330,7 +334,10 @@ namespace AzFramework
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
const auto clampRotation = [](const float angle)
{
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
};
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
// clamp pitch to be +-90 degrees
@@ -377,9 +384,10 @@ namespace AzFramework
const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed;
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed;
const auto inv = [](const bool invert) {
constexpr float Dir[] = {1.0f, -1.0f};
return Dir[static_cast<int>(invert)];
const auto inv = [](const bool invert)
{
constexpr float Dir[] = { 1.0f, -1.0f };
return Dir[aznumeric_cast<int>(invert)];
};
nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX);
@@ -475,7 +483,8 @@ namespace AzFramework
const auto axisY = translationBasis.GetBasisY();
const auto axisZ = translationBasis.GetBasisZ();
const float speed = [boost = m_boost]() {
const float speed = [boost = m_boost]()
{
return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f);
}();
@@ -555,10 +564,12 @@ namespace AzFramework
if (Beginning())
{
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] {
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn]
{
if (lookAtFn)
{
if (const auto lookAt = lookAtFn())
// pass through the camera's position and look vector for use in the lookAt function
if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
{
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
@@ -692,14 +703,20 @@ namespace AzFramework
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime)
{
const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
const auto clamp_rotation = [](const float angle)
{
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
};
// keep yaw in 0 - 360 range
float targetYaw = clamp_rotation(targetCamera.m_yaw);
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
// return the sign of the float input (-1, 0, 1)
const auto sign = [](const float value) { return aznumeric_cast<float>((0.0f < value) - (value < 0.0f)); };
const auto sign = [](const float value)
{
return aznumeric_cast<float>((0.0f < value) - (value < 0.0f));
};
// ensure smooth transition when moving across 0 - 360 boundary
const float yawDelta = targetYaw - currentYaw;
@@ -727,26 +744,28 @@ namespace AzFramework
const auto& inputChannelId = inputChannel.GetInputChannelId();
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
const bool wasMouseButton =
AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) {
const bool wasMouseButton = AZStd::any_of(
InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(),
[inputChannelId](const auto& button)
{
return button == inputChannelId;
});
if (inputChannelId == InputDeviceMouse::Movement::X)
{
return HorizontalMotionEvent{(int)inputChannel.GetValue()};
return HorizontalMotionEvent{ aznumeric_cast<int>(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Y)
{
return VerticalMotionEvent{(int)inputChannel.GetValue()};
return VerticalMotionEvent{ aznumeric_cast<int>(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
return ScrollEvent{inputChannel.GetValue()};
return ScrollEvent{ inputChannel.GetValue() };
}
else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
{
return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() };
}
return AZStd::monostate{};
@@ -34,9 +34,9 @@ namespace AzFramework
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
//!< or position of m_lookAt when m_lookDist is greater
//!< than zero.
float m_yaw{0.0};
float m_pitch{0.0};
float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
float m_yaw{ 0.0 };
float m_pitch{ 0.0 };
float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
//! View camera transform (v in MVP).
AZ::Transform View() const;
@@ -195,7 +195,11 @@ namespace AzFramework
inline bool Cameras::Exclusive() const
{
return AZStd::any_of(
m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); });
m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
[](const auto& cameraInput)
{
return cameraInput->Exclusive();
});
}
//! Responsible for updating a series of cameras given various inputs.
@@ -209,7 +213,7 @@ namespace AzFramework
private:
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
};
class RotateCameraInput : public CameraInput
@@ -237,7 +241,7 @@ namespace AzFramework
inline PanAxes LookPan(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
return {orientation.GetBasisX(), orientation.GetBasisZ()};
return { orientation.GetBasisX(), orientation.GetBasisZ() };
}
inline PanAxes OrbitPan(const Camera& camera)
@@ -245,12 +249,13 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
const auto basisY = [&orientation] {
const auto basisY = [&orientation]
{
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
return {basisX, basisY};
return { basisX, basisY };
}
class PanCameraInput : public CameraInput
@@ -285,7 +290,8 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
const auto basisY = [&orientation] {
const auto basisY = [&orientation]
{
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
@@ -398,7 +404,7 @@ namespace AzFramework
class OrbitCameraInput : public CameraInput
{
public:
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>()>;
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>(const AZ::Vector3& position, const AZ::Vector3& direction)>;
// CameraInput overrides ...
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;