diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp index 66ed42af8f..a4aab24be4 100644 --- a/Code/Editor/Core/QtEditorApplication.cpp +++ b/Code/Editor/Core/QtEditorApplication.cpp @@ -44,7 +44,7 @@ enum { // in milliseconds GameModeIdleFrequency = 0, - EditorModeIdleFrequency = 0, + EditorModeIdleFrequency = 1, InactiveModeFrequency = 10, UninitializedFrequency = 9999, }; diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp index 600f2089e6..29cf348ab5 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.cpp +++ b/Code/Editor/EditorModularViewportCameraComposer.cpp @@ -175,27 +175,15 @@ namespace SandboxEditor m_pivotCamera = AZStd::make_shared(SandboxEditor::CameraPivotChannelId()); m_pivotCamera->SetPivotFn( - [viewportId = m_viewportId]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) + []([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) { - AZStd::optional lookAtAfterInterpolation; - AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( - lookAtAfterInterpolation, viewportId, - &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::LookAtAfterInterpolation); - - // initially attempt to use the last set look at point after an interpolation has finished - // note: ignore this if it is the same location as the camera (e.g. after go to position) - if (lookAtAfterInterpolation.has_value() && !lookAtAfterInterpolation->IsClose(position)) - { - return *lookAtAfterInterpolation; - } - - // otherwise fall back to the selected entity pivot + // use the manipulator transform as the pivot point AZStd::optional entityPivot; AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( entityPivot, AzToolsFramework::GetEntityContextId(), &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); - // finally just use the identity + // otherwise just use the identity return entityPivot.value_or(AZ::Transform::CreateIdentity()).GetTranslation(); }); diff --git a/Code/Editor/EditorViewportCamera.cpp b/Code/Editor/EditorViewportCamera.cpp index 0c7a1559d1..b25e7072ff 100644 --- a/Code/Editor/EditorViewportCamera.cpp +++ b/Code/Editor/EditorViewportCamera.cpp @@ -48,7 +48,7 @@ namespace SandboxEditor { AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( viewportContext->GetId(), &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, - AZ::Transform::CreateFromQuaternionAndTranslation(CameraRotation(pitch, yaw), position), 0.0f); + AZ::Transform::CreateFromQuaternionAndTranslation(CameraRotation(pitch, yaw), position)); } } diff --git a/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp b/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp index affe5794cc..1a44d43370 100644 --- a/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp +++ b/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp @@ -167,7 +167,7 @@ namespace UnitTest AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f)), AZ::Vector3(20.0f, 40.0f, 60.0f)); AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, - transformToInterpolateTo, 0.0f); + transformToInterpolateTo); // simulate interpolation m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); @@ -193,7 +193,7 @@ namespace UnitTest // When AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, - transformToInterpolateTo, 0.0f); + transformToInterpolateTo); // simulate interpolation m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 47bd214b8d..666700a874 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1739,8 +1739,7 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework:: AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( viewportContext->GetId(), - &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform, - distanceToLookAt); + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform); } } } diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index 6b3f1c2633..b510315995 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -36,9 +36,6 @@ #include "CryEdit.h" #include "Viewport.h" -// Atom Renderer -#include - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING @@ -1237,13 +1234,6 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout() { componentApplication->TickSystem(); } - - // Directly tick the renderer, as it's no longer part of the system tick - if (auto rpiSystem = AZ::RPI::RPISystemInterface::Get()) - { - rpiSystem->SimulationTick(); - rpiSystem->RenderTick(); - } } } diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index 98182a9568..8eb620f69e 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -340,6 +340,14 @@ namespace AZ // (Load jobs will attempt to reuse blocked threads before spinning off new job threads) ProcessLoadJob(); } + + // Pump the AssetBus function queue once more after the load has completed in case additional + // functions have been queued between the last call to DispatchEvents and the completion + // of the current load job + if (m_shouldDispatchEvents) + { + AssetManager::Instance().DispatchEvents(); + } } void Finish() diff --git a/Code/Framework/AzCore/AzCore/Component/Component.h b/Code/Framework/AzCore/AzCore/Component/Component.h index 3cbb9b5a86..677517d896 100644 --- a/Code/Framework/AzCore/AzCore/Component/Component.h +++ b/Code/Framework/AzCore/AzCore/Component/Component.h @@ -22,6 +22,7 @@ #include #include // Used as the allocator for most components. #include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index a13f11c007..168807cd97 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -74,8 +74,6 @@ #include #include -AZ_CVAR(float, g_simulation_tick_rate, 0, nullptr, AZ::ConsoleFunctorFlags::Null, "The rate at which the game simulation tick loop runs, or 0 for as fast as possible"); - static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments) { if (arguments.empty()) @@ -1396,23 +1394,6 @@ namespace AZ AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick"); EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now)); } - - // If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame, - // sleeping if there's still time remaining. - if (g_simulation_tick_rate > 0.f) - { - now = AZStd::chrono::system_clock::now(); - - // Work in microsecond durations here as that's the native measurement time for time_point - constexpr float microsecondsPerSecond = 1000.f * 1000.f; - const AZStd::chrono::microseconds timeBudgetPerTick(static_cast(microsecondsPerSecond / g_simulation_tick_rate)); - AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now; - - if (timeUntilNextTick.count() > 0) - { - AZStd::this_thread::sleep_for(timeUntilNextTick); - } - } } } diff --git a/Code/Framework/AzCore/AzCore/Component/TickBus.h b/Code/Framework/AzCore/AzCore/Component/TickBus.h index 966a3c303e..e65efb93f2 100644 --- a/Code/Framework/AzCore/AzCore/Component/TickBus.h +++ b/Code/Framework/AzCore/AzCore/Component/TickBus.h @@ -46,8 +46,6 @@ namespace AZ TICK_PRE_RENDER = 750, ///< Suggested tick handler position to update render-related data. - TICK_RENDER = 800, ///< Suggested tick handler position for rendering. - TICK_DEFAULT = 1000, ///< Default tick handler position when the handler is constructed. TICK_UI = 2000, ///< Suggested tick handler position for UI components. diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTracking.h b/Code/Framework/AzCore/AzCore/Debug/AssetTracking.h index 5c3c835271..615634c05a 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTracking.h +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTracking.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h index 58754ff9b8..ff8966e8e0 100644 --- a/Code/Framework/AzCore/AzCore/EBus/EBus.h +++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h @@ -19,14 +19,11 @@ #pragma once #include +#include #include #include - // Included for backwards compatibility purposes -#include -#include #include -// End backwards compat #include #include @@ -90,14 +87,14 @@ namespace AZ * For available settings, see AZ::EBusHandlerPolicy. * By default, an EBus supports any number of handlers. */ - static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple; + static constexpr EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple; /** * Defines how many addresses exist on the EBus. * For available settings, see AZ::EBusAddressPolicy. * By default, an EBus uses a single address. */ - static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single; + static constexpr EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single; /** * The type of ID that is used to address the EBus. @@ -152,14 +149,14 @@ namespace AZ * `::ExecuteQueuedEvents()`. * By default, the event queue is disabled. */ - static const bool EnableEventQueue = false; + static constexpr bool EnableEventQueue = false; /** * Specifies whether the bus should accept queued messages by default or not. * If set to false, Bus::AllowFunctionQueuing(true) must be called before events are accepted. * Used only when #EnableEventQueue is true. */ - static const bool EventQueueingActiveByDefault = true; + static constexpr bool EventQueueingActiveByDefault = true; /** * Specifies whether the EBus supports queueing functions which take reference @@ -168,7 +165,7 @@ namespace AZ * You should only use this if you know that the data being passed as arguments will * outlive the dispatch of the queued event. */ - static const bool EnableQueuedReferences = false; + static constexpr bool EnableQueuedReferences = false; /** * Locking primitive that is used when adding and removing @@ -197,7 +194,7 @@ namespace AZ * to do. * By default, the standard policy is used, which locks around all dispatches */ - static const bool LocklessDispatch = false; + static constexpr bool LocklessDispatch = false; /** * Specifies where EBus data is stored. diff --git a/Code/Framework/AzCore/AzCore/EBus/IEventScheduler.h b/Code/Framework/AzCore/AzCore/EBus/IEventScheduler.h index 5c1bbf6dab..021e8edfab 100644 --- a/Code/Framework/AzCore/AzCore/EBus/IEventScheduler.h +++ b/Code/Framework/AzCore/AzCore/EBus/IEventScheduler.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/EBus/Policies.h b/Code/Framework/AzCore/AzCore/EBus/Policies.h index db11043ef8..86cbe5d02f 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Policies.h +++ b/Code/Framework/AzCore/AzCore/EBus/Policies.h @@ -18,9 +18,8 @@ #include #include #include +#include -#include -#include namespace AZ { @@ -251,29 +250,21 @@ namespace AZ void Execute() { AZ_Warning("System", m_isActive, "You are calling execute queued functions on a bus which has not activated its function queuing! Call YourBus::AllowFunctionQueuing(true)!"); - while (true) + + MessageQueueType localMessages; + + // Swap the current list of queue functions with a local instance { - BusMessageCall invoke; + AZStd::scoped_lock lock(m_messagesMutex); + AZStd::swap(localMessages, m_messages); + } - ////////////////////////////////////////////////////////////////////////// - // Pop element from the queue. - { - AZStd::lock_guard lock(m_messagesMutex); - size_t numMessages = m_messages.size(); - if (numMessages == 0) - { - break; - } - AZStd::swap(invoke, m_messages.front()); - m_messages.pop(); - if (numMessages == 1) - { - m_messages = {}; - } - } - ////////////////////////////////////////////////////////////////////////// - - invoke(); + // Execute the queue functions safely now that are owned by the function + while (!localMessages.empty()) + { + const BusMessageCall& localMessage = localMessages.front(); + localMessage(); + localMessages.pop(); } } diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h index 0a1af21213..7f48f301aa 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp index caa4cda8f5..3e6376323c 100644 --- a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp +++ b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp @@ -366,6 +366,42 @@ namespace UnitTest }; + static constexpr AZStd::chrono::seconds MaxDispatchTimeoutSeconds = BaseAssetManagerTest::DefaultTimeoutSeconds * 12; + + template + bool DispatchEventsUntilCondition(AZ::Data::AssetManager& assetManager, Pred&& conditionPredicate, + AZStd::chrono::seconds logIntervalSeconds = BaseAssetManagerTest::DefaultTimeoutSeconds, + AZStd::chrono::seconds maxTimeoutSeconds = MaxDispatchTimeoutSeconds) + { + // If the Max Timeout is hit the test will be marked as a failure + + AZStd::chrono::time_point dispatchEventTimeStart = AZStd::chrono::system_clock::now(); + AZStd::chrono::seconds dispatchEventNextLogTime = logIntervalSeconds; + + while (!conditionPredicate()) + { + AZStd::chrono::time_point currentTime = AZStd::chrono::system_clock::now(); + if (AZStd::chrono::seconds elapsedTime{ currentTime - dispatchEventTimeStart }; + elapsedTime >= dispatchEventNextLogTime) + { + const testing::TestInfo* test_info = ::testing::UnitTest::GetInstance()->current_test_info(); + AZ_Printf("AssetManagerLoadingTest", "The DispatchEventsUntiTimeout function has been waiting for %llu seconds" + " in test %s.%s", elapsedTime.count(), test_info->test_case_name(), test_info->name()); + // Update the next log time to be the next multiple of DefaultTimeout Seconds + // after current elapsed time + dispatchEventNextLogTime = elapsedTime + logIntervalSeconds - ((elapsedTime + logIntervalSeconds) % logIntervalSeconds); + if (elapsedTime >= maxTimeoutSeconds) + { + return false; + } + } + assetManager.DispatchEvents(); + AZStd::this_thread::yield(); + } + + return true; + } + #if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS || AZ_TRAIT_DISABLE_ASSET_MANAGER_FLOOD_TEST TEST_F(AssetJobsFloodTest, DISABLED_FloodTest) #else @@ -1358,42 +1394,74 @@ namespace UnitTest m_assetHandlerAndCatalog->m_numCreations = 0; m_assetHandlerAndCatalog->m_numDestructions = 0; { + ContainerReadyListener containerLoadingCompleteListener(NoLoadAssetId); OnAssetReadyListener readyListener(NoLoadAssetId, azrtti_typeid()); - OnAssetReadyListener depenencyListener(MyAsset2Id, azrtti_typeid()); + OnAssetReadyListener dependencyListener(MyAsset2Id, azrtti_typeid()); + + SCOPED_TRACE("LoadDependencies_BehaviorObeyed"); + + auto AssetOnlyReady = [&readyListener]() -> bool + { + return readyListener.m_ready; + }; + auto AssetAndDependencyReady = [&readyListener, &dependencyListener]() -> bool + { + return readyListener.m_ready && dependencyListener.m_ready; + }; + auto AssetContainerReady = [&containerLoadingCompleteListener]() -> bool + { + return containerLoadingCompleteListener.m_ready; + }; auto noLoadRef = m_testAssetManager->GetAsset(NoLoadAssetId, azrtti_typeid(), AZ::Data::AssetLoadBehavior::Default); - auto maxTimeout = AZStd::chrono::system_clock::now() + DefaultTimeoutSeconds; + // Dispatch AssetBus events until the NoLoadAssetId has signaled an OnAssetReady + // event or the timeout has been reached + EXPECT_TRUE(DispatchEventsUntilCondition(*m_testAssetManager, AssetOnlyReady)) + << "The DispatchEventsUntiTimeout function has not completed in " + << MaxDispatchTimeoutSeconds.count() << " seconds. The test will be marked as a failure\n"; + + // Dispatch AssetBus events until the asset container used to load + // NoLoadAssetId has signaled an OnAssetContainerReady event + // or the timeout has been reached + // Wait until the current asset container has finished loading the NoLoadAssetId + // before trigger another load + // If the wait does not occur here, most likely what would occur is + // the AssetManager::m_ownedAssetContainers object is still loading the NoLoadAssetId + // using the default AssetLoadParameters + // If a call to GetAsset occurs at this point while the Asset is still loading + // it will ignore the new loadParams below and instead just re-use the existing + // AssetContainerReader instance, resulting in the dependent MyAsset2Id not + // being loaded + // The function that can return an existing AssetContainer instance is the + // AssetManager::GetAssetContainer. Since it can be in the middle of a load, + // updating the AssetLoadParams would have an effect on the current in progress + // load + EXPECT_TRUE(DispatchEventsUntilCondition(*m_testAssetManager, AssetContainerReady)) + << "The DispatchEventsUntiTimeout function has not completed in " + << MaxDispatchTimeoutSeconds.count() << " seconds. The test will be marked as a failure\n"; + + // Reset the ContainerLoadingComplete ready status back to 0 + containerLoadingCompleteListener.m_ready = 0; - while (!readyListener.m_ready) - { - m_testAssetManager->DispatchEvents(); - if (AZStd::chrono::system_clock::now() > maxTimeout) - { - break; - } - AZStd::this_thread::yield(); - } - EXPECT_EQ(readyListener.m_ready, 1); - EXPECT_EQ(depenencyListener.m_ready, 0); - AZ::Data::AssetLoadParameters loadParams(nullptr, AZ::Data::AssetDependencyLoadRules::LoadAll); loadParams.m_reloadMissingDependencies = true; auto loadDependencyRef = m_testAssetManager->GetAsset(NoLoadAssetId, azrtti_typeid(), AZ::Data::AssetLoadBehavior::Default, loadParams); - while (!depenencyListener.m_ready || !readyListener.m_ready) - { - m_testAssetManager->DispatchEvents(); - if (AZStd::chrono::system_clock::now() > maxTimeout) - { - break; - } - AZStd::this_thread::yield(); - } + // Dispatch AssetBus events until the NoLoadAssetId and the MyAsset2Id has signaled + // an OnAssetReady event or the timeout has been reached + EXPECT_TRUE(DispatchEventsUntilCondition(*m_testAssetManager, AssetAndDependencyReady)) + << "The DispatchEventsUntiTimeout function has not completed in " + << MaxDispatchTimeoutSeconds.count() << " seconds. The test will be marked as a failure\n"; + EXPECT_EQ(readyListener.m_ready, 1); - EXPECT_EQ(depenencyListener.m_ready, 1); + EXPECT_EQ(dependencyListener.m_ready, 1); + + EXPECT_TRUE(DispatchEventsUntilCondition(*m_testAssetManager, AssetContainerReady)) + << "The DispatchEventsUntiTimeout function has not completed in " + << MaxDispatchTimeoutSeconds.count() << " seconds. The test will be marked as a failure\n"; } CheckFinishedCreationsAndDestructions(); diff --git a/Code/Framework/AzCore/Tests/UUIDTests.cpp b/Code/Framework/AzCore/Tests/UUIDTests.cpp index 5d4fb7a711..a18dc33c4f 100644 --- a/Code/Framework/AzCore/Tests/UUIDTests.cpp +++ b/Code/Framework/AzCore/Tests/UUIDTests.cpp @@ -7,6 +7,7 @@ */ #include #include +#include using namespace AZ; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h index 646410f8db..ae1e3dfa9c 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Logging/MissingAssetLogger.h b/Code/Framework/AzFramework/AzFramework/Logging/MissingAssetLogger.h index 9434ca80ae..b49609d820 100644 --- a/Code/Framework/AzFramework/AzFramework/Logging/MissingAssetLogger.h +++ b/Code/Framework/AzFramework/AzFramework/Logging/MissingAssetLogger.h @@ -8,6 +8,7 @@ #pragma once +#include #include namespace AzFramework { class LogFile; } diff --git a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionStructures.h b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionStructures.h index 11c3fedb2b..9d6cd48102 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionStructures.h +++ b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionStructures.h @@ -11,6 +11,7 @@ #include #include #include +#include #include //! Common structures for Render geometry queries diff --git a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h index 7479b0d1e1..0eb699475f 100644 --- a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h +++ b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index f759857505..475a7d5504 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -32,17 +32,14 @@ namespace AzGameFramework // at the Assets alias, otherwise to attempting to mount the engine pak // from the Cache folder AZ::IO::FixedMaxPath enginePakPath = AZ::Utils::GetExecutableDirectory(); - enginePakPath /= "Engine.pak"; - if (m_archiveFileIO->Exists(enginePakPath.c_str())) + enginePakPath /= "engine.pak"; + if (!m_archive->OpenPack("@assets@", enginePakPath.Native())) { - m_archive->OpenPack("@assets@", enginePakPath.Native()); - } - else if (enginePakPath.clear(); m_settingsRegistry->Get(enginePakPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) - { - // fall back to checking if there is an Engine.pak in the Asset Cache - enginePakPath /= "Engine.pak"; - if (m_archiveFileIO->Exists(enginePakPath.c_str())) + enginePakPath.clear(); + if (m_settingsRegistry->Get(enginePakPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) { + // fall back to checking Project Cache Root. + enginePakPath /= "engine.pak"; m_archive->OpenPack("@assets@", enginePakPath.Native()); } } diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitsetView.inl b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitsetView.inl index 8cbdd27e09..6192cfa878 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitsetView.inl +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitsetView.inl @@ -15,12 +15,12 @@ namespace AzNetworking , m_startOffset(startOffset) , m_count(startOffset < bitset.GetValidBitCount() && startOffset + count <= bitset.GetValidBitCount() ? count : 0) { - AZ_Assert(startOffset + count <= bitset.GetValidBitCount(), "Out of bounds setup in BitsetSubset. Defaulting to 0 bit count."); + AZ_Warning("FixedSizeBitsetView", startOffset + count <= bitset.GetValidBitCount(), "Out of bounds setup in BitsetSubset. Defaulting to 0 bit count."); } inline void FixedSizeBitsetView::SetBit(uint32_t index, bool value) { - AZ_Assert(index < m_count, "Out of bounds access in BitsetSubset (requested %u, count %u)", index, m_count); + AZ_Warning("FixedSizeBitsetView", index < m_count, "Out of bounds access in BitsetSubset (requested %u, count %u)", index, m_count); if (m_count) { m_bitset.SetBit(m_startOffset + index, value); @@ -29,7 +29,7 @@ namespace AzNetworking inline bool FixedSizeBitsetView::GetBit(uint32_t index) const { - AZ_Assert(index < m_count, "Out of bounds access in BitsetSubset (requested %u, count %u)", index, m_count); + AZ_Warning("FixedSizeBitsetView", index < m_count, "Out of bounds access in BitsetSubset (requested %u, count %u)", index, m_count); if (m_count) { return m_bitset.GetBit(m_startOffset + index); diff --git a/Code/Framework/AzNetworking/AzNetworking/Framework/NetworkingSystemComponent.cpp b/Code/Framework/AzNetworking/AzNetworking/Framework/NetworkingSystemComponent.cpp index 83588f4acb..16e4e26f67 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Framework/NetworkingSystemComponent.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Framework/NetworkingSystemComponent.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include namespace AzNetworking diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnectionSet.h b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnectionSet.h index 8594bf87db..7fa66b0470 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnectionSet.h +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpConnectionSet.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AzNetworking { diff --git a/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetTests.cpp b/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetTests.cpp index f22e815526..12e242c86c 100644 --- a/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetTests.cpp +++ b/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetTests.cpp @@ -55,5 +55,8 @@ namespace UnitTest unusedBitTest.SetBit(i, false); } EXPECT_FALSE(unusedBitTest.AnySet()); + + unusedBitTest.SetBit(0, true); + EXPECT_TRUE(unusedBitTest.AnySet()); } } diff --git a/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetViewTests.cpp b/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetViewTests.cpp index 6f32eacda9..8ac3b63f1b 100644 --- a/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetViewTests.cpp +++ b/Code/Framework/AzNetworking/Tests/DataStructures/FixedSizeBitsetViewTests.cpp @@ -42,4 +42,29 @@ namespace UnitTest EXPECT_FALSE(view.GetBit(0)); } } + + TEST(FixedSizeBitsetView, EmptyBitset) + { + AzNetworking::FixedSizeBitset<32> bitset; + AzNetworking::FixedSizeBitsetView view(bitset, 10, 0); + EXPECT_FALSE(view.GetBit(0)); + } + + TEST(FixedSizeBitsetView, TestAnySet) + { + const uint32_t VIEW_SIZE = 5; + + AzNetworking::FixedSizeBitset<9> unusedBitTest(true); + AzNetworking::FixedSizeBitsetView view(unusedBitTest, 0, VIEW_SIZE); + for (uint32_t i = 0; i < VIEW_SIZE; ++i) + { + view.SetBit(i, false); + } + EXPECT_FALSE(view.AnySet()); + + view.SetBit(0, true); + EXPECT_TRUE(view.AnySet()); + + EXPECT_EQ(view.GetValidBitCount(), VIEW_SIZE); + } } diff --git a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp index bc9ecab2cb..3031f66774 100644 --- a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp +++ b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp @@ -148,6 +148,11 @@ namespace UnitTest EXPECT_EQ(testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount(), 1); EXPECT_EQ(testClient.m_clientNetworkInterface->GetConnectionSet().GetConnectionCount(), 1); + + testClient.m_clientNetworkInterface->SetTimeoutEnabled(true); + EXPECT_TRUE(testClient.m_clientNetworkInterface->IsTimeoutEnabled()); + + EXPECT_TRUE(testServer.m_serverNetworkInterface->StopListening()); } #if AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS diff --git a/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp b/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp index c4de3fc6dd..91db3b4549 100644 --- a/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp +++ b/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp @@ -125,6 +125,18 @@ namespace UnitTest AzNetworking::NetworkingSystemComponent* m_networkingSystemComponent; }; + TEST_F(UdpTransportTests, PacketIdWrap) + { + const uint32_t SEQUENCE_BOUNDARY = 0xFFFF; + UdpPacketTracker tracker; + + for (uint32_t i = 0; i < SEQUENCE_BOUNDARY; ++i) + { + tracker.GetNextPacketId(); + } + EXPECT_EQ(tracker.GetNextPacketId(), PacketId(SEQUENCE_BOUNDARY + 1)); + } + TEST_F(UdpTransportTests, AckReplication) { static const SequenceId TestReliableSequenceId = InvalidSequenceId; @@ -266,6 +278,15 @@ namespace UnitTest EXPECT_EQ(testServer.m_serverNetworkInterface->GetConnectionSet().GetConnectionCount(), 1); EXPECT_EQ(testClient.m_clientNetworkInterface->GetConnectionSet().GetConnectionCount(), 1); + + testClient.m_clientNetworkInterface->SetTimeoutEnabled(true); + EXPECT_TRUE(testClient.m_clientNetworkInterface->IsTimeoutEnabled()); + + EXPECT_FALSE(dynamic_cast(testClient.m_clientNetworkInterface)->IsEncrypted()); + + EXPECT_TRUE(testServer.m_serverNetworkInterface->StopListening()); + EXPECT_FALSE(testServer.m_serverNetworkInterface->StopListening()); + EXPECT_FALSE(dynamic_cast(testServer.m_serverNetworkInterface)->IsOpen()); } TEST_F(UdpTransportTests, TestMultipleClients) diff --git a/Code/Framework/AzNetworking/Tests/Utilities/IpAddressTests.cpp b/Code/Framework/AzNetworking/Tests/Utilities/IpAddressTests.cpp index 435ebb48e0..c143556670 100644 --- a/Code/Framework/AzNetworking/Tests/Utilities/IpAddressTests.cpp +++ b/Code/Framework/AzNetworking/Tests/Utilities/IpAddressTests.cpp @@ -11,4 +11,16 @@ namespace UnitTest { + TEST(IpAddressTests, TestIpQuads) + { + const AzNetworking::IpAddress ip = AzNetworking::IpAddress(127, 0, 0, 1, 12345); + + EXPECT_EQ(ip.GetQuadA(), 127); + EXPECT_EQ(ip.GetQuadB(), 0); + EXPECT_EQ(ip.GetQuadC(), 0); + EXPECT_EQ(ip.GetQuadD(), 1); + + EXPECT_EQ(ip.GetString(), "127.0.0.1:12345"); + EXPECT_EQ(ip.GetIpString(), "127.0.0.1"); + } } diff --git a/Code/Framework/AzNetworking/Tests/Utilities/QuantizedValuesTests.cpp b/Code/Framework/AzNetworking/Tests/Utilities/QuantizedValuesTests.cpp index 13bf9bdb0a..0f0bcac54d 100644 --- a/Code/Framework/AzNetworking/Tests/Utilities/QuantizedValuesTests.cpp +++ b/Code/Framework/AzNetworking/Tests/Utilities/QuantizedValuesTests.cpp @@ -79,13 +79,12 @@ namespace UnitTest template void TestQuantizedValuesHelper01() { - AzNetworking::QuantizedValues testIn, testOut; // Transmits float values between 0 and 1 using NUM_BYTES + AzNetworking::QuantizedValues testIn(ValueFromFloat::Construct(0.0f)), testOut; // Transmits float values between 0 and 1 using NUM_BYTES AZStd::array buffer; AzNetworking::NetworkInputSerializer inputSerializer(buffer.data(), static_cast(buffer.size())); AzNetworking::NetworkOutputSerializer outputSerializer(buffer.data(), static_cast(buffer.size())); - testIn = ValueFromFloat::Construct(0.0f); EXPECT_EQ(static_cast::ValueType>(testIn), ValueFromFloat::Construct(0.0f)); testIn.Serialize(inputSerializer); EXPECT_EQ(inputSerializer.GetSize(), NUM_BYTES * NUM_ELEMENTS); @@ -95,6 +94,8 @@ namespace UnitTest testIn = ValueFromFloat::Construct(1.0f); EXPECT_EQ(static_cast::ValueType>(testIn), ValueFromFloat::Construct(1.0f)); testIn.Serialize(inputSerializer); + EXPECT_NE(testIn, testOut); + EXPECT_NE(testIn.GetQuantizedIntegralValues()[0], testOut.GetQuantizedIntegralValues()[0]); testOut.Serialize(outputSerializer); EXPECT_EQ(testIn, testOut); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg new file mode 100644 index 0000000000..b12640bd59 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg new file mode 100644 index 0000000000..b1b09104b1 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg new file mode 100644 index 0000000000..3c40cb82b2 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg @@ -0,0 +1,15 @@ + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg new file mode 100644 index 0000000000..a9c5811d7d --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg new file mode 100644 index 0000000000..684c32a08d --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg new file mode 100644 index 0000000000..456785f1bc --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg new file mode 100644 index 0000000000..ec3d1114bb --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg new file mode 100644 index 0000000000..98f56f547d --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc index 7321128b57..16d55f1b8c 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc @@ -390,6 +390,14 @@ img/UI20/toolbar/Y_axis.svg img/UI20/toolbar/Z_axis.svg img/UI20/toolbar/XY2_copy.svg + img/UI20/toolbar/joints/Damping.svg + img/UI20/toolbar/joints/MaxForce.svg + img/UI20/toolbar/joints/MaxTorque.svg + img/UI20/toolbar/joints/SnapPosition.svg + img/UI20/toolbar/joints/SnapRotation.svg + img/UI20/toolbar/joints/Stiffness.svg + img/UI20/toolbar/joints/SwingLimits.svg + img/UI20/toolbar/joints/TwistLimits.svg img/triangle0.png img/triangle0_highlighted.png img/line.png diff --git a/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/Platform_Unimplemented.cpp b/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/Platform_Unimplemented.cpp index ea6c6bc5b8..afa75d8333 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/Platform_Unimplemented.cpp +++ b/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/Platform_Unimplemented.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include "Platform.h" +#include #include class ModuleHandle diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index acf935e6dc..c6772ea2d7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -20,7 +20,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") AZ_POP_DISABLE_WARNING AZ_CVAR( - bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + bool, ed_useNewAssetBrowserTableView, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new AssetBrowser TableView for searching assets."); namespace AzToolsFramework { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp index 966cd5a43a..4ebeb03a71 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp @@ -29,7 +29,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4244, "-Wunknown-warning-option") // disable warnin AZ_POP_DISABLE_WARNING AZ_CVAR( - bool, ed_hideAssetPickerPathColumn, false, nullptr, AZ::ConsoleFunctorFlags::Null, + bool, ed_hideAssetPickerPathColumn, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Hide AssetPicker path column for a clearer view."); AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryCache.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryCache.h index e2929c0d3e..7b94108a91 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryCache.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryCache.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h index d765d4e1e5..685770dd20 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h @@ -7,6 +7,7 @@ */ #pragma once +#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorBus.h index becdba44ea..9b12ea27d4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorBus.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace AZ::Data { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp index 0259142135..4d849466ee 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp @@ -8,8 +8,9 @@ #include "ComponentModeCollection.h" -#include #include +#include +#include namespace AzToolsFramework { @@ -17,7 +18,7 @@ namespace AzToolsFramework { AZ_CLASS_ALLOCATOR_IMPL(ComponentModeCollection, AZ::SystemAllocator, 0) - static const char* const s_nextActiveComponentModeTitle = "Edit Next"; + static const char* const s_nextActiveComponentModeTitle = "Edit Next"; static const char* const s_previousActiveComponentModeTitle = "Edit Previous"; static const char* const s_nextActiveComponentModeDesc = "Move to the next component"; static const char* const s_prevActiveComponentModeDesc = "Move to the previous component"; @@ -119,6 +120,11 @@ namespace AzToolsFramework } }; + ComponentModeCollection::ComponentModeCollection(ViewportEditorModeTrackerInterface* viewportEditorModeTracker) + : m_viewportEditorModeTracker(viewportEditorModeTracker) + { + } + void ComponentModeCollection::AddComponentMode( const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid componentType, const ComponentModeFactoryFunction& componentModeBuilder) @@ -209,6 +215,11 @@ namespace AzToolsFramework GetEntityContextId(), &EditorComponentModeNotifications::EnteredComponentMode, m_activeComponentTypes); + // this call to activate the component mode editor state should eventually replace the bus call in + // ComponentModeCollection::BeginComponentMode() to EditorComponentModeNotifications::EnteredComponentMode + // such that all of the notifications for activating/deactivating the different editor modes are in a central location + m_viewportEditorModeTracker->ActivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Component); + // enable actions for the first/primary ComponentMode // note: if multiple ComponentModes are activated at the same time, actions // are not available together, the 'active' mode will bind its actions one at a time @@ -282,6 +293,10 @@ namespace AzToolsFramework &EditorComponentModeNotifications::LeftComponentMode, m_activeComponentTypes); + // this call to deactivate the component mode editor state should eventually replace the bus call in + // ComponentModeCollection::EndComponentMode() to EditorComponentModeNotifications::LeftComponentMode + // such that all of the notifications for activating/deactivating the different editor modes are in a central location + m_viewportEditorModeTracker->DeactivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Component); // clear stored modes and builders for this ComponentMode // TLDR: avoid 'use after free' error diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h index 7dd97dc0c9..9e299d2323 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h @@ -15,6 +15,7 @@ namespace AzToolsFramework { class EditorMetricsEventsBusTraits; + class ViewportEditorModeTrackerInterface; namespace ComponentModeFramework { @@ -25,7 +26,7 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR_DECL /// @cond - ComponentModeCollection() = default; + explicit ComponentModeCollection(ViewportEditorModeTrackerInterface* viewportEditorModeTracker); ~ComponentModeCollection() = default; ComponentModeCollection(const ComponentModeCollection&) = delete; ComponentModeCollection& operator=(const ComponentModeCollection&) = delete; @@ -101,6 +102,7 @@ namespace AzToolsFramework size_t m_selectedComponentModeIndex = 0; ///< Index into the array of active ComponentModes, current index is 'selected' ComponentMode. bool m_adding = false; ///< Are we currently adding individual ComponentModes to the Editor wide ComponentMode. bool m_componentMode = false; ///< Editor (global) ComponentMode flag - is ComponentMode active or not. + ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes. }; } // namespace ComponentModeFramework } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h index a4b90f95b7..a2b23fa8d6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/BaseManipulator.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/BaseManipulator.h index a2b004763b..06e9c82e55 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/BaseManipulator.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/BaseManipulator.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 0d2696f14b..6ef2d756fb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -818,7 +818,14 @@ namespace AzToolsFramework auto linkIterator = m_linkIdMap.find(linkId); if (linkIterator != m_linkIdMap.end()) { - return AreDirtyTemplatesPresent(linkIterator->second.GetSourceTemplateId()); + if (AreDirtyTemplatesPresent(linkIterator->second.GetSourceTemplateId())) + { + return true; + } + else + { + continue; + } } } return false; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/SourceControlAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/SourceControlAPI.h index df9b136752..5eb4a31ffb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/SourceControlAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/SourceControlAPI.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp index f98638fd69..7a9a5a4d7a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp @@ -119,11 +119,12 @@ namespace AzToolsFramework // replace the default input handler with one specific for dealing with // entity selection in the viewport + EditorInteractionSystemViewportSelectionRequestBus::Event( GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler, - [](const EditorVisibleEntityDataCache* entityDataCache) + [](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker) { - return AZStd::make_unique(entityDataCache); + return AZStd::make_unique(entityDataCache, viewportEditorModeTracker); }); if (!pickModeEntityContextId.IsNull()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index b3a660d0f2..c4aefecce5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -166,11 +167,12 @@ namespace UnitTest m_editorActions.Connect(); const auto viewportHandlerBuilder = - [this](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache) + [this](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache, + [[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker) { // create the default viewport (handles ComponentMode) AZStd::unique_ptr defaultSelection = - AZStd::make_unique(entityDataCache); + AZStd::make_unique(entityDataCache, viewportEditorModeTracker); // override the phantom widget so we can use out custom test widget defaultSelection->SetOverridePhantomWidget(&m_editorActions.m_componentModeWidget); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp index 7903668409..30958cfbc1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp @@ -9,6 +9,7 @@ #include "EditorDefaultSelection.h" #include +#include #include #include #include @@ -19,21 +20,26 @@ namespace AzToolsFramework { AZ_CLASS_ALLOCATOR_IMPL(EditorDefaultSelection, AZ::SystemAllocator, 0) - EditorDefaultSelection::EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache) + EditorDefaultSelection::EditorDefaultSelection( + const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker) : m_phantomWidget(nullptr) , m_entityDataCache(entityDataCache) + , m_viewportEditorModeTracker(viewportEditorModeTracker) + , m_componentModeCollection(viewportEditorModeTracker) { ActionOverrideRequestBus::Handler::BusConnect(GetEntityContextId()); ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusConnect(); m_manipulatorManager = AZStd::make_shared(AzToolsFramework::g_mainManipulatorManagerId); m_transformComponentSelection = AZStd::make_unique(entityDataCache); + m_viewportEditorModeTracker->ActivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Default); } EditorDefaultSelection::~EditorDefaultSelection() { ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusDisconnect(); ActionOverrideRequestBus::Handler::BusDisconnect(); + m_viewportEditorModeTracker->DeactivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Default); } void EditorDefaultSelection::SetOverridePhantomWidget(QWidget* phantomOverrideWidget) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h index 5763bf227c..e4c794e99e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h @@ -15,6 +15,8 @@ namespace AzToolsFramework { + class ViewportEditorModeTrackerInterface; + //! The default selection/input handler for the editor (includes handling ComponentMode). class EditorDefaultSelection : public ViewportInteraction::InternalViewportSelectionRequests @@ -25,7 +27,7 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR_DECL //! @cond - explicit EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache); + EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker); EditorDefaultSelection(const EditorDefaultSelection&) = delete; EditorDefaultSelection& operator=(const EditorDefaultSelection&) = delete; virtual ~EditorDefaultSelection(); @@ -110,5 +112,7 @@ namespace AzToolsFramework AZStd::shared_ptr m_manipulatorManager; //!< The default manipulator manager. ViewportInteraction::MouseInteraction m_currentInteraction; //!< Current mouse interaction to be used for drawing manipulators. + ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes. + }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp index 7002436d13..5d03231aab 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp @@ -10,9 +10,24 @@ #include #include +#include namespace AzToolsFramework { + EditorInteractionSystemComponent::EditorInteractionSystemComponent() + : m_viewportEditorMode(AZStd::make_unique()) + { + AZ_Assert(AZ::Interface::Get() == nullptr, "Unexpected registration of viewport editor mode tracker.") + AZ::Interface::Register(m_viewportEditorMode.get()); + } + + EditorInteractionSystemComponent::~EditorInteractionSystemComponent() + { + m_interactionRequests.reset(); + AZ_Assert(AZ::Interface::Get() != nullptr, "Unexpected unregistration of viewport editor mode tracker.") + AZ::Interface::Unregister(m_viewportEditorMode.get()); + } + void EditorInteractionSystemComponent::Activate() { EditorInteractionSystemViewportSelectionRequestBus::Handler::BusConnect(GetEntityContextId()); @@ -41,7 +56,8 @@ namespace AzToolsFramework return m_interactionRequests->InternalHandleMouseManipulatorInteraction(mouseInteraction); } - void EditorInteractionSystemComponent::SetHandler(const ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder) + void EditorInteractionSystemComponent::SetHandler( + const ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder) { // when setting a handler, make sure we're connected to the ViewportDebugDisplayEventBus so we // can forward calls to the specific type implementing ViewportSelectionRequests @@ -59,7 +75,7 @@ namespace AzToolsFramework m_entityDataCache = AZStd::make_unique(); m_interactionRequests.reset(); // BusConnect/Disconnect in constructor/destructor, // so have to reset before assigning the new one - m_interactionRequests = interactionRequestsBuilder(m_entityDataCache.get()); + m_interactionRequests = interactionRequestsBuilder(m_entityDataCache.get(), m_viewportEditorMode.get()); } EditorInteractionSystemViewportSelectionRequestBus::Handler::BusConnect(GetEntityContextId()); @@ -68,9 +84,9 @@ namespace AzToolsFramework void EditorInteractionSystemComponent::SetDefaultHandler() { SetHandler( - [](const EditorVisibleEntityDataCache* entityDataCache) + [](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker) { - return AZStd::make_unique(entityDataCache); + return AZStd::make_unique(entityDataCache, viewportEditorModeTracker); }); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h index 17521eab14..856fd2e326 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h @@ -14,6 +14,8 @@ namespace AzToolsFramework { + class ViewportEditorModeTracker; + //! System Component to wrap active input handler. //! EditorInteractionSystemComponent is notified of viewport mouse events from RenderViewport //! and forwards them to a concrete implementation of ViewportSelectionRequests. @@ -26,6 +28,9 @@ namespace AzToolsFramework public: AZ_COMPONENT(EditorInteractionSystemComponent, "{146D0317-AF42-45AB-A953-F54198525DD5}") + EditorInteractionSystemComponent(); + ~EditorInteractionSystemComponent(); + static void Reflect(AZ::ReflectContext* context); // EditorInteractionSystemViewportSelectionRequestBus @@ -54,5 +59,7 @@ namespace AzToolsFramework AZStd::unique_ptr m_interactionRequests; //!< Hold a concrete implementation of //!< ViewportSelectionRequests to handle viewport //!< input and drawing for the Editor. + + AZStd::unique_ptr m_viewportEditorMode; //!< Editor mode tracker for each viewport. }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h index ee3f83f74d..3579460ca0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h @@ -17,6 +17,7 @@ namespace AzToolsFramework { class EditorVisibleEntityDataCache; + class ViewportEditorModeTrackerInterface; //! Bus to handle all mouse events originating from the viewport. //! Coordinated by the EditorInteractionSystemComponent @@ -32,8 +33,8 @@ namespace AzToolsFramework }; //! Alias for factory function to create a new type implementing the ViewportSelectionRequests interface. - using ViewportSelectionRequestsBuilderFn = - AZStd::function(const EditorVisibleEntityDataCache*)>; + using ViewportSelectionRequestsBuilderFn = AZStd::function( + const EditorVisibleEntityDataCache*, ViewportEditorModeTrackerInterface*)>; //! Interface for system component implementing the ViewportSelectionRequests interface. //! This interface also includes a setter to set a custom handler also implementing diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp index ea1bc73056..18eda140a0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp @@ -8,6 +8,7 @@ #include "EditorPickEntitySelection.h" +#include #include #include @@ -15,9 +16,12 @@ namespace AzToolsFramework { AZ_CLASS_ALLOCATOR_IMPL(EditorPickEntitySelection, AZ::SystemAllocator, 0) - EditorPickEntitySelection::EditorPickEntitySelection(const EditorVisibleEntityDataCache* entityDataCache) + EditorPickEntitySelection::EditorPickEntitySelection( + const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker) : m_editorHelpers(AZStd::make_unique(entityDataCache)) + , m_viewportEditorModeTracker(viewportEditorModeTracker) { + m_viewportEditorModeTracker->ActivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Pick); } EditorPickEntitySelection::~EditorPickEntitySelection() @@ -26,6 +30,8 @@ namespace AzToolsFramework { ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, m_hoveredEntityId, false); } + + m_viewportEditorModeTracker->DeactivateMode({ /* DefaultViewportId */ }, ViewportEditorMode::Pick); } // note: entityIdUnderCursor is the authoritative entityId we get each frame by querying diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h index e8d83af932..62fa4161b7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h @@ -13,6 +13,8 @@ namespace AzToolsFramework { + class ViewportEditorModeTrackerInterface; + //! Viewport interaction that will handle assigning an entity in the viewport to //! an entity field in the entity inspector. class EditorPickEntitySelection : public ViewportInteraction::InternalViewportSelectionRequests @@ -20,7 +22,8 @@ namespace AzToolsFramework public: AZ_CLASS_ALLOCATOR_DECL - EditorPickEntitySelection(const EditorVisibleEntityDataCache* entityDataCache); + EditorPickEntitySelection( + const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker); ~EditorPickEntitySelection(); private: @@ -32,5 +35,6 @@ namespace AzToolsFramework AZStd::unique_ptr m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc). AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any). AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display. + ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes. }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.cpp index 4adddb02e1..105712c789 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.cpp @@ -45,22 +45,6 @@ namespace AzToolsFramework return m_editorModes[static_cast(mode)]; } - void ViewportEditorModeTracker::RegisterInterface() - { - if (AZ::Interface::Get() == nullptr) - { - AZ::Interface::Register(this); - } - } - - void ViewportEditorModeTracker::UnregisterInterface() - { - if (AZ::Interface::Get() != nullptr) - { - AZ::Interface::Unregister(this); - } - } - AZ::Outcome ViewportEditorModeTracker::ActivateMode( const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h index 6ae68b39b2..5b382c44e7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h @@ -41,12 +41,6 @@ namespace AzToolsFramework : public ViewportEditorModeTrackerInterface { public: - //! Registers this object with the AZ::Interface. - void RegisterInterface(); - - //! Unregisters this object with the AZ::Interface. - void UnregisterInterface(); - // ViewportEditorModeTrackerInterface overrides ... AZ::Outcome ActivateMode(const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode) override; AZ::Outcome DeactivateMode(const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp index e933940d95..372587c110 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp @@ -29,13 +29,29 @@ namespace AzToolsFramework::ViewportUi::Internal void ButtonGroup::SetHighlightedButton(ButtonId buttonId) { + if (buttonId == m_highlightedButtonId) // the requested button is highlighted, so do nothing. + { + return; + } + if (auto buttonEntry = m_buttons.find(buttonId); buttonEntry != m_buttons.end()) { - for (auto& button : m_buttons) - { - button.second->m_state = Button::State::Deselected; - } + ClearHighlightedButton(); buttonEntry->second->m_state = Button::State::Selected; + m_highlightedButtonId = buttonId; + } + } + + void ButtonGroup::ClearHighlightedButton() + { + if (m_highlightedButtonId == InvalidButtonId) + { + return; + } + if (auto buttonEntry = m_buttons.find(m_highlightedButtonId); buttonEntry != m_buttons.end()) + { + buttonEntry->second->m_state = Button::State::Deselected; + m_highlightedButtonId = InvalidButtonId; } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h index 0500a80c36..7b6864a71b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h @@ -8,6 +8,7 @@ #pragma once +#include #include namespace AzToolsFramework::ViewportUi::Internal @@ -24,6 +25,7 @@ namespace AzToolsFramework::ViewportUi::Internal ~ButtonGroup() = default; void SetHighlightedButton(ButtonId buttonId); + void ClearHighlightedButton(); void SetViewportUiElementId(ViewportUiElementId id); ViewportUiElementId GetViewportUiElementId() const; @@ -39,5 +41,6 @@ namespace AzToolsFramework::ViewportUi::Internal AZ::Event m_buttonTriggeredEvent; ViewportUiElementId m_viewportUiId; AZStd::unordered_map> m_buttons; + ButtonId m_highlightedButtonId = InvalidButtonId; }; } // namespace AzToolsFramework::ViewportUi::Internal diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp index cee4a311e8..255d11f561 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp @@ -50,6 +50,16 @@ namespace AzToolsFramework::ViewportUi } } + void ViewportUiManager::ClearClusterActiveButton(ClusterId clusterId) + { + if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end()) + { + auto cluster = clusterIt->second; + cluster->ClearHighlightedButton(); + UpdateButtonGroupUi(cluster.get()); + } + } + void ViewportUiManager::SetSwitcherActiveButton(const SwitcherId switcherId, const ButtonId buttonId) { if (auto switcherIt = m_switcherButtonGroups.find(switcherId); switcherIt != m_switcherButtonGroups.end()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h index c5ecf7aee6..9ec6648451 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h @@ -30,6 +30,7 @@ namespace AzToolsFramework::ViewportUi const ClusterId CreateCluster(Alignment align) override; const SwitcherId CreateSwitcher(Alignment align) override; void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override; + void ClearClusterActiveButton(ClusterId clusterId) override; void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override; void SetClusterButtonLocked(ClusterId clusterId, ButtonId buttonId, bool isLocked) override; void SetClusterButtonTooltip(ClusterId clusterId, ButtonId buttonId, const AZStd::string& tooltip) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h index 649186c7e7..108d23950a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h @@ -59,6 +59,8 @@ namespace AzToolsFramework::ViewportUi virtual const SwitcherId CreateSwitcher(Alignment align) = 0; //! Sets the active button of the cluster. This is the button which will display as highlighted. virtual void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) = 0; + //! Clears the active button of the cluster if one is active. The button will no longer display as highlighted. + virtual void ClearClusterActiveButton(ClusterId clusterId) = 0; //! Sets the active button of the switcher. This is the button which has a text label. virtual void SetSwitcherActiveButton(SwitcherId clusterId, ButtonId buttonId) = 0; //! Adds a locked overlay to the cluster button's icon. diff --git a/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.cpp b/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.cpp new file mode 100644 index 0000000000..11a077f53c --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.cpp @@ -0,0 +1,60 @@ +/* + * 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 + +#include + +namespace UnitTest +{ + AZ::Aabb BoundsTestComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) + { + return GetWorldBounds(); + } + + bool BoundsTestComponent::EditorSelectionIntersectRayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) + { + return AzToolsFramework::AabbIntersectRay(src, dir, GetWorldBounds(), distance); + } + + bool BoundsTestComponent::SupportsEditorRayIntersect() + { + return true; + } + + void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) + { + // noop + } + + void BoundsTestComponent::Activate() + { + AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId()); + AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); + } + + void BoundsTestComponent::Deactivate() + { + AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); + AzFramework::BoundsRequestBus::Handler::BusDisconnect(); + } + + AZ::Aabb BoundsTestComponent::GetWorldBounds() + { + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); + return GetLocalBounds().GetTransformedAabb(worldFromLocal); + } + + AZ::Aabb BoundsTestComponent::GetLocalBounds() + { + return AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f)); + } + +} // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.h b/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.h new file mode 100644 index 0000000000..1aabcfcd64 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/BoundsTestComponent.h @@ -0,0 +1,46 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include + +namespace UnitTest +{ + //! Basic component that implements BoundsRequestBus and EditorComponentSelectionRequestsBus to be compatible + //! with the Editor visibility system. + //! Note: Used for simulating selection (picking) in the viewport. + class BoundsTestComponent + : public AzToolsFramework::Components::EditorComponentBase + , public AzFramework::BoundsRequestBus::Handler + , public AzToolsFramework::EditorComponentSelectionRequestsBus::Handler + { + public: + AZ_EDITOR_COMPONENT( + BoundsTestComponent, "{E6312E9D-8489-4677-9980-C93C328BC92C}", AzToolsFramework::Components::EditorComponentBase); + + static void Reflect(AZ::ReflectContext* context); + + // AZ::Component overrides ... + void Activate() override; + void Deactivate() override; + + // EditorComponentSelectionRequestsBus overrides ... + AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override; + bool EditorSelectionIntersectRayViewport( + const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; + bool SupportsEditorRayIntersect() override; + + // BoundsRequestBus overrides ... + AZ::Aabb GetWorldBounds() override; + AZ::Aabb GetLocalBounds() override; + }; + +} // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 52470f41e3..81909ac511 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -22,12 +21,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -41,6 +38,8 @@ #include #include +#include + namespace AZ { std::ostream& operator<<(std::ostream& os, const EntityId entityId) @@ -123,80 +122,6 @@ namespace UnitTest EXPECT_FALSE(m_cache.IsVisibleEntityVisible(m_cache.GetVisibleEntityIndexFromId(m_entityIds[2]).value())); } - //! Basic component that implements BoundsRequestBus and EditorComponentSelectionRequestsBus to be compatible - //! with the Editor visibility system. - //! Note: Used for simulating selection (picking) in the viewport. - class BoundsTestComponent - : public AzToolsFramework::Components::EditorComponentBase - , public AzFramework::BoundsRequestBus::Handler - , public AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - { - public: - AZ_EDITOR_COMPONENT( - BoundsTestComponent, "{E6312E9D-8489-4677-9980-C93C328BC92C}", AzToolsFramework::Components::EditorComponentBase); - - static void Reflect(AZ::ReflectContext* context); - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override; - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - }; - - AZ::Aabb BoundsTestComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) - { - return GetWorldBounds(); - } - - bool BoundsTestComponent::EditorSelectionIntersectRayViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) - { - return AzToolsFramework::AabbIntersectRay(src, dir, GetWorldBounds(), distance); - } - - bool BoundsTestComponent::SupportsEditorRayIntersect() - { - return true; - } - - void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) - { - // noop - } - - void BoundsTestComponent::Activate() - { - AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); - } - - void BoundsTestComponent::Deactivate() - { - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - } - - AZ::Aabb BoundsTestComponent::GetWorldBounds() - { - AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - return GetLocalBounds().GetTransformedAabb(worldFromLocal); - } - - AZ::Aabb BoundsTestComponent::GetLocalBounds() - { - return AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f)); - } - // Fixture to support testing EditorTransformComponentSelection functionality on an Entity selection. class EditorTransformComponentSelectionFixture : public ToolsApplicationFixture { @@ -344,9 +269,10 @@ namespace UnitTest using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; EditorInteractionSystemViewportSelectionRequestBus::Event( AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler, - [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache) + [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache, + [[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker) { - return AZStd::make_unique(entityDataCache); + return AZStd::make_unique(entityDataCache, viewportEditorModeTracker); }); // When diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp new file mode 100644 index 0000000000..bc026a4baf --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp @@ -0,0 +1,78 @@ +/* + * 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 + +#include + +#include + +namespace AzToolsFramework +{ + void EditorFocusModeFixture::SetUpEditorFixtureImpl() + { + // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is + // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash + // in the unit tests. + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + + m_focusModeInterface = AZ::Interface::Get(); + ASSERT_TRUE(m_focusModeInterface != nullptr); + + // register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus + GetApplication()->RegisterComponentDescriptor(UnitTest::BoundsTestComponent::CreateDescriptor()); + + GenerateTestHierarchy(); + } + + void EditorFocusModeFixture::GenerateTestHierarchy() + { + /* + * City + * |_ Street + * |_ Car + * | |_ Passenger + * |_ SportsCar + * |_ Passenger + */ + + m_entityMap[CityEntityName] = CreateEditorEntity(CityEntityName, AZ::EntityId()); + m_entityMap[StreetEntityName] = CreateEditorEntity(StreetEntityName, m_entityMap[CityEntityName]); + m_entityMap[CarEntityName] = CreateEditorEntity(CarEntityName, m_entityMap[StreetEntityName]); + m_entityMap[Passenger1EntityName] = CreateEditorEntity(Passenger1EntityName, m_entityMap[CarEntityName]); + m_entityMap[SportsCarEntityName] = CreateEditorEntity(SportsCarEntityName, m_entityMap[StreetEntityName]); + m_entityMap[Passenger2EntityName] = CreateEditorEntity(Passenger2EntityName, m_entityMap[SportsCarEntityName]); + + // Add a BoundsTestComponent to the Car entity. + AZ::Entity* entity = GetEntityById(m_entityMap[CarEntityName]); + + entity->Deactivate(); + entity->CreateComponent(); + entity->Activate(); + + // Move the CarEntity so it's out of the way. + AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, CarEntityPosition); + + // Setup the camera so the Car entity is in view. + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 0.0f)), CameraPosition)); + } + + AZ::EntityId EditorFocusModeFixture::CreateEditorEntity(const char* name, AZ::EntityId parentId) + { + AZ::Entity* entity = nullptr; + UnitTest::CreateDefaultEditorEntity(name, &entity); + + // Parent + AZ::TransformBus::Event(entity->GetId(), &AZ::TransformInterface::SetParent, parentId); + + return entity->GetId(); + } +} diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h new file mode 100644 index 0000000000..a461b45e1b --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h @@ -0,0 +1,48 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +namespace AzToolsFramework +{ + class EditorFocusModeFixture + : public UnitTest::ToolsApplicationFixture + { + protected: + void SetUpEditorFixtureImpl() override; + + void GenerateTestHierarchy(); + AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId); + + AZStd::unordered_map m_entityMap; + FocusModeInterface* m_focusModeInterface = nullptr; + + public: + AzFramework::CameraState m_cameraState; + + inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f); + + inline static const char* CityEntityName = "City"; + inline static const char* StreetEntityName = "Street"; + inline static const char* CarEntityName = "Car"; + inline static const char* SportsCarEntityName = "SportsCar"; + inline static const char* Passenger1EntityName = "Passenger1"; + inline static const char* Passenger2EntityName = "Passenger2"; + + inline static AZ::Vector3 CarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); + }; +} diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp new file mode 100644 index 0000000000..750137814d --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp @@ -0,0 +1,135 @@ +/* + * 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 + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace AzToolsFramework +{ + class EditorFocusModeSelectionFixture + : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin + { + public: + void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition) + { + // Calculate the world position in screen space + const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState); + + // Click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + } + }; + + void ClearSelectedEntities() + { + AzToolsFramework::ToolsApplicationRequestBus::Broadcast( + &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList()); + } + + AzToolsFramework::EntityIdList GetSelectedEntities() + { + AzToolsFramework::EntityIdList selectedEntities; + AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult( + selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities); + return selectedEntities; + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnLevel) + { + // Clear the focus, disabling focus mode + m_focusModeInterface->ClearFocusRoot(); + // Clear selection + ClearSelectedEntities(); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(CarEntityPosition); + + // Verify entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnAncestor) + { + // Set the focus on the Street Entity (parent of the test entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); + // Clear selection + ClearSelectedEntities(); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(CarEntityPosition); + + // Verify entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnItself) + { + // Set the focus on the Car Entity (test entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); + // Clear selection + ClearSelectedEntities(); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(CarEntityPosition); + + // Verify entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnSibling) + { + // Set the focus on the SportsCar Entity (sibling of the test entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]); + // Clear selection + ClearSelectedEntities(); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(CarEntityPosition); + + // entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 0); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnDescendant) + { + // Set the focus on the Passenger1 Entity (child of the entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); + // Clear selection + ClearSelectedEntities(); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(CarEntityPosition); + + // entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 0); + } +} diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp index 5972da58a7..7dfdff655a 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp @@ -6,123 +6,99 @@ * */ -#include -#include -#include -#include -#include +#include namespace AzToolsFramework { - class EditorFocusModeTests - : public ::testing::Test + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_SetFocus) { - protected: - void SetUp() override - { - m_app.Start(m_descriptor); + // When an entity is set as the focus root, GetFocusRoot should return its EntityId. + m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); + EXPECT_EQ(m_focusModeInterface->GetFocusRoot(), m_entityMap[CarEntityName]); - // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is - // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash - // in the unit tests. - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - - GenerateTestHierarchy(); - } - - void GenerateTestHierarchy() - { - /* - * City - * |_ Street - * |_ Car - * | |_ Passenger - * |_ SportsCar - * |_ Passenger - */ - - m_entityMap["cityId"] = CreateEditorEntity("City", AZ::EntityId()); - m_entityMap["streetId"] = CreateEditorEntity("Street", m_entityMap["cityId"]); - m_entityMap["carId"] = CreateEditorEntity("Car", m_entityMap["streetId"]); - m_entityMap["passengerId1"] = CreateEditorEntity("Passenger", m_entityMap["carId"]); - m_entityMap["sportsCarId"] = CreateEditorEntity("SportsCar", m_entityMap["streetId"]); - m_entityMap["passengerId2"] = CreateEditorEntity("Passenger", m_entityMap["sportsCarId"]); - } - - AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId) - { - AZ::Entity* entity = nullptr; - UnitTest::CreateDefaultEditorEntity(name, &entity); - - // Parent - AZ::TransformBus::Event(entity->GetId(), &AZ::TransformInterface::SetParent, parentId); - - return entity->GetId(); - } - - void TearDown() override - { - m_app.Stop(); - } - - UnitTest::ToolsTestApplication m_app{ "EditorFocusModeTests" }; - AZ::ComponentApplication::Descriptor m_descriptor; - AZStd::unordered_map m_entityMap; - }; - - TEST_F(EditorFocusModeTests, EditorFocusModeTests_SetFocus) - { - FocusModeInterface* focusModeInterface = AZ::Interface::Get(); - EXPECT_TRUE(focusModeInterface != nullptr); - - focusModeInterface->SetFocusRoot(m_entityMap["carId"]); - EXPECT_EQ(focusModeInterface->GetFocusRoot(), m_entityMap["carId"]); - - focusModeInterface->ClearFocusRoot(); - EXPECT_EQ(focusModeInterface->GetFocusRoot(), AZ::EntityId()); + // Restore default expected focus. + m_focusModeInterface->ClearFocusRoot(); } - TEST_F(EditorFocusModeTests, EditorFocusModeTests_IsInFocusSubTree) + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_ClearFocus) { - FocusModeInterface* focusModeInterface = AZ::Interface::Get(); - EXPECT_TRUE(focusModeInterface != nullptr); + // Change the value from the default. + m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); - focusModeInterface->ClearFocusRoot(); - - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true); + // Calling ClearFocusRoot restores the default focus root (which is an invalid EntityId). + m_focusModeInterface->ClearFocusRoot(); + EXPECT_EQ(m_focusModeInterface->GetFocusRoot(), AZ::EntityId()); + } - focusModeInterface->SetFocusRoot(m_entityMap["streetId"]); + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_AncestorsDescendants) + { + // When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't. + { + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); + } - focusModeInterface->SetFocusRoot(m_entityMap["carId"]); + // Restore default expected focus. + m_focusModeInterface->ClearFocusRoot(); + } - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), true); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), false); + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Siblings) + { + // If the root entity has siblings, they are also outside of the focus subtree. + { + m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); - focusModeInterface->SetFocusRoot(m_entityMap["passengerId2"]); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false); + } - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["cityId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["streetId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["carId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId1"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["sportsCarId"]), false); - EXPECT_EQ(focusModeInterface->IsInFocusSubTree(m_entityMap["passengerId2"]), true); + // Restore default expected focus. + m_focusModeInterface->ClearFocusRoot(); + } - focusModeInterface->ClearFocusRoot(); + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Leaf) + { + // If the root is a leaf, then the focus subtree will consists of just that entity. + { + m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]); + + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); + } + + // Restore default expected focus. + m_focusModeInterface->ClearFocusRoot(); + } + + TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Clear) + { + // Change the value from the default. + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); + + // When the focus is cleared, the whole level is in the focus subtree; so we expect all entities to return true. + { + m_focusModeInterface->ClearFocusRoot(); + + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); + } } } diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp index ffd6cd2a44..d3c3a2250b 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp @@ -30,88 +30,127 @@ namespace UnitTest * |_ Passenger */ - m_entityMap["passenger1"] = CreateEntity("Passenger1"); - m_entityMap["passenger2"] = CreateEntity("Passenger2"); - m_entityMap["city"] = CreateEntity("City"); + // Create loose entities + m_entityMap[Passenger1EntityName] = CreateEntity(Passenger1EntityName); + m_entityMap[Passenger2EntityName] = CreateEntity(Passenger2EntityName); + m_entityMap[CityEntityName] = CreateEntity(CityEntityName); + // Call HandleEntitiesAdded to the loose entities to register them with the Prefab EOS AzToolsFramework::EditorEntityContextRequestBus::Broadcast( &AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, - AzToolsFramework::EntityList{ m_entityMap["passenger1"], m_entityMap["passenger2"], m_entityMap["city"] }); + AzToolsFramework::EntityList{ m_entityMap[Passenger1EntityName], m_entityMap[Passenger2EntityName], m_entityMap[CityEntityName] }); + // Create a car prefab from the passenger1 entity. The container entity will be created as part of the process. AZStd::unique_ptr carInstance = - m_prefabSystemComponent->CreatePrefab({ m_entityMap["passenger1"] }, {}, "test/car"); + m_prefabSystemComponent->CreatePrefab({ m_entityMap[Passenger1EntityName] }, {}, "test/car"); ASSERT_TRUE(carInstance); - m_instanceMap["car"] = carInstance.get(); + m_instanceMap[CarEntityName] = carInstance.get(); + // Create a sportscar prefab from the passenger2 entity. The container entity will be created as part of the process. AZStd::unique_ptr sportsCarInstance = - m_prefabSystemComponent->CreatePrefab({ m_entityMap["passenger2"] }, {}, "test/sportsCar"); + m_prefabSystemComponent->CreatePrefab({ m_entityMap[Passenger2EntityName] }, {}, "test/sportsCar"); ASSERT_TRUE(sportsCarInstance); - m_instanceMap["sportsCar"] = sportsCarInstance.get(); + m_instanceMap[SportsCarEntityName] = sportsCarInstance.get(); + // Create a street prefab that nests the car and sportscar instances created above. The container entity will be created as part of the process. AZStd::unique_ptr streetInstance = m_prefabSystemComponent->CreatePrefab({}, MakeInstanceList( AZStd::move(carInstance), AZStd::move(sportsCarInstance) ), "test/street"); ASSERT_TRUE(streetInstance); - m_instanceMap["street"] = streetInstance.get(); + m_instanceMap[StreetEntityName] = streetInstance.get(); + // Create a city prefab that nests the street instances created above and the city entity. The container entity will be created as part of the process. m_rootInstance = - m_prefabSystemComponent->CreatePrefab({ m_entityMap["city"] }, MakeInstanceList(AZStd::move(streetInstance)), "test/city"); + m_prefabSystemComponent->CreatePrefab({ m_entityMap[CityEntityName] }, MakeInstanceList(AZStd::move(streetInstance)), "test/city"); ASSERT_TRUE(m_rootInstance); - m_instanceMap["city"] = m_rootInstance.get(); + m_instanceMap[CityEntityName] = m_rootInstance.get(); + } + + void SetUpEditorFixtureImpl() override + { + PrefabTestFixture::SetUpEditorFixtureImpl(); + + m_prefabFocusInterface = AZ::Interface::Get(); + ASSERT_TRUE(m_prefabFocusInterface != nullptr); + + GenerateTestHierarchy(); + } + + void TearDownEditorFixtureImpl() override + { + m_rootInstance.release(); + + PrefabTestFixture::TearDownEditorFixtureImpl(); } AZStd::unordered_map m_entityMap; AZStd::unordered_map m_instanceMap; AZStd::unique_ptr m_rootInstance; + + PrefabFocusInterface* m_prefabFocusInterface = nullptr; + + inline static const char* CityEntityName = "City"; + inline static const char* StreetEntityName = "Street"; + inline static const char* CarEntityName = "Car"; + inline static const char* SportsCarEntityName = "SportsCar"; + inline static const char* Passenger1EntityName = "Passenger1"; + inline static const char* Passenger2EntityName = "Passenger2"; }; - TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab) + TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab_RootContainer) { - GenerateTestHierarchy(); - - PrefabFocusInterface* prefabFocusInterface = AZ::Interface::Get(); - EXPECT_TRUE(prefabFocusInterface != nullptr); - // Verify FocusOnOwningPrefab works when passing the container entity of the root prefab. { - prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["city"]->GetContainerEntityId()); - EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["city"]->GetTemplateId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); + EXPECT_EQ(m_prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap[CityEntityName]->GetTemplateId()); - auto instance = prefabFocusInterface->GetFocusedPrefabInstance(); + auto instance = m_prefabFocusInterface->GetFocusedPrefabInstance(); EXPECT_TRUE(instance.has_value()); - EXPECT_EQ(&instance->get(), m_instanceMap["city"]); + EXPECT_EQ(&instance->get(), m_instanceMap[CityEntityName]); } + } + TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab_RootEntity) + { // Verify FocusOnOwningPrefab works when passing a nested entity of the root prefab. { - prefabFocusInterface->FocusOnOwningPrefab(m_entityMap["city"]->GetId()); - EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["city"]->GetTemplateId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId()); + EXPECT_EQ(m_prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap[CityEntityName]->GetTemplateId()); - auto instance = prefabFocusInterface->GetFocusedPrefabInstance(); + auto instance = m_prefabFocusInterface->GetFocusedPrefabInstance(); EXPECT_TRUE(instance.has_value()); - EXPECT_EQ(&instance->get(), m_instanceMap["city"]); + EXPECT_EQ(&instance->get(), m_instanceMap[CityEntityName]); } + } + TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab_NestedContainer) + { // Verify FocusOnOwningPrefab works when passing the container entity of a nested prefab. { - prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["car"]->GetContainerEntityId()); - EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["car"]->GetTemplateId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId()); + EXPECT_EQ(m_prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap[CarEntityName]->GetTemplateId()); - auto instance = prefabFocusInterface->GetFocusedPrefabInstance(); + auto instance = m_prefabFocusInterface->GetFocusedPrefabInstance(); EXPECT_TRUE(instance.has_value()); - EXPECT_EQ(&instance->get(), m_instanceMap["car"]); + EXPECT_EQ(&instance->get(), m_instanceMap[CarEntityName]); } + } + TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab_NestedEntity) + { // Verify FocusOnOwningPrefab works when passing a nested entity of the a nested prefab. { - prefabFocusInterface->FocusOnOwningPrefab(m_entityMap["passenger1"]->GetId()); - EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap["car"]->GetTemplateId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId()); + EXPECT_EQ(m_prefabFocusInterface->GetFocusedPrefabTemplateId(), m_instanceMap[CarEntityName]->GetTemplateId()); - auto instance = prefabFocusInterface->GetFocusedPrefabInstance(); + auto instance = m_prefabFocusInterface->GetFocusedPrefabInstance(); EXPECT_TRUE(instance.has_value()); - EXPECT_EQ(&instance->get(), m_instanceMap["car"]); + EXPECT_EQ(&instance->get(), m_instanceMap[CarEntityName]); } + } + TEST_F(PrefabFocusTests, PrefabFocus_FocusOnOwningPrefab_Clear) + { // Verify FocusOnOwningPrefab points to the root prefab when the focus is cleared. { AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipInterface = @@ -120,54 +159,51 @@ namespace UnitTest prefabEditorEntityOwnershipInterface->GetRootPrefabInstance(); EXPECT_TRUE(rootPrefabInstance.has_value()); - prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId()); - EXPECT_EQ(prefabFocusInterface->GetFocusedPrefabTemplateId(), rootPrefabInstance->get().GetTemplateId()); + m_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId()); + EXPECT_EQ(m_prefabFocusInterface->GetFocusedPrefabTemplateId(), rootPrefabInstance->get().GetTemplateId()); - auto instance = prefabFocusInterface->GetFocusedPrefabInstance(); + auto instance = m_prefabFocusInterface->GetFocusedPrefabInstance(); EXPECT_TRUE(instance.has_value()); EXPECT_EQ(&instance->get(), &rootPrefabInstance->get()); } - - m_rootInstance.release(); } - TEST_F(PrefabFocusTests, PrefabFocus_IsOwningPrefabBeingFocused) + TEST_F(PrefabFocusTests, PrefabFocus_IsOwningPrefabBeingFocused_Content) { - GenerateTestHierarchy(); - - PrefabFocusInterface* prefabFocusInterface = AZ::Interface::Get(); - EXPECT_TRUE(prefabFocusInterface != nullptr); - // Verify IsOwningPrefabBeingFocused returns true for all entities in a focused prefab (container/nested) { - prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["city"]->GetContainerEntityId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); - EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["city"]->GetContainerEntityId())); - EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["city"]->GetId())); + EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); + EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); } + } + TEST_F(PrefabFocusTests, PrefabFocus_IsOwningPrefabBeingFocused_AncestorsDescendants) + { // Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (ancestors/descendants) { - prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["street"]->GetContainerEntityId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId()); - EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["street"]->GetContainerEntityId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["city"]->GetContainerEntityId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["city"]->GetId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["car"]->GetContainerEntityId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger1"]->GetId())); + EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); } + } + TEST_F(PrefabFocusTests, PrefabFocus_IsOwningPrefabBeingFocused_Siblings) + { // Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (siblings) { - prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap["sportsCar"]->GetContainerEntityId()); + m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()); - EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["sportsCar"]->GetContainerEntityId())); - EXPECT_TRUE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger2"]->GetId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap["car"]->GetContainerEntityId())); - EXPECT_FALSE(prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap["passenger1"]->GetId())); + EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId())); + EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); } - - m_rootInstance.release(); } } diff --git a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp index 3954ef6dc6..866d88b7ba 100644 --- a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp @@ -7,7 +7,9 @@ */ #include +#include #include +#include #include namespace UnitTest @@ -18,6 +20,7 @@ namespace UnitTest using ViewportEditorModeInfo = AzToolsFramework::ViewportEditorModeInfo; using ViewportId = ViewportEditorModeInfo::IdType; using ViewportEditorModesInterface = AzToolsFramework::ViewportEditorModesInterface; + using ViewportEditorModeTrackerInterface = AzToolsFramework::ViewportEditorModeTrackerInterface; void ActivateModeAndExpectSuccess(ViewportEditorModes& editorModeState, ViewportEditorMode mode) { @@ -47,6 +50,26 @@ namespace UnitTest } } + void ExpectOnlyModeActive(const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) + { + for (auto modeIndex = 0; modeIndex < ViewportEditorModes::NumEditorModes; modeIndex++) + { + const auto currentMode = static_cast(modeIndex); + const bool expectedActive = (mode == currentMode); + EXPECT_EQ(editorModeState.IsModeActive(currentMode), expectedActive); + } + } + + void ExpectOnlyModeInactive(const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) + { + for (auto modeIndex = 0; modeIndex < ViewportEditorModes::NumEditorModes; modeIndex++) + { + const auto currentMode = static_cast(modeIndex); + const bool expectedActive = (mode != currentMode); + EXPECT_EQ(editorModeState.IsModeActive(currentMode), expectedActive); + } + } + // Fixture for testing editor mode states class ViewportEditorModesTestsFixture : public ::testing::Test @@ -116,7 +139,7 @@ namespace UnitTest m_editorModes[mode].m_onEnter = true; } - virtual void OnEditorModeDeactivated([[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) override + void OnEditorModeDeactivated([[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) override { m_editorModes[mode].m_onExit = true; } @@ -152,6 +175,22 @@ namespace UnitTest AZStd::array, ViewportEditorModes::NumEditorModes> m_editorModeHandlers; }; + // Fixture for testing the integration of viewport editor mode state tracker + class ViewportEditorModeTrackerIntegrationTestFixture + : public ToolsApplicationFixture + { + public: + void SetUpEditorFixtureImpl() override + { + m_viewportEditorModeTracker = AZ::Interface::Get(); + ASSERT_NE(m_viewportEditorModeTracker, nullptr); + m_viewportEditorModes = m_viewportEditorModeTracker->GetViewportEditorModes({}); + } + + ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; + const ViewportEditorModesInterface* m_viewportEditorModes = nullptr; + }; + TEST_F(ViewportEditorModesTestsFixture, NumberOfEditorModesIsEqualTo4) { EXPECT_EQ(ViewportEditorModes::NumEditorModes, 4); @@ -168,38 +207,14 @@ namespace UnitTest TEST_P(ViewportEditorModesTestsFixtureWithParams, SettingModeActiveActivatesOnlyThatMode) { ActivateModeAndExpectSuccess(m_editorModes, m_selectedEditorMode); - - for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++) - { - const auto editorMode = static_cast(mode); - if (editorMode == m_selectedEditorMode) - { - EXPECT_TRUE(m_editorModes.IsModeActive(static_cast(editorMode))); - } - else - { - EXPECT_FALSE(m_editorModes.IsModeActive(static_cast(editorMode))); - } - } + ExpectOnlyModeActive(m_editorModes, m_selectedEditorMode); } TEST_P(ViewportEditorModesTestsFixtureWithParams, SettingModeInactiveInactivatesOnlyThatMode) { SetAllModesActive(m_editorModes); DeactivateModeAndExpectSuccess(m_editorModes, m_selectedEditorMode); - - for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++) - { - const auto editorMode = static_cast(mode); - if (editorMode == m_selectedEditorMode) - { - EXPECT_FALSE(m_editorModes.IsModeActive(editorMode)); - } - else - { - EXPECT_TRUE(m_editorModes.IsModeActive(editorMode)); - } - } + ExpectOnlyModeInactive(m_editorModes, m_selectedEditorMode); } TEST_P(ViewportEditorModesTestsFixtureWithParams, SettingMultipleModesActiveActivatesAllThoseModesNonMutuallyExclusively) @@ -298,7 +313,7 @@ namespace UnitTest EXPECT_EQ(m_viewportEditorModeTracker.GetTrackedViewportCount(), 0); } - TEST_F(ViewportEditorModeTrackerTestFixture, RegisteringViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatId) + TEST_F(ViewportEditorModeTrackerTestFixture, ActivatingViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatId) { // Given a viewport not currently being tracked const ViewportId viewportid = 0; @@ -318,7 +333,7 @@ namespace UnitTest EXPECT_TRUE(viewportEditorModeState->IsModeActive(editorMode)); } - TEST_F(ViewportEditorModeTrackerTestFixture, UnregisteringViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatIdButReturnsError) + TEST_F(ViewportEditorModeTrackerTestFixture, DeactivatingViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatIdButReturnsError) { // Given a viewport not currently being tracked const ViewportId viewportid = 0; @@ -351,7 +366,7 @@ namespace UnitTest EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr); } - TEST_F(ViewportEditorModeTrackerTestFixture, RegisteringViewportEditorModesForExistingIdInThatStateReturnsError) + TEST_F(ViewportEditorModeTrackerTestFixture, ActivatingViewportEditorModesForExistingIdInThatStateReturnsError) { // Given a viewport not currently tracked const ViewportId viewportid = 0; @@ -390,7 +405,7 @@ namespace UnitTest } } - TEST_F(ViewportEditorModeTrackerTestFixture, UnregisteringViewportEditorModesForExistingIdNotInThatStateReturnssError) + TEST_F(ViewportEditorModeTrackerTestFixture, DeactivatingViewportEditorModesForExistingIdNotInThatStateReturnssError) { // Given a viewport not currently tracked const ViewportId viewportid = 0; @@ -432,7 +447,7 @@ namespace UnitTest TEST_F( ViewportEditorModePublisherTestFixture, - RegisteringViewportEditorModesForExistingIdPublishesOnViewportEditorModeRegisterEventForAllSubscribers) + ActivatingViewportEditorModesForExistingIdPublishesOnViewportEditorModeActivateEventForAllSubscribers) { // Given a set of subscribers tracking the editor modes for their exclusive viewport for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++) @@ -465,7 +480,7 @@ namespace UnitTest TEST_F( ViewportEditorModePublisherTestFixture, - UnregisteringViewportEditorModesForExistingIdPublishesOnViewportEditorModeUnregisterEventForAllSubscribers) + DeactivatingViewportEditorModesForExistingIdPublishesOnViewportEditorModeDeactivatingEventForAllSubscribers) { // Given a set of subscribers tracking the editor modes for their exclusive viewport for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++) @@ -495,4 +510,54 @@ namespace UnitTest EXPECT_TRUE(expectedEditorModeSet->second.m_onExit); } } + + TEST_F(ViewportEditorModeTrackerIntegrationTestFixture, InitialViewportEditorModeIsDefault) + { + ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default); + } + + TEST_F( + ViewportEditorModeTrackerIntegrationTestFixture, EnteringComponentModeAfterInitialStateHasViewportEditorModesDefaultAndComponentModeActive) + { + // When component mode is entered + AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast( + &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode, + AZStd::vector{}); + + bool inComponentMode = false; + AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::BroadcastResult( + inComponentMode, &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::InComponentMode); + + // Expect to be in component mode + EXPECT_TRUE(inComponentMode); + + // Expect the default and component viewport editor modes to be active + EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default)); + EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component)); + + // Do not expect the pick and focus viewport editor modes to be active + EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick)); + EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus)); + } + + TEST_F( + ViewportEditorModeTrackerIntegrationTestFixture, + EnteringEditorPickEntitySelectionAfterInitialStateHasOnlyViewportEditorModePickModeActive) + { + // When entering pick mode + using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; + EditorInteractionSystemViewportSelectionRequestBus::Event( + AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler, + [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache, + [[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker) + { + return AZStd::make_unique(entityDataCache, viewportEditorModeTracker); + }); + + // Expect only the pick viewport editor mode to be active + ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Pick); + } + + // FocusMode integration tests will follow (LYN-6995) + } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp index 676b9c5e35..daf4b9c29a 100644 --- a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp @@ -127,6 +127,25 @@ namespace UnitTest EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Selected); } + TEST_F(ViewportUiManagerTestFixture, ClearClusterActiveButtonSetsButtonStateToDeselected) + { + // setup + auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft); + auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, ""); + + auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId); + auto button = clusterEntry->second->GetButton(buttonId); + + // first set a button to active + m_viewportManagerWrapper.GetViewportManager()->SetClusterActiveButton(clusterId, buttonId); + EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Selected); + + // clear the active button on the cluster + m_viewportManagerWrapper.GetViewportManager()->ClearClusterActiveButton(clusterId); + // the button should now be deselected + EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Deselected); + } + TEST_F(ViewportUiManagerTestFixture, RegisterClusterEventHandlerConnectsHandlerToClusterEvent) { auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft); diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index ecc7d17ccc..11ea5a0b38 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -12,6 +12,8 @@ set(FILES AssetFileInfoListComparison.cpp AssetSeedManager.cpp AssetSystemMocks.h + BoundsTestComponent.cpp + BoundsTestComponent.h ComponentAdapterTests.cpp ComponentAddRemove.cpp ComponentModeTestDoubles.cpp @@ -34,6 +36,9 @@ set(FILES EntityTestbed.h FileFunc.cpp FingerprintingTests.cpp + FocusMode/EditorFocusModeFixture.cpp + FocusMode/EditorFocusModeFixture.h + FocusMode/EditorFocusModeSelectionTests.cpp FocusMode/EditorFocusModeTests.cpp GenericComponentWrapperTest.cpp InstanceDataHierarchy.cpp diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index 2c70717e8f..3187095094 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -808,7 +808,7 @@ void CSystem::OpenBasicPaks() const char* const assetsDir = "@assets@"; // After game paks to have same search order as with files on disk - m_env.pCryPak->OpenPack(assetsDir, "Engine.pak"); + m_env.pCryPak->OpenPack(assetsDir, "engine.pak"); #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_15 @@ -1261,7 +1261,7 @@ AZ_POP_DISABLE_WARNING InlineInitializationProcessing("CSystem::Init Create console"); // Need to load the engine.pak that includes the config files needed during initialization - m_env.pCryPak->OpenPack("@assets@", "Engine.pak"); + m_env.pCryPak->OpenPack("@assets@", "engine.pak"); InitFileSystem_LoadEngineFolders(startupParams); diff --git a/Code/Tools/AssetProcessor/native/unittests/AssetProcessorServerUnitTests.h b/Code/Tools/AssetProcessor/native/unittests/AssetProcessorServerUnitTests.h index 209897fd6e..8358bc3d2e 100644 --- a/Code/Tools/AssetProcessor/native/unittests/AssetProcessorServerUnitTests.h +++ b/Code/Tools/AssetProcessor/native/unittests/AssetProcessorServerUnitTests.h @@ -11,6 +11,7 @@ #if !defined(Q_MOC_RUN) #include "UnitTestRunner.h" #include "native/utilities/IniConfiguration.h" +#include #include #endif diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 9ae3cc2c87..b9369b5bb0 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorStyleMessages.h b/Code/Tools/Standalone/Source/LUA/LUAEditorStyleMessages.h index 6ddc462e94..cf27245682 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorStyleMessages.h +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorStyleMessages.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/Gems/AWSClientAuth/Code/Include/Private/AWSClientAuthBus.h b/Gems/AWSClientAuth/Code/Include/Private/AWSClientAuthBus.h index 4e625a563c..63d5bb2a83 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/AWSClientAuthBus.h +++ b/Gems/AWSClientAuth/Code/Include/Private/AWSClientAuthBus.h @@ -9,6 +9,8 @@ #include +#include + namespace Aws { namespace CognitoIdentityProvider diff --git a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h index f0b9b45aff..39e96517a7 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h @@ -9,6 +9,7 @@ #include #include +#include #include diff --git a/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp b/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp index f111b972e4..798da14aa1 100644 --- a/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp +++ b/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include /////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h index f4ce51fc02..e40bf39923 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h @@ -56,8 +56,7 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// - virtual void OnBootstrapSceneReady([[maybe_unused]]AZ::RPI::Scene* bootstrapScene){} - virtual void OnFrameRateLimitChanged([[maybe_unused]]float fpsLimit){} + virtual void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) = 0; }; using NotificationBus = AZ::EBus; } // namespace Bootstrap diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h index fbf3bad935..21cc91420b 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h @@ -23,8 +23,6 @@ namespace AZ::Render::Bootstrap virtual AZ::RPI::ScenePtr GetOrCreateAtomSceneFromAzScene(AzFramework::Scene* scene) = 0; virtual bool EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext) = 0; - virtual float GetFrameRateLimit() const = 0; - virtual void SetFrameRateLimit(float fpsLimit) = 0; protected: ~Request() = default; diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index 8a6b7db1ca..1349bc34f9 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -42,14 +42,7 @@ #include #include -static void OnFrameRateLimitChanged(const float& fpsLimit) -{ - AZ::Render::Bootstrap::RequestBus::Broadcast( - &AZ::Render::Bootstrap::RequestBus::Events::SetFrameRateLimit, fpsLimit); -} - AZ_CVAR(AZ::CVarFixedString, r_default_pipeline_name, AZ_TRAIT_BOOTSTRAPSYSTEMCOMPONENT_PIPELINE_NAME, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Default Render pipeline name"); -AZ_CVAR(float, r_fps_limit, 0, OnFrameRateLimitChanged, AZ::ConsoleFunctorFlags::Null, "The maximum framerate to render at, or 0 for unlimited"); namespace AZ { @@ -358,22 +351,6 @@ namespace AZ return true; } - float BootstrapSystemComponent::GetFrameRateLimit() const - { - return r_fps_limit; - } - - void BootstrapSystemComponent::SetFrameRateLimit(float fpsLimit) - { - r_fps_limit = fpsLimit; - if (m_viewportContext) - { - m_viewportContext->SetFpsLimit(r_fps_limit); - } - Render::Bootstrap::NotificationBus::Broadcast( - &Render::Bootstrap::NotificationBus::Events::OnFrameRateLimitChanged, fpsLimit); - } - void BootstrapSystemComponent::CreateDefaultRenderPipeline() { EnsureDefaultRenderPipelineInstalledForScene(m_defaultScene, m_viewportContext); @@ -413,11 +390,23 @@ namespace AZ } void BootstrapSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time) - { } + { + // Temp: When running in the launcher without the legacy renderer + // we need to call RenderTick on the viewport context each frame. + if (m_viewportContext) + { + AZ::ApplicationTypeQuery appType; + ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType); + if (appType.IsGame()) + { + m_viewportContext->RenderTick(); + } + } + } int BootstrapSystemComponent::GetTickOrder() { - return TICK_PRE_RENDER; + return TICK_LAST; } void BootstrapSystemComponent::OnWindowClosed() diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h index 438c6cb236..566d19b1a4 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h @@ -69,8 +69,6 @@ namespace AZ // Render::Bootstrap::RequestBus::Handler overrides ... AZ::RPI::ScenePtr GetOrCreateAtomSceneFromAzScene(AzFramework::Scene* scene) override; bool EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext) override; - float GetFrameRateLimit() const override; - void SetFrameRateLimit(float fpsLimit) override; protected: // Component overrides ... diff --git a/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype index 9a2edc9fca..17209771e5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype @@ -5,7 +5,7 @@ "properties": { "general": [ { - "id": "texcoord", + "name": "texcoord", "displayName": "Texture Coordinate Stream", "description": "Which UV channel to use when sampling textures.", "type": "Int", @@ -14,75 +14,75 @@ "max": 8 }, { - "id": "enableShadows", + "name": "enableShadows", "displayName": "Enable Shadows", "description": "Whether to use the shadow maps.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableShadows" + "name": "o_enableShadows" } }, { - "id": "enableDirectionalLights", + "name": "enableDirectionalLights", "displayName": "Enable Directional Lights", "description": "Whether to use directional lights.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableDirectionalLights" + "name": "o_enableDirectionalLights" } }, { - "id": "enablePunctualLights", + "name": "enablePunctualLights", "displayName": "Enable Punctual Lights", "description": "Whether to use punctual lights.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enablePunctualLights" + "name": "o_enablePunctualLights" } }, { - "id": "enableAreaLights", + "name": "enableAreaLights", "displayName": "Enable Area Lights", "description": "Whether to use area lights.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableAreaLights" + "name": "o_enableAreaLights" } }, { - "id": "enableIBL", + "name": "enableIBL", "displayName": "Enable IBL", "description": "Whether to use Image Based Lighting (IBL).", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableIBL" + "name": "o_enableIBL" } } ], "baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_baseColor" + "name": "m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -91,31 +91,31 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_baseColorFactor" + "name": "m_baseColorFactor" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map.", "type": "Bool", "defaultValue": true }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Base color texture map", "type": "Image", "defaultValue": "Textures/Default/default_basecolor.tif", "connection": { "type": "ShaderInput", - "id": "m_baseColorMap" + "name": "m_baseColorMap" } } ], "metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -124,30 +124,30 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_metallicFactor" + "name": "m_metallicFactor" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_metallicMap" + "name": "m_metallicMap" } } ], "roughness": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -156,31 +156,31 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessFactor" + "name": "m_roughnessFactor" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Texture map for defining surface roughness.", "type": "Image", "defaultValue": "Textures/Default/default_roughness.tif", "connection": { "type": "ShaderInput", - "id": "m_roughnessMap" + "name": "m_roughnessMap" } } ], "specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -189,51 +189,51 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_specularF0Factor" + "name": "m_specularF0Factor" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Texture map for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularF0Map" + "name": "m_specularF0Map" } }, { - "id": "applySpecularAA", + "name": "applySpecularAA", "displayName": "Apply Specular AA", "description": "Whether to apply specular anti-aliasing in the shader.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_applySpecularAA" + "name": "o_applySpecularAA" } }, { - "id": "enableMultiScatterCompensation", + "name": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", "description": "Whether to enable multiple scattering compensation.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" + "name": "o_specularF0_enableMultiScatterCompensation" } } ], "normal": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -243,85 +243,85 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_normalFactor" + "name": "m_normalFactor" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Texture map for defining surface normal direction.", "type": "Image", "defaultValue": "Textures/Default/default_normal.tif", "connection": { "type": "ShaderInput", - "id": "m_normalMap" + "name": "m_normalMap" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalX" + "name": "m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalY" + "name": "m_flipNormalY" } } ], "opacity": [ { - "id": "mode", + "name": "mode", "displayName": "Opacity Mode", "description": "Opacity mode for this texture. 0: Opaque, 1: Cutout, 2:Blended", "type": "Uint", "defaultValue": 0, "connection": { "type": "ShaderOption", - "id": "o_opacity_mode" + "name": "o_opacity_mode" } }, { - "id": "alphaSource", + "name": "alphaSource", "displayName": "Alpha Source", "description": "Source texture of alpha value. 0:Packed, 1:Split, 2:None", "type": "Uint", "defaultValue": 0, "connection": { "type": "ShaderOption", - "id": "o_opacity_source" + "name": "o_opacity_source" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Texture map for defining surface opacity.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_opacityMap" + "name": "m_opacityMap" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Factor for cutout threshold and blending", "type": "Float", @@ -330,11 +330,11 @@ "defaultValue": 0.5, "connection": { "type": "ShaderInput", - "id": "m_opacityFactor" + "name": "m_opacityFactor" } }, { - "id": "doubleSided", + "name": "doubleSided", "displayName": "Double-sided", "description": "Whether to render back-faces or just front-faces.", "type": "Bool" @@ -342,14 +342,14 @@ ], "uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", "defaultValue": [0.0, 0.0] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -357,7 +357,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -365,7 +365,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -374,7 +374,7 @@ "max": 1.0 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -383,7 +383,7 @@ "max": 1.0 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -393,7 +393,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -403,29 +403,29 @@ ], "emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type":"Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_emissiveEnabled" + "name": "o_emissiveEnabled" } }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_emissiveColor" + "name": "m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted, in EV100 unit", "type": "Float", @@ -434,33 +434,33 @@ "max": 5 }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Texture map for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_emissiveMap" + "name": "m_emissiveMap" } } ], "parallax": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Whether to enable the parallax feature.", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the depth values", "type": "Float", @@ -469,39 +469,39 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_heightmapScale" + "name": "m_heightmapScale" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture Map", "description": "Depthmap to create parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_heightmap" + "name": "m_heightmap" } }, { - "id": "algorithm", + "name": "algorithm", "displayName": "Algorithm", "description": "Select the algorithm to use for parallax mapping. 0: Basic, 1:Steep, 2:POM, 3:Relief, 4:Contact refinement", "type": "Uint", "defaultValue": 0, "connection":{ "type": "ShaderOption", - "id": "o_parallax_algorithm" + "name": "o_parallax_algorithm" } }, { - "id": "quality", + "name": "quality", "displayName": "Quality", "description": "Quality of parallax mapping. 0:Low, 1:Medium, 2:High, 3:Ultra", "type": "Uint", "defaultValue": 0, "connection":{ "type": "ShaderOption", - "id": "o_parallax_quality" + "name": "o_parallax_quality" } } ] diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.materialtype index 59b7af8439..74246f85db 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.materialtype @@ -5,7 +5,7 @@ "properties": { "settings": [ { - "id": "opacity", + "name": "opacity", "displayName": "Opacity", "description": "Opacity of the shadow effect.", "type": "Float", @@ -14,17 +14,17 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_opacity" + "name": "m_opacity" } }, { - "id": "shadeAll", + "name": "shadeAll", "displayName": "Shade All", "description": "Shades the entire geometry with the shadow color, not just what's in shadow. For debugging.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_shadeAll" + "name": "o_shadeAll" } } ] diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 9b2c465352..bed3b69c4c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -4,88 +4,88 @@ "version": 3, "groups": [ { - "id": "baseColor", + "name": "baseColor", "displayName": "Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "metallic", + "name": "metallic", "displayName": "Metallic", "description": "Properties for configuring whether the surface is metallic or not." }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "specularF0", + "name": "specularF0", "displayName": "Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "normal", + "name": "normal", "displayName": "Normal", "description": "Properties related to configuring surface normal." }, { - "id": "detailLayerGroup", + "name": "detailLayerGroup", "displayName": "Detail Layer", "description": "Properties for Fine Details Layer." }, { - "id": "detailUV", + "name": "detailUV", "displayName": "Detail Layer UV", "description": "Properties for modifying detail layer UV." }, { - "id": "anisotropy", + "name": "anisotropy", "displayName": "Anisotropic Material Response", "description": "How much is this material response anisotropic." }, { - "id": "occlusion", + "name": "occlusion", "displayName": "Occlusion", "description": "Properties for baked textures that represent geometric occlusion of light." }, { - "id": "emissive", + "name": "emissive", "displayName": "Emissive", "description": "Properties to add light emission, independent of other lights in the scene." }, { - "id": "subsurfaceScattering", + "name": "subsurfaceScattering", "displayName": "Subsurface Scattering", "description": "Properties for configuring subsurface scattering effects." }, { - "id": "clearCoat", + "name": "clearCoat", "displayName": "Clear Coat", "description": "Properties for configuring gloss clear coat" }, { - "id": "parallax", + "name": "parallax", "displayName": "Displacement", "description": "Properties for parallax effect produced by a height map." }, { - "id": "opacity", + "name": "opacity", "displayName": "Opacity", "description": "Properties for configuring the materials transparency." }, { - "id": "uv", + "name": "uv", "displayName": "UVs", "description": "Properties for configuring UV transforms." }, { // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader - "id": "irradiance", + "name": "irradiance", "displayName": "Irradiance", "description": "Properties for configuring the irradiance used in global illumination." }, { - "id": "general", + "name": "general", "displayName": "General Settings", "description": "General settings." } @@ -93,97 +93,97 @@ "properties": { "general": [ { - "id": "applySpecularAA", + "name": "applySpecularAA", "displayName": "Apply Specular AA", "description": "Whether to apply specular anti-aliasing in the shader.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_applySpecularAA" + "name": "o_applySpecularAA" } }, { - "id": "enableShadows", + "name": "enableShadows", "displayName": "Enable Shadows", "description": "Whether to use the shadow maps.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableShadows" + "name": "o_enableShadows" } }, { - "id": "enableDirectionalLights", + "name": "enableDirectionalLights", "displayName": "Enable Directional Lights", "description": "Whether to use directional lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableDirectionalLights" + "name": "o_enableDirectionalLights" } }, { - "id": "enablePunctualLights", + "name": "enablePunctualLights", "displayName": "Enable Punctual Lights", "description": "Whether to use punctual lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enablePunctualLights" + "name": "o_enablePunctualLights" } }, { - "id": "enableAreaLights", + "name": "enableAreaLights", "displayName": "Enable Area Lights", "description": "Whether to use area lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableAreaLights" + "name": "o_enableAreaLights" } }, { - "id": "enableIBL", + "name": "enableIBL", "displayName": "Enable IBL", "description": "Whether to use Image Based Lighting (IBL).", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableIBL" + "name": "o_enableIBL" } }, { - "id": "forwardPassIBLSpecular", + "name": "forwardPassIBLSpecular", "displayName": "Forward Pass IBL Specular", "description": "Whether to apply IBL specular in the forward pass.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_materialUseForwardPassIBLSpecular" + "name": "o_materialUseForwardPassIBLSpecular" } } ], "baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_baseColor" + "name": "m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -192,28 +192,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_baseColorFactor" + "name": "m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_baseColorMap" + "name": "m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -221,11 +221,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_baseColorMapUvIndex" + "name": "m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -233,13 +233,13 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_baseColorTextureBlendMode" + "name": "o_baseColorTextureBlendMode" } } ], "metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -248,28 +248,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_metallicFactor" + "name": "m_metallicFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_metallicMap" + "name": "m_metallicMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Metallic map UV set", "type": "Enum", @@ -277,30 +277,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_metallicMapUvIndex" + "name": "m_metallicMapUvIndex" } } ], "roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_roughnessMap" + "name": "m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -308,12 +308,12 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_roughnessMapUvIndex" + "name": "m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -322,12 +322,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessLowerBound" + "name": "m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -336,12 +336,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessUpperBound" + "name": "m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -350,24 +350,24 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessFactor" + "name": "m_roughnessFactor" } } ], "anisotropy": [ { - "id": "enableAnisotropy", + "name": "enableAnisotropy", "displayName": "Enable Anisotropy", "description": "Enable anisotropic surface response for non uniform reflection along the axis", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableAnisotropy" + "name": "o_enableAnisotropy" } }, { - "id": "factor", + "name": "factor", "displayName": "Anisotropy Factor", "description": "Strength factor for the anisotropy: negative = along v, positive = along u", "type": "Float", @@ -376,11 +376,11 @@ "max": 0.95, "connection": { "type": "ShaderInput", - "id": "m_anisotropicFactor" + "name": "m_anisotropicFactor" } }, { - "id": "anisotropyAngle", + "name": "anisotropyAngle", "displayName": "Anisotropy Angle", "description": "Anisotropy direction of major reflection axis: 0 = 0 degrees, 1.0 = 180 degrees", "type": "Float", @@ -389,13 +389,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_anisotropicAngle" + "name": "m_anisotropicAngle" } } ], "specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -404,28 +404,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_specularF0Factor" + "name": "m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularF0Map" + "name": "m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -433,31 +433,31 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_specularF0MapUvIndex" + "name": "m_specularF0MapUvIndex" } }, // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR { - "id": "enableMultiScatterCompensation", + "name": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", "description": "Whether to enable multiple scattering compensation.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" + "name": "o_specularF0_enableMultiScatterCompensation" } } ], "clearCoat": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the percentage of effect applied", "type": "Float", @@ -466,28 +466,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatFactor" + "name": "m_clearCoatFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Strength factor texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatInfluenceMap" + "name": "m_clearCoatInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Strength factor map UV set", "type": "Enum", @@ -495,11 +495,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatInfluenceMapUvIndex" + "name": "m_clearCoatInfluenceMapUvIndex" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Clear coat layer roughness", "type": "Float", @@ -508,28 +508,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughness" + "name": "m_clearCoatRoughness" } }, { - "id": "roughnessMap", + "name": "roughnessMap", "displayName": " Roughness Map", "description": "Texture for defining surface roughness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughnessMap" + "name": "m_clearCoatRoughnessMap" } }, { - "id": "useRoughnessMap", + "name": "useRoughnessMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the roughness value.", "type": "Bool", "defaultValue": true }, { - "id": "roughnessMapUv", + "name": "roughnessMapUv", "displayName": " UV", "description": "Roughness map UV set", "type": "Enum", @@ -537,11 +537,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughnessMapUvIndex" + "name": "m_clearCoatRoughnessMapUvIndex" } }, { - "id": "normalStrength", + "name": "normalStrength", "displayName": "Normal Strength", "description": "Scales the impact of the clear coat normal map", "type": "Float", @@ -550,28 +550,28 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalStrength" + "name": "m_clearCoatNormalStrength" } }, { - "id": "normalMap", + "name": "normalMap", "displayName": "Normal Map", "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalMap" + "name": "m_clearCoatNormalMap" } }, { - "id": "useNormalMap", + "name": "useNormalMap", "displayName": " Use Texture", "description": "Whether to use the normal map", "type": "Bool", "defaultValue": true }, { - "id": "normalMapUv", + "name": "normalMapUv", "displayName": " UV", "description": "Normal map UV set", "type": "Enum", @@ -579,30 +579,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalMapUvIndex" + "name": "m_clearCoatNormalMapUvIndex" } } ], "normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_normalMap" + "name": "m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -610,33 +610,33 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_normalMapUvIndex" + "name": "m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalX" + "name": "m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalY" + "name": "m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -645,13 +645,13 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_normalFactor" + "name": "m_normalFactor" } } ], "opacity": [ { - "id": "mode", + "name": "mode", "displayName": "Opacity Mode", "description": "Indicates the general approach how transparency is to be applied.", "type": "Enum", @@ -659,11 +659,11 @@ "defaultValue": "Opaque", "connection": { "type": "ShaderOption", - "id": "o_opacity_mode" + "name": "o_opacity_mode" } }, { - "id": "alphaSource", + "name": "alphaSource", "displayName": "Alpha Source", "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).", "type": "Enum", @@ -671,21 +671,21 @@ "defaultValue": "Packed", "connection": { "type": "ShaderOption", - "id": "o_opacity_source" + "name": "o_opacity_source" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface opacity.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_opacityMap" + "name": "m_opacityMap" } }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Opacity map UV set", "type": "Enum", @@ -693,11 +693,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_opacityMapUvIndex" + "name": "m_opacityMapUvIndex" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Factor for cutout threshold and blending", "type": "Float", @@ -706,17 +706,17 @@ "defaultValue": 0.5, "connection": { "type": "ShaderInput", - "id": "m_opacityFactor" + "name": "m_opacityFactor" } }, { - "id": "doubleSided", + "name": "doubleSided", "displayName": "Double-sided", "description": "Whether to render back-faces or just front-faces.", "type": "Bool" }, { - "id": "alphaAffectsSpecular", + "name": "alphaAffectsSpecular", "displayName": "Alpha affects specular", "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", "type": "float", @@ -725,13 +725,13 @@ "defaultValue": 0.0, "connection": { "type": "ShaderInput", - "id": "m_opacityAffectsSpecularFactor" + "name": "m_opacityAffectsSpecularFactor" } } ], "uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -739,7 +739,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in U.", "type": "float", @@ -747,7 +747,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -755,7 +755,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -764,7 +764,7 @@ "max": 1.0 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -773,7 +773,7 @@ "max": 1.0 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -783,7 +783,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -793,24 +793,24 @@ ], "occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMap" + "name": "m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -818,11 +818,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMapUvIndex" + "name": "m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -831,28 +831,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionFactor" + "name": "m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMap" + "name": "m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -860,11 +860,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMapUvIndex" + "name": "m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -873,20 +873,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionFactor" + "name": "m_specularOcclusionFactor" } } ], "emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", "defaultValue": false }, { - "id": "unit", + "name": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", @@ -894,18 +894,18 @@ "defaultValue": "Ev100" }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_emissiveColor" + "name": "m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted.", "type": "Float", @@ -916,24 +916,24 @@ "softMax": 16 }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_emissiveMap" + "name": "m_emissiveMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Emissive map UV set", "type": "Enum", @@ -941,30 +941,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_emissiveMapUvIndex" + "name": "m_emissiveMapUvIndex" } } ], "parallax": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Height Map", "description": "Displacement height map to create parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_heightmap" + "name": "m_heightmap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the height map.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Height map UV set", "type": "Enum", @@ -972,11 +972,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_parallaxUvIndex" + "name": "m_parallaxUvIndex" } }, { - "id": "factor", + "name": "factor", "displayName": "Height Map Scale", "description": "The total height of the height map in local model units.", "type": "Float", @@ -985,11 +985,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_heightmapScale" + "name": "m_heightmapScale" } }, { - "id": "offset", + "name": "offset", "displayName": "Offset", "description": "Adjusts the overall displacement amount in local model units.", "type": "Float", @@ -998,11 +998,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_heightmapOffset" + "name": "m_heightmapOffset" } }, { - "id": "algorithm", + "name": "algorithm", "displayName": "Algorithm", "description": "Select the algorithm to use for parallax mapping.", "type": "Enum", @@ -1010,11 +1010,11 @@ "defaultValue": "POM", "connection": { "type": "ShaderOption", - "id": "o_parallax_algorithm" + "name": "o_parallax_algorithm" } }, { - "id": "quality", + "name": "quality", "displayName": "Quality", "description": "Quality of parallax mapping.", "type": "Enum", @@ -1022,46 +1022,46 @@ "defaultValue": "Low", "connection": { "type": "ShaderOption", - "id": "o_parallax_quality" + "name": "o_parallax_quality" } }, { - "id": "pdo", + "name": "pdo", "displayName": "Pixel Depth Offset", "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_enablePixelDepthOffset" + "name": "o_parallax_enablePixelDepthOffset" } }, { - "id": "showClipping", + "name": "showClipping", "displayName": "Show Clipping", "description": "Highlight areas where the height map is clipped by the mesh surface.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_highlightClipping" + "name": "o_parallax_highlightClipping" } } ], "subsurfaceScattering": [ { - "id": "enableSubsurfaceScattering", + "name": "enableSubsurfaceScattering", "displayName": "Subsurface Scattering", "description": "Enable subsurface scattering feature, this will disable metallic and parallax mapping property due to incompatibility", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableSubsurfaceScattering" + "name": "o_enableSubsurfaceScattering" } }, { - "id": "subsurfaceScatterFactor", + "name": "subsurfaceScatterFactor", "displayName": " Factor", "description": "Strength factor for scaling percentage of subsurface scattering effect applied", "type": "float", @@ -1070,28 +1070,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringFactor" + "name": "m_subsurfaceScatteringFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Texture for controlling the strength of subsurface scattering", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringInfluenceMap" + "name": "m_subsurfaceScatteringInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Influence Map", "description": "Whether to use the influence map.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Influence map UV set", "type": "Enum", @@ -1099,18 +1099,18 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringInfluenceMapUvIndex" + "name": "m_subsurfaceScatteringInfluenceMapUvIndex" } }, { - "id": "scatterColor", + "name": "scatterColor", "displayName": " Scatter color", "description": "Color of volume light traveled through", "type": "Color", "defaultValue": [ 1.0, 0.27, 0.13 ] }, { - "id": "scatterDistance", + "name": "scatterDistance", "displayName": " Scatter distance", "description": "How far light traveled inside the volume", "type": "float", @@ -1119,7 +1119,7 @@ "softMax": 20.0 }, { - "id": "quality", + "name": "quality", "displayName": " Quality", "description": "How much percent of sample will be used for each pixel, more samples improve quality and reduce artifacts, especially when the scatter distance is relatively large, but slow down computation time, 1.0 = full set 200 samples per pixel", "type": "float", @@ -1128,11 +1128,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringQuality" + "name": "m_subsurfaceScatteringQuality" } }, { - "id": "transmissionMode", + "name": "transmissionMode", "displayName": "Transmission", "description": "Algorithm used for calculating transmission", "type": "Enum", @@ -1140,11 +1140,11 @@ "defaultValue": "None", "connection": { "type": "ShaderOption", - "id": "o_transmission_mode" + "name": "o_transmission_mode" } }, { - "id": "thickness", + "name": "thickness", "displayName": " Thickness", "description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel", "type": "float", @@ -1153,24 +1153,24 @@ "max": 1.0 }, { - "id": "thicknessMap", + "name": "thicknessMap", "displayName": " Thickness Map", "description": "Texture for controlling per pixel thickness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_transmissionThicknessMap" + "name": "m_transmissionThicknessMap" } }, { - "id": "useThicknessMap", + "name": "useThicknessMap", "displayName": " Use Thickness Map", "description": "Whether to use the thickness map", "type": "Bool", "defaultValue": true }, { - "id": "thicknessMapUv", + "name": "thicknessMapUv", "displayName": " UV", "description": "Thickness map UV set", "type": "Enum", @@ -1178,18 +1178,18 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_transmissionThicknessMapUvIndex" + "name": "m_transmissionThicknessMapUvIndex" } }, { - "id": "transmissionTint", + "name": "transmissionTint", "displayName": " Transmission Tint", "description": "Color of the volume light traveling through", "type": "Color", "defaultValue": [ 1.0, 0.8, 0.6 ] }, { - "id": "transmissionPower", + "name": "transmissionPower", "displayName": " Power", "description": "How much transmitted light scatter radially ", "type": "float", @@ -1198,7 +1198,7 @@ "softMax": 20.0 }, { - "id": "transmissionDistortion", + "name": "transmissionDistortion", "displayName": " Distortion", "description": "How much light direction distorted towards surface normal", "type": "float", @@ -1207,7 +1207,7 @@ "max": 1.0 }, { - "id": "transmissionAttenuation", + "name": "transmissionAttenuation", "displayName": " Attenuation", "description": "How fast transmitted light fade with thickness", "type": "float", @@ -1216,7 +1216,7 @@ "softMax": 20.0 }, { - "id": "transmissionScale", + "name": "transmissionScale", "displayName": " Scale", "description": "Strength of transmission", "type": "float", @@ -1227,14 +1227,14 @@ ], "detailLayerGroup": [ { - "id": "enableDetailLayer", + "name": "enableDetailLayer", "displayName": "Enable Detail Layer", "description": "Enable detail layer for fine details and scratches", "type": "Bool", "defaultValue": false }, { - "id": "blendDetailFactor", + "name": "blendDetailFactor", "displayName": "Blend Factor", "description": "Scales the overall impact of the detail layer.", "type": "Float", @@ -1243,28 +1243,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_detail_blendFactor" + "name": "m_detail_blendFactor" } }, { - "id": "blendDetailMask", + "name": "blendDetailMask", "displayName": "Blend Mask", "description": "Detailed blend mask for application of the detail maps.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_blendMask_texture" + "name": "m_detail_blendMask_texture" } }, { - "id": "enableDetailMaskTexture", + "name": "enableDetailMaskTexture", "displayName": " Use Texture", "description": "Enable detail blend mask", "type": "Bool", "defaultValue": true }, { - "id": "blendDetailMaskUv", + "name": "blendDetailMaskUv", "displayName": " Blend Mask UV", "description": "Which UV set to use for sampling the detail blend mask", "type": "Enum", @@ -1272,11 +1272,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_detail_blendMask_uvIndex" + "name": "m_detail_blendMask_uvIndex" } }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "Detail Map UVs", "description": "Which UV set to use for detail map sampling", "type": "Enum", @@ -1284,28 +1284,28 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_detail_allMapsUvIndex" + "name": "m_detail_allMapsUvIndex" } }, { - "id": "enableBaseColor", + "name": "enableBaseColor", "displayName": "Enable Base Color", "description": "Enable detail blending for base color", "type": "Bool", "defaultValue": false }, { - "id": "baseColorDetailMap", + "name": "baseColorDetailMap", "displayName": " Texture", "description": "Detailed Base Color Texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_baseColor_texture" + "name": "m_detail_baseColor_texture" } }, { - "id": "baseColorDetailBlend", + "name": "baseColorDetailBlend", "displayName": " Blend Factor", "description": "How much to blend the detail layer into the base color.", "type": "Float", @@ -1314,18 +1314,18 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_detail_baseColor_factor" + "name": "m_detail_baseColor_factor" } }, { - "id": "enableNormals", + "name": "enableNormals", "displayName": "Enable Normal", "description": "Enable detail normal map to be used for fine detail normal such as scratches and small dents", "type": "Bool", "defaultValue": false }, { - "id": "normalDetailStrength", + "name": "normalDetailStrength", "displayName": " Factor", "description": "Strength factor for scaling the Detail Normal", "type": "Float", @@ -1334,45 +1334,45 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_factor" + "name": "m_detail_normal_factor" } }, { - "id": "normalDetailMap", + "name": "normalDetailMap", "displayName": " Texture", "description": "Detailed Normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_normal_texture" + "name": "m_detail_normal_texture" } }, { - "id": "normalDetailFlipX", + "name": "normalDetailFlipX", "displayName": " Flip X Channel", "description": "Flip Detail tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_flipX" + "name": "m_detail_normal_flipX" } }, { - "id": "normalDetailFlipY", + "name": "normalDetailFlipY", "displayName": " Flip Y Channel", "description": "Flip Detail bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_flipY" + "name": "m_detail_normal_flipY" } } ], "detailUV": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -1380,7 +1380,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -1388,7 +1388,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -1396,7 +1396,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -1405,7 +1405,7 @@ "max": 1.0 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -1414,7 +1414,7 @@ "max": 1.0 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -1424,7 +1424,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -1435,14 +1435,14 @@ "irradiance": [ // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ] }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index fe86576cf8..0969cc36e8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -4,52 +4,52 @@ "version": 3, "groups": [ { - "id": "baseColor", + "name": "baseColor", "displayName": "Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "specularF0", + "name": "specularF0", "displayName": "Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "normal", + "name": "normal", "displayName": "Normal", "description": "Properties related to configuring surface normal." }, { - "id": "detailLayerGroup", + "name": "detailLayerGroup", "displayName": "Detail Layer", "description": "Properties for Fine Details Layer." }, { - "id": "detailUV", + "name": "detailUV", "displayName": "Detail Layer UV", "description": "Properties for modifying detail layer UV." }, { - "id": "occlusion", + "name": "occlusion", "displayName": "Occlusion", "description": "Properties for baked textures that represent geometric occlusion of light." }, { - "id": "subsurfaceScattering", + "name": "subsurfaceScattering", "displayName": "Subsurface Scattering", "description": "Properties for configuring subsurface scattering effects." }, { - "id": "wrinkleLayers", + "name": "wrinkleLayers", "displayName": "Wrinkle Layers", "description": "Properties for wrinkle maps to support morph animation, using vertex color blend weights." }, { - "id": "general", + "name": "general", "displayName": "General Settings", "description": "General settings." } @@ -57,86 +57,86 @@ "properties": { "general": [ { - "id": "applySpecularAA", + "name": "applySpecularAA", "displayName": "Apply Specular AA", "description": "Whether to apply specular anti-aliasing in the shader.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_applySpecularAA" + "name": "o_applySpecularAA" } }, { - "id": "enableShadows", + "name": "enableShadows", "displayName": "Enable Shadows", "description": "Whether to use the shadow maps.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableShadows" + "name": "o_enableShadows" } }, { - "id": "enableDirectionalLights", + "name": "enableDirectionalLights", "displayName": "Enable Directional Lights", "description": "Whether to use directional lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableDirectionalLights" + "name": "o_enableDirectionalLights" } }, { - "id": "enablePunctualLights", + "name": "enablePunctualLights", "displayName": "Enable Punctual Lights", "description": "Whether to use punctual lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enablePunctualLights" + "name": "o_enablePunctualLights" } }, { - "id": "enableAreaLights", + "name": "enableAreaLights", "displayName": "Enable Area Lights", "description": "Whether to use area lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableAreaLights" + "name": "o_enableAreaLights" } }, { - "id": "enableIBL", + "name": "enableIBL", "displayName": "Enable IBL", "description": "Whether to use Image Based Lighting (IBL).", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableIBL" + "name": "o_enableIBL" } } ], "baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_baseColor" + "name": "m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -145,28 +145,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_baseColorFactor" + "name": "m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_baseColorMap" + "name": "m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -174,11 +174,11 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_baseColorMapUvIndex" + "name": "m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -186,30 +186,30 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_baseColorTextureBlendMode" + "name": "o_baseColorTextureBlendMode" } } ], "roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_roughnessMap" + "name": "m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -217,12 +217,12 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_roughnessMapUvIndex" + "name": "m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -231,12 +231,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessLowerBound" + "name": "m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -245,12 +245,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessUpperBound" + "name": "m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -259,13 +259,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessFactor" + "name": "m_roughnessFactor" } } ], "specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -274,28 +274,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_specularF0Factor" + "name": "m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularF0Map" + "name": "m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -303,41 +303,41 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_specularF0MapUvIndex" + "name": "m_specularF0MapUvIndex" } }, // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR { - "id": "enableMultiScatterCompensation", + "name": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", "description": "Whether to enable multiple scattering compensation.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" + "name": "o_specularF0_enableMultiScatterCompensation" } } ], "normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_normalMap" + "name": "m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -345,33 +345,33 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_normalMapUvIndex" + "name": "m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalX" + "name": "m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalY" + "name": "m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -380,30 +380,30 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_normalFactor" + "name": "m_normalFactor" } } ], "occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMap" + "name": "m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -411,11 +411,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMapUvIndex" + "name": "m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -424,28 +424,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionFactor" + "name": "m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMap" + "name": "m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -453,11 +453,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMapUvIndex" + "name": "m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -466,24 +466,24 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionFactor" + "name": "m_specularOcclusionFactor" } } ], "subsurfaceScattering": [ { - "id": "enableSubsurfaceScattering", + "name": "enableSubsurfaceScattering", "displayName": "Subsurface Scattering", "description": "Enable subsurface scattering feature, this will disable metallic and parallax mapping property due to incompatibility", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_enableSubsurfaceScattering" + "name": "o_enableSubsurfaceScattering" } }, { - "id": "subsurfaceScatterFactor", + "name": "subsurfaceScatterFactor", "displayName": " Factor", "description": "Strength factor for scaling percentage of subsurface scattering effect applied", "type": "float", @@ -492,28 +492,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringFactor" + "name": "m_subsurfaceScatteringFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Texture for controlling the strength of subsurface scattering", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringInfluenceMap" + "name": "m_subsurfaceScatteringInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Influence Map", "description": "Whether to use the influence map.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Influence map UV set", "type": "Enum", @@ -521,18 +521,18 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringInfluenceMapUvIndex" + "name": "m_subsurfaceScatteringInfluenceMapUvIndex" } }, { - "id": "scatterColor", + "name": "scatterColor", "displayName": " Scatter color", "description": "Color of volume light traveled through", "type": "Color", "defaultValue": [ 1.0, 0.27, 0.13 ] }, { - "id": "scatterDistance", + "name": "scatterDistance", "displayName": " Scatter distance", "description": "How far light traveled inside the volume", "type": "float", @@ -541,7 +541,7 @@ "softMax": 20.0 }, { - "id": "quality", + "name": "quality", "displayName": " Quality", "description": "How much percent of sample will be used for each pixel, more samples improve quality and reduce artifacts, especially when the scatter distance is relatively large, but slow down computation time, 1.0 = full set 200 samples per pixel", "type": "float", @@ -550,11 +550,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_subsurfaceScatteringQuality" + "name": "m_subsurfaceScatteringQuality" } }, { - "id": "transmissionMode", + "name": "transmissionMode", "displayName": "Transmission", "description": "Algorithm used for calculating transmission", "type": "Enum", @@ -562,11 +562,11 @@ "defaultValue": "None", "connection": { "type": "ShaderOption", - "id": "o_transmission_mode" + "name": "o_transmission_mode" } }, { - "id": "thickness", + "name": "thickness", "displayName": " Thickness", "description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel", "type": "float", @@ -575,24 +575,24 @@ "max": 1.0 }, { - "id": "thicknessMap", + "name": "thicknessMap", "displayName": " Thickness Map", "description": "Texture for controlling per pixel thickness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_transmissionThicknessMap" + "name": "m_transmissionThicknessMap" } }, { - "id": "useThicknessMap", + "name": "useThicknessMap", "displayName": " Use Thickness Map", "description": "Whether to use the thickness map", "type": "Bool", "defaultValue": true }, { - "id": "thicknessMapUv", + "name": "thicknessMapUv", "displayName": " UV", "description": "Thickness map UV set", "type": "Enum", @@ -600,18 +600,18 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_transmissionThicknessMapUvIndex" + "name": "m_transmissionThicknessMapUvIndex" } }, { - "id": "transmissionTint", + "name": "transmissionTint", "displayName": " Transmission Tint", "description": "Color of the volume light traveling through", "type": "Color", "defaultValue": [ 1.0, 0.8, 0.6 ] }, { - "id": "transmissionPower", + "name": "transmissionPower", "displayName": " Power", "description": "How much transmitted light scatter radially ", "type": "float", @@ -620,7 +620,7 @@ "softMax": 20.0 }, { - "id": "transmissionDistortion", + "name": "transmissionDistortion", "displayName": " Distortion", "description": "How much light direction distorted towards surface normal", "type": "float", @@ -629,7 +629,7 @@ "max": 1.0 }, { - "id": "transmissionAttenuation", + "name": "transmissionAttenuation", "displayName": " Attenuation", "description": "How fast transmitted light fade with thickness", "type": "float", @@ -638,7 +638,7 @@ "softMax": 20.0 }, { - "id": "transmissionScale", + "name": "transmissionScale", "displayName": " Scale", "description": "Strength of transmission", "type": "float", @@ -649,14 +649,14 @@ ], "wrinkleLayers": [ { - "id": "enable", + "name": "enable", "displayName": "Enable Wrinkle Layers", "description": "Enable wrinkle layers for morph animations, using vertex color blend weights.", "type": "Bool", "defaultValue": false }, { - "id": "count", + "name": "count", "displayName": "Number Of Layers", "description": "The number of wrinkle map layers to use. The blend values come from the 'COLOR0' vertex stream, where R/G/B/A correspond to wrinkle layers 1/2/3/4 respectively.", "type": "UInt", @@ -665,109 +665,109 @@ "max": 4 }, { - "id": "showBlendValues", + "name": "showBlendValues", "displayName": "Show Blend Values", "description": "Enable a debug mode that draws the blend values as red, green, blue, and white overlays.", "type": "Bool", "defaultValue": false }, { - "id": "enableBaseColor", + "name": "enableBaseColor", "displayName": "Enable Base Color Maps", "description": "Enable support for blending the base color according to morph animations.", "type": "Bool", "defaultValue": false }, { - "id": "baseColorMap1", + "name": "baseColorMap1", "displayName": " Base Color 1", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_baseColor_texture1" + "name": "m_wrinkle_baseColor_texture1" } }, { - "id": "baseColorMap2", + "name": "baseColorMap2", "displayName": " Base Color 2", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_baseColor_texture2" + "name": "m_wrinkle_baseColor_texture2" } }, { - "id": "baseColorMap3", + "name": "baseColorMap3", "displayName": " Base Color 3", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_baseColor_texture3" + "name": "m_wrinkle_baseColor_texture3" } }, { - "id": "baseColorMap4", + "name": "baseColorMap4", "displayName": " Base Color 4", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_baseColor_texture4" + "name": "m_wrinkle_baseColor_texture4" } }, { - "id": "enableNormal", + "name": "enableNormal", "displayName": "Enable Normal Maps", "description": "Enable support for blending the normal maps according to morph animations.", "type": "Bool", "defaultValue": false }, { - "id": "normalMap1", + "name": "normalMap1", "displayName": " Normals 1", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_normal_texture1" + "name": "m_wrinkle_normal_texture1" } }, { - "id": "normalMap2", + "name": "normalMap2", "displayName": " Normals 2", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_normal_texture2" + "name": "m_wrinkle_normal_texture2" } }, { - "id": "normalMap3", + "name": "normalMap3", "displayName": " Normals 3", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_normal_texture3" + "name": "m_wrinkle_normal_texture3" } }, { - "id": "normalMap4", + "name": "normalMap4", "displayName": " Normals 4", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_wrinkle_normal_texture4" + "name": "m_wrinkle_normal_texture4" } } ], "detailLayerGroup": [ { - "id": "enableDetailLayer", + "name": "enableDetailLayer", "displayName": "Enable Detail Layer", "description": "Enable detail layer for fine details and scratches", "type": "Bool", "defaultValue": false }, { - "id": "blendDetailFactor", + "name": "blendDetailFactor", "displayName": "Blend Factor", "description": "Scales the overall impact of the detail layer.", "type": "Float", @@ -776,28 +776,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_detail_blendFactor" + "name": "m_detail_blendFactor" } }, { - "id": "blendDetailMask", + "name": "blendDetailMask", "displayName": "Blend Mask", "description": "Detailed blend mask for application of the detail maps.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_blendMask_texture" + "name": "m_detail_blendMask_texture" } }, { - "id": "enableDetailMaskTexture", + "name": "enableDetailMaskTexture", "displayName": " Use Texture", "description": "Enable detail blend mask", "type": "Bool", "defaultValue": true }, { - "id": "blendDetailMaskUv", + "name": "blendDetailMaskUv", "displayName": " Blend Mask UV", "description": "Which UV set to use for sampling the detail blend mask", "type": "Enum", @@ -805,11 +805,11 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_detail_blendMask_uvIndex" + "name": "m_detail_blendMask_uvIndex" } }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "Detail Map UVs", "description": "Which UV set to use for detail map sampling", "type": "Enum", @@ -817,28 +817,28 @@ "defaultValue": "Unwrapped", "connection": { "type": "ShaderInput", - "id": "m_detail_allMapsUvIndex" + "name": "m_detail_allMapsUvIndex" } }, { - "id": "enableBaseColor", + "name": "enableBaseColor", "displayName": "Enable Base Color", "description": "Enable detail blending for base color", "type": "Bool", "defaultValue": false }, { - "id": "baseColorDetailMap", + "name": "baseColorDetailMap", "displayName": " Texture", "description": "Detailed Base Color Texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_baseColor_texture" + "name": "m_detail_baseColor_texture" } }, { - "id": "baseColorDetailBlend", + "name": "baseColorDetailBlend", "displayName": " Blend Factor", "description": "How much to blend the detail layer into the base color.", "type": "Float", @@ -847,18 +847,18 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_detail_baseColor_factor" + "name": "m_detail_baseColor_factor" } }, { - "id": "enableNormals", + "name": "enableNormals", "displayName": "Enable Normal", "description": "Enable detail normal map to be used for fine detail normal such as scratches and small dents", "type": "Bool", "defaultValue": false }, { - "id": "normalDetailStrength", + "name": "normalDetailStrength", "displayName": " Factor", "description": "Strength factor for scaling the Detail Normal", "type": "Float", @@ -867,45 +867,45 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_factor" + "name": "m_detail_normal_factor" } }, { - "id": "normalDetailMap", + "name": "normalDetailMap", "displayName": " Texture", "description": "Detailed Normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_detail_normal_texture" + "name": "m_detail_normal_texture" } }, { - "id": "normalDetailFlipX", + "name": "normalDetailFlipX", "displayName": " Flip X Channel", "description": "Flip Detail tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_flipX" + "name": "m_detail_normal_flipX" } }, { - "id": "normalDetailFlipY", + "name": "normalDetailFlipY", "displayName": " Flip Y Channel", "description": "Flip Detail bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_detail_normal_flipY" + "name": "m_detail_normal_flipY" } } ], "detailUV": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -913,7 +913,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -921,7 +921,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -929,7 +929,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -938,7 +938,7 @@ "max": 1.0 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -947,7 +947,7 @@ "max": 1.0 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -957,7 +957,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index bccb530eb4..5fa0dcb217 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -4,28 +4,28 @@ "version": 3, "groups": [ { - "id": "blend", + "name": "blend", "displayName": "Blend Settings", "description": "Properties for configuring how layers are blended together." }, { - "id": "parallax", + "name": "parallax", "displayName": "Parallax Settings", "description": "Properties for configuring the parallax effect, applied to all layers." }, { - "id": "uv", + "name": "uv", "displayName": "UVs", "description": "Properties for configuring UV transforms for the entire material, including the blend masks." }, { // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader - "id": "irradiance", + "name": "irradiance", "displayName": "Irradiance", "description": "Properties for configuring the irradiance used in global illumination." }, { - "id": "general", + "name": "general", "displayName": "General Settings", "description": "General settings." }, @@ -33,52 +33,52 @@ // Layer 1 Groups //############################################################################################## { - "id": "layer1_baseColor", + "name": "layer1_baseColor", "displayName": "Layer 1: Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "layer1_metallic", + "name": "layer1_metallic", "displayName": "Layer 1: Metallic", "description": "Properties for configuring whether the surface is metallic or not." }, { - "id": "layer1_roughness", + "name": "layer1_roughness", "displayName": "Layer 1: Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "layer1_specularF0", + "name": "layer1_specularF0", "displayName": "Layer 1: Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "layer1_normal", + "name": "layer1_normal", "displayName": "Layer 1: Normal", "description": "Properties related to configuring surface normal." }, { - "id": "layer1_occlusion", + "name": "layer1_occlusion", "displayName": "Layer 1: Occlusion", "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { - "id": "layer1_emissive", + "name": "layer1_emissive", "displayName": "Layer 1: Emissive", "description": "Properties to add light emission, independent of other lights in the scene." }, { - "id": "layer1_clearCoat", + "name": "layer1_clearCoat", "displayName": "Layer 1: Clear Coat", "description": "Properties for configuring gloss clear coat" }, { - "id": "layer1_parallax", + "name": "layer1_parallax", "displayName": "Layer 1: Displacement", "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { - "id": "layer1_uv", + "name": "layer1_uv", "displayName": "Layer 1: UVs", "description": "Properties for configuring UV transforms." }, @@ -86,52 +86,52 @@ // Layer 2 Groups //############################################################################################## { - "id": "layer2_baseColor", + "name": "layer2_baseColor", "displayName": "Layer 2: Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "layer2_metallic", + "name": "layer2_metallic", "displayName": "Layer 2: Metallic", "description": "Properties for configuring whether the surface is metallic or not." }, { - "id": "layer2_roughness", + "name": "layer2_roughness", "displayName": "Layer 2: Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "layer2_specularF0", + "name": "layer2_specularF0", "displayName": "Layer 2: Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "layer2_normal", + "name": "layer2_normal", "displayName": "Layer 2: Normal", "description": "Properties related to configuring surface normal." }, { - "id": "layer2_occlusion", + "name": "layer2_occlusion", "displayName": "Layer 2: Occlusion", "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { - "id": "layer2_emissive", + "name": "layer2_emissive", "displayName": "Layer 2: Emissive", "description": "Properties to add light emission, independent of other lights in the scene." }, { - "id": "layer2_clearCoat", + "name": "layer2_clearCoat", "displayName": "Layer 2: Clear Coat", "description": "Properties for configuring gloss clear coat" }, { - "id": "layer2_parallax", + "name": "layer2_parallax", "displayName": "Layer 2: Displacement", "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { - "id": "layer2_uv", + "name": "layer2_uv", "displayName": "Layer 2: UVs", "description": "Properties for configuring UV transforms." }, @@ -139,52 +139,52 @@ // Layer 3 Groups //############################################################################################## { - "id": "layer3_baseColor", + "name": "layer3_baseColor", "displayName": "Layer 3: Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "layer3_metallic", + "name": "layer3_metallic", "displayName": "Layer 3: Metallic", "description": "Properties for configuring whether the surface is metallic or not." }, { - "id": "layer3_roughness", + "name": "layer3_roughness", "displayName": "Layer 3: Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "layer3_specularF0", + "name": "layer3_specularF0", "displayName": "Layer 3: Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "layer3_normal", + "name": "layer3_normal", "displayName": "Layer 3: Normal", "description": "Properties related to configuring surface normal." }, { - "id": "layer3_occlusion", + "name": "layer3_occlusion", "displayName": "Layer 3: Occlusion", "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { - "id": "layer3_emissive", + "name": "layer3_emissive", "displayName": "Layer 3: Emissive", "description": "Properties to add light emission, independent of other lights in the scene." }, { - "id": "layer3_clearCoat", + "name": "layer3_clearCoat", "displayName": "Layer 3: Clear Coat", "description": "Properties for configuring gloss clear coat" }, { - "id": "layer3_parallax", + "name": "layer3_parallax", "displayName": "Layer 3: Displacement", "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { - "id": "layer3_uv", + "name": "layer3_uv", "displayName": "Layer 3: UVs", "description": "Properties for configuring UV transforms." } @@ -195,118 +195,118 @@ //############################################################################################## "general": [ { - "id": "applySpecularAA", + "name": "applySpecularAA", "displayName": "Apply Specular AA", "description": "Whether to apply specular anti-aliasing in the shader.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_applySpecularAA" + "name": "o_applySpecularAA" } }, { - "id": "enableMultiScatterCompensation", + "name": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", "description": "Whether to enable multiple scattering compensation.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" + "name": "o_specularF0_enableMultiScatterCompensation" } }, { - "id": "enableShadows", + "name": "enableShadows", "displayName": "Enable Shadows", "description": "Whether to use the shadow maps.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableShadows" + "name": "o_enableShadows" } }, { - "id": "enableDirectionalLights", + "name": "enableDirectionalLights", "displayName": "Enable Directional Lights", "description": "Whether to use directional lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableDirectionalLights" + "name": "o_enableDirectionalLights" } }, { - "id": "enablePunctualLights", + "name": "enablePunctualLights", "displayName": "Enable Punctual Lights", "description": "Whether to use punctual lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enablePunctualLights" + "name": "o_enablePunctualLights" } }, { - "id": "enableAreaLights", + "name": "enableAreaLights", "displayName": "Enable Area Lights", "description": "Whether to use area lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableAreaLights" + "name": "o_enableAreaLights" } }, { - "id": "enableIBL", + "name": "enableIBL", "displayName": "Enable IBL", "description": "Whether to use Image Based Lighting (IBL).", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableIBL" + "name": "o_enableIBL" } }, { - "id": "forwardPassIBLSpecular", + "name": "forwardPassIBLSpecular", "displayName": "Forward Pass IBL Specular", "description": "Whether to apply IBL specular in the forward pass.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_materialUseForwardPassIBLSpecular" + "name": "o_materialUseForwardPassIBLSpecular" } } ], "blend": [ { - "id": "enableLayer2", + "name": "enableLayer2", "displayName": "Enable Layer 2", "description": "Whether to enable layer 2.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_layer2_enabled" + "name": "o_layer2_enabled" } }, { - "id": "enableLayer3", + "name": "enableLayer3", "displayName": "Enable Layer 3", "description": "Whether to enable layer 3.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_layer3_enabled" + "name": "o_layer3_enabled" } }, { - "id": "blendSource", + "name": "blendSource", "displayName": "Blend Source", "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", "type": "Enum", @@ -314,22 +314,22 @@ "defaultValue": "BlendMaskTexture", "connection": { "type": "ShaderOption", - "id": "o_layerBlendSource" + "name": "o_layerBlendSource" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Blend Mask Texture", "description": "RGB image where each channel is the blend mask for one of the three available layers.", "type": "Image", "defaultValue": "Textures/DefaultBlendMask_layers.png", "connection": { "type": "ShaderInput", - "id": "m_blendMaskTexture" + "name": "m_blendMaskTexture" } }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "Blend Mask UV", "description": "Blend Mask UV set.", "type": "Enum", @@ -337,11 +337,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_blendMaskUvIndex" + "name": "m_blendMaskUvIndex" } }, { - "id": "displacementBlendDistance", + "name": "displacementBlendDistance", "displayName": "Blend Distance", "description": "Adjusts how smoothly to transition between layers when displacement blending is enabled.", "type": "Float", @@ -351,11 +351,11 @@ "step": 0.001, "connection": { "type": "ShaderInput", - "id": "m_displacementBlendDistance" + "name": "m_displacementBlendDistance" } }, { - "id": "debugDrawMode", + "name": "debugDrawMode", "displayName": "Debug Draw Mode", "description": "Enables various debug view features.", "type": "Enum", @@ -363,7 +363,7 @@ "defaultValue": "None", "connection": { "type": "ShaderOption", - "id": "o_debugDrawMode" + "name": "o_debugDrawMode" } } ], @@ -372,14 +372,14 @@ // Note parallax is enabled by default so that as soon as a user hooks up displacement settings they will see some parallax applied. // The functor that controls parallax will set o_parallax_feature_enabled=false when all the individual layers have no displacement, so // a default value of true here will not have any initial impact on performance. - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Whether to enable the parallax feature for this material.", "type": "Bool", "defaultValue": true }, { - "id": "parallaxUv", + "name": "parallaxUv", "displayName": "UV", "description": "UV set that supports parallax mapping.", "type": "Enum", @@ -387,11 +387,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_parallaxUvIndex" + "name": "m_parallaxUvIndex" } }, { - "id": "algorithm", + "name": "algorithm", "displayName": "Algorithm", "description": "Select the algorithm to use for parallax mapping.", "type": "Enum", @@ -399,11 +399,11 @@ "defaultValue": "POM", "connection": { "type": "ShaderOption", - "id": "o_parallax_algorithm" + "name": "o_parallax_algorithm" } }, { - "id": "quality", + "name": "quality", "displayName": "Quality", "description": "Quality of parallax mapping.", "type": "Enum", @@ -411,35 +411,35 @@ "defaultValue": "Low", "connection": { "type": "ShaderOption", - "id": "o_parallax_quality" + "name": "o_parallax_quality" } }, { - "id": "pdo", + "name": "pdo", "displayName": "Pixel Depth Offset", "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_enablePixelDepthOffset" + "name": "o_parallax_enablePixelDepthOffset" } }, { - "id": "showClipping", + "name": "showClipping", "displayName": "Show Clipping", "description": "Highlight areas where the height map is clipped by the mesh surface.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_highlightClipping" + "name": "o_parallax_highlightClipping" } } ], "uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -447,7 +447,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -455,7 +455,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -463,7 +463,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -473,7 +473,7 @@ "step": 0.001 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -483,7 +483,7 @@ "step": 0.001 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -493,7 +493,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -504,14 +504,14 @@ "irradiance": [ // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ] }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -525,18 +525,18 @@ //############################################################################################## "layer1_baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer1_m_baseColor" + "name": "m_layer1_m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -545,28 +545,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_baseColorFactor" + "name": "m_layer1_m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_baseColorMap" + "name": "m_layer1_m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -574,11 +574,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_baseColorMapUvIndex" + "name": "m_layer1_m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -586,13 +586,13 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_layer1_o_baseColorTextureBlendMode" + "name": "o_layer1_o_baseColorTextureBlendMode" } } ], "layer1_metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -601,28 +601,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_metallicFactor" + "name": "m_layer1_m_metallicFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_metallicMap" + "name": "m_layer1_m_metallicMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Metallic map UV set", "type": "Enum", @@ -630,30 +630,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_metallicMapUvIndex" + "name": "m_layer1_m_metallicMapUvIndex" } } ], "layer1_roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_roughnessMap" + "name": "m_layer1_m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -661,12 +661,12 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_roughnessMapUvIndex" + "name": "m_layer1_m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -675,12 +675,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_roughnessLowerBound" + "name": "m_layer1_m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -689,12 +689,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_roughnessUpperBound" + "name": "m_layer1_m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -703,13 +703,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_roughnessFactor" + "name": "m_layer1_m_roughnessFactor" } } ], "layer1_specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -718,28 +718,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularF0Factor" + "name": "m_layer1_m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularF0Map" + "name": "m_layer1_m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -747,30 +747,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularF0MapUvIndex" + "name": "m_layer1_m_specularF0MapUvIndex" } } ], "layer1_normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_normalMap" + "name": "m_layer1_m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -778,33 +778,33 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_normalMapUvIndex" + "name": "m_layer1_m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_flipNormalX" + "name": "m_layer1_m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_flipNormalY" + "name": "m_layer1_m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -813,20 +813,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_normalFactor" + "name": "m_layer1_m_normalFactor" } } ], "layer1_clearCoat": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the percentage of effect applied", "type": "Float", @@ -835,28 +835,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatFactor" + "name": "m_layer1_m_clearCoatFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Strength factor texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatInfluenceMap" + "name": "m_layer1_m_clearCoatInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Strength factor map UV set", "type": "Enum", @@ -864,11 +864,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatInfluenceMapUvIndex" + "name": "m_layer1_m_clearCoatInfluenceMapUvIndex" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Clear coat layer roughness", "type": "Float", @@ -877,28 +877,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughness" + "name": "m_layer1_m_clearCoatRoughness" } }, { - "id": "roughnessMap", + "name": "roughnessMap", "displayName": " Roughness Map", "description": "Texture for defining surface roughness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughnessMap" + "name": "m_layer1_m_clearCoatRoughnessMap" } }, { - "id": "useRoughnessMap", + "name": "useRoughnessMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the roughness value.", "type": "Bool", "defaultValue": true }, { - "id": "roughnessMapUv", + "name": "roughnessMapUv", "displayName": " UV", "description": "Roughness map UV set", "type": "Enum", @@ -906,11 +906,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatRoughnessMapUvIndex" + "name": "m_layer1_m_clearCoatRoughnessMapUvIndex" } }, { - "id": "normalStrength", + "name": "normalStrength", "displayName": "Normal Strength", "description": "Scales the impact of the clear coat normal map", "type": "Float", @@ -919,28 +919,28 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalStrength" + "name": "m_layer1_m_clearCoatNormalStrength" } }, { - "id": "normalMap", + "name": "normalMap", "displayName": "Normal Map", "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalMap" + "name": "m_layer1_m_clearCoatNormalMap" } }, { - "id": "useNormalMap", + "name": "useNormalMap", "displayName": " Use Texture", "description": "Whether to use the normal map", "type": "Bool", "defaultValue": true }, { - "id": "normalMapUv", + "name": "normalMapUv", "displayName": " UV", "description": "Normal map UV set", "type": "Enum", @@ -948,30 +948,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_clearCoatNormalMapUvIndex" + "name": "m_layer1_m_clearCoatNormalMapUvIndex" } } ], "layer1_occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionMap" + "name": "m_layer1_m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -979,11 +979,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionMapUvIndex" + "name": "m_layer1_m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -992,28 +992,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_diffuseOcclusionFactor" + "name": "m_layer1_m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionMap" + "name": "m_layer1_m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -1021,11 +1021,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionMapUvIndex" + "name": "m_layer1_m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -1034,20 +1034,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_specularOcclusionFactor" + "name": "m_layer1_m_specularOcclusionFactor" } } ], "layer1_emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", "defaultValue": false }, { - "id": "unit", + "name": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", @@ -1055,18 +1055,18 @@ "defaultValue": "Ev100" }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer1_m_emissiveColor" + "name": "m_layer1_m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted.", "type": "Float", @@ -1077,24 +1077,24 @@ "softMax": 16 }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_emissiveMap" + "name": "m_layer1_m_emissiveMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Emissive map UV set", "type": "Enum", @@ -1102,30 +1102,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_emissiveMapUvIndex" + "name": "m_layer1_m_emissiveMapUvIndex" } } ], "layer1_parallax": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Height Map", "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_heightmap" + "name": "m_layer1_m_heightmap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the height map.", "type": "Bool", "defaultValue": true }, { - "id": "factor", + "name": "factor", "displayName": "Scale", "description": "The total height of the height map in local model units.", "type": "Float", @@ -1134,11 +1134,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_heightmapScale" + "name": "m_layer1_m_heightmapScale" } }, { - "id": "offset", + "name": "offset", "displayName": "Offset", "description": "Adjusts the overall displacement amount in local model units.", "type": "Float", @@ -1147,13 +1147,13 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_heightmapOffset" + "name": "m_layer1_m_heightmapOffset" } } ], "layer1_uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -1161,7 +1161,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -1169,7 +1169,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -1177,7 +1177,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -1187,7 +1187,7 @@ "step": 0.001 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -1197,7 +1197,7 @@ "step": 0.001 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -1207,7 +1207,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -1220,18 +1220,18 @@ //############################################################################################## "layer2_baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer2_m_baseColor" + "name": "m_layer2_m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -1240,28 +1240,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_baseColorFactor" + "name": "m_layer2_m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_baseColorMap" + "name": "m_layer2_m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -1269,11 +1269,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_baseColorMapUvIndex" + "name": "m_layer2_m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -1281,13 +1281,13 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_layer2_o_baseColorTextureBlendMode" + "name": "o_layer2_o_baseColorTextureBlendMode" } } ], "layer2_metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -1296,28 +1296,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_metallicFactor" + "name": "m_layer2_m_metallicFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_metallicMap" + "name": "m_layer2_m_metallicMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Metallic map UV set", "type": "Enum", @@ -1325,30 +1325,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_metallicMapUvIndex" + "name": "m_layer2_m_metallicMapUvIndex" } } ], "layer2_roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_roughnessMap" + "name": "m_layer2_m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -1356,12 +1356,12 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_roughnessMapUvIndex" + "name": "m_layer2_m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -1370,12 +1370,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_roughnessLowerBound" + "name": "m_layer2_m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -1384,12 +1384,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_roughnessUpperBound" + "name": "m_layer2_m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -1398,13 +1398,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_roughnessFactor" + "name": "m_layer2_m_roughnessFactor" } } ], "layer2_specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -1413,28 +1413,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularF0Factor" + "name": "m_layer2_m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularF0Map" + "name": "m_layer2_m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -1442,30 +1442,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularF0MapUvIndex" + "name": "m_layer2_m_specularF0MapUvIndex" } } ], "layer2_normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_normalMap" + "name": "m_layer2_m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -1473,33 +1473,33 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_normalMapUvIndex" + "name": "m_layer2_m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_flipNormalX" + "name": "m_layer2_m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_flipNormalY" + "name": "m_layer2_m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -1508,20 +1508,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_normalFactor" + "name": "m_layer2_m_normalFactor" } } ], "layer2_clearCoat": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the percentage of effect applied", "type": "Float", @@ -1530,28 +1530,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatFactor" + "name": "m_layer2_m_clearCoatFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Strength factor texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatInfluenceMap" + "name": "m_layer2_m_clearCoatInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Strength factor map UV set", "type": "Enum", @@ -1559,11 +1559,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatInfluenceMapUvIndex" + "name": "m_layer2_m_clearCoatInfluenceMapUvIndex" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Clear coat layer roughness", "type": "Float", @@ -1572,28 +1572,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughness" + "name": "m_layer2_m_clearCoatRoughness" } }, { - "id": "roughnessMap", + "name": "roughnessMap", "displayName": " Roughness Map", "description": "Texture for defining surface roughness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughnessMap" + "name": "m_layer2_m_clearCoatRoughnessMap" } }, { - "id": "useRoughnessMap", + "name": "useRoughnessMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the roughness value.", "type": "Bool", "defaultValue": true }, { - "id": "roughnessMapUv", + "name": "roughnessMapUv", "displayName": " UV", "description": "Roughness map UV set", "type": "Enum", @@ -1601,11 +1601,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatRoughnessMapUvIndex" + "name": "m_layer2_m_clearCoatRoughnessMapUvIndex" } }, { - "id": "normalStrength", + "name": "normalStrength", "displayName": "Normal Strength", "description": "Scales the impact of the clear coat normal map", "type": "Float", @@ -1614,28 +1614,28 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalStrength" + "name": "m_layer2_m_clearCoatNormalStrength" } }, { - "id": "normalMap", + "name": "normalMap", "displayName": "Normal Map", "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalMap" + "name": "m_layer2_m_clearCoatNormalMap" } }, { - "id": "useNormalMap", + "name": "useNormalMap", "displayName": " Use Texture", "description": "Whether to use the normal map", "type": "Bool", "defaultValue": true }, { - "id": "normalMapUv", + "name": "normalMapUv", "displayName": " UV", "description": "Normal map UV set", "type": "Enum", @@ -1643,30 +1643,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_clearCoatNormalMapUvIndex" + "name": "m_layer2_m_clearCoatNormalMapUvIndex" } } ], "layer2_occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionMap" + "name": "m_layer2_m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -1674,11 +1674,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionMapUvIndex" + "name": "m_layer2_m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -1687,28 +1687,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_diffuseOcclusionFactor" + "name": "m_layer2_m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionMap" + "name": "m_layer2_m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -1716,11 +1716,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionMapUvIndex" + "name": "m_layer2_m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -1729,20 +1729,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_specularOcclusionFactor" + "name": "m_layer2_m_specularOcclusionFactor" } } ], "layer2_emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", "defaultValue": false }, { - "id": "unit", + "name": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", @@ -1750,18 +1750,18 @@ "defaultValue": "Ev100" }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer2_m_emissiveColor" + "name": "m_layer2_m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted.", "type": "Float", @@ -1772,24 +1772,24 @@ "softMax": 16 }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_emissiveMap" + "name": "m_layer2_m_emissiveMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Emissive map UV set", "type": "Enum", @@ -1797,30 +1797,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_emissiveMapUvIndex" + "name": "m_layer2_m_emissiveMapUvIndex" } } ], "layer2_parallax": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Height Map", "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_heightmap" + "name": "m_layer2_m_heightmap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the height map.", "type": "Bool", "defaultValue": true }, { - "id": "factor", + "name": "factor", "displayName": "Scale", "description": "The total height of the height map in local model units.", "type": "Float", @@ -1829,11 +1829,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_heightmapScale" + "name": "m_layer2_m_heightmapScale" } }, { - "id": "offset", + "name": "offset", "displayName": "Offset", "description": "Adjusts the overall displacement amount in local model units.", "type": "Float", @@ -1842,13 +1842,13 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_heightmapOffset" + "name": "m_layer2_m_heightmapOffset" } } ], "layer2_uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -1856,7 +1856,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -1864,7 +1864,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -1872,7 +1872,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -1882,7 +1882,7 @@ "step": 0.001 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -1892,7 +1892,7 @@ "step": 0.001 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -1902,7 +1902,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -1915,18 +1915,18 @@ //############################################################################################## "layer3_baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer3_m_baseColor" + "name": "m_layer3_m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -1935,28 +1935,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_baseColorFactor" + "name": "m_layer3_m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_baseColorMap" + "name": "m_layer3_m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -1964,11 +1964,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_baseColorMapUvIndex" + "name": "m_layer3_m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -1976,13 +1976,13 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_layer3_o_baseColorTextureBlendMode" + "name": "o_layer3_o_baseColorTextureBlendMode" } } ], "layer3_metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -1991,28 +1991,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_metallicFactor" + "name": "m_layer3_m_metallicFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_metallicMap" + "name": "m_layer3_m_metallicMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Metallic map UV set", "type": "Enum", @@ -2020,30 +2020,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_metallicMapUvIndex" + "name": "m_layer3_m_metallicMapUvIndex" } } ], "layer3_roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_roughnessMap" + "name": "m_layer3_m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -2051,12 +2051,12 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_roughnessMapUvIndex" + "name": "m_layer3_m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -2065,12 +2065,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_roughnessLowerBound" + "name": "m_layer3_m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -2079,12 +2079,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_roughnessUpperBound" + "name": "m_layer3_m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -2093,13 +2093,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_roughnessFactor" + "name": "m_layer3_m_roughnessFactor" } } ], "layer3_specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -2108,28 +2108,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularF0Factor" + "name": "m_layer3_m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularF0Map" + "name": "m_layer3_m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -2137,30 +2137,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularF0MapUvIndex" + "name": "m_layer3_m_specularF0MapUvIndex" } } ], "layer3_normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_normalMap" + "name": "m_layer3_m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -2168,33 +2168,33 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_normalMapUvIndex" + "name": "m_layer3_m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_flipNormalX" + "name": "m_layer3_m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_flipNormalY" + "name": "m_layer3_m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -2203,20 +2203,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_normalFactor" + "name": "m_layer3_m_normalFactor" } } ], "layer3_clearCoat": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the percentage of effect applied", "type": "Float", @@ -2225,28 +2225,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatFactor" + "name": "m_layer3_m_clearCoatFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Strength factor texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatInfluenceMap" + "name": "m_layer3_m_clearCoatInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Strength factor map UV set", "type": "Enum", @@ -2254,11 +2254,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatInfluenceMapUvIndex" + "name": "m_layer3_m_clearCoatInfluenceMapUvIndex" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Clear coat layer roughness", "type": "Float", @@ -2267,28 +2267,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughness" + "name": "m_layer3_m_clearCoatRoughness" } }, { - "id": "roughnessMap", + "name": "roughnessMap", "displayName": " Roughness Map", "description": "Texture for defining surface roughness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughnessMap" + "name": "m_layer3_m_clearCoatRoughnessMap" } }, { - "id": "useRoughnessMap", + "name": "useRoughnessMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the roughness value.", "type": "Bool", "defaultValue": true }, { - "id": "roughnessMapUv", + "name": "roughnessMapUv", "displayName": " UV", "description": "Roughness map UV set", "type": "Enum", @@ -2296,11 +2296,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatRoughnessMapUvIndex" + "name": "m_layer3_m_clearCoatRoughnessMapUvIndex" } }, { - "id": "normalStrength", + "name": "normalStrength", "displayName": "Normal Strength", "description": "Scales the impact of the clear coat normal map", "type": "Float", @@ -2309,28 +2309,28 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalStrength" + "name": "m_layer3_m_clearCoatNormalStrength" } }, { - "id": "normalMap", + "name": "normalMap", "displayName": "Normal Map", "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalMap" + "name": "m_layer3_m_clearCoatNormalMap" } }, { - "id": "useNormalMap", + "name": "useNormalMap", "displayName": " Use Texture", "description": "Whether to use the normal map", "type": "Bool", "defaultValue": true }, { - "id": "normalMapUv", + "name": "normalMapUv", "displayName": " UV", "description": "Normal map UV set", "type": "Enum", @@ -2338,30 +2338,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_clearCoatNormalMapUvIndex" + "name": "m_layer3_m_clearCoatNormalMapUvIndex" } } ], "layer3_occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionMap" + "name": "m_layer3_m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -2369,11 +2369,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionMapUvIndex" + "name": "m_layer3_m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -2382,28 +2382,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_diffuseOcclusionFactor" + "name": "m_layer3_m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionMap" + "name": "m_layer3_m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -2411,11 +2411,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionMapUvIndex" + "name": "m_layer3_m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -2424,20 +2424,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_specularOcclusionFactor" + "name": "m_layer3_m_specularOcclusionFactor" } } ], "layer3_emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", "defaultValue": false }, { - "id": "unit", + "name": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", @@ -2445,18 +2445,18 @@ "defaultValue": "Ev100" }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_layer3_m_emissiveColor" + "name": "m_layer3_m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted.", "type": "Float", @@ -2467,24 +2467,24 @@ "softMax": 16 }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_emissiveMap" + "name": "m_layer3_m_emissiveMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Emissive map UV set", "type": "Enum", @@ -2492,30 +2492,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_emissiveMapUvIndex" + "name": "m_layer3_m_emissiveMapUvIndex" } } ], "layer3_parallax": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Height Map", "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_heightmap" + "name": "m_layer3_m_heightmap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the height map.", "type": "Bool", "defaultValue": true }, { - "id": "factor", + "name": "factor", "displayName": "Scale", "description": "The total height of the height map in local model units.", "type": "Float", @@ -2524,11 +2524,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_heightmapScale" + "name": "m_layer3_m_heightmapScale" } }, { - "id": "offset", + "name": "offset", "displayName": "Offset", "description": "Adjusts the overall displacement amount in local model units.", "type": "Float", @@ -2537,13 +2537,13 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_layer3_m_heightmapOffset" + "name": "m_layer3_m_heightmapOffset" } } ], "layer3_uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -2551,7 +2551,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in V.", "type": "float", @@ -2559,7 +2559,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -2567,7 +2567,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -2577,7 +2577,7 @@ "step": 0.001 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -2587,7 +2587,7 @@ "step": 0.001 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -2597,7 +2597,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 8b7e4b1c7e..6eb82b85ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -4,68 +4,68 @@ "version": 3, "groups": [ { - "id": "baseColor", + "name": "baseColor", "displayName": "Base Color", "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." }, { - "id": "metallic", + "name": "metallic", "displayName": "Metallic", "description": "Properties for configuring whether the surface is metallic or not." }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Properties for configuring how rough the surface appears." }, { - "id": "specularF0", + "name": "specularF0", "displayName": "Specular Reflectance f0", "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." }, { - "id": "normal", + "name": "normal", "displayName": "Normal", "description": "Properties related to configuring surface normal." }, { - "id": "occlusion", + "name": "occlusion", "displayName": "Occlusion", "description": "Properties for baked textures that represent geometric occlusion of light." }, { - "id": "emissive", + "name": "emissive", "displayName": "Emissive", "description": "Properties to add light emission, independent of other lights in the scene." }, { - "id": "clearCoat", + "name": "clearCoat", "displayName": "Clear Coat", "description": "Properties for configuring gloss clear coat" }, { - "id": "parallax", + "name": "parallax", "displayName": "Displacement", "description": "Properties for parallax effect produced by a height map." }, { - "id": "opacity", + "name": "opacity", "displayName": "Opacity", "description": "Properties for configuring the materials transparency." }, { - "id": "uv", + "name": "uv", "displayName": "UVs", "description": "Properties for configuring UV transforms." }, { // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader - "id": "irradiance", + "name": "irradiance", "displayName": "Irradiance", "description": "Properties for configuring the irradiance used in global illumination." }, { - "id": "general", + "name": "general", "displayName": "General Settings", "description": "General settings." } @@ -73,97 +73,97 @@ "properties": { "general": [ { - "id": "applySpecularAA", + "name": "applySpecularAA", "displayName": "Apply Specular AA", "description": "Whether to apply specular anti-aliasing in the shader.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_applySpecularAA" + "name": "o_applySpecularAA" } }, { - "id": "enableShadows", + "name": "enableShadows", "displayName": "Enable Shadows", "description": "Whether to use the shadow maps.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableShadows" + "name": "o_enableShadows" } }, { - "id": "enableDirectionalLights", + "name": "enableDirectionalLights", "displayName": "Enable Directional Lights", "description": "Whether to use directional lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableDirectionalLights" + "name": "o_enableDirectionalLights" } }, { - "id": "enablePunctualLights", + "name": "enablePunctualLights", "displayName": "Enable Punctual Lights", "description": "Whether to use punctual lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enablePunctualLights" + "name": "o_enablePunctualLights" } }, { - "id": "enableAreaLights", + "name": "enableAreaLights", "displayName": "Enable Area Lights", "description": "Whether to use area lights.", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableAreaLights" + "name": "o_enableAreaLights" } }, { - "id": "enableIBL", + "name": "enableIBL", "displayName": "Enable IBL", "description": "Whether to use Image Based Lighting (IBL).", "type": "Bool", "defaultValue": true, "connection": { "type": "ShaderOption", - "id": "o_enableIBL" + "name": "o_enableIBL" } }, { - "id": "forwardPassIBLSpecular", + "name": "forwardPassIBLSpecular", "displayName": "Forward Pass IBL Specular", "description": "Whether to apply IBL specular in the forward pass.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_materialUseForwardPassIBLSpecular" + "name": "o_materialUseForwardPassIBLSpecular" } } ], "baseColor": [ { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_baseColor" + "name": "m_baseColor" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", @@ -172,28 +172,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_baseColorFactor" + "name": "m_baseColorFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Base color texture map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_baseColorMap" + "name": "m_baseColorMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Base color map UV set", "type": "Enum", @@ -201,11 +201,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_baseColorMapUvIndex" + "name": "m_baseColorMapUvIndex" } }, { - "id": "textureBlendMode", + "name": "textureBlendMode", "displayName": "Texture Blend Mode", "description": "Selects the equation to use when combining Color, Factor, and Texture.", "type": "Enum", @@ -213,13 +213,13 @@ "defaultValue": "Multiply", "connection": { "type": "ShaderOption", - "id": "o_baseColorTextureBlendMode" + "name": "o_baseColorTextureBlendMode" } } ], "metallic": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "This value is linear, black is non-metal and white means raw metal.", "type": "Float", @@ -228,28 +228,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_metallicFactor" + "name": "m_metallicFactor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_metallicMap" + "name": "m_metallicMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Metallic map UV set", "type": "Enum", @@ -257,30 +257,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_metallicMapUvIndex" + "name": "m_metallicMapUvIndex" } } ], "roughness": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface roughness.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_roughnessMap" + "name": "m_roughnessMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Roughness map UV set", "type": "Enum", @@ -288,12 +288,12 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_roughnessMapUvIndex" + "name": "m_roughnessMapUvIndex" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "lowerBound", + "name": "lowerBound", "displayName": "Lower Bound", "description": "The roughness value that corresponds to black in the texture.", "type": "Float", @@ -302,12 +302,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessLowerBound" + "name": "m_roughnessLowerBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "upperBound", + "name": "upperBound", "displayName": "Upper Bound", "description": "The roughness value that corresponds to white in the texture.", "type": "Float", @@ -316,12 +316,12 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessUpperBound" + "name": "m_roughnessUpperBound" } }, { // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Controls the roughness value", "type": "Float", @@ -330,13 +330,13 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughnessFactor" + "name": "m_roughnessFactor" } } ], "specularF0": [ { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", "type": "Float", @@ -345,28 +345,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_specularF0Factor" + "name": "m_specularF0Factor" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface reflectance.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularF0Map" + "name": "m_specularF0Map" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Specular reflection map UV set", "type": "Enum", @@ -374,31 +374,31 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_specularF0MapUvIndex" + "name": "m_specularF0MapUvIndex" } }, // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR { - "id": "enableMultiScatterCompensation", + "name": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", "description": "Whether to enable multiple scattering compensation.", "type": "Bool", "connection": { "type": "ShaderOption", - "id": "o_specularF0_enableMultiScatterCompensation" + "name": "o_specularF0_enableMultiScatterCompensation" } } ], "clearCoat": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", "defaultValue": false }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the percentage of effect applied", "type": "Float", @@ -407,28 +407,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatFactor" + "name": "m_clearCoatFactor" } }, { - "id": "influenceMap", + "name": "influenceMap", "displayName": " Influence Map", "description": "Strength factor texture", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatInfluenceMap" + "name": "m_clearCoatInfluenceMap" } }, { - "id": "useInfluenceMap", + "name": "useInfluenceMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the Factor value.", "type": "Bool", "defaultValue": true }, { - "id": "influenceMapUv", + "name": "influenceMapUv", "displayName": " UV", "description": "Strength factor map UV set", "type": "Enum", @@ -436,11 +436,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatInfluenceMapUvIndex" + "name": "m_clearCoatInfluenceMapUvIndex" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "description": "Clear coat layer roughness", "type": "Float", @@ -449,28 +449,28 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughness" + "name": "m_clearCoatRoughness" } }, { - "id": "roughnessMap", + "name": "roughnessMap", "displayName": " Roughness Map", "description": "Texture for defining surface roughness", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughnessMap" + "name": "m_clearCoatRoughnessMap" } }, { - "id": "useRoughnessMap", + "name": "useRoughnessMap", "displayName": " Use Texture", "description": "Whether to use the texture, or just default to the roughness value.", "type": "Bool", "defaultValue": true }, { - "id": "roughnessMapUv", + "name": "roughnessMapUv", "displayName": " UV", "description": "Roughness map UV set", "type": "Enum", @@ -478,11 +478,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatRoughnessMapUvIndex" + "name": "m_clearCoatRoughnessMapUvIndex" } }, { - "id": "normalStrength", + "name": "normalStrength", "displayName": "Normal Strength", "description": "Scales the impact of the clear coat normal map", "type": "Float", @@ -491,28 +491,28 @@ "max": 2.0, "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalStrength" + "name": "m_clearCoatNormalStrength" } }, { - "id": "normalMap", + "name": "normalMap", "displayName": "Normal Map", "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalMap" + "name": "m_clearCoatNormalMap" } }, { - "id": "useNormalMap", + "name": "useNormalMap", "displayName": " Use Texture", "description": "Whether to use the normal map", "type": "Bool", "defaultValue": true }, { - "id": "normalMapUv", + "name": "normalMapUv", "displayName": " UV", "description": "Normal map UV set", "type": "Enum", @@ -520,30 +520,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_clearCoatNormalMapUvIndex" + "name": "m_clearCoatNormalMapUvIndex" } } ], "normal": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface normal direction.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_normalMap" + "name": "m_normalMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture, or just rely on vertex normals.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Normal map UV set", "type": "Enum", @@ -551,33 +551,33 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_normalMapUvIndex" + "name": "m_normalMapUvIndex" } }, { - "id": "flipX", + "name": "flipX", "displayName": "Flip X Channel", "description": "Flip tangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalX" + "name": "m_flipNormalX" } }, { - "id": "flipY", + "name": "flipY", "displayName": "Flip Y Channel", "description": "Flip bitangent direction for this normal map.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderInput", - "id": "m_flipNormalY" + "name": "m_flipNormalY" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the values", "type": "Float", @@ -586,13 +586,13 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_normalFactor" + "name": "m_normalFactor" } } ], "opacity": [ { - "id": "mode", + "name": "mode", "displayName": "Opacity Mode", "description": "Indicates the general approach how transparency is to be applied.", "type": "Enum", @@ -600,11 +600,11 @@ "defaultValue": "Opaque", "connection": { "type": "ShaderOption", - "id": "o_opacity_mode" + "name": "o_opacity_mode" } }, { - "id": "alphaSource", + "name": "alphaSource", "displayName": "Alpha Source", "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).", "type": "Enum", @@ -612,21 +612,21 @@ "defaultValue": "Packed", "connection": { "type": "ShaderOption", - "id": "o_opacity_source" + "name": "o_opacity_source" } }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining surface opacity.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_opacityMap" + "name": "m_opacityMap" } }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Opacity map UV set", "type": "Enum", @@ -634,11 +634,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_opacityMapUvIndex" + "name": "m_opacityMapUvIndex" } }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Factor for cutout threshold and blending", "type": "Float", @@ -647,17 +647,17 @@ "defaultValue": 0.5, "connection": { "type": "ShaderInput", - "id": "m_opacityFactor" + "name": "m_opacityFactor" } }, { - "id": "doubleSided", + "name": "doubleSided", "displayName": "Double-sided", "description": "Whether to render back-faces or just front-faces.", "type": "Bool" }, { - "id": "alphaAffectsSpecular", + "name": "alphaAffectsSpecular", "displayName": "Alpha affects specular", "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", "type": "float", @@ -666,13 +666,13 @@ "defaultValue": 0.0, "connection": { "type": "ShaderInput", - "id": "m_opacityAffectsSpecularFactor" + "name": "m_opacityAffectsSpecularFactor" } } ], "uv": [ { - "id": "center", + "name": "center", "displayName": "Center", "description": "Center point for scaling and rotation transformations.", "type": "vector2", @@ -680,7 +680,7 @@ "defaultValue": [ 0.5, 0.5 ] }, { - "id": "tileU", + "name": "tileU", "displayName": "Tile U", "description": "Scales texture coordinates in U.", "type": "float", @@ -688,7 +688,7 @@ "step": 0.1 }, { - "id": "tileV", + "name": "tileV", "displayName": "Tile V", "description": "Scales texture coordinates in V.", "type": "float", @@ -696,7 +696,7 @@ "step": 0.1 }, { - "id": "offsetU", + "name": "offsetU", "displayName": "Offset U", "description": "Offsets texture coordinates in the U direction.", "type": "float", @@ -705,7 +705,7 @@ "max": 1.0 }, { - "id": "offsetV", + "name": "offsetV", "displayName": "Offset V", "description": "Offsets texture coordinates in the V direction.", "type": "float", @@ -714,7 +714,7 @@ "max": 1.0 }, { - "id": "rotateDegrees", + "name": "rotateDegrees", "displayName": "Rotate", "description": "Rotates the texture coordinates (degrees).", "type": "float", @@ -724,7 +724,7 @@ "step": 1.0 }, { - "id": "scale", + "name": "scale", "displayName": "Scale", "description": "Scales texture coordinates in both U and V.", "type": "float", @@ -734,24 +734,24 @@ ], "occlusion": [ { - "id": "diffuseTextureMap", + "name": "diffuseTextureMap", "displayName": "Diffuse AO", "description": "Texture for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMap" + "name": "m_diffuseOcclusionMap" } }, { - "id": "diffuseUseTexture", + "name": "diffuseUseTexture", "displayName": " Use Texture", "description": "Whether to use the Diffuse AO map.", "type": "Bool", "defaultValue": true }, { - "id": "diffuseTextureMapUv", + "name": "diffuseTextureMapUv", "displayName": " UV", "description": "Diffuse AO map UV set.", "type": "Enum", @@ -759,11 +759,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionMapUvIndex" + "name": "m_diffuseOcclusionMapUvIndex" } }, { - "id": "diffuseFactor", + "name": "diffuseFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", @@ -772,28 +772,28 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_diffuseOcclusionFactor" + "name": "m_diffuseOcclusionFactor" } }, { - "id": "specularTextureMap", + "name": "specularTextureMap", "displayName": "Specular Cavity", "description": "Texture for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMap" + "name": "m_specularOcclusionMap" } }, { - "id": "specularUseTexture", + "name": "specularUseTexture", "displayName": " Use Texture", "description": "Whether to use the Specular Cavity map.", "type": "Bool", "defaultValue": true }, { - "id": "specularTextureMapUv", + "name": "specularTextureMapUv", "displayName": " UV", "description": "Specular Cavity map UV set.", "type": "Enum", @@ -801,11 +801,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionMapUvIndex" + "name": "m_specularOcclusionMapUvIndex" } }, { - "id": "specularFactor", + "name": "specularFactor", "displayName": " Factor", "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", @@ -814,20 +814,20 @@ "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_specularOcclusionFactor" + "name": "m_specularOcclusionFactor" } } ], "emissive": [ { - "id": "enable", + "name": "enable", "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", "defaultValue": false }, { - "id": "unit", + "name": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", @@ -835,18 +835,18 @@ "defaultValue": "Ev100" }, { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_emissiveColor" + "name": "m_emissiveColor" } }, { - "id": "intensity", + "name": "intensity", "displayName": "Intensity", "description": "The amount of energy emitted.", "type": "Float", @@ -857,24 +857,24 @@ "softMax": 16 }, { - "id": "textureMap", + "name": "textureMap", "displayName": "Texture", "description": "Texture for defining emissive area.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_emissiveMap" + "name": "m_emissiveMap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Emissive map UV set", "type": "Enum", @@ -882,30 +882,30 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_emissiveMapUvIndex" + "name": "m_emissiveMapUvIndex" } } ], "parallax": [ { - "id": "textureMap", + "name": "textureMap", "displayName": "Height Map", "description": "Displacement height map to create parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_heightmap" + "name": "m_heightmap" } }, { - "id": "useTexture", + "name": "useTexture", "displayName": "Use Texture", "description": "Whether to use the height map.", "type": "Bool", "defaultValue": true }, { - "id": "textureMapUv", + "name": "textureMapUv", "displayName": "UV", "description": "Height map UV set", "type": "Enum", @@ -913,11 +913,11 @@ "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_parallaxUvIndex" + "name": "m_parallaxUvIndex" } }, { - "id": "factor", + "name": "factor", "displayName": "Height Map Scale", "description": "The total height of the height map in local model units.", "type": "Float", @@ -926,11 +926,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_heightmapScale" + "name": "m_heightmapScale" } }, { - "id": "offset", + "name": "offset", "displayName": "Offset", "description": "Adjusts the overall displacement amount in local model units.", "type": "Float", @@ -939,11 +939,11 @@ "softMax": 0.1, "connection": { "type": "ShaderInput", - "id": "m_heightmapOffset" + "name": "m_heightmapOffset" } }, { - "id": "algorithm", + "name": "algorithm", "displayName": "Algorithm", "description": "Select the algorithm to use for parallax mapping.", "type": "Enum", @@ -951,11 +951,11 @@ "defaultValue": "POM", "connection": { "type": "ShaderOption", - "id": "o_parallax_algorithm" + "name": "o_parallax_algorithm" } }, { - "id": "quality", + "name": "quality", "displayName": "Quality", "description": "Quality of parallax mapping.", "type": "Enum", @@ -963,43 +963,43 @@ "defaultValue": "Low", "connection": { "type": "ShaderOption", - "id": "o_parallax_quality" + "name": "o_parallax_quality" } }, { - "id": "pdo", + "name": "pdo", "displayName": "Pixel Depth Offset", "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_enablePixelDepthOffset" + "name": "o_parallax_enablePixelDepthOffset" } }, { - "id": "showClipping", + "name": "showClipping", "displayName": "Show Clipping", "description": "Highlight areas where the height map is clipped by the mesh surface.", "type": "Bool", "defaultValue": false, "connection": { "type": "ShaderOption", - "id": "o_parallax_highlightClipping" + "name": "o_parallax_highlightClipping" } } ], "irradiance": [ // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader { - "id": "color", + "name": "color", "displayName": "Color", "description": "Color is displayed as sRGB but the values are stored as linear color.", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ] }, { - "id": "factor", + "name": "factor", "displayName": "Factor", "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", "type": "Float", diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h index 987e78ae0f..40555bae00 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h @@ -39,13 +39,24 @@ namespace AZ //! Otherwise an attempt will be made to find or create a shared instance. void RebuildInstance(); + //! Release asset and instance references + void Release(); + + //! Return true if contained assets have not been loaded + bool RequiresLoading() const; + + //! Applies property overrides to material instance + bool ApplyProperties(); + //! Returns a string composed of the asset path. AZStd::string ToString() const; Data::Asset m_materialAsset; + Data::Asset m_defaultMaterialAsset; Data::Instance m_materialInstance; MaterialPropertyOverrideMap m_propertyOverrides; RPI::MaterialModelUvOverrideMap m_matModUvOverrides; + bool m_materialInstancePreCreated = false; }; using MaterialAssignmentMap = AZStd::unordered_map; diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index 5b90ed7f06..8984ec160b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -71,9 +71,9 @@ namespace AZ } MaterialAssignment::MaterialAssignment(const AZ::Data::AssetId& materialAssetId) - : m_materialInstance() + : m_materialAsset(materialAssetId, AZ::AzTypeInfo::Uuid()) + , m_materialInstance() { - m_materialAsset.Create(materialAssetId); } MaterialAssignment::MaterialAssignment(const Data::Asset& asset) @@ -90,12 +90,70 @@ namespace AZ void MaterialAssignment::RebuildInstance() { + if (m_materialInstancePreCreated) + { + return; + } + if (m_materialAsset.IsReady()) { - m_materialInstance = - m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset); + m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset); AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized"); } + else if (m_defaultMaterialAsset.IsReady()) + { + m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_defaultMaterialAsset) : RPI::Material::Create(m_defaultMaterialAsset); + AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized"); + } + } + + void MaterialAssignment::Release() + { + if (!m_materialInstancePreCreated) + { + m_materialInstance = nullptr; + } + m_materialAsset.Release(); + m_defaultMaterialAsset.Release(); + } + + bool MaterialAssignment::RequiresLoading() const + { + return + !m_materialInstancePreCreated && + !m_materialAsset.IsReady() && + !m_materialAsset.IsLoading() && + !m_defaultMaterialAsset.IsReady() && + !m_defaultMaterialAsset.IsLoading(); + } + + bool MaterialAssignment::ApplyProperties() + { + // if there is no instance or no properties there's nothing to apply + if (!m_materialInstance || m_propertyOverrides.empty()) + { + return true; + } + + if (m_materialInstance->CanCompile()) + { + for (const auto& propertyPair : m_propertyOverrides) + { + if (!propertyPair.second.empty()) + { + const auto& materialPropertyIndex = m_materialInstance->FindPropertyIndex(propertyPair.first); + if (!materialPropertyIndex.IsNull()) + { + m_materialInstance->SetPropertyValue( + materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); + } + } + } + + return m_materialInstance->Compile(); + } + + return false; } AZStd::string MaterialAssignment::ToString() const diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ThreadLocalContext.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ThreadLocalContext.h index dbea45c54a..4d3534b845 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ThreadLocalContext.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ThreadLocalContext.h @@ -11,6 +11,7 @@ #include #include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h new file mode 100644 index 0000000000..44b8805667 --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h @@ -0,0 +1,38 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include + +namespace AZ +{ + class ReflectContext; + + namespace RPI + { + //! The property connection itself is rather simple, but we need this custom serializer to provide backward compatibility + //! for when the "id" key was changed to "name". If the JSON serialization system is ever updated to provide built-in + //! support for versioning, then we can probably remove this class. + class JsonMaterialPropertyConnectionSerializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonMaterialPropertyConnectionSerializer, "{2B7F00CF-51F7-4409-9C0E-914E59696FB9}", 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; + }; + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h new file mode 100644 index 0000000000..138dace86a --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h @@ -0,0 +1,38 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include + +namespace AZ +{ + class ReflectContext; + + namespace RPI + { + //! The property group itself is rather simple, but we need this custom serializer to provide backward compatibility + //! for when the "id" key was changed to "name". If the JSON serialization system is ever updated to provide built-in + //! support for versioning, then we can probably remove this class. + class JsonMaterialPropertyGroupSerializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonMaterialPropertyGroupSerializer, "{74C56BBC-2084-46AF-9393-04C2FBDF6B20}", 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; + }; + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h index 7019289466..04b6222404 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h @@ -40,12 +40,12 @@ namespace AZ AZ_TYPE_INFO(AZ::RPI::MaterialTypeSourceData::PropertyConnection, "{C2F37C26-D7EF-4142-A650-EF50BB18610F}"); PropertyConnection() = default; - PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view nameId, int32_t shaderIndex = -1); + PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view fieldName, int32_t shaderIndex = -1); MaterialPropertyOutputType m_type = MaterialPropertyOutputType::Invalid; //! The name of a specific shader setting. This will either be a ShaderResourceGroup input or a ShaderOption, depending on m_type - AZStd::string m_nameId; + AZStd::string m_fieldName; //! For m_type==ShaderOption, this is either the index of a specific shader in m_shaderCollection, or -1 which means every shader in m_shaderCollection. //! For m_type==ShaderInput, this field is not used. @@ -58,8 +58,8 @@ namespace AZ { AZ_TYPE_INFO(AZ::RPI::MaterialTypeSourceData::GroupDefinition, "{B2D0FC5C-72A3-435E-A194-1BFDABAC253D}"); - //! The unique name of the property group. A property's full ID will be groupNameId.propertyNameId. - AZStd::string m_nameId; + //! The unique name of the property group. The full property ID will be groupName.propertyName + AZStd::string m_name; // Editor metadata ... AZStd::string m_displayName; @@ -74,7 +74,7 @@ namespace AZ static const float DefaultMax; static const float DefaultStep; - AZStd::string m_nameId; //!< The name of the property within the property group. The full ID will be groupNameId.propertyNameId. + AZStd::string m_name; //!< The name of the property within the property group. The full property ID will be groupName.propertyName. MaterialPropertyVisibility m_visibility = MaterialPropertyVisibility::Default; @@ -130,7 +130,7 @@ namespace AZ AZStd::vector m_groups; //! Collection of all available user-facing properties - AZStd::map m_properties; + AZStd::map m_properties; }; AZStd::string m_description; @@ -151,9 +151,9 @@ namespace AZ //! Copy over UV custom names to the properties enum values. void ResolveUvEnums(); - const GroupDefinition* FindGroup(AZStd::string_view groupNameId) const; + const GroupDefinition* FindGroup(AZStd::string_view groupName) const; - const PropertyDefinition* FindProperty(AZStd::string_view groupNameId, AZStd::string_view propertyNameId) const; + const PropertyDefinition* FindProperty(AZStd::string_view groupName, AZStd::string_view propertyName) const; //! Construct a complete list of group definitions, including implicit groups, arranged in the same order as the source data //! Groups with the same name will be consolidated into a single entry diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index 7801e0c3a7..d12e848a02 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -15,6 +15,13 @@ namespace AZ { + class JsonDeserializerContext; + + namespace JsonSerializationResult + { + union ResultCode; + } + namespace RPI { class MaterialTypeSourceData; @@ -35,6 +42,17 @@ namespace AZ //! @param filePath a relative path if document is provided, an absolute path if document is not provided. //! @param document the loaded json document. AZ::Outcome LoadMaterialTypeSourceData(const AZStd::string& filePath, const rapidjson::Value* document = nullptr); + + //! Utility function for custom JSON serializers to report results as "Skipped" when encountering keys that aren't recognized + //! as part of the custom format. + //! @param acceptedFieldNames an array of names that are recognized by the custom format + //! @param acceptedFieldNameCount the number of elements in @acceptedFieldNames + //! @param object the JSON object being loaded + //! @param context the common JsonDeserializerContext that is central to the serialization process + //! @param result the ResultCode that well be updated with the Outcomes "Skipped" if an unrecognized field is encountered + void CheckForUnrecognizedJsonFields( + const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, + const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode& result); } } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h index 3976ef989b..d8a0cf0e7d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h @@ -70,8 +70,8 @@ namespace AZ virtual ~Material(); - //! Finds the material property index from the material property name - MaterialPropertyIndex FindPropertyIndex(const Name& name) const; + //! Finds the material property index from the material property ID + MaterialPropertyIndex FindPropertyIndex(const Name& propertyId) const; //! Sets the value of a material property. The template data type must match the property's data type. //! @return true if property value was changed diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h index cc25aa17c4..90389687de 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -161,25 +161,19 @@ namespace AZ //! Add this RenderPipeline to RPI system's RenderTick and it will be rendered whenever //! the RPI system's RenderTick is called. - //! The RenderPipeline is rendered per RenderTick by default. + //! The RenderPipeline is rendered per RenderTick by default unless AddToRenderTickOnce() was called. void AddToRenderTick(); - //! Add this RenderPipeline to RPI system's RenderTick and it will be rendered every RenderTick - //! after the specified interval has elapsed since the last rendered frame. - //! @param renderInterval The desired time between rendered frames, in seconds. - void AddToRenderTickAtInterval(AZStd::chrono::duration renderInterval); - //! Disable render for this RenderPipeline void RemoveFromRenderTick(); ~RenderPipeline(); - + enum class RenderMode : uint8_t { - RenderEveryTick, //!< Render at each RPI system render tick. - RenderAtTargetRate, //!< Render on RPI system render tick after a target refresh rate interval has passed. - RenderOnce, //!< Render once in next RPI system render tick. - NoRender //!< Render disabled. + RenderEveryTick, // Render at each RPI system render tick + RenderOnce, // Render once in next RPI system render tick + NoRender // Render disabled. }; //! Get current render mode @@ -191,12 +185,6 @@ namespace AZ //! Get draw filter mask RHI::DrawFilterMask GetDrawFilterMask() const; - using FrameNotificationEvent = AZ::Event<>; - //! Notifies a listener when a frame is about to be prepared for render, before SRGs are bound. - void ConnectPrepareFrameHandler(FrameNotificationEvent::Handler& handler); - //! Notifies a listener when the rendering of a frame has finished - void ConnectEndFrameHandler(FrameNotificationEvent::Handler& handler); - private: RenderPipeline() = default; @@ -214,11 +202,8 @@ namespace AZ void OnAddedToScene(Scene* scene); void OnRemovedFromScene(Scene* scene); - // Called before this pipeline is about to be rendered and before SRGs are bound. - void OnPrepareFrame(); - // Called when this pipeline is about to be rendered - void OnStartFrame(); + void OnStartFrame(const TickTimeInfo& tick); // Called when the rendering of current frame is finished. void OnFrameEnd(); @@ -243,14 +228,8 @@ namespace AZ PipelineViewMap m_pipelineViewsByTag; - // The system time when the last time this pipeline render was started - AZStd::chrono::system_clock::time_point m_lastRenderStartTime; - - // The current system time, as of OnPrepareFrame's execution. - AZStd::chrono::system_clock::time_point m_lastRenderRequestTime; - - // The target time between renders when m_renderMode is RenderMode::RenderAtTargetRate - AZStd::chrono::duration m_targetRefreshRate; + /// The system time when the last time this pipeline render was started + float m_lastRenderStartTime = 0; // RenderPipeline's name id, it will be used to identify the render pipeline when it's added to a Scene RenderPipelineId m_nameId; @@ -280,11 +259,7 @@ namespace AZ RHI::DrawFilterTag m_drawFilterTag; // A mask to filter draw items submitted by passes of this render pipeline. // This mask is created from the value of m_drawFilterTag. - RHI::DrawFilterMask m_drawFilterMask = 0; - - // Events for notification on render state - FrameNotificationEvent m_prepareFrameEvent; - FrameNotificationEvent m_endFrameEvent; + RHI::DrawFilterMask m_drawFilterMask = 0; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h index 748c470edf..ca531d2de6 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h @@ -67,9 +67,6 @@ namespace AZ //! Notifies when the PrepareRender phase is ending virtual void OnEndPrepareRender() {} - - //! Notifies when the render tick for a given frame has finished. - virtual void OnFrameEnd() {} }; using SceneNotificationBus = AZ::EBus; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h index feed24a80d..966e6b3016 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h @@ -51,21 +51,9 @@ namespace AZ //! Sets the root scene associated with this viewport. //! This does not provide a default render pipeline, one must be provided to enable rendering. void SetRenderScene(ScenePtr scene); - - //! Gets the maximum frame rate this viewport context's pipeline can render at, 0 for unlimited. - //! The target framerate for the pipeline will be determined by this frame limit and the - //! vsync settings for the current window. - float GetFpsLimit() const; - - //! Sets the maximum frame rate this viewport context's pipeline can render at, 0 for unlimited. - //! The target framerate for the pipeline will be determined by this frame limit and the - //! vsync settings for the current window. - void SetFpsLimit(float fpsLimit); - - //! Gets the target frame rate for this viewport context. - //! This returns the lowest of either the current VSync refresh rate - //! or 0 for an unlimited frame rate (if there's no FPS limit and vsync is off). - float GetTargetFrameRate() const; + //! Runs one simulation and render tick and renders a frame to this viewport's window. + //! @note This is likely to be replaced by a tick management system in the RPI. + void RenderTick(); //! Gets the current name of this ViewportContext. //! This name is used to tie this ViewportContext to its View stack, and ViewportContexts may be @@ -86,28 +74,19 @@ namespace AZ //! \see AzFramework::WindowRequests::GetDpiScaleFactor float GetDpiScalingFactor() const; - //! Gets the current vsync interval, as a divisor of the current refresh rate. - //! A value of 0 indicates that vsync is disabled. - uint32_t GetVsyncInterval() const; - - //! Gets the current display refresh rate, in frames per second. - uint32_t GetRefreshRate() const; - // SceneNotificationBus interface overrides... //! Ensures our default view remains set when our scene's render pipelines are modified. void OnRenderPipelineAdded(RenderPipelinePtr pipeline) override; //! Ensures our default view remains set when our scene's render pipelines are modified. void OnRenderPipelineRemoved(RenderPipeline* pipeline) override; + //! OnBeginPrepareRender is forwarded to our RenderTick notification to allow subscribers to do rendering. + void OnBeginPrepareRender() override; // WindowNotificationBus interface overrides... //! Used to fire a notification when our window resizes. void OnWindowResized(uint32_t width, uint32_t height) override; //! Used to fire a notification when our window DPI changes. void OnDpiScaleFactorChanged(float dpiScaleFactor) override; - //! Used to fire a notification when our vsync interval changes. - void OnVsyncIntervalChanged(uint32_t interval) override; - //! Used to fire a notification when our refresh rate changes. - void OnRefreshRateChanged(uint32_t refreshRate) override; using SizeChangedEvent = AZ::Event; //! Notifies consumers when the viewport size has changed. @@ -119,12 +98,6 @@ namespace AZ //! Alternatively, connect to ViewportContextNotificationsBus and listen to ViewportContextNotifications::OnViewportDpiScalingChanged. void ConnectDpiScalingFactorChangedHandler(ScalarChangedEvent::Handler& handler); - using UintChangedEvent = AZ::Event; - //! Notifies consumers when the vsync interval has changed. - void ConnectVsyncIntervalChangedHandler(UintChangedEvent::Handler& handler); - //! Notifies consumers when the refresh rate has changed. - void ConnectRefreshRateChangedHandler(UintChangedEvent::Handler& handler); - using MatrixChangedEvent = AZ::Event; //! Notifies consumers when the view matrix has changed. void ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler); @@ -166,24 +139,15 @@ namespace AZ void SetDefaultView(ViewPtr view); // Ensures our render pipeline's default camera matches ours. void UpdatePipelineView(); - // Ensures our render pipeline refresh rate matches our refresh rate. - void UpdatePipelineRefreshRate(); - // Resets the current pipeline reference and ensures pipeline events are disconnected. - void ResetCurrentPipeline(); ScenePtr m_rootScene; WindowContextSharedPtr m_windowContext; ViewPtr m_defaultView; AzFramework::WindowSize m_viewportSize; float m_viewportDpiScaleFactor = 1.0f; - uint32_t m_vsyncInterval = 1; - uint32_t m_refreshRate = 60; - float m_fpsLimit = 0.f; SizeChangedEvent m_sizeChangedEvent; ScalarChangedEvent m_dpiScalingFactorChangedEvent; - UintChangedEvent m_vsyncIntervalChangedEvent; - UintChangedEvent m_refreshRateChangedEvent; MatrixChangedEvent m_viewMatrixChangedEvent; MatrixChangedEvent::Handler m_onViewMatrixChangedHandler; MatrixChangedEvent m_projectionMatrixChangedEvent; @@ -193,9 +157,6 @@ namespace AZ ViewChangedEvent m_defaultViewChangedEvent; ViewportIdEvent m_aboutToBeDestroyedEvent; - AZ::Event<>::Handler m_prepareFrameHandler; - AZ::Event<>::Handler m_endFrameHandler; - ViewportContextManager* m_manager; RenderPipelinePtr m_currentPipeline; Name m_name; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h index fa13a3987a..0b53172ba2 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h @@ -110,13 +110,11 @@ namespace AZ virtual void OnViewportSizeChanged(AzFramework::WindowSize size){AZ_UNUSED(size);} //! Called when the window DPI scaling changes for a given viewport context. virtual void OnViewportDpiScalingChanged(float dpiScale){AZ_UNUSED(dpiScale);} - //! Called when the active view changes for a given viewport context. + //! Called when the active view for a given viewport context name changes. virtual void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view){AZ_UNUSED(view);} //! Called when the viewport is to be rendered. - //! Add draws to this function if they only need to be rendered to this viewport. - virtual void OnRenderTick(){} - //! Called when the viewport finishes rendering a frame. - virtual void OnFrameEnd(){} + //! Add draws to this functions if they only need to be rendered to this viewport. + virtual void OnRenderTick(){}; protected: ~ViewportContextNotifications() = default; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h index 45c8f0dc30..bc020b8129 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h @@ -35,7 +35,7 @@ namespace AZ AZ_DISABLE_COPY_MOVE(MaterialPropertiesLayout); size_t GetPropertyCount() const; - MaterialPropertyIndex FindPropertyIndex(const Name& propertyName) const; + MaterialPropertyIndex FindPropertyIndex(const Name& propertyId) const; const MaterialPropertyDescriptor* GetPropertyDescriptor(MaterialPropertyIndex index) const; private: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index ef0678046c..86ea8ab688 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -47,7 +47,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 108; // Set materialtype dependency to OrderOnce + materialBuilderDescriptor.m_version = 109; // Changed "id" to "name" in serialization materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyConnectionSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyConnectionSerializer.cpp new file mode 100644 index 0000000000..a0be7b9dca --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyConnectionSerializer.cpp @@ -0,0 +1,126 @@ +/* + * 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 +#include + +#include +#include +#include +#include + +namespace AZ +{ + namespace RPI + { + namespace JsonMaterialPropertyConnectionSerializerInternal + { + namespace Field + { + static constexpr const char type[] = "type"; + static constexpr const char name[] = "name"; + static constexpr const char id[] = "id"; // For backward compatibility + static constexpr const char shaderIndex[] = "shaderIndex"; + } + + static const AZStd::string_view AcceptedFields[] = + { + Field::type, + Field::name, + Field::id, + Field::shaderIndex + }; + } + + AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyConnectionSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertyConnectionSerializerInternal; + + AZ_Assert(azrtti_typeid() == outputValueTypeId, + "Unable to deserialize material property connection to json because the provided type is %s", + outputValueTypeId.ToString().c_str()); + AZ_UNUSED(outputValueTypeId); + + MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast(outputValue); + AZ_Assert(propertyConnection, "Output value for JsonMaterialPropertyConnectionSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::ReadField); + + if (!inputValue.IsObject()) + { + return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property connection must be a JSON object."); + } + + MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result); + + result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_type, azrtti_typeid(), inputValue, Field::type, context)); + + JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid(), inputValue, Field::name, context); + if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed) + { + // This "id" key is for backward compatibility. + result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid(), inputValue, Field::id, context)); + } + else + { + result.Combine(nameResult); + } + + result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_shaderIndex, azrtti_typeid(), inputValue, Field::shaderIndex, context)); + + if (result.GetProcessing() == JsonSerializationResult::Processing::Completed) + { + return context.Report(result, "Successfully loaded property connection."); + } + else + { + return context.Report(result, "Partially loaded property connection."); + } + } + + + JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, + [[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertyConnectionSerializerInternal; + + AZ_Assert(azrtti_typeid() == valueTypeId, + "Unable to serialize material property connection to json because the provided type is %s", + valueTypeId.ToString().c_str()); + AZ_UNUSED(valueTypeId); + + const MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast(inputValue); + AZ_Assert(propertyConnection, "Input value for JsonMaterialPropertyConnectionSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::WriteValue); + + outputValue.SetObject(); + + MaterialTypeSourceData::PropertyConnection defaultConnection; + + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::type, &propertyConnection->m_type, &defaultConnection.m_type, azrtti_typeid(), context)); + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyConnection->m_fieldName, &defaultConnection.m_fieldName, azrtti_typeid(), context)); + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::shaderIndex, &propertyConnection->m_shaderIndex, &defaultConnection.m_shaderIndex, azrtti_typeid(), context)); + + if (result.GetProcessing() == JsonSerializationResult::Processing::Completed) + { + return context.Report(result, "Successfully stored property connection."); + } + else + { + return context.Report(result, "Partially stored property connection."); + } + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyGroupSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyGroupSerializer.cpp new file mode 100644 index 0000000000..b54ba012d4 --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyGroupSerializer.cpp @@ -0,0 +1,125 @@ +/* + * 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 +#include + +#include +#include +#include +#include + +namespace AZ +{ + namespace RPI + { + namespace JsonMaterialPropertyGroupSerializerInternal + { + namespace Field + { + static constexpr const char name[] = "name"; + static constexpr const char id[] = "id"; // For backward compatibility + static constexpr const char displayName[] = "displayName"; + static constexpr const char description[] = "description"; + } + + static const AZStd::string_view AcceptedFields[] = + { + Field::name, + Field::id, + Field::displayName, + Field::description + }; + } + + AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyGroupSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertyGroupSerializerInternal; + + AZ_Assert(azrtti_typeid() == outputValueTypeId, + "Unable to deserialize material property group to json because the provided type is %s", + outputValueTypeId.ToString().c_str()); + AZ_UNUSED(outputValueTypeId); + + MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast(outputValue); + AZ_Assert(propertyGroup, "Output value for JsonMaterialPropertyGroupSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::ReadField); + + if (!inputValue.IsObject()) + { + return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property group must be a JSON object."); + } + + MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result); + + JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid(), inputValue, Field::name, context); + if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed) + { + // This "id" key is for backward compatibility. + result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid(), inputValue, Field::id, context)); + } + else + { + result.Combine(nameResult); + } + + result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_displayName, azrtti_typeid(), inputValue, Field::displayName, context)); + result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_description, azrtti_typeid(), inputValue, Field::description, context)); + + if (result.GetProcessing() == JsonSerializationResult::Processing::Completed) + { + return context.Report(result, "Successfully loaded property group."); + } + else + { + return context.Report(result, "Partially loaded property group."); + } + } + + + JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, + [[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertyGroupSerializerInternal; + + AZ_Assert(azrtti_typeid() == valueTypeId, + "Unable to serialize material property group to json because the provided type is %s", + valueTypeId.ToString().c_str()); + AZ_UNUSED(valueTypeId); + + const MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast(inputValue); + AZ_Assert(propertyGroup, "Input value for JsonMaterialPropertyGroupSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::WriteValue); + + outputValue.SetObject(); + + AZStd::string defaultEmpty; + + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyGroup->m_name, &defaultEmpty, azrtti_typeid(), context)); + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::displayName, &propertyGroup->m_displayName, &defaultEmpty, azrtti_typeid(), context)); + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::description, &propertyGroup->m_description, &defaultEmpty, azrtti_typeid(), context)); + + if (result.GetProcessing() == JsonSerializationResult::Processing::Completed) + { + return context.Report(result, "Successfully stored property group."); + } + else + { + return context.Report(result, "Partially stored property group."); + } + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertySerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertySerializer.cpp index f3d499ac78..4c66f753f2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertySerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertySerializer.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -23,11 +24,12 @@ namespace AZ { namespace RPI { - namespace // Avoid conflicts in uber builds + namespace JsonMaterialPropertySerializerInternal { namespace Field { - static constexpr const char id[] = "id"; + static constexpr const char name[] = "name"; + static constexpr const char id[] = "id"; // For backward compatibility static constexpr const char displayName[] = "displayName"; static constexpr const char description[] = "description"; static constexpr const char type[] = "type"; @@ -46,6 +48,7 @@ namespace AZ static const AZStd::string_view AcceptedFields[] = { + Field::name, Field::id, Field::displayName, Field::description, @@ -103,6 +106,7 @@ namespace AZ JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; JSR::ResultCode result(JSR::Tasks::ReadField); @@ -160,6 +164,7 @@ namespace AZ JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; JSR::ResultCode result(JSR::Tasks::ReadField); @@ -181,6 +186,7 @@ namespace AZ const rapidjson::Value& inputValue, JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; AZ_Assert(azrtti_typeid() == outputValueTypeId, "Unable to deserialize material property to json because the provided type is %s", @@ -197,28 +203,19 @@ namespace AZ return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property definition must be a JSON object."); } - // First check for unexpected fields - for (auto iter = inputValue.MemberBegin(); iter != inputValue.MemberEnd(); ++iter) + MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result); + + JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid(), inputValue, Field::name, context); + if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed) { - bool matched = false; - - for (int i = 0; i < AZ_ARRAY_SIZE(AcceptedFields); ++i) - { - if (iter->name.GetString() == AcceptedFields[i]) - { - matched = true; - break; - } - } - - if (!matched) - { - ScopedContextPath subPath{context, iter->name.GetString()}; - result.Combine(context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Skipped, "Skipping unrecognized field")); - } + // This "id" key is for backward compatibility. + result.Combine(ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid(), inputValue, Field::id, context)); + } + else + { + result.Combine(nameResult); } - result.Combine(ContinueLoadingFromJsonObjectField(&property->m_nameId, azrtti_typeid(), inputValue, Field::id, context)); result.Combine(ContinueLoadingFromJsonObjectField(&property->m_displayName, azrtti_typeid(), inputValue, Field::displayName, context)); result.Combine(ContinueLoadingFromJsonObjectField(&property->m_description, azrtti_typeid(), inputValue, Field::description, context)); result.Combine(ContinueLoadingFromJsonObjectField(&property->m_dataType, azrtti_typeid(), inputValue, Field::type, context)); @@ -302,6 +299,8 @@ namespace AZ JsonSerializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; + JSR::ResultCode result(JSR::Tasks::WriteValue); if (property->m_value.Is()) @@ -345,6 +344,8 @@ namespace AZ JsonSerializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; + JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue); if (property->m_value.Is()) @@ -360,6 +361,7 @@ namespace AZ [[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; AZ_Assert(azrtti_typeid() == valueTypeId, "Unable to serialize material property to json because the provided type is %s", @@ -374,7 +376,7 @@ namespace AZ outputValue.SetObject(); const AZStd::string emptyString; - result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::id, &property->m_nameId, &emptyString, azrtti_typeid(), context)); + result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &property->m_name, &emptyString, azrtti_typeid(), context)); result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::displayName, &property->m_displayName, &emptyString, azrtti_typeid(), context)); result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::description, &property->m_description, &emptyString, azrtti_typeid(), context)); @@ -452,6 +454,8 @@ namespace AZ const rapidjson::Value& inputValue, JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; + JSR::ResultCode result(JSR::Tasks::ReadField); if (inputValue.HasMember(Field::vectorLabels)) @@ -467,6 +471,8 @@ namespace AZ { AZStd::string emptyString; namespace JSR = JsonSerializationResult; + using namespace JsonMaterialPropertySerializerInternal; + JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue); if (!property->m_vectorLabels.empty()) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp index 060a563c53..3b2d36451a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp @@ -62,18 +62,18 @@ namespace AZ return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Catastrophic, "Material type reference not found."); } - // Construct the full property name (groupId.propertyId) by parsing it from the JSON path string. - size_t startPropertyNameId = context.GetPath().Get().rfind('/'); - size_t startGroupNameId = context.GetPath().Get().rfind('/', startPropertyNameId-1); - AZStd::string_view groupNameId = context.GetPath().Get().substr(startGroupNameId + 1, startPropertyNameId - startGroupNameId - 1); - AZStd::string_view propertyNameId = context.GetPath().Get().substr(startPropertyNameId + 1); + // Construct the full property name (groupName.propertyName) by parsing it from the JSON path string. + size_t startPropertyName = context.GetPath().Get().rfind('/'); + size_t startGroupName = context.GetPath().Get().rfind('/', startPropertyName-1); + AZStd::string_view groupName = context.GetPath().Get().substr(startGroupName + 1, startPropertyName - startGroupName - 1); + AZStd::string_view propertyName = context.GetPath().Get().substr(startPropertyName + 1); JSR::ResultCode result(JSR::Tasks::ReadField); - auto propertyDefinition = materialType->FindProperty(groupNameId, propertyNameId); + auto propertyDefinition = materialType->FindProperty(groupName, propertyName); if (!propertyDefinition) { - AZStd::string message = AZStd::string::format("Property '%.*s.%.*s' not found in material type.", AZ_STRING_ARG(groupNameId), AZ_STRING_ARG(propertyNameId)); + AZStd::string message = AZStd::string::format("Property '%.*s.%.*s' not found in material type.", AZ_STRING_ARG(groupName), AZ_STRING_ARG(propertyName)); return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, message); } else diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index 5a95cb35a6..1cc57f4d47 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -46,29 +48,17 @@ namespace AZ if (JsonRegistrationContext* jsonContext = azrtti_cast(context)) { jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType(); } else if (auto* serializeContext = azrtti_cast(context)) { - serializeContext->Class() - ->Version(1) - ->Field("type", &PropertyConnection::m_type) - ->Field("id", &PropertyConnection::m_nameId) - ->Field("shaderIndex", &PropertyConnection::m_shaderIndex) - ; + serializeContext->Class()->Version(3); + serializeContext->Class()->Version(4); + serializeContext->Class()->Version(1); serializeContext->RegisterGenericType(); - serializeContext->Class() - ->Version(1) - ->Field("id", &GroupDefinition::m_nameId) - ->Field("displayName", &GroupDefinition::m_displayName) - ->Field("description", &GroupDefinition::m_description) - ; - - serializeContext->Class() - ->Version(1) - ; - serializeContext->Class() ->Version(2) ->Field("file", &ShaderVariantReferenceData::m_shaderFilePath) @@ -96,9 +86,9 @@ namespace AZ } } - MaterialTypeSourceData::PropertyConnection::PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view nameId, int32_t shaderIndex) + MaterialTypeSourceData::PropertyConnection::PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view fieldName, int32_t shaderIndex) : m_type(type) - , m_nameId(nameId) + , m_fieldName(fieldName) , m_shaderIndex(shaderIndex) { } @@ -107,11 +97,11 @@ namespace AZ const float MaterialTypeSourceData::PropertyDefinition::DefaultMax = std::numeric_limits::max(); const float MaterialTypeSourceData::PropertyDefinition::DefaultStep = 0.1f; - const MaterialTypeSourceData::GroupDefinition* MaterialTypeSourceData::FindGroup(AZStd::string_view groupNameId) const + const MaterialTypeSourceData::GroupDefinition* MaterialTypeSourceData::FindGroup(AZStd::string_view groupName) const { for (const GroupDefinition& group : m_propertyLayout.m_groups) { - if (group.m_nameId == groupNameId) + if (group.m_name == groupName) { return &group; } @@ -120,9 +110,9 @@ namespace AZ return nullptr; } - const MaterialTypeSourceData::PropertyDefinition* MaterialTypeSourceData::FindProperty(AZStd::string_view groupNameId, AZStd::string_view propertyNameId) const + const MaterialTypeSourceData::PropertyDefinition* MaterialTypeSourceData::FindProperty(AZStd::string_view groupName, AZStd::string_view propertyName) const { - auto groupIter = m_propertyLayout.m_properties.find(groupNameId); + auto groupIter = m_propertyLayout.m_properties.find(groupName); if (groupIter == m_propertyLayout.m_properties.end()) { return nullptr; @@ -130,7 +120,7 @@ namespace AZ for (const PropertyDefinition& property : groupIter->second) { - if (property.m_nameId == propertyNameId) + if (property.m_name == propertyName) { return &property; } @@ -169,24 +159,24 @@ namespace AZ AZStd::unordered_set foundGroups; for (const auto& groupDefinition : m_propertyLayout.m_groups) { - if (foundGroups.insert(groupDefinition.m_nameId).second) + if (foundGroups.insert(groupDefinition.m_name).second) { groupDefinitions.push_back(groupDefinition); } else { - AZ_Warning("Material source data", false, "Duplicate group '%s' found.", groupDefinition.m_nameId.c_str()); + AZ_Warning("Material source data", false, "Duplicate group '%s' found.", groupDefinition.m_name.c_str()); } } // Some groups are defined implicitly, in the "properties" section where a group name is used but not explicitly defined in the "groups" section. for (const auto& propertyListPair : m_propertyLayout.m_properties) { - const AZStd::string& groupNameId = propertyListPair.first; - if (foundGroups.insert(groupNameId).second) + const AZStd::string& groupName = propertyListPair.first; + if (foundGroups.insert(groupName).second) { MaterialTypeSourceData::GroupDefinition groupDefinition; - groupDefinition.m_nameId = groupNameId; + groupDefinition.m_name = groupName; groupDefinitions.push_back(groupDefinition); } } @@ -203,12 +193,12 @@ namespace AZ for (const auto& propertyListPair : m_propertyLayout.m_properties) { - const AZStd::string& groupNameId = propertyListPair.first; + const AZStd::string& groupName = propertyListPair.first; const auto& propertyList = propertyListPair.second; for (const auto& propertyDefinition : propertyList) { - const AZStd::string& propertyNameId = propertyDefinition.m_nameId; - if (!callback(groupNameId, propertyNameId, propertyDefinition)) + const AZStd::string& propertyName = propertyDefinition.m_name; + if (!callback(groupName, propertyName, propertyDefinition)) { return; } @@ -225,15 +215,15 @@ namespace AZ for (const auto& groupDefinition : GetGroupDefinitionsInDisplayOrder()) { - const AZStd::string& groupNameId = groupDefinition.m_nameId; - const auto propertyListItr = m_propertyLayout.m_properties.find(groupNameId); + const AZStd::string& groupName = groupDefinition.m_name; + const auto propertyListItr = m_propertyLayout.m_properties.find(groupName); if (propertyListItr != m_propertyLayout.m_properties.end()) { const auto& propertyList = propertyListItr->second; for (const auto& propertyDefinition : propertyList) { - const AZStd::string& propertyNameId = propertyDefinition.m_nameId; - if (!callback(groupNameId, propertyNameId, propertyDefinition)) + const AZStd::string& propertyName = propertyDefinition.m_name; + if (!callback(groupName, propertyName, propertyDefinition)) { return; } @@ -249,7 +239,7 @@ namespace AZ const uint32_t index = propertyValue.GetValue(); if (index >= propertyDefinition.m_enumValues.size()) { - AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_nameId.c_str()); + AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str()); return false; } @@ -272,7 +262,7 @@ namespace AZ imageAsset.GetId(), imageAsset.GetType(), platformName, imageAssetInfo, rootFilePath); if (!result) { - AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyDefinition.m_nameId.c_str()); + AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyDefinition.m_name.c_str()); return false; } } @@ -340,13 +330,13 @@ namespace AZ for (auto& groupIter : m_propertyLayout.m_properties) { - const AZStd::string& groupNameId = groupIter.first; + const AZStd::string& groupName = groupIter.first; for (const PropertyDefinition& property : groupIter.second) { // Register the property... - MaterialPropertyId propertyId{ groupNameId, property.m_nameId }; + MaterialPropertyId propertyId{ groupName, property.m_name }; if (!propertyId.IsValid()) { @@ -366,16 +356,16 @@ namespace AZ switch (output.m_type) { case MaterialPropertyOutputType::ShaderInput: - materialTypeAssetCreator.ConnectMaterialPropertyToShaderInput(Name{ output.m_nameId.data() }); + materialTypeAssetCreator.ConnectMaterialPropertyToShaderInput(Name{ output.m_fieldName.data() }); break; case MaterialPropertyOutputType::ShaderOption: if (output.m_shaderIndex >= 0) { - materialTypeAssetCreator.ConnectMaterialPropertyToShaderOption(Name{ output.m_nameId.data() }, output.m_shaderIndex); + materialTypeAssetCreator.ConnectMaterialPropertyToShaderOption(Name{ output.m_fieldName.data() }, output.m_shaderIndex); } else { - materialTypeAssetCreator.ConnectMaterialPropertyToShaderOptions(Name{ output.m_nameId.data() }); + materialTypeAssetCreator.ConnectMaterialPropertyToShaderOptions(Name{ output.m_fieldName.data() }); } break; case MaterialPropertyOutputType::Invalid: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 62f4f02e3c..90ce9e66ce 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include @@ -99,6 +101,29 @@ namespace AZ return AZ::Success(AZStd::move(materialType)); } } + + void CheckForUnrecognizedJsonFields(const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode &result) + { + for (auto iter = object.MemberBegin(); iter != object.MemberEnd(); ++iter) + { + bool matched = false; + + for (uint32_t i = 0; i < acceptedFieldNameCount; ++i) + { + if (iter->name.GetString() == acceptedFieldNames[i]) + { + matched = true; + break; + } + } + + if (!matched) + { + ScopedContextPath subPath{context, iter->name.GetString()}; + result.Combine(context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Skipped, "Skipping unrecognized field")); + } + } + } } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp index 789d43712e..2567d221e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp @@ -14,9 +14,6 @@ #include #include -#include -#include -#include #include #include @@ -96,29 +93,20 @@ namespace AZ } m_rpiSystem.Initialize(m_rpiDescriptor); - AZ::TickBus::Handler::BusConnect(); + AZ::SystemTickBus::Handler::BusConnect(); } void RPISystemComponent::Deactivate() { - AZ::TickBus::Handler::BusDisconnect(); + AZ::SystemTickBus::Handler::BusDisconnect(); m_rpiSystem.Shutdown(); } - void RPISystemComponent::OnTick([[maybe_unused]]float deltaTime, [[maybe_unused]]ScriptTimePoint time) + void RPISystemComponent::OnSystemTick() { - if (deltaTime == 0.f) - { - return; - } - m_rpiSystem.SimulationTick(); m_rpiSystem.RenderTick(); } - int RPISystemComponent::GetTickOrder() - { - return AZ::ComponentTickBus::TICK_RENDER; - } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h index 7933e1581c..e0a128c3f1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h @@ -32,7 +32,7 @@ namespace AZ */ class RPISystemComponent final : public AZ::Component - , private AZ::TickBus::Handler + , public AZ::SystemTickBus::Handler { public: AZ_COMPONENT(RPISystemComponent, "{83E301F3-7A0C-4099-B530-9342B91B1BC0}"); @@ -50,9 +50,8 @@ namespace AZ private: RPISystemComponent(const RPISystemComponent&) = delete; - // TickBus overrides... - void OnTick(float deltaTime, ScriptTimePoint time) override; - int GetTickOrder() override; + // SystemTickBus overrides... + void OnSystemTick() override; RPISystem m_rpiSystem; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index d44ed40c7b..c87646e17d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -386,9 +386,9 @@ namespace AZ return m_currentChangeId; } - MaterialPropertyIndex Material::FindPropertyIndex(const Name& name) const + MaterialPropertyIndex Material::FindPropertyIndex(const Name& propertyId) const { - return m_layout->FindPropertyIndex(name); + return m_layout->FindPropertyIndex(propertyId); } template diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index c5e871697b..a8d94e9a91 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -93,11 +93,8 @@ namespace AZ void Pass::SetEnabled(bool enabled) { - if (m_flags.m_enabled != enabled) - { - m_flags.m_enabled = enabled; - OnHierarchyChange(); - } + m_flags.m_enabled = enabled; + OnHierarchyChange(); } bool Pass::IsEnabled() const diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp index 409a084e4f..1b99abae4e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp @@ -301,26 +301,6 @@ namespace AZ m_drawFilterMask = 0; } - void RenderPipeline::OnPrepareFrame() - { - m_lastRenderRequestTime = AZStd::chrono::system_clock::now(); - - // If we're attempting to render at a target interval, check to see if we're within - // 1ms of that interval, enabling rendering only if we are. - if (m_renderMode == RenderMode::RenderAtTargetRate) - { - constexpr AZStd::chrono::duration updateThresholdMs(0.001f); - const bool shouldRender = - m_lastRenderRequestTime - m_lastRenderStartTime + updateThresholdMs >= m_targetRefreshRate; - m_rootPass->SetEnabled(shouldRender); - } - - if (NeedsRender()) - { - m_prepareFrameEvent.Signal(); - } - } - void RenderPipeline::OnPassModified() { if (m_needsPassRecreate) @@ -395,11 +375,11 @@ namespace AZ m_scene->RemoveRenderPipeline(m_nameId); } - void RenderPipeline::OnStartFrame() + void RenderPipeline::OnStartFrame(const TickTimeInfo& tick) { AZ_PROFILE_SCOPE(RPI, "RenderPipeline: OnStartFrame"); - m_lastRenderStartTime = m_lastRenderRequestTime; + m_lastRenderStartTime = tick.m_currentGameTime; OnPassModified(); @@ -427,7 +407,6 @@ namespace AZ { RemoveFromRenderTick(); } - m_endFrameEvent.Signal(); } void RenderPipeline::CollectPersistentViews(AZStd::map& outViewMasks) const @@ -510,13 +489,6 @@ namespace AZ m_renderMode = RenderMode::RenderEveryTick; } - void RenderPipeline::AddToRenderTickAtInterval(AZStd::chrono::duration renderInterval) - { - m_rootPass->SetEnabled(false); - m_renderMode = RenderMode::RenderAtTargetRate; - m_targetRefreshRate = renderInterval; - } - void RenderPipeline::RemoveFromRenderTick() { m_renderMode = RenderMode::NoRender; @@ -530,7 +502,7 @@ namespace AZ bool RenderPipeline::NeedsRender() const { - return m_rootPass->IsEnabled(); + return m_renderMode != RenderMode::NoRender; } RHI::DrawFilterTag RenderPipeline::GetDrawFilterTag() const @@ -543,16 +515,6 @@ namespace AZ return m_drawFilterMask; } - void RenderPipeline::ConnectPrepareFrameHandler(FrameNotificationEvent::Handler& handler) - { - handler.Connect(m_prepareFrameEvent); - } - - void RenderPipeline::ConnectEndFrameHandler(FrameNotificationEvent::Handler& handler) - { - handler.Connect(m_endFrameEvent); - } - void RenderPipeline::SetDrawFilterTag(RHI::DrawFilterTag tag) { m_drawFilterTag = tag; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index a7ecf089c0..646cba1999 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -418,7 +418,7 @@ namespace AZ } } - void Scene::PrepareRender([[maybe_unused]]const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) + void Scene::PrepareRender(const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) { AZ_PROFILE_SCOPE(RPI, "Scene: PrepareRender"); @@ -429,27 +429,20 @@ namespace AZ SceneNotificationBus::Event(GetId(), &SceneNotification::OnBeginPrepareRender); - // Get active pipelines which need to be rendered and notify them of an impending frame. + // Get active pipelines which need to be rendered and notify them frame started AZStd::vector activePipelines; { - AZ_PROFILE_SCOPE(RPI, "Scene: OnPrepareFrame"); + AZ_PROFILE_SCOPE(RPI, "Scene: OnStartFrame"); for (auto& pipeline : m_pipelines) { - pipeline->OnPrepareFrame(); if (pipeline->NeedsRender()) { activePipelines.push_back(pipeline); + pipeline->OnStartFrame(tickInfo); } } } - // Get active pipelines which need to be rendered and notify them frame started - for (const auto& pipeline : activePipelines) - { - AZ_PROFILE_SCOPE(RPI, "Scene: OnStartFrame"); - pipeline->OnStartFrame(); - } - // Return if there is no active render pipeline if (activePipelines.empty()) { @@ -589,12 +582,10 @@ namespace AZ void Scene::OnFrameEnd() { AZ_PROFILE_SCOPE(RPI, "Scene: OnFrameEnd"); - bool didRender = false; for (auto& pipeline : m_pipelines) { if (pipeline->NeedsRender()) { - didRender = true; pipeline->OnFrameEnd(); } } @@ -602,10 +593,6 @@ namespace AZ { fp->OnRenderEnd(); } - if (didRender) - { - SceneNotificationBus::Event(GetId(), &SceneNotification::OnFrameEnd); - } } void Scene::UpdateSrgs() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp index 528d32e217..e11624a921 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp @@ -23,11 +23,11 @@ namespace AZ { namespace RPI { - AZStd::string GetMetricsFilePath() + AZ::IO::FixedMaxPath GetMetricsFilePath() { - char shaderMetricPath[AZ_MAX_PATH_LEN]; - AZ::Utils::GetExecutableDirectory(shaderMetricPath, AZ_MAX_PATH_LEN); - return AZStd::string(shaderMetricPath) + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "ShaderMetrics.json"; + AZ::IO::FixedMaxPath resolvedPath; + AZ::IO::LocalFileIO::GetInstance()->ResolvePath(resolvedPath, "@user@/ShaderMetrics.json"); + return resolvedPath; } ShaderMetricsSystemInterface* ShaderMetricsSystemInterface::Get() @@ -64,7 +64,7 @@ namespace AZ void ShaderMetricsSystem::ReadLog() { - const AZStd::string metricsFilePath = GetMetricsFilePath(); + const AZ::IO::FixedMaxPath metricsFilePath = GetMetricsFilePath(); if (AZ::IO::LocalFileIO::GetInstance()->Exists(metricsFilePath.c_str())) { @@ -80,7 +80,7 @@ namespace AZ void ShaderMetricsSystem::WriteLog() { - const AZStd::string metricsFilePath = GetMetricsFilePath(); + const AZ::IO::FixedMaxPath metricsFilePath = GetMetricsFilePath(); auto saveResult = AZ::JsonSerializationUtils::SaveObjectToFile(&m_metrics, metricsFilePath.c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index c2356cea45..8c1e38ba58 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -241,10 +241,7 @@ namespace AZ { AZ_PROFILE_SCOPE(RPI, "View: FinalizeDrawLists"); m_drawListContext.FinalizeLists(); - if (m_passesByDrawList) - { - SortFinalizedDrawLists(); - } + SortFinalizedDrawLists(); } void View::SortFinalizedDrawLists() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index 3dcbae2fb9..77114e5cf5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -25,13 +25,14 @@ namespace AZ , m_viewportSize(1, 1) { m_windowContext->Initialize(device, nativeWindow); - AzFramework::WindowRequestBus::Event(nativeWindow, [this](AzFramework::WindowRequestBus::Events* window) - { - m_viewportSize = window->GetClientAreaSize(); - m_viewportDpiScaleFactor = window->GetDpiScaleFactor(); - m_vsyncInterval = window->GetSyncInterval(); - m_refreshRate = window->GetDisplayRefreshRate(); - }); + AzFramework::WindowRequestBus::EventResult( + m_viewportSize, + nativeWindow, + &AzFramework::WindowRequestBus::Events::GetClientAreaSize); + AzFramework::WindowRequestBus::EventResult( + m_viewportDpiScaleFactor, + nativeWindow, + &AzFramework::WindowRequestBus::Events::GetDpiScaleFactor); AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow); AzFramework::ViewportRequestBus::Handler::BusConnect(id); @@ -45,20 +46,6 @@ namespace AZ m_viewMatrixChangedEvent.Signal(matrix); }); - m_prepareFrameHandler = RenderPipeline::FrameNotificationEvent::Handler( - [this]() - { - ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick); - ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick); - }); - - m_endFrameHandler = RenderPipeline::FrameNotificationEvent::Handler( - [this]() - { - ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnFrameEnd); - ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnFrameEnd); - }); - SetRenderScene(renderScene); } @@ -124,38 +111,26 @@ namespace AZ { SceneNotificationBus::Handler::BusConnect(m_rootScene->GetId()); } - ResetCurrentPipeline(); + m_currentPipeline.reset(); UpdatePipelineView(); - UpdatePipelineRefreshRate(); } m_sceneChangedEvent.Signal(scene); } - float ViewportContext::GetFpsLimit() const + void ViewportContext::RenderTick() { - return m_fpsLimit; - } - - void ViewportContext::SetFpsLimit(float fpsLimit) - { - m_fpsLimit = fpsLimit; - UpdatePipelineRefreshRate(); - } - - float ViewportContext::GetTargetFrameRate() const - { - float targetFrameRate = GetFpsLimit(); - const AZ::u32 vsyncInterval = GetVsyncInterval(); - if (vsyncInterval != 0) + // add the current pipeline to next render tick if it's not already added. + if (m_currentPipeline && m_currentPipeline->GetRenderMode() != RenderPipeline::RenderMode::RenderOnce) { - const float vsyncFrameRate = static_cast(GetRefreshRate()) / static_cast(vsyncInterval); - if (targetFrameRate == 0.f || vsyncFrameRate < targetFrameRate) - { - targetFrameRate = vsyncFrameRate; - } + m_currentPipeline->AddToRenderTickOnce(); } - return targetFrameRate; + } + + void ViewportContext::OnBeginPrepareRender() + { + ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick); + ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick); } AZ::Name ViewportContext::GetName() const @@ -183,16 +158,6 @@ namespace AZ return m_viewportDpiScaleFactor; } - uint32_t ViewportContext::GetVsyncInterval() const - { - return m_vsyncInterval; - } - - uint32_t ViewportContext::GetRefreshRate() const - { - return m_refreshRate; - } - void ViewportContext::ConnectSizeChangedHandler(SizeChangedEvent::Handler& handler) { handler.Connect(m_sizeChangedEvent); @@ -203,16 +168,6 @@ namespace AZ handler.Connect(m_dpiScalingFactorChangedEvent); } - void ViewportContext::ConnectVsyncIntervalChangedHandler(UintChangedEvent::Handler& handler) - { - handler.Connect(m_vsyncIntervalChangedEvent); - } - - void ViewportContext::ConnectRefreshRateChangedHandler(UintChangedEvent::Handler& handler) - { - handler.Connect(m_refreshRateChangedEvent); - } - void ViewportContext::ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler) { handler.Connect(m_viewMatrixChangedEvent); @@ -308,43 +263,12 @@ namespace AZ m_currentPipelineChangedEvent.Signal(m_currentPipeline); } - if (m_currentPipeline) + if (auto pipeline = GetCurrentPipeline()) { - if (!m_prepareFrameHandler.IsConnected()) - { - m_currentPipeline->ConnectPrepareFrameHandler(m_prepareFrameHandler); - m_currentPipeline->ConnectEndFrameHandler(m_endFrameHandler); - } - m_currentPipeline->SetDefaultView(m_defaultView); + pipeline->SetDefaultView(m_defaultView); } } - void ViewportContext::UpdatePipelineRefreshRate() - { - if (!m_currentPipeline) - { - return; - } - - const float refreshRate = GetTargetFrameRate(); - // If we have a truly unlimited framerate, just render every tick - if (refreshRate == 0.f) - { - m_currentPipeline->AddToRenderTick(); - } - else - { - m_currentPipeline->AddToRenderTickAtInterval(AZStd::chrono::duration(1.f / refreshRate)); - } - } - - void ViewportContext::ResetCurrentPipeline() - { - m_prepareFrameHandler.Disconnect(); - m_endFrameHandler.Disconnect(); - m_currentPipeline.reset(); - } - RenderPipelinePtr ViewportContext::GetCurrentPipeline() { return m_currentPipeline; @@ -357,9 +281,8 @@ namespace AZ // in the event prioritization is added later if (pipeline->GetWindowHandle() == m_windowContext->GetWindowHandle()) { - ResetCurrentPipeline(); + m_currentPipeline.reset(); UpdatePipelineView(); - UpdatePipelineRefreshRate(); } } @@ -367,9 +290,8 @@ namespace AZ { if (m_currentPipeline.get() == pipeline) { - ResetCurrentPipeline(); + m_currentPipeline.reset(); UpdatePipelineView(); - UpdatePipelineRefreshRate(); } } @@ -383,30 +305,10 @@ namespace AZ } } - void ViewportContext::OnRefreshRateChanged(uint32_t refreshRate) - { - if (m_refreshRate != refreshRate) - { - m_refreshRate = refreshRate; - m_refreshRateChangedEvent.Signal(m_refreshRate); - UpdatePipelineRefreshRate(); - } - } - void ViewportContext::OnDpiScaleFactorChanged(float dpiScaleFactor) { m_viewportDpiScaleFactor = dpiScaleFactor; m_dpiScalingFactorChangedEvent.Signal(dpiScaleFactor); } - - void ViewportContext::OnVsyncIntervalChanged(uint32_t interval) - { - if (m_vsyncInterval != interval) - { - m_vsyncInterval = interval; - m_vsyncIntervalChangedEvent.Signal(m_vsyncInterval); - UpdatePipelineRefreshRate(); - } - } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertiesLayout.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertiesLayout.cpp index 273ea321a6..1c5142031d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertiesLayout.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertiesLayout.cpp @@ -34,9 +34,9 @@ namespace AZ return m_materialPropertyDescriptors.size(); } - MaterialPropertyIndex MaterialPropertiesLayout::FindPropertyIndex(const Name& propertyName) const + MaterialPropertyIndex MaterialPropertiesLayout::FindPropertyIndex(const Name& propertyId) const { - return m_materialPropertyIndexes.Find(propertyName); + return m_materialPropertyIndexes.Find(propertyId); } const MaterialPropertyDescriptor* MaterialPropertiesLayout::GetPropertyDescriptor(MaterialPropertyIndex index) const diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp index ce842d385d..9afc05a237 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp @@ -46,7 +46,7 @@ namespace JsonSerializationTests AZStd::shared_ptr CreatePartialDefaultInstance() override { auto result = AZStd::make_shared(); - result->m_nameId = "testProperty"; + result->m_name = "testProperty"; result->m_dataType = AZ::RPI::MaterialPropertyDataType::Float; result->m_step = 1.0f; result->m_value = 0.0f; @@ -57,7 +57,7 @@ namespace JsonSerializationTests { return R"( { - "id": "testProperty", + "name": "testProperty", "type": "Float", "step": 1.0 })"; @@ -66,7 +66,7 @@ namespace JsonSerializationTests AZStd::shared_ptr CreateFullySetInstance() override { auto result = AZStd::make_shared(); - result->m_nameId = "testProperty"; + result->m_name = "testProperty"; result->m_description = "description"; result->m_displayName = "display_name"; result->m_dataType = AZ::RPI::MaterialPropertyDataType::Float; @@ -87,7 +87,7 @@ namespace JsonSerializationTests { return R"( { - "id": "testProperty", + "name": "testProperty", "displayName": "display_name", "description": "description", "type": "Float", @@ -101,7 +101,7 @@ namespace JsonSerializationTests "connection": { "type": "ShaderOption", - "id": "o_foo", + "name": "o_foo", "shaderIndex": 2 }, "enumIsUv": true @@ -135,7 +135,7 @@ namespace JsonSerializationTests const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& lhs, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& rhs) override { - if (lhs.m_nameId != rhs.m_nameId) { return false; } + if (lhs.m_name != rhs.m_name) { return false; } if (lhs.m_description != rhs.m_description) { return false; } if (lhs.m_displayName != rhs.m_displayName) { return false; } if (lhs.m_dataType != rhs.m_dataType) { return false; } @@ -153,7 +153,7 @@ namespace JsonSerializationTests auto& leftConnection = lhs.m_outputConnections[i]; auto& rightConnection = rhs.m_outputConnections[i]; if (leftConnection.m_type != rightConnection.m_type) { return false; } - if (leftConnection.m_nameId != rightConnection.m_nameId) { return false; } + if (leftConnection.m_fieldName != rightConnection.m_fieldName) { return false; } if (leftConnection.m_shaderIndex != rightConnection.m_shaderIndex) { return false; } } return true; @@ -202,7 +202,7 @@ namespace UnitTest { const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "displayName": "Test Property", "description": "This is a property description", "type": "Float" @@ -216,12 +216,12 @@ namespace UnitTest EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); EXPECT_EQ(AZ::JsonSerializationResult::Outcomes::PartialDefaults, loadResult.m_jsonResultCode.GetOutcome()); - EXPECT_EQ("testProperty", propertyData.m_nameId); + EXPECT_EQ("testProperty", propertyData.m_name); EXPECT_EQ("Test Property", propertyData.m_displayName); EXPECT_EQ("This is a property description", propertyData.m_description); EXPECT_EQ(MaterialPropertyDataType::Float, propertyData.m_dataType); - EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/displayName", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/description", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/type", "Success")); @@ -237,7 +237,7 @@ namespace UnitTest // Note we are keeping id and type because they are required fields const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "type": "Float" } )"; @@ -252,7 +252,7 @@ namespace UnitTest EXPECT_TRUE(propertyData.m_displayName.empty()); EXPECT_TRUE(propertyData.m_description.empty()); - EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/type", "Success")); EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped)); @@ -280,7 +280,7 @@ namespace UnitTest { const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "type": "foo" } )"; @@ -294,7 +294,7 @@ namespace UnitTest EXPECT_EQ(AZ::RPI::MaterialPropertyDataType::Invalid, propertyData.m_dataType); - EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/type", "Enum value could not read")); } @@ -303,7 +303,7 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Float", "defaultValue": 0.5, "min": 0.1, @@ -313,7 +313,7 @@ namespace UnitTest "step": 0.05 }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Int", "defaultValue": -1, "min": -5, @@ -323,7 +323,7 @@ namespace UnitTest "step": 1 }, { - "id": "testProperty3", + "name": "testProperty3", "type": "UInt", "defaultValue": 4294901761, "min": 4294901760, @@ -368,7 +368,7 @@ namespace UnitTest for (int i = 0; i < propertyData.size(); ++i) { AZStd::string prefix = AZStd::string::format("/%d", i); - EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/type", "Success")); EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/defaultValue", "Success")); EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/min", "Success")); @@ -388,19 +388,19 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "displayName": "Test Property 1", "description": "Test", "type": "Float" }, { - "id": "testProperty2", + "name": "testProperty2", "displayName": "Test Property 2", "description": "Test", "type": "Int" }, { - "id": "testProperty3", + "name": "testProperty3", "displayName": "Test Property 3", "description": "Test", "type": "UInt" @@ -443,13 +443,13 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Vector2", "vectorLabels": ["U", "V"], "defaultValue": [0.6, 0.5] }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Vector4", "vectorLabels": ["A", "B", "C", "D"], "defaultValue": [0.3, 0.4, 0.5, 0.6] @@ -485,21 +485,21 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "visibilityIsDefault", + "name": "visibilityIsDefault", "type": "Float" }, { - "id": "visibilityIsEditable", + "name": "visibilityIsEditable", "type": "Float", "visibility": "Enabled" }, { - "id": "visibilityIsDisabled", + "name": "visibilityIsDisabled", "type": "Float", "visibility": "Disabled" }, { - "id": "visibilityIsHidden", + "name": "visibilityIsHidden", "type": "Float", "visibility": "Hidden" } @@ -509,20 +509,20 @@ namespace UnitTest const AZStd::string expectedOutputJson = R"( [ { - "id": "visibilityIsDefault", + "name": "visibilityIsDefault", "type": "Float" }, { - "id": "visibilityIsEditable", + "name": "visibilityIsEditable", "type": "Float" }, { - "id": "visibilityIsDisabled", + "name": "visibilityIsDisabled", "type": "Float", "visibility": "Disabled" }, { - "id": "visibilityIsHidden", + "name": "visibilityIsHidden", "type": "Float", "visibility": "Hidden" } @@ -552,7 +552,7 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Float", "defaultValue": true, "min": -1, @@ -560,7 +560,7 @@ namespace UnitTest "step": "1" }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Int", "defaultValue": true, "min": -1.5, @@ -568,7 +568,7 @@ namespace UnitTest "step": "1" }, { - "id": "testProperty3", + "name": "testProperty3", "type": "UInt", "defaultValue": "4294963200", "min": true, @@ -610,32 +610,32 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Bool", "defaultValue": true }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Vector2", "defaultValue": [0.1, 0.2] }, { - "id": "testProperty3", + "name": "testProperty3", "type": "Vector3", "defaultValue": [0.3, 0.4, 0.5] }, { - "id": "testProperty4", + "name": "testProperty4", "type": "Vector4", "defaultValue": [0.6, 0.5, 0.8, 0.4] }, { - "id": "testProperty5", + "name": "testProperty5", "type": "Color", "defaultValue": [0.1, 0.2, 0.3] }, { - "id": "testProperty6", + "name": "testProperty6", "type": "Image", "defaultValue": "Default.png" } @@ -669,7 +669,7 @@ namespace UnitTest for (int i = 0; i < propertyData.size(); ++i) { AZStd::string prefix = AZStd::string::format("/%d", i); - EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/type", "Success")); EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/defaultValue", "Success")); } @@ -684,27 +684,27 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Bool" }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Vector2" }, { - "id": "testProperty3", + "name": "testProperty3", "type": "Vector3" }, { - "id": "testProperty4", + "name": "testProperty4", "type": "Vector4" }, { - "id": "testProperty5", + "name": "testProperty5", "type": "Color" }, { - "id": "testProperty6", + "name": "testProperty6", "type": "Image" } ] @@ -745,27 +745,27 @@ namespace UnitTest const AZStd::string inputJson = R"( [ { - "id": "testProperty1", + "name": "testProperty1", "type": "Bool", "defaultValue": 1 }, { - "id": "testProperty2", + "name": "testProperty2", "type": "Vector2", "defaultValue": { "x": 0.4, "y": 0.1 } }, { - "id": "testProperty3", + "name": "testProperty3", "type": "Vector3", "defaultValue": { "x": 0.4, "y": 0.1, "z": 0.5 } }, { - "id": "testProperty4", + "name": "testProperty4", "type": "Vector4", "defaultValue": { "x": 0.4, "y": 0.1, "z": 0.5, "w": 0.6 } }, { - "id": "testProperty5", + "name": "testProperty5", "type": "Color", "defaultValue": { "hex": "FF00FF" } } @@ -798,6 +798,41 @@ namespace UnitTest TEST_F(MaterialPropertySerializerTests, LoadAndStoreJson_OneConnection) { + const AZStd::string inputJson = R"( + { + "name": "testProperty", + "type": "Float", + "connection": { + "type": "ShaderOption", + "name": "o_foo", + "shaderIndex": 2 + } + } + )"; + + MaterialTypeSourceData::PropertyDefinition propertyData; + JsonTestResult loadResult = LoadTestDataFromJson(propertyData, inputJson); + + EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask()); + EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); + + EXPECT_EQ(1, propertyData.m_outputConnections.size()); + EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[0].m_type); + EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName); + EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex); + + EXPECT_TRUE(loadResult.ContainsMessage("/connection/type", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/connection/name", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/connection/shaderIndex", "Success")); + EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped)); + + TestStoreToJson(propertyData, inputJson); + } + + TEST_F(MaterialPropertySerializerTests, LoadUsingOldFormat) + { + // Tests backward compatibility for when "id" was the key instead of "name", for both the property and its connections. + const AZStd::string inputJson = R"( { "id": "testProperty", @@ -815,35 +850,35 @@ namespace UnitTest EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask()); EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); + + EXPECT_EQ("testProperty", propertyData.m_name); EXPECT_EQ(1, propertyData.m_outputConnections.size()); EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[0].m_type); - EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_nameId); + EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName); EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex); EXPECT_TRUE(loadResult.ContainsMessage("/connection/type", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/connection/id", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/connection/shaderIndex", "Success")); EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped)); - - TestStoreToJson(propertyData, inputJson); } TEST_F(MaterialPropertySerializerTests, LoadAndStoreJson_MultipleConnections) { const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "type": "Float", "connection": [ { "type": "ShaderInput", - "id": "o_foo", + "name": "o_foo", "shaderIndex": 2 }, { "type": "ShaderOption", - "id": "o_bar", + "name": "o_bar", "shaderIndex": 1 } ] @@ -858,18 +893,18 @@ namespace UnitTest EXPECT_EQ(2, propertyData.m_outputConnections.size()); EXPECT_EQ(MaterialPropertyOutputType::ShaderInput, propertyData.m_outputConnections[0].m_type); - EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_nameId); + EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName); EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex); EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[1].m_type); - EXPECT_EQ("o_bar", propertyData.m_outputConnections[1].m_nameId); + EXPECT_EQ("o_bar", propertyData.m_outputConnections[1].m_fieldName); EXPECT_EQ(1, propertyData.m_outputConnections[1].m_shaderIndex); EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/type", "Success")); - EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/shaderIndex", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/type", "Success")); - EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/id", "Success")); + EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/name", "Success")); EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/shaderIndex", "Success")); EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped)); @@ -881,12 +916,12 @@ namespace UnitTest // "conection" is misspelled const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "type": "Float", "conection": [ { "type": "ShaderInput", - "id": "o_foo", + "name": "o_foo", "shaderIndex": 2 } ] @@ -899,7 +934,7 @@ namespace UnitTest EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask()); EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); - EXPECT_EQ(propertyData.m_nameId, "testProperty"); + EXPECT_EQ(propertyData.m_name, "testProperty"); EXPECT_EQ(propertyData.m_dataType, MaterialPropertyDataType::Float); EXPECT_EQ(propertyData.m_outputConnections.size(), 0); @@ -911,13 +946,13 @@ namespace UnitTest // "shadrIndex" is misspelled const AZStd::string inputJson = R"( { - "id": "testProperty", + "name": "testProperty", "type": "Float", "connection": [ { "type": "ShaderInput", "shadrIndex": 2, - "id": "o_foo" + "name": "o_foo" } ] } @@ -929,10 +964,10 @@ namespace UnitTest EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask()); EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing()); - EXPECT_EQ(propertyData.m_nameId, "testProperty"); + EXPECT_EQ(propertyData.m_name, "testProperty"); EXPECT_EQ(propertyData.m_dataType, MaterialPropertyDataType::Float); EXPECT_EQ(propertyData.m_outputConnections.size(), 1); - EXPECT_EQ(propertyData.m_outputConnections[0].m_nameId, "o_foo"); + EXPECT_EQ(propertyData.m_outputConnections[0].m_fieldName, "o_foo"); EXPECT_EQ(propertyData.m_outputConnections[0].m_type, MaterialPropertyOutputType::ShaderInput); EXPECT_EQ(propertyData.m_outputConnections[0].m_shaderIndex, -1); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index 553c3243e1..dd3b3b2711 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -89,14 +89,14 @@ namespace UnitTest } }; - void AddPropertyGroup(MaterialSourceData& material, AZStd::string_view groupNameId) + void AddPropertyGroup(MaterialSourceData& material, AZStd::string_view groupName) { - material.m_properties.insert(groupNameId); + material.m_properties.insert(groupName); } - void AddProperty(MaterialSourceData& material, AZStd::string_view groupNameId, AZStd::string_view propertyNameId, const MaterialPropertyValue& anyValue) + void AddProperty(MaterialSourceData& material, AZStd::string_view groupName, AZStd::string_view propertyName, const MaterialPropertyValue& anyValue) { - material.m_properties[groupNameId][propertyNameId].m_value = anyValue; + material.m_properties[groupName][propertyName].m_value = anyValue; } TEST_F(MaterialSourceDataTests, CreateMaterialAsset_BasicProperties) @@ -205,25 +205,25 @@ namespace UnitTest " \"propertyLayout\": { \n" " \"version\": 1, \n" " \"groups\": [ \n" - " { \"id\": \"groupA\" }, \n" - " { \"id\": \"groupB\" }, \n" - " { \"id\": \"groupC\" } \n" + " { \"name\": \"groupA\" }, \n" + " { \"name\": \"groupB\" }, \n" + " { \"name\": \"groupC\" } \n" " ], \n" " \"properties\": { \n" " \"groupA\": [ \n" - " {\"id\": \"MyBool\", \"type\": \"bool\"}, \n" - " {\"id\": \"MyInt\", \"type\": \"int\"}, \n" - " {\"id\": \"MyUInt\", \"type\": \"uint\"} \n" + " {\"name\": \"MyBool\", \"type\": \"bool\"}, \n" + " {\"name\": \"MyInt\", \"type\": \"int\"}, \n" + " {\"name\": \"MyUInt\", \"type\": \"uint\"} \n" " ], \n" " \"groupB\": [ \n" - " {\"id\": \"MyFloat\", \"type\": \"float\"}, \n" - " {\"id\": \"MyFloat2\", \"type\": \"vector2\"}, \n" - " {\"id\": \"MyFloat3\", \"type\": \"vector3\"} \n" + " {\"name\": \"MyFloat\", \"type\": \"float\"}, \n" + " {\"name\": \"MyFloat2\", \"type\": \"vector2\"}, \n" + " {\"name\": \"MyFloat3\", \"type\": \"vector3\"} \n" " ], \n" " \"groupC\": [ \n" - " {\"id\": \"MyFloat4\", \"type\": \"vector4\"}, \n" - " {\"id\": \"MyColor\", \"type\": \"color\"}, \n" - " {\"id\": \"MyImage\", \"type\": \"image\"} \n" + " {\"name\": \"MyFloat4\", \"type\": \"vector4\"}, \n" + " {\"name\": \"MyColor\", \"type\": \"color\"}, \n" + " {\"name\": \"MyImage\", \"type\": \"image\"} \n" " ] \n" " } \n" " } \n" @@ -271,7 +271,7 @@ namespace UnitTest "properties": { "general": [ { - "id": "testColor", + "name": "testColor", "type": "color" } ] @@ -381,7 +381,7 @@ namespace UnitTest "properties": { "general": [ { - "id": "testColor", + "name": "testColor", "type": "color" } ] @@ -427,7 +427,7 @@ namespace UnitTest "properties": { "general": [ { - "id": "testColor", + "name": "testColor", "type": "color" } ] diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp index 179dc7c966..ba4a58b9ff 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp @@ -510,7 +510,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename }); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyBool"; + propertySource.m_name = "MyBool"; propertySource.m_displayName = "My Bool"; propertySource.m_description = "This is a bool"; propertySource.m_dataType = MaterialPropertyDataType::Bool; @@ -536,7 +536,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename }); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyFloat"; + propertySource.m_name = "MyFloat"; propertySource.m_displayName = "My Float"; propertySource.m_description = "This is a float"; propertySource.m_min = 0.0f; @@ -566,7 +566,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename }); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyImage"; + propertySource.m_name = "MyImage"; propertySource.m_displayName = "My Image"; propertySource.m_description = "This is an image"; propertySource.m_dataType = MaterialPropertyDataType::Image; @@ -591,7 +591,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename}); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyInt"; + propertySource.m_name = "MyInt"; propertySource.m_displayName = "My Integer"; propertySource.m_dataType = MaterialPropertyDataType::Int; propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{MaterialPropertyOutputType::ShaderOption, AZStd::string("o_foo"), 0}); @@ -614,7 +614,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename}); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyInt"; + propertySource.m_name = "MyInt"; propertySource.m_dataType = MaterialPropertyDataType::Int; propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{MaterialPropertyOutputType::ShaderOption, AZStd::string("DoesNotExist"), 0}); sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); @@ -633,7 +633,7 @@ namespace UnitTest MaterialTypeSourceData::PropertyDefinition propertySource; propertySource.m_dataType = MaterialPropertyDataType::Int; - propertySource.m_nameId = "a"; + propertySource.m_name = "a"; sourceData.m_propertyLayout.m_properties["not a valid name because it has spaces"].push_back(propertySource); // Expected errors: @@ -654,7 +654,7 @@ namespace UnitTest MaterialTypeSourceData::PropertyDefinition propertySource; propertySource.m_dataType = MaterialPropertyDataType::Int; - propertySource.m_nameId = "not a valid name because it has spaces"; + propertySource.m_name = "not a valid name because it has spaces"; sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); // Expected errors: @@ -674,7 +674,7 @@ namespace UnitTest MaterialTypeSourceData::PropertyDefinition propertySource; propertySource.m_dataType = MaterialPropertyDataType::Int; - propertySource.m_nameId = "a"; + propertySource.m_name = "a"; sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); @@ -738,7 +738,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ "shaderC.shader" }); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyInt"; + propertySource.m_name = "MyInt"; propertySource.m_displayName = "Integer"; propertySource.m_description = "Integer property that is connected to multiple shader settings"; propertySource.m_dataType = MaterialPropertyDataType::Int; @@ -797,7 +797,7 @@ namespace UnitTest MaterialTypeSourceData sourceData; MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "NonAliasFloat"; + propertySource.m_name = "NonAliasFloat"; propertySource.m_displayName = "Non-Alias Float"; propertySource.m_description = "This float is processed by a functor, not with a direct alias"; propertySource.m_dataType = MaterialPropertyDataType::Float; @@ -842,13 +842,13 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename}); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "EnableSpecialPassA"; + propertySource.m_name = "EnableSpecialPassA"; propertySource.m_displayName = "Enable Special Pass"; propertySource.m_description = "This is a bool to enable an extra shader/pass"; propertySource.m_dataType = MaterialPropertyDataType::Bool; // Note that we don't fill propertySource.m_outputConnections because this is not a direct-connected property sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); - propertySource.m_nameId = "EnableSpecialPassB"; + propertySource.m_name = "EnableSpecialPassB"; sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); sourceData.m_materialFunctorSourceData.push_back( @@ -902,7 +902,7 @@ namespace UnitTest sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename}); MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = "MyProperty"; + propertySource.m_name = "MyProperty"; propertySource.m_dataType = MaterialPropertyDataType::Bool; // Note that we don't fill propertySource.m_outputConnections because this is not a direct-connected property sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource); @@ -938,7 +938,7 @@ namespace UnitTest auto addProperty = [&sourceData](MaterialPropertyDataType dateType, const char* propertyName, const char* srgConstantName, const AZ::RPI::MaterialPropertyValue& value) { MaterialTypeSourceData::PropertyDefinition propertySource; - propertySource.m_nameId = propertyName; + propertySource.m_name = propertyName; propertySource.m_dataType = dateType; propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{ MaterialPropertyOutputType::ShaderInput, AZStd::string(srgConstantName) }); propertySource.m_value = value; @@ -975,6 +975,152 @@ namespace UnitTest // Note that serialization of individual fields within material properties is thoroughly tested in // MaterialPropertySerializerTests, so the sample property data used here is cursory. + const AZStd::string inputJson = R"( + { + "description": "This is a general description about the material", + "propertyLayout": { + "version": 2, + "groups": [ + { + "name": "groupA", + "displayName": "Property Group A", + "description": "Description of property group A" + }, + { + "name": "groupB", + "displayName": "Property Group B", + "description": "Description of property group B" + } + ], + "properties": { + "groupA": [ + { + "name": "foo", + "type": "Bool", + "defaultValue": true + }, + { + "name": "bar", + "type": "Image", + "defaultValue": "Default.png", + "visibility": "Hidden" + } + ], + "groupB": [ + { + "name": "foo", + "type": "Float", + "defaultValue": 0.5 + }, + { + "name": "bar", + "type": "Color", + "defaultValue": [0.5, 0.5, 0.5], + "visibility": "Disabled" + } + ] + } + }, + "shaders": [ + { + "file": "ForwardPass.shader", + "tag": "ForwardPass", + "options": { + "o_optionA": "False", + "o_optionB": "True" + } + }, + { + "file": "DepthPass.shader", + "options": { + "o_optionC": "1", + "o_optionD": "2" + } + } + ], + "functors": [ + { + "type": "EnableShader", + "args": { + "enablePassProperty": "groupA.foo", + "shaderIndex": 1 + } + }, + { + "type": "Splat3", + "args": { + "floatPropertyInput": "groupB.foo", + "float3ShaderSettingOutput": "m_someFloat3" + } + } + ] + } + )"; + + MaterialTypeSourceData material; + JsonTestResult loadResult = LoadTestDataFromJson(material, inputJson); + + EXPECT_EQ(material.m_description, "This is a general description about the material"); + + EXPECT_EQ(material.m_propertyLayout.m_version, 2); + + EXPECT_EQ(material.m_propertyLayout.m_groups.size(), 2); + EXPECT_TRUE(material.FindGroup("groupA") != nullptr); + EXPECT_TRUE(material.FindGroup("groupB") != nullptr); + EXPECT_EQ(material.FindGroup("groupA")->m_displayName, "Property Group A"); + EXPECT_EQ(material.FindGroup("groupB")->m_displayName, "Property Group B"); + EXPECT_EQ(material.FindGroup("groupA")->m_description, "Description of property group A"); + EXPECT_EQ(material.FindGroup("groupB")->m_description, "Description of property group B"); + + EXPECT_EQ(material.m_propertyLayout.m_properties.size(), 2); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"].size(), 2); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"].size(), 2); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_name, "foo"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_name, "bar"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_name, "foo"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_name, "bar"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_dataType, MaterialPropertyDataType::Bool); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_dataType, MaterialPropertyDataType::Image); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_dataType, MaterialPropertyDataType::Float); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_dataType, MaterialPropertyDataType::Color); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_visibility, MaterialPropertyVisibility::Enabled); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_visibility, MaterialPropertyVisibility::Hidden); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_visibility, MaterialPropertyVisibility::Enabled); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_visibility, MaterialPropertyVisibility::Disabled); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_value, true); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_value, AZStd::string{"Default.png"}); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_value, 0.5f); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_value, AZ::Color(0.5f, 0.5f, 0.5f, 1.0f)); + + EXPECT_EQ(material.m_shaderCollection.size(), 2); + EXPECT_EQ(material.m_shaderCollection[0].m_shaderFilePath, "ForwardPass.shader"); + EXPECT_EQ(material.m_shaderCollection[1].m_shaderFilePath, "DepthPass.shader"); + EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues.size(), 2); + EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues.size(), 2); + EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues[Name{"o_optionA"}], Name{"False"}); + EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues[Name{"o_optionB"}], Name{"True"}); + EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues[Name{"o_optionC"}], Name{"1"}); + EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues[Name{"o_optionD"}], Name{"2"}); + EXPECT_EQ(material.m_shaderCollection[0].m_shaderTag, Name{"ForwardPass"}); + + EXPECT_EQ(material.m_materialFunctorSourceData.size(), 2); + EXPECT_TRUE(azrtti_cast(material.m_materialFunctorSourceData[0]->GetActualSourceData().get())); + EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[0]->GetActualSourceData().get())->m_enablePassPropertyId, "groupA.foo"); + EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[0]->GetActualSourceData().get())->m_shaderIndex, 1); + EXPECT_TRUE(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())); + EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_floatPropertyInputId, "groupB.foo"); + EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_float3ShaderSettingOutputId, "m_someFloat3"); + + AZStd::string outputJson; + JsonTestResult storeResult = StoreTestDataToJson(material, outputJson); + ExpectSimilarJson(inputJson, outputJson); + } + + TEST_F(MaterialTypeSourceDataTests, LoadAllFieldsUsingOldFormat) + { + // The content of this test was copied from LoadAndStoreJson_AllFields to prove backward compatibility. + // (The "store" part of the test was not included because the saved data will be the new format). + const AZStd::string inputJson = R"( { "description": "This is a general description about the material", @@ -1075,10 +1221,10 @@ namespace UnitTest EXPECT_EQ(material.m_propertyLayout.m_properties.size(), 2); EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"].size(), 2); EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"].size(), 2); - EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_nameId, "foo"); - EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_nameId, "bar"); - EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_nameId, "foo"); - EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_nameId, "bar"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_name, "foo"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_name, "bar"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_name, "foo"); + EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_name, "bar"); EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_dataType, MaterialPropertyDataType::Bool); EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_dataType, MaterialPropertyDataType::Image); EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_dataType, MaterialPropertyDataType::Float); @@ -1110,10 +1256,6 @@ namespace UnitTest EXPECT_TRUE(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())); EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_floatPropertyInputId, "groupB.foo"); EXPECT_EQ(azrtti_cast(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_float3ShaderSettingOutputId, "m_someFloat3"); - - AZStd::string outputJson; - JsonTestResult storeResult = StoreTestDataToJson(material, outputJson); - ExpectSimilarJson(inputJson, outputJson); } TEST_F(MaterialTypeSourceDataTests, CreateMaterialTypeAsset_PropertyImagePath) @@ -1127,7 +1269,7 @@ namespace UnitTest "version": 2, "groups": [ { - "id": "general", + "name": "general", "displayName": "General", "description": "" } @@ -1135,12 +1277,12 @@ namespace UnitTest "properties": { "general": [ { - "id": "absolute", + "name": "absolute", "type": "Image", "defaultValue": "%s" }, { - "id": "relative", + "name": "relative", "type": "Image", "defaultValue": "%s" } diff --git a/Gems/Atom/RPI/Code/atom_rpi_edit_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_edit_files.cmake index c7a459f217..e32d19ffd7 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_edit_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_edit_files.cmake @@ -18,6 +18,8 @@ set(FILES Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h Include/Atom/RPI.Edit/Material/MaterialConverterBus.h Include/Atom/RPI.Edit/Material/MaterialPropertyId.h + Include/Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h + Include/Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h Include/Atom/RPI.Edit/Material/MaterialPropertySerializer.h Include/Atom/RPI.Edit/Material/MaterialPropertyValueSerializer.h Include/Atom/RPI.Edit/Material/MaterialPropertyValueSourceData.h @@ -36,6 +38,8 @@ set(FILES Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp Source/RPI.Edit/Material/MaterialTypeSourceData.cpp Source/RPI.Edit/Material/MaterialPropertyId.cpp + Source/RPI.Edit/Material/MaterialPropertyGroupSerializer.cpp + Source/RPI.Edit/Material/MaterialPropertyConnectionSerializer.cpp Source/RPI.Edit/Material/MaterialPropertySerializer.cpp Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp Source/RPI.Edit/Material/MaterialPropertyValueSourceData.cpp diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick.materialtype b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick.materialtype index 0b62638c5a..00f11663f7 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick.materialtype +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick.materialtype @@ -4,12 +4,12 @@ "version": 3, "groups": [ { - "id": "shape", + "name": "shape", "displayName": "Shape", "description": "Properties for configuring size, shape, and position of the bricks." }, { - "id": "appearance", + "name": "appearance", "displayName": "Appearance", "description": "Properties for configuring the appearance of the bricks and grout lines." } @@ -17,7 +17,7 @@ "properties": { "shape": [ { - "id": "brickWidth", + "name": "brickWidth", "displayName": "Brick Width", "description": "The width of each brick.", "type": "Float", @@ -27,11 +27,11 @@ "step": 0.001, "connection": { "type": "ShaderInput", - "id": "m_brickWidth" + "name": "m_brickWidth" } }, { - "id": "brickHeight", + "name": "brickHeight", "displayName": "Brick Height", "description": "The height of each brick.", "type": "Float", @@ -41,11 +41,11 @@ "step": 0.001, "connection": { "type": "ShaderInput", - "id": "m_brickHeight" + "name": "m_brickHeight" } }, { - "id": "brickOffset", + "name": "brickOffset", "displayName": "Offset", "description": "The offset of each stack of bricks as a percentage of brick width.", "type": "Float", @@ -54,11 +54,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_brickOffset" + "name": "m_brickOffset" } }, { - "id": "lineWidth", + "name": "lineWidth", "displayName": "Line Width", "description": "The width of the grout lines.", "type": "Float", @@ -68,11 +68,11 @@ "step": 0.0001, "connection": { "type": "ShaderInput", - "id": "m_lineWidth" + "name": "m_lineWidth" } }, { - "id": "lineDepth", + "name": "lineDepth", "displayName": "Line Depth", "description": "The depth of the grout lines.", "type": "Float", @@ -81,34 +81,34 @@ "softMax": 0.02, "connection": { "type": "ShaderInput", - "id": "m_lineDepth" + "name": "m_lineDepth" } } ], "appearance": [ { - "id": "noiseTexture", + "name": "noiseTexture", "type": "Image", "defaultValue": "TestData/Textures/noise512.png", "visibility": "Hidden", "connection": { "type": "ShaderInput", - "id": "m_noise" + "name": "m_noise" } }, { - "id": "brickColor", + "name": "brickColor", "displayName": "Brick Color", "description": "The color of the bricks.", "type": "Color", "defaultValue": [1.0,1.0,1.0], "connection": { "type": "ShaderInput", - "id": "m_brickColor" + "name": "m_brickColor" } }, { - "id": "brickColorNoise", + "name": "brickColorNoise", "displayName": "Brick Color Noise", "description": "Scale the variation of brick color.", "type": "Float", @@ -117,22 +117,22 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_brickNoiseFactor" + "name": "m_brickNoiseFactor" } }, { - "id": "lineColor", + "name": "lineColor", "displayName": "Line Color", "description": "The color of the grout lines.", "type": "Color", "defaultValue": [0.5,0.5,0.5], "connection": { "type": "ShaderInput", - "id": "m_lineColor" + "name": "m_lineColor" } }, { - "id": "lineColorNoise", + "name": "lineColorNoise", "displayName": "Line Color Noise", "description": "Scale the variation of grout line color.", "type": "Float", @@ -141,11 +141,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_lineNoiseFactor" + "name": "m_lineNoiseFactor" } }, { - "id": "brickColorBleed", + "name": "brickColorBleed", "displayName": "Brick Color Bleed", "description": "Distance into the grout line that the brick color will continue.", "type": "Float", @@ -154,11 +154,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_brickColorBleed" + "name": "m_brickColorBleed" } }, { - "id": "ao", + "name": "ao", "displayName": "Ambient Occlusion", "description": "The strength of baked ambient occlusion in the grout lines.", "type": "Float", @@ -167,7 +167,7 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_aoFactor" + "name": "m_aoFactor" } } ] diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR.materialtype b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR.materialtype index fb2b8523e1..81ebd63c28 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR.materialtype +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR.materialtype @@ -4,24 +4,24 @@ "version": 3, "groups": [ { - "id": "settings", + "name": "settings", "displayName": "Settings" } ], "properties": { "settings": [ { - "id": "color", + "name": "color", "displayName": "Color", "type": "Color", "defaultValue": [ 1.0, 1.0, 1.0 ], "connection": { "type": "ShaderInput", - "id": "m_baseColor" + "name": "m_baseColor" } }, { - "id": "metallic", + "name": "metallic", "displayName": "Metallic", "type": "Float", "defaultValue": 0.0, @@ -29,11 +29,11 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_metallic" + "name": "m_metallic" } }, { - "id": "roughness", + "name": "roughness", "displayName": "Roughness", "type": "Float", "defaultValue": 1.0, @@ -41,7 +41,7 @@ "max": 1.0, "connection": { "type": "ShaderInput", - "id": "m_roughness" + "name": "m_roughness" } } ] diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h index 565c9f00a3..bf18d36c2c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -32,10 +32,10 @@ namespace AtomToolsFramework // AtomToolsDocumentRequestBus::Handler implementation AZStd::string_view GetAbsolutePath() const override; AZStd::string_view GetRelativePath() const override; - const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; - const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; + const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override; + const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; - void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; + void SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; bool Reopen() override; bool Save() override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h index 9ee53680ae..68e5e38cbd 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h @@ -42,8 +42,8 @@ namespace AtomToolsFramework AZ_CLASS_ALLOCATOR(DynamicPropertyConfig, AZ::SystemAllocator, 0); DynamicPropertyType m_dataType = DynamicPropertyType::Invalid; - AZ::Name m_id; - AZStd::string m_nameId; + AZ::Name m_id; //!< The full property ID, which will normally be "groupName.propertyName" + AZStd::string m_name; AZStd::string m_displayName; AZStd::string m_groupName; AZStd::string m_description; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h index 900dc3535c..6e5ac6e463 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h @@ -41,27 +41,27 @@ namespace AtomToolsFramework //! Add a group consisting of a collapsable header and widget virtual void AddGroup( - const AZStd::string& groupNameId, + const AZStd::string& groupName, const AZStd::string& groupDisplayName, const AZStd::string& groupDescription, QWidget* groupWidget) = 0; //! Sets the visibility of a specific property group. This impacts both the header and the widget. - virtual void SetGroupVisible(const AZStd::string& groupNameId, bool visible) = 0; + virtual void SetGroupVisible(const AZStd::string& groupName, bool visible) = 0; //! Returns whether a specific property is visible. //! Note this follows the same rules as QWidget::isVisible(), meaning a group could be not visible due to the widget's parents being not visible. - virtual bool IsGroupVisible(const AZStd::string& groupNameId) const = 0; + virtual bool IsGroupVisible(const AZStd::string& groupName) const = 0; //! Returns whether a specific property is explicitly hidden. //! Note this follows the same rules as QWidget::isHidden(), meaning a group that is hidden will not become visible automatically when the parent becomes visible. - virtual bool IsGroupHidden(const AZStd::string& groupNameId) const = 0; + virtual bool IsGroupHidden(const AZStd::string& groupName) const = 0; //! Calls Refresh for a specific InspectorGroupWidget, allowing for non-destructive UI changes - virtual void RefreshGroup(const AZStd::string& groupNameId) = 0; + virtual void RefreshGroup(const AZStd::string& groupName) = 0; //! Calls Rebuild for a specific InspectorGroupWidget, allowing for destructive UI changes - virtual void RebuildGroup(const AZStd::string& groupNameId) = 0; + virtual void RebuildGroup(const AZStd::string& groupName) = 0; //! Calls Refresh for all InspectorGroupWidget, allowing for non-destructive UI changes virtual void RefreshAll() = 0; @@ -70,13 +70,13 @@ namespace AtomToolsFramework virtual void RebuildAll() = 0; //! Expands a specific group - virtual void ExpandGroup(const AZStd::string& groupNameId) = 0; + virtual void ExpandGroup(const AZStd::string& groupName) = 0; //! Collapses a specific group - virtual void CollapseGroup(const AZStd::string& groupNameId) = 0; + virtual void CollapseGroup(const AZStd::string& groupName) = 0; //! Checks the expansion state of a specific group - virtual bool IsGroupExpanded(const AZStd::string& groupNameId) const = 0; + virtual bool IsGroupExpanded(const AZStd::string& groupName) const = 0; //! Expands all groups and headers virtual void ExpandAll() = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h index adcd94ca10..7e655d978e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -52,33 +52,33 @@ namespace AtomToolsFramework void AddGroupsEnd() override; void AddGroup( - const AZStd::string& groupNameId, + const AZStd::string& groupName, const AZStd::string& groupDisplayName, const AZStd::string& groupDescription, QWidget* groupWidget) override; - void SetGroupVisible(const AZStd::string& groupNameId, bool visible) override; - bool IsGroupVisible(const AZStd::string& groupNameId) const override; - bool IsGroupHidden(const AZStd::string& groupNameId) const override; + void SetGroupVisible(const AZStd::string& groupName, bool visible) override; + bool IsGroupVisible(const AZStd::string& groupName) const override; + bool IsGroupHidden(const AZStd::string& groupName) const override; - void RefreshGroup(const AZStd::string& groupNameId) override; - void RebuildGroup(const AZStd::string& groupNameId) override; + void RefreshGroup(const AZStd::string& groupName) override; + void RebuildGroup(const AZStd::string& groupName) override; void RefreshAll() override; void RebuildAll() override; - void ExpandGroup(const AZStd::string& groupNameId) override; - void CollapseGroup(const AZStd::string& groupNameId) override; - bool IsGroupExpanded(const AZStd::string& groupNameId) const override; + void ExpandGroup(const AZStd::string& groupName) override; + void CollapseGroup(const AZStd::string& groupName) override; + bool IsGroupExpanded(const AZStd::string& groupName) const override; void ExpandAll() override; void CollapseAll() override; protected: - virtual bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const; - virtual void OnGroupExpanded(const AZStd::string& groupNameId); - virtual void OnGroupCollapsed(const AZStd::string& groupNameId); - virtual void OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event); + virtual bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const; + virtual void OnGroupExpanded(const AZStd::string& groupName); + virtual void OnGroupCollapsed(const AZStd::string& groupName); + virtual void OnHeaderClicked(const AZStd::string& groupName, QMouseEvent* event); private: QScopedPointer m_ui; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h index 32897ab4d9..1200cb3d79 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h @@ -112,8 +112,7 @@ namespace AtomToolsFramework void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; // ModularViewportCameraControllerRequestBus overrides ... - void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) override; - AZStd::optional LookAtAfterInterpolation() const override; + void InterpolateToTransform(const AZ::Transform& worldFromLocal) override; AZ::Transform GetReferenceFrame() const override; void SetReferenceFrame(const AZ::Transform& worldFromLocal) override; void ClearReferenceFrame() override; @@ -149,9 +148,8 @@ namespace AtomToolsFramework CameraAnimation m_cameraAnimation; //!< Camera animation state (used during CameraMode::Animation). CameraMode m_cameraMode = CameraMode::Control; //!< The current mode the camera is operating in. - AZStd::optional m_lookAtAfterInterpolation; //!< The look at point after an interpolation has finished. - //!< Will be cleared when the view changes (camera looks away). - AZ::Transform m_referenceFrameOverride = AZ::Transform::CreateIdentity(); //!< + //! An additional reference frame the camera can operate in (identity has no effect). + AZ::Transform m_referenceFrameOverride = AZ::Transform::CreateIdentity(); //! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally). bool m_updatingTransformInternally = false; //! Listen for camera view changes outside of the camera controller. diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h index 388d24164a..ab397692e4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h @@ -29,11 +29,7 @@ namespace AtomToolsFramework //! Begin a smooth transition of the camera to the requested transform. //! @param worldFromLocal The transform of where the camera should end up. - //! @param lookAtDistance The distance between the camera transform and the imagined look at point. - virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) = 0; - - //! Look at point after an interpolation has finished and no translation has occurred. - virtual AZStd::optional LookAtAfterInterpolation() const = 0; + virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0; //! Return the current reference frame. //! @note If a reference frame has not been set or a frame has been cleared, this is just the identity. diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index 318a49027a..623d759c9f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -22,8 +21,6 @@ #include #include #include -#include -#include namespace AtomToolsFramework { @@ -38,8 +35,6 @@ namespace AtomToolsFramework , public AzFramework::WindowRequestBus::Handler , protected AzFramework::InputChannelEventListener , protected AZ::TickBus::Handler - , protected AZ::Render::Bootstrap::NotificationBus::Handler - , protected AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler { public: //! Creates a RenderViewportWidget. @@ -126,7 +121,6 @@ namespace AtomToolsFramework // AZ::TickBus::Handler ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - int GetTickOrder() override; // QWidget ... void resizeEvent(QResizeEvent *event) override; @@ -134,21 +128,9 @@ namespace AtomToolsFramework void enterEvent(QEvent* event) override; void leaveEvent(QEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; - void focusInEvent(QFocusEvent* event) override; - - // AZ::Render::Bootstrap::NotificationBus::Handler ... - void OnFrameRateLimitChanged(float fpsLimit) override; - - // AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler ... - void OnInactiveViewportFrameRateChanged(float fpsLimit) override; private: - AzFramework::NativeWindowHandle GetNativeWindowHandle() const; - void UpdateFrameRate(); - - void SetScreen(QScreen* screen); void SendWindowResizeEvent(); - void NotifyUpdateRefreshRate(); // The underlying ViewportContext, our entry-point to the Atom RPI. AZ::RPI::ViewportContextPtr m_viewportContext; @@ -169,11 +151,5 @@ namespace AtomToolsFramework AZ::ScriptTimePoint m_time; // Maps our internal Qt events into AzFramework InputChannels for our ViewportControllerList. AzToolsFramework::QtEventToAzInputMapper* m_inputChannelMapper = nullptr; - // Stores our current screen, used for tracking the current refresh rate. - QScreen* m_screen = nullptr; - // Stores the last RenderViewportWidget that has received user focus. - // This is used for optional framerate throtting for "inactive" viewports via the - // ed_inactive_viewport_fps_limit CVAR. - AZ::EnvironmentVariable m_lastFocusedViewport; }; } //namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h deleted file mode 100644 index 0563bd6bf2..0000000000 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 - * - */ - -#pragma once - -#include - -namespace AtomToolsFramework -{ - //! Provides an interface for providing notifications specific to RenderViewportWidget. - //! @note Most behaviors in RenderViewportWidget are handled by its underyling - //! ViewportContext, this bus is specifically for functionality exclusive to the - //! Qt layer provided by RenderViewportWidget. - class RenderViewportWidgetNotifications : public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Triggered when the idle frame rate limit for inactive viewports changed. - //! Controlled by the ed_inactive_viewport_fps_limit CVAR. - //! Active viewports are controlled by the r_fps_limit CVAR. - virtual void OnInactiveViewportFrameRateChanged([[maybe_unused]]float fpsLimit){} - - protected: - ~RenderViewportWidgetNotifications() = default; - }; - - using RenderViewportWidgetNotificationBus = AZ::EBus; -} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index 336737f419..1e2c685c3c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -38,16 +38,16 @@ namespace AtomToolsFramework return m_relativePath; } - const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName) const + const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyId) const { - AZ_UNUSED(propertyFullName); + AZ_UNUSED(propertyId); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidValue; } - const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty([[maybe_unused]] const AZ::Name& propertyFullName) const + const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty([[maybe_unused]] const AZ::Name& propertyId) const { - AZ_UNUSED(propertyFullName); + AZ_UNUSED(propertyId); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidProperty; } @@ -59,9 +59,9 @@ namespace AtomToolsFramework return false; } - void AtomToolsDocument::SetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName, [[maybe_unused]] const AZStd::any& value) + void AtomToolsDocument::SetPropertyValue([[maybe_unused]] const AZ::Name& propertyId, [[maybe_unused]] const AZStd::any& value) { - AZ_UNUSED(propertyFullName); + AZ_UNUSED(propertyId); AZ_UNUSED(value); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp index d08728aad1..2054858726 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp @@ -192,7 +192,7 @@ namespace AtomToolsFramework AZStd::string DynamicProperty::GetDisplayName() const { - return !m_config.m_displayName.empty() ? m_config.m_displayName : m_config.m_nameId; + return !m_config.m_displayName.empty() ? m_config.m_displayName : m_config.m_name; } AZStd::string DynamicProperty::GetGroupName() const diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp index 5ef2dbb2c5..fbe188364a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp @@ -72,7 +72,7 @@ namespace AtomToolsFramework } void InspectorWidget::AddGroup( - const AZStd::string& groupNameId, + const AZStd::string& groupName, const AZStd::string& groupDisplayName, const AZStd::string& groupDescription, QWidget* groupWidget) @@ -82,31 +82,31 @@ namespace AtomToolsFramework groupHeader->setToolTip(groupDescription.c_str()); m_ui->m_groupContentsLayout->addWidget(groupHeader); - groupWidget->setObjectName(groupNameId.c_str()); + groupWidget->setObjectName(groupName.c_str()); groupWidget->setParent(m_ui->m_groupContents); m_ui->m_groupContentsLayout->addWidget(groupWidget); - m_groups[groupNameId] = {groupHeader, groupWidget}; + m_groups[groupName] = {groupHeader, groupWidget}; - connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupNameId](QMouseEvent* event) { - OnHeaderClicked(groupNameId, event); + connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupName](QMouseEvent* event) { + OnHeaderClicked(groupName, event); }); - connect(groupHeader, &InspectorGroupHeaderWidget::expanded, this, [this, groupNameId]() { OnGroupExpanded(groupNameId); }); - connect(groupHeader, &InspectorGroupHeaderWidget::collapsed, this, [this, groupNameId]() { OnGroupCollapsed(groupNameId); }); + connect(groupHeader, &InspectorGroupHeaderWidget::expanded, this, [this, groupName]() { OnGroupExpanded(groupName); }); + connect(groupHeader, &InspectorGroupHeaderWidget::collapsed, this, [this, groupName]() { OnGroupCollapsed(groupName); }); - if (ShouldGroupAutoExpanded(groupNameId)) + if (ShouldGroupAutoExpanded(groupName)) { - ExpandGroup(groupNameId); + ExpandGroup(groupName); } else { - CollapseGroup(groupNameId); + CollapseGroup(groupName); } } - void InspectorWidget::SetGroupVisible(const AZStd::string& groupNameId, bool visible) + void InspectorWidget::SetGroupVisible(const AZStd::string& groupName, bool visible) { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); if (groupItr != m_groups.end()) { groupItr->second.m_header->setVisible(visible); @@ -114,29 +114,29 @@ namespace AtomToolsFramework } } - bool InspectorWidget::IsGroupVisible(const AZStd::string& groupNameId) const + bool InspectorWidget::IsGroupVisible(const AZStd::string& groupName) const { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); return groupItr != m_groups.end() ? groupItr->second.m_header->isVisible() : false; } - bool InspectorWidget::IsGroupHidden(const AZStd::string& groupNameId) const + bool InspectorWidget::IsGroupHidden(const AZStd::string& groupName) const { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); return groupItr != m_groups.end() ? groupItr->second.m_header->isHidden() : false; } - void InspectorWidget::RefreshGroup(const AZStd::string& groupNameId) + void InspectorWidget::RefreshGroup(const AZStd::string& groupName) { - for (auto groupWidget : m_ui->m_groupContents->findChildren(groupNameId.c_str())) + for (auto groupWidget : m_ui->m_groupContents->findChildren(groupName.c_str())) { groupWidget->Refresh(); } } - void InspectorWidget::RebuildGroup(const AZStd::string& groupNameId) + void InspectorWidget::RebuildGroup(const AZStd::string& groupName) { - for (auto groupWidget : m_ui->m_groupContents->findChildren(groupNameId.c_str())) + for (auto groupWidget : m_ui->m_groupContents->findChildren(groupName.c_str())) { groupWidget->Rebuild(); } @@ -158,9 +158,9 @@ namespace AtomToolsFramework } } - void InspectorWidget::ExpandGroup(const AZStd::string& groupNameId) + void InspectorWidget::ExpandGroup(const AZStd::string& groupName) { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); if (groupItr != m_groups.end()) { groupItr->second.m_header->SetExpanded(true); @@ -168,9 +168,9 @@ namespace AtomToolsFramework } } - void InspectorWidget::CollapseGroup(const AZStd::string& groupNameId) + void InspectorWidget::CollapseGroup(const AZStd::string& groupName) { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); if (groupItr != m_groups.end()) { groupItr->second.m_header->SetExpanded(false); @@ -178,9 +178,9 @@ namespace AtomToolsFramework } } - bool InspectorWidget::IsGroupExpanded(const AZStd::string& groupNameId) const + bool InspectorWidget::IsGroupExpanded(const AZStd::string& groupName) const { - auto groupItr = m_groups.find(groupNameId); + auto groupItr = m_groups.find(groupName); return groupItr != m_groups.end() ? groupItr->second.m_header->IsExpanded() : false; } @@ -202,33 +202,33 @@ namespace AtomToolsFramework } } - bool InspectorWidget::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const + bool InspectorWidget::ShouldGroupAutoExpanded(const AZStd::string& groupName) const { - AZ_UNUSED(groupNameId); + AZ_UNUSED(groupName); return true; } - void InspectorWidget::OnGroupExpanded(const AZStd::string& groupNameId) + void InspectorWidget::OnGroupExpanded(const AZStd::string& groupName) { - AZ_UNUSED(groupNameId); + AZ_UNUSED(groupName); } - void InspectorWidget::OnGroupCollapsed(const AZStd::string& groupNameId) + void InspectorWidget::OnGroupCollapsed(const AZStd::string& groupName) { - AZ_UNUSED(groupNameId); + AZ_UNUSED(groupName); } - void InspectorWidget::OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event) + void InspectorWidget::OnHeaderClicked(const AZStd::string& groupName, QMouseEvent* event) { if (event->button() == Qt::MouseButton::LeftButton) { - if (!IsGroupExpanded(groupNameId)) + if (!IsGroupExpanded(groupName)) { - ExpandGroup(groupNameId); + ExpandGroup(groupName); } else { - CollapseGroup(groupNameId); + CollapseGroup(groupName); } return; } @@ -236,8 +236,8 @@ namespace AtomToolsFramework if (event->button() == Qt::MouseButton::RightButton) { QMenu menu; - menu.addAction("Expand", [this, groupNameId]() { ExpandGroup(groupNameId); })->setEnabled(!IsGroupExpanded(groupNameId)); - menu.addAction("Collapse", [this, groupNameId]() { CollapseGroup(groupNameId); })->setEnabled(IsGroupExpanded(groupNameId)); + menu.addAction("Expand", [this, groupName]() { ExpandGroup(groupName); })->setEnabled(!IsGroupExpanded(groupName)); + menu.addAction("Collapse", [this, groupName]() { CollapseGroup(groupName); })->setEnabled(IsGroupExpanded(groupName)); menu.addAction("Expand All", [this]() { ExpandAll(); }); menu.addAction("Collapse All", [this]() { CollapseAll(); }); menu.exec(event->globalPos()); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 641cf63d04..0b14f9313f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -74,7 +74,7 @@ namespace AtomToolsFramework void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition) { propertyConfig.m_dataType = ConvertToEditableType(propertyDefinition.m_dataType); - propertyConfig.m_nameId = propertyDefinition.m_nameId; + propertyConfig.m_name = propertyDefinition.m_name; propertyConfig.m_displayName = propertyDefinition.m_displayName; propertyConfig.m_description = propertyDefinition.m_description; propertyConfig.m_defaultValue = ConvertToEditableType(propertyDefinition.m_value); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp index 0bdd6fb55c..a92bfdbcdb 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp @@ -227,19 +227,6 @@ namespace AtomToolsFramework { m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_cameraProps, event.m_deltaTime.count()); - - // if there has been an interpolation, only clear the look at point if it is no longer - // centered in the view (the camera has looked away from it) - if (m_lookAtAfterInterpolation.has_value()) - { - if (const float lookDirection = - (*m_lookAtAfterInterpolation - m_camera.Translation()).GetNormalized().Dot(m_camera.Transform().GetBasisY()); - !AZ::IsCloseMag(lookDirection, 1.0f, 0.001f)) - { - m_lookAtAfterInterpolation = {}; - } - } - m_modularCameraViewportContext->SetCameraTransform(m_referenceFrameOverride * m_camera.Transform()); } else if (m_cameraMode == CameraMode::Animation) @@ -277,16 +264,10 @@ namespace AtomToolsFramework m_updatingTransformInternally = false; } - void ModularViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance) + void ModularViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal) { m_cameraMode = CameraMode::Animation; m_cameraAnimation = CameraAnimation{ m_referenceFrameOverride * m_camera.Transform(), worldFromLocal, 0.0f }; - m_lookAtAfterInterpolation = worldFromLocal.GetTranslation() + worldFromLocal.GetBasisY() * lookAtDistance; - } - - AZStd::optional ModularViewportCameraControllerInstance::LookAtAfterInterpolation() const - { - return m_lookAtAfterInterpolation; } AZ::Transform ModularViewportCameraControllerInstance::GetReferenceFrame() const diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 2a15041e20..7192afebf7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -6,42 +6,23 @@ * */ -#include -#include -#include +#include #include #include -#include -#include -#include +#include #include #include #include #include +#include +#include +#include #include -#include #include -#include -#include -#include +#include #include - -static void OnInactiveViewportFrameRateChanged(const float& fpsLimit) -{ - AtomToolsFramework::RenderViewportWidgetNotificationBus::Broadcast( - &AtomToolsFramework::RenderViewportWidgetNotificationBus::Events::OnInactiveViewportFrameRateChanged, fpsLimit); -} - -AZ_CVAR( - float, - ed_inactive_viewport_fps_limit, - 0, - OnInactiveViewportFrameRateChanged, - AZ::ConsoleFunctorFlags::Null, - "The maximum framerate to render viewports that don't have focus at"); - -static constexpr const char* LastFocusedViewportVariableName = "AtomToolsFramework::RenderViewportWidget::LastFocusedViewport"; +#include namespace AtomToolsFramework { @@ -49,12 +30,6 @@ namespace AtomToolsFramework : QWidget(parent) , AzFramework::InputChannelEventListener(AzFramework::InputChannelEventListener::GetPriorityDefault()) { - m_lastFocusedViewport = AZ::Environment::FindVariable(LastFocusedViewportVariableName); - if (!m_lastFocusedViewport) - { - m_lastFocusedViewport = AZ::Environment::CreateVariable(LastFocusedViewportVariableName, nullptr); - } - if (shouldInitializeViewportContext) { InitializeViewportContext(); @@ -63,24 +38,13 @@ namespace AtomToolsFramework setUpdatesEnabled(false); setFocusPolicy(Qt::FocusPolicy::WheelFocus); setMouseTracking(true); - - // Wait a frame for our window handle to be constructed, then wire up our screen change signals. - QTimer::singleShot( - 0, - [this]() - { - QObject::connect(windowHandle(), &QWindow::screenChanged, this, &RenderViewportWidget::SetScreen); - }); - SetScreen(screen()); } bool RenderViewportWidget::InitializeViewportContext(AzFramework::ViewportId id) { if (m_viewportContext != nullptr) { - AZ_Assert( - id == AzFramework::InvalidViewportId || m_viewportContext->GetId() == id, - "Attempted to reinitialize RenderViewportWidget with a different ID"); + AZ_Assert(id == AzFramework::InvalidViewportId || m_viewportContext->GetId() == id, "Attempted to reinitialize RenderViewportWidget with a different ID"); return true; } @@ -95,7 +59,7 @@ namespace AtomToolsFramework // Before we do anything else, we must create a ViewportContext which will give us a ViewportId if we didn't manually specify one. AZ::RPI::ViewportContextRequestsInterface::CreationParameters params; params.device = AZ::RHI::RHISystemInterface::Get()->GetDevice(); - params.windowHandle = GetNativeWindowHandle(); + params.windowHandle = reinterpret_cast(winId()); params.id = id; AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle); m_viewportContext = viewportContextManager->CreateViewportContext(AZ::Name(), params); @@ -116,46 +80,29 @@ namespace AtomToolsFramework AzFramework::InputChannelEventListener::Connect(); AZ::TickBus::Handler::BusConnect(); AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle); - AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); - AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler::BusConnect(); m_inputChannelMapper = new AzToolsFramework::QtEventToAzInputMapper(this, id); // Forward input events to our controller list. - QObject::connect( - m_inputChannelMapper, &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, this, + QObject::connect(m_inputChannelMapper, &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, this, [this](const AzFramework::InputChannel* inputChannel, QEvent* event) - { - const AzFramework::NativeWindowHandle windowId = GetNativeWindowHandle(); - if (m_controllerList->HandleInputChannelEvent( - AzFramework::ViewportControllerInputEvent{ GetId(), windowId, *inputChannel })) - { - // If the controller handled the input event, mark the event as accepted so it doesn't continue to propagate. - if (event) - { - event->setAccepted(true); - } - } - }); - - // Update our target frame rate. If we're the only viewport, become active. - if (m_lastFocusedViewport.Get() == nullptr) { - m_lastFocusedViewport.Set(this); - } - UpdateFrameRate(); - + AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); + if (m_controllerList->HandleInputChannelEvent(AzFramework::ViewportControllerInputEvent{GetId(), windowId, *inputChannel})) + { + // If the controller handled the input event, mark the event as accepted so it doesn't continue to propagate. + if (event) + { + event->setAccepted(true); + } + } + }); return true; } RenderViewportWidget::~RenderViewportWidget() { - if (m_lastFocusedViewport.Get() == this) - { - m_lastFocusedViewport.Set(nullptr); - } - AzFramework::WindowRequestBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); AzFramework::InputChannelEventListener::Disconnect(); @@ -234,22 +181,17 @@ namespace AtomToolsFramework bool shouldConsumeEvent = true; - const bool eventHandled = m_controllerList->HandleInputChannelEvent({ GetId(), GetNativeWindowHandle(), inputChannel }); + AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); + const bool eventHandled = m_controllerList->HandleInputChannelEvent({GetId(), windowId, inputChannel}); - // If our controllers handled the event and it's one we can safely consume (i.e. it's not an Ended event that other viewports might - // need), consume it. + // If our controllers handled the event and it's one we can safely consume (i.e. it's not an Ended event that other viewports might need), consume it. return eventHandled && shouldConsumeEvent; } - void RenderViewportWidget::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint time) + void RenderViewportWidget::OnTick([[maybe_unused]]float deltaTime, AZ::ScriptTimePoint time) { m_time = time; - m_controllerList->UpdateViewport({ GetId(), AzFramework::FloatSeconds(deltaTime), m_time }); - } - - int RenderViewportWidget::GetTickOrder() - { - return AZ::ComponentTickBus::TICK_PRE_RENDER; + m_controllerList->UpdateViewport({GetId(), AzFramework::FloatSeconds(deltaTime), m_time}); } void RenderViewportWidget::resizeEvent([[maybe_unused]] QResizeEvent* event) @@ -277,75 +219,6 @@ namespace AtomToolsFramework m_mousePosition = event->localPos(); } - void RenderViewportWidget::focusInEvent([[maybe_unused]] QFocusEvent* event) - { - RenderViewportWidget* lastFocusedViewport = m_lastFocusedViewport.Get(); - if (lastFocusedViewport == this) - { - return; - } - - RenderViewportWidget* previousFocusWidget = lastFocusedViewport; - m_lastFocusedViewport.Set(this); - - // Ensure this viewport and whatever viewport last had focus (if any) respect - // the active / inactive viewport frame rate settings. - UpdateFrameRate(); - if (previousFocusWidget != nullptr) - { - previousFocusWidget->UpdateFrameRate(); - } - } - - void RenderViewportWidget::OnFrameRateLimitChanged([[maybe_unused]] float fpsLimit) - { - UpdateFrameRate(); - } - - void RenderViewportWidget::OnInactiveViewportFrameRateChanged([[maybe_unused]] float fpsLimit) - { - UpdateFrameRate(); - } - - AzFramework::NativeWindowHandle RenderViewportWidget::GetNativeWindowHandle() const - { - return reinterpret_cast(winId()); - } - - void RenderViewportWidget::UpdateFrameRate() - { - if (ed_inactive_viewport_fps_limit > 0.f && m_lastFocusedViewport.Get() != this) - { - m_viewportContext->SetFpsLimit(ed_inactive_viewport_fps_limit); - } - else - { - float fpsLimit = 0.f; - AZ::Render::Bootstrap::RequestBus::BroadcastResult(fpsLimit, &AZ::Render::Bootstrap::RequestBus::Events::GetFrameRateLimit); - m_viewportContext->SetFpsLimit(fpsLimit); - } - } - - void RenderViewportWidget::SetScreen(QScreen* screen) - { - if (m_screen != screen) - { - if (m_screen) - { - QObject::disconnect(m_screen, &QScreen::refreshRateChanged, this, &RenderViewportWidget::NotifyUpdateRefreshRate); - } - - if (screen) - { - QObject::connect(m_screen, &QScreen::refreshRateChanged, this, &RenderViewportWidget::NotifyUpdateRefreshRate); - } - - NotifyUpdateRefreshRate(); - - m_screen = screen; - } - } - void RenderViewportWidget::SendWindowResizeEvent() { // Scale the size by the DPI of the platform to @@ -353,14 +226,8 @@ namespace AtomToolsFramework const QSize uiWindowSize = size(); const QSize windowSize = uiWindowSize * devicePixelRatioF(); - AzFramework::WindowNotificationBus::Event( - GetNativeWindowHandle(), &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); - } - - void RenderViewportWidget::NotifyUpdateRefreshRate() - { - AzFramework::WindowNotificationBus::Event( - GetNativeWindowHandle(), &AzFramework::WindowNotificationBus::Events::OnRefreshRateChanged, GetDisplayRefreshRate()); + const AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); + AzFramework::WindowNotificationBus::Event(windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); } AZ::Name RenderViewportWidget::GetCurrentContextName() const @@ -418,7 +285,9 @@ namespace AtomToolsFramework // Build camera state from Atom camera transforms AzFramework::CameraState cameraState = AzFramework::CreateCameraFromWorldFromViewMatrix( - currentView->GetViewToWorldMatrix(), AZ::Vector2{ aznumeric_cast(width()), aznumeric_cast(height()) }); + currentView->GetViewToWorldMatrix(), + AZ::Vector2{aznumeric_cast(width()), aznumeric_cast(height())} + ); AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, currentView->GetViewToClipMatrix()); // Convert from Z-up @@ -430,7 +299,8 @@ namespace AtomToolsFramework AzFramework::ScreenPoint RenderViewportWidget::ViewportWorldToScreen(const AZ::Vector3& worldPosition) { - if (AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView(); currentView == nullptr) + if (AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView(); + currentView == nullptr) { return AzFramework::ScreenPoint(0, 0); } @@ -443,10 +313,12 @@ namespace AtomToolsFramework const auto& cameraProjection = m_viewportContext->GetCameraProjectionMatrix(); const auto& cameraView = m_viewportContext->GetCameraViewMatrix(); - const AZ::Vector4 normalizedScreenPosition{ screenPosition.m_x * 2.f / width() - 1.0f, - (height() - screenPosition.m_y) * 2.f / height() - 1.0f, - 1.f - depth, // [GFX TODO] [ATOM-1501] Currently we always assume reverse depth - 1.f }; + const AZ::Vector4 normalizedScreenPosition { + screenPosition.m_x * 2.f / width() - 1.0f, + (height() - screenPosition.m_y) * 2.f / height() - 1.0f, + 1.f - depth, // [GFX TODO] [ATOM-1501] Currently we always assume reverse depth + 1.f + }; AZ::Matrix4x4 worldFromScreen = cameraProjection * cameraView; worldFromScreen.InvertFull(); @@ -475,7 +347,7 @@ namespace AtomToolsFramework AZ::Vector3 rayDirection = pos1.value() - pos0.value(); rayDirection.Normalize(); - return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{ rayOrigin, rayDirection }; + return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{rayOrigin, rayDirection}; } float RenderViewportWidget::DeviceScalingFactor() @@ -505,12 +377,12 @@ namespace AtomToolsFramework AzFramework::WindowSize RenderViewportWidget::GetClientAreaSize() const { - return AzFramework::WindowSize{ aznumeric_cast(width()), aznumeric_cast(height()) }; + return AzFramework::WindowSize{aznumeric_cast(width()), aznumeric_cast(height())}; } void RenderViewportWidget::ResizeClientArea(AzFramework::WindowSize clientAreaSize) { - const QSize targetSize = QSize{ aznumeric_cast(clientAreaSize.m_width), aznumeric_cast(clientAreaSize.m_height) }; + const QSize targetSize = QSize{aznumeric_cast(clientAreaSize.m_width), aznumeric_cast(clientAreaSize.m_height)}; resize(targetSize); } @@ -520,7 +392,7 @@ namespace AtomToolsFramework return false; } - void RenderViewportWidget::SetFullScreenState([[maybe_unused]] bool fullScreenState) + void RenderViewportWidget::SetFullScreenState([[maybe_unused]]bool fullScreenState) { // The RenderViewportWidget does not currently support full screen. } @@ -543,20 +415,11 @@ namespace AtomToolsFramework uint32_t RenderViewportWidget::GetDisplayRefreshRate() const { - return static_cast(screen()->refreshRate()); + return 60; } uint32_t RenderViewportWidget::GetSyncInterval() const { - uint32_t interval = 1; - - // Get vsync_interval from AzFramework::NativeWindow, which owns it. - // NativeWindow also handles broadcasting OnVsyncIntervalChanged to all - // WindowNotificationBus listeners. - if (auto console = AZ::Interface::Get()) - { - console->GetCvarValue("vsync_interval", interval); - } - return interval; + return 1; } -} // namespace AtomToolsFramework +} //namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index a24b45179f..3d4bb82eec 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -28,7 +28,6 @@ set(FILES Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h - Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindow.h diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowSettings.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowSettings.h index dd42f79106..c56da58ff1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowSettings.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowSettings.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #endif diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index d032f35e38..17e292ac16 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -59,7 +59,7 @@ namespace MaterialEditor return &m_materialTypeSourceData; } - const AZStd::any& MaterialDocument::GetPropertyValue(const AZ::Name& propertyFullName) const + const AZStd::any& MaterialDocument::GetPropertyValue(const AZ::Name& propertyId) const { using namespace AZ; using namespace RPI; @@ -70,10 +70,10 @@ namespace MaterialEditor return m_invalidValue; } - const auto it = m_properties.find(propertyFullName); + const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr()); + AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); return m_invalidValue; } @@ -81,7 +81,7 @@ namespace MaterialEditor return property.GetValue(); } - const AtomToolsFramework::DynamicProperty& MaterialDocument::GetProperty(const AZ::Name& propertyFullName) const + const AtomToolsFramework::DynamicProperty& MaterialDocument::GetProperty(const AZ::Name& propertyId) const { if (!IsOpen()) { @@ -89,10 +89,10 @@ namespace MaterialEditor return m_invalidProperty; } - const auto it = m_properties.find(propertyFullName); + const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr()); + AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); return m_invalidProperty; } @@ -118,7 +118,7 @@ namespace MaterialEditor return it->second; } - void MaterialDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) + void MaterialDocument::SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) { using namespace AZ; using namespace RPI; @@ -129,10 +129,10 @@ namespace MaterialEditor return; } - const auto it = m_properties.find(propertyFullName); + const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr()); + AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); return; } @@ -143,8 +143,7 @@ namespace MaterialEditor AtomToolsFramework::DynamicProperty& property = it->second; property.SetValue(AtomToolsFramework::ConvertToEditableType(propertyValue)); - const AZ::RPI::MaterialPropertyId propertyId = AZ::RPI::MaterialPropertyId::Parse(propertyFullName.GetStringView()); - const auto propertyIndex = m_materialInstance->FindPropertyIndex(propertyFullName); + const auto propertyIndex = m_materialInstance->FindPropertyIndex(propertyId); if (!propertyIndex.IsNull()) { if (m_materialInstance->SetPropertyValue(propertyIndex, propertyValue)) @@ -593,8 +592,9 @@ namespace MaterialEditor bool result = true; // populate sourceData with properties that meet the filter - m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) { - const MaterialPropertyId propertyId(groupNameId, propertyNameId); + m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { + + const MaterialPropertyId propertyId(groupName, propertyName); const auto it = m_properties.find(propertyId.GetFullName()); if (it != m_properties.end() && propertyFilter(it->second)) @@ -609,7 +609,7 @@ namespace MaterialEditor return false; } - sourceData.m_properties[groupNameId][propertyNameId].m_value = propertyValue; + sourceData.m_properties[groupName][propertyName].m_value = propertyValue; } } return true; @@ -770,11 +770,11 @@ namespace MaterialEditor // Populate the property map from a combination of source data and assets // Assets must still be used for now because they contain the final accumulated value after all other materials // in the hierarchy are applied - m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) { + m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { AtomToolsFramework::DynamicPropertyConfig propertyConfig; // Assign id before conversion so it can be used in dynamic description - propertyConfig.m_id = MaterialPropertyId(groupNameId, propertyNameId).GetCStr(); + propertyConfig.m_id = MaterialPropertyId(groupName, propertyName).GetCStr(); const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id); const bool propertyIndexInBounds = propertyIndex.IsValid() && propertyIndex.GetIndex() < m_materialAsset->GetPropertyValues().size(); @@ -786,8 +786,8 @@ namespace MaterialEditor propertyConfig.m_showThumbnail = true; propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]); propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(parentPropertyValues[propertyIndex.GetIndex()]); - auto groupDefinition = m_materialTypeSourceData.FindGroup(groupNameId); - propertyConfig.m_groupName = groupDefinition ? groupDefinition->m_displayName : groupNameId; + auto groupDefinition = m_materialTypeSourceData.FindGroup(groupName); + propertyConfig.m_groupName = groupDefinition ? groupDefinition->m_displayName : groupName; m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig); } return true; @@ -796,7 +796,7 @@ namespace MaterialEditor // Populate the property group visibility map for (MaterialTypeSourceData::GroupDefinition& group : m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder()) { - m_propertyGroupVisibility[AZ::Name{group.m_nameId}] = true; + m_propertyGroupVisibility[AZ::Name{group.m_name}] = true; } // Adding properties for material type and parent as part of making dynamic @@ -808,7 +808,7 @@ namespace MaterialEditor AtomToolsFramework::DynamicPropertyConfig propertyConfig; propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset; propertyConfig.m_id = "overview.materialType"; - propertyConfig.m_nameId = "materialType"; + propertyConfig.m_name = "materialType"; propertyConfig.m_displayName = "Material Type"; propertyConfig.m_groupName = "Overview"; propertyConfig.m_description = "The material type defines the layout, properties, default values, shader connections, and other " @@ -823,7 +823,7 @@ namespace MaterialEditor propertyConfig = {}; propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset; propertyConfig.m_id = "overview.parentMaterial"; - propertyConfig.m_nameId = "parentMaterial"; + propertyConfig.m_name = "parentMaterial"; propertyConfig.m_displayName = "Parent Material"; propertyConfig.m_groupName = "Overview"; propertyConfig.m_description = @@ -846,7 +846,7 @@ namespace MaterialEditor propertyConfig = {}; propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::String; propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput).GetCStr(); - propertyConfig.m_nameId = shaderInput; + propertyConfig.m_name = shaderInput; propertyConfig.m_displayName = shaderInput; propertyConfig.m_groupName = "UV Sets"; propertyConfig.m_description = shaderInput; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index d732680b7b..03997a2a91 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -43,10 +43,10 @@ namespace MaterialEditor //////////////////////////////////////////////////////////////////////// // AtomToolsFramework::AtomToolsDocument //////////////////////////////////////////////////////////////////////// - const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; - const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; + const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override; + const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; - void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; + void SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; bool Reopen() override; bool Save() override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 7edff11174..6d6fd377e3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -182,7 +182,9 @@ namespace MaterialEditor AZ_Error("MaterialViewportRenderer", m_shadowCatcherMaterial != nullptr, "Could not create shadow catcher material."); AZ::Render::MaterialAssignmentMap shadowCatcherMaterials; - shadowCatcherMaterials[AZ::Render::DefaultMaterialAssignmentId].m_materialInstance = m_shadowCatcherMaterial; + auto& shadowCatcherMaterialAssignment = shadowCatcherMaterials[AZ::Render::DefaultMaterialAssignmentId]; + shadowCatcherMaterialAssignment.m_materialInstance = m_shadowCatcherMaterial; + shadowCatcherMaterialAssignment.m_materialInstancePreCreated = true; AZ::Render::MaterialComponentRequestBus::Event(m_shadowCatcherEntity->GetId(), &AZ::Render::MaterialComponentRequestBus::Events::SetMaterialOverrides, shadowCatcherMaterials); @@ -291,7 +293,9 @@ namespace MaterialEditor MaterialDocumentRequestBus::EventResult(materialInstance, documentId, &MaterialDocumentRequestBus::Events::GetInstance); AZ::Render::MaterialAssignmentMap materials; - materials[AZ::Render::DefaultMaterialAssignmentId].m_materialInstance = materialInstance; + auto& materialAssignment = materials[AZ::Render::DefaultMaterialAssignmentId]; + materialAssignment.m_materialInstance = materialInstance; + materialAssignment.m_materialInstancePreCreated = true; AZ::Render::MaterialComponentRequestBus::Event(m_modelEntity->GetId(), &AZ::Render::MaterialComponentRequestBus::Events::SetMaterialOverrides, materials); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp index 28d7d3d3f5..df0b179dc1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp @@ -44,20 +44,20 @@ namespace MaterialEditor AtomToolsFramework::InspectorWidget::Reset(); } - bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const + bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupName) const { - auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId)); + auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupName)); return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end(); } - void MaterialInspector::OnGroupExpanded(const AZStd::string& groupNameId) + void MaterialInspector::OnGroupExpanded(const AZStd::string& groupName) { - m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId)); + m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupName)); } - void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupNameId) + void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupName) { - m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId)); + m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupName)); } void MaterialInspector::OnDocumentOpened(const AZ::Uuid& documentId) @@ -86,9 +86,9 @@ namespace MaterialEditor AddGroupsEnd(); } - AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const + AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupName) const { - return AZ::Crc32(AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupNameId.c_str())); + return AZ::Crc32(AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupName.c_str())); } bool MaterialInspector::CompareInstanceNodeProperties( @@ -105,10 +105,10 @@ namespace MaterialEditor MaterialDocumentRequestBus::EventResult( materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData); - const AZStd::string groupNameId = "overview"; + const AZStd::string groupName = "overview"; const AZStd::string groupDisplayName = "Overview"; const AZStd::string groupDescription = materialTypeSourceData->m_description; - auto& group = m_groups[groupNameId]; + auto& group = m_groups[groupName]; AtomToolsFramework::DynamicProperty property; AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( @@ -122,9 +122,9 @@ namespace MaterialEditor // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId), + &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName), [this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); }); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } void MaterialInspector::AddUvNamesGroup() @@ -132,10 +132,10 @@ namespace MaterialEditor AZ::Data::Asset materialAsset; MaterialDocumentRequestBus::EventResult(materialAsset, m_documentId, &MaterialDocumentRequestBus::Events::GetAsset); - const AZStd::string groupNameId = UvGroupName; + const AZStd::string groupName = UvGroupName; const AZStd::string groupDisplayName = "UV Sets"; const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model."; - auto& group = m_groups[groupNameId]; + auto& group = m_groups[groupName]; const auto& uvNameMap = materialAsset->GetMaterialTypeAsset()->GetUvNameMap(); group.m_properties.reserve(uvNameMap.size()); @@ -145,7 +145,7 @@ namespace MaterialEditor AtomToolsFramework::DynamicProperty property; AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, - AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName()); + AZ::RPI::MaterialPropertyId(groupName, uvNamePair.m_shaderInput.ToString()).GetFullName()); group.m_properties.push_back(property); property.SetValue(property.GetConfig().m_parentValue); @@ -153,9 +153,9 @@ namespace MaterialEditor // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId), + &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName), [this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); }); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } void MaterialInspector::AddPropertiesGroup() @@ -166,14 +166,14 @@ namespace MaterialEditor for (const auto& groupDefinition : materialTypeSourceData->GetGroupDefinitionsInDisplayOrder()) { - const AZStd::string& groupNameId = groupDefinition.m_nameId; - const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId; + const AZStd::string& groupName = groupDefinition.m_name; + const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupName; const AZStd::string& groupDescription = !groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName; - auto& group = m_groups[groupNameId]; + auto& group = m_groups[groupName]; const auto& propertyLayout = materialTypeSourceData->m_propertyLayout; - const auto& propertyListItr = propertyLayout.m_properties.find(groupNameId); + const auto& propertyListItr = propertyLayout.m_properties.find(groupName); if (propertyListItr != propertyLayout.m_properties.end()) { group.m_properties.reserve(propertyListItr->second.size()); @@ -182,21 +182,21 @@ namespace MaterialEditor AtomToolsFramework::DynamicProperty property; AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, - AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName()); + AZ::RPI::MaterialPropertyId(groupName, propertyDefinition.m_name).GetFullName()); group.m_properties.push_back(property); } } // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId), + &group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName), [this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); }); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); bool isGroupVisible = false; AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( - isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId}); - SetGroupVisible(groupNameId, isGroupVisible); + isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupName}); + SetGroupVisible(groupName, isGroupVisible); } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h index 845a8cb0f7..dedcd79f5e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h @@ -37,12 +37,12 @@ namespace MaterialEditor void Reset() override; protected: - bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override; - void OnGroupExpanded(const AZStd::string& groupNameId) override; - void OnGroupCollapsed(const AZStd::string& groupNameId) override; + bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const override; + void OnGroupExpanded(const AZStd::string& groupName) override; + void OnGroupCollapsed(const AZStd::string& groupName) override; private: - AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const; + AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupName) const; bool CompareInstanceNodeProperties( const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) const; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index c7d4b195a3..2a061a2ed6 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -35,26 +35,26 @@ namespace MaterialEditor void SettingsWidget::AddDocumentSettingsGroup() { - const AZStd::string groupNameId = "documentSettings"; + const AZStd::string groupName = "documentSettings"; const AZStd::string groupDisplayName = "Document Settings"; const AZStd::string groupDescription = "Document Settings"; const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSettingsGroup")); AddGroup( - groupNameId, groupDisplayName, groupDescription, + groupName, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); } void SettingsWidget::AddDocumentSystemSettingsGroup() { - const AZStd::string groupNameId = "documentSystemSettings"; + const AZStd::string groupName = "documentSystemSettings"; const AZStd::string groupDisplayName = "Document System Settings"; const AZStd::string groupDescription = "Document System Settings"; const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); AddGroup( - groupNameId, groupDisplayName, groupDescription, + groupName, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp index 04c53457ae..a00d3eec05 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp @@ -54,19 +54,19 @@ namespace MaterialEditor void ViewportSettingsInspector::AddGeneralGroup() { - const AZStd::string groupNameId = "generalSettings"; + const AZStd::string groupName = "generalSettings"; const AZStd::string groupDisplayName = "General Settings"; const AZStd::string groupDescription = "General Settings"; AddGroup( - groupNameId, groupDisplayName, groupDescription, + groupName, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( - m_viewportSettings.get(), nullptr, m_viewportSettings->TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId))); + m_viewportSettings.get(), nullptr, m_viewportSettings->TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName))); } void ViewportSettingsInspector::AddModelGroup() { - const AZStd::string groupNameId = "modelSettings"; + const AZStd::string groupName = "modelSettings"; const AZStd::string groupDisplayName = "Model Settings"; const AZStd::string groupDescription = "Model Settings"; @@ -94,12 +94,12 @@ namespace MaterialEditor if (m_modelPreset) { auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget, GetGroupSaveStateKey(groupNameId)); + m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget, GetGroupSaveStateKey(groupName)); groupWidget->layout()->addWidget(inspectorWidget); } - AddGroup(groupNameId, groupDisplayName, groupDescription, groupWidget); + AddGroup(groupName, groupDisplayName, groupDescription, groupWidget); } void ViewportSettingsInspector::AddModelPreset() @@ -153,7 +153,7 @@ namespace MaterialEditor void ViewportSettingsInspector::AddLightingGroup() { - const AZStd::string groupNameId = "lightingSettings"; + const AZStd::string groupName = "lightingSettings"; const AZStd::string groupDisplayName = "Lighting Settings"; const AZStd::string groupDescription = "Lighting Settings"; @@ -182,12 +182,12 @@ namespace MaterialEditor { auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), this, groupWidget, - GetGroupSaveStateKey(groupNameId)); + GetGroupSaveStateKey(groupName)); groupWidget->layout()->addWidget(inspectorWidget); } - AddGroup(groupNameId, groupDisplayName, groupDescription, groupWidget); + AddGroup(groupName, groupDisplayName, groupDescription, groupWidget); } void ViewportSettingsInspector::AddLightingPreset() @@ -355,25 +355,25 @@ namespace MaterialEditor return savePath; } - AZ::Crc32 ViewportSettingsInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const + AZ::Crc32 ViewportSettingsInspector::GetGroupSaveStateKey(const AZStd::string& groupName) const { - return AZ::Crc32(AZStd::string::format("ViewportSettingsInspector::PropertyGroup::%s", groupNameId.c_str())); + return AZ::Crc32(AZStd::string::format("ViewportSettingsInspector::PropertyGroup::%s", groupName.c_str())); } - bool ViewportSettingsInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const + bool ViewportSettingsInspector::ShouldGroupAutoExpanded(const AZStd::string& groupName) const { - auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId)); + auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupName)); return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end(); } - void ViewportSettingsInspector::OnGroupExpanded(const AZStd::string& groupNameId) + void ViewportSettingsInspector::OnGroupExpanded(const AZStd::string& groupName) { - m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId)); + m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupName)); } - void ViewportSettingsInspector::OnGroupCollapsed(const AZStd::string& groupNameId) + void ViewportSettingsInspector::OnGroupCollapsed(const AZStd::string& groupName) { - m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId)); + m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupName)); } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h index d1cd7a7cf3..6299ddb1f2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h @@ -75,10 +75,10 @@ namespace MaterialEditor AZStd::string GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const; - AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const; - bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override; - void OnGroupExpanded(const AZStd::string& groupNameId) override; - void OnGroupCollapsed(const AZStd::string& groupNameId) override; + AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupName) const; + bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const override; + void OnGroupExpanded(const AZStd::string& groupName) override; + void OnGroupCollapsed(const AZStd::string& groupName) override; AZ::Render::ModelPresetPtr m_modelPreset; AZ::Render::LightingPresetPtr m_lightingPreset; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetCollectionAsyncLoader.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetCollectionAsyncLoader.h index 2d05a68771..d1027daa36 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetCollectionAsyncLoader.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/AssetCollectionAsyncLoader.h @@ -7,6 +7,7 @@ */ #pragma once +#include #include #include #include diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index bf356fa4b5..7d659ebb7a 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -183,15 +183,6 @@ namespace AZ::Render DrawFramerate(); } - void AtomViewportDisplayInfoSystemComponent::OnFrameEnd() - { - auto currentTime = AZStd::chrono::system_clock::now(); - if (!m_fpsHistory.empty()) - { - m_fpsHistory.back().m_endFrameTime = currentTime; - } - } - AtomBridge::ViewportInfoDisplayState AtomViewportDisplayInfoSystemComponent::GetDisplayState() const { return aznumeric_cast(r_displayInfo.operator int()); @@ -257,11 +248,11 @@ namespace AZ::Render void AtomViewportDisplayInfoSystemComponent::UpdateFramerate() { auto currentTime = AZStd::chrono::system_clock::now(); - while (!m_fpsHistory.empty() && (currentTime - m_fpsHistory.front().m_beginFrameTime) > m_fpsInterval) + while (!m_fpsHistory.empty() && (currentTime - m_fpsHistory.front()) > m_fpsInterval) { m_fpsHistory.pop_front(); } - m_fpsHistory.push_back(FrameTimingInfo(currentTime)); + m_fpsHistory.push_back(currentTime); } void AtomViewportDisplayInfoSystemComponent::DrawFramerate() @@ -270,31 +261,25 @@ namespace AZ::Render double minFPS = DBL_MAX; double maxFPS = 0; AZStd::chrono::duration deltaTime; - AZStd::chrono::milliseconds totalFrameMS(0); for (const auto& time : m_fpsHistory) { if (lastTime.has_value()) { - deltaTime = time.m_beginFrameTime - lastTime.value(); + deltaTime = time - lastTime.value(); double fps = AZStd::chrono::seconds(1) / deltaTime; minFPS = AZStd::min(minFPS, fps); maxFPS = AZStd::max(maxFPS, fps); } - lastTime = time.m_beginFrameTime; - - if (time.m_endFrameTime.has_value()) - { - totalFrameMS += time.m_endFrameTime.value() - time.m_beginFrameTime; - } + lastTime = time; } double averageFPS = 0; double averageFrameMs = 0; if (m_fpsHistory.size() > 1) { - deltaTime = m_fpsHistory.back().m_beginFrameTime - m_fpsHistory.front().m_beginFrameTime; - averageFPS = AZStd::chrono::seconds(m_fpsHistory.size() - 1) / deltaTime; - averageFrameMs = aznumeric_cast(totalFrameMS.count()) / (m_fpsHistory.size() - 1); + deltaTime = m_fpsHistory.back() - m_fpsHistory.front(); + averageFPS = AZStd::chrono::seconds(m_fpsHistory.size()) / deltaTime; + averageFrameMs = 1000.0f/averageFPS; } const double frameIntervalSeconds = m_fpsInterval.count(); @@ -303,7 +288,7 @@ namespace AZ::Render AZStd::string::format( "FPS %.1f [%.0f..%.0f], %.1fms/frame, avg over %.1fs", averageFPS, - minFPS == DBL_MAX ? 0.0 : minFPS, + minFPS, maxFPS, averageFrameMs, frameIntervalSeconds), diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h index 689cfdb43b..1d53e188d0 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -45,7 +45,6 @@ namespace AZ // AZ::RPI::ViewportContextNotificationBus::Handler overrides... void OnRenderTick() override; - void OnFrameEnd() override; // AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler overrides... AtomBridge::ViewportInfoDisplayState GetDisplayState() const override; @@ -62,8 +61,6 @@ namespace AZ void DrawPassInfo(); void DrawFramerate(); - void UpdateScene(AZ::RPI::ScenePtr scene); - static constexpr float BaseFontSize = 0.7f; AZStd::string m_rendererDescription; @@ -71,17 +68,7 @@ namespace AZ AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr; float m_lineSpacing; AZStd::chrono::duration m_fpsInterval = AZStd::chrono::seconds(1); - struct FrameTimingInfo - { - AZStd::chrono::system_clock::time_point m_beginFrameTime; - AZStd::optional m_endFrameTime; - - explicit FrameTimingInfo(AZStd::chrono::system_clock::time_point beginFrameTime) - : m_beginFrameTime(beginFrameTime) - { - } - }; - AZStd::deque m_fpsHistory; + AZStd::deque m_fpsHistory; AZStd::optional m_lastMemoryUpdate; bool m_updateRootPassQuery = true; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index ace16ba6ca..ed7f1564ac 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -151,7 +151,9 @@ namespace AZ //! Returns the list of all ModelMaterialSlot's for the model, across all LODs. virtual RPI::ModelMaterialSlotMap GetModelMaterialSlots() const = 0; + //! Returns the available, overridable material slots and the default assigned materials virtual MaterialAssignmentMap GetMaterialAssignments() const = 0; + virtual AZStd::unordered_set GetModelUvNames() const = 0; }; using MaterialReceiverRequestBus = EBus; @@ -161,6 +163,7 @@ namespace AZ : public ComponentBus { public: + //! Notification that overridable material slots are available or have changed virtual void OnMaterialAssignmentsChanged() = 0; }; using MaterialReceiverNotificationBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index a3152faf87..8aec91616b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -88,6 +88,12 @@ namespace AZ AZ::Data::AssetId materialAssetId = {}; MaterialComponentRequestBus::EventResult( materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + if (!materialAssetId.IsValid()) + { + MaterialComponentRequestBus::EventResult( + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, + m_materialAssignmentId); + } if (!materialAssetId.IsValid()) { @@ -169,7 +175,7 @@ namespace AZ void MaterialPropertyInspector::AddDetailsGroup() { - const AZStd::string& groupNameId = "Details"; + const AZStd::string& groupName = "Details"; const AZStd::string& groupDisplayName = "Details"; const AZStd::string& groupDescription = ""; @@ -235,15 +241,15 @@ namespace AZ propertyGroupContainer->layout()->addWidget(materialInfoWidget); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupContainer); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupContainer); } void MaterialPropertyInspector::AddUvNamesGroup() { - const AZStd::string groupNameId = AZ::RPI::UvGroupName; + const AZStd::string groupName = AZ::RPI::UvGroupName; const AZStd::string groupDisplayName = "UV Sets"; const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model."; - auto& group = m_groups[groupNameId]; + auto& group = m_groups[groupName]; const RPI::MaterialUvNameMap& uvNameMap = m_editData.m_materialAsset->GetMaterialTypeAsset()->GetUvNameMap(); group.m_properties.reserve(uvNameMap.size()); @@ -257,8 +263,8 @@ namespace AZ propertyConfig = {}; propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::String; - propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInputStr).GetCStr(); - propertyConfig.m_nameId = shaderInputStr; + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInputStr).GetCStr(); + propertyConfig.m_name = shaderInputStr; propertyConfig.m_displayName = shaderInputStr; propertyConfig.m_groupName = groupDisplayName; propertyConfig.m_description = shaderInputStr; @@ -271,8 +277,8 @@ namespace AZ // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId)); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); + &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupName)); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } void MaterialPropertyInspector::Populate() @@ -285,13 +291,13 @@ namespace AZ // Copy all of the properties from the material asset to the source data that will be exported for (const auto& groupDefinition : m_editData.m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder()) { - const AZStd::string& groupNameId = groupDefinition.m_nameId; - const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId; + const AZStd::string& groupName = groupDefinition.m_name; + const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupName; const AZStd::string& groupDescription = !groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName; - auto& group = m_groups[groupNameId]; + auto& group = m_groups[groupName]; const auto& propertyLayout = m_editData.m_materialTypeSourceData.m_propertyLayout; - const auto& propertyListItr = propertyLayout.m_properties.find(groupNameId); + const auto& propertyListItr = propertyLayout.m_properties.find(groupName); if (propertyListItr != propertyLayout.m_properties.end()) { group.m_properties.reserve(propertyListItr->second.size()); @@ -300,7 +306,7 @@ namespace AZ AtomToolsFramework::DynamicPropertyConfig propertyConfig; // Assign id before conversion so it can be used in dynamic description - propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName(); + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, propertyDefinition.m_name).GetFullName(); AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition); @@ -316,8 +322,8 @@ namespace AZ // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId)); - AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); + &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupName)); + AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget); } AddGroupsEnd(); @@ -496,11 +502,11 @@ namespace AZ } } - AZ::Crc32 MaterialPropertyInspector::GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const + AZ::Crc32 MaterialPropertyInspector::GetSaveStateKeyForGroup(const AZStd::string& groupName) const { return AZ::Crc32(AZStd::string::format( "MaterialPropertyInspector::PropertyGroup::%s::%s", m_editData.m_materialAssetId.ToString().c_str(), - groupNameId.c_str())); + groupName.c_str())); } bool MaterialPropertyInspector::AreNodePropertyValuesEqual( @@ -728,11 +734,16 @@ namespace AZ void MaterialPropertyInspector::UpdateUI() { - AZ::Data::AssetId assetId; + AZ::Data::AssetId materialAssetId = {}; MaterialComponentRequestBus::EventResult( - assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + if (!materialAssetId.IsValid()) + { + MaterialComponentRequestBus::EventResult( + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_materialAssignmentId); + } - if (IsLoaded() && m_editData.m_materialAssetId == assetId) + if (IsLoaded() && m_editData.m_materialAssetId == materialAssetId) { LoadOverridesFromEntity(); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h index 11eb2cec51..d3142ddc95 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h @@ -100,7 +100,7 @@ namespace AZ void RunEditorMaterialFunctors(); void UpdateMaterialInstanceProperty(const AtomToolsFramework::DynamicProperty& property); - AZ::Crc32 GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const; + AZ::Crc32 GetSaveStateKeyForGroup(const AZStd::string& groupName) const; static bool AreNodePropertyValuesEqual( const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index c4d21ba599..f5d38f48c4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -118,10 +118,16 @@ namespace AZ } }; + AZ::Data::AssetId EditorMaterialComponentSlot::GetActiveAssetId() const + { + return m_materialAsset.GetId().IsValid() ? m_materialAsset.GetId() : GetDefaultAssetId(); + } + AZ::Data::AssetId EditorMaterialComponentSlot::GetDefaultAssetId() const { AZ::Data::AssetId assetId; - MaterialComponentRequestBus::EventResult(assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id); + MaterialComponentRequestBus::EventResult( + assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id); return assetId; } @@ -135,7 +141,7 @@ namespace AZ bool EditorMaterialComponentSlot::HasSourceData() const { // The slot only has valid source data if the source path is valid and the file has the correct extension - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); + const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId()); return !sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } @@ -220,7 +226,7 @@ namespace AZ void EditorMaterialComponentSlot::OpenMaterialEditor() const { - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); + const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId()); if (!sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) { EditorMaterialSystemComponentRequestBus::Broadcast( @@ -236,7 +242,7 @@ namespace AZ void EditorMaterialComponentSlot::OpenUvNameMapInspector() { - if (m_materialAsset.GetId().IsValid()) + if (GetActiveAssetId().IsValid()) { AZStd::unordered_set modelUvNames; MaterialReceiverRequestBus::EventResult(modelUvNames, m_entityId, &MaterialReceiverRequestBus::Events::GetModelUvNames); @@ -252,7 +258,7 @@ namespace AZ }; if (EditorMaterialComponentInspector::OpenInspectorDialog( - m_materialAsset.GetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback)) + GetActiveAssetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback)) { OnDataChanged(); } @@ -274,10 +280,10 @@ namespace AZ action->setEnabled(HasSourceData()); action = menu.addAction("Edit Material Instance...", [this]() { OpenMaterialInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(GetActiveAssetId().IsValid()); action = menu.addAction("Edit Material Instance UV Map...", [this]() { OpenUvNameMapInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(GetActiveAssetId().IsValid()); menu.addSeparator(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h index 01e357f1bb..377fe9a18b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h @@ -30,6 +30,7 @@ namespace AZ static void Reflect(ReflectContext* context); static bool ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); + AZ::Data::AssetId GetActiveAssetId() const; AZ::Data::AssetId GetDefaultAssetId() const; AZStd::string GetLabel() const; bool HasSourceData() const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp index e7059ccdf7..070c42fd7c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp @@ -137,8 +137,8 @@ namespace AZ // Copy all of the properties from the material asset to the source data that will be exported result = true; - editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) { - const AZ::RPI::MaterialPropertyId propertyId(groupNameId, propertyNameId); + editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) { + const AZ::RPI::MaterialPropertyId propertyId(groupName, propertyName); const AZ::RPI::MaterialPropertyIndex propertyIndex = editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName()); @@ -170,7 +170,7 @@ namespace AZ return true; } - exportData.m_properties[groupNameId][propertyDefinition.m_nameId].m_value = propertyValue; + exportData.m_properties[groupName][propertyDefinition.m_name].m_value = propertyValue; return true; }); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp index 91b519a06b..64bc54bae8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp @@ -81,7 +81,7 @@ namespace AZ { AddGroupsBegin(); - const AZStd::string groupNameId = "ModelUvMap"; + const AZStd::string groupName = "ModelUvMap"; const AZStd::string groupDisplayName = "Material to Model UV Map"; const AZStd::string groupDescription = "Custom map that maps a UV name from the material to one from the model."; @@ -96,8 +96,8 @@ namespace AZ const AZStd::string materialUvName = m_materialUvNames[i].m_uvName.GetStringView(); propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Enum; - propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInput).GetFullName(); - propertyConfig.m_nameId = shaderInput; + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInput).GetFullName(); + propertyConfig.m_name = shaderInput; propertyConfig.m_displayName = materialUvName; propertyConfig.m_description = shaderInput; propertyConfig.m_defaultValue = 0u; @@ -108,7 +108,7 @@ namespace AZ m_group.m_properties.back().SetValue(AZStd::any(m_modelUvNameIndices[i])); } - AddGroup(groupNameId, groupDisplayName, groupDescription, + AddGroup(groupName, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget(&m_group, nullptr, m_group.TYPEINFO_Uuid(), this)); AddGroupsEnd(); @@ -238,7 +238,7 @@ namespace AZ ResetModelUvNameIndices(); - const AZStd::string groupNameId = "ModelUvMap"; + const AZStd::string groupName = "ModelUvMap"; size_t uvSize = m_materialUvNames.size(); for (size_t i = 0u; i < uvSize; ++i) @@ -248,8 +248,8 @@ namespace AZ const AZStd::string materialUvName = m_materialUvNames[i].m_uvName.GetStringView(); propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Enum; - propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInput).GetFullName(); - propertyConfig.m_nameId = shaderInput; + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInput).GetFullName(); + propertyConfig.m_name = shaderInput; propertyConfig.m_displayName = materialUvName; propertyConfig.m_description = shaderInput; propertyConfig.m_defaultValue = 0u; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index bd148c8ba4..4c26042a26 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -111,12 +111,14 @@ namespace AZ m_queuedMaterialUpdateNotification = false; MaterialComponentRequestBus::Handler::BusConnect(m_entityId); + MaterialReceiverNotificationBus::Handler::BusConnect(m_entityId); LoadMaterials(); } void MaterialComponentController::Deactivate() { MaterialComponentRequestBus::Handler::BusDisconnect(); + MaterialReceiverNotificationBus::Handler::BusDisconnect(); TickBus::Handler::BusDisconnect(); ReleaseMaterials(); @@ -146,56 +148,26 @@ namespace AZ void MaterialComponentController::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { - AZStd::unordered_set propertyOverrides; - AZStd::swap(m_queuedPropertyOverrides, propertyOverrides); + AZStd::unordered_set materialsWithDirtyProperties; + AZStd::swap(m_materialsWithDirtyProperties, materialsWithDirtyProperties); // Iterate through all MaterialAssignmentId's that have property overrides and attempt to apply them // if material instance is already compiling, delay application of property overrides until next frame - for (const auto& materialAssignmentId : propertyOverrides) + for (const auto& materialAssignmentId : materialsWithDirtyProperties) { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) + if (materialIt != m_configuration.m_materials.end()) { - //Skip materials that do not exist in the map - continue; - } - - auto materialInstance = materialIt->second.m_materialInstance; - if (!materialInstance) - { - //Skip materials with an invalid instances - continue; - } - - if (!materialInstance->CanCompile()) - { - //If a material cannot currently be compiled then it must be queued again - m_queuedPropertyOverrides.emplace(materialAssignmentId); - continue; - } - - const auto& propertyOverrides2 = materialIt->second.m_propertyOverrides; - for (auto& propertyPair : propertyOverrides2) - { - if (propertyPair.second.empty()) + if (!materialIt->second.ApplyProperties()) { - continue; + // If a material cannot currently be compiled then it must be queued again + m_materialsWithDirtyProperties.emplace(materialAssignmentId); } - - const auto& materialPropertyIndex = materialInstance->FindPropertyIndex(propertyPair.first); - if (materialPropertyIndex.IsNull()) - { - continue; - } - - materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); } - - materialInstance->Compile(); } // Only disconnect from tick bus and send notification after all pending properties have been applied - if (m_queuedPropertyOverrides.empty()) + if (m_materialsWithDirtyProperties.empty()) { if (m_queuedMaterialUpdateNotification) { @@ -213,15 +185,35 @@ namespace AZ Data::AssetBus::MultiHandler::BusDisconnect(); bool anyQueued = false; - for (auto& materialPair : m_configuration.m_materials) + auto queueAsset = [&anyQueued, this](AZ::Data::Asset& materialAsset) -> bool { - auto& materialAsset = materialPair.second.m_materialAsset; - - if (materialAsset.GetId().IsValid() && !Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId())) + if (materialAsset.GetId().IsValid() && !this->Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId())) { anyQueued = true; materialAsset.QueueLoad(); - Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId()); + this->Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId()); + return true; + } + return false; + }; + + for (auto& materialPair : m_configuration.m_materials) + { + if (materialPair.second.m_materialInstancePreCreated) + { + continue; + } + + materialPair.second.m_defaultMaterialAsset = {}; + if (!queueAsset(materialPair.second.m_materialAsset)) + { + // Only assign and load the default material if there was no material override and there are propoerties to apply + if (!materialPair.second.m_propertyOverrides.empty() || !materialPair.second.m_matModUvOverrides.empty()) + { + materialPair.second.m_defaultMaterialAsset = AZ::Data::Asset( + GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo::Uuid()); + queueAsset(materialPair.second.m_defaultMaterialAsset); + } } } @@ -234,10 +226,8 @@ namespace AZ void MaterialComponentController::InitializeMaterialInstance(const Data::Asset& asset) { bool allReady = true; - - for (auto& materialPair : m_configuration.m_materials) + auto updateAsset = [&](AZ::Data::Asset& materialAsset) { - auto& materialAsset = materialPair.second.m_materialAsset; if (materialAsset.GetId() == asset.GetId()) { materialAsset = asset; @@ -247,6 +237,12 @@ namespace AZ { allReady = false; } + }; + + for (auto& materialPair : m_configuration.m_materials) + { + updateAsset(materialPair.second.m_materialAsset); + updateAsset(materialPair.second.m_defaultMaterialAsset); } if (allReady) @@ -269,11 +265,7 @@ namespace AZ for (auto& materialPair : m_configuration.m_materials) { - if (materialPair.second.m_materialAsset.GetId().IsValid()) - { - materialPair.second.m_materialAsset.Release(); - materialPair.second.m_materialInstance = nullptr; - } + materialPair.second.Release(); } MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsUpdated, m_configuration.m_materials); @@ -441,12 +433,7 @@ namespace AZ AZ::Data::AssetId MaterialComponentController::GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const { auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) - { - return {}; - } - - return materialIt->second.m_materialAsset.GetId(); + return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_materialAsset.GetId() : AZ::Data::AssetId(); } void MaterialComponentController::ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId) @@ -460,18 +447,21 @@ namespace AZ void MaterialComponentController::SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) { auto& materialAssignment = m_configuration.m_materials[materialAssignmentId]; + const bool wasEmpty = materialAssignment.m_propertyOverrides.empty(); + materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; - // When applying property overrides for the first time, new instance needs to be created in case the current instance is already used somewhere else to keep overrides local - if (materialAssignment.m_propertyOverrides.empty()) + if (materialAssignment.RequiresLoading()) { - materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; - materialAssignment.RebuildInstance(); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialAssignment); - QueueMaterialUpdateNotification(); + LoadMaterials(); + return; } - else + + if (wasEmpty != materialAssignment.m_propertyOverrides.empty()) { - materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; + materialAssignment.RebuildInstance(); + MaterialComponentNotificationBus::Event( + m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialAssignment); + QueueMaterialUpdateNotification(); } QueuePropertyChanges(materialAssignmentId); @@ -704,6 +694,12 @@ namespace AZ const bool wasEmpty = materialAssignment.m_propertyOverrides.empty(); materialAssignment.m_propertyOverrides = propertyOverrides; + if (materialAssignment.RequiresLoading()) + { + LoadMaterials(); + return; + } + if (wasEmpty != materialAssignment.m_propertyOverrides.empty()) { materialAssignment.RebuildInstance(); @@ -713,14 +709,11 @@ namespace AZ QueuePropertyChanges(materialAssignmentId); } - MaterialPropertyOverrideMap MaterialComponentController::GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const + MaterialPropertyOverrideMap MaterialComponentController::GetPropertyOverrides( + const MaterialAssignmentId& materialAssignmentId) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) - { - return {}; - } - return materialIt->second.m_propertyOverrides; + return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_propertyOverrides : MaterialPropertyOverrideMap(); } void MaterialComponentController::SetModelUvOverrides( @@ -730,6 +723,12 @@ namespace AZ const bool wasEmpty = materialAssignment.m_matModUvOverrides.empty(); materialAssignment.m_matModUvOverrides = modelUvOverrides; + if (materialAssignment.RequiresLoading()) + { + LoadMaterials(); + return; + } + if (wasEmpty != materialAssignment.m_matModUvOverrides.empty()) { materialAssignment.RebuildInstance(); @@ -743,16 +742,24 @@ namespace AZ const MaterialAssignmentId& materialAssignmentId) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) + return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_matModUvOverrides : AZ::RPI::MaterialModelUvOverrideMap(); + } + + void MaterialComponentController::OnMaterialAssignmentsChanged() + { + for (const auto& materialPair : m_configuration.m_materials) { - return {}; + if (materialPair.second.RequiresLoading()) + { + LoadMaterials(); + return; + } } - return materialIt->second.m_matModUvOverrides; } void MaterialComponentController::QueuePropertyChanges(const MaterialAssignmentId& materialAssignmentId) { - m_queuedPropertyOverrides.emplace(materialAssignmentId); + m_materialsWithDirtyProperties.emplace(materialAssignmentId); if (!TickBus::Handler::BusIsConnected()) { TickBus::Handler::BusConnect(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index 2bf15ca3b8..1594456a31 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -22,6 +22,7 @@ namespace AZ //! to provide material overrides on a per-entity basis. class MaterialComponentController final : MaterialComponentRequestBus::Handler + , MaterialReceiverNotificationBus::Handler , Data::AssetBus::MultiHandler , TickBus::Handler { @@ -100,6 +101,9 @@ namespace AZ const MaterialAssignmentId& materialAssignmentId, const AZ::RPI::MaterialModelUvOverrideMap& modelUvOverrides) override; AZ::RPI::MaterialModelUvOverrideMap GetModelUvOverrides(const MaterialAssignmentId& materialAssignmentId) const override; + //! MaterialReceiverNotificationBus::Handler overrides... + void OnMaterialAssignmentsChanged() override; + private: AZ_DISABLE_COPY(MaterialComponentController); @@ -121,7 +125,7 @@ namespace AZ EntityId m_entityId; MaterialComponentConfig m_configuration; - AZStd::unordered_set m_queuedPropertyOverrides; + AZStd::unordered_set m_materialsWithDirtyProperties; bool m_queuedMaterialUpdateNotification = false; }; } // namespace Render diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp index d8880f6fcc..56f7ee567e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp @@ -726,10 +726,12 @@ namespace EMotionFX { MCore::LockGuardRecursive lock(m_mutex); - return AZStd::accumulate(begin(m_childSets), end(m_childSets), size_t{0}, [](size_t total, const MotionSet* motionSet) + size_t result = 0; + for (const MotionSet* motionSet : m_childSets) { - return total + motionSet->GetIsOwnedByRuntime(); - }); + result += !motionSet->GetIsOwnedByRuntime(); + } + return result; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StateController.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StateController.h index 053ed98978..54dccb8ae0 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StateController.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StateController.h @@ -8,6 +8,7 @@ #pragma once #include +#include // A configurable queue that allows for multiple sources to try to control a single value in a configurable way // such that each object can control the object independently of the other systems, while still maintaining a reasonable state. diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp index 33eb26653a..9e15ae6ce0 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,7 @@ namespace Multiplayer { - + bool CollisionLayerBasedControllerFilter(const physx::PxController& controllerA, const physx::PxController& controllerB) { PHYSX_SCENE_READ_LOCK(controllerA.getActor()->getScene()); @@ -82,7 +83,7 @@ namespace Multiplayer return physx::PxQueryHitType::eNONE; } - + void NetworkCharacterComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -116,7 +117,7 @@ namespace Multiplayer callbackManager->SetObjectPreFilter(CollisionLayerBasedObjectPreFilter); } } - + if (!HasController()) { GetNetworkTransformComponent()->TranslationAddEvent(m_translationEventHandler); @@ -134,7 +135,7 @@ namespace Multiplayer } void NetworkCharacterComponent::OnSyncRewind() - { + { if (m_physicsCharacter == nullptr) { return; diff --git a/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h b/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h index 4659bf3677..24e33ea584 100644 --- a/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h +++ b/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h @@ -8,21 +8,20 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include namespace PhysX { /// Sub component mode for modifying the asset scale on a collider in the viewport. - class ColliderAssetScaleMode - : public PhysX::ColliderSubComponentMode + class ColliderAssetScaleMode : public PhysXSubComponentModeBase { public: AZ_CLASS_ALLOCATOR_DECL ColliderAssetScaleMode(); - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderBoxMode.h b/Gems/PhysX/Code/Editor/ColliderBoxMode.h index a8e0c03a3a..75ce928d80 100644 --- a/Gems/PhysX/Code/Editor/ColliderBoxMode.h +++ b/Gems/PhysX/Code/Editor/ColliderBoxMode.h @@ -8,19 +8,18 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include namespace PhysX { /// Sub component mode for modifying the box dimensions on a collider. - class ColliderBoxMode - : public PhysX::ColliderSubComponentMode + class ColliderBoxMode : public PhysXSubComponentModeBase { public: AZ_CLASS_ALLOCATOR_DECL - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h b/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h index b152801988..ceedd84a35 100644 --- a/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h +++ b/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h @@ -8,7 +8,7 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include #include @@ -16,13 +16,13 @@ namespace PhysX { /// Sub component mode for modifying the height and radius on a capsule collider. class ColliderCapsuleMode - : public PhysX::ColliderSubComponentMode + : public PhysXSubComponentModeBase , private AzFramework::EntityDebugDisplayEventBus::Handler { public: AZ_CLASS_ALLOCATOR_DECL - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp b/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp index 994811b8d1..5de625f679 100644 --- a/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp +++ b/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp @@ -7,7 +7,6 @@ */ #include "ColliderComponentMode.h" -#include "ColliderSubComponentMode.h" #include "ColliderOffsetMode.h" #include "ColliderRotationMode.h" #include "ColliderBoxMode.h" @@ -15,6 +14,7 @@ #include "ColliderCapsuleMode.h" #include "ColliderAssetScaleMode.h" +#include #include #include diff --git a/Gems/PhysX/Code/Editor/ColliderComponentMode.h b/Gems/PhysX/Code/Editor/ColliderComponentMode.h index 420e621054..b4ca060065 100644 --- a/Gems/PhysX/Code/Editor/ColliderComponentMode.h +++ b/Gems/PhysX/Code/Editor/ColliderComponentMode.h @@ -15,7 +15,7 @@ namespace PhysX { - class ColliderSubComponentMode; + class PhysXSubComponentModeBase; //! ComponentMode for the Collider Component - Manages a list of Sub-Component Modes and //! is responsible for switching between and activating them. @@ -53,7 +53,7 @@ namespace PhysX void CreateSubModes(); void ResetCurrentMode(); - AZStd::unordered_map> m_subModes; + AZStd::unordered_map> m_subModes; SubMode m_subMode = SubMode::Dimensions; //! Create the Viewport UI cluster for sub mode selection. diff --git a/Gems/PhysX/Code/Editor/ColliderOffsetMode.h b/Gems/PhysX/Code/Editor/ColliderOffsetMode.h index bcf140a5e3..6a2e6a8a12 100644 --- a/Gems/PhysX/Code/Editor/ColliderOffsetMode.h +++ b/Gems/PhysX/Code/Editor/ColliderOffsetMode.h @@ -8,21 +8,20 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include namespace PhysX { /// Sub component mode for modifying offset on a collider in the viewport. - class ColliderOffsetMode - : public PhysX::ColliderSubComponentMode + class ColliderOffsetMode : public PhysXSubComponentModeBase { public: AZ_CLASS_ALLOCATOR_DECL ColliderOffsetMode(); - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderRotationMode.h b/Gems/PhysX/Code/Editor/ColliderRotationMode.h index e1f578aed7..dc37e23b0e 100644 --- a/Gems/PhysX/Code/Editor/ColliderRotationMode.h +++ b/Gems/PhysX/Code/Editor/ColliderRotationMode.h @@ -8,7 +8,7 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include #include @@ -16,7 +16,7 @@ namespace PhysX { /// Sub component mode for modifying the rotation on a collider in the viewport. class ColliderRotationMode - : public PhysX::ColliderSubComponentMode + : public PhysXSubComponentModeBase , private AzFramework::EntityDebugDisplayEventBus::Handler { public: @@ -24,7 +24,7 @@ namespace PhysX ColliderRotationMode(); - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderSphereMode.h b/Gems/PhysX/Code/Editor/ColliderSphereMode.h index 08ee813cd0..7d255d598b 100644 --- a/Gems/PhysX/Code/Editor/ColliderSphereMode.h +++ b/Gems/PhysX/Code/Editor/ColliderSphereMode.h @@ -8,7 +8,7 @@ #pragma once -#include "ColliderSubComponentMode.h" +#include #include #include @@ -16,13 +16,13 @@ namespace PhysX { /// Sub component mode for modifying the box dimensions on a collider. class ColliderSphereMode - : public PhysX::ColliderSubComponentMode + : public PhysXSubComponentModeBase , private AzFramework::EntityDebugDisplayEventBus::Handler { public: AZ_CLASS_ALLOCATOR_DECL - // ColliderSubComponentMode ... + // PhysXSubComponentModeBase ... void Setup(const AZ::EntityComponentIdPair& idPair) override; void Refresh(const AZ::EntityComponentIdPair& idPair) override; void Teardown(const AZ::EntityComponentIdPair& idPair) override; diff --git a/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h b/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h deleted file mode 100644 index 4711a20c86..0000000000 --- a/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * - */ - -#pragma once - -namespace AZ -{ - class EntityComponentIdPair; -} - -namespace PhysX -{ - /// Interface to implement when adding a new editing mode - /// for collider component mode. - class ColliderSubComponentMode - { - public: - virtual ~ColliderSubComponentMode() {}; - - /// Called when the mode is entered to initialise the mode. - /// @param idPair The entity/component id pair. - virtual void Setup(const AZ::EntityComponentIdPair& idPair) = 0; - - /// Called when the mode needs to refresh it's values. - /// @param idPair The entity/component id pair. - virtual void Refresh(const AZ::EntityComponentIdPair& idPair) = 0; - - /// Called when the mode exits to perform cleanup. - /// @param idPair The entity/component id pair. - virtual void Teardown(const AZ::EntityComponentIdPair& idPair) = 0; - - /// Called when reset hotkey is pressed. - /// Should reset values in the sub component mode to sensible defaults. - /// @param idPair The entity/component id pair. - virtual void ResetValues(const AZ::EntityComponentIdPair& idPair) = 0; - }; -} diff --git a/Gems/PhysX/Code/Editor/EditorJointCommon.h b/Gems/PhysX/Code/Editor/EditorJointCommon.h new file mode 100644 index 0000000000..031b293942 --- /dev/null +++ b/Gems/PhysX/Code/Editor/EditorJointCommon.h @@ -0,0 +1,17 @@ +/* + * 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 + * + */ + +#pragma once + +#include + +namespace PhysX +{ + //! Pair of floating point values for angular limits. + using AngleLimitsFloatPair = AZStd::pair; +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp b/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp deleted file mode 100644 index 39b028bef3..0000000000 --- a/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp +++ /dev/null @@ -1,577 +0,0 @@ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace PhysX -{ - namespace - { - //! Uri's for shortcut actions. - const AZ::Crc32 GoToNextModeActionUri = AZ_CRC("com.o3de.action.physx.joint.nextmode", 0xe9cf4ed6); - const AZ::Crc32 GoToPrevModeActionUri = AZ_CRC("com.o3de.action.physx.joint.prevmode", 0xe70f8daa); - } - - const AZStd::string EditorJointComponentMode::s_parameterAngularPair = "Twist Limits"; - const AZStd::string EditorJointComponentMode::s_parameterDamping = "Damping"; - const AZStd::string EditorJointComponentMode::s_parameterMaxForce = "Maximum Force"; - const AZStd::string EditorJointComponentMode::s_parameterMaxTorque = "Maximum Torque"; - const AZStd::string EditorJointComponentMode::s_parameterPosition = "Position"; - const AZStd::string EditorJointComponentMode::s_parameterRotation = "Rotation"; - const AZStd::string EditorJointComponentMode::s_parameterSnapPosition = "Snap Position"; - const AZStd::string EditorJointComponentMode::s_parameterSnapRotation = "Snap Rotation"; - const AZStd::string EditorJointComponentMode::s_parameterStiffness = "Stiffness"; - const AZStd::string EditorJointComponentMode::s_parameterSwingLimit = "Swing Limits"; - const AZStd::string EditorJointComponentMode::s_parameterTolerance = "Tolerance"; - const AZStd::string EditorJointComponentMode::s_parameterTransform = "Transform"; - const AZStd::string EditorJointComponentMode::s_parameterComponentMode = "Component Mode"; - const AZStd::string EditorJointComponentMode::s_parameterLeadEntity = "Lead Entity"; - const AZStd::string EditorJointComponentMode::s_parameterSelectOnSnap = "Select on Snap"; - - EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type) - : m_name(name), m_type(type) - { - } - - EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , float exponent - , float max - , float min) - : m_name(name), m_type(type), m_exponent(exponent), m_max(max), m_min(min) - { - } - - EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , const AZ::Vector3& axis - , float max - , float min) - : m_name(name), m_type(type), m_axis(axis), m_max(max), m_min(min) - { - } - - EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , float max - , float min) - : m_name(name), m_type(type), m_max(max), m_min(min) - { - } - - EditorJointComponentMode::EditorJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType) - : EditorBaseComponentMode(entityComponentIdPair, componentType) - , m_entityComponentIdPair(entityComponentIdPair) - , m_componentType(componentType) - { - EditorJointRequestBus::Event( - m_entityComponentIdPair - , &EditorJointRequests::SetBoolValue - , EditorJointComponentMode::s_parameterComponentMode - , true); - } - - EditorJointComponentMode::~EditorJointComponentMode() - { - EditorJointRequestBus::Event( - m_entityComponentIdPair - , &EditorJointRequests::SetBoolValue - , EditorJointComponentMode::s_parameterComponentMode - , false); - } - - bool EditorJointComponentMode::HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) - { - if (mouseInteraction.m_mouseEvent == AzToolsFramework::ViewportInteraction::MouseEvent::Wheel && - mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl()) - { - NextMode(); - return true; - } - - // Propagate mouse interaction to sub-component mode. - if (m_currentSubComponentMode) - { - m_currentSubComponentMode->HandleMouseInteraction(mouseInteraction); - } - - return false; - } - - AZStd::vector EditorJointComponentMode::PopulateActionsImpl() - { - AzToolsFramework::ActionOverride goToNextMode; - goToNextMode.SetUri(GoToNextModeActionUri); - goToNextMode.SetKeySequence(QKeySequence(Qt::Key_Tab)); - goToNextMode.SetTitle("Next Mode"); - goToNextMode.SetTip("Go to next mode"); - goToNextMode.SetEntityComponentIdPair(GetEntityComponentIdPair()); - goToNextMode.SetCallback([this]() - { - NextMode(); - }); - - AzToolsFramework::ActionOverride goToPrevMode; - goToPrevMode.SetUri(GoToPrevModeActionUri); - goToPrevMode.SetKeySequence(QKeySequence(Qt::SHIFT + Qt::Key_Tab)); - goToPrevMode.SetTitle("Previous Mode"); - goToPrevMode.SetTip("Go to previous mode"); - goToPrevMode.SetEntityComponentIdPair(GetEntityComponentIdPair()); - goToPrevMode.SetCallback([this]() - { - PreviousMode(); - }); - - return {goToNextMode, goToPrevMode}; - } - - void EditorJointComponentMode::NextMode() - { - const bool isForwardChange = true; - ChangeMode(isForwardChange); - } - - void EditorJointComponentMode::PreviousMode() - { - const bool isForwardChange = false; - ChangeMode(isForwardChange); - } - - void EditorJointComponentMode::ChangeMode(bool forwardChange) - { - if (m_configMap.empty()) - { - return; - } - - AZStd::string previousModeName; - if (m_currentSubComponentMode) - { - previousModeName = m_currentSubComponentMode->m_name; - m_currentSubComponentMode.reset(); - } - - ConfigMapIter configIter = m_configMap.begin(); - if (!previousModeName.empty()) - { - configIter = m_configMap.find(previousModeName); - } - - AZ::u32 iterCount = 0; - do - { - if (forwardChange) - { - ++configIter; - if (configIter == m_configMap.end()) - { - configIter = m_configMap.begin(); - } - } - else - { - if (configIter == m_configMap.begin()) - { - configIter = m_configMap.end(); - } - --configIter; - } - ++iterCount; - } while (!IsSubComponentModeUsed(configIter->second.m_name) && iterCount != m_configMap.size()); - - if (iterCount == m_configMap.size()) // All sub component modes are not in use. - { - return; - } - - SetCurrentSubComponentMode(configIter->second.m_name); - } - - void EditorJointComponentMode::SetCurrentSubComponentMode(const AZStd::string& subComponentModeName) - { - ConfigMapIter configIter = m_configMap.find(subComponentModeName); - if (configIter == m_configMap.end()) - { - AZ_Warning("EditorJointComponentMode" - , false - , "Attempt to set sub component mode which does not exist: %s" - , subComponentModeName.c_str()); - return; - } - EditorSubComponentModeConfig config = configIter->second; - - EditorJointRequestBus::EventResult( - config.m_selectLeadOnSnap, m_entityComponentIdPair - , &EditorJointRequests::GetBoolValue - , s_parameterSelectOnSnap); - - m_currentSubComponentMode.reset(); - - switch (config.m_type) - { - case EditorSubComponentModeType::Linear: - SetSubComponentModeLinear(config); - break; - case EditorSubComponentModeType::AnglePair: - SetSubComponentModeAnglePair(config); - break; - case EditorSubComponentModeType::AngleCone: - SetSubComponentModeAngleCone(config); - break; - case EditorSubComponentModeType::Vec3: - SetSubComponentModeVec3(config); - break; - case EditorSubComponentModeType::Rotation: - SetSubComponentModeRotation(config); - break; - case EditorSubComponentModeType::SnapPosition: - SetSubComponentModeSnapPosition(config); - break; - case EditorSubComponentModeType::SnapRotation: - SetSubComponentModeSnapRotation(config); - break; - default: - AZ_Error("EditorJointComponentMode::SetCurrentSubComponentMode" - , false - , "Unsupported sub-component mode type."); - } - } - - bool EditorJointComponentMode::IsSubComponentModeUsed(const AZStd::string& subComponentModeName) - { - bool isUsed = false; - EditorJointRequestBus::EventResult( - isUsed, m_entityComponentIdPair - , &EditorJointRequests::IsParameterUsed - , subComponentModeName); - return isUsed; - } - - void EditorJointComponentMode::SetSubComponentModeAngleCone(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name - , config.m_max - , config.m_min); - } - - void EditorJointComponentMode::SetSubComponentModeAnglePair(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name - , config.m_axis - , config.m_max - , config.m_min - , config.m_min - , -config.m_max); - } - - void EditorJointComponentMode::SetSubComponentModeLinear(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name - , config.m_exponent - , config.m_max - , config.m_min); - } - - void EditorJointComponentMode::SetSubComponentModeVec3(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name); - } - - void EditorJointComponentMode::SetSubComponentModeRotation(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name); - } - - void EditorJointComponentMode::SetSubComponentModeSnapPosition(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name - , config.m_selectLeadOnSnap); - } - - void EditorJointComponentMode::SetSubComponentModeSnapRotation(const EditorSubComponentModeConfig& config) - { - m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair - , m_componentType - , config.m_name); - } - - EditorBallJointComponentMode::EditorBallJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType) - : EditorJointComponentMode(entityComponentIdPair, componentType) - { - m_configMap = Configure(); - NextMode(); - } - - EditorBallJointComponentMode::~EditorBallJointComponentMode() - { - if (m_currentSubComponentMode) - { - m_currentSubComponentMode.reset(); - } - } - - void EditorJointComponentMode::Refresh() - { - if (m_currentSubComponentMode) - { - m_currentSubComponentMode->Refresh(); - } - } - - AZStd::map EditorBallJointComponentMode::Configure() - { - AZStd::map configMap; - - configMap.emplace( - EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeType::Vec3) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeType::Rotation) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterSnapPosition - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapPosition - , EditorSubComponentModeType::SnapPosition) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterSnapRotation - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapRotation - , EditorSubComponentModeType::SnapRotation) - ); - - const float exponentBreakage = 1.0f; - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - const float exponentSpring = 2.0f; - - configMap.emplace( - EditorJointComponentMode::s_parameterDamping - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterDamping - , EditorSubComponentModeType::Linear - , exponentSpring - , PhysX::EditorJointLimitConeConfig::s_springMax - , PhysX::EditorJointLimitConeConfig::s_springMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterStiffness - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterStiffness - , EditorSubComponentModeType::Linear - , exponentSpring - , PhysX::EditorJointLimitConeConfig::s_springMax - , PhysX::EditorJointLimitConeConfig::s_springMin) - ); - - // Cone tip to base is always X-axis. - //The angle cone defines the limitations for rotation about the Y and Z axes. - configMap.emplace( - EditorJointComponentMode::s_parameterSwingLimit - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSwingLimit - , EditorSubComponentModeType::AngleCone - , PhysX::EditorJointLimitConeConfig::s_angleMax - , PhysX::EditorJointLimitConeConfig::s_angleMin) - ); - - return configMap; - } - - EditorFixedJointComponentMode::EditorFixedJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType) - : EditorJointComponentMode(entityComponentIdPair, componentType) - { - m_configMap = Configure(); - NextMode(); - } - - EditorFixedJointComponentMode::~EditorFixedJointComponentMode() - { - if (m_currentSubComponentMode) - { - m_currentSubComponentMode.reset(); - } - } - - AZStd::map EditorFixedJointComponentMode::Configure() - { - AZStd::map configMap; - - configMap.emplace( - EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeType::Vec3) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeType::Rotation) - ); - - const float exponentBreakage = 1.0f; - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - return configMap; - } - - EditorHingeJointComponentMode::EditorHingeJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType) - : EditorJointComponentMode(entityComponentIdPair, componentType) - { - m_configMap = Configure(); - NextMode(); - } - - EditorHingeJointComponentMode::~EditorHingeJointComponentMode() - { - if (m_currentSubComponentMode) - { - m_currentSubComponentMode.reset(); - } - } - - AZStd::map EditorHingeJointComponentMode::Configure() - { - AZStd::map configMap; - - configMap.emplace( - EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition - , EditorSubComponentModeType::Vec3) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation - , EditorSubComponentModeType::Rotation) - ); - - const float exponentBreakage = 1.0f; - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque - , EditorSubComponentModeType::Linear - , exponentBreakage - , PhysX::EditorJointConfig::s_breakageMax - , PhysX::EditorJointConfig::s_breakageMin) - ); - - const float exponentSpring = 2.0f; - - configMap.emplace( - EditorJointComponentMode::s_parameterDamping - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterDamping - , EditorSubComponentModeType::Linear - , exponentSpring - , PhysX::EditorJointLimitPairConfig::s_springMax - , PhysX::EditorJointLimitPairConfig::s_springMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterStiffness - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterStiffness - , EditorSubComponentModeType::Linear - , exponentSpring - , PhysX::EditorJointLimitPairConfig::s_springMax - , PhysX::EditorJointLimitPairConfig::s_springMin) - ); - - AZ::Vector3 axis = AZ::Vector3::CreateAxisX(); // PhysX revolute joints uses the x-axis by default - configMap.emplace( - EditorJointComponentMode::s_parameterAngularPair - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterAngularPair - , EditorSubComponentModeType::AnglePair - , axis - , PhysX::EditorJointLimitPairConfig::s_angleMax - , PhysX::EditorJointLimitPairConfig::s_angleMin) - ); - - configMap.emplace( - EditorJointComponentMode::s_parameterSnapPosition - , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapPosition - , EditorSubComponentModeType::SnapPosition) - ); - - return configMap; - } -} // namespace LmbrCentral diff --git a/Gems/PhysX/Code/Editor/EditorJointComponentMode.h b/Gems/PhysX/Code/Editor/EditorJointComponentMode.h deleted file mode 100644 index 023edcc24b..0000000000 --- a/Gems/PhysX/Code/Editor/EditorJointComponentMode.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 - * - */ -#pragma once - -#include -#include - -#include - -namespace PhysX -{ - enum class EditorSubComponentModeType : AZ::u8 - { - Linear, /// sub-component mode to modify a single linear value, e.g. a float value. - AnglePair, /// sub-component mode to modify a pair of float values representing angles. - AngleCone, /// sub-component mode to modify a constraint's swing limits and local transformation. - Rotation, /// sub-component mode to modify local transformation. - SnapPosition, /// sub-component mode to modify local position using a point-and-snap feature in the viewport. - SnapRotation, /// sub-component mode to modify local rotation using a point-and-snap feature in the viewport. - Vec3 /// sub-component mode to modify a Vector3 value. - }; - - /// Contains configuration of a sub-component mode. Shared by different types of sub-component mode. - /// Alternative implementation of this struct using AZStd::Variant is pending the development of the rest of the joint types. - struct EditorSubComponentModeConfig - { - EditorSubComponentModeConfig() = default; - - EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type); - - EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , float exponent - , float max - , float min); - - EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , const AZ::Vector3& axis - , float max - , float min); - - EditorSubComponentModeConfig(const AZStd::string& name - , EditorSubComponentModeType type - , float max - , float min); - - AZStd::string m_name; - EditorSubComponentModeType m_type; - AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); - float m_exponent = 1.0f; - float m_max = FLT_MAX; - float m_min = -FLT_MAX; - bool m_selectLeadOnSnap = true; ///< A user may use the snap-to-position component mode to snap the position of a joint to an entity. This flag indicates if the snapped-to entity would be selected as a joint's lead when that happens. - }; - - /// Generic component mode that supports multiple sub-component modes. - class EditorJointComponentMode - : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode - { - public: - static const AZStd::string s_parameterAngularPair; - static const AZStd::string s_parameterDamping; - static const AZStd::string s_parameterMaxForce; - static const AZStd::string s_parameterMaxTorque; - static const AZStd::string s_parameterPosition; - static const AZStd::string s_parameterRotation; - static const AZStd::string s_parameterSnapPosition; - static const AZStd::string s_parameterSnapRotation; - static const AZStd::string s_parameterStiffness; - static const AZStd::string s_parameterSwingLimit; - static const AZStd::string s_parameterTolerance; - static const AZStd::string s_parameterTransform; - static const AZStd::string s_parameterComponentMode; - static const AZStd::string s_parameterLeadEntity; - static const AZStd::string s_parameterSelectOnSnap; - - EditorJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType); - ~EditorJointComponentMode(); - - // EditorBaseComponentMode - void Refresh() override; - - /// Returns map of sub-component mode configurations required by this component mode. - virtual AZStd::map Configure() = 0; - - protected: - /// AzToolsFramework::ViewportInteraction::MouseViewportRequests - bool HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; - - /// EditorBaseComponentMode - AZStd::vector PopulateActionsImpl() override; - - /// Changes to the next sub-component mode found in m_configMap. - void NextMode(); - - /// Changes to the previous sub-component mode found in m_configMap. - void PreviousMode(); - - /// Changes to the next or previous sub-component mode found in m_configMap. - void ChangeMode(bool forwardChange); - - /// Replaces m_currentSubComponentMode with a new one instantiated using the configuration identified by the input subComponentModeName. - void SetCurrentSubComponentMode(const AZStd::string& subComponentModeName); - - AZStd::shared_ptr m_currentSubComponentMode = nullptr; ///< The active sub-component mode in this component mode. - AZ::Uuid m_componentType = AZ::Uuid::CreateNull(); - AZStd::map m_configMap; ///< Contains sub-component mode configurations supported by this component mode. - AZ::EntityComponentIdPair m_entityComponentIdPair; - - private: - bool IsSubComponentModeUsed(const AZStd::string& subComponentModeName); - - void SetSubComponentModeAngleCone(const EditorSubComponentModeConfig& config); - void SetSubComponentModeAnglePair(const EditorSubComponentModeConfig& config); - void SetSubComponentModeLinear(const EditorSubComponentModeConfig& config); - void SetSubComponentModeVec3(const EditorSubComponentModeConfig& config); - void SetSubComponentModeRotation(const EditorSubComponentModeConfig& config); - void SetSubComponentModeSnapPosition(const EditorSubComponentModeConfig& config); - void SetSubComponentModeSnapRotation(const EditorSubComponentModeConfig& config); - }; - - /// Ball joint specific component mode. Configure() is overriden to set up the required sub-component modes. - class EditorBallJointComponentMode - : public EditorJointComponentMode - { - public: - EditorBallJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType); - ~EditorBallJointComponentMode(); - - // EditorJointComponentMode - AZStd::map Configure() override; - }; - - /// Fixed joint specific component mode. Configure() is overriden to set up the required sub-component modes. - class EditorFixedJointComponentMode - : public EditorJointComponentMode - { - public: - EditorFixedJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType); - ~EditorFixedJointComponentMode(); - - // EditorJointComponentMode - AZStd::map Configure() override; - }; - - /// Hinge joint specific component mode. Configure() is overriden to set up the required sub-component modes. - class EditorHingeJointComponentMode - : public EditorJointComponentMode - { - public: - EditorHingeJointComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType); - ~EditorHingeJointComponentMode(); - - // EditorJointComponentMode - AZStd::map Configure() override; - }; - - using ConfigMap = AZStd::map; - using ConfigMapIter = ConfigMap::iterator; - using ConfigMapReverseIter = ConfigMap::reverse_iterator; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp b/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp deleted file mode 100644 index 53b27f6cde..0000000000 --- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 -#include - -namespace PhysX -{ - EditorJointTypeDrawer::EditorJointTypeDrawer(EditorJointType jointType, - AzFramework::EntityContextId entityContextId, - const AZStd::string& subComponentModeName): - m_subComponentModeName(subComponentModeName) - { - AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(entityContextId); - EditorJointTypeDrawerBus::Handler::BusConnect(EditorJointTypeDrawerId(jointType, - EditorSubComponentModeNameCrc(subComponentModeName))); - } - - EditorJointTypeDrawer::~EditorJointTypeDrawer() - { - EditorJointTypeDrawerBus::Handler::BusDisconnect(); - AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); - } - - void EditorJointTypeDrawer::DisplayViewport2d( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - const AZ::u32 stateBefore = debugDisplay.GetState(); - - const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId); - - const float xOffsetCurrentMode = 125.0f; - const float yOffsetCurrentMode = 55.0f; - - const float xOffsetHotKeys = 125.0f; - const float yOffsetHotKeys = 30.0f; - - const float viewportWidthHalf = cameraState.m_viewportSize.GetX() / 2.0f; - const float viewportHeight = cameraState.m_viewportSize.GetY(); - - debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 1.0f)); - - AZStd::string screenTextCurrentMode = "Edit mode: " + m_subComponentModeName; - float xPos = viewportWidthHalf - xOffsetCurrentMode; - float yPos = viewportHeight - yOffsetCurrentMode; - float textSize = 2.0f; - debugDisplay.Draw2dTextLabel(xPos, yPos, textSize, screenTextCurrentMode.c_str()); - - AZStd::string screenTextHotKeys = " or to change modes"; - xPos = viewportWidthHalf - xOffsetHotKeys; - yPos = viewportHeight - yOffsetHotKeys; - textSize = 1.2f; - debugDisplay.Draw2dTextLabel(xPos, yPos, textSize, screenTextHotKeys.c_str()); - - debugDisplay.SetState(stateBefore); - } - - AZStd::shared_ptr EditorJointTypeDrawer::GetEditorJointTypeDrawer() - { - return shared_from_this(); - } - -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h b/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h deleted file mode 100644 index 4172424f00..0000000000 --- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - * - */ -#pragma once - -#include -#include -#include - -namespace PhysX -{ - /// This class enables drawing in the viewport once for the component modes of multiple components in one entity. - /// Until the component mode framework allows a way to do this, a work-around like this class is necessary. - /// An instance of this class is created for each pair of component type and sub-component mode. - class EditorJointTypeDrawer - : public EditorJointTypeDrawerBus::Handler - , public AZStd::enable_shared_from_this - , private AzFramework::ViewportDebugDisplayEventBus::Handler - { - public: - EditorJointTypeDrawer(EditorJointType id, - AzFramework::EntityContextId entityContextId, - const AZStd::string& subComponentModeName); - ~EditorJointTypeDrawer(); - - private: - // AzFramework::ViewportDebugDisplayEventBus - void DisplayViewport2d( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // PhysX::EditorJointTypeDrawerBus - AZStd::shared_ptr GetEditorJointTypeDrawer() override; - - AZStd::string m_subComponentModeName;///< Name of the sub component mode. E.g. Position, Rotation, Snap Position, etc. - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h b/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h deleted file mode 100644 index e47c447fe2..0000000000 --- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 - * - */ -#pragma once - -#include - -namespace PhysX -{ - class EditorJointTypeDrawer; - - using EditorJointType = AZ::Uuid; - using EditorSubComponentModeNameCrc = AZ::Crc32; - using EditorJointTypeDrawerId = AZStd::pair; - - /// The sub-component mode of a component type uses this bus (by invoking GetEditorJointTypeDrawer) to retrieve a drawer. - /// If nothing is returned, it creates an instance of the drawer that will be shared by other instances of the same component type. - class EditorJointTypeDrawerRequests : public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - using BusIdType = EditorJointTypeDrawerId; - - virtual AZStd::shared_ptr GetEditorJointTypeDrawer() = 0; - }; - using EditorJointTypeDrawerBus = AZ::EBus; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp deleted file mode 100644 index 43b9fd77f3..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp +++ /dev/null @@ -1,453 +0,0 @@ - -/* - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace -{ - const float ArrowLength = 2.0f; - const float ConeHeight = 3.0f; - const float XRotationManipulatorRadius = 2.0f; - const float XRotationManipulatorWidth = 0.05f; -} - -namespace PhysX -{ - struct SharedRotationState - { - AZ::Vector3 m_axis; - AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity(); - AngleLimitsFloatPair m_valuePair; - }; - - EditorSubComponentModeAngleCone::EditorSubComponentModeAngleCone( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , float max - , float min) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) - , m_max(max) - , m_min(min) - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - const AZ::Quaternion localRotation = localTransform.GetRotation(); - - // Initialize manipulators used to resize the base of the cone. - m_yLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); - m_yLinearManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_yLinearManipulator->SetAxis(AZ::Vector3::CreateAxisZ()); - - m_zLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); - m_zLinearManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_zLinearManipulator->SetAxis(AZ::Vector3::CreateAxisY()); - - m_yzPlanarManipulator = AzToolsFramework::PlanarManipulator::MakeShared(worldTransform); - m_yzPlanarManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_yzPlanarManipulator->SetAxes(AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ()); - - ConfigureLinearView(ArrowLength - , AZ::Color(1.0f, 0.0f, 0.0f, 1.0f) - , AZ::Color(0.0f, 1.0f, 0.0f, 1.0f) - , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); - - ConfigurePlanarView(AZ::Color(0.0f, 1.0f, 0.0f, 1.0f) - , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); - - // Position and orientate manipulators - AZ::Transform displacementTransform = localTransform; - AZ::Vector3 displacementTranslate = localRotation.TransformVector(AZ::Vector3(ConeHeight, 0.0f, 0.0f)); - displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); - - m_yLinearManipulator->SetLocalTransform(displacementTransform); - m_zLinearManipulator->SetLocalTransform(displacementTransform); - m_yzPlanarManipulator->SetLocalTransform(displacementTransform); - - // Initialize rotation manipulator for rotating cone - m_xRotationManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); - m_xRotationManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_xRotationManipulator->SetAxis(AZ::Vector3::CreateAxisX()); - m_xRotationManipulator->SetLocalTransform(localTransform); - - const AZ::Color xRotationManipulatorColor = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f); - m_xRotationManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( - *m_xRotationManipulator, xRotationManipulatorColor, - XRotationManipulatorRadius, XRotationManipulatorWidth, AzToolsFramework::DrawHalfDottedCircle)); - - AZStd::shared_ptr sharedRotationState = - AZStd::make_shared(); - - struct SharedState - { - AngleLimitsFloatPair m_startValues; - }; - auto sharedState = AZStd::make_shared(); - - m_yLinearManipulator->InstallLeftMouseDownCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable - { - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - sharedState->m_startValues = currentValue; - }); - - m_yLinearManipulator->InstallMouseMoveCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action) - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - const AZ::Quaternion localRotation = localTransform.GetRotation(); - const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis)); - const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * ConeHeight; - const float newBaseY = originalBaseY + axisDisplacement; - const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / ConeHeight)), m_min, m_max); - - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValuePair - , m_name - , AngleLimitsFloatPair(newAngle, sharedState->m_startValues.second)); - - m_yLinearManipulator->SetBoundsDirty(); - }); - - m_zLinearManipulator->InstallLeftMouseDownCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable - { - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - sharedState->m_startValues = currentValue; - }); - - m_zLinearManipulator->InstallMouseMoveCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action) - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - const AZ::Quaternion localRotation = localTransform.GetRotation(); - const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis)); - const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * ConeHeight; - const float newBaseZ = originalBaseZ + axisDisplacement; - const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / ConeHeight)), m_min, m_max); - - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValuePair - , m_name - , AngleLimitsFloatPair(sharedState->m_startValues.first, newAngle)); - - m_zLinearManipulator->SetBoundsDirty(); - }); - - m_yzPlanarManipulator->InstallLeftMouseDownCallback( - [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& /*action*/) mutable - { - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - sharedState->m_startValues = currentValue; - }); - - m_yzPlanarManipulator->InstallMouseMoveCallback( - [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& action) - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - const AZ::Quaternion localRotation = localTransform.GetRotation(); - - const float axisDisplacementY = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisY())); - const float axisDisplacementZ = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisZ())); - const float axisDisplacement = axisDisplacementZ > axisDisplacementY? axisDisplacementZ : axisDisplacementY; - - const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * ConeHeight; - const float newBaseY = originalBaseY + axisDisplacement; - const float newAngleY = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / ConeHeight)), m_min, m_max); - - const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * ConeHeight; - const float newBaseZ = originalBaseZ + axisDisplacement; - const float newAngleZ = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / ConeHeight)), m_min, m_max); - - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValuePair - , m_name - , AngleLimitsFloatPair(newAngleY, newAngleZ)); - - m_yzPlanarManipulator->SetBoundsDirty(); - }); - - struct SharedStateXRotate - { - AZ::Transform m_startTM; - }; - auto sharedStateXRotate = AZStd::make_shared(); - - auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized(); - sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ()); - sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity(); - - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - - sharedRotationState->m_valuePair = currentValue; - }; - - auto mouseDownRotateXCallback = [this, sharedStateXRotate]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - PhysX::EditorJointRequestBus::EventResult(sharedStateXRotate->m_startTM - , m_entityComponentId - , &PhysX::EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - }; - - m_xRotationManipulator->InstallLeftMouseDownCallback(mouseDownRotateXCallback); - - m_xRotationManipulator->InstallMouseMoveCallback( - [this, sharedStateXRotate] - (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; - - AZ::Transform newTransform = AZ::Transform::CreateIdentity(); - newTransform = sharedStateXRotate->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta); - - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetVector3Value - , PhysX::EditorJointComponentMode::s_parameterPosition - , newTransform.GetTranslation()); - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetVector3Value - , PhysX::EditorJointComponentMode::s_parameterRotation - , newTransform.GetRotation().GetEulerDegrees()); - - m_yLinearManipulator->SetLocalOrientation(manipulatorOrientation); - m_zLinearManipulator->SetLocalOrientation(manipulatorOrientation); - m_yLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisY())); - m_zLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisZ())); - m_xRotationManipulator->SetLocalOrientation(manipulatorOrientation); - - m_yLinearManipulator->SetBoundsDirty(); - m_zLinearManipulator->SetBoundsDirty(); - m_xRotationManipulator->SetBoundsDirty(); - }); - - m_xRotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - m_yLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - m_zLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - m_yzPlanarManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); - - Refresh(); - } - - EditorSubComponentModeAngleCone::~EditorSubComponentModeAngleCone() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - - m_xRotationManipulator->Unregister(); - m_yLinearManipulator->Unregister(); - m_zLinearManipulator->Unregister(); - m_yzPlanarManipulator->Unregister(); - } - - void EditorSubComponentModeAngleCone::Refresh() - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - float coneHeight = ConeHeight; - AngleLimitsFloatPair yzSwingAngleLimits; - EditorJointRequestBus::EventResult( - yzSwingAngleLimits, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - - // Draw inverted cone (negative cone height) if angles are larger than 90 deg. - if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f) - { - coneHeight = -ConeHeight; - } - - // reposition manipulators - const AZ::Quaternion localRotation = localTransform.GetRotation(); - const AZ::Vector3 linearManipulatorOffset = localTransform.GetTranslation() + localRotation.TransformVector(AZ::Vector3(coneHeight, 0.0f, 0.0f)); - - m_xRotationManipulator->SetLocalTransform(localTransform); - m_xRotationManipulator->SetBoundsDirty(); - - localTransform.SetTranslation(linearManipulatorOffset); - - m_yLinearManipulator->SetLocalTransform(localTransform); - m_zLinearManipulator->SetLocalTransform(localTransform); - m_yzPlanarManipulator->SetLocalTransform(localTransform); - m_yLinearManipulator->SetBoundsDirty(); - m_zLinearManipulator->SetBoundsDirty(); - m_yzPlanarManipulator->SetBoundsDirty(); - } - - void EditorSubComponentModeAngleCone::ConfigureLinearView( - float axisLength, [[maybe_unused]] const AZ::Color& axis1Color, const AZ::Color& axis2Color, - const AZ::Color& axis3Color) - { - const float coneLength = 0.28f; - const float coneRadius = 0.07f; - - const auto configureLinearView = [coneLength, axisLength, coneRadius]( - AzToolsFramework::LinearManipulator* linearManipulator, const AZ::Color& color) - { - AzToolsFramework::ManipulatorViews views; - views.emplace_back(CreateManipulatorViewLine( - *linearManipulator, color, axisLength, AzToolsFramework::ManipulatorLineBoundWidth())); - views.emplace_back(CreateManipulatorViewCone( - *linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength), - coneLength, coneRadius)); - linearManipulator->SetViews(AZStd::move(views)); - }; - - configureLinearView(m_yLinearManipulator.get(), axis2Color); - configureLinearView(m_zLinearManipulator.get(), axis3Color); - } - - void EditorSubComponentModeAngleCone::ConfigurePlanarView(const AZ::Color& planeColor, - const AZ::Color& plane2Color) - { - const float planeSize = 0.6f; - AzToolsFramework::ManipulatorViews views; - views.emplace_back(CreateManipulatorViewQuad( - *m_yzPlanarManipulator - , planeColor - , plane2Color - , planeSize)); - m_yzPlanarManipulator->SetViews(AZStd::move(views)); - } - - void EditorSubComponentModeAngleCone::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - AZ::u32 stateBefore = debugDisplay.GetState(); - debugDisplay.CullOff(); - - debugDisplay.PushMatrix(worldTransform); - debugDisplay.PushMatrix(localTransform); - - const float xAxisArrowLength = 2.0f; - debugDisplay.SetColor(AZ::Color(1.0f, 0.0f, 0.0f, 1.0f)); - debugDisplay.DrawArrow(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(xAxisArrowLength, 0.0f, 0.0f)); - - AngleLimitsFloatPair yzSwingAngleLimits; - EditorJointRequestBus::EventResult( - yzSwingAngleLimits, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - - const AZ::u32 numEllipseSamples = 16; - AZ::Vector3 ellipseSamples[numEllipseSamples]; - float coneHeight = ConeHeight; - - // Draw inverted cone if angles are larger than 90 deg. - if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f) - { - coneHeight = -ConeHeight; - } - - // Compute points along perimeter of cone base - const float coney = tanf(AZ::DegToRad(yzSwingAngleLimits.first)) * coneHeight; - const float conez = tanf(AZ::DegToRad(yzSwingAngleLimits.second)) * coneHeight; - const float step = AZ::Constants::TwoPi / numEllipseSamples; - for (size_t i = 0; i < numEllipseSamples; ++i) - { - const float angleStep = step * i; - ellipseSamples[i].SetX(coneHeight); - ellipseSamples[i].SetY(conez * sin(angleStep)); - ellipseSamples[i].SetZ(coney * cos(angleStep)); - } - - // draw cone - for (size_t i = 0; i < numEllipseSamples; ++i) - { - size_t nextIndex = i + 1; - if (i == numEllipseSamples - 1) - { - nextIndex = 0; - } - - // draw cone sides - debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 0.2f)); - debugDisplay.DrawTri(AZ::Vector3(0.0f, 0.0f, 0.0f), ellipseSamples[i], ellipseSamples[nextIndex]); - - // draw parameter of cone base - debugDisplay.SetColor(AZ::Color(0.4f, 0.4f, 0.4f, 0.4f)); - debugDisplay.DrawLine(ellipseSamples[i], ellipseSamples[nextIndex]); - } - - // draw axis lines at base of cone, and from tip to base. - debugDisplay.SetColor(AZ::Color(0.5f, 0.5f, 0.5f, 0.6f)); - debugDisplay.DrawLine(ellipseSamples[0], ellipseSamples[numEllipseSamples/2]); - debugDisplay.DrawLine(ellipseSamples[numEllipseSamples*3/4], ellipseSamples[numEllipseSamples/4]); - debugDisplay.DrawLine(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(coneHeight, 0.0f, 0.0f)); - - debugDisplay.PopMatrix();//pop local transform - debugDisplay.PopMatrix();//pop world transform - debugDisplay.SetState(stateBefore); - - // reposition and reorientate manipulators - Refresh(); - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h deleted file mode 100644 index bf113b4be1..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h +++ /dev/null @@ -1,63 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include -#include -#include -#include - -namespace AzToolsFramework -{ - class AngularManipulator; - class LinearManipulator; - class PlanarManipulator; -} - -namespace PhysX -{ - class EditorSubComponentModeAngleCone - : public PhysX::EditorSubComponentModeBase - , private AzFramework::EntityDebugDisplayEventBus::Handler - { - public: - EditorSubComponentModeAngleCone( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , float max - , float min); - ~EditorSubComponentModeAngleCone(); - - // PhysX::EditorSubComponentModeBase - void Refresh() override; - - private: - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - void ConfigureLinearView( - float axisLength, - const AZ::Color& axis1Color, const AZ::Color& axis2Color, - const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)); - - void ConfigurePlanarView(const AZ::Color& planeColor = AZ::Color(0.0f, 1.0f, 0.0f, 0.5f) - , const AZ::Color& plane2Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)); - - AZStd::shared_ptr m_xRotationManipulator; - AZStd::shared_ptr m_yLinearManipulator; - AZStd::shared_ptr m_zLinearManipulator; - AZStd::shared_ptr m_yzPlanarManipulator; - - float m_max = FLT_MAX; - float m_min = 0.0f; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp deleted file mode 100644 index 6fa74a3f05..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp +++ /dev/null @@ -1,318 +0,0 @@ - -/* - * 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 -#include -#include - -#include -#include -#include - -namespace -{ - const float Alpha = 0.6f; - const AZ::Color ColorDefault = AZ::Color(1.0f, 1.0f, 1.0f, Alpha); - const AZ::Color ColorFirst = AZ::Color(1.0f, 0.0f, 0.0f, Alpha); - const AZ::Color ColorSecond = AZ::Color(0.0f, 1.0f, 0.0f, Alpha); - const AZ::Color ColorSweepArc = AZ::Color(1.0f, 1.0f, 1.0f, Alpha); - - const float SweepLineDisplaceFactor = 0.5f; - const float SweepLineThickness = 1.0f; - const float SweepLineGranularity = 1.0f; -} - -namespace PhysX -{ - EditorSubComponentModeAnglePair::EditorSubComponentModeAnglePair( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , const AZ::Vector3& axis - , float firstMax - , float firstMin - , float secondMax - , float secondMin) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) - , m_axis(axis) - , m_firstMax(firstMax) - , m_firstMin(firstMin) - , m_secondMax(secondMax) - , m_secondMin(secondMin) - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - const AZ::Quaternion localRotation = localTransform.GetRotation(); - - AZ::Vector3 displacement = m_axis; - AZ::Transform displacementTransform = localTransform; - AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement); - displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); - - m_firstManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); - m_firstManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_firstManipulator->SetAxis(m_axis); - m_firstManipulator->SetLocalTransform(displacementTransform); - - displacement = -m_axis; - displacementTranslate = localRotation.TransformVector(displacement); - displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); - m_secondManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); - m_secondManipulator->AddEntityComponentIdPair(m_entityComponentId); - m_secondManipulator->SetAxis(m_axis); - m_secondManipulator->SetLocalTransform(displacementTransform); - - const float manipulatorRadius = 2.0f; - const float manipulatorWidth = 0.05f; - m_firstManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( - *m_firstManipulator, ColorFirst, - manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle)); - - m_secondManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( - *m_secondManipulator, ColorSecond, - manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle)); - - Refresh(); - - AZStd::shared_ptr sharedRotationState = - AZStd::make_shared(); - - auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - const AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized(); - sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ()); - sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity(); - - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - - sharedRotationState->m_valuePair = currentValue; - }; - - m_firstManipulator->InstallLeftMouseDownCallback(mouseDownCallback); - - m_secondManipulator->InstallLeftMouseDownCallback(mouseDownCallback); - - m_firstManipulator->InstallMouseMoveCallback( - [this, sharedRotationState] - (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - float angleDelta; - AZ::Quaternion manipulatorOrientation; - const float newValue = MouseMove(sharedRotationState, action, true, angleDelta, manipulatorOrientation); - if (newValue > m_firstMax || newValue < m_firstMin) - { - return; - } - m_firstManipulator->SetLocalOrientation(manipulatorOrientation); - const float newFirstValue = AZ::GetClamp(sharedRotationState->m_valuePair.first + angleDelta, m_firstMin, m_firstMax); - - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValuePair - , m_name - , AngleLimitsFloatPair(newFirstValue, sharedRotationState->m_valuePair.second)); - - m_firstManipulator->SetBoundsDirty(); - }); - - m_secondManipulator->InstallMouseMoveCallback( - [this, sharedRotationState] - (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - float angleDelta; - AZ::Quaternion manipulatorOrientation; - const float newValue = MouseMove(sharedRotationState, action, false, angleDelta, manipulatorOrientation); - if (newValue > m_secondMax || newValue < m_secondMin) - { - return; //Not handling values exceeding limits - } - - m_secondManipulator->SetLocalOrientation(manipulatorOrientation); - float newSecondValue = AZ::GetClamp(sharedRotationState->m_valuePair.second + angleDelta, m_secondMin, m_secondMax); - - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValuePair - , m_name - , AngleLimitsFloatPair(sharedRotationState->m_valuePair.first, newSecondValue)); - - m_secondManipulator->SetBoundsDirty(); - }); - - - m_firstManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - m_secondManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); - } - - EditorSubComponentModeAnglePair::~EditorSubComponentModeAnglePair() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - - m_firstManipulator->Unregister(); - m_secondManipulator->Unregister(); - } - - void EditorSubComponentModeAnglePair::Refresh() - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - const AZ::Quaternion localRotation = localTransform.GetRotation(); - - AZ::Transform displacementTransform = localTransform; - AZ::Vector3 displacement = m_axis; - AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement); - displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); - m_firstManipulator->SetLocalTransform(displacementTransform); - - displacement = -m_axis; - displacementTranslate = localRotation.TransformVector(displacement); - displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); - m_secondManipulator->SetLocalTransform(displacementTransform); - - m_firstManipulator->SetBoundsDirty(); - m_secondManipulator->SetBoundsDirty(); - } - - void EditorSubComponentModeAnglePair::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - AngleLimitsFloatPair currentValue; - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , m_name); - - const float size = 2.0f; - AZ::Vector3 axisPoint = m_axis * size * 0.5f; - - AZStd::array points = { - -axisPoint - , axisPoint - , axisPoint - , -axisPoint - }; - - if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON) - { - points[2].SetZ(size); - points[3].SetZ(size); - } - else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON) - { - points[2].SetX(size); - points[3].SetX(size); - } - else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON) - { - points[2].SetX(size); - points[3].SetX(size); - } - - AZ::u32 stateBefore = debugDisplay.GetState(); - debugDisplay.CullOff(); - debugDisplay.SetAlpha(Alpha); - - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - debugDisplay.PushMatrix(worldTransform); - debugDisplay.PushMatrix(localTransform); - - debugDisplay.SetColor(ColorSweepArc); - - const AZ::Vector3 zeroVector = AZ::Vector3::CreateZero(); - const AZ::Vector3 posPosition = m_axis * SweepLineDisplaceFactor; - const AZ::Vector3 negPosition = -posPosition; - debugDisplay.DrawArc(posPosition, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis); - debugDisplay.DrawArc(zeroVector, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis); - debugDisplay.DrawArc(negPosition, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis); - debugDisplay.DrawArc(posPosition, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis); - debugDisplay.DrawArc(zeroVector, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis); - debugDisplay.DrawArc(negPosition, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis); - - AZ::Quaternion firstRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.first)); - AZ::Transform firstTM = AZ::Transform::CreateFromQuaternion(firstRotate); - debugDisplay.PushMatrix(firstTM); - debugDisplay.SetColor(ColorFirst); - debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); - debugDisplay.PopMatrix(); - - AZ::Quaternion secondRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.second)); - AZ::Transform secondTM = AZ::Transform::CreateFromQuaternion(secondRotate); - debugDisplay.PushMatrix(secondTM); - debugDisplay.SetColor(ColorSecond); - debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); - debugDisplay.PopMatrix(); - - debugDisplay.SetColor(ColorDefault); - debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); - - debugDisplay.PopMatrix(); // pop local transform - debugDisplay.PopMatrix(); // pop global transform - debugDisplay.SetState(stateBefore); - - // reposition and reorientate manipulators - Refresh(); - } - - float EditorSubComponentModeAnglePair::MouseMove(AZStd::shared_ptr& sharedRotationState - , const AzToolsFramework::AngularManipulator::Action& action - , bool isFirstValue - , float& angleDelta - , AZ::Quaternion& manipulatorOrientation) - { - sharedRotationState->m_savedOrientation = action.m_current.m_delta.GetInverseFull(); - angleDelta = 0.0f; - AZ::Vector3 axis = m_axis; - sharedRotationState->m_savedOrientation.ConvertToAxisAngle(axis, angleDelta); - // Polarity of axis is switched by ConvertToAxisAngle call depending on direction of rotation - if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON) - { - angleDelta = AZ::RadToDeg(angleDelta) * axis.GetX(); - } - else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON) - { - angleDelta = AZ::RadToDeg(angleDelta) * axis.GetY(); - } - else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON) - { - angleDelta = AZ::RadToDeg(angleDelta) * axis.GetZ(); - } - - manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; - - if (isFirstValue) - { - return sharedRotationState->m_valuePair.first + angleDelta; - } - else - { - return sharedRotationState->m_valuePair.second + angleDelta; - } - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h deleted file mode 100644 index cb96570ebe..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h +++ /dev/null @@ -1,66 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include -#include - -#include -#include - -namespace PhysX -{ - class EditorSubComponentModeAnglePair - : public PhysX::EditorSubComponentModeBase - , private AzFramework::EntityDebugDisplayEventBus::Handler - { - public: - EditorSubComponentModeAnglePair( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , const AZ::Vector3& axis - , float firstMax - , float firstMin - , float secondMax - , float secondMin); - ~EditorSubComponentModeAnglePair(); - - // PhysX::EditorSubComponentModeBase - void Refresh() override; - - private: - struct SharedRotationState - { - AZ::Vector3 m_axis; - AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity(); - AngleLimitsFloatPair m_valuePair; - }; - - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - float MouseMove(AZStd::shared_ptr& sharedRotationState - , const AzToolsFramework::AngularManipulator::Action& action - , bool isFirstValue - , float& angleDelta - , AZ::Quaternion& manipulatorOrientation); - - AZStd::shared_ptr m_firstManipulator; - AZStd::shared_ptr m_secondManipulator; - - AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); - float m_firstMax = FLT_MAX; - float m_firstMin = -FLT_MAX; - float m_secondMax = FLT_MAX; - float m_secondMin = -FLT_MAX; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp deleted file mode 100644 index 1e02d52859..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -/* - * 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 -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeBase::EditorSubComponentModeBase( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name) - : m_entityComponentId(entityComponentIdPair), - m_name(name) - { - // The first time this is called, no object will respond to this bus call as no object is connected at the address, - // and m_jointTypeDrawer will remain as a nullptr. - EditorJointTypeDrawerBus::EventResult(m_jointTypeDrawer, - EditorJointTypeDrawerId(componentType, EditorSubComponentModeNameCrc(name)), - &EditorJointTypeDrawerBus::Events::GetEditorJointTypeDrawer); - - if (!m_jointTypeDrawer) - { - // Once this is called, the bus call to GetEditorJointTypeDrawer above will no longer get a null response, until m_jointTypeDrawer is destroyed. - m_jointTypeDrawer = AZStd::make_shared(componentType, - AzToolsFramework::GetEntityContextId(), - m_name); - } - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h deleted file mode 100644 index 09e06927f3..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h +++ /dev/null @@ -1,55 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include - -namespace AzFramework -{ - class DebugDisplayRequests; - struct ViewportInfo; -} - -namespace AzToolsFramework -{ - namespace ViewportInteraction - { - struct MouseInteractionEvent; - } -} - -namespace PhysX -{ - class EditorJointTypeDrawer; - - /// Base class for (joints) sub-component modes. - class EditorSubComponentModeBase - { - public: - EditorSubComponentModeBase( - const AZ::EntityComponentIdPair& entityComponentIdPair, - const AZ::Uuid& componentType, - const AZStd::string& name); - virtual ~EditorSubComponentModeBase() = default; - - /// Additional mouse handling by sub-component mode. Does not absorb mouse event. - virtual void HandleMouseInteraction( - [[maybe_unused]] const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) {}; - - virtual void Refresh() = 0; - - AZStd::string m_name;///< Name of sub-component mode. - - protected: - AZ::EntityComponentIdPair m_entityComponentId;///< Entity Id and component pair. - - private: - AZStd::shared_ptr m_jointTypeDrawer;///< Drawer that draws component type specific objects in the viewport. - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp deleted file mode 100644 index 378e1fb982..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp +++ /dev/null @@ -1,133 +0,0 @@ - -/* - * 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 -#include - -#include -#include - -#include -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeLinear::EditorSubComponentModeLinear( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , float exponent - , float max - , float min) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) - , m_exponent(exponent) - , m_inverseExponent(1.0f/exponent) - , m_max(max) - , m_min(min) - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - m_manipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); - m_manipulator->AddEntityComponentIdPair(m_entityComponentId); - m_manipulator->SetAxis(AZ::Vector3::CreateAxisX()); - m_manipulator->SetLocalTransform(localTransform); - - Refresh(); - - const AZ::Color manipulatorColor(0.3f, 0.3f, 0.3f, 1.0f); - const float manipulatorSize = 0.05f; - - AzToolsFramework::ManipulatorViews views; - views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(manipulatorColor - , manipulatorSize)); - m_manipulator->SetViews(AZStd::move(views)); - - struct SharedState - { - float m_startingValue = 0.0f; - }; - auto sharedState = AZStd::make_shared(); - - m_manipulator->InstallLeftMouseDownCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable - { - float currentValue = 0.0f; - - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValue - , m_name); - sharedState->m_startingValue = currentValue; - }); - - m_manipulator->InstallMouseMoveCallback( - [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action) - { - const float axisDisplacement = action.LocalPositionOffset().Dot(action.m_fixed.m_axis); - - float newValue = AZ::GetClamp(sharedState->m_startingValue + DisplacementToDeltaValue(axisDisplacement), m_min, m_max); - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetLinearValue - , m_name - , newValue); - - const AZ::Vector3 localPosition = action.LocalPosition().GetMax(AZ::Vector3(0.01f, 0.0f, 0.0f)); - m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(localPosition)); - m_manipulator->SetBoundsDirty(); - }); - - m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - } - - EditorSubComponentModeLinear::~EditorSubComponentModeLinear() - { - m_manipulator->Unregister(); - } - - void EditorSubComponentModeLinear::Refresh() - { - float currentValue = 0.0f; - - EditorJointRequestBus::EventResult( - currentValue, m_entityComponentId - , &EditorJointRequests::GetLinearValue - , m_name); - - m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX() * ValueToDisplacement(currentValue))); - } - - float EditorSubComponentModeLinear::DisplacementToDeltaValue(float displacement) const - { - if (displacement > 0.0f) - { - return powf(displacement, m_exponent); - } - else if (displacement < 0.0f) - { - return -powf(fabsf(displacement), m_exponent); - } - else - { - return 0.0f; - } - } - - float EditorSubComponentModeLinear::ValueToDisplacement(float value) const - { - return powf(value, m_inverseExponent); - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h deleted file mode 100644 index 4d44d4aad4..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h +++ /dev/null @@ -1,46 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include - -namespace AzToolsFramework -{ - class LinearManipulator; -} - -namespace PhysX -{ - class EditorSubComponentModeLinear - : public PhysX::EditorSubComponentModeBase - { - public: - EditorSubComponentModeLinear( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , float exponent - , float max - , float min); - ~EditorSubComponentModeLinear(); - - // PhysX::EditorSubComponentModeBase - void Refresh() override; - - private: - float DisplacementToDeltaValue(float displacement) const; - float ValueToDisplacement(float value) const; - - float m_exponent = 1.0f; - float m_inverseExponent = 1.0f; - AZStd::shared_ptr m_manipulator; - float m_max = FLT_MAX; - float m_min = -FLT_MAX; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp deleted file mode 100644 index 7586ecc955..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp +++ /dev/null @@ -1,151 +0,0 @@ - -/* - * 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 -#include -#include -#include - -#include -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeRotation::EditorSubComponentModeRotation( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) - { - CreateManipulators(); - RegisterManipulators(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); - } - - EditorSubComponentModeRotation::~EditorSubComponentModeRotation() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - UnregisterManipulators(); - } - - void EditorSubComponentModeRotation::Refresh() - { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - for (auto rotationManipulator : m_rotationManipulators) - { - rotationManipulator->SetLocalTransform(localTransform); - rotationManipulator->SetBoundsDirty(); - } - } - - void EditorSubComponentModeRotation::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - [[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay) - { - Refresh(); //Update position and orientation of manipulators. - } - - void EditorSubComponentModeRotation::CreateManipulators() - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - const AZ::Quaternion worldRotation = worldTransform.GetRotation(); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - const AZStd::array axes = { AZ::Vector3::CreateAxisX() - , AZ::Vector3::CreateAxisY() - , AZ::Vector3::CreateAxisZ()}; - - const AZStd::array colors = { AZ::Color(1.0f, 0.0f, 0.0f, 1.0f) - , AZ::Color(0.0f, 1.0f, 0.0f, 1.0f) - , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)}; - - for (AZ::u32 i = 0; i < 3; ++i) - { - m_rotationManipulators[i] = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); - m_rotationManipulators[i]->AddEntityComponentIdPair(m_entityComponentId); - m_rotationManipulators[i]->SetAxis(axes[i]); - m_rotationManipulators[i]->SetLocalTransform(localTransform); - const float manipulatorRadius = 2.0f; - m_rotationManipulators[i]->SetView(AzToolsFramework::CreateManipulatorViewCircle( - *m_rotationManipulators[i], colors[i], manipulatorRadius, - AzToolsFramework::ManipulatorCicleBoundWidth(), AzToolsFramework::DrawHalfDottedCircle)); - } - - Refresh(); - InstallManipulatorMouseCallbacks(); - } - - void EditorSubComponentModeRotation::InstallManipulatorMouseCallbacks() - { - struct SharedState - { - AZ::Transform m_startTM; - }; - auto sharedState = AZStd::make_shared(); - - auto mouseDownRotateXCallback = [this, sharedState]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - PhysX::EditorJointRequestBus::EventResult(sharedState->m_startTM - , m_entityComponentId - , &PhysX::EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - }; - - for (AZ::u32 index = 0; index < 3; ++index) - { - m_rotationManipulators[index]->InstallLeftMouseDownCallback(mouseDownRotateXCallback); - - m_rotationManipulators[index]->InstallMouseMoveCallback( - [this, index, sharedState] - (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void - { - const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; - - AZ::Transform newTransform = AZ::Transform::CreateIdentity(); - newTransform = sharedState->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta); - - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetVector3Value - , PhysX::EditorJointComponentMode::s_parameterRotation - , newTransform.GetRotation().GetEulerDegrees()); - - m_rotationManipulators[index]->SetLocalOrientation(manipulatorOrientation); - m_rotationManipulators[index]->SetBoundsDirty(); - }); - } - } - - void EditorSubComponentModeRotation::RegisterManipulators() - { - for (auto rotationManipulator : m_rotationManipulators) - { - rotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - } - } - - void EditorSubComponentModeRotation::UnregisterManipulators() - { - for (auto rotationManipulator : m_rotationManipulators) - { - rotationManipulator->Unregister(); - } - } -} diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h deleted file mode 100644 index 349738909a..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h +++ /dev/null @@ -1,48 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include -#include - -namespace AzToolsFramework -{ - class AngularManipulator; -} - -namespace PhysX -{ - class EditorSubComponentModeRotation - : public PhysX::EditorSubComponentModeBase - , private AzFramework::EntityDebugDisplayEventBus::Handler - { - public: - EditorSubComponentModeRotation( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name); - ~EditorSubComponentModeRotation(); - - // PhysX::EditorSubComponentModeBase - void Refresh() override; - - private: - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - void CreateManipulators(); - void InstallManipulatorMouseCallbacks(); - void RegisterManipulators(); - void UnregisterManipulators(); - - AZStd::array, 3> m_rotationManipulators; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp deleted file mode 100644 index b086eb64ff..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp +++ /dev/null @@ -1,97 +0,0 @@ - -/* - * 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 -#include -#include -#include - -#include -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeSnapPosition::EditorSubComponentModeSnapPosition( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , bool selectLeadOnSnap) - : EditorSubComponentModeSnap(entityComponentIdPair, componentType, name) - , m_selectLeadOnSnap(selectLeadOnSnap) - { - InitMouseDownCallBack(); - m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); - } - - EditorSubComponentModeSnapPosition::~EditorSubComponentModeSnapPosition() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - m_manipulator->Unregister(); - } - - void EditorSubComponentModeSnapPosition::DisplaySpecificSnapType( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay, - const AZ::Vector3& jointPosition, - const AZ::Vector3& snapDirection, - const float snapLength) - { - const float arrowLength = 1.0f; - const float iconGap = 1.0f; - const AZ::Vector3 iconPosition = jointPosition + - (snapDirection * (snapLength + arrowLength + iconGap)); - - debugDisplay.SetColor(AZ::Colors::Red); - debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(arrowLength, 0.0f, 0.0f)); - debugDisplay.SetColor(AZ::Colors::Green); - debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.2f, arrowLength, 0.2f)); - debugDisplay.SetColor(AZ::Colors::Blue); - debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.0f, 0.0f, arrowLength)); - } - - void EditorSubComponentModeSnapPosition::InitMouseDownCallBack() - { - m_manipulator->InstallLeftMouseDownCallback( - [this](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable - { - if (!m_pickedEntity.IsValid()) - { - return; - } - - const AZ::Vector3 newLocalPosition = PhysX::Utils::ComputeJointLocalTransform( - PhysX::Utils::GetEntityWorldTransformWithScale(m_pickedEntity), - PhysX::Utils::GetEntityWorldTransformWithScale(m_entityComponentId.GetEntityId())).GetTranslation(); - - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetVector3Value - , PhysX::EditorJointComponentMode::s_parameterPosition - , newLocalPosition); - - const bool selectedEntityIsNotJointEntity = m_pickedEntity != m_entityComponentId.GetEntityId(); - - AZ_Error("EditorSubComponentModeSnapPosition", - selectedEntityIsNotJointEntity, - "Joint's lead entity cannot be the same as the entity in which the joint resides. Select lead entity on snap failed."); - - if (m_selectLeadOnSnap && - selectedEntityIsNotJointEntity) - { - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetEntityIdValue - , PhysX::EditorJointComponentMode::s_parameterLeadEntity - , m_pickedEntity); - } - - m_manipulator->SetBoundsDirty(); - }); - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h deleted file mode 100644 index d2fe803431..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include - -namespace PhysX -{ - /// This sub-component mode gets an entity position from its base class on mouse down - /// and sets a position (AZ::Vector3) value in the component that uses it. - class EditorSubComponentModeSnapPosition - : public EditorSubComponentModeSnap - { - public: - EditorSubComponentModeSnapPosition( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name - , bool selectLeadOnSnap); - ~EditorSubComponentModeSnapPosition() override; - - protected: - // PhysX::EditorSubComponentModeSnap - void DisplaySpecificSnapType( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay, - const AZ::Vector3& jointPosition, - const AZ::Vector3& snapDirection, - float snapLength) override; - - void InitMouseDownCallBack() override; - - private: - bool m_selectLeadOnSnap = true; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp deleted file mode 100644 index c68e058e29..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp +++ /dev/null @@ -1,122 +0,0 @@ - -/* - * 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 -#include -#include - -#include -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeSnapRotation::EditorSubComponentModeSnapRotation( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name) - : EditorSubComponentModeSnap(entityComponentIdPair, componentType, name) - { - InitMouseDownCallBack(); - m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); - } - - EditorSubComponentModeSnapRotation::~EditorSubComponentModeSnapRotation() - { - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - m_manipulator->Unregister(); - } - - void EditorSubComponentModeSnapRotation::DisplaySpecificSnapType( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay, - const AZ::Vector3& jointPosition, - const AZ::Vector3& snapDirection, - const float snapLength) - { - const float circleRadius = 0.5f; - const float iconGap = 1.0f; - - const AZ::Vector3 iconPosition = jointPosition + - (snapDirection * (snapLength + circleRadius * 2.0f + iconGap)); - - debugDisplay.SetColor(AZ::Colors::Red); - debugDisplay.DrawCircle(iconPosition, circleRadius, 0); - debugDisplay.SetColor(AZ::Colors::Green); - debugDisplay.DrawCircle(iconPosition, circleRadius, 1); - debugDisplay.SetColor(AZ::Colors::Blue); - debugDisplay.DrawCircle(iconPosition, circleRadius, 2); - } - - void EditorSubComponentModeSnapRotation::InitMouseDownCallBack() - { - m_manipulator->InstallLeftMouseDownCallback( - [this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action) mutable - { - if (!m_pickedEntity.IsValid()) - { - return; - } - - AZ::EntityId leadEntityId; - PhysX::EditorJointRequestBus::EventResult(leadEntityId, - m_entityComponentId, - &PhysX::EditorJointRequests::GetEntityIdValue, - PhysX::EditorJointComponentMode::s_parameterLeadEntity); - - if (leadEntityId.IsValid() && m_pickedEntity == leadEntityId) - { - AZ_Warning("EditorsubComponentModeSnapRotation", - false, - "The entity %s is the lead of the joint. Please snap rotation (or orientation) of joint to another entity that is not the lead entity.", - GetPickedEntityName().c_str()); - return; - } - - AZ::Transform worldTransform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult( - worldTransform, m_entityComponentId.GetEntityId(), &AZ::TransformInterface::GetWorldTM); - worldTransform.ExtractUniformScale(); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - AZ::Transform pickedEntityTransform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult( - pickedEntityTransform, m_pickedEntity, &AZ::TransformInterface::GetWorldTM); - - const AZ::Transform worldTransformInv = worldTransform.GetInverse(); - const AZ::Vector3 pickedLocalPosition = worldTransformInv.TransformVector(pickedEntityTransform.GetTranslation()) - localTransform.GetTranslation(); - - if (abs(pickedLocalPosition.GetLength()) < FLT_EPSILON) - { - AZ_Warning("EditorsubComponentModeSnapRotation", - false, - "The entity %s is too close to the joint position. Please snap rotation to an entity that is not at the position of the joint.", - GetPickedEntityName().c_str()); - return; - } - - const AZ::Vector3 targetDirection = pickedLocalPosition.GetNormalized(); - const AZ::Vector3 sourceDirection = AZ::Vector3::CreateAxisX(); - const AZ::Quaternion newLocalRotation = AZ::Quaternion::CreateShortestArc(sourceDirection, targetDirection); - - PhysX::EditorJointRequestBus::Event(m_entityComponentId - , &PhysX::EditorJointRequests::SetVector3Value - , PhysX::EditorJointComponentMode::s_parameterRotation //using rotation parameter name to set the local rotation value - , newLocalRotation.GetEulerDegrees()); - - m_manipulator->SetBoundsDirty(); - }); - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h deleted file mode 100644 index 06d41df206..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h +++ /dev/null @@ -1,38 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include - -namespace PhysX -{ - /// TThis sub-component mode gets an entity position from its base class on mouse down - /// and sets a rotation (AZ::Quaternion) value in the component that uses it. - class EditorSubComponentModeSnapRotation - : public EditorSubComponentModeSnap - { - public: - EditorSubComponentModeSnapRotation( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name); - ~EditorSubComponentModeSnapRotation() override; - - protected: - // PhysX::EditorSubComponentModeSnap - void DisplaySpecificSnapType( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay, - const AZ::Vector3& jointPosition, - const AZ::Vector3& snapDirection, - float snapLength) override; - - void InitMouseDownCallBack() override; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp deleted file mode 100644 index 7e8affb086..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * 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 -#include -#include - -#include -#include -#include - -namespace PhysX -{ - EditorSubComponentModeVec3::EditorSubComponentModeVec3( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) - , m_translationManipulators(AzToolsFramework::TranslationManipulators::Dimensions::Three, - AZ::Transform::Identity(), AZ::Vector3::CreateOne()) - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Vector3 localTranslation; - EditorJointRequestBus::EventResult( - localTranslation, m_entityComponentId - , &EditorJointRequests::GetVector3Value - , m_name); - - m_translationManipulators.SetSpace(worldTransform); - m_translationManipulators.SetLocalPosition(localTranslation); - m_translationManipulators.AddEntityComponentIdPair(m_entityComponentId); - - m_translationManipulators.Register(AzToolsFramework::g_mainManipulatorManagerId); - - AzToolsFramework::ConfigureTranslationManipulatorAppearance3d(&m_translationManipulators); - - m_translationManipulators.InstallLinearManipulatorMouseMoveCallback([this]( - const AzToolsFramework::LinearManipulator::Action& action) - { - OnManipulatorMoved(action.LocalPosition()); - }); - - m_translationManipulators.InstallPlanarManipulatorMouseMoveCallback([this]( - const AzToolsFramework::PlanarManipulator::Action& action) - { - OnManipulatorMoved(action.LocalPosition()); - }); - - m_translationManipulators.InstallSurfaceManipulatorMouseMoveCallback([this]( - const AzToolsFramework::SurfaceManipulator::Action& action) - { - OnManipulatorMoved(action.LocalPosition()); - }); - } - - EditorSubComponentModeVec3::~EditorSubComponentModeVec3() - { - m_translationManipulators.Unregister(); - } - - void EditorSubComponentModeVec3::Refresh() - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Vector3 localTranslation; - EditorJointRequestBus::EventResult( - localTranslation, m_entityComponentId - , &EditorJointRequests::GetVector3Value - , m_name); - - m_translationManipulators.SetSpace(worldTransform); - m_translationManipulators.SetLocalPosition(localTranslation); - m_translationManipulators.SetBoundsDirty(); - } - - void EditorSubComponentModeVec3::OnManipulatorMoved(const AZ::Vector3& position) - { - m_translationManipulators.SetLocalPosition(position); - EditorJointRequestBus::Event( - m_entityComponentId - , &EditorJointRequests::SetVector3Value - , m_name - , position); - } -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h deleted file mode 100644 index 849125eb1c..0000000000 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h +++ /dev/null @@ -1,34 +0,0 @@ - -/* - * 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 - * - */ -#pragma once - -#include -#include - -namespace PhysX -{ - class EditorSubComponentModeVec3 - : public PhysX::EditorSubComponentModeBase - { - public: - EditorSubComponentModeVec3( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name); - ~EditorSubComponentModeVec3(); - - // PhysX::EditorSubComponentModeBase - void Refresh() override; - - private: - void OnManipulatorMoved(const AZ::Vector3& position); - - AzToolsFramework::TranslationManipulators m_translationManipulators; - }; -} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp new file mode 100644 index 0000000000..ce95e27db3 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp @@ -0,0 +1,601 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsComponentMode, AZ::SystemAllocator, 0); + + namespace SubModeData + { + const AZ::Crc32 SwitchToTranslationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotranslationsubmode"); + static const char* TranslationTitle = "Switch to Position Mode"; + static const char* TranslationToolTip = "Position Mode - Change the position of the joint."; + + const AZ::Crc32 SwitchToRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtorotationsubmode"); + static const char* RotationTitle = "Switch to Rotation Mode"; + static const char* RotationToolTip = "Rotation Mode- Change the rotation of the joint."; + + const AZ::Crc32 SwitchToMaxForceSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxforce"); + static const char* MaxForceTitle = "Switch to Max Force Mode"; + static const char* MaxForceToolTip = "Max Force Mode - Change the maximum force allowed before the joint breaks."; + + const AZ::Crc32 SwitchToMaxTorqueSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxtorque"); + static const char* MaxTorqueTitle = "Switch to Max Torque Mode"; + static const char* MaxTorqueToolTip = "Max Torque Mode - Change the maximum torque allowed before the joint breaks."; + + const AZ::Crc32 SwitchToDampingSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtodamping"); + static const char* DampingTitle = "Switch to Damping Mode"; + static const char* DampingToolTip = "Damping Mode - Change the damping strength of the joint when beyond the limit."; + + const AZ::Crc32 SwitchToStiffnessSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtostiffness"); + static const char* StiffnessTitle = "Switch to Stiffness Mode"; + static const char* StiffnessToolTip = "Stiffness Mode - Change the stiffness strength of the joint when beyond the limit."; + + const AZ::Crc32 SwitchToTwistLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotwistlimits"); + static const char* TwistLimitsTitle = "Switch to Twist Limits Mode"; + static const char* TwistLimitsToolTip = "Twist Limits Mode - Change the limits of the joint."; + + const AZ::Crc32 SwitchToSwingLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtoswinglimits"); + static const char* SwingLimitsTitle = "Switch to Swing Limits Mode"; + static const char* SwingLimitsToolTip = "Swing Limits Mode - Change the limits of the joint."; + + const AZ::Crc32 SwitchToSnapPositionSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnapposition"); + static const char* SnapPositionTitle = "Switch to Snap Position Mode"; + static const char* SnapPositionToolTip = "Snap Position Mode - Snap the position of the joint to another Entity."; + + const AZ::Crc32 SwitchToSnapRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnaprotation"); + static const char* SnapRotationTitle = "Switch to Snap Rotation Mode"; + static const char* SnapRotationToolTip = "Snap Rotation Mode - Snap the rotation of the joint toward another Entity."; + + const AZ::Crc32 ResetSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.resetsubmode"); + static const char* ResetTitle = "Reset Current Mode"; + static const char* ResetToolTip = "Reset changes made during this mode edit."; + + } // namespace ActionData + + namespace Internal + { + static AzToolsFramework::ViewportUi::ButtonId RegisterClusterButton( + AzToolsFramework::ViewportUi::ClusterId clusterId, const char* iconName, const char* tooltip) + { + AzToolsFramework::ViewportUi::ButtonId buttonId; + AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( + buttonId, AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateClusterButton, clusterId, + AZStd::string::format(":/stylesheet/img/UI20/toolbar/%s.svg", iconName)); + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, clusterId, buttonId, tooltip); + + return buttonId; + } + + void RefreshUI() + { + // The reason this is in a free function is because ColliderComponentMode + // privately inherits from ToolsApplicationNotificationBus. Trying to invoke + // the bus inside the class scope causes the compiler to complain it's not accessible + // to due private inheritance. + // Using the global namespace operator :: should have fixed that, except there + // is a bug in the Microsoft compiler meaning it doesn't work. So this is a work around. + AzToolsFramework::ToolsApplicationNotificationBus::Broadcast( + &AzToolsFramework::ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values); + } + } // namespace Internal + + JointsComponentMode::JointsComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType) + : AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode(entityComponentIdPair, componentType) + { + m_modeSelectionClusterIds.assign(static_cast(ClusterGroups::GroupCount), AzToolsFramework::ViewportUi::InvalidClusterId); + SetupSubModes(entityComponentIdPair); + + EditorJointRequestBus::Event( + entityComponentIdPair, &EditorJointRequests::SetBoolValue, JointsComponentModeCommon::ParamaterNames::ComponentMode, true); + } + + JointsComponentMode::~JointsComponentMode() + { + EditorJointRequestBus::Event( + GetEntityComponentIdPair(), &EditorJointRequests::SetBoolValue, JointsComponentModeCommon::ParamaterNames::ComponentMode, + false); + + TeardownSubModes(); + m_subModes[m_subMode]->Teardown(GetEntityComponentIdPair()); + } + + void JointsComponentMode::Refresh() + { + m_subModes[m_subMode]->Refresh(GetEntityComponentIdPair()); + } + + AZStd::vector JointsComponentMode::PopulateActionsImpl() + { + const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair(); + + AZStd::vector subModesState; + EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState); + + auto makeActionOverride = [](const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Crc32& actionUri, + const QString& title, const QString& tip,const AZStd::function&& callback) + { + AzToolsFramework::ActionOverride actionOverride; + actionOverride.SetTitle(title); + actionOverride.SetTip(tip); + actionOverride.SetUri(actionUri); + actionOverride.SetEntityComponentIdPair(entityComponentIdPair); + actionOverride.SetCallback(callback); + return actionOverride; + }; + + AZStd::vector actions; + + // translation action + { + AzToolsFramework::ActionOverride translateAction = makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToTranslationSubMode, + SubModeData::TranslationTitle, SubModeData::TranslationToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::Translation, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]); + }); + translateAction.SetKeySequence(QKeySequence(Qt::Key_1)); + actions.emplace_back(translateAction); + } + + // rotation action + { + AzToolsFramework::ActionOverride rotationAction = makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToRotationSubMode, + SubModeData::RotationTitle, SubModeData::RotationToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::Rotation, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation]); + }); + rotationAction.SetKeySequence(QKeySequence(Qt::Key_2)); + actions.emplace_back(rotationAction); + } + + //setup action for other enabled options + for (auto [modeType, parameterString] : subModesState) + { + switch (modeType) + { + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToMaxForceSubMode, + SubModeData::MaxForceTitle, SubModeData::MaxForceToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToMaxTorqueSubMode, + SubModeData::MaxTorqueTitle, SubModeData::MaxTorqueToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::Damping: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToDampingSubMode, + SubModeData::DampingTitle, SubModeData::DampingToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::Damping, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToStiffnessSubMode, + SubModeData::StiffnessTitle, SubModeData::StiffnessToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToTwistLimitsSubMode, + SubModeData::TwistLimitsTitle, SubModeData::TwistLimitsToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToSwingLimitsSubMode, + SubModeData::SwingLimitsTitle, SubModeData::SwingLimitsToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToSnapPositionSubMode, + SubModeData::SnapPositionTitle, SubModeData::SnapPositionToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition]); + })); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation: + { + actions.emplace_back(makeActionOverride( + entityComponentIdPair, SubModeData::SwitchToSnapRotationSubMode, + SubModeData::SnapRotationTitle, SubModeData::SnapRotationToolTip, + [this]() + { + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation]); + })); + } + break; + } + } + + // reset values + { + AzToolsFramework::ActionOverride resetValuesAction = makeActionOverride( + entityComponentIdPair, SubModeData::ResetSubMode, + SubModeData::ResetTitle, SubModeData::ResetToolTip, + [this]() + { + ResetCurrentMode(); + }); + resetValuesAction.SetKeySequence(QKeySequence(Qt::Key_R)); + actions.emplace_back(resetValuesAction); + } + + return actions; + } + + AZStd::vector JointsComponentMode::PopulateViewportUiImpl() + { + return AZStd::vector(m_modeSelectionClusterIds.begin(), m_modeSelectionClusterIds.end()); + } + + void JointsComponentMode::SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData) + { + + if (auto subMode = m_subModes.find(newMode); + subMode != m_subModes.end()) + { + const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair(); + m_subModes[m_subMode]->Teardown(entityComponentIdPair); + m_subMode = newMode; + subMode->second->Setup(entityComponentIdPair); + + // if this button is on a different cluster. clear the active state. + if (m_activeButton.m_clusterId != buttonData.m_clusterId) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::ClearClusterActiveButton, m_activeButton.m_clusterId); + } + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, buttonData.m_clusterId, + buttonData.m_buttonId); + m_activeButton = buttonData; + } + else + { + AZ_Assert(false, "PhysXJoints Uninitialized joint component mode selected."); + } + } + + bool JointsComponentMode::HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) + { + // Propagate mouse interaction to sub-component mode. + if (m_subModes[m_subMode]) + { + m_subModes[m_subMode]->HandleMouseInteraction(mouseInteraction); + } + + return false; + } + + void JointsComponentMode::SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair) + { + //create the 3 cluster groups + for (auto& clusterId : m_modeSelectionClusterIds) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult( + clusterId, AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, + AzToolsFramework::ViewportUi::Alignment::TopLeft); + } + + //retrieve the enabled sub components from the entity + AZStd::vector subModesState; + EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState); + + const AzToolsFramework::ViewportUi::ClusterId group1ClusterId = GetClusterId(ClusterGroups::Group1); + const AzToolsFramework::ViewportUi::ClusterId group2ClusterId = GetClusterId(ClusterGroups::Group2); + //hide cluster 2, if something is added to it. it will make is visible + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, + group2ClusterId, false); + + const AzToolsFramework::ViewportUi::ClusterId group3ClusterId = GetClusterId(ClusterGroups::Group3); + // hide cluster 3, if something is added to it. it will make is visible + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, + group3ClusterId, false); + + //translation and rotation are enabled for all joints in group 1 + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] = + AZStd::make_unique(); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] = + ButtonData{ group1ClusterId, Internal::RegisterClusterButton(group1ClusterId, "Move", SubModeData::TranslationToolTip) }; + + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation] = AZStd::make_unique(); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation] = + ButtonData{ group1ClusterId, Internal::RegisterClusterButton(group1ClusterId, "Rotate", SubModeData::RotationTitle) }; + + //some constants for some modes + const float ExponentBreakage = 1.0f; + const float ExponentSpring = 2.0f; + + //setup the remaining modes if they're in the enabled list. + for (auto [modeType, parameterString] : subModesState) + { + switch (modeType) + { + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] = + AZStd::make_unique( + parameterString, ExponentBreakage, EditorJointConfig::s_breakageMax, EditorJointConfig::s_breakageMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group3ClusterId, "joints/MaxForce", SubModeData::MaxForceToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] = + ButtonData{ group3ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] = + AZStd::make_unique( + parameterString, ExponentBreakage, EditorJointConfig::s_breakageMax, EditorJointConfig::s_breakageMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group3ClusterId, "joints/MaxTorque", SubModeData::MaxTorqueToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] = + ButtonData{ group3ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::Damping: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] = + AZStd::make_unique( + parameterString, ExponentSpring, EditorJointLimitBase::s_springMax, EditorJointLimitBase::s_springMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group2ClusterId, "joints/Damping", SubModeData::DampingToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] = ButtonData{ group2ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] = + AZStd::make_unique( + parameterString, ExponentSpring, EditorJointLimitBase::s_springMax, EditorJointLimitBase::s_springMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group2ClusterId, "joints/Stiffness", SubModeData::StiffnessToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] = + ButtonData{ group2ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] = + AZStd::make_unique( + parameterString, + AZ::Vector3::CreateAxisX(), // PhysX revolute joints uses the x-axis by default + EditorJointLimitPairConfig::s_angleMax, EditorJointLimitPairConfig::s_angleMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group2ClusterId, "joints/TwistLimits", SubModeData::TwistLimitsToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] = + ButtonData{ group2ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] = + AZStd::make_unique( + parameterString, EditorJointLimitPairConfig::s_angleMax, EditorJointLimitPairConfig::s_angleMin); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group2ClusterId, "joints/SwingLimits", SubModeData::SwingLimitsToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] = + ButtonData{ group2ClusterId, buttonId }; + + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true); + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition] = + AZStd::make_unique(); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group1ClusterId, "joints/SnapPosition", SubModeData::SnapPositionToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition] = + ButtonData{ group1ClusterId, buttonId }; + } + break; + case JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation: + { + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation] = + AZStd::make_unique(); + + const AzToolsFramework::ViewportUi::ButtonId buttonId = + Internal::RegisterClusterButton(group1ClusterId, "joints/SnapRotation", SubModeData::SnapRotationToolTip); + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation] = + ButtonData{ group1ClusterId, buttonId }; + } + break; + } + } + + //register click handler for the buttons + m_modeSelectionHandlers.push_back(AZ::Event::Handler( + [this](AzToolsFramework::ViewportUi::ButtonId buttonId) + { + for (auto itr : m_buttonData) + { + if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group1) && itr.second.m_buttonId == buttonId) + { + SetCurrentMode(itr.first, itr.second); + break; + } + } + })); + m_modeSelectionHandlers.push_back(AZ::Event::Handler( + [this](AzToolsFramework::ViewportUi::ButtonId buttonId) + { + for (auto itr : m_buttonData) + { + if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group2) && itr.second.m_buttonId == buttonId) + { + SetCurrentMode(itr.first, itr.second); + break; + } + } + })); + m_modeSelectionHandlers.push_back(AZ::Event::Handler( + [this](AzToolsFramework::ViewportUi::ButtonId buttonId) + { + for (auto itr : m_buttonData) + { + if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group3) && itr.second.m_buttonId == buttonId) + { + SetCurrentMode(itr.first, itr.second); + break; + } + } + })); + + for (int i = 0; i < static_cast(ClusterGroups::GroupCount); i++) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, + &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, m_modeSelectionClusterIds[i], + m_modeSelectionHandlers[i]); + } + + // set the translate as enabled by default. + SetCurrentMode( + JointsComponentModeCommon::SubComponentModes::ModeType::Translation, + m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]); + + m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]->Setup(GetEntityComponentIdPair()); + m_subMode = JointsComponentModeCommon::SubComponentModes::ModeType::Translation; + } + + void JointsComponentMode::ResetCurrentMode() + { + const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair(); + m_subModes[m_subMode]->ResetValues(entityComponentIdPair); + m_subModes[m_subMode]->Refresh(entityComponentIdPair); + + Internal::RefreshUI(); + } + + void JointsComponentMode::TeardownSubModes() + { + for (auto clusterid : m_modeSelectionClusterIds) + { + AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event( + AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster, + clusterid); + } + } + + AzToolsFramework::ViewportUi::ClusterId JointsComponentMode::GetClusterId(ClusterGroups group) + { + return m_modeSelectionClusterIds[static_cast(group)]; + } +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h new file mode 100644 index 0000000000..812bc71ec1 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h @@ -0,0 +1,79 @@ +/* + * 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 + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace AZ +{ + class EntityComponentIdPair; +} + +namespace PhysX +{ + //! Class responsible for managing component mode for joints. + class JointsComponentMode final + : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType); + ~JointsComponentMode(); + + // EditorBaseComponentMode ... + void Refresh() override; + AZStd::vector PopulateActionsImpl() override; + AZStd::vector PopulateViewportUiImpl() override; + private: + //! Used to identify the group of component modes. + enum class ClusterGroups + { + Group1 = 0, //!< Position Joint, Rotate Joint, Snap Position, Snap Rotation. + Group2, //!< Damping, Stiffness, Twist Limits, Swing Limits. + Group3, //!< Max Force, Max Torque. + + GroupCount + }; + + //! Used to track the cluster that a specific button is apart of. + struct ButtonData + { + AzToolsFramework::ViewportUi::ClusterId m_clusterId; + AzToolsFramework::ViewportUi::ButtonId m_buttonId; + }; + + void SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData); + bool HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; + void SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair); + void ResetCurrentMode(); + void TeardownSubModes(); + + AzToolsFramework::ViewportUi::ClusterId GetClusterId(ClusterGroups group); + + AZStd::fixed_vector(ClusterGroups::GroupCount)> m_modeSelectionClusterIds; //!< List of the cluster ui's. The sub modes are split across 3 groups and each group is it's own cluster ui. + AZStd::unordered_map m_buttonData; //!< Mapping of joint component modes to the button data. + + AZStd::fixed_vector::Handler, static_cast(ClusterGroups::GroupCount)> + m_modeSelectionHandlers; //!< Input handlers for each cluster UI. + ButtonData m_activeButton; //!< The current highlighted button data. + + JointsComponentModeCommon::SubComponentModes::ModeType m_subMode = JointsComponentModeCommon::SubComponentModes::ModeType::Translation; //!< The current component mode that is active. + AZStd::unordered_map> m_subModes; //!< The logic handlers for each component mode. + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp new file mode 100644 index 0000000000..a400745c51 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp @@ -0,0 +1,27 @@ +/* + * 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 + +namespace PhysX::JointsComponentModeCommon +{ + const AZStd::string_view ParamaterNames::TwistLimits = "Twist Limits"; + const AZStd::string_view ParamaterNames::Damping = "Damping"; + const AZStd::string_view ParamaterNames::MaxForce = "Maximum Force"; + const AZStd::string_view ParamaterNames::MaxTorque = "Maximum Torque"; + const AZStd::string_view ParamaterNames::Position = "Position"; + const AZStd::string_view ParamaterNames::Rotation = "Rotation"; + const AZStd::string_view ParamaterNames::SnapPosition = "Snap Position"; + const AZStd::string_view ParamaterNames::SnapRotation = "Snap Rotation"; + const AZStd::string_view ParamaterNames::Stiffness = "Stiffness"; + const AZStd::string_view ParamaterNames::SwingLimit = "Swing Limits"; + const AZStd::string_view ParamaterNames::Transform = "Transform"; + const AZStd::string_view ParamaterNames::ComponentMode = "Component Mode"; + const AZStd::string_view ParamaterNames::LeadEntity = "Lead Entity"; + +} // namespace PhysX::JointsComponentModeCommon diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h new file mode 100644 index 0000000000..3deb3b7e3f --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h @@ -0,0 +1,70 @@ +/* + * 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 + * + */ +#pragma once + +#include +#include +#include +#include + +namespace PhysX::JointsComponentModeCommon +{ + namespace SubComponentModes + { + //! Used to identify a specific sub component mode used with joints + enum class ModeType : AZ::u32 + { + Translation = 0, + Rotation, + MaxForce, + MaxTorque, + Damping, + Stiffness, + TwistLimits, + SwingLimits, + SnapPosition, + SnapRotation, + + ModeCount + }; + + //! Shared data structure used with Angle Cone and Angle Pair sub component modes. + //! Holds information about the axis and limits of the angle. + struct AngleModesSharedRotationState + { + AZ::Vector3 m_axis; //!< The Axis of rotation to apply the limits. + AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity(); //!< The angle delta of the last mouse action. + PhysX::AngleLimitsFloatPair m_valuePair; //!< the current limits of the angle. + }; + } // namespace SubComponentModes + + //! Name Identifiers for the joint components sub modes. + struct ParamaterNames + { + static const AZStd::string_view TwistLimits; + static const AZStd::string_view Damping; + static const AZStd::string_view MaxForce; + static const AZStd::string_view MaxTorque; + static const AZStd::string_view Position; + static const AZStd::string_view Rotation; + static const AZStd::string_view SnapPosition; + static const AZStd::string_view SnapRotation; + static const AZStd::string_view Stiffness; + static const AZStd::string_view SwingLimit; + static const AZStd::string_view Transform; + static const AZStd::string_view ComponentMode; + static const AZStd::string_view LeadEntity; + }; + + //! A pairing of Sub component Names, and Id. + struct SubModeParamaterState + { + SubComponentModes::ModeType m_modeType = SubComponentModes::ModeType::ModeCount; //!< The Id of the sub component mode. + AZStd::string m_parameterName; //!< The name of the sub component mode. + }; +} // namespace PhysX::JointsComponentModeCommon diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp new file mode 100644 index 0000000000..11abe0fa2a --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp @@ -0,0 +1,432 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeAngleCone, AZ::SystemAllocator, 0); + + namespace Internal + { + const float ArrowLength = 2.0f; + const float ConeHeight = 3.0f; + const float XRotationManipulatorRadius = 2.0f; + const float XRotationManipulatorWidth = 0.05f; + } // namespace Internal + + JointsSubComponentModeAngleCone::JointsSubComponentModeAngleCone( + const AZStd::string& propertyName, float max, float min) + : m_propertyName(propertyName) + , m_max(max) + , m_min(min) + { + + } + + void JointsSubComponentModeAngleCone::Setup(const AZ::EntityComponentIdPair& idPair) + { + m_entityComponentIdPair = idPair; + EditorJointRequestBus::EventResult( + m_resetPostion, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Position); + EditorJointRequestBus::EventResult( + m_resetRotation, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation); + EditorJointRequestBus::EventResult( + m_resetLimits, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentIdPair.GetEntityId()); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + const AZ::Quaternion localRotation = localTransform.GetRotation(); + + // Initialize manipulators used to resize the base of the cone. + m_yLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); + m_yLinearManipulator->AddEntityComponentIdPair(m_entityComponentIdPair); + m_yLinearManipulator->SetAxis(AZ::Vector3::CreateAxisZ()); + + m_zLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); + m_zLinearManipulator->AddEntityComponentIdPair(m_entityComponentIdPair); + m_zLinearManipulator->SetAxis(AZ::Vector3::CreateAxisY()); + + m_yzPlanarManipulator = AzToolsFramework::PlanarManipulator::MakeShared(worldTransform); + m_yzPlanarManipulator->AddEntityComponentIdPair(m_entityComponentIdPair); + m_yzPlanarManipulator->SetAxes(AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ()); + + ConfigureLinearView( + Internal::ArrowLength, AZ::Color(1.0f, 0.0f, 0.0f, 1.0f), AZ::Color(0.0f, 1.0f, 0.0f, 1.0f), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); + + ConfigurePlanarView(AZ::Color(0.0f, 1.0f, 0.0f, 1.0f), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); + + // Position and orientate manipulators + AZ::Transform displacementTransform = localTransform; + AZ::Vector3 displacementTranslate = localRotation.TransformVector(AZ::Vector3(Internal::ConeHeight, 0.0f, 0.0f)); + displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); + + m_yLinearManipulator->SetLocalTransform(displacementTransform); + m_zLinearManipulator->SetLocalTransform(displacementTransform); + m_yzPlanarManipulator->SetLocalTransform(displacementTransform); + + // Initialize rotation manipulator for rotating cone + m_xRotationManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); + m_xRotationManipulator->AddEntityComponentIdPair(m_entityComponentIdPair); + m_xRotationManipulator->SetAxis(AZ::Vector3::CreateAxisX()); + m_xRotationManipulator->SetLocalTransform(localTransform); + + const AZ::Color xRotationManipulatorColor = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f); + m_xRotationManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( + *m_xRotationManipulator, xRotationManipulatorColor, Internal::XRotationManipulatorRadius, Internal::XRotationManipulatorWidth, + AzToolsFramework::DrawHalfDottedCircle)); + + AZStd::shared_ptr sharedRotationState = + AZStd::make_shared(); + + struct SharedState + { + AngleLimitsFloatPair m_startValues; + }; + auto sharedState = AZStd::make_shared(); + + m_yLinearManipulator->InstallLeftMouseDownCallback( + [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable + { + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult( + currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + sharedState->m_startValues = currentValue; + }); + + m_yLinearManipulator->InstallMouseMoveCallback( + [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, + JointsComponentModeCommon::ParamaterNames::Transform); + const AZ::Quaternion localRotation = localTransform.GetRotation(); + const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis)); + const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * Internal::ConeHeight; + const float newBaseY = originalBaseY + axisDisplacement; + const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / Internal::ConeHeight)), m_min, m_max); + + EditorJointRequestBus::Event( + m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, + AngleLimitsFloatPair(newAngle, sharedState->m_startValues.second)); + + m_yLinearManipulator->SetBoundsDirty(); + }); + + m_zLinearManipulator->InstallLeftMouseDownCallback( + [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable + { + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult( + currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + sharedState->m_startValues = currentValue; + }); + + m_zLinearManipulator->InstallMouseMoveCallback( + [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, + JointsComponentModeCommon::ParamaterNames::Transform); + const AZ::Quaternion localRotation = localTransform.GetRotation(); + const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis)); + const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * Internal::ConeHeight; + const float newBaseZ = originalBaseZ + axisDisplacement; + const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / Internal::ConeHeight)), m_min, m_max); + + EditorJointRequestBus::Event( + m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, + AngleLimitsFloatPair(sharedState->m_startValues.first, newAngle)); + + m_zLinearManipulator->SetBoundsDirty(); + }); + + m_yzPlanarManipulator->InstallLeftMouseDownCallback( + [this, sharedState]([[maybe_unused]]const AzToolsFramework::PlanarManipulator::Action& action) mutable + { + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult( + currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + sharedState->m_startValues = currentValue; + }); + + m_yzPlanarManipulator->InstallMouseMoveCallback( + [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& action) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, + JointsComponentModeCommon::ParamaterNames::Transform); + + const AZ::Quaternion localRotation = localTransform.GetRotation(); + + const float axisDisplacementY = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisY())); + const float axisDisplacementZ = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisZ())); + const float axisDisplacement = axisDisplacementZ > axisDisplacementY ? axisDisplacementZ : axisDisplacementY; + + const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * Internal::ConeHeight; + const float newBaseY = originalBaseY + axisDisplacement; + const float newAngleY = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / Internal::ConeHeight)), m_min, m_max); + + const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * Internal::ConeHeight; + const float newBaseZ = originalBaseZ + axisDisplacement; + const float newAngleZ = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / Internal::ConeHeight)), m_min, m_max); + + EditorJointRequestBus::Event( + m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, + AngleLimitsFloatPair(newAngleY, newAngleZ)); + + m_yzPlanarManipulator->SetBoundsDirty(); + }); + + struct SharedStateXRotate + { + AZ::Transform m_startTM; + }; + auto sharedStateXRotate = AZStd::make_shared(); + + auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized(); + sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ()); + sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity(); + + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult( + currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + sharedRotationState->m_valuePair = currentValue; + }; + + auto mouseDownRotateXCallback = + [this, sharedStateXRotate]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + PhysX::EditorJointRequestBus::EventResult( + sharedStateXRotate->m_startTM, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetTransformValue, + JointsComponentModeCommon::ParamaterNames::Transform); + }; + + m_xRotationManipulator->InstallLeftMouseDownCallback(mouseDownRotateXCallback); + + m_xRotationManipulator->InstallMouseMoveCallback( + [this, sharedStateXRotate](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; + + AZ::Transform newTransform = AZ::Transform::CreateIdentity(); + newTransform = sharedStateXRotate->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta); + + PhysX::EditorJointRequestBus::Event( + m_entityComponentIdPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, + newTransform.GetTranslation()); + PhysX::EditorJointRequestBus::Event( + m_entityComponentIdPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, + newTransform.GetRotation().GetEulerDegrees()); + + m_yLinearManipulator->SetLocalOrientation(manipulatorOrientation); + m_zLinearManipulator->SetLocalOrientation(manipulatorOrientation); + m_yLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisY())); + m_zLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisZ())); + m_xRotationManipulator->SetLocalOrientation(manipulatorOrientation); + + m_yLinearManipulator->SetBoundsDirty(); + m_zLinearManipulator->SetBoundsDirty(); + m_xRotationManipulator->SetBoundsDirty(); + }); + + m_xRotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + m_yLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + m_zLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + m_yzPlanarManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + + AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentIdPair.GetEntityId()); + + Refresh(m_entityComponentIdPair); + } + + void JointsSubComponentModeAngleCone::Refresh(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + float coneHeight = Internal::ConeHeight; + AngleLimitsFloatPair yzSwingAngleLimits; + EditorJointRequestBus::EventResult(yzSwingAngleLimits, idPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + // Draw inverted cone (negative cone height) if angles are larger than 90 deg. + if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f) + { + coneHeight = -Internal::ConeHeight; + } + + // reposition manipulators + const AZ::Quaternion localRotation = localTransform.GetRotation(); + const AZ::Vector3 linearManipulatorOffset = + localTransform.GetTranslation() + localRotation.TransformVector(AZ::Vector3(coneHeight, 0.0f, 0.0f)); + + m_xRotationManipulator->SetLocalTransform(localTransform); + + localTransform.SetTranslation(linearManipulatorOffset); + + m_yLinearManipulator->SetLocalTransform(localTransform); + m_zLinearManipulator->SetLocalTransform(localTransform); + m_yzPlanarManipulator->SetLocalTransform(localTransform); + } + + void JointsSubComponentModeAngleCone::Teardown(const AZ::EntityComponentIdPair& idPair) + { + AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); + + m_xRotationManipulator->RemoveEntityComponentIdPair(idPair); + m_xRotationManipulator->Unregister(); + m_yLinearManipulator->RemoveEntityComponentIdPair(idPair); + m_yLinearManipulator->Unregister(); + m_zLinearManipulator->RemoveEntityComponentIdPair(idPair); + m_zLinearManipulator->Unregister(); + m_yzPlanarManipulator->RemoveEntityComponentIdPair(idPair); + m_yzPlanarManipulator->Unregister(); + } + + void JointsSubComponentModeAngleCone::ResetValues(const AZ::EntityComponentIdPair& idPair) + { + EditorJointRequestBus::Event( + idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, m_resetPostion); + EditorJointRequestBus::Event( + idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, m_resetRotation); + EditorJointRequestBus::Event(idPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, m_resetLimits); + } + + void JointsSubComponentModeAngleCone::ConfigureLinearView( + float axisLength, [[maybe_unused]] const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color) + { + const float coneLength = 0.28f; + const float coneRadius = 0.07f; + + const auto configureLinearView = + [coneLength, axisLength, coneRadius](AzToolsFramework::LinearManipulator* linearManipulator, const AZ::Color& color) + { + AzToolsFramework::ManipulatorViews views; + views.emplace_back(CreateManipulatorViewLine( + *linearManipulator, color, axisLength, + AzToolsFramework::ManipulatorLineBoundWidth(AzFramework::InvalidViewportId))); + views.emplace_back(CreateManipulatorViewCone( + *linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength), coneLength, coneRadius)); + linearManipulator->SetViews(AZStd::move(views)); + }; + + configureLinearView(m_yLinearManipulator.get(), axis2Color); + configureLinearView(m_zLinearManipulator.get(), axis3Color); + } + + void JointsSubComponentModeAngleCone::ConfigurePlanarView(const AZ::Color& planeColor, const AZ::Color& plane2Color) + { + const float planeSize = 0.6f; + AzToolsFramework::ManipulatorViews views; + views.emplace_back(CreateManipulatorViewQuad(*m_yzPlanarManipulator, planeColor, plane2Color, planeSize)); + m_yzPlanarManipulator->SetViews(AZStd::move(views)); + } + + void JointsSubComponentModeAngleCone::DisplayEntityViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentIdPair.GetEntityId()); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, + JointsComponentModeCommon::ParamaterNames::Transform); + + AZ::u32 stateBefore = debugDisplay.GetState(); + debugDisplay.CullOff(); + + debugDisplay.PushMatrix(worldTransform); + debugDisplay.PushMatrix(localTransform); + + const float xAxisArrowLength = 2.0f; + debugDisplay.SetColor(AZ::Color(1.0f, 0.0f, 0.0f, 1.0f)); + debugDisplay.DrawArrow(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(xAxisArrowLength, 0.0f, 0.0f)); + + AngleLimitsFloatPair yzSwingAngleLimits; + EditorJointRequestBus::EventResult( + yzSwingAngleLimits, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + const AZ::u32 numEllipseSamples = 16; + AZ::Vector3 ellipseSamples[numEllipseSamples]; + float coneHeight = Internal::ConeHeight; + + // Draw inverted cone if angles are larger than 90 deg. + if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f) + { + coneHeight = -Internal::ConeHeight; + } + + // Compute points along perimeter of cone base + const float coney = tanf(AZ::DegToRad(yzSwingAngleLimits.first)) * coneHeight; + const float conez = tanf(AZ::DegToRad(yzSwingAngleLimits.second)) * coneHeight; + const float step = AZ::Constants::TwoPi / numEllipseSamples; + for (size_t i = 0; i < numEllipseSamples; ++i) + { + const float angleStep = step * i; + ellipseSamples[i].SetX(coneHeight); + ellipseSamples[i].SetY(conez * sin(angleStep)); + ellipseSamples[i].SetZ(coney * cos(angleStep)); + } + + // draw cone + for (size_t i = 0; i < numEllipseSamples; ++i) + { + size_t nextIndex = i + 1; + if (i == numEllipseSamples - 1) + { + nextIndex = 0; + } + + // draw cone sides + debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 0.2f)); + debugDisplay.DrawTri(AZ::Vector3(0.0f, 0.0f, 0.0f), ellipseSamples[i], ellipseSamples[nextIndex]); + + // draw parameter of cone base + debugDisplay.SetColor(AZ::Color(0.4f, 0.4f, 0.4f, 0.4f)); + debugDisplay.DrawLine(ellipseSamples[i], ellipseSamples[nextIndex]); + } + + // draw axis lines at base of cone, and from tip to base. + debugDisplay.SetColor(AZ::Color(0.5f, 0.5f, 0.5f, 0.6f)); + debugDisplay.DrawLine(ellipseSamples[0], ellipseSamples[numEllipseSamples / 2]); + debugDisplay.DrawLine(ellipseSamples[numEllipseSamples * 3 / 4], ellipseSamples[numEllipseSamples / 4]); + debugDisplay.DrawLine(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(coneHeight, 0.0f, 0.0f)); + + debugDisplay.PopMatrix(); // pop local transform + debugDisplay.PopMatrix(); // pop world transform + debugDisplay.SetState(stateBefore); + + // reposition and reorientate manipulators + Refresh(m_entityComponentIdPair); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h new file mode 100644 index 0000000000..3f6d001112 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h @@ -0,0 +1,69 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace AzToolsFramework +{ + class AngularManipulator; + class LinearManipulator; + class PlanarManipulator; +} // namespace AzToolsFramework + +namespace PhysX +{ + class JointsSubComponentModeAngleCone final + : public PhysXSubComponentModeBase + , private AzFramework::EntityDebugDisplayEventBus::Handler + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeAngleCone(const AZStd::string& propertyName, float max, float min); + + // PhysXSubComponentModeBase ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void Refresh(const AZ::EntityComponentIdPair& idPair) override; + void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + private: + void ConfigureLinearView( + float axisLength, + const AZ::Color& axis1Color, + const AZ::Color& axis2Color, + const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)); + + void ConfigurePlanarView( + const AZ::Color& planeColor = AZ::Color(0.0f, 1.0f, 0.0f, 0.5f), + const AZ::Color& plane2Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)); + + // AzFramework::EntityDebugDisplayEventBus + void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + + float m_max = AZStd::numeric_limits::max(); + float m_min = -AZStd::numeric_limits::max(); + + AZ::EntityComponentIdPair m_entityComponentIdPair; + AZ::Vector3 m_resetPostion; + AZ::Vector3 m_resetRotation; + AngleLimitsFloatPair m_resetLimits; + AZStd::string m_propertyName; + AZStd::shared_ptr m_xRotationManipulator; + AZStd::shared_ptr m_yLinearManipulator; + AZStd::shared_ptr m_zLinearManipulator; + AZStd::shared_ptr m_yzPlanarManipulator; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp new file mode 100644 index 0000000000..84b0cd4b5b --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp @@ -0,0 +1,305 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeAnglePair, AZ::SystemAllocator, 0); + + namespace Internal + { + const float Alpha = 0.6f; + const AZ::Color ColorDefault = AZ::Color(1.0f, 1.0f, 1.0f, Alpha); + const AZ::Color ColorFirst = AZ::Color(1.0f, 0.0f, 0.0f, Alpha); + const AZ::Color ColorSecond = AZ::Color(0.0f, 1.0f, 0.0f, Alpha); + const AZ::Color ColorSweepArc = AZ::Color(1.0f, 1.0f, 1.0f, Alpha); + + const float SweepLineDisplaceFactor = 0.5f; + const float SweepLineThickness = 1.0f; + const float SweepLineGranularity = 1.0f; + } // namespace Internal + + JointsSubComponentModeAnglePair::JointsSubComponentModeAnglePair( + const AZStd::string& propertyName, const AZ::Vector3& axis, float max, float min) + : m_propertyName(propertyName) + , m_axis(axis) + , m_firstMax(max) + , m_firstMin(min) + , m_secondMax(min) + , m_secondMin(-max) + { + + } + + void JointsSubComponentModeAnglePair::Setup(const AZ::EntityComponentIdPair& idPair) + { + m_entityComponentIdPair = idPair; + EditorJointRequestBus::EventResult(m_resetValue, idPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + const AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(idPair.GetEntityId()); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + const AZ::Quaternion localRotation = localTransform.GetRotation(); + + AZ::Vector3 displacement = m_axis; + AZ::Transform displacementTransform = localTransform; + AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement); + displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); + + m_firstManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); + m_firstManipulator->AddEntityComponentIdPair(idPair); + m_firstManipulator->SetAxis(m_axis); + m_firstManipulator->SetLocalTransform(displacementTransform); + + displacement = -m_axis; + displacementTranslate = localRotation.TransformVector(displacement); + displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); + m_secondManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); + m_secondManipulator->AddEntityComponentIdPair(idPair); + m_secondManipulator->SetAxis(m_axis); + m_secondManipulator->SetLocalTransform(displacementTransform); + + const float manipulatorRadius = 2.0f; + const float manipulatorWidth = 0.05f; + m_firstManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( + *m_firstManipulator, Internal::ColorFirst, manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle)); + + m_secondManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle( + *m_secondManipulator, Internal::ColorSecond, manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle)); + + Refresh(idPair); + + m_sharedRotationState = AZStd::make_shared(); + + auto mouseDownCallback = [this, + idPair](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + const AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized(); + m_sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ()); + m_sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity(); + + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult(currentValue, idPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + m_sharedRotationState->m_valuePair = currentValue; + }; + + m_firstManipulator->InstallLeftMouseDownCallback(mouseDownCallback); + + m_secondManipulator->InstallLeftMouseDownCallback(mouseDownCallback); + + m_firstManipulator->InstallMouseMoveCallback( + [this, idPair](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + float angleDelta; + AZ::Quaternion manipulatorOrientation; + const float newValue = MouseMove(m_sharedRotationState, action, true, angleDelta, manipulatorOrientation); + if (newValue > m_firstMax || newValue < m_firstMin) + { + return; + } + m_firstManipulator->SetLocalOrientation(manipulatorOrientation); + const float newFirstValue = AZ::GetClamp(m_sharedRotationState->m_valuePair.first + angleDelta, m_firstMin, m_firstMax); + + EditorJointRequestBus::Event( + idPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, + AngleLimitsFloatPair(newFirstValue, m_sharedRotationState->m_valuePair.second)); + }); + + m_secondManipulator->InstallMouseMoveCallback( + [this, idPair](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + float angleDelta; + AZ::Quaternion manipulatorOrientation; + const float newValue = MouseMove(m_sharedRotationState, action, false, angleDelta, manipulatorOrientation); + if (newValue > m_secondMax || newValue < m_secondMin) + { + return; // Not handling values exceeding limits + } + + m_secondManipulator->SetLocalOrientation(manipulatorOrientation); + float newSecondValue = AZ::GetClamp(m_sharedRotationState->m_valuePair.second + angleDelta, m_secondMin, m_secondMax); + + EditorJointRequestBus::Event( + idPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, + AngleLimitsFloatPair(m_sharedRotationState->m_valuePair.first, newSecondValue)); + }); + + m_firstManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + m_secondManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + + AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(idPair.GetEntityId()); + } + + void JointsSubComponentModeAnglePair::Refresh(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + const AZ::Quaternion localRotation = localTransform.GetRotation(); + + AZ::Transform displacementTransform = localTransform; + AZ::Vector3 displacement = m_axis; + AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement); + displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); + m_firstManipulator->SetLocalTransform(displacementTransform); + + displacement = -m_axis; + displacementTranslate = localRotation.TransformVector(displacement); + displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate); + m_secondManipulator->SetLocalTransform(displacementTransform); + } + + void JointsSubComponentModeAnglePair::Teardown(const AZ::EntityComponentIdPair& idPair) + { + AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); + m_firstManipulator->RemoveEntityComponentIdPair(idPair); + m_firstManipulator->Unregister(); + m_secondManipulator->RemoveEntityComponentIdPair(idPair); + m_secondManipulator->Unregister(); + } + + void JointsSubComponentModeAnglePair::ResetValues(const AZ::EntityComponentIdPair& idPair) + { + EditorJointRequestBus::Event(idPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, m_resetValue); + + m_firstManipulator->SetLocalOrientation(AZ::Quaternion::CreateFromAxisAngle(m_axis, m_resetValue.first)); + m_secondManipulator->SetLocalOrientation(AZ::Quaternion::CreateFromAxisAngle(m_axis, m_resetValue.first)); + } + + float JointsSubComponentModeAnglePair::MouseMove( + AZStd::shared_ptr& sharedRotationState, + const AzToolsFramework::AngularManipulator::Action& action, + bool isFirstValue, + float& angleDelta, + AZ::Quaternion& manipulatorOrientation) + { + sharedRotationState->m_savedOrientation = action.m_current.m_delta.GetInverseFull(); + angleDelta = 0.0f; + AZ::Vector3 axis = m_axis; + sharedRotationState->m_savedOrientation.ConvertToAxisAngle(axis, angleDelta); + // Polarity of axis is switched by ConvertToAxisAngle call depending on direction of rotation + if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON) + { + angleDelta = AZ::RadToDeg(angleDelta) * axis.GetX(); + } + else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON) + { + angleDelta = AZ::RadToDeg(angleDelta) * axis.GetY(); + } + else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON) + { + angleDelta = AZ::RadToDeg(angleDelta) * axis.GetZ(); + } + + manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; + + if (isFirstValue) + { + return sharedRotationState->m_valuePair.first + angleDelta; + } + return sharedRotationState->m_valuePair.second + angleDelta; + } + + void JointsSubComponentModeAnglePair::DisplayEntityViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + AngleLimitsFloatPair currentValue; + EditorJointRequestBus::EventResult(currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName); + + const float size = 2.0f; + AZ::Vector3 axisPoint = m_axis * size * 0.5f; + + AZStd::array points = { -axisPoint, axisPoint, axisPoint, -axisPoint }; + + if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON) + { + points[2].SetZ(size); + points[3].SetZ(size); + } + else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON) + { + points[2].SetX(size); + points[3].SetX(size); + } + else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON) + { + points[2].SetX(size); + points[3].SetX(size); + } + + AZ::u32 stateBefore = debugDisplay.GetState(); + debugDisplay.CullOff(); + debugDisplay.SetAlpha(Internal::Alpha); + + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentIdPair.GetEntityId()); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + debugDisplay.PushMatrix(worldTransform); + debugDisplay.PushMatrix(localTransform); + + debugDisplay.SetColor(Internal::ColorSweepArc); + + const AZ::Vector3 zeroVector = AZ::Vector3::CreateZero(); + const AZ::Vector3 posPosition = m_axis * Internal::SweepLineDisplaceFactor; + const AZ::Vector3 negPosition = -posPosition; + debugDisplay.DrawArc( + posPosition, Internal::SweepLineThickness, -currentValue.first, currentValue.first, Internal::SweepLineGranularity, -m_axis); + debugDisplay.DrawArc( + zeroVector, Internal::SweepLineThickness, -currentValue.first, currentValue.first, Internal::SweepLineGranularity, -m_axis); + debugDisplay.DrawArc( + negPosition, Internal::SweepLineThickness, -currentValue.first, currentValue.first, Internal::SweepLineGranularity, -m_axis); + debugDisplay.DrawArc( + posPosition, Internal::SweepLineThickness, 0.0f, abs(currentValue.second), Internal::SweepLineGranularity, -m_axis); + debugDisplay.DrawArc( + zeroVector, Internal::SweepLineThickness, 0.0f, abs(currentValue.second), Internal::SweepLineGranularity, -m_axis); + debugDisplay.DrawArc( + negPosition, Internal::SweepLineThickness, 0.0f, abs(currentValue.second), Internal::SweepLineGranularity, -m_axis); + + AZ::Quaternion firstRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.first)); + AZ::Transform firstTM = AZ::Transform::CreateFromQuaternion(firstRotate); + debugDisplay.PushMatrix(firstTM); + debugDisplay.SetColor(Internal::ColorFirst); + debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); + debugDisplay.PopMatrix(); + + AZ::Quaternion secondRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.second)); + AZ::Transform secondTM = AZ::Transform::CreateFromQuaternion(secondRotate); + debugDisplay.PushMatrix(secondTM); + debugDisplay.SetColor(Internal::ColorSecond); + debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); + debugDisplay.PopMatrix(); + + debugDisplay.SetColor(Internal::ColorDefault); + debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]); + + debugDisplay.PopMatrix(); // pop local transform + debugDisplay.PopMatrix(); // pop global transform + debugDisplay.SetState(stateBefore); + + // reposition and reorientate manipulators + Refresh(m_entityComponentIdPair); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.h new file mode 100644 index 0000000000..b50a16bf77 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.h @@ -0,0 +1,70 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + class Vector3; +} // namespace AZ + +namespace PhysX +{ + namespace AngleComponentModes + { + struct SharedRotationState; + } // namespace AngleComponentModes + + class JointsSubComponentModeAnglePair final + : public PhysXSubComponentModeBase + , private AzFramework::EntityDebugDisplayEventBus::Handler + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeAnglePair(const AZStd::string& propertyName, const AZ::Vector3& axis, float max, float min); + + // PhysXSubComponentModeBase ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void Refresh(const AZ::EntityComponentIdPair& idPair) override; + void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + private: + float MouseMove( + AZStd::shared_ptr& sharedRotationState, + const AzToolsFramework::AngularManipulator::Action& action, + bool isFirstValue, + float& angleDelta, + AZ::Quaternion& manipulatorOrientation); + + // AzFramework::EntityDebugDisplayEventBus + void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + + AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); + float m_firstMax = AZStd::numeric_limits::max(); + float m_firstMin = -AZStd::numeric_limits::max(); + float m_secondMax = AZStd::numeric_limits::max(); + float m_secondMin = -AZStd::numeric_limits::max(); + AZStd::shared_ptr m_sharedRotationState; + AngleLimitsFloatPair m_resetValue; + AZ::EntityComponentIdPair m_entityComponentIdPair; + + AZStd::string m_propertyName; + AZStd::shared_ptr m_firstManipulator; + AZStd::shared_ptr m_secondManipulator; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.cpp new file mode 100644 index 0000000000..ec073b49ef --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.cpp @@ -0,0 +1,133 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeLinearFloat, AZ::SystemAllocator, 0); + + JointsSubComponentModeLinearFloat::JointsSubComponentModeLinearFloat( + const AZStd::string& propertyName, float exponent, float max, float min) + : m_propertyName(propertyName) + , m_exponent(exponent) + , m_inverseExponent(1.0f / exponent) + , m_max(max) + , m_min(min) + { + + } + + void JointsSubComponentModeLinearFloat::Setup(const AZ::EntityComponentIdPair& idPair) + { + EditorJointRequestBus::EventResult(m_resetValue, idPair, &EditorJointRequests::GetLinearValue, m_propertyName); + + const AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(idPair.GetEntityId()); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + m_manipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); + m_manipulator->AddEntityComponentIdPair(idPair); + m_manipulator->SetAxis(AZ::Vector3::CreateAxisX()); + m_manipulator->SetLocalTransform(localTransform); + + Refresh(idPair); + + const AZ::Color manipulatorColor(0.3f, 0.3f, 0.3f, 1.0f); + const float manipulatorSize = 0.05f; + + AzToolsFramework::ManipulatorViews views; + views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(manipulatorColor, manipulatorSize)); + m_manipulator->SetViews(AZStd::move(views)); + + struct SharedState + { + float m_startingValue = 0.0f; + }; + auto sharedState = AZStd::make_shared(); + + m_manipulator->InstallLeftMouseDownCallback( + [this, sharedState, idPair]([[maybe_unused]]const AzToolsFramework::LinearManipulator::Action& action) mutable + { + float currentValue = 0.0f; + + EditorJointRequestBus::EventResult(currentValue, idPair, &EditorJointRequests::GetLinearValue, m_propertyName); + sharedState->m_startingValue = currentValue; + }); + + m_manipulator->InstallMouseMoveCallback( + [this, sharedState, idPair](const AzToolsFramework::LinearManipulator::Action& action) + { + const float axisDisplacement = action.LocalPositionOffset().Dot(action.m_fixed.m_axis); + + float newValue = AZ::GetClamp(sharedState->m_startingValue + DisplacementToDeltaValue(axisDisplacement), m_min, m_max); + EditorJointRequestBus::Event(idPair, &EditorJointRequests::SetLinearValue, m_propertyName, newValue); + + const AZ::Vector3 localPosition = action.LocalPosition().GetMax(AZ::Vector3(0.01f, 0.0f, 0.0f)); + m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(localPosition)); + }); + + m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + } + + void JointsSubComponentModeLinearFloat::Refresh(const AZ::EntityComponentIdPair& idPair) + { + float currentValue = 0.0f; + EditorJointRequestBus::EventResult(currentValue, idPair, &EditorJointRequests::GetLinearValue, m_propertyName); + + m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX() * ValueToDisplacement(currentValue))); + } + + void JointsSubComponentModeLinearFloat::Teardown(const AZ::EntityComponentIdPair& idPair) + { + m_manipulator->RemoveEntityComponentIdPair(idPair); + m_manipulator->Unregister(); + m_manipulator.reset(); + } + + void JointsSubComponentModeLinearFloat::ResetValues(const AZ::EntityComponentIdPair& idPair) + { + EditorJointRequestBus::Event(idPair, &EditorJointRequests::SetLinearValue, m_propertyName, m_resetValue); + m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX() * ValueToDisplacement(m_resetValue))); + } + + float JointsSubComponentModeLinearFloat::DisplacementToDeltaValue(float displacement) const + { + if (displacement > 0.0f) + { + return AZStd::pow(displacement, m_exponent); + } + else if (displacement < 0.0f) + { + return -AZStd::pow(fabsf(displacement), m_exponent); + } + else + { + return 0.0f; + } + } + + float JointsSubComponentModeLinearFloat::ValueToDisplacement(float value) const + { + return AZStd::pow(value, m_inverseExponent); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.h new file mode 100644 index 0000000000..d65e59d081 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.h @@ -0,0 +1,56 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace AZ +{ + class Vector3; +} // namespace AZ + +namespace AzToolsFramework +{ + class LinearManipulator; +} // namespace AzToolsFramework + +namespace PhysX +{ + class JointsSubComponentModeLinearFloat final + : public PhysXSubComponentModeBase + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeLinearFloat( + const AZStd::string& propertyName, float exponent, float max, float min); + + // PhysXSubComponentModeBase ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void Refresh(const AZ::EntityComponentIdPair& idPair) override; + void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + private: + float DisplacementToDeltaValue(float displacement) const; + float ValueToDisplacement(float value) const; + + float m_exponent = 1.0f; + float m_inverseExponent = 1.0f; + float m_max = AZStd::numeric_limits::max(); + float m_min = -AZStd::numeric_limits::max(); + float m_resetValue = 0.0f; + AZStd::string m_propertyName; + AZStd::shared_ptr m_manipulator; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.cpp new file mode 100644 index 0000000000..2bca1700e5 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.cpp @@ -0,0 +1,134 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeRotation, AZ::SystemAllocator, 0); + + void JointsSubComponentModeRotation::Setup(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(idPair.GetEntityId()); + + const AZ::Quaternion worldRotation = worldTransform.GetRotation(); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + EditorJointRequestBus::EventResult( + m_resetValue, idPair, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation); + + const AZStd::array axes = { AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ() }; + + const AZStd::array colors = { AZ::Color(1.0f, 0.0f, 0.0f, 1.0f), AZ::Color(0.0f, 1.0f, 0.0f, 1.0f), + AZ::Color(0.0f, 0.0f, 1.0f, 1.0f) }; + + for (AZ::u32 i = 0; i < 3; ++i) + { + m_manipulators[i] = AzToolsFramework::AngularManipulator::MakeShared(worldTransform); + m_manipulators[i]->AddEntityComponentIdPair(idPair); + m_manipulators[i]->SetAxis(axes[i]); + m_manipulators[i]->SetLocalTransform(localTransform); + const float manipulatorRadius = 2.0f; + m_manipulators[i]->SetView(AzToolsFramework::CreateManipulatorViewCircle( + *m_manipulators[i], colors[i], manipulatorRadius, + AzToolsFramework::ManipulatorCicleBoundWidth(), AzToolsFramework::DrawHalfDottedCircle)); + + m_manipulators[i]->Register(AzToolsFramework::g_mainManipulatorManagerId); + } + InstallManipulatorMouseCallbacks(idPair); + } + + void JointsSubComponentModeRotation::Refresh(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + for (auto rotationManipulator : m_manipulators) + { + rotationManipulator->SetLocalTransform(localTransform); + } + } + + void JointsSubComponentModeRotation::Teardown(const AZ::EntityComponentIdPair& idPair) + { + for (auto rotationManipulator : m_manipulators) + { + rotationManipulator->RemoveEntityComponentIdPair(idPair); + rotationManipulator->Unregister(); + } + } + + void JointsSubComponentModeRotation::ResetValues(const AZ::EntityComponentIdPair& idPair) + { + EditorJointRequestBus::Event( + idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, m_resetValue); + + const AZ::Quaternion reset = AZ::Quaternion::CreateFromEulerAnglesDegrees(m_resetValue); + for (auto manipulator : m_manipulators) + { + manipulator->SetLocalOrientation(reset); + } + } + + void JointsSubComponentModeRotation::InstallManipulatorMouseCallbacks(const AZ::EntityComponentIdPair& idPair) + { + struct SharedState + { + AZ::Transform m_startTM; + }; + auto sharedState = AZStd::make_shared(); + + auto mouseDownRotateXCallback = + [sharedState, idPair]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + EditorJointRequestBus::EventResult( + sharedState->m_startTM, idPair, &PhysX::EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + }; + + for (AZ::u32 index = 0; index < 3; ++index) + { + m_manipulators[index]->InstallLeftMouseDownCallback(mouseDownRotateXCallback); + + m_manipulators[index]->InstallMouseMoveCallback( + [this, index, sharedState, idPair](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void + { + const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta; + + AZ::Transform newTransform = AZ::Transform::CreateIdentity(); + newTransform = sharedState->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta); + + EditorJointRequestBus::Event( + idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, + newTransform.GetRotation().GetEulerDegrees()); + + m_manipulators[index]->SetLocalOrientation(manipulatorOrientation); + }); + } + } +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.h new file mode 100644 index 0000000000..a9a1888dd0 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.h @@ -0,0 +1,44 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace AzToolsFramework +{ + class AngularManipulator; +} + +namespace PhysX +{ + class JointsSubComponentModeRotation final + : public PhysXSubComponentModeBase + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeRotation() = default; + + // PhysXSubComponentModeBase ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void Refresh(const AZ::EntityComponentIdPair& idPair) override; + void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + private: + void InstallManipulatorMouseCallbacks(const AZ::EntityComponentIdPair& idPair); + + AZ::Vector3 m_resetValue = AZ::Vector3::CreateZero(); + AZStd::array, 3> m_manipulators; + }; +} diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.cpp similarity index 71% rename from Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.cpp rename to Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.cpp index 5220b2e274..0f3467eb54 100644 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.cpp +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.cpp @@ -1,4 +1,3 @@ - /* * 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. @@ -6,49 +5,67 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include -#include +#include + +#include #include +#include #include -#include -#include +#include #include #include namespace PhysX { - EditorSubComponentModeSnap::EditorSubComponentModeSnap( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name) - : EditorSubComponentModeBase(entityComponentIdPair, componentType, name) + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeSnap, AZ::SystemAllocator, 0); + + void JointsSubComponentModeSnap::Setup(const AZ::EntityComponentIdPair& idPair) { + m_entityComponentId = idPair; + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); AZ::Transform localTransform = AZ::Transform::CreateIdentity(); EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); + localTransform, m_entityComponentId, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); m_manipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform); m_manipulator->AddEntityComponentIdPair(m_entityComponentId); m_manipulator->SetAxis(AZ::Vector3::CreateAxisX()); m_manipulator->SetLocalTransform(localTransform); - Refresh(); + Refresh(idPair); const AZ::Color manipulatorColor(0.3f, 0.3f, 0.3f, 1.0f); const float manipulatorSize = 0.05f; AzToolsFramework::ManipulatorViews views; - views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(manipulatorColor - , manipulatorSize)); + views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(manipulatorColor, manipulatorSize)); m_manipulator->SetViews(AZStd::move(views)); + + m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId); + AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId()); } - void EditorSubComponentModeSnap::HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) + void JointsSubComponentModeSnap::Refresh(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + m_manipulator->SetLocalTransform(localTransform); + } + + void JointsSubComponentModeSnap::Teardown(const AZ::EntityComponentIdPair& idPair) + { + AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); + + m_manipulator->RemoveEntityComponentIdPair(idPair); + m_manipulator->Unregister(); + m_manipulator.reset(); + } + + void JointsSubComponentModeSnap::HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) { if (mouseInteraction.m_mouseEvent == AzToolsFramework::ViewportInteraction::MouseEvent::Move) { @@ -63,25 +80,36 @@ namespace PhysX const AZ::Quaternion worldRotateInv = worldRotate.GetInverseFull(); m_manipulator->SetLocalPosition(worldRotateInv.TransformVector(m_pickedPosition - worldTransform.GetTranslation())); - m_manipulator->SetBoundsDirty(); } } } - void EditorSubComponentModeSnap::Refresh() + AZStd::string JointsSubComponentModeSnap::GetPickedEntityName() { - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - m_manipulator->SetLocalTransform(localTransform); + AZStd::string pickedEntityName; + if (m_pickedEntity.IsValid()) + { + AZ::ComponentApplicationBus::BroadcastResult( + pickedEntityName, &AZ::ComponentApplicationRequests::GetEntityName, m_pickedEntity); + } + return pickedEntityName; } - void EditorSubComponentModeSnap::DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) + AZ::Vector3 JointsSubComponentModeSnap::GetPosition() const + { + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); + + AZ::Quaternion worldRotate = worldTransform.GetRotation(); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentId, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + return worldTransform.GetTranslation() + worldRotate.TransformVector(localTransform.GetTranslation()); + } + + void JointsSubComponentModeSnap::DisplayEntityViewport( + const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { AZ::u32 stateBefore = debugDisplay.GetState(); @@ -89,11 +117,9 @@ namespace PhysX AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - AZ::Transform localTransform = AZ::Transform::CreateIdentity();; + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); + localTransform, m_entityComponentId, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); debugDisplay.PushMatrix(worldTransform); debugDisplay.PushMatrix(localTransform); @@ -104,9 +130,7 @@ namespace PhysX AngleLimitsFloatPair yzSwingAngleLimits; EditorJointRequestBus::EventResult( - yzSwingAngleLimits, m_entityComponentId - , &EditorJointRequests::GetLinearValuePair - , PhysX::EditorJointComponentMode::s_parameterSwingLimit); + yzSwingAngleLimits, m_entityComponentId, &EditorJointRequests::GetLinearValuePair, JointsComponentModeCommon::ParamaterNames::SwingLimit); const AZ::u32 numEllipseSamples = 16; AZStd::array ellipseSamples; @@ -154,8 +178,8 @@ namespace PhysX debugDisplay.DrawLine(ellipseSamples[numEllipseSamples * 3 / 4], ellipseSamples[numEllipseSamples / 4]); debugDisplay.DrawLine(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(coneHeight, 0.0f, 0.0f)); - debugDisplay.PopMatrix();//pop local transform - debugDisplay.PopMatrix();//pop world transform + debugDisplay.PopMatrix(); // pop local transform + debugDisplay.PopMatrix(); // pop world transform // draw line from joint to mouse-over entity if (m_pickedEntity.IsValid()) @@ -173,40 +197,9 @@ namespace PhysX debugDisplay.DrawWireBox(m_pickedEntityAabb.GetMin(), m_pickedEntityAabb.GetMax()); // draw something, e.g. an icon, to indicate type of snapping - DisplaySpecificSnapType(viewportInfo, - debugDisplay, - position, - directionNorm, - directionLength); + DisplaySpecificSnapType(viewportInfo, debugDisplay, position, directionNorm, directionLength); } debugDisplay.SetState(stateBefore); } - - AZStd::string EditorSubComponentModeSnap::GetPickedEntityName() - { - AZStd::string pickedEntityName; - if (m_pickedEntity.IsValid()) - { - AZ::ComponentApplicationBus::BroadcastResult(pickedEntityName, - &AZ::ComponentApplicationRequests::GetEntityName, - m_pickedEntity); - } - return pickedEntityName; - } - - AZ::Vector3 EditorSubComponentModeSnap::GetPosition() const - { - AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId()); - - AZ::Quaternion worldRotate = worldTransform.GetRotation(); - - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EditorJointRequestBus::EventResult( - localTransform, m_entityComponentId - , &EditorJointRequests::GetTransformValue - , PhysX::EditorJointComponentMode::s_parameterTransform); - - return worldTransform.GetTranslation() + worldRotate.TransformVector(localTransform.GetTranslation()); - } } // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.h similarity index 51% rename from Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.h rename to Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.h index 585d46c2b6..843fffd4c8 100644 --- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnap.h +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.h @@ -1,4 +1,3 @@ - /* * 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. @@ -6,12 +5,16 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once +#include +#include +#include #include -#include #include +#include namespace AzToolsFramework { @@ -20,48 +23,43 @@ namespace AzToolsFramework namespace PhysX { - /// This sub-component mode uses EditorViewportEntityPicker to get the position of an entity that the mouse is hovering over. - /// Classes inheriting from this class can use the mouse-over entity position to perform custom actions. - class EditorSubComponentModeSnap - : public PhysX::EditorSubComponentModeBase + class JointsSubComponentModeSnap + : public PhysXSubComponentModeBase , protected AzFramework::EntityDebugDisplayEventBus::Handler { public: - EditorSubComponentModeSnap( - const AZ::EntityComponentIdPair& entityComponentIdPair - , const AZ::Uuid& componentType - , const AZStd::string& name); - virtual ~EditorSubComponentModeSnap() = default; + AZ_CLASS_ALLOCATOR_DECL; - // PhysX::EditorSubComponentModeBase - void HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; - void Refresh() override; + JointsSubComponentModeSnap() = default; + + // PhysXSubComponentModeBase ... + virtual void Setup(const AZ::EntityComponentIdPair& idPair) override; + virtual void Refresh(const AZ::EntityComponentIdPair& idPair) override; + virtual void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; protected: - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; + AZStd::string GetPickedEntityName(); + AZ::Vector3 GetPosition() const; - /// Override to draw specific snap type display + // AzFramework::EntityDebugDisplayEventBus + void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + + //! Override to draw specific snap type display virtual void DisplaySpecificSnapType( [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, [[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay, [[maybe_unused]] const AZ::Vector3& jointPosition, [[maybe_unused]] const AZ::Vector3& snapDirection, - [[maybe_unused]] float snapLength) {} - - virtual void InitMouseDownCallBack() = 0; - - AZStd::string GetPickedEntityName(); - AZ::Vector3 GetPosition() const; - - AZStd::shared_ptr m_manipulator; + [[maybe_unused]] float snapLength) + { + } EditorViewportEntityPicker m_picker; AZ::EntityId m_pickedEntity; AZ::Aabb m_pickedEntityAabb = AZ::Aabb::CreateNull(); AZ::Vector3 m_pickedPosition; + AZ::EntityComponentIdPair m_entityComponentId; + AZStd::shared_ptr m_manipulator; }; -} // namespace PhysX +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.cpp new file mode 100644 index 0000000000..809ccd97cb --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.cpp @@ -0,0 +1,91 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeSnapPosition, AZ::SystemAllocator, 0); + + void JointsSubComponentModeSnapPosition::Setup(const AZ::EntityComponentIdPair& idPair) + { + JointsSubComponentModeSnap::Setup(idPair); + + PhysX::EditorJointRequestBus::EventResult( + m_resetPosition, m_entityComponentId, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Position); + + PhysX::EditorJointRequestBus::EventResult( + m_resetLeadEntity, m_entityComponentId, &PhysX::EditorJointRequests::GetEntityIdValue, + JointsComponentModeCommon::ParamaterNames::LeadEntity); + + m_manipulator->InstallLeftMouseDownCallback( + [this](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable + { + if (!m_pickedEntity.IsValid()) + { + return; + } + + const AZ::Vector3 newLocalPosition = PhysX::Utils::ComputeJointLocalTransform( + PhysX::Utils::GetEntityWorldTransformWithScale(m_pickedEntity), + PhysX::Utils::GetEntityWorldTransformWithScale(m_entityComponentId.GetEntityId())) + .GetTranslation(); + + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, + newLocalPosition); + + const bool selectedEntityIsNotJointEntity = m_pickedEntity != m_entityComponentId.GetEntityId(); + + AZ_Error( + "EditorSubComponentModeSnapPosition", selectedEntityIsNotJointEntity, + "Joint's lead entity cannot be the same as the entity in which the joint resides. Select lead entity on snap failed."); + + if (selectedEntityIsNotJointEntity) + { + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetEntityIdValue, JointsComponentModeCommon::ParamaterNames::LeadEntity, + m_pickedEntity); + } + }); + } + + void JointsSubComponentModeSnapPosition::ResetValues([[maybe_unused]]const AZ::EntityComponentIdPair& idPair) + { + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, m_resetPosition); + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetEntityIdValue, JointsComponentModeCommon::ParamaterNames::LeadEntity, m_resetLeadEntity); + } + + void JointsSubComponentModeSnapPosition::DisplaySpecificSnapType( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay, + const AZ::Vector3& jointPosition, + const AZ::Vector3& snapDirection, + float snapLength) + { + const float arrowLength = 1.0f; + const float iconGap = 1.0f; + const AZ::Vector3 iconPosition = jointPosition + (snapDirection * (snapLength + arrowLength + iconGap)); + + debugDisplay.SetColor(AZ::Colors::Red); + debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(arrowLength, 0.0f, 0.0f)); + debugDisplay.SetColor(AZ::Colors::Green); + debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.2f, arrowLength, 0.2f)); + debugDisplay.SetColor(AZ::Colors::Blue); + debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.0f, 0.0f, arrowLength)); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.h new file mode 100644 index 0000000000..c762db54d2 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.h @@ -0,0 +1,42 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include + +namespace PhysX +{ + class JointsSubComponentModeSnapPosition final + : public JointsSubComponentModeSnap + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeSnapPosition() = default; + + // JointsSubComponentModeSnap ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + protected: + // JointsSubComponentModeSnap ... + void DisplaySpecificSnapType( + const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay, + const AZ::Vector3& jointPosition, + const AZ::Vector3& snapDirection, + float snapLength) override; + + private: + AZ::Vector3 m_resetPosition; + AZ::EntityId m_resetLeadEntity; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.cpp new file mode 100644 index 0000000000..7d48bf7772 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.cpp @@ -0,0 +1,117 @@ +/* + * 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 + +#include +#include +#include +#include + +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeSnapRotation, AZ::SystemAllocator, 0); + + void JointsSubComponentModeSnapRotation::Setup(const AZ::EntityComponentIdPair& idPair) + { + JointsSubComponentModeSnap::Setup(idPair); + + PhysX::EditorJointRequestBus::EventResult( + m_resetRotation, m_entityComponentId, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation); + + m_manipulator->InstallLeftMouseDownCallback( + [this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action) mutable + { + if (!m_pickedEntity.IsValid()) + { + return; + } + + AZ::EntityId leadEntityId; + PhysX::EditorJointRequestBus::EventResult( + leadEntityId, m_entityComponentId, &PhysX::EditorJointRequests::GetEntityIdValue, + JointsComponentModeCommon::ParamaterNames::LeadEntity); + + if (leadEntityId.IsValid() && m_pickedEntity == leadEntityId) + { + AZ_Warning( + "EditorsubComponentModeSnapRotation", false, + "The entity %s is the lead of the joint. Please snap rotation (or orientation) of joint to another entity that is " + "not the lead entity.", + GetPickedEntityName().c_str()); + return; + } + + AZ::Transform worldTransform = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldTransform, m_entityComponentId.GetEntityId(), &AZ::TransformInterface::GetWorldTM); + worldTransform.ExtractUniformScale(); + + AZ::Transform localTransform = AZ::Transform::CreateIdentity(); + EditorJointRequestBus::EventResult( + localTransform, m_entityComponentId, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform); + + AZ::Transform pickedEntityTransform = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(pickedEntityTransform, m_pickedEntity, &AZ::TransformInterface::GetWorldTM); + + const AZ::Transform worldTransformInv = worldTransform.GetInverse(); + const AZ::Vector3 pickedLocalPosition = + worldTransformInv.TransformVector(pickedEntityTransform.GetTranslation()) - localTransform.GetTranslation(); + + if (AZStd::abs(pickedLocalPosition.GetLength()) < FLT_EPSILON) + { + AZ_Warning( + "EditorsubComponentModeSnapRotation", false, + "The entity %s is too close to the joint position. Please snap rotation to an entity that is not at the position " + "of the joint.", + GetPickedEntityName().c_str()); + return; + } + + const AZ::Vector3 targetDirection = pickedLocalPosition.GetNormalized(); + const AZ::Vector3 sourceDirection = AZ::Vector3::CreateAxisX(); + const AZ::Quaternion newLocalRotation = AZ::Quaternion::CreateShortestArc(sourceDirection, targetDirection); + + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetVector3Value, + JointsComponentModeCommon::ParamaterNames::Rotation // using rotation parameter name to set the local rotation value + , + newLocalRotation.GetEulerDegrees()); + }); + } + + void JointsSubComponentModeSnapRotation::ResetValues([[maybe_unused]] const AZ::EntityComponentIdPair& idPair) + { + PhysX::EditorJointRequestBus::Event( + m_entityComponentId, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, m_resetRotation); + } + + void JointsSubComponentModeSnapRotation::DisplaySpecificSnapType( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay, + const AZ::Vector3& jointPosition, + const AZ::Vector3& snapDirection, + float snapLength) + { + const float circleRadius = 0.5f; + const float iconGap = 1.0f; + + const AZ::Vector3 iconPosition = jointPosition + (snapDirection * (snapLength + circleRadius * 2.0f + iconGap)); + + debugDisplay.SetColor(AZ::Colors::Red); + debugDisplay.DrawCircle(iconPosition, circleRadius, 0); + debugDisplay.SetColor(AZ::Colors::Green); + debugDisplay.DrawCircle(iconPosition, circleRadius, 1); + debugDisplay.SetColor(AZ::Colors::Blue); + debugDisplay.DrawCircle(iconPosition, circleRadius, 2); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.h new file mode 100644 index 0000000000..d8aa613684 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.h @@ -0,0 +1,41 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include + +namespace PhysX +{ + class JointsSubComponentModeSnapRotation final + : public JointsSubComponentModeSnap + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeSnapRotation() = default; + + // JointsSubComponentModeSnap ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + protected: + // JointsSubComponentModeSnap ... + void DisplaySpecificSnapType( + const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay, + const AZ::Vector3& jointPosition, + const AZ::Vector3& snapDirection, + float snapLength) override; + + private: + AZ::Vector3 m_resetRotation; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.cpp new file mode 100644 index 0000000000..becb79a1d9 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.cpp @@ -0,0 +1,90 @@ +/* + * 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 + +#include +#include +#include +#include + +#include +#include +#include + +namespace PhysX +{ + AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeTranslation, AZ::SystemAllocator, 0); + + JointsSubComponentModeTranslation::JointsSubComponentModeTranslation() + : m_manipulator( + AzToolsFramework::TranslationManipulators::Dimensions::Three, AZ::Transform::Identity(), AZ::Vector3::CreateOne()) + { + } + + void JointsSubComponentModeTranslation::Setup(const AZ::EntityComponentIdPair& idPair) + { + AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(idPair.GetEntityId()); + + EditorJointRequestBus::EventResult( + m_resetValue, idPair, &EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Position); + + m_manipulator.SetSpace(worldTransform); + m_manipulator.SetLocalPosition(m_resetValue); + + m_manipulator.AddEntityComponentIdPair(idPair); + m_manipulator.Register(AzToolsFramework::g_mainManipulatorManagerId); + AzToolsFramework::ConfigureTranslationManipulatorAppearance3d(&m_manipulator); + m_manipulator.InstallLinearManipulatorMouseMoveCallback( + [this, idPair](const AzToolsFramework::LinearManipulator::Action& action) + { + OnManipulatorMoved(action.LocalPosition(), idPair); + }); + + m_manipulator.InstallPlanarManipulatorMouseMoveCallback( + [this, idPair](const AzToolsFramework::PlanarManipulator::Action& action) + { + OnManipulatorMoved(action.LocalPosition(), idPair); + }); + + m_manipulator.InstallSurfaceManipulatorMouseMoveCallback( + [this, idPair](const AzToolsFramework::SurfaceManipulator::Action& action) + { + OnManipulatorMoved(action.LocalPosition(), idPair); + }); + } + + void JointsSubComponentModeTranslation::Refresh(const AZ::EntityComponentIdPair& idPair) + { + AZ::Vector3 localTranslation; + EditorJointRequestBus::EventResult( + localTranslation, idPair, &EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Position); + m_manipulator.SetLocalPosition(localTranslation); + } + + void JointsSubComponentModeTranslation::Teardown(const AZ::EntityComponentIdPair& idPair) + { + m_manipulator.RemoveEntityComponentIdPair(idPair); + m_manipulator.Unregister(); + } + + void JointsSubComponentModeTranslation::ResetValues(const AZ::EntityComponentIdPair& idPair) + { + PhysX::EditorJointRequestBus::Event( + idPair, &EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, m_resetValue); + m_manipulator.SetLocalPosition(m_resetValue); + } + + void JointsSubComponentModeTranslation::OnManipulatorMoved(const AZ::Vector3& position, const AZ::EntityComponentIdPair& idPair) + { + m_manipulator.SetLocalPosition(position); + PhysX::EditorJointRequestBus::Event( + idPair, &EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, position); + } + +} // namespace PhysX diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.h new file mode 100644 index 0000000000..2e25556889 --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.h @@ -0,0 +1,43 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + class Vector3; +} // namespace AZ + +namespace PhysX +{ + class JointsSubComponentModeTranslation final + : public PhysXSubComponentModeBase + { + public: + AZ_CLASS_ALLOCATOR_DECL; + + JointsSubComponentModeTranslation(); + + // PhysXSubComponentModeBase ... + void Setup(const AZ::EntityComponentIdPair& idPair) override; + void Refresh(const AZ::EntityComponentIdPair& idPair) override; + void Teardown(const AZ::EntityComponentIdPair& idPair) override; + void ResetValues(const AZ::EntityComponentIdPair& idPair) override; + + private: + void OnManipulatorMoved(const AZ::Vector3& position, const AZ::EntityComponentIdPair& idPair); + + AZ::Vector3 m_resetValue = AZ::Vector3::CreateZero(); + AzToolsFramework::TranslationManipulators m_manipulator; + }; +} diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/PhysXSubComponentModeBase.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/PhysXSubComponentModeBase.h new file mode 100644 index 0000000000..0478d6e1ee --- /dev/null +++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/PhysXSubComponentModeBase.h @@ -0,0 +1,48 @@ +/* + * 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 + * + */ +#pragma once + +namespace AZ +{ + class EntityComponentIdPair; +} // namespace AZ + +namespace AzToolsFramework::ViewportInteraction +{ + struct MouseInteractionEvent; +} // namespace AzToolsFramework::ViewportInteraction + +namespace PhysX +{ + class PhysXSubComponentModeBase + { + public: + virtual ~PhysXSubComponentModeBase() = default; + + //! Called when the mode is entered to initialize the mode. + //! @param idPair The entity/component id pair. + virtual void Setup(const AZ::EntityComponentIdPair& idPair) = 0; + + //! Called when the mode needs to refresh it's values. + //! @param idPair The entity/component id pair. + virtual void Refresh(const AZ::EntityComponentIdPair& idPair) = 0; + + //! Called when the mode exits to perform cleanup. + //! @param idPair The entity/component id pair. + virtual void Teardown(const AZ::EntityComponentIdPair& idPair) = 0; + + //! Called when reset hot key is pressed. + //! Should reset values in the sub component mode to sensible defaults. + //! @param idPair The entity/component id pair. + virtual void ResetValues(const AZ::EntityComponentIdPair& idPair) = 0; + + //! Additional mouse handling by sub-component mode. Does not absorb mouse event. + virtual void HandleMouseInteraction( + [[maybe_unused]] const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) {}; + }; +} // namespace PhysX diff --git a/Gems/PhysX/Code/Include/PhysX/EditorJointBus.h b/Gems/PhysX/Code/Include/PhysX/EditorJointBus.h index e62a8b7e15..20145f1f76 100644 --- a/Gems/PhysX/Code/Include/PhysX/EditorJointBus.h +++ b/Gems/PhysX/Code/Include/PhysX/EditorJointBus.h @@ -9,59 +9,58 @@ #include #include +#include +#include namespace PhysX { - /// Pair of floating point values for angular limits. - using AngleLimitsFloatPair = AZStd::pair; - - /// Messages serviced by Editor Joint Components. + //! Messages serviced by Editor Joint Components. class EditorJointRequests : public AZ::EntityComponentBus { public: static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - /// Get bool parameter value identified by name. - /// @return Value of bool parameter. + //! Get bool parameter value identified by name. + //! @return Value of bool parameter. virtual bool GetBoolValue(const AZStd::string& parameterName) = 0; - /// Get entityID parameter value identified by name. - /// @return Value of entityID parameter. + //! Get entityID parameter value identified by name. + //! @return Value of entityID parameter. virtual AZ::EntityId GetEntityIdValue(const AZStd::string& parameterName) = 0; - /// Get linear parameter value identified by name. - /// @return Value of linear value parameter. + //! Get linear parameter value identified by name. + //! @return Value of linear value parameter. virtual float GetLinearValue(const AZStd::string& parameterName) = 0; - /// Get linear parameter value pair identified by name. - /// @return Linear parameter value pair. + //! Get linear parameter value pair identified by name. + //! @return Linear parameter value pair. virtual AngleLimitsFloatPair GetLinearValuePair(const AZStd::string& parameterName) = 0; - /// Get vector3 value identified by name. - /// @return Vector3 parameter value. + //! Get vector3 value identified by name. + //! @return Vector3 parameter value. virtual AZ::Vector3 GetVector3Value(const AZStd::string& parameterName) = 0; - /// Get transform value identified by name. - /// @return Transform parameter value. + //! Get transform value identified by name. + //! @return Transform parameter value. virtual AZ::Transform GetTransformValue(const AZStd::string& parameterName) = 0; - /// Checks if parameter is used. - virtual bool IsParameterUsed(const AZStd::string& parameterName) = 0; + //! Get the Sub Component modes to enable. + virtual AZStd::vector GetSubComponentModesState() = 0; - /// Set bool parameter value identified by name. + //! Set bool parameter value identified by name. virtual void SetBoolValue(const AZStd::string& parameterName, bool value) = 0; - /// Set entity ID parameter value identified by name. + //! Set entity ID parameter value identified by name. virtual void SetEntityIdValue(const AZStd::string& parameterName, AZ::EntityId value) = 0; - /// Set linear parameter value identified by name. + //! Set linear parameter value identified by name. virtual void SetLinearValue(const AZStd::string& parameterName, float value) = 0; - /// Set linear parameter value pair identified by name. + //! Set linear parameter value pair identified by name. virtual void SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair) = 0; - /// Set vector3 parameter value identified by name. + //! Set vector3 parameter value identified by name. virtual void SetVector3Value(const AZStd::string& parameterName, const AZ::Vector3& value) = 0; }; using EditorJointRequestBus = AZ::EBus; diff --git a/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp b/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp index da000baeed..92952bcdaa 100644 --- a/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorBallJointComponent.cpp @@ -13,7 +13,8 @@ #include #include -#include +#include +#include #include #include @@ -73,9 +74,8 @@ namespace PhysX AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusConnect(entityId); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler* selection = this; - m_componentModeDelegate.ConnectWithSingleComponentMode < - EditorBallJointComponent, EditorBallJointComponentMode>( - AZ::EntityComponentIdPair(entityId, GetId()), selection); + m_componentModeDelegate.ConnectWithSingleComponentMode( + AZ::EntityComponentIdPair(entityId, GetId()), selection); PhysX::EditorJointRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(entityId, GetId())); } @@ -100,23 +100,19 @@ namespace PhysX float EditorBallJointComponent::GetLinearValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxForce) { return m_config.m_forceMax; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxTorque) { return m_config.m_torqueMax; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - return m_swingLimit.m_standardLimitConfig.m_tolerance; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Damping) { return m_swingLimit.m_standardLimitConfig.m_damping; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Stiffness) { return m_swingLimit.m_standardLimitConfig.m_stiffness; } @@ -126,7 +122,7 @@ namespace PhysX AngleLimitsFloatPair EditorBallJointComponent::GetLinearValuePair(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterSwingLimit) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::SwingLimit) { return AngleLimitsFloatPair(m_swingLimit.m_limitY, m_swingLimit.m_limitZ); } @@ -134,49 +130,58 @@ namespace PhysX return AngleLimitsFloatPair(); } - bool EditorBallJointComponent::IsParameterUsed(const AZStd::string& parameterName) + AZStd::vector EditorBallJointComponent::GetSubComponentModesState() { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce - || parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque - ) + AZStd::vector subModes; + + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition, + JointsComponentModeCommon::ParamaterNames::SnapPosition }); + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation, + JointsComponentModeCommon::ParamaterNames::SnapRotation }); + + if (AZStd::vector baseSubModes = + EditorJointComponent::GetSubComponentModesState(); + !baseSubModes.empty()) { - return m_config.m_breakable; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - return !m_swingLimit.m_standardLimitConfig.m_isSoftLimit; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) - { - return m_swingLimit.m_standardLimitConfig.m_isSoftLimit; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) - { - return m_swingLimit.m_standardLimitConfig.m_isSoftLimit; + subModes.insert(subModes.end(), baseSubModes.begin(), baseSubModes.end()); } - return true; // Sub-component mode always enabled unless disabled explicitly. + if (m_swingLimit.m_standardLimitConfig.m_isLimited) + { + subModes.emplace_back( + JointsComponentModeCommon::SubModeParamaterState{ JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits, + JointsComponentModeCommon::ParamaterNames::SwingLimit }); + + if (m_swingLimit.m_standardLimitConfig.m_isSoftLimit) + { + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::Damping, JointsComponentModeCommon::ParamaterNames::Damping }); + subModes.emplace_back( + JointsComponentModeCommon::SubModeParamaterState{ JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness, + JointsComponentModeCommon::ParamaterNames::Stiffness }); + } + } + + return subModes; } void EditorBallJointComponent::SetLinearValue(const AZStd::string& parameterName, float value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxForce) { m_config.m_forceMax = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxTorque) { m_config.m_torqueMax = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - m_swingLimit.m_standardLimitConfig.m_tolerance = value; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Damping) { m_swingLimit.m_standardLimitConfig.m_damping = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Stiffness) { m_swingLimit.m_standardLimitConfig.m_stiffness = value; } @@ -184,7 +189,7 @@ namespace PhysX void EditorBallJointComponent::SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterSwingLimit) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::SwingLimit) { m_swingLimit.m_limitY = valuePair.first; m_swingLimit.m_limitZ = valuePair.second; @@ -193,7 +198,7 @@ namespace PhysX void EditorBallJointComponent::SetBoolValue(const AZStd::string& parameterName, bool value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::ComponentMode) { m_swingLimit.m_standardLimitConfig.m_inComponentMode = value; m_config.m_inComponentMode = value; @@ -202,10 +207,6 @@ namespace PhysX &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay , AzToolsFramework::Refresh_EntireTree); } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap) - { - m_config.m_selectLeadOnSnap = value; - } } void EditorBallJointComponent::DisplayEntityViewport( @@ -228,7 +229,7 @@ namespace PhysX EditorJointRequestBus::EventResult(localTransform, AZ::EntityComponentIdPair(entityId, GetId()), &EditorJointRequests::GetTransformValue, - PhysX::EditorJointComponentMode::s_parameterTransform); + PhysX::JointsComponentModeCommon::ParamaterNames::Transform); AZ::u32 stateBefore = debugDisplay.GetState(); debugDisplay.CullOff(); diff --git a/Gems/PhysX/Code/Source/EditorBallJointComponent.h b/Gems/PhysX/Code/Source/EditorBallJointComponent.h index 1702532a88..ad925dc79d 100644 --- a/Gems/PhysX/Code/Source/EditorBallJointComponent.h +++ b/Gems/PhysX/Code/Source/EditorBallJointComponent.h @@ -41,7 +41,7 @@ namespace PhysX // PhysX::EditorJointRequests float GetLinearValue(const AZStd::string& parameterName) override; AngleLimitsFloatPair GetLinearValuePair(const AZStd::string& parameterName) override; - bool IsParameterUsed(const AZStd::string& parameterName) override; + AZStd::vector GetSubComponentModesState() override; void SetBoolValue(const AZStd::string& parameterName, bool value) override; void SetLinearValue(const AZStd::string& parameterName, float value) override; void SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair) override; diff --git a/Gems/PhysX/Code/Source/EditorFixedJointComponent.cpp b/Gems/PhysX/Code/Source/EditorFixedJointComponent.cpp index bf5af6b78d..94f57690ba 100644 --- a/Gems/PhysX/Code/Source/EditorFixedJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorFixedJointComponent.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include namespace PhysX @@ -70,9 +70,8 @@ namespace PhysX AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusConnect(entityId); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler* selection = this; - m_componentModeDelegate.ConnectWithSingleComponentMode < - EditorFixedJointComponent, EditorFixedJointComponentMode>( - AZ::EntityComponentIdPair(entityId, GetId()), selection); + m_componentModeDelegate.ConnectWithSingleComponentMode( + AZ::EntityComponentIdPair(entityId, GetId()), selection); PhysX::EditorJointRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(entityId, GetId())); } @@ -91,4 +90,9 @@ namespace PhysX m_config.m_followerEntity = GetEntityId(); // joint is always in the same entity as the follower body. gameEntity->CreateComponent(m_config.ToGameTimeConfig(), m_config.ToGenericProperties()); } + + AZStd::vector EditorFixedJointComponent::GetSubComponentModesState() + { + return EditorJointComponent::GetSubComponentModesState(); + } } diff --git a/Gems/PhysX/Code/Source/EditorFixedJointComponent.h b/Gems/PhysX/Code/Source/EditorFixedJointComponent.h index 10056020d8..f32243776d 100644 --- a/Gems/PhysX/Code/Source/EditorFixedJointComponent.h +++ b/Gems/PhysX/Code/Source/EditorFixedJointComponent.h @@ -37,6 +37,9 @@ namespace PhysX // EditorComponentBase void BuildGameEntity(AZ::Entity* gameEntity) override; + // EditorJointComponent + AZStd::vector GetSubComponentModesState() override; + private: using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; ComponentModeDelegate m_componentModeDelegate; ///< Responsible for detecting ComponentMode activation diff --git a/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp b/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp index 6676b9865e..5537502327 100644 --- a/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorHingeJointComponent.cpp @@ -12,8 +12,9 @@ #include #include +#include +#include #include -#include #include #include @@ -74,7 +75,7 @@ namespace PhysX AzToolsFramework::EditorComponentSelectionRequestsBus::Handler* selection = this; m_componentModeDelegate.ConnectWithSingleComponentMode < - EditorHingeJointComponent, EditorHingeJointComponentMode>( + EditorHingeJointComponent, JointsComponentMode>( AZ::EntityComponentIdPair(entityId, GetId()), selection); PhysX::EditorJointRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(entityId, GetId())); @@ -100,23 +101,19 @@ namespace PhysX float EditorHingeJointComponent::GetLinearValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxForce) { return m_config.m_forceMax; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxTorque) { return m_config.m_torqueMax; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - return m_angularLimit.m_standardLimitConfig.m_tolerance; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Damping) { return m_angularLimit.m_standardLimitConfig.m_damping; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Stiffness) { return m_angularLimit.m_standardLimitConfig.m_stiffness; } @@ -126,7 +123,7 @@ namespace PhysX AngleLimitsFloatPair EditorHingeJointComponent::GetLinearValuePair(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterAngularPair) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::TwistLimits) { return AngleLimitsFloatPair(m_angularLimit.m_limitPositive, m_angularLimit.m_limitNegative); } @@ -134,33 +131,41 @@ namespace PhysX return AngleLimitsFloatPair(); } - bool EditorHingeJointComponent::IsParameterUsed(const AZStd::string& parameterName) + AZStd::vector EditorHingeJointComponent::GetSubComponentModesState() { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce - || parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque - ) + AZStd::vector subModes; + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition, + JointsComponentModeCommon::ParamaterNames::SnapPosition }); + + if (AZStd::vector baseSubModes = + EditorJointComponent::GetSubComponentModesState(); + !baseSubModes.empty()) { - return m_config.m_breakable; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - return !m_angularLimit.m_standardLimitConfig.m_isSoftLimit; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) - { - return m_angularLimit.m_standardLimitConfig.m_isSoftLimit; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) - { - return m_angularLimit.m_standardLimitConfig.m_isSoftLimit; + subModes.insert(subModes.end(), baseSubModes.begin(), baseSubModes.end()); } - return true; // Sub-component mode always enabled unless disabled explicitly. + if (m_angularLimit.m_standardLimitConfig.m_isLimited) + { + subModes.emplace_back( + JointsComponentModeCommon::SubModeParamaterState{ JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits, + JointsComponentModeCommon::ParamaterNames::TwistLimits }); + + if (m_angularLimit.m_standardLimitConfig.m_isSoftLimit) + { + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::Damping, JointsComponentModeCommon::ParamaterNames::Damping }); + subModes.emplace_back( + JointsComponentModeCommon::SubModeParamaterState{ JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness, + JointsComponentModeCommon::ParamaterNames::Stiffness }); + } + } + return subModes; } void EditorHingeJointComponent::SetBoolValue(const AZStd::string& parameterName, bool value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::ComponentMode) { m_angularLimit.m_standardLimitConfig.m_inComponentMode = value; m_config.m_inComponentMode = value; @@ -169,31 +174,23 @@ namespace PhysX &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay , AzToolsFramework::Refresh_EntireTree); } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap) - { - m_config.m_selectLeadOnSnap = value; - } } void EditorHingeJointComponent::SetLinearValue(const AZStd::string& parameterName, float value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxForce) { m_config.m_forceMax = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::MaxTorque) { m_config.m_torqueMax = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterTolerance) - { - m_angularLimit.m_standardLimitConfig.m_tolerance = value; - } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterDamping) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Damping) { m_angularLimit.m_standardLimitConfig.m_damping = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterStiffness) + else if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::Stiffness) { m_angularLimit.m_standardLimitConfig.m_stiffness = value; } @@ -201,7 +198,7 @@ namespace PhysX void EditorHingeJointComponent::SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterAngularPair) + if (parameterName == PhysX::JointsComponentModeCommon::ParamaterNames::TwistLimits) { m_angularLimit.m_limitPositive = valuePair.first; m_angularLimit.m_limitNegative = valuePair.second; @@ -267,7 +264,7 @@ namespace PhysX EditorJointRequestBus::EventResult(localTransform, AZ::EntityComponentIdPair(entityId, GetId()), &EditorJointRequests::GetTransformValue, - PhysX::EditorJointComponentMode::s_parameterTransform); + PhysX::JointsComponentModeCommon::ParamaterNames::Transform); debugDisplay.PushMatrix(worldTransform); debugDisplay.PushMatrix(localTransform); diff --git a/Gems/PhysX/Code/Source/EditorHingeJointComponent.h b/Gems/PhysX/Code/Source/EditorHingeJointComponent.h index 7c5bd8ad2f..6a2010464e 100644 --- a/Gems/PhysX/Code/Source/EditorHingeJointComponent.h +++ b/Gems/PhysX/Code/Source/EditorHingeJointComponent.h @@ -41,7 +41,7 @@ namespace PhysX // PhysX::EditorJointRequests float GetLinearValue(const AZStd::string& parameterName) override; AngleLimitsFloatPair GetLinearValuePair(const AZStd::string& parameterName) override; - bool IsParameterUsed(const AZStd::string& parameterName) override; + AZStd::vector GetSubComponentModesState() override; void SetBoolValue(const AZStd::string& parameterName, bool value) override; void SetLinearValue(const AZStd::string& parameterName, float value) override; void SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair) override; diff --git a/Gems/PhysX/Code/Source/EditorJointComponent.cpp b/Gems/PhysX/Code/Source/EditorJointComponent.cpp index 7b2d612cf1..88e192026d 100644 --- a/Gems/PhysX/Code/Source/EditorJointComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorJointComponent.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -134,21 +134,18 @@ namespace PhysX bool EditorJointComponent::GetBoolValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode) + if (parameterName == JointsComponentModeCommon::ParamaterNames::ComponentMode) { return m_config.m_inComponentMode; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap) - { - return m_config.m_selectLeadOnSnap; - } + AZ_Error("EditorJointComponent::GetBoolValue", false, "bool parameter not recognized: %s", parameterName.c_str()); return false; } AZ::EntityId EditorJointComponent::GetEntityIdValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterLeadEntity) + if (parameterName == JointsComponentModeCommon::ParamaterNames::LeadEntity) { return m_config.m_leadEntity; } @@ -160,11 +157,11 @@ namespace PhysX float EditorJointComponent::GetLinearValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == JointsComponentModeCommon::ParamaterNames::MaxForce) { return m_config.m_forceMax; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == JointsComponentModeCommon::ParamaterNames::MaxTorque) { return m_config.m_torqueMax; } @@ -181,7 +178,7 @@ namespace PhysX AZ::Transform EditorJointComponent::GetTransformValue(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterTransform) + if (parameterName == JointsComponentModeCommon::ParamaterNames::Transform) { return AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateFromEulerAnglesDegrees(m_config.m_localRotation), m_config.m_localPosition); @@ -192,11 +189,11 @@ namespace PhysX AZ::Vector3 EditorJointComponent::GetVector3Value(const AZStd::string& parameterName) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterPosition) + if (parameterName == JointsComponentModeCommon::ParamaterNames::Position) { return m_config.m_localPosition; } - if (parameterName == PhysX::EditorJointComponentMode::s_parameterRotation) + if (parameterName == JointsComponentModeCommon::ParamaterNames::Rotation) { return m_config.m_localRotation; } @@ -204,24 +201,27 @@ namespace PhysX return AZ::Vector3::CreateZero(); } - bool EditorJointComponent::IsParameterUsed(const AZStd::string& parameterName) + AZStd::vector EditorJointComponent::GetSubComponentModesState() { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce - || parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque - ) + AZStd::vector subModes; + if (m_config.m_breakable) { - return m_config.m_breakable; + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce, JointsComponentModeCommon::ParamaterNames::MaxForce }); + subModes.emplace_back(JointsComponentModeCommon::SubModeParamaterState{ + JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque, + JointsComponentModeCommon::ParamaterNames::MaxTorque }); } - return true; // Sub-component mode always enabled unless disabled explicitly. + return subModes; } void EditorJointComponent::SetLinearValue(const AZStd::string& parameterName, float value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce) + if (parameterName == JointsComponentModeCommon::ParamaterNames::MaxForce) { m_config.m_forceMax = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque) + else if (parameterName == JointsComponentModeCommon::ParamaterNames::MaxTorque) { m_config.m_torqueMax = value; } @@ -235,11 +235,11 @@ namespace PhysX void EditorJointComponent::SetVector3Value(const AZStd::string& parameterName, const AZ::Vector3& value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterPosition) + if (parameterName == JointsComponentModeCommon::ParamaterNames::Position) { m_config.m_localPosition = value; } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterRotation) + else if (parameterName == JointsComponentModeCommon::ParamaterNames::Rotation) { m_config.m_localRotation = value; } @@ -247,7 +247,7 @@ namespace PhysX void EditorJointComponent::SetBoolValue(const AZStd::string& parameterName, bool value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode) + if (parameterName == JointsComponentModeCommon::ParamaterNames::ComponentMode) { m_config.m_inComponentMode = value; @@ -255,15 +255,11 @@ namespace PhysX &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay , AzToolsFramework::Refresh_EntireTree); } - else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap) - { - m_config.m_selectLeadOnSnap = value; - } } void EditorJointComponent::SetEntityIdValue(const AZStd::string& parameterName, AZ::EntityId value) { - if (parameterName == PhysX::EditorJointComponentMode::s_parameterLeadEntity) + if (parameterName == JointsComponentModeCommon::ParamaterNames::LeadEntity) { m_config.SetLeadEntityId(value); } diff --git a/Gems/PhysX/Code/Source/EditorJointComponent.h b/Gems/PhysX/Code/Source/EditorJointComponent.h index 8e92e9820a..69142e6aed 100644 --- a/Gems/PhysX/Code/Source/EditorJointComponent.h +++ b/Gems/PhysX/Code/Source/EditorJointComponent.h @@ -56,7 +56,7 @@ namespace PhysX AngleLimitsFloatPair GetLinearValuePair(const AZStd::string& parameterName) override; AZ::Transform GetTransformValue(const AZStd::string& parameterName) override; AZ::Vector3 GetVector3Value(const AZStd::string& parameterName) override; - bool IsParameterUsed(const AZStd::string& parameterName) override; + AZStd::vector GetSubComponentModesState() override; void SetBoolValue(const AZStd::string& parameterName, bool value) override; void SetEntityIdValue(const AZStd::string& parameterName, AZ::EntityId value) override; void SetLinearValue(const AZStd::string& parameterName, float value) override; diff --git a/Gems/PhysX/Code/physx_editor_files.cmake b/Gems/PhysX/Code/physx_editor_files.cmake index 82f26feff3..5c0c038976 100644 --- a/Gems/PhysX/Code/physx_editor_files.cmake +++ b/Gems/PhysX/Code/physx_editor_files.cmake @@ -82,7 +82,6 @@ set(FILES Editor/ComboBoxEditButtonPair.cpp Editor/ColliderComponentMode.h Editor/ColliderComponentMode.cpp - Editor/ColliderSubComponentMode.h Editor/ColliderOffsetMode.h Editor/ColliderOffsetMode.cpp Editor/ColliderBoxMode.h @@ -99,36 +98,35 @@ set(FILES Editor/DebugDraw.h Editor/PolygonPrismMeshUtils.cpp Editor/PolygonPrismMeshUtils.h - Editor/EditorJointComponentMode.cpp - Editor/EditorJointComponentMode.h + Editor/EditorJointCommon.h Editor/EditorJointConfiguration.cpp Editor/EditorJointConfiguration.h - Editor/EditorJointTypeDrawer.cpp - Editor/EditorJointTypeDrawer.h - Editor/EditorJointTypeDrawerBus.h - Editor/EditorSubComponentModeAngleCone.cpp - Editor/EditorSubComponentModeAngleCone.h - Editor/EditorSubComponentModeAnglePair.cpp - Editor/EditorSubComponentModeAnglePair.h - Editor/EditorSubComponentModeBase.cpp - Editor/EditorSubComponentModeBase.h - Editor/EditorSubComponentModeLinear.cpp - Editor/EditorSubComponentModeLinear.h - Editor/EditorSubComponentModeRotation.cpp - Editor/EditorSubComponentModeRotation.h - Editor/EditorSubComponentModeSnap.cpp - Editor/EditorSubComponentModeSnap.h - Editor/EditorSubComponentModeSnapPosition.cpp - Editor/EditorSubComponentModeSnapPosition.h - Editor/EditorSubComponentModeSnapRotation.cpp - Editor/EditorSubComponentModeSnapRotation.h - Editor/EditorSubComponentModeVec3.cpp - Editor/EditorSubComponentModeVec3.h Editor/EditorViewportEntityPicker.cpp Editor/EditorViewportEntityPicker.h Editor/Source/Components/EditorSystemComponent.h Editor/Source/Components/EditorSystemComponent.cpp + Editor/Source/ComponentModes/Joints/JointsComponentMode.h + Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp + Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h + Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp + Editor/Source/ComponentModes/PhysXSubComponentModeBase.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeLinearFloat.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeRotation.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnap.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapPosition.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeSnapRotation.cpp + Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.h + Editor/Source/ComponentModes/Joints/JointsSubComponentModeTranslate.cpp Editor/Source/Configuration/PhysXEditorSettingsRegistryManager.h Editor/Source/Configuration/PhysXEditorSettingsRegistryManager.cpp ) diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h index 4a3ba89832..1e4fb27831 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h @@ -11,6 +11,7 @@ #include #include +#include #include #include diff --git a/cmake/Projects.cmake b/cmake/Projects.cmake index d3f4b33b03..61cb101909 100644 --- a/cmake/Projects.cmake +++ b/cmake/Projects.cmake @@ -151,18 +151,18 @@ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$") if(NOT DEFINED LY_ASSET_DEPLOY_ASSET_TYPE) set(LY_ASSET_DEPLOY_ASSET_TYPE @LY_ASSET_DEPLOY_ASSET_TYPE@) endif() - message(STATUS "Generating ${install_output_folder}/Engine.pak from @full_directory_path@/Cache/${LY_ASSET_DEPLOY_ASSET_TYPE}") + message(STATUS "Generating ${install_output_folder}/engine.pak from @full_directory_path@/Cache/${LY_ASSET_DEPLOY_ASSET_TYPE}") file(MAKE_DIRECTORY "${install_output_folder}") cmake_path(SET cache_product_path "@full_directory_path@/Cache/${LY_ASSET_DEPLOY_ASSET_TYPE}") file(GLOB product_assets "${cache_product_path}/*") if(product_assets) execute_process( - COMMAND ${CMAKE_COMMAND} -E tar "cf" "${install_output_folder}/Engine.pak" --format=zip -- ${product_assets} + COMMAND ${CMAKE_COMMAND} -E tar "cf" "${install_output_folder}/engine.pak" --format=zip -- ${product_assets} WORKING_DIRECTORY "${cache_product_path}" RESULT_VARIABLE archive_creation_result ) if(archive_creation_result EQUAL 0) - message(STATUS "${install_output_folder}/Engine.pak generated") + message(STATUS "${install_output_folder}/engine.pak generated") endif() endif() endif()