[Scummvm-git-logs] scummvm master -> 28e6fbde66b998294a1d461fdeaea8d360f7e0da

sev- noreply at scummvm.org
Thu Mar 5 18:18:43 UTC 2026


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

Summary:
3e20e03fd8 DIRECTOR: DT: Add new theme (color)
a276163f66 BACKENDS: IMGUI: Make ImGuiLogger _colors public
28e6fbde66 DIRECTOR: DT: Refactor theme system and add global Dark/Light toggle


Commit: 3e20e03fd8b1ed3bfd8b85d048213621fbc92dd6
    https://github.com/scummvm/scummvm/commit/3e20e03fd8b1ed3bfd8b85d048213621fbc92dd6
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-03-05T19:18:38+01:00

Commit Message:
DIRECTOR: DT: Add new theme (color)

Changed paths:
    engines/director/debugger/dt-internal.h
    engines/director/debugger/dt-score.cpp


diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index db1493031cf..fcaac3d366c 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -112,6 +112,13 @@ typedef struct WindowFlag {
 
 typedef struct ImGuiState {
 
+	struct WatchLogEntry {
+		Common::String varName;
+		Common::String value;
+		Common::String scriptRef;
+		bool isWrite;
+	};
+
 	struct ScoreConfig {
 		float _sidebarWidth = 60.0f;
 		float _cellWidth = 14.0f;
@@ -125,9 +132,27 @@ typedef struct ImGuiState {
 		float _sidebar1Height = _cellHeight * 6;
 		float _labelBarHeight = _cellHeight;
 		float _cellHeightExtended = 5 * _cellHeight;
-		ImU32 _tableLightColor = IM_COL32(51,  51,  51,  255);
-		ImU32 _tableDarkColor = IM_COL32(38, 38, 38, 255);
-		ImU32 _borderColor = IM_COL32(102, 102, 102, 100);
+
+		// dark theme colors
+		ImU32 _darkTableLight = IM_COL32(51, 51, 51, 255);
+		ImU32 _darkTableDark = IM_COL32(38, 38, 38, 255);
+		ImU32 _darkBorder = IM_COL32(102, 102, 102, 100);
+
+		// light theme colors
+		ImU32 _lightTableLight = IM_COL32(240, 240, 240, 255);
+		ImU32 _lightTableDark = IM_COL32(210, 210, 210, 255);
+		ImU32 _lightBorder = IM_COL32(150, 150, 150, 150);
+
+		// text colors
+		ImU32 _sidebarTextColor = IM_COL32(200, 200, 200, 255);
+		static constexpr ImU32 _gridTextColor = IM_COL32(30, 30, 30, 255);
+
+		// active colors
+		ImU32 _tableLightColor = _darkTableLight;
+		ImU32 _tableDarkColor = _darkTableDark;
+		ImU32 _borderColor = _darkBorder;
+
+		bool _isLightTheme = false;
 	} _scoreCfg;
 
 	struct ScoreState {
@@ -236,13 +261,14 @@ typedef struct ImGuiState {
 	Common::Array<Common::Array<Common::Pair<uint, uint>>> _continuationData;
 	Common::String _loadedContinuationData;
 
+	Common::Array<WatchLogEntry> _watchLog;
+
 	Common::String _scoreWindow;
 	Common::String _channelsWindow;
 	Common::String _castWindow;
 	int _scoreMode = 0;
 	int _scoreFrameOffset = 1;
 	int _scorePageSlider = 0;
-
 	int _selectedChannel = -1;
 
 	ImFont *_tinyFont = nullptr;
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index 0f8e951bb5c..b2f4506d81a 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -51,6 +51,7 @@ const char *modes2[] = {
 };
 
 struct ScoreLayout {
+	ImVec2 themeSelectorPos;
 	ImVec2 labelBarPos;
 	ImVec2 sidebar1Pos;
 	ImVec2 mainChannelGridPos;
@@ -62,8 +63,21 @@ struct ScoreLayout {
 	ImVec2 sliderYPos;
 };
 
-static ScoreLayout computeLayout(ImVec2 origin, const ImGuiState::ScoreConfig &cfg) {
+static ScoreLayout computeLayout(ImVec2 origin, ImGuiState::ScoreConfig &cfg) {
 	ScoreLayout l;
+	ImVec2 size = ImGui::GetWindowSize();
+	float paddingX = cfg._sidebarWidth + 50.0f;
+	float paddingY = cfg._rulerHeight + cfg._cellHeight * 7 + 150.0f;
+	cfg._visibleFrames = MAX<int>((size.x - paddingX) / cfg._cellWidth, 10);
+	cfg._visibleChannels = MAX<int>((size.y - paddingY) / cfg._cellHeight, 10);
+	cfg._tableWidth = cfg._cellWidth * cfg._visibleFrames;
+	cfg._tableHeight = cfg._cellHeight * cfg._visibleChannels;
+	cfg._rulerWidth = cfg._tableWidth;
+	cfg._sidebar1Height = cfg._cellHeight * 6;
+	cfg._labelBarHeight = cfg._cellHeight;
+	cfg._cellHeightExtended = 5 * cfg._cellHeight;
+
+	l.themeSelectorPos = ImVec2(origin.x, origin.y);
 	l.labelBarPos = ImVec2(origin.x + cfg._sidebarWidth, origin.y);
 	l.sidebar1Pos = ImVec2(origin.x, origin.y + cfg._labelBarHeight);
 	l.mainChannelGridPos = ImVec2(origin.x + cfg._sidebarWidth, origin.y + cfg._labelBarHeight);
@@ -202,7 +216,7 @@ static void drawSidebar1(ImDrawList *dl, ImVec2 startPos, Score *score) {
 		float textlen = ImGui::CalcTextSize(icon).x;
 		float textX = startPos.x + toggleColWidth + (labelColWidth - textlen) / 2.0f;
 		float textY = y + (cfg._cellHeight - ImGui::GetTextLineHeight()) / 2.0f;
-		dl->AddText(iconFont, 0.0f, ImVec2(textX, textY), U32(_state->_colors._type_color), icon);
+		dl->AddText(iconFont, 0.0f, ImVec2(textX, textY), cfg._sidebarTextColor, icon);
 
 		// invisible button covering the row for interaction
 		ImGui::SetCursorScreenPos(rowMin);
@@ -261,15 +275,15 @@ static void drawSidebar2(ImDrawList *dl, ImVec2 startPos, Score *score) {
 
 		if (_state->_scoreMode != kModeExtended) {
 			float textY = y + (cellH - ImGui::GetTextLineHeight()) / 2.0f;
-			dl->AddText(ImVec2(textX, textY), U32(_state->_colors._keyword_color), buf);
+			dl->AddText(ImVec2(textX, textY), cfg._sidebarTextColor, buf);
 		} else { // draw channel number and labels
-			dl->AddText(ImVec2(textX, y + 2.0f), U32(_state->_colors._keyword_color), buf);
+			dl->AddText(ImVec2(textX, y + 2.0f), cfg._sidebarTextColor, buf);
 			const char *subLabels[] = { "Member", "Behavior", "Ink", "Blend", "Location" };
 			float lineH = ImGui::GetTextLineHeight();
 			for (int s = 0; s < 5; s++) {
 				float subX = textX - 17.0f;
 				float subY = y + lineH + 2.0f + s * lineH; // offset below channel number
-				dl->AddText(ImVec2(subX, subY), U32(_state->_colors._type_color), subLabels[s]);
+				dl->AddText(ImVec2(subX, subY), cfg._sidebarTextColor, subLabels[s]);
 			}
 		}
 	}
@@ -609,7 +623,7 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					snprintf(buf, sizeof(buf), "%s", getDisplayName(cm).c_str());
 				else if (sprite.isQDShape())
 					snprintf(buf, sizeof(buf), "Q");
-				dl->AddText(ImVec2(textX, baseY), U32(_state->_colors._line_color), buf);
+				dl->AddText(ImVec2(textX, baseY), cfg._gridTextColor, buf);
 
 				// Behavior
 				buf[0] = '\0';
@@ -617,18 +631,18 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					CastMember *sc = cast->getCastMember(sprite._scriptId.member, true);
 					if (sc) snprintf(buf, sizeof(buf), "%s", getDisplayName(sc).c_str());
 				}
-				dl->AddText(ImVec2(textX, baseY + lineH), U32(_state->_colors._line_color), buf);
+				dl->AddText(ImVec2(textX, baseY + lineH), cfg._gridTextColor, buf);
 
 				// Ink
-				dl->AddText(ImVec2(textX, baseY + lineH * 2), U32(_state->_colors._line_color), inkType2str(sprite._ink));
+				dl->AddText(ImVec2(textX, baseY + lineH * 2), cfg._gridTextColor, inkType2str(sprite._ink));
 
 				// Blend
 				snprintf(buf, sizeof(buf), "%d", sprite._blendAmount);
-				dl->AddText(ImVec2(textX, baseY + lineH * 3), U32(_state->_colors._line_color), buf);
+				dl->AddText(ImVec2(textX, baseY + lineH * 3), cfg._gridTextColor, buf);
 
 				// Location
 				snprintf(buf, sizeof(buf), "%d,%d", sprite._startPoint.x, sprite._startPoint.y);
-				dl->AddText(ImVec2(textX, baseY + lineH *4), U32(_state->_colors._line_color), buf);
+				dl->AddText(ImVec2(textX, baseY + lineH *4), cfg._gridTextColor, buf);
 			}
 
 			if (startVisible && _state->_scoreMode != kModeExtended) {
@@ -661,7 +675,7 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					break;
 				}
 				if (label[0])
-					dl->AddText(ImVec2(x1 + 4.0f, y + (cellH - ImGui::GetTextLineHeight()) / 2.0f), U32(_state->_colors._line_color), label);
+					dl->AddText(ImVec2(x1 + 4.0f, y + (cellH - ImGui::GetTextLineHeight()) / 2.0f), cfg._gridTextColor, label);
 
 			}
 
@@ -922,14 +936,14 @@ static void drawLabelBar(ImDrawList *dl, ImVec2 pos, Score *score) {
 			float textY = y + (cfg._labelBarHeight - ImGui::GetTextLineHeight()) / 2.0f;
 
 			dl->AddText(ImVec2(x - ImGui::CalcTextSize(ICON_MS_BEENHERE).x / 2.0f, textY),
-						U32(_state->_colors._type_color), ICON_MS_BEENHERE);
+						cfg._sidebarTextColor, ICON_MS_BEENHERE);
 
 			float iconW = ImGui::CalcTextSize(ICON_MS_BEENHERE).x;
 			float textX = x + iconW / 2.0f + 2.0f;
 			float textWidth = ImGui::CalcTextSize(labelName->c_str()).x;
 
 			if (textX + textWidth < finalPos.x) // prevent text being drawn outside the table bounds
-				dl->AddText(ImVec2(textX, textY), U32(_state->_colors._type_color), labelName->c_str());
+				dl->AddText(ImVec2(textX, textY), cfg._sidebarTextColor, labelName->c_str());
 
 			float px = pos.x + f * cfg._cellWidth;
 			ImGui::SetCursorScreenPos(ImVec2(px, y));
@@ -942,6 +956,23 @@ static void drawLabelBar(ImDrawList *dl, ImVec2 pos, Score *score) {
 	}
 }
 
+static void drawThemeButton(ImVec2 pos) {
+	ImGui::SetCursorScreenPos(pos);
+	if (ImGui::Button(ICON_MS_LIGHT_MODE)) {
+		auto &cfg = _state->_scoreCfg;
+		cfg._isLightTheme = !cfg._isLightTheme;
+		cfg._sidebarTextColor = cfg._isLightTheme ? cfg._gridTextColor : cfg._sidebarTextColor;
+		if (cfg._isLightTheme) {
+			cfg._tableLightColor = cfg._lightTableLight;
+			cfg._tableDarkColor = cfg._lightTableDark;
+			cfg._borderColor = cfg._lightBorder;
+		} else {
+			cfg._tableLightColor = cfg._darkTableLight;
+			cfg._tableDarkColor = cfg._darkTableDark;
+			cfg._borderColor = cfg._darkBorder;
+		}
+	}
+}
 
 void showScore() {
 	if (!_state->_w.score)
@@ -975,17 +1006,15 @@ void showScore() {
 		if (!numFrames || _state->_selectedScoreCast.channel >= (int)score->_scoreCache[0]->_sprites.size())
 			_state->_selectedScoreCast.channel = 0;
 
-
-
 		drawSpriteInspector(score, cast, numFrames);
-
 		int numChannels = MIN<int>(score->_scoreCache[0]->_sprites.size(), score->_maxChannelsUsed + 10);
 		handleScrolling(score, numChannels);
 
 		ImDrawList *dl	= ImGui::GetWindowDrawList();
-		ImVec2	 origin = ImGui::GetCursorScreenPos();
+		ImVec2 origin = ImGui::GetCursorScreenPos();
 		ScoreLayout layout = computeLayout(origin, _state->_scoreCfg);
 
+		drawThemeButton(layout.themeSelectorPos);
 		drawLabelBar(dl, layout.labelBarPos, score);
 		drawSidebar1(dl, layout.sidebar1Pos, score);
 		drawMainChannelGrid(dl, layout.mainChannelGridPos, score);


Commit: a276163f662ff487cef8d0dd96e80652b05cd792
    https://github.com/scummvm/scummvm/commit/a276163f662ff487cef8d0dd96e80652b05cd792
Author: Krish Ganatra (ganatrakrish2882005 at gmail.com)
Date: 2026-03-05T19:18:38+01:00

Commit Message:
BACKENDS: IMGUI: Make ImGuiLogger _colors public

Changed paths:
    backends/imgui/components/imgui_logger.h


diff --git a/backends/imgui/components/imgui_logger.h b/backends/imgui/components/imgui_logger.h
index 4a93b29a298..df7259eb70d 100644
--- a/backends/imgui/components/imgui_logger.h
+++ b/backends/imgui/components/imgui_logger.h
@@ -43,6 +43,7 @@ class ImGuiLogger {
 	bool _showInfo = true;
 	bool _showdebug = true;
 
+public: // Added for ScummVM
 	struct {
 		ImVec4 _logger_error_b = ImVec4(1.f, 0.f, 0.f, 1.f);
 		ImVec4 _logger_warning_b = ImVec4(1.f, 1.f, 0.f, 1.f);


Commit: 28e6fbde66b998294a1d461fdeaea8d360f7e0da
    https://github.com/scummvm/scummvm/commit/28e6fbde66b998294a1d461fdeaea8d360f7e0da
Author: Krish Ganatra (ganatrakrish2882005 at gmail.com)
Date: 2026-03-05T19:18:38+01:00

Commit Message:
DIRECTOR: DT: Refactor theme system and add global Dark/Light toggle

Changed paths:
    engines/director/debugger/debugtools.cpp
    engines/director/debugger/dt-cast.cpp
    engines/director/debugger/dt-controlpanel.cpp
    engines/director/debugger/dt-internal.h
    engines/director/debugger/dt-lists.cpp
    engines/director/debugger/dt-score.cpp
    engines/director/debugger/dt-script-d2.cpp
    engines/director/debugger/dt-script-d4.cpp
    engines/director/debugger/dt-scripts.cpp


diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 299d67d6e64..dcff9c3be01 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -342,13 +342,13 @@ ImGuiImage getTextID(CastMember *castMember) {
 }
 
 void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
-	ImU32 var_color = ImGui::GetColorU32(_state->_colors._var_ref);
+	ImU32 var_color = ImGui::GetColorU32(_state->theme->var_ref);
 	ImU32 color;
 
-	color = ImGui::GetColorU32(_state->_colors._bp_color_disabled);
+	color = ImGui::GetColorU32(_state->theme->bp_color_disabled);
 
 	if (_state->_variables.contains(name))
-		color = ImGui::GetColorU32(_state->_colors._bp_color_enabled);
+		color = ImGui::GetColorU32(_state->theme->bp_color_enabled);
 
 	ImDrawList *dl = ImGui::GetWindowDrawList();
 	ImVec2 pos = ImGui::GetCursorScreenPos();
@@ -357,23 +357,23 @@ void displayVariable(const Common::String &name, bool changed, bool outOfScope)
 
 	ImGui::InvisibleButton("Line", ImVec2(textSize.x + eyeSize.x, textSize.y));
 	if (ImGui::IsItemClicked(0)) {
-		if (color == ImGui::GetColorU32(_state->_colors._bp_color_enabled)) {
+		if (color == ImGui::GetColorU32(_state->theme->bp_color_enabled)) {
 			_state->_variables.erase(name);
-			color = ImGui::GetColorU32(_state->_colors._bp_color_disabled);
+			color = ImGui::GetColorU32(_state->theme->bp_color_disabled);
 		} else {
 			_state->_variables[name] = true;
-			color = ImGui::GetColorU32(_state->_colors._bp_color_enabled);
+			color = ImGui::GetColorU32(_state->theme->bp_color_enabled);
 		}
 	}
 
 	if (changed) {
-		var_color = ImGui::GetColorU32(_state->_colors._var_ref_changed);
+		var_color = ImGui::GetColorU32(_state->theme->var_ref_changed);
 	} else if (outOfScope) {
-		var_color = ImGui::GetColorU32(_state->_colors._var_ref_out_of_scope);
+		var_color = ImGui::GetColorU32(_state->theme->var_ref_out_of_scope);
 	}
 
-	if (color == ImGui::GetColorU32(_state->_colors._bp_color_disabled) && ImGui::IsItemHovered()) {
-		color = ImGui::GetColorU32(_state->_colors._bp_color_hover);
+	if (color == ImGui::GetColorU32(_state->theme->bp_color_disabled) && ImGui::IsItemHovered()) {
+		color = ImGui::GetColorU32(_state->theme->bp_color_hover);
 	}
 
 	dl->AddText(pos, color, ICON_MS_VISIBILITY " ");
@@ -412,7 +412,7 @@ void setScriptToDisplay(const ImGuiScript &script) {
 
 void displayScriptRef(CastMemberID &scriptId) {
 	if (scriptId.member) {
-		ImGui::TextColored(_state->_colors._script_ref, "%d", scriptId.member);
+		ImGui::TextColored(_state->theme->script_ref, "%d", scriptId.member);
 
 		ImGui::SetItemTooltip(scriptId.asString().c_str());
 
@@ -488,6 +488,154 @@ Window *windowListCombo(Common::String *target) {
 	return res;
 }
 
+static const DebuggerTheme themes[kThemeCount] = {
+	// [kThemeDark]
+	{
+		IM_COL32(0x33, 0x33, 0x33, 0xFF), // tableLightColor
+		IM_COL32(0x26, 0x26, 0x26, 0xFF), // tableDarkColor
+		IM_COL32(0x66, 0x66, 0x66, 0x64), // borderColor
+		IM_COL32(0xC8, 0xC8, 0xC8, 0xFF), // sidebarTextColor
+		IM_COL32(0x1E, 0x1E, 0x1E, 0xFF), // gridTextColor
+		IM_COL32(0xC8, 0x32, 0x00, 0xFF), // playhead_color
+		IM_COL32(0xFF, 0xFF, 0x00, 0x20), // current_statement_bg
+		IM_COL32(0x30, 0x30, 0xFF, 0xFF), // channel_toggle
+		IM_COL32(0x94, 0x00, 0xD3, 0xFF), // channelSelectedCol
+		IM_COL32(0xFF, 0xFF, 0x00, 0x3C), // channelHoveredCol
+		{                                 // contColors
+			IM_COL32(0xCE, 0xCE, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xFF, 0xCE, 0x80),
+			IM_COL32(0xCE, 0xFF, 0xCE, 0x80),
+			IM_COL32(0xCE, 0xFF, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xCE, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xCE, 0x9C, 0x80)
+		},
+
+		ImVec4(0.9f, 0.08f, 0.0f, 0.0f),   // bp_color_disabled
+		ImVec4(0.9f, 0.08f, 0.0f, 1.0f),   // bp_color_enabled
+		ImVec4(0.42f, 0.17f, 0.13f, 1.0f), // bp_color_hover
+
+		ImVec4(1.00f, 1.00f, 0.00f, 1.0f),  // current_statement
+		ImVec4(0.18f, 0.18f, 0.18f, 1.0f),  // line_color
+		ImVec4(1.00f, 0.77f, 0.36f, 1.0f),  // call_color
+		ImVec4(0.38f, 0.49f, 1.00f, 1.0f),  // builtin_color
+		ImVec4(0.29f, 0.80f, 0.37f, 1.0f),  // var_color
+		ImVec4(1.00f, 0.62f, 0.85f, 0.62f), // literal_color
+		ImVec4(1.00f, 0.65f, 0.62f, 0.58f), // comment_color
+		ImVec4(0.72f, 0.72f, 0.72f, 0.75f), // type_color
+		ImVec4(0.76f, 0.76f, 0.76f, 1.0f),  // keyword_color
+		ImVec4(1.00f, 0.29f, 0.94f, 1.0f),  // the_color
+
+		ImVec4(0.50f, 0.50f, 1.00f, 1.0f), // script_ref
+		ImVec4(0.90f, 0.90f, 0.00f, 1.0f), // var_ref
+		ImVec4(1.00f, 0.00f, 0.00f, 1.0f), // var_ref_changed
+		ImVec4(1.00f, 0.00f, 1.00f, 1.0f), // var_ref_out_of_scope
+
+		ImVec4(0.8f, 0.8f, 0.8f, 1.0f), // cp_color
+		ImVec4(1.0f, 0.6f, 0.6f, 1.0f), // cp_color_red
+		ImVec4(1.0f, 1.0f, 0.4f, 1.0f), // cp_active_color
+		ImVec4(0.2f, 0.2f, 1.0f, 1.0f), // cp_bgcolor
+		ImVec4(0.3f, 0.3f, 1.0f, 1.0f), // cp_playing_color
+		ImVec4(0.9f, 0.8f, 0.5f, 1.0f), // cp_path_color
+
+		ImVec4(1.0f, 0.0f, 0.0f, 1.0f), // logger_error_b
+		ImVec4(1.0f, 1.0f, 0.0f, 1.0f), // logger_warning_b
+		ImVec4(10.f, 1.0f, 1.0f, 1.0f), // logger_info_b
+		ImVec4(0.8f, 0.8f, 0.8f, 1.0f), // logger_debug_b
+		ImVec4(1.0f, 0.4f, 0.4f, 1.0f), // logger_error
+		ImVec4(1.0f, 1.0f, 0.4f, 1.0f), // logger_warning
+		ImVec4(1.0f, 0.8f, 0.6f, 1.0f), // logger_info
+		ImVec4(0.8f, 0.8f, 0.8f, 1.0f)  // logger_debug
+	},
+	// [kThemeLight]
+	{
+		IM_COL32(0xF0, 0xF0, 0xF0, 0xFF), // tableLightColor
+		IM_COL32(0xD2, 0xD2, 0xD2, 0xFF), // tableDarkColor
+		IM_COL32(0x96, 0x96, 0x96, 0x96), // borderColor
+		IM_COL32(0x1E, 0x1E, 0x1E, 0xFF), // sidebarTextColor
+		IM_COL32(0x1E, 0x1E, 0x1E, 0xFF), // gridTextColor
+		IM_COL32(0xC8, 0x32, 0x00, 0xFF), // playhead_color
+		IM_COL32(0xFF, 0xFF, 0x00, 0x60), // current_statement_bg
+		IM_COL32(0x00, 0x00, 0xB0, 0xFF), // channel_toggle
+		IM_COL32(0x94, 0x00, 0xD3, 0xFF), // channelSelectedCol
+		IM_COL32(0xD0, 0x90, 0x00, 0x50), // channelHoveredCol
+		{                                 // contColors
+			IM_COL32(0xCE, 0xCE, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xFF, 0xCE, 0x80),
+			IM_COL32(0xCE, 0xFF, 0xCE, 0x80),
+			IM_COL32(0xCE, 0xFF, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xCE, 0xFF, 0x80),
+			IM_COL32(0xFF, 0xCE, 0x9C, 0x80)
+		},
+
+		ImVec4(0.9f, 0.08f, 0.0f, 0.0f), // bp_color_disabled
+		ImVec4(0.9f, 0.08f, 0.0f, 1.0f), // bp_color_enabled
+		ImVec4(0.6f, 0.05f, 0.0f, 1.0f), // bp_color_hover
+
+		ImVec4(0.82f, 0.44f, 0.00f, 1.0f), // current_statement
+		ImVec4(0.18f, 0.18f, 0.18f, 1.0f), // line_color
+		ImVec4(0.00f, 0.00f, 0.00f, 1.0f), // call_color
+		ImVec4(0.00f, 0.53f, 0.00f, 1.0f), // builtin_color
+		ImVec4(0.00f, 0.00f, 0.00f, 1.0f), // var_color
+		ImVec4(0.33f, 0.33f, 0.33f, 1.0f), // literal_color
+		ImVec4(0.87f, 0.00f, 0.00f, 1.0f), // comment_color
+		ImVec4(0.33f, 0.33f, 0.33f, 1.0f), // type_color
+		ImVec4(0.00f, 0.00f, 0.93f, 1.0f), // keyword_color
+		ImVec4(0.00f, 0.00f, 0.93f, 1.0f), // the_color
+
+		ImVec4(0.00f, 0.20f, 0.80f, 1.0f), // script_ref
+		ImVec4(0.72f, 0.53f, 0.00f, 1.0f), // var_ref
+		ImVec4(0.80f, 0.00f, 0.00f, 1.0f), // var_ref_changed
+		ImVec4(0.60f, 0.00f, 0.60f, 1.0f), // var_ref_out_of_scope
+
+		ImVec4(0.1f, 0.1f, 0.1f, 1.0f),    // cp_color
+		ImVec4(0.8f, 0.0f, 0.0f, 1.0f),    // cp_color_red
+		ImVec4(0.8f, 0.4f, 0.0f, 1.0f),    // cp_active_color
+		ImVec4(0.7f, 0.8f, 1.0f, 0.5f),    // cp_bgcolor
+		ImVec4(0.0f, 0.0f, 0.8f, 1.0f),    // cp_playing_color
+		ImVec4(0.55f, 0.42f, 0.05f, 1.0f), // cp_path_color
+
+		ImVec4(0.8f, 0.0f, 0.0f, 1.0f),    // logger_error_b
+		ImVec4(0.8f, 0.4f, 0.0f, 1.0f),    // logger_warning_b
+		ImVec4(0.1f, 0.1f, 0.1f, 1.0f),    // logger_info_b
+		ImVec4(0.4f, 0.4f, 0.4f, 1.0f),    // logger_debug_b
+		ImVec4(0.7f, 0.0f, 0.0f, 1.0f),    // logger_error
+		ImVec4(0.7f, 0.4f, 0.0f, 1.0f),    // logger_warning
+		ImVec4(0.15f, 0.15f, 0.15f, 1.0f), // logger_info
+		ImVec4(0.4f, 0.4f, 0.4f, 1.0f)     // logger_debug
+	}
+};
+
+static const char *themeNames[kThemeCount] = {
+	"Dark",
+	"Light"
+};
+
+void setTheme(int themeIndex) {
+	if (!_state || themeIndex < 0 || themeIndex >= kThemeCount)
+		return;
+
+	_state->_activeThemeID = themeIndex;
+	_state->theme = &themes[themeIndex];
+
+	if (themeIndex == kThemeLight) {
+		ImGui::StyleColorsLight();
+	} else {
+		ImGui::StyleColorsDark();
+	}
+
+	if (_state->_logger) {
+		auto &lc = _state->_logger->_colors;
+		lc._logger_error_b = _state->theme->logger_error_b;
+		lc._logger_warning_b = _state->theme->logger_warning_b;
+		lc._logger_info_b = _state->theme->logger_info_b;
+		lc._logger_debug_b = _state->theme->logger_debug_b;
+		lc._logger_error = _state->theme->logger_error;
+		lc._logger_warning = _state->theme->logger_warning;
+		lc._logger_info = _state->theme->logger_info;
+		lc._logger_debug = _state->theme->logger_debug;
+	}
+}
+
 static void showSettings() {
 	if (!_state->_w.settings)
 		return;
@@ -495,27 +643,10 @@ static void showSettings() {
 	ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
 	ImGui::SetNextWindowSize(ImVec2(480, 240), ImGuiCond_FirstUseEver);
 	if (ImGui::Begin("Settings", &_state->_w.settings)) {
-		ImGui::ColorEdit4("Breakpoint disabled", &_state->_colors._bp_color_disabled.x);
-		ImGui::ColorEdit4("Breakpoint enabled", &_state->_colors._bp_color_enabled.x);
-		ImGui::ColorEdit4("Breakpoint hover", &_state->_colors._bp_color_hover.x);
-
-		ImGui::ColorEdit4("Channel toggle", &_state->_colors._channel_toggle.x);
-
-		ImGui::SeparatorText("Lingo syntax");
-		ImGui::ColorEdit4("Line", &_state->_colors._line_color.x);
-		ImGui::ColorEdit4("Call", &_state->_colors._call_color.x);
-		ImGui::ColorEdit4("Builtin", &_state->_colors._builtin_color.x);
-		ImGui::ColorEdit4("Variable", &_state->_colors._var_color.x);
-		ImGui::ColorEdit4("Literal", &_state->_colors._literal_color.x);
-		ImGui::ColorEdit4("Comment", &_state->_colors._comment_color.x);
-		ImGui::ColorEdit4("Type", &_state->_colors._type_color.x);
-		ImGui::ColorEdit4("Keyword", &_state->_colors._keyword_color.x);
-		ImGui::ColorEdit4("The entity", &_state->_colors._the_color.x);
-
-		ImGui::SeparatorText("References");
-		ImGui::ColorEdit4("Script", &_state->_colors._script_ref.x);
-		ImGui::ColorEdit4("Variable", &_state->_colors._var_ref.x);
-		ImGui::ColorEdit4("Variable changed", &_state->_colors._var_ref_changed.x);
+		ImGui::SeparatorText("Global Theme");
+		if (ImGui::Combo("Theme", &_state->_activeThemeID, themeNames, kThemeCount)) {
+			setTheme(_state->_activeThemeID);
+		}
 
 		_state->_logger->drawColorOptions();
 	}
@@ -561,6 +692,8 @@ void onImGuiInit() {
 
 	_state->_logger = new ImGuiEx::ImGuiLogger;
 
+	setTheme(_state->_activeThemeID);
+
 	Common::setLogWatcher(onLog);
 }
 
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 3fd80f17183..4ae6e758e35 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -323,10 +323,10 @@ void showCast() {
 							const ImVec2 p1 = ImGui::GetItemRectMax();
 							ImGui::PushClipRect(p0, p1, true);
 							ImDrawList *draw_list = ImGui::GetWindowDrawList();
-							draw_list->AddRect(p0, p1, IM_COL32_WHITE);
+							draw_list->AddRect(p0, p1, _state->theme->borderColor);
 							const ImVec2 pos = p0 + ImVec2((thumbnailSize - textWidth) * 0.5f, (thumbnailSize - textHeight) * 0.5f);
-							draw_list->AddText(nullptr, 0.f, pos, IM_COL32_WHITE, name.c_str(), 0, thumbnailSize);
-							draw_list->AddText(nullptr, 0.f, p1 - ImVec2(16, 16), IM_COL32_WHITE, toIcon(castMember._value->_type));
+							draw_list->AddText(nullptr, 0.f, pos, _state->theme->gridTextColor, name.c_str(), 0, thumbnailSize);
+							draw_list->AddText(nullptr, 0.f, p1 - ImVec2(16, 16), _state->theme->gridTextColor, toIcon(castMember._value->_type));
 							ImGui::PopClipRect();
 						}
 						ImGui::EndGroup();
diff --git a/engines/director/debugger/dt-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index 0f62f8c48fc..305dcc05fba 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -132,10 +132,10 @@ void showControlPanel() {
 		Score *score = movie->getScore();
 		ImDrawList *dl = ImGui::GetWindowDrawList();
 
-		ImU32 color = ImGui::GetColorU32(ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
-		ImU32 color_red = ImGui::GetColorU32(ImVec4(1.0f, 0.6f, 0.6f, 1.0f));
-		ImU32 active_color = ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 0.4f, 1.0f));
-		ImU32 bgcolor = ImGui::GetColorU32(ImVec4(0.2f, 0.2f, 1.0f, 1.0f));
+		ImU32 color = ImGui::GetColorU32(_state->theme->cp_color);
+		ImU32 color_red = ImGui::GetColorU32(_state->theme->cp_color_red);
+		ImU32 active_color = ImGui::GetColorU32(_state->theme->cp_active_color);
+		ImU32 bgcolor = ImGui::GetColorU32(_state->theme->cp_bgcolor);
 		ImVec2 p = ImGui::GetCursorScreenPos();
 		ImVec2 buttonSize(20, 14);
 		float bgX1 = -4.0f, bgX2 = 21.0f;
@@ -248,7 +248,7 @@ void showControlPanel() {
 				dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
 
 			if (score->_playState == kPlayStarted)
-				color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 1.0f, 1.0f));
+				color = ImGui::GetColorU32(_state->theme->cp_playing_color);
 
 			dl->AddTriangleFilled(ImVec2(p.x, p.y), ImVec2(p.x, p.y + 16), ImVec2(p.x + 14, p.y + 8), color);
 
@@ -266,7 +266,7 @@ void showControlPanel() {
 
 		{
 			ImGui::Separator();
-			ImGui::TextColored(ImVec4(0.9f, 0.8f, 0.5f, 1.0f), movie->getArchive()->getPathName().toString().c_str());
+			ImGui::TextColored(_state->theme->cp_path_color, movie->getArchive()->getPathName().toString().c_str());
 			ImGui::SetItemTooltip(movie->getArchive()->getPathName().toString().c_str());
 		}
 
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index fcaac3d366c..37be478c097 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -110,6 +110,67 @@ typedef struct WindowFlag {
 	bool *flag;
 } WindowFlag;
 
+enum ThemeID {
+	kThemeDark = 0,
+	kThemeLight,
+	kThemeCount
+};
+
+struct DebuggerTheme {
+	ImU32 tableLightColor;
+	ImU32 tableDarkColor;
+	ImU32 borderColor;
+	ImU32 sidebarTextColor;
+	ImU32 gridTextColor;
+	ImU32 playhead_color;
+	ImU32 current_statement_bg;
+	ImU32 channel_toggle;
+	ImU32 channelSelectedCol;
+	ImU32 channelHoveredCol;
+	ImU32 contColors[6];
+
+	// Breakpoints
+	ImVec4 bp_color_disabled;
+	ImVec4 bp_color_enabled;
+	ImVec4 bp_color_hover;
+
+	// Syntax Highlighting
+	ImVec4 current_statement;
+	ImVec4 line_color;
+	ImVec4 call_color;
+	ImVec4 builtin_color;
+	ImVec4 var_color;
+	ImVec4 literal_color;
+	ImVec4 comment_color;
+	ImVec4 type_color;
+	ImVec4 keyword_color;
+	ImVec4 the_color;
+
+	// Variable / Script References
+	ImVec4 script_ref;
+	ImVec4 var_ref;
+	ImVec4 var_ref_changed;
+	ImVec4 var_ref_out_of_scope;
+
+	// Control Panel
+	ImVec4 cp_color;
+	ImVec4 cp_color_red;
+	ImVec4 cp_active_color;
+	ImVec4 cp_bgcolor;
+	ImVec4 cp_playing_color;
+	ImVec4 cp_path_color;
+
+	// Logger
+	ImVec4 logger_error_b;
+	ImVec4 logger_warning_b;
+	ImVec4 logger_info_b;
+	ImVec4 logger_debug_b;
+	ImVec4 logger_error;
+	ImVec4 logger_warning;
+	ImVec4 logger_info;
+	ImVec4 logger_debug;
+};
+
 typedef struct ImGuiState {
 
 	struct WatchLogEntry {
@@ -132,27 +193,6 @@ typedef struct ImGuiState {
 		float _sidebar1Height = _cellHeight * 6;
 		float _labelBarHeight = _cellHeight;
 		float _cellHeightExtended = 5 * _cellHeight;
-
-		// dark theme colors
-		ImU32 _darkTableLight = IM_COL32(51, 51, 51, 255);
-		ImU32 _darkTableDark = IM_COL32(38, 38, 38, 255);
-		ImU32 _darkBorder = IM_COL32(102, 102, 102, 100);
-
-		// light theme colors
-		ImU32 _lightTableLight = IM_COL32(240, 240, 240, 255);
-		ImU32 _lightTableDark = IM_COL32(210, 210, 210, 255);
-		ImU32 _lightBorder = IM_COL32(150, 150, 150, 150);
-
-		// text colors
-		ImU32 _sidebarTextColor = IM_COL32(200, 200, 200, 255);
-		static constexpr ImU32 _gridTextColor = IM_COL32(30, 30, 30, 255);
-
-		// active colors
-		ImU32 _tableLightColor = _darkTableLight;
-		ImU32 _tableDarkColor = _darkTableDark;
-		ImU32 _borderColor = _darkBorder;
-
-		bool _isLightTheme = false;
 	} _scoreCfg;
 
 	struct ScoreState {
@@ -185,47 +225,6 @@ typedef struct ImGuiState {
 		uint _callstackSize = 0;
 	} _dbg;
 
-	struct {
-		ImVec4 _bp_color_disabled = ImVec4(0.9f, 0.08f, 0.0f, 0.0f);
-		ImVec4 _bp_color_enabled = ImVec4(0.9f, 0.08f, 0.0f, 1.0f);
-		ImVec4 _bp_color_hover = ImVec4(0.42f, 0.17f, 0.13f, 1.0f);
-
-		ImVec4 _channel_toggle = ImColor(IM_COL32(0x30, 0x30, 0xFF, 0xFF));
-
-		ImVec4 _current_statement = ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0xFF));
-		//ImVec4 _line_color = ImVec4(0.44f, 0.44f, 0.44f, 1.0f);
-		ImVec4 _line_color = ImColor(IM_COL32(0x2F, 0x2F, 0x2F, 0xFF)); // added for better contrast
-		ImVec4 _call_color = ImColor(IM_COL32(0xFF, 0xC5, 0x5C, 0xFF));
-		ImVec4 _builtin_color = ImColor(IM_COL32(0x60, 0x7C, 0xFF, 0xFF));
-		ImVec4 _var_color = ImColor(IM_COL32(0x4B, 0xCD, 0x5E, 0xFF));
-		ImVec4 _literal_color = ImColor(IM_COL32(0xFF, 0x9F, 0xDA, 0x9E));
-		ImVec4 _comment_color = ImColor(IM_COL32(0xFF, 0xA5, 0x9D, 0x95));
-		//ImVec4 _type_color = ImColor(IM_COL32(0x13, 0xC5, 0xF9, 0xFF));
-		ImVec4 _type_color = ImColor(IM_COL32(0xB8, 0xB8, 0xB8, 0xC0)); // added this instead because better contrast
-		ImVec4 _keyword_color = ImColor(IM_COL32(0xC1, 0xC1, 0xC1, 0xFF));
-		ImVec4 _the_color = ImColor(IM_COL32(0xFF, 0x49, 0xEF, 0xFF));
-
-		ImVec4 _script_ref = ImColor(IM_COL32(0x7f, 0x7f, 0xff, 0xfff));
-		ImVec4 _var_ref = ImColor(IM_COL32(0xe6, 0xe6, 0x00, 0xff));
-		ImVec4 _var_ref_changed = ImColor(IM_COL32(0xFF, 0x00, 0x00, 0xFF));
-		ImVec4 _var_ref_out_of_scope = ImColor(IM_COL32(0xFF, 0x00, 0xFF, 0xFF));
-
-		// Colors to show continuation data
-		// They come from the Authoring tool
-		ImColor _contColors[6] = {
-			ImColor(IM_COL32(0xce, 0xce, 0xff, 0x80)), // 0xceceff,
-			ImColor(IM_COL32(0xff, 0xff, 0xce, 0x80)), // 0xffffce,
-			ImColor(IM_COL32(0xce, 0xff, 0xce, 0x80)), // 0xceffce,
-			ImColor(IM_COL32(0xce, 0xff, 0xff, 0x80)), // 0xceffff,
-			ImColor(IM_COL32(0xff, 0xce, 0xff, 0x80)), // 0xffceff,
-			ImColor(IM_COL32(0xff, 0xce, 0x9c, 0x80)), // 0xffce9c,
-		};
-
-		ImColor _channelSelectedCol = ImColor(IM_COL32(0x94, 0x00, 0xD3, 0xFF));
-		ImColor _channelHoveredCol = ImColor(IM_COL32(0xFF, 0xFF, 0, 0x3C));
-		int _contColorIndex = 0;
-	} _colors;
-
 
 	struct {
 		DatumHash _locals;
@@ -273,6 +272,9 @@ typedef struct ImGuiState {
 
 	ImFont *_tinyFont = nullptr;
 
+	int _activeThemeID = kThemeLight;
+	const DebuggerTheme *theme = nullptr;
+
 	struct {
 		Common::Path path;
 		uint32 resType = 0;
@@ -305,6 +307,7 @@ void displayVariable(const Common::String &name, bool changed, bool outOfScope =
 ImColor brightenColor(const ImColor &color, float factor);
 Window *windowListCombo(Common::String *target);
 Common::String formatHandlerName(int scriptId, int castId, Common::String handlerName, ScriptType scriptType, bool childScript);
+void setTheme(int themeIndex);
 
 void showCast();		// dt-cast.cpp
 void showCastDetails();	// dt-castdetails.cpp
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index 7d8efa8c5ea..7f312f0a59c 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -195,26 +195,26 @@ void showBreakpointList() {
 				ImVec2 pos = ImGui::GetCursorScreenPos();
 				const ImVec2 mid(pos.x + 7, pos.y + 7);
 
-				ImVec4 color = bps[i].enabled ? _state->_colors._bp_color_enabled : _state->_colors._bp_color_disabled;
+				ImVec4 color = bps[i].enabled ? _state->theme->bp_color_enabled : _state->theme->bp_color_disabled;
 				ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
 				if (ImGui::IsItemClicked(0)) {
 					if (bps[i].enabled) {
 						bps[i].enabled = false;
-						color = _state->_colors._bp_color_disabled;
+						color = _state->theme->bp_color_disabled;
 					} else {
 						bps[i].enabled = true;
-						color = _state->_colors._bp_color_enabled;
+						color = _state->theme->bp_color_enabled;
 					}
 				}
 
 				if (!bps[i].enabled && ImGui::IsItemHovered()) {
-					color = _state->_colors._bp_color_hover;
+					color = _state->theme->bp_color_hover;
 				}
 
 				if (bps[i].enabled)
 					dl->AddCircleFilled(mid, 4.0f, ImColor(color));
 				else
-					dl->AddCircle(mid, 4.0f, ImColor(_state->_colors._line_color));
+					dl->AddCircle(mid, 4.0f, ImColor(_state->theme->line_color));
 
 				// enabled column
 				ImGui::TableNextColumn();
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index b2f4506d81a..f6292e81102 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -200,15 +200,15 @@ static void drawSidebar1(ImDrawList *dl, ImVec2 startPos, Score *score) {
 		ImVec2 rowMin = ImVec2(startPos.x, y);
 		ImVec2 rowMax = ImVec2(startPos.x + totalWidth, y + cfg._cellHeight);
 
-		dl->AddRectFilled(rowMin, rowMax, cfg._tableDarkColor);
-		addThinRect(dl, rowMin, rowMax, cfg._borderColor);
+		dl->AddRectFilled(rowMin, rowMax, _state->theme->tableDarkColor);
+		addThinRect(dl, rowMin, rowMax, _state->theme->borderColor);
 
 		float radius = 5.0f;
 		float pad  = cfg._cellHeight * 0.12f; // inner padding
 
 		ImVec2 center(rowMin.x + pad + radius, rowMax.y - pad - radius);
 
-		dl->AddCircleFilled(center, radius, U32(_state->_colors._channel_toggle));
+		dl->AddCircleFilled(center, radius, _state->theme->channel_toggle);
 
 		// channel number centered in the right column
 		ImFont *iconFont = ImGui::GetIO().FontDefault;
@@ -216,7 +216,7 @@ static void drawSidebar1(ImDrawList *dl, ImVec2 startPos, Score *score) {
 		float textlen = ImGui::CalcTextSize(icon).x;
 		float textX = startPos.x + toggleColWidth + (labelColWidth - textlen) / 2.0f;
 		float textY = y + (cfg._cellHeight - ImGui::GetTextLineHeight()) / 2.0f;
-		dl->AddText(iconFont, 0.0f, ImVec2(textX, textY), cfg._sidebarTextColor, icon);
+		dl->AddText(iconFont, 0.0f, ImVec2(textX, textY), _state->theme->sidebarTextColor, icon);
 
 		// invisible button covering the row for interaction
 		ImGui::SetCursorScreenPos(rowMin);
@@ -245,8 +245,8 @@ static void drawSidebar2(ImDrawList *dl, ImVec2 startPos, Score *score) {
 		if (ch >= (int)score->_channels.size()) break;
 
 
-		dl->AddRectFilled(rowMin, rowMax, cfg._tableDarkColor);
-		addThinRect(dl, rowMin, rowMax, cfg._borderColor);
+		dl->AddRectFilled(rowMin, rowMax, _state->theme->tableDarkColor);
+		addThinRect(dl, rowMin, rowMax, _state->theme->borderColor);
 
 		// toggle circle
 		// small square at bottom-left of the cell (size relative to cell)
@@ -256,9 +256,9 @@ static void drawSidebar2(ImDrawList *dl, ImVec2 startPos, Score *score) {
 		ImVec2 center(rowMin.x + pad + radius, rowMax.y - pad - radius);
 
 		if (score->_channels[ch]->_visible)
-			dl->AddCircleFilled(center, radius, U32(_state->_colors._channel_toggle));
+			dl->AddCircleFilled(center, radius, _state->theme->channel_toggle);
 		else
-			dl->AddCircle(center, radius, U32(_state->_colors._channel_toggle));
+			dl->AddCircle(center, radius, _state->theme->channel_toggle);
 
 		ImGui::SetCursorScreenPos(rowMin);
 		ImGui::InvisibleButton(Common::String::format("##s2toggle%d", ch).c_str(), ImVec2(toggleColWidth, cellH));
@@ -275,15 +275,15 @@ static void drawSidebar2(ImDrawList *dl, ImVec2 startPos, Score *score) {
 
 		if (_state->_scoreMode != kModeExtended) {
 			float textY = y + (cellH - ImGui::GetTextLineHeight()) / 2.0f;
-			dl->AddText(ImVec2(textX, textY), cfg._sidebarTextColor, buf);
+			dl->AddText(ImVec2(textX, textY), _state->theme->sidebarTextColor, buf);
 		} else { // draw channel number and labels
-			dl->AddText(ImVec2(textX, y + 2.0f), cfg._sidebarTextColor, buf);
+			dl->AddText(ImVec2(textX, y + 2.0f), _state->theme->sidebarTextColor, buf);
 			const char *subLabels[] = { "Member", "Behavior", "Ink", "Blend", "Location" };
 			float lineH = ImGui::GetTextLineHeight();
 			for (int s = 0; s < 5; s++) {
 				float subX = textX - 17.0f;
 				float subY = y + lineH + 2.0f + s * lineH; // offset below channel number
-				dl->AddText(ImVec2(subX, subY), cfg._sidebarTextColor, subLabels[s]);
+				dl->AddText(ImVec2(subX, subY), _state->theme->sidebarTextColor, subLabels[s]);
 			}
 		}
 	}
@@ -295,8 +295,8 @@ static void drawRuler(ImDrawList *dl, ImVec2 startPos) {
 	ImVec2 p1 = startPos;
 	ImVec2 p2 = {p1.x + cfg._rulerWidth, p1.y + cfg._rulerHeight};
 
-	dl->AddRectFilled(p1, p2, cfg._tableDarkColor);
-	addThinRect(dl, p1, p2, cfg._borderColor);
+	dl->AddRectFilled(p1, p2, _state->theme->tableDarkColor);
+	addThinRect(dl, p1, p2, _state->theme->borderColor);
 
 	float bigTickLen = cfg._rulerHeight * 0.4f;
 	float smallTickLen = cfg._rulerHeight * 0.3f;
@@ -313,10 +313,10 @@ static void drawRuler(ImDrawList *dl, ImVec2 startPos) {
 			char buf[16];
 			snprintf(buf, sizeof(buf), "%d", i);
 			float textlen = ImGui::CalcTextSize(buf).x;
-			dl->AddText(ImVec2(rulerX - textlen / 2, p1.y + 4.0), U32(_state->_colors._type_color), buf);
+			dl->AddText(ImVec2(rulerX - textlen / 2, p1.y + 4.0), U32(_state->theme->type_color), buf);
 		}
 
-		dl->AddLine(ImVec2(rulerX, p2.y), ImVec2(rulerX, p2.y - len), U32(_state->_colors._line_color), thickness);
+		dl->AddLine(ImVec2(rulerX, p2.y), ImVec2(rulerX, p2.y - len), U32(_state->theme->line_color), thickness);
 	}
 }
 
@@ -548,9 +548,9 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 			float x = startPos.x + f * cfg._cellWidth;
 			ImVec2 cellMin = ImVec2(x, y);
 			ImVec2 cellMax = ImVec2(x + cfg._cellWidth, y + cellH);
-			ImU32 col = ((rf + 1) % 5 == 0) ? cfg._tableDarkColor : cfg._tableLightColor;
+			ImU32 col = ((rf + 1) % 5 == 0) ? _state->theme->tableDarkColor : _state->theme->tableLightColor;
 			dl->AddRectFilled(cellMin, cellMax, col);
-			addThinRect(dl, cellMin, cellMax, cfg._borderColor);
+			addThinRect(dl, cellMin, cellMax, _state->theme->borderColor);
 		}
 
 		// pass 2: draw sprite span bars on top of cells
@@ -591,25 +591,25 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 							   _state->_hoveredScoreCast.frame <= spanEnd);
 
 			if (isSelected)
-				color = U32(_state->_colors._channelSelectedCol);
+				color = _state->theme->channelSelectedCol;
 			else if (isHovered)
-				color = U32(_state->_colors._channelHoveredCol);
+				color = _state->theme->channelHoveredCol;
 			else {
 				int colorIdx = sprite._colorcode & 0x07;
 				if (colorIdx > 5) colorIdx = 0;
-				color = U32(_state->_colors._contColors[colorIdx]);
+				color = _state->theme->contColors[colorIdx];
 			}
 
 			float rounding = 0.0f;
 			dl->AddRectFilled(ImVec2(x1, y + pad), ImVec2(x2 - 1.0f, y + cellH - pad), color, rounding);
 			// horizontal line through the middle, offset from x1 if circle is present
-			dl->AddLine(ImVec2(x1 + (startVisible ? 6.0f : 0.0f), cy), ImVec2(x2 - 6.0f, cy), U32(_state->_colors._line_color), 1.0f);
+			dl->AddLine(ImVec2(x1 + (startVisible ? 6.0f : 0.0f), cy), ImVec2(x2 - 6.0f, cy), U32(_state->theme->line_color), 1.0f);
 
 			if (startVisible)
-				dl->AddCircle(ImVec2(x1 + 4.0f, cy), 3.0f, U32(_state->_colors._line_color), 0, 1.5f);
+				dl->AddCircle(ImVec2(x1 + 4.0f, cy), 3.0f, U32(_state->theme->line_color), 0, 1.5f);
 
 			if (endVisible)
-				dl->AddRect(ImVec2(x2 - 7.0f, cy - 3.0f), ImVec2(x2 - 1.0f, cy + 3.0f), U32(_state->_colors._line_color), 0.0f, 0, 1.5f);
+				dl->AddRect(ImVec2(x2 - 7.0f, cy - 3.0f), ImVec2(x2 - 1.0f, cy + 3.0f), U32(_state->theme->line_color), 0.0f, 0, 1.5f);
 
 
 			if (_state->_scoreMode == kModeExtended && startVisible && (sprite._castId.member || sprite.isQDShape())) {
@@ -623,7 +623,7 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					snprintf(buf, sizeof(buf), "%s", getDisplayName(cm).c_str());
 				else if (sprite.isQDShape())
 					snprintf(buf, sizeof(buf), "Q");
-				dl->AddText(ImVec2(textX, baseY), cfg._gridTextColor, buf);
+				dl->AddText(ImVec2(textX, baseY), _state->theme->gridTextColor, buf);
 
 				// Behavior
 				buf[0] = '\0';
@@ -631,18 +631,18 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					CastMember *sc = cast->getCastMember(sprite._scriptId.member, true);
 					if (sc) snprintf(buf, sizeof(buf), "%s", getDisplayName(sc).c_str());
 				}
-				dl->AddText(ImVec2(textX, baseY + lineH), cfg._gridTextColor, buf);
+				dl->AddText(ImVec2(textX, baseY + lineH), _state->theme->gridTextColor, buf);
 
 				// Ink
-				dl->AddText(ImVec2(textX, baseY + lineH * 2), cfg._gridTextColor, inkType2str(sprite._ink));
+				dl->AddText(ImVec2(textX, baseY + lineH * 2), _state->theme->gridTextColor, inkType2str(sprite._ink));
 
 				// Blend
 				snprintf(buf, sizeof(buf), "%d", sprite._blendAmount);
-				dl->AddText(ImVec2(textX, baseY + lineH * 3), cfg._gridTextColor, buf);
+				dl->AddText(ImVec2(textX, baseY + lineH * 3), _state->theme->gridTextColor, buf);
 
 				// Location
 				snprintf(buf, sizeof(buf), "%d,%d", sprite._startPoint.x, sprite._startPoint.y);
-				dl->AddText(ImVec2(textX, baseY + lineH *4), cfg._gridTextColor, buf);
+				dl->AddText(ImVec2(textX, baseY + lineH *4), _state->theme->gridTextColor, buf);
 			}
 
 			if (startVisible && _state->_scoreMode != kModeExtended) {
@@ -675,7 +675,7 @@ static void drawSpriteGrid(ImDrawList *dl, ImVec2 startPos, Score *score, Cast *
 					break;
 				}
 				if (label[0])
-					dl->AddText(ImVec2(x1 + 4.0f, y + (cellH - ImGui::GetTextLineHeight()) / 2.0f), cfg._gridTextColor, label);
+					dl->AddText(ImVec2(x1 + 4.0f, y + (cellH - ImGui::GetTextLineHeight()) / 2.0f), _state->theme->gridTextColor, label);
 
 			}
 
@@ -727,9 +727,9 @@ static void drawMainChannelGrid(ImDrawList *dl, ImVec2 startPos, Score *score) {
 			float x = startPos.x + f * cfg._cellWidth;
 			ImVec2 cellMin = ImVec2(x, y);
 			ImVec2 cellMax = ImVec2(x + cfg._cellWidth, y + cfg._cellHeight);
-			ImU32 col = ((rf + 1) % 5 == 0) ? cfg._tableDarkColor : cfg._tableLightColor;
+			ImU32 col = ((rf + 1) % 5 == 0) ? _state->theme->tableDarkColor : _state->theme->tableLightColor;
 			dl->AddRectFilled(cellMin, cellMax, col);
-			addThinRect(dl, cellMin, cellMax, cfg._borderColor);
+			addThinRect(dl, cellMin, cellMax, _state->theme->borderColor);
 		}
 
 		// pass 2, span bars
@@ -778,12 +778,12 @@ static void drawMainChannelGrid(ImDrawList *dl, ImVec2 startPos, Score *score) {
 			float cy = y + cfg._cellHeight * 0.2;
 			float pad = 0.0f;
 
-			dl->AddRectFilled(ImVec2(x1, y + pad), ImVec2(x2 - 1.0f, y + cfg._cellHeight - pad), U32(_state->_colors._contColors[ch % 6]), 0.0f);
-			dl->AddLine(ImVec2(x1 + (startVisible ? 6.0f : 0.0f), cy), ImVec2(x2 - 6.0f, cy), U32(_state->_colors._line_color), 1.0f);
+			dl->AddRectFilled(ImVec2(x1, y + pad), ImVec2(x2 - 1.0f, y + cfg._cellHeight - pad), _state->theme->contColors[ch % 6], 0.0f);
+			dl->AddLine(ImVec2(x1 + (startVisible ? 6.0f : 0.0f), cy), ImVec2(x2 - 6.0f, cy), U32(_state->theme->line_color), 1.0f);
 			if (startVisible)
-				dl->AddCircle(ImVec2(x1 + 4.0f, cy), 3.0f,  U32(_state->_colors._line_color), 0, 1.5f);
+				dl->AddCircle(ImVec2(x1 + 4.0f, cy), 3.0f,  U32(_state->theme->line_color), 0, 1.5f);
 			if (endVisible)
-				dl->AddRect(ImVec2(x2 - 7.0f, cy - 3.0f), ImVec2(x2 - 1.0f, cy + 3.0f), U32(_state->_colors._line_color), 0.0f, 0, 1.5f);
+				dl->AddRect(ImVec2(x2 - 7.0f, cy - 3.0f), ImVec2(x2 - 1.0f, cy + 3.0f), U32(_state->theme->line_color), 0.0f, 0, 1.5f);
 			f = (runEnd - startFrame) + 1; // skip to after the run
 		}
 
@@ -868,12 +868,11 @@ static void drawPlayhead(ImDrawList *dl, ImVec2 rulerPos, ImVec2 mainChannelGrid
 	float px = rulerPos.x + (currentFrameNum - start) * cfg._cellWidth;
 	float top = mainChannelGridPos.y; // top of main channel grid
 	float bottom = gridPos.y + cfg._tableHeight; // bottom of sprite grid
-	ImU32 RED = IM_COL32(200, 50, 0, 255);
 
-	dl->AddLine(ImVec2(px, top), ImVec2(px, bottom), RED, 2.0f);
+	dl->AddLine(ImVec2(px, top), ImVec2(px, bottom), _state->theme->playhead_color, 2.0f);
 
 	// triangle marker in the ruler
-	dl->AddTriangleFilled(ImVec2(px - 5.0f, rulerPos.y), ImVec2(px + 5.0f, rulerPos.y), ImVec2(px, rulerPos.y + 8.0f), RED);
+	dl->AddTriangleFilled(ImVec2(px - 5.0f, rulerPos.y), ImVec2(px + 5.0f, rulerPos.y), ImVec2(px, rulerPos.y + 8.0f), _state->theme->playhead_color);
 }
 
 static void handleScrolling(Score *score, int numChannels) {
@@ -922,8 +921,8 @@ static void drawLabelBar(ImDrawList *dl, ImVec2 pos, Score *score) {
 
 	// draw background rectangle
 	ImVec2 finalPos = ImVec2(pos.x + cfg._tableWidth, pos.y + cfg._labelBarHeight);
-	dl->AddRectFilled(pos, finalPos, cfg._tableDarkColor);
-	dl->AddRect(pos, finalPos, cfg._tableLightColor);
+	dl->AddRectFilled(pos, finalPos, _state->theme->tableDarkColor);
+	dl->AddRect(pos, finalPos, _state->theme->tableLightColor);
 
 	for (int f = 0; f < cfg._visibleFrames; f++) {
 		int rf = startFrame + f;
@@ -936,14 +935,14 @@ static void drawLabelBar(ImDrawList *dl, ImVec2 pos, Score *score) {
 			float textY = y + (cfg._labelBarHeight - ImGui::GetTextLineHeight()) / 2.0f;
 
 			dl->AddText(ImVec2(x - ImGui::CalcTextSize(ICON_MS_BEENHERE).x / 2.0f, textY),
-						cfg._sidebarTextColor, ICON_MS_BEENHERE);
+						_state->theme->sidebarTextColor, ICON_MS_BEENHERE);
 
 			float iconW = ImGui::CalcTextSize(ICON_MS_BEENHERE).x;
 			float textX = x + iconW / 2.0f + 2.0f;
 			float textWidth = ImGui::CalcTextSize(labelName->c_str()).x;
 
 			if (textX + textWidth < finalPos.x) // prevent text being drawn outside the table bounds
-				dl->AddText(ImVec2(textX, textY), cfg._sidebarTextColor, labelName->c_str());
+				dl->AddText(ImVec2(textX, textY), _state->theme->sidebarTextColor, labelName->c_str());
 
 			float px = pos.x + f * cfg._cellWidth;
 			ImGui::SetCursorScreenPos(ImVec2(px, y));
@@ -956,24 +955,6 @@ static void drawLabelBar(ImDrawList *dl, ImVec2 pos, Score *score) {
 	}
 }
 
-static void drawThemeButton(ImVec2 pos) {
-	ImGui::SetCursorScreenPos(pos);
-	if (ImGui::Button(ICON_MS_LIGHT_MODE)) {
-		auto &cfg = _state->_scoreCfg;
-		cfg._isLightTheme = !cfg._isLightTheme;
-		cfg._sidebarTextColor = cfg._isLightTheme ? cfg._gridTextColor : cfg._sidebarTextColor;
-		if (cfg._isLightTheme) {
-			cfg._tableLightColor = cfg._lightTableLight;
-			cfg._tableDarkColor = cfg._lightTableDark;
-			cfg._borderColor = cfg._lightBorder;
-		} else {
-			cfg._tableLightColor = cfg._darkTableLight;
-			cfg._tableDarkColor = cfg._darkTableDark;
-			cfg._borderColor = cfg._darkBorder;
-		}
-	}
-}
-
 void showScore() {
 	if (!_state->_w.score)
 		return;
@@ -1014,7 +995,6 @@ void showScore() {
 		ImVec2 origin = ImGui::GetCursorScreenPos();
 		ScoreLayout layout = computeLayout(origin, _state->_scoreCfg);
 
-		drawThemeButton(layout.themeSelectorPos);
 		drawLabelBar(dl, layout.labelBarPos, score);
 		drawSidebar1(dl, layout.sidebar1Pos, score);
 		drawMainChannelGrid(dl, layout.mainChannelGridPos, score);
@@ -1126,9 +1106,9 @@ void showChannels() {
 					}
 
 					if (score->_channels[i]->_visible)
-						dl->AddCircleFilled(mid, 4.0f, U32(_state->_colors._channel_toggle));
+						dl->AddCircleFilled(mid, 4.0f, _state->theme->channel_toggle);
 					else
-						dl->AddCircle(mid, 4.0f, U32(_state->_colors._channel_toggle));
+						dl->AddCircle(mid, 4.0f, _state->theme->channel_toggle);
 
 					ImGui::PopID();
 				}
diff --git a/engines/director/debugger/dt-script-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index dc31440cba4..350af024e27 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -56,7 +56,7 @@ public:
 	virtual bool visitHandlerNode(HandlerNode *node) {
 		ImGui::Text("on ");
 		ImGui::SameLine();
-		ImGui::TextColored(_state->_colors._call_color, "%s", node->name->c_str());
+		ImGui::TextColored(_state->theme->call_color, "%s", node->name->c_str());
 		if (!node->args->empty()) {
 			ImGui::SameLine();
 			ImGui::Text(" ");
@@ -86,7 +86,7 @@ public:
 		}
 		unindent();
 		renderLine(node->endOffset);
-		ImGui::TextColored(_state->_colors._keyword_color, "end");
+		ImGui::TextColored(_state->theme->keyword_color, "end");
 		return true;
 	}
 
@@ -120,7 +120,7 @@ public:
 		ImGui::Text("%s ", node->name->c_str());
 		ImGui::SameLine();
 		if (*node->name == "go") {
-			ImGui::TextColored(_state->_colors._keyword_color, "to ");
+			ImGui::TextColored(_state->theme->keyword_color, "to ");
 			ImGui::SameLine();
 		}
 		for (uint i = 0; i < node->args->size(); i++) {
@@ -138,40 +138,40 @@ public:
 	}
 
 	virtual bool visitPutIntoNode(PutIntoNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "put ");
+		ImGui::TextColored(_state->theme->keyword_color, "put ");
 		ImGui::SameLine();
 		node->val->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " into ");
+		ImGui::TextColored(_state->theme->keyword_color, " into ");
 		ImGui::SameLine();
 		node->var->accept(this);
 		return true;
 	}
 
 	virtual bool visitPutAfterNode(PutAfterNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "put ");
+		ImGui::TextColored(_state->theme->keyword_color, "put ");
 		ImGui::SameLine();
 		node->val->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " after ");
+		ImGui::TextColored(_state->theme->keyword_color, " after ");
 		ImGui::SameLine();
 		node->var->accept(this);
 		return true;
 	}
 
 	virtual bool visitPutBeforeNode(PutBeforeNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "put ");
+		ImGui::TextColored(_state->theme->keyword_color, "put ");
 		ImGui::SameLine();
 		node->val->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " before ");
+		ImGui::TextColored(_state->theme->keyword_color, " before ");
 		ImGui::SameLine();
 		node->var->accept(this);
 		return true;
 	}
 
 	virtual bool visitSetNode(SetNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "set ");
+		ImGui::TextColored(_state->theme->keyword_color, "set ");
 		ImGui::SameLine();
 		node->val->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " to ");
+		ImGui::TextColored(_state->theme->keyword_color, " to ");
 		ImGui::SameLine();
 		node->var->accept(this);
 		return true;
@@ -207,10 +207,10 @@ public:
 	}
 
 	virtual bool visitIfStmtNode(IfStmtNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "if ");
+		ImGui::TextColored(_state->theme->keyword_color, "if ");
 		ImGui::SameLine();
 		node->cond->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " then ");
+		ImGui::TextColored(_state->theme->keyword_color, " then ");
 		if (node->stmts->size() == 1) {
 			ImGui::SameLine();
 			(*node->stmts)[0]->accept(this);
@@ -224,17 +224,17 @@ public:
 			}
 			unindent();
 			renderLine(node->endOffset);
-			ImGui::TextColored(_state->_colors._keyword_color, "endif");
+			ImGui::TextColored(_state->theme->keyword_color, "endif");
 			ImGui::SameLine();
 		}
 		return true;
 	}
 
 	virtual bool visitIfElseStmtNode(IfElseStmtNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "if ");
+		ImGui::TextColored(_state->theme->keyword_color, "if ");
 		ImGui::SameLine();
 		node->cond->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " then ");
+		ImGui::TextColored(_state->theme->keyword_color, " then ");
 		if (node->stmts1->size() == 1) {
 			ImGui::SameLine();
 			(*node->stmts1)[0]->accept(this);
@@ -253,7 +253,7 @@ public:
 			unindent();
 			renderLine(offset);
 		}
-		ImGui::TextColored(_state->_colors._keyword_color, "else ");
+		ImGui::TextColored(_state->theme->keyword_color, "else ");
 		if (node->stmts2->size() == 1) {
 			ImGui::SameLine();
 			(*node->stmts2)[0]->accept(this);
@@ -269,14 +269,14 @@ public:
 			}
 			unindent();
 			renderLine(offset);
-			ImGui::TextColored(_state->_colors._keyword_color, "endif");
+			ImGui::TextColored(_state->theme->keyword_color, "endif");
 			ImGui::SameLine();
 		}
 		return true;
 	}
 
 	virtual bool visitRepeatWhileNode(RepeatWhileNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "repeat while ");
+		ImGui::TextColored(_state->theme->keyword_color, "repeat while ");
 		ImGui::SameLine();
 		node->cond->accept(this);
 		ImGui::NewLine();
@@ -291,17 +291,17 @@ public:
 		}
 		unindent();
 		renderLine(offset);
-		ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
+		ImGui::TextColored(_state->theme->keyword_color, "endrepeat");
 		return true;
 	}
 
 	virtual bool visitRepeatWithToNode(RepeatWithToNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "repeat with ");
+		ImGui::TextColored(_state->theme->keyword_color, "repeat with ");
 		ImGui::SameLine();
 		ImGui::Text("%s = ", node->var->c_str());
 		ImGui::SameLine();
 		node->start->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, " %s ", node->down ? "down to" : "to");
+		ImGui::TextColored(_state->theme->keyword_color, " %s ", node->down ? "down to" : "to");
 		node->end->accept(this);
 		ImGui::NewLine();
 		indent();
@@ -313,12 +313,12 @@ public:
 		}
 		unindent();
 		renderLine(node->endOffset);
-		ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
+		ImGui::TextColored(_state->theme->keyword_color, "endrepeat");
 		return true;
 	}
 
 	virtual bool visitRepeatWithInNode(RepeatWithInNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "repeat with ");
+		ImGui::TextColored(_state->theme->keyword_color, "repeat with ");
 		ImGui::SameLine();
 		ImGui::Text("%s in ", node->var->c_str());
 		ImGui::SameLine();
@@ -333,27 +333,27 @@ public:
 		}
 		unindent();
 		renderLine(node->endOffset);
-		ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
+		ImGui::TextColored(_state->theme->keyword_color, "endrepeat");
 		return true;
 	}
 
 	virtual bool visitNextRepeatNode(NextRepeatNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "next repeat");
+		ImGui::TextColored(_state->theme->keyword_color, "next repeat");
 		return true;
 	}
 
 	virtual bool visitExitRepeatNode(ExitRepeatNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "exit repeat");
+		ImGui::TextColored(_state->theme->keyword_color, "exit repeat");
 		return true;
 	}
 
 	virtual bool visitExitNode(ExitNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "exit");
+		ImGui::TextColored(_state->theme->keyword_color, "exit");
 		return true;
 	}
 
 	virtual bool visitReturnNode(ReturnNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "return");
+		ImGui::TextColored(_state->theme->keyword_color, "return");
 		if (node->expr) {
 			ImGui::Text(" ");
 			ImGui::SameLine();
@@ -364,11 +364,11 @@ public:
 	}
 
 	virtual bool visitTellNode(TellNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "tell ");
+		ImGui::TextColored(_state->theme->keyword_color, "tell ");
 		node->target->accept(this);
 		if (node->stmts->size() == 1) {
 			ImGui::SameLine();
-			ImGui::TextColored(_state->_colors._keyword_color, " to ");
+			ImGui::TextColored(_state->theme->keyword_color, " to ");
 			ImGui::SameLine();
 			(*node->stmts)[0]->accept(this);
 		} else {
@@ -381,17 +381,17 @@ public:
 			}
 			unindent();
 			renderLine(node->endOffset);
-			ImGui::TextColored(_state->_colors._keyword_color, "endtell");
+			ImGui::TextColored(_state->theme->keyword_color, "endtell");
 		}
 		return true;
 	}
 
 	virtual bool visitWhenNode(WhenNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "when ");
