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.
347 lines
11 KiB
C++
347 lines
11 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 <Components/Slots/Extender/ExtenderSlotComponent.h>
|
|
|
|
#include <Components/Slots/Extender/ExtenderSlotLayoutComponent.h>
|
|
#include <Components/Slots/SlotConnectionFilterComponent.h>
|
|
#include <Components/StylingComponent.h>
|
|
#include <GraphCanvas/Components/Connections/ConnectionFilters/ConnectionFilters.h>
|
|
|
|
namespace GraphCanvas
|
|
{
|
|
//////////////////////////
|
|
// ExtenderSlotComponent
|
|
//////////////////////////
|
|
|
|
void ExtenderSlotComponent::Reflect(AZ::ReflectContext* reflectContext)
|
|
{
|
|
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
|
|
if (serializeContext)
|
|
{
|
|
serializeContext->Class<ExtenderSlotComponent, SlotComponent>()
|
|
->Version(SaveVersion::Current)
|
|
->Field("ExtensionId", &ExtenderSlotComponent::m_extenderId)
|
|
;
|
|
}
|
|
}
|
|
|
|
AZ::Entity* ExtenderSlotComponent::CreateExtenderSlot(const AZ::EntityId& nodeId, const ExtenderSlotConfiguration& extenderSlotConfiguration)
|
|
{
|
|
AZ::Entity* entity = SlotComponent::CreateCoreSlotEntity();
|
|
|
|
ExtenderSlotComponent* extenderSlot = aznew ExtenderSlotComponent(extenderSlotConfiguration);
|
|
|
|
if (!entity->AddComponent(extenderSlot))
|
|
{
|
|
AZ_Error("GraphCanvas", false, "Failed to add ExtenderSlotComponent to entity.");
|
|
delete extenderSlot;
|
|
delete entity;
|
|
return nullptr;
|
|
}
|
|
|
|
entity->CreateComponent<ExtenderSlotLayoutComponent>();
|
|
entity->CreateComponent<StylingComponent>(Styling::Elements::ExtenderSlot, nodeId, "");
|
|
|
|
SlotConnectionFilterComponent* connectionFilter = entity->CreateComponent<SlotConnectionFilterComponent>();
|
|
|
|
SlotTypeFilter* slotTypeFilter = aznew SlotTypeFilter(ConnectionFilterType::Include);
|
|
slotTypeFilter->AddSlotType(SlotTypes::DataSlot);
|
|
|
|
connectionFilter->AddFilter(slotTypeFilter);
|
|
|
|
ConnectionTypeFilter* connectionTypeFilter = aznew ConnectionTypeFilter(ConnectionFilterType::Include);
|
|
|
|
switch (extenderSlot->GetConnectionType())
|
|
{
|
|
case ConnectionType::CT_Input:
|
|
connectionTypeFilter->AddConnectionType(CT_Output);
|
|
break;
|
|
case ConnectionType::CT_Output:
|
|
connectionTypeFilter->AddConnectionType(CT_Input);
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
|
|
connectionFilter->AddFilter(connectionTypeFilter);
|
|
|
|
return entity;
|
|
}
|
|
|
|
ExtenderSlotComponent::ExtenderSlotComponent()
|
|
: SlotComponent(SlotTypes::ExtenderSlot)
|
|
{
|
|
if (m_slotConfiguration.m_slotGroup == SlotGroups::Invalid)
|
|
{
|
|
m_slotConfiguration.m_slotGroup = SlotGroups::ExtenderGroup;
|
|
}
|
|
}
|
|
|
|
ExtenderSlotComponent::ExtenderSlotComponent(const ExtenderSlotConfiguration& extenderSlotConfiguration)
|
|
: SlotComponent(SlotTypes::ExtenderSlot, extenderSlotConfiguration)
|
|
, m_extenderId(extenderSlotConfiguration.m_extenderId)
|
|
{
|
|
}
|
|
|
|
ExtenderSlotComponent::~ExtenderSlotComponent()
|
|
{
|
|
}
|
|
|
|
void ExtenderSlotComponent::Init()
|
|
{
|
|
SlotComponent::Init();
|
|
}
|
|
|
|
void ExtenderSlotComponent::Activate()
|
|
{
|
|
SlotComponent::Activate();
|
|
|
|
ExtenderSlotRequestBus::Handler::BusConnect(GetEntityId());
|
|
}
|
|
|
|
void ExtenderSlotComponent::Deactivate()
|
|
{
|
|
SlotComponent::Deactivate();
|
|
|
|
ExtenderSlotRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void ExtenderSlotComponent::OnSceneMemberAboutToSerialize(GraphSerialization&)
|
|
{
|
|
}
|
|
|
|
void ExtenderSlotComponent::AddConnectionId(const AZ::EntityId& connectionId, const Endpoint& endpoint)
|
|
{
|
|
AZ_UNUSED(connectionId);
|
|
AZ_UNUSED(endpoint);
|
|
}
|
|
|
|
void ExtenderSlotComponent::RemoveConnectionId(const AZ::EntityId& connectionId, const Endpoint& endpoint)
|
|
{
|
|
AZ_UNUSED(connectionId);
|
|
AZ_UNUSED(endpoint);
|
|
}
|
|
|
|
void ExtenderSlotComponent::SetNode(const AZ::EntityId& nodeId)
|
|
{
|
|
SlotComponent::SetNode(nodeId);
|
|
}
|
|
|
|
SlotConfiguration* ExtenderSlotComponent::CloneSlotConfiguration() const
|
|
{
|
|
ExtenderSlotConfiguration* slotConfiguration = aznew ExtenderSlotConfiguration();
|
|
|
|
slotConfiguration->m_extenderId = m_extenderId;
|
|
|
|
PopulateSlotConfiguration((*slotConfiguration));
|
|
|
|
return slotConfiguration;
|
|
}
|
|
|
|
int ExtenderSlotComponent::GetLayoutPriority() const
|
|
{
|
|
return std::numeric_limits<int>::min();
|
|
}
|
|
|
|
void ExtenderSlotComponent::SetLayoutPriority(int layoutPriority)
|
|
{
|
|
// Extenders should not have their layout priority changed
|
|
AZ_UNUSED(layoutPriority);
|
|
}
|
|
|
|
void ExtenderSlotComponent::OnMoveFinalized(bool isValidConnection)
|
|
{
|
|
ConnectionNotificationBus::Handler::BusDisconnect();
|
|
|
|
m_proposedSlot = false;
|
|
m_trackedConnectionId.SetInvalid();
|
|
|
|
if (m_createdSlot.IsValid())
|
|
{
|
|
if (isValidConnection)
|
|
{
|
|
NodeId nodeId = GetNode();
|
|
|
|
GraphId graphId;
|
|
SceneMemberRequestBus::EventResult(graphId, GetNode(), &SceneMemberRequests::GetScene);
|
|
|
|
GraphModelRequestBus::Event(graphId, &GraphModelRequests::FinalizeExtension, nodeId, m_extenderId);
|
|
|
|
m_createdSlot.SetInvalid();
|
|
}
|
|
else
|
|
{
|
|
EraseSlot();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExtenderSlotComponent::OnSourceSlotIdChanged(const SlotId& oldSlotId, const SlotId& /*newSlotId*/)
|
|
{
|
|
if (m_proposedSlot)
|
|
{
|
|
if (oldSlotId == m_createdSlot)
|
|
{
|
|
CleanupProposedSlot();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExtenderSlotComponent::OnTargetSlotIdChanged(const SlotId& oldSlotId, const SlotId& /*newSlotId*/)
|
|
{
|
|
if (m_proposedSlot)
|
|
{
|
|
if (oldSlotId == m_createdSlot)
|
|
{
|
|
CleanupProposedSlot();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExtenderSlotComponent::TriggerExtension()
|
|
{
|
|
// Don't need to track anything. Just create the slot then ignore whatever the return is.
|
|
ConstructSlot(GraphModelRequests::ExtensionRequestReason::UserRequest);
|
|
|
|
if (m_createdSlot.IsValid())
|
|
{
|
|
const bool isValidSlot = true;
|
|
OnMoveFinalized(isValidSlot);
|
|
|
|
GraphId graphId;
|
|
SceneMemberRequestBus::EventResult(graphId, GetNode(), &SceneMemberRequests::GetScene);
|
|
|
|
GraphModelRequestBus::Event(graphId, &GraphModelRequests::RequestUndoPoint);
|
|
}
|
|
|
|
m_createdSlot.SetInvalid();
|
|
}
|
|
|
|
Endpoint ExtenderSlotComponent::ExtendForConnectionProposal(const ConnectionId& connectionId, const Endpoint& endpoint)
|
|
{
|
|
// Don't want to extend if we are already extended.
|
|
if (m_createdSlot.IsValid())
|
|
{
|
|
return Endpoint();
|
|
}
|
|
|
|
ConstructSlot(GraphModelRequests::ExtensionRequestReason::ConnectionProposal);
|
|
|
|
if (!m_createdSlot.IsValid())
|
|
{
|
|
return Endpoint();
|
|
}
|
|
|
|
bool isValidConnection = false;
|
|
SlotRequestBus::EventResult(isValidConnection, m_createdSlot, &SlotRequests::CanCreateConnectionTo, endpoint);
|
|
|
|
if (!isValidConnection)
|
|
{
|
|
EraseSlot();
|
|
return Endpoint();
|
|
}
|
|
|
|
m_proposedSlot = true;
|
|
|
|
m_trackedConnectionId = connectionId;
|
|
ConnectionNotificationBus::Handler::BusConnect(connectionId);
|
|
|
|
return Endpoint(GetNode(), m_createdSlot);
|
|
}
|
|
|
|
void ExtenderSlotComponent::OnFinalizeDisplay()
|
|
{
|
|
}
|
|
|
|
void ExtenderSlotComponent::ConstructSlot(GraphModelRequests::ExtensionRequestReason reason)
|
|
{
|
|
if (!m_createdSlot.IsValid())
|
|
{
|
|
NodeId nodeId = GetNode();
|
|
|
|
GraphId graphId;
|
|
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
|
|
|
|
{
|
|
ScopedGraphUndoBlocker undoBlocker(graphId);
|
|
GraphModelRequestBus::EventResult(m_createdSlot, graphId, &GraphModelRequests::RequestExtension, nodeId, m_extenderId, reason);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExtenderSlotComponent::EraseSlot()
|
|
{
|
|
if (m_createdSlot.IsValid())
|
|
{
|
|
NodeId nodeId = GetNode();
|
|
|
|
GraphId graphId;
|
|
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
|
|
|
|
{
|
|
ScopedGraphUndoBlocker undoBlocker(graphId);
|
|
GraphModelRequestBus::Event(graphId, &GraphModelRequests::RemoveSlot, Endpoint(nodeId, m_createdSlot));
|
|
GraphModelRequestBus::Event(graphId, &GraphModelRequests::ExtensionCancelled, nodeId, m_extenderId);
|
|
}
|
|
|
|
m_createdSlot.SetInvalid();
|
|
}
|
|
}
|
|
|
|
void ExtenderSlotComponent::CleanupProposedSlot()
|
|
{
|
|
ConnectionNotificationBus::Handler::BusDisconnect();
|
|
|
|
m_proposedSlot = false;
|
|
m_trackedConnectionId.SetInvalid();
|
|
|
|
EraseSlot();
|
|
}
|
|
|
|
AZ::Entity* ExtenderSlotComponent::ConstructConnectionEntity(const Endpoint& sourceEndpoint, const Endpoint& targetEndpoint, bool createModelConnection)
|
|
{
|
|
ConstructSlot(GraphModelRequests::ExtensionRequestReason::Internal);
|
|
|
|
if (m_createdSlot.IsValid())
|
|
{
|
|
Endpoint otherEndpoint;
|
|
|
|
if (GetConnectionType() == CT_Input)
|
|
{
|
|
otherEndpoint = sourceEndpoint;
|
|
}
|
|
else if (GetConnectionType() == CT_Output)
|
|
{
|
|
otherEndpoint = targetEndpoint;
|
|
}
|
|
|
|
if (createModelConnection)
|
|
{
|
|
SlotRequestBus::EventResult(m_trackedConnectionId, m_createdSlot, &SlotRequests::CreateConnectionWithEndpoint, otherEndpoint);
|
|
}
|
|
else
|
|
{
|
|
SlotRequestBus::EventResult(m_trackedConnectionId, m_createdSlot, &SlotRequests::DisplayConnectionWithEndpoint, otherEndpoint);
|
|
}
|
|
|
|
AZ::Entity* connectionEntity = nullptr;
|
|
|
|
if (m_trackedConnectionId.IsValid())
|
|
{
|
|
ConnectionNotificationBus::Handler::BusConnect(m_trackedConnectionId);
|
|
|
|
AZ::ComponentApplicationBus::BroadcastResult(connectionEntity, &AZ::ComponentApplicationRequests::FindEntity, m_trackedConnectionId);
|
|
}
|
|
|
|
return connectionEntity;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
}
|