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>
|
|
|
|
|
2022-03-27 13:29:28 -04:00
|
|
|
namespace gui::console
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
bool auto_scroll = true;
|
|
|
|
int history_index = -1;
|
2021-12-28 11:14:47 -05:00
|
|
|
std::string input;
|
|
|
|
std::string filter;
|
2022-06-17 14:00:39 -04:00
|
|
|
std::vector<dvars::dvar_info> matches;
|
2021-12-20 20:00:22 -05:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-12-28 11:14:47 -05:00
|
|
|
if (matches.size() < 24 && matches.size() > 0)
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
2022-06-17 14:00:39 -04:00
|
|
|
const auto match = matches.begin()->name.data();
|
2021-12-20 20:00:22 -05:00
|
|
|
data->DeleteChars(0, data->BufTextLen);
|
|
|
|
data->InsertChars(0, match, match + strlen(match));
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ImGuiInputTextFlags_CallbackHistory:
|
|
|
|
{
|
2022-03-27 13:29:28 -04:00
|
|
|
const auto& history = game_console::get_history();
|
2021-12-20 20:00:22 -05:00
|
|
|
|
|
|
|
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{};
|
|
|
|
|
2022-03-27 13:29:28 -04:00
|
|
|
const auto& output = game_console::get_output();
|
2021-12-22 16:25:41 -05:00
|
|
|
for (const auto& line : output)
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
2021-12-21 09:21:50 -05:00
|
|
|
if (utils::string::find_lower(line, filter))
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
|
|
|
text.append(line.data());
|
|
|
|
text.append("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 16:01:50 -04:00
|
|
|
if (!text.empty() && text[text.size() - 1] == '\n')
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
|
|
|
text.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_frame()
|
|
|
|
{
|
2022-03-27 13:29:28 -04:00
|
|
|
static auto* enabled = &gui::enabled_menus["console"];
|
|
|
|
if (!*enabled)
|
2021-12-20 20:00:22 -05:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-22 16:25:41 -05:00
|
|
|
const auto filtered_text = get_filtered_text();
|
|
|
|
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
|
|
|
static const auto input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion |
|
|
|
|
ImGuiInputTextFlags_CallbackHistory;
|
2021-12-20 20:00:22 -05:00
|
|
|
|
2022-03-27 13:29:28 -04:00
|
|
|
ImGui::Begin("Console", enabled);
|
2021-12-20 20:00:22 -05:00
|
|
|
|
|
|
|
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);
|
2021-12-21 09:21:50 -05:00
|
|
|
gui::notification("Console", "Text copied to clipboard");
|
2021-12-20 20:00:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
if (ImGui::Button("Options"))
|
|
|
|
{
|
|
|
|
ImGui::OpenPopup("Options");
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::InputText("Filter", &filter);
|
|
|
|
|
|
|
|
ImGui::BeginChild("console_scroll", ImVec2(0, -footer_height_to_reserve), false);
|
|
|
|
|
2022-03-27 13:29:28 -04:00
|
|
|
const auto& output = game_console::get_output();
|
2021-12-28 15:41:11 -05:00
|
|
|
for (const auto& line : output)
|
|
|
|
{
|
|
|
|
if (utils::string::find_lower(line, filter))
|
|
|
|
{
|
|
|
|
ImGui::Text(line.data(), ImVec2(-1, -1));
|
|
|
|
}
|
|
|
|
}
|
2021-12-20 20:00:22 -05:00
|
|
|
|
|
|
|
if (auto_scroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
|
|
|
|
{
|
|
|
|
ImGui::SetScrollHereY(1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
if (ImGui::InputText("Input", &input, input_text_flags, input_text_edit))
|
|
|
|
{
|
2022-03-27 13:29:28 -04:00
|
|
|
auto& history = game_console::get_history();
|
2021-12-21 09:21:50 -05:00
|
|
|
|
|
|
|
if (history_index != -1)
|
|
|
|
{
|
|
|
|
const auto itr = history.begin() + history_index;
|
|
|
|
|
|
|
|
if (*itr == input)
|
|
|
|
{
|
|
|
|
history.erase(history.begin() + history_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-22 20:15:33 -05:00
|
|
|
ImGui::SetKeyboardFocusHere(-1);
|
2021-12-20 20:00:22 -05:00
|
|
|
game_console::add(input.data());
|
2021-12-22 20:15:33 -05:00
|
|
|
history_index = -1;
|
2021-12-20 20:00:22 -05:00
|
|
|
input.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class component final : public component_interface
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void post_unpack() override
|
|
|
|
{
|
|
|
|
gui::on_frame(on_frame);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:29:28 -04:00
|
|
|
REGISTER_COMPONENT(gui::console::component)
|