+		ImGui::TextColored(_state->theme->keyword_color, "when ");
 		ImGui::SameLine();
 		ImGui::Text("%s", node->event->c_str());
 		ImGui::SameLine();
-		ImGui::TextColored(_state->_colors._keyword_color, " then ");
+		ImGui::TextColored(_state->theme->keyword_color, " then ");
 		ImGui::SameLine();
 		ImGui::Text("%s", node->code->c_str());
 		ImGui::SameLine();
@@ -399,46 +399,46 @@ public:
 	}
 
 	virtual bool visitDeleteNode(DeleteNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "delete ");
+		ImGui::TextColored(_state->theme->keyword_color, "delete ");
 		ImGui::SameLine();
 		node->chunk->accept(this);
 		return true;
 	}
 
 	virtual bool visitHiliteNode(HiliteNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "hilite ");
+		ImGui::TextColored(_state->theme->keyword_color, "hilite ");
 		ImGui::SameLine();
 		node->chunk->accept(this);
 		return true;
 	}
 
 	virtual bool visitAssertErrorNode(AssertErrorNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "scummvmAssertError ");
+		ImGui::TextColored(_state->theme->keyword_color, "scummvmAssertError ");
 		ImGui::SameLine();
 		node->stmt->accept(this);
 		return true;
 	}
 
 	virtual bool visitIntNode(IntNode *node) {
-		ImGui::TextColored(_state->_colors._literal_color, "%d", node->val);
+		ImGui::TextColored(_state->theme->literal_color, "%d", node->val);
 		ImGui::SameLine();
 		return true;
 	}
 
 	virtual bool visitFloatNode(FloatNode *node) {
-		ImGui::TextColored(_state->_colors._literal_color, "%g", node->val);
+		ImGui::TextColored(_state->theme->literal_color, "%g", node->val);
 		ImGui::SameLine();
 		return true;
 	}
 
 	virtual bool visitSymbolNode(SymbolNode *node) {
-		ImGui::TextColored(_state->_colors._literal_color, "%s", node->val->c_str());
+		ImGui::TextColored(_state->theme->literal_color, "%s", node->val->c_str());
 		ImGui::SameLine();
 		return true;
 	}
 
 	virtual bool visitStringNode(StringNode *node) {
-		ImGui::TextColored(_state->_colors._literal_color, "\"%s\"", node->val->c_str());
+		ImGui::TextColored(_state->theme->literal_color, "\"%s\"", node->val->c_str());
 		ImGui::SameLine();
 		return true;
 	}
