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/GraphCanvas/Code/Source/Components/Nodes/General/GeneralSlotLayoutComponent.cpp

819 lines
26 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 <functional>
#include <QGraphicsItem>
#include <QGraphicsLayoutItem>
#include <QGraphicsScene>
#include <QGraphicsWidget>
#include <QPainter>
#include <AzCore/RTTI/TypeInfo.h>
#include <Components/Nodes/General/GeneralSlotLayoutComponent.h>
#include <Components/Nodes/General/GeneralNodeFrameComponent.h>
#include <GraphCanvas/Components/GeometryBus.h>
#include <GraphCanvas/Components/Nodes/NodeLayoutBus.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Editor/GraphCanvasProfiler.h>
#include <GraphCanvas/tools.h>
namespace GraphCanvas
{
///////////////////////////////
// GeneralSlotLayoutComponent
///////////////////////////////
void GeneralSlotLayoutComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<SlotGroupConfiguration>()
->Version(1)
->Field("LayoutOrder", &SlotGroupConfiguration::m_layoutOrder)
;
serializeContext->Class<GeneralSlotLayoutComponent, AZ::Component>()
->Version(2)
->Field("EnableDividers", &GeneralSlotLayoutComponent::m_enableDividers)
->Field("ConfigurationMap", &GeneralSlotLayoutComponent::m_slotGroupConfigurations)
;
}
}
GeneralSlotLayoutComponent::GeneralSlotLayoutComponent()
: m_enableDividers(false)
{
}
GeneralSlotLayoutComponent::~GeneralSlotLayoutComponent()
{
}
void GeneralSlotLayoutComponent::Init()
{
m_nodeSlotsUi = aznew GeneralSlotLayoutGraphicsWidget(*this);
// Default ordering of the slots determined by the SlotGroupConfiguration value.
// Values are displayed lowest first to highest last.
//
// This needs to be done using emplace and in init to deal with serialization(serialization will not step on any values
// already in this map, so they all need to be added after the deserialization step has occurred)
m_slotGroupConfigurations.emplace(SlotGroups::ExecutionGroup, SlotGroupConfiguration(0));
m_slotGroupConfigurations.emplace(SlotGroups::PropertyGroup, SlotGroupConfiguration(1));
m_slotGroupConfigurations.emplace(SlotGroups::VariableReferenceGroup, SlotGroupConfiguration(2));
m_slotGroupConfigurations.emplace(SlotGroups::DataGroup, SlotGroupConfiguration(3));
m_slotGroupConfigurations.emplace(SlotGroups::VariableSourceGroup, SlotGroupConfiguration(4));
}
void GeneralSlotLayoutComponent::Activate()
{
if (m_nodeSlotsUi)
{
m_nodeSlotsUi->Activate();
}
}
void GeneralSlotLayoutComponent::Deactivate()
{
if (m_nodeSlotsUi)
{
m_nodeSlotsUi->Deactivate();
}
}
QGraphicsWidget* GeneralSlotLayoutComponent::GetGraphicsWidget()
{
return m_nodeSlotsUi;
}
////////////////////////////////////
// GeneralSlotLayoutGraphicsWidget
////////////////////////////////////
////////////////////////
// LayoutDividerWidget
////////////////////////
GeneralSlotLayoutGraphicsWidget::LayoutDividerWidget::LayoutDividerWidget(QGraphicsItem* parent)
: QGraphicsWidget(parent)
{
setAutoFillBackground(true);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setContentsMargins(0, 0, 0, 0);
}
void GeneralSlotLayoutGraphicsWidget::LayoutDividerWidget::UpdateStyle(const Styling::StyleHelper& styleHelper)
{
prepareGeometryChange();
qreal border = AZStd::max(1., styleHelper.GetAttribute(Styling::Attribute::BorderWidth, 0.));
QColor dividerColor = styleHelper.GetColor(Styling::Attribute::BorderColor);
QPalette widgetPalette = palette();
widgetPalette.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::Window, dividerColor);
setPalette(widgetPalette);
setMinimumHeight(border);
setPreferredHeight(border);
setMaximumHeight(border);
updateGeometry();
update();
}
//////////////////////////
// LinearSlotGroupLayout
//////////////////////////
GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::LinearSlotGroupWidget(QGraphicsItem* parent)
: QGraphicsWidget(parent)
, m_inputs(nullptr)
, m_outputs(nullptr)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_inputs = new QGraphicsLinearLayout(Qt::Vertical);
m_inputs->setContentsMargins(0, 0, 0, 0);
m_inputs->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
{
QGraphicsWidget* spacer = new QGraphicsWidget();
spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
spacer->setContentsMargins(0, 0, 0, 0);
spacer->setPreferredSize(0, 0);
m_inputs->addItem(spacer);
}
m_outputs = new QGraphicsLinearLayout(Qt::Vertical);
m_outputs->setContentsMargins(0, 0, 0, 0);
m_outputs->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
{
QGraphicsWidget* spacer = new QGraphicsWidget();
spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
spacer->setContentsMargins(0, 0, 0, 0);
spacer->setPreferredSize(0, 0);
m_outputs->addItem(spacer);
}
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout(Qt::Horizontal);
setLayout(layout);
layout->setInstantInvalidatePropagation(true);
// Creating the actual display
// <input><spacer><output>
layout->addItem(m_inputs);
m_horizontalSpacer = new QGraphicsWidget();
m_horizontalSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_horizontalSpacer->setContentsMargins(0, 0, 0, 0);
m_horizontalSpacer->setPreferredSize(0, 0);
layout->addItem(m_horizontalSpacer);
layout->addItem(m_outputs);
layout->setAlignment(m_outputs, Qt::AlignRight);
}
void GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::DisplaySlot(const AZ::EntityId& slotId)
{
ConnectionType connectionType = ConnectionType::CT_Invalid;
SlotRequestBus::EventResult(connectionType, slotId, &SlotRequests::GetConnectionType);
int layoutOrder = 0;
SlotLayoutInfo slotInfo(slotId);
if (connectionType == CT_Input)
{
SlotUINotificationBus::MultiHandler::BusConnect(slotId);
m_inputSlotSet.insert(slotId);
layoutOrder = LayoutSlot(m_inputs, m_inputSlots, slotInfo);
}
else if (connectionType == CT_Output)
{
SlotUINotificationBus::MultiHandler::BusConnect(slotId);
m_outputSlotSet.insert(slotId);
LayoutSlot(m_outputs, m_outputSlots, slotInfo);
}
else
{
AZ_Warning("GraphCanvas", false, "Invalid Connection Type for slot. Cannot add to Node Layout");
}
}
void GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::RemoveSlot(const AZ::EntityId& slotId)
{
ConnectionType connectionType = ConnectionType::CT_Invalid;
SlotRequestBus::EventResult(connectionType, slotId, &SlotRequests::GetConnectionType);
QGraphicsLayoutItem* layoutItem = GetLayoutItem(slotId);
if (layoutItem)
{
SlotUINotificationBus::MultiHandler::BusDisconnect(slotId);
if (scene())
{
scene()->removeItem(layoutItem->graphicsItem());
}
if (connectionType == CT_Input)
{
m_inputSlotSet.erase(slotId);
m_inputs->removeItem(layoutItem);
for (unsigned int i = 0; i < m_inputSlots.size(); ++i)
{
if (m_inputSlots[i].m_slotId == slotId)
{
m_inputSlots.erase(m_inputSlots.begin() + i);
break;
}
}
}
else if (connectionType == CT_Output)
{
m_outputSlotSet.erase(slotId);
m_outputs->removeItem(layoutItem);
for (unsigned int i = 0; i < m_outputSlots.size(); ++i)
{
if (m_outputSlots[i].m_slotId == slotId)
{
m_outputSlots.erase(m_outputSlots.begin() + i);
break;
}
}
}
}
}
const AZStd::vector< SlotLayoutInfo >& GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::GetInputSlots() const
{
return m_inputSlots;
}
const AZStd::vector< SlotLayoutInfo >& GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::GetOutputSlots() const
{
return m_outputSlots;
}
bool GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::IsEmpty() const
{
// 1 because there is a spacer in each of the layouts that we need to account for.
return m_inputs->count() == 1 && m_outputs->count() == 1;
}
void GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::UpdateStyle(const Styling::StyleHelper& styleHelper)
{
prepareGeometryChange();
qreal spacing = styleHelper.GetAttribute(Styling::Attribute::Spacing, 0);
qreal margin = styleHelper.GetAttribute(Styling::Attribute::Margin, 0);
setContentsMargins(margin, margin, margin, margin);
for (QGraphicsLinearLayout* internalLayout : { m_inputs, m_outputs })
{
internalLayout->setSpacing(spacing);
internalLayout->invalidate();
internalLayout->updateGeometry();
}
updateGeometry();
update();
}
void GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::OnSlotLayoutPriorityChanged(int layoutPriority)
{
const SlotId* slotId = SlotUINotificationBus::GetCurrentBusId();
if (slotId == nullptr)
{
return;
}
AZStd::vector< SlotLayoutInfo >* layoutVector = nullptr;
QGraphicsLinearLayout* layoutElement = nullptr;
if (m_inputSlotSet.count((*slotId)) > 0)
{
layoutVector = &m_inputSlots;
layoutElement = m_inputs;
}
else if (m_outputSlotSet.count((*slotId)) > 0)
{
layoutVector = &m_outputSlots;
layoutElement = m_outputs;
}
if (layoutVector == nullptr || layoutElement == nullptr)
{
return;
}
for (auto layoutIter = layoutVector->begin(); layoutIter != layoutVector->end(); ++layoutIter)
{
if (layoutIter->m_slotId == (*slotId))
{
SlotLayoutInfo info = (*layoutIter);
info.m_priority = layoutPriority;
layoutVector->erase(layoutIter);
QGraphicsLayoutItem* layoutItem = GetLayoutItem(info.m_slotId);
layoutElement->removeItem(layoutItem);
LayoutSlot(layoutElement, (*layoutVector), info);
break;
}
}
}
int GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::LayoutSlot(QGraphicsLinearLayout* layout, AZStd::vector<SlotLayoutInfo>& slotList, const SlotLayoutInfo& slotInfo)
{
bool inserted = false;
int i = 0;
auto listIter = slotList.begin();
while (listIter != slotList.end())
{
if (listIter->m_priority < slotInfo.m_priority)
{
inserted = true;
slotList.insert(listIter, slotInfo);
break;
}
++i;
++listIter;
}
if (!inserted)
{
slotList.insert(slotList.end(), slotInfo);
}
QGraphicsLayoutItem* layoutItem = GetLayoutItem(slotInfo.m_slotId);
if (layoutItem)
{
layout->insertItem(i, layoutItem);
layout->setAlignment(layoutItem, Qt::AlignTop);
SlotRequestBus::Event(slotInfo.m_slotId, &SlotRequests::SetDisplayOrdering, i);
}
return i;
}
QGraphicsLayoutItem* GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget::GetLayoutItem(const AZ::EntityId& slotId) const
{
QGraphicsLayoutItem* layoutItem = nullptr;
VisualRequestBus::EventResult(layoutItem, slotId, &VisualRequests::AsGraphicsLayoutItem);
AZ_Assert(layoutItem, "Slot must return a GraphicsLayoutItem.");
return layoutItem;
}
////////////////////////////////////
// GeneralSlotLayoutGraphicsWidget
////////////////////////////////////
GeneralSlotLayoutGraphicsWidget::GeneralSlotLayoutGraphicsWidget(GeneralSlotLayoutComponent& nodeSlots)
: m_nodeSlots(nodeSlots)
, m_entityId(nodeSlots.GetEntityId())
, m_addedToScene(false)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
setGraphicsItem(this);
setAcceptHoverEvents(false);
setFlag(ItemIsMovable, false);
setContentsMargins(0, 0, 0, 0);
setData(GraphicsItemName, QStringLiteral("Slots/%1").arg(static_cast<AZ::u64>(GetEntityId()), 16, 16, QChar('0')));
m_groupLayout = new QGraphicsLinearLayout(Qt::Vertical);
m_groupLayout->setSpacing(0);
m_groupLayout->setInstantInvalidatePropagation(true);
setLayout(m_groupLayout);
}
GeneralSlotLayoutGraphicsWidget::~GeneralSlotLayoutGraphicsWidget()
{
// Because I'm allowing for re-use of widgets. There's no guarantee which widgets
// will have a valid parent. So we want to clear our display, then delete everything
// that we own.
ClearLayout();
for (LayoutDividerWidget* divider : m_dividers)
{
delete divider;
}
for (auto& mapPair : m_slotGroups)
{
delete mapPair.second;
}
}
void GeneralSlotLayoutGraphicsWidget::Activate()
{
SlotLayoutRequestBus::Handler::BusConnect(GetEntityId());
NodeNotificationBus::Handler::BusConnect(GetEntityId());
NodeSlotsRequestBus::Handler::BusConnect(GetEntityId());
StyleNotificationBus::Handler::BusConnect(GetEntityId());
SceneMemberNotificationBus::Handler::BusConnect(GetEntityId());
}
void GeneralSlotLayoutGraphicsWidget::OnNodeActivated()
{
ActivateSlots();
UpdateLayout();
}
void GeneralSlotLayoutGraphicsWidget::Deactivate()
{
ClearLayout();
SceneMemberNotificationBus::Handler::BusDisconnect();
StyleNotificationBus::Handler::BusDisconnect();
NodeSlotsRequestBus::Handler::BusDisconnect();
NodeNotificationBus::Handler::BusDisconnect();
SlotLayoutRequestBus::Handler::BusDisconnect();
}
void GeneralSlotLayoutGraphicsWidget::OnSlotAddedToNode(const AZ::EntityId& slotId)
{
bool needsUpate = DisplaySlot(slotId);
if (needsUpate)
{
UpdateLayout();
}
}
void GeneralSlotLayoutGraphicsWidget::OnSlotRemovedFromNode(const AZ::EntityId& slotId)
{
bool needsUpdate = RemoveSlot(slotId);
if (needsUpdate)
{
UpdateLayout();
}
}
QGraphicsLayoutItem* GeneralSlotLayoutGraphicsWidget::GetGraphicsLayoutItem()
{
return this;
}
void GeneralSlotLayoutGraphicsWidget::OnSceneSet(const AZ::EntityId& /*sceneId*/)
{
m_addedToScene = true;
UpdateLayout();
}
void GeneralSlotLayoutGraphicsWidget::SetDividersEnabled(bool enabled)
{
m_nodeSlots.m_enableDividers = enabled;
UpdateLayout();
}
void GeneralSlotLayoutGraphicsWidget::ConfigureSlotGroup(SlotGroup group, SlotGroupConfiguration configuration)
{
if (group != SlotGroups::Invalid)
{
m_nodeSlots.m_slotGroupConfigurations[group] = configuration;
UpdateLayout();
}
}
int GeneralSlotLayoutGraphicsWidget::GetSlotGroupDisplayOrder(SlotGroup group) const
{
AZStd::set<SlotGroup, SlotGroupConfigurationComparator> slotOrdering(SlotGroupConfigurationComparator(&m_nodeSlots.m_slotGroupConfigurations));
for (auto& mapPair : m_slotGroups)
{
if (!mapPair.second->IsEmpty())
{
const SlotGroupConfiguration& configuration = m_nodeSlots.m_slotGroupConfigurations[mapPair.first];
if (configuration.m_visible)
{
slotOrdering.insert(mapPair.first);
}
}
}
int counter = 1;
for (const SlotGroup& slotGroup : slotOrdering)
{
if (slotGroup == group)
{
return counter;
}
++counter;
}
return -1;
}
bool GeneralSlotLayoutGraphicsWidget::IsSlotGroupVisible(SlotGroup group) const
{
bool isVisible = false;
if (group != SlotGroups::Invalid)
{
SlotGroupConfiguration& slotConfiguration = m_nodeSlots.m_slotGroupConfigurations[group];
isVisible = slotConfiguration.m_visible;
}
return isVisible;
}
void GeneralSlotLayoutGraphicsWidget::SetSlotGroupVisible(SlotGroup group, bool visible)
{
if (group != SlotGroups::Invalid)
{
SlotGroupConfiguration& slotConfiguration = m_nodeSlots.m_slotGroupConfigurations[group];
if (slotConfiguration.m_visible != visible)
{
slotConfiguration.m_visible = visible;
UpdateLayout();
}
}
}
void GeneralSlotLayoutGraphicsWidget::ClearSlotGroup(SlotGroup group)
{
if (group != SlotGroups::Invalid)
{
LinearSlotGroupWidget* slotGroupWidget = FindCreateSlotGroupWidget(group);
if (slotGroupWidget)
{
AZStd::vector< SlotLayoutInfo > inputSlots = slotGroupWidget->GetInputSlots();
for (const SlotLayoutInfo& inputSlot : inputSlots)
{
NodeRequestBus::Event(GetEntityId(), &NodeRequests::RemoveSlot, inputSlot.m_slotId);
}
AZStd::vector< SlotLayoutInfo > outputSlots = slotGroupWidget->GetOutputSlots();
for (const SlotLayoutInfo& outputSlot : outputSlots)
{
NodeRequestBus::Event(GetEntityId(), &NodeRequests::RemoveSlot, outputSlot.m_slotId);
}
}
}
}
void GeneralSlotLayoutGraphicsWidget::OnStyleChanged()
{
UpdateStyles();
update();
}
bool GeneralSlotLayoutGraphicsWidget::DisplaySlot(const AZ::EntityId& slotId)
{
bool needsUpdate = false;
SlotGroup slotGroup = SlotGroups::Invalid;
SlotRequestBus::EventResult(slotGroup, slotId, &SlotRequests::GetSlotGroup);
LinearSlotGroupWidget* groupWidget = FindCreateSlotGroupWidget(slotGroup);
if (groupWidget)
{
needsUpdate = groupWidget->IsEmpty();
groupWidget->DisplaySlot(slotId);
}
return needsUpdate;
}
bool GeneralSlotLayoutGraphicsWidget::RemoveSlot(const AZ::EntityId& slotId)
{
bool needsUpdate = false;
SlotGroup slotGroup = SlotGroups::Invalid;
SlotRequestBus::EventResult(slotGroup, slotId, &SlotRequests::GetSlotGroup);
LinearSlotGroupWidget* groupWidget = FindCreateSlotGroupWidget(slotGroup);
if (groupWidget)
{
groupWidget->RemoveSlot(slotId);
needsUpdate = groupWidget->IsEmpty();
}
return needsUpdate;
}
void GeneralSlotLayoutGraphicsWidget::ActivateSlots()
{
AZStd::vector<AZ::EntityId> slotIds;
NodeRequestBus::EventResult(slotIds, m_nodeSlots.GetEntityId(), &NodeRequests::GetSlotIds);
for (const AZ::EntityId& slotId : slotIds)
{
AZ::Entity* slot = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(slot, &AZ::ComponentApplicationRequests::FindEntity, slotId);
AZ_Assert(slot, "A Slot (ID: %s) of Node (ID: %s) has no Entity!", slotId.ToString().data(), m_nodeSlots.GetEntityId().ToString().data());
DisplaySlot(slotId);
}
}
void GeneralSlotLayoutGraphicsWidget::ClearLayout()
{
// Clear out our previous configurations
while (m_groupLayout->count() > 0)
{
m_groupLayout->removeAt(m_groupLayout->count() - 1);
}
}
void GeneralSlotLayoutGraphicsWidget::UpdateLayout()
{
if (!m_addedToScene)
{
return;
}
ClearLayout();
prepareGeometryChange();
AZStd::set<SlotGroup, SlotGroupConfigurationComparator> slotOrdering(SlotGroupConfigurationComparator(&m_nodeSlots.m_slotGroupConfigurations));
for (auto& mapPair : m_slotGroups)
{
if (!mapPair.second->IsEmpty())
{
const SlotGroupConfiguration& configuration = m_nodeSlots.m_slotGroupConfigurations[mapPair.first];
if (configuration.m_visible)
{
slotOrdering.insert(mapPair.first);
}
else
{
// Fun with SceneFilter's.
// If an object with a scene filter is removed from the scene
// That scene filter gets destroyed or invalidated in some way.
//
// This means if we were to ever remove a data slot from the scene
// and add it back on, we need to re-hook up everything.
auto groupIter = m_slotGroups.find(mapPair.first);
if (groupIter != m_slotGroups.end())
{
if (groupIter->second->scene() != nullptr)
{
groupIter->second->scene()->removeItem(groupIter->second);
}
}
}
}
}
for (auto& divider : m_dividers)
{
if (divider->isVisible())
{
divider->setVisible(false);
}
}
int dividerCount = 0;
bool needsDivider = false;
for (const SlotGroup& slotGroup : slotOrdering)
{
if (needsDivider)
{
needsDivider = false;
LayoutDividerWidget* dividerWidget = FindCreateDividerWidget(dividerCount);
++dividerCount;
m_groupLayout->addItem(dividerWidget);
dividerWidget->setVisible(true);
}
auto groupIter = m_slotGroups.find(slotGroup);
if (groupIter != m_slotGroups.end())
{
needsDivider = m_nodeSlots.m_enableDividers;
m_groupLayout->addItem(groupIter->second);
}
}
RefreshDisplay();
NodeUIRequestBus::Event(GetEntityId(), &NodeUIRequests::AdjustSize);
}
void GeneralSlotLayoutGraphicsWidget::UpdateStyles()
{
m_styleHelper.SetStyle(GetEntityId(), Styling::Elements::GeneralSlotLayout);
prepareGeometryChange();
qreal margin = m_styleHelper.GetAttribute(Styling::Attribute::Margin, 0.0);
m_groupLayout->setContentsMargins(margin, margin, margin, margin);
m_groupLayout->setSpacing(m_styleHelper.GetAttribute(Styling::Attribute::Spacing, 0.0));
for (LayoutDividerWidget* divider : m_dividers)
{
divider->UpdateStyle(m_styleHelper);
}
for (auto& mapPair : m_slotGroups)
{
mapPair.second->UpdateStyle(m_styleHelper);
}
RefreshDisplay();
}
void GeneralSlotLayoutGraphicsWidget::RefreshDisplay()
{
updateGeometry();
update();
}
GeneralSlotLayoutGraphicsWidget::LinearSlotGroupWidget* GeneralSlotLayoutGraphicsWidget::FindCreateSlotGroupWidget(SlotGroup slotType)
{
AZ_Warning("GraphCanvas", slotType != SlotGroups::Invalid, "Trying to Create a Slot Group for an Invalid slot group");
LinearSlotGroupWidget* retVal = nullptr;
if (slotType != SlotGroups::Invalid)
{
auto mapIter = m_slotGroups.find(slotType);
if (mapIter != m_slotGroups.end())
{
retVal = mapIter->second;
}
else
{
auto configurationIter = m_nodeSlots.m_slotGroupConfigurations.find(slotType);
if (configurationIter == m_nodeSlots.m_slotGroupConfigurations.end())
{
SlotGroupConfiguration groupConfiguration;
groupConfiguration.m_layoutOrder = static_cast<int>(m_nodeSlots.m_slotGroupConfigurations.size());
m_nodeSlots.m_slotGroupConfigurations[slotType] = groupConfiguration;
}
retVal = aznew LinearSlotGroupWidget(this);
retVal->UpdateStyle(m_styleHelper);
m_slotGroups[slotType] = retVal;
}
}
return retVal;
}
GeneralSlotLayoutGraphicsWidget::LayoutDividerWidget* GeneralSlotLayoutGraphicsWidget::FindCreateDividerWidget(int index)
{
AZ_Error("GraphCanvas", index <= m_dividers.size(), "Invalid Divider Creation flow. Jumped the line in divider indexing.");
LayoutDividerWidget* retVal = nullptr;
while (index >= m_dividers.size())
{
// Create and configure a new divider
LayoutDividerWidget* divider = aznew LayoutDividerWidget(this);
divider->UpdateStyle(m_styleHelper);
m_dividers.push_back(divider);
}
retVal = m_dividers[index];
return retVal;
}
}