Merge branch 'main' into non-uniform-scale-blast
This commit is contained in:
@@ -193,13 +193,12 @@ namespace AzFramework
|
||||
bool handling = false;
|
||||
for (auto& cameraInput : m_activeCameraInputs)
|
||||
{
|
||||
cameraInput->HandleEvents(event, cursorDelta, scrollDelta);
|
||||
handling = !cameraInput->Idle() || handling;
|
||||
handling = cameraInput->HandleEvents(event, cursorDelta, scrollDelta) || handling;
|
||||
}
|
||||
|
||||
for (auto& cameraInput : m_idleCameraInputs)
|
||||
{
|
||||
cameraInput->HandleEvents(event, cursorDelta, scrollDelta);
|
||||
handling = cameraInput->HandleEvents(event, cursorDelta, scrollDelta) || handling;
|
||||
}
|
||||
|
||||
return handling;
|
||||
@@ -262,17 +261,26 @@ namespace AzFramework
|
||||
{
|
||||
m_activeCameraInputs[i]->Reset();
|
||||
m_idleCameraInputs.push_back(m_activeCameraInputs[i]);
|
||||
m_activeCameraInputs[i] = m_activeCameraInputs[m_activeCameraInputs.size() - 1];
|
||||
using AZStd::swap;
|
||||
swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
|
||||
m_activeCameraInputs.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Cameras::Clear()
|
||||
{
|
||||
Reset();
|
||||
AZ_Assert(m_activeCameraInputs.empty(), "Active Camera Inputs is not empty");
|
||||
|
||||
m_idleCameraInputs.clear();
|
||||
}
|
||||
|
||||
RotateCameraInput::RotateCameraInput(const InputChannelId rotateChannelId)
|
||||
: m_rotateChannelId(rotateChannelId)
|
||||
{
|
||||
}
|
||||
|
||||
void RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
const ClickDetector::ClickEvent clickEvent = [&event, this] {
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
@@ -304,6 +312,11 @@ namespace AzFramework
|
||||
// noop
|
||||
break;
|
||||
}
|
||||
|
||||
// note - must also check !ending to ensure the mouse up (release) event
|
||||
// is not consumed and can be propagated to other systems.
|
||||
// (don't swallow mouse up events)
|
||||
return !Idle() && !Ending();
|
||||
}
|
||||
|
||||
Camera RotateCameraInput::StepCamera(
|
||||
@@ -330,7 +343,7 @@ namespace AzFramework
|
||||
{
|
||||
}
|
||||
|
||||
void PanCameraInput::HandleEvents(
|
||||
bool PanCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
@@ -347,6 +360,8 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera PanCameraInput::StepCamera(
|
||||
@@ -411,7 +426,7 @@ namespace AzFramework
|
||||
{
|
||||
}
|
||||
|
||||
void TranslateCameraInput::HandleEvents(
|
||||
bool TranslateCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
@@ -429,7 +444,8 @@ namespace AzFramework
|
||||
m_boost = true;
|
||||
}
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
// ensure we don't process end events in the idle state
|
||||
else if (input->m_state == InputChannel::State::Ended && !Idle())
|
||||
{
|
||||
m_translation &= ~(translationFromKey(input->m_channelId));
|
||||
if (m_translation == TranslationType::Nil)
|
||||
@@ -442,6 +458,8 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera TranslateCameraInput::StepCamera(
|
||||
@@ -503,7 +521,7 @@ namespace AzFramework
|
||||
m_boost = false;
|
||||
}
|
||||
|
||||
void OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta)
|
||||
bool OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -522,8 +540,10 @@ namespace AzFramework
|
||||
|
||||
if (Active())
|
||||
{
|
||||
m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
return m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera OrbitCameraInput::StepCamera(
|
||||
@@ -533,7 +553,7 @@ namespace AzFramework
|
||||
|
||||
if (Beginning())
|
||||
{
|
||||
const auto hasLookAt = [&nextCamera, &targetCamera, lookAtFn = m_lookAtFn] {
|
||||
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] {
|
||||
if (lookAtFn)
|
||||
{
|
||||
if (const auto lookAt = lookAtFn())
|
||||
@@ -585,13 +605,15 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitDollyScrollCameraInput::HandleEvents(
|
||||
bool OrbitDollyScrollCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera OrbitDollyScrollCameraInput::StepCamera(
|
||||
@@ -609,7 +631,7 @@ namespace AzFramework
|
||||
{
|
||||
}
|
||||
|
||||
void OrbitDollyCursorMoveCameraInput::HandleEvents(
|
||||
bool OrbitDollyCursorMoveCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
@@ -626,6 +648,8 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera OrbitDollyCursorMoveCameraInput::StepCamera(
|
||||
@@ -637,13 +661,15 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void ScrollTranslationCameraInput::HandleEvents(
|
||||
bool ScrollTranslationCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
BeginActivation();
|
||||
}
|
||||
|
||||
return !Idle();
|
||||
}
|
||||
|
||||
Camera ScrollTranslationCameraInput::StepCamera(
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace AzFramework
|
||||
ResetImpl();
|
||||
}
|
||||
|
||||
virtual void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) = 0;
|
||||
virtual bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) = 0;
|
||||
virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0;
|
||||
|
||||
virtual bool Exclusive() const
|
||||
@@ -171,16 +171,29 @@ namespace AzFramework
|
||||
class Cameras
|
||||
{
|
||||
public:
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta);
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
|
||||
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
//! Reset the state of all cameras.
|
||||
void Reset();
|
||||
//! Remove all cameras that were added.
|
||||
void Clear();
|
||||
//! Is one of the cameras in the active camera inputs marked as 'exclusive'.
|
||||
//! @note This implies no other sibling cameras can begin while the exclusive camera is running.
|
||||
bool Exclusive() const;
|
||||
|
||||
private:
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_activeCameraInputs;
|
||||
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_idleCameraInputs;
|
||||
};
|
||||
|
||||
inline bool Cameras::Exclusive() const
|
||||
{
|
||||
return AZStd::any_of(
|
||||
m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); });
|
||||
}
|
||||
|
||||
class CameraSystem
|
||||
{
|
||||
public:
|
||||
@@ -200,7 +213,7 @@ namespace AzFramework
|
||||
explicit RotateCameraInput(InputChannelId rotateChannelId);
|
||||
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
@@ -241,7 +254,7 @@ namespace AzFramework
|
||||
PanCameraInput(InputChannelId panChannelId, PanAxesFn panAxesFn);
|
||||
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
@@ -282,7 +295,7 @@ namespace AzFramework
|
||||
explicit TranslateCameraInput(TranslationAxesFn translationAxesFn);
|
||||
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
void ResetImpl() override;
|
||||
|
||||
@@ -352,7 +365,7 @@ namespace AzFramework
|
||||
{
|
||||
public:
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
};
|
||||
|
||||
@@ -362,7 +375,7 @@ namespace AzFramework
|
||||
explicit OrbitDollyCursorMoveCameraInput(InputChannelId dollyChannelId);
|
||||
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
@@ -373,7 +386,7 @@ namespace AzFramework
|
||||
{
|
||||
public:
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
};
|
||||
|
||||
@@ -383,7 +396,7 @@ namespace AzFramework
|
||||
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>()>;
|
||||
|
||||
// CameraInput overrides ...
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
bool Exclusive() const override;
|
||||
|
||||
|
||||
@@ -17,6 +17,17 @@ namespace AzFramework
|
||||
{
|
||||
ClickDetector::ClickOutcome ClickDetector::DetectClick(const ClickEvent clickEvent, const ScreenVector& cursorDelta)
|
||||
{
|
||||
const auto previousDetectionState = m_detectionState;
|
||||
if (previousDetectionState == DetectionState::WaitingForMove)
|
||||
{
|
||||
// only allow the action to begin if the mouse has been moved a small amount
|
||||
m_moveAccumulator += ScreenVectorLength(cursorDelta);
|
||||
if (m_moveAccumulator > m_deadZone)
|
||||
{
|
||||
m_detectionState = DetectionState::Moved;
|
||||
}
|
||||
}
|
||||
|
||||
if (clickEvent == ClickEvent::Down)
|
||||
{
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
@@ -52,15 +63,9 @@ namespace AzFramework
|
||||
return clickOutcome;
|
||||
}
|
||||
|
||||
if (m_detectionState == DetectionState::WaitingForMove)
|
||||
if (previousDetectionState == DetectionState::WaitingForMove && m_detectionState == DetectionState::Moved)
|
||||
{
|
||||
// only allow the action to begin if the mouse has been moved a small amount
|
||||
m_moveAccumulator += ScreenVectorLength(cursorDelta);
|
||||
if (m_moveAccumulator > m_deadZone)
|
||||
{
|
||||
m_detectionState = DetectionState::Moved;
|
||||
return ClickOutcome::Move;
|
||||
}
|
||||
return ClickOutcome::Move;
|
||||
}
|
||||
|
||||
return ClickOutcome::Nil;
|
||||
|
||||
@@ -50,7 +50,11 @@ namespace AzFramework
|
||||
//! Called from any type of 'handle event' function.
|
||||
ClickOutcome DetectClick(ClickEvent clickEvent, const ScreenVector& cursorDelta);
|
||||
|
||||
//! Override the default double click interval.
|
||||
//! @note Default is 400ms - system default.
|
||||
void SetDoubleClickInterval(float doubleClickInterval);
|
||||
//! Override the dead zone before a 'move' outcome will be triggered.
|
||||
void SetDeadZone(float deadZone);
|
||||
|
||||
private:
|
||||
//! Internal state of ClickDetector based on incoming events.
|
||||
@@ -72,4 +76,9 @@ namespace AzFramework
|
||||
{
|
||||
m_doubleClickInterval = doubleClickInterval;
|
||||
}
|
||||
|
||||
inline void ClickDetector::SetDeadZone(const float deadZone)
|
||||
{
|
||||
m_deadZone = deadZone;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
|
||||
AZStd::unordered_map<Instance*, PrefabDom> nestedInstanceLinkPatchesMap;
|
||||
|
||||
// Retrieve all entities affected and identify Instances
|
||||
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
|
||||
@@ -96,6 +97,16 @@ namespace AzToolsFramework
|
||||
// target templates of the other instances.
|
||||
for (auto& nestedInstance : instances)
|
||||
{
|
||||
auto linkRef = m_prefabSystemComponentInterface->FindLink(nestedInstance->GetLinkId());
|
||||
|
||||
if (linkRef.has_value())
|
||||
{
|
||||
PrefabDom oldLinkPatches;
|
||||
oldLinkPatches.CopyFrom(linkRef->get().GetLinkDom(), oldLinkPatches.GetAllocator());
|
||||
|
||||
nestedInstanceLinkPatchesMap.emplace(nestedInstance.get(), AZStd::move(oldLinkPatches));
|
||||
}
|
||||
|
||||
RemoveLink(nestedInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
|
||||
}
|
||||
|
||||
@@ -122,6 +133,9 @@ namespace AzToolsFramework
|
||||
|
||||
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
|
||||
|
||||
// Apply the correct transform to the container for the new instance, and store the patch for use when creating the link.
|
||||
PrefabDom patch = ApplyContainerTransformAndGeneratePatch(containerEntityId, commonRootEntityId, topLevelEntities);
|
||||
|
||||
// Parent the non-container top level entities to the container entity.
|
||||
// Parenting the top level container entities will be done during the creation of links.
|
||||
for (AZ::Entity* topLevelEntity : topLevelEntities)
|
||||
@@ -141,35 +155,55 @@ namespace AzToolsFramework
|
||||
|
||||
instanceToCreate->get().GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
|
||||
AZ_Assert(nestedInstance, "Invalid nested instance found in the new prefab created.");
|
||||
|
||||
EntityOptionalReference nestedInstanceContainerEntity = nestedInstance->GetContainerEntity();
|
||||
AZ_Assert(
|
||||
nestedInstanceContainerEntity, "Invalid container entity found for the nested instance used in prefab creation.");
|
||||
|
||||
AZ::EntityId parentId;
|
||||
AZ::TransformBus::EventResult(
|
||||
parentId, nestedInstanceContainerEntity->get().GetId(), &AZ::TransformBus::Events::GetParentId);
|
||||
AZ::EntityId nestedInstanceContainerEntityId = nestedInstanceContainerEntity->get().GetId();
|
||||
PrefabDom previousPatch;
|
||||
|
||||
auto entityIterator = AZStd::find_if(
|
||||
entities.begin(), entities.end(), [parentId](AZ::Entity* entity) { return entity->GetId() == parentId; });
|
||||
|
||||
// If the previous parent entity of the nested instance is not part of the entities of the newly created prefab,
|
||||
// then set the parent of the nested prefab as the container entity of the newly created prefab.
|
||||
if (entityIterator == entities.end())
|
||||
// Retrieve the previous patch if it exists
|
||||
if (nestedInstanceLinkPatchesMap.contains(nestedInstance.get()))
|
||||
{
|
||||
parentId = containerEntityId;
|
||||
previousPatch = AZStd::move(nestedInstanceLinkPatchesMap[nestedInstance.get()]);
|
||||
}
|
||||
|
||||
// These link creations shouldn't be undone because that would put the template in a non-usable state if a user
|
||||
// chooses to instantiate the template after undoing the creation.
|
||||
CreateLink(
|
||||
{&nestedInstanceContainerEntity->get()}, *nestedInstance, instanceToCreate->get().GetTemplateId(),
|
||||
undoBatch.GetUndoBatch(), parentId, false);
|
||||
CreateLink(*nestedInstance, instanceToCreate->get().GetTemplateId(), undoBatch.GetUndoBatch(), AZStd::move(previousPatch), false);
|
||||
|
||||
// If this nested instance's container is a top level entity in the new prefab, re-parent it and apply the change.
|
||||
if (AZStd::find(topLevelEntities.begin(), topLevelEntities.end(), &nestedInstanceContainerEntity->get()) != topLevelEntities.end())
|
||||
{
|
||||
Prefab::PrefabDom containerEntityDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *nestedInstanceContainerEntity);
|
||||
|
||||
AZ::TransformBus::Event(nestedInstanceContainerEntityId, &AZ::TransformBus::Events::SetParent, containerEntityId);
|
||||
|
||||
PrefabDom containerEntityDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *nestedInstanceContainerEntity);
|
||||
|
||||
PrefabDom reparentPatch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(reparentPatch, containerEntityDomBefore, containerEntityDomAfter);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(reparentPatch, nestedInstanceContainerEntityId);
|
||||
|
||||
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes as a separate step
|
||||
m_prefabUndoCache.Store(nestedInstanceContainerEntityId, AZStd::move(containerEntityDomAfter));
|
||||
|
||||
// Save these changes as patches to the link
|
||||
PrefabUndoLinkUpdate* linkUpdate = aznew PrefabUndoLinkUpdate(AZStd::to_string(static_cast<AZ::u64>(nestedInstanceContainerEntityId)));
|
||||
linkUpdate->SetParent(undoBatch.GetUndoBatch());
|
||||
linkUpdate->Capture(reparentPatch, nestedInstance->GetLinkId());
|
||||
|
||||
linkUpdate->Redo();
|
||||
}
|
||||
});
|
||||
|
||||
// Create a link between the templates of the newly created instance and the instance it's being parented under.
|
||||
CreateLink(
|
||||
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(),
|
||||
undoBatch.GetUndoBatch(), commonRootEntityId);
|
||||
instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(),
|
||||
AZStd::move(patch));
|
||||
|
||||
for (AZ::Entity* topLevelEntity : topLevelEntities)
|
||||
{
|
||||
@@ -199,6 +233,40 @@ namespace AzToolsFramework
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PrefabDom PrefabPublicHandler::ApplyContainerTransformAndGeneratePatch(AZ::EntityId containerEntityId, AZ::EntityId parentEntityId, const EntityList& childEntities)
|
||||
{
|
||||
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
|
||||
AZ_Assert(containerEntity, "Invalid container entity passed to ApplyContainerTransformAndGeneratePatch.");
|
||||
|
||||
// Generate the transform for the container entity out of the top level entities, and set it
|
||||
// This step needs to be done before anything is parented to the container, else children position will be wrong
|
||||
Prefab::PrefabDom containerEntityDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity);
|
||||
|
||||
AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero());
|
||||
AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero());
|
||||
|
||||
// Set container entity to be child of common root
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, parentEntityId);
|
||||
|
||||
// Set the transform (translation, rotation) of the container entity
|
||||
GenerateContainerEntityTransform(childEntities, containerEntityTranslation, containerEntityRotation);
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation);
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation);
|
||||
|
||||
PrefabDom containerEntityDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity);
|
||||
|
||||
PrefabDom patch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
|
||||
|
||||
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
|
||||
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
|
||||
|
||||
return AZStd::move(patch);
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::InstantiatePrefab(
|
||||
AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position)
|
||||
{
|
||||
@@ -249,10 +317,10 @@ namespace AzToolsFramework
|
||||
// Initialize Undo Batch object
|
||||
ScopedUndoBatch undoBatch("Instantiate Prefab");
|
||||
|
||||
// Instantiate the Prefab
|
||||
PrefabDom instanceToParentUnderDomBeforeCreate;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceToParentUnderDomBeforeCreate, instanceToParentUnder->get());
|
||||
|
||||
// Instantiate the Prefab
|
||||
auto instanceToCreate = prefabEditorEntityOwnershipInterface->InstantiatePrefab(relativePath, instanceToParentUnder);
|
||||
|
||||
if (!instanceToCreate)
|
||||
@@ -264,11 +332,32 @@ namespace AzToolsFramework
|
||||
PrefabUndoHelpers::UpdatePrefabInstance(
|
||||
instanceToParentUnder->get(), "Update prefab instance", instanceToParentUnderDomBeforeCreate, undoBatch.GetUndoBatch());
|
||||
|
||||
CreateLink({}, instanceToCreate->get(), instanceToParentUnder->get().GetTemplateId(), undoBatch.GetUndoBatch(), parent);
|
||||
// Create Link with correct container patches
|
||||
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
|
||||
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
|
||||
AZ_Assert(containerEntity, "Invalid container entity detected in InstantiatePrefab.");
|
||||
|
||||
// Apply position
|
||||
Prefab::PrefabDom containerEntityDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity);
|
||||
|
||||
// Set container entity's parent
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, parent);
|
||||
|
||||
// Set the position of the container entity
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetWorldTranslation, position);
|
||||
|
||||
PrefabDom containerEntityDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity);
|
||||
|
||||
// Generate patch to be stored in the link
|
||||
PrefabDom patch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
|
||||
|
||||
CreateLink(instanceToCreate->get(), instanceToParentUnder->get().GetTemplateId(), undoBatch.GetUndoBatch(), AZStd::move(patch));
|
||||
|
||||
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
|
||||
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
@@ -335,33 +424,9 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::CreateLink(
|
||||
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId, const bool isUndoRedoSupportNeeded)
|
||||
Instance& sourceInstance, TemplateId targetTemplateId,
|
||||
UndoSystem::URSequencePoint* undoBatch, PrefabDom patch, const bool isUndoRedoSupportNeeded)
|
||||
{
|
||||
AZ::EntityId containerEntityId = sourceInstance.GetContainerEntityId();
|
||||
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
|
||||
Prefab::PrefabDom containerEntityDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity);
|
||||
|
||||
AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero());
|
||||
AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero());
|
||||
|
||||
// Set the transform (translation, rotation) of the container entity
|
||||
GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation);
|
||||
|
||||
// Set container entity to be child of common root
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId);
|
||||
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation);
|
||||
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation);
|
||||
|
||||
PrefabDom containerEntityDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity);
|
||||
|
||||
PrefabDom patch;
|
||||
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
|
||||
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
|
||||
|
||||
LinkId linkId;
|
||||
if (isUndoRedoSupportNeeded)
|
||||
{
|
||||
@@ -377,9 +442,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
sourceInstance.SetLinkId(linkId);
|
||||
|
||||
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
|
||||
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::RemoveLink(
|
||||
|
||||
@@ -68,20 +68,32 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||
|
||||
/**
|
||||
* Applies the correct transform changes to the container entity based on the parent and child entities provided, and returns an appropriate patch.
|
||||
* The container will be parented to parentId, moved to the average transform of the future direct children and its cache will be updated.
|
||||
* This helper function won't support undo/redo, update the templates or create any links. All that needs to be done by the caller.
|
||||
*
|
||||
* \param containerEntityId The container to apply the changes to.
|
||||
* \param parentEntityId The id of the entity the container should be parented to.
|
||||
* \param childEntities A list of entities that will subsequently be parented to this container.
|
||||
* \return The PrefabDom containing the patches that should be stored in the parent link.
|
||||
*/
|
||||
PrefabDom ApplyContainerTransformAndGeneratePatch(
|
||||
AZ::EntityId containerEntityId, AZ::EntityId parentEntityId, const EntityList& childEntities);
|
||||
|
||||
/**
|
||||
* Creates a link between the templates of an instance and its parent.
|
||||
*
|
||||
* \param topLevelEntities The list of entities that are immediate children to the container entity of the instance.
|
||||
* \param sourceInstance The instance that corresponds to the source template of the link.
|
||||
* \param targetInstance The id of the target template.
|
||||
* \param undoBatch The undo batch to set as parent for this create link action.
|
||||
* \param commonRootEntityId The id of the entity that the source instance should be parented under.
|
||||
* \param patch The patch to store in the newly created link dom.
|
||||
* \param isUndoRedoSupportNeeded The flag indicating whether the link should be created with undo/redo support or not.
|
||||
*/
|
||||
void CreateLink(
|
||||
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
|
||||
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId, const bool isUndoRedoSupportNeeded = true);
|
||||
Instance& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch,
|
||||
PrefabDom patch, const bool isUndoRedoSupportNeeded = true);
|
||||
|
||||
/**
|
||||
* Removes the link between template of the sourceInstance and the template corresponding to targetTemplateId.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzFramework/Viewport/CameraState.h>
|
||||
#include <AzFramework/Viewport/ViewportId.h>
|
||||
#include <AzFramework/Viewport/ClickDetector.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportTypes.h>
|
||||
|
||||
@@ -304,4 +305,24 @@ namespace AzToolsFramework
|
||||
|
||||
return entityContextId;
|
||||
}
|
||||
|
||||
//! Maps a mouse interaction event to a ClickDetector event.
|
||||
//! @note Function only cares about up or down events, all other events are mapped to Nil (ignored).
|
||||
inline AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+9
-4
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
@@ -27,8 +28,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
|
||||
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
|
||||
|
||||
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
|
||||
const auto clickOutcome = m_clickDetector.DetectClick(selectClickEvent, m_cursorState.CursorDelta());
|
||||
if (clickOutcome == AzFramework::ClickDetector::ClickOutcome::Move)
|
||||
{
|
||||
if (m_leftMouseDown)
|
||||
{
|
||||
@@ -58,8 +62,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
|
||||
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
if (clickOutcome == AzFramework::ClickDetector::ClickOutcome::Release)
|
||||
{
|
||||
if (m_leftMouseUp)
|
||||
{
|
||||
@@ -77,6 +80,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
|
||||
m_cursorState.Update();
|
||||
|
||||
if (m_boxSelectRegion)
|
||||
{
|
||||
debugDisplay.DepthTestOff();
|
||||
|
||||
+21
-17
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzFramework/Viewport/ClickDetector.h>
|
||||
#include <AzFramework/Viewport/CursorState.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportTypes.h>
|
||||
|
||||
#include <QRect>
|
||||
@@ -26,49 +28,49 @@ namespace AzFramework
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
/// Utility to provide box select (click and drag) support for viewport types.
|
||||
/// Users can override the mouse event callbacks and display scene function to customize behavior.
|
||||
//! Utility to provide box select (click and drag) support for viewport types.
|
||||
//! Users can override the mouse event callbacks and display scene function to customize behavior.
|
||||
class EditorBoxSelect
|
||||
{
|
||||
public:
|
||||
EditorBoxSelect() = default;
|
||||
|
||||
/// Return if a box select action is currently taking place.
|
||||
//! Return if a box select action is currently taking place.
|
||||
bool Active() const { return m_boxSelectRegion.has_value(); }
|
||||
|
||||
/// Update the box select for various mouse events.
|
||||
/// Call HandleMouseInteraction from type/system implementing MouseViewportRequests interface.
|
||||
//! Update the box select for various mouse events.
|
||||
//! Call HandleMouseInteraction from type/system implementing MouseViewportRequests interface.
|
||||
void HandleMouseInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
|
||||
|
||||
/// Responsible for drawing the 2d box representing the selection in screen space.
|
||||
//! Responsible for drawing the 2d box representing the selection in screen space.
|
||||
void Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay);
|
||||
|
||||
/// Custom drawing behavior to happen during a box select.
|
||||
//! Custom drawing behavior to happen during a box select.
|
||||
void DisplayScene(
|
||||
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay);
|
||||
|
||||
/// Set the left mouse down callback.
|
||||
//! Set the left mouse down callback.
|
||||
void InstallLeftMouseDown(
|
||||
const AZStd::function<void(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)>& leftMouseDown);
|
||||
/// Set the mouse move callback.
|
||||
//! Set the mouse move callback.
|
||||
void InstallMouseMove(
|
||||
const AZStd::function<void(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)>& mouseMove);
|
||||
/// Set the left mouse up callback.
|
||||
//! Set the left mouse up callback.
|
||||
void InstallLeftMouseUp(
|
||||
const AZStd::function<void()>& leftMouseUp);
|
||||
/// Set the display scene callback.
|
||||
//! Set the display scene callback.
|
||||
void InstallDisplayScene(
|
||||
const AZStd::function<void(
|
||||
const AzFramework::ViewportInfo& viewportInfo,
|
||||
AzFramework::DebugDisplayRequests& debugDisplay)>& displayScene);
|
||||
|
||||
/// Return the box select region.
|
||||
/// If a box selection is being made, return the current rectangle representing the area.
|
||||
/// If there is currently no active box select, then the Maybe type will be empty (there will be no region/area).
|
||||
//! Return the box select region.
|
||||
//! If a box selection is being made, return the current rectangle representing the area.
|
||||
//! If there is currently no active box select, then the Maybe type will be empty (there will be no region/area).
|
||||
const AZStd::optional<QRect>& BoxRegion() const { return m_boxSelectRegion; }
|
||||
|
||||
/// Return the active modifiers from the previous frame.
|
||||
//! Return the active modifiers from the previous frame.
|
||||
ViewportInteraction::KeyboardModifiers PreviousModifiers() const { return m_previousModifiers; }
|
||||
|
||||
private:
|
||||
@@ -79,7 +81,9 @@ namespace AzToolsFramework
|
||||
AZStd::function<void(
|
||||
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)> m_displayScene;
|
||||
|
||||
AZStd::optional<QRect> m_boxSelectRegion; ///< Maybe/optional value to store box select region while active.
|
||||
ViewportInteraction::KeyboardModifiers m_previousModifiers; ///< Modifier keys active on the previous frame.
|
||||
AZStd::optional<QRect> m_boxSelectRegion; //!< Maybe/optional value to store box select region while active.
|
||||
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< Modifier keys active on the previous frame.
|
||||
AzFramework::ClickDetector m_clickDetector; //!< Utility type to detect if a mouse click or move has occurred.
|
||||
AzFramework::CursorState m_cursorState; //!< Utility type to track the current cursor position (and movement/delta).
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+1
-16
@@ -1782,22 +1782,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction);
|
||||
|
||||
const AzFramework::ClickDetector::ClickEvent selectClickEvent = [&mouseInteraction] {
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}();
|
||||
|
||||
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
|
||||
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
|
||||
const auto clickOutcome = m_clickDetector.DetectClick(selectClickEvent, m_cursorState.CursorDelta());
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class CameraInputFixture : public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
AzFramework::Camera m_camera;
|
||||
AzFramework::Camera m_targetCamera;
|
||||
AZStd::shared_ptr<AzFramework::CameraSystem> m_cameraSystem;
|
||||
|
||||
bool HandleEventAndUpdate(const AzFramework::InputEvent& event)
|
||||
{
|
||||
constexpr float deltaTime = 0.01666f; // 60fps
|
||||
const bool consumed = m_cameraSystem->HandleEvents(event);
|
||||
m_camera = m_cameraSystem->StepCamera(m_targetCamera, deltaTime);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsTestFixture::SetUp();
|
||||
|
||||
AzFramework::ReloadCameraKeyBindings();
|
||||
|
||||
m_cameraSystem = AZStd::make_shared<AzFramework::CameraSystem>();
|
||||
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Right);
|
||||
auto firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation);
|
||||
|
||||
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
|
||||
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
|
||||
auto orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation);
|
||||
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
|
||||
m_cameraSystem->m_cameras.AddCamera(firstPersonRotateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(firstPersonTranslateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(orbitCamera);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_cameraSystem->m_cameras.Clear();
|
||||
m_cameraSystem.reset();
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CameraInputFixture, BeginEndOrbitCameraConsumesCorrectEvents)
|
||||
{
|
||||
// set initial mouse position
|
||||
const bool consumed1 = HandleEventAndUpdate(AzFramework::CursorEvent{AzFramework::ScreenPoint(5, 5)});
|
||||
// begin orbit camera
|
||||
const bool consumed2 = HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{AzFramework::InputDeviceKeyboard::Key::ModifierAltL, AzFramework::InputChannel::State::Began});
|
||||
// begin listening for orbit rotate (click detector) - event is not consumed
|
||||
const bool consumed3 = HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began});
|
||||
// begin orbit rotate (mouse has moved sufficient distance to initiate)
|
||||
const bool consumed4 = HandleEventAndUpdate(AzFramework::CursorEvent{AzFramework::ScreenPoint(10, 10)});
|
||||
// end orbit (mouse up) - event is not consumed
|
||||
const bool consumed5 = HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Ended});
|
||||
|
||||
const auto allConsumed = AZStd::vector<bool>{consumed1, consumed2, consumed3, consumed4, consumed5};
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
EXPECT_THAT(allConsumed, ElementsAre(false, true, false, true, false));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
@@ -139,4 +139,21 @@ namespace UnitTest
|
||||
EXPECT_THAT(secondaryDownOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // ignored double click
|
||||
EXPECT_THAT(secondaryUpOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // click not registered
|
||||
}
|
||||
|
||||
// if the click detector registers a mouse down event, but then all intermediate calls are ignored
|
||||
// (another system may start intercepting events and swallowing them) then when we do receive a mouse
|
||||
// up event we should ensure we take into account the current delta - if the delta is large, then the
|
||||
// outcome will be release
|
||||
TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterIgnoringMouseMovesBeforeMouseUpWithLargeDelta)
|
||||
{
|
||||
using ::testing::Eq;
|
||||
|
||||
const ClickDetector::ClickOutcome downOutcome =
|
||||
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
|
||||
const ClickDetector::ClickOutcome upOutcome =
|
||||
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(50, 50));
|
||||
|
||||
EXPECT_THAT(downOutcome, Eq(ClickDetector::ClickOutcome::Nil));
|
||||
EXPECT_THAT(upOutcome, Eq(ClickDetector::ClickOutcome::Release));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -17,6 +17,7 @@ set(FILES
|
||||
BinToTextEncode.cpp
|
||||
ComponentAddRemove.cpp
|
||||
ComponentAdapterTests.cpp
|
||||
CameraInputTests.cpp
|
||||
ClickDetectorTests.cpp
|
||||
CursorStateTests.cpp
|
||||
EntityContext.cpp
|
||||
|
||||
Reference in New Issue
Block a user