Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
OutputWindow.cpp
Go to the documentation of this file.
1
2
7
8#include <imgui_internal.h>
9#include <IconsForkAwesome.h>
10
11namespace Divide
12{
13 constexpr U16 g_maxLogEntries = 1024u;
14 static U16 g_logEntries = 256;
15
16 static std::atomic_size_t g_writeIndex = 0;
18
19 namespace
20 {
21 void PrintColouredText(const string& text, const ImVec4& colour)
22 {
23 ImGui::PushStyleColor( ImGuiCol_Text, colour );
24 ImGui::TextUnformatted( text.c_str(), text.c_str() + text.length() );
25 ImGui::PopStyleColor();
26 }
27 }
28
30 : DockedWindow( parent, descriptor ),
31 _inputBuf{}
32 {
33 memset( _inputBuf, 0, sizeof _inputBuf );
34
35 g_writeIndex = 0;
37 {
40 } );
41
42 g_log.resize( g_maxLogEntries );
43 }
44
46 {
48 {
50 }
51
52 clearLog();
53 }
54
55
57 {
58 for ( auto& entry : g_log)
59 {
60 entry = {};
61 }
62
63 g_writeIndex.store( 0 );
64 _scrollToBottom = true;
65 }
66
68 {
70
71 static bool infoFlag = true;
72 static bool warningFlag = true;
73 static bool errorFlag = true;
74
75 ImGui::PushStyleColor( ImGuiCol_ChildBg, ImVec4( 0.3f, 0.3f, 0.3f, 1.0f ) );
76 {
77 bool tooltip = false;
78 ImGui::Text( ICON_FK_SEARCH ); tooltip = tooltip || ImGui::IsItemHovered();
79 ImGui::SameLine();
80 ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );
81 _filter.Draw( "##Filter", 180 ); tooltip = tooltip || ImGui::IsItemHovered();
82 if ( tooltip )
83 {
84 ImGui::SetTooltip( "Search/Filter (\"incl,-excl\") (\"error\")" );
85 }
86 ImGui::SameLine(0.f, 30.f);
87 ImGui::Text( "Max log entries: ");
88 ImGui::SameLine();
89 ImGui::SetNextItemWidth( 100 );
90 U16 logSize = g_logEntries;
91 if (ImGui::InputScalar( "##MaxLogEntries", ImGuiDataType_U16, &logSize, nullptr, nullptr, nullptr, ImGuiInputTextFlags_EnterReturnsTrue ))
92 {
93 if ( logSize != g_logEntries)
94 {
95 g_logEntries = CLAMPED<U16>( logSize, 1u, g_maxLogEntries );
96 }
97 }
98 ImGui::SameLine();
99 if ( ImGui::Checkbox( "Info", &infoFlag ) )
100 {
102 }
103 ImGui::SameLine();
104 if ( ImGui::Checkbox( "Warning", &warningFlag ) )
105 {
107 }
108 ImGui::SameLine();
109 if ( ImGui::Checkbox( "Error", &errorFlag ) )
110 {
112 }
113 }
114 ImGui::PopStyleVar();
115 ImGuiWindow* window = ImGui::GetCurrentWindow();
116 ImGui::SameLine( window->SizeFull.x - 200 );
117 if ( ImGui::SmallButton( "Clear" ) )
118 {
119 clearLog();
120 }
121 ImGui::SameLine();
122 const bool copy_to_clipboard = ImGui::SmallButton( "Copy" );
123 ImGui::Separator();
124
125 ImGui::BeginChild( "ScrollingRegion", ImVec2( 0, -ImGui::GetFrameHeightWithSpacing() ), false, ImGuiWindowFlags_HorizontalScrollbar );
126 if ( ImGui::BeginPopupContextWindow() )
127 {
128 if ( ImGui::Selectable( "Clear" ) )
129 {
130 clearLog();
131 }
132 ImGui::EndPopup();
133 }
134
135 static ImVec4 colours[] = {
136 ImVec4( 1.0f, 1.0f, 1.0f, 1.0f ),
137 ImVec4( 1.0f, 1.0f, 0.0f, 1.0f ),
138 ImVec4( 1.0f, 0.4f, 0.4f, 1.0f ),
139 ImVec4( 0.0f, 0.0f, 1.0f, 1.0f )
140 };
141
142 size_t readIndex = 0u;
143 size_t writeIndex = g_writeIndex.load();
144 if ( writeIndex >= g_logEntries )
145 {
146 readIndex = writeIndex - g_logEntries;
147 }
148 else
149 {
150 size_t remainder = g_logEntries - writeIndex;
151 readIndex = g_maxLogEntries - remainder;
152 }
153
154 ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 4, 1 ) ); // Tighten spacing
155
156 if ( copy_to_clipboard )
157 {
158 ImGui::LogToClipboard();
159 }
160 {
161 PROFILE_SCOPE( "Print Scrolling region ", Profiler::Category::GUI );
162
164
165 static string output="";
166
167 output.resize(0);
168
169 for ( U16 i = 0u; i < g_logEntries; ++i )
170 {
171 const Console::OutputEntry& message = g_log[(readIndex + i) % g_maxLogEntries];
172 const char* msgBegin = message._text.c_str();
173 const char* msgEnd = message._text.c_str() + message._text.length();
174
175 if ( !_filter.PassFilter( msgBegin, msgEnd ) ) [[unlikely]]
176 {
177 continue;
178 }
179 switch (message._type)
180 {
182 {
184 continue;
185 } break;
188 {
189 if ( !infoFlag )
190 {
191 continue;
192 }
193 } break;
195 {
196 if ( !warningFlag )
197 {
198 continue;
199 }
200 } break;
202 {
203 if ( !errorFlag)
204 {
205 continue;
206 }
207 } break;
208 };
209
210 if ( previousType != message._type )
211 {
212 if ( !output.empty() )
213 {
214 PrintColouredText(output, colours[to_U8( previousType )]);
215 output.resize(0);
216 }
217 previousType = message._type;
218 }
219
220 output.append( message._text );
221 output.append( "\n" );
222 }
223
224 if ( !output.empty() )
225 {
226 PrintColouredText( output, colours[to_U8( previousType )] );
227 }
228 }
229
230
232 {
234 _scrollToButtomReset = false;
235 }
236
237 if ( copy_to_clipboard )
238 {
239 ImGui::LogFinish();
240 }
241
242 ImGui::PopStyleVar();
243 ImGui::EndChild();
244 ImGui::Separator();
245
246 ImGui::Text( "Input:" ); ImGui::SameLine();
247 if ( ImGui::InputText( "##Input:",
248 _inputBuf,
250 ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory,
251 []( ImGuiInputTextCallbackData* data ) noexcept
252 {
253 const OutputWindow* console = static_cast<OutputWindow*>(data->UserData);
254 return console->TextEditCallback( data );
255 },
256 (void*)this ) )
257 {
258 char* input_end = _inputBuf + strlen( _inputBuf );
259 while ( input_end > _inputBuf && input_end[-1] == ' ' )
260 {
261 input_end--;
262 }
263 *input_end = 0;
264
265 if ( _inputBuf[0] )
266 {
268 }
269 strcpy( _inputBuf, "" );
270 }
271 {
272 bool tooltip = false;
273 ImGui::SameLine( window->SizeFull.x - 125 );
274 ImGui::Text( ICON_FK_ARROW_CIRCLE_DOWN ); tooltip = tooltip || ImGui::IsItemHovered();
275 ImGui::SameLine();
276 ImGui::PushID( ICON_FK_ARROW_CIRCLE_DOWN"_ID" );
277 ImGui::Checkbox( "", &_scrollToBottom ); tooltip = tooltip || ImGui::IsItemHovered();
278 ImGui::PopID();
279 if ( tooltip )
280 {
281 ImGui::SetTooltip( "Auto-scroll to bottom" );
282 }
283 }
284 // Demonstrate keeping auto focus on the input box
285 if ( ImGui::IsItemHovered() ||
286 (ImGui::IsWindowFocused( ImGuiFocusedFlags_RootAndChildWindows ) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked( 0 )) )
287 {
288 ImGui::SetKeyboardFocusHere( -1 ); // Auto focus previous widget
289 }
290 ImGui::PopStyleColor();
291 }
292
294 {
295 g_log[g_writeIndex.fetch_add( 1 ) % g_maxLogEntries] = entry;
296 }
297
298 void OutputWindow::executeCommand( const char* command_line )
299 {
300 PrintText(
301 {
302 Util::StringFormat( "# {}\n", command_line ).c_str(),
304 }
305 );
307 }
308
309 I32 OutputWindow::TextEditCallback( const ImGuiInputTextCallbackData* data ) noexcept
310 {
311 switch ( data->EventFlag )
312 {
313 case ImGuiInputTextFlags_CallbackCompletion:
314 case ImGuiInputTextFlags_CallbackHistory:
315 default: break;
316 }
317
318 return -1;
319 }
320
321} //namespace Divide
#define DIVIDE_UNEXPECTED_CALL()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
OutputWindow(Editor &parent, const Descriptor &descriptor)
~OutputWindow() override
ImGuiTextFilter _filter
Definition: OutputWindow.h:60
void executeCommand(const char *command_line)
static void PrintText(const Console::OutputEntry &entry)
static I32 TextEditCallback(const ImGuiInputTextCallbackData *data) noexcept
void drawInternal() override
size_t _consoleCallbackIndex
Definition: OutputWindow.h:55
#define IM_ARRAYSIZE(_ARR)
constexpr Optick::Category::Type GUI
Definition: Profiler.h:64
Str StringFormat(const char *fmt, Args &&...args)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
int32_t I32
eastl::vector< Type > vector
Definition: Vector.h:42
Project & parent
Definition: DefaultScene.h:41
uint16_t U16
constexpr U8 to_U8(const T value)
constexpr U16 g_maxLogEntries
static std::atomic_size_t g_writeIndex
static U16 g_logEntries
Project const SceneEntry & entry
Definition: DefaultScene.h:41
static vector< Console::OutputEntry > g_log
void SetScrollHereY(float center_y_ratio)
Definition: Console.h:119
EntryType _type
Definition: Console.h:121
string _text
Definition: Console.h:120
static bool UnbindConsoleOutput(size_t &index)
Definition: Console.cpp:206
static size_t BindConsoleOutput(const ConsolePrintCallback &guiConsoleCallback)
Definition: Console.cpp:194