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.
220 lines
8.2 KiB
C++
220 lines
8.2 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 <Editor/QtMetaTypes.h>
|
|
#include <Editor/PropertyWidgets/EventDataHandler.h>
|
|
#include <QAbstractListModel>
|
|
#include <QVBoxLayout>
|
|
|
|
|
|
namespace EMotionFX
|
|
{
|
|
AZ_CLASS_ALLOCATOR_IMPL(EventDataTypeSelectionWidget, EditorAllocator, 0)
|
|
AZ_CLASS_ALLOCATOR_IMPL(EventDataHandler, EditorAllocator, 0)
|
|
|
|
class EventDataTypeSelectionWidget::EventDataTypesModel
|
|
: public QAbstractListModel
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
UuidRole = Qt::UserRole
|
|
};
|
|
|
|
EventDataTypesModel();
|
|
EventDataTypesModel(const EventDataTypesModel&) = delete;
|
|
EventDataTypesModel(EventDataTypesModel&&) = delete;
|
|
|
|
static AZStd::shared_ptr<EventDataTypesModel> Get();
|
|
|
|
int rowCount(const QModelIndex& parent) const override;
|
|
|
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
|
|
|
private:
|
|
static AZStd::weak_ptr<EventDataTypesModel> dataTypesModel;
|
|
AZStd::vector<AZStd::pair<QString, AZ::Uuid> > m_eventDataClassNames;
|
|
};
|
|
AZStd::weak_ptr<EventDataTypeSelectionWidget::EventDataTypesModel> EventDataTypeSelectionWidget::EventDataTypesModel::dataTypesModel;
|
|
|
|
EventDataTypeSelectionWidget::EventDataTypesModel::EventDataTypesModel()
|
|
{
|
|
AZ::SerializeContext* context;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
|
|
m_eventDataClassNames.emplace_back("<none>", AZ::Uuid::CreateNull());
|
|
|
|
context->EnumerateDerived<EventData>(
|
|
[this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&)
|
|
{
|
|
// Only add this type if it has the "Creatable" class attribute
|
|
// set to true
|
|
const AZ::Edit::ClassData* editData = classData->m_editData;
|
|
if (!editData)
|
|
{
|
|
return true;
|
|
}
|
|
for (const AZ::Edit::ElementData& element : editData->m_elements)
|
|
{
|
|
if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
|
|
{
|
|
const AZ::Attribute* attribute = AZ::FindAttribute(AZ_CRC("Creatable", 0x47bff8c4), element.m_attributes);
|
|
if (!attribute)
|
|
{
|
|
continue;
|
|
}
|
|
const AZ::AttributeContainerType<bool>* typedAttribute = static_cast<const AZ::AttributeContainerType<bool>*>(attribute);
|
|
// instance is nullptr because this is a class-level
|
|
// attribute and not one on a specific instance
|
|
if (typedAttribute->Get(/*instance =*/ nullptr))
|
|
{
|
|
m_eventDataClassNames.emplace_back(editData->m_name, classData->m_typeId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
}
|
|
|
|
AZStd::shared_ptr<EventDataTypeSelectionWidget::EventDataTypesModel> EventDataTypeSelectionWidget::EventDataTypesModel::Get()
|
|
{
|
|
AZStd::shared_ptr<EventDataTypesModel> model;
|
|
if (dataTypesModel.expired())
|
|
{
|
|
model = AZStd::make_shared<EventDataTypesModel>();
|
|
}
|
|
else
|
|
{
|
|
model = dataTypesModel.lock();
|
|
}
|
|
return model;
|
|
}
|
|
|
|
int EventDataTypeSelectionWidget::EventDataTypesModel::rowCount(const QModelIndex& parent) const
|
|
{
|
|
if (parent.isValid())
|
|
{
|
|
return 0;
|
|
}
|
|
return static_cast<int>(m_eventDataClassNames.size());
|
|
}
|
|
|
|
QVariant EventDataTypeSelectionWidget::EventDataTypesModel::data(const QModelIndex& index, int role) const
|
|
{
|
|
if (!index.isValid())
|
|
{
|
|
return QVariant();
|
|
}
|
|
|
|
if (role == Qt::DisplayRole)
|
|
{
|
|
return m_eventDataClassNames[index.row()].first;
|
|
}
|
|
else if (role == UuidRole)
|
|
{
|
|
return QVariant::fromValue(m_eventDataClassNames[index.row()].second);
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
EventDataTypeSelectionWidget::EventDataTypeSelectionWidget(QWidget* parent)
|
|
: QWidget(parent)
|
|
{
|
|
m_comboBox = new QComboBox(this);
|
|
m_model = EventDataTypesModel::Get();
|
|
m_comboBox->setModel(m_model.get());
|
|
|
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
layout->addWidget(m_comboBox);
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->setSpacing(0);
|
|
|
|
connect(
|
|
m_comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
|
this, &EventDataTypeSelectionWidget::currentIndexChanged
|
|
);
|
|
}
|
|
|
|
const AZ::Uuid EventDataTypeSelectionWidget::GetSelectedClass() const
|
|
{
|
|
return m_comboBox->currentData(EventDataTypesModel::UuidRole).value<AZ::Uuid>();
|
|
}
|
|
|
|
void EventDataTypeSelectionWidget::SetSelectedClass(const AZ::Uuid& classId)
|
|
{
|
|
const int newRow = m_comboBox->findData(
|
|
QVariant::fromValue(classId),
|
|
EventDataTypesModel::UuidRole,
|
|
Qt::MatchExactly
|
|
);
|
|
m_comboBox->setCurrentIndex(newRow);
|
|
}
|
|
|
|
AZ::u32 EventDataHandler::GetHandlerName() const
|
|
{
|
|
return AZ_CRC("EMotionFX::EventData", 0xca242382);
|
|
}
|
|
|
|
QWidget* EventDataHandler::CreateGUI(QWidget* parent)
|
|
{
|
|
EventDataTypeSelectionWidget* widget = aznew EventDataTypeSelectionWidget(parent);
|
|
connect(widget, &EventDataTypeSelectionWidget::currentIndexChanged, this, [widget]()
|
|
{
|
|
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, widget);
|
|
});
|
|
return widget;
|
|
}
|
|
|
|
void EventDataHandler::ConsumeAttribute([[maybe_unused]] EventDataTypeSelectionWidget* widget, [[maybe_unused]] AZ::u32 attrib, [[maybe_unused]] AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
|
|
{
|
|
}
|
|
|
|
void EventDataHandler::WriteGUIValuesIntoProperty(size_t /*index*/, EventDataTypeSelectionWidget* selectionWidget, AZStd::shared_ptr<const EventData>& instance, AzToolsFramework::InstanceDataNode* /*node*/)
|
|
{
|
|
const AZ::Uuid& newTypeId = selectionWidget->GetSelectedClass();
|
|
if (azrtti_typeid(instance.get()) == newTypeId)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (newTypeId == AZ::Uuid::CreateNull())
|
|
{
|
|
instance = nullptr;
|
|
}
|
|
else
|
|
{
|
|
AZ::SerializeContext* context;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
const AZ::SerializeContext::ClassData* classData = context->FindClassData(newTypeId);
|
|
instance.reset(static_cast<EMotionFX::EventData*>(classData->m_factory->Create(classData->m_name)));
|
|
|
|
// Deduplicate the event data
|
|
instance = GetEMotionFX().GetEventManager()->FindEventData(instance);
|
|
}
|
|
|
|
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestRefresh, AzToolsFramework::Refresh_EntireTree);
|
|
}
|
|
|
|
bool EventDataHandler::ReadValuesIntoGUI(size_t /*index*/, EventDataTypeSelectionWidget* selectionWidget, const AZStd::shared_ptr<const EventData>& instance, AzToolsFramework::InstanceDataNode* /*node*/)
|
|
{
|
|
if (instance)
|
|
{
|
|
selectionWidget->SetSelectedClass(azrtti_typeid(instance.get()));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} // namespace EMotionFX
|
|
#include <Source/Editor/PropertyWidgets/moc_EventDataHandler.cpp>
|