containersWindow.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. #include "containersWindow.h"
  2. #include <pikaImgui/pikaImgui.h>
  3. #include "imguiComboSearch.h"
  4. #include <imgui_spinner.h>
  5. #include <validatePath.h>
  6. void pika::ContainersWindow::init(pika::pikaImgui::ImGuiIdsManager &imguiIdsManager)
  7. {
  8. imguiIds = imguiIdsManager.getImguiIds(10);
  9. }
  10. void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pika::LoadedDll &loadedDll,
  11. pika::ContainerManager &containerManager, pika::pikaImgui::ImGuiIdsManager &imguiIdsManager)
  12. {
  13. ImGui::PushID(imguiIds);
  14. if (!ImGui::Begin(ICON_NAME, &open))
  15. {
  16. ImGui::End();
  17. ImGui::PopID();
  18. return;
  19. }
  20. static int selected = 0;
  21. std::string selectedContainerToLaunch = "";
  22. {
  23. ImGui::BeginGroup();
  24. ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
  25. if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_Reorderable))
  26. {
  27. if (ImGui::BeginTabItem(ICON_FK_PLUS_SQUARE_O " Create container"))
  28. {
  29. ImGui::Text("Available containers");
  30. ImGui::Separator();
  31. //left
  32. ImGui::PushID(imguiIds +1);
  33. ImGui::BeginGroup();
  34. {
  35. static char filter[256] = {};
  36. std::vector<std::string> containerNames;
  37. containerNames.reserve(loadedDll.containerInfo.size());
  38. for (auto &i : loadedDll.containerInfo)
  39. {
  40. containerNames.push_back(i.containerName);
  41. }
  42. auto contentSize = ImGui::GetItemRectSize();
  43. contentSize.y -= ImGui::GetFrameHeightWithSpacing();
  44. contentSize.x /= 2;
  45. ImGui::ListWithFilter("##list box container info", &itemCurrentAvailableCOntainers, filter, sizeof(filter),
  46. containerNames, contentSize);
  47. }
  48. ImGui::EndGroup();
  49. ImGui::PopID();
  50. ImGui::SameLine();
  51. //right
  52. ImGui::PushID(imguiIds + 2);
  53. ImGui::BeginGroup();
  54. {
  55. if (itemCurrentAvailableCOntainers < loadedDll.containerInfo.size())
  56. {
  57. auto &c = loadedDll.containerInfo[itemCurrentAvailableCOntainers];
  58. ImGui::Text("Container info: %s", c.containerName.c_str());
  59. ImGui::Separator();
  60. selectedContainerToLaunch = c.containerName;
  61. if (ImGui::BeginTabBar("##Tabs for container info", ImGuiTabBarFlags_Reorderable))
  62. {
  63. if (ImGui::BeginTabItem(ICON_FK_PIE_CHART " Memory"))
  64. {
  65. ImGui::NewLine();
  66. #pragma region total memory requirement
  67. size_t totalHeapMemory = c.containerStaticInfo.defaultHeapMemorySize;
  68. for (auto i : c.containerStaticInfo.bonusAllocators)
  69. {
  70. totalHeapMemory += i;
  71. }
  72. size_t totalMemory = totalHeapMemory + c.containerStructBaseSize;
  73. ImGui::Text("Total Memory requirement: ");
  74. ImGui::SameLine();
  75. pika::pikaImgui::displayMemorySizeValue(totalMemory);
  76. ImGui::Text("Total Heap requirement: ");
  77. ImGui::SameLine();
  78. pika::pikaImgui::displayMemorySizeValue(totalHeapMemory);
  79. #pragma endregion
  80. ImGui::NewLine();
  81. ImGui::Text("Static Memory requirement: ");
  82. ImGui::SameLine();
  83. pika::pikaImgui::displayMemorySizeValue(c.containerStructBaseSize);
  84. ImGui::Text("Default Heap Memory requirement: ");
  85. ImGui::SameLine();
  86. pika::pikaImgui::displayMemorySizeValue(c.containerStaticInfo.defaultHeapMemorySize);
  87. ImGui::Text("Other Heap Memory Allocators count: ");
  88. ImGui::SameLine();
  89. pika::pikaImgui::displayMemorySizeValue(c.containerStaticInfo.bonusAllocators.size());
  90. if (!c.containerStaticInfo.bonusAllocators.empty())
  91. {
  92. if (ImGui::BeginChild("##heap allocators",
  93. {0, 100}, true, ImGuiWindowFlags_AlwaysVerticalScrollbar))
  94. {
  95. for (auto i : c.containerStaticInfo.bonusAllocators)
  96. {
  97. pika::pikaImgui::displayMemorySizeValue(i);
  98. }
  99. }
  100. ImGui::EndChild();
  101. }
  102. ImGui::EndTabItem();
  103. }
  104. if (ImGui::BeginTabItem(ICON_FK_PLUS_SQUARE_O" Launch"))
  105. {
  106. ImGui::NewLine();
  107. if (!selectedContainerToLaunch.empty()
  108. && ImGui::Button(ICON_FK_PLAY " Launch a default configuration"))
  109. {
  110. if (createAtSpecificMemoryRegion)
  111. {
  112. containerManager.createContainer(selectedContainerToLaunch, loadedDll,
  113. logManager, imguiIdsManager, pika::TB(1));
  114. }
  115. else
  116. {
  117. containerManager.createContainer(selectedContainerToLaunch, loadedDll, logManager,
  118. imguiIdsManager);
  119. }
  120. }
  121. ImGui::Checkbox("allocate at specific memory region", &createAtSpecificMemoryRegion);
  122. //ImGui::NewLine();
  123. {
  124. static int currentSelectedSnapshot = 0;
  125. auto snapshots = pika::getAvailableSnapshotsAnyMemoryPosition(c);
  126. if (!selectedContainerToLaunch.empty()
  127. && ImGui::Button(ICON_FK_PICTURE_O " Launch a snapshot"))
  128. {
  129. auto s = snapshots[currentSelectedSnapshot];
  130. auto memPos = getSnapshotMemoryPosition(s.c_str());
  131. if (memPos == nullptr)
  132. {
  133. logManager.log("Failes to get snapshot info", pika::logError);
  134. }
  135. else
  136. {
  137. auto c = containerManager.createContainer(
  138. selectedContainerToLaunch, loadedDll, logManager,
  139. imguiIdsManager, (size_t)memPos);
  140. //no need to log error since create container does that
  141. if (c != 0)
  142. {
  143. if (!containerManager.setSnapshotToContainer(c,
  144. s.c_str(), logManager, imguiIdsManager))
  145. {
  146. containerManager.destroyContainer(c, loadedDll, logManager);
  147. }
  148. }
  149. }
  150. }
  151. auto contentSize = ImGui::GetItemRectSize();
  152. contentSize.y -= ImGui::GetFrameHeightWithSpacing();
  153. //contentSize.x /= 2;
  154. ImGui::ListWithFilter("##list box snapshots", &currentSelectedSnapshot,
  155. filterSnapshots, sizeof(filterSnapshots),
  156. snapshots, contentSize);
  157. }
  158. ImGui::EndTabItem();
  159. }
  160. ImGui::EndTabBar();
  161. }
  162. }
  163. else
  164. {
  165. ImGui::Text("Container info:");
  166. ImGui::Separator();
  167. }
  168. }
  169. ImGui::EndGroup();
  170. ImGui::PopID();
  171. ImGui::EndTabItem();
  172. }
  173. if (ImGui::BeginTabItem(ICON_FK_MICROCHIP " Running containers"))
  174. {
  175. ImGui::Text("Running containers");
  176. ImGui::SameLine();
  177. pika::pikaImgui::helpMarker(
  178. ICON_FK_BOLT ": Container is running;\n"
  179. ICON_FK_PAUSE_CIRCLE_O ": Container is on pause;\n"
  180. ICON_FK_VIDEO_CAMERA ": Container is being recorded;\n"
  181. ICON_FK_REPEAT ": Container is on input playback."
  182. );
  183. ImGui::Separator();
  184. //left
  185. std::vector<pika::containerId_t> containerIds;
  186. std::vector<std::string> containerNames;
  187. ImGui::PushID(imguiIds + 3);
  188. ImGui::BeginGroup();
  189. {
  190. containerIds.reserve(containerManager.runningContainers.size());
  191. containerNames.reserve(containerManager.runningContainers.size());
  192. for (auto &i : containerManager.runningContainers)
  193. {
  194. containerIds.push_back(i.first);
  195. containerNames.push_back(
  196. std::string(i.second.flags.getStatusIcon()) + " " + i.second.baseContainerName + ": " + std::to_string(i.first));
  197. }
  198. auto contentSize = ImGui::GetItemRectSize();
  199. contentSize.y -= ImGui::GetFrameHeightWithSpacing();
  200. contentSize.x /= 2;
  201. ImGui::ListWithFilter("##list box container info", &itemCurrentCreatedContainers,
  202. filterContainerInfo, sizeof(filterContainerInfo),
  203. containerNames, contentSize);
  204. }
  205. ImGui::EndGroup();
  206. ImGui::PopID();
  207. ImGui::SameLine();
  208. //right
  209. ImGui::PushID(imguiIds + 4);
  210. ImGui::BeginGroup();
  211. {
  212. if (itemCurrentCreatedContainers < containerIds.size())
  213. {
  214. auto &c = containerManager.runningContainers[containerIds[itemCurrentCreatedContainers]];
  215. ImGui::Text("Running container: %s #%u", c.baseContainerName, containerIds[itemCurrentCreatedContainers]);
  216. ImGui::Separator();
  217. #pragma region buttons
  218. //calculate cursor pos for 3 buttons
  219. {
  220. ImGuiStyle &style = ImGui::GetStyle();
  221. float width = 0.0f;
  222. width += ImGui::CalcTextSize(ICON_FK_PAUSE).x;
  223. width += style.ItemSpacing.x;
  224. width += ImGui::CalcTextSize(ICON_FK_PAUSE).x;
  225. width += style.ItemSpacing.x;
  226. width += ImGui::CalcTextSize(ICON_FK_PAUSE).x;
  227. pika::pikaImgui::alignForWidth(width);
  228. }
  229. if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_RUNNING)
  230. {
  231. if (ImGui::Button(ICON_FK_PAUSE))
  232. {
  233. c.flags.status = pika::RuntimeContainer::FLAGS::STATUS_PAUSE;
  234. }
  235. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  236. {
  237. ImGui::SetTooltip("Pause container.");
  238. }
  239. }
  240. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_PAUSE)
  241. {
  242. if (ImGui::Button(ICON_FK_PLAY))
  243. {
  244. c.flags.status = pika::RuntimeContainer::FLAGS::STATUS_RUNNING;
  245. }
  246. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  247. {
  248. ImGui::SetTooltip("Resume container.");
  249. }
  250. }
  251. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED)
  252. {
  253. ImGui::BeginDisabled();
  254. if (ImGui::Button(ICON_FK_PAUSE))
  255. {
  256. }
  257. ImGui::EndDisabled();
  258. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  259. {
  260. ImGui::SetTooltip("Can't pause container while it is recorded."); //todo implement
  261. }
  262. }
  263. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_PLAYBACK)
  264. {
  265. if (ImGui::Button(ICON_FK_REPEAT))
  266. {
  267. c.flags.status = pika::RuntimeContainer::FLAGS::STATUS_RUNNING;
  268. }
  269. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  270. {
  271. ImGui::SetTooltip("Stop playback");
  272. }
  273. }
  274. ImGui::SameLine();
  275. bool stopped = false;
  276. if (ImGui::Button(ICON_FK_STOP))
  277. {
  278. //todo mabe defer here when api is made
  279. containerManager.destroyContainer(containerIds[itemCurrentCreatedContainers], loadedDll, logManager);
  280. stopped = true;
  281. }
  282. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  283. {
  284. ImGui::SetTooltip("Stop container.");
  285. }
  286. ImGui::SameLine();
  287. if (ImGui::Button(ICON_FK_EJECT))
  288. {
  289. containerManager.forceTerminateContainer(containerIds[itemCurrentCreatedContainers], loadedDll, logManager);
  290. stopped = true;
  291. }
  292. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  293. {
  294. ImGui::SetTooltip("Force stop container (not recomended).\nThis won't call any destructors.");
  295. }
  296. #pragma endregion
  297. if(!stopped)
  298. {
  299. ImGui::Text("Status: %s", c.flags.getStatusName());
  300. ImGui::Separator();
  301. if (ImGui::BeginTabBar("##Tabs for play and record", ImGuiTabBarFlags_Reorderable))
  302. {
  303. if (ImGui::BeginTabItem(ICON_FK_CAMERA " Snapshot"))
  304. {
  305. //snapshot button
  306. {
  307. if (ImGui::Button(ICON_FK_CAMERA))
  308. {
  309. if (pika::isFileNameValid(snapshotName, sizeof(snapshotName)))
  310. {
  311. if (!containerManager.makeSnapshot(containerIds[itemCurrentCreatedContainers], logManager, snapshotName))
  312. {
  313. logManager.log("Coultn't make snapshot", pika::logError);
  314. }
  315. else
  316. {
  317. logManager.log("Successfully created snapshot.");
  318. }
  319. }
  320. else
  321. {
  322. logManager.log("File name invalid", pika::logError);
  323. }
  324. }
  325. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  326. {
  327. ImGui::SetTooltip("Make snapshot");
  328. }
  329. ImGui::SameLine();
  330. ImGui::InputText("snapshot name", snapshotName, sizeof(snapshotName));
  331. }
  332. ImGui::NewLine();
  333. ImGui::Separator();
  334. #pragma region snapshots
  335. {
  336. auto snapshots = pika::getAvailableSnapshots(
  337. containerManager.runningContainers[containerIds[itemCurrentCreatedContainers]]);
  338. auto contentSize = ImGui::GetItemRectSize();
  339. contentSize.y -= ImGui::GetFrameHeightWithSpacing();
  340. contentSize.x /= 2;
  341. ImGui::ListWithFilter("##list box snapshots", &currentSelectedSnapshot,
  342. filterSnapshots, sizeof(filterSnapshots),
  343. snapshots, contentSize);
  344. ImGui::SameLine();
  345. if (snapshots.size() == 0 || currentSelectedSnapshot >= snapshots.size())
  346. {
  347. ImGui::BeginDisabled(true);
  348. }
  349. else
  350. {
  351. ImGui::BeginDisabled(false);
  352. }
  353. if (ImGui::Button(ICON_FK_PLAY "##play snapshot"))
  354. {
  355. if (!containerManager.setSnapshotToContainer(
  356. containerIds[itemCurrentCreatedContainers],
  357. snapshots[currentSelectedSnapshot].c_str(), logManager, imguiIdsManager
  358. ))
  359. {
  360. logManager.log("Failed to assign snapshot", pika::logError);
  361. }
  362. }
  363. ImGui::EndDisabled();
  364. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  365. {
  366. ImGui::SetTooltip("Play this snapshot to this container");
  367. }
  368. }
  369. #pragma endregion
  370. ImGui::EndTabItem();
  371. }
  372. if (ImGui::BeginTabItem(ICON_FK_VIDEO_CAMERA " Record"))
  373. {
  374. //recording
  375. {
  376. if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_RUNNING)
  377. {
  378. if (ImGui::Button(ICON_FK_VIDEO_CAMERA))
  379. {
  380. if (pika::isFileNameValid(recordingName, sizeof(recordingName)))
  381. {
  382. containerManager.startRecordingContainer
  383. (containerIds[itemCurrentCreatedContainers], logManager, recordingName);
  384. }
  385. else
  386. {
  387. logManager.log("File name invalid", pika::logError);
  388. }
  389. }
  390. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  391. {
  392. ImGui::SetTooltip("start recording");
  393. }
  394. }
  395. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED)
  396. {
  397. if (ImGui::Button(ICON_FK_STOP_CIRCLE))
  398. {
  399. containerManager.stopRecordingContainer
  400. (containerIds[itemCurrentCreatedContainers], logManager);
  401. }
  402. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  403. {
  404. ImGui::SetTooltip("stop recording");
  405. }
  406. }
  407. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_PAUSE)
  408. {
  409. ImGui::BeginDisabled(1);
  410. if (ImGui::Button(ICON_FK_VIDEO_CAMERA))
  411. {
  412. }
  413. ImGui::EndDisabled();
  414. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  415. {
  416. ImGui::SetTooltip("Can't record while container is paused");
  417. }
  418. }
  419. else if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_PLAYBACK)
  420. {
  421. ImGui::BeginDisabled(1);
  422. if (ImGui::Button(ICON_FK_VIDEO_CAMERA))
  423. {
  424. }
  425. ImGui::EndDisabled();
  426. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  427. {
  428. ImGui::SetTooltip("Can't record while container is on playback");
  429. }
  430. }
  431. ImGui::BeginDisabled(c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED);
  432. ImGui::SameLine();
  433. ImGui::InputText("recording name", recordingName, sizeof(recordingName));
  434. ImGui::EndDisabled();
  435. }
  436. ImGui::NewLine();
  437. ImGui::Separator();
  438. #pragma region recordings
  439. auto recordings = pika::getAvailableRecordings(
  440. containerManager.runningContainers[containerIds[itemCurrentCreatedContainers]]);
  441. auto contentSize = ImGui::GetItemRectSize();
  442. contentSize.y -= ImGui::GetFrameHeightWithSpacing();
  443. contentSize.x /= 2;
  444. ImGui::ListWithFilter("##list box recordings", &currentSelectedRecording,
  445. filterSnapshots, sizeof(filterSnapshots),
  446. recordings, contentSize);
  447. ImGui::SameLine();
  448. if (recordings.size() == 0 || currentSelectedRecording >= recordings.size()
  449. || c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED)
  450. {
  451. ImGui::BeginDisabled(true);
  452. }
  453. else
  454. {
  455. ImGui::BeginDisabled(false);
  456. }
  457. if (ImGui::Button(ICON_FK_PLAY "##play recording"))
  458. {
  459. if (!containerManager.setRecordingToContainer(
  460. containerIds[itemCurrentCreatedContainers],
  461. recordings[currentSelectedSnapshot].c_str(), logManager, imguiIdsManager
  462. ))
  463. {
  464. logManager.log("Failed to assign recording", pika::logError);
  465. }
  466. }
  467. ImGui::EndDisabled();
  468. if (c.flags.status == pika::RuntimeContainer::FLAGS::STATUS_BEING_RECORDED)
  469. {
  470. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  471. {
  472. ImGui::SetTooltip("Can't play a recording because the container is being recorded at the moment");
  473. }
  474. }
  475. else
  476. {
  477. if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
  478. {
  479. ImGui::SetTooltip("Play this recording to this container");
  480. }
  481. }
  482. #pragma endregion
  483. ImGui::EndTabItem();
  484. }
  485. ImGui::EndTabBar();
  486. }
  487. }
  488. }
  489. else
  490. {
  491. ImGui::Text("Running container:");
  492. ImGui::Separator();
  493. }
  494. }
  495. ImGui::EndGroup();
  496. ImGui::PopID();
  497. ImGui::EndTabItem();
  498. }
  499. ImGui::EndTabBar();
  500. }
  501. ImGui::EndChild();
  502. //you can add buttons here
  503. ImGui::EndGroup();
  504. }
  505. //todo container profiler will have an instance per container with imgui id and stuff.
  506. ImGui::End();
  507. ImGui::PopID();
  508. }
  509. //todo options hide show push notidications also engine push notifications that are forced