Expose Raw BC Properties to Node Palette.
This commit is contained in:
@@ -88,6 +88,13 @@ namespace ScriptCanvas
|
||||
Current,
|
||||
};
|
||||
|
||||
enum class PropertyStatus : AZ::u8
|
||||
{
|
||||
Getter,
|
||||
None,
|
||||
Setter,
|
||||
};
|
||||
|
||||
struct VersionData
|
||||
{
|
||||
AZ_TYPE_INFO(VersionData, "{14C629F6-467B-46FE-8B63-48FDFCA42175}");
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace ScriptCanvas
|
||||
Event,
|
||||
Free,
|
||||
Member,
|
||||
Getter,
|
||||
Setter,
|
||||
Count,
|
||||
};
|
||||
|
||||
|
||||
@@ -394,6 +394,7 @@ namespace ScriptCanvas
|
||||
AZ::Uuid m_type = AZ::Uuid::CreateNull();
|
||||
AZStd::string m_className;
|
||||
AZStd::string m_methodName;
|
||||
PropertyStatus m_propertyStatus = PropertyStatus::None;
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
|
||||
@@ -104,8 +104,7 @@ namespace ScriptCanvas
|
||||
|
||||
const FunctorOut& Nodeable::GetExecutionOutChecked(size_t index) const
|
||||
{
|
||||
|
||||
if (index >= m_outs.size() && m_outs[index])
|
||||
if (index >= m_outs.size() || !m_outs[index])
|
||||
{
|
||||
return m_noOpFunctor;
|
||||
}
|
||||
|
||||
@@ -537,6 +537,20 @@ namespace ScriptCanvas
|
||||
return azrtti_istypeof<const ScriptCanvas::Nodes::Logic::Break*>(execution->GetId().m_node);
|
||||
}
|
||||
|
||||
bool IsClassPropertyRead(ExecutionTreeConstPtr execution)
|
||||
{
|
||||
return execution->GetSymbol() == Symbol::FunctionCall
|
||||
&& azrtti_istypeof<const ScriptCanvas::Nodes::Core::Method*>(execution->GetId().m_node)
|
||||
&& azrtti_cast<const ScriptCanvas::Nodes::Core::Method*>(execution->GetId().m_node)->GetPropertyStatus() == PropertyStatus::Getter;
|
||||
}
|
||||
|
||||
bool IsClassPropertyWrite(ExecutionTreeConstPtr execution)
|
||||
{
|
||||
return execution->GetSymbol() == Symbol::FunctionCall
|
||||
&& azrtti_istypeof<const ScriptCanvas::Nodes::Core::Method*>(execution->GetId().m_node)
|
||||
&& azrtti_cast<const ScriptCanvas::Nodes::Core::Method*>(execution->GetId().m_node)->GetPropertyStatus() == PropertyStatus::Setter;
|
||||
}
|
||||
|
||||
bool IsCodeConstructable(Grammar::VariableConstPtr value)
|
||||
{
|
||||
return Data::IsValueType(value->m_datum.GetType())
|
||||
@@ -1280,7 +1294,6 @@ namespace ScriptCanvas
|
||||
return identifier;
|
||||
}
|
||||
|
||||
|
||||
ExecutionTraversalResult TraverseExecutionConnectionsRecurse(const EndpointsResolved& nextEndpoints, AZStd::unordered_set<const Slot*>& previousIns, GraphExecutionPathTraversalListener& listener);
|
||||
|
||||
ExecutionTraversalResult TraverseExecutionConnectionsRecurse(const EndpointResolved& in, AZStd::unordered_set<const Slot*>& previousIns, GraphExecutionPathTraversalListener& listener);
|
||||
|
||||
@@ -79,6 +79,10 @@ namespace ScriptCanvas
|
||||
|
||||
bool IsBreak(const ExecutionTreeConstPtr& execution);
|
||||
|
||||
bool IsClassPropertyRead(ExecutionTreeConstPtr execution);
|
||||
|
||||
bool IsClassPropertyWrite(ExecutionTreeConstPtr execution);
|
||||
|
||||
bool IsCodeConstructable(VariableConstPtr value);
|
||||
|
||||
bool IsCycle(const Node& node);
|
||||
|
||||
@@ -193,6 +193,22 @@ namespace ScriptCanvas
|
||||
return DynamicDataType::Any;
|
||||
}
|
||||
|
||||
PropertyStatus Method::GetPropertyStatus() const
|
||||
{
|
||||
switch (m_methodType)
|
||||
{
|
||||
case MethodType::Getter:
|
||||
return PropertyStatus::Getter;
|
||||
|
||||
case MethodType::Setter:
|
||||
return PropertyStatus::Setter;
|
||||
|
||||
default:
|
||||
return PropertyStatus::None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Method::InitializeMethod(const MethodConfiguration& config)
|
||||
{
|
||||
m_namespaces = config.m_namespaces ? *config.m_namespaces : m_namespaces;
|
||||
@@ -239,7 +255,7 @@ namespace ScriptCanvas
|
||||
OnInitializeOutputPost(outputConfig);
|
||||
}
|
||||
|
||||
void Method::InitializeBehaviorMethod(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName)
|
||||
void Method::InitializeBehaviorMethod(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName, PropertyStatus propertyStatus)
|
||||
{
|
||||
AZ::BehaviorContext* behaviorContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
|
||||
@@ -255,13 +271,13 @@ namespace ScriptCanvas
|
||||
{
|
||||
InitializeFree(namespaces, methodName);
|
||||
}
|
||||
else if (auto ebusIterator = behaviorContext->m_ebuses.find(className); ebusIterator == behaviorContext->m_ebuses.end())
|
||||
else if (auto ebusIterator = behaviorContext->m_ebuses.find(className); ebusIterator != behaviorContext->m_ebuses.end())
|
||||
{
|
||||
InitializeClass(namespaces, className, methodName);
|
||||
InitializeEvent(namespaces, className, methodName);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeEvent(namespaces, className, methodName);
|
||||
InitializeClass(namespaces, className, methodName, propertyStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +307,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
}
|
||||
|
||||
void Method::InitializeClass(const NamespacePath&, AZStd::string_view className, AZStd::string_view methodName)
|
||||
void Method::InitializeClass(const NamespacePath&, AZStd::string_view className, AZStd::string_view methodName, PropertyStatus propertyStatus)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
|
||||
@@ -299,9 +315,11 @@ namespace ScriptCanvas
|
||||
const AZ::BehaviorClass* bcClass{};
|
||||
AZStd::string prettyClassName;
|
||||
|
||||
if (BehaviorContextUtils::FindClass(method, bcClass, className, methodName, &prettyClassName))
|
||||
if (BehaviorContextUtils::FindClass(method, bcClass, className, methodName, propertyStatus, &prettyClassName))
|
||||
{
|
||||
MethodConfiguration config(*method, MethodType::Member);
|
||||
const auto methodType = propertyStatus == PropertyStatus::None ? MethodType::Member : propertyStatus == PropertyStatus::Getter ? MethodType::Getter : MethodType::Setter;
|
||||
|
||||
MethodConfiguration config(*method, methodType);
|
||||
config.m_class = bcClass;
|
||||
config.m_namespaces = &m_namespaces;
|
||||
config.m_className = &className;
|
||||
@@ -647,8 +665,12 @@ namespace ScriptCanvas
|
||||
break;
|
||||
|
||||
case MethodType::Member:
|
||||
case MethodType::Getter:
|
||||
case MethodType::Setter:
|
||||
{
|
||||
if (BehaviorContextUtils::FindClass(method, bcClass, m_className, methodName, nullptr, m_warnOnMissingFunction))
|
||||
PropertyStatus status = m_methodType == MethodType::Getter ? PropertyStatus::Getter : m_methodType == MethodType::Setter ? PropertyStatus::Setter : PropertyStatus::None;
|
||||
|
||||
if (BehaviorContextUtils::FindClass(method, bcClass, m_className, methodName, status, nullptr, m_warnOnMissingFunction))
|
||||
{
|
||||
outClass = bcClass;
|
||||
outMethod = method;
|
||||
|
||||
@@ -87,14 +87,13 @@ namespace ScriptCanvas
|
||||
bool IsObjectClass(AZStd::string_view objectClass) const { return objectClass.compare(m_className) == 0; }
|
||||
|
||||
//! Attempts to initialize node with a BehaviorContext BehaviorMethod
|
||||
//! If the className is empty, then the methodName is searched on the BehaviorContext
|
||||
//! If className is not empty the className is used to look for a registered BehaviorEBus in the BehaviorContext
|
||||
//! and if found, the methodName is searched among the BehaviorEBus events
|
||||
//! Otherwise the className is used to look for a registered BehaviorClass in the BehaviorContext
|
||||
//! and if found, the methodName is searched among the BehaviorClass methods
|
||||
void InitializeBehaviorMethod(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName);
|
||||
//! 1) If the names match an overloaded method, including one using ExplicitOverloadInfo, then that method is used. Else:
|
||||
//! 2) If the class name is empty, then search for a free method is searched for in the BehaviorContext and there is a warning if not found.
|
||||
//! 3) If the class name matches an ebus, methodName is searched among the BehaviorEBus events, and there is a warning if not found.
|
||||
//! 4) if the class name does NOT match an ebus, className and methodName are used to look for a registered BehaviorClass in the BehaviorContext, and there is a warning if not found.
|
||||
void InitializeBehaviorMethod(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName, PropertyStatus propertyStatus);
|
||||
|
||||
void InitializeClass(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName);
|
||||
void InitializeClass(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName, PropertyStatus propertyStatus);
|
||||
|
||||
void InitializeEvent(const NamespacePath& namespaces, AZStd::string_view busName, AZStd::string_view eventName);
|
||||
|
||||
@@ -126,6 +125,8 @@ namespace ScriptCanvas
|
||||
|
||||
virtual DynamicDataType GetOverloadedOutputType(size_t resultIndex) const;
|
||||
|
||||
PropertyStatus GetPropertyStatus() const;
|
||||
|
||||
protected:
|
||||
void ConfigureMethod(const AZ::BehaviorMethod& method, const AZ::BehaviorClass* bcClass);
|
||||
|
||||
|
||||
@@ -637,6 +637,16 @@ namespace ScriptCanvas
|
||||
{
|
||||
WriteGlobalPropertyRead(execution);
|
||||
}
|
||||
else if (Grammar::IsClassPropertyRead(execution))
|
||||
{
|
||||
WriteClassPropertyRead(execution);
|
||||
m_dotLua.WriteNewLine();
|
||||
}
|
||||
else if (Grammar::IsClassPropertyWrite(execution))
|
||||
{
|
||||
WriteClassPropertyWrite(execution);
|
||||
m_dotLua.WriteNewLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool isNullCheckRequired = Grammar::IsFunctionCallNullCheckRequired(execution);
|
||||
@@ -1208,6 +1218,19 @@ namespace ScriptCanvas
|
||||
TranslateNodeableParse();
|
||||
}
|
||||
|
||||
void GraphToLua::WriteClassPropertyRead(Grammar::ExecutionTreeConstPtr execution)
|
||||
{
|
||||
WriteFunctionCallInput(execution, 0, IsFormatStringInput::No);
|
||||
m_dotLua.Write(".%s", Grammar::ToIdentifier(execution->GetName()).c_str());
|
||||
}
|
||||
|
||||
void GraphToLua::WriteClassPropertyWrite(Grammar::ExecutionTreeConstPtr execution)
|
||||
{
|
||||
WriteClassPropertyRead(execution);
|
||||
m_dotLua.Write(" = ");
|
||||
WriteFunctionCallInput(execution, 1, IsFormatStringInput::No);
|
||||
}
|
||||
|
||||
void GraphToLua::WriteConditionalCaseSwitch(Grammar::ExecutionTreeConstPtr execution, Grammar::Symbol symbol, const Grammar::ExecutionChild& child, size_t index)
|
||||
{
|
||||
if (symbol == Grammar::Symbol::RandomSwitch)
|
||||
|
||||
@@ -116,6 +116,8 @@ namespace ScriptCanvas
|
||||
void TranslateNodeableParse();
|
||||
void TranslateStaticInitialization();
|
||||
void TranslateVariableInitialization(AZStd::string_view leftValue);
|
||||
void WriteClassPropertyRead(Grammar::ExecutionTreeConstPtr);
|
||||
void WriteClassPropertyWrite(Grammar::ExecutionTreeConstPtr);
|
||||
void WriteConditionalCaseSwitch(Grammar::ExecutionTreeConstPtr execution, Grammar::Symbol symbol, const Grammar::ExecutionChild& child, size_t index);
|
||||
enum class IsLeadingCommaRequired { No, Yes };
|
||||
void WriteConstructionArgs();
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace ScriptCanvas
|
||||
return { typeID };
|
||||
}
|
||||
|
||||
bool BehaviorContextUtils::FindClass(const AZ::BehaviorMethod*& outMethod, const AZ::BehaviorClass*& outClass, [[maybe_unused]] AZStd::string_view className, [[maybe_unused]] AZStd::string_view methodName, [[maybe_unused]] AZStd::string* outPrettyClassName, [[maybe_unused]] bool warnOnMissing)
|
||||
bool BehaviorContextUtils::FindClass(const AZ::BehaviorMethod*& outMethod, const AZ::BehaviorClass*& outClass, [[maybe_unused]] AZStd::string_view className, [[maybe_unused]] AZStd::string_view methodName, PropertyStatus propertyStatus, [[maybe_unused]] AZStd::string* outPrettyClassName, [[maybe_unused]] bool warnOnMissing)
|
||||
{
|
||||
AZ::BehaviorContext* behaviorContext(nullptr);
|
||||
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
|
||||
@@ -81,16 +81,36 @@ namespace ScriptCanvas
|
||||
const AZ::BehaviorClass* behaviorClass(classIter->second);
|
||||
AZ_Assert(behaviorClass, "BehaviorContext Class entry %s has no class pointer", className.data());
|
||||
|
||||
const auto methodIter(behaviorClass->m_methods.find(methodName.data()));
|
||||
if (methodIter == behaviorClass->m_methods.end())
|
||||
|
||||
AZ::BehaviorMethod* method{};
|
||||
|
||||
if (propertyStatus == PropertyStatus::None)
|
||||
{
|
||||
AZ_Warning("Script Canvas", !warnOnMissing, "No method by name of %s found in BehaviorContext class %s", methodName.data(), className.data());
|
||||
return false;
|
||||
const auto methodIter(behaviorClass->m_methods.find(methodName.data()));
|
||||
if (methodIter != behaviorClass->m_methods.end())
|
||||
{
|
||||
method = methodIter->second;
|
||||
propertyStatus = PropertyStatus::None;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("Script Canvas", !warnOnMissing, "No method by name of %s found in BehaviorContext class %s", methodName.data(), className.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto propertyIter(behaviorClass->m_properties.find(methodName.data()));
|
||||
if (propertyIter == behaviorClass->m_properties.end())
|
||||
{
|
||||
AZ_Warning("Script Canvas", !warnOnMissing, "No property by name of %s found in BehaviorContext class %s", methodName.data(), className.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
method = propertyStatus == PropertyStatus::Getter ? propertyIter->second->m_getter : propertyIter->second->m_setter;
|
||||
}
|
||||
|
||||
// this argument is the first argument...so perhaps remove the distinction between class and member functions, since it probably won't follow polymorphism
|
||||
// if it will, keep the distinction, and add the first argument separately
|
||||
AZ::BehaviorMethod* method(methodIter->second);
|
||||
if (!method)
|
||||
{
|
||||
AZ_Warning("Script Canvas", !warnOnMissing, "BehaviorContext Method entry %s has no method pointer", methodName.data());
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ScriptCanvas
|
||||
class BehaviorContextUtils
|
||||
{
|
||||
public:
|
||||
static bool FindClass(const AZ::BehaviorMethod*& outMethod, const AZ::BehaviorClass*& outClass, AZStd::string_view className, AZStd::string_view methodName, AZStd::string* outPrettyClassName = nullptr, bool warnOnMissing = true);
|
||||
static bool FindClass(const AZ::BehaviorMethod*& outMethod, const AZ::BehaviorClass*& outClass, AZStd::string_view className, AZStd::string_view methodName, PropertyStatus propertyStatus = PropertyStatus::None, AZStd::string* outPrettyClassName = nullptr, bool warnOnMissing = true);
|
||||
static bool FindEBus(const AZ::BehaviorEBus*& outEBus, AZStd::string_view ebusName, bool warnOnMissing = true);
|
||||
static bool FindExplicitOverload(const AZ::BehaviorMethod*& outMethod, const AZ::BehaviorClass*& outClass, AZStd::string_view className, AZStd::string_view methodName, AZStd::string* outPrettyClassName = nullptr);
|
||||
static AZStd::string FindExposedMethodName(const AZ::BehaviorMethod& method, const AZ::BehaviorClass* behaviorClass);
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConstructMethodNodeIdentifier(methodNode->GetRawMethodClassName(), methodNode->GetName());
|
||||
return ConstructMethodNodeIdentifier(methodNode->GetRawMethodClassName(), methodNode->GetName(), methodNode->GetPropertyStatus());
|
||||
}
|
||||
}
|
||||
else if (auto ebusNode = azrtti_cast<const Nodes::Core::EBusEventHandler*>(scriptCanvasNode))
|
||||
@@ -158,13 +158,14 @@ namespace ScriptCanvas
|
||||
return resultHash;
|
||||
}
|
||||
|
||||
NodeTypeIdentifier NodeUtils::ConstructMethodNodeIdentifier(AZStd::string_view methodClass, AZStd::string_view methodName)
|
||||
NodeTypeIdentifier NodeUtils::ConstructMethodNodeIdentifier(AZStd::string_view methodClass, AZStd::string_view methodName, ScriptCanvas::PropertyStatus propertyStatus)
|
||||
{
|
||||
NodeTypeIdentifier resultHash = 0;
|
||||
|
||||
AZStd::hash_combine(resultHash, AZStd::hash<AZ::Uuid>()(azrtti_typeid<ScriptCanvas::Nodes::Core::Method>()));
|
||||
AZStd::hash_combine(resultHash, AZStd::hash<AZStd::string_view>()(methodClass));
|
||||
AZStd::hash_combine(resultHash, AZStd::hash<AZStd::string>()(methodName));
|
||||
AZStd::hash_combine(resultHash, AZStd::hash<AZ::u8>()(static_cast<AZ::u8>(propertyStatus)));
|
||||
|
||||
return resultHash;
|
||||
}
|
||||
@@ -253,7 +254,7 @@ namespace ScriptCanvas
|
||||
if (auto* method = azrtti_cast<ScriptCanvas::Nodes::Core::Method*>(node))
|
||||
{
|
||||
ScriptCanvas::NamespacePath emptyNamespaces;
|
||||
method->InitializeBehaviorMethod(emptyNamespaces, config.m_className, config.m_methodName);
|
||||
method->InitializeBehaviorMethod(emptyNamespaces, config.m_className, config.m_methodName, config.m_propertyStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace ScriptCanvas
|
||||
|
||||
static NodeTypeIdentifier ConstructCustomNodeIdentifier(const AZ::Uuid& nodeId);
|
||||
|
||||
static NodeTypeIdentifier ConstructMethodNodeIdentifier(AZStd::string_view methodClass, AZStd::string_view methodName);
|
||||
static NodeTypeIdentifier ConstructMethodNodeIdentifier(AZStd::string_view methodClass, AZStd::string_view methodName, ScriptCanvas::PropertyStatus propertyStatus);
|
||||
static NodeTypeIdentifier ConstructGlobalMethodNodeIdentifier(AZStd::string_view methodName);
|
||||
static NodeTypeIdentifier ConstructMethodOverloadedNodeIdentifier(AZStd::string_view methodName);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user