/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace EMotionFX { AZ_CLASS_ALLOCATOR_IMPL(AnimGraphParameterPicker, EditorAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleParameterHandler, EditorAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(AnimGraphMultipleParameterHandler, EditorAllocator, 0); AnimGraphParameterPicker::AnimGraphParameterPicker(QWidget* parent, bool singleSelection, bool parameterMaskMode) : QWidget(parent) , m_animGraph(nullptr) , m_affectedByParameterChanges(nullptr) , m_pickButton(nullptr) , m_resetButton(nullptr) , m_shrinkButton(nullptr) , m_singleSelection(singleSelection) , m_parameterMaskMode(parameterMaskMode) { QHBoxLayout* hLayout = new QHBoxLayout(); hLayout->setMargin(0); m_pickButton = new QPushButton(this); connect(m_pickButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnPickClicked); hLayout->addWidget(m_pickButton); m_resetButton = new QPushButton(this); EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "/Images/Icons/Clear.svg", "Reset selection"); connect(m_resetButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnResetClicked); hLayout->addWidget(m_resetButton); if (m_parameterMaskMode) { m_shrinkButton = new QPushButton(); EMStudio::EMStudioManager::MakeTransparentButton(m_shrinkButton, "/Images/Icons/Cut.svg", "Shrink the parameter mask to the ports that are actually connected."); connect(m_shrinkButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnShrinkClicked); hLayout->addWidget(m_shrinkButton); } setLayout(hLayout); UpdateInterface(); } AnimGraphParameterPicker::~AnimGraphParameterPicker() { AZ::Data::AssetBus::Handler::BusDisconnect(); } void AnimGraphParameterPicker::OnResetClicked() { if (m_parameterNames.empty()) { return; } UpdateParameterNames(AZStd::vector()); } void AnimGraphParameterPicker::OnShrinkClicked() { if (!m_affectedByParameterChanges) { AZ_Error("EMotionFX", false, "Cannot shrink parameter mask. No valid parameter picker rule."); return; } AZStd::vector parameterNames; if (m_affectedByParameterChanges) { m_affectedByParameterChanges->AddRequiredParameters(parameterNames); } UpdateParameterNames(parameterNames); } void AnimGraphParameterPicker::UpdateInterface() { // Set the picker button name based on the number of nodes. const size_t numParameters = m_parameterNames.size(); if (numParameters == 0) { if (m_singleSelection) { m_pickButton->setText("Select parameter"); } else { m_pickButton->setText("Select parameters"); } m_resetButton->setVisible(false); } else if (numParameters == 1) { m_pickButton->setText(m_parameterNames[0].c_str()); m_resetButton->setVisible(true); } else { m_pickButton->setText(QString("%1 parameters").arg(numParameters)); m_resetButton->setVisible(true); } // Build and set the tooltip containing all nodes. QString tooltip; for (size_t i = 0; i < numParameters; ++i) { tooltip += m_parameterNames[i].c_str(); if (i != numParameters - 1) { tooltip += "\n"; } } m_pickButton->setToolTip(tooltip); } void AnimGraphParameterPicker::SetObjectAffectedByParameterChanges(ObjectAffectedByParameterChanges* affectedObject) { m_affectedByParameterChanges = affectedObject; m_parameterNames = m_affectedByParameterChanges->GetParameters(); UpdateInterface(); } void AnimGraphParameterPicker::InitializeParameterNames(const AZStd::vector& parameterNames) { if (m_parameterNames != parameterNames) { m_parameterNames = parameterNames; UpdateInterface(); } } void AnimGraphParameterPicker::UpdateParameterNames(const AZStd::vector& parameterNames) { if (m_parameterNames != parameterNames) { m_parameterNames = parameterNames; if (m_affectedByParameterChanges) { m_affectedByParameterChanges->ParameterMaskChanged(m_parameterNames); } emit ParametersChanged(m_parameterNames); UpdateInterface(); } } const AZStd::vector& AnimGraphParameterPicker::GetParameterNames() const { return m_parameterNames; } void AnimGraphParameterPicker::SetSingleParameterName(const AZStd::string& parameterName) { AZStd::vector parameterNames; if (!parameterName.empty()) { parameterNames.emplace_back(parameterName); } InitializeParameterNames(parameterNames); } const AZStd::string AnimGraphParameterPicker::GetSingleParameterName() const { if (m_parameterNames.empty()) { return AZStd::string(); } return m_parameterNames[0]; } void AnimGraphParameterPicker::OnAssetReady(AZ::Data::Asset asset) { m_animGraphAsset = asset; m_animGraph = m_animGraphAsset->GetAnimGraph(); } void AnimGraphParameterPicker::OnAssetReloaded(AZ::Data::Asset asset) { m_animGraphAsset = asset; m_animGraph = m_animGraphAsset->GetAnimGraph(); } void AnimGraphParameterPicker::OnPickClicked() { AnimGraph* animGraph = m_animGraph; if (m_affectedByParameterChanges) { animGraph = m_affectedByParameterChanges->GetParameterAnimGraph(); } if (!animGraph) { AZ_Error("EMotionFX", false, "Cannot open anim graph parameter selection window. No valid anim graph."); return; } // Create and show the node picker window EMStudio::ParameterSelectionWindow selectionWindow(this, m_singleSelection); selectionWindow.GetParameterWidget()->SetFilterTypes(m_filterTypes); selectionWindow.Update(animGraph, m_parameterNames); selectionWindow.setModal(true); if (selectionWindow.exec() != QDialog::Rejected) { AZStd::vector parameterNames = selectionWindow.GetParameterWidget()->GetSelectedParameters(); if (m_parameterMaskMode) { if (m_affectedByParameterChanges) { m_affectedByParameterChanges->AddRequiredParameters(parameterNames); } } UpdateParameterNames(parameterNames); } } void AnimGraphParameterPicker::SetAnimGraph(AnimGraph* animGraph) { m_animGraph = animGraph; m_animGraphAsset.Reset(); AZ::Data::AssetBus::Handler::BusDisconnect(); } void AnimGraphParameterPicker::SetAnimGraphAsset(const AZ::Data::Asset& animGraphAsset) { m_animGraphAsset = animGraphAsset; m_animGraph = animGraphAsset->GetAnimGraph(); AZ::Data::AssetBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusConnect(m_animGraphAsset.GetId()); } //--------------------------------------------------------------------------------------------------------------------------------------------------------- AnimGraphSingleParameterHandler::AnimGraphSingleParameterHandler() : QObject() , AzToolsFramework::PropertyHandler() { } AZ::u32 AnimGraphSingleParameterHandler::GetHandlerName() const { return AZ_CRC("AnimGraphParameter", 0x778af55a); } QWidget* AnimGraphSingleParameterHandler::CreateGUI(QWidget* parent) { AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true); connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker](const AZStd::vector& newParameters) { EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, picker); }); return picker; } void AnimGraphSingleParameterHandler::ConsumeAttribute(AnimGraphParameterPicker* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) { if (attrib == AZ::Edit::Attributes::ReadOnly) { bool value; if (attrValue->Read(value)) { GUI->setEnabled(!value); } } if (attrib == AZ_CRC("AnimGraph", 0x0d53d4b3)) { AnimGraph* animGraph = nullptr; attrValue->Read(animGraph); GUI->SetAnimGraph(animGraph); } if (attrib == AZ_CRC("AnimGraphAsset", 0x27aae8f2)) { AZ::Data::Asset animGraphAsset; attrValue->Read>(animGraphAsset); if (animGraphAsset) { GUI->SetAnimGraphAsset(animGraphAsset); } } } void AnimGraphSingleParameterHandler::WriteGUIValuesIntoProperty(size_t index, AnimGraphParameterPicker* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) { instance = GUI->GetSingleParameterName(); } bool AnimGraphSingleParameterHandler::ReadValuesIntoGUI(size_t index, AnimGraphParameterPicker* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) { QSignalBlocker signalBlocker(GUI); GUI->SetSingleParameterName(instance); return true; } //--------------------------------------------------------------------------------------------------------------------------------------------------------- AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleNumberParameterHandler, EditorAllocator, 0); AnimGraphSingleNumberParameterHandler::AnimGraphSingleNumberParameterHandler() : AnimGraphSingleParameterHandler() { } AZ::u32 AnimGraphSingleNumberParameterHandler::GetHandlerName() const { return AZ_CRC("AnimGraphNumberParameter", 0x8023eba9); } QWidget* AnimGraphSingleNumberParameterHandler::CreateGUI(QWidget* parent) { AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true); picker->SetFilterTypes({ azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid()}); connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker](const AZStd::vector& newParameters) { EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, picker); }); return picker; } //--------------------------------------------------------------------------------------------------------------------------------------------------------- AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleVector2ParameterHandler, EditorAllocator, 0); AnimGraphSingleVector2ParameterHandler::AnimGraphSingleVector2ParameterHandler() : AnimGraphSingleParameterHandler() { } AZ::u32 AnimGraphSingleVector2ParameterHandler::GetHandlerName() const { return AZ_CRC("AnimGraphVector2Parameter", 0x151dfae7); } QWidget* AnimGraphSingleVector2ParameterHandler::CreateGUI(QWidget* parent) { AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true); picker->SetFilterTypes({azrtti_typeid()}); connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker](const AZStd::vector& newParameters) { EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, picker); }); return picker; } //--------------------------------------------------------------------------------------------------------------------------------------------------------- AnimGraphMultipleParameterHandler::AnimGraphMultipleParameterHandler() : QObject() , AzToolsFramework::PropertyHandler, AnimGraphParameterPicker>() , m_animGraph(nullptr) { } AZ::u32 AnimGraphMultipleParameterHandler::GetHandlerName() const { return AZ_CRC("AnimGraphMultipleParameter", 0x4d5e082c); } QWidget* AnimGraphMultipleParameterHandler::CreateGUI(QWidget* parent) { AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, false); connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker](const AZStd::vector& newParameters) { EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, picker); }); return picker; } void AnimGraphMultipleParameterHandler::ConsumeAttribute(AnimGraphParameterPicker* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) { if (attrib == AZ::Edit::Attributes::ReadOnly) { bool value; if (attrValue->Read(value)) { GUI->setEnabled(!value); } } if (attrib == AZ_CRC("AnimGraph", 0x0d53d4b3)) { attrValue->Read(m_animGraph); GUI->SetAnimGraph(m_animGraph); } } void AnimGraphMultipleParameterHandler::WriteGUIValuesIntoProperty(size_t index, AnimGraphParameterPicker* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) { instance = GUI->GetParameterNames(); } bool AnimGraphMultipleParameterHandler::ReadValuesIntoGUI(size_t index, AnimGraphParameterPicker* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) { QSignalBlocker signalBlocker(GUI); GUI->InitializeParameterNames(instance); return true; } } // namespace EMotionFX