@@ -490,7 +490,7 @@ public:
 
 	virtual bool visitFuncNode(FuncNode *node) {
 		const bool isBuiltin = g_lingo->_builtinCmds.contains(*node->name);
-		const ImVec4 color = (ImVec4)ImColor(isBuiltin ? _state->_colors._builtin_color : _state->_colors._call_color);
+		const ImVec4 color = (ImVec4)ImColor(isBuiltin ? _state->theme->builtin_color : _state->theme->call_color);
 		ImGui::TextColored(color, "%s(", node->name->c_str());
 		if (!isBuiltin && ImGui::IsItemHovered() && ImGui::BeginTooltip()) {
 			ImGui::Text("Go to definition");
@@ -539,7 +539,7 @@ public:
 	}
 
 	virtual bool visitVarNode(VarNode *node) {
-		ImGui::TextColored(_state->_colors._var_color, "%s", node->name->c_str());
+		ImGui::TextColored(_state->theme->var_color, "%s", node->name->c_str());
 		if (ImGui::IsItemHovered() && g_lingo->_globalvars.contains(*node->name)) {
 			const Datum &val = g_lingo->_globalvars.getVal(*node->name);
 			ImGui::BeginTooltip();
@@ -619,52 +619,52 @@ public:
 	}
 
 	virtual bool visitFrameNode(FrameNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "frame ");
+		ImGui::TextColored(_state->theme->keyword_color, "frame ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
 	}
 
 	virtual bool visitMovieNode(MovieNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "movie ");
+		ImGui::TextColored(_state->theme->keyword_color, "movie ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
 	}
 
 	virtual bool visitIntersectsNode(IntersectsNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
+		ImGui::TextColored(_state->theme->keyword_color, "sprite ");
 		ImGui::SameLine();
 		node->sprite1->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, "intersects ");
+		ImGui::TextColored(_state->theme->keyword_color, "intersects ");
 		node->sprite2->accept(this);
 		return true;
 	}
 
 	virtual bool visitWithinNode(WithinNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
+		ImGui::TextColored(_state->theme->keyword_color, "sprite ");
 		ImGui::SameLine();
 		node->sprite1->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, "within ");
+		ImGui::TextColored(_state->theme->keyword_color, "within ");
 		node->sprite2->accept(this);
 		return true;
 	}
 
 	virtual bool visitTheNode(TheNode *node) {
-		ImGui::TextColored(_state->_colors._the_color, "the %s", node->prop->c_str());
+		ImGui::TextColored(_state->theme->the_color, "the %s", node->prop->c_str());
 		ImGui::SameLine();
 		return true;
 	}
 
 	virtual bool visitTheOfNode(TheOfNode *node) {
-		ImGui::TextColored(_state->_colors._the_color, "the %s of ", node->prop->c_str());
+		ImGui::TextColored(_state->theme->the_color, "the %s of ", node->prop->c_str());
 		ImGui::SameLine();
 		node->obj->accept(this);
 		return true;
 	}
 
 	virtual bool visitTheNumberOfNode(TheNumberOfNode *node) {
-		ImGui::TextColored(_state->_colors._the_color, "the number of ");
+		ImGui::TextColored(_state->theme->the_color, "the number of ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
@@ -672,7 +672,7 @@ public:
 
 	virtual bool visitTheLastNode(TheLastNode *node) {
 		// TODO: change the node to know if it's 'in' or 'of'
-		ImGui::TextColored(_state->_colors._the_color, "the last %s in/of ", toString(node->type).c_str());
+		ImGui::TextColored(_state->theme->the_color, "the last %s in/of ", toString(node->type).c_str());
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
@@ -692,37 +692,37 @@ public:
 			break;
 		}
 		const char *key2 = node->entity == kTheDate ? "date" : "time";
-		ImGui::TextColored(_state->_colors._the_color, "the %s %s", key1, key2);
+		ImGui::TextColored(_state->theme->the_color, "the %s %s", key1, key2);
 		ImGui::SameLine();
 		return true;
 	}
 
 	virtual bool visitMenuNode(MenuNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "menu ");
+		ImGui::TextColored(_state->theme->keyword_color, "menu ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
 	}
 
 	virtual bool visitMenuItemNode(MenuItemNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "menuitem ");
+		ImGui::TextColored(_state->theme->keyword_color, "menuitem ");
 		ImGui::SameLine();
 		node->arg1->accept(this);
-		ImGui::TextColored(_state->_colors._keyword_color, "of menu ");
+		ImGui::TextColored(_state->theme->keyword_color, "of menu ");
 		ImGui::SameLine();
 		node->arg2->accept(this);
 		return true;
 	}
 
 	virtual bool visitSoundNode(SoundNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "sound ");
