You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportToolBar.cpp

208 lines
9.9 KiB
C++

/*
* 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 <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(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);
{
QMenu* contextMenu = new QMenu(renderOptionsButton);
renderOptionsButton->setText("Render Options");
renderOptionsButton->setMenu(contextMenu);
renderOptionsButton->setPopupMode(QToolButton::InstantPopup);
renderOptionsButton->setVisible(true);
renderOptionsButton->setIcon(QIcon(":/EMotionFXAtom/Visualization.svg"));
addWidget(renderOptionsButton);
CreateViewOptionEntry(contextMenu, "Solid", EMotionFX::ActorRenderFlagIndex::SOLID);
CreateViewOptionEntry(contextMenu, "Wireframe", EMotionFX::ActorRenderFlagIndex::WIREFRAME);
// [EMFX-TODO] Add those option once implemented.
// CreateViewOptionEntry(contextMenu, "Lighting", EMotionFX::ActorRenderFlagIndex::RENDER_LIGHTING);
// CreateViewOptionEntry(contextMenu, "Backface Culling", EMotionFX::ActorRenderFlagIndex::RENDER_BACKFACECULLING);
contextMenu->addSeparator();
CreateViewOptionEntry(contextMenu, "Vertex Normals", EMotionFX::ActorRenderFlagIndex::VERTEXNORMALS);
CreateViewOptionEntry(contextMenu, "Face Normals", EMotionFX::ActorRenderFlagIndex::FACENORMALS);
CreateViewOptionEntry(contextMenu, "Tangents", EMotionFX::ActorRenderFlagIndex::TANGENTS);
CreateViewOptionEntry(contextMenu, "Actor Bounding Boxes", EMotionFX::ActorRenderFlagIndex::AABB);
contextMenu->addSeparator();
CreateViewOptionEntry(contextMenu, "Line Skeleton", EMotionFX::ActorRenderFlagIndex::LINESKELETON);
CreateViewOptionEntry(contextMenu, "Solid Skeleton", EMotionFX::ActorRenderFlagIndex::SKELETON);
CreateViewOptionEntry(contextMenu, "Joint Names", EMotionFX::ActorRenderFlagIndex::NODENAMES);
CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlagIndex::NODEORIENTATION);
// [EMFX-TODO] Add those option once implemented.
// CreateViewOptionEntry(contextMenu, "Actor Bind Pose", EMotionFX::ActorRenderFlagIndex::RENDER_ACTORBINDPOSE);
contextMenu->addSeparator();
CreateViewOptionEntry(contextMenu, "Hit Detection Colliders", EMotionFX::ActorRenderFlagIndex::HITDETECTION_COLLIDERS, true,
":/EMotionFXAtom/HitDetection.svg");
CreateViewOptionEntry(contextMenu, "Ragdoll Colliders", EMotionFX::ActorRenderFlagIndex::RAGDOLL_COLLIDERS, true,
":/EMotionFXAtom/RagdollCollider.svg");
CreateViewOptionEntry(contextMenu, "Ragdoll Joint Limits", EMotionFX::ActorRenderFlagIndex::RAGDOLL_JOINTLIMITS, true,
":/EMotionFXAtom/RagdollJointLimit.svg");
CreateViewOptionEntry(contextMenu, "Cloth Colliders", EMotionFX::ActorRenderFlagIndex::CLOTH_COLLIDERS, true,
":/EMotionFXAtom/Cloth.svg");
CreateViewOptionEntry(contextMenu, "Simulated Object Colliders", EMotionFX::ActorRenderFlagIndex::SIMULATEDOBJECT_COLLIDERS, true,
":/EMotionFXAtom/SimulatedObjectCollider.svg");
CreateViewOptionEntry(contextMenu, "Simulated Joints", EMotionFX::ActorRenderFlagIndex::SIMULATEJOINTS);
}
// Add the camera button
QToolButton* cameraButton = new QToolButton(this);
{
QMenu* cameraMenu = new QMenu(cameraButton);
// Add the camera option
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)
{
RenderOptions::CameraViewMode mode = pair.first;
cameraMenu->addAction(
pair.second.c_str(),
[this, mode]()
{
m_plugin->GetRenderOptions()->SetCameraViewMode(mode);
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::UpdateCameraViewMode, mode);
});
}
cameraMenu->addSeparator();
cameraMenu->addAction(
"Reset Camera",
[this]()
{
m_plugin->GetRenderOptions()->SetCameraViewMode(RenderOptions::CameraViewMode::DEFAULT);
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::UpdateCameraViewMode, RenderOptions::CameraViewMode::DEFAULT);
});
cameraMenu->addSeparator();
m_followCharacterAction = cameraMenu->addAction("Follow Character");
m_followCharacterAction->setCheckable(true);
m_followCharacterAction->setChecked(false);
connect(m_followCharacterAction, &QAction::triggered, this,
[this]()
{
m_plugin->GetRenderOptions()->SetCameraFollowUp(m_followCharacterAction->isChecked());
AnimViewportRequestBus::Broadcast(
&AnimViewportRequestBus::Events::UpdateCameraFollowUp, m_followCharacterAction->isChecked());
;
});
cameraButton->setMenu(cameraMenu);
cameraButton->setText("Camera Option");
cameraButton->setPopupMode(QToolButton::InstantPopup);
cameraButton->setVisible(true);
cameraButton->setIcon(QIcon(":/EMotionFXAtom/Camera_category.svg"));
addWidget(cameraButton);
}
LoadSettings();
}
AnimViewportToolBar::~AnimViewportToolBar()
{
}
void AnimViewportToolBar::CreateViewOptionEntry(
QMenu* menu, const char* menuEntryName, AZ::u8 actionIndex, bool visible, const char* iconFileName)
{
QAction* action = menu->addAction(
menuEntryName,
[this, actionIndex]()
{
m_plugin->GetRenderOptions()->ToggerRenderFlag(actionIndex);
// Send the reset camera event.
AnimViewportRequestBus::Broadcast(&AnimViewportRequestBus::Events::UpdateRenderFlags, m_plugin->GetRenderOptions()->GetRenderFlags());
});
action->setCheckable(true);
action->setVisible(visible);
if (iconFileName)
{
action->setIcon(QIcon(iconFileName));
}
m_renderActions[actionIndex] = action;
}
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::ActorRenderFlags renderFlags = renderOptions->GetRenderFlags();
for (uint8 i = 0; i < EMotionFX::ActorRenderFlagIndex::NUM_RENDERFLAGINDEXES; ++i)
{
QAction* action = m_renderActions[i];
if (action)
{
action->setChecked(EMotionFX::ActorRenderFlagUtil::CheckBit(renderFlags, i));
}
}
}
} // namespace EMStudio