[Scummvm-git-logs] scummvm master -> 322fca8f2af48dc5c55f9fd0a6ba2fb82c9dac04

neuromancer noreply at scummvm.org
Sun Nov 9 13:17:02 UTC 2025


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

Summary:
322fca8f2a PRIVATE: allow to highlight decisions areas to make sure players can see them


Commit: 322fca8f2af48dc5c55f9fd0a6ba2fb82c9dac04
    https://github.com/scummvm/scummvm/commit/322fca8f2af48dc5c55f9fd0a6ba2fb82c9dac04
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-11-09T14:15:55+01:00

Commit Message:
PRIVATE: allow to highlight decisions areas to make sure players can see them

Changed paths:
    engines/private/detection.cpp
    engines/private/detection.h
    engines/private/metaengine.cpp
    engines/private/private.cpp
    engines/private/private.h


diff --git a/engines/private/detection.cpp b/engines/private/detection.cpp
index dc7def16fc3..e15a6b6a057 100644
--- a/engines/private/detection.cpp
+++ b/engines/private/detection.cpp
@@ -48,7 +48,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from the US release v1.0.0.23
@@ -58,7 +58,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye",  // EU release (UK)
@@ -68,7 +68,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_GRB,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from the EU release
@@ -78,7 +78,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_GRB,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from PCGamer Disc 2.6 JULY 1996 v1.0.0.12
@@ -88,7 +88,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Another demo
@@ -98,7 +98,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // EU release (ES)
@@ -108,7 +108,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::ES_ESP,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from the EU release (ES)
@@ -118,7 +118,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::ES_ESP,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // EU release (FR)
@@ -128,7 +128,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::FR_FRA,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // EU release (DE)
@@ -138,7 +138,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::DE_DEU,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from the EU release (DE)
@@ -148,7 +148,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::DE_DEU,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // Demo from the EU release (FR)
@@ -158,7 +158,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::FR_FRA,
 		Common::kPlatformWindows,
 		ADGF_DEMO,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye",  // RU release
@@ -168,7 +168,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::RU_RUS,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye",  // KO release
@@ -178,7 +178,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::KO_KOR,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye",  // JP release
@@ -188,7 +188,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::JA_JPN,
 		Common::kPlatformWindows,
 		ADGF_NO_FLAGS,
-		GUIO1(GUIO_NOMIDI)
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // MacOS release (US)
@@ -198,7 +198,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformMacintosh,
 		ADGF_NO_FLAGS,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // MacOS release (US) uninstalled
@@ -226,7 +226,7 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_USA,
 		Common::kPlatformMacintosh,
 		ADGF_DEMO,
-		GUIO2(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES)
+		GUIO3(GUIO_NOMIDI, GAMEOPTION_SFX_SUBTITLES, GAMEOPTION_HIGHLIGHT_MASKS)
 	},
 	{
 		"private-eye", // MacOS demo (US) uninstalled
diff --git a/engines/private/detection.h b/engines/private/detection.h
index 833ef07ae5e..7e0d803276d 100644
--- a/engines/private/detection.h
+++ b/engines/private/detection.h
@@ -2,5 +2,6 @@
 #define PRIVATE_DETECTION_H
 
 #define GAMEOPTION_SFX_SUBTITLES GUIO_GAMEOPTIONS1
+#define GAMEOPTION_HIGHLIGHT_MASKS GUIO_GAMEOPTIONS2
 
 #endif // PRIVATE_DETECTION_H
diff --git a/engines/private/metaengine.cpp b/engines/private/metaengine.cpp
index 07276a53dd7..e53a0b54422 100644
--- a/engines/private/metaengine.cpp
+++ b/engines/private/metaengine.cpp
@@ -42,6 +42,17 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 			0
 		}
 	},
