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

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