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.
603 lines
22 KiB
C++
603 lines
22 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#include <EMotionFX/Source/AnimGraphManager.h>
|
|
#include <EMotionFX/Source/BlendSpaceManager.h>
|
|
#include <EMotionFX/Source/EMotionFXManager.h>
|
|
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
|
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
|
#include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.h>
|
|
#include <Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.h>
|
|
#include <Editor/AnimGraphEditorBus.h>
|
|
#include <QHBoxLayout>
|
|
#include <QMessageBox>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
|
|
|
|
namespace EMotionFX
|
|
{
|
|
AZ_CLASS_ALLOCATOR_IMPL(BlendSpaceMotionWidget, EditorAllocator, 0)
|
|
AZ_CLASS_ALLOCATOR_IMPL(BlendSpaceMotionContainerWidget, EditorAllocator, 0)
|
|
AZ_CLASS_ALLOCATOR_IMPL(BlendSpaceMotionContainerHandler, EditorAllocator, 0)
|
|
|
|
BlendSpaceMotionWidget::BlendSpaceMotionWidget(BlendSpaceNode::BlendSpaceMotion* motion, QGridLayout* layout, int row)
|
|
: m_motion(motion)
|
|
{
|
|
const AZStd::string& motionId = motion->GetMotionId();
|
|
const bool showYFields = motion->GetDimension() == 2;
|
|
|
|
int column = 0;
|
|
|
|
// Motion name
|
|
m_labelMotion = new QLabel(motionId.c_str());
|
|
m_labelMotion->setObjectName("m_labelMotion");
|
|
m_labelMotion->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
layout->addWidget(m_labelMotion, row, column);
|
|
column++;
|
|
|
|
// Motion position x
|
|
QHBoxLayout* layoutX = new QHBoxLayout();
|
|
layoutX->setAlignment(Qt::AlignRight);
|
|
|
|
QLabel* labelX = new QLabel("X");
|
|
labelX->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
labelX->setStyleSheet("QLabel { font-weight: bold; color : red; }");
|
|
layoutX->addWidget(labelX);
|
|
|
|
m_spinboxX = new AzQtComponents::DoubleSpinBox();
|
|
m_spinboxX->setSingleStep(0.1);
|
|
m_spinboxX->setDecimals(4);
|
|
m_spinboxX->setRange(-FLT_MAX, FLT_MAX);
|
|
m_spinboxX->setProperty("motionId", motionId.c_str());
|
|
layoutX->addWidget(m_spinboxX);
|
|
|
|
layout->addLayout(layoutX, row, column);
|
|
column++;
|
|
|
|
// Motion position y
|
|
if (showYFields)
|
|
{
|
|
QHBoxLayout* layoutY = new QHBoxLayout();
|
|
layoutY->setAlignment(Qt::AlignRight);
|
|
|
|
QLabel* labelY = new QLabel("Y");
|
|
labelY->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
labelY->setStyleSheet("QLabel { font-weight: bold; color : green; }");
|
|
layoutY->addWidget(labelY);
|
|
|
|
m_spinboxY = new AzQtComponents::DoubleSpinBox();
|
|
m_spinboxY->setSingleStep(0.1);
|
|
m_spinboxY->setDecimals(4);
|
|
m_spinboxY->setRange(-FLT_MAX, FLT_MAX);
|
|
m_spinboxY->setProperty("motionId", motionId.c_str());
|
|
layoutY->addWidget(m_spinboxY);
|
|
|
|
layout->addLayout(layoutY, row, column);
|
|
column++;
|
|
}
|
|
else
|
|
{
|
|
m_spinboxY = nullptr;
|
|
}
|
|
|
|
// Restore button.
|
|
const int iconSize = 20;
|
|
m_restoreButton = new QPushButton();
|
|
m_restoreButton->setToolTip("Restore value to automatically computed one");
|
|
m_restoreButton->setMinimumSize(iconSize, iconSize);
|
|
m_restoreButton->setMaximumSize(iconSize, iconSize);
|
|
m_restoreButton->setIcon(QIcon(":/EMotionFX/Restore.svg"));
|
|
m_restoreButton->setProperty("motionId", motionId.c_str());
|
|
layout->addWidget(m_restoreButton, row, column);
|
|
column++;
|
|
|
|
// Remove motion from blend space button.
|
|
m_removeButton = new QPushButton();
|
|
m_removeButton->setToolTip("Remove motion from blend space");
|
|
m_removeButton->setMinimumSize(iconSize, iconSize);
|
|
m_removeButton->setMaximumSize(iconSize, iconSize);
|
|
m_removeButton->setIcon(QIcon(":/EMotionFX/Trash.svg"));
|
|
layout->addWidget(m_removeButton, row, column);
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionWidget::UpdateInterface(EMotionFX::BlendSpaceNode* blendSpaceNode, EMotionFX::AnimGraphInstance* animGraphInstance)
|
|
{
|
|
bool positionsComputed = false;
|
|
AZ::Vector2 computedPosition = AZ::Vector2::CreateZero();
|
|
if (blendSpaceNode && animGraphInstance)
|
|
{
|
|
blendSpaceNode->ComputeMotionCoordinates(m_motion->GetMotionId(), animGraphInstance, computedPosition);
|
|
positionsComputed = true;
|
|
}
|
|
|
|
// Spinbox X
|
|
m_spinboxX->blockSignals(true);
|
|
|
|
if (m_motion->IsXCoordinateSetByUser())
|
|
{
|
|
m_spinboxX->setValue(m_motion->GetXCoordinate());
|
|
}
|
|
else
|
|
{
|
|
m_spinboxX->setValue(computedPosition.GetX());
|
|
}
|
|
|
|
m_spinboxX->blockSignals(false);
|
|
m_spinboxX->setEnabled(m_motion->IsXCoordinateSetByUser() || positionsComputed);
|
|
|
|
|
|
// Spinbox Y
|
|
if (m_spinboxY)
|
|
{
|
|
m_spinboxY->blockSignals(true);
|
|
|
|
if (m_motion->IsYCoordinateSetByUser())
|
|
{
|
|
m_spinboxY->setValue(m_motion->GetYCoordinate());
|
|
}
|
|
else
|
|
{
|
|
m_spinboxY->setValue(computedPosition.GetY());
|
|
}
|
|
|
|
m_spinboxY->blockSignals(false);
|
|
m_spinboxY->setEnabled(m_motion->IsYCoordinateSetByUser() || positionsComputed);
|
|
}
|
|
|
|
// Enable the restore button in case the user manually set any of the.
|
|
const bool enableRestoreButton = m_motion->IsXCoordinateSetByUser() || m_motion->IsYCoordinateSetByUser();
|
|
m_restoreButton->setEnabled(enableRestoreButton);
|
|
|
|
// is motion invalid?
|
|
if (m_motion->TestFlag(EMotionFX::BlendSpaceNode::BlendSpaceMotion::TypeFlags::InvalidMotion))
|
|
{
|
|
m_labelMotion->setStyleSheet("#m_labelMotion { border: 1px solid red; }");
|
|
m_labelMotion->setToolTip("Invalid motion.Select a motion set that contains this motion or add it to the current one.");
|
|
}
|
|
else
|
|
{
|
|
m_labelMotion->setStyleSheet("#m_labelMotion { border: none; }");
|
|
m_labelMotion->setToolTip("");
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BlendSpaceMotionContainerWidget::BlendSpaceMotionContainerWidget([[maybe_unused]] BlendSpaceNode* blendSpaceNode, QWidget* parent)
|
|
: QWidget(parent)
|
|
, m_blendSpaceNode(nullptr)
|
|
, m_containerWidget(nullptr)
|
|
, m_addMotionsLabel(nullptr)
|
|
{
|
|
QVBoxLayout* mainLayout = new QVBoxLayout();
|
|
mainLayout->setSpacing(0);
|
|
mainLayout->setMargin(0);
|
|
setLayout(mainLayout);
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::SetBlendSpaceNode(BlendSpaceNode* blendSpaceNode)
|
|
{
|
|
m_blendSpaceNode = blendSpaceNode;
|
|
ReInit();
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::SetMotions(const AZStd::vector<BlendSpaceNode::BlendSpaceMotion>& motions)
|
|
{
|
|
m_motions = motions;
|
|
ReInit();
|
|
}
|
|
|
|
|
|
const AZStd::vector<BlendSpaceNode::BlendSpaceMotion>& BlendSpaceMotionContainerWidget::GetMotions() const
|
|
{
|
|
return m_motions;
|
|
}
|
|
|
|
|
|
BlendSpaceMotionWidget* BlendSpaceMotionContainerWidget::FindWidgetByMotionId(const AZStd::string& motionId) const
|
|
{
|
|
for (BlendSpaceMotionWidget* container : m_motionWidgets)
|
|
{
|
|
const BlendSpaceNode::BlendSpaceMotion* motion = container->m_motion;
|
|
if (motion->GetMotionId() == motionId)
|
|
{
|
|
return container;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
BlendSpaceMotionWidget* BlendSpaceMotionContainerWidget::FindWidget(QObject* object)
|
|
{
|
|
const AZStd::string motionId = object->property("motionId").toString().toUtf8().data();
|
|
|
|
BlendSpaceMotionWidget* widget = FindWidgetByMotionId(motionId);
|
|
AZ_Assert(widget, "Can't find widget for motion with id '%s'.", motionId.c_str());
|
|
|
|
return widget;
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::OnAddMotion()
|
|
{
|
|
EMotionFX::MotionSet* motionSet = nullptr;
|
|
AnimGraphEditorRequestBus::BroadcastResult(motionSet, &AnimGraphEditorRequests::GetSelectedMotionSet);
|
|
if (!motionSet)
|
|
{
|
|
QMessageBox::warning(this, "No Motion Set", "Cannot open motion selection window. Please make sure exactly one motion set is selected.");
|
|
return;
|
|
}
|
|
|
|
// Create and show the motion picker window.
|
|
EMStudio::MotionSetSelectionWindow motionPickWindow(this);
|
|
motionPickWindow.GetHierarchyWidget()->SetSelectionMode(false);
|
|
motionPickWindow.Update(motionSet);
|
|
motionPickWindow.setModal(true);
|
|
|
|
if (motionPickWindow.exec() == QDialog::Rejected) // we pressed cancel or the close cross
|
|
{
|
|
return;
|
|
}
|
|
|
|
const AZStd::vector<AZStd::string> selectedMotionIds = motionPickWindow.GetHierarchyWidget()->GetSelectedMotionIds(motionSet);
|
|
if (selectedMotionIds.empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (const AZStd::string& selectedMotionId : selectedMotionIds)
|
|
{
|
|
bool alreadyExists = false;
|
|
|
|
for (const BlendSpaceNode::BlendSpaceMotion& blendSpaceMotion : m_motions)
|
|
{
|
|
if (blendSpaceMotion.GetMotionId() == selectedMotionId)
|
|
{
|
|
alreadyExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!alreadyExists)
|
|
{
|
|
BlendSpaceNode::BlendSpaceMotion newMotion(selectedMotionId);
|
|
m_motions.emplace_back(BlendSpaceNode::BlendSpaceMotion(selectedMotionId));
|
|
}
|
|
}
|
|
|
|
m_blendSpaceNode->SetMotions(m_motions);
|
|
m_motions = m_blendSpaceNode->GetMotions();
|
|
|
|
ReInit();
|
|
emit MotionsChanged();
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::OnRemoveMotion(const BlendSpaceNode::BlendSpaceMotion* motion)
|
|
{
|
|
// Iterate through the arributes back to front and delete the ones with the motion id from the delete button.
|
|
// Note: Normally there should only be once instance as motion ids should be unique within this array.
|
|
const AZ::s64 motionCount = m_motions.size();
|
|
for (AZ::s64 i = motionCount - 1; i >= 0; i--)
|
|
{
|
|
if (&m_motions[i] == motion)
|
|
{
|
|
m_motions.erase(m_motions.begin() + i);
|
|
}
|
|
}
|
|
|
|
ReInit();
|
|
emit MotionsChanged();
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::OnPositionXChanged(double value)
|
|
{
|
|
UpdateMotionPosition(sender(), static_cast<float>(value), true, false);
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::OnPositionYChanged(double value)
|
|
{
|
|
UpdateMotionPosition(sender(), static_cast<float>(value), false, true);
|
|
}
|
|
|
|
|
|
// Get the currently active anim graph instance in case only exactly one actor instance is selected.
|
|
EMotionFX::AnimGraphInstance* BlendSpaceMotionContainerWidget::GetSingleSelectedAnimGraphInstance() const
|
|
{
|
|
if (!m_blendSpaceNode)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
EMotionFX::ActorInstance* actorInstance = CommandSystem::GetCommandManager()->GetCurrentSelection().GetSingleActorInstance();
|
|
if (!actorInstance)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance();
|
|
if (animGraphInstance && animGraphInstance->GetAnimGraph() != m_blendSpaceNode->GetAnimGraph())
|
|
{
|
|
// The currently activated anim graph in the plugin differs from the one the current actor instance uses.
|
|
animGraphInstance = nullptr;
|
|
}
|
|
|
|
return animGraphInstance;
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::UpdateMotionPosition(QObject* object, float value, bool updateX, bool updateY)
|
|
{
|
|
BlendSpaceMotionWidget* widget = FindWidget(object);
|
|
if (!widget)
|
|
{
|
|
AZ_Error("EMotionFX", false, "Cannot update motion position. Can't find widget for QObject.");
|
|
return;
|
|
}
|
|
|
|
BlendSpaceNode::BlendSpaceMotion* blendSpaceMotion = widget->m_motion;
|
|
if (!blendSpaceMotion)
|
|
{
|
|
AZ_Error("EMotionFX", false, "Cannot update motion position. Blend space motion widget does not have a motion assigned to it.");
|
|
return;
|
|
}
|
|
|
|
// Get the anim graph instance in case only exactly one actor instance is selected.
|
|
EMotionFX::AnimGraphInstance* animGraphInstance = GetSingleSelectedAnimGraphInstance();
|
|
if (animGraphInstance)
|
|
{
|
|
// Compute the position of the motion using the set evaluators.
|
|
AZ::Vector2 computedPosition;
|
|
m_blendSpaceNode->ComputeMotionCoordinates(blendSpaceMotion->GetMotionId(), animGraphInstance, computedPosition);
|
|
|
|
const float epsilon = 1.0f / (powf(10, static_cast<float>(widget->m_spinboxX->decimals())));
|
|
if (updateX)
|
|
{
|
|
if (blendSpaceMotion->IsXCoordinateSetByUser())
|
|
{
|
|
// If we already manually set the motion position, just update the x coordinate.
|
|
blendSpaceMotion->SetXCoordinate(value);
|
|
}
|
|
else
|
|
{
|
|
// Check if the user just clicked the interface and triggered a value change or if he actually changed the value.
|
|
if (!AZ::IsClose(computedPosition.GetX(), value, epsilon))
|
|
{
|
|
// Mark the position as manually set in case the user entered a new position that differs from the automatically computed one.
|
|
blendSpaceMotion->MarkXCoordinateSetByUser(true);
|
|
blendSpaceMotion->SetXCoordinate(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (updateY)
|
|
{
|
|
if (blendSpaceMotion->IsYCoordinateSetByUser())
|
|
{
|
|
blendSpaceMotion->SetYCoordinate(value);
|
|
}
|
|
else
|
|
{
|
|
if (!AZ::IsClose(computedPosition.GetY(), value, epsilon))
|
|
{
|
|
blendSpaceMotion->MarkYCoordinateSetByUser(true);
|
|
blendSpaceMotion->SetYCoordinate(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In case there is no character, only the motion positions that are already in manual mode are enabled.
|
|
// Thus, we can just forward the position shown in the interface to the attribute.
|
|
|
|
if (updateX)
|
|
{
|
|
blendSpaceMotion->MarkXCoordinateSetByUser(true);
|
|
blendSpaceMotion->SetXCoordinate(value);
|
|
}
|
|
if (updateY)
|
|
{
|
|
blendSpaceMotion->MarkYCoordinateSetByUser(true);
|
|
blendSpaceMotion->SetYCoordinate(value);
|
|
}
|
|
}
|
|
|
|
ReInit();
|
|
emit MotionsChanged();
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::OnRestorePosition()
|
|
{
|
|
BlendSpaceMotionWidget* widget = FindWidget(sender());
|
|
if (!widget)
|
|
{
|
|
AZ_Error("EMotionFX", false, "Cannot update motion position. Can't find widget for QObject.");
|
|
return;
|
|
}
|
|
|
|
// Get the anim graph instance in case only exactly one actor instance is selected.
|
|
EMotionFX::AnimGraphInstance* animGraphInstance = GetSingleSelectedAnimGraphInstance();
|
|
|
|
// Get access to the blend space node of the anim graph to be able to calculate the blend space position.
|
|
if (m_blendSpaceNode && animGraphInstance)
|
|
{
|
|
m_blendSpaceNode->RestoreMotionCoordinates(*widget->m_motion, animGraphInstance);
|
|
|
|
ReInit();
|
|
emit MotionsChanged();
|
|
}
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::UpdateInterface()
|
|
{
|
|
// Get the anim graph instance in case only exactly one actor instance is selected.
|
|
EMotionFX::AnimGraphInstance* animGraphInstance = GetSingleSelectedAnimGraphInstance();
|
|
|
|
for (BlendSpaceMotionWidget* widget : m_motionWidgets)
|
|
{
|
|
widget->UpdateInterface(m_blendSpaceNode, animGraphInstance);
|
|
}
|
|
|
|
if (m_motions.empty())
|
|
{
|
|
m_addMotionsLabel->setText("Add motions and set coordinates.");
|
|
}
|
|
else
|
|
{
|
|
m_addMotionsLabel->setText("");
|
|
}
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerWidget::ReInit()
|
|
{
|
|
if (m_containerWidget)
|
|
{
|
|
// Hide the old widget and request deletion.
|
|
m_containerWidget->hide();
|
|
m_containerWidget->deleteLater();
|
|
|
|
m_containerWidget = nullptr;
|
|
m_addMotionsLabel = nullptr;
|
|
m_motionWidgets.clear();
|
|
}
|
|
|
|
m_containerWidget = new QWidget();
|
|
m_containerWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
|
|
QVBoxLayout* widgetLayout = new QVBoxLayout();
|
|
QHBoxLayout* topRowLayout = new QHBoxLayout();
|
|
|
|
// Add helper label left of the add button.
|
|
m_addMotionsLabel = new QLabel();
|
|
topRowLayout->addWidget(m_addMotionsLabel, 0, Qt::AlignLeft);
|
|
|
|
// Add motions button.
|
|
QPushButton* addMotionsButton = new QPushButton();
|
|
EMStudio::EMStudioManager::MakeTransparentButton(addMotionsButton, "Images/Icons/Plus.svg", "Add motions to blend space");
|
|
connect(addMotionsButton, &QPushButton::clicked, this, &BlendSpaceMotionContainerWidget::OnAddMotion);
|
|
topRowLayout->addWidget(addMotionsButton, 0, Qt::AlignRight);
|
|
|
|
widgetLayout->addLayout(topRowLayout);
|
|
|
|
if (!m_motions.empty())
|
|
{
|
|
QWidget* motionsWidget = new QWidget(m_containerWidget);
|
|
motionsWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
QGridLayout* motionsLayout = new QGridLayout();
|
|
motionsLayout->setMargin(0);
|
|
|
|
const size_t motionCount = m_motions.size();
|
|
for (size_t i = 0; i < motionCount; ++i)
|
|
{
|
|
BlendSpaceNode::BlendSpaceMotion* blendSpaceMotion = &m_motions[i];
|
|
BlendSpaceMotionWidget* motionWidget = new BlendSpaceMotionWidget(blendSpaceMotion, motionsLayout, static_cast<int>(i));
|
|
|
|
connect(motionWidget->m_spinboxX, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &EMotionFX::BlendSpaceMotionContainerWidget::OnPositionXChanged);
|
|
if (motionWidget->m_spinboxY)
|
|
{
|
|
connect(motionWidget->m_spinboxY, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &EMotionFX::BlendSpaceMotionContainerWidget::OnPositionYChanged);
|
|
}
|
|
connect(motionWidget->m_restoreButton, &QPushButton::clicked, this, &BlendSpaceMotionContainerWidget::OnRestorePosition);
|
|
connect(motionWidget->m_removeButton, &QPushButton::clicked, [this, blendSpaceMotion]()
|
|
{
|
|
OnRemoveMotion(blendSpaceMotion);
|
|
});
|
|
|
|
m_motionWidgets.emplace_back(motionWidget);
|
|
}
|
|
|
|
motionsWidget->setLayout(motionsLayout);
|
|
widgetLayout->addWidget(motionsWidget);
|
|
}
|
|
|
|
m_containerWidget->setLayout(widgetLayout);
|
|
layout()->addWidget(m_containerWidget);
|
|
|
|
UpdateInterface();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BlendSpaceMotionContainerHandler::BlendSpaceMotionContainerHandler()
|
|
: QObject()
|
|
, AzToolsFramework::PropertyHandler<AZStd::vector<BlendSpaceNode::BlendSpaceMotion>, BlendSpaceMotionContainerWidget>()
|
|
, m_blendSpaceNode(nullptr)
|
|
{
|
|
}
|
|
|
|
|
|
AZ::u32 BlendSpaceMotionContainerHandler::GetHandlerName() const
|
|
{
|
|
return AZ_CRC("BlendSpaceMotionContainer", 0x8025d37d);
|
|
}
|
|
|
|
|
|
QWidget* BlendSpaceMotionContainerHandler::CreateGUI(QWidget* parent)
|
|
{
|
|
BlendSpaceMotionContainerWidget* picker = aznew BlendSpaceMotionContainerWidget(m_blendSpaceNode, parent);
|
|
|
|
connect(picker, &BlendSpaceMotionContainerWidget::MotionsChanged, this, [picker]()
|
|
{
|
|
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, picker);
|
|
});
|
|
|
|
return picker;
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerHandler::ConsumeAttribute(BlendSpaceMotionContainerWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
|
|
{
|
|
if (attrValue)
|
|
{
|
|
m_blendSpaceNode = static_cast<BlendSpaceNode*>(attrValue->GetInstancePointer());
|
|
GUI->SetBlendSpaceNode(m_blendSpaceNode);
|
|
}
|
|
|
|
if (attrib == AZ::Edit::Attributes::ReadOnly)
|
|
{
|
|
bool value;
|
|
if (attrValue->Read<bool>(value))
|
|
{
|
|
GUI->setEnabled(!value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void BlendSpaceMotionContainerHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, BlendSpaceMotionContainerWidget* GUI, property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
|
{
|
|
instance = GUI->GetMotions();
|
|
}
|
|
|
|
|
|
bool BlendSpaceMotionContainerHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, BlendSpaceMotionContainerWidget* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
|
{
|
|
QSignalBlocker signalBlocker(GUI);
|
|
GUI->SetMotions(instance);
|
|
return true;
|
|
}
|
|
} // namespace EMotionFX
|
|
|
|
#include <Source/Editor/PropertyWidgets/moc_BlendSpaceMotionContainerHandler.cpp>
|