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.

Console.cpp 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*!
  2. * \file src/Console.cpp
  3. * \brief Console Window
  4. *
  5. * \author xythobuz
  6. */
  7. #include <cstring>
  8. #include "imgui/imgui.h"
  9. #include "global.h"
  10. #include "Log.h"
  11. #include "commands/Command.h"
  12. #include "Console.h"
  13. bool Console::visible = false;
  14. char Console::buffer[bufferLength + 1] = "";
  15. unsigned long Console::lastLogLength = 0;
  16. std::vector<std::string> Console::lastCommands;
  17. long Console::lastCommandIndex = -1;
  18. std::string Console::bufferedCommand;
  19. int Console::callback(ImGuiTextEditCallbackData* data) {
  20. bool update = false;
  21. std::string completion;
  22. switch (data->EventKey) {
  23. case ImGuiKey_Tab:
  24. completion = Command::autoComplete(data->Buf);
  25. if (completion.size() > 0) {
  26. data->DeleteChars(0, data->BufSize);
  27. data->InsertChars(0, completion.c_str());
  28. data->CursorPos = strlen(data->Buf);
  29. }
  30. break;
  31. case ImGuiKey_UpArrow:
  32. update = true;
  33. if (lastCommandIndex < (long)(lastCommands.size() - 1)) {
  34. lastCommandIndex++;
  35. if (lastCommandIndex == 0)
  36. bufferedCommand = data->Buf;
  37. }
  38. break;
  39. case ImGuiKey_DownArrow:
  40. update = true;
  41. if (lastCommandIndex > -1)
  42. lastCommandIndex--;
  43. break;
  44. }
  45. if (update) {
  46. if ((lastCommandIndex >= 0) && (lastCommandIndex < lastCommands.size())) {
  47. if (lastCommands.at(lastCommands.size() - 1 - lastCommandIndex) != buffer) {
  48. data->DeleteChars(0, data->BufSize);
  49. data->InsertChars(0, lastCommands.at(lastCommands.size() - 1 - lastCommandIndex).c_str());
  50. }
  51. } else {
  52. data->DeleteChars(0, data->BufSize);
  53. if (bufferedCommand.size() > 0) {
  54. data->InsertChars(0, bufferedCommand.c_str());
  55. }
  56. }
  57. data->CursorPos = strlen(data->Buf);
  58. }
  59. return 0;
  60. }
  61. void Console::display() {
  62. if (!visible)
  63. return;
  64. if (ImGui::Begin("Console", &visible, ImVec2(600, 400))) {
  65. static bool scrollToBottom = false;
  66. if (lastLogLength != Log::size()) {
  67. lastLogLength = Log::size();
  68. scrollToBottom = true;
  69. }
  70. static bool visibleLogs[LOG_COUNT] = { true, true, true, true, true };
  71. ImGui::Checkbox("Error##log", &visibleLogs[1]);
  72. ImGui::SameLine();
  73. ImGui::Checkbox("Warning##log", &visibleLogs[2]);
  74. ImGui::SameLine();
  75. ImGui::Checkbox("User##log", &visibleLogs[0]);
  76. ImGui::SameLine();
  77. ImGui::Checkbox("Info##log", &visibleLogs[3]);
  78. ImGui::SameLine();
  79. ImGui::Checkbox("Debug##log", &visibleLogs[4]);
  80. static bool logToTTY = false, logToClipboard = false, logToFile = false;
  81. if (ImGui::Button("Log to TTY")) { logToTTY = true; }
  82. ImGui::SameLine();
  83. if (ImGui::Button("Log to Clipboard")) { logToClipboard = true; }
  84. ImGui::SameLine();
  85. if (ImGui::Button("Log to File")) { logToFile = true; }
  86. ImGui::Separator();
  87. ImGui::BeginChild("ConsoleText", ImVec2(0, -ImGui::GetTextLineHeightWithSpacing() * 2));
  88. if (logToTTY)
  89. ImGui::LogToTTY();
  90. else if (logToClipboard)
  91. ImGui::LogToClipboard();
  92. else if (logToFile)
  93. ImGui::LogToFile();
  94. for (unsigned long i = 0; i < Log::size(); i++) {
  95. auto& entry = Log::getEntry(i);
  96. orAssertLessThan(entry.level, LOG_COUNT);
  97. if (!visibleLogs[entry.level]) {
  98. continue;
  99. }
  100. ImVec4 col(1.0f, 1.0f, 1.0f, 1.0f);
  101. if (entry.level == LOG_ERROR) {
  102. col = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
  103. } else if (entry.level == LOG_WARNING) {
  104. col = ImVec4(1.0f, 1.0f, 0.0f, 1.0f);
  105. } else if (entry.level == LOG_DEBUG) {
  106. col = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
  107. } else if (entry.level == LOG_USER) {
  108. col = ImVec4(0.5f, 0.75f, 1.0f, 1.0f);
  109. }
  110. ImGui::PushStyleColor(ImGuiCol_Text, col);
  111. ImGui::TextWrapped("%s", entry.text.c_str());
  112. ImGui::PopStyleColor();
  113. }
  114. if (logToTTY || logToClipboard || logToFile) {
  115. ImGui::LogFinish();
  116. logToTTY = logToClipboard = logToFile = false;
  117. }
  118. if (scrollToBottom) {
  119. ImGui::SetScrollHere();
  120. scrollToBottom = false;
  121. }
  122. ImGui::EndChild();
  123. bool focusInput = false;
  124. if (ImGui::InputText("Command", buffer, bufferLength,
  125. ImGuiInputTextFlags_EnterReturnsTrue
  126. | ImGuiInputTextFlags_CallbackCompletion
  127. | ImGuiInputTextFlags_CallbackHistory,
  128. &Console::callback)) {
  129. Log::get(LOG_USER) << "> " << buffer << Log::endl;
  130. if (strlen(buffer) > 0) {
  131. int error = Command::command(buffer);
  132. if (error != 0) {
  133. Log::get(LOG_USER) << "Error code: " << error << Log::endl;
  134. }
  135. if ((lastCommands.size() == 0) || (lastCommands[lastCommands.size() - 1] != buffer))
  136. lastCommands.push_back(std::string(buffer));
  137. }
  138. lastCommandIndex = -1;
  139. buffer[0] = '\0';
  140. scrollToBottom = true;
  141. focusInput = true;
  142. bufferedCommand.clear();
  143. }
  144. if (ImGui::IsItemHovered() || focusInput) {
  145. ImGui::SetKeyboardFocusHere(-1);
  146. }
  147. }
  148. ImGui::End();
  149. }