[Scummvm-git-logs] scummvm master -> 3370b6917c78e9d33d68f74e0c5fd8d48a35eb59

dreammaster dreammaster at scummvm.org
Sun Aug 8 02:38:00 UTC 2021


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

Summary:
3370b6917c AGS: Revert AGSFlashlight to more closely match original


Commit: 3370b6917c78e9d33d68f74e0c5fd8d48a35eb59
    https://github.com/scummvm/scummvm/commit/3370b6917c78e9d33d68f74e0c5fd8d48a35eb59
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-08-07T19:11:52-07:00

Commit Message:
AGS: Revert AGSFlashlight to more closely match original

The plugin previously had a bunch of hacks since the
AGS engine was rendering the screen at 32-bits rather than
16-bits the original was designed for. But with more recent
engine changes, the screen is 16-bits again. So I was able
to revert the hacks and return to the original code

Changed paths:
  A engines/ags/plugins/ags_flashlight/gfx.cpp
    engines/ags/module.mk
    engines/ags/plugins/ags_flashlight/ags_flashlight.cpp


diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 5fdbd157e5..e3f945268c 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -327,6 +327,7 @@ MODULE_OBJS = \
 	plugins/ags_creditz/drawing.o \
 	plugins/ags_fire/ags_fire.o \
 	plugins/ags_flashlight/ags_flashlight.o \
+	plugins/ags_flashlight/gfx.o \
 	plugins/ags_galaxy_steam/ags_wadjeteye_steam.o \
 	plugins/ags_galaxy_steam/ags_galaxy_steam.o \
 	plugins/ags_joy/ags_joy.o \
diff --git a/engines/ags/plugins/ags_flashlight/ags_flashlight.cpp b/engines/ags/plugins/ags_flashlight/ags_flashlight.cpp
index 89ac4da79b..19a49c0d82 100644
--- a/engines/ags/plugins/ags_flashlight/ags_flashlight.cpp
+++ b/engines/ags/plugins/ags_flashlight/ags_flashlight.cpp
@@ -98,369 +98,11 @@ int64 AGSFlashlight::AGS_EngineOnEvent(int event, NumberPtr data) {
 		// Get screen size once here.
 		_engine->GetScreenDimensions(&screen_width, &screen_height, &screen_color_depth);
 		_engine->UnrequestEventHook(AGSE_PRESCREENDRAW);
-
-		// Only 32 bit color depth is supported.
-		if (screen_color_depth != 32) {
-			_engine->UnrequestEventHook(AGSE_PREGUIDRAW);
-			_engine->UnrequestEventHook(AGSE_PRESCREENDRAW);
-			_engine->UnrequestEventHook(AGSE_SAVEGAME);
-			_engine->UnrequestEventHook(AGSE_RESTOREGAME);
-		}
 	}
 
 	return 0;
 }
 