+		ImGui::TextColored(_state->theme->keyword_color, "sound ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
 	}
 
 	virtual bool visitSpriteNode(SpriteNode *node) {
-		ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
+		ImGui::TextColored(_state->theme->keyword_color, "sprite ");
 		ImGui::SameLine();
 		node->arg->accept(this);
 		return true;
@@ -748,11 +748,11 @@ public:
 		ImGui::SameLine();
 		node->start->accept(this);
 		if (node->end) {
-			ImGui::TextColored(_state->_colors._keyword_color, " to ");
+			ImGui::TextColored(_state->theme->keyword_color, " to ");
 			ImGui::SameLine();
 			node->end->accept(this);
 		}
-		ImGui::TextColored(_state->_colors._keyword_color, " of ");
+		ImGui::TextColored(_state->theme->keyword_color, " of ");
 		ImGui::SameLine();
 		node->src->accept(this);
 		return true;
@@ -814,18 +814,18 @@ private:
 		const float width = ImGui::GetContentRegionAvail().x;
 		const ImVec2 mid(pos.x + 7, pos.y + 7);
 
-		ImVec4 color = _state->_colors._bp_color_disabled;
+		ImVec4 color = _state->theme->bp_color_disabled;
 		const Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
 		if (bp)
-			color = _state->_colors._bp_color_enabled;
+			color = _state->theme->bp_color_enabled;
 
 		ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
 
 		// click on breakpoint column?
 		if (ImGui::IsItemClicked(0)) {
-			if (color == _state->_colors._bp_color_enabled) {
+			if (color == _state->theme->bp_color_enabled) {
 				g_lingo->delBreakpoint(bp->id);
-				color = _state->_colors._bp_color_disabled;
+				color = _state->theme->bp_color_disabled;
 			} else {
 				Director::Breakpoint newBp;
 				newBp.type = kBreakpointFunction;
@@ -833,32 +833,32 @@ private:
 				newBp.funcName = _script.handlerId;
 				newBp.funcOffset = pc;
 				g_lingo->addBreakpoint(newBp);
-				color = _state->_colors._bp_color_enabled;
+				color = _state->theme->bp_color_enabled;
 			}
 		}
 
-		if (color == _state->_colors._bp_color_disabled && ImGui::IsItemHovered()) {
-			color = _state->_colors._bp_color_hover;
+		if (color == _state->theme->bp_color_disabled && ImGui::IsItemHovered()) {
+			color = _state->theme->bp_color_hover;
 		}
 
 		// draw breakpoint
 		if (!bp || bp->enabled)
 			dl->AddCircleFilled(mid, 4.0f, ImColor(color));
 		else
-			dl->AddCircle(mid, 4.0f, ImColor(_state->_colors._line_color));
+			dl->AddCircle(mid, 4.0f, ImColor(_state->theme->line_color));
 
 		// draw current statement
 		if (showCurrentStatement) {
-			dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
-			dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
+			dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->theme->current_statement));
+			dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->theme->current_statement));
 			if (!_scrollDone && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
 				ImGui::SetScrollHereY(0.5f);
 				_scrollDone = true;
 			}
