Merge branch 'main' of https://github.com/aws-lumberyard/o3de into Spawnable/ScriptCanvas/Integration

This commit is contained in:
sconel
2021-05-26 16:45:23 -07:00
407 changed files with 35045 additions and 3306 deletions
@@ -75,7 +75,7 @@ public: \
void ConfigureSlots() override; \
bool RequiresDynamicSlotOrdering() const override; \
bool IsDeprecated() const override; \
{% if deprecationUuid is defined %} NodeConfiguration GetReplacementNodeConfiguration() const override; \
{% if deprecationUuid is defined %} ScriptCanvas::NodeConfiguration GetReplacementNodeConfiguration() const override; \
{% endif %}
using Node::FindDatum; \
{% if Class.attrib['GraphEntryPoint'] is defined %} bool IsEntryPoint() const override { return {%if Class.attrib['GraphEntryPoint'] == "True" %}true{%else%}false{%endif%}; } \
@@ -168,4 +168,4 @@ struct {{ className | replace(' ','') }}Property
{% endfor %}
{% endfor %}
{% endfor %}
@@ -22,6 +22,7 @@
namespace ScriptCanvas
{
class Slot;
struct NodeUpdateSlotReport;
class Connection
: public AZ::Component
@@ -64,6 +65,8 @@ namespace ScriptCanvas
// GraphNotificationBus
void OnNodeRemoved(const ID& nodeId) override;
void UpdateConnectionStatus(NodeUpdateSlotReport& report);
protected:
//-------------------------------------------------------------------------
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -33,7 +33,7 @@ namespace ScriptCanvas
{
if (m_availableIndexes.empty())
{
return -1;
return std::numeric_limits<AZ::u32>::max();
}
return (*m_availableIndexes.begin());
@@ -151,19 +151,22 @@ namespace ScriptCanvas
for (const AZ::BehaviorParameter* behaviorParameter : paramTypes.second)
{
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(behaviorParameter->m_typeId);
if (ScriptCanvas::Data::IsValueType(dataType))
if (behaviorParameter)
{
isValueType = true;
}
else if (ScriptCanvas::Data::IsContainerType(dataType))
{
isContainerType = true;
}
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(behaviorParameter->m_typeId);
if (ScriptCanvas::Data::IsValueType(dataType))
{
isValueType = true;
}
else if (ScriptCanvas::Data::IsContainerType(dataType))
{
isContainerType = true;
}
if (isValueType && isContainerType)
{
break;
if (isValueType && isContainerType)
{
break;
}
}
}
@@ -616,6 +616,34 @@ namespace ScriptCanvas
return false;
}
void Graph::RemoveAllConnections()
{
for (auto connectionEntity : m_graphData.m_connections)
{
if (auto connection = connectionEntity ? AZ::EntityUtils::FindFirstDerivedComponent<Connection>(connectionEntity) : nullptr)
{
if (connection->GetSourceEndpoint().IsValid())
{
EndpointNotificationBus::Event(connection->GetSourceEndpoint(), &EndpointNotifications::OnEndpointDisconnected, connection->GetTargetEndpoint());
}
if (connection->GetTargetEndpoint().IsValid())
{
EndpointNotificationBus::Event(connection->GetTargetEndpoint(), &EndpointNotifications::OnEndpointDisconnected, connection->GetSourceEndpoint());
}
}
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnConnectionRemoved, connectionEntity->GetId());
}
for (auto& connectionRef : m_graphData.m_connections)
{
delete connectionRef;
}
m_graphData.m_connections.clear();
}
bool Graph::RemoveConnection(const AZ::EntityId& connectionId)
{
if (connectionId.IsValid())
@@ -752,7 +780,6 @@ namespace ScriptCanvas
auto* connectionEntity = aznew AZ::Entity("Connection");
connectionEntity->CreateComponent<Connection>(sourceEndpoint, targetEndpoint);
AZ::Entity* nodeEntity{};
AZ::ComponentApplicationBus::BroadcastResult(nodeEntity, &AZ::ComponentApplicationRequests::FindEntity, sourceEndpoint.GetNodeId());
auto node = nodeEntity ? AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity) : nullptr;
@@ -87,6 +87,7 @@ namespace ScriptCanvas
Slot* FindSlot(const Endpoint& endpoint) const override;
bool AddConnection(const AZ::EntityId&) override;
void RemoveAllConnections();
bool RemoveConnection(const AZ::EntityId& connectionId) override;
AZStd::vector<AZ::EntityId> GetConnections() const override;
AZStd::vector<Endpoint> GetConnectedEndpoints(const Endpoint& firstEndpoint) const override;
@@ -53,7 +53,9 @@ namespace ScriptCanvas
template<typename DatumType>
void AddDefaultInputAndOutputTypeSlot(DatumType&& defaultValue);
void AddInputTypeAndOutputTypeSlot(const Data::Type& type);
bool IsDeprecated() const override { return true; }
void OnActivate() override;
void OnInputChanged(const Datum& input, const SlotId& id) override;
void MarkDefaultableInput() override {}
@@ -347,6 +347,11 @@ namespace ScriptCanvas
}
}
void Slot::ClearDynamicGroup()
{
m_dynamicGroup = AZ::Crc32{};
}
void Slot::ConvertToLatentExecutionOut()
{
if (IsExecution() && IsOutput())
@@ -68,6 +68,8 @@ namespace ScriptCanvas
void AddContract(const ContractDescriptor& contractDesc);
void ClearDynamicGroup();
template<typename T>
T* FindContract()
{
@@ -1036,12 +1036,12 @@ namespace ScriptCanvas
if (azrtti_istypeof<ScriptCanvas::Nodes::NodeableNodeOverloaded*>(&node))
{
// todo Add node to these errors
AddError(nullptr, ValidationConstPtr(aznew NotYetImplemented(node.GetEntityId(), AZStd::string::format("NodeableNodeOverloaded doesn't have enough data connected to select a valid overload: %s", node.GetDebugName().data()))));
AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("%s: %s", ParseErrors::NodeableNodeOverloadAmbiguous, node.GetDebugName().data()))));
}
else
{
// todo Add node to these errors
AddError(nullptr, ValidationConstPtr(aznew NotYetImplemented(node.GetEntityId(), AZStd::string::format("NodeableNode did not construct its internal node: %s", node.GetDebugName().data()))));
AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("%s: %s", ParseErrors::NodeableNodeDidNotConstructInternalNodeable, node.GetDebugName().data()))));
}
}
}
@@ -2535,7 +2535,7 @@ namespace ScriptCanvas
if (IsInfiniteVariableWriteHandlingLoop(*this, variableHandling, variableHandling->m_function, true))
{
AddError(variableHandling->m_function, aznew NotYetImplemented(AZ::EntityId(), ScriptCanvas::ParseErrors::InfiniteLoopWritingToVariable));
AddError(variableHandling->m_function, aznew Internal::ParseError(AZ::EntityId(), ScriptCanvas::ParseErrors::InfiniteLoopWritingToVariable));
return false;
}
@@ -3312,7 +3312,7 @@ namespace ScriptCanvas
}
else
{
AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), childOutSlotsOutcome.TakeError()));
AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), childOutSlotsOutcome.TakeError()));
}
}
}
@@ -3615,9 +3615,11 @@ namespace ScriptCanvas
void AbstractCodeModel::ParseExecutionMultipleOutSyntaxSugar(ExecutionTreePtr execution, const EndpointsResolved& executionOutNodes, const AZStd::vector<const Slot*>& outSlots)
{
const auto executionNodeId = execution->GetId().m_node ? execution->GetId().m_node->GetEntityId() : AZ::EntityId();
if (executionOutNodes.size() != outSlots.size())
{
AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarMismatchOutSize);
AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarMismatchOutSize);
}
if (execution->GetSymbol() != Symbol::Sequence)
@@ -3630,13 +3632,13 @@ namespace ScriptCanvas
if (!child)
{
AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNullChildFound);
AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNullChildFound);
return;
}
if (child->m_execution)
{
AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNonNullChildExecutionFound);
AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNonNullChildExecutionFound);
return;
}
@@ -3660,7 +3662,7 @@ namespace ScriptCanvas
if (execution->GetChildrenCount() != executionOutNodes.size())
{
AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarChildExecutionRemovedAndNotReplaced);
AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarChildExecutionRemovedAndNotReplaced);
return;
}
}
@@ -4187,7 +4189,7 @@ namespace ScriptCanvas
}
else
{
AddError(nullptr, aznew NotYetImplemented(execution->GetNodeId(), dataSlotsOutcome.TakeError()));
AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), dataSlotsOutcome.TakeError()));
}
}
}
@@ -4494,13 +4496,13 @@ namespace ScriptCanvas
}
else
{
AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), returnSlotsOutcome.TakeError()));
AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), returnSlotsOutcome.TakeError()));
}
}
}
else
{
AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), outputSlotsOutcome.TakeError()));
AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), outputSlotsOutcome.TakeError()));
}
}
@@ -35,15 +35,6 @@ namespace ScriptCanvas
}
}
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> ArithmeticExpression::GetReplacementSlotsMap() const
{
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> slotsMap;
slotsMap.emplace(k_evaluateName, AZStd::vector<AZStd::string>{ "In" });
slotsMap.emplace(k_outName, AZStd::vector<AZStd::string>{ "Out" });
slotsMap.emplace(k_resultName, AZStd::vector<AZStd::string>{ "Result" });
return slotsMap;
}
void ArithmeticExpression::OnInit()
{
{
@@ -72,7 +72,6 @@ namespace ScriptCanvas
bool IsDeprecated() const override { return true; }
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> GetReplacementSlotsMap() const override;
void CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map<SlotId, AZStd::vector<SlotId>>& outSlotIdMap) const override;
protected:
@@ -94,8 +94,6 @@ namespace ScriptCanvas
void ForEach::OnInit()
{
ResetLoop();
if (!m_sourceSlot.IsValid())
{
DynamicDataSlotConfiguration slotConfiguration;
@@ -130,33 +128,6 @@ namespace ScriptCanvas
EndpointNotificationBus::Handler::BusConnect({ GetEntityId(), m_sourceSlot });
}
void ForEach::OnInputSignal(const SlotId& slotId)
{
auto inSlotId = ForEachProperty::GetInSlotId(this);
if (slotId == inSlotId || slotId == SlotId{})
{
if (slotId == inSlotId)
{
if (!InitializeLoop())
{
// Loop initialization failed
SignalOutput(ForEachProperty::GetFinishedSlotId(this));
return;
}
}
if (!m_breakCalled)
{
Iterate();
}
}
else if (slotId == ForEachProperty::GetBreakSlotId(this))
{
m_breakCalled = true;
SignalOutput(ForEachProperty::GetFinishedSlotId(this));
}
}
UpdateResult ForEach::OnUpdateNode()
{
if (auto continueSlot = GetSlotByNameAndType("Continue", CombinedSlotType::ExecutionIn))
@@ -167,161 +138,6 @@ namespace ScriptCanvas
return UpdateResult::DirtyGraph;
}
bool ForEach::InitializeLoop()
{
ResetLoop();
const Datum* input = FindDatum(m_sourceSlot);
if (input && !input->Empty())
{
if (!Data::IsContainerType(input->GetType()))
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Iteration not supported on this type: %s", Data::GetName(m_sourceContainer.GetType()).c_str());
return false;
}
// Make a copy of the source datum
m_sourceContainer = *input;
// Get the size of the container
auto sizeOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_sourceContainer, "Size");
if (!sizeOutcome)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get size of container: %s", sizeOutcome.GetError().c_str());
return false;
}
Datum sizeResult = sizeOutcome.TakeValue();
const size_t* sizePtr = sizeResult.GetAs<size_t>();
m_size = sizePtr ? *sizePtr : 0;
if (Data::IsSetContainerType(m_sourceContainer.GetType()) || Data::IsMapContainerType(m_sourceContainer.GetType()))
{
// If it's a map or set, get the vector of keys
auto keysVectorOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_sourceContainer, "GetKeys");
if (!keysVectorOutcome)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get vector of keys: %s", keysVectorOutcome.GetError().c_str());
return false;
}
m_keysVector = keysVectorOutcome.TakeValue();
// Check size of vector of keys for safety
auto keysSizeOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_keysVector, "Size");
if (!keysSizeOutcome)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get size of vector of keys: %s", keysSizeOutcome.GetError().c_str());
return false;
}
Datum keysSizeResult = keysSizeOutcome.TakeValue();
const size_t* keysSizePtr = keysSizeResult.GetAs<size_t>();
size_t keysSize = keysSizePtr ? *keysSizePtr : 0;
if (m_size != keysSize)
{
// This shouldn't happen
SCRIPTCANVAS_REPORT_ERROR((*this), "Container size and vector of keys size mismatch.");
return false;
}
}
return true;
}
return false;
}
void ForEach::Iterate()
{
if (m_sourceContainer.Empty() || m_index >= m_size)
{
SignalOutput(ForEachProperty::GetFinishedSlotId(this));
return;
}
Datum& container = Data::IsVectorContainerType(m_sourceContainer.GetType()) ? m_sourceContainer : m_keysVector;
auto keyAtOutcome = BehaviorContextMethodHelper::CallMethodOnDatumUnpackOutcomeSuccess(container, "At", m_index);
if (!keyAtOutcome)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get key in container: %s", keyAtOutcome.GetError().c_str());
return;
}
Datum keyAtResult = keyAtOutcome.TakeValue();
if (!SetPropertySlotData(keyAtResult, k_keySlotIndex))
{
// Unable to set property slot
SCRIPTCANVAS_REPORT_ERROR((*this), "Unable to set one of the property slots on this node.");
SignalOutput(ForEachProperty::GetFinishedSlotId(this));
return;
}
if (Data::IsMapContainerType(m_sourceContainer.GetType()))
{
// If the container is a map, we want to get the value for the current key
auto valueAtOutcome = BehaviorContextMethodHelper::CallMethodOnDatumUnpackOutcomeSuccess(m_sourceContainer, "At", keyAtResult);
if (!valueAtOutcome)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get value for key in container: %s", valueAtOutcome.GetError().c_str());
return;
}
Datum valueAtResult = valueAtOutcome.TakeValue();
if (!SetPropertySlotData(valueAtResult, k_valueSlotIndex))
{
// Unable to set property slot
SCRIPTCANVAS_REPORT_ERROR((*this), "Unable to set one of the property slots on this node.");
SignalOutput(ForEachProperty::GetFinishedSlotId(this));
return;
}
}
++m_index;
SignalOutput(ForEachProperty::GetEachSlotId(this));
}
bool ForEach::SetPropertySlotData(Datum& atResult, size_t propertyIndex)
{
if (atResult.Empty())
{
// Something went wrong with the Behavior Context call
SCRIPTCANVAS_REPORT_ERROR((*this), "Behavior Context call failed; unable to retrieve element from container.");
return false;
}
if (m_propertySlots.size() <= propertyIndex)
{
// Missing a property slot
SCRIPTCANVAS_REPORT_ERROR((*this), "Node in invalid state; missing a property slot.");
return false;
}
PushOutput(atResult, *GetSlot(m_propertySlots[propertyIndex].m_propertySlotId));
return true;
}
void ForEach::ResetLoop()
{
// Reset node state
m_index = 0;
m_size = 0;
m_breakCalled = false;
m_sourceContainer = Datum();
m_keysVector = Datum();
}
void ForEach::OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType)
{
if (dynamicGroup == GetContainerGroupId() && dataType.IsValid())
@@ -56,44 +56,29 @@ namespace ScriptCanvas
bool IsBreakSlot(const SlotId&) const;
bool IsOutOfDate(const VersionData& graphVersion) const override;
bool IsOutOfDate(const VersionData& graphVersion) const override;
UpdateResult OnUpdateNode() override;
protected:
ExecutionNameMap GetExecutionNameMap() const override;
void OnInit() override;
void OnInputSignal(const SlotId&) override;
bool InitializeLoop();
void Iterate();
bool SetPropertySlotData(Datum& atResult, size_t propertyIndex);
void ResetLoop();
void OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType) override;
void ClearPropertySlots();
void AddPropertySlotsFromType(const Data::Type& dataType);
static AZ::Crc32 GetContainerGroupId() { return AZ_CRC("ContainerGroup", 0xb81ed451); }
SlotId m_sourceSlot;
AZ::TypeId m_previousTypeId;
AZStd::vector<Data::PropertyMetadata> m_propertySlots;
private:
static const size_t k_keySlotIndex;
static const size_t k_valueSlotIndex;
size_t m_index;
size_t m_size;
static AZ::Crc32 GetContainerGroupId() { return AZ_CRC("ContainerGroup", 0xb81ed451); }
bool m_breakCalled;
void AddPropertySlotsFromType(const Data::Type& dataType);
Datum m_sourceContainer;
Datum m_keysVector;
void ClearPropertySlots();
ExecutionNameMap GetExecutionNameMap() const override;
void OnInit() override;
void OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType) override;
SlotId m_sourceSlot;
AZ::TypeId m_previousTypeId;
AZStd::vector<Data::PropertyMetadata> m_propertySlots;
};
}
}
@@ -410,6 +410,11 @@ namespace ScriptCanvas
return m_asset.GetId();
}
const AZStd::string& FunctionCallNode::GetAssetHint() const
{
return m_asset.GetHint();
}
AZ::Outcome<DependencyReport, void> FunctionCallNode::GetDependencies() const
{
DependencyReport report;
@@ -70,6 +70,8 @@ namespace ScriptCanvas
AZ::Data::AssetId GetAssetId() const;
const AZStd::string& GetAssetHint() const;
const AZStd::string& GetName() const;
void Initialize(AZ::Data::AssetId assetId, const ScriptCanvas::Grammar::FunctionSourceId& sourceId);
@@ -19,6 +19,32 @@
#include <ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidPropertyEvent.h>
namespace FunctionDefinitionNodeCpp
{
void VersionUpdateRemoveDefaultDisplayGroup(ScriptCanvas::Nodes::Core::FunctionDefinitionNode& node)
{
using namespace ScriptCanvas;
using namespace ScriptCanvas::Nodes::Core;
AZ::SerializeContext* serializeContext{};
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (serializeContext)
{
const auto& classData = serializeContext->FindClassData(azrtti_typeid<FunctionDefinitionNode>());
if (classData && classData->m_version < FunctionDefinitionNode::NodeVersion::RemoveDefaultDisplayGroup)
{
for (auto& slot : node.ModAllSlots())
{
if (slot->GetType() == CombinedSlotType::DataIn || slot->GetType() == CombinedSlotType::DataOut)
{
slot->ClearDynamicGroup();
}
}
}
}
}
}
namespace ScriptCanvas
{
namespace Nodes
@@ -113,6 +139,12 @@ namespace ScriptCanvas
}
}
void FunctionDefinitionNode::OnInit()
{
Nodeling::OnInit();
FunctionDefinitionNodeCpp::VersionUpdateRemoveDefaultDisplayGroup(*this);
}
void FunctionDefinitionNode::SetupSlots()
{
auto groupedSlots = GetSlotsWithDisplayGroup(GetSlotDisplayGroup());
@@ -208,7 +240,6 @@ namespace ScriptCanvas
slotConfiguration.SetConnectionType(connectionType);
slotConfiguration.m_displayGroup = GetDataDisplayGroup();
slotConfiguration.m_dynamicGroup = GetDataDynamicTypeGroup();
slotConfiguration.m_dynamicDataType = DynamicDataType::Any;
slotConfiguration.m_isUserAdded = true;
@@ -29,14 +29,13 @@ namespace ScriptCanvas
class FunctionDefinitionNode
: public Internal::Nodeling
{
private:
public:
enum NodeVersion
{
Initial = 1
Initial = 1,
RemoveDefaultDisplayGroup,
};
public:
SCRIPTCANVAS_NODE(FunctionDefinitionNode);
FunctionDefinitionNode() = default;
@@ -78,14 +77,15 @@ namespace ScriptCanvas
static constexpr AZ::Crc32 GetAddNodelingInputDataSlot() { return AZ_CRC_CE("AddNodelingInputDataSlot"); }
static constexpr AZ::Crc32 GetAddNodelingOutputDataSlot() { return AZ_CRC_CE("AddNodelingOutputDataSlot"); }
static constexpr AZ::Crc32 GetDataDynamicTypeGroup() { return AZ_CRC_CE("DataGroup"); }
AZStd::string GetDataDisplayGroup() const { return "DataDisplayGroup"; }
SlotId HandleExtension(AZ::Crc32 extensionId) override;
void ConfigureVisualExtensions() override;
void OnInit() override;
void OnSetup() override;
private:
@@ -208,7 +208,6 @@ namespace ScriptCanvas
}
}
void Method::InitializeMethod(const MethodConfiguration& config)
{
m_namespaces = config.m_namespaces ? *config.m_namespaces : m_namespaces;
@@ -239,7 +238,11 @@ namespace ScriptCanvas
for (size_t argIndex(0), sentinel(config.m_method.GetNumArguments()); argIndex != sentinel; ++argIndex)
{
SlotId addedSlot = AddMethodInputSlot(config, argIndex);
MethodHelper::SetSlotToDefaultValue(*this, addedSlot, config, argIndex);
if (addedSlot.IsValid())
{
MethodHelper::SetSlotToDefaultValue(*this, addedSlot, config, argIndex);
}
}
}
@@ -132,6 +132,8 @@ namespace ScriptCanvas
const Slot* GetIfBranchSlot(bool branch) const;
AZ_INLINE const AZStd::string& GetLookupName() const { return m_lookupName; }
AZ_INLINE AZStd::recursive_mutex& GetMutex() { return m_mutex; }
ConstSlotsOutcome GetSlotsInExecutionThreadByTypeImpl(const Slot& executionSlot, CombinedSlotType targetSlotType, const Slot* executionChildSlot) const override;
@@ -160,6 +162,8 @@ namespace ScriptCanvas
bool SanityCheckBranchOnResultMethod(const AZ::BehaviorMethod& branchOnResultMethod) const;
AZ_INLINE void SetClassNamePretty(AZStd::string_view classNamePretty) { m_classNamePretty = classNamePretty; }
void SetMethodUnchecked(const AZ::BehaviorMethod* method, const AZ::BehaviorClass* behaviorClass);
AZ_INLINE void SetWarnOnMissingFunction(bool enabled) { m_warnOnMissingFunction = enabled; }
@@ -94,7 +94,7 @@ namespace ScriptCanvas
{
if (!m_updatingDisplay)
{
RefreshActiveIndexes();
RefreshActiveIndexes(true, true);
UpdateSlotDisplay();
}
}
@@ -135,10 +135,8 @@ namespace ScriptCanvas
return Data::Type::Invalid();
}
AZ::Outcome<AZStd::string, void> MethodOverloaded::GetFunctionCallName(const Slot* slot) const
AZ::Outcome<AZStd::string, void> MethodOverloaded::GetFunctionCallName([[maybe_unused]] const Slot* slot) const
{
AZ_UNUSED(slot);
AZStd::string overloadName;
int activeIndex = GetActiveIndex();
@@ -188,7 +186,7 @@ namespace ScriptCanvas
// this prevents repeated updates based on changes to slots
Method::InitializeMethod(config);
SetClassNamePretty("");
RefreshActiveIndexes();
ConfigureContracts();
@@ -197,7 +195,12 @@ namespace ScriptCanvas
SlotId MethodOverloaded::AddMethodInputSlot(const MethodConfiguration& config, size_t argumentIndex)
{
const AZ::BehaviorParameter* argumentPtr = config.m_method.GetArgument(argumentIndex);
AZ_Assert(argumentPtr, "Method: %s had a null argument at index: %d", config.m_lookupName->data(), argumentIndex);
if (!argumentPtr)
{
return SlotId{};
}
const auto& argument = *argumentPtr;
auto nameAndToolTip = MethodHelper::GetArgumentNameAndToolTip(config, argumentIndex);
@@ -507,7 +510,7 @@ namespace ScriptCanvas
}
}
void MethodOverloaded::RefreshActiveIndexes(bool checkForConnections)
void MethodOverloaded::RefreshActiveIndexes(bool checkForConnections, bool adjustSlots)
{
DataIndexMapping concreteInputTypes;
DataIndexMapping concreteOutputTypes;
@@ -519,6 +522,35 @@ namespace ScriptCanvas
if (m_overloadSelection.m_availableIndexes.size() == 1)
{
auto methodOverload = m_overloadConfiguration.m_overloads[(*m_overloadSelection.m_availableIndexes.begin())];
if (adjustSlots)
{
const size_t numArguments = methodOverload.first->GetNumArguments();
const size_t numInputSlots = m_orderedInputSlotIds.size();
if (numArguments > numInputSlots)
{
MethodConfiguration config(*methodOverload.first, GetMethodType());
AZStd::string_view lookupName = GetLookupName();
config.m_lookupName = &lookupName;
for (size_t index = numInputSlots; index != numArguments; ++index)
{
AddMethodInputSlot(config, index);
}
}
else if (numArguments < numInputSlots)
{
const size_t removeCount = numInputSlots - numArguments;
// remove extra slots, assuming remaining ones are of valid type (if not valid name)
for (size_t count = 0; count != removeCount; ++count)
{
RemoveSlot(m_orderedInputSlotIds.back());
m_orderedInputSlotIds.pop_back();
}
}
}
SetMethodUnchecked(methodOverload.first, methodOverload.second);
}
}
@@ -681,9 +713,6 @@ namespace ScriptCanvas
return AZ::Success();
}
}
}
}
@@ -106,7 +106,7 @@ namespace ScriptCanvas
void SetupMethodData(const AZ::BehaviorMethod* lookupMethod, const AZ::BehaviorClass* lookupClass);
void ConfigureContracts();
void RefreshActiveIndexes(bool checkForConnections = true);
void RefreshActiveIndexes(bool checkForConnections = true, bool adjustSlots = false);
void FindDataIndexMappings(DataIndexMapping& inputMapping, DataIndexMapping& outputMapping, bool checkForConnections) const;
void UpdateSlotDisplay();
@@ -47,21 +47,10 @@ namespace ScriptCanvas
AZ::Transform currentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(currentTransform, targetEntity, &AZ::TransformInterface::GetWorldTM);
AZ::Vector3 position = currentTransform.GetTranslation();
AZ::Quaternion currentRotation = currentTransform.GetRotation();
currentTransform.SetRotation((rotation * currentTransform.GetRotation().GetNormalized()));
AZ::Quaternion newRotation = (rotation * currentRotation);
newRotation.Normalize();
AZ::Transform newTransform = AZ::Transform::CreateIdentity();
newTransform.SetScale(currentTransform.GetScale());
newTransform.SetRotation(newRotation);
newTransform.SetTranslation(position);
AZ::TransformBus::Event(targetEntity, &AZ::TransformInterface::SetWorldTM, newTransform);
AZ::TransformBus::Event(targetEntity, &AZ::TransformInterface::SetWorldTM, currentTransform);
}
}
@@ -44,22 +44,12 @@ namespace ScriptCanvas
{
AZ::Quaternion rotation = AZ::ConvertEulerDegreesToQuaternion(angles);
AZ::Transform currentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(currentTransform, targetEntity, &AZ::TransformInterface::GetWorldTM);
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, targetEntity, &AZ::TransformInterface::GetWorldTM);
AZ::Vector3 position = currentTransform.GetTranslation();
AZ::Quaternion currentRotation = currentTransform.GetRotation();
transform.SetRotation((rotation * transform.GetRotation()).GetNormalized());
AZ::Quaternion newRotation = (rotation * currentRotation);
newRotation.Normalize();
AZ::Transform newTransform = AZ::Transform::CreateIdentity();
newTransform.CreateScale(currentTransform.ExtractScale());
newTransform.SetRotation(newRotation);
newTransform.SetTranslation(position);
AZ::TransformBus::Event(targetEntity, &AZ::TransformInterface::SetWorldTM, newTransform);
AZ::TransformBus::Event(targetEntity, &AZ::TransformInterface::SetWorldTM, transform);
}
}
}
@@ -393,14 +393,6 @@ namespace ScriptCanvas
AZ_UNUSED(sourceType);
}
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> OperatorBase::GetReplacementSlotsMap() const
{
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> slotsMap;
slotsMap.emplace("In", AZStd::vector<AZStd::string>{ "In" });
slotsMap.emplace("Out", AZStd::vector<AZStd::string>{ "Out" });
return slotsMap;
}
void OperatorBase::CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map<SlotId, AZStd::vector<SlotId>>& outSlotIdMap) const
{
auto newDataInSlots = replacementNode->GetSlotsByType(ScriptCanvas::CombinedSlotType::DataIn);
@@ -57,7 +57,6 @@ namespace ScriptCanvas
AZStd::vector< SourceSlotConfiguration > m_sourceSlotConfigurations;
};
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> GetReplacementSlotsMap() const override;
void CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map<SlotId, AZStd::vector<SlotId>>& outSlotIdMap) const override;
using TypeList = AZStd::vector<AZ::TypeId>;
@@ -8,7 +8,7 @@
Base="ScriptCanvas::Node"
Version="2"
GeneratePropertyFriend="True"
DeprecationUUID="32A4BEDC-C207-4472-61DE-9A716402620A"
DeprecationUUID="{32A4BEDC-C207-4472-61DE-9A716402620A}"
Deprecated="This node has been deprecated in favor of the nodeable form"
Description="Provides a time value.">
<In Name="Start" Description="Starts the timer."/>
@@ -25,4 +25,4 @@
IsInput="False"
IsOutput="True" />
</Class>
</ScriptCanvas>
</ScriptCanvas>
@@ -62,6 +62,8 @@ namespace ScriptCanvas
constexpr const char* NoChildrenAfterRoot = "No children after parsing function root";
constexpr const char* NoChildrenInExtraction = "No children found in property extraction node";
constexpr const char* NoDataPresent = "Could not construct from graph, no graph data was present";
constexpr const char* NodeableNodeOverloadAmbiguous = "NodeableNodeOverloaded doesn't have enough data connected to select a valid overload";
constexpr const char* NodeableNodeDidNotConstructInternalNodeable = "NodeableNode did not construct its internal Nodeable";
constexpr const char* NoInputToForEach = "No Input To For Each Loop";
constexpr const char* NoOutForExecution = "No out slot for execution root";
constexpr const char* NoOutSlotInFunctionDefinitionStart = "No 'Out' slot in start of function definition";
@@ -12,9 +12,26 @@
#include "VersioningUtils.h"
#include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Core/Connection.h>
namespace ScriptCanvas
{
AZStd::vector<Endpoint> GraphUpdateSlotReport::Convert(const Endpoint& oldEndpoint) const
{
auto iter = m_oldSlotsToNewSlots.find(oldEndpoint);
return iter != m_oldSlotsToNewSlots.end() ? iter->second : AZStd::vector<Endpoint>{ oldEndpoint };
}
bool GraphUpdateSlotReport::IsEmpty() const
{
return m_deletedOldSlots.empty() && m_oldSlotsToNewSlots.empty();
}
bool NodeUpdateSlotReport::IsEmpty() const
{
return m_deletedOldSlots.empty() && m_oldSlotsToNewSlots.empty();
}
void VersioningUtils::CopyOldValueToDataSlot(Slot* newSlot, const VariableId& oldVariableReference, const Datum* oldDatum)
{
if (oldVariableReference.IsValid())
@@ -36,6 +53,99 @@ namespace ScriptCanvas
}
}
void MergeUpdateSlotReport(const AZ::EntityId& scriptCanvasNodeId, GraphUpdateSlotReport& report, const NodeUpdateSlotReport& source)
{
report.m_deletedOldSlots.reserve(source.m_deletedOldSlots.size());
for (auto& slotId : source.m_deletedOldSlots)
{
report.m_deletedOldSlots.insert({ scriptCanvasNodeId, slotId });
}
report.m_oldSlotsToNewSlots.reserve(source.m_oldSlotsToNewSlots.size());
for (auto& oldToNewIter : source.m_oldSlotsToNewSlots)
{
AZStd::vector<Endpoint> newEndpoints;
newEndpoints.reserve(oldToNewIter.second.size());
for (auto& targetSlotId : oldToNewIter.second)
{
newEndpoints.push_back({ scriptCanvasNodeId, targetSlotId });
}
report.m_oldSlotsToNewSlots[{ scriptCanvasNodeId, oldToNewIter.first}] = AZStd::move(newEndpoints);
}
}
AZStd::vector<AZStd::pair<Endpoint, Endpoint>> CollectEndpoints(const AZStd::vector<AZ::Entity*>& connections, bool logEntityNames)
{
AZStd::vector<AZStd::string> names;
AZStd::vector<AZStd::pair<Endpoint, Endpoint>> endpoints;
for (auto& connectionEntity : connections)
{
if (logEntityNames)
{
names.push_back(connectionEntity->GetName());
}
if (auto connection = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Connection>(connectionEntity->GetId()))
{
endpoints.push_back(AZStd::make_pair(connection->GetSourceEndpoint(), connection->GetTargetEndpoint()));
}
}
if (logEntityNames)
{
AZStd::sort(names.begin(), names.end());
AZStd::string result = "\nConnection Name list:\n";
for (auto& name : names)
{
result += "\n";
result += name;
}
AZ_TracePrintf("ScriptCanvas", result.c_str());
}
return endpoints;
}
void UpdateConnectionStatus(Graph& graph, const GraphUpdateSlotReport& report)
{
GraphData* graphData = graph.GetGraphData();
if (!graphData)
{
AZ_Error("ScriptCanvas", false, "Graph was missing graph data to update");
return;
}
AZStd::unordered_set<SlotId> oldConnectedSlots;
AZ_TracePrintf("ScriptCanvas", "Connections list before: ");
auto endpoints = CollectEndpoints(graphData->m_connections, true);
graph.RemoveAllConnections();
for (auto& iter : endpoints)
{
const AZStd::vector<Endpoint>& sources = report.Convert(iter.first);
const AZStd::vector<Endpoint>& targets = report.Convert(iter.second);
for (const auto& source : sources)
{
for (const auto& target : targets)
{
graph.ConnectByEndpoint(source, target);
}
}
}
graphData->BuildEndpointMap();
AZ_TracePrintf("ScriptCanvas", "Connections list after: ");
CollectEndpoints(graphData->m_connections, true);
}
void VersioningUtils::CreateRemapConnectionsForSourceEndpoint(const Graph& graph, const Endpoint& oldSourceEndpoint, const Endpoint& newSourceEndpoint,
ReplacementConnectionMap& connectionMap)
{
@@ -15,6 +15,8 @@
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/utils.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/Endpoint.h>
#include <ScriptCanvas/Variable/VariableCore.h>
namespace AZ
@@ -25,13 +27,36 @@ namespace AZ
namespace ScriptCanvas
{
class Datum;
class Endpoint;
class Graph;
class Slot;
using ReplacementEndpointPairs = AZStd::unordered_set<AZStd::pair<ScriptCanvas::Endpoint, ScriptCanvas::Endpoint>>;
using ReplacementEndpointPairs = AZStd::unordered_set<AZStd::pair<Endpoint, Endpoint>>;
using ReplacementConnectionMap = AZStd::unordered_map<AZ::EntityId, ReplacementEndpointPairs>;
struct NodeUpdateSlotReport
{
AZStd::unordered_set<SlotId> m_deletedOldSlots;
AZStd::unordered_map<SlotId, AZStd::vector<SlotId>> m_oldSlotsToNewSlots;
bool IsEmpty() const;
};
struct GraphUpdateSlotReport
{
AZStd::unordered_set<Endpoint> m_deletedOldSlots;
AZStd::unordered_map<Endpoint, AZStd::vector<Endpoint>> m_oldSlotsToNewSlots;
AZStd::vector<Endpoint> Convert(const Endpoint& oldEndpoint) const;
bool IsEmpty() const;
};
void MergeUpdateSlotReport(const AZ::EntityId& scriptCanvasNodeId, GraphUpdateSlotReport& report, const NodeUpdateSlotReport& source);
AZStd::vector<AZStd::pair<Endpoint, Endpoint>> CollectEndpoints(const AZStd::vector<AZ::Entity*>& connections, bool logEntityNames = false);
void UpdateConnectionStatus(Graph& graph, const GraphUpdateSlotReport& report);
class VersioningUtils
{
public: