/* * 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 AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option") #include AZ_POP_DISABLE_WARNING #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ScriptCanvasEditor { AZStd::optional CreateFromAnyPath(const SourceHandle& source, const AZ::IO::Path& path) { return CompleteDescription(SourceHandle::FromRelativePath(source, path)); } AZStd::optional CompleteDescription(const SourceHandle& source) { using namespace AzToolsFramework; if (AssetSystemRequestBus::Events* assetSystem = AssetSystemRequestBus::FindFirstHandler()) { if (!source.Id().IsNull()) { AZStd::string watchFolderID; AZ::Data::AssetInfo assetInfoID; if (assetSystem->GetSourceInfoBySourceUUID(source.Id(), assetInfoID, watchFolderID)) { return SourceHandle::MarkAbsolutePath ( SourceHandle::FromRelativePath(source, assetInfoID.m_assetId.m_guid, assetInfoID.m_relativePath.c_str()) , (AZ::IO::Path(watchFolderID) / AZ::IO::Path(assetInfoID.m_relativePath))); } } if (!source.RelativePath().empty()) { AZStd::string watchFolderPath; AZ::Data::AssetInfo assetInfoPath; if (assetSystem->GetSourceInfoBySourcePath(source.RelativePath().c_str(), assetInfoPath, watchFolderPath) && assetInfoPath.m_assetId.IsValid()) { return SourceHandle::MarkAbsolutePath ( SourceHandle::FromRelativePath(source, assetInfoPath.m_assetId.m_guid, assetInfoPath.m_relativePath.c_str()) , (AZ::IO::Path(watchFolderPath) / AZ::IO::Path(assetInfoPath.m_relativePath))); } } } return AZStd::nullopt; } bool CompleteDescriptionInPlace(SourceHandle& source) { if (auto completed = CompleteDescription(source)) { source = *completed; return true; } else { return false; } } ////////////////////////// // NodeIdentifierFactory ////////////////////////// ScriptCanvas::NodeTypeIdentifier NodeIdentifierFactory::ConstructNodeIdentifier(const GraphCanvas::GraphCanvasTreeItem* treeItem) { ScriptCanvas::NodeTypeIdentifier resultHash = 0; if (auto getVariableMethodTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructGetVariableNodeIdentifier(getVariableMethodTreeItem->GetVariableId()); } else if (auto setVariableMethodTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructSetVariableNodeIdentifier(setVariableMethodTreeItem->GetVariableId()); } else if (auto classMethodTreeItem = azrtti_cast(treeItem)) { if (classMethodTreeItem->IsOverload()) { resultHash = ScriptCanvas::NodeUtils::ConstructMethodOverloadedNodeIdentifier(classMethodTreeItem->GetMethodName()); } else { resultHash = ScriptCanvas::NodeUtils::ConstructMethodNodeIdentifier(classMethodTreeItem->GetClassMethodName(), classMethodTreeItem->GetMethodName(), classMethodTreeItem->GetPropertyStatus()); } } else if (auto globalMethodTreeItem = azrtti_cast(treeItem); globalMethodTreeItem != nullptr) { resultHash = ScriptCanvas::NodeUtils::ConstructGlobalMethodNodeIdentifier(globalMethodTreeItem->GetMethodName()); } else if (auto customNodeTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructCustomNodeIdentifier(customNodeTreeItem->GetTypeId()); } else if (auto sendEbusEventTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructEBusEventSenderIdentifier(sendEbusEventTreeItem->GetBusId(), sendEbusEventTreeItem->GetEventId()); } else if (auto handleEbusEventTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructEBusEventReceiverIdentifier(handleEbusEventTreeItem->GetBusId(), handleEbusEventTreeItem->GetEventId()); } else if (auto functionTreeItem = azrtti_cast(treeItem)) { resultHash = ScriptCanvas::NodeUtils::ConstructFunctionNodeIdentifier(functionTreeItem->GetAssetId()); } return resultHash; } AZStd::vector< ScriptCanvas::NodeTypeIdentifier > NodeIdentifierFactory::ConstructNodeIdentifiers(const GraphCanvas::GraphCanvasTreeItem* treeItem) { AZStd::vector< ScriptCanvas::NodeTypeIdentifier > nodeIdentifiers; if (auto scriptEventTreeItem = azrtti_cast(treeItem)) { nodeIdentifiers.emplace_back(ScriptCanvas::NodeUtils::ConstructScriptEventReceiverIdentifier(scriptEventTreeItem->GetBusIdentifier(), scriptEventTreeItem->GetEventIdentifier())); nodeIdentifiers.emplace_back(ScriptCanvas::NodeUtils::ConstructSendScriptEventIdentifier(scriptEventTreeItem->GetBusIdentifier(), scriptEventTreeItem->GetEventIdentifier())); } else { nodeIdentifiers.emplace_back(ConstructNodeIdentifier(treeItem)); } return nodeIdentifiers; } ////////////////////////// // GraphStatisticsHelper ////////////////////////// void GraphStatisticsHelper::Reflect(AZ::ReflectContext* reflectContext) { AZ::SerializeContext* serializeContext = azrtti_cast(reflectContext); if (serializeContext) { serializeContext->Class() ->Version(1) ->Field("InstanceCounter", &GraphStatisticsHelper::m_nodeIdentifierCount) ; } } void GraphStatisticsHelper::PopulateStatisticData(const EditorGraph* editorGraph) { // Opportunistically use this time to refresh out node count array. m_nodeIdentifierCount.clear(); for (auto* nodeEntity : editorGraph->GetNodeEntities()) { auto nodeComponent = AZ::EntityUtils::FindFirstDerivedComponent(nodeEntity); if (nodeComponent) { if (auto ebusHandlerNode = azrtti_cast(nodeComponent)) { GraphCanvas::NodeId graphCanvasNodeId; SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, nodeEntity->GetId(), &SceneMemberMappingRequests::GetGraphCanvasEntityId); const ScriptCanvas::Nodes::Core::EBusEventHandler::EventMap& events = ebusHandlerNode->GetEvents(); ScriptCanvas::EBusBusId busId = ebusHandlerNode->GetEBusId(); for (const auto& eventPair : events) { bool hasEvent = false; EBusHandlerNodeDescriptorRequestBus::EventResult(hasEvent, graphCanvasNodeId, &EBusHandlerNodeDescriptorRequests::ContainsEvent, eventPair.second.m_eventId); // In case we are populating from an uncreated scene if we don't have a valid graph canvas node id // just accept everything. We can overreport on unknown data for now. if (hasEvent || !graphCanvasNodeId.IsValid()) { RegisterNodeType(ScriptCanvas::NodeUtils::ConstructEBusEventReceiverIdentifier(busId, eventPair.second.m_eventId)); } } } else if (auto scriptEventHandler = azrtti_cast(nodeComponent)) { GraphCanvas::NodeId graphCanvasNodeId; SceneMemberMappingRequestBus::EventResult(graphCanvasNodeId, nodeEntity->GetId(), &SceneMemberMappingRequests::GetGraphCanvasEntityId); EBusHandlerNodeDescriptorRequests* ebusDescriptorRequests = EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasNodeId); if (ebusDescriptorRequests == nullptr) { continue; } AZStd::vector< HandlerEventConfiguration > eventConfigurations = ebusDescriptorRequests->GetEventConfigurations(); ScriptCanvas::EBusBusId busId = scriptEventHandler->GetBusId(); for (const auto& eventConfiguration : eventConfigurations) { bool hasEvent = ebusDescriptorRequests->ContainsEvent(eventConfiguration.m_eventId); // In case we are populating from an uncreated scene if we don't have a valid graph canvas node id // just accept everything. We can overreport on unknown data for now. if (hasEvent) { RegisterNodeType(ScriptCanvas::NodeUtils::ConstructScriptEventReceiverIdentifier(busId, eventConfiguration.m_eventId)); } } } else { ScriptCanvas::NodeTypeIdentifier nodeType = nodeComponent->GetNodeType(); // Fallback in case something isn't initialized for whatever reason if (nodeType == 0) { nodeType = ScriptCanvas::NodeUtils::ConstructNodeType(nodeComponent); } RegisterNodeType(nodeType); } } } } void GraphStatisticsHelper::RegisterNodeType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier) { auto nodeIter = m_nodeIdentifierCount.find(nodeTypeIdentifier); if (nodeIter == m_nodeIdentifierCount.end()) { m_nodeIdentifierCount.emplace(AZStd::make_pair(nodeTypeIdentifier, 1)); } else { nodeIter->second++; } } }