+	{
+		GAMEOPTION_HIGHLIGHT_MASKS,
+		{
+			_s("Highlight decision areas"),
+			_s("Highlight clickable areas in decision scenes."),
+			"highlightMasks",
+			true,
+			0,
+			0
+		}
+	},
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
diff --git a/engines/private/private.cpp b/engines/private/private.cpp
index 14d302b985a..40e7cd42ee6 100644
--- a/engines/private/private.cpp
+++ b/engines/private/private.cpp
@@ -57,6 +57,7 @@ PrivateEngine::PrivateEngine(OSystem *syst, const ADGameDescription *gd)
 	  _subtitles(nullptr), _sfxSubtitles(false), _useSubtitles(false),
 	  _defaultCursor(nullptr),
 	  _screenW(640), _screenH(480) {
+	_highlightMasks = false;
 	_rnd = new Common::RandomSource("private");
 
 	// Global object for external reference
@@ -237,6 +238,9 @@ Common::Error PrivateEngine::run() {
 	if (!Common::parseBool(ConfMan.get("sfxSubtitles"), _sfxSubtitles))
 		warning("Failed to parse bool from sfxSubtitles options");
 
+	if (!Common::parseBool(ConfMan.get("highlightMasks"), _shouldHighlightMasks))
+		warning("Failed to parse bool from highlightMasks options");
+
 	if (!_useSubtitles && _sfxSubtitles) {
 		warning("SFX subtitles are enabled, but no subtitles will be shown");
 	}
@@ -502,6 +506,7 @@ void PrivateEngine::clearAreas() {
 
 	_exits.clear();
 	_masks.clear();
+	_highlightMasks = false;
 	_locationMasks.clear();
 	_memoryMasks.clear();
 
@@ -811,6 +816,7 @@ void PrivateEngine::selectExit(Common::Point mousePos) {
 	if (!ns.empty()) {
 		_numberClicks++; // count click only if it hits a hotspot
 		_nextSetting = ns;
+		_highlightMasks = false;
 	}
 }
 
@@ -846,6 +852,7 @@ void PrivateEngine::selectMask(Common::Point mousePos) {
 	if (!ns.empty()) {
 		_numberClicks++; // count click only if it hits a hotspot
 		_nextSetting = ns;
+		_highlightMasks = false;
 	}
 }
 
@@ -1938,6 +1945,9 @@ void PrivateEngine::loadMaskAndInfo(MaskInfo *m, const Common::String &name, int
 
 Graphics::Surface *PrivateEngine::loadMask(const Common::String &name, int x, int y, bool drawn) {
 	debugC(1, kPrivateDebugFunction, "%s(%s,%d,%d,%d)", __FUNCTION__, name.c_str(), x, y, drawn);
+	if (_shouldHighlightMasks && name.contains("\\decision\\"))
+		_highlightMasks = true;
+
 	MaskInfo m;
 	loadMaskAndInfo(&m, name, x, y, drawn);
 	return m.surf;
@@ -1947,6 +1957,42 @@ void PrivateEngine::drawMask(Graphics::Surface *surf) {
 	_compositeSurface->transBlitFrom(*surf, _origin, _transparentColor);
 }
 
+void drawCircle(Graphics::ManagedSurface *surface, int x, int y, int radius, int color) {
+	int cx = 0;
+	int cy = radius;
+	int df = 1 - radius;
+	int d_e = 3;
+	int d_se = -2 * radius + 5;
+
+	do {
+		surface->setPixel(x + cx, y + cy, color);
+		surface->setPixel(x - cx, y + cy, color);
+		surface->setPixel(x + cx, y - cy, color);
+		surface->setPixel(x - cx, y - cy, color);
+		surface->setPixel(x + cy, y + cx, color);
+		surface->setPixel(x - cy, y + cx, color);
+		surface->setPixel(x + cy, y - cx, color);
+		surface->setPixel(x - cy, y - cx, color);
+
+		if (df < 0) {
+			df += d_e;
+			d_e += 2;
+			d_se += 2;
+		} else {
+			df += d_se;
+			d_e += 2;
+			d_se += 4;
+			cy--;
+		}
+		cx++;
+	} while (cx <= cy);
+
+	for (int i = -radius; i <= radius; i++) {
+		surface->setPixel(x + i, y, color);
+		surface->setPixel(x, y + i, color);
+	}
+}
+
 void PrivateEngine::drawScreen() {
 	if (_videoDecoder && !_videoDecoder->isPaused()) {
 		const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
@@ -1975,6 +2021,47 @@ void PrivateEngine::drawScreen() {
 			drawScreenFrame((byte *) &newPalette);
 		}
 
+		if (_highlightMasks) {
+			byte redIndex = 0;
+			int min_dist = 1000 * 1000;
+			for (int i = 0; i < 256; ++i) {
+				int r = newPalette[i * 3 + 0];
+				int g = newPalette[i * 3 + 1];
+				int b = newPalette[i * 3 + 2];
+				int dist = (255 - r) * (255 - r) + g * g + b * b;
+				if (dist < min_dist) {
+					min_dist = dist;
+					redIndex = i;
+				}
+			}
+
+			for (MaskList::const_iterator it = _masks.begin(); it != _masks.end(); ++it) {
+				const MaskInfo &m = *it;
+				if (m.surf == nullptr) continue;
+
+				long sumX = 0;
+				long sumY = 0;
+				int count = 0;
+
+				for (int sx = 0; sx < m.surf->w; ++sx) {
+					for (int sy = 0; sy < m.surf->h; ++sy) {
+						if (m.surf->getPixel(sx, sy) != _transparentColor) {
+							sumX += sx;
+							sumY += sy;
+							count++;
+						}
+					}
+				}
+
+				if (count > 0) {
+					int centerX = sumX / count;
+					int centerY = sumY / count;
+
+					drawCircle(_compositeSurface, centerX + _origin.x, centerY + _origin.y, 7, redIndex);
+				}
+			}
+		}
+
 		Common::Rect w(_origin.x, _origin.y, _screenW - _origin.x, _screenH - _origin.y);
 		Graphics::Surface sa = _compositeSurface->getSubArea(w);
 		g_system->copyRectToScreen(sa.getPixels(), sa.pitch, _origin.x, _origin.y, sa.w, sa.h);
diff --git a/engines/private/private.h b/engines/private/private.h
index 666c5110a7e..0e9a23420db 100644
--- a/engines/private/private.h
+++ b/engines/private/private.h
@@ -174,6 +174,8 @@ private:
 	int _screenW, _screenH;
 
 public:
+	bool _shouldHighlightMasks;
+	bool _highlightMasks;
 	PrivateEngine(OSystem *syst, const ADGameDescription *gd);
 	~PrivateEngine();
 




More information about the Scummvm-git-logs mailing list