Files
o3de/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

500 lines
17 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/Data/DataSlotComponent.h>
#include <Components/Connections/ConnectionComponent.h>
#include <Components/Connections/DataConnections/DataConnectionComponent.h>
#include <Components/Slots/Data/DataSlotConnectionPin.h>
#include <Components/Slots/Data/DataSlotLayoutComponent.h>
#include <Components/Slots/SlotConnectionFilterComponent.h>
#include <Components/StylingComponent.h>
#include <GraphCanvas/Components/Connections/ConnectionFilters/ConnectionFilters.h>
#include <GraphCanvas/Components/Connections/ConnectionFilters/DataConnectionFilters.h>
#include <GraphCanvas/Components/StyleBus.h>
namespace GraphCanvas
{
//////////////////////
// DataSlotComponent
//////////////////////
void DataSlotComponent::Reflect(AZ::ReflectContext* reflectContext)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext);
if (serializeContext)
{
serializeContext->Class<DataSlotComponent, SlotComponent>()
->Version(6)
->Field("TypeId", &DataSlotComponent::m_dataTypeId)
->Field("DataSlotType", &DataSlotComponent::m_dataSlotType)
->Field("CanConvertSlotTypes", &DataSlotComponent::m_canConvertSlotTypes)
->Field("ContainedTypeIds", &DataSlotComponent::m_containedTypeIds)
->Field("DataValueType", &DataSlotComponent::m_valueType)
->Field("IsUserSlot", &DataSlotComponent::m_isUserSlot)
;
}
}
AZ::Entity* DataSlotComponent::CreateDataSlot(const AZ::EntityId& nodeId, const DataSlotConfiguration& dataSlotConfiguration)
{
AZ::Entity* entity = SlotComponent::CreateCoreSlotEntity();
DataSlotComponent* dataSlot = aznew DataSlotComponent(dataSlotConfiguration);
if (!entity->AddComponent(dataSlot))
{
delete dataSlot;
delete entity;
return nullptr;
}
entity->CreateComponent<DataSlotLayoutComponent>();
entity->CreateComponent<StylingComponent>(Styling::Elements::DataSlot, 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 (dataSlot->GetConnectionType())
{
case ConnectionType::CT_Input:
connectionTypeFilter->AddConnectionType(CT_Output);
break;
case ConnectionType::CT_Output:
connectionTypeFilter->AddConnectionType(CT_Input);
break;
default:
break;
};
connectionFilter->AddFilter(connectionTypeFilter);
connectionFilter->AddFilter(aznew DataSlotTypeFilter());
return entity;
}
DataSlotComponent::DataSlotComponent()
: SlotComponent(SlotTypes::DataSlot)
, m_canConvertSlotTypes(false)
, m_dataSlotType(DataSlotType::Value)
, m_valueType(DataValueType::Primitive)
, m_dataTypeId(AZ::Uuid::CreateNull())
, m_previousDataSlotType(DataSlotType::Unknown)
, m_isUserSlot(false)
{
if (m_slotConfiguration.m_slotGroup == SlotGroups::Invalid)
{
m_slotConfiguration.m_slotGroup = SlotGroups::DataGroup;
}
}
DataSlotComponent::DataSlotComponent(const DataSlotConfiguration& dataSlotConfiguration)
: SlotComponent(SlotTypes::DataSlot, dataSlotConfiguration)
, m_canConvertSlotTypes(dataSlotConfiguration.m_canConvertTypes)
, m_dataSlotType(dataSlotConfiguration.m_dataSlotType)
, m_valueType(dataSlotConfiguration.m_dataValueType)
, m_dataTypeId(dataSlotConfiguration.m_typeId)
, m_containedTypeIds(dataSlotConfiguration.m_containerTypeIds)
, m_previousDataSlotType(DataSlotType::Unknown)
, m_isUserSlot(dataSlotConfiguration.m_isUserAdded)
{
if (m_slotConfiguration.m_slotGroup == SlotGroups::Invalid)
{
m_slotConfiguration.m_slotGroup = SlotGroups::DataGroup;
}
}
DataSlotComponent::~DataSlotComponent()
{
}
void DataSlotComponent::Init()
{
SlotComponent::Init();
}
void DataSlotComponent::Activate()
{
SlotComponent::Activate();
DataSlotRequestBus::Handler::BusConnect(GetEntityId());
// Will usually happen in a copy/paste scenario
if (m_valueType == DataValueType::Container)
{
SetDataAndContainedTypeIds(m_dataTypeId, m_containedTypeIds, m_valueType);
}
}
void DataSlotComponent::Deactivate()
{
SlotComponent::Deactivate();
DataSlotRequestBus::Handler::BusDisconnect();
}
void DataSlotComponent::DisplayProposedConnection(const AZ::EntityId& connectionId, const Endpoint& endpoint)
{
const bool updateDisplay = false;
RestoreDisplay(updateDisplay);
DataSlotType slotType = DataSlotType::Unknown;
DataSlotRequestBus::EventResult(slotType, endpoint.GetSlotId(), &DataSlotRequests::GetDataSlotType);
m_displayedConnection = connectionId;
m_connections.emplace_back(m_displayedConnection);
m_previousDataSlotType = m_dataSlotType;
bool isDisabled = false;
if (slotType == DataSlotType::Value)
{
m_dataSlotType = DataSlotType::Value;
isDisabled = HasConnections();
}
else if (slotType == DataSlotType::Reference)
{
if (DataSlotUtils::IsValueDataReferenceType(m_dataSlotType) || CanConvertToReference())
{
m_dataSlotType = DataSlotType::Reference;
}
}
if (m_previousDataSlotType != m_dataSlotType)
{
DataSlotNotificationBus::Event(GetEntityId(), &DataSlotNotifications::OnDataSlotTypeChanged, m_dataSlotType);
}
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, isDisabled);
UpdateDisplay();
}
void DataSlotComponent::RemoveProposedConnection(const AZ::EntityId& /*connectionId*/, const Endpoint& /*endpoint*/)
{
RestoreDisplay(true);
}
void DataSlotComponent::AddConnectionId(const AZ::EntityId& connectionId, const Endpoint& endpoint)
{
SlotComponent::AddConnectionId(connectionId, endpoint);
if (m_dataSlotType == DataSlotType::Value)
{
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, true);
}
else if (m_dataSlotType == DataSlotType::Reference)
{
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, false);
}
else
{
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, HasConnections());
}
}
void DataSlotComponent::RemoveConnectionId(const AZ::EntityId& connectionId, const Endpoint& endpoint)
{
SlotComponent::RemoveConnectionId(connectionId, endpoint);
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, HasConnections());
}
void DataSlotComponent::SetNode(const AZ::EntityId& nodeId)
{
SlotComponent::SetNode(nodeId);
}
SlotConfiguration* DataSlotComponent::CloneSlotConfiguration() const
{
DataSlotConfiguration* slotConfiguration = aznew DataSlotConfiguration();
slotConfiguration->m_dataSlotType = GetDataSlotType();
slotConfiguration->m_typeId = GetDataTypeId();
slotConfiguration->m_containerTypeIds = m_containedTypeIds;
slotConfiguration->m_isUserAdded = m_isUserSlot;
PopulateSlotConfiguration((*slotConfiguration));
return slotConfiguration;
}
void DataSlotComponent::UpdateDisplay()
{
DataSlotLayoutRequestBus::Event(GetEntityId(), &DataSlotLayoutRequests::UpdateDisplay);
}
void DataSlotComponent::RestoreDisplay(bool updateDisplay)
{
if (m_previousDataSlotType != DataSlotType::Unknown)
{
bool typeChanged = m_dataSlotType != m_previousDataSlotType;
m_dataSlotType = m_previousDataSlotType;
if (m_displayedConnection.IsValid())
{
for (auto connectionIter = m_connections.begin(); connectionIter != m_connections.end(); ++connectionIter)
{
if (*connectionIter == m_displayedConnection)
{
m_connections.erase(connectionIter);
break;
}
}
}
if (updateDisplay)
{
UpdatePropertyDisplayState();
if (typeChanged)
{
DataSlotNotificationBus::Event(GetEntityId(), &DataSlotNotifications::OnDataSlotTypeChanged, m_dataSlotType);
}
UpdateDisplay();
}
m_previousDataSlotType = DataSlotType::Unknown;
m_displayedConnection.SetInvalid();
}
}
void DataSlotComponent::OnFinalizeDisplay()
{
UpdatePropertyDisplayState();
}
void DataSlotComponent::UpdatePropertyDisplayState()
{
if (m_dataSlotType == DataSlotType::Reference)
{
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, false);
}
else if (DataSlotUtils::IsValueDataSlotType(m_dataSlotType))
{
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, HasConnections());
}
}
bool DataSlotComponent::ConvertToReference()
{
if (CanConvertToReference())
{
AZ::EntityId nodeId = GetNode();
GraphId graphId;
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
{
ScopedGraphUndoBlocker undoBlocker(graphId);
bool convertedToReference = false;
GraphModelRequestBus::EventResult(convertedToReference, graphId, &GraphModelRequests::ConvertSlotToReference, Endpoint(nodeId, GetEntityId()));
if (convertedToReference)
{
m_dataSlotType = DataSlotType::Reference;
DataSlotNotificationBus::Event(GetEntityId(), &DataSlotNotifications::OnDataSlotTypeChanged, m_dataSlotType);
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, false);
}
}
if (m_dataSlotType == DataSlotType::Reference)
{
GraphModelRequestBus::Event(graphId, &GraphModelRequests::RequestUndoPoint);
}
}
return m_dataSlotType == DataSlotType::Reference;
}
bool DataSlotComponent::CanConvertToReference() const
{
bool canToggleReference = false;
if (m_canConvertSlotTypes && DataSlotUtils::IsValueDataSlotType(m_dataSlotType) && !HasConnections())
{
AZ::EntityId nodeId = GetNode();
GraphId graphId;
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
GraphModelRequestBus::EventResult(canToggleReference, graphId, &GraphModelRequests::CanConvertSlotToReference, Endpoint(nodeId, GetEntityId()));
}
return canToggleReference;
}
bool DataSlotComponent::ConvertToValue()
{
if (CanConvertToValue())
{
AZ::EntityId nodeId = GetNode();
GraphId graphId;
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
{
ScopedGraphUndoBlocker undoBlocker(graphId);
bool converted = false;
GraphModelRequestBus::EventResult(converted, graphId, &GraphModelRequests::ConvertSlotToValue, Endpoint(nodeId, GetEntityId()));
if (converted)
{
m_dataSlotType = DataSlotType::Value;
DataSlotNotificationBus::Event(GetEntityId(), &DataSlotNotifications::OnDataSlotTypeChanged, m_dataSlotType);
NodePropertyRequestBus::Event(GetEntityId(), &NodePropertyRequests::SetDisabled, HasConnections());
}
}
if (DataSlotUtils::IsValueDataSlotType(m_dataSlotType))
{
GraphModelRequestBus::Event(graphId, &GraphModelRequests::RequestUndoPoint);
}
}
return DataSlotUtils::IsValueDataSlotType(m_dataSlotType);
}
bool DataSlotComponent::CanConvertToValue() const
{
bool canConvertToValue = false;
if (m_canConvertSlotTypes && m_dataSlotType == DataSlotType::Reference)
{
AZ::EntityId nodeId = GetNode();
GraphId graphId;
SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene);
GraphModelRequestBus::EventResult(canConvertToValue, graphId, &GraphModelRequests::CanConvertSlotToValue, Endpoint(nodeId, GetEntityId()));
}
return canConvertToValue;
}
DataSlotType DataSlotComponent::GetDataSlotType() const
{
return m_dataSlotType;
}
DataValueType DataSlotComponent::GetDataValueType() const
{
return m_valueType;
}
AZ::Uuid DataSlotComponent::GetDataTypeId() const
{
return m_dataTypeId;
}
void DataSlotComponent::SetDataTypeId(AZ::Uuid typeId)
{
if (m_dataTypeId != typeId)
{
m_dataTypeId = typeId;
UpdateDisplay();
}
}
bool DataSlotComponent::IsUserSlot() const
{
return m_isUserSlot;
}
const Styling::StyleHelper* DataSlotComponent::GetDataColorPalette() const
{
AZ::EntityId sceneId;
SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &SceneMemberRequests::GetScene);
EditorId editorId;
SceneRequestBus::EventResult(editorId, sceneId, &SceneRequests::GetEditorId);
const Styling::StyleHelper* stylingHelper = nullptr;
StyleManagerRequestBus::EventResult(stylingHelper, editorId, &StyleManagerRequests::FindDataColorPalette, m_dataTypeId);
return stylingHelper;
}
size_t DataSlotComponent::GetContainedTypesCount() const
{
return m_containedTypeIds.size();
}
AZ::Uuid DataSlotComponent::GetContainedTypeId(size_t index) const
{
return m_containedTypeIds[index];
}
const GraphCanvas::Styling::StyleHelper* DataSlotComponent::GetContainedTypeColorPalette(size_t index) const
{
AZ::Uuid dataTypeId = m_containedTypeIds[index];
AZ::EntityId sceneId;
SceneMemberRequestBus::EventResult(sceneId, GetEntityId(), &SceneMemberRequests::GetScene);
EditorId editorId;
SceneRequestBus::EventResult(editorId, sceneId, &SceneRequests::GetEditorId);
const Styling::StyleHelper* stylingHelper = nullptr;
StyleManagerRequestBus::EventResult(stylingHelper, editorId, &StyleManagerRequests::FindDataColorPalette, dataTypeId);
return stylingHelper;
}
void DataSlotComponent::SetDataAndContainedTypeIds(AZ::Uuid typeId, const AZStd::vector<AZ::Uuid>& typeIds, DataValueType valueType)
{
if (m_dataTypeId != typeId)
{
m_dataTypeId = typeId;
// Handles a weird case with string.
// Since it's a primitive, but is a container of chars.
if (valueType == DataValueType::Primitive)
{
m_containedTypeIds.clear();
}
else
{
m_containedTypeIds = typeIds;
}
m_valueType = valueType;
DataSlotNotificationBus::Event(GetEntityId(), &DataSlotNotifications::OnDisplayTypeChanged, m_dataTypeId, m_containedTypeIds);
UpdatePropertyDisplayState();
}
}
AZ::Entity* DataSlotComponent::ConstructConnectionEntity(const Endpoint& sourceEndpoint, const Endpoint& targetEndpoint, bool createModelConnection)
{
const AZStd::string k_valueConnectionSubStyle = ".varFlow";
const AZStd::string k_referenceConnectionSubStyle = ".referenceFlow";
bool isReference = GetDataSlotType() == DataSlotType::Reference;
// Create this Connection's entity.
return DataConnectionComponent::CreateDataConnection(sourceEndpoint, targetEndpoint, createModelConnection, isReference ? k_referenceConnectionSubStyle : k_valueConnectionSubStyle);
}
}