606ba45cf2
- Avoid saving blast global configuration unnecessarily every time the editor is opened. - Fixed how to obtain the default physics material library. The relative path needs to be from the project folder, not the asset folder inside the project. It was also missing saving the physx configuration after a the default library is assigned to it. - Fixed asset id for physics material asset 'assets/physics/surfacetypemateriallibrary.physmaterial' Signed-off-by: moraaar moraaar@amazon.com
515 lines
21 KiB
C++
515 lines
21 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
#include <Source/SystemComponent.h>
|
|
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/std/smart_ptr/make_shared.h>
|
|
#include <PhysX/MeshAsset.h>
|
|
#include <PhysX/HeightFieldAsset.h>
|
|
#include <Source/Utils.h>
|
|
#include <Source/Collision.h>
|
|
#include <Source/Shape.h>
|
|
#include <Source/Pipeline/MeshAssetHandler.h>
|
|
#include <Source/Pipeline/HeightFieldAssetHandler.h>
|
|
#include <Source/PhysXCharacters/API/CharacterUtils.h>
|
|
#include <Source/PhysXCharacters/API/CharacterController.h>
|
|
#include <Source/WindProvider.h>
|
|
|
|
#include <PhysX/Debug/PhysXDebugInterface.h>
|
|
#include <System/PhysXSystem.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
bool SystemComponent::VersionConverter(AZ::SerializeContext& context,
|
|
AZ::SerializeContext::DataElementNode& classElement)
|
|
{
|
|
using GlobalCollisionDebugState = Debug::DebugDisplayData::GlobalCollisionDebugState;
|
|
|
|
if (classElement.GetVersion() <= 1)
|
|
{
|
|
const int pvdTransportTypeElemIndex = classElement.FindElement(AZ_CRC("PvdTransportType", 0x91e0b21e));
|
|
|
|
if (pvdTransportTypeElemIndex >= 0)
|
|
{
|
|
Debug::PvdTransportType pvdTransportTypeValue;
|
|
AZ::SerializeContext::DataElementNode& pvdTransportElement = classElement.GetSubElement(pvdTransportTypeElemIndex);
|
|
pvdTransportElement.GetData<Debug::PvdTransportType>(pvdTransportTypeValue);
|
|
|
|
if (pvdTransportTypeValue == static_cast<Debug::PvdTransportType>(2))
|
|
{
|
|
// version 2 removes Disabled (2) value default to Network instead.
|
|
const bool success = pvdTransportElement.SetData<Debug::PvdTransportType>(context, Debug::PvdTransportType::Network);
|
|
if (!success)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (classElement.GetVersion() <= 2)
|
|
{
|
|
const int globalColliderDebugDrawElemIndex = classElement.FindElement(AZ_CRC("GlobalColliderDebugDraw", 0xca73ed43));
|
|
|
|
if (globalColliderDebugDrawElemIndex >= 0)
|
|
{
|
|
bool oldGlobalColliderDebugDrawElemDebug = false;
|
|
AZ::SerializeContext::DataElementNode& globalColliderDebugDrawElem = classElement.GetSubElement(globalColliderDebugDrawElemIndex);
|
|
// Previously globalColliderDebugDraw was a bool indicating whether to always draw debug or to manually set on the element
|
|
if (!globalColliderDebugDrawElem.GetData<bool>(oldGlobalColliderDebugDrawElemDebug))
|
|
{
|
|
return false;
|
|
}
|
|
classElement.RemoveElement(globalColliderDebugDrawElemIndex);
|
|
const GlobalCollisionDebugState newValue = oldGlobalColliderDebugDrawElemDebug ? GlobalCollisionDebugState::AlwaysOn : GlobalCollisionDebugState::Manual;
|
|
classElement.AddElementWithData(context, "GlobalColliderDebugDraw", newValue);
|
|
}
|
|
}
|
|
|
|
if (classElement.GetVersion() <= 3)
|
|
{
|
|
classElement.AddElementWithData(context, "ShowJointHierarchy", true);
|
|
classElement.AddElementWithData(context, "JointHierarchyLeadColor",
|
|
Debug::DebugDisplayData::JointLeadColor::Aquamarine);
|
|
classElement.AddElementWithData(context, "JointHierarchyFollowerColor",
|
|
Debug::DebugDisplayData::JointFollowerColor::Magenta);
|
|
classElement.AddElementWithData(context, "jointHierarchyDistanceThreshold", 1.0f);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SystemComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
Pipeline::MeshAsset::Reflect(context);
|
|
|
|
PhysX::ReflectionUtils::ReflectPhysXOnlyApi(context);
|
|
|
|
if (auto* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serialize->Class<SystemComponent, AZ::Component>()
|
|
->Version(1)
|
|
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("AssetBuilder") }))
|
|
->Field("Enabled", &SystemComponent::m_enabled)
|
|
;
|
|
|
|
if (AZ::EditContext* editContext = serialize->GetEditContext())
|
|
{
|
|
editContext->Class<SystemComponent>("PhysX", "Global PhysX physics configuration")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::Category, "PhysX")
|
|
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &SystemComponent::m_enabled,
|
|
"Enabled", "Enables the PhysX system component.")
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
|
{
|
|
provided.push_back(AZ_CRC("PhysXService", 0x75beae2d));
|
|
}
|
|
|
|
void SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
|
{
|
|
incompatible.push_back(AZ_CRC("PhysXService", 0x75beae2d));
|
|
}
|
|
|
|
void SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
|
{
|
|
}
|
|
|
|
void SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
|
{
|
|
dependent.push_back(AZ_CRC_CE("AssetDatabaseService"));
|
|
dependent.push_back(AZ_CRC_CE("AssetCatalogService"));
|
|
}
|
|
|
|
SystemComponent::SystemComponent()
|
|
: m_enabled(true)
|
|
, m_onSystemInitializedHandler(
|
|
[this](const AzPhysics::SystemConfiguration* config)
|
|
{
|
|
EnableAutoManagedPhysicsTick(config->m_autoManageSimulationUpdate);
|
|
})
|
|
, m_onSystemConfigChangedHandler(
|
|
[this](const AzPhysics::SystemConfiguration* config)
|
|
{
|
|
EnableAutoManagedPhysicsTick(config->m_autoManageSimulationUpdate);
|
|
})
|
|
{
|
|
}
|
|
|
|
SystemComponent::~SystemComponent()
|
|
{
|
|
if (m_collisionRequests.Get() == this)
|
|
{
|
|
m_collisionRequests.Unregister(this);
|
|
}
|
|
if (m_physicsSystem.Get() == this)
|
|
{
|
|
m_physicsSystem.Unregister(this);
|
|
}
|
|
}
|
|
|
|
// AZ::Component interface implementation
|
|
void SystemComponent::Init()
|
|
{
|
|
//Old API interfaces
|
|
if (m_collisionRequests.Get() == nullptr)
|
|
{
|
|
m_collisionRequests.Register(this);
|
|
}
|
|
if (m_physicsSystem.Get() == nullptr)
|
|
{
|
|
m_physicsSystem.Register(this);
|
|
}
|
|
}
|
|
|
|
template<typename AssetHandlerT, typename AssetT>
|
|
void RegisterAsset(AZStd::vector<AZStd::unique_ptr<AZ::Data::AssetHandler>>& assetHandlers)
|
|
{
|
|
AssetHandlerT* handler = aznew AssetHandlerT();
|
|
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, AZ::AzTypeInfo<AssetT>::Uuid());
|
|
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, AssetHandlerT::s_assetFileExtension);
|
|
assetHandlers.emplace_back(handler);
|
|
}
|
|
|
|
void SystemComponent::Activate()
|
|
{
|
|
if (!m_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_materialManager.Connect();
|
|
m_defaultWorldComponent.Activate();
|
|
|
|
// Assets related work
|
|
auto* materialAsset = aznew AzFramework::GenericAssetHandler<Physics::MaterialLibraryAsset>("Physics Material", "Physics", "physmaterial");
|
|
materialAsset->Register();
|
|
m_assetHandlers.emplace_back(materialAsset);
|
|
|
|
// Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService".
|
|
RegisterAsset<Pipeline::MeshAssetHandler, Pipeline::MeshAsset>(m_assetHandlers);
|
|
RegisterAsset<Pipeline::HeightFieldAssetHandler, Pipeline::HeightFieldAsset>(m_assetHandlers);
|
|
|
|
// Connect to relevant buses
|
|
Physics::SystemRequestBus::Handler::BusConnect();
|
|
PhysX::SystemRequestsBus::Handler::BusConnect();
|
|
Physics::CollisionRequestBus::Handler::BusConnect();
|
|
|
|
ActivatePhysXSystem();
|
|
}
|
|
|
|
void SystemComponent::Deactivate()
|
|
{
|
|
AZ::TickBus::Handler::BusDisconnect();
|
|
Physics::CollisionRequestBus::Handler::BusDisconnect();
|
|
PhysX::SystemRequestsBus::Handler::BusDisconnect();
|
|
Physics::SystemRequestBus::Handler::BusDisconnect();
|
|
|
|
// Reset material manager
|
|
m_materialManager.ReleaseAllMaterials();
|
|
|
|
m_defaultWorldComponent.Deactivate();
|
|
m_materialManager.Disconnect();
|
|
|
|
m_windProvider.reset();
|
|
|
|
m_onSystemInitializedHandler.Disconnect();
|
|
m_onSystemConfigChangedHandler.Disconnect();
|
|
if (m_physXSystem != nullptr)
|
|
{
|
|
m_physXSystem->Shutdown();
|
|
m_physXSystem = nullptr;
|
|
}
|
|
m_assetHandlers.clear(); //this need to be after m_physXSystem->Shutdown(); For it will drop the default material library reference.
|
|
}
|
|
|
|
physx::PxConvexMesh* SystemComponent::CreateConvexMesh(const void* vertices, AZ::u32 vertexNum, AZ::u32 vertexStride)
|
|
{
|
|
physx::PxConvexMeshDesc desc;
|
|
desc.points.data = vertices;
|
|
desc.points.count = vertexNum;
|
|
desc.points.stride = vertexStride;
|
|
// we provide points only, therefore the PxConvexFlag::eCOMPUTE_CONVEX flag must be specified
|
|
desc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
|
|
|
|
//TEMP until this in moved over
|
|
physx::PxConvexMesh* convex = m_physXSystem->GetPxCooking()->createConvexMesh(desc,
|
|
m_physXSystem->GetPxPhysics()->getPhysicsInsertionCallback());
|
|
AZ_Error("PhysX", convex, "Error. Unable to create convex mesh");
|
|
|
|
return convex;
|
|
}
|
|
|
|
bool SystemComponent::CookConvexMeshToFile(const AZStd::string& filePath, const AZ::Vector3* vertices, AZ::u32 vertexCount)
|
|
{
|
|
AZStd::vector<AZ::u8> physxData;
|
|
|
|
if (CookConvexMeshToMemory(vertices, vertexCount, physxData))
|
|
{
|
|
return Utils::WriteCookedMeshToFile(filePath, physxData,
|
|
Physics::CookedMeshShapeConfiguration::MeshType::Convex);
|
|
}
|
|
|
|
AZ_Error("PhysX", false, "CookConvexMeshToFile. Convex cooking failed for %s.", filePath.c_str());
|
|
return false;
|
|
}
|
|
|
|
bool SystemComponent::CookTriangleMeshToFile(const AZStd::string& filePath, const AZ::Vector3* vertices, AZ::u32 vertexCount,
|
|
const AZ::u32* indices, AZ::u32 indexCount)
|
|
{
|
|
AZStd::vector<AZ::u8> physxData;
|
|
|
|
if (CookTriangleMeshToMemory(vertices, vertexCount, indices, indexCount, physxData))
|
|
{
|
|
return Utils::WriteCookedMeshToFile(filePath, physxData,
|
|
Physics::CookedMeshShapeConfiguration::MeshType::TriangleMesh);
|
|
}
|
|
|
|
AZ_Error("PhysX", false, "CookTriangleMeshToFile. Mesh cooking failed for %s.", filePath.c_str());
|
|
return false;
|
|
}
|
|
|
|
bool SystemComponent::CookConvexMeshToMemory(const AZ::Vector3* vertices, AZ::u32 vertexCount, AZStd::vector<AZ::u8>& result)
|
|
{
|
|
physx::PxDefaultMemoryOutputStream memoryStream;
|
|
|
|
bool cookingResult = Utils::CookConvexToPxOutputStream(vertices, vertexCount, memoryStream);
|
|
|
|
if(cookingResult)
|
|
{
|
|
result.insert(result.end(), memoryStream.getData(), memoryStream.getData() + memoryStream.getSize());
|
|
}
|
|
|
|
return cookingResult;
|
|
}
|
|
|
|
bool SystemComponent::CookTriangleMeshToMemory(const AZ::Vector3* vertices, AZ::u32 vertexCount,
|
|
const AZ::u32* indices, AZ::u32 indexCount, AZStd::vector<AZ::u8>& result)
|
|
{
|
|
physx::PxDefaultMemoryOutputStream memoryStream;
|
|
bool cookingResult = Utils::CookTriangleMeshToToPxOutputStream(vertices, vertexCount, indices, indexCount, memoryStream);
|
|
|
|
if (cookingResult)
|
|
{
|
|
result.insert(result.end(), memoryStream.getData(), memoryStream.getData() + memoryStream.getSize());
|
|
}
|
|
|
|
return cookingResult;
|
|
}
|
|
|
|
physx::PxConvexMesh* SystemComponent::CreateConvexMeshFromCooked(const void* cookedMeshData, AZ::u32 bufferSize)
|
|
{
|
|
physx::PxDefaultMemoryInputData inpStream(reinterpret_cast<physx::PxU8*>(const_cast<void*>(cookedMeshData)), bufferSize);
|
|
//TEMP until this in moved over
|
|
return m_physXSystem->GetPxPhysics()->createConvexMesh(inpStream);
|
|
}
|
|
|
|
physx::PxTriangleMesh* SystemComponent::CreateTriangleMeshFromCooked(const void* cookedMeshData, AZ::u32 bufferSize)
|
|
{
|
|
physx::PxDefaultMemoryInputData inpStream(reinterpret_cast<physx::PxU8*>(const_cast<void*>(cookedMeshData)), bufferSize);
|
|
//TEMP until this in moved over
|
|
return m_physXSystem->GetPxPhysics()->createTriangleMesh(inpStream);
|
|
}
|
|
|
|
AZStd::shared_ptr<Physics::Shape> SystemComponent::CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration)
|
|
{
|
|
auto shapePtr = AZStd::make_shared<PhysX::Shape>(colliderConfiguration, configuration);
|
|
|
|
if (shapePtr->GetPxShape())
|
|
{
|
|
return shapePtr;
|
|
}
|
|
|
|
AZ_Error("PhysX", false, "SystemComponent::CreateShape error. Unable to create a shape from configuration.");
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
AZStd::shared_ptr<Physics::Material> SystemComponent::CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration)
|
|
{
|
|
return AZStd::make_shared<PhysX::Material>(materialConfiguration);
|
|
}
|
|
|
|
void SystemComponent::ReleaseNativeMeshObject(void* nativeMeshObject)
|
|
{
|
|
if (nativeMeshObject)
|
|
{
|
|
static_cast<physx::PxBase*>(nativeMeshObject)->release();
|
|
}
|
|
}
|
|
|
|
AzPhysics::CollisionLayer SystemComponent::GetCollisionLayerByName(const AZStd::string& layerName)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.GetLayer(layerName);
|
|
}
|
|
|
|
AZStd::string SystemComponent::GetCollisionLayerName(const AzPhysics::CollisionLayer& layer)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.GetName(layer);
|
|
}
|
|
|
|
bool SystemComponent::TryGetCollisionLayerByName(const AZStd::string& layerName, AzPhysics::CollisionLayer& layer)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.TryGetLayer(layerName, layer);
|
|
}
|
|
|
|
AzPhysics::CollisionGroup SystemComponent::GetCollisionGroupByName(const AZStd::string& groupName)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionGroups.FindGroupByName(groupName);
|
|
}
|
|
|
|
bool SystemComponent::TryGetCollisionGroupByName(const AZStd::string& groupName, AzPhysics::CollisionGroup& group)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionGroups.TryFindGroupByName(groupName, group);
|
|
}
|
|
|
|
AZStd::string SystemComponent::GetCollisionGroupName(const AzPhysics::CollisionGroup& collisionGroup)
|
|
{
|
|
AZStd::string groupName;
|
|
for (const auto& group : m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionGroups.GetPresets())
|
|
{
|
|
if (group.m_group.GetMask() == collisionGroup.GetMask())
|
|
{
|
|
groupName = group.m_name;
|
|
break;
|
|
}
|
|
}
|
|
return groupName;
|
|
}
|
|
|
|
AzPhysics::CollisionGroup SystemComponent::GetCollisionGroupById(const AzPhysics::CollisionGroups::Id& groupId)
|
|
{
|
|
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionGroups.FindGroupById(groupId);
|
|
}
|
|
|
|
void SystemComponent::SetCollisionLayerName(int index, const AZStd::string& layerName)
|
|
{
|
|
m_physXSystem->SetCollisionLayerName(aznumeric_cast<int>(index), layerName);
|
|
}
|
|
|
|
void SystemComponent::CreateCollisionGroup(const AZStd::string& groupName, const AzPhysics::CollisionGroup& group)
|
|
{
|
|
m_physXSystem->CreateCollisionGroup(groupName, group);
|
|
}
|
|
|
|
physx::PxFilterData SystemComponent::CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group)
|
|
{
|
|
return PhysX::Collision::CreateFilterData(layer, group);
|
|
}
|
|
|
|
physx::PxCooking* SystemComponent::GetCooking()
|
|
{
|
|
//TEMP until this in moved over
|
|
return m_physXSystem->GetPxCooking();
|
|
}
|
|
|
|
void SystemComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
|
{
|
|
if (m_physXSystem)
|
|
{
|
|
m_physXSystem->Simulate(deltaTime);
|
|
}
|
|
}
|
|
|
|
int SystemComponent::GetTickOrder()
|
|
{
|
|
return AZ::ComponentTickBus::TICK_PHYSICS_SYSTEM;
|
|
}
|
|
|
|
void SystemComponent::EnableAutoManagedPhysicsTick(bool shouldTick)
|
|
{
|
|
if (shouldTick && !m_isTickingPhysics)
|
|
{
|
|
AZ::TickBus::Handler::BusConnect();
|
|
}
|
|
else if (!shouldTick && m_isTickingPhysics)
|
|
{
|
|
AZ::TickBus::Handler::BusDisconnect();
|
|
}
|
|
m_isTickingPhysics = shouldTick;
|
|
}
|
|
|
|
void SystemComponent::ActivatePhysXSystem()
|
|
{
|
|
m_physXSystem = GetPhysXSystem();
|
|
if (m_physXSystem)
|
|
{
|
|
m_physXSystem->RegisterSystemInitializedEvent(m_onSystemInitializedHandler);
|
|
m_physXSystem->RegisterSystemConfigurationChangedEvent(m_onSystemConfigChangedHandler);
|
|
const PhysXSettingsRegistryManager& registryManager = m_physXSystem->GetSettingsRegistryManager();
|
|
if (AZStd::optional<PhysXSystemConfiguration> config = registryManager.LoadSystemConfiguration();
|
|
config.has_value())
|
|
{
|
|
m_physXSystem->Initialize(&(*config));
|
|
}
|
|
else //load defaults if there is no config
|
|
{
|
|
const PhysXSystemConfiguration defaultConfig = PhysXSystemConfiguration::CreateDefault();
|
|
m_physXSystem->Initialize(&defaultConfig);
|
|
|
|
auto saveCallback = []([[maybe_unused]] const PhysXSystemConfiguration& config, [[maybe_unused]] PhysXSettingsRegistryManager::Result result)
|
|
{
|
|
AZ_Warning("PhysX", result == PhysXSettingsRegistryManager::Result::Success,
|
|
"Unable to save the default PhysX configuration.");
|
|
};
|
|
registryManager.SaveSystemConfiguration(defaultConfig, saveCallback);
|
|
}
|
|
|
|
//Load the DefaultSceneConfig
|
|
if (AZStd::optional<AzPhysics::SceneConfiguration> config = registryManager.LoadDefaultSceneConfiguration();
|
|
config.has_value())
|
|
{
|
|
m_physXSystem->UpdateDefaultSceneConfiguration((*config));
|
|
}
|
|
else //load defaults if there is no config
|
|
{
|
|
const AzPhysics::SceneConfiguration defaultConfig = AzPhysics::SceneConfiguration::CreateDefault();
|
|
m_physXSystem->UpdateDefaultSceneConfiguration(defaultConfig);
|
|
|
|
auto saveCallback = []([[maybe_unused]] const AzPhysics::SceneConfiguration& config, [[maybe_unused]] PhysXSettingsRegistryManager::Result result)
|
|
{
|
|
AZ_Warning("PhysX", result == PhysXSettingsRegistryManager::Result::Success,
|
|
"Unable to save the default Scene configuration.");
|
|
};
|
|
registryManager.SaveDefaultSceneConfiguration(defaultConfig, saveCallback);
|
|
}
|
|
|
|
//load the debug configuration and initialize the PhysX debug interface
|
|
if (auto* debug = AZ::Interface<Debug::PhysXDebugInterface>::Get())
|
|
{
|
|
if (AZStd::optional<Debug::DebugConfiguration> config = registryManager.LoadDebugConfiguration();
|
|
config.has_value())
|
|
{
|
|
debug->Initialize(*config);
|
|
}
|
|
else //load defaults if there is no config
|
|
{
|
|
const Debug::DebugConfiguration defaultConfig = Debug::DebugConfiguration::CreateDefault();
|
|
debug->Initialize(defaultConfig);
|
|
|
|
auto saveCallback = []([[maybe_unused]] const Debug::DebugConfiguration& config, [[maybe_unused]] PhysXSettingsRegistryManager::Result result)
|
|
{
|
|
AZ_Warning("PhysX", result == PhysXSettingsRegistryManager::Result::Success,
|
|
"Unable to save the default PhysX Debug configuration.");
|
|
};
|
|
registryManager.SaveDebugConfiguration(defaultConfig, saveCallback);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_windProvider = AZStd::make_unique<WindProvider>();
|
|
}
|
|
} // namespace PhysX
|