DeveloperConsole.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/core/DeveloperConsole.h>
  6. namespace anki
  7. {
  8. DeveloperConsole::~DeveloperConsole()
  9. {
  10. LoggerSingleton::get().removeMessageHandler(this, loggerCallback);
  11. while(!m_logItems.isEmpty())
  12. {
  13. LogItem* item = &m_logItems.getFront();
  14. m_logItems.popFront();
  15. item->m_msg.destroy(m_alloc);
  16. m_alloc.deleteInstance(item);
  17. }
  18. }
  19. Error DeveloperConsole::init(AllocAlignedCallback allocCb, void* allocCbUserData)
  20. {
  21. m_alloc = HeapAllocator<U8>(allocCb, allocCbUserData);
  22. zeroMemory(m_inputText);
  23. ANKI_CHECK(m_manager->newInstance(m_font, "engine_data/UbuntuMonoRegular.ttf", std::initializer_list<U32>{16}));
  24. // Add a new callback to the logger
  25. LoggerSingleton::get().addMessageHandler(this, loggerCallback);
  26. return Error::NONE;
  27. }
  28. void DeveloperConsole::build(CanvasPtr ctx)
  29. {
  30. const Vec4 oldWindowColor = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
  31. ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w = 0.3f;
  32. ctx->pushFont(m_font, 16);
  33. ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar);
  34. ImGui::SetWindowPos(Vec2(0.0f, 0.0f));
  35. ImGui::SetWindowSize(Vec2(ctx->getWidth(), ctx->getHeight() * (2.0f / 3.0f)));
  36. // Push the items
  37. const F32 footerHeightToPreserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
  38. ImGui::BeginChild("ScrollingRegion",
  39. Vec2(0, -footerHeightToPreserve),
  40. false,
  41. ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
  42. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, Vec2(4.0f, 1.0f)); // Tighten spacing
  43. for(const LogItem& item : m_logItems)
  44. {
  45. switch(item.m_type)
  46. {
  47. case LoggerMessageType::NORMAL:
  48. ImGui::PushStyleColor(ImGuiCol_Text, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
  49. break;
  50. case LoggerMessageType::ERROR:
  51. case LoggerMessageType::FATAL:
  52. ImGui::PushStyleColor(ImGuiCol_Text, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
  53. break;
  54. case LoggerMessageType::WARNING:
  55. ImGui::PushStyleColor(ImGuiCol_Text, Vec4(0.9f, 0.6f, 0.14f, 1.0f));
  56. break;
  57. default:
  58. ANKI_ASSERT(0);
  59. }
  60. static const Array<const char*, static_cast<U>(LoggerMessageType::COUNT)> MSG_TEXT = {{"I", "E", "W", "F"}};
  61. ImGui::TextWrapped("[%s][%s] %s (%s:%d %s)",
  62. MSG_TEXT[static_cast<U>(item.m_type)],
  63. (item.m_subsystem) ? item.m_subsystem : "N/A ",
  64. item.m_msg.cstr(),
  65. item.m_file,
  66. item.m_line,
  67. item.m_func);
  68. ImGui::PopStyleColor();
  69. }
  70. ImGui::SetScrollHereY(1.0f);
  71. ImGui::PopStyleVar();
  72. ImGui::EndChild();
  73. // Commands
  74. ImGui::Separator();
  75. if(ImGui::InputText(
  76. "", &m_inputText[0], m_inputText.getSizeInBytes(), ImGuiInputTextFlags_EnterReturnsTrue, nullptr, nullptr))
  77. {
  78. ANKI_LOGI("Command: %s", &m_inputText[0]);
  79. m_inputText[0] = '\0';
  80. }
  81. ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
  82. ImGui::End();
  83. ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = oldWindowColor;
  84. ctx->popFont();
  85. }
  86. void DeveloperConsole::newLogItem(const LoggerMessageInfo& inf)
  87. {
  88. LogItem* newLogItem;
  89. // Pop first
  90. if(m_logItemCount + 1 > MAX_LOG_ITEMS)
  91. {
  92. LogItem* first = &m_logItems.getFront();
  93. m_logItems.popFront();
  94. first->m_msg.destroy(m_alloc);
  95. // Re-use the log item
  96. newLogItem = first;
  97. --m_logItemCount;
  98. }
  99. else
  100. {
  101. newLogItem = m_alloc.newInstance<LogItem>();
  102. }
  103. // Create the new item
  104. newLogItem->m_file = inf.m_file;
  105. newLogItem->m_func = inf.m_func;
  106. newLogItem->m_subsystem = inf.m_subsystem;
  107. newLogItem->m_msg.create(m_alloc, inf.m_msg);
  108. newLogItem->m_line = inf.m_line;
  109. newLogItem->m_type = inf.m_type;
  110. // Push it back
  111. m_logItems.pushBack(newLogItem);
  112. ++m_logItemCount;
  113. }
  114. } // end namespace anki