123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- /*
- * 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
- *
- */
- // AZ
- #include <AzCore/IO/Path/Path.h>
- #include <AzCore/Math/Color.h>
- #include <AzCore/Math/Vector2.h>
- #include <AzCore/Math/Vector3.h>
- #include <AzCore/Math/Vector4.h>
- #include <AzCore/RTTI/BehaviorContext.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzCore/Serialization/Json/RegistrationContext.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- // Graph Model
- #include <GraphModel/Model/Connection.h>
- #include <GraphModel/Model/Graph.h>
- #include <GraphModel/Model/GraphContext.h>
- #include <GraphModel/Model/Node.h>
- #include <GraphModel/Model/Slot.h>
- namespace GraphModel
- {
- void SlotIdData::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
- if (serializeContext)
- {
- serializeContext->Class<SlotIdData>()
- ->Version(0)
- ->Field("m_name", &SlotIdData::m_name)
- ->Field("m_subId", &SlotIdData::m_subId)
- ;
- }
- }
- SlotIdData::SlotIdData(const SlotName& name)
- : m_name(name)
- {
- }
- SlotIdData::SlotIdData(const SlotName& name, SlotSubId subId)
- : m_name(name)
- , m_subId(subId)
- {
- }
- bool SlotIdData::IsValid() const
- {
- return !m_name.empty() && (m_subId >= 0);
- }
- bool SlotIdData::operator==(const SlotIdData& rhs) const
- {
- return (m_name == rhs.m_name) && (m_subId == rhs.m_subId);
- }
- bool SlotIdData::operator!=(const SlotIdData& rhs) const
- {
- return (m_name != rhs.m_name) || (m_subId != rhs.m_subId);
- }
- bool SlotIdData::operator<(const SlotIdData& rhs) const
- {
- if (m_name < rhs.m_name)
- {
- return true;
- }
- if (m_name == rhs.m_name)
- {
- return m_subId < rhs.m_subId;
- }
- return false;
- }
- bool SlotIdData::operator>(const SlotIdData& rhs) const
- {
- if (m_name > rhs.m_name)
- {
- return true;
- }
- if (m_name == rhs.m_name)
- {
- return m_subId > rhs.m_subId;
- }
- return false;
- }
- AZStd::size_t SlotIdData::GetHash() const
- {
- AZStd::size_t result = 0;
- AZStd::hash_combine(result, m_name);
- AZStd::hash_combine(result, m_subId);
- return result;
- }
- /////////////////////////////////////////////////////////
- // SlotDefinition
- SlotDefinitionPtr SlotDefinition::CreateInputData(
- AZStd::string_view name,
- AZStd::string_view displayName,
- DataTypePtr dataType,
- AZStd::any defaultValue,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- const AZStd::vector<AZStd::string>& enumValues,
- bool visibleOnNode,
- bool editableOnNode)
- {
- return CreateInputData(
- name,
- displayName,
- DataTypeList{ dataType },
- defaultValue,
- description,
- extendableSlotConfiguration,
- enumValues,
- visibleOnNode,
- editableOnNode);
- }
- SlotDefinitionPtr SlotDefinition::CreateInputData(
- AZStd::string_view name,
- AZStd::string_view displayName,
- DataTypeList supportedDataTypes,
- AZStd::any defaultValue,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- const AZStd::vector<AZStd::string>& enumValues,
- bool visibleOnNode,
- bool editableOnNode)
- {
- AZStd::shared_ptr<SlotDefinition> slotDefinition = AZStd::make_shared<SlotDefinition>();
- slotDefinition->m_slotDirection = SlotDirection::Input;
- slotDefinition->m_slotType = SlotType::Data;
- slotDefinition->m_name = name;
- slotDefinition->m_displayName = displayName;
- slotDefinition->m_supportedDataTypes = supportedDataTypes;
- slotDefinition->m_defaultValue = defaultValue;
- slotDefinition->m_description = description;
- slotDefinition->m_enumValues = enumValues;
- slotDefinition->m_visibleOnNode = visibleOnNode;
- slotDefinition->m_editableOnNode = editableOnNode;
- HandleExtendableSlotRegistration(slotDefinition, extendableSlotConfiguration);
- return slotDefinition;
- }
- SlotDefinitionPtr SlotDefinition::CreateOutputData(
- AZStd::string_view name,
- AZStd::string_view displayName,
- DataTypePtr dataType,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- const AZStd::vector<AZStd::string>& enumValues,
- bool visibleOnNode,
- bool editableOnNode)
- {
- AZStd::shared_ptr<SlotDefinition> slotDefinition = AZStd::make_shared<SlotDefinition>();
- slotDefinition->m_slotDirection = SlotDirection::Output;
- slotDefinition->m_slotType = SlotType::Data;
- slotDefinition->m_name = name;
- slotDefinition->m_displayName = displayName;
- slotDefinition->m_supportedDataTypes = { dataType };
- slotDefinition->m_defaultValue = dataType->GetDefaultValue();
- slotDefinition->m_enumValues = enumValues;
- slotDefinition->m_description = description;
- slotDefinition->m_visibleOnNode = visibleOnNode;
- slotDefinition->m_editableOnNode = editableOnNode;
- HandleExtendableSlotRegistration(slotDefinition, extendableSlotConfiguration);
- return slotDefinition;
- }
- SlotDefinitionPtr SlotDefinition::CreateInputEvent(
- AZStd::string_view name,
- AZStd::string_view displayName,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- bool visibleOnNode,
- bool editableOnNode)
- {
- AZStd::shared_ptr<SlotDefinition> slotDefinition = AZStd::make_shared<SlotDefinition>();
- slotDefinition->m_slotDirection = SlotDirection::Input;
- slotDefinition->m_slotType = SlotType::Event;
- slotDefinition->m_name = name;
- slotDefinition->m_displayName = displayName;
- slotDefinition->m_description = description;
- slotDefinition->m_visibleOnNode = visibleOnNode;
- slotDefinition->m_editableOnNode = editableOnNode;
- HandleExtendableSlotRegistration(slotDefinition, extendableSlotConfiguration);
- return slotDefinition;
- }
- SlotDefinitionPtr SlotDefinition::CreateOutputEvent(
- AZStd::string_view name,
- AZStd::string_view displayName,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- bool visibleOnNode,
- bool editableOnNode)
- {
- AZStd::shared_ptr<SlotDefinition> slotDefinition = AZStd::make_shared<SlotDefinition>();
- slotDefinition->m_slotDirection = SlotDirection::Output;
- slotDefinition->m_slotType = SlotType::Event;
- slotDefinition->m_name = name;
- slotDefinition->m_displayName = displayName;
- slotDefinition->m_description = description;
- slotDefinition->m_visibleOnNode = visibleOnNode;
- slotDefinition->m_editableOnNode = editableOnNode;
- HandleExtendableSlotRegistration(slotDefinition, extendableSlotConfiguration);
- return slotDefinition;
- }
- SlotDefinitionPtr SlotDefinition::CreateProperty(
- AZStd::string_view name,
- AZStd::string_view displayName,
- DataTypePtr dataType,
- AZStd::any defaultValue,
- AZStd::string_view description,
- ExtendableSlotConfiguration* extendableSlotConfiguration,
- const AZStd::vector<AZStd::string>& enumValues,
- bool visibleOnNode,
- bool editableOnNode)
- {
- AZStd::shared_ptr<SlotDefinition> slotDefinition = AZStd::make_shared<SlotDefinition>();
- slotDefinition->m_slotDirection = SlotDirection::Input;
- slotDefinition->m_slotType = SlotType::Property;
- slotDefinition->m_name = name;
- slotDefinition->m_displayName = displayName;
- slotDefinition->m_supportedDataTypes = { dataType };
- slotDefinition->m_defaultValue = defaultValue;
- slotDefinition->m_enumValues = enumValues;
- slotDefinition->m_description = description;
- slotDefinition->m_visibleOnNode = visibleOnNode;
- slotDefinition->m_editableOnNode = editableOnNode;
- HandleExtendableSlotRegistration(slotDefinition, extendableSlotConfiguration);
- return slotDefinition;
- }
- void SlotDefinition::HandleExtendableSlotRegistration(
- AZStd::shared_ptr<SlotDefinition> slotDefinition, ExtendableSlotConfiguration* extendableSlotConfiguration)
- {
- if (extendableSlotConfiguration)
- {
- slotDefinition->m_extendableSlotConfiguration = *extendableSlotConfiguration;
- if (slotDefinition->m_extendableSlotConfiguration.m_minimumSlots > slotDefinition->m_extendableSlotConfiguration.m_maximumSlots)
- {
- AZ_Assert(false, "Invalid extendable slot configuration for %s, minimum slots greater than maximum slots", slotDefinition->GetName().c_str());
- return;
- }
- slotDefinition->m_extendableSlotConfiguration.m_isValid = true;
- }
- }
- SlotDirection SlotDefinition::GetSlotDirection() const
- {
- return m_slotDirection;
- }
- SlotType SlotDefinition::GetSlotType() const
- {
- return m_slotType;
- }
- bool SlotDefinition::SupportsValues() const
- {
- return (GetSlotType() == SlotType::Data && GetSlotDirection() == SlotDirection::Input) ||
- (GetSlotType() == SlotType::Property);
- }
- bool SlotDefinition::SupportsDataTypes() const
- {
- return GetSlotType() == SlotType::Data || GetSlotType() == SlotType::Property;
- }
- bool SlotDefinition::SupportsConnections() const
- {
- return GetSlotType() == SlotType::Data || GetSlotType() == SlotType::Event;
- }
- bool SlotDefinition::IsVisibleOnNode() const
- {
- return m_visibleOnNode;
- }
- bool SlotDefinition::IsEditableOnNode() const
- {
- return m_editableOnNode;
- }
- bool SlotDefinition::SupportsExtendability() const
- {
- return m_extendableSlotConfiguration.m_isValid;
- }
- bool SlotDefinition::Is(SlotDirection slotDirection, SlotType slotType) const
- {
- return GetSlotDirection() == slotDirection && GetSlotType() == slotType;
- }
- const DataTypeList& SlotDefinition::GetSupportedDataTypes() const
- {
- return m_supportedDataTypes;
- }
- const SlotName& SlotDefinition::GetName() const
- {
- return m_name;
- }
- const AZStd::string& SlotDefinition::GetDisplayName() const
- {
- return m_displayName;
- }
- const AZStd::string& SlotDefinition::GetDescription() const
- {
- return m_description;
- }
- AZStd::any SlotDefinition::GetDefaultValue() const
- {
- return m_defaultValue;
- }
- const AZStd::vector<AZStd::string>& SlotDefinition::GetEnumValues() const
- {
- return m_enumValues;
- }
- const int SlotDefinition::GetMinimumSlots() const
- {
- return m_extendableSlotConfiguration.m_minimumSlots;
- }
- const int SlotDefinition::GetMaximumSlots() const
- {
- return m_extendableSlotConfiguration.m_maximumSlots;
- }
- const AZStd::string& SlotDefinition::GetExtensionLabel() const
- {
- return m_extendableSlotConfiguration.m_addButtonLabel;
- }
- const AZStd::string& SlotDefinition::GetExtensionTooltip() const
- {
- return m_extendableSlotConfiguration.m_addButtonTooltip;
- }
- /////////////////////////////////////////////////////////
- // Slot
- void Slot::Reflect(AZ::ReflectContext* context)
- {
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<Slot>()
- ->Version(1)
- ->Field("m_value", &Slot::m_value)
- ->Field("m_subId", &Slot::m_subId)
- ;
- }
- }
- Slot::Slot(GraphPtr graph, SlotDefinitionPtr slotDefinition, SlotSubId subId)
- : GraphElement(graph)
- , m_slotDefinition(slotDefinition)
- , m_subId(subId)
- {
- // The m_value must be initialized with an object of the appropriate type, or GetValue() will fail the first time its called.
- SetValue(m_slotDefinition->GetDefaultValue());
- }
- void Slot::PostLoadSetup(GraphPtr graph, SlotDefinitionPtr slotDefinition)
- {
- AZ_Assert(nullptr == GetGraph(), "This slot is not freshly loaded");
- m_graph = graph;
- m_slotDefinition = slotDefinition;
- ClearCachedData();
- if (SupportsValues())
- {
- AZ_Error(
- GetGraph()->GetSystemName(),
- GetDataType(),
- "Possible data corruption. Slot [%s] does not match any supported data type.",
- GetDisplayName().c_str());
- }
- }
- NodePtr Slot::GetParentNode() const
- {
- AZStd::scoped_lock lock(m_parentNodeMutex);
- if (m_parentNodeDirty)
- {
- m_parentNodeDirty = false;
- for (auto nodePair : GetGraph()->GetNodes())
- {
- if (nodePair.second->Contains(shared_from_this()))
- {
- m_parentNode = nodePair.second;
- return m_parentNode;
- }
- }
- }
- return m_parentNode;
- }
- AZStd::any Slot::GetValue() const
- {
- return !m_value.empty() ? m_value : GetDefaultValue();
- }
- const Slot::ConnectionList& Slot::GetConnections() const
- {
- AZStd::scoped_lock lock(m_connectionsMutex);
- if (m_connectionsDirty)
- {
- m_connectionsDirty = false;
- m_connections.clear();
- m_connections.reserve(GetGraph()->GetConnectionCount());
- for (const auto& connection : GetGraph()->GetConnections())
- {
- const auto& sourceSlot = connection->GetSourceSlot();
- const auto& targetSlot = connection->GetTargetSlot();
- if (targetSlot.get() == this || sourceSlot.get() == this)
- {
- m_connections.emplace_back(connection);
- }
- }
- }
- return m_connections;
- }
- SlotDefinitionPtr Slot::GetDefinition() const
- {
- return m_slotDefinition;
- }
- bool Slot::Is(SlotDirection slotDirection, SlotType slotType) const
- {
- return m_slotDefinition->Is(slotDirection, slotType);
- }
- SlotDirection Slot::GetSlotDirection() const
- {
- return m_slotDefinition->GetSlotDirection();
- }
- SlotType Slot::GetSlotType() const
- {
- return m_slotDefinition->GetSlotType();
- }
- bool Slot::SupportsValues() const
- {
- return m_slotDefinition->SupportsValues();
- }
- bool Slot::SupportsDataTypes() const
- {
- return m_slotDefinition->SupportsDataTypes();
- }
- bool Slot::SupportsConnections() const
- {
- return m_slotDefinition->SupportsConnections();
- }
- bool Slot::SupportsExtendability() const
- {
- return m_slotDefinition->SupportsExtendability();
- }
- bool Slot::IsVisibleOnNode() const
- {
- return m_slotDefinition->IsVisibleOnNode();
- }
- bool Slot::IsEditableOnNode() const
- {
- return m_slotDefinition->IsEditableOnNode();
- }
- const SlotName& Slot::GetName() const
- {
- return m_slotDefinition->GetName();
- }
- const AZStd::string& Slot::GetDisplayName() const
- {
- return m_slotDefinition->GetDisplayName();
- }
- const AZStd::string& Slot::GetDescription() const
- {
- return m_slotDefinition->GetDescription();
- }
- const AZStd::vector<AZStd::string>& Slot::GetEnumValues() const
- {
- return m_slotDefinition->GetEnumValues();
- }
- AZStd::any Slot::GetDefaultValue() const
- {
- return m_slotDefinition->GetDefaultValue();
- }
- const DataTypeList& Slot::GetSupportedDataTypes() const
- {
- return m_slotDefinition->GetSupportedDataTypes();
- }
- bool Slot::IsSupportedDataType(DataTypePtr dataType) const
- {
- for (DataTypePtr supportedDataType : GetSupportedDataTypes())
- {
- if (supportedDataType == dataType)
- {
- return true;
- }
- }
- return false;
- }
- const int Slot::GetMinimumSlots() const
- {
- return m_slotDefinition->GetMinimumSlots();
- }
- const int Slot::GetMaximumSlots() const
- {
- return m_slotDefinition->GetMaximumSlots();
- }
- SlotId Slot::GetSlotId() const
- {
- return SlotId(GetName(), m_subId);
- }
- SlotSubId Slot::GetSlotSubId() const
- {
- return m_subId;
- }
- DataTypePtr Slot::GetDataType() const
- {
- // Because some slots support multiple data types search for the one corresponding to the value
- return GetDataTypeForValue(GetValue());
- }
- DataTypePtr Slot::GetDefaultDataType() const
- {
- return GetDataTypeForValue(GetDefaultValue());
- }
- void Slot::SetValue(const AZStd::any& value)
- {
- if (SupportsValues())
- {
- #if defined(AZ_ENABLE_TRACING)
- DataTypePtr dataTypeRequested = GetDataTypeForValue(value);
- AssertWithTypeInfo(IsSupportedDataType(dataTypeRequested), dataTypeRequested, "Slot::SetValue Requested with the wrong type");
- #endif
- m_value = value;
- }
- }
- #if defined(AZ_ENABLE_TRACING)
- void Slot::AssertWithTypeInfo(bool expression, DataTypePtr dataTypeRequested, const char* message) const
- {
- DataTypePtr dataType = GetDataType();
- AZ_Assert(expression, "%s Slot %s (Current DataType=['%s', '%s', %s]. Requested DataType=['%s', '%s', %s]). Current Value TypeId=%s.",
- message,
- GetDisplayName().c_str(),
- !dataType ? "nullptr" : dataType->GetDisplayName().c_str(),
- !dataType ? "nullptr" : dataType->GetCppName().c_str(),
- !dataType ? "nullptr" : dataType->GetTypeUuidString().c_str(),
- !dataTypeRequested ? "nullptr" : dataTypeRequested->GetDisplayName().c_str(),
- !dataTypeRequested ? "nullptr" : dataTypeRequested->GetCppName().c_str(),
- !dataTypeRequested ? "nullptr" : dataTypeRequested->GetTypeUuidString().c_str(),
- GetValue().type().ToString<AZStd::string>().c_str()
- );
- }
- #endif // AZ_ENABLE_TRACING
- DataTypePtr Slot::GetDataTypeForTypeId(const AZ::Uuid& typeId) const
- {
- // Search for and return the first data type that supports the input type ID
- for (DataTypePtr dataType : GetSupportedDataTypes())
- {
- // If this slot does not support input values but has registered data types then the first data type will be returned.
- if (!SupportsDataTypes() || dataType->IsSupportedType(typeId))
- {
- return dataType;
- }
- }
- return {};
- }
- DataTypePtr Slot::GetDataTypeForValue(const AZStd::any& value) const
- {
- // Search for and return the first data type that supports the input value
- for (DataTypePtr dataType : GetSupportedDataTypes())
- {
- // If this slot does not support input values but has registered data types then the first data type will be returned.
- if (!SupportsValues() || dataType->IsSupportedValue(value))
- {
- return dataType;
- }
- }
- return {};
- }
- void Slot::ClearCachedData()
- {
- {
- AZStd::scoped_lock lock(m_parentNodeMutex);
- m_parentNodeDirty = true;
- m_parentNode = {};
- }
- {
- AZStd::scoped_lock lock(m_connectionsMutex);
- m_connectionsDirty = true;
- m_connections.clear();
- }
- }
- } // namespace GraphModel
|