Interpreter.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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/Framework/Interpreter.h>
  9. #include <AzCore/Component/TickBus.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <Builder/ScriptCanvasBuilder.h>
  13. #include <ScriptCanvas/Bus/ScriptCanvasBus.h>
  14. namespace ScriptCanvasEditor
  15. {
  16. using namespace ScriptCanvas;
  17. using namespace ScriptCanvasBuilder;
  18. Interpreter::Interpreter()
  19. {
  20. m_handlerPropertiesChanged = m_configuration.ConnectToPropertiesChanged([this](const Configuration&) { OnPropertiesChanged(); });
  21. m_handlerSourceCompiled = m_configuration.ConnectToSourceCompiled([this](const Configuration&) { OnSourceCompiled(); });
  22. m_handlerSourceFailed = m_configuration.ConnectToSourceFailed([this](const Configuration&) { OnSourceFailed(); });
  23. // #scriptcanvas_component_extension
  24. m_configuration.SetAcceptsComponentScript(false);
  25. m_handlerUnacceptedComponentScript = m_configuration.ConnectToIncompatilbleScript([this](const Configuration&) { OnSourceIncompatible(); });
  26. }
  27. Interpreter::~Interpreter()
  28. {
  29. DataSystemAssetNotificationsBus::Handler::BusDisconnect();
  30. }
  31. AZ::EventHandler<const Interpreter&> Interpreter::ConnectOnStatusChanged(AZStd::function<void(const Interpreter&)>&& function) const
  32. {
  33. AZ::EventHandler<const Interpreter&> handler(function);
  34. handler.Connect(m_onStatusChanged);
  35. return handler;
  36. }
  37. bool Interpreter::Execute()
  38. {
  39. if (m_executor.IsExecutable())
  40. {
  41. AZ::SystemTickBus::QueueFunction([this]()
  42. {
  43. MutexLock lock(m_mutex);
  44. if ((m_runtimePropertiesDirty || !m_executor.IsPure()) && m_executor.GetRuntimeOverrides().m_runtimeAsset.IsReady())
  45. {
  46. InitializeExecution(m_executor.GetRuntimeOverrides().m_runtimeAsset);
  47. m_runtimePropertiesDirty = false;
  48. }
  49. if (m_executor.IsExecutable())
  50. {
  51. SetSatus(InterpreterStatus::Running);
  52. if (m_executor.IsPure())
  53. {
  54. m_executor.Execute();
  55. SetSatus(InterpreterStatus::Ready);
  56. }
  57. else
  58. {
  59. m_executor.Execute();
  60. }
  61. }
  62. });
  63. return true;
  64. }
  65. else
  66. {
  67. return false;
  68. }
  69. }
  70. const Configuration& Interpreter::GetConfiguration() const
  71. {
  72. return m_configuration;
  73. }
  74. InterpreterStatus Interpreter::GetStatus() const
  75. {
  76. return m_status;
  77. }
  78. AZStd::string_view Interpreter::GetStatusString() const
  79. {
  80. return ToString(m_status);
  81. }
  82. bool Interpreter::InitializeExecution(ScriptCanvas::RuntimeAssetPtr asset)
  83. {
  84. if (asset.Get())
  85. {
  86. if (m_executor.IsExecutable())
  87. {
  88. m_executor.StopAndClearExecutable();
  89. }
  90. auto overrides = ConvertToRuntime(m_configuration.GetOverrides());
  91. if (ReplaceAsset(overrides, asset))
  92. {
  93. m_executor.TakeRuntimeDataOverrides(AZStd::move(overrides));
  94. m_executor.Initialize();
  95. m_runtimePropertiesDirty = false;
  96. return true;
  97. }
  98. }
  99. return false;
  100. }
  101. bool Interpreter::IsExecutable() const
  102. {
  103. return m_executor.IsExecutable();
  104. }
  105. Configuration& Interpreter::ModConfiguration()
  106. {
  107. return m_configuration;
  108. }
  109. void Interpreter::OnAssetNotReady()
  110. {
  111. MutexLock lock(m_mutex);
  112. if (m_executor.IsExecutable())
  113. {
  114. m_executor.StopAndClearExecutable();
  115. }
  116. m_runtimePropertiesDirty = true;
  117. SetSatus(InterpreterStatus::Pending);
  118. }
  119. void Interpreter::OnPropertiesChanged()
  120. {
  121. m_runtimePropertiesDirty = true;
  122. DataSystemAssetNotificationsBus::Handler::BusDisconnect();
  123. DataSystemAssetNotificationsBus::Handler::BusConnect(m_configuration.GetSource().Id());
  124. }
  125. void Interpreter::OnReady(ScriptCanvas::RuntimeAssetPtr asset)
  126. {
  127. MutexLock lock(m_mutex);
  128. if (InitializeExecution(asset))
  129. {
  130. SetSatus(InterpreterStatus::Ready);
  131. }
  132. else
  133. {
  134. SetSatus(InterpreterStatus::Misconfigured);
  135. }
  136. }
  137. void Interpreter::OnSourceCompiled()
  138. {
  139. MutexLock lock(m_mutex);
  140. m_runtimePropertiesDirty = true;
  141. SetSatus(InterpreterStatus::Configured);
  142. BuilderAssetResult assetResult;
  143. DataSystemAssetRequestsBus::BroadcastResult(assetResult, &DataSystemAssetRequests::LoadAsset, m_configuration.GetSource());
  144. if (assetResult.status == BuilderAssetStatus::Ready)
  145. {
  146. OnReady(assetResult.data);
  147. }
  148. }
  149. void Interpreter::OnSourceFailed()
  150. {
  151. MutexLock lock(m_mutex);
  152. if (m_executor.IsExecutable())
  153. {
  154. m_executor.StopAndClearExecutable();
  155. }
  156. m_runtimePropertiesDirty = true;
  157. SetSatus(InterpreterStatus::Misconfigured);
  158. }
  159. void Interpreter::OnSourceIncompatible()
  160. {
  161. MutexLock lock(m_mutex);
  162. if (m_executor.IsExecutable())
  163. {
  164. m_executor.StopAndClearExecutable();
  165. }
  166. m_runtimePropertiesDirty = true;
  167. SetSatus(InterpreterStatus::Incompatible);
  168. }
  169. void Interpreter::Reflect(AZ::ReflectContext* context)
  170. {
  171. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  172. {
  173. serializeContext->Class<Interpreter>()
  174. ->Field("sourceName", &Interpreter::m_configuration)
  175. ;
  176. if (auto editContext = serializeContext->GetEditContext())
  177. {
  178. editContext->Class<Interpreter>("Script Canvas Interpreter", "Select, Configure, and Execute a ScriptCanvas Graph")
  179. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  180. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  181. ->DataElement(AZ::Edit::UIHandlers::Default, &Interpreter::m_configuration, "Configuration", "Configuration")
  182. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  183. ;
  184. }
  185. }
  186. }
  187. void Interpreter::RefreshConfiguration()
  188. {
  189. MutexLock lock(m_mutex);
  190. m_configuration.Refresh();
  191. m_runtimePropertiesDirty = true;
  192. }
  193. void Interpreter::ResetUserData()
  194. {
  195. MutexLock lock(m_mutex);
  196. m_executor.TakeUserData(ExecutionUserData(Execution::TypeErasedReference(this, azrtti_typeid(this))));
  197. m_runtimePropertiesDirty = true;
  198. }
  199. void Interpreter::SetScript(SourceHandle source)
  200. {
  201. MutexLock lock(m_mutex);
  202. m_configuration.Refresh(source);
  203. }
  204. void Interpreter::SetSatus(InterpreterStatus status)
  205. {
  206. if (status != m_status)
  207. {
  208. m_status = status;
  209. m_onStatusChanged.Signal(*this);
  210. }
  211. }
  212. void Interpreter::Stop()
  213. {
  214. MutexLock lock(m_mutex);
  215. if (m_executor.IsExecutable())
  216. {
  217. AZ::SystemTickBus::QueueFunction([this]()
  218. {
  219. MutexLock lock(m_mutex);
  220. if (m_executor.IsExecutable())
  221. {
  222. m_executor.StopAndKeepExecutable();
  223. }
  224. SystemRequestBus::Broadcast(&SystemRequests::RequestGarbageCollect);
  225. if (m_executor.IsExecutable())
  226. {
  227. SetSatus(InterpreterStatus::Ready);
  228. }
  229. else
  230. {
  231. SetSatus(InterpreterStatus::Pending);
  232. }
  233. });
  234. }
  235. else
  236. {
  237. SetSatus(InterpreterStatus::Pending);
  238. }
  239. }
  240. void Interpreter::TakeUserData(ExecutionUserData&& runtimeUserData)
  241. {
  242. MutexLock lock(m_mutex);
  243. m_executor.TakeUserData(AZStd::move(runtimeUserData));
  244. m_runtimePropertiesDirty = true;
  245. }
  246. }