Skip to content

Commit f776531

Browse files
authored
Fix and improve the console window (Kenix3#819)
* Fix and improve the console window * drop local var
1 parent 27a5023 commit f776531

File tree

2 files changed

+96
-25
lines changed

2 files changed

+96
-25
lines changed

src/window/gui/ConsoleWindow.cpp

+92-23
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,60 @@ int32_t ConsoleWindow::ClearCommand(std::shared_ptr<Console> console, const std:
5959
return 0;
6060
}
6161

62+
int32_t ConsoleWindow::UnbindCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
63+
std::string* output) {
64+
if (args.size() > 1) {
65+
auto window = std::static_pointer_cast<ConsoleWindow>(
66+
Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"));
67+
if (!window) {
68+
if (output) {
69+
*output += "A console window is necessary for Unbind";
70+
}
71+
72+
return 1;
73+
}
74+
75+
for (int k = ImGuiKey_NamedKey_BEGIN; k < ImGuiKey_NamedKey_END; k++) {
76+
std::string key(ImGui::GetKeyName((ImGuiKey)k));
77+
bool unbound = false;
78+
79+
if (toLowerCase(args[1]) == toLowerCase(key)) {
80+
if (window->mBindings.contains((ImGuiKey)k)) {
81+
if (output) {
82+
*output += "Unbound '" + args[1] + " from " + window->mBindings[(ImGuiKey)k];
83+
}
84+
window->mBindings.erase((ImGuiKey)k);
85+
unbound = true;
86+
}
87+
if (window->mBindingToggle.contains((ImGuiKey)k)) {
88+
if (output) {
89+
if (unbound) {
90+
*output += "\n";
91+
}
92+
*output += "Unbound toggle '" + args[1] + " from " + window->mBindingToggle[(ImGuiKey)k];
93+
}
94+
window->mBindingToggle.erase((ImGuiKey)k);
95+
unbound = true;
96+
}
97+
98+
if (!unbound) {
99+
if (output) {
100+
*output += "Nothing bound to '" + args[1];
101+
}
102+
}
103+
break;
104+
}
105+
}
106+
} else {
107+
if (output) {
108+
*output += "Not enough arguments";
109+
}
110+
return 1;
111+
}
112+
113+
return 0;
114+
}
115+
62116
int32_t ConsoleWindow::BindCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
63117
std::string* output) {
64118
if (args.size() > 2) {
@@ -72,9 +126,7 @@ int32_t ConsoleWindow::BindCommand(std::shared_ptr<Console> console, const std::
72126
return 1;
73127
}
74128

75-
const ImGuiIO* io = &ImGui::GetIO();
76-
77-
for (size_t k = 0; k < std::size(io->KeysData); k++) {
129+
for (int k = ImGuiKey_NamedKey_BEGIN; k < ImGuiKey_NamedKey_END; k++) {
78130
std::string key(ImGui::GetKeyName((ImGuiKey)k));
79131

80132
if (toLowerCase(args[1]) == toLowerCase(key)) {
@@ -112,9 +164,7 @@ int32_t ConsoleWindow::BindToggleCommand(std::shared_ptr<Console> console, const
112164
return 1;
113165
}
114166

115-
const ImGuiIO* io = &ImGui::GetIO();
116-
117-
for (size_t k = 0; k < std::size(io->KeysData); k++) {
167+
for (int k = ImGuiKey_NamedKey_BEGIN; k < ImGuiKey_NamedKey_END; k++) {
118168
std::string key(ImGui::GetKeyName((ImGuiKey)k));
119169

120170
if (toLowerCase(args[1]) == toLowerCase(key)) {
@@ -254,9 +304,11 @@ void ConsoleWindow::InitElement() {
254304
"Sets a console variable.",
255305
{ { "varName", ArgumentType::TEXT }, { "varValue", ArgumentType::TEXT } } });
256306
Context::GetInstance()->GetConsole()->AddCommand(
257-
"get", { GetCommand, "Bind key as a bool toggle", { { "varName", ArgumentType::TEXT } } });
307+
"get", { GetCommand, "Gets a console variable", { { "varName", ArgumentType::TEXT } } });
258308
Context::GetInstance()->GetConsole()->AddCommand("help", { HelpCommand, "Shows all the commands" });
259309
Context::GetInstance()->GetConsole()->AddCommand("clear", { ClearCommand, "Clear the console history" });
310+
Context::GetInstance()->GetConsole()->AddCommand(
311+
"unbind", { UnbindCommand, "Unbinds a key", { { "key", ArgumentType::TEXT } } });
260312
Context::GetInstance()->GetConsole()->AddCommand(
261313
"bind",
262314
{ BindCommand, "Binds key to commands", { { "key", ArgumentType::TEXT }, { "cmd", ArgumentType::TEXT } } });
@@ -311,7 +363,7 @@ void ConsoleWindow::DrawElement() {
311363
}
312364
ImGui::EndTable();
313365
}
314-
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
366+
if (ImGui::IsKeyPressed(ImGuiKey_Escape, false)) {
315367
mOpenAutocomplete = false;
316368
}
317369
ImGui::PopStyleColor();
@@ -333,7 +385,7 @@ void ConsoleWindow::DrawElement() {
333385

334386
// Renders top bar filters
335387
if (ImGui::Button("Clear")) {
336-
mLog[mCurrentChannel].clear();
388+
ClearLogs(mCurrentChannel);
337389
}
338390

339391
if (CVarGetInteger("gSinkEnabled", 0)) {
@@ -386,19 +438,20 @@ void ConsoleWindow::DrawElement() {
386438
ImGuiWindowFlags_HorizontalScrollbar);
387439
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(.3f, .3f, .3f, 1.0f));
388440
if (ImGui::BeginTable("History", 1)) {
441+
bool focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
442+
const std::vector<ConsoleLine> channel = mLog[mCurrentChannel];
389443

390-
if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) {
391-
if (mSelectedId < (int32_t)mLog.size() - 1) {
444+
if (focused && ImGui::IsKeyPressed(ImGuiKey_DownArrow)) {
445+
if (mSelectedId < (int32_t)channel.size() - 1) {
392446
++mSelectedId;
393447
}
394448
}
395-
if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) {
449+
if (focused && ImGui::IsKeyPressed(ImGuiKey_UpArrow)) {
396450
if (mSelectedId > 0) {
397451
--mSelectedId;
398452
}
399453
}
400454

401-
const std::vector<ConsoleLine> channel = mLog[mCurrentChannel];
402455
for (size_t i = 0; i < channel.size(); i++) {
403456
ConsoleLine line = channel[i];
404457
if (!mFilter.empty() && line.Text.find(mFilter) == std::string::npos) {
@@ -442,6 +495,9 @@ void ConsoleWindow::DrawElement() {
442495
ImGuiInputTextFlags_CallbackCompletion |
443496
ImGuiInputTextFlags_CallbackHistory;
444497
ImGui::PushItemWidth(-53.0f);
498+
499+
float yBeforeInput = ImGui::GetCursorPosY();
500+
445501
if (ImGui::InputTextWithHint("##CMDInput", ">", mInputBuffer, gMaxBufferSize, flags,
446502
&ConsoleWindow::CallbackStub, this)) {
447503
inputFocus = true;
@@ -453,7 +509,8 @@ void ConsoleWindow::DrawElement() {
453509

454510
if (mCmdHint != "None") {
455511
if (ImGui::IsItemFocused()) {
456-
ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y));
512+
// Place the tooltip above the console input field
513+
ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y - ((size.y - yBeforeInput) * 2)));
457514
ImGui::SameLine();
458515
ImGui::BeginTooltip();
459516
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
@@ -481,6 +538,7 @@ void ConsoleWindow::DrawElement() {
481538

482539
void ConsoleWindow::Dispatch(const std::string& line) {
483540
mCmdHint = "None";
541+
mHistoryIndex = -1;
484542
mHistory.push_back(line);
485543
SendInfoMessage("> " + line);
486544
auto console = Context::GetInstance()->GetConsole();
@@ -514,7 +572,6 @@ void ConsoleWindow::Dispatch(const std::string& line) {
514572
int ConsoleWindow::CallbackStub(ImGuiInputTextCallbackData* data) {
515573
const auto instance = static_cast<ConsoleWindow*>(data->UserData);
516574
const bool emptyHistory = instance->mHistory.empty();
517-
const int historyIndex = instance->mHistoryIndex;
518575
auto console = Context::GetInstance()->GetConsole();
519576
std::string history;
520577

@@ -533,23 +590,30 @@ int ConsoleWindow::CallbackStub(ImGuiInputTextCallbackData* data) {
533590
if (emptyHistory) {
534591
break;
535592
}
536-
if (historyIndex < static_cast<int>(instance->mHistory.size()) - 1) {
537-
instance->mHistoryIndex += 1;
593+
if (instance->mHistoryIndex > 0) {
594+
instance->mHistoryIndex -= 1;
595+
} else if (instance->mHistoryIndex < 0) {
596+
instance->mHistoryIndex = static_cast<int>(instance->mHistory.size()) - 1;
538597
}
539598
data->DeleteChars(0, data->BufTextLen);
540-
data->InsertChars(0, instance->mHistory[instance->mHistoryIndex].c_str());
599+
if (instance->mHistoryIndex >= 0) {
600+
data->InsertChars(0, instance->mHistory[instance->mHistoryIndex].c_str());
601+
}
541602
instance->mCmdHint = "None";
542603
break;
543604
case ImGuiKey_DownArrow:
544605
if (emptyHistory) {
545606
break;
546607
}
547-
if (historyIndex > -1) {
548-
instance->mHistoryIndex -= 1;
608+
if (instance->mHistoryIndex >= 0 &&
609+
instance->mHistoryIndex < static_cast<int>(instance->mHistory.size()) - 1) {
610+
instance->mHistoryIndex += 1;
611+
} else {
612+
instance->mHistoryIndex = -1;
549613
}
550614
data->DeleteChars(0, data->BufTextLen);
551-
if (historyIndex >= 0) {
552-
data->InsertChars(0, instance->mHistory[historyIndex].c_str());
615+
if (instance->mHistoryIndex >= 0) {
616+
data->InsertChars(0, instance->mHistory[instance->mHistoryIndex].c_str());
553617
}
554618
instance->mCmdHint = "None";
555619
break;
@@ -591,7 +655,8 @@ void ConsoleWindow::Append(const std::string& channel, spdlog::level::level_enum
591655
vsnprintf(buf.data(), buf.size(), fmt, args);
592656

593657
buf[buf.size() - 1] = 0;
594-
mLog[channel].push_back({ std::string(buf.begin(), buf.end()), priority });
658+
// Do not copy the null terminator into the std::string
659+
mLog[channel].push_back({ std::string(buf.begin(), buf.end() - 1), priority });
595660
}
596661

597662
void ConsoleWindow::Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...) {
@@ -625,12 +690,16 @@ void ConsoleWindow::SendErrorMessage(const std::string& str) {
625690

626691
void ConsoleWindow::ClearLogs(std::string channel) {
627692
mLog[channel].clear();
693+
mSelectedEntries.clear();
694+
mSelectedId = -1;
628695
}
629696

630697
void ConsoleWindow::ClearLogs() {
631698
for (auto [key, var] : mLog) {
632699
var.clear();
633700
}
701+
mSelectedEntries.clear();
702+
mSelectedId = -1;
634703
}
635704

636705
std::string ConsoleWindow::GetCurrentChannel() {

src/window/gui/ConsoleWindow.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class ConsoleWindow : public GuiWindow {
4646
std::string* output);
4747
static int32_t HelpCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
4848
std::string* output);
49+
static int32_t UnbindCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
50+
std::string* output);
4951
static int32_t BindCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
5052
std::string* output);
5153
static int32_t BindToggleCommand(std::shared_ptr<Console> console, const std::vector<std::string>& args,
@@ -64,7 +66,7 @@ class ConsoleWindow : public GuiWindow {
6466
bool mOpenAutocomplete = false;
6567
char* mInputBuffer = nullptr;
6668
char* mFilterBuffer = nullptr;
67-
std::string mCmdHint = "Null";
69+
std::string mCmdHint = "None";
6870
spdlog::level::level_enum mLevelFilter = spdlog::level::trace;
6971
std::map<ImGuiKey, std::string> mBindings;
7072
std::map<ImGuiKey, std::string> mBindingToggle;
@@ -87,4 +89,4 @@ class ConsoleWindow : public GuiWindow {
8789
};
8890
static constexpr size_t gMaxBufferSize = 255;
8991
};
90-
} // namespace Ship
92+
} // namespace Ship

0 commit comments

Comments
 (0)