| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604 |
- /*
- * 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 <AzCore/Interface/Interface.h>
- #include <AzCore/RTTI/BehaviorContextUtilities.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
- #include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
- #include <Editor/View/Widgets/NodePalette/NodePaletteModel.h>
- #include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
- #include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
- #include <Editor/Nodes/NodeUtils.h>
- #include <Editor/Settings.h>
- #include <Editor/Translation/TranslationHelper.h>
- #include <ScriptCanvas/Data/DataRegistry.h>
- #include <ScriptCanvas/Libraries/Libraries.h>
- #include <ScriptCanvas/Libraries/Core/GetVariable.h>
- #include <ScriptCanvas/Libraries/Core/Method.h>
- #include <ScriptCanvas/Libraries/Core/SetVariable.h>
- #include <ScriptCanvas/Utils/NodeUtils.h>
- #include <ScriptCanvas/Data/Traits.h>
- #include <StaticLib/GraphCanvas/Styling/definitions.h>
- AZ_DEFINE_BUDGET(NodePaletteModel);
- namespace
- {
- static constexpr char DefaultGlobalConstantCategory[] = "Global Constants";
- static constexpr char DefaultGlobalMethodCategory[] = "Global Methods";
- static constexpr char DefaultClassMethodCategory[] = "Class Methods";
- static constexpr char DefaultEbusHandlerCategory[] = "Event Handlers";
- static constexpr char DefaultEbusEventCategory[] = "Events";
- // Various Helper Methods
- bool IsDeprecated(const AZ::AttributeArray& attributes)
- {
- bool isDeprecated{};
- if (auto isDeprecatedAttributePtr = AZ::FindAttribute(AZ::Script::Attributes::Deprecated, attributes))
- {
- AZ::AttributeReader(nullptr, isDeprecatedAttributePtr).Read<bool>(isDeprecated);
- }
- return isDeprecated;
- }
- bool ShouldExcludeFromNodeList(const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>* excludeAttributeData, const AZ::Uuid& typeId)
- {
- if (excludeAttributeData)
- {
- AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly;
- if (typeId == AzToolsFramework::Components::EditorComponentBase::TYPEINFO_Uuid())
- {
- return true;
- }
- return (static_cast<AZ::u64>(excludeAttributeData->Get(nullptr)) & exclusionFlags) != 0; // warning C4800: 'AZ::u64': forcing value to bool 'true' or 'false' (performance warning)
- }
- return false;
- }
- bool HasExcludeFromNodeListAttribute(const AZ::SerializeContext* serializeContext, const AZ::Uuid& typeId)
- {
- const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(typeId);
- if (classData && classData->m_editData)
- {
- if (auto editorElementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
- {
- if (auto excludeAttribute = editorElementData->FindAttribute(AZ::Script::Attributes::ExcludeFrom))
- {
- auto excludeAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(excludeAttribute);
- return excludeAttributeData && ShouldExcludeFromNodeList(excludeAttributeData, typeId);
- }
- }
- }
- return false;
- }
- // Checks for and returns the Category attribute from an AZ::AttributeArray
- AZStd::string GetCategoryPath(const AZ::AttributeArray& attributes, const AZ::BehaviorContext& behaviorContext)
- {
- AZStd::string retVal;
- AZ::Attribute* categoryAttribute = AZ::FindAttribute(AZ::Script::Attributes::Category, attributes);
- if (categoryAttribute)
- {
- AZ::AttributeReader(nullptr, categoryAttribute).Read<AZStd::string>(retVal, behaviorContext);
- }
- return retVal;
- }
- bool IsExplicitOverload(const AZ::BehaviorMethod& method)
- {
- return AZ::FindAttribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, method.m_attributes) != nullptr;
- }
- void RegisterMethod
- ( ScriptCanvasEditor::NodePaletteModel& nodePaletteModel
- , const AZ::BehaviorContext& behaviorContext
- , const AZStd::string& categoryPath
- , const AZ::BehaviorClass* behaviorClass
- , const AZStd::string& name
- , const AZ::BehaviorMethod& method
- , ScriptCanvas::PropertyStatus propertyStatus
- , bool isOverloaded)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "RegisterMethod");
- if (IsDeprecated(method.m_attributes))
- {
- return;
- }
- if (behaviorClass && !isOverloaded)
- {
- auto excludeMethodAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, method.m_attributes));
- if (ShouldExcludeFromNodeList(excludeMethodAttributeData, behaviorClass->m_azRtti ? behaviorClass->m_azRtti->GetTypeId() : behaviorClass->m_typeId))
- {
- return;
- }
- }
- const auto isExposableOutcome = ScriptCanvas::IsExposable(method);
- if (!isExposableOutcome.IsSuccess())
- {
- AZ_Warning("ScriptCanvas", false, "Unable to expose method: %s to ScriptCanvas because: %s", method.m_name.data(), isExposableOutcome.GetError().data());
- return;
- }
- nodePaletteModel.RegisterClassNode(categoryPath, behaviorClass ? behaviorClass->m_name : "", name, &method, &behaviorContext, propertyStatus, isOverloaded);
- }
- void RegisterGlobalMethod(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel, const AZ::BehaviorContext& behaviorContext,
- const AZ::BehaviorMethod& behaviorMethod)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "RegisterGlobalMethod");
- const auto isExposableOutcome = ScriptCanvas::IsExposable(behaviorMethod);
- if (!isExposableOutcome.IsSuccess())
- {
- AZ_Warning("ScriptCanvas", false, "Unable to expose method: %s to ScriptCanvas because: %s",
- behaviorMethod.m_name.c_str(), isExposableOutcome.GetError().data());
- return;
- }
- if (!AZ::Internal::IsInScope(behaviorMethod.m_attributes, AZ::Script::Attributes::ScopeFlags::Common))
- {
- return; // skip this method
- }
- nodePaletteModel.RegisterGlobalMethodNode(behaviorContext, behaviorMethod);
- }
- //! Retrieve the list of EBuses t hat should not be exposed in the ScriptCanvasEditor Node Palette
- AZStd::unordered_set<AZ::Crc32> GetEBusExcludeSet(const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "GetEBusExcludeSet");
- // We will skip buses that are ONLY registered on classes that derive from EditorComponentBase,
- // because they don't have a runtime implementation. Buses such as the TransformComponent which
- // is implemented by both an EditorComponentBase derived class and a Component derived class
- // will still appear
- AZStd::unordered_set<AZ::Crc32> skipBuses;
- AZStd::unordered_set<AZ::Crc32> potentialSkipBuses;
- AZStd::unordered_set<AZ::Crc32> nonSkipBuses;
- for (const auto& classIter : behaviorContext.m_classes)
- {
- const AZ::BehaviorClass* behaviorClass = classIter.second;
- if (IsDeprecated(behaviorClass->m_attributes))
- {
- continue;
- }
- // Only bind Behavior Classes marked with the Scope type of Launcher
- if (!AZ::Internal::IsInScope(behaviorClass->m_attributes, AZ::Script::Attributes::ScopeFlags::Launcher))
- {
- continue; // skip this class
- }
- // Check for "ExcludeFrom" attribute for ScriptCanvas
- auto excludeClassAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(
- AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes));
- // We don't want to show any components, since there isn't anything we can do with them
- // from ScriptCanvas since we use buses to communicate to everything.
- if (ShouldExcludeFromNodeList(excludeClassAttributeData, behaviorClass->m_azRtti ? behaviorClass->m_azRtti->GetTypeId() : behaviorClass->m_typeId))
- {
- for (const auto& requestBus : behaviorClass->m_requestBuses)
- {
- skipBuses.insert(AZ::Crc32(requestBus.c_str()));
- }
- continue;
- }
- auto baseClass = AZStd::find(behaviorClass->m_baseClasses.begin(),
- behaviorClass->m_baseClasses.end(),
- AzToolsFramework::Components::EditorComponentBase::TYPEINFO_Uuid());
- if (baseClass != behaviorClass->m_baseClasses.end())
- {
- for (const auto& requestBus : behaviorClass->m_requestBuses)
- {
- potentialSkipBuses.insert(AZ::Crc32(requestBus.c_str()));
- }
- }
- // If the Ebus does not inherit from EditorComponentBase then do not skip it
- else
- {
- for (const auto& requestBus : behaviorClass->m_requestBuses)
- {
- nonSkipBuses.insert(AZ::Crc32(requestBus.c_str()));
- }
- }
- }
- // Add buses which are not on the non-skip list to the skipBuses set
- for (auto potentialSkipBus : potentialSkipBuses)
- {
- if (nonSkipBuses.find(potentialSkipBus) == nonSkipBuses.end())
- {
- skipBuses.insert(potentialSkipBus);
- }
- }
- return skipBuses;
- }
- //! Register all nodes populated into the ScriptCanvas NodeRegistry
- void PopulateScriptCanvasDerivedNodes(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::SerializeContext& serializeContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateScriptCanvasDerivedNodes");
- nodePaletteModel.RegisterDefaultCateogryInformation();
- for (auto& descriptor : ScriptCanvasModel::Instance().GetDescriptors())
- {
- const auto& classId = descriptor->GetUuid();
- if (const AZ::SerializeContext::ClassData* nodeClassData = serializeContext.FindClassData(classId))
- {
- if (HasExcludeFromNodeListAttribute(&serializeContext, classId))
- {
- continue;
- }
- // Skip over some of our more dynamic nodes that we want to populate using different means
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::GetVariableNode>())
- {
- continue;
- }
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::SetVariableNode>())
- {
- continue;
- }
- else
- {
- nodePaletteModel.RegisterCustomNode(nodeClassData);
- }
- }
- }
- ScriptCanvas::NodeRegistry* registry = ScriptCanvas::NodeRegistry::GetInstance();
- for (auto nodeId : registry->m_nodes)
- {
- if (HasExcludeFromNodeListAttribute(&serializeContext, nodeId))
- {
- continue;
- }
- // Pass in the associated class data so we can do more intensive lookups?
- const AZ::SerializeContext::ClassData* nodeClassData = serializeContext.FindClassData(nodeId);
- if (nodeClassData == nullptr)
- {
- continue;
- }
- // Skip over some of our more dynamic nodes that we want to populate using different means
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::GetVariableNode>())
- {
- continue;
- }
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::SetVariableNode>())
- {
- continue;
- }
- else
- {
- nodePaletteModel.RegisterCustomNode(nodeClassData);
- }
- }
- }
- void PopulateScriptCanvasDerivedNodesDeprecated(
- ScriptCanvasEditor::NodePaletteModel& nodePaletteModel, const AZ::SerializeContext& serializeContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateScriptCanvasDerivedNodes");
- // Get all the types.
- auto EnumerateLibraryDefintionNodes = [&nodePaletteModel,
- &serializeContext](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
- {
- ScriptCanvasEditor::CategoryInformation categoryInfo;
- AZStd::string categoryPath = classData->m_editData ? classData->m_editData->m_name : classData->m_name;
- if (classData->m_editData)
- {
- auto editorElementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData);
- if (editorElementData)
- {
- if (auto categoryAttribute = editorElementData->FindAttribute(AZ::Edit::Attributes::Category))
- {
- if (auto categoryAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
- {
- categoryPath = categoryAttributeData->Get(nullptr);
- }
- }
- if (auto categoryStyleAttribute = editorElementData->FindAttribute(AZ::Edit::Attributes::CategoryStyle))
- {
- if (auto categoryAttributeData =
- azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryStyleAttribute))
- {
- categoryInfo.m_styleOverride = categoryAttributeData->Get(nullptr);
- }
- }
- if (auto titlePaletteAttribute = editorElementData->FindAttribute(ScriptCanvas::Attributes::Node::TitlePaletteOverride))
- {
- if (auto categoryAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(titlePaletteAttribute))
- {
- categoryInfo.m_paletteOverride = categoryAttributeData->Get(nullptr);
- }
- }
- }
- }
- nodePaletteModel.RegisterCategoryInformation(categoryPath, categoryInfo);
- // Children
- for (auto& node : ScriptCanvas::Library::LibraryDefinition::GetNodes(classData->m_typeId))
- {
- if (HasExcludeFromNodeListAttribute(&serializeContext, node.first))
- {
- continue;
- }
- // Pass in the associated class data so we can do more intensive lookups?
- const AZ::SerializeContext::ClassData* nodeClassData = serializeContext.FindClassData(node.first);
- if (nodeClassData == nullptr)
- {
- continue;
- }
- // Skip over some of our more dynamic nodes that we want to populate using different means
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::GetVariableNode>())
- {
- continue;
- }
- else if (nodeClassData->m_azRtti && nodeClassData->m_azRtti->IsTypeOf<ScriptCanvas::Nodes::Core::SetVariableNode>())
- {
- continue;
- }
- else
- {
- nodePaletteModel.RegisterCustomNode(nodeClassData, categoryPath);
- }
- }
- return true;
- };
- const AZ::TypeId& libraryDefTypeId = azrtti_typeid<ScriptCanvas::Library::LibraryDefinition>();
- serializeContext.EnumerateDerived(EnumerateLibraryDefintionNodes, libraryDefTypeId, libraryDefTypeId);
- }
- void PopulateVariablePalette()
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateVariablePalette");
- auto dataRegistry = ScriptCanvas::GetDataRegistry();
- for (auto& type : dataRegistry->m_creatableTypes)
- {
- if (!type.second.m_isTransient)
- {
- ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type.first);
- }
- }
- }
- void PopulateBehaviorContextGlobalMethods(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextGlobalMethods");
- // BehaviorMethods are not associated with a class
- // therefore the Uuid is set to Null
- const AZ::Uuid behaviorMethodUuid = AZ::Uuid::CreateNull();
- for (const auto& [methodName, behaviorMethod] : behaviorContext.m_methods)
- {
- // Skip behavior methods that are deprecated
- if (behaviorMethod == nullptr || IsDeprecated(behaviorMethod->m_attributes))
- {
- continue;
- }
- // Check for "ExcludeFrom" attribute for ScriptCanvas
- auto excludeMethodAttributeData = azrtti_cast<const AZ::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(
- AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorMethod->m_attributes));
- if (ShouldExcludeFromNodeList(excludeMethodAttributeData, behaviorMethodUuid))
- {
- continue;
- }
- RegisterGlobalMethod(nodePaletteModel, behaviorContext, *behaviorMethod);
- }
- }
- //! Iterates over all Properties directly reflected to the BehaviorContext instance
- //! and registers there Getter/Setter methods to the NodePaletteModel
- void PopulateBehaviorContextGlobalProperties(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextGlobalProperties");
- const AZ::Uuid behaviorMethodUuid = AZ::Uuid::CreateNull();
- for (const auto& [propertyName, behaviorProperty] : behaviorContext.m_properties)
- {
- // Skip behavior properties that are deprecated
- if (behaviorProperty == nullptr || IsDeprecated(behaviorProperty->m_attributes))
- {
- continue;
- }
- // Check for "ExcludeFrom" attribute for ScriptCanvas
- auto excludePropertyAttributeData = azrtti_cast<const AZ::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(
- AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorProperty->m_attributes));
- if (ShouldExcludeFromNodeList(excludePropertyAttributeData, behaviorMethodUuid))
- {
- continue;
- }
- if (behaviorProperty->m_getter && !behaviorProperty->m_setter)
- {
- nodePaletteModel.RegisterGlobalConstant(behaviorContext, behaviorProperty , *behaviorProperty->m_getter);
- }
- else
- {
- if (behaviorProperty->m_getter)
- {
- RegisterGlobalMethod(nodePaletteModel, behaviorContext, *behaviorProperty->m_getter);
- }
- if (behaviorProperty->m_setter)
- {
- RegisterGlobalMethod(nodePaletteModel, behaviorContext, *behaviorProperty->m_setter);
- }
- }
- }
- }
- void PopulateBehaviorContextClassMethods(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextClassMethods");
- AZ::SerializeContext* serializeContext{};
- AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- for (const auto& classIter : behaviorContext.m_classes)
- {
- const AZ::BehaviorClass* behaviorClass = classIter.second;
- if (IsDeprecated(behaviorClass->m_attributes))
- {
- continue;
- }
- if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::Internal::ImplementedAsNodeGeneric, behaviorClass->m_attributes))
- {
- continue;
- }
- if (auto excludeFromPointer = AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes))
- {
- AZ::Script::Attributes::ExcludeFlags excludeFlags{};
- AZ::AttributeReader(nullptr, excludeFromPointer).Read<AZ::Script::Attributes::ExcludeFlags>(excludeFlags);
- if ((excludeFlags & (AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly)) != 0)
- {
- continue;
- }
- }
- if (!AZ::Internal::IsInScope(behaviorClass->m_attributes, AZ::Script::Attributes::ScopeFlags::Launcher))
- {
- continue;
- }
- // Objects and Object methods
- {
- AZStd::string categoryPath;
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorClassContext << behaviorClass->m_name.c_str() << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- categoryPath = details.m_category;
- if (categoryPath.empty())
- {
- categoryPath = GetCategoryPath(behaviorClass->m_attributes, behaviorContext);
- }
- auto dataRegistry = ScriptCanvas::GetDataRegistry();
- ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(behaviorClass->m_typeId);
- if (type.IsValid())
- {
- if (dataRegistry->m_creatableTypes.contains(type))
- {
- ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type);
- }
- }
- AZStd::string classNamePretty(classIter.first);
- AZ::Attribute* prettyNameAttribute = AZ::FindAttribute(AZ::ScriptCanvasAttributes::PrettyName, behaviorClass->m_attributes);
- if (prettyNameAttribute)
- {
- AZ::AttributeReader(nullptr, prettyNameAttribute).Read<AZStd::string>(classNamePretty, behaviorContext);
- }
- if (categoryPath.empty())
- {
- if (!classNamePretty.empty())
- {
- categoryPath = classNamePretty;
- }
- else
- {
- categoryPath = DefaultClassMethodCategory;
- }
- }
- categoryPath.append("/");
- if (details.m_name.empty())
- {
- categoryPath.append(classNamePretty.c_str());
- }
- else
- {
- categoryPath.append(details.m_name.c_str());
- }
- for (auto property : behaviorClass->m_properties)
- {
- if (property.second->m_getter)
- {
- RegisterMethod(nodePaletteModel, behaviorContext, categoryPath, behaviorClass, property.first, *property.second->m_getter, ScriptCanvas::PropertyStatus::Getter, behaviorClass->IsMethodOverloaded(property.first));
- }
- if (property.second->m_setter)
- {
- RegisterMethod(nodePaletteModel, behaviorContext, categoryPath, behaviorClass, property.first, *property.second->m_setter, ScriptCanvas::PropertyStatus::Setter, behaviorClass->IsMethodOverloaded(property.first));
- }
- }
- for (auto methodIter : behaviorClass->m_methods)
- {
- if (!IsExplicitOverload(*methodIter.second))
- {
- // Respect the exclusion flags
- auto attributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, methodIter.second->m_attributes));
- if (ShouldExcludeFromNodeList(attributeData , {}))
- {
- continue;
- }
- RegisterMethod(nodePaletteModel, behaviorContext, categoryPath, behaviorClass, methodIter.first, *methodIter.second, ScriptCanvas::PropertyStatus::None, behaviorClass->IsMethodOverloaded(methodIter.first));
- }
- }
- }
- }
- }
- void PopulateBehaviorContextOverloadedMethods(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextOverloadedMethods");
- for (const AZ::ExplicitOverloadInfo& explicitOverload : behaviorContext.m_explicitOverloads)
- {
- RegisterMethod(nodePaletteModel, behaviorContext, explicitOverload.m_categoryPath, nullptr, explicitOverload.m_name, *explicitOverload.m_overloads.begin()->first, ScriptCanvas::PropertyStatus::None, true);
- }
- }
- void PopulateBehaviorContextEBusHandler(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext, const AZ::BehaviorEBus& behaviorEbus)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextEBusHandler");
- if (AZ::ScopedBehaviorEBusHandler handler{ behaviorEbus }; handler)
- {
- auto excludeEbusAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(
- AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorEbus.m_attributes));
- if (ShouldExcludeFromNodeList(excludeEbusAttributeData, handler->RTTI_GetType()))
- {
- return;
- }
- const AZ::BehaviorEBusHandler::EventArray& events(handler->GetEvents());
- if (!events.empty())
- {
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::EBusHandlerContext << behaviorEbus.m_name.c_str() << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- AZStd::string categoryPath = details.m_category.empty() ? GetCategoryPath(behaviorEbus.m_attributes, behaviorContext) : details.m_category;
- // Treat the EBusHandler name as a Category key in order to allow multiple buses to be merged into a single Category.
- {
- if (!categoryPath.empty())
- {
- categoryPath.append("/");
- }
- else
- {
- categoryPath = AZStd::string::format("%s/", DefaultEbusHandlerCategory);
- }
- if (!details.m_name.empty())
- {
- categoryPath.append(details.m_name.c_str());
- }
- else if (categoryPath.contains(DefaultEbusHandlerCategory))
- {
- // Use the BehaviorEBus name to categorize within the default ebus handler category
- categoryPath.append(behaviorEbus.m_name.c_str());
- }
- }
- for (const auto& event : events)
- {
- nodePaletteModel.RegisterEBusHandlerNodeModelInformation(categoryPath.c_str(), behaviorEbus.m_name, event.m_name, ScriptCanvas::EBusBusId(behaviorEbus.m_name), event);
- }
- }
- }
- }
- void PopulateBehaviorContextEBusEventMethods(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext, const AZ::BehaviorEBus& behaviorEbus)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextEBusEventMethods");
- if (!behaviorEbus.m_events.empty())
- {
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::EBusSenderContext << behaviorEbus.m_name.c_str() << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- AZStd::string categoryPath = details.m_category.empty() ? GetCategoryPath(behaviorEbus.m_attributes, behaviorContext) : details.m_category;
- // Parent
- AZStd::string displayName = details.m_name;
- // Treat the EBus name as a Category key in order to allow multiple buses to be merged into a single Category.
- if (!categoryPath.empty())
- {
- categoryPath.append("/");
- }
- else
- {
- categoryPath = AZStd::string::format("%s/", DefaultEbusEventCategory);
- }
- if (!details.m_name.empty())
- {
- categoryPath.append(details.m_name.c_str());
- }
- else if (categoryPath.contains(DefaultEbusEventCategory))
- {
- // Use the behavior EBus name to categorize within the ebus event category
- categoryPath.append(behaviorEbus.m_name.c_str());
- }
- ScriptCanvasEditor::CategoryInformation ebusCategoryInformation;
- ebusCategoryInformation.m_tooltip = details.m_tooltip;
- nodePaletteModel.RegisterCategoryInformation(categoryPath, ebusCategoryInformation);
- for (auto event : behaviorEbus.m_events)
- {
- if (IsDeprecated(event.second.m_attributes))
- {
- continue;
- }
- auto excludeEventAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, event.second.m_attributes));
- if (ShouldExcludeFromNodeList(excludeEventAttributeData, AZ::Uuid::CreateNull()))
- {
- continue; // skip this event
- }
- const bool isOverload{ false }; // overloaded events are not trivially supported
- nodePaletteModel.RegisterEBusSenderNodeModelInformation(categoryPath, behaviorEbus.m_name, event.first, ScriptCanvas::EBusBusId(behaviorEbus.m_name.c_str()), ScriptCanvas::EBusEventId(event.first.c_str()), ScriptCanvas::PropertyStatus::None, isOverload);
- }
- }
- }
- void PopulateBehaviorContextEBuses(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel,
- const AZ::BehaviorContext& behaviorContext)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateBehaviorContextEBuses");
- AZStd::unordered_set<AZ::Crc32> skipBuses = GetEBusExcludeSet(behaviorContext);
- for (const auto& [ebusName, behaviorEbus] : behaviorContext.m_ebuses)
- {
- if (behaviorEbus == nullptr)
- {
- continue;
- }
- auto skipBusIterator = skipBuses.find(AZ::Crc32(ebusName));
- if (skipBusIterator != skipBuses.end())
- {
- continue;
- }
- // Skip buses mapped by their deprecated name (usually duplicates)
- if (ebusName == behaviorEbus->m_deprecatedName)
- {
- continue;
- }
- // Only bind Behavior Buses marked with the Scope type of Launcher
- if (!AZ::Internal::IsInScope(behaviorEbus->m_attributes, AZ::Script::Attributes::ScopeFlags::Launcher))
- {
- continue; // skip this bus
- }
- if (IsDeprecated(behaviorEbus->m_attributes))
- {
- continue;
- }
- auto excludeEbusAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(
- AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorEbus->m_attributes));
- if (ShouldExcludeFromNodeList(excludeEbusAttributeData, AZ::Uuid::CreateNull()))
- {
- continue;
- }
- if (auto runtimeEbusAttributePtr = AZ::FindAttribute(AZ::RuntimeEBusAttribute, behaviorEbus->m_attributes))
- {
- bool isRuntimeEbus = false;
- AZ::AttributeReader(nullptr, runtimeEbusAttributePtr).Read<bool>(isRuntimeEbus);
- if (isRuntimeEbus)
- {
- continue;
- }
- }
- // EBus Handler
- PopulateBehaviorContextEBusHandler(nodePaletteModel, behaviorContext, *behaviorEbus);
- // EBus Sender
- PopulateBehaviorContextEBusEventMethods(nodePaletteModel, behaviorContext, *behaviorEbus);
- }
- }
- // Helper function for populating the node palette model.
- // Pulled out just to make the tabbing a bit nicer, since it's a huge method.
- void PopulateNodePaletteModel(ScriptCanvasEditor::NodePaletteModel& nodePaletteModel)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "PopulateNodePaletteModel");
- AZ::SerializeContext* serializeContext = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- AZ::BehaviorContext* behaviorContext = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
- AZ_Assert(serializeContext, "Could not find SerializeContext. Aborting Palette Creation.");
- AZ_Assert(behaviorContext, "Could not find BehaviorContext. Aborting Palette Creation.");
- if (serializeContext == nullptr || behaviorContext == nullptr)
- {
- return;
- }
- // Populates the NodePalette in ScriptCanvas NodeRegistry
- PopulateScriptCanvasDerivedNodes(nodePaletteModel, *serializeContext);
- // Deprecated, populates the NodePalette in deprecated ScriptCanvas NodeRegistry
- PopulateScriptCanvasDerivedNodesDeprecated(nodePaletteModel, *serializeContext);
- // Populates the VariablePalette with type registered with the ScriptCanvas DataRegistry
- PopulateVariablePalette();
- // Populates the NodePalette with Behavior Class method nodes
- PopulateBehaviorContextClassMethods(nodePaletteModel, *behaviorContext);
- // Populates the NodePalette with BehaviorContext methods overloaded on the same name
- PopulateBehaviorContextOverloadedMethods(nodePaletteModel, *behaviorContext);
- // Populates the NodePalette with EBus Event method nodes and EBus Event handler nodes
- PopulateBehaviorContextEBuses(nodePaletteModel, *behaviorContext);
- // Populates the NodePalette with Methods reflected directly on the BehaviorContext
- PopulateBehaviorContextGlobalMethods(nodePaletteModel, *behaviorContext);
- // Populates the NodePalette with Properties reflected directly on the BehaviorContext
- PopulateBehaviorContextGlobalProperties(nodePaletteModel, *behaviorContext);
- }
- }
- namespace ScriptCanvasEditor
- {
- ////////////////////////////////
- // NodePaletteModelInformation
- ////////////////////////////////
- void NodePaletteModelInformation::PopulateTreeItem(GraphCanvas::NodePaletteTreeItem& treeItem) const
- {
- if (!m_toolTip.empty())
- {
- treeItem.SetToolTip(m_toolTip.c_str());
- }
- if (!m_styleOverride.empty())
- {
- treeItem.SetStyleOverride(m_styleOverride.c_str());
- }
- if (!m_titlePaletteOverride.empty())
- {
- const bool forceSet = true;
- treeItem.SetTitlePalette(m_titlePaletteOverride.c_str(), forceSet);
- }
- }
- /////////////////////
- // NodePaletteModel
- /////////////////////
- NodePaletteModel::NodePaletteModel()
- : m_paletteId(AZ::Entity::MakeId())
- {
- UpgradeNotificationsBus::Handler::BusConnect();
- }
- NodePaletteModel::~NodePaletteModel()
- {
- UpgradeNotificationsBus::Handler::BusDisconnect();
- DisconnectLambdas();
- ClearRegistry();
- }
- NodePaletteId NodePaletteModel::GetNotificationId() const
- {
- return m_paletteId;
- }
- void NodePaletteModel::AssignAssetModel(AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* assetModel)
- {
- m_assetModel = assetModel;
- if (m_assetModel)
- {
- TraverseTree();
- ConnectLambdas();
- }
- }
- void NodePaletteModel::ConnectLambdas()
- {
- {
- auto connection = QObject::connect(m_assetModel, &QAbstractItemModel::rowsInserted, [this](const QModelIndex& parentIndex, int first, int last) { this->OnRowsInserted(parentIndex, first, last); });
- m_lambdaConnections.emplace_back(connection);
- }
- {
- auto connection = QObject::connect(m_assetModel, &QAbstractItemModel::rowsAboutToBeRemoved, [this](const QModelIndex& parentIndex, int first, int last) { this->OnRowsAboutToBeRemoved(parentIndex, first, last); });
- m_lambdaConnections.emplace_back(connection);
- }
- }
- void NodePaletteModel::DisconnectLambdas()
- {
- for (auto connection : m_lambdaConnections)
- {
- QObject::disconnect(connection);
- }
- }
- void NodePaletteModel::RepopulateModel()
- {
- AZ_PROFILE_FUNCTION(ScriptCanvas);
- ClearRegistry();
- PopulateNodePaletteModel((*this));
- if (m_assetModel)
- {
- TraverseTree();
- }
- NodePaletteModelNotificationBus::Event(m_paletteId, &NodePaletteModelNotifications::OnAssetModelRepopulated);
- }
- void NodePaletteModel::RegisterCustomNode(const AZ::SerializeContext::ClassData* classData, const AZStd::string& categoryPath)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterCustomNode");
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier = ScriptCanvas::NodeUtils::ConstructCustomNodeIdentifier(classData->m_typeId);
- auto mapIter = m_registeredNodes.find(nodeIdentifier);
- if (mapIter == m_registeredNodes.end())
- {
- CustomNodeModelInformation* customNodeInformation = aznew CustomNodeModelInformation();
- customNodeInformation->m_nodeIdentifier = nodeIdentifier;
- customNodeInformation->m_typeId = classData->m_typeId;
- customNodeInformation->m_displayName = classData->m_name;
- customNodeInformation->m_categoryPath = categoryPath;
- bool isDeprecated(false);
- if (classData && classData->m_editData && classData->m_editData->m_name)
- {
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::CustomNodeContext << classData->m_typeId.ToString<AZStd::string>().c_str() << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- if (details.m_name.empty())
- {
- details.m_name = classData->m_editData->m_name;
- details.m_tooltip = classData->m_editData->m_description;
- }
- customNodeInformation->m_displayName = details.m_name;
- customNodeInformation->m_toolTip = details.m_tooltip;
- if (customNodeInformation->m_displayName.empty())
- {
- customNodeInformation->m_displayName = classData->m_editData->m_name;
- }
- auto editorDataElement = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData);
- if (editorDataElement)
- {
- if (auto categoryStyleAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::CategoryStyle))
- {
- if (auto categoryAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryStyleAttribute))
- {
- if (categoryAttributeData->Get(nullptr))
- {
- customNodeInformation->m_styleOverride = categoryAttributeData->Get(nullptr);
- }
- }
- }
- if (auto categoryNameAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::Category))
- {
- if(auto categoryNameAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryNameAttribute))
- {
- if (categoryNameAttributeData->Get(nullptr))
- {
- customNodeInformation->m_categoryPath = categoryNameAttributeData->Get(nullptr);
- }
- }
- }
- if (auto titlePaletteAttribute = editorDataElement->FindAttribute(ScriptCanvas::Attributes::Node::TitlePaletteOverride))
- {
- if (auto titlePaletteAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(titlePaletteAttribute))
- {
- if (titlePaletteAttributeData->Get(nullptr))
- {
- customNodeInformation->m_titlePaletteOverride = titlePaletteAttributeData->Get(nullptr);
- }
- }
- }
- if (auto deprecatedAttribute = editorDataElement->FindAttribute(AZ::Script::Attributes::Deprecated))
- {
- if (auto deprecatedAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<bool>*>(deprecatedAttribute))
- {
- isDeprecated = deprecatedAttributeData->Get(nullptr);
- }
- }
- if (customNodeInformation->m_toolTip.empty() && classData->m_editData->m_description)
- {
- customNodeInformation->m_toolTip = classData->m_editData->m_description;
- }
- }
- if (!details.m_category.empty())
- {
- customNodeInformation->m_categoryPath = details.m_category;
- }
- }
- if (!isDeprecated)
- {
- m_registeredNodes.emplace(AZStd::make_pair(nodeIdentifier, customNodeInformation));
- }
- else
- {
- delete customNodeInformation;
- }
- }
- }
- void NodePaletteModel::RegisterClassNode
- ( const AZStd::string& categoryPath
- , const AZStd::string& methodClass
- , const AZStd::string& methodName
- , const AZ::BehaviorMethod*
- , const AZ::BehaviorContext*
- , ScriptCanvas::PropertyStatus propertyStatus
- , bool isOverload)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterClassNode");
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier = isOverload ? ScriptCanvas::NodeUtils::ConstructMethodOverloadedNodeIdentifier(methodName) : ScriptCanvas::NodeUtils::ConstructMethodNodeIdentifier(methodClass, methodName, propertyStatus);
- auto registerIter = m_registeredNodes.find(nodeIdentifier);
- if (registerIter == m_registeredNodes.end())
- {
- MethodNodeModelInformation* methodModelInformation = aznew MethodNodeModelInformation();
- methodModelInformation->m_isOverload = isOverload;
- methodModelInformation->m_nodeIdentifier = nodeIdentifier;
- methodModelInformation->m_classMethod = methodClass;
- methodModelInformation->m_methodName = methodName;
- methodModelInformation->m_propertyStatus = propertyStatus;
- methodModelInformation->m_titlePaletteOverride = "MethodNodeTitlePalette";
- GraphCanvas::TranslationKey catkey;
- catkey << ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorClassContext << methodClass.c_str() << "details";
- GraphCanvas::TranslationRequests::Details catdetails;
- GraphCanvas::TranslationRequestBus::BroadcastResult(catdetails, &GraphCanvas::TranslationRequests::GetDetails, catkey, catdetails);
- GraphCanvas::TranslationKey key;
- AZStd::string context;
- AZStd::string updatedMethodName;
- if (propertyStatus != ScriptCanvas::PropertyStatus::None)
- {
- updatedMethodName = (propertyStatus == ScriptCanvas::PropertyStatus::Getter) ? "Get" : "Set";
- context = (propertyStatus == ScriptCanvas::PropertyStatus::Getter) ? "Getter" : "Setter";
- }
- updatedMethodName += methodName;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorClassContext << methodClass << "methods" << updatedMethodName << context << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- methodModelInformation->m_displayName = details.m_name.empty() ? updatedMethodName : details.m_name;
- methodModelInformation->m_toolTip = details.m_tooltip;
- methodModelInformation->m_categoryPath = categoryPath;
- if (methodModelInformation->m_categoryPath.empty())
- {
- methodModelInformation->m_categoryPath = DefaultClassMethodCategory;
- }
- m_registeredNodes.emplace(AZStd::make_pair(nodeIdentifier, methodModelInformation));
- }
- }
- void NodePaletteModel::RegisterGlobalConstant(const AZ::BehaviorContext&, const AZ::BehaviorProperty* behaviorProperty, const AZ::BehaviorMethod& behaviorMethod)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterGlobalConstant");
- // Construct Node Identifier using the BehaviorMethod name and the ScriptCanvas Method typeid
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier =
- ScriptCanvas::NodeUtils::ConstructGlobalMethodNodeIdentifier(behaviorMethod.m_name);
- // Register the methodModelInformation if not already registered
- if (auto registerIter = m_registeredNodes.find(nodeIdentifier); registerIter == m_registeredNodes.end())
- {
- auto methodModelInformation = AZStd::make_unique<GlobalMethodNodeModelInformation>();
- methodModelInformation->m_nodeIdentifier = nodeIdentifier;
- methodModelInformation->m_methodName = behaviorMethod.m_name;
- methodModelInformation->m_isProperty = true;
- methodModelInformation->m_titlePaletteOverride = "MethodNodeTitlePalette";
- AZStd::string name = behaviorProperty->m_name;
- AZ::StringFunc::Replace(name, "::Getter", "");
- AZ::StringFunc::Replace(name, "::Setter", "");
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorGlobalPropertyContext << name << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- methodModelInformation->m_displayName = details.m_name;
- methodModelInformation->m_toolTip = details.m_tooltip;
- methodModelInformation->m_categoryPath = details.m_category;
- if (methodModelInformation->m_categoryPath.empty())
- {
- methodModelInformation->m_categoryPath = DefaultGlobalConstantCategory;
- }
- m_registeredNodes.emplace(nodeIdentifier, methodModelInformation.release());
- }
- }
- void NodePaletteModel::RegisterGlobalMethodNode(const AZ::BehaviorContext& behaviorContext, const AZ::BehaviorMethod& behaviorMethod)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterGlobalMethodNode");
- // Construct Node Identifier using the BehaviorMethod name and the ScriptCanvas Method typeid
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier =
- ScriptCanvas::NodeUtils::ConstructGlobalMethodNodeIdentifier(behaviorMethod.m_name);
- // Register the methodModelInformation if not already registered
- if (auto registerIter = m_registeredNodes.find(nodeIdentifier); registerIter == m_registeredNodes.end())
- {
- auto methodModelInformation = AZStd::make_unique<GlobalMethodNodeModelInformation>();
- methodModelInformation->m_methodName = behaviorMethod.m_name;
- methodModelInformation->m_nodeIdentifier = nodeIdentifier;
- methodModelInformation->m_isProperty = false;
- methodModelInformation->m_titlePaletteOverride = "MethodNodeTitlePalette";
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorGlobalMethodContext << behaviorMethod.m_name.c_str() << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- methodModelInformation->m_displayName = details.m_name.empty() ? behaviorMethod.m_name : details.m_name;
- methodModelInformation->m_toolTip = details.m_tooltip.empty() ? "" : details.m_tooltip;
- if (details.m_category.empty())
- {
- auto categoryPath = GetCategoryPath(behaviorMethod.m_attributes, behaviorContext);
- methodModelInformation->m_categoryPath = categoryPath.empty() ? DefaultGlobalMethodCategory : categoryPath;
- }
- else
- {
- methodModelInformation->m_categoryPath = details.m_category;
- }
- m_registeredNodes.emplace(nodeIdentifier, methodModelInformation.release());
- }
- }
- void NodePaletteModel::RegisterEBusHandlerNodeModelInformation(AZStd::string_view categoryPath, AZStd::string_view busName, AZStd::string_view eventName, const ScriptCanvas::EBusBusId& busId, const AZ::BehaviorEBusHandler::BusForwarderEvent& forwardEvent)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterEBusHandlerNodeModelInformation");
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier = ScriptCanvas::NodeUtils::ConstructEBusEventReceiverIdentifier(busId, forwardEvent.m_eventId);
- auto nodeIter = m_registeredNodes.find(nodeIdentifier);
- if (nodeIter == m_registeredNodes.end())
- {
- EBusHandlerNodeModelInformation* handlerInformation = aznew EBusHandlerNodeModelInformation();
- handlerInformation->m_titlePaletteOverride = "HandlerNodeTitlePalette";
- handlerInformation->m_categoryPath = categoryPath;
- handlerInformation->m_nodeIdentifier = nodeIdentifier;
- handlerInformation->m_busName = busName;
- handlerInformation->m_eventName = eventName;
- handlerInformation->m_busId = busId;
- handlerInformation->m_eventId = forwardEvent.m_eventId;
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::EBusHandlerContext << busName << "methods" << eventName << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- handlerInformation->m_displayName = details.m_name.empty() ? eventName : details.m_name.c_str();
- handlerInformation->m_toolTip = details.m_tooltip.empty() ? "" : details.m_tooltip;
- m_registeredNodes.emplace(AZStd::make_pair(nodeIdentifier, handlerInformation));
- }
- }
- void NodePaletteModel::RegisterEBusSenderNodeModelInformation
- ( AZStd::string_view categoryPath
- , AZStd::string_view busName
- , AZStd::string_view eventName
- , const ScriptCanvas::EBusBusId& busId
- , const ScriptCanvas::EBusEventId& eventId
- , ScriptCanvas::PropertyStatus propertyStatus
- , bool isOverload)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterEBusSenderNodeModelInformation");
- ScriptCanvas::NodeTypeIdentifier nodeIdentifier = isOverload ? ScriptCanvas::NodeUtils::ConstructEBusEventSenderOverloadedIdentifier(busId, eventId) : ScriptCanvas::NodeUtils::ConstructEBusEventSenderIdentifier(busId, eventId);
- auto nodeIter = m_registeredNodes.find(nodeIdentifier);
- if (nodeIter == m_registeredNodes.end())
- {
- EBusSenderNodeModelInformation* senderInformation = aznew EBusSenderNodeModelInformation();
- senderInformation->m_isOverload = isOverload;
- senderInformation->m_titlePaletteOverride = "MethodNodeTitlePalette";
- senderInformation->m_categoryPath = categoryPath;
- senderInformation->m_nodeIdentifier = nodeIdentifier;
- senderInformation->m_propertyStatus = propertyStatus;
- senderInformation->m_busName = busName;
- senderInformation->m_eventName = eventName;
- senderInformation->m_busId = busId;
- senderInformation->m_eventId = eventId;
- GraphCanvas::TranslationKey key;
- key << ScriptCanvasEditor::TranslationHelper::AssetContext::EBusSenderContext << busName << "methods" << eventName << "details";
- GraphCanvas::TranslationRequests::Details details;
- GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
- senderInformation->m_displayName = details.m_name.empty() ? eventName : details.m_name.c_str();
- senderInformation->m_toolTip = details.m_tooltip.empty() ? "" : details.m_tooltip;
- m_registeredNodes.emplace(AZStd::make_pair(nodeIdentifier, senderInformation));
- }
- }
- AZStd::vector<ScriptCanvas::NodeTypeIdentifier> NodePaletteModel::RegisterScriptEvent(ScriptEvents::ScriptEventsAsset* scriptEventAsset)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterScriptEvent");
- const ScriptEvents::ScriptEvent& scriptEvent = scriptEventAsset->m_definition;
- ScriptCanvas::EBusBusId busId = scriptEventAsset->GetBusId();
- AZStd::string category = scriptEvent.GetCategory();
- auto methods = scriptEvent.GetMethods();
- AZStd::vector<ScriptCanvas::NodeTypeIdentifier> identifiers;
- // Each event has a handler and a receiver
- identifiers.reserve(methods.size() * 2);
- for (const auto& method : methods)
- {
- ScriptCanvas::EBusEventId eventId = method.GetEventId();
- ScriptCanvas::NodeTypeIdentifier senderIdentifier = ScriptCanvas::NodeUtils::ConstructSendScriptEventIdentifier(busId, eventId);
- ScriptCanvas::NodeTypeIdentifier receiverIdentifier = ScriptCanvas::NodeUtils::ConstructScriptEventReceiverIdentifier(busId, eventId);
- ScriptEventHandlerNodeModelInformation* handlerInformation = aznew ScriptEventHandlerNodeModelInformation();
- handlerInformation->m_titlePaletteOverride = "HandlerNodeTitlePalette";
- handlerInformation->m_busName = scriptEvent.GetName();
- handlerInformation->m_eventName = method.GetName();
- handlerInformation->m_displayName = method.GetName();
- handlerInformation->m_categoryPath = scriptEvent.GetCategory();
- handlerInformation->m_busId = busId;
- handlerInformation->m_eventId = eventId;
- handlerInformation->m_nodeIdentifier = receiverIdentifier;
- m_registeredNodes.emplace(AZStd::make_pair(receiverIdentifier, handlerInformation));
- ScriptEventSenderNodeModelInformation* senderInformation = aznew ScriptEventSenderNodeModelInformation();
- senderInformation->m_titlePaletteOverride = "MethodNodeTitlePalette";
- senderInformation->m_busName = scriptEvent.GetName();
- senderInformation->m_eventName = method.GetName();
- senderInformation->m_displayName = method.GetName();
- senderInformation->m_categoryPath = scriptEvent.GetCategory();
- senderInformation->m_busId = busId;
- senderInformation->m_eventId = eventId;
- senderInformation->m_nodeIdentifier = senderIdentifier;
- m_registeredNodes.emplace(AZStd::make_pair(senderIdentifier, senderInformation));
- m_assetMapping.insert(AZStd::make_pair(scriptEventAsset->GetId(), senderIdentifier));
- m_assetMapping.insert(AZStd::make_pair(scriptEventAsset->GetId(), receiverIdentifier));
- identifiers.emplace_back(senderIdentifier);
- identifiers.emplace_back(receiverIdentifier);
- }
- return identifiers;
- }
- void NodePaletteModel::RegisterDefaultCateogryInformation()
- {
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "ComparisonNodeTitlePalette";
- m_categoryInformation["Math/Comparisions"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "CoreNodeTitlePalette";
- m_categoryInformation["Core"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "LogicNodeTitlePalette";
- m_categoryInformation["Logic"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "MathNodeTitlePalette";
- m_categoryInformation["Math"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "OperatorsNodeTitlePalette";
- m_categoryInformation["Operators"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "StringNodeTitlePalette";
- m_categoryInformation["String"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "TimeNodeTitlePalette";
- m_categoryInformation["Timing"] = categoryInformation;
- }
- {
- CategoryInformation categoryInformation;
- categoryInformation.m_paletteOverride = "TestingNodeTitlePalette";
- m_categoryInformation["Utilities/Unit Testing"] = categoryInformation;
- }
- }
- void NodePaletteModel::RegisterCategoryInformation(const AZStd::string& category, const CategoryInformation& categoryInformation)
- {
- auto categoryIter = m_categoryInformation.find(category);
- if (categoryIter == m_categoryInformation.end())
- {
- m_categoryInformation[category] = categoryInformation;
- }
- }
- const CategoryInformation* NodePaletteModel::FindCategoryInformation(const AZStd::string& categoryStyle) const
- {
- auto categoryIter = m_categoryInformation.find(categoryStyle);
- if (categoryIter != m_categoryInformation.end())
- {
- return &(categoryIter->second);
- }
- return nullptr;
- }
- const CategoryInformation* NodePaletteModel::FindBestCategoryInformation(AZStd::string_view categoryView) const
- {
- const CategoryInformation* bestCategoryFit = nullptr;
- auto categoryIter = m_categoryInformation.find(categoryView);
- size_t offset = AZStd::string_view::npos;
- AZStd::string_view categoryTrail = categoryView;
- while (categoryIter == m_categoryInformation.end() && !categoryTrail.empty())
- {
- size_t seperator = categoryTrail.find_last_of('/', offset);
- if (seperator == AZStd::string_view::npos)
- {
- categoryTrail = {};
- }
- else
- {
- categoryTrail = categoryTrail.substr(0, seperator - 1);
- categoryIter = m_categoryInformation.find(categoryTrail);
- }
- }
- if (categoryIter != m_categoryInformation.end())
- {
- bestCategoryFit = &(categoryIter->second);
- }
- return bestCategoryFit;
- }
- const NodePaletteModelInformation* NodePaletteModel::FindNodePaletteInformation(const ScriptCanvas::NodeTypeIdentifier& nodeType) const
- {
- auto registryIter = m_registeredNodes.find(nodeType);
- if (registryIter != m_registeredNodes.end())
- {
- return registryIter->second;
- }
- return nullptr;
- }
- const NodePaletteModel::NodePaletteRegistry& NodePaletteModel::GetNodeRegistry() const
- {
- return m_registeredNodes;
- }
- GraphCanvas::GraphCanvasTreeItem* NodePaletteModel::CreateCategoryNode(AZStd::string_view categoryPath, AZStd::string_view categoryName, GraphCanvas::GraphCanvasTreeItem* parentItem) const
- {
- GraphCanvas::NodePaletteTreeItem* treeItem = parentItem->CreateChildNode<GraphCanvas::NodePaletteTreeItem>(categoryName, ScriptCanvasEditor::AssetEditorId);
- const CategoryInformation* categoryInformation = FindCategoryInformation(categoryPath);
- if (categoryInformation)
- {
- if (!categoryInformation->m_tooltip.empty())
- {
- treeItem->SetToolTip(categoryInformation->m_tooltip.c_str());
- }
- if (!categoryInformation->m_paletteOverride.empty())
- {
- treeItem->SetTitlePalette(categoryInformation->m_paletteOverride.c_str());
- }
- if (!categoryInformation->m_styleOverride.empty())
- {
- treeItem->SetStyleOverride(categoryInformation->m_styleOverride.c_str());
- }
- }
- return treeItem;
- }
- void NodePaletteModel::OnRowsInserted(const QModelIndex& parentIndex, int first, int last)
- {
- for (int i = first; i <= last; ++i)
- {
- QModelIndex modelIndex = m_assetModel->index(i, 0, parentIndex);
- QModelIndex sourceIndex = m_assetModel->mapToSource(modelIndex);
- AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry = reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
- auto nodeTypeIdentifiers = ProcessAsset(entry);
- for (auto nodeTypeIdentifier : nodeTypeIdentifiers)
- {
- auto nodeIter = m_registeredNodes.find(nodeTypeIdentifier);
- if (nodeIter != m_registeredNodes.end())
- {
- NodePaletteModelNotificationBus::Event(m_paletteId, &NodePaletteModelNotifications::OnAssetNodeAdded, nodeIter->second);
- }
- }
- }
- }
- void NodePaletteModel::OnRowsAboutToBeRemoved(const QModelIndex& parentIndex, int first, int last)
- {
- for (int i = first; i <= last; ++i)
- {
- QModelIndex modelIndex = m_assetModel->index(first, 0, parentIndex);
- QModelIndex sourceIndex = m_assetModel->mapToSource(modelIndex);
- const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry = reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
- if (entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product)
- {
- const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* productEntry = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry*>(entry);
- if (productEntry)
- {
- RemoveAsset(productEntry->GetAssetId());
- }
- }
- }
- }
- void NodePaletteModel::TraverseTree(QModelIndex index)
- {
- QModelIndex sourceIndex = m_assetModel->mapToSource(index);
- AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry = reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
- ProcessAsset(entry);
- int rowCount = m_assetModel->rowCount(index);
- for (int i = 0; i < rowCount; ++i)
- {
- QModelIndex nextIndex = m_assetModel->index(i, 0, index);
- TraverseTree(nextIndex);
- }
- }
- AZStd::vector<ScriptCanvas::NodeTypeIdentifier> NodePaletteModel::ProcessAsset(AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
- {
- AZ_PROFILE_SCOPE(NodePaletteModel, "NodePaletteModel::RegisterScriptEvent");
- AZStd::lock_guard<AZStd::recursive_mutex> myLocker(m_mutex);
- if (entry)
- {
- if (entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product)
- {
- const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* productEntry = static_cast<const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry*>(entry);
- if (productEntry->GetAssetType() == azrtti_typeid<ScriptEvents::ScriptEventsAsset>())
- {
- const AZ::Data::AssetId& assetId = productEntry->GetAssetId();
- auto busAsset = AZ::Data::AssetManager::Instance().GetAsset(assetId, azrtti_typeid<ScriptEvents::ScriptEventsAsset>(), AZ::Data::AssetLoadBehavior::PreLoad);
- busAsset.BlockUntilLoadComplete();
- if (busAsset.IsReady())
- {
- ScriptEvents::ScriptEventsAsset* data = busAsset.GetAs<ScriptEvents::ScriptEventsAsset>();
- return RegisterScriptEvent(data);
- }
- else
- {
- AZ_TracePrintf("NodePaletteModel", "Could not refresh node palette properly, the asset failed to load correctly.");
- }
- }
- }
- }
- return AZStd::vector<ScriptCanvas::NodeTypeIdentifier>();
- }
- void NodePaletteModel::RemoveAsset(const AZ::Data::AssetId& assetId)
- {
- auto mapRange = m_assetMapping.equal_range(assetId);
- for (auto rangeIter = mapRange.first; rangeIter != mapRange.second; ++rangeIter)
- {
- auto nodeIter = m_registeredNodes.find(rangeIter->second);
- if (nodeIter != m_registeredNodes.end())
- {
- NodePaletteModelNotificationBus::Event(m_paletteId, &NodePaletteModelNotifications::OnAssetNodeRemoved, nodeIter->second);
- delete nodeIter->second;
- m_registeredNodes.erase(nodeIter);
- }
- }
- }
- void NodePaletteModel::ClearRegistry()
- {
- for (auto& mapPair : m_registeredNodes)
- {
- delete mapPair.second;
- }
- m_registeredNodes.clear();
- m_categoryInformation.clear();
- }
- }
|