diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index c98a244d8f..c475ad8948 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -32,17 +32,19 @@ #include #include +#include #include #include -#include +#include +#include namespace EMStudio { static constexpr float DepthNear = 0.01f; - AnimViewportRenderer::AnimViewportRenderer(AZStd::shared_ptr windowContext) - : m_windowContext(windowContext) + AnimViewportRenderer::AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext) + : m_windowContext(viewportContext->GetWindowContext()) { // Create a new entity context m_entityContext = AZStd::make_unique(); @@ -72,33 +74,14 @@ namespace EMStudio m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineAsset, *m_windowContext.get()); pipelineAsset.Release(); m_scene->AddRenderPipeline(m_renderPipeline); + m_renderPipeline->SetDefaultView(viewportContext->GetDefaultView()); // Currently the scene has to be activated after render pipeline was added so some feature processors (i.e. imgui) can be // initialized properly with pipeline's pass information. m_scene->Activate(); AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene); - AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId(); - // Configure camera - AzFramework::EntityContextRequestBus::EventResult( - m_cameraEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "Cameraentity"); - AZ_Assert(m_cameraEntity != nullptr, "Failed to create camera entity."); - - // Add debug camera and controller components - AZ::Debug::CameraComponentConfig cameraConfig(m_windowContext); - cameraConfig.m_fovY = AZ::Constants::HalfPi; - cameraConfig.m_depthNear = DepthNear; - m_cameraComponent = m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraComponent->SetConfiguration(cameraConfig); - m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraEntity->Init(); - m_cameraEntity->Activate(); - - // Connect camera to pipeline's default view after camera entity activated - m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId()); - // Get the FeatureProcessors m_meshFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -162,7 +145,7 @@ namespace EMStudio // Destroy all the entity we created. m_entityContext->DestroyEntity(m_iblEntity); m_entityContext->DestroyEntity(m_postProcessEntity); - m_entityContext->DestroyEntity(m_cameraEntity); + //m_entityContext->DestroyEntity(m_cameraEntity); m_entityContext->DestroyEntity(m_gridEntity); for (AZ::Entity* entity : m_actorEntities) { @@ -204,26 +187,6 @@ namespace EMStudio AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); - - Camera::Configuration cameraConfig; - Camera::CameraRequestBus::EventResult( - cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); - - // Reset the camera position - static constexpr float StartingDistanceMultiplier = 2.0f; - static constexpr float StartingRotationAngle = AZ::Constants::QuarterPi / 2.0f; - - AZ::Vector3 targetPosition = iblTransform.GetTranslation(); - const float distance = 1.0f * StartingDistanceMultiplier; - const AZ::Quaternion cameraRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), StartingRotationAngle); - AZ::Vector3 cameraPosition(targetPosition.GetX(), targetPosition.GetY() - distance, targetPosition.GetZ()); - cameraPosition = cameraRotation.TransformVector(cameraPosition); - AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); - AZ::TransformBus::Event(m_cameraEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, cameraTransform); - - // Setup primary camera controls - AZ::Debug::CameraControllerRequestBus::Event( - m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); } void AnimViewportRenderer::ReinitActorEntities() @@ -292,6 +255,13 @@ namespace EMStudio EMotionFX::Integration::ActorComponent* actorComponent = actorEntity->FindComponent(); actorComponent->SetActorAsset(actorAsset); + // Since this entity belongs to the animation editor, we need to set the isOwnByRuntime flag to false. + actorComponent->GetActorInstance()->SetIsOwnedByRuntime(false); + // Selet the actor instance in the command manager after it has been created. + AZStd::string outResult; + EMStudioManager::GetInstance()->GetCommandManager()->ExecuteCommandInsideCommand( + AZStd::string::format("Select -actorInstanceID %i", actorComponent->GetActorInstance()->GetID()).c_str(), outResult); + return actorEntity; } @@ -312,8 +282,8 @@ namespace EMStudio ->GetOrCreateExposureControlSettingsInterface(); Camera::Configuration cameraConfig; - Camera::CameraRequestBus::EventResult( - cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); + cameraConfig.m_fovRadians = AZ::Constants::HalfPi; + cameraConfig.m_nearClipDistance = DepthNear; preset->ApplyLightingPreset( iblFeatureProcessor, m_skyboxFeatureProcessor, exposureControlSettingInterface, m_directionalLightFeatureProcessor, diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index 8671068199..dd420c175c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ namespace EMStudio public: AZ_CLASS_ALLOCATOR(AnimViewportRenderer, AZ::SystemAllocator, 0); - AnimViewportRenderer(AZStd::shared_ptr windowContext); + AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext); ~AnimViewportRenderer(); void Reinit(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index 39b45507da..81678d477e 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -6,7 +6,11 @@ * */ +#include +#include +#include #include +#include #include #include @@ -17,7 +21,6 @@ namespace EMStudio : AtomToolsFramework::RenderViewportWidget(parent) { setObjectName(QString::fromUtf8("AtomViewportWidget")); - resize(869, 574); QSizePolicy qSize(QSizePolicy::Preferred, QSizePolicy::Preferred); qSize.setHorizontalStretch(0); qSize.setVerticalStretch(0); @@ -26,6 +29,119 @@ namespace EMStudio setAutoFillBackground(false); setStyleSheet(QString::fromUtf8("")); - m_renderer = AZStd::make_unique(GetViewportContext()->GetWindowContext()); + m_renderer = AZStd::make_unique(GetViewportContext()); + + SetupCameras(); + SetupCameraController(); + } + + template + AZStd::remove_cvref_t GetRegistry(const AZStd::string_view setting, T&& defaultValue) + { + AZStd::remove_cvref_t value = AZStd::forward(defaultValue); + if (const auto* registry = AZ::SettingsRegistry::Get()) + { + T potentialValue; + if (registry->Get(potentialValue, setting)) + { + value = AZStd::move(potentialValue); + } + } + + return value; + } + + // TODO: TranslateCameraInput should have a way to initiate with default channel id setup. + static AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() + { + constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId"; + constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId"; + constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId"; + constexpr AZStd::string_view CameraTranslateRightIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateRightId"; + constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId"; + constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId"; + constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId"; + + AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds; + translateCameraInputChannelIds.m_leftChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateLeftIdSetting, AZStd::string("keyboard_key_alphanumeric_A")).c_str()); + translateCameraInputChannelIds.m_rightChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateRightIdSetting, AZStd::string("keyboard_key_alphanumeric_D")).c_str()); + translateCameraInputChannelIds.m_forwardChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateForwardIdSetting, AZStd::string("keyboard_key_alphanumeric_W")).c_str()); + translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId( + GetRegistry(CameraTranslateBackwardIdSetting, AZStd::string("keyboard_key_alphanumeric_S")).c_str()); + translateCameraInputChannelIds.m_upChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateUpIdSetting, AZStd::string("keyboard_key_alphanumeric_E")).c_str()); + translateCameraInputChannelIds.m_downChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateDownIdSetting, AZStd::string("keyboard_key_alphanumeric_Q")).c_str()); + translateCameraInputChannelIds.m_boostChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateBoostIdSetting, AZStd::string("keyboard_key_modifier_shift_l")).c_str()); + + return translateCameraInputChannelIds; + } + + void AnimViewportWidget::SetupCameras() + { + constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId"; + constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId"; + + m_orbitRotateCamera = AZStd::make_shared( + AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str())); + + const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); + m_orbitTranslateCamera = + AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannelIds); + m_orbitDollyScrollCamera = AZStd::make_shared(); + } + + void AnimViewportWidget::SetupCameraController() + { + auto controller = AZStd::make_shared(); + controller->SetCameraViewportContextBuilderCallback( + [viewportId = + GetViewportContext()->GetId()](AZStd::unique_ptr& cameraViewportContext) + { + cameraViewportContext = AZStd::make_unique(viewportId); + }); + + controller->SetCameraPriorityBuilderCallback( + [](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn) + { + cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority; + }); + + controller->SetCameraPropsBuilderCallback( + [](AzFramework::CameraProps& cameraProps) + { + cameraProps.m_rotateSmoothnessFn = [] + { + return 5.0f; + }; + + cameraProps.m_translateSmoothnessFn = [] + { + return 5.0f; + }; + + cameraProps.m_rotateSmoothingEnabledFn = [] + { + return true; + }; + + cameraProps.m_translateSmoothingEnabledFn = [] + { + return true; + }; + }); + + controller->SetCameraListBuilderCallback( + [this](AzFramework::Cameras& cameras) + { + cameras.AddCamera(m_orbitRotateCamera); + cameras.AddCamera(m_orbitTranslateCamera); + cameras.AddCamera(m_orbitDollyScrollCamera); + }); + GetControllerList()->Add(controller); } -} +} // namespace EMStudio diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 6d1d91ac0d..64bf4cd5dd 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -8,7 +8,7 @@ #pragma once #include - +#include namespace EMStudio { @@ -22,6 +22,12 @@ namespace EMStudio AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); } private: + void SetupCameras(); + void SetupCameraController(); + AZStd::unique_ptr m_renderer; + AZStd::shared_ptr m_orbitRotateCamera; + AZStd::shared_ptr m_orbitTranslateCamera; + AZStd::shared_ptr m_orbitDollyScrollCamera; }; } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 1f35212b8b..948006e2b5 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -28,7 +28,7 @@ namespace EMStudio const char* AtomRenderPlugin::GetName() const { - return "Atom Render Window"; + return "Atom Render Window (Preview)"; } uint32 AtomRenderPlugin::GetClassID() const @@ -86,6 +86,7 @@ namespace EMStudio verticalLayout->setSpacing(1); verticalLayout->setMargin(0); m_animViewportWidget = new AnimViewportWidget(m_innerWidget); + verticalLayout->addWidget(m_animViewportWidget); // Register command callbacks. m_createActorInstanceCallback = new CreateActorInstanceCallback(false);