-void AGSFlashlight::calc_x_n(uint32 x) {
-	flashlight_x = x;
-
-	flashlight_n = flashlight_x >> 24;
-
-	if (flashlight_n)
-		flashlight_n = (flashlight_n + 1) / 8;
-
-	flashlight_x = ((flashlight_x >> 19) & 0x001F) | ((flashlight_x >> 5) & 0x07E0) | ((flashlight_x << 8) & 0xF800);
-
-	flashlight_x = (flashlight_x | (flashlight_x << 16)) & 0x7E0F81F;
-}
-
-inline uint32 AGSFlashlight::_blender_alpha16_bgr(uint32 y) {
-	uint32 result;
-
-	y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F;
-
-	result = ((flashlight_x - y) * flashlight_n / 32 + y) & 0x7E0F81F;
-
-	return ((result & 0xFFFF) | (result >> 16));
-}
-
-inline void AGSFlashlight::setPixel(int x, int y, uint32 color, uint32 *pixel) {
-	if ((x >= g_DarknessDiameter) || (y >= g_DarknessDiameter) || (x < 0) || (y < 0))
-		return;
-
-	*(pixel + (y * g_DarknessDiameter) + x) = color;
-}
-
-void AGSFlashlight::plotCircle(int xm, int ym, int r, uint32 color) {
-	uint32 *pixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
-
-	int x = -r;
-	int y = 0;
-	int err = 2 - 2 * r;
-
-	do {
-		setPixel(xm - x, ym + y, color, pixel); //   I. Quadrant
-		setPixel(xm - x - 1, ym + y, color, pixel);
-
-		setPixel(xm - y, ym - x, color, pixel); // II. Quadrant
-		setPixel(xm - y, ym - x - 1, color, pixel);
-
-		setPixel(xm + x, ym - y, color, pixel); // III. Quadrant
-		setPixel(xm + x + 1, ym - y, color, pixel);
-
-		setPixel(xm + y, ym + x, color, pixel); //  IV. Quadrant
-		setPixel(xm + y, ym + x + 1, color, pixel);
-
-		r = err;
-		if (r > x)
-			err +=  ++x * 2 + 1;
-
-		if (r <= y)
-			err +=  ++y * 2 + 1;
-	} while (x < 0);
-
-	_engine->ReleaseBitmapSurface(g_LightBitmap);
-}
-
-void AGSFlashlight::ClipToRange(int &variable, int min, int max) {
-	if (variable < min)
-		variable = min;
-
-	if (variable > max)
-		variable = max;
-}
-
-void AGSFlashlight::AlphaBlendBitmap() {
-	uint32 *destpixel = (uint32 *)_engine->GetRawBitmapSurface(_engine->GetVirtualScreen());
-	uint32 *sourcepixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
-
-	uint32 *currentdestpixel = destpixel;
-	uint32 *currentsourcepixel = sourcepixel;
-
-	int x, y;
-
-	int targetX = (g_FlashlightDrawAtX > -1) ? g_FlashlightDrawAtX : 0;
-	int targetY = (g_FlashlightDrawAtY > -1) ? g_FlashlightDrawAtY : 0;
-
-	int startX = (g_FlashlightDrawAtX < 0) ? -1 * g_FlashlightDrawAtX : 0;
-	int endX = (g_FlashlightDrawAtX + g_DarknessDiameter < screen_width) ? g_DarknessDiameter : g_DarknessDiameter - ((g_FlashlightDrawAtX + g_DarknessDiameter) - screen_width);
-
-	int startY = (g_FlashlightDrawAtY < 0) ? -1 * g_FlashlightDrawAtY : 0;
-	int endY = (g_FlashlightDrawAtY + g_DarknessDiameter < screen_height) ? g_DarknessDiameter :  g_DarknessDiameter - ((g_FlashlightDrawAtY + g_DarknessDiameter) - screen_height);
-
-	for (y = 0; y < endY - startY; y++) {
-		currentdestpixel = destpixel + (y + targetY) * screen_width + targetX;
-		currentsourcepixel = sourcepixel + (y + startY) * g_DarknessDiameter + startX;
-
-		for (x = 0; x < endX - startX; x++) {
-			calc_x_n(*currentsourcepixel);
-			*currentdestpixel = (uint16)_blender_alpha16_bgr(*currentdestpixel);
-
-			currentdestpixel++;
-			currentsourcepixel++;
-		}
-	}
-
-	_engine->ReleaseBitmapSurface(_engine->GetVirtualScreen());
-	_engine->ReleaseBitmapSurface(g_LightBitmap);
-}
-
-void AGSFlashlight::DrawTint() {
-	int x, y;
-	BITMAP *screen = _engine->GetVirtualScreen();
-	uint16 *destpixel = (uint16 *)_engine->GetRawBitmapSurface(screen);
-
-	int32 red, blue, green, alpha;
-
-	for (y = 0; y < screen_height; y++) {
-		for (x = 0; x < screen_width; x++) {
-			_engine->GetRawColorComponents(16, *destpixel, &red, &green, &blue, &alpha);
-
-			if (g_RedTint != 0) {
-				red += g_RedTint * 8;
-				if (red > 255)
-					red = 255;
-				else if (red < 0)
-					red = 0;
-			}
-
-			if (g_BlueTint != 0) {
-				blue += g_BlueTint * 8;
-				if (blue > 255)
-					blue = 255;
-				else if (blue < 0)
-					blue = 0;
-			}
-
-			if (g_GreenTint != 0) {
-				green += g_GreenTint * 8;
-				if (green > 255)
-					green = 255;
-				else if (green < 0)
-					green = 0;
-			}
-
-			*destpixel = _engine->MakeRawColorPixel(16, red, green, blue, alpha);
-			destpixel++;
-		}
-	}
-
-	_engine->ReleaseBitmapSurface(screen);
-}
-
-#define DARKEN(VAL, SHIFT) (((int)(col >> SHIFT) & 255) * light / 255)
-
-uint32 AGSFlashlight::blendPixel(uint32 col, bool isAlpha24, int light) {
-	byte b0 = isAlpha24 ? DARKEN(col, 0) : (col & 0xff);
-	byte b1 = DARKEN(col, 8);
-	byte b2 = DARKEN(col, 16);
-	byte b3 = !isAlpha24 ? DARKEN(col, 24) : (col >> 24) & 0xff;
-
-	return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
-}
-
-
-void AGSFlashlight::DrawDarkness() {
-	int x, y;
-	BITMAP *screen = _engine->GetVirtualScreen();
-	const Graphics::PixelFormat &format = screen->format;
-	uint32 *destpixel = (uint32 *)_engine->GetRawBitmapSurface(screen);
-
-	int light = (int)((float)g_DarknessLightLevel * 2.55f);
-	uint32 color = format.ARGBToColor(255 - light, 0, 0, 0);
-	uint32 *currentpixel;
-
-	assert(format.aShift == 0 || format.aShift == 24);
-	bool isAlpha24 = format.aShift == 24;
-
-	calc_x_n(color);
-
-	if (g_DarknessSize == 0) {
-		// Whole screen.
-		for (x = 0; x < screen_width * screen_height; x++) {
-			*destpixel = blendPixel(*destpixel, isAlpha24, light);
-			destpixel++;
-		}
-	} else {
-		// Top.
-		if (g_FlashlightDrawAtY > -1) {
-			currentpixel = destpixel;
-			for (y = 0; y < g_FlashlightDrawAtY; y++) {
-				for (x = 0; x < screen_width; x++) {
-					*currentpixel = blendPixel(*currentpixel, isAlpha24, light);
-					currentpixel++;
-				}
-			}
-		}
-
-		// Bottom.
-		if (g_FlashlightDrawAtY + g_DarknessDiameter < screen_height) {
-			currentpixel = destpixel + (g_FlashlightDrawAtY + g_DarknessDiameter) * screen_width;
-			for (y = g_FlashlightDrawAtY + g_DarknessDiameter; y < screen_height; y++) {
-				for (x = 0; x < screen_width; x++) {
-					*currentpixel = blendPixel(*currentpixel, isAlpha24, light);
-					currentpixel++;
-				}
-			}
-		}
-
-		// Left.
-		if (g_FlashlightDrawAtX > 0) {
-			currentpixel = destpixel;
-			int startpoint = (g_FlashlightDrawAtY > 0) ? g_FlashlightDrawAtY : 0;
-			int endpoint = (g_FlashlightDrawAtY + g_DarknessDiameter >= screen_height) ? screen_height + 1 : g_FlashlightDrawAtY + g_DarknessDiameter + 1;
-			for (y = startpoint; y < endpoint; y++) {
-				for (x = 0; x < g_FlashlightDrawAtX; x++) {
-					*currentpixel = blendPixel(*currentpixel, isAlpha24, light);
-					currentpixel++;
-				}
-
-				currentpixel = destpixel + screen_width * y;
-			}
-		}
-
-		// Right.
-		if (g_FlashlightDrawAtX + g_DarknessDiameter < screen_width) {
-			currentpixel = destpixel + (g_FlashlightDrawAtX + g_DarknessDiameter);
-			int startpoint = (g_FlashlightDrawAtY > 0) ? g_FlashlightDrawAtY : 0;
-			int endpoint = (g_FlashlightDrawAtY + g_DarknessDiameter >= screen_height) ? screen_height + 1 : g_FlashlightDrawAtY + g_DarknessDiameter + 1;
-			for (y = startpoint; y < endpoint; y++) {
-				for (x = g_FlashlightDrawAtX + g_DarknessDiameter; x < screen_width; x++) {
-					*currentpixel = blendPixel(*currentpixel, isAlpha24, light);
-					currentpixel++;
-				}
-
-				currentpixel = destpixel + screen_width * y + (g_FlashlightDrawAtX + g_DarknessDiameter);
-			}
-		}
-	}
-
-	_engine->ReleaseBitmapSurface(screen);
-}
-
-void AGSFlashlight::CreateLightBitmap() {
-	if (g_DarknessSize == 0)
-		return;
-
-	if (g_LightBitmap)
-		_engine->FreeBitmap(g_LightBitmap);
-
-	g_LightBitmap = _engine->CreateBlankBitmap(g_DarknessDiameter, g_DarknessDiameter, 32);
-
-	// Fill with darkness color.
-	uint32 color = (255 - (int)((float)g_DarknessLightLevel * 2.55f)) << 24;
-	uint32 *pixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
-
-	int i;
-	for (i = 0; i < g_DarknessDiameter * g_DarknessDiameter; i++)
-		*pixel++ = (uint32)color;
-
-	// Draw light circle if wanted.
-	if (g_DarknessSize > 0) {
-		int current_value = 0;
-		color = (255 - (int)((float)g_BrightnessLightLevel * 2.55f));
-		uint32 targetcolor = ((255 - (int)((float)g_DarknessLightLevel * 2.55f)));
-
-		int increment = (targetcolor - color) / (g_DarknessSize - g_BrightnessSize);
-		float perfect_increment = (float)(targetcolor - color) / (float)(g_DarknessSize - g_BrightnessSize);
-
-		float error_term;
-
-		for (i = g_BrightnessSize; i < g_DarknessSize; i++) {
-			error_term = (perfect_increment * (i - g_BrightnessSize)) - current_value;
-
-			if (error_term >= 1.0f)
-				increment++;
-			else if (error_term <= -1.0f)
-				increment--;
-
-			current_value += increment;
-
-			if ((uint)current_value > targetcolor)
-				current_value = targetcolor;
-
-			plotCircle(g_DarknessSize, g_DarknessSize, i, (current_value << 24) + color);
-		}
-	}
-
-	// Draw inner fully lit circle.
-	if (g_BrightnessSize > 0) {
-		color = (255 - (int)((float)g_BrightnessLightLevel * 2.55f)) << 24;
-
-		for (i = 0; i < g_BrightnessSize; i++)
-			plotCircle(g_DarknessSize, g_DarknessSize, i, color);
-	}
-
-	_engine->ReleaseBitmapSurface(g_LightBitmap);
-}
-
-void AGSFlashlight::Update() {
-	if (g_BitmapMustBeUpdated) {
-		CreateLightBitmap();
-		g_BitmapMustBeUpdated = false;
-	}
-
-	if (g_FlashlightFollowMouse) {
-		_engine->GetMousePosition(&g_FlashlightX, &g_FlashlightY);
-	} else if (g_FollowCharacter != nullptr) {
-		g_FlashlightX = g_FollowCharacter->x + g_FollowCharacterDx;
-		g_FlashlightY = g_FollowCharacter->y + g_FollowCharacterDy;
-
-		if ((g_FollowCharacterHorz != 0) || (g_FollowCharacterVert != 0)) {
-			switch (g_FollowCharacter->loop) {
-			// Down
-			case 0:
-			case 4:
-			case 6:
-				g_FlashlightY += g_FollowCharacterVert;
-				break;
-
-			// Up
-			case 3:
-			case 5:
-			case 7:
-				g_FlashlightY -= g_FollowCharacterVert;
-				break;
-
-			// Left
-			case 1:
-				g_FlashlightX -= g_FollowCharacterHorz;
-				break;
-
-			// Right:
-			case 2:
-				g_FlashlightX += g_FollowCharacterHorz;
-				break;
-			}
-		}
-	}
-
-	g_FlashlightDrawAtX = g_FlashlightX - g_DarknessSize;
-	g_FlashlightDrawAtY = g_FlashlightY - g_DarknessSize;
-
-
-	if ((g_GreenTint != 0) || (g_RedTint != 0) || (g_BlueTint != 0))
-		DrawTint();
-
-	if (g_DarknessSize > 0)
-		AlphaBlendBitmap();
-
-	if (g_DarknessLightLevel != 100)
-		DrawDarkness();
-
-	_engine->MarkRegionDirty(0, 0, screen_width, screen_height);
-}
-
 void AGSFlashlight::syncGame(Serializer &s) {
 	uint32 SaveVersion = SaveMagic;
 	s.syncAsInt(SaveVersion);
@@ -497,10 +139,6 @@ void AGSFlashlight::syncGame(Serializer &s) {
 	}
 }
 
