[Scummvm-git-logs] scummvm master -> ecf0aee51ee15f4273ac9de093d5a0d2e620fdf2

scemino noreply at scummvm.org
Fri May 24 13:51:30 UTC 2024


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
ecf0aee51e DIRECTOR: Add ImGui logger


Commit: ecf0aee51ee15f4273ac9de093d5a0d2e620fdf2
    https://github.com/scummvm/scummvm/commit/ecf0aee51ee15f4273ac9de093d5a0d2e620fdf2
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-24T15:50:30+02:00

Commit Message:
DIRECTOR: Add ImGui logger

Changed paths:
    engines/director/debugtools.cpp


diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index d3d038d6893..0a446ab7428 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -24,6 +24,8 @@
 #include "backends/imgui/imgui.h"
 #include "backends/imgui/imgui_fonts.h"
 #include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/system.h"
 #include "graphics/surface.h"
 #include "graphics/opengl/shader.h"
 #include "image/png.h"
@@ -101,21 +103,251 @@ typedef struct ImGuiWindows {
 	bool score = false;
 	bool bpList = false;
 	bool settings = false;
+	bool logger = false;
 } ImGuiWindows;
 
-static void toggleButton(const char *label, bool *p_value, bool inverse = false) {
+static bool toggleButton(const char *label, bool *p_value, bool inverse = false) {
 	int pop = 0;
 	if (*p_value != inverse) {
 		ImVec4 hovered = ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered];
 		ImGui::PushStyleColor(ImGuiCol_Button, hovered);
 		pop = 1;
 	}
-	if (ImGui::Button(label)) {
+	bool result = ImGui::Button(label);
+	if (result) {
 		*p_value = !*p_value;
 	}
 	ImGui::PopStyleColor(pop);
+	return result;
 }
 
+struct ImGuiLogger {
+	char _inputBuf[256];
+	ImVector<char *> _items;
+	ImVector<char *> _history;
+	int _historyPos; // -1: new line, 0.._history.Size-1 browsing history.
+	ImGuiTextFilter _filter;
+	bool _autoScroll;
+	bool _scrollToBottom;
+	bool _showError = true;
+	bool _showWarn = true;
+	bool _showInfo = true;
+	bool _showdebug = true;
+
+	ImGuiLogger() {
+		clear();
+		memset(_inputBuf, 0, sizeof(_inputBuf));
+		_historyPos = -1;
+		_autoScroll = true;
+		_scrollToBottom = false;
+	}
+
+	~ImGuiLogger() {
+		clear();
+		for (int i = 0; i < _history.Size; i++)
+			free(_history[i]);
+	}
+
+	void clear() {
+		for (int i = 0; i < _items.Size; i++)
+			free(_items[i]);
+		_items.clear();
+	}
+
+	void addLog(const char *fmt, ...) IM_FMTARGS(2) {
+		// FIXME-OPT
+		char buf[1024];
+		va_list args;
+		va_start(args, fmt);
+		vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
+		buf[IM_ARRAYSIZE(buf) - 1] = 0;
+		va_end(args);
+		_items.push_back(Strdup(buf));
+	}
+
+	void draw(const char *title, bool *p_open) {
+		if (!*p_open)
+			return;
+
+		ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
+		if (!ImGui::Begin(title, p_open)) {
+			ImGui::End();
+			return;
+		}
+
+		// As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
+		// Here we create a context menu only available from the title bar.
+		if (ImGui::BeginPopupContextItem()) {
+			if (ImGui::MenuItem("Close ImGuiLogger"))
+				*p_open = false;
+			ImGui::EndPopup();
+		}
+
+		// Clear
+		if (ImGui::Button("\ue0b8")) {
+			clear();
+		}
+		ImGui::SetItemTooltip("Clear");
+		ImGui::SameLine();
+
+		// Copy
+		bool copy_to_clipboard = ImGui::Button("\ue14d");
+		ImGui::SetItemTooltip("Copy to clipboard");
+		ImGui::SameLine();
+
+		// debug channels
+		int numChannels = 0;
+		auto channels = DebugMan.getDebugChannels();
+		for (auto &channel : channels) {
+			if (channel.name == "imgui")
+				continue;
+			bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
+			if (enabled)
+				numChannels++;
+		}
+
+		Common::String selChannels(Common::String::format("(%d channel%s)", numChannels, numChannels > 1 ? "s" : ""));
+		ImGui::PushItemWidth(120);
+		if (ImGui::BeginCombo("##Channels", selChannels.c_str())) {
+			for (auto &channel : channels) {
+				if (channel.name == "imgui")
+					continue;
+				bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
+				if (ImGui::Checkbox(channel.name.c_str(), &enabled)) {
+					if (enabled) {
+						DebugMan.enableDebugChannel(channel.channel);
+					} else {
+						DebugMan.disableDebugChannel(channel.channel);
+					}
+				}
+				ImGui::SetItemTooltip("%s", channel.description.c_str());
+			}
+			ImGui::EndCombo();
+		}
+		ImGui::SameLine();
+
+		// Options menu
+		if (ImGui::BeginPopup("Options")) {
+			if (ImGui::InputInt("Debug Level", &gDebugLevel)) {
+				if (gDebugLevel < 0)
+					gDebugLevel = 0;
+			}
+			ImGui::Separator();
+			ImGui::Checkbox("Auto-scroll", &_autoScroll);
+			ImGui::EndPopup();
+		}
+
+		// Options, Filter
+		if (ImGui::Button("\ue8b8"))
+			ImGui::OpenPopup("Options");
+		ImGui::SetItemTooltip("Options");
+		ImGui::SameLine();
+
+		ImGui::Spacing();
+		ImGui::SameLine();
+
+		// Error
+		ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 0.f, 0.f, 1.f));
+		toggleButton("\ue160", &_showError);
+		ImGui::PopStyleColor();
+		ImGui::SameLine();
+
+		// Warning
+		ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 0.f, 1.f));
+		toggleButton("\ue002", &_showWarn);
+		ImGui::PopStyleColor();
+		ImGui::SameLine();
+
+		// Info
+		ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f));
+		toggleButton("\ue88e", &_showInfo);
+		ImGui::PopStyleColor();
+		ImGui::SameLine();
+
+		// Debug
+		ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.f));
+		toggleButton("\ue868", &_showdebug);
+		ImGui::PopStyleColor();
+		ImGui::SameLine();
+
+		_filter.Draw("Filter (\"incl,-excl\") (\"warn\")", 180);
+		ImGui::Separator();
+
+		ImGui::BeginChild("ScrollingRegion", ImVec2(), false, ImGuiWindowFlags_HorizontalScrollbar);
+		if (ImGui::BeginPopupContextWindow()) {
+			if (ImGui::Selectable("\ue0b8 Clear"))
+				clear();
+			if (ImGui::Selectable("\ue14d Copy"))
+				copy_to_clipboard = true;
+			ImGui::EndPopup();
+		}
+
+		ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
+		if (copy_to_clipboard)
+			ImGui::LogToClipboard();
+		for (int i = 0; i < _items.Size; i++) {
+			const char *item = _items[i];
+			bool isError = strstr(item, "[error]");
+			if (!_showError && isError)
+				continue;
+
+			bool isWarn = strstr(item, "[warn]");
+			if (!_showWarn && isWarn)
+				continue;
+
+			bool isDebug = strstr(item, "[debug]");
+			if (!_showdebug && isDebug)
+				continue;
+
+			if (!_showInfo && !isError && !isWarn && !isDebug)
+				continue;
+
+			if (!_filter.PassFilter(item))
+				continue;
+
+			// Normally you would store more information in your item (e.g. make _items[] an array of structure, store color/type etc.)
+			bool pop_color = false;
+			if (isError) {
+				item += 7;
+				ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f));
+				pop_color = true;
+			} else if (isWarn) {
+				item += 6;
+				ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.4f, 1.0f));
+				pop_color = true;
+			} else if (isDebug) {
+				item += 7;
+				ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
+				pop_color = true;
+			} else if (strncmp(item, "> ", 2) == 0) {
+				ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.6f, 1.0f));
+				pop_color = true;
+			}
+			ImGui::TextUnformatted(item);
+			if (pop_color)
+				ImGui::PopStyleColor();
+		}
+		if (copy_to_clipboard)
+			ImGui::LogFinish();
+
+		if (_scrollToBottom || (_autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
+			ImGui::SetScrollHereY(1.0f);
+		_scrollToBottom = false;
+
+		ImGui::PopStyleVar();
+		ImGui::EndChild();
+		ImGui::End();
+	}
+
+private:
+	static char *Strdup(const char *str) {
+		size_t len = strlen(str) + 1;
+		void *buf = malloc(len);
+		IM_ASSERT(buf);
+		return (char *)memcpy(buf, (const void *)str, len);
+	}
+};
+
 typedef struct ImGuiState {
 	struct {
 		Common::HashMap<Graphics::Surface *, ImGuiImage> _textures;
@@ -168,6 +400,8 @@ typedef struct ImGuiState {
 	int _scoreMode = 0;
 
 	ImFont *_tinyFont = nullptr;
+
+	ImGuiLogger _logger;
 } ImGuiState;
 
 ImGuiState *_state = nullptr;
@@ -1527,7 +1761,7 @@ static void showControlPanel() {
 
 			dl->AddLine(ImVec2(p.x + 8.5f, p.y + 1), ImVec2(p.x + 8.5f, p.y + 10), color_red, 2);
 			dl->AddLine(ImVec2(p.x + 5.5f, p.y + 6), ImVec2(p.x + 8.5f, p.y + 9), color_red, 2);
-			dl->AddLine(ImVec2(p.x + 12, p.y + 6),   ImVec2(p.x + 8.5f, p.y + 9), color_red, 2);
+			dl->AddLine(ImVec2(p.x + 12, p.y + 6), ImVec2(p.x + 8.5f, p.y + 9), color_red, 2);
 			dl->AddCircleFilled(ImVec2(p.x + 9, p.y + 15), 2.0f, color);
 
 			ImGui::SetItemTooltip("Step Into");
@@ -1546,7 +1780,7 @@ static void showControlPanel() {
 
 			dl->AddLine(ImVec2(p.x + 8.5f, p.y + 1), ImVec2(p.x + 8.5f, p.y + 10), color_red, 2);
 			dl->AddLine(ImVec2(p.x + 5.5f, p.y + 5), ImVec2(p.x + 8.5f, p.y + 1), color_red, 2);
-			dl->AddLine(ImVec2(p.x + 12, p.y + 5),   ImVec2(p.x + 8.5f, p.y + 1), color_red, 2);
+			dl->AddLine(ImVec2(p.x + 12, p.y + 5), ImVec2(p.x + 8.5f, p.y + 1), color_red, 2);
 			dl->AddCircleFilled(ImVec2(p.x + 9, p.y + 15), 2.0f, color);
 
 			ImGui::SetItemTooltip("Step Out");
@@ -1609,21 +1843,21 @@ static const char *toString(ScriptType scriptType) {
 
 static const char *toIcon(CastType castType) {
 	static const char *castTypes[] = {
-		"",       // Empty
-		"\uf79e", // Bitmap			// backround_dot_large
-		"\ue8da", // FilmLoop		// theaters
-		"\uf6f1", // Text			// match_case
-		"\ue40a", // Palette		// palette
-		"\uefa2", // Picture		// imagesmode
-		"\ue050", // Sound			// volume_up
-		"\uf4ab", // Button			// slab_serif
-		"\ue602", // Shape			// shapes
-		"\ue02c", // Movie			// movie
-		"\uf49a", // DigitalVideo	// animated_images
-		"\uf0c8", // Script			// forms_apps_script
-		"\uf4f1", // RTE			// brand_family
-		"?",      // ???
-		"\uf50c"};// Transition		// transition_fade
+		"",        // Empty
+		"\uf79e",  // Bitmap			// backround_dot_large
+		"\ue8da",  // FilmLoop		// theaters
+		"\uf6f1",  // Text			// match_case
+		"\ue40a",  // Palette		// palette
+		"\uefa2",  // Picture		// imagesmode
+		"\ue050",  // Sound			// volume_up
+		"\uf4ab",  // Button			// slab_serif
+		"\ue602",  // Shape			// shapes
+		"\ue02c",  // Movie			// movie
+		"\uf49a",  // DigitalVideo	// animated_images
+		"\uf0c8",  // Script			// forms_apps_script
+		"\uf4f1",  // RTE			// brand_family
+		"?",       // ???
+		"\uf50c"}; // Transition		// transition_fade
 	if (castType < 0 || castType > kCastTransition)
 		return "";
 	return castTypes[(int)castType];
@@ -1727,7 +1961,7 @@ static void showCast() {
 		ImGui::SetItemTooltip("Grid");
 		ImGui::SameLine();
 
-		if (ImGui::Button("\uef4f")) {	// filter_alt
+		if (ImGui::Button("\uef4f")) { // filter_alt
 			ImGui::OpenPopup("filters_popup");
 		}
 		ImGui::SameLine();
@@ -2438,13 +2672,13 @@ static void showFuncList() {
 
 // Make the UI compact because there are so many fields
 static void PushStyleCompact() {
-    ImGuiStyle& style = ImGui::GetStyle();
-    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
-    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
+	ImGuiStyle &style = ImGui::GetStyle();
+	ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
+	ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
 }
 
 static void PopStyleCompact() {
-    ImGui::PopStyleVar(2);
+	ImGui::PopStyleVar(2);
 }
 
 static void showSettings() {
@@ -2484,7 +2718,8 @@ static void showBreakpointList() {
 				ImGui::TableSetupColumn(NULL, i == 2 ? ImGuiTableColumnFlags_WidthStretch : ImGuiTableColumnFlags_NoHeaderWidth);
 
 			for (uint i = 0; i < bps.size(); i++) {
-				if(bps[i].type != kBreakpointFunction) continue;
+				if (bps[i].type != kBreakpointFunction)
+					continue;
 
 				ImGui::TableNextRow();
 				ImGui::TableNextColumn();
@@ -2540,7 +2775,7 @@ static void showBreakpointList() {
 				const ImU32 cross_col = ImGui::GetColorU32(ImGuiCol_Text);
 				const ImVec2 center = pos + ImVec2(0.5f + fontSize * 0.5f, 1.0f + fontSize * 0.5f);
 				if (hovered)
-        			dl->AddCircleFilled(center, MAX(2.0f, fontSize * 0.5f + 1.0f), ImGui::GetColorU32(ImGuiCol_ButtonActive));
+					dl->AddCircleFilled(center, MAX(2.0f, fontSize * 0.5f + 1.0f), ImGui::GetColorU32(ImGuiCol_ButtonActive));
 				dl->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
 				dl->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
 
@@ -2549,7 +2784,7 @@ static void showBreakpointList() {
 				ImGui::Text("%d", bps[i].funcOffset);
 				ImGui::PopID();
 
-				if(del) {
+				if (del) {
 					g_lingo->delBreakpoint(bps[i].id);
 					break;
 				}
@@ -2778,10 +3013,13 @@ static void showScore() {
 			ImGui::BeginChild("Ink", ImVec2(150.0f, 20.0f));
 
 			if (castMember || shape) {
-				ImGui::Text("%s", inkType2str(sprite->_ink)); ImGui::SameLine(70);
+				ImGui::Text("%s", inkType2str(sprite->_ink));
+				ImGui::SameLine(70);
 				ImGui::SetItemTooltip("Ink");
-				ImGui::Text("|"); ImGui::SameLine();
-				ImGui::Text("%d", sprite->_blendAmount); ImGui::SameLine();
+				ImGui::Text("|");
+				ImGui::SameLine();
+				ImGui::Text("%d", sprite->_blendAmount);
+				ImGui::SameLine();
 				ImGui::SetItemTooltip("Blend");
 			}
 			ImGui::PopStyleColor();
@@ -2828,12 +3066,15 @@ static void showScore() {
 			if (castMember || shape) {
 				ImVec4 fg = convertColor(sprite->_foreColor);
 
-				ImGui::ColorButton("foreColor", fg); ImGui::SameLine();
+				ImGui::ColorButton("foreColor", fg);
+				ImGui::SameLine();
 				ImGui::Text("#%02x%02x%02x", (int)(fg.x * 255), (int)(fg.y * 255), (int)(fg.z * 255));
 				ImGui::SetItemTooltip("Foreground Color");
 				ImVec4 bg = convertColor(sprite->_backColor);
-				ImGui::ColorButton("backColor", bg); ImGui::SameLine();
-				ImGui::Text("#%02x%02x%02x", (int)(bg.x * 255), (int)(bg.y * 255), (int)(bg.z * 255)); ImGui::SameLine();
+				ImGui::ColorButton("backColor", bg);
+				ImGui::SameLine();
+				ImGui::Text("#%02x%02x%02x", (int)(bg.x * 255), (int)(bg.y * 255), (int)(bg.z * 255));
+				ImGui::SameLine();
 				ImGui::SetItemTooltip("Background Color");
 			}
 
@@ -2900,8 +3141,8 @@ static void showScore() {
 		ImGuiTableFlags addonFlags = _state->_scoreMode == kModeExtended ? 0 : ImGuiTableFlags_RowBg;
 
 		if (ImGui::BeginTable("Score", tableColumns + 1,
-					ImGuiTableFlags_Borders | ImGuiTableFlags_HighlightHoveredColumn |
-					ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | addonFlags)) {
+							  ImGuiTableFlags_Borders | ImGuiTableFlags_HighlightHoveredColumn |
+								  ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | addonFlags)) {
 			ImGuiTableFlags flags = ImGuiTableColumnFlags_WidthFixed;
 
 			ImGui::TableSetupScrollFreeze(1, 2);
@@ -2984,6 +3225,23 @@ static void showScore() {
 	ImGui::End();
 }
 
+void onLog(LogMessageType::Type type, int level, uint32 debugChannels, const char *message) {
+	switch (type) {
+	case LogMessageType::kError:
+		_state->_logger.addLog("[error]%s", message);
+		break;
+	case LogMessageType::kWarning:
+		_state->_logger.addLog("[warn]%s", message);
+		break;
+	case LogMessageType::kInfo:
+		_state->_logger.addLog("%s", message);
+		break;
+	case LogMessageType::kDebug:
+		_state->_logger.addLog("[debug]%s", message);
+		break;
+	}
+}
+
 void onImGuiInit() {
 	ImGuiIO &io = ImGui::GetIO();
 	io.Fonts->AddFontDefault();
@@ -3001,6 +3259,8 @@ void onImGuiInit() {
 	_state = new ImGuiState();
 
 	_state->_tinyFont = ImGui::addTTFFontFromArchive("FreeSans.ttf", 10.0f, nullptr, nullptr);
+
+	Common::setLogWatcher(onLog);
 }
 
 void onImGuiRender() {
@@ -3045,6 +3305,7 @@ void onImGuiRender() {
 			ImGui::MenuItem("Breakpoints", NULL, &_state->_w.bpList);
 			ImGui::MenuItem("Vars", NULL, &_state->_w.vars);
 			ImGui::MenuItem("Settings", NULL, &_state->_w.settings);
+			ImGui::MenuItem("Logger", NULL, &_state->_w.logger);
 
 			ImGui::SeparatorText("Misc");
 			if (ImGui::MenuItem("Save state")) {
@@ -3069,9 +3330,11 @@ void onImGuiRender() {
 	showScore();
 	showBreakpointList();
 	showSettings();
+	_state->_logger.draw("Logger", &_state->_w.logger);
 }
 
 void onImGuiCleanup() {
+	Common::setLogWatcher(nullptr);
 	if (_state)
 		delete _state->_tinyFont;
 




More information about the Scummvm-git-logs mailing list