-			dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
+			dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), _state->theme->current_statement_bg, 0.4f);
 		}
 		// draw separator
-		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->_colors._line_color));
+		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->theme->line_color));
 
 		ImGui::SetItemTooltip("Click to add a breakpoint");
 		ImGui::SameLine();
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 9bf5336c5d8..7f74b91508a 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -58,7 +58,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::CommentNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._comment_color), "-- %s", node.text.c_str());
+		ImGui::TextColored(ImColor(_state->theme->comment_color), "-- %s", node.text.c_str());
 		ImGui::SameLine();
 	}
 
@@ -67,9 +67,9 @@ public:
 	}
 
 	virtual void visit(const LingoDec::NewObjNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), "new");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), "new");
 		ImGui::SameLine();
-		ImGui::TextColored(ImColor(_state->_colors._type_color), "%s", node.objType.c_str());
+		ImGui::TextColored(ImColor(_state->theme->type_color), "%s", node.objType.c_str());
 		ImGui::SameLine();
 		ImGui::Text(" (");
 		ImGui::SameLine();
@@ -103,7 +103,7 @@ public:
 			renderIndentation();
 		}
 
-		const ImVec4 color = (ImVec4)ImColor(g_lingo->_builtinCmds.contains(node.name) ? _state->_colors._builtin_color : _state->_colors._call_color);
+		const ImVec4 color = (ImVec4)ImColor(g_lingo->_builtinCmds.contains(node.name) ? _state->theme->builtin_color : _state->theme->call_color);
 		ImGui::TextColored(color, "%s", node.name.c_str());
 		// TODO: we should test Director::builtins too (but inaccessible)
 		if (!g_lingo->_builtinFuncs.contains(node.name) && ImGui::IsItemHovered() && ImGui::BeginTooltip()) {
@@ -168,12 +168,12 @@ public:
 	}
 
 	virtual void visit(const LingoDec::PutStmtNode &node) override {
-		write(node._startOffset, "put ", _state->_colors._keyword_color);
+		write(node._startOffset, "put ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.value->accept(*this);
 		ImGui::Text(" ");
 		ImGui::SameLine();
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), LingoDec::StandardNames::putTypeNames[node.type]);
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), LingoDec::StandardNames::putTypeNames[node.type]);
 		ImGui::SameLine();
 		ImGui::Text(" ");
 		ImGui::SameLine();