-// ********************************************
-// ************  AGS Interface  ***************
-// ********************************************
-
 void AGSFlashlight::SetFlashlightTint(ScriptMethodParams &params) {
 	PARAMS3(int, RedTint, int, GreenTint, int, BlueTint);
 	ClipToRange(RedTint, -31, 31);
diff --git a/engines/ags/plugins/ags_flashlight/gfx.cpp b/engines/ags/plugins/ags_flashlight/gfx.cpp
new file mode 100644
index 0000000000..ea110f764d
--- /dev/null
+++ b/engines/ags/plugins/ags_flashlight/gfx.cpp
@@ -0,0 +1,374 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/plugins/ags_flashlight/ags_flashlight.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace AGSFlashlight {
+
+void AGSFlashlight::calc_x_n(uint32 _x) {
+	flashlight_x = _x;
+
+	flashlight_n = flashlight_x >> 24;
+
+	if (flashlight_n)
+		flashlight_n = (flashlight_n + 1) / 8;
+
+	flashlight_x = ((flashlight_x >> 19) & 0x001F) | ((flashlight_x >> 5) & 0x07E0) | ((flashlight_x << 8) & 0xF800);
+
+	flashlight_x = (flashlight_x | (flashlight_x << 16)) & 0x7E0F81F;
+}
+
+
+uint32 AGSFlashlight::_blender_alpha16_bgr(uint32 y) {
+	uint32 result;
+
+	y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F;
+
+	result = ((flashlight_x - y) * flashlight_n / 32 + y) & 0x7E0F81F;
+
+	return ((result & 0xFFFF) | (result >> 16));
+}
+
+
+
+void AGSFlashlight::setPixel(int x, int y, uint32 color, uint32 *pixel) {
+	if ((x >= g_DarknessDiameter) || (y >= g_DarknessDiameter) || (x < 0) || (y < 0))
+		return;
+
+	*(pixel + (y * g_DarknessDiameter) + x) = color;
+}
+
+
+void AGSFlashlight::plotCircle(int xm, int ym, int r, uint32 color) {
+	uint32 *pixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
+
+	int x = -r;
+	int y = 0;
+	int err = 2 - 2 * r;
+
+	do {
+		setPixel(xm - x, ym + y, color, pixel); //   I. Quadrant 
+		setPixel(xm - x - 1, ym + y, color, pixel);
+
+		setPixel(xm - y, ym - x, color, pixel); // II. Quadrant
+		setPixel(xm - y, ym - x - 1, color, pixel);
+
+		setPixel(xm + x, ym - y, color, pixel); // III. Quadrant
+		setPixel(xm + x + 1, ym - y, color, pixel);
+
+		setPixel(xm + y, ym + x, color, pixel); //  IV. Quadrant
+		setPixel(xm + y, ym + x + 1, color, pixel);
+
+		r = err;
+		if (r > x)
+			err += ++x * 2 + 1;
+
+		if (r <= y)
+			err += ++y * 2 + 1;
+	} while (x < 0);
+
+	_engine->ReleaseBitmapSurface(g_LightBitmap);
+}
+
+
+void AGSFlashlight::ClipToRange(int &variable, int min, int max) {
+	if (variable < min)
+		variable = min;
+
+	if (variable > max)
+		variable = max;
+}
+
+
+void AGSFlashlight::AlphaBlendBitmap() {
+	uint16 *destpixel = (uint16 *)_engine->GetRawBitmapSurface(_engine->GetVirtualScreen());
+	uint32 *sourcepixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
+
+	uint16 *currentdestpixel = destpixel;
+	uint32 *currentsourcepixel = sourcepixel;
+
+	int x, y;
+
+	int targetX = (g_FlashlightDrawAtX > -1) ? g_FlashlightDrawAtX : 0;
+	int targetY = (g_FlashlightDrawAtY > -1) ? g_FlashlightDrawAtY : 0;
+
+	int startX = (g_FlashlightDrawAtX < 0) ? -1 * g_FlashlightDrawAtX : 0;
+	int endX = (g_FlashlightDrawAtX + g_DarknessDiameter < screen_width) ? g_DarknessDiameter : g_DarknessDiameter - ((g_FlashlightDrawAtX + g_DarknessDiameter) - screen_width);
+
+	int startY = (g_FlashlightDrawAtY < 0) ? -1 * g_FlashlightDrawAtY : 0;
+	int endY = (g_FlashlightDrawAtY + g_DarknessDiameter < screen_height) ? g_DarknessDiameter : g_DarknessDiameter - ((g_FlashlightDrawAtY + g_DarknessDiameter) - screen_height);
+
+	for (y = 0; y < endY - startY; y++) {
+		currentdestpixel = destpixel + (y + targetY) * screen_width + targetX;
+		currentsourcepixel = sourcepixel + (y + startY) * g_DarknessDiameter + startX;
+
+		for (x = 0; x < endX - startX; x++) {
+			calc_x_n(*currentsourcepixel);
+			*currentdestpixel = (uint16)_blender_alpha16_bgr(*currentdestpixel);
+
+			currentdestpixel++;
+			currentsourcepixel++;
+		}
+	}
+
+	_engine->ReleaseBitmapSurface(_engine->GetVirtualScreen());
+	_engine->ReleaseBitmapSurface(g_LightBitmap);
+}
+
+
+void AGSFlashlight::DrawTint() {
+	int x, y;
+	BITMAP *screen = _engine->GetVirtualScreen();
+	uint16 *destpixel = (uint16 *)_engine->GetRawBitmapSurface(screen);
+
+	int32 red, blue, green, alpha;
+
+	for (y = 0; y < screen_height; y++) {
+		for (x = 0; x < screen_width; x++) {
+			_engine->GetRawColorComponents(16, *destpixel, &red, &green, &blue, &alpha);
+
+			if (g_RedTint != 0) {
+				red += g_RedTint * 8;
+				if (red > 255)
+					red = 255;
+				else if (red < 0)
+					red = 0;
+			}
+
+			if (g_BlueTint != 0) {
+				blue += g_BlueTint * 8;
+				if (blue > 255)
+					blue = 255;
+				else if (blue < 0)
+					blue = 0;
+			}
+
+			if (g_GreenTint != 0) {
+				green += g_GreenTint * 8;
+				if (green > 255)
+					green = 255;
+				else if (green < 0)
+					green = 0;
+			}
+
+			*destpixel = _engine->MakeRawColorPixel(16, red, green, blue, alpha);
+			destpixel++;
+		}
+	}
+
+	_engine->ReleaseBitmapSurface(screen);
+}
+
+
+void AGSFlashlight::DrawDarkness() {
+	int x, y;
+	uint32 color = (255 - (int)((float)g_DarknessLightLevel * 2.55f)) << 24;
+	BITMAP *screen = _engine->GetVirtualScreen();
+	assert(screen->format.bytesPerPixel == 2);
+	uint16 *destpixel = (uint16 *)_engine->GetRawBitmapSurface(screen);
+	uint16 *currentpixel;
+
+	calc_x_n(color);
+
+	if (g_DarknessSize == 0) {
+		// Whole screen.
+		for (x = 0; x < screen_width * screen_height; x++) {
+			*destpixel = (uint16)_blender_alpha16_bgr(*destpixel);
+			destpixel++;
+		}
+	} else {
+		// Top.
+		if (g_FlashlightDrawAtY > -1) {
+			currentpixel = destpixel;
+			for (y = 0; y < g_FlashlightDrawAtY; y++) {
+				for (x = 0; x < screen_width; x++) {
+					*currentpixel = (uint16)_blender_alpha16_bgr(*currentpixel);
+					currentpixel++;
+				}
+			}
+		}
+
+		// Bottom.
+		if (g_FlashlightDrawAtY + g_DarknessDiameter < screen_height) {
+			currentpixel = destpixel + (g_FlashlightDrawAtY + g_DarknessDiameter) * screen_width;
+			for (y = g_FlashlightDrawAtY + g_DarknessDiameter; y < screen_height; y++) {
+				for (x = 0; x < screen_width; x++) {
+					*currentpixel = (uint16)_blender_alpha16_bgr(*currentpixel);
+					currentpixel++;
+				}
+			}
+		}
+
+		// Left.
+		if (g_FlashlightDrawAtX > 0) {
+			currentpixel = destpixel;
+			int startpoint = (g_FlashlightDrawAtY > 0) ? g_FlashlightDrawAtY : 0;
+			int endpoint = (g_FlashlightDrawAtY + g_DarknessDiameter >= screen_height) ? screen_height + 1 : g_FlashlightDrawAtY + g_DarknessDiameter + 1;
+			for (y = startpoint; y < endpoint; y++) {
+				for (x = 0; x < g_FlashlightDrawAtX; x++) {
+					*currentpixel = (uint16)_blender_alpha16_bgr(*currentpixel);
+					currentpixel++;
+				}
+
+				currentpixel = destpixel + screen_width * y;
+			}
+		}
+
+		// Right.
+		if (g_FlashlightDrawAtX + g_DarknessDiameter < screen_width) {
+			currentpixel = destpixel + (g_FlashlightDrawAtX + g_DarknessDiameter);
+			int startpoint = (g_FlashlightDrawAtY > 0) ? g_FlashlightDrawAtY : 0;
+			int endpoint = (g_FlashlightDrawAtY + g_DarknessDiameter >= screen_height) ? screen_height + 1 : g_FlashlightDrawAtY + g_DarknessDiameter + 1;
+			for (y = startpoint; y < endpoint; y++) {
+				for (x = g_FlashlightDrawAtX + g_DarknessDiameter; x < screen_width; x++) {
+					*currentpixel = (uint16)_blender_alpha16_bgr(*currentpixel);
+					currentpixel++;
+				}
+
+				currentpixel = destpixel + screen_width * y + (g_FlashlightDrawAtX + g_DarknessDiameter);
+			}
+		}
+	}
+
+	_engine->ReleaseBitmapSurface(screen);
+}
+
+
+void AGSFlashlight::CreateLightBitmap() {
+	if (g_DarknessSize == 0)
+		return;
+
+	if (g_LightBitmap)
+		_engine->FreeBitmap(g_LightBitmap);
+
+	g_LightBitmap = _engine->CreateBlankBitmap(g_DarknessDiameter, g_DarknessDiameter, 32);
+
+	// Fill with darkness color.
+	uint32 color = (255 - (int)((float)g_DarknessLightLevel * 2.55f)) << 24;
+	uint32 *pixel = (uint32 *)_engine->GetRawBitmapSurface(g_LightBitmap);
+
+	int i;
+	for (i = 0; i < g_DarknessDiameter * g_DarknessDiameter; i++)
+		*pixel++ = (uint32)color;
+
+	// Draw light circle if wanted.
+	if (g_DarknessSize > 0) {
+		uint32 current_value = 0;
+		color = (255 - (int)((float)g_BrightnessLightLevel * 2.55f));
+		uint32 targetcolor = ((255 - (int)((float)g_DarknessLightLevel * 2.55f)));
+
+		int increment = (targetcolor - color) / (g_DarknessSize - g_BrightnessSize);
+		float perfect_increment = (float)(targetcolor - color) / (float)(g_DarknessSize - g_BrightnessSize);
+
+		float error_term;
+
+		for (i = g_BrightnessSize; i < g_DarknessSize; i++) {
+			error_term = (perfect_increment * (i - g_BrightnessSize)) - current_value;
+
+			if (error_term >= 1.0f)
+				increment++;
+			else if (error_term <= -1.0f)
+				increment--;
+
+			current_value += increment;
+
+			if (current_value > targetcolor)
+				current_value = targetcolor;
+
+			plotCircle(g_DarknessSize, g_DarknessSize, i, (current_value << 24) + color);
+		}
+	}
+
+	// Draw inner fully lit circle.
+	if (g_BrightnessSize > 0) {
+		color = (255 - (int)((float)g_BrightnessLightLevel * 2.55f)) << 24;
+
+		for (i = 0; i < g_BrightnessSize; i++)
+			plotCircle(g_DarknessSize, g_DarknessSize, i, color);
+	}
+
+	_engine->ReleaseBitmapSurface(g_LightBitmap);
+}
+
+
+void AGSFlashlight::Update() {
+	if (g_BitmapMustBeUpdated) {
+		CreateLightBitmap();
+		g_BitmapMustBeUpdated = false;
+	}
+
+	if (g_FlashlightFollowMouse) {
+		_engine->GetMousePosition(&g_FlashlightX, &g_FlashlightY);
+	} else if (g_FollowCharacter != nullptr) {
+		g_FlashlightX = g_FollowCharacter->x + g_FollowCharacterDx;
+		g_FlashlightY = g_FollowCharacter->y + g_FollowCharacterDy;
+
+		if ((g_FollowCharacterHorz != 0) || (g_FollowCharacterVert != 0)) {
+			switch (g_FollowCharacter->loop) {
+				// Down
+			case 0:
+			case 4:
+			case 6:
+				g_FlashlightY += g_FollowCharacterVert;
+				break;
+
+				// Up
+			case 3:
+			case 5:
+			case 7:
+				g_FlashlightY -= g_FollowCharacterVert;
+				break;
+
+				// Left
+			case 1:
+				g_FlashlightX -= g_FollowCharacterHorz;
+				break;
+
+				// Right:
+			case 2:
+				g_FlashlightX += g_FollowCharacterHorz;
+				break;
+			}
+		}
+	}
+
+	g_FlashlightDrawAtX = g_FlashlightX - g_DarknessSize;
+	g_FlashlightDrawAtY = g_FlashlightY - g_DarknessSize;
+
+
+	if ((g_GreenTint != 0) || (g_RedTint != 0) || (g_BlueTint != 0))
+		DrawTint();
+
+	if (g_DarknessSize > 0)
+		AlphaBlendBitmap();
+
+	if (g_DarknessLightLevel != 100)
+		DrawDarkness();
+
+	_engine->MarkRegionDirty(0, 0, screen_width, screen_height);
+}
+
+} // namespace AGSFlashlight
+} // namespace Plugins
+} // namespace AGS3




More information about the Scummvm-git-logs mailing list