LoggingDataAggregator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Editor/View/Widgets/LoggingPanel/LoggingDataAggregator.h>
  9. namespace ScriptCanvasEditor
  10. {
  11. //////////////////////////
  12. // LoggingDataAggregator
  13. //////////////////////////
  14. LoggingDataAggregator::LoggingDataAggregator()
  15. : m_id(AZ::Entity::MakeId())
  16. , m_ignoreRegistrations(false)
  17. , m_hasAnchor(false)
  18. , m_anchorTimeStamp(0)
  19. {
  20. LoggingDataRequestBus::Handler::BusConnect(m_id);
  21. m_debugLogRoot = aznew DebugLogRootItem();
  22. }
  23. LoggingDataAggregator::~LoggingDataAggregator()
  24. {
  25. }
  26. const LoggingDataId& LoggingDataAggregator::GetDataId() const
  27. {
  28. return m_id;
  29. }
  30. const LoggingDataAggregator* LoggingDataAggregator::FindLoggingData() const
  31. {
  32. return this;
  33. }
  34. void LoggingDataAggregator::EnableRegistration(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
  35. {
  36. if (m_ignoreRegistrations)
  37. {
  38. return;
  39. }
  40. bool signalAddition = false;
  41. if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
  42. {
  43. auto insertResult = m_loggedAssetSet.insert(graphIdentifier);
  44. signalAddition = insertResult.second;
  45. }
  46. else
  47. {
  48. signalAddition = true;
  49. auto equalRange = m_loggingEntityMapping.equal_range(namedEntityId);
  50. for (auto mapIter = equalRange.first; mapIter != equalRange.second; ++mapIter)
  51. {
  52. if (mapIter->second == graphIdentifier)
  53. {
  54. signalAddition = false;
  55. break;
  56. }
  57. }
  58. if (signalAddition)
  59. {
  60. m_loggingEntityMapping.insert(AZStd::make_pair(namedEntityId, graphIdentifier));
  61. }
  62. }
  63. if (signalAddition)
  64. {
  65. m_ignoreRegistrations = true;
  66. LoggingDataNotificationBus::Event(GetDataId(), &LoggingDataNotifications::OnEnabledStateChanged, true, namedEntityId, graphIdentifier);
  67. m_ignoreRegistrations = false;
  68. OnRegistrationEnabled(namedEntityId, graphIdentifier);
  69. }
  70. }
  71. void LoggingDataAggregator::DisableRegistration(const AZ::NamedEntityId& namedEntityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
  72. {
  73. if (m_ignoreRegistrations)
  74. {
  75. return;
  76. }
  77. bool signalErase = false;
  78. if (graphIdentifier.m_componentId == k_dynamicallySpawnedControllerId)
  79. {
  80. size_t eraseCount = m_loggedAssetSet.erase(graphIdentifier);
  81. signalErase = eraseCount > 0;
  82. }
  83. else
  84. {
  85. auto equalRange = m_loggingEntityMapping.equal_range(namedEntityId);
  86. for (auto mapIter = equalRange.first; mapIter != equalRange.second; ++mapIter)
  87. {
  88. if (mapIter->second == graphIdentifier)
  89. {
  90. signalErase = true;
  91. m_loggingEntityMapping.erase(mapIter);
  92. break;
  93. }
  94. }
  95. }
  96. if (signalErase)
  97. {
  98. m_ignoreRegistrations = true;
  99. LoggingDataNotificationBus::Event(GetDataId(), &LoggingDataNotifications::OnEnabledStateChanged, false, namedEntityId, graphIdentifier);
  100. m_ignoreRegistrations = false;
  101. OnRegistrationDisabled(namedEntityId, graphIdentifier);
  102. }
  103. }
  104. AZ::NamedEntityId LoggingDataAggregator::FindNamedEntityId(const AZ::EntityId& entityId)
  105. {
  106. auto cacheIter = m_entityNameCache.find(entityId);
  107. if (cacheIter != m_entityNameCache.end())
  108. {
  109. return AZ::NamedEntityId(entityId, cacheIter->second);
  110. }
  111. return AZ::NamedEntityId(entityId, "<unknown>");
  112. }
  113. const EntityGraphRegistrationMap& LoggingDataAggregator::GetEntityGraphRegistrationMap() const
  114. {
  115. return m_registrationMap;
  116. }
  117. const LoggingEntityMap& LoggingDataAggregator::GetLoggingEntityMap() const
  118. {
  119. return m_loggingEntityMapping;
  120. }
  121. const LoggingAssetSet& LoggingDataAggregator::GetLoggingAssetSet() const
  122. {
  123. return m_loggedAssetSet;
  124. }
  125. void LoggingDataAggregator::ProcessSignal([[maybe_unused]] const ScriptCanvas::Signal& signal)
  126. {
  127. //GraphIdentifier identifier;
  128. //identifier.m_entityId = signal.m_runtimeEntity;
  129. //identifier.m_assetId = signal.m_graphCount.m_assetId;
  130. //identifier.m_sequenceId = signal.m_graphCount.m_count;
  131. //auto aggregateIter = m_lastAggregateItemMap.find(identifier);
  132. //if (aggregateIter != m_lastAggregateItemMap.end())
  133. //{
  134. // /*
  135. // if (aggregateIter->second->TryProcessSignal(signal))
  136. // {
  137. // return;
  138. // }
  139. // */
  140. // m_lastAggregateItemMap.erase(identifier);
  141. //}
  142. // Signal events are ambiguous on their own. Will need a secondary source of information to be able to disambiguate them.
  143. }
  144. void LoggingDataAggregator::ProcessNodeStateChanged([[maybe_unused]] const ScriptCanvas::NodeStateChange& stateChangeSignal)
  145. {
  146. }
  147. void LoggingDataAggregator::ProcessInputSignal(const ScriptCanvas::InputSignal& inputSignal)
  148. {
  149. if (!m_hasAnchor)
  150. {
  151. m_hasAnchor = true;
  152. m_anchorTimeStamp = inputSignal.GetTimestamp();
  153. }
  154. // For every input we always want to make a new element.
  155. ScriptCanvas::Timestamp relativeTimeStamp = inputSignal.GetTimestamp() - m_anchorTimeStamp;
  156. ExecutionLogTreeItem* treeItem = m_debugLogRoot->CreateExecutionItem(GetDataId(), inputSignal.m_nodeType, inputSignal, inputSignal.m_endpoint.GetNamedNodeId());
  157. m_lastAggregateItemMap[inputSignal] = treeItem;
  158. treeItem->RegisterExecutionInput(ScriptCanvas::Endpoint(), inputSignal.m_endpoint.GetSlotId(), inputSignal.m_endpoint.GetSlotName(), AZStd::chrono::milliseconds(relativeTimeStamp));
  159. for (auto dataMap : inputSignal.m_data)
  160. {
  161. AZStd::string valueString = dataMap.second.m_datum.ToString();
  162. treeItem->RegisterDataInput(ScriptCanvas::Endpoint(), dataMap.first, dataMap.first.m_name, valueString, GetTreeRoot()->GetUpdatePolicy() == DebugLogRootItem::UpdatePolicy::RealTime);
  163. }
  164. }
  165. void LoggingDataAggregator::ProcessOutputSignal(const ScriptCanvas::OutputSignal& outputSignal)
  166. {
  167. if (!m_hasAnchor)
  168. {
  169. m_hasAnchor = true;
  170. m_anchorTimeStamp = outputSignal.GetTimestamp();
  171. }
  172. // For the output we want to correlate it with the appropriate starting node
  173. auto lastAggregateIter = m_lastAggregateItemMap.find(outputSignal);
  174. ExecutionLogTreeItem* treeItem = nullptr;
  175. if (lastAggregateIter != m_lastAggregateItemMap.end())
  176. {
  177. treeItem = lastAggregateIter->second;
  178. if (treeItem->HasExecutionOutput()
  179. || treeItem->GetNodeId() != outputSignal.m_endpoint.GetNodeId())
  180. {
  181. treeItem = nullptr;
  182. }
  183. }
  184. if (treeItem == nullptr)
  185. {
  186. treeItem = m_debugLogRoot->CreateExecutionItem(GetDataId(), outputSignal.m_nodeType, outputSignal, outputSignal.m_endpoint.GetNamedNodeId());
  187. m_lastAggregateItemMap[outputSignal] = treeItem;
  188. }
  189. ScriptCanvas::Timestamp relativeTimeStamp = outputSignal.GetTimestamp() - m_anchorTimeStamp;
  190. treeItem->RegisterExecutionOutput(outputSignal.m_endpoint.GetSlotId(), outputSignal.m_endpoint.GetSlotName(), AZStd::chrono::milliseconds(relativeTimeStamp));
  191. for (auto dataMap : outputSignal.m_data)
  192. {
  193. AZStd::string valueString = dataMap.second.m_datum.ToString();
  194. treeItem->RegisterDataOutput(dataMap.first, dataMap.first.m_name, valueString, GetTreeRoot()->GetUpdatePolicy() == DebugLogRootItem::UpdatePolicy::RealTime);
  195. }
  196. }
  197. void LoggingDataAggregator::ProcessAnnotateNode(const ScriptCanvas::AnnotateNodeSignal& annotateNodeSignal)
  198. {
  199. auto lastAggregateIter = m_lastAggregateItemMap.find(annotateNodeSignal);
  200. if (lastAggregateIter != m_lastAggregateItemMap.end())
  201. {
  202. ExecutionLogTreeItem* treeItem = lastAggregateIter->second;
  203. treeItem->RegisterAnnotation(annotateNodeSignal, GetTreeRoot()->GetUpdatePolicy() == DebugLogRootItem::UpdatePolicy::RealTime);
  204. }
  205. }
  206. void LoggingDataAggregator::ProcessVariableChangedSignal([[maybe_unused]] const ScriptCanvas::VariableChange& variableChangeSignal)
  207. {
  208. }
  209. DebugLogRootItem* LoggingDataAggregator::GetTreeRoot() const
  210. {
  211. return m_debugLogRoot;
  212. }
  213. void LoggingDataAggregator::RegisterEntityName(const AZ::EntityId& entityId, AZStd::string_view entityName)
  214. {
  215. auto nameIter = m_entityNameCache.find(entityId);
  216. if (nameIter == m_entityNameCache.end())
  217. {
  218. m_entityNameCache[entityId] = entityName;
  219. }
  220. }
  221. void LoggingDataAggregator::UnregisterEntityName(const AZ::EntityId& entityId)
  222. {
  223. // While we are capturing, we never want to update this list.
  224. if (!IsCapturingData())
  225. {
  226. m_entityNameCache.erase(entityId);
  227. }
  228. }
  229. void LoggingDataAggregator::OnRegistrationEnabled(const AZ::NamedEntityId&, const ScriptCanvas::GraphIdentifier&)
  230. {
  231. }
  232. void LoggingDataAggregator::OnRegistrationDisabled(const AZ::NamedEntityId&, const ScriptCanvas::GraphIdentifier&)
  233. {
  234. }
  235. void LoggingDataAggregator::ResetLog()
  236. {
  237. m_debugLogRoot->ResetData();
  238. }
  239. void LoggingDataAggregator::ResetData()
  240. {
  241. m_endpointData.clear();
  242. m_variableData.clear();
  243. for (const auto& registrationPair : m_registrationMap)
  244. {
  245. LoggingDataNotificationBus::Event(GetDataId(), &LoggingDataNotifications::OnEntityGraphUnregistered, registrationPair.first, registrationPair.second);
  246. }
  247. m_registrationMap.clear();
  248. // Entity registrations are all transient. We need to clear them when we reset data.
  249. // The assets should be static, so we can persist them.
  250. m_loggingEntityMapping.clear();
  251. m_lastAggregateItemMap.clear();
  252. m_lastExecutionThreadMap.clear();
  253. if (!IsCapturingData())
  254. {
  255. m_entityNameCache.clear();
  256. }
  257. m_hasAnchor = false;
  258. m_anchorTimeStamp = ScriptCanvas::Timestamp(0);
  259. }
  260. void LoggingDataAggregator::RegisterScriptCanvas(const AZ::NamedEntityId& entityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
  261. {
  262. bool foundMatch = false;
  263. auto matchedRange = m_registrationMap.equal_range(entityId);
  264. for (auto mapIter = matchedRange.first; mapIter != matchedRange.second; ++mapIter)
  265. {
  266. if (mapIter->second == graphIdentifier)
  267. {
  268. foundMatch = true;
  269. AZ_Warning("ScriptCanvas", false, "Received a duplicated registration callback.");
  270. break;
  271. }
  272. }
  273. if (!foundMatch)
  274. {
  275. m_registrationMap.insert(AZStd::make_pair(entityId, graphIdentifier));
  276. LoggingDataNotificationBus::Event(GetDataId(), &LoggingDataNotifications::OnEntityGraphRegistered, entityId, graphIdentifier);
  277. }
  278. }
  279. void LoggingDataAggregator::UnregisterScriptCanvas(const AZ::NamedEntityId& entityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
  280. {
  281. bool foundMatch = false;
  282. {
  283. auto matchedRange = m_registrationMap.equal_range(entityId);
  284. for (auto mapIter = matchedRange.first; mapIter != matchedRange.second; ++mapIter)
  285. {
  286. if (mapIter->second == graphIdentifier)
  287. {
  288. foundMatch = true;
  289. m_registrationMap.erase(mapIter);
  290. break;
  291. }
  292. }
  293. }
  294. {
  295. auto matchedRange = m_loggingEntityMapping.equal_range(entityId);
  296. for (auto mapIter = matchedRange.first; mapIter != matchedRange.second; ++mapIter)
  297. {
  298. if (mapIter->second == graphIdentifier)
  299. {
  300. m_loggingEntityMapping.erase(mapIter);
  301. break;
  302. }
  303. }
  304. }
  305. if (foundMatch)
  306. {
  307. LoggingDataNotificationBus::Event(GetDataId(), &LoggingDataNotifications::OnEntityGraphUnregistered, entityId, graphIdentifier);
  308. }
  309. }
  310. }