3#include "InspectorGuiHelper.h"
5#include "Systems/Core/ScriptSystem.h"
7#include "Scripting/ScriptingManager.h"
9#include "Utilities/Parsing.h"
11#include "Renderer/IRenderer.h"
13#include "Foundation/Reflection/TypeDatabase.h"
22 int editorCallback(ImGuiInputTextCallbackData* data)
25 auto & editor = engine->editorContext;
27 auto & io = ImGui::GetIO();
29 if (editor.currentCompletions.size() > 1) {
30 ImGui::SetNextWindowPos(ImVec2(ImGui::GetItemRectMin().x + editor.completionOffset * 7.0f, ImGui::GetItemRectMax().y - 15.0f));
31 ImGui::SetNextWindowSize(ImVec2(200, 300));
32 ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGui::GetStyle().Colors[ImGuiCol_Border]);
33 ImGui::BeginTooltip();
34 for (
size_t i = 0; i < editor.currentCompletions.size(); ++i) {
35 auto & completion = editor.currentCompletions[i];
36 const ImColor col = i ==
static_cast<size_t>(editor.completionIndex) ? ImColor(1.0f, 1.0f, 1.0f, 1.0f) : ImColor(0.7f, 0.7f, 0.7f, 1.0f);
37 ImGui::PushStyleColor(ImGuiCol_Text, col.Value);
38 ImGui::TextUnformatted(std::string(completion).c_str());
39 ImGui::PopStyleColor();
41 if (i ==
static_cast<size_t>(editor.completionIndex)) {
42 ImGui::SetScrollHereY(0.5f);
46 ImGui::PopStyleColor();
49 if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) {
50 if (editor.currentCompletions.empty()) {
51 editor.original = std::string(data->Buf, data->BufTextLen);
53 static thread_local Cogs::Core::TokenStream splits;
54 static thread_local Cogs::Core::TokenStream tokens;
55 static thread_local Cogs::Core::TokenStream completions;
60 Cogs::Core::split(editor.original,
" =\t,:[](){};", splits);
62 if (splits.empty())
return 0;
64 Cogs::Core::split(splits.back(),
".", tokens);
66 if (editor.original.back() ==
'.') {
67 tokens.push_back(
nullptr);
68 editor.completionOffset = editor.original.size();
70 editor.completionOffset = tokens.back().data() - editor.original.data();
73 engine->completions(tokens, completions);
75 std::sort(completions.begin(), completions.end());
77 editor.currentCompletions = completions;
78 editor.completionIndex = 0;
80 if (tokens.back().size()) {
81 editor.currentCompletions.push_back(tokens.back());
84 editor.completionIndex += io.KeyShift ? -1 : 1;
87 if (editor.currentCompletions.empty())
return 0;
89 if (editor.completionIndex >= (
int)editor.currentCompletions.size()) editor.completionIndex = 0;
90 else if (editor.completionIndex < 0) editor.completionIndex = (int)editor.currentCompletions.size() - 1;
92 auto & suggestion = editor.currentCompletions[editor.completionIndex];
93 data->DeleteChars((
int)editor.completionOffset, data->BufTextLen - (int)editor.completionOffset);
94 data->InsertChars((
int)editor.completionOffset, suggestion.data(), suggestion.data() + suggestion.size());
95 data->CursorPos = data->BufTextLen;
96 data->BufDirty =
true;
97 editor.suggested = std::string(data->Buf, data->BufTextLen);
98 }
else if (!editor.currentCompletions.empty() && std::string_view(data->Buf, data->BufTextLen) != std::string_view(editor.suggested)) {
99 editor.currentCompletions.clear();
100 editor.completionIndex = 0;
105 if (editor.commandHistory.empty())
return 0;
107 auto modifyHistory = [&](
int offset) {
108 editor.historyIndex += offset;
109 editor.historyIndex = std::max(0, std::min(editor.historyIndex, (
int)editor.commandHistory.size() - 1));
111 data->BufTextLen = snprintf(data->Buf, data->BufSize,
"%s", editor.commandHistory[editor.historyIndex].c_str());
112 data->BufDirty =
true;
113 data->CursorPos = data->BufTextLen;
116 if (ImGui::IsKeyPressed(ImGuiKey_UpArrow) && (io.KeyShift || data->CursorPos == 0) && !editor.movedUp) {
119 editor.movedUp =
true;
122 }
else if (editor.movedUp && !ImGui::IsKeyPressed(ImGuiKey_UpArrow)) {
123 editor.movedUp =
false;
126 if (ImGui::IsKeyPressed(ImGuiKey_DownArrow) && io.KeyShift && !editor.movedDown) {
129 editor.movedDown =
true;
132 }
else if (editor.movedDown && !ImGui::IsKeyPressed(ImGuiKey_DownArrow)) {
133 editor.movedDown =
false;
140void Cogs::Core::scriptConsole(Context * context,
bool * show)
143 ImGui::SetNextWindowSize(ImVec2(600, 1000), ImGuiCond_Once);
145 guiBegin(
"Script Console", show);
147 auto & scriptingManager = context->scriptingManager;
149 for (
auto & scriptEngine : scriptingManager->engines) {
150 auto & editor = scriptEngine->editorContext;
152 ImGui::Text(
"%s", scriptEngine->editorContext.name.c_str());
154 ImGui::BeginChild((editor.name +
" History").c_str(), ImVec2(0, 200),
false, ImGuiWindowFlags_HorizontalScrollbar);
156 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1));
158 for (
auto & h : editor.history) {
159 ImColor col = ImColor(1.0f, 1.0f, 1.0f, 1.0f);
160 if (h.find(
"Error:") != std::string::npos) {
161 col = ImColor(1.0f, 0.4f, 0.4f, 1.0f);
162 }
else if (h.find(
"> ") == 0) {
163 col = ImColor(0.7f, 0.7f, 0.7f, 1.0f);
165 ImGui::PushStyleColor(ImGuiCol_Text, col.Value);
166 ImGui::TextUnformatted(h.c_str());
167 ImGui::PopStyleColor();
170 if (editor.scrollToBottom) {
171 ImGui::SetScrollHereY();
172 editor.scrollToBottom =
false;
175 ImGui::PopStyleVar();
178 ImGui::PushItemWidth(-1);
179 if (ImGui::InputTextMultiline((editor.name +
" Source").c_str(),
180 (
char *)editor.buffer.data(),
181 editor.buffer.size(),
183 ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CtrlEnterForNewLine | ImGuiInputTextFlags_CallbackAlways | ImGuiInputTextFlags_CallbackCompletion,
185 scriptEngine.get())) {
187 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
189 guiRenderer->addTextToGlyphBuilder(editor.buffer.data());
192 auto command = std::string(editor.buffer.data());
194 if (command.size()) {
195 editor.history.emplace_back(
"> " + command +
"\n");
197 editor.commandHistory.emplace_back(std::move(command));
199 std::string result(scriptEngine->eval(editor.buffer.data()));
201 editor.history.emplace_back(result +
"\n");
202 editor.scrollToBottom =
true;
204 editor.buffer.clear();
205 editor.buffer.resize(16384);
207 editor.historyIndex = (int)editor.commandHistory.size();
210 ImGui::SetKeyboardFocusHere(1);
218void Cogs::Core::scriptInspector(Context * ,
bool * )