Merge branch 'development' into Atom/mriegger/stopdecalflickering
Signed-off-by: mrieggeramzn <mriegger@amazon.com>
@@ -44,7 +44,7 @@ enum
|
||||
{
|
||||
// in milliseconds
|
||||
GameModeIdleFrequency = 0,
|
||||
EditorModeIdleFrequency = 0,
|
||||
EditorModeIdleFrequency = 1,
|
||||
InactiveModeFrequency = 10,
|
||||
UninitializedFrequency = 9999,
|
||||
};
|
||||
|
||||
@@ -175,27 +175,15 @@ namespace SandboxEditor
|
||||
m_pivotCamera = AZStd::make_shared<AzFramework::PivotCameraInput>(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<AZ::Vector3> 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<AZ::Transform> 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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() });
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
#include "CryEdit.h"
|
||||
#include "Viewport.h"
|
||||
|
||||
// Atom Renderer
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <TrackView/ui_SequenceBatchRenderDialog.h>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h> // Used as the allocator for most components.
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -74,8 +74,6 @@
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
|
||||
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<int>(microsecondsPerSecond / g_simulation_tick_rate));
|
||||
AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now;
|
||||
|
||||
if (timeUntilNextTick.count() > 0)
|
||||
{
|
||||
AZStd::this_thread::sleep_for(timeUntilNextTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/EBus/Policies.h>
|
||||
|
||||
|
||||
@@ -19,14 +19,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/BusImpl.h>
|
||||
#include <AzCore/EBus/Environment.h>
|
||||
#include <AzCore/EBus/Results.h>
|
||||
#include <AzCore/EBus/Internal/Debug.h>
|
||||
|
||||
// Included for backwards compatibility purposes
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/typetraits/is_same.h>
|
||||
// End backwards compat
|
||||
|
||||
#include <AzCore/std/utils.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
@@ -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
|
||||
* `<BusName>::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.
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
#include <AzCore/std/function/invoke.h>
|
||||
#include <AzCore/std/containers/queue.h>
|
||||
#include <AzCore/std/containers/intrusive_set.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/EBus/Environment.h>
|
||||
|
||||
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<MutexType> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/function/invoke.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
|
||||
@@ -366,6 +366,42 @@ namespace UnitTest
|
||||
|
||||
};
|
||||
|
||||
static constexpr AZStd::chrono::seconds MaxDispatchTimeoutSeconds = BaseAssetManagerTest::DefaultTimeoutSeconds * 12;
|
||||
|
||||
template <typename Pred>
|
||||
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<AssetWithAssetReference>());
|
||||
OnAssetReadyListener depenencyListener(MyAsset2Id, azrtti_typeid<AssetWithAssetReference>());
|
||||
OnAssetReadyListener dependencyListener(MyAsset2Id, azrtti_typeid<AssetWithAssetReference>());
|
||||
|
||||
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<AssetWithAssetReference>(),
|
||||
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<AssetWithAssetReference>(),
|
||||
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();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Memory/PoolAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzFramework/Archive/Codec.h>
|
||||
#include <AzFramework/Archive/ZipDirStructures.h>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Logging/MissingAssetNotificationBus.h>
|
||||
|
||||
namespace AzFramework { class LogFile; }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
//! Common structures for Render geometry queries
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzNetworking
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzNetworking/Utilities/IpAddress.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnectionSet.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
|
||||
@@ -55,5 +55,8 @@ namespace UnitTest
|
||||
unusedBitTest.SetBit(i, false);
|
||||
}
|
||||
EXPECT_FALSE(unusedBitTest.AnySet());
|
||||
|
||||
unusedBitTest.SetBit(0, true);
|
||||
EXPECT_TRUE(unusedBitTest.AnySet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<UdpNetworkInterface*>(testClient.m_clientNetworkInterface)->IsEncrypted());
|
||||
|
||||
EXPECT_TRUE(testServer.m_serverNetworkInterface->StopListening());
|
||||
EXPECT_FALSE(testServer.m_serverNetworkInterface->StopListening());
|
||||
EXPECT_FALSE(dynamic_cast<UdpNetworkInterface*>(testServer.m_serverNetworkInterface)->IsOpen());
|
||||
}
|
||||
|
||||
TEST_F(UdpTransportTests, TestMultipleClients)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,13 +79,12 @@ namespace UnitTest
|
||||
template <uint32_t NUM_ELEMENTS, uint32_t NUM_BYTES>
|
||||
void TestQuantizedValuesHelper01()
|
||||
{
|
||||
AzNetworking::QuantizedValues<NUM_ELEMENTS, NUM_BYTES, 0, 1> testIn, testOut; // Transmits float values between 0 and 1 using NUM_BYTES
|
||||
AzNetworking::QuantizedValues<NUM_ELEMENTS, NUM_BYTES, 0, 1> testIn(ValueFromFloat<NUM_ELEMENTS>::Construct(0.0f)), testOut; // Transmits float values between 0 and 1 using NUM_BYTES
|
||||
|
||||
AZStd::array<uint8_t, 1024> buffer;
|
||||
AzNetworking::NetworkInputSerializer inputSerializer(buffer.data(), static_cast<uint32_t>(buffer.size()));
|
||||
AzNetworking::NetworkOutputSerializer outputSerializer(buffer.data(), static_cast<uint32_t>(buffer.size()));
|
||||
|
||||
testIn = ValueFromFloat<NUM_ELEMENTS>::Construct(0.0f);
|
||||
EXPECT_EQ(static_cast<typename ValueFromFloat<NUM_ELEMENTS>::ValueType>(testIn), ValueFromFloat<NUM_ELEMENTS>::Construct(0.0f));
|
||||
testIn.Serialize(inputSerializer);
|
||||
EXPECT_EQ(inputSerializer.GetSize(), NUM_BYTES * NUM_ELEMENTS);
|
||||
@@ -95,6 +94,8 @@ namespace UnitTest
|
||||
testIn = ValueFromFloat<NUM_ELEMENTS>::Construct(1.0f);
|
||||
EXPECT_EQ(static_cast<typename ValueFromFloat<NUM_ELEMENTS>::ValueType>(testIn), ValueFromFloat<NUM_ELEMENTS>::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);
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M16.9,16.7c0,0.7-0.6,1.3-1.3,1.3h-7c-0.7,0-1.3-0.6-1.3-1.3v-0.5h-2v0.5c0,1.8,1.5,3.3,3.3,3.3h2
|
||||
c-0.2,0.5-0.1,1.2,0.3,1.6c0.6,0.6,1.5,0.6,2.1,0c0.4-0.4,0.5-1,0.3-1.6h2.3c1.8,0,3.3-1.5,3.3-3.3v-0.5l-2,0V16.7z M12.3,20.9
|
||||
c-0.2,0.2-0.6,0.2-0.8,0c-0.2-0.2-0.2-0.5,0-0.8c0.2-0.2,0.5-0.2,0.8,0c0,0,0,0,0,0C12.5,20.3,12.5,20.7,12.3,20.9z"/>
|
||||
<rect x="6.5" y="8" transform="matrix(0.9939 -0.1101 0.1101 0.9939 -0.8771 1.3776)" class="st0" width="11" height="1.4"/>
|
||||
<rect x="6.5" y="10.6" transform="matrix(0.9939 -0.1101 0.1101 0.9939 -1.1681 1.3937)" class="st0" width="11" height="1.4"/>
|
||||
<rect x="6.5" y="13.2" transform="matrix(0.9939 -0.1101 0.1101 0.9939 -1.4588 1.4055)" class="st0" width="11" height="1.4"/>
|
||||
<path class="st0" d="M13.3,4c0.1-0.2,0.1-0.3,0.1-0.5c0-0.8-0.6-1.4-1.4-1.4s-1.4,0.6-1.4,1.4c0,0.2,0,0.4,0.1,0.5H5.2v2.3h13.6V4
|
||||
H13.3z M12,4c-0.3,0-0.6-0.3-0.6-0.6c0-0.3,0.3-0.6,0.6-0.6s0.6,0.3,0.6,0.6C12.6,3.7,12.3,4,12,4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M3,17.9v1.3c5.9,1.2,12.1,1.2,18,0v-1.3C15.1,19.1,8.9,19.1,3,17.9z"/>
|
||||
<path class="st0" d="M3,15.9v1.3c5.9,1.2,12.1,1.2,18,0v-1.3C15.1,17.2,8.9,17.2,3,15.9z"/>
|
||||
<path class="st0" d="M3,14v1.3c5.9,1.2,12.1,1.2,18-0.1v-1.3C15.1,15.2,8.9,15.3,3,14z"/>
|
||||
<path class="st0" d="M6.5,11.5c0.1,0.1,0.2,0.2,0.4,0.2c0.1,0,0.3-0.1,0.4-0.2l2-2.1c0.2-0.2,0.2-0.5,0-0.8c-0.2-0.2-0.5-0.2-0.7,0
|
||||
c0,0,0,0,0,0L7.4,9.9V3.3C7.4,3.2,7.3,3,7.2,3c0,0,0,0,0,0H6.7C6.5,3,6.4,3.1,6.4,3.3v0.2v6.4L5.3,8.7C5,8.5,4.7,8.5,4.5,8.7
|
||||
C4.4,8.8,4.4,8.9,4.3,9.1c0,0.1,0.1,0.3,0.2,0.4L6.5,11.5z"/>
|
||||
<path class="st0" d="M16.7,11.5c0.1,0.1,0.2,0.2,0.4,0.2c0.1,0,0.3-0.1,0.4-0.2l2-2.1c0.2-0.2,0.2-0.5,0-0.8
|
||||
c-0.2-0.2-0.5-0.2-0.7,0c0,0,0,0,0,0l-1.1,1.1V3.3c0-0.2-0.1-0.3-0.2-0.3c0,0,0,0,0,0h-0.5c-0.2,0-0.3,0.1-0.3,0.3v0.2v6.4
|
||||
l-1.1-1.2c-0.2-0.2-0.6-0.2-0.8,0c-0.1,0.1-0.1,0.2-0.1,0.4c0,0.1,0.1,0.3,0.1,0.4L16.7,11.5z"/>
|
||||
<path class="st0" d="M9.6,11.3l2,2.1c0.1,0.1,0.2,0.2,0.4,0.2c0.1,0,0.3-0.1,0.4-0.2l2-2.1c0.2-0.2,0.2-0.5,0-0.8c0,0,0,0,0,0
|
||||
c-0.2-0.2-0.5-0.2-0.7,0c0,0,0,0,0,0l-1.1,1.1V5.1c0-0.2-0.1-0.3-0.3-0.3c0,0,0,0,0,0h-0.5c-0.2,0-0.3,0.1-0.3,0.3v0.1v6.4
|
||||
l-1.1-1.1c-0.2-0.2-0.5-0.2-0.7,0c0,0,0,0,0,0c-0.1,0.1-0.2,0.2-0.2,0.4C9.4,11,9.5,11.2,9.6,11.3z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M12,12.2c-5.9,0-7-1.6-7-1.6v7.2c0.1,1,3,1.9,6.7,1.9V21c0,0.2,0.1,0.3,0.3,0.3s0.3-0.1,0.3-0.3v-1.3
|
||||
c3.6,0,6.5-0.9,6.7-1.9v-7.2C19,10.6,17.9,12.2,12,12.2z"/>
|
||||
<path class="st0" d="M12.3,7.6V6.9l0.8,0.4V6.6c2.7-0.1,5.2-0.7,5.2-1.4c0-0.8-2.7-1.2-6-1.2V3c0-0.2-0.1-0.3-0.3-0.3
|
||||
c-0.2,0-0.3,0.1-0.3,0.3v1c-3.3,0-6,0.4-6,1.2c0,0.2,0.5,0.4,0.8,0.5C7.2,5.9,8,6.1,8.8,6.1c0.3,0,0.5,0,0.8,0C9.4,6,9.2,6,9,6
|
||||
C7.6,5.9,7.2,5.5,7.2,5.2c0-0.5,1.8-0.7,4.4-0.7v1.1l-1,0.5l1,0.5v1.1C8,7.7,5,8.5,5,9.6c0,1.1,3.1,2,7,2s7-0.9,7-2
|
||||
C19,8.5,16,7.7,12.3,7.6z M12.3,4.6c2.6,0,4.5,0.2,4.5,0.7c0,0.5-1.7,0.6-3.6,0.7v-1l-0.9,0.4V4.6z M8.4,9.6c0-0.5,1.4-0.9,3.2-1v2
|
||||
C9.8,10.6,8.4,10.1,8.4,9.6z M12.3,10.6v-2c1.8,0,3.2,0.5,3.2,1C15.6,10.1,14.2,10.6,12.3,10.6z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M19.6,11.7l-2.2-2.2l0,0l-1.7-1.7l0,0h0l0,0l0,0h0l0,0L13.4,10l-0.1,0.1l0,0l0,0l1.7,1.7l0,0l1.6,1.6
|
||||
c1,0.8,1.1,2.2,0.4,3.2c-0.3,0.3-0.8,0.5-1.2,0.5c-0.7,0-1.5-0.3-2-0.8l-1.6-1.6l0,0L10.5,13l-0.7,0.7l-1.7,1.7l3.9,3.9
|
||||
c2.2,2,5.6,1.7,7.6-0.5C21.3,16.7,21.3,13.7,19.6,11.7z M18.4,18.5c-1.6,1.4-4.1,1.4-5.7,0l-2.2-2.2l0.9-0.9L13,17
|
||||
c0.7,0.7,1.7,1.1,2.7,1.1c0.7,0,1.5-0.3,2-0.8c1.2-1.4,1-3.5-0.3-4.7l-1.6-1.6l0.9-0.9l2.2,2.2C20.4,14.2,20.2,16.9,18.4,18.5z"/>
|
||||
<polygon class="st0" points="6.1,7.5 5.1,7.5 5.1,5.9 3,8 5.1,10.1 5.1,8.5 6.1,8.5 "/>
|
||||
<polygon class="st0" points="7.5,6.1 8.5,6.1 8.5,5.1 10.1,5.1 8,3 5.9,5.1 7.5,5.1 "/>
|
||||
<polygon class="st0" points="8.5,11 8.5,10 7.5,10 7.5,10.9 5.9,10.9 8,13 10.1,11 "/>
|
||||
<polygon class="st0" points="10,7.5 10,8.5 10.9,8.5 10.9,10.1 13,8 10.9,5.9 11,7.5 "/>
|
||||
<rect x="6.5" y="6.5" class="st0" width="3" height="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M19.6,11.7l-2.2-2.2l0,0l-1.7-1.7l0,0h0l0,0l0,0h0l0,0L13.4,10l-0.1,0.1l0,0l0,0l1.7,1.7l0,0l1.6,1.6
|
||||
c1,0.8,1.1,2.2,0.4,3.2c-0.3,0.3-0.8,0.5-1.2,0.5c-0.7,0-1.5-0.3-2-0.8l-1.6-1.6l0,0L10.5,13l-0.7,0.7l-1.7,1.7l3.9,3.9
|
||||
c2.2,2,5.6,1.7,7.6-0.5C21.3,16.7,21.3,13.7,19.6,11.7z M18.4,18.5c-1.6,1.4-4.1,1.4-5.7,0l-2.2-2.2l0.9-0.9L13,17
|
||||
c0.7,0.7,1.7,1.1,2.7,1.1c0.7,0,1.5-0.3,2-0.8c1.2-1.4,1-3.5-0.3-4.7l-1.6-1.6l0.9-0.9l2.2,2.2C20.4,14.2,20.2,16.9,18.4,18.5z"/>
|
||||
<path class="st0" d="M7.1,9.5l2.1,2.1v-1.2c2.3-0.3,4-1.4,4-3.4c0-2.3-2.2-3.5-5-3.5s-5,1.2-5,3.5c0,0.5,0.2,1.1,0.6,1.5
|
||||
C4.3,9,5,9.4,5.8,9.5c0.4,0.1,0.6,0.2,0.6,0.1S6.2,9.4,5.9,9.2C5,8.9,4.4,8,4.5,7c0-1.4,1.5-2,3.7-2S12,5.6,12,7
|
||||
c0,1.2-1.1,2-2.8,2.2V7.4L7.1,9.5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M14.5,11.3L14.5,11.3c-0.1,0-0.2,0-0.3,0.1c-0.2,0.1-0.4,0.2-0.6,0.4c-0.5,0.4-1,0.6-1.6,0.7
|
||||
c-0.6-0.1-1.2-0.4-1.6-0.7c-0.2-0.1-0.4-0.3-0.6-0.4c-0.1,0-0.2-0.1-0.3-0.1H9.5c-2.4,0-3,1-3,1c-0.1,0.2-0.2,0.3-0.3,0.5v1.5
|
||||
c0,0.4,0.5,0.8,0.5,0.8l1.6,1.6c0.5,0.5,0.8,1.3,0.9,2V21c0,0.4,0.3,0.7,0.7,0.7c0,0,0,0,0,0h4.1c0.4,0,0.7-0.3,0.7-0.7
|
||||
c0,0,0,0,0,0v-2.3c0-0.7,0.3-1.5,0.9-2l1.6-1.6c0,0,0.5-0.4,0.5-0.8v-1.5c-0.1-0.2-0.2-0.4-0.3-0.5C17.5,12.3,16.9,11.3,14.5,11.3z
|
||||
"/>
|
||||
<path class="st0" d="M9.5,10.3c0.2,0,0.3,0.1,0.5,0.1c0.6,0.3,1.3,1.1,2.1,1.1s1.5-0.8,2.1-1.1c0.1-0.1,0.3-0.1,0.5-0.1
|
||||
c2.7,0,3.3,1.1,3.3,1.1V11c0-0.6-0.3-1.2-0.7-1.7l-1.5-1.6c-0.5-0.7-0.7-1.5-0.7-2.4V3c0-0.6-0.4-1-1-1h-3.8c-0.6,0-1,0.4-1,1v2.3
|
||||
C9.1,6.2,8.9,7,8.4,7.7L6.9,9.3C6.5,9.7,6.2,10.4,6.2,11v0.5C6.2,11.5,6.8,10.3,9.5,10.3z"/>
|
||||
<path class="st0" d="M19.6,7.8c-0.1-0.2-0.3-0.2-0.5-0.1C19,7.7,18.9,7.9,19,8.1c1.4,2.5,1.4,5.4,0,7.9c0,0,0,0,0,0
|
||||
c-0.1,0.2,0,0.4,0.1,0.4c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.3-0.1C21.1,13.7,21.1,10.4,19.6,7.8z"/>
|
||||
<path class="st0" d="M4.1,11.7c0-1.2,0.3-2.4,0.8-3.4c0.1-0.2,0-0.4-0.2-0.4C4.5,7.8,4.3,7.8,4.3,8c-1.2,2.5-1.1,5.4,0.2,7.8
|
||||
C4.5,15.9,4.6,16,4.7,16c0,0,0.1,0,0.1,0c0,0,0,0,0,0C5,15.9,5.1,15.7,5,15.5C4.4,14.3,4.1,13,4.1,11.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M19.3,10.7l0.1-2.5c0-0.2-0.2-0.4-0.4-0.4c-0.3,0-0.5,0.2-0.5,0.5l-0.1,1.6L18,9.5l0,0
|
||||
c-0.1-0.1-0.2-0.2-0.2-0.2c-0.4-0.4-0.9-0.7-1.3-0.9L17,6.7c0.1-0.3,0-0.6-0.3-0.7c0,0-0.1,0-0.1,0l-3.1-0.6
|
||||
c-0.3-0.1-0.6,0.1-0.7,0.4c0,0,0,0.1,0,0.1l-0.1,1.4C10.3,7,7.9,7.8,6,9.5l0,0L5.6,9.8V8.2c0-0.3-0.2-0.5-0.5-0.5c0,0,0,0,0,0
|
||||
c-0.2,0-0.5,0.2-0.5,0.4c0,0,0,0,0,0v2.5c0,0.3,0.2,0.5,0.5,0.5l2.5,0.1c0.3,0,0.5-0.2,0.5-0.5c0-0.3-0.2-0.5-0.5-0.5l-1.5-0.1
|
||||
C6.3,10,6.4,9.8,6.6,9.7c1.8-1.5,4-2.1,6.1-1.9l-0.1,1.9c0,0.4,0.3,0.7,0.6,0.8l0.3,0.1l-1.8,9.2c-0.6,0.1-1.1,0.6-1.1,1.2
|
||||
c0,0.7,0.6,1.3,1.3,1.3s1.3-0.6,1.3-1.3c0-0.4-0.2-0.8-0.6-1l1.8-9.2l0.3,0.1c0.4,0.1,0.7-0.1,0.9-0.5l0.5-1.4
|
||||
c0.6,0.3,1.1,0.7,1.6,1.2l0.1,0.1c0,0,0.1,0.1,0.1,0.1h-1.6c-0.1,0-0.3,0-0.3,0.1c-0.1,0.1-0.1,0.2-0.2,0.3c0,0.2,0.2,0.4,0.4,0.5
|
||||
c0,0,0,0,0,0h2.5C19.1,11.2,19.3,11,19.3,10.7z"/>
|
||||
<path class="st0" d="M2.8,10.1c-0.1-0.1-0.3-0.1-0.4,0c-0.1,0.1-0.1,0.3,0,0.4l2.9,2.7c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.2,0,0.2-0.1
|
||||
c0.1-0.1,0.1-0.3,0-0.4L2.8,10.1z"/>
|
||||
<path class="st0" d="M21.5,10c-0.1-0.1-0.3-0.1-0.4,0l-2.7,2.9c0,0.1-0.1,0.1-0.1,0.2c0,0.1,0,0.1,0.1,0.2c0.1,0.1,0.3,0.1,0.4,0
|
||||
l2.6-2.9C21.6,10.3,21.6,10.1,21.5,10z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M17.5,18.1c-0.1,0-0.1,0-0.2,0H6.9l7.4-7.3c0.3-0.2,0.3-0.6,0-0.9c0,0,0,0,0,0c-0.1-0.1-0.3-0.2-0.5-0.2
|
||||
c-0.2,0-0.3,0.1-0.5,0.2L6,17.2V6.9c0-0.4-0.3-0.7-0.7-0.7C5,6.2,4.7,6.5,4.7,6.9c0,0,0,0,0,0L4.6,17.1c0,0,0,0,0,0
|
||||
c-1.3,0-2.3,1-2.3,2.3s1,2.3,2.3,2.3s2.3-1,2.3-2.3h10.4c0.4,0,0.7-0.2,0.7-0.6C18.1,18.5,17.9,18.1,17.5,18.1z"/>
|
||||
<path class="st0" d="M21.8,13.2c-0.2-0.2-0.6-0.2-0.9,0l-1.3,1.3V14c-0.1-5.2-4.3-9.4-9.5-9.4H9.6l1.3-1.2c0.2-0.2,0.2-0.6,0-0.9
|
||||
c-0.1-0.1-0.3-0.2-0.4-0.2c-0.2,0-0.3,0.1-0.4,0.2L7.7,4.8C7.6,4.9,7.5,5.1,7.5,5.2c0,0.2,0.1,0.3,0.2,0.4l2.3,2.3
|
||||
c0.2,0.2,0.6,0.2,0.9,0c0.2-0.2,0.2-0.6,0-0.8L9.6,5.8h0.5c4.6,0,8.3,3.6,8.3,8.2c0,0,0,0,0,0v0.5l-1.3-1.3
|
||||
c-0.1-0.1-0.3-0.2-0.4-0.2c-0.2,0-0.3,0.1-0.4,0.2c-0.2,0.2-0.2,0.6,0,0.8c0,0,0,0,0,0l2.4,2.3c0.2,0.2,0.6,0.2,0.9,0l2.3-2.3
|
||||
C22.1,13.8,22.1,13.4,21.8,13.2z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -390,6 +390,14 @@
|
||||
<file>img/UI20/toolbar/Y_axis.svg</file>
|
||||
<file>img/UI20/toolbar/Z_axis.svg</file>
|
||||
<file>img/UI20/toolbar/XY2_copy.svg</file>
|
||||
<file>img/UI20/toolbar/joints/Damping.svg</file>
|
||||
<file>img/UI20/toolbar/joints/MaxForce.svg</file>
|
||||
<file>img/UI20/toolbar/joints/MaxTorque.svg</file>
|
||||
<file>img/UI20/toolbar/joints/SnapPosition.svg</file>
|
||||
<file>img/UI20/toolbar/joints/SnapRotation.svg</file>
|
||||
<file>img/UI20/toolbar/joints/Stiffness.svg</file>
|
||||
<file>img/UI20/toolbar/joints/SwingLimits.svg</file>
|
||||
<file>img/UI20/toolbar/joints/TwistLimits.svg</file>
|
||||
<file>img/triangle0.png</file>
|
||||
<file>img/triangle0_highlighted.png</file>
|
||||
<file>img/line.png</file>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include "Platform.h"
|
||||
#include <AzTest/Platform.h>
|
||||
#include <iostream>
|
||||
|
||||
class ModuleHandle
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
namespace AZ::Data
|
||||
{
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
#include "ComponentModeCollection.h"
|
||||
|
||||
#include <AzToolsFramework/Commands/ComponentModeCommand.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
|
||||
#include <AzToolsFramework/Commands/ComponentModeCommand.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorSpace.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
|
||||
@@ -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<EditorPickEntitySelection>(entityDataCache);
|
||||
return AZStd::make_unique<EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
if (!pickModeEntityContextId.IsNull())
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
#include <AZTestShared/Utils/Utils.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityTransformBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
@@ -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<AzToolsFramework::EditorDefaultSelection> defaultSelection =
|
||||
AZStd::make_unique<AzToolsFramework::EditorDefaultSelection>(entityDataCache);
|
||||
AZStd::make_unique<AzToolsFramework::EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);
|
||||
|
||||
// override the phantom widget so we can use out custom test widget
|
||||
defaultSelection->SetOverridePhantomWidget(&m_editorActions.m_componentModeWidget);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "EditorDefaultSelection.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
@@ -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::ManipulatorManager>(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
m_transformComponentSelection = AZStd::make_unique<EditorTransformComponentSelection>(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)
|
||||
|
||||
@@ -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<AzToolsFramework::ManipulatorManager> 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
|
||||
|
||||
@@ -10,9 +10,24 @@
|
||||
|
||||
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
|
||||
#include <AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
EditorInteractionSystemComponent::EditorInteractionSystemComponent()
|
||||
: m_viewportEditorMode(AZStd::make_unique<ViewportEditorModeTracker>())
|
||||
{
|
||||
AZ_Assert(AZ::Interface<ViewportEditorModeTrackerInterface>::Get() == nullptr, "Unexpected registration of viewport editor mode tracker.")
|
||||
AZ::Interface<ViewportEditorModeTrackerInterface>::Register(m_viewportEditorMode.get());
|
||||
}
|
||||
|
||||
EditorInteractionSystemComponent::~EditorInteractionSystemComponent()
|
||||
{
|
||||
m_interactionRequests.reset();
|
||||
AZ_Assert(AZ::Interface<ViewportEditorModeTrackerInterface>::Get() != nullptr, "Unexpected unregistration of viewport editor mode tracker.")
|
||||
AZ::Interface<ViewportEditorModeTrackerInterface>::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<EditorVisibleEntityDataCache>();
|
||||
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<EditorDefaultSelection>(entityDataCache);
|
||||
return AZStd::make_unique<EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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<InternalViewportSelectionRequests> m_interactionRequests; //!< Hold a concrete implementation of
|
||||
//!< ViewportSelectionRequests to handle viewport
|
||||
//!< input and drawing for the Editor.
|
||||
|
||||
AZStd::unique_ptr<ViewportEditorModeTracker> m_viewportEditorMode; //!< Editor mode tracker for each viewport.
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -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<AZStd::unique_ptr<ViewportInteraction::InternalViewportSelectionRequests>(const EditorVisibleEntityDataCache*)>;
|
||||
using ViewportSelectionRequestsBuilderFn = AZStd::function<AZStd::unique_ptr<ViewportInteraction::InternalViewportSelectionRequests>(
|
||||
const EditorVisibleEntityDataCache*, ViewportEditorModeTrackerInterface*)>;
|
||||
|
||||
//! Interface for system component implementing the ViewportSelectionRequests interface.
|
||||
//! This interface also includes a setter to set a custom handler also implementing
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "EditorPickEntitySelection.h"
|
||||
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <QApplication>
|
||||
|
||||
@@ -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<EditorHelpers>(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
|
||||
|
||||
@@ -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<EditorHelpers> 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
|
||||
|
||||
@@ -45,22 +45,6 @@ namespace AzToolsFramework
|
||||
return m_editorModes[static_cast<AZ::u32>(mode)];
|
||||
}
|
||||
|
||||
void ViewportEditorModeTracker::RegisterInterface()
|
||||
{
|
||||
if (AZ::Interface<ViewportEditorModeTrackerInterface>::Get() == nullptr)
|
||||
{
|
||||
AZ::Interface<ViewportEditorModeTrackerInterface>::Register(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportEditorModeTracker::UnregisterInterface()
|
||||
{
|
||||
if (AZ::Interface<ViewportEditorModeTrackerInterface>::Get() != nullptr)
|
||||
{
|
||||
AZ::Interface<ViewportEditorModeTrackerInterface>::Unregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> ViewportEditorModeTracker::ActivateMode(
|
||||
const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode)
|
||||
{
|
||||
|
||||
@@ -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<void, AZStd::string> ActivateMode(const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode) override;
|
||||
AZ::Outcome<void, AZStd::string> DeactivateMode(const ViewportEditorModeInfo& viewportEditorModeInfo, ViewportEditorMode mode) override;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/ViewportUi/ViewportUiRequestBus.h>
|
||||
|
||||
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<ButtonId> m_buttonTriggeredEvent;
|
||||
ViewportUiElementId m_viewportUiId;
|
||||
AZStd::unordered_map<ButtonId, AZStd::unique_ptr<Button>> m_buttons;
|
||||
ButtonId m_highlightedButtonId = InvalidButtonId;
|
||||
};
|
||||
} // namespace AzToolsFramework::ViewportUi::Internal
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <Tests/BoundsTestComponent.h>
|
||||
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
|
||||
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
|
||||
@@ -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 <AzFramework/Visibility/BoundsBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
|
||||
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
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
|
||||
@@ -22,12 +21,10 @@
|
||||
#include <AzManipulatorTestFramework/ViewportInteraction.h>
|
||||
#include <AzQtComponents/Components/GlobalEventFilter.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityModel.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
@@ -41,6 +38,8 @@
|
||||
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
|
||||
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
|
||||
|
||||
#include<Tests/BoundsTestComponent.h>
|
||||
|
||||
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<AzToolsFramework::EditorPickEntitySelection>(entityDataCache);
|
||||
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
// When
|
||||
|
||||
@@ -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 <Tests/FocusMode/EditorFocusModeFixture.h>
|
||||
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
|
||||
#include <Tests/BoundsTestComponent.h>
|
||||
|
||||
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<FocusModeInterface>::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<UnitTest::BoundsTestComponent>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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 <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
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<AZStd::string, AZ::EntityId> 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);
|
||||
};
|
||||
}
|
||||
@@ -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 <Tests/FocusMode/EditorFocusModeFixture.h>
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
|
||||
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
|
||||
|
||||
#include <AzToolsFramework/Component/EditorComponentAPIBus.h>
|
||||
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
|
||||
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EditorFocusModeSelectionFixture
|
||||
: public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -6,123 +6,99 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <Tests/FocusMode/EditorFocusModeFixture.h>
|
||||
|
||||
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<AZStd::string, AZ::EntityId> m_entityMap;
|
||||
};
|
||||
|
||||
TEST_F(EditorFocusModeTests, EditorFocusModeTests_SetFocus)
|
||||
{
|
||||
FocusModeInterface* focusModeInterface = AZ::Interface<FocusModeInterface>::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<FocusModeInterface>::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<AzToolsFramework::Prefab::Instance> 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<AzToolsFramework::Prefab::Instance> 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<AzToolsFramework::Prefab::Instance> 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<PrefabFocusInterface>::Get();
|
||||
ASSERT_TRUE(m_prefabFocusInterface != nullptr);
|
||||
|
||||
GenerateTestHierarchy();
|
||||
}
|
||||
|
||||
void TearDownEditorFixtureImpl() override
|
||||
{
|
||||
m_rootInstance.release();
|
||||
|
||||
PrefabTestFixture::TearDownEditorFixtureImpl();
|
||||
}
|
||||
|
||||
AZStd::unordered_map<AZStd::string, AZ::Entity*> m_entityMap;
|
||||
AZStd::unordered_map<AZStd::string, Instance*> m_instanceMap;
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> 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<PrefabFocusInterface>::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<PrefabFocusInterface>::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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
*/
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h>
|
||||
|
||||
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<ViewportEditorMode>(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<ViewportEditorMode>(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<AZStd::unique_ptr<ViewportEditorModeNotificationsBusHandler>, 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<ViewportEditorModeTrackerInterface>::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<ViewportEditorMode>(mode);
|
||||
if (editorMode == m_selectedEditorMode)
|
||||
{
|
||||
EXPECT_TRUE(m_editorModes.IsModeActive(static_cast<ViewportEditorMode>(editorMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_FALSE(m_editorModes.IsModeActive(static_cast<ViewportEditorMode>(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<ViewportEditorMode>(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<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
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<AzToolsFramework::EditorPickEntitySelection>(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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "UnitTestRunner.h"
|
||||
#include "native/utilities/IniConfiguration.h"
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Aws
|
||||
{
|
||||
namespace CognitoIdentityProvider
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
#include <AWSCoreBus.h>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Memory/MemoryDrillerBus.h>
|
||||
#include <AzCore/Debug/AssetTrackingTypesImpl.h>
|
||||
#include <AzCore/Debug/AssetTracking.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.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<Notification>;
|
||||
} // namespace Bootstrap
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -42,14 +42,7 @@
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <BootstrapSystemComponent_Traits_Platform.h>
|
||||
|
||||
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()
|
||||
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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<RPI::MaterialAsset> m_materialAsset;
|
||||
Data::Asset<RPI::MaterialAsset> m_defaultMaterialAsset;
|
||||
Data::Instance<RPI::Material> m_materialInstance;
|
||||
MaterialPropertyOverrideMap m_propertyOverrides;
|
||||
RPI::MaterialModelUvOverrideMap m_matModUvOverrides;
|
||||
bool m_materialInstancePreCreated = false;
|
||||
};
|
||||
|
||||
using MaterialAssignmentMap = AZStd::unordered_map<MaterialAssignmentId, MaterialAssignment>;
|
||||
|
||||
@@ -71,9 +71,9 @@ namespace AZ
|
||||
}
|
||||
|
||||
MaterialAssignment::MaterialAssignment(const AZ::Data::AssetId& materialAssetId)
|
||||
: m_materialInstance()
|
||||
: m_materialAsset(materialAssetId, AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid())
|
||||
, m_materialInstance()
|
||||
{
|
||||
m_materialAsset.Create(materialAssetId);
|
||||
}
|
||||
|
||||
MaterialAssignment::MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& 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
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <AzCore/std/parallel/threadbus.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -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 <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
|
||||
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
|
||||