Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Menu.cpp 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*!
  2. * \file src/Menu.cpp
  3. * \brief Main Menu
  4. *
  5. * \author xythobuz
  6. */
  7. #include "imgui/imgui.h"
  8. #include "global.h"
  9. #include "Console.h"
  10. #include "Game.h"
  11. #include "Log.h"
  12. #include "RunTime.h"
  13. #include "UI.h"
  14. #include "TextureManager.h"
  15. #include "system/Window.h"
  16. #include "utils/random.h"
  17. #include "utils/strings.h"
  18. #include "Menu.h"
  19. const glm::vec4 Menu::textColor(0.5f, 0.7f, 1.0f, 1.0f);
  20. const glm::vec4 Menu::selectedColor(1.0f, 0.0f, 0.0f, 1.0f);
  21. bool Menu::visible = false;
  22. Folder* Menu::mapFolder = nullptr;
  23. std::vector<Script> Menu::scripts;
  24. std::vector<Folder> Menu::paths;
  25. std::vector<int> Menu::images;
  26. int Menu::initialize() {
  27. shutdown();
  28. mapFolder = new Folder(RunTime::getPakDir());
  29. std::vector<File> files;
  30. mapFolder->findRecursiveFilesEndingWith(files, "tombpc.dat");
  31. for (auto& f : files) {
  32. scripts.emplace_back();
  33. auto s = scripts.size() - 1;
  34. images.push_back(-1);
  35. auto i = images.size() - 1;
  36. std::string path = convertPathDelimiter(removeLastPathElement(f.getPath()));
  37. paths.emplace_back(path);
  38. auto p = paths.size() - 1;
  39. if (scripts.at(s).load(f.getPath()) != 0) {
  40. Log::get(LOG_ERROR) << "Invalid Script: \"" << f.getPath()
  41. << "\"!" << Log::endl;
  42. scripts.pop_back();
  43. } else {
  44. // Load one of the pictures of this level
  45. std::vector<File> texFiles;
  46. paths.at(p).findRecursiveFilesEndingWith(texFiles, ".pcx");
  47. paths.at(p).findRecursiveFilesEndingWith(texFiles, ".bmp");
  48. paths.at(p).findRecursiveFilesEndingWith(texFiles, ".png");
  49. paths.at(p).findRecursiveFilesEndingWith(texFiles, ".tga");
  50. paths.at(p).findRecursiveFilesEndingWith(texFiles, ".jpg");
  51. if (texFiles.size() > 0) {
  52. int which = randomInteger(texFiles.size() - 1);
  53. images.at(i) = TextureManager::loadImage(texFiles.at(which).getPath(),
  54. TextureStorage::SYSTEM);
  55. }
  56. }
  57. }
  58. return 0;
  59. }
  60. void Menu::shutdown() {
  61. if (mapFolder != nullptr) {
  62. delete mapFolder;
  63. mapFolder = nullptr;
  64. }
  65. scripts.clear();
  66. paths.clear();
  67. images.clear(); //! \fixme free texture slots
  68. }
  69. void Menu::display() {
  70. if (!visible)
  71. return;
  72. glm::vec2 size = Window::getSize();
  73. if (!ImGui::Begin("Menu", nullptr, ImVec2(size.x, size.y), -1.0f, ImGuiWindowFlags_NoTitleBar
  74. | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse
  75. | ImGuiWindowFlags_NoSavedSettings)) {
  76. ImGui::End();
  77. return;
  78. }
  79. ImGui::SetWindowPos(ImVec2(0, 0));
  80. ImGui::SetWindowSize(ImVec2(size.x, size.y));
  81. // Draw heading with version string
  82. auto headingSize = ImGui::CalcTextSize(VERSION);
  83. headingSize.x *= 3.0f; headingSize.y *= 3.0f;
  84. ImGui::SetWindowFontScale(3.0f);
  85. ImGui::SameLine(0, (size.x / 2) - (headingSize.x / 2));
  86. ImGui::TextColored(textColor, VERSION);
  87. ImGui::SetWindowFontScale(1.0f);
  88. static ImGuiFs::Dialog* dialog = nullptr;
  89. const bool browseButtonPressed = ImGui::Button("Select Level File");
  90. if (browseButtonPressed) {
  91. if (dialog != nullptr)
  92. delete dialog;
  93. dialog = new ImGuiFs::Dialog();
  94. }
  95. if (dialog) {
  96. dialog->chooseFileDialog(browseButtonPressed, RunTime::getPakDir().c_str(),
  97. ".phd;.psx;.tub;.tr2", nullptr, ImVec2(400, 300), ImGui::GetMousePos());
  98. std::string selectedFile = dialog->getChosenPath();
  99. if (selectedFile.length() > 0) {
  100. Game::loadLevel(selectedFile);
  101. delete dialog;
  102. dialog = nullptr;
  103. }
  104. }
  105. ImGui::SameLine();
  106. if (ImGui::Button("Toggle Console")) {
  107. Console::setVisible(!Console::isVisible());
  108. }
  109. ImGui::SameLine();
  110. if (ImGui::Button("Toggle Debug Window")) {
  111. UI::setVisible(!UI::isVisible());
  112. }
  113. ImGui::Separator();
  114. // Set up columns for game list
  115. ImGui::Columns(3, "menuscripts");
  116. static bool offsets = false;
  117. if (!offsets) {
  118. ImGui::SetColumnOffset(1, 140.0f);
  119. ImGui::SetColumnOffset(2, size.x - 200.0f);
  120. offsets = true;
  121. }
  122. // List found games
  123. for (int i = 0; i < scripts.size(); i++) {
  124. ImGui::PushID(i);
  125. Script& s = scripts.at(i);
  126. if (images.at(i) >= 0) {
  127. auto bm = TextureManager::getBufferManager(images.at(i), TextureStorage::SYSTEM);
  128. ImGui::Image(bm, ImVec2(128, 128));
  129. }
  130. ImGui::NextColumn();
  131. ImGui::TextWrapped("Language: %s", s.getLanguage().c_str());
  132. ImGui::TextWrapped("Description: %s", s.getDescription().c_str());
  133. if (ImGui::TreeNode("", "%d Levels", s.levelCount())) {
  134. for (int l = 0; l < s.levelCount(); l++) {
  135. ImGui::PushID(l);
  136. ImGui::Bullet();
  137. ImGui::TextWrapped("%s (%s)", s.getLevelName(l).c_str(), s.getLevelFilename(l).c_str());
  138. ImGui::SameLine();
  139. if (ImGui::Button("Play level")) {
  140. std::vector<File> levelFiles;
  141. paths.at(i).findRecursiveFilesEndingWith(levelFiles,
  142. getLastPathElement(s.getLevelFilename(l)));
  143. if (levelFiles.size() == 0) {
  144. Log::get(LOG_ERROR) << "Could not find level \""
  145. << getLastPathElement(s.getLevelFilename(l))
  146. << "\"!" << Log::endl;
  147. } else {
  148. Game::loadLevel(levelFiles.at(0).getPath());
  149. }
  150. }
  151. ImGui::PopID();
  152. }
  153. ImGui::TreePop();
  154. }
  155. if (ImGui::TreeNode("", "%d Cut-Scenes", s.cutsceneCount())) {
  156. for (int c = 0; c < s.cutsceneCount(); c++) {
  157. ImGui::Bullet();
  158. ImGui::TextWrapped("%s", s.getCutsceneFilename(c).c_str());
  159. }
  160. ImGui::TreePop();
  161. }
  162. if (ImGui::TreeNode("", "%d Videos", s.videoCount())) {
  163. for (int v = 0; v < s.videoCount(); v++) {
  164. ImGui::Bullet();
  165. ImGui::TextWrapped("%s", s.getVideoFilename(v).c_str());
  166. }
  167. ImGui::TreePop();
  168. }
  169. if (ImGui::TreeNode("", "%d Pictures", s.pictureCount())) {
  170. for (int p = 0; p < s.pictureCount(); p++) {
  171. ImGui::Bullet();
  172. ImGui::TextWrapped("%s", s.getPictureFilename(p).c_str());
  173. }
  174. ImGui::TreePop();
  175. }
  176. if (ImGui::TreeNode("", "%d Titles", s.titleCount())) {
  177. for (int t = 0; t < s.titleCount(); t++) {
  178. ImGui::Bullet();
  179. ImGui::TextWrapped("%s", s.getTitleFilename(t).c_str());
  180. }
  181. ImGui::TreePop();
  182. }
  183. ImGui::NextColumn();
  184. ImGui::TextWrapped("Real Gameplay not yet implemented!");
  185. ImGui::NextColumn();
  186. if (i < (scripts.size() - 1))
  187. ImGui::Separator();
  188. ImGui::PopID();
  189. }
  190. ImGui::Columns(1);
  191. if (scripts.size() == 0) {
  192. ImGui::TextWrapped("OpenRaiders built-in TombRaider-Script detection mechanism could not find any suitable TR2/TR3 script files (called \"TOMBPC.DAT\") in your PAK folder \"%s\"! Use the \"Select Level File\" Button to load a single level without starting the entire game.",
  193. RunTime::getPakDir().c_str());
  194. }
  195. ImGui::End();
  196. }