You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
12 KiB
C++
281 lines
12 KiB
C++
/*
|
|
* 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 <PhysX_precompiled.h>
|
|
|
|
#include "EditorSystemComponent.h"
|
|
#include <AzCore/Interface/Interface.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzFramework/Physics/SystemBus.h>
|
|
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
|
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
|
|
|
#include <IEditor.h>
|
|
#include <ISurfaceType.h>
|
|
|
|
#include <Editor/ConfigStringLineEditCtrl.h>
|
|
#include <Editor/EditorJointConfiguration.h>
|
|
#include <Editor/EditorWindow.h>
|
|
#include <Editor/PropertyTypes.h>
|
|
#include <System/PhysXSystem.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
constexpr const char* DefaultAssetFilename = "SurfaceTypeMaterialLibrary";
|
|
constexpr const char* TemplateAssetFilename = "PhysX/TemplateMaterialLibrary";
|
|
|
|
static AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> GetMaterialLibraryTemplate()
|
|
{
|
|
const auto& assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
|
|
|
|
AZStd::vector<AZStd::string> assetTypeExtensions;
|
|
AZ::AssetTypeInfoBus::Event(assetType, &AZ::AssetTypeInfo::GetAssetTypeExtensions, assetTypeExtensions);
|
|
|
|
if (assetTypeExtensions.size() == 1)
|
|
{
|
|
// Constructing the path to the library asset
|
|
const AZStd::string& assetExtension = assetTypeExtensions[0];
|
|
|
|
// Use the path relative to the asset root to avoid hardcoding full path in the configuration
|
|
AZStd::string relativePath = TemplateAssetFilename;
|
|
AzFramework::StringFunc::Path::ReplaceExtension(relativePath, assetExtension.c_str());
|
|
|
|
AZ::Data::AssetId assetId;
|
|
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
|
assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath.c_str(), assetType, false /*autoRegisterIfNotFound*/);
|
|
|
|
if (assetId.IsValid())
|
|
{
|
|
return AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(assetId, AZ::Data::AssetLoadBehavior::NoLoad);
|
|
}
|
|
}
|
|
|
|
return AZStd::nullopt;
|
|
}
|
|
|
|
static AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> CreateMaterialLibrary(const AZStd::string& fullTargetFilePath, const AZStd::string& relativePath)
|
|
{
|
|
AZ::IO::FileIOStream fileStream(fullTargetFilePath.c_str(), AZ::IO::OpenMode::ModeWrite);
|
|
if (fileStream.IsOpen())
|
|
{
|
|
const auto& assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
|
|
AZ::Data::AssetId assetId;
|
|
|
|
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
|
assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath.c_str(), assetType, true /*autoRegisterIfNotFound*/);
|
|
|
|
AZ::Data::Asset<AZ::Data::AssetData> newAsset =
|
|
AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::Default);
|
|
|
|
if (auto* newMaterialLibraryData = azrtti_cast<Physics::MaterialLibraryAsset*>(newAsset.GetData()))
|
|
{
|
|
if (auto templateLibraryOpt = GetMaterialLibraryTemplate())
|
|
{
|
|
if (const auto* templateMaterialLibData = azrtti_cast<Physics::MaterialLibraryAsset*>(templateLibraryOpt->GetData()))
|
|
{
|
|
templateLibraryOpt->QueueLoad();
|
|
templateLibraryOpt->BlockUntilLoadComplete();
|
|
|
|
// Fill the newly created material library using the template data
|
|
for (const auto& materialData : templateMaterialLibData->GetMaterialsData())
|
|
{
|
|
newMaterialLibraryData->AddMaterialData(materialData);
|
|
}
|
|
|
|
// check it out in the source control system
|
|
AzToolsFramework::SourceControlCommandBus::Broadcast(
|
|
&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, fullTargetFilePath.c_str(), true /*allowMultiCheckout*/,
|
|
[](bool /*success*/, const AzToolsFramework::SourceControlFileInfo& /*info*/) {});
|
|
|
|
// Save the material library asset into a file
|
|
auto assetHandler = AZ::Data::AssetManager::Instance().GetHandler(assetType);
|
|
if (assetHandler->SaveAssetData(newAsset, &fileStream))
|
|
{
|
|
return newAsset;
|
|
}
|
|
else
|
|
{
|
|
AZ_Error(
|
|
"PhysX", false,
|
|
"CreateSurfaceTypeMaterialLibrary: Unable to save Surface Types Material Library Asset to %s",
|
|
fullTargetFilePath.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return AZStd::nullopt;
|
|
}
|
|
|
|
void EditorSystemComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
EditorJointLimitConfig::Reflect(context);
|
|
EditorJointLimitPairConfig::Reflect(context);
|
|
EditorJointLimitConeConfig::Reflect(context);
|
|
EditorJointConfig::Reflect(context);
|
|
|
|
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<EditorSystemComponent, AZ::Component>()
|
|
->Version(1);
|
|
}
|
|
}
|
|
|
|
void EditorSystemComponent::Activate()
|
|
{
|
|
Physics::EditorWorldBus::Handler::BusConnect();
|
|
AzToolsFramework::EditorContextMenuBus::Handler::BusConnect();
|
|
|
|
m_onMaterialLibraryLoadErrorEventHandler = AzPhysics::SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler(
|
|
[this]([[maybe_unused]] AzPhysics::SystemEvents::MaterialLibraryLoadErrorType error)
|
|
{
|
|
// Attempt to set/create the default material library if there was an error
|
|
if (auto* physxSystem = GetPhysXSystem())
|
|
{
|
|
if (auto retrievedMaterialLibrary = RetrieveDefaultMaterialLibrary())
|
|
{
|
|
physxSystem->UpdateMaterialLibrary(retrievedMaterialLibrary.value());
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
|
{
|
|
AzPhysics::SceneConfiguration editorWorldConfiguration = physicsSystem->GetDefaultSceneConfiguration();
|
|
editorWorldConfiguration.m_sceneName = AzPhysics::EditorPhysicsSceneName;
|
|
m_editorWorldSceneHandle = physicsSystem->AddScene(editorWorldConfiguration);
|
|
physicsSystem->RegisterOnMaterialLibraryLoadErrorEventHandler(m_onMaterialLibraryLoadErrorEventHandler);
|
|
}
|
|
|
|
PhysX::RegisterConfigStringLineEditHandler(); // Register custom unique string line edit control
|
|
PhysX::Editor::RegisterPropertyTypes();
|
|
|
|
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
|
|
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
|
|
}
|
|
|
|
void EditorSystemComponent::Deactivate()
|
|
{
|
|
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
|
|
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
|
|
AzToolsFramework::EditorContextMenuBus::Handler::BusDisconnect();
|
|
Physics::EditorWorldBus::Handler::BusDisconnect();
|
|
|
|
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
|
{
|
|
physicsSystem->RemoveScene(m_editorWorldSceneHandle);
|
|
}
|
|
m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle;
|
|
|
|
m_onMaterialLibraryLoadErrorEventHandler.Disconnect();
|
|
}
|
|
|
|
AzPhysics::SceneHandle EditorSystemComponent::GetEditorSceneHandle() const
|
|
{
|
|
return m_editorWorldSceneHandle;
|
|
}
|
|
|
|
void EditorSystemComponent::OnStartPlayInEditorBegin()
|
|
{
|
|
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
|
{
|
|
if (AzPhysics::Scene* scene = physicsSystem->GetScene(m_editorWorldSceneHandle))
|
|
{
|
|
scene->SetEnabled(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorSystemComponent::OnStopPlayInEditor()
|
|
{
|
|
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
|
{
|
|
if (AzPhysics::Scene* scene = physicsSystem->GetScene(m_editorWorldSceneHandle))
|
|
{
|
|
scene->SetEnabled(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorSystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags)
|
|
{
|
|
|
|
}
|
|
|
|
void EditorSystemComponent::NotifyRegisterViews()
|
|
{
|
|
PhysX::Editor::EditorWindow::RegisterViewClass();
|
|
}
|
|
|
|
AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> EditorSystemComponent::RetrieveDefaultMaterialLibrary()
|
|
{
|
|
AZ::Data::AssetId resultAssetId;
|
|
|
|
auto assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
|
|
|
|
AZStd::vector<AZStd::string> assetTypeExtensions;
|
|
AZ::AssetTypeInfoBus::Event(assetType, &AZ::AssetTypeInfo::GetAssetTypeExtensions, assetTypeExtensions);
|
|
|
|
if (assetTypeExtensions.size() == 1)
|
|
{
|
|
// Constructing the path to the library asset
|
|
const AZStd::string& assetExtension = assetTypeExtensions[0];
|
|
|
|
// Use the path relative to the asset root to avoid hardcoding full path in the configuration
|
|
AZStd::string relativePath = DefaultAssetFilename;
|
|
AzFramework::StringFunc::Path::ReplaceExtension(relativePath, assetExtension.c_str());
|
|
|
|
// Try to find an already existing material library
|
|
AZ::Data::AssetCatalogRequestBus::BroadcastResult(resultAssetId,
|
|
&AZ::Data::AssetCatalogRequests::GetAssetIdByPath, relativePath.c_str(), azrtti_typeid<Physics::MaterialLibraryAsset>(), false /*autoRegisterIfNotFound*/);
|
|
|
|
if (!resultAssetId.IsValid())
|
|
{
|
|
// No file for the default material library, create it
|
|
const char* assetRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@");
|
|
AZStd::string fullPath;
|
|
AzFramework::StringFunc::Path::ConstructFull(assetRoot, DefaultAssetFilename, assetExtension.c_str(), fullPath);
|
|
|
|
if (auto materialLibraryOpt = CreateMaterialLibrary(fullPath, relativePath))
|
|
{
|
|
return materialLibraryOpt;
|
|
}
|
|
else
|
|
{
|
|
AZ_Warning("PhysX", false,
|
|
"CreateMaterialLibrary: Failed to create material library at %s. "
|
|
"Please check if the file is writable", fullPath.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AZ::Data::Asset<AZ::Data::AssetData> existingMaterialLibrary =
|
|
AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(resultAssetId, AZ::Data::AssetLoadBehavior::NoLoad);
|
|
|
|
return existingMaterialLibrary;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AZ_Warning("PhysX", false,
|
|
"RetrieveDefaultMaterialLibrary: Number of extensions for the physics material library asset is %u"
|
|
" but should be 1. Please check if the asset registered itself with the asset system correctly",
|
|
assetTypeExtensions.size())
|
|
}
|
|
|
|
return AZStd::nullopt;
|
|
}
|
|
}
|
|
|