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 @@ + + + + Icons / Video Control / Video + Created with Sketch. + + + + + 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 )