Follow character option (#5538)

* Follow character option

Signed-off-by: rhhong <rhhong@amazon.com>

* CR feedback

Signed-off-by: rhhong <rhhong@amazon.com>
This commit is contained in:
Roman
2021-11-11 13:57:52 -08:00
committed by GitHub
parent 4a34686e4e
commit 2c58da46dc
6 changed files with 50 additions and 15 deletions
@@ -178,20 +178,13 @@ namespace EMStudio
if (!m_actorEntities.empty())
{
// Find the actor instance and calculate the center from aabb.
AZ::Vector3 actorCenter = AZ::Vector3::CreateZero();
EMotionFX::Integration::ActorComponent* actorComponent =
m_actorEntities[0]->FindComponent<EMotionFX::Integration::ActorComponent>();
EMotionFX::ActorInstance* actorInstance = actorComponent->GetActorInstance();
if (actorInstance)
{
actorCenter += actorInstance->GetAabb().GetCenter();
result = actorInstance->GetAabb().GetCenter();
}
// Just return the position of the first entity.
AZ::Transform worldTransform;
AZ::TransformBus::EventResult(worldTransform, m_actorEntities[0]->GetId(), &AZ::TransformBus::Events::GetWorldTM);
result = worldTransform.GetTranslation();
result += actorCenter;
}
return result;
@@ -36,6 +36,9 @@ namespace EMStudio
//! Set the camera view mode.
virtual void SetCameraViewMode(CameraViewMode mode) = 0;
//! Set the camera follow up
virtual void SetFollowCharacter(bool follow) = 0;
//! Toggle render option flag
virtual void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag) = 0;
};
@@ -87,6 +87,19 @@ namespace EMStudio
// Send the reset camera event.
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::ResetCamera);
});
cameraMenu->addSeparator();
m_followCharacterAction = cameraMenu->addAction("Follow Character");
m_followCharacterAction->setCheckable(true);
m_followCharacterAction->setChecked(false);
connect(m_followCharacterAction, &QAction::triggered, this,
[this]()
{
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::SetFollowCharacter, m_followCharacterAction->isChecked());
;
});
cameraButton->setMenu(cameraMenu);
cameraButton->setText("Camera Option");
cameraButton->setPopupMode(QToolButton::InstantPopup);
@@ -31,5 +31,6 @@ namespace EMStudio
QMenu* menu, const char* menuEntryName, uint32_t actionIndex, bool visible = true, char* iconFileName = nullptr);
QAction* m_actions[EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS] = { nullptr };
QAction* m_followCharacterAction = nullptr;
};
}
@@ -147,36 +147,43 @@ namespace EMStudio
switch (mode)
{
case CameraViewMode::FRONT:
cameraPosition.Set(0.0f, CameraDistance, targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY() + CameraDistance, targetPosition.GetZ());
break;
case CameraViewMode::BACK:
cameraPosition.Set(0.0f, -CameraDistance, targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY() - CameraDistance, targetPosition.GetZ());
break;
case CameraViewMode::TOP:
cameraPosition.Set(0.0f, 0.0f, CameraDistance + targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY(), CameraDistance + targetPosition.GetZ());
break;
case CameraViewMode::BOTTOM:
cameraPosition.Set(0.0f, 0.0f, -CameraDistance + targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY(), -CameraDistance + targetPosition.GetZ());
break;
case CameraViewMode::LEFT:
cameraPosition.Set(-CameraDistance, 0.0f, targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX() - CameraDistance, targetPosition.GetY(), targetPosition.GetZ());
break;
case CameraViewMode::RIGHT:
cameraPosition.Set(CameraDistance, 0.0f, targetPosition.GetZ());
cameraPosition.Set(targetPosition.GetX() + CameraDistance, targetPosition.GetY(), targetPosition.GetZ());
break;
case CameraViewMode::DEFAULT:
// The default view mode is looking from the top left of the character.
cameraPosition.Set(-CameraDistance, CameraDistance, CameraDistance + targetPosition.GetZ());
cameraPosition.Set(
targetPosition.GetX() - CameraDistance, targetPosition.GetY() + CameraDistance, targetPosition.GetZ() + CameraDistance);
break;
}
GetViewportContext()->SetCameraTransform(AZ::Transform::CreateLookAt(cameraPosition, targetPosition));
}
void AnimViewportWidget::SetFollowCharacter(bool follow)
{
m_followCharacter = follow;
}
void AnimViewportWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time)
{
RenderViewportWidget::OnTick(deltaTime, time);
CalculateCameraProjection();
RenderCustomPluginData();
FollowCharacter();
}
void AnimViewportWidget::CalculateCameraProjection()
@@ -205,6 +212,20 @@ namespace EMStudio
}
}
void AnimViewportWidget::FollowCharacter()
{
if (m_followCharacter)
{
// When follow charater move is enabled, we are adding the delta of the character movement to the camera per frame.
AZ::Vector3 camPos = GetViewportContext()->GetCameraTransform().GetTranslation();
camPos += m_renderer->GetCharacterCenter() - m_prevCharacterPos;
AZ::Transform newCamTransform = GetViewportContext()->GetCameraTransform();
newCamTransform.SetTranslation(camPos);
GetViewportContext()->SetCameraTransform(newCamTransform);
}
m_prevCharacterPos = m_renderer->GetCharacterCenter();
}
void AnimViewportWidget::ToggleRenderFlag(EMotionFX::ActorRenderFlag flag)
{
m_renderFlags[flag] = !m_renderFlags[flag];
@@ -38,6 +38,7 @@ namespace EMStudio
void CalculateCameraProjection();
void RenderCustomPluginData();
void FollowCharacter();
void SetupCameras();
void SetupCameraController();
@@ -48,6 +49,7 @@ namespace EMStudio
// AnimViewportRequestBus::Handler overrides
void ResetCamera();
void SetCameraViewMode(CameraViewMode mode);
void SetFollowCharacter(bool follow);
void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag);
// ViewportPluginRequestBus::Handler overrides
@@ -61,5 +63,7 @@ namespace EMStudio
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_translateCamera;
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
EMotionFX::ActorRenderFlagBitset m_renderFlags;
bool m_followCharacter = false;
AZ::Vector3 m_prevCharacterPos;
};
}