/* * 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 #include "EditorSystemComponent.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace PhysX { constexpr const char* DefaultAssetFilename = "SurfaceTypeMaterialLibrary"; constexpr const char* TemplateAssetFilename = "PhysX/TemplateMaterialLibrary"; static AZStd::optional> GetMaterialLibraryTemplate() { const auto& assetType = AZ::AzTypeInfo::Uuid(); AZStd::vector 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(assetId, AZ::Data::AssetLoadBehavior::NoLoad); } } return AZStd::nullopt; } static AZStd::optional> 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::Uuid(); AZ::Data::AssetId assetId; AZ::Data::AssetCatalogRequestBus::BroadcastResult( assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath.c_str(), assetType, true /*autoRegisterIfNotFound*/); AZ::Data::Asset newAsset = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::Default); if (auto* newMaterialLibraryData = azrtti_cast(newAsset.GetData())) { if (auto templateLibraryOpt = GetMaterialLibraryTemplate()) { if (const auto* templateMaterialLibData = azrtti_cast(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(context)) { serializeContext->Class() ->Version(1); } } void EditorSystemComponent::Activate() { Physics::EditorWorldBus::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::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(); Physics::EditorWorldBus::Handler::BusDisconnect(); if (auto* physicsSystem = AZ::Interface::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::Get()) { if (AzPhysics::Scene* scene = physicsSystem->GetScene(m_editorWorldSceneHandle)) { scene->SetEnabled(false); } } } void EditorSystemComponent::OnStopPlayInEditor() { if (auto* physicsSystem = AZ::Interface::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> EditorSystemComponent::RetrieveDefaultMaterialLibrary() { AZ::Data::AssetId resultAssetId; auto assetType = AZ::AzTypeInfo::Uuid(); AZStd::vector 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(), 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 existingMaterialLibrary = AZ::Data::AssetManager::Instance().GetAsset(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; } }