diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Camera_category.svg b/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Camera_category.svg
new file mode 100644
index 0000000000..4c7ca1871b
--- /dev/null
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Camera_category.svg
@@ -0,0 +1,10 @@
+
+
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Resources.qrc b/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Resources.qrc
new file mode 100644
index 0000000000..28ae322d5b
--- /dev/null
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Assets/Icons/Resources.qrc
@@ -0,0 +1,5 @@
+
+
+ Camera_category.svg
+
+
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt
index cc71e4f237..bb829ebeec 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt
@@ -49,6 +49,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
NAME EMotionFX_Atom.Editor GEM_MODULE
NAMESPACE Gem
+ AUTORCC
FILES_CMAKE
emotionfx_atom_editor_files.cmake
INCLUDE_DIRECTORIES
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp
index 52f857551c..7b20bf2f5d 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp
@@ -181,6 +181,20 @@ namespace EMStudio
ResetEnvironment();
}
+ AZ::Vector3 AnimViewportRenderer::GetCenter() const
+ {
+ AZ::Vector3 result = AZ::Vector3::CreateZero();
+ if (!m_actorEntities.empty())
+ {
+ // 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();
+ }
+
+ return result;
+ }
+
void AnimViewportRenderer::ResetEnvironment()
{
// Reset environment
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h
index dd420c175c..cd1c567743 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h
@@ -49,6 +49,9 @@ namespace EMStudio
void Reinit();
+ //! Return the center position of the existing objects.
+ AZ::Vector3 GetCenter() const;
+
private:
// This function resets the light, camera and other environment settings.
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRequestBus.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRequestBus.h
new file mode 100644
index 0000000000..03784c2158
--- /dev/null
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRequestBus.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include
+
+
+namespace EMStudio
+{
+ enum CameraViewMode
+ {
+ FRONT,
+ BACK,
+ TOP,
+ BOTTOM,
+ LEFT,
+ RIGHT,
+ DEFAULT
+ };
+
+ class AnimViewportRequests
+ : public AZ::EBusTraits
+ {
+ public:
+ static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+ static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+
+ //! Reset the camera to initial state.
+ virtual void ResetCamera() = 0;
+
+ //! Set the camera view mode.
+ virtual void SetCameraViewMode(CameraViewMode mode) = 0;
+ };
+
+ using AnimViewportRequestBus = AZ::EBus;
+} // namespace EMStudio
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.cpp
new file mode 100644
index 0000000000..a47a773e10
--- /dev/null
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace EMStudio
+{
+ AnimViewportToolBar::AnimViewportToolBar(QWidget* parent)
+ : QToolBar(parent)
+ {
+ AzQtComponents::ToolBar::addMainToolBarStyle(this);
+
+ // Add the camera button
+ QToolButton* cameraButton = new QToolButton(this);
+ QMenu* cameraMenu = new QMenu(cameraButton);
+
+ // Add the camera option
+ const AZStd::vector> cameraOptionNames = {
+ { CameraViewMode::FRONT, "Front" }, { CameraViewMode::BACK, "Back" }, { CameraViewMode::TOP, "Top" },
+ { CameraViewMode::BOTTOM, "Bottom" }, { CameraViewMode::LEFT, "Left" }, { CameraViewMode::RIGHT, "Right" },
+ };
+
+ for (const auto& pair : cameraOptionNames)
+ {
+ CameraViewMode mode = pair.first;
+ cameraMenu->addAction(
+ pair.second.c_str(),
+ [mode]()
+ {
+ // Send the reset camera event.
+ AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::SetCameraViewMode, mode);
+ });
+ }
+
+ cameraMenu->addSeparator();
+ cameraMenu->addAction("Reset Camera",
+ []()
+ {
+ // Send the reset camera event.
+ AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::ResetCamera);
+ });
+ cameraButton->setMenu(cameraMenu);
+ cameraButton->setText("Camera Option");
+ cameraButton->setPopupMode(QToolButton::InstantPopup);
+ cameraButton->setVisible(true);
+ cameraButton->setIcon(QIcon(":/EMotionFXAtom/Camera_category.svg"));
+ addWidget(cameraButton);
+ }
+} // namespace EMStudio
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.h
new file mode 100644
index 0000000000..23ef5fdcd8
--- /dev/null
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.h
@@ -0,0 +1,24 @@
+/*
+ * 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
+
+#if !defined(Q_MOC_RUN)
+#include
+#include
+#endif
+
+namespace EMStudio
+{
+ class AnimViewportToolBar : public QToolBar
+ {
+ public:
+ AnimViewportToolBar(QWidget* parent = nullptr);
+ ~AnimViewportToolBar() = default;
+ };
+}
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp
index 6a6c9df901..a6980c18ef 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp
@@ -34,6 +34,23 @@ namespace EMStudio
SetupCameras();
SetupCameraController();
+ Reinit();
+
+ AnimViewportRequestBus::Handler::BusConnect();
+ }
+
+ AnimViewportWidget::~AnimViewportWidget()
+ {
+ AnimViewportRequestBus::Handler::BusDisconnect();
+ }
+
+ void AnimViewportWidget::Reinit(bool resetCamera)
+ {
+ if (resetCamera)
+ {
+ ResetCamera();
+ }
+ m_renderer->Reinit();
}
void AnimViewportWidget::SetupCameras()
@@ -100,4 +117,43 @@ namespace EMStudio
});
GetControllerList()->Add(controller);
}
+
+ void AnimViewportWidget::ResetCamera()
+ {
+ SetCameraViewMode(CameraViewMode::DEFAULT);
+ }
+
+ void AnimViewportWidget::SetCameraViewMode([[maybe_unused]]CameraViewMode mode)
+ {
+ // Set the camera view mode.
+ AZ::Vector3 targetPosition = m_renderer->GetCenter();
+ targetPosition.SetZ(targetPosition.GetY() + TargetCenterOffsetZ);
+ AZ::Vector3 cameraPosition;
+ switch (mode)
+ {
+ case CameraViewMode::FRONT:
+ cameraPosition.Set(0.0f, CameraDistance, targetPosition.GetZ());
+ break;
+ case CameraViewMode::BACK:
+ cameraPosition.Set(0.0f, -CameraDistance, targetPosition.GetZ());
+ break;
+ case CameraViewMode::TOP:
+ cameraPosition.Set(0.0f, 0.0f, CameraDistance + targetPosition.GetZ());
+ break;
+ case CameraViewMode::BOTTOM:
+ cameraPosition.Set(0.0f, 0.0f, -CameraDistance + targetPosition.GetZ());
+ break;
+ case CameraViewMode::LEFT:
+ cameraPosition.Set(-CameraDistance, 0.0f, targetPosition.GetZ());
+ break;
+ case CameraViewMode::RIGHT:
+ cameraPosition.Set(CameraDistance, 0.0f, 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());
+ break;
+ }
+ GetViewportContext()->SetCameraTransform(AZ::Transform::CreateLookAt(cameraPosition, targetPosition));
+ }
} // namespace EMStudio
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h
index 7c2e085f84..a0ba3a83c6 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h
@@ -9,6 +9,7 @@
#include
#include
+#include
namespace EMStudio
{
@@ -16,15 +17,26 @@ namespace EMStudio
class AnimViewportWidget
: public AtomToolsFramework::RenderViewportWidget
+ , private AnimViewportRequestBus::Handler
{
public:
AnimViewportWidget(QWidget* parent = nullptr);
+ ~AnimViewportWidget();
AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); }
+ void Reinit(bool resetCamera = true);
+
private:
void SetupCameras();
void SetupCameraController();
+ // AnimViewportRequestBus::Handler overrides
+ void ResetCamera();
+ void SetCameraViewMode(CameraViewMode mode);
+
+ static constexpr float CameraDistance = 2.0f;
+ static constexpr float TargetCenterOffsetZ = 1.0f;
+
AZStd::unique_ptr m_renderer;
AZStd::shared_ptr m_rotateCamera;
AZStd::shared_ptr m_translateCamera;
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp
index 91a34e16cd..bc74592485 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp
@@ -8,6 +8,7 @@
#include
#include
+#include
#include
#include
@@ -76,7 +77,7 @@ namespace EMStudio
void AtomRenderPlugin::ReinitRenderer()
{
- m_animViewportWidget->GetAnimViewportRenderer()->Reinit();
+ m_animViewportWidget->Reinit();
}
bool AtomRenderPlugin::Init()
@@ -88,6 +89,12 @@ namespace EMStudio
verticalLayout->setSizeConstraint(QLayout::SetNoConstraint);
verticalLayout->setSpacing(1);
verticalLayout->setMargin(0);
+
+ // Add the tool bar
+ AnimViewportToolBar* toolBar = new AnimViewportToolBar(m_innerWidget);
+ verticalLayout->addWidget(toolBar);
+
+ // Add the viewport widget
m_animViewportWidget = new AnimViewportWidget(m_innerWidget);
verticalLayout->addWidget(m_animViewportWidget);
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake
index a88581099f..330a3c4af7 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake
@@ -7,6 +7,7 @@
#
set(FILES
+ ../Assets/Icons/Resources.qrc
Source/ActorModule.cpp
Source/Editor/EditorSystemComponent.h
Source/Editor/EditorSystemComponent.cpp
@@ -18,4 +19,7 @@ set(FILES
Tools/EMStudio/AnimViewportRenderer.cpp
Tools/EMStudio/AnimViewportSettings.h
Tools/EMStudio/AnimViewportSettings.cpp
+ Tools/EMStudio/AnimViewportToolBar.h
+ Tools/EMStudio/AnimViewportToolBar.cpp
+ Tools/EMStudio/AnimViewportRequestBus.h
)