Add manipulator for atom render plugin in animation editor. (#7068)

* small bugfix

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

* ActorInstanceId default to -1 when no %lastresult matches

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

* CR feedback - wrap function to get the first available editor actor instance.

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

* Remove mcore inline

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

* Fixed the bug that delete an instance from actor manager crashes the editor.

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

* Move the manipulator controller.

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

* Add manipulator icon

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

* Add manipulators

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

* move more option to renderOption, and loading all going through the plugin

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

* code cleanup

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

* code cleanup

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

* more code cleanup

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

* CR FEEDBACK

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

* Fix profile_nounity build

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

* CR feedback - move more code to azToolsframework and share them between animation editor and editorlib

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

* Using the MouseViewportRequests in viewportMessage and remove the custom bus

Signed-off-by: rhhong <rhhong@amazon.com>
This commit is contained in:
Roman
2022-01-25 11:25:18 -08:00
committed by GitHub
parent adfd77c67c
commit 55146d037a
26 changed files with 790 additions and 208 deletions
+5 -50
View File
@@ -17,6 +17,7 @@
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/Viewport/ViewportInteractionHelpers.h>
#include <QApplication>
@@ -33,53 +34,6 @@ namespace SandboxEditor
ViewportManipulatorControllerInstance::~ViewportManipulatorControllerInstance() = default;
AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton(
const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::MouseButton;
using InputButton = AzFramework::InputDeviceMouse::Button;
const auto& id = inputChannel.GetInputChannelId();
if (id == InputButton::Left)
{
return MouseButton::Left;
}
if (id == InputButton::Middle)
{
return MouseButton::Middle;
}
if (id == InputButton::Right)
{
return MouseButton::Right;
}
return MouseButton::None;
}
bool ViewportManipulatorControllerInstance::IsMouseMove(const AzFramework::InputChannel& inputChannel)
{
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
}
AzToolsFramework::ViewportInteraction::KeyboardModifier ViewportManipulatorControllerInstance::GetKeyboardModifier(
const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
{
return KeyboardModifier::Alt;
}
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
{
return KeyboardModifier::Ctrl;
}
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
{
return KeyboardModifier::Shift;
}
return KeyboardModifier::None;
}
bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
// We only care about manipulator and viewport interaction events
@@ -97,6 +51,7 @@ namespace SandboxEditor
using AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
using AzToolsFramework::ViewportInteraction::ProjectedViewportRay;
using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
using AzToolsFramework::ViewportInteraction::Helpers;
bool interactionHandled = false;
float wheelDelta = 0.0f;
@@ -109,7 +64,7 @@ namespace SandboxEditor
const bool finishedProcessingEvents = event.m_priority == InteractionPriority;
const auto state = event.m_inputChannel.GetState();
if (IsMouseMove(event.m_inputChannel))
if (Helpers::IsMouseMove(event.m_inputChannel))
{
// Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after
if (event.m_priority == ManipulatorPriority)
@@ -136,7 +91,7 @@ namespace SandboxEditor
eventType = MouseEvent::Move;
}
else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
else if (auto mouseButton = Helpers::GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
{
const AZ::u32 mouseButtonValue = static_cast<AZ::u32>(mouseButton);
overrideButton = mouseButton;
@@ -178,7 +133,7 @@ namespace SandboxEditor
}
}
}
else if (auto keyboardModifier = GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
else if (auto keyboardModifier = Helpers::GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
{
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
{
@@ -35,10 +35,6 @@ namespace SandboxEditor
private:
bool IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton) const;
static AzToolsFramework::ViewportInteraction::MouseButton GetMouseButton(const AzFramework::InputChannel& inputChannel);
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
static AzToolsFramework::ViewportInteraction::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
//! Represents the time and location of a click.
struct ClickEvent
{
@@ -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 <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzToolsFramework/Viewport/ViewportInteractionHelpers.h>
namespace AzToolsFramework::ViewportInteraction
{
MouseButton Helpers::GetMouseButton(const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::MouseButton;
using InputButton = AzFramework::InputDeviceMouse::Button;
const AzFramework::InputChannelId& id = inputChannel.GetInputChannelId();
if (id == InputButton::Left)
{
return MouseButton::Left;
}
if (id == InputButton::Middle)
{
return MouseButton::Middle;
}
if (id == InputButton::Right)
{
return MouseButton::Right;
}
return MouseButton::None;
}
bool Helpers::IsMouseMove(const AzFramework::InputChannel& inputChannel)
{
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
}
KeyboardModifier Helpers::GetKeyboardModifier(const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
{
return KeyboardModifier::Alt;
}
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
{
return KeyboardModifier::Ctrl;
}
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
{
return KeyboardModifier::Shift;
}
return KeyboardModifier::None;
}
} // namespace AzToolsFramework::ViewportInteraction
@@ -0,0 +1,23 @@
/*
* 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 <AzFramework/Input/Channels/InputChannel.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
namespace AzToolsFramework::ViewportInteraction
{
class Helpers
{
public:
static MouseButton GetMouseButton(const AzFramework::InputChannel& inputChannel);
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
static KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
};
} // namespace AzToolsFramework::ViewportInteraction
@@ -150,6 +150,9 @@ namespace AzToolsFramework
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
};
//! A bus to listen to just the MouseViewportRequests.
using ViewportMouseRequestBus = AZ::EBus<MouseViewportRequests, ViewportEBusTraits>;
//! Requests that can be made to the viewport to query and modify its state.
class ViewportInteractionRequests
{
@@ -504,6 +504,8 @@ set(FILES
Viewport/EditorContextMenu.cpp
Viewport/VertexContainerDisplay.h
Viewport/VertexContainerDisplay.cpp
Viewport/ViewportInteractionHelpers.h
Viewport/ViewportInteractionHelpers.cpp
Viewport/ViewportMessages.h
Viewport/ViewportMessages.cpp
Viewport/ViewportTypes.h
@@ -1,6 +1,9 @@
<RCC>
<qresource prefix="/EMotionFXAtom">
<file>Camera_category.svg</file>
<file>Rotate.svg</file>
<file>Scale.svg</file>
<file>Translate.svg</file>
<file>Visualization.svg</file>
</qresource>
</RCC>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 60 (88103) - https://sketch.com -->
<title>Icons / System / Rotate</title>
<desc>Created with Sketch.</desc>
<g id="Icons-/-System-/-Rotate" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<path d="M12,5 C17.5228475,5 22,7.3608081 22,12 C22,15.4442471 19.5322235,17.6326643 16.0008886,18.5315221 L16,21.2426407 L11.7573593,17 L16,12.7573593 L16.0016674,15.9550948 C18.184759,15.2133604 19.5351812,13.8176329 19.5351812,12 C19.5351812,9.23857625 16.418278,7.49466813 12,7.49466813 C7.581722,7.49466813 4.51608017,9.23857625 4.51608017,12 C4.51608017,13.8140495 5.83906099,15.2078553 7.99939095,15.9507002 L8.00012145,18.5317791 C4.46824702,17.6330816 2,15.4445755 2,12 C2,7.3608081 6.4771525,5 12,5 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 60 (88103) - https://sketch.com -->
<title>Icons / System / Scale</title>
<desc>Created with Sketch.</desc>
<g id="Icons-/-System-/-Scale" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<path d="M21,3 L21,9 L18.7,6.7 L14.4000589,11 L13,9.59994107 L17.3,5.3 L15,3 L21,3 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M3,21 L3,15 L5.356,17.356 L9.71109794,13 L11,14.2889021 L6.644,18.644 L9,21 L3,21 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 842 B

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 59 (86127) - https://sketch.com -->
<title>Icons / System / Move</title>
<desc>Created with Sketch.</desc>
<g id="Icons-/-System-/-Move" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<rect id="Rectangle" fill="#FFFFFF" x="11" y="3" width="2" height="18"></rect>
<rect id="Rectangle" fill="#FFFFFF" x="3" y="11" width="18" height="2"></rect>
<polygon id="Rectangle" fill="#FFFFFF" transform="translate(12.000000, 6.000000) rotate(45.000000) translate(-12.000000, -6.000000) " points="9 3 15 3 9 9"></polygon>
<polygon id="Rectangle" fill="#FFFFFF" transform="translate(12.000000, 18.000000) scale(1, -1) rotate(45.000000) translate(-12.000000, -18.000000) " points="9 15 15 15 9 21"></polygon>
<polygon id="Rectangle" fill="#FFFFFF" points="22.2426407 12 18 16.2426407 18 7.75735931"></polygon>
<polygon id="Rectangle" fill="#FFFFFF" transform="translate(6.000000, 12.000000) scale(-1, 1) rotate(135.000000) translate(-6.000000, -12.000000) " points="3 9 9 9 3 15"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,141 @@
/*
* 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 <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/Viewport/ViewportInteractionHelpers.h>
#include <EMStudio/AnimViewportInputController.h>
namespace EMStudio
{
bool AnimViewportInputController::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
using AzFramework::InputChannel;
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
using AzToolsFramework::ViewportInteraction::MouseButton;
using AzToolsFramework::ViewportInteraction::MouseEvent;
using AzToolsFramework::ViewportInteraction::MouseInteraction;
using AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
using AzToolsFramework::ViewportInteraction::ProjectedViewportRay;
using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
using AzToolsFramework::ViewportInteraction::Helpers;
bool interactionHandled = false;
float wheelDelta = 0.0f;
AZStd::optional<MouseButton> overrideButton;
AZStd::optional<MouseEvent> eventType;
const auto state = event.m_inputChannel.GetState();
if (Helpers::IsMouseMove(event.m_inputChannel))
{
const auto* position = event.m_inputChannel.GetCustomData<AzFramework::InputChannel::PositionData2D>();
AZ_Assert(position, "Expected PositionData2D but found nullptr");
AzFramework::WindowSize windowSize;
AzFramework::WindowRequestBus::EventResult(
windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize);
const auto screenPoint = AzFramework::ScreenPoint(
aznumeric_cast<int>(position->m_normalizedPosition.GetX() * windowSize.m_width),
aznumeric_cast<int>(position->m_normalizedPosition.GetY() * windowSize.m_height));
ProjectedViewportRay ray{};
ViewportInteractionRequestBus::EventResult(
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint);
m_mouseInteraction.m_mousePick.m_rayOrigin = ray.m_origin;
m_mouseInteraction.m_mousePick.m_rayDirection = ray.m_direction;
m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint;
eventType = MouseEvent::Move;
}
else if (auto mouseButton = Helpers::GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
{
const AZ::u32 mouseButtonValue = static_cast<AZ::u32>(mouseButton);
overrideButton = mouseButton;
if (state == InputChannel::State::Began)
{
m_mouseInteraction.m_mouseButtons.m_mouseButtons |= mouseButtonValue;
eventType = MouseEvent::Down;
}
else if (state == InputChannel::State::Ended)
{
// If we've actually logged a mouse down event, forward a mouse up event.
// This prevents corner cases like the context menu thinking it should be opened even though no one clicked in this
// viewport, due to RenderViewportWidget ensuring all controllers get InputChannel::State::Ended events.
if (m_mouseInteraction.m_mouseButtons.m_mouseButtons & mouseButtonValue)
{
eventType = MouseEvent::Up;
}
}
}
else if (auto keyboardModifier = Helpers::GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
{
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
{
m_mouseInteraction.m_keyboardModifiers.m_keyModifiers |= static_cast<AZ::u32>(keyboardModifier);
}
else if (state == InputChannel::State::Ended)
{
m_mouseInteraction.m_keyboardModifiers.m_keyModifiers &= ~static_cast<AZ::u32>(keyboardModifier);
}
}
else if (event.m_inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::Movement::Z)
{
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
{
eventType = MouseEvent::Wheel;
wheelDelta = event.m_inputChannel.GetValue();
}
}
if (eventType)
{
MouseInteraction mouseInteraction = m_mouseInteraction;
if (overrideButton)
{
mouseInteraction.m_mouseButtons.m_mouseButtons = static_cast<AZ::u32>(overrideButton.value());
}
mouseInteraction.m_interactionId.m_viewportId = GetViewportId();
auto currentCursorState = AzFramework::SystemCursorState::Unknown;
AzFramework::InputSystemCursorRequestBus::EventResult(
currentCursorState, event.m_inputChannel.GetInputDevice().GetInputDeviceId(),
&AzFramework::InputSystemCursorRequestBus::Events::GetSystemCursorState);
const auto mouseInteractionEvent = [mouseInteraction, event = eventType.value(), wheelDelta,
cursorCaptured = currentCursorState == AzFramework::SystemCursorState::ConstrainedAndHidden]
{
switch (event)
{
case MouseEvent::Up:
case MouseEvent::Down:
case MouseEvent::Move:
case MouseEvent::DoubleClick:
return MouseInteractionEvent(AZStd::move(mouseInteraction), event, cursorCaptured);
case MouseEvent::Wheel:
return MouseInteractionEvent(AZStd::move(mouseInteraction), wheelDelta);
}
AZ_Assert(false, "Unhandled MouseEvent");
return MouseInteractionEvent(MouseInteraction{}, MouseEvent::Up, false);
}();
AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus::EventResult(interactionHandled,
GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus::Handler::HandleMouseInteraction,
mouseInteractionEvent);
}
return interactionHandled;
}
} // namespace EMStudio
@@ -0,0 +1,36 @@
/*
* 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 <AzFramework/Viewport/SingleViewportController.h>
#include <AzFramework/Input/Events/InputChannelEventListener.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
namespace AzToolsFramework
{
class ManipulatorManager;
}
namespace EMStudio
{
//! Provide input control for manipulators in AnimViewport
class AnimViewportInputController
: public AzFramework::SingleViewportController
{
public:
AZ_TYPE_INFO(AnimViewportInputController, "{A1629CB6-2292-4B7D-8B49-F614BD4746AA}");
AZ_CLASS_ALLOCATOR(AnimViewportInputController, AZ::SystemAllocator, 0)
// AzFramework::SingleViewportController overrides...
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
private:
AzToolsFramework::ViewportInteraction::MouseInteraction m_mouseInteraction;
};
} // namespace EMStudio
@@ -210,6 +210,20 @@ namespace EMStudio
return m_frameworkScene;
}
AZ::EntityId AnimViewportRenderer::GetEntityId() const
{
if (m_actorEntities.empty())
{
return AZ::EntityId();
}
return m_actorEntities[0]->GetId();
}
AzFramework::EntityContextId AnimViewportRenderer::GetEntityContextId() const
{
return m_entityContext->GetContextId();
}
void AnimViewportRenderer::ResetEnvironment()
{
// Reset environment
@@ -55,8 +55,9 @@ namespace EMStudio
AZ::Vector3 GetCharacterCenter() const;
void UpdateActorRenderFlag(EMotionFX::ActorRenderFlagBitset renderFlags);
AZStd::shared_ptr<AzFramework::Scene> GetFrameworkScene() const;
AZ::EntityId GetEntityId() const;
AzFramework::EntityContextId GetEntityContextId() const;
private:
@@ -8,21 +8,10 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <Integration/Rendering/RenderFlag.h>
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h>
namespace EMStudio
{
enum CameraViewMode
{
FRONT,
BACK,
TOP,
BOTTOM,
LEFT,
RIGHT,
DEFAULT
};
class AnimViewportRequests
: public AZ::EBusTraits
{
@@ -30,17 +19,14 @@ namespace EMStudio
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;
//! Update the camera view mode.
virtual void UpdateCameraViewMode(EMStudio::RenderOptions::CameraViewMode mode) = 0;
//! Set the camera view mode.
virtual void SetCameraViewMode(CameraViewMode mode) = 0;
//! Update the camera follow up option
virtual void UpdateCameraFollowUp(bool followUp) = 0;
//! Set the camera follow up
virtual void SetFollowCharacter(bool follow) = 0;
//! Toggle render option flag
virtual void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag) = 0;
//! Update render flags
virtual void UpdateRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags) = 0;
};
using AnimViewportRequestBus = AZ::EBus<AnimViewportRequests>;
@@ -7,21 +7,48 @@
*/
#include <QToolButton>
#include <QPushButton>
#include <QMenu>
#include <QSettings>
#include <EMStudio/AtomRenderPlugin.h>
#include <EMStudio/AnimViewportToolBar.h>
#include <EMStudio/AnimViewportRequestBus.h>
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
#include <AzCore/std/string/string.h>
#include <AzQtComponents/Components/Widgets/ToolBar.h>
namespace EMStudio
{
AnimViewportToolBar::AnimViewportToolBar(QWidget* parent)
AnimViewportToolBar::AnimViewportToolBar(AtomRenderPlugin* plugin, QWidget* parent)
: QToolBar(parent)
, m_plugin(plugin)
{
AzQtComponents::ToolBar::addMainToolBarStyle(this);
// Add the manipulator actions
QActionGroup* manipulatorGroup = new QActionGroup(this);
manipulatorGroup->setExclusive(true);
manipulatorGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional);
m_manipulatorActions[RenderOptions::TRANSLATE] = addAction(QIcon(":/EMotionFXAtom/Translate.svg"), "Translate");
m_manipulatorActions[RenderOptions::ROTATE] = addAction(QIcon(":/EMotionFXAtom/Rotate.svg"), "Rotate");
m_manipulatorActions[RenderOptions::SCALE] = addAction(QIcon(":/EMotionFXAtom/Scale.svg"), "Scale");
for (size_t i = RenderOptions::ManipulatorMode::TRANSLATE; i < RenderOptions::ManipulatorMode::NUM_MODES; ++i)
{
m_manipulatorActions[i]->setCheckable(true);
connect(
m_manipulatorActions[i], &QAction::triggered, this,
[this, i]()
{
const RenderOptions::ManipulatorMode mode =
m_manipulatorActions[i]->isChecked() ? RenderOptions::ManipulatorMode(i) : RenderOptions::ManipulatorMode::SELECT;
m_plugin->GetRenderOptions()->SetManipulatorMode(mode);
m_plugin->SetManipulatorMode(mode);
});
manipulatorGroup->addAction(m_manipulatorActions[i]);
}
addSeparator();
// Add the render view options button
QToolButton* renderOptionsButton = new QToolButton(this);
{
@@ -66,30 +93,35 @@ namespace EMStudio
QMenu* cameraMenu = new QMenu(cameraButton);
// Add the camera option
const AZStd::vector<AZStd::pair<CameraViewMode, AZStd::string>> cameraOptionNames = {
{ CameraViewMode::FRONT, "Front" }, { CameraViewMode::BACK, "Back" }, { CameraViewMode::TOP, "Top" },
{ CameraViewMode::BOTTOM, "Bottom" }, { CameraViewMode::LEFT, "Left" }, { CameraViewMode::RIGHT, "Right" },
const AZStd::vector<AZStd::pair<RenderOptions::CameraViewMode, AZStd::string>> cameraOptionNames = {
{ RenderOptions::CameraViewMode::FRONT, "Front" },
{ RenderOptions::CameraViewMode::BACK, "Back" },
{ RenderOptions::CameraViewMode::TOP, "Top" },
{ RenderOptions::CameraViewMode::BOTTOM, "Bottom" },
{ RenderOptions::CameraViewMode::LEFT, "Left" },
{ RenderOptions::CameraViewMode::RIGHT, "Right" },
};
for (const auto& pair : cameraOptionNames)
{
CameraViewMode mode = pair.first;
RenderOptions::CameraViewMode mode = pair.first;
cameraMenu->addAction(
pair.second.c_str(),
[mode]()
[this, mode]()
{
// Send the reset camera event.
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::SetCameraViewMode, mode);
m_plugin->GetRenderOptions()->SetCameraViewMode(mode);
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::UpdateCameraViewMode, mode);
});
}
cameraMenu->addSeparator();
cameraMenu->addAction(
"Reset Camera",
[]()
[this]()
{
// Send the reset camera event.
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::ResetCamera);
m_plugin->GetRenderOptions()->SetCameraViewMode(RenderOptions::CameraViewMode::DEFAULT);
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::UpdateCameraViewMode, RenderOptions::CameraViewMode::DEFAULT);
});
cameraMenu->addSeparator();
@@ -99,8 +131,9 @@ namespace EMStudio
connect(m_followCharacterAction, &QAction::triggered, this,
[this]()
{
m_plugin->GetRenderOptions()->SetCameraFollowUp(m_followCharacterAction->isChecked());
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::SetFollowCharacter, m_followCharacterAction->isChecked());
&AnimViewportRequestBus::Events::UpdateCameraFollowUp, m_followCharacterAction->isChecked());
;
});
@@ -117,7 +150,6 @@ namespace EMStudio
AnimViewportToolBar::~AnimViewportToolBar()
{
SaveSettings();
}
void AnimViewportToolBar::CreateViewOptionEntry(
@@ -125,11 +157,11 @@ namespace EMStudio
{
QAction* action = menu->addAction(
menuEntryName,
[actionIndex]()
[this, actionIndex]()
{
m_plugin->GetRenderOptions()->ToggerRenderFlag(actionIndex);
// Send the reset camera event.
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::ToggleRenderFlag, (EMotionFX::ActorRenderFlag)actionIndex);
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::UpdateRenderFlags, m_plugin->GetRenderOptions()->GetRenderFlags());
});
action->setCheckable(true);
action->setVisible(visible);
@@ -139,38 +171,32 @@ namespace EMStudio
action->setIcon(QIcon(iconFileName));
}
m_actions[actionIndex] = action;
m_renderActions[actionIndex] = action;
}
void AnimViewportToolBar::SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags)
void AnimViewportToolBar::LoadSettings()
{
const RenderOptions* renderOptions = m_plugin->GetRenderOptions();
const bool isChecked = renderOptions->GetCameraFollowUp();
m_followCharacterAction->setChecked(isChecked);
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::UpdateCameraFollowUp, isChecked);
RenderOptions::ManipulatorMode mode = renderOptions->GetManipulatorMode();
m_plugin->SetManipulatorMode(mode);
if (mode != RenderOptions::ManipulatorMode::SELECT)
{
m_manipulatorActions[mode]->setChecked(true);
}
const EMotionFX::ActorRenderFlagBitset renderFlags = renderOptions->GetRenderFlags();
for (size_t i = 0; i < renderFlags.size(); ++i)
{
QAction* action = m_actions[i];
QAction* action = m_renderActions[i];
if (action)
{
action->setChecked(renderFlags[i]);
}
}
}
void AnimViewportToolBar::LoadSettings()
{
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
const bool isChecked = settings.value("CameraFollowUp", false).toBool();
m_followCharacterAction->setChecked(isChecked);
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::SetFollowCharacter, isChecked);
}
void AnimViewportToolBar::SaveSettings()
{
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
settings.setValue("CameraFollowUp", m_followCharacterAction->isChecked());
}
} // namespace EMStudio
@@ -18,21 +18,23 @@
namespace EMStudio
{
class AnimRenderPlugin;
class AnimViewportToolBar : public QToolBar
{
public:
AnimViewportToolBar(QWidget* parent = nullptr);
AnimViewportToolBar(AtomRenderPlugin* plugin, QWidget* parent);
~AnimViewportToolBar();
void SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags);
void LoadSettings();
void SaveSettings();
private:
void CreateViewOptionEntry(
QMenu* menu, const char* menuEntryName, uint32_t actionIndex, bool visible = true, char* iconFileName = nullptr);
QAction* m_actions[EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS] = { nullptr };
AtomRenderPlugin* m_plugin = nullptr;
QAction* m_manipulatorActions[RenderOptions::ManipulatorMode::NUM_MODES] = { nullptr };
QAction* m_renderActions[EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS] = { nullptr };
QAction* m_followCharacterAction = nullptr;
};
}
@@ -37,7 +37,6 @@ namespace EMStudio
m_renderer = AZStd::make_unique<AnimViewportRenderer>(GetViewportContext(), m_plugin->GetRenderOptions());
SetScene(m_renderer->GetFrameworkScene(), false);
LoadRenderFlags();
SetupCameras();
SetupCameraController();
Reinit();
@@ -48,7 +47,6 @@ namespace EMStudio
AnimViewportWidget::~AnimViewportWidget()
{
SaveRenderFlags();
ViewportPluginRequestBus::Handler::BusDisconnect();
AnimViewportRequestBus::Handler::BusDisconnect();
}
@@ -56,19 +54,14 @@ namespace EMStudio
void AnimViewportWidget::Reinit(bool resetCamera)
{
m_renderer->Reinit();
m_renderer->UpdateActorRenderFlag(m_renderFlags);
m_renderer->UpdateActorRenderFlag(m_plugin->GetRenderOptions()->GetRenderFlags());
if (resetCamera)
{
ResetCamera();
UpdateCameraViewMode(RenderOptions::CameraViewMode::DEFAULT);
}
}
EMotionFX::ActorRenderFlagBitset AnimViewportWidget::GetRenderFlags() const
{
return m_renderFlags;
}
void AnimViewportWidget::SetupCameras()
{
m_rotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(EMStudio::ViewportUtil::BuildRotateCameraInputId());
@@ -134,37 +127,32 @@ namespace EMStudio
GetControllerList()->Add(controller);
}
void AnimViewportWidget::ResetCamera()
{
SetCameraViewMode(CameraViewMode::DEFAULT);
}
void AnimViewportWidget::SetCameraViewMode(CameraViewMode mode)
void AnimViewportWidget::UpdateCameraViewMode(RenderOptions::CameraViewMode mode)
{
// Set the camera view mode.
const AZ::Vector3 targetPosition = m_renderer->GetCharacterCenter();
AZ::Vector3 cameraPosition;
switch (mode)
{
case CameraViewMode::FRONT:
case RenderOptions::CameraViewMode::FRONT:
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY() + CameraDistance, targetPosition.GetZ());
break;
case CameraViewMode::BACK:
case RenderOptions::CameraViewMode::BACK:
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY() - CameraDistance, targetPosition.GetZ());
break;
case CameraViewMode::TOP:
case RenderOptions::CameraViewMode::TOP:
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY(), CameraDistance + targetPosition.GetZ());
break;
case CameraViewMode::BOTTOM:
case RenderOptions::CameraViewMode::BOTTOM:
cameraPosition.Set(targetPosition.GetX(), targetPosition.GetY(), -CameraDistance + targetPosition.GetZ());
break;
case CameraViewMode::LEFT:
case RenderOptions::CameraViewMode::LEFT:
cameraPosition.Set(targetPosition.GetX() - CameraDistance, targetPosition.GetY(), targetPosition.GetZ());
break;
case CameraViewMode::RIGHT:
case RenderOptions::CameraViewMode::RIGHT:
cameraPosition.Set(targetPosition.GetX() + CameraDistance, targetPosition.GetY(), targetPosition.GetZ());
break;
case CameraViewMode::DEFAULT:
case RenderOptions::CameraViewMode::DEFAULT:
// The default view mode is looking from the top left of the character.
cameraPosition.Set(
targetPosition.GetX() - CameraDistance, targetPosition.GetY() + CameraDistance, targetPosition.GetZ() + CameraDistance);
@@ -178,9 +166,9 @@ namespace EMStudio
AZ::Vector3::CreateAxisY(-CameraDistance));
}
void AnimViewportWidget::SetFollowCharacter(bool follow)
void AnimViewportWidget::UpdateCameraFollowUp(bool followUp)
{
if (follow)
if (followUp)
{
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
GetViewportId(), &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetCameraOffset,
@@ -195,8 +183,6 @@ namespace EMStudio
GetViewportId(), &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetCameraPivotAttached,
GetViewportContext()->GetCameraTransform().GetTranslation());
}
m_followCharacter = follow;
}
void AnimViewportWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time)
@@ -229,13 +215,13 @@ namespace EMStudio
for (size_t i = 0; i < numPlugins; ++i)
{
EMStudioPlugin* plugin = GetPluginManager()->GetActivePlugin(i);
plugin->Render(m_renderFlags);
plugin->Render(m_plugin->GetRenderOptions()->GetRenderFlags());
}
}
void AnimViewportWidget::FollowCharacter()
{
if (m_followCharacter)
if (m_plugin->GetRenderOptions()->GetCameraFollowUp())
{
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
GetViewportId(), &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetCameraPivotAttached,
@@ -243,38 +229,9 @@ namespace EMStudio
}
}
void AnimViewportWidget::ToggleRenderFlag(EMotionFX::ActorRenderFlag flag)
void AnimViewportWidget::UpdateRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags)
{
m_renderFlags[flag] = !m_renderFlags[flag];
m_renderer->UpdateActorRenderFlag(m_renderFlags);
}
void AnimViewportWidget::LoadRenderFlags()
{
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
{
QString name = QString(i);
const bool isEnabled = settings.value(name).toBool();
m_renderFlags[i] = isEnabled;
}
m_renderer->UpdateActorRenderFlag(m_renderFlags);
}
void AnimViewportWidget::SaveRenderFlags()
{
AZStd::string renderFlagsFilename(EMStudioManager::GetInstance()->GetAppDataFolder());
renderFlagsFilename += "AnimViewportRenderFlags.cfg";
QSettings settings(renderFlagsFilename.c_str(), QSettings::IniFormat, this);
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
{
QString name = QString(i);
settings.setValue(name, (bool)m_renderFlags[i]);
}
m_renderer->UpdateActorRenderFlag(renderFlags);
}
AZ::s32 AnimViewportWidget::GetViewportId() const
@@ -31,7 +31,6 @@ namespace EMStudio
AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); }
void Reinit(bool resetCamera = true);
EMotionFX::ActorRenderFlagBitset GetRenderFlags() const;
private:
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
@@ -43,14 +42,10 @@ namespace EMStudio
void SetupCameras();
void SetupCameraController();
void LoadRenderFlags();
void SaveRenderFlags();
// AnimViewportRequestBus::Handler overrides
void ResetCamera();
void SetCameraViewMode(CameraViewMode mode);
void SetFollowCharacter(bool follow);
void ToggleRenderFlag(EMotionFX::ActorRenderFlag flag);
void UpdateCameraViewMode(RenderOptions::CameraViewMode mode);
void UpdateCameraFollowUp(bool follow);
void UpdateRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags);
// ViewportPluginRequestBus::Handler overrides
AZ::s32 GetViewportId() const;
@@ -62,7 +57,5 @@ namespace EMStudio
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_rotateCamera;
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_translateCamera;
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
EMotionFX::ActorRenderFlagBitset m_renderFlags;
bool m_followCharacter = false;
};
}
@@ -6,31 +6,49 @@
*
*/
#include <AzFramework/Viewport/ViewportControllerList.h>
#include <AzFramework/Viewport/ViewportColors.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
#include <AzToolsFramework/Viewport/ViewportSettings.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <EMStudio/AtomRenderPlugin.h>
#include <EMStudio/AnimViewportRenderer.h>
#include <EMStudio/AnimViewportToolBar.h>
#include <EMStudio/AnimViewportInputController.h>
#include <Integration/Components/ActorComponent.h>
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
#include <EMotionFX/Source/Allocators.h>
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
#include <QHBoxLayout>
#include <QGuiApplication>
namespace EMStudio
{
AZ_CLASS_ALLOCATOR_IMPL(AtomRenderPlugin, EMotionFX::EditorAllocator, 0);
const AzToolsFramework::ManipulatorManagerId g_animManipulatorManagerId =
AzToolsFramework::ManipulatorManagerId(AZ::Crc32("AnimManipulatorManagerId"));
AtomRenderPlugin::AtomRenderPlugin()
: DockWidgetPlugin()
, m_translationManipulators(
AzToolsFramework::TranslationManipulators::Dimensions::Three, AZ::Transform::Identity(), AZ::Vector3::CreateOne())
, m_rotateManipulators(AZ::Transform::CreateIdentity())
, m_scaleManipulators(AZ::Transform::CreateIdentity())
{
}
AtomRenderPlugin::~AtomRenderPlugin()
{
SaveRenderOptions();
GetCommandManager()->RemoveCommandCallback(m_importActorCallback, false);
GetCommandManager()->RemoveCommandCallback(m_removeActorCallback, false);
delete m_importActorCallback;
delete m_removeActorCallback;
AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus::Handler::BusDisconnect();
}
const char* AtomRenderPlugin::GetName() const
@@ -86,6 +104,7 @@ namespace EMStudio
void AtomRenderPlugin::ReinitRenderer()
{
m_animViewportWidget->Reinit();
SetManipulatorMode(m_renderOptions.GetManipulatorMode());
}
bool AtomRenderPlugin::Init()
@@ -104,21 +123,171 @@ namespace EMStudio
m_animViewportWidget = new AnimViewportWidget(this);
// Add the tool bar
AnimViewportToolBar* toolBar = new AnimViewportToolBar(m_innerWidget);
toolBar->SetRenderFlags(m_animViewportWidget->GetRenderFlags());
AnimViewportToolBar* toolBar = new AnimViewportToolBar(this, m_innerWidget);
verticalLayout->addWidget(toolBar);
verticalLayout->addWidget(m_animViewportWidget);
m_manipulatorManager = AZStd::make_shared<AzToolsFramework::ManipulatorManager>(g_animManipulatorManagerId);
SetupManipulators();
// Register command callbacks.
m_importActorCallback = new ImportActorCallback(false);
m_removeActorCallback = new RemoveActorCallback(false);
EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("ImportActor", m_importActorCallback);
EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("RemoveActor", m_removeActorCallback);
AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus::Handler::BusConnect(
m_animViewportWidget->GetViewportContext()->GetId());
return true;
}
void AtomRenderPlugin::SetupManipulators()
{
// Add the manipulator controller
m_animViewportWidget->GetControllerList()->Add(AZStd::make_shared<AnimViewportInputController>());
// Gather information about the entity
AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
worldTransform.SetTranslation(m_animViewportWidget->GetAnimViewportRenderer()->GetCharacterCenter());
// Setup the translation manipulator
m_translationManipulators.SetSpace(worldTransform);
AzToolsFramework::ConfigureTranslationManipulatorAppearance3d(&m_translationManipulators);
m_translationManipulators.InstallLinearManipulatorMouseMoveCallback(
[this](const AzToolsFramework::LinearManipulator::Action& action)
{
OnManipulatorMoved(action.LocalPosition());
});
m_translationManipulators.InstallPlanarManipulatorMouseMoveCallback(
[this](const AzToolsFramework::PlanarManipulator::Action& action)
{
OnManipulatorMoved(action.LocalPosition());
});
m_translationManipulators.InstallSurfaceManipulatorMouseMoveCallback(
[this](const AzToolsFramework::SurfaceManipulator::Action& action)
{
OnManipulatorMoved(action.LocalPosition());
});
// Setup the rotation manipulator
m_rotateManipulators.SetSpace(worldTransform);
m_rotateManipulators.SetLocalAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
m_rotateManipulators.ConfigureView(
AzToolsFramework::RotationManipulatorRadius(), AzFramework::ViewportColors::XAxisColor, AzFramework::ViewportColors::YAxisColor,
AzFramework::ViewportColors::ZAxisColor);
m_rotateManipulators.InstallMouseMoveCallback(
[this](const AzToolsFramework::AngularManipulator::Action& action)
{
OnManipulatorRotated(action.LocalOrientation());
});
// Setup the scale manipulator
m_scaleManipulators.SetSpace(worldTransform);
m_scaleManipulators.SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
m_scaleManipulators.ConfigureView(
AzToolsFramework::LinearManipulatorAxisLength(), AzFramework::ViewportColors::XAxisColor,
AzFramework::ViewportColors::YAxisColor, AzFramework::ViewportColors::ZAxisColor);
m_scaleManipulators.InstallAxisMouseMoveCallback(
[this](const AzToolsFramework::LinearManipulator::Action& action)
{
OnManipulatorScaled(action.LocalScale(), action.LocalScaleOffset());
});
}
void AtomRenderPlugin::SetManipulatorMode(RenderOptions::ManipulatorMode mode)
{
if (!m_manipulatorManager)
{
return;
}
if (mode == RenderOptions::ManipulatorMode::SELECT)
{
m_translationManipulators.Unregister();
m_rotateManipulators.Unregister();
m_scaleManipulators.Unregister();
return;
}
const AZ::EntityId entityId = m_animViewportWidget->GetAnimViewportRenderer()->GetEntityId();
if (!entityId.IsValid())
{
return;
}
AZ::Vector3 localPos;
AZ::TransformBus::EventResult(localPos, entityId, &AZ::TransformBus::Events::GetLocalTranslation);
switch (mode)
{
case RenderOptions::ManipulatorMode::SELECT:
// The AtomRenderPlugin doesn't implement a select mode
break;
case RenderOptions::ManipulatorMode::TRANSLATE:
{
m_translationManipulators.Register(g_animManipulatorManagerId);
m_translationManipulators.SetLocalPosition(localPos);
m_rotateManipulators.Unregister();
m_scaleManipulators.Unregister();
}
break;
case RenderOptions::ManipulatorMode::ROTATE:
{
m_translationManipulators.Unregister();
m_rotateManipulators.Register(g_animManipulatorManagerId);
m_rotateManipulators.SetLocalPosition(localPos);
m_scaleManipulators.Unregister();
}
break;
case RenderOptions::ManipulatorMode::SCALE:
{
m_translationManipulators.Unregister();
m_rotateManipulators.Unregister();
m_scaleManipulators.Register(g_animManipulatorManagerId);
m_scaleManipulators.SetLocalPosition(localPos);
}
break;
}
}
void AtomRenderPlugin::OnManipulatorMoved(const AZ::Vector3& position)
{
m_translationManipulators.SetLocalPosition(position);
const AZ::EntityId entityId = m_animViewportWidget->GetAnimViewportRenderer()->GetEntityId();
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
}
void AtomRenderPlugin::OnManipulatorRotated(const AZ::Quaternion& rotation)
{
const AZ::EntityId entityId = m_animViewportWidget->GetAnimViewportRenderer()->GetEntityId();
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, rotation);
}
void AtomRenderPlugin::OnManipulatorScaled(
const AZ::Vector3& scale, const AZ::Vector3& scaleOffset)
{
// Use the scaleOffset to determine which axis to use on the uniform scale.
float localScale = 1.0f;
if (scaleOffset.GetX() != 0.0f)
{
localScale = scale.GetX();
}
else if (scaleOffset.GetY() != 0.0f)
{
localScale = scale.GetY();
}
else if (scaleOffset.GetZ() != 0.0f)
{
localScale = scale.GetZ();
}
const AZ::EntityId entityId = m_animViewportWidget->GetAnimViewportRenderer()->GetEntityId();
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalUniformScale, localScale);
}
void AtomRenderPlugin::LoadRenderOptions()
{
AZStd::string renderOptionsFilename(GetManager()->GetAppDataFolder());
@@ -127,11 +296,78 @@ namespace EMStudio
m_renderOptions = RenderOptions::Load(&settings);
}
const RenderOptions* AtomRenderPlugin::GetRenderOptions() const
void AtomRenderPlugin::SaveRenderOptions()
{
AZStd::string renderOptionsFilename(GetManager()->GetAppDataFolder());
renderOptionsFilename += "EMStudioRenderOptions.cfg";
QSettings settings(renderOptionsFilename.c_str(), QSettings::IniFormat, this);
m_renderOptions.Save(&settings);
}
RenderOptions* AtomRenderPlugin::GetRenderOptions()
{
return &m_renderOptions;
}
void AtomRenderPlugin::Render([[maybe_unused]]EMotionFX::ActorRenderFlagBitset renderFlags)
{
if (!m_animViewportWidget)
{
return;
}
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, m_animViewportWidget->GetViewportContext()->GetId());
AzFramework::DebugDisplayRequests* debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
namespace AztfVi = AzToolsFramework::ViewportInteraction;
AztfVi::KeyboardModifiers keyboardModifiers;
AztfVi::EditorModifierKeyRequestBus::BroadcastResult(
keyboardModifiers, &AztfVi::EditorModifierKeyRequestBus::Events::QueryKeyboardModifiers);
debugDisplay->DepthTestOff();
const AzFramework::ScreenPoint screenPoint = AztfVi::ScreenPointFromQPoint(m_animViewportWidget->mapFromGlobal(QCursor::pos()));
m_manipulatorManager->DrawManipulators(
*debugDisplay, m_animViewportWidget->GetCameraState(),
AztfVi::BuildMouseInteraction(
AztfVi::BuildMousePick(m_animViewportWidget->GetCameraState(), screenPoint),
AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())),
AztfVi::InteractionId(AZ::EntityId(), m_animViewportWidget->GetViewportContext()->GetId()), keyboardModifiers ));
debugDisplay->DepthTestOn();
}
bool AtomRenderPlugin::HandleMouseInteraction(
const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteractionEvent)
{
if (!m_manipulatorManager)
{
return false;
}
using AzToolsFramework::ViewportInteraction::MouseEvent;
const auto& mouseInteraction = mouseInteractionEvent.m_mouseInteraction;
switch (mouseInteractionEvent.m_mouseEvent)
{
case MouseEvent::Down:
return m_manipulatorManager->ConsumeViewportMousePress(mouseInteraction);
case MouseEvent::DoubleClick:
return false;
case MouseEvent::Move:
{
const AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult mouseMoveResult =
m_manipulatorManager->ConsumeViewportMouseMove(mouseInteraction);
return mouseMoveResult == AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult::Interacting;
}
case MouseEvent::Up:
return m_manipulatorManager->ConsumeViewportMouseRelease(mouseInteraction);
case MouseEvent::Wheel:
return m_manipulatorManager->ConsumeViewportMouseWheel(mouseInteraction);
default:
return false;
}
}
// Command callbacks
bool ReinitAtomRenderPlugin()
{
@@ -9,10 +9,14 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Manipulators/RotationManipulators.h>
#include <AzToolsFramework/Manipulators/ScaleManipulators.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <MCore/Source/Command.h>
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h>
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h>
#include <EMStudio/AnimViewportWidget.h>
#include <QWidget>
#endif
@@ -26,6 +30,7 @@ namespace EMStudio
{
class AtomRenderPlugin
: public DockWidgetPlugin
, private AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus::Handler
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -53,17 +58,36 @@ namespace EMStudio
void ReinitRenderer();
void LoadRenderOptions();
const RenderOptions* GetRenderOptions() const;
void SaveRenderOptions();
RenderOptions* GetRenderOptions();
void Render(EMotionFX::ActorRenderFlagBitset renderFlags) override;
void SetManipulatorMode(RenderOptions::ManipulatorMode mode);
private:
// AzToolsFramework::ViewportInteraction::ViewportMouseRequestBus overrides...
bool HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteractionEvent) override;
void SetupManipulators();
void OnManipulatorMoved(const AZ::Vector3& position);
void OnManipulatorRotated(const AZ::Quaternion& rotation);
void OnManipulatorScaled(const AZ::Vector3& scale, const AZ::Vector3& scaleOffset);
QWidget* m_innerWidget = nullptr;
AnimViewportWidget* m_animViewportWidget = nullptr;
RenderOptions m_renderOptions;
// Manipulators
AzToolsFramework::TranslationManipulators m_translationManipulators;
AzToolsFramework::RotationManipulators m_rotateManipulators;
AzToolsFramework::ScaleManipulators m_scaleManipulators;
AZStd::shared_ptr<AzToolsFramework::ManipulatorManager> m_manipulatorManager;
MCORE_DEFINECOMMANDCALLBACK(ImportActorCallback);
MCORE_DEFINECOMMANDCALLBACK(RemoveActorCallback);
ImportActorCallback* m_importActorCallback = nullptr;
RemoveActorCallback* m_removeActorCallback = nullptr;
};
extern const AzToolsFramework::ManipulatorManagerId g_animManipulatorManagerId;
}// namespace EMStudio
@@ -22,4 +22,6 @@ set(FILES
Tools/EMStudio/AnimViewportToolBar.h
Tools/EMStudio/AnimViewportToolBar.cpp
Tools/EMStudio/AnimViewportRequestBus.h
Tools/EMStudio/AnimViewportInputController.h
Tools/EMStudio/AnimViewportInputController.cpp
)
@@ -177,6 +177,10 @@ namespace EMStudio
SetNearClipPlaneDistance(other.GetNearClipPlaneDistance());
SetFarClipPlaneDistance(other.GetFarClipPlaneDistance());
SetFOV(other.GetFOV());
SetRenderFlags(other.GetRenderFlags());
SetManipulatorMode(other.GetManipulatorMode());
SetCameraViewMode(other.GetCameraViewMode());
SetCameraFollowUp(other.GetCameraFollowUp());
return *this;
}
@@ -247,6 +251,16 @@ namespace EMStudio
settings->setValue(s_renderSelectionBoxOptionName, m_renderSelectionBox);
settings->setValue("manipulatorMode", static_cast<int>(m_manipulatorMode));
settings->setValue("cameraViewMode", static_cast<int>(m_cameraViewMode));
settings->setValue("cameraFollowUp", m_cameraFollowUp);
// Save render flags
settings->beginGroup("renderFlags");
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
{
settings->setValue(QString(i), (bool)m_renderFlags[i]);
}
settings->endGroup();
}
RenderOptions RenderOptions::Load(QSettings* settings)
@@ -315,6 +329,18 @@ namespace EMStudio
options.m_renderSelectionBox = settings->value(s_renderSelectionBoxOptionName, options.m_renderSelectionBox).toBool();
options.m_manipulatorMode = static_cast<ManipulatorMode>(settings->value("manipulatorMode", options.m_manipulatorMode).toInt());
options.m_cameraViewMode = static_cast<CameraViewMode>(settings->value("cameraViewMode", options.m_cameraViewMode).toInt());
options.m_cameraFollowUp = settings->value("CameraFollowUp", options.m_cameraFollowUp).toBool();
// Read render flags
settings->beginGroup("renderFlags");
for (uint32 i = 0; i < EMotionFX::ActorRenderFlag::NUM_RENDERFLAGS; ++i)
{
const bool defaultValue = (i == EMotionFX::ActorRenderFlag::RENDER_SOLID);
const bool isEnabled = settings->value(QString(i), defaultValue).toBool();
options.m_renderFlags[i] = isEnabled;
}
settings->endGroup();
options.CopyToRenderActorSettings(EMotionFX::GetRenderActorSettings());
@@ -1058,6 +1084,41 @@ namespace EMStudio
return m_manipulatorMode;
}
void RenderOptions::SetCameraViewMode(CameraViewMode mode)
{
m_cameraViewMode = mode;
}
RenderOptions::CameraViewMode RenderOptions::GetCameraViewMode() const
{
return m_cameraViewMode;
}
void RenderOptions::SetCameraFollowUp(bool followUp)
{
m_cameraFollowUp = followUp;
}
bool RenderOptions::GetCameraFollowUp() const
{
return m_cameraFollowUp;
}
void RenderOptions::ToggerRenderFlag(int index)
{
m_renderFlags[index] = !m_renderFlags[index];
}
void RenderOptions::SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags)
{
m_renderFlags = renderFlags;
}
EMotionFX::ActorRenderFlagBitset RenderOptions::GetRenderFlags() const
{
return m_renderFlags;
}
void RenderOptions::CopyToRenderActorSettings(AZ::Render::RenderActorSettings& settings) const
{
settings.m_vertexNormalsScale = m_vertexNormalsScale;
@@ -15,6 +15,7 @@
#include "../EMStudioConfig.h"
#include "../PluginOptions.h"
#include "../PluginOptionsBus.h"
#include <Integration/Rendering/RenderFlag.h>
QT_FORWARD_DECLARE_CLASS(QSettings);
@@ -83,6 +84,26 @@ namespace EMStudio
static const char* s_lastUsedLayoutOptionName;
static const char* s_renderSelectionBoxOptionName;
enum ManipulatorMode
{
SELECT = 0,
TRANSLATE = 1,
ROTATE = 2,
SCALE = 3,
NUM_MODES = 4
};
enum CameraViewMode
{
FRONT,
BACK,
TOP,
BOTTOM,
LEFT,
RIGHT,
DEFAULT
};
RenderOptions();
~RenderOptions();
RenderOptions& operator=(const RenderOptions& other);
@@ -254,18 +275,19 @@ namespace EMStudio
bool GetRenderSelectionBox() const { return m_renderSelectionBox; }
void SetRenderSelectionBox(bool renderSelectionBox);
enum ManipulatorMode
{
SELECT = 0,
TRANSLATE = 1,
ROTATE = 2,
SCALE = 3,
NUM_MODES = 4
};
void SetManipulatorMode(ManipulatorMode mode);
ManipulatorMode GetManipulatorMode() const;
void SetCameraViewMode(CameraViewMode mode);
CameraViewMode GetCameraViewMode() const;
void SetCameraFollowUp(bool followUp);
bool GetCameraFollowUp() const;
void ToggerRenderFlag(int index);
void SetRenderFlags(EMotionFX::ActorRenderFlagBitset renderFlags);
EMotionFX::ActorRenderFlagBitset GetRenderFlags() const;
private:
void OnGridUnitSizeChangedCallback() const;
void OnVertexNormalsScaleChangedCallback() const;
@@ -378,10 +400,13 @@ namespace EMStudio
AZ::Color m_simulatedObjectColliderColor;
AZ::Color m_selectedSimulatedObjectColliderColor;
// The following are not in the UI
// The following are not in the UI
AZStd::string m_lastUsedLayout;
bool m_renderSelectionBox;
ManipulatorMode m_manipulatorMode = SELECT;
ManipulatorMode m_manipulatorMode = ManipulatorMode::SELECT;
CameraViewMode m_cameraViewMode = CameraViewMode::DEFAULT;
bool m_cameraFollowUp = false;
EMotionFX::ActorRenderFlagBitset m_renderFlags;
};
} // namespace EMStudio
@@ -709,8 +709,10 @@ namespace EMStudio
renderOptionsFilename += "EMStudioRenderOptions.cfg";
QSettings settings(renderOptionsFilename.c_str(), QSettings::IniFormat, this);
// save the general render options
m_renderOptions.Save(&settings);
// Deprecation of renderPlugin.
// Since we are using the same render option save file for atom render plugin, do not save the render options in the RenderPlugin to
// prevent double save.
// m_renderOptions.Save(&settings);
AZStd::string groupName;
if (m_currentLayout)
@@ -50,8 +50,6 @@ namespace EMStudio
m_plugin->CreateRenderWidget(this, &m_renderWidget, &renderWidget);
verticalLayout->addWidget(renderWidget);
new QActionGroup(this);
QActionGroup* group = new QActionGroup(this);
group->setExclusive(true);