IPCServerApp.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include <Atomic/IO/Log.h>
  2. #include <Atomic/IO/FileSystem.h>
  3. #include <Atomic/IO/IOEvents.h>
  4. #include <Atomic/Core/ProcessUtils.h>
  5. #include <Atomic/Core/CoreEvents.h>
  6. #include <Atomic/IPC/IPC.h>
  7. #include <Atomic/IPC/IPCEvents.h>
  8. #include <Atomic/IPC/IPCWorker.h>
  9. #include <Atomic/IPC/IPCBroker.h>
  10. #include <ToolCore/ToolSystem.h>
  11. #include <ToolCore/ToolEnvironment.h>
  12. #include <ToolCore/Project/Project.h>
  13. #include <ToolCore/Project/ProjectSettings.h>
  14. #include <Atomic/UI/SystemUI/DebugHud.h>
  15. #include <AtomicApp/Player/IPCPlayerAppEvents.h>
  16. #include <AtomicJS/Javascript/JSIPCEvents.h>
  17. #include <Atomic/Input/InputEvents.h>
  18. #include "IPCServerApp.h"
  19. #pragma push_macro("PostMessage")
  20. #undef PostMessage
  21. using namespace ToolCore;
  22. namespace Atomic
  23. {
  24. IPCServerApp::IPCServerApp(Context* context) :
  25. AppBase(context),
  26. playerEnabled_(false)
  27. {
  28. }
  29. IPCServerApp::~IPCServerApp()
  30. {
  31. }
  32. void IPCServerApp::Setup()
  33. {
  34. AppBase::Setup();
  35. // Register IPC system
  36. context_->RegisterSubsystem(new IPC(context_));
  37. ToolEnvironment* env = new ToolEnvironment(context_);
  38. context_->RegisterSubsystem(env);
  39. env->Initialize();
  40. ToolSystem* system = new ToolSystem(context_);
  41. context_->RegisterSubsystem(system);
  42. engineParameters_["Headless"] = true;
  43. engineParameters_["LogLevel"] = LOG_INFO;
  44. }
  45. void IPCServerApp::Stop()
  46. {
  47. IPC* ipc = GetSubsystem<IPC>();
  48. if (ipc)
  49. {
  50. ipc->Shutdown();
  51. }
  52. AppBase::Stop();
  53. }
  54. bool IPCServerApp::RunIPCPlayer(const String& projectName, const String& projectPath, const String &addArgs)
  55. {
  56. /* Params to pass in (possibly) from PE
  57. --windowposx 244
  58. --windowposy 157
  59. --windowwidth 1440
  60. --windowheight 806
  61. --resizable
  62. ALSO STUFF TO TELL VSEATOMIC WHICH CUTSCENE TO LAUNCH..app delegate will need to parse run params I think
  63. */
  64. if (playerBroker_.NotNull())
  65. return false;
  66. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  67. ToolSystem* tsystem = GetSubsystem<ToolSystem>();
  68. ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
  69. String projectAssembly = projectName + ".dll";
  70. String projectExe = projectName + ".exe";
  71. String playerBinary = "";
  72. String resourcePath = projectPath + "Resources/" + projectAssembly;
  73. // TODO: We need to configure project as managed
  74. if (fileSystem->FileExists(resourcePath))
  75. {
  76. #ifdef ATOMIC_DEV_BUILD
  77. #ifdef ATOMIC_DEBUG
  78. playerBinary = projectPath + "AtomicNET/Debug/Bin/Desktop/" + projectExe;
  79. #else
  80. playerBinary = projectPath + "AtomicNET/Release/Bin/Desktop/" + projectExe;
  81. #endif
  82. #else
  83. // TODO: We are using the release build of the managed project here, how and when to use debug?
  84. playerBinary = projectPath + "AtomicNET/Release/Bin/Desktop/" + projectExe;
  85. #endif
  86. if (!fileSystem->FileExists(playerBinary))
  87. {
  88. ATOMIC_LOGERRORF("Managed player: %s does not exist", playerBinary.CString());
  89. return false;
  90. }
  91. }
  92. else
  93. {
  94. return false;
  95. }
  96. Vector<String> vargs;
  97. String args = ToString("--player --project \"%s\"", projectPath.CString());
  98. vargs = args.Split(' ');
  99. #ifdef ATOMIC_DEV_BUILD
  100. vargs.Insert(0, ToString("\"%s/Resources/\"", tenv->GetRootSourceDir().CString()));
  101. #else
  102. #ifdef ATOMIC_PLATFORM_OSX
  103. vargs.Insert(0, ToString("\"%s\"", (fileSystem->GetProgramDir() + "../Resources/").CString()));
  104. #else
  105. vargs.Insert(0, ToString("\"%s\"", (fileSystem->GetProgramDir() + "Resources/").CString()));
  106. #endif
  107. #endif
  108. vargs.Insert(0, "--resourcePrefix");
  109. if (addArgs.Length() > 0)
  110. vargs.Insert(0, addArgs.Split(' '));
  111. String dump;
  112. dump.Join(vargs, " ");
  113. ATOMIC_LOGINFOF("Launching Broker %s %s", playerBinary.CString(), dump.CString());
  114. IPC* ipc = GetSubsystem<IPC>();
  115. playerBroker_ = ipc->SpawnWorker(playerBinary, vargs);
  116. if (playerBroker_)
  117. {
  118. SubscribeToEvent(playerBroker_, E_IPCWORKERSTART, ATOMIC_HANDLER(IPCServerApp, HandleIPCWorkerStarted));
  119. SubscribeToEvent(playerBroker_, E_IPCJSERROR, ATOMIC_HANDLER(IPCServerApp, HandleIPCJSError));
  120. SubscribeToEvent(playerBroker_, E_IPCWORKEREXIT, ATOMIC_HANDLER(IPCServerApp, HandleIPCWorkerExit));
  121. SubscribeToEvent(playerBroker_, E_IPCWORKERLOG, ATOMIC_HANDLER(IPCServerApp, HandleIPCWorkerLog));
  122. }
  123. return playerBroker_.NotNull();
  124. }
  125. void IPCServerApp::HandleIPCWorkerStarted(StringHash eventType, VariantMap& eventData)
  126. {
  127. VariantMap startupData;
  128. DebugHud* debugHud = GetSubsystem<DebugHud>();
  129. startupData["debugHudMode"] = debugHud ? debugHud->GetMode() : (unsigned)0;
  130. startupData["debugHudProfilerMode"] = (unsigned)(debugHud ? debugHud->GetProfilerMode() : DEBUG_HUD_PROFILE_PERFORMANCE);
  131. playerBroker_->PostMessage(E_IPCINITIALIZE, startupData);
  132. playerEnabled_ = true;
  133. }
  134. void IPCServerApp::HandleIPCWorkerExit(StringHash eventType, VariantMap& eventData)
  135. {
  136. if (eventData[IPCWorkerExit::P_BROKER] == playerBroker_)
  137. {
  138. playerBroker_ = 0;
  139. playerEnabled_ = false;
  140. UnsubscribeFromEvent(E_IPCWORKERSTART);
  141. UnsubscribeFromEvent(E_IPCPLAYERPAUSERESUMEREQUEST);
  142. UnsubscribeFromEvent(E_IPCPLAYERUPDATESPAUSEDRESUMED);
  143. UnsubscribeFromEvent(E_IPCPLAYERPAUSESTEPREQUEST);
  144. UnsubscribeFromEvent(E_IPCPLAYEREXITREQUEST);
  145. }
  146. else
  147. {
  148. ATOMIC_LOGERROR("IPCServerApp::HandleIPCWorkerExit - Unknown Broker");
  149. }
  150. }
  151. void IPCServerApp::HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData)
  152. {
  153. using namespace IPCWorkerLog;
  154. // convert to a player log
  155. VariantMap playerLogData;
  156. playerLogData["message"] = eventData[P_MESSAGE].GetString();
  157. playerLogData["level"] = eventData[P_LEVEL].GetInt();
  158. //SendEvent("EditorPlayerLog", playerLogData);
  159. }
  160. void IPCServerApp::HandleIPCJSError(StringHash eventType, VariantMap& eventData)
  161. {
  162. }
  163. void IPCServerApp::RequestTogglePlayerUpdatesPaused()
  164. {
  165. if (!playerBroker_)
  166. {
  167. return;
  168. }
  169. VariantMap noEventData;
  170. playerBroker_->PostMessage(E_PAUSERESUMEREQUESTED, noEventData);
  171. }
  172. void IPCServerApp::RequestPlayerPauseStep()
  173. {
  174. if (!playerBroker_)
  175. {
  176. return;
  177. }
  178. VariantMap noEventData;
  179. playerBroker_->PostMessage(E_PAUSESTEPREQUESTED, noEventData);
  180. }
  181. void IPCServerApp::RequestPlayerExit()
  182. {
  183. if (!playerBroker_)
  184. {
  185. return;
  186. }
  187. VariantMap noEventData;
  188. playerBroker_->PostMessage(E_EXITREQUESTED, noEventData);
  189. }
  190. }
  191. #pragma pop_macro("PostMessage")