Fixes for CameraInput handling (#6425)
* add temporary optimize off calls Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix + tests for camera input issue Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * simplify boolean expression (PR feedback) Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d065eb9498
commit
01770a1574
@@ -213,27 +213,33 @@ namespace AzFramework
|
||||
|
||||
Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime)
|
||||
{
|
||||
for (int i = 0; i < m_idleCameraInputs.size();)
|
||||
for (int idleIndex = 0; idleIndex < m_idleCameraInputs.size();)
|
||||
{
|
||||
auto& cameraInput = m_idleCameraInputs[i];
|
||||
auto& cameraInput = m_idleCameraInputs[idleIndex];
|
||||
const bool canBegin = cameraInput->Beginning() &&
|
||||
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
|
||||
[](const auto& input)
|
||||
{
|
||||
return !input->Exclusive();
|
||||
}) &&
|
||||
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
|
||||
(!cameraInput->Exclusive() || m_activeCameraInputs.empty());
|
||||
|
||||
if (canBegin)
|
||||
{
|
||||
m_activeCameraInputs.push_back(cameraInput);
|
||||
using AZStd::swap;
|
||||
swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]);
|
||||
swap(m_idleCameraInputs[idleIndex], m_idleCameraInputs[m_idleCameraInputs.size() - 1]);
|
||||
m_idleCameraInputs.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
// if a camera attempted to start but was not allowed to, ensure activation is cancelled
|
||||
if (!cameraInput->Idle())
|
||||
{
|
||||
cameraInput->CancelActivation();
|
||||
}
|
||||
|
||||
idleIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,21 +251,21 @@ namespace AzFramework
|
||||
return acc;
|
||||
});
|
||||
|
||||
for (int i = 0; i < m_activeCameraInputs.size();)
|
||||
for (int activeIndex = 0; activeIndex < m_activeCameraInputs.size();)
|
||||
{
|
||||
auto& cameraInput = m_activeCameraInputs[i];
|
||||
auto& cameraInput = m_activeCameraInputs[activeIndex];
|
||||
if (cameraInput->Ending())
|
||||
{
|
||||
cameraInput->ClearActivation();
|
||||
m_idleCameraInputs.push_back(cameraInput);
|
||||
using AZStd::swap;
|
||||
swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
|
||||
swap(m_activeCameraInputs[activeIndex], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
|
||||
m_activeCameraInputs.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
cameraInput->ContinueActivation();
|
||||
i++;
|
||||
activeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,9 +476,10 @@ namespace AzFramework
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
m_translation |= TranslationFromKey(input->m_channelId, m_translateCameraInputChannelIds);
|
||||
if (m_translation != TranslationType::Nil)
|
||||
if (auto translation = TranslationFromKey(input->m_channelId, m_translateCameraInputChannelIds);
|
||||
translation != TranslationType::Nil)
|
||||
{
|
||||
m_translation |= translation;
|
||||
BeginActivation();
|
||||
}
|
||||
|
||||
@@ -484,11 +491,16 @@ namespace AzFramework
|
||||
// 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, m_translateCameraInputChannelIds));
|
||||
if (m_translation == TranslationType::Nil)
|
||||
if (auto translation = TranslationFromKey(input->m_channelId, m_translateCameraInputChannelIds);
|
||||
translation != TranslationType::Nil)
|
||||
{
|
||||
EndActivation();
|
||||
m_translation &= ~translation;
|
||||
if (m_translation == TranslationType::Nil)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
|
||||
if (input->m_channelId == m_translateCameraInputChannelIds.m_boostChannelId)
|
||||
{
|
||||
m_boost = false;
|
||||
|
||||
@@ -185,6 +185,11 @@ namespace AzFramework
|
||||
m_activation = Activation::Ending;
|
||||
}
|
||||
|
||||
void CancelActivation()
|
||||
{
|
||||
m_activation = Activation::Idle;
|
||||
}
|
||||
|
||||
void ContinueActivation()
|
||||
{
|
||||
// continue activation is called after the first step of the camera input,
|
||||
|
||||
@@ -416,4 +416,78 @@ namespace UnitTest
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(m_camera.m_pitch, FloatNear(expectedPitch, 0.001f));
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, InvalidTranslationInputKeyCannotBeginTranslateCameraInputAgain)
|
||||
{
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
const bool consumed =
|
||||
m_cameraSystem->HandleEvents(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::IsTrue;
|
||||
EXPECT_THAT(consumed, IsTrue());
|
||||
EXPECT_THAT(m_firstPersonTranslateCamera->Beginning(), IsFalse());
|
||||
EXPECT_THAT(m_firstPersonTranslateCamera->Active(), IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, InvalidTranslationInputKeyDownCannotBeginTranslateCameraInputAgain)
|
||||
{
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
const bool consumed =
|
||||
m_cameraSystem->HandleEvents(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::IsTrue;
|
||||
EXPECT_THAT(consumed, IsTrue());
|
||||
EXPECT_THAT(m_firstPersonTranslateCamera->Beginning(), IsFalse());
|
||||
EXPECT_THAT(m_firstPersonTranslateCamera->Active(), IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, InvalidTranslationInputKeyUpDoesNotAffectTranslateCameraInputEnd)
|
||||
{
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
const bool consumed =
|
||||
m_cameraSystem->HandleEvents(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Ended });
|
||||
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::IsTrue;
|
||||
EXPECT_THAT(consumed, IsTrue());
|
||||
EXPECT_THAT(m_firstPersonTranslateCamera->Idle(), IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, OrbitCameraInputCannotBeLeftInInvalidStateIfItCannotFullyBeginAfterInputChannelBegin)
|
||||
{
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::IsTrue;
|
||||
EXPECT_THAT(m_orbitCamera->Beginning(), IsFalse());
|
||||
EXPECT_THAT(m_orbitCamera->Idle(), IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, OrbitCameraInputCannotBeLeftInInvalidStateIfItCannotFullyBeginAfterInputChannelBeginAndEnd)
|
||||
{
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Ended });
|
||||
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::IsTrue;
|
||||
EXPECT_THAT(m_orbitCamera->Ending(), IsFalse());
|
||||
EXPECT_THAT(m_orbitCamera->Idle(), IsTrue());
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
Reference in New Issue
Block a user