h2-mod/src/client/component/gui_console.cpp

193 lines
3.9 KiB
C++
Raw Normal View History

2021-12-20 20:00:22 -05:00
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "scheduler.hpp"
#include "command.hpp"
#include "game_console.hpp"
#include "gui.hpp"
#include <utils/string.hpp>
#include <utils/hook.hpp>
#include <utils/concurrency.hpp>
namespace gui_console
{
namespace
{
bool auto_scroll = true;
int history_index = -1;
std::string input{};
std::string filter{};
std::vector<std::string> matches{};
int input_text_edit(ImGuiInputTextCallbackData* data)
{
switch (data->EventFlag)
{
case ImGuiInputTextFlags_CallbackCompletion:
{
matches.clear();
const std::string text = data->Buf;
if (text.find(" ") != std::string::npos)
{
game_console::find_matches(text.substr(0, text.find(" ")), matches, true);
}
else
{
game_console::find_matches(text, matches, false);
}
if (matches.size() == 1)
{
const auto match = matches[0].data();
data->DeleteChars(0, data->BufTextLen);
data->InsertChars(0, match, match + strlen(match));
}
break;
}
case ImGuiInputTextFlags_CallbackHistory:
{
const auto history = game_console::get_history();
if (data->EventKey == ImGuiKey_UpArrow)
{
if (++history_index >= history.size())
{
history_index = static_cast<int>(history.size()) - 1;
}
data->DeleteChars(0, data->BufTextLen);
if (history_index != -1)
{
const auto text = history.at(history_index).data();
data->InsertChars(0, text, text + strlen(text));
}
}
else if (data->EventKey == ImGuiKey_DownArrow)
{
if (--history_index < -1)
{
history_index = -1;
}
data->DeleteChars(0, data->BufTextLen);
if (history_index != -1)
{
const auto text = history.at(history_index).data();
data->InsertChars(0, text, text + strlen(text));
}
}
break;
}
}
return 0;
}
std::string get_filtered_text()
{
std::string text{};
const auto history = game_console::get_output();
for (const auto& line : history)
{
if (strstr(line.data(), filter.data()))
{
text.append(line.data());
text.append("\n");
}
}
if (text[text.size() - 1] == '\n')
{
text.pop_back();
}
return text;
}
void on_frame()
{
auto* open = &gui::enabled_menus["console"];
if (!*open)
{
return;
}
auto filtered_text = get_filtered_text();
static auto input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion |
ImGuiInputTextFlags_CallbackHistory;
ImGui::Begin("Console", open);
if (ImGui::BeginPopup("Options"))
{
ImGui::Checkbox("Auto-scroll", &auto_scroll);
ImGui::EndPopup();
}
if (ImGui::Button("Clear"))
{
game_console::clear_console();
}
ImGui::SameLine();
if (ImGui::Button("Copy"))
{
utils::string::set_clipboard_data(filtered_text);
}
ImGui::Separator();
if (ImGui::Button("Options"))
{
ImGui::OpenPopup("Options");
}
ImGui::SameLine();
ImGui::InputText("Filter", &filter);
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
ImGui::BeginChild("console_scroll", ImVec2(0, -footer_height_to_reserve), false);
ImGui::Text(filtered_text.data(), ImVec2(-1, -1));
if (auto_scroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
{
ImGui::SetScrollHereY(1.0f);
}
ImGui::EndChild();
if (ImGui::InputText("Input", &input, input_text_flags, input_text_edit))
{
game_console::add(input.data());
input.clear();
ImGui::SetKeyboardFocusHere(-1);
}
ImGui::End();
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
gui::on_frame(on_frame);
}
};
}
REGISTER_COMPONENT(gui_console::component)