Removes ComponentPalette/CategoriesList and ComponentPalette/ComponentDataModel from Code/Editor/Plugins/ComponentEntityEditorPlugin
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
-97
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* 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 "CategoriesList.h"
|
||||
|
||||
ComponentCategoryList::ComponentCategoryList(QWidget* parent /*= nullptr*/)
|
||||
: QTreeWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ComponentCategoryList::Init()
|
||||
{
|
||||
setColumnCount(1);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setDragDropMode(QAbstractItemView::DragDropMode::DragOnly);
|
||||
setDragEnabled(true);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setAllColumnsShowFocus(true);
|
||||
setStyleSheet("QTreeWidget { selection-background-color: rgba(255,255,255,0.2); }");
|
||||
|
||||
QStringList headers;
|
||||
headers << tr("Categories");
|
||||
setHeaderLabels(headers);
|
||||
|
||||
const QString parentCategoryIconPath = QString("Icons/PropertyEditor/Browse_on.png");
|
||||
const QString categoryIconPath = QString("Icons/PropertyEditor/Browse.png");
|
||||
|
||||
QTreeWidgetItem* allCategory = new QTreeWidgetItem(this);
|
||||
allCategory->setText(0, "All");
|
||||
allCategory->setIcon(0, QIcon(categoryIconPath));
|
||||
|
||||
// Need this briefly to collect the list of available categories.
|
||||
ComponentDataModel dataModel(this);
|
||||
for (const auto& cat : dataModel.GetCategories())
|
||||
{
|
||||
QString categoryString = QString(cat.c_str());
|
||||
QStringList categories = categoryString.split('/', Qt::SkipEmptyParts);
|
||||
|
||||
QTreeWidgetItem* parent = nullptr;
|
||||
QTreeWidgetItem* categoryWidget = nullptr;
|
||||
|
||||
for (const auto& categoryName : categories)
|
||||
{
|
||||
if (parent)
|
||||
{
|
||||
categoryWidget = new QTreeWidgetItem(parent);
|
||||
categoryWidget->setIcon(0, QIcon(categoryIconPath));
|
||||
|
||||
// Store the full category path in a user role because we'll need it to locate the actual category
|
||||
categoryWidget->setData(0, Qt::UserRole, QVariant::fromValue(categoryString));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto existingCategory = findItems(categoryName, Qt::MatchExactly);
|
||||
if (existingCategory.empty())
|
||||
{
|
||||
categoryWidget = new QTreeWidgetItem(this);
|
||||
categoryWidget->setIcon(0, QIcon(parentCategoryIconPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryWidget = static_cast<QTreeWidgetItem*>(existingCategory.first());
|
||||
categoryWidget->setIcon(0, QIcon(parentCategoryIconPath));
|
||||
}
|
||||
}
|
||||
|
||||
parent = categoryWidget;
|
||||
|
||||
categoryWidget->setText(0, categoryName);
|
||||
}
|
||||
}
|
||||
|
||||
expandAll();
|
||||
|
||||
connect(this, &QTreeWidget::itemClicked, this, &ComponentCategoryList::OnItemClicked);
|
||||
}
|
||||
|
||||
void ComponentCategoryList::OnItemClicked(QTreeWidgetItem* item, int /*column*/)
|
||||
{
|
||||
QVariant userData = item->data(0, Qt::UserRole);
|
||||
if (userData.isValid())
|
||||
{
|
||||
// Send in the full category path, not just the child category name
|
||||
emit OnCategoryChange(userData.value<QString>().toStdString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
emit OnCategoryChange(item->text(0).toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#include <UI/ComponentPalette/moc_CategoriesList.cpp>
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ComponentDataModel.h"
|
||||
#include <QTreeWidget>
|
||||
#endif
|
||||
|
||||
//! ComponentCategoryList
|
||||
//! Provides a list of all reflected categories that users can select for quick
|
||||
//! filtering the filtered component list.
|
||||
class ComponentCategoryList : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(ComponentCategoryList, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit ComponentCategoryList(QWidget* parent = nullptr);
|
||||
|
||||
void Init();
|
||||
|
||||
Q_SIGNALS:
|
||||
void OnCategoryChange(const char* category);
|
||||
|
||||
protected:
|
||||
|
||||
// Will emit OnCategoryChange signal
|
||||
void OnItemClicked(QTreeWidgetItem* item, int column);
|
||||
|
||||
};
|
||||
-547
@@ -1,547 +0,0 @@
|
||||
/*
|
||||
* 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 "ComponentDataModel.h"
|
||||
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Commands/EntityStateCommand.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/API/EntityCompositionRequestBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
|
||||
#include <Editor/IEditor.h>
|
||||
#include <Editor/Viewport.h>
|
||||
#include <Editor/ViewManager.h>
|
||||
#include <CryCommon/MathConversion.h>
|
||||
|
||||
#include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h>
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
namespace
|
||||
{
|
||||
// This is a helper function that given an object that derives from QAbstractItemModel,
|
||||
// it will request the model's "ClassDataRole" class data for an entry and use that
|
||||
// information to create a new entity with the selected components.
|
||||
AZ::EntityId CreateEntityFromSelection(const QModelIndexList& selection, QAbstractItemModel* model)
|
||||
{
|
||||
AZ::Vector3 position = AZ::Vector3::CreateZero();
|
||||
CViewport *view = GetIEditor()->GetViewManager()->GetGameViewport();
|
||||
int width, height;
|
||||
view->GetDimensions(&width, &height);
|
||||
position = LYVec3ToAZVec3(view->ViewToWorld(QPoint(width / 2, height / 2)));
|
||||
|
||||
AZ::EntityId newEntityId;
|
||||
EBUS_EVENT_RESULT(newEntityId, AzToolsFramework::EditorRequests::Bus, CreateNewEntityAtPosition, position, AZ::EntityId());
|
||||
if (newEntityId.IsValid())
|
||||
{
|
||||
// Add all the selected components.
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto index : selection)
|
||||
{
|
||||
// We only need to consider the first column, it's important that the data() function that
|
||||
// returns ComponentDataModel::ClassDataRole also does so for the first column.
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariant classDataVariant = model->data(index, ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequestBus::Broadcast(&AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, AzToolsFramework::EntityIdList{ newEntityId }, componentsToAdd);
|
||||
|
||||
return newEntityId;
|
||||
}
|
||||
|
||||
return AZ::EntityId();
|
||||
}
|
||||
}
|
||||
|
||||
namespace ComponentDataUtilities
|
||||
{
|
||||
// This is a helper function to add the specified components to the selected entities, it relies on the provided
|
||||
// QAbstractItemModel to determine the appropriate ClassData to use to create the components (given that some widgets
|
||||
// may provide proxy models that alter the order).
|
||||
void AddComponentsToSelectedEntities(const QModelIndexList& selectedComponents, QAbstractItemModel* model)
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
if (selectedEntities.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add all the selected components.
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto index : selectedComponents)
|
||||
{
|
||||
// We only need to consider the first column, it's important that the data() function that
|
||||
// returns ComponentDataModel::ClassDataRole also does so for the first column.
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariant classDataVariant = model->data(index, ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequestBus::Broadcast(&AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, selectedEntities, componentsToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ComponentDataModel
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ComponentDataModel::ComponentDataModel(QObject* parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
|
||||
|
||||
serializeContext->EnumerateDerived<AZ::Component>([this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
|
||||
{
|
||||
bool allowed = false;
|
||||
bool hidden = false;
|
||||
AZStd::string category = "Miscellaneous";
|
||||
|
||||
if (classData->m_editData)
|
||||
{
|
||||
for (const AZ::Edit::ElementData& element : classData->m_editData->m_elements)
|
||||
{
|
||||
if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentIcons[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
}
|
||||
|
||||
for (const AZ::Edit::AttributePair& attribPair : element.m_attributes)
|
||||
{
|
||||
if (attribPair.first == AZ::Edit::Attributes::AppearsInAddComponentMenu)
|
||||
{
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<AZ::Crc32>*>(attribPair.second))
|
||||
{
|
||||
if (data->Get(nullptr) == AZ_CRC("Game"))
|
||||
{
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attribPair.first == AZ::Edit::Attributes::AddableByUser)
|
||||
{
|
||||
// skip this component if user is not allowed to add it directly
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<bool>*>(attribPair.second))
|
||||
{
|
||||
if (!data->Get(nullptr))
|
||||
{
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attribPair.first == AZ::Edit::Attributes::Category)
|
||||
{
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<const char*>*>(attribPair.second))
|
||||
{
|
||||
category = data->Get(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allowed && !hidden)
|
||||
{
|
||||
m_componentList.push_back(classData);
|
||||
m_componentMap[category].push_back(classData);
|
||||
m_categories.insert(category);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// we'd like viewport events
|
||||
AzQtComponents::DragAndDropEventsBus::Handler::BusConnect(AzQtComponents::DragAndDropContexts::EditorViewport);
|
||||
}
|
||||
|
||||
ComponentDataModel::~ComponentDataModel()
|
||||
{
|
||||
AzQtComponents::DragAndDropEventsBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ComponentDataModel::flags([[maybe_unused]] const QModelIndex &index) const
|
||||
{
|
||||
return Qt::ItemFlags(
|
||||
Qt::ItemIsEnabled |
|
||||
Qt::ItemIsDragEnabled |
|
||||
Qt::ItemIsDropEnabled |
|
||||
Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
const AZ::SerializeContext::ClassData* ComponentDataModel::GetClassData(const QModelIndex& index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_componentList.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_componentList[row];
|
||||
}
|
||||
|
||||
const char* ComponentDataModel::GetCategory(const AZ::SerializeContext::ClassData* classData)
|
||||
{
|
||||
if (classData)
|
||||
{
|
||||
if (auto editorDataElement = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
|
||||
{
|
||||
if (auto categoryAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::Category))
|
||||
{
|
||||
if (auto categoryData = azdynamic_cast<AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
|
||||
{
|
||||
const char* result = categoryData->Get(nullptr);
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
QModelIndex ComponentDataModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
if (row >= rowCount(parent) || column >= columnCount(parent))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(row, column, (void*)(m_componentList[row]));
|
||||
}
|
||||
|
||||
QModelIndex ComponentDataModel::parent([[maybe_unused]] const QModelIndex &child) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int ComponentDataModel::rowCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return static_cast<int>(m_componentList.size());
|
||||
}
|
||||
|
||||
int ComponentDataModel::columnCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return ColumnIndex::Count;
|
||||
}
|
||||
|
||||
QVariant ComponentDataModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = m_componentList[index.row()];
|
||||
if (!classData)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case ClassDataRole:
|
||||
if (index.column() == 0) // Only get data for one column
|
||||
{
|
||||
return QVariant::fromValue<void*>(reinterpret_cast<void*>(const_cast<AZ::SerializeContext::ClassData*>(classData)));
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
if (index.column() == ColumnIndex::Name)
|
||||
{
|
||||
return QVariant(classData->m_editData->m_name);
|
||||
}
|
||||
else
|
||||
if (index.column() == ColumnIndex::Category)
|
||||
{
|
||||
if (auto editorDataElement = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
|
||||
{
|
||||
if (auto categoryAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::Category))
|
||||
{
|
||||
if (auto categoryData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
|
||||
{
|
||||
return QVariant(categoryData->Get(nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
return QVariant(classData->m_editData->m_description);
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
if (index.column() == ColumnIndex::Icon)
|
||||
{
|
||||
auto iconIterator = m_componentIcons.find(classData->m_typeId);
|
||||
if (iconIterator != m_componentIcons.end())
|
||||
{
|
||||
return iconIterator->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QMimeData* ComponentDataModel::mimeData(const QModelIndexList& indices) const
|
||||
{
|
||||
QModelIndexList list;
|
||||
|
||||
// Filter out columns we are not interested in.
|
||||
for (const QModelIndex& index : indices)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
list.push_back(index);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> sortedList;
|
||||
for (QModelIndex index : list)
|
||||
{
|
||||
QVariant classDataVariant = index.data(ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
sortedList.push_back(classData);
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData* mimeData = nullptr;
|
||||
if (!sortedList.empty())
|
||||
{
|
||||
mimeData = AzToolsFramework::ComponentTypeMimeData::Create(sortedList).release();
|
||||
}
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool ComponentDataModel::CanAcceptDragAndDropEvent(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) const
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzQtComponents;
|
||||
|
||||
// if a listener with a higher priority already claimed this event, do not touch it.
|
||||
if ((!event) || (event->isAccepted()) || (!event->mimeData()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ViewportDragContext* contextVP = azrtti_cast<ViewportDragContext*>(&context);
|
||||
if (!contextVP)
|
||||
{
|
||||
// not a viewport event. This is for some other GUI such as the main window itself.
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> componentClassDataList;
|
||||
return AzToolsFramework::ComponentTypeMimeData::Get(event->mimeData(), componentClassDataList);
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragEnter(QDragEnterEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
if (CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
// opportunities to show special highlights, or ghosted entities or previews here.
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragMove(QDragMoveEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
if (CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
// opportunities to update special highlights, or ghosted entities or previews here.
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragLeave(QDragLeaveEvent* /*event*/)
|
||||
{
|
||||
// opportunities to remove ghosted entities or previews here.
|
||||
}
|
||||
|
||||
void ComponentDataModel::Drop(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzQtComponents;
|
||||
|
||||
// ALWAYS CHECK - you are not the only one connected to this bus, and someone else may have already
|
||||
// handled the event or accepted the drop - it might not contain types relevant to you.
|
||||
// you still get informed about the drop event in case you did some stuff in your gui and need to clean it up.
|
||||
if (!CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// note that the above call already checks all the pointers such as event, or whether context is a VP context, mimetype, etc
|
||||
ViewportDragContext* contextVP = azrtti_cast<ViewportDragContext*>(&context);
|
||||
|
||||
// we don't get given this action by Qt unless we already returned accepted from one of the other ones (such as drag move of drag enter)
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
|
||||
AzToolsFramework::ScopedUndoBatch undo("Create entity from components");
|
||||
const AZStd::string name = AZStd::string::format("Entity%d", GetIEditor()->GetObjectManager()->GetObjectCount());
|
||||
|
||||
AZ::Entity* newEntity = aznew AZ::Entity(name.c_str());
|
||||
if (newEntity)
|
||||
{
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(&AzToolsFramework::EditorEntityContextRequests::AddRequiredComponents, *newEntity);
|
||||
auto* transformComponent = newEntity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldTM(AZ::Transform::CreateTranslation(contextVP->m_hitLocation));
|
||||
}
|
||||
|
||||
// Add the entity to the editor context, which activates it and creates the sandbox object.
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(&AzToolsFramework::EditorEntityContextRequests::AddEditorEntity, newEntity);
|
||||
|
||||
// Prepare undo command last so it captures the final state of the entity.
|
||||
AzToolsFramework::EntityCreateCommand* command = aznew AzToolsFramework::EntityCreateCommand(static_cast<AZ::u64>(newEntity->GetId()));
|
||||
command->Capture(newEntity);
|
||||
command->SetParent(undo.GetUndoBatch());
|
||||
|
||||
// Only need to add components to the new entity
|
||||
AzToolsFramework::EntityIdList entities = { newEntity->GetId() };
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> componentClassDataList;
|
||||
AzToolsFramework::ComponentTypeMimeData::Get(event->mimeData(), componentClassDataList);
|
||||
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto classData : componentClassDataList)
|
||||
{
|
||||
if (!classData)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome addedComponentsResult = AZ::Failure(AZStd::string("Failed to call AddComponentsToEntities on EntityCompositionRequestBus"));
|
||||
AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(addedComponentsResult, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, entities, componentsToAdd);
|
||||
|
||||
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::AddDirtyEntity, newEntity->GetId());
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entities);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId ComponentDataProxyModel::NewEntityFromSelection(const QModelIndexList& selection)
|
||||
{
|
||||
return CreateEntityFromSelection(selection, this);
|
||||
}
|
||||
|
||||
AZ::EntityId ComponentDataModel::NewEntityFromSelection(const QModelIndexList& selection)
|
||||
{
|
||||
return CreateEntityFromSelection(selection, this);
|
||||
}
|
||||
|
||||
bool ComponentDataProxyModel::filterAcceptsRow(int sourceRow, [[maybe_unused]] const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (m_selectedCategory.empty() && !filterRegExp().isValid())
|
||||
return true;
|
||||
|
||||
ComponentDataModel* dataModel = static_cast<ComponentDataModel*>(sourceModel());
|
||||
if (sourceRow < 0 || sourceRow >= dataModel->GetComponents().size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::SerializeContext::ClassData* classData = dataModel->GetComponents()[sourceRow];
|
||||
if (!classData)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Category
|
||||
if (!m_selectedCategory.empty())
|
||||
{
|
||||
AZStd::string currentCateogry = ComponentDataModel::GetCategory(classData);
|
||||
|
||||
if (AzFramework::StringFunc::Find(currentCateogry.c_str(), m_selectedCategory.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filterRegExp().isValid())
|
||||
{
|
||||
QString componentName = QString::fromUtf8(classData->m_editData->m_name);
|
||||
return componentName.contains(filterRegExp());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ComponentDataProxyModel::SetSelectedCategory(const AZStd::string& category)
|
||||
{
|
||||
m_selectedCategory = category;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void ComponentDataProxyModel::ClearSelectedCategory()
|
||||
{
|
||||
m_selectedCategory.clear();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
#include "UI/ComponentPalette/moc_ComponentDataModel.cpp"
|
||||
-128
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
#include <AzQtComponents/Buses/DragAndDrop.h>
|
||||
#endif
|
||||
|
||||
namespace ComponentDataUtilities
|
||||
{
|
||||
// Given a list of selected components, use the provided model to get the components to add to any selected entities.
|
||||
void AddComponentsToSelectedEntities(const QModelIndexList& selectedComponents, QAbstractItemModel* model);
|
||||
}
|
||||
|
||||
class CViewport;
|
||||
|
||||
//! ComponentDataModel
|
||||
//! Holds the data required to display components in a table, this includes component name, categories, icons.
|
||||
class ComponentDataModel
|
||||
: public QAbstractTableModel
|
||||
, protected AzQtComponents::DragAndDropEventsBus::Handler // its okay if more than one of these is installed, the first one gets it.
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ComponentDataModel, AZ::SystemAllocator, 0);
|
||||
|
||||
using ComponentClassList = AZStd::vector<const AZ::SerializeContext::ClassData*>;
|
||||
using ComponentCategorySet = AZStd::set<AZStd::string>;
|
||||
using ComponentClassMap = AZStd::unordered_map<AZStd::string, AZStd::vector<const AZ::SerializeContext::ClassData*>>;
|
||||
using ComponentIconMap = AZStd::unordered_map<AZ::Uuid, QIcon>;
|
||||
|
||||
enum ColumnIndex
|
||||
{
|
||||
Icon,
|
||||
Category,
|
||||
Name,
|
||||
Count
|
||||
};
|
||||
|
||||
enum CustomRoles
|
||||
{
|
||||
ClassDataRole = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
ComponentDataModel(QObject* parent = nullptr);
|
||||
~ComponentDataModel() override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||
|
||||
const AZ::SerializeContext::ClassData* GetClassData(const QModelIndex&) const;
|
||||
|
||||
AZ::EntityId NewEntityFromSelection(const QModelIndexList& selection);
|
||||
|
||||
static const char* GetCategory(const AZ::SerializeContext::ClassData* classData);
|
||||
|
||||
ComponentClassList& GetComponents() { return m_componentList; }
|
||||
ComponentCategorySet& GetCategories() { return m_categories; }
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzQtComponents::DragAndDropEventsBus::Handler
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void DragEnter(QDragEnterEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
void DragMove(QDragMoveEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
void DragLeave(QDragLeaveEvent* event) override;
|
||||
void Drop(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
bool CanAcceptDragAndDropEvent(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) const;
|
||||
|
||||
ComponentClassList m_componentList;
|
||||
ComponentClassMap m_componentMap;
|
||||
ComponentIconMap m_componentIcons;
|
||||
ComponentCategorySet m_categories;
|
||||
};
|
||||
|
||||
//! ComponentDataProxyModel
|
||||
//! FilterProxy for the ComponentDataModel is used along with the search criteria to filter the
|
||||
//! list of components based on tags and/or selected category.
|
||||
class ComponentDataProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ComponentDataProxyModel, AZ::SystemAllocator, 0);
|
||||
|
||||
ComponentDataProxyModel(QObject* parent = nullptr)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{}
|
||||
|
||||
// Creates a new entity and adds the selected components to it.
|
||||
// It is specialized here to ensure it uses the correct indices according to the sorted data.
|
||||
AZ::EntityId NewEntityFromSelection(const QModelIndexList& selection);
|
||||
|
||||
// Filters rows according to the specifed tags and/or selected category
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
// Set the category to filter by.
|
||||
void SetSelectedCategory(const AZStd::string& category);
|
||||
void ClearSelectedCategory();
|
||||
|
||||
protected:
|
||||
|
||||
AZStd::string m_selectedCategory;
|
||||
};
|
||||
-4
@@ -20,10 +20,6 @@ set(FILES
|
||||
UI/QComponentEntityEditorOutlinerWindow.cpp
|
||||
UI/AssetCatalogModel.h
|
||||
UI/AssetCatalogModel.cpp
|
||||
UI/ComponentPalette/CategoriesList.h
|
||||
UI/ComponentPalette/CategoriesList.cpp
|
||||
UI/ComponentPalette/ComponentDataModel.h
|
||||
UI/ComponentPalette/ComponentDataModel.cpp
|
||||
UI/ComponentPalette/ComponentPaletteSettings.h
|
||||
UI/Outliner/OutlinerDisplayOptionsMenu.h
|
||||
UI/Outliner/OutlinerDisplayOptionsMenu.cpp
|
||||
|
||||
Reference in New Issue
Block a user