@@ -182,91 +182,91 @@ public:
 	}
 
 	virtual void visit(const LingoDec::TheExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the %s", node.prop.c_str());
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the %s", node.prop.c_str());
 		ImGui::SameLine();
 	}
 
 	virtual void visit(const LingoDec::ExitStmtNode &node) override {
-		write(node._startOffset, "exit", _state->_colors._keyword_color);
+		write(node._startOffset, "exit", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::WhenStmtNode &node) override {
-		write(node._startOffset, "when ", _state->_colors._keyword_color);
+		write(node._startOffset, "when ", _state->theme->keyword_color);
 		ImGui::SameLine();
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), LingoDec::StandardNames::whenEventNames[node.event]);
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), LingoDec::StandardNames::whenEventNames[node.event]);
 		ImGui::SameLine();
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " then ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " then ");
 		ImGui::SameLine();
 		ImGui::Text("%s", node.script.c_str());
 	}
 
 	virtual void visit(const LingoDec::RepeatWhileStmtNode &node) override {
-		write(node._startOffset, "repeat while ", _state->_colors._keyword_color);
+		write(node._startOffset, "repeat while ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.condition->accept(*this);
 		ImGui::NewLine();
 		node.block->accept(*this);
-		write(node._endOffset, "end repeat", _state->_colors._keyword_color);
+		write(node._endOffset, "end repeat", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::RepeatWithInStmtNode &node) override {
-		write(node._startOffset, "repeat with ", _state->_colors._keyword_color);
+		write(node._startOffset, "repeat with ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		renderVar(node.varName);
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " in ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " in ");
 		ImGui::SameLine();
 		node.list->accept(*this);
 		ImGui::NewLine();
 		node.block->accept(*this);
-		write(node._endOffset, "end repeat", _state->_colors._keyword_color);
+		write(node._endOffset, "end repeat", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::RepeatWithToStmtNode &node) override {
-		write(node._startOffset, "repeat with ", _state->_colors._keyword_color);
+		write(node._startOffset, "repeat with ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		renderVar(node.varName);
 		ImGui::Text(" = ");
 		ImGui::SameLine();
 		node.start->accept(*this);
 		if (node.up) {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " to ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " to ");
 			ImGui::SameLine();
 		} else {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " down to ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " down to ");
 			ImGui::SameLine();
 		}
 		node.end->accept(*this);
 		ImGui::NewLine();
 		node.block->accept(*this);
-		write(node._endOffset, "end repeat", _state->_colors._keyword_color);
+		write(node._endOffset, "end repeat", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::IfStmtNode &node) override {
 		{
-			write(node._startOffset, "if ", _state->_colors._keyword_color);
+			write(node._startOffset, "if ", _state->theme->keyword_color);
 			ImGui::SameLine();
 			node.condition->accept(*this);
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " then ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " then ");
 		}
 		node.block1->accept(*this);
 		if (node.hasElse) {
-			write(node.block2->_startOffset, "else ", _state->_colors._keyword_color);
+			write(node.block2->_startOffset, "else ", _state->theme->keyword_color);
 			node.block2->accept(*this);
 		}
-		write(node._endOffset, "end if", _state->_colors._keyword_color);
+		write(node._endOffset, "end if", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::TellStmtNode &node) override {
-		write(node._startOffset, "tell ", _state->_colors._keyword_color);
+		write(node._startOffset, "tell ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.window->accept(*this);
 		ImGui::NewLine();
 		node.block->accept(*this);
-		write(node._endOffset, "end tell", _state->_colors._keyword_color);
+		write(node._endOffset, "end tell", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::EndCaseNode &node) override {
-		write(node._endOffset, "end case", _state->_colors._keyword_color);
+		write(node._endOffset, "end case", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::CaseLabelNode &node) override {
@@ -303,11 +303,11 @@ public:
 		ImGui::SameLine();
 		node.first->accept(*this);
 		if (!(node.last->type == LingoDec::kLiteralNode && node.last->getValue()->type == LingoDec::kDatumInt && node.last->getValue()->i == 0)) {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " to ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " to ");
 			ImGui::SameLine();
 			node.last->accept(*this);
 		}
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " of ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " of ");
 		ImGui::SameLine();
 		node.string->accept(*this);
 	}
@@ -329,10 +329,10 @@ public:
 	}
 
 	virtual void visit(const LingoDec::CaseStmtNode &node) override {
-		write(node._startOffset, "case ", _state->_colors._keyword_color);
+		write(node._startOffset, "case ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.value->accept(*this);
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " of ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " of ");
 		indent();
 		if (node.firstLabel) {
 			node.firstLabel->accept(*this);
@@ -341,7 +341,7 @@ public:
 			node.otherwise->accept(*this);
 		}
 		unindent();
-		write(node._endOffset, "end case", _state->_colors._keyword_color);
+		write(node._endOffset, "end case", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::ObjCallNode &node) override {
@@ -394,9 +394,9 @@ public:
 			ImGui::Text("%s", node.prop.c_str());
 			ImGui::SameLine();
 		} else {
-			ImGui::TextColored(_state->_colors._the_color, "the %s", node.prop.c_str());
+			ImGui::TextColored(_state->theme->the_color, "the %s", node.prop.c_str());
 			ImGui::SameLine();
-			ImGui::TextColored(_state->_colors._keyword_color, " of ");
+			ImGui::TextColored(_state->theme->keyword_color, " of ");
 			ImGui::SameLine();
 
 			bool parenObj = (node.obj->type == LingoDec::kBinaryOpNode);
@@ -453,7 +453,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::OtherwiseNode &node) override {
-		write(node._startOffset, "otherwise:", _state->_colors._keyword_color);
+		write(node._startOffset, "otherwise:", _state->theme->keyword_color);
 		node.block->accept(*this);
 	}
 
@@ -487,7 +487,7 @@ public:
 			}
 
 			if (hasCastID) {
-				ImGui::TextColored(ImColor(_state->_colors._keyword_color), "of castLib");
+				ImGui::TextColored(ImColor(_state->theme->keyword_color), "of castLib");
 				ImGui::SameLine();
 
 				bool parenCastID = (node.castID->type == LingoDec::kBinaryOpNode);
@@ -507,18 +507,18 @@ public:
 	virtual void visit(const LingoDec::PlayCmdStmtNode &node) override {
 		auto &rawArgs = node.argList->getValue()->l;
 
-		write(node._startOffset, "play ", _state->_colors._keyword_color);
+		write(node._startOffset, "play ", _state->theme->keyword_color);
 		ImGui::SameLine();
 
 		if (rawArgs.size() == 0) {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " done");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " done");
 			ImGui::SameLine();
 			return;
 		}
 
 		auto &frame = rawArgs[0];
 		if (rawArgs.size() == 1) {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " frame ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " frame ");
 			ImGui::SameLine();
 			frame->accept(*this);
 			return;
@@ -526,23 +526,23 @@ public:
 
 		auto &movie = rawArgs[1];
 		if (!(frame->type == LingoDec::kLiteralNode && frame->getValue()->type == LingoDec::kDatumInt && frame->getValue()->i == 1)) {
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " frame ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " frame ");
 			ImGui::SameLine();
 			frame->accept(*this);
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " of ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " of ");
 			ImGui::SameLine();
 		}
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " movie ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " movie ");
 		ImGui::SameLine();
 		movie->accept(*this);
 	}
 
 	virtual void visit(const LingoDec::ThePropExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), "the ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), "the ");
 		ImGui::SameLine();
 		ImGui::Text(node.prop.c_str());
 		ImGui::SameLine();
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " of ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " of ");
 		ImGui::SameLine();
 
 		bool parenObj = (node.obj->type == LingoDec::kBinaryOpNode);
@@ -558,7 +558,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::MenuPropExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the %s of menu ", LingoDec::StandardNames::menuPropertyNames[node.prop]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the %s of menu ", LingoDec::StandardNames::menuPropertyNames[node.prop]);
 		ImGui::SameLine();
 
 		bool parenMenuID = (node.menuID->type == LingoDec::kBinaryOpNode);
@@ -574,7 +574,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::SoundCmdStmtNode &node) override {
-		write(node._startOffset, "sound ", _state->_colors._keyword_color);
+		write(node._startOffset, "sound ", _state->theme->keyword_color);
 		ImGui::SameLine();
 		ImGui::Text(node.cmd.c_str());
 		ImGui::SameLine();
@@ -587,7 +587,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::SoundPropExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the %s of sound ", LingoDec::StandardNames::soundPropertyNames[node.prop]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the %s of sound ", LingoDec::StandardNames::soundPropertyNames[node.prop]);
 		ImGui::SameLine();
 
 		bool parenSoundID = (node.soundID->type == LingoDec::kBinaryOpNode);
@@ -604,10 +604,10 @@ public:
 
 	virtual void visit(const LingoDec::AssignmentStmtNode &node) override {
 		if (!_dot) {
-			write(node._startOffset, "set ", _state->_colors._keyword_color);
+			write(node._startOffset, "set ", _state->theme->keyword_color);
 			ImGui::SameLine();
 			node.variable->accept(*this);
-			ImGui::TextColored(ImColor(_state->_colors._keyword_color), " to ");
+			ImGui::TextColored(ImColor(_state->theme->keyword_color), " to ");
 			ImGui::SameLine();
 			node.value->accept(*this);
 		} else {
@@ -620,11 +620,11 @@ public:
 	}
 
 	virtual void visit(const LingoDec::ExitRepeatStmtNode &node) override {
-		write(node._startOffset, "exit repeat", _state->_colors._keyword_color);
+		write(node._startOffset, "exit repeat", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::NextRepeatStmtNode &node) override {
-		write(node._startOffset, "next repeat", _state->_colors._keyword_color);
+		write(node._startOffset, "next repeat", _state->theme->keyword_color);
 	}
 
 	virtual void visit(const LingoDec::ObjBracketExprNode &node) override {
@@ -647,7 +647,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::SpritePropExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the %s of sprite ", LingoDec::StandardNames::spritePropertyNames[node.prop]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the %s of sprite ", LingoDec::StandardNames::spritePropertyNames[node.prop]);
 		ImGui::SameLine();
 
 		bool parenSpriteID = (node.spriteID->type == LingoDec::kBinaryOpNode);
@@ -663,19 +663,19 @@ public:
 	}
 
 	virtual void visit(const LingoDec::ChunkDeleteStmtNode &node) override {
-		write(node._startOffset, "delete", _state->_colors._keyword_color);
+		write(node._startOffset, "delete", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.chunk->accept(*this);
 	}
 
 	virtual void visit(const LingoDec::ChunkHiliteStmtNode &node) override {
-		write(node._startOffset, "hilite", _state->_colors._keyword_color);
+		write(node._startOffset, "hilite", _state->theme->keyword_color);
 		ImGui::SameLine();
 		node.chunk->accept(*this);
 	}
 
 	virtual void visit(const LingoDec::MenuItemPropExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the %s of menuItem ", LingoDec::StandardNames::menuItemPropertyNames[node.prop]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the %s of menuItem ", LingoDec::StandardNames::menuItemPropertyNames[node.prop]);
 		ImGui::SameLine();
 
 		bool parenItemID = (node.itemID->type == LingoDec::kBinaryOpNode);
@@ -689,7 +689,7 @@ public:
 			ImGui::SameLine();
 		}
 
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " of menu ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " of menu ");
 		ImGui::SameLine();
 
 		bool parenMenuID = (node.menuID->type == LingoDec::kBinaryOpNode);
@@ -733,7 +733,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::SpriteWithinExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), "sprite ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), "sprite ");
 		ImGui::SameLine();
 
 		bool parenFirstSprite = (node.firstSprite->type == LingoDec::kBinaryOpNode);
@@ -747,7 +747,7 @@ public:
 			ImGui::SameLine();
 		}
 
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " within ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " within ");
 		ImGui::SameLine();
 
 		bool parenSecondSprite = (node.secondSprite->type == LingoDec::kBinaryOpNode);
@@ -763,7 +763,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::LastStringChunkExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the last %s in ", LingoDec::StandardNames::chunkTypeNames[node.type]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the last %s in ", LingoDec::StandardNames::chunkTypeNames[node.type]);
 		ImGui::SameLine();
 
 		bool parenObj = (node.obj->type == LingoDec::kBinaryOpNode);
@@ -779,7 +779,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::SpriteIntersectsExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), "sprite ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), "sprite ");
 		ImGui::SameLine();
 
 		bool parenFirstSprite = (node.firstSprite->type == LingoDec::kBinaryOpNode);
@@ -793,7 +793,7 @@ public:
 			ImGui::SameLine();
 		}
 
-		ImGui::TextColored(ImColor(_state->_colors._keyword_color), " intersects ");
+		ImGui::TextColored(ImColor(_state->theme->keyword_color), " intersects ");
 		ImGui::SameLine();
 
 		bool parenSecondSprite = (node.secondSprite->type == LingoDec::kBinaryOpNode);
@@ -809,7 +809,7 @@ public:
 	}
 
 	virtual void visit(const LingoDec::StringChunkCountExprNode &node) override {
-		ImGui::TextColored(ImColor(_state->_colors._the_color), "the number of %ss in ", LingoDec::StandardNames::chunkTypeNames[node.type]);
+		ImGui::TextColored(ImColor(_state->theme->the_color), "the number of %ss in ", LingoDec::StandardNames::chunkTypeNames[node.type]);
 		ImGui::SameLine();
 
 		bool parenObj = (node.obj->type == LingoDec::kBinaryOpNode);
@@ -858,7 +858,7 @@ private:
 	void write(LingoDec::Datum &datum) {
 		switch (datum.type) {
 		case LingoDec::kDatumVoid:
-			ImGui::TextColored(_state->_colors._keyword_color, "VOID");
+			ImGui::TextColored(_state->theme->keyword_color, "VOID");
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumSymbol:
@@ -866,35 +866,35 @@ private:
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumVarRef:
-			ImGui::TextColored(_state->_colors._var_color, datum.s.c_str());
+			ImGui::TextColored(_state->theme->var_color, datum.s.c_str());
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumString:
 			if (datum.s.empty()) {
-				ImGui::TextColored(_state->_colors._keyword_color, "EMPTY");
+				ImGui::TextColored(_state->theme->keyword_color, "EMPTY");
 				ImGui::SameLine();
 				return;
 			}
 			if (datum.s.size() == 1) {
 				switch (datum.s[0]) {
 				case '\x03':
-					ImGui::TextColored(_state->_colors._keyword_color, "ENTER");
+					ImGui::TextColored(_state->theme->keyword_color, "ENTER");
 					ImGui::SameLine();
 					return;
 				case '\x08':
-					ImGui::TextColored(_state->_colors._keyword_color, "BACKSPACE");
+					ImGui::TextColored(_state->theme->keyword_color, "BACKSPACE");
 					ImGui::SameLine();
 					return;
 				case '\t':
-					ImGui::TextColored(_state->_colors._keyword_color, "TAB");
+					ImGui::TextColored(_state->theme->keyword_color, "TAB");
 					ImGui::SameLine();
 					return;
 				case '\r':
-					ImGui::TextColored(_state->_colors._keyword_color, "RETURN");
+					ImGui::TextColored(_state->theme->keyword_color, "RETURN");
 					ImGui::SameLine();
 					return;
 				case '"':
-					ImGui::TextColored(_state->_colors._keyword_color, "QUOTE");
+					ImGui::TextColored(_state->theme->keyword_color, "QUOTE");
 					ImGui::SameLine();
 					return;
 				default:
@@ -905,11 +905,11 @@ private:
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumInt:
-			ImGui::TextColored(_state->_colors._literal_color, "%d", datum.i);
+			ImGui::TextColored(_state->theme->literal_color, "%d", datum.i);
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumFloat:
-			ImGui::TextColored(_state->_colors._literal_color, "%g", datum.f);
+			ImGui::TextColored(_state->theme->literal_color, "%g", datum.f);
 			ImGui::SameLine();
 			return;
 		case LingoDec::kDatumList:
@@ -958,7 +958,7 @@ private:
 	}
 
 	void renderVar(const Common::String &varName) {
-		ImGui::TextColored(_state->_colors._var_color, "%s", varName.c_str());
+		ImGui::TextColored(_state->theme->var_color, "%s", varName.c_str());
 		if (ImGui::IsItemHovered() && g_lingo->_globalvars.contains(varName)) {
 			const Datum &val = g_lingo->_globalvars.getVal(varName);
 			ImGui::BeginTooltip();
@@ -987,9 +987,9 @@ private:
 		}
 
 		bool isMethod = _script.isMethod;
-		write(node._startOffset, isMethod ? "method " : "on ", _state->_colors._keyword_color);
+		write(node._startOffset, isMethod ? "method " : "on ", _state->theme->keyword_color);
 		ImGui::SameLine();
-		ImGui::TextColored(_state->_colors._call_color, "%s", _script.handlerId.c_str());
+		ImGui::TextColored(_state->theme->call_color, "%s", _script.handlerId.c_str());
 		ImGui::SameLine();
 
 		if (!_script.argumentNames.empty()) {
@@ -1019,7 +1019,7 @@ private:
 				if (i > 0)
 					ImGui::Text(",");
 				ImGui::SameLine();
-				ImGui::TextColored(_state->_colors._var_color, "%s", _script.propertyNames[i].c_str());
+				ImGui::TextColored(_state->theme->var_color, "%s", _script.propertyNames[i].c_str());
 				ImGui::SameLine();
 			}
 		}
@@ -1043,7 +1043,7 @@ private:
 		node.block->accept(*this);
 
 		if (!isMethod) {
-			write(node._endOffset, "end", _state->_colors._keyword_color);
+			write(node._endOffset, "end", _state->theme->keyword_color);
 		}
 	}
 
@@ -1116,7 +1116,10 @@ private:
 		}
 	}
 
-	void write(uint32 offset, const Common::String &code, ImVec4 color = ImVec4(1, 1, 1, 1)) {
+	void write(uint32 offset, const Common::String &code, ImVec4 color = ImVec4(-1, -1, -1, -1)) {
+		if (color.x < 0)
+			color = ImGui::ColorConvertU32ToFloat4(_state->theme->gridTextColor);
+
 		renderLine(offset);
 		renderIndentation();
 		ImGui::TextColored(color, "%s", code.c_str());
@@ -1157,10 +1160,10 @@ private:
 		const float width = ImGui::GetContentRegionAvail().x;
 		const ImVec2 mid(pos.x + 7, pos.y + 7);
 
-		ImVec4 color = _state->_colors._bp_color_disabled;
+		ImVec4 color = _state->theme->bp_color_disabled;
 		const Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
 		if (bp)
-			color = _state->_colors._bp_color_enabled;
+			color = _state->theme->bp_color_enabled;
 
 		// Need to give a new id for each button
 		Common::String id = _script.handlerId + _renderLineID;
@@ -1171,9 +1174,9 @@ private:
 
 		// click on breakpoint column?
 		if (ImGui::IsItemClicked(0)) {
-			if (color == _state->_colors._bp_color_enabled) {
+			if (color == _state->theme->bp_color_enabled) {
 				g_lingo->delBreakpoint(bp->id);
-				color = _state->_colors._bp_color_disabled;
+				color = _state->theme->bp_color_disabled;
 			} else {
 				Director::Breakpoint newBp;
 				newBp.type = kBreakpointFunction;
@@ -1181,32 +1184,32 @@ private:
 				newBp.funcName = _script.handlerId;
 				newBp.funcOffset = pc;
 				g_lingo->addBreakpoint(newBp);
-				color = _state->_colors._bp_color_enabled;
+				color = _state->theme->bp_color_enabled;
 			}
 		}
 
-		if (color == _state->_colors._bp_color_disabled && ImGui::IsItemHovered()) {
-			color = _state->_colors._bp_color_hover;
+		if (color == _state->theme->bp_color_disabled && ImGui::IsItemHovered()) {
+			color = _state->theme->bp_color_hover;
 		}
 
 		// draw breakpoint
 		if (!bp || bp->enabled)
 			dl->AddCircleFilled(mid, 4.0f, ImColor(color));
 		else
-			dl->AddCircle(mid, 4.0f, ImColor(_state->_colors._line_color));
+			dl->AddCircle(mid, 4.0f, ImColor(_state->theme->line_color));
 
 		// draw current statement
 		if (showCurrentStatement) {
-			dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
-			dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
+			dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->theme->current_statement));
+			dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->theme->current_statement));
 			if (_state->_dbg._scrollToPC && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
 				ImGui::SetScrollHereY(0.5f);
 				_state->_dbg._scrollToPC = false;
 			}
-			dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
+			dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), _state->theme->current_statement_bg, 0.4f);
 		}
 		// draw separator
-		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->_colors._line_color));
+		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->theme->line_color));
 
 		ImGui::SetItemTooltip("Click to add a breakpoint");
 		ImGui::SameLine();
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 46981eaf86d..2dd5a15189d 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -60,34 +60,34 @@ static void renderCastScript(Symbol &sym) {
 		const ImVec2 mid(pos.x + 7, pos.y + 7);
 		Common::String bpName = Common::String::format("%s-%d", handlerName.c_str(), pc);
 
-		color = _state->_colors._bp_color_disabled;
+		color = _state->theme->bp_color_disabled;
 
 		Director::Breakpoint *bp = getBreakpoint(handlerName, sym.ctx->_id, pc);
 		if (bp)
-			color = _state->_colors._bp_color_enabled;
+			color = _state->theme->bp_color_enabled;
 
 		ImGui::PushID(pc);
 		ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
 		if (ImGui::IsItemClicked(0)) {
 			if (bp) {
 				g_lingo->delBreakpoint(bp->id);
-				color = _state->_colors._bp_color_disabled;
+				color = _state->theme->bp_color_disabled;
 			} else {
 				Director::Breakpoint newBp;
 				newBp.type = kBreakpointFunction;
 				newBp.funcName = handlerName;
 				newBp.funcOffset = pc;
 				g_lingo->addBreakpoint(newBp);
-				color = _state->_colors._bp_color_enabled;
+				color = _state->theme->bp_color_enabled;
 			}
 		}
 
-		if (color == _state->_colors._bp_color_disabled && ImGui::IsItemHovered()) {
-			color = _state->_colors._bp_color_hover;
+		if (color == _state->theme->bp_color_disabled && ImGui::IsItemHovered()) {
+			color = _state->theme->bp_color_hover;
 		}
 
 		dl->AddCircleFilled(mid, 4.0f, ImColor(color));
-		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->_colors._line_color));
+		dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->theme->line_color));
 
 		ImGui::SetItemTooltip("Click to add a breakpoint");
 




More information about the Scummvm-git-logs mailing list