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

dreammaster noreply at scummvm.org
Wed Mar 16 05:29:46 UTC 2022


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

Summary:
6bf83c7f39 AGS: Removed Overlays' arbitrary limit
bde0988e08 AGS: fixed speech overlays drawn behind GUI
8c60e694cc AGS: Simplified SpriteListEntry use
d4e81c2ecb AGS: Moved irrelevant code out from draw_sprite_list()
2b7e671eb7 AGS: Remade VideoMemDDB class into BaseDDB, tidy ddb declarations
ccb87178d5 AGS: Simplified add_to_sprite_list() argument list
46f1f776c9 AGS: Sort overlays along with GUI
796c2dcd0e AGS: Overlay.ZOrder and use zorder for custom overlays
731db80bb4 AGS: Script API Overlay.Transparency
b07b63920a AGS: Serialize overlay.z and transparency


Commit: 6bf83c7f391548dad8a8c06f7277b42699b75508
    https://github.com/scummvm/scummvm/commit/6bf83c7f391548dad8a8c06f7277b42699b75508
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:36-07:00

Commit Message:
AGS: Removed Overlays' arbitrary limit

>From upstream 735dcfb14069b38aace4cef9468d44b63349d1bd

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/dynobj/script_overlay.cpp
    engines/ags/engine/ac/global_character.cpp
    engines/ags/engine/ac/global_overlay.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/overlay.h
    engines/ags/engine/ac/runtime_defines.h
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/game/savegame_v321.cpp
    engines/ags/engine/main/update.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 705639a4778..17247d1e723 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -707,7 +707,7 @@ ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx) {
 	if (ovri < 0)
 		quit("!SayBackground internal error: no overlay");
 
-	ScriptOverlay *scOver = create_scriptobj_for_overlay(_G(screenover)[ovri]);
+	ScriptOverlay *scOver = create_scriptobj_for_overlay(_GP(screenover)[ovri]);
 	scOver->borderHeight = 0;
 	scOver->borderWidth = 0;
 	scOver->isBackgroundSpeech = 1;
@@ -2265,14 +2265,13 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 	_G(said_speech_line) = 1;
 
-	int aa;
 	if (_GP(play).bgspeech_stay_on_display == 0) {
 		// remove any background speech
-		for (aa = 0; aa < _G(numscreenover); aa++) {
-			if (_G(screenover)[aa].timeout > 0) {
-				remove_screen_overlay(_G(screenover)[aa].type);
-				aa--;
-			}
+		for (size_t i = 0; i < _GP(screenover).size();) {
+			if (_GP(screenover)[i].timeout > 0)
+				remove_screen_overlay(_GP(screenover)[i].type);
+			else
+				i++;
 		}
 	}
 	_G(said_text) = 1;
@@ -2283,7 +2282,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 	int isPause = 1;
 	// if the message is all .'s, don't display anything
-	for (aa = 0; texx[aa] != 0; aa++) {
+	for (size_t aa = 0; texx[aa] != 0; aa++) {
 		if (texx[aa] != '.') {
 			isPause = 0;
 			break;
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 4734132dac1..62a7d458bec 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -258,7 +258,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	// we should not delete text_window_ds here, because it is now owned by Overlay
 
 	if (disp_type >= DISPLAYTEXT_NORMALOVERLAY) {
-		return _G(screenover)[nse].type;
+		return _GP(screenover)[nse].type;
 	}
 
 	//
@@ -346,10 +346,10 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 			_GP(play).messagetime = 2;
 
 		if (!overlayPositionFixed) {
-			_G(screenover)[nse].positionRelativeToScreen = false;
-			VpPoint vpt = _GP(play).GetRoomViewport(0)->ScreenToRoom(_G(screenover)[nse].x, _G(screenover)[nse].y, false);
-			_G(screenover)[nse].x = vpt.first.X;
-			_G(screenover)[nse].y = vpt.first.Y;
+			_GP(screenover)[nse].positionRelativeToScreen = false;
+			VpPoint vpt = _GP(play).GetRoomViewport(0)->ScreenToRoom(_GP(screenover)[nse].x, _GP(screenover)[nse].y, false);
+			_GP(screenover)[nse].x = vpt.first.X;
+			_GP(screenover)[nse].y = vpt.first.Y;
 		}
 
 		GameLoopUntilNoOverlay();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index fd26f053966..7cc060ae416 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1954,20 +1954,18 @@ void draw_fps(const Rect &viewport) {
 
 // Draw GUI and overlays of all kinds, anything outside the room space
 void draw_gui_and_overlays() {
-	int gg;
-
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
 		add_thing_to_draw(nullptr, AGSE_PREGUIDRAW, 0, TRANS_RUN_PLUGIN, false);
 
 	// draw overlays, except text boxes and portraits
-	for (gg = 0; gg < _G(numscreenover); gg++) {
+	for (const auto &over : _GP(screenover)) {
 		// complete overlay draw in non-transparent mode
-		if (_G(screenover)[gg].type == OVER_COMPLETE)
-			add_thing_to_draw(_G(screenover)[gg].bmp, _G(screenover)[gg].x, _G(screenover)[gg].y, TRANS_OPAQUE, false);
-		else if (_G(screenover)[gg].type != OVER_TEXTMSG && _G(screenover)[gg].type != OVER_PICTURE) {
+		if (over.type == OVER_COMPLETE)
+			add_thing_to_draw(over.bmp, over.x, over.y, TRANS_OPAQUE, false);
+		else if (over.type != OVER_TEXTMSG && over.type != OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(_G(screenover)[gg], &tdxp, &tdyp);
-			add_thing_to_draw(_G(screenover)[gg].bmp, tdxp, tdyp, 0, _G(screenover)[gg].hasAlphaChannel);
+			get_overlay_position(over, &tdxp, &tdyp);
+			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, over.hasAlphaChannel);
 		}
 	}
 
@@ -2024,7 +2022,7 @@ void draw_gui_and_overlays() {
 		}
 		_G(our_eip) = 38;
 		// Draw the GUIs
-		for (gg = 0; gg < _GP(game).numgui; gg++) {
+		for (int gg = 0; gg < _GP(game).numgui; gg++) {
 			aa = _GP(play).gui_draw_order[gg];
 			if (!_GP(guis)[aa].IsDisplayed()) continue;
 			if (_GP(guis)[aa].Transparency == 255) continue;
@@ -2045,11 +2043,11 @@ void draw_gui_and_overlays() {
 	}
 
 	// draw speech and portraits (so that they appear over GUIs)
-	for (gg = 0; gg < _G(numscreenover); gg++) {
-		if (_G(screenover)[gg].type == OVER_TEXTMSG || _G(screenover)[gg].type == OVER_PICTURE) {
+	for (const auto &over : _GP(screenover)) {
+		if (over.type == OVER_TEXTMSG || over.type == OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(_G(screenover)[gg], &tdxp, &tdyp);
-			add_thing_to_draw(_G(screenover)[gg].bmp, tdxp, tdyp, 0, false);
+			get_overlay_position(over, &tdxp, &tdyp);
+			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, false);
 		}
 	}
 
diff --git a/engines/ags/engine/ac/dynobj/script_overlay.cpp b/engines/ags/engine/ac/dynobj/script_overlay.cpp
index e6d887c31a0..f28cd5e3aa3 100644
--- a/engines/ags/engine/ac/dynobj/script_overlay.cpp
+++ b/engines/ags/engine/ac/dynobj/script_overlay.cpp
@@ -35,7 +35,7 @@ int ScriptOverlay::Dispose(const char *address, bool force) {
 	// with that handle later
 	int overlayIndex = find_overlay_of_type(overlayId);
 	if (overlayIndex >= 0) {
-		_G(screenover)[overlayIndex].associatedOverlayHandle = 0;
+		_GP(screenover)[overlayIndex].associatedOverlayHandle = 0;
 	}
 
 	// if this is being removed voluntarily (ie. pointer out of
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index d0756c7aa18..5f3e26687b0 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -548,20 +548,19 @@ void DisplaySpeechAt(int xx, int yy, int wii, int aschar, const char *spch) {
 
 int DisplaySpeechBackground(int charid, const char *speel) {
 	// remove any previous background speech for this character
-	int cc;
-	for (cc = 0; cc < _G(numscreenover); cc++) {
-		if (_G(screenover)[cc].bgSpeechForChar == charid) {
-			remove_screen_overlay_index(cc);
-			cc--;
-		}
+	for (size_t i = 0; i < _GP(screenover).size();) {
+		if (_GP(screenover)[i].bgSpeechForChar == charid)
+			remove_screen_overlay_index(i);
+		else
+			i++;
 	}
 
 	int ovrl = CreateTextOverlay(OVR_AUTOPLACE, charid, _GP(play).GetUIViewport().GetWidth() / 2, FONT_SPEECH,
 	                             -_GP(game).chars[charid].talkcolor, get_translation(speel), DISPLAYTEXT_NORMALOVERLAY);
 
 	int scid = find_overlay_of_type(ovrl);
-	_G(screenover)[scid].bgSpeechForChar = charid;
-	_G(screenover)[scid].timeout = GetTextDisplayTime(speel, 1);
+	_GP(screenover)[scid].bgSpeechForChar = charid;
+	_GP(screenover)[scid].timeout = GetTextDisplayTime(speel, 1);
 	return ovrl;
 }
 
diff --git a/engines/ags/engine/ac/global_overlay.cpp b/engines/ags/engine/ac/global_overlay.cpp
index 01466e9aa3a..c2c26a2cbbf 100644
--- a/engines/ags/engine/ac/global_overlay.cpp
+++ b/engines/ags/engine/ac/global_overlay.cpp
@@ -52,7 +52,7 @@ int CreateGraphicOverlay(int xx, int yy, int slott, int trans) {
 	wputblock(screeno, 0, 0, _GP(spriteset)[slott], trans);
 	bool hasAlpha = (_GP(game).SpriteInfos[slott].Flags & SPF_ALPHACHANNEL) != 0;
 	int nse = add_screen_overlay(xx, yy, OVER_CUSTOM, screeno, hasAlpha);
-	return _G(screenover)[nse].type;
+	return _GP(screenover)[nse].type;
 }
 
 int CreateTextOverlayCore(int xx, int yy, int wii, int fontid, int text_color, const char *text, int disp_type, int allowShrink) {
@@ -86,8 +86,8 @@ void MoveOverlay(int ovrid, int newx, int newy) {
 
 	int ovri = find_overlay_of_type(ovrid);
 	if (ovri < 0) quit("!MoveOverlay: invalid overlay ID specified");
-	_G(screenover)[ovri].x = newx;
-	_G(screenover)[ovri].y = newy;
+	_GP(screenover)[ovri].x = newx;
+	_GP(screenover)[ovri].y = newy;
 }
 
 int IsOverlayValid(int ovrid) {
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 7aa8743de39..af73beca9ec 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -54,8 +54,8 @@ void Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int text_color,
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!Overlay.SetText: invalid overlay ID specified");
-	int xx = game_to_data_coord(_G(screenover)[ovri].x) - scover->borderWidth;
-	int yy = game_to_data_coord(_G(screenover)[ovri].y) - scover->borderHeight;
+	int xx = game_to_data_coord(_GP(screenover)[ovri].x) - scover->borderWidth;
+	int yy = game_to_data_coord(_GP(screenover)[ovri].y) - scover->borderHeight;
 
 	RemoveOverlay(scover->overlayId);
 	const int disp_type = scover->overlayId;
@@ -70,7 +70,7 @@ int Overlay_GetX(ScriptOverlay *scover) {
 		quit("!invalid overlay ID specified");
 
 	int tdxp, tdyp;
-	get_overlay_position(_G(screenover)[ovri], &tdxp, &tdyp);
+	get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
 
 	return game_to_data_coord(tdxp);
 }
@@ -80,7 +80,7 @@ void Overlay_SetX(ScriptOverlay *scover, int newx) {
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
 
-	_G(screenover)[ovri].x = data_to_game_coord(newx);
+	_GP(screenover)[ovri].x = data_to_game_coord(newx);
 }
 
 int Overlay_GetY(ScriptOverlay *scover) {
@@ -89,7 +89,7 @@ int Overlay_GetY(ScriptOverlay *scover) {
 		quit("!invalid overlay ID specified");
 
 	int tdxp, tdyp;
-	get_overlay_position(_G(screenover)[ovri], &tdxp, &tdyp);
+	get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
 
 	return game_to_data_coord(tdyp);
 }
@@ -99,21 +99,21 @@ void Overlay_SetY(ScriptOverlay *scover, int newy) {
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
 
-	_G(screenover)[ovri].y = data_to_game_coord(newy);
+	_GP(screenover)[ovri].y = data_to_game_coord(newy);
 }
 
 int Overlay_GetWidth(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
-	return game_to_data_coord(_G(screenover)[ovri].pic->GetWidth());
+	return game_to_data_coord(_GP(screenover)[ovri].pic->GetWidth());
 }
 
 int Overlay_GetHeight(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
-	return game_to_data_coord(_G(screenover)[ovri].pic->GetHeight());
+	return game_to_data_coord(_GP(screenover)[ovri].pic->GetHeight());
 }
 
 int Overlay_GetValid(ScriptOverlay *scover) {
@@ -148,8 +148,8 @@ ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colo
 	sco->overlayId = CreateTextOverlayCore(x, y, width, font, colour, text, DISPLAYTEXT_NORMALOVERLAY, 0);
 
 	int ovri = find_overlay_of_type(sco->overlayId);
-	sco->borderWidth = game_to_data_coord(_G(screenover)[ovri].x - x);
-	sco->borderHeight = game_to_data_coord(_G(screenover)[ovri].y - y);
+	sco->borderWidth = game_to_data_coord(_GP(screenover)[ovri].x - x);
+	sco->borderHeight = game_to_data_coord(_GP(screenover)[ovri].y - y);
 	sco->isBackgroundSpeech = 0;
 
 	ccRegisterManagedObject(sco, sco);
@@ -194,8 +194,8 @@ static void dispose_overlay(ScreenOverlay &over) {
 		ccAttemptDisposeObject(over.associatedOverlayHandle);
 }
 
-void remove_screen_overlay_index(int over_idx) {
-	ScreenOverlay &over = _G(screenover)[over_idx];
+void remove_screen_overlay_index(size_t over_idx) {
+	ScreenOverlay &over = _GP(screenover)[over_idx];
 	// TODO: move these custom settings outside of this function
 	if (over.type == _GP(play).complete_overlay_on) {
 		_GP(play).complete_overlay_on = 0;
@@ -209,18 +209,16 @@ void remove_screen_overlay_index(int over_idx) {
 		_G(face_talking) = -1;
 	}
 	dispose_overlay(over);
-	_G(numscreenover)--;
-	for (int i = over_idx; i < _G(numscreenover); ++i)
-		_G(screenover)[i] = _G(screenover)[i + 1];
+	_GP(screenover).erase(_GP(screenover).begin() + over_idx);
 	// if an overlay before the sierra-style speech one is removed, update the index
 	// TODO: this is bad, need more generic system to store overlay references
-	if (_G(face_talking) > over_idx)
+	if ((size_t)_G(face_talking) > over_idx)
 		_G(face_talking)--;
 }
 
 void remove_screen_overlay(int type) {
-	for (int i = 0; i < _G(numscreenover);) {
-		if (type < 0 || _G(screenover)[i].type == type)
+	for (size_t i = 0; i < _GP(screenover).size();) {
+		if (type < 0 || _GP(screenover)[i].type == type)
 			remove_screen_overlay_index(i);
 		else
 			i++;
@@ -228,28 +226,27 @@ void remove_screen_overlay(int type) {
 }
 
 int find_overlay_of_type(int type) {
-	for (int i = 0; i < _G(numscreenover); ++i) {
-		if (_G(screenover)[i].type == type) return i;
+	for (size_t i = 0; i < _GP(screenover).size(); ++i) {
+		if (_GP(screenover)[i].type == type) return i;
 	}
 	return -1;
 }
 
-int add_screen_overlay(int x, int y, int type, Bitmap *piccy, bool alphaChannel) {
+size_t add_screen_overlay(int x, int y, int type, Bitmap *piccy, bool alphaChannel) {
 	return add_screen_overlay(x, y, type, piccy, 0, 0, alphaChannel);
 }
 
-int add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel) {
+size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel) {
 	if (type == OVER_CUSTOM) {
 		// find an unused custom ID; TODO: find a better approach!
-		for (int id = OVER_CUSTOM + 1; id < OVER_CUSTOM + 100; ++id) {
+		for (uint id = OVER_CUSTOM + 1; id <= _GP(screenover).size() + OVER_CUSTOM + 1; ++id) {
 			if (find_overlay_of_type(id) == -1) {
-				type = id;
-				break;
+				type = id; break;
 			}
 		}
 	}
 
-	ScreenOverlay &over = _G(screenover)[_G(numscreenover)++];
+	ScreenOverlay over;
 	over.pic = piccy;
 	over.bmp = _G(gfxDriver)->CreateDDBFromBitmap(piccy, alphaChannel);
 	over.x = x;
@@ -273,7 +270,9 @@ int add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_of
 	} else if (type == OVER_PICTURE) {
 		_GP(play).speech_face_scover = create_scriptobj_addref(over);
 	}
-	return _G(numscreenover) - 1;
+
+	_GP(screenover).push_back(std::move(over));
+	return _GP(screenover).size() - 1;
 }
 
 void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
@@ -319,13 +318,13 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
 }
 
 void recreate_overlay_ddbs() {
-	for (int i = 0; i < _G(numscreenover); ++i) {
-		if (_G(screenover)[i].bmp)
-			_G(gfxDriver)->DestroyDDB(_G(screenover)[i].bmp);
-		if (_G(screenover)[i].pic)
-			_G(screenover)[i].bmp = _G(gfxDriver)->CreateDDBFromBitmap(_G(screenover)[i].pic, false);
+	for (auto &over : _GP(screenover)) {
+		if (over.bmp)
+			_G(gfxDriver)->DestroyDDB(over.bmp);
+		if (over.pic)
+			over.bmp = _G(gfxDriver)->CreateDDBFromBitmap(over.pic, false);
 		else
-			_G(screenover)[i].bmp = nullptr;
+			over.bmp = nullptr;
 	}
 }
 
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index 8c181124db4..bd7f07bb72d 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -22,7 +22,6 @@
 #ifndef AGS_ENGINE_AC_OVERLAY_H
 #define AGS_ENGINE_AC_OVERLAY_H
 
-#include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/dynobj/script_overlay.h"
 
@@ -50,9 +49,9 @@ int  find_overlay_of_type(int type);
 void remove_screen_overlay(int type);
 // Calculates overlay position in screen coordinates
 void get_overlay_position(const ScreenOverlay &over, int *x, int *y);
-int  add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, bool alphaChannel = false);
-int  add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel = false);
-void remove_screen_overlay_index(int over_idx);
+size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, bool alphaChannel = false);
+size_t  add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel = false);
+void remove_screen_overlay_index(size_t over_idx);
 // Creates and registers a managed script object for existing overlay object
 ScriptOverlay *create_scriptobj_for_overlay(ScreenOverlay &over);
 void recreate_overlay_ddbs();
diff --git a/engines/ags/engine/ac/runtime_defines.h b/engines/ags/engine/ac/runtime_defines.h
index 78dddc288a7..76c8802e0a8 100644
--- a/engines/ags/engine/ac/runtime_defines.h
+++ b/engines/ags/engine/ac/runtime_defines.h
@@ -118,7 +118,6 @@ const int LegacyRoomVolumeFactor = 30;
 #define FOR_SCRIPT    2
 #define FOR_EXITLOOP  3
 #define CHMLSOFFS (MAX_ROOM_OBJECTS+1)    // reserve this many movelists for objects & stuff
-#define MAX_SCREEN_OVERLAYS 20
 #define abort_all_conditions _G(restrict_until)
 #define MAX_SCRIPT_AT_ONCE 10
 #define EVENT_NONE       0
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 23d559e83de..80f13a7504f 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -746,24 +746,23 @@ HSaveError ReadDynamicSprites(Stream *in, int32_t cmp_ver, const PreservedParams
 }
 
 HSaveError WriteOverlays(Stream *out) {
-	out->WriteInt32(_G(numscreenover));
-	for (int i = 0; i < _G(numscreenover); ++i) {
-		_G(screenover)[i].WriteToFile(out);
-		serialize_bitmap(_G(screenover)[i].pic, out);
+	out->WriteInt32(_GP(screenover).size());
+	for (const auto &over : _GP(screenover)) {
+		over.WriteToFile(out);
+		serialize_bitmap(over.pic, out);
 	}
 	return HSaveError::None();
 }
 
 HSaveError ReadOverlays(Stream *in, int32_t cmp_ver, const PreservedParams &pp, RestoredData &r_data) {
 	HSaveError err;
-	int over_count = in->ReadInt32();
-	if (!AssertCompatLimit(err, over_count, MAX_SCREEN_OVERLAYS, "overlays"))
-		return err;
-	_G(numscreenover) = over_count;
-	for (int i = 0; i < _G(numscreenover); ++i) {
-		_G(screenover)[i].ReadFromFile(in, cmp_ver);
-		if (_G(screenover)[i].hasSerializedBitmap)
-			_G(screenover)[i].pic = read_serialized_bitmap(in);
+	size_t over_count = in->ReadInt32();
+	for (size_t i = 0; i < over_count; ++i) {
+		ScreenOverlay over;
+		over.ReadFromFile(in, cmp_ver);
+		if (over.hasSerializedBitmap)
+			over.pic = read_serialized_bitmap(in);
+		_GP(screenover).push_back(over);
 	}
 	return err;
 }
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 815bffe669f..8e849caef7d 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -267,20 +267,21 @@ static void restore_game_ambientsounds(Stream *in, RestoredData &r_data) {
 	}
 }
 
-static void ReadOverlays_Aligned(Stream *in) {
+static void ReadOverlays_Aligned(Stream *in, size_t num_overs) {
 	AlignedStream align_s(in, Shared::kAligned_Read);
-	for (int i = 0; i < _G(numscreenover); ++i) {
-		_G(screenover)[i].ReadFromFile(&align_s, 0);
+	for (size_t i = 0; i < num_overs; ++i) {
+		_GP(screenover)[i].ReadFromFile(&align_s, 0);
 		align_s.Reset();
 	}
 }
 
 static void restore_game_overlays(Stream *in) {
-	_G(numscreenover) = in->ReadInt32();
-	ReadOverlays_Aligned(in);
-	for (int bb = 0; bb < _G(numscreenover); bb++) {
-		if (_G(screenover)[bb].hasSerializedBitmap)
-			_G(screenover)[bb].pic = read_serialized_bitmap(in);
+	size_t num_overs = in->ReadInt32();
+	_GP(screenover).resize(num_overs);
+	ReadOverlays_Aligned(in, num_overs);
+	for (size_t i = 0; i < num_overs; ++i) {
+		if (_GP(screenover)[i].hasSerializedBitmap)
+			_GP(screenover)[i].pic = read_serialized_bitmap(in);
 	}
 }
 
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index 2cab5a488d2..a927dbb9eb0 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -220,12 +220,15 @@ void update_following_exactly_characters(int &numSheep, int *followingAsSheep) {
 
 void update_overlay_timers() {
 	// update overlay timers
-	for (int aa = 0; aa < _G(numscreenover); aa++) {
-		if (_G(screenover)[aa].timeout > 0) {
-			_G(screenover)[aa].timeout--;
-			if (_G(screenover)[aa].timeout == 0)
-				remove_screen_overlay(_G(screenover)[aa].type);
+	for (size_t i = 0; i < _GP(screenover).size();) {
+		if (_GP(screenover)[i].timeout > 0) {
+			_GP(screenover)[i].timeout--;
+			if (_GP(screenover)[i].timeout == 0) {
+				remove_screen_overlay_index(i);
+				continue;
+			}
 		}
+		i++;
 	}
 }
 
@@ -390,14 +393,14 @@ void update_sierra_speech() {
 				if (_G(facetalk_qfg4_override_placement_y)) {
 					view_frame_y = _GP(play).speech_portrait_y;
 				} else {
-					view_frame_y = (_G(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
+					view_frame_y = (_GP(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
 				}
-				_G(screenover)[_G(face_talking)].pic->Clear(0);
+				_GP(screenover)[_G(face_talking)].pic->Clear(0);
 			} else {
-				_G(screenover)[_G(face_talking)].pic->ClearTransparent();
+				_GP(screenover)[_G(face_talking)].pic->ClearTransparent();
 			}
 
-			Bitmap *frame_pic = _G(screenover)[_G(face_talking)].pic;
+			Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].pic;
 			const ViewFrame *face_vf = &_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)];
 			bool face_has_alpha = (_GP(game).SpriteInfos[face_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
 			DrawViewFrame(frame_pic, face_vf, view_frame_x, view_frame_y);
@@ -409,7 +412,7 @@ void update_sierra_speech() {
 				DrawViewFrame(frame_pic, blink_vf, view_frame_x, view_frame_y, face_has_alpha);
 			}
 
-			_G(gfxDriver)->UpdateDDBFromBitmap(_G(screenover)[_G(face_talking)].bmp, _G(screenover)[_G(face_talking)].pic, face_has_alpha);
+			_G(gfxDriver)->UpdateDDBFromBitmap(_GP(screenover)[_G(face_talking)].bmp, _GP(screenover)[_G(face_talking)].pic, face_has_alpha);
 		}  // end if updatedFrame
 	}
 }
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 613366bda3b..2e42791721d 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -303,7 +303,7 @@ Globals::Globals() {
 	_mouse = new Mouse();
 
 	// overlay.cpp globals
-	_screenover = new ScreenOverlay[MAX_SCREEN_OVERLAYS];
+	_screenover = new std::vector<ScreenOverlay>();
 
 	// plugins globals
 	_engineExports = new Plugins::Core::EngineExports();
@@ -540,7 +540,7 @@ Globals::~Globals() {
 	delete _mouse;
 
 	// overlay.cpp globals
-	delete[] _screenover;
+	delete _screenover;
 
 	// plugins globals
 	delete _engineExports;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 18ed2a1d4ee..fff26b1577f 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1149,9 +1149,8 @@ public:
 	 * @{
 	 */
 
-	ScreenOverlay *_screenover;
+	std::vector<ScreenOverlay> *_screenover;
 	int _is_complete_overlay = 0;
-	int _numscreenover = 0;
 
 	/**@}*/
 


Commit: bde0988e0894d1a317e4111dc93a3107a90ac965
    https://github.com/scummvm/scummvm/commit/bde0988e0894d1a317e4111dc93a3107a90ac965
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:36-07:00

Commit Message:
AGS: fixed speech overlays drawn behind GUI

>From upstream d651448d16fd3a72d5ede24ee6ad4c87a7d3d7d1

Was broken by d7c091890d2cde07776cca4ebbed7352d379612d

Changed paths:
    engines/ags/engine/ac/draw.cpp


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 7cc060ae416..15832695fac 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1952,6 +1952,10 @@ void draw_fps(const Rect &viewport) {
 	invalidate_sprite_glob(1, yp, ddb);
 }
 
+static inline bool is_over_above_gui(int type) {
+	return type == OVER_TEXTMSG || type == OVER_PICTURE || type == OVER_TEXTSPEECH;
+}
+
 // Draw GUI and overlays of all kinds, anything outside the room space
 void draw_gui_and_overlays() {
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
@@ -1962,7 +1966,7 @@ void draw_gui_and_overlays() {
 		// complete overlay draw in non-transparent mode
 		if (over.type == OVER_COMPLETE)
 			add_thing_to_draw(over.bmp, over.x, over.y, TRANS_OPAQUE, false);
-		else if (over.type != OVER_TEXTMSG && over.type != OVER_PICTURE) {
+		else if (!is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
 			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, over.hasAlphaChannel);
@@ -2044,7 +2048,7 @@ void draw_gui_and_overlays() {
 
 	// draw speech and portraits (so that they appear over GUIs)
 	for (const auto &over : _GP(screenover)) {
-		if (over.type == OVER_TEXTMSG || over.type == OVER_PICTURE) {
+		if (is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
 			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, false);


Commit: 8c60e694cc814e0a4114fffe55181e7cdee0523f
    https://github.com/scummvm/scummvm/commit/8c60e694cc814e0a4114fffe55181e7cdee0523f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:37-07:00

Commit Message:
AGS: Simplified SpriteListEntry use

>From upstream 69a32a7a123e346f4ad724ed31f400f26d926280

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/draw.h
    engines/ags/engine/ac/runtime_defines.h
    engines/ags/engine/ac/sprite_list_entry.h
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 15832695fac..03ca6901eb4 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -77,14 +77,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-SpriteListEntry::SpriteListEntry()
-	: bmp(nullptr)
-	, pic(nullptr)
-	, baseline(0), x(0), y(0)
-	, transparent(0)
-	, takesPriorityIfEqual(false), hasAlphaChannel(false) {
-}
-
 void setpal() {
 	set_palette_range(_G(palette), 0, 255, 0);
 }
@@ -763,6 +755,57 @@ IDriverDependantBitmap *recycle_ddb_bitmap(IDriverDependantBitmap *bimp, Bitmap
 	return bimp;
 }
 
+//------------------------------------------------------------------------
+// Functions for filling the lists of sprites to render
+
+static void clear_draw_list() {
+	_GP(thingsToDrawList).clear();
+}
+
+static void add_thing_to_draw(IDriverDependantBitmap *bmp, int x, int y, int trans) {
+	SpriteListEntry sprite;
+	sprite.bmp = bmp;
+	sprite.x = x;
+	sprite.y = y;
+	sprite.transparent = trans;
+	_GP(thingsToDrawList).push_back(sprite);
+}
+
+static void add_render_stage(int stage) {
+	SpriteListEntry sprite;
+	sprite.renderStage = stage;
+	_GP(thingsToDrawList).push_back(sprite);
+}
+
+static void clear_sprite_list() {
+	_GP(sprlist).clear();
+}
+
+static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, bool isWalkBehind) {
+	if (spp == nullptr)
+		quit("add_to_sprite_list: attempted to draw NULL sprite");
+	// completely invisible, so don't draw it at all
+	if (trans == 255)
+		return;
+
+	SpriteListEntry sprite;
+	sprite.bmp = spp;
+	sprite.baseline = baseline;
+	sprite.x = xx;
+	sprite.y = yy;
+	sprite.transparent = trans;
+
+	if (_G(walkBehindMethod) == DrawAsSeparateSprite)
+		sprite.takesPriorityIfEqual = !isWalkBehind;
+	else
+		sprite.takesPriorityIfEqual = isWalkBehind;
+
+	_GP(sprlist).push_back(sprite);
+}
+
+//
+//------------------------------------------------------------------------
+
 void invalidate_cached_walkbehinds() {
 	memset(&_GP(actspswbcache)[0], 0, sizeof(CachedActSpsData) * _GP(actspswbcache).size());
 }
@@ -901,58 +944,10 @@ void sort_out_char_sprite_walk_behind(int actspsIndex, int xx, int yy, int basel
 	}
 
 	if (_GP(actspswbcache)[actspsIndex].isWalkBehindHere) {
-		add_to_sprite_list(_GP(actspswbbmp)[actspsIndex], xx, yy, basel, 0, -1, true);
+		add_to_sprite_list(_GP(actspswbbmp)[actspsIndex], xx, yy, basel, 0, true);
 	}
 }
 
-void clear_draw_list() {
-	_GP(thingsToDrawList).clear();
-}
-void add_thing_to_draw(IDriverDependantBitmap *bmp, int x, int y, int trans, bool alphaChannel) {
-	SpriteListEntry sprite;
-	sprite.pic = nullptr;
-	sprite.bmp = bmp;
-	sprite.x = x;
-	sprite.y = y;
-	sprite.transparent = trans;
-	sprite.hasAlphaChannel = alphaChannel;
-	_GP(thingsToDrawList).push_back(sprite);
-}
-
-// the sprite list is an intermediate list used to order
-// objects and characters by their baselines before everything
-// is added to the Thing To Draw List
-void clear_sprite_list() {
-	_GP(sprlist).clear();
-}
-void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, int sprNum, bool isWalkBehind) {
-
-	if (spp == nullptr)
-		quit("add_to_sprite_list: attempted to draw NULL sprite");
-	// completely invisible, so don't draw it at all
-	if (trans == 255)
-		return;
-
-	SpriteListEntry sprite;
-	if ((sprNum >= 0) && ((_GP(game).SpriteInfos[sprNum].Flags & SPF_ALPHACHANNEL) != 0))
-		sprite.hasAlphaChannel = true;
-	else
-		sprite.hasAlphaChannel = false;
-
-	sprite.bmp = spp;
-	sprite.baseline = baseline;
-	sprite.x = xx;
-	sprite.y = yy;
-	sprite.transparent = trans;
-
-	if (_G(walkBehindMethod) == DrawAsSeparateSprite)
-		sprite.takesPriorityIfEqual = !isWalkBehind;
-	else
-		sprite.takesPriorityIfEqual = isWalkBehind;
-
-	_GP(sprlist).push_back(sprite);
-}
-
 void repair_alpha_channel(Bitmap *dest, Bitmap *bgpic) {
 	// Repair the alpha channel, because sprites may have been drawn
 	// over it by the buttons, etc
@@ -1008,12 +1003,11 @@ bool spritelistentry_less(const SpriteListEntry &e1, const SpriteListEntry &e2)
 
 
 void draw_sprite_list() {
-
 	if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
 		for (int ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
 			if (_G(walkBehindBitmap)[ee] != nullptr) {
 				add_to_sprite_list(_G(walkBehindBitmap)[ee], _G(walkBehindLeft)[ee], _G(walkBehindTop)[ee],
-				                   _G(croom)->walkbehind_base[ee], 0, -1, true);
+				                   _G(croom)->walkbehind_base[ee], 0, true);
 			}
 		}
 	}
@@ -1021,7 +1015,7 @@ void draw_sprite_list() {
 	std::sort(_GP(sprlist).begin(), _GP(sprlist).end(), spritelistentry_less);
 
 	if (pl_any_want_hook(AGSE_PRESCREENDRAW))
-		add_thing_to_draw(nullptr, AGSE_PRESCREENDRAW, 0, TRANS_RUN_PLUGIN, false);
+		add_render_stage(AGSE_PRESCREENDRAW);
 
 	// copy the sorted sprites into the Things To Draw list
 	_GP(thingsToDrawList).insert(_GP(thingsToDrawList).end(), _GP(sprlist).begin(), _GP(sprlist).end());
@@ -1523,7 +1517,7 @@ void prepare_objects_for_drawing() {
 				_GP(actspsbmp)[useindx]->SetLightLevel(0);
 		}
 
-		add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, _G(objs)[aa].num);
+		add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, false);
 	}
 }
 
@@ -1815,7 +1809,7 @@ void prepare_characters_for_drawing() {
 		chin->actx = atxp;
 		chin->acty = atyp;
 
-		add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, sppic);
+		add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, false);
 	}
 }
 
@@ -1845,7 +1839,7 @@ void prepare_room_sprites() {
 				update_walk_behind_images();
 			}
 		}
-		add_thing_to_draw(_G(roomBackgroundBmp), 0, 0, 0, false);
+		add_thing_to_draw(_G(roomBackgroundBmp), 0, 0, 0);
 	}
 	_G(current_background_is_dirty) = false; // Note this is only place where this flag is checked
 
@@ -1959,17 +1953,17 @@ static inline bool is_over_above_gui(int type) {
 // Draw GUI and overlays of all kinds, anything outside the room space
 void draw_gui_and_overlays() {
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
-		add_thing_to_draw(nullptr, AGSE_PREGUIDRAW, 0, TRANS_RUN_PLUGIN, false);
+		add_render_stage(AGSE_PREGUIDRAW);
 
 	// draw overlays, except text boxes and portraits
 	for (const auto &over : _GP(screenover)) {
 		// complete overlay draw in non-transparent mode
 		if (over.type == OVER_COMPLETE)
-			add_thing_to_draw(over.bmp, over.x, over.y, TRANS_OPAQUE, false);
+			add_thing_to_draw(over.bmp, over.x, over.y, 0);
 		else if (!is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, over.hasAlphaChannel);
+			add_thing_to_draw(over.bmp, tdxp, tdyp, 0);
 		}
 	}
 
@@ -2037,7 +2031,7 @@ void draw_gui_and_overlays() {
 			        (_GP(guis)[aa].PopupStyle != kGUIPopupNoAutoRemove))
 				continue;
 
-			add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency, _GP(guis)[aa].HasAlphaChannel());
+			add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency);
 
 			// only poll if the interface is enabled (mouseovers should not
 			// work while in Wait state)
@@ -2051,7 +2045,7 @@ void draw_gui_and_overlays() {
 		if (is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, false);
+			add_thing_to_draw(over.bmp, tdxp, tdyp, 0);
 		}
 	}
 
@@ -2060,17 +2054,13 @@ void draw_gui_and_overlays() {
 
 // Push the gathered list of sprites into the active graphic renderer
 void put_sprite_list_on_screen(bool in_room) {
-	// *** Draw the Things To Draw List ***
-
-	SpriteListEntry *thisThing;
-
 	for (size_t i = 0; i < _GP(thingsToDrawList).size(); ++i) {
-		thisThing = &_GP(thingsToDrawList)[i];
+		const auto *thisThing = &_GP(thingsToDrawList)[i];
 
 		if (thisThing->bmp != nullptr) {
 			// mark the image's region as dirty
 			invalidate_sprite(thisThing->x, thisThing->y, thisThing->bmp, in_room);
-		} else if ((thisThing->transparent != TRANS_RUN_PLUGIN) &&
+		} else if ((thisThing->renderStage < 0) &&
 		           (thisThing->bmp == nullptr)) {
 			quit("Null pointer added to draw list");
 		}
@@ -2081,9 +2071,9 @@ void put_sprite_list_on_screen(bool in_room) {
 			}
 
 			_G(gfxDriver)->DrawSprite(thisThing->x, thisThing->y, thisThing->bmp);
-		} else if (thisThing->transparent == TRANS_RUN_PLUGIN) {
+		} else if (thisThing->renderStage >= 0) {
 			// meta entry to run the plugin hook
-			_G(gfxDriver)->DrawSprite(thisThing->x, thisThing->y, nullptr);
+			_G(gfxDriver)->DrawSprite(thisThing->renderStage, 0, nullptr);
 		} else
 			quit("Unknown entry in draw list");
 	}
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 9a5bccce96d..fd3b0342a49 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -127,7 +127,6 @@ void construct_engine_overlay();
 // Clears black game borders in legacy letterbox mode
 void clear_letterbox_borders();
 
-void add_to_sprite_list(Engine::IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, int sprNum, bool isWalkBehind = false);
 void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
 void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,
                                Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
diff --git a/engines/ags/engine/ac/runtime_defines.h b/engines/ags/engine/ac/runtime_defines.h
index 76c8802e0a8..c88fda4c634 100644
--- a/engines/ags/engine/ac/runtime_defines.h
+++ b/engines/ags/engine/ac/runtime_defines.h
@@ -139,11 +139,6 @@ const int LegacyRoomVolumeFactor = 30;
 
 #define MAX_PLUGIN_OBJECT_READERS 50
 
-#define TRANS_ALPHA_CHANNEL 20000
-#define TRANS_OPAQUE        20001
-#define TRANS_RUN_PLUGIN    20002
-
-
 #define LOCTYPE_HOTSPOT 1
 #define LOCTYPE_CHAR 2
 #define LOCTYPE_OBJ  3
diff --git a/engines/ags/engine/ac/sprite_list_entry.h b/engines/ags/engine/ac/sprite_list_entry.h
index aa59d981c91..382bf77c664 100644
--- a/engines/ags/engine/ac/sprite_list_entry.h
+++ b/engines/ags/engine/ac/sprite_list_entry.h
@@ -27,15 +27,16 @@
 namespace AGS3 {
 
 struct SpriteListEntry {
-	AGS::Engine::IDriverDependantBitmap *bmp;
-	AGS::Shared::Bitmap *pic;
-	int baseline;
-	int x, y;
-	int transparent;
-	bool takesPriorityIfEqual;
-	bool hasAlphaChannel;
-
-	SpriteListEntry();
+	Engine::IDriverDependantBitmap *bmp = nullptr;
+	AGS::Shared::Bitmap *pic = nullptr;
+	int transparent = 0;
+	int x = 0, y = 0;
+	int baseline = 0;
+	// Tells if this item should take priority during sort if z1 == z2
+	// TODO: this is some compatibility feature - find out if may be omited and done without extra struct?
+	bool takesPriorityIfEqual = false;
+	// Mark for the render stage callback (if >= 0 other fields are ignored)
+	int renderStage = -1;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index fff26b1577f..545a011b04a 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -559,8 +559,10 @@ public:
 	 */
 
 	std::vector<RoomCameraDrawData> *_CameraDrawData;
-	std::vector<SpriteListEntry> *_sprlist;
+	// Two lists of sprites to push into renderer during next render pass
+	// thingsToDrawList - is the main list, unsorted, drawn in the index order
 	std::vector<SpriteListEntry> *_thingsToDrawList;
+	std::vector<SpriteListEntry> *_sprlist;
 
 	AGS::Engine::IGraphicsDriver *_gfxDriver = nullptr;
 	AGS::Engine::IDriverDependantBitmap *_blankImage = nullptr;


Commit: d4e81c2ecb33ec52bf98ec4a8e7223b4a992ef1e
    https://github.com/scummvm/scummvm/commit/d4e81c2ecb33ec52bf98ec4a8e7223b4a992ef1e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:37-07:00

Commit Message:
AGS: Moved irrelevant code out from draw_sprite_list()

>From upstream 8c01d1f60449ab99c0ee09d29318214a2795d2dc

Changed paths:
    engines/ags/engine/ac/draw.cpp


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 03ca6901eb4..51e48246ad6 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -803,6 +803,23 @@ static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int
 	_GP(sprlist).push_back(sprite);
 }
 
+// function to sort the sprites into baseline order
+static bool spritelistentry_less(const SpriteListEntry &e1, const SpriteListEntry &e2) {
+	if (e1.baseline == e2.baseline) {
+		if (e1.takesPriorityIfEqual)
+			return false;
+		if (e2.takesPriorityIfEqual)
+			return true;
+	}
+	return e1.baseline < e2.baseline;
+}
+
+// copy the sorted sprites into the Things To Draw list
+static void draw_sprite_list() {
+	std::sort(_GP(sprlist).begin(), _GP(sprlist).end(), spritelistentry_less);
+	_GP(thingsToDrawList).insert(_GP(thingsToDrawList).end(), _GP(sprlist).begin(), _GP(sprlist).end());
+}
+
 //
 //------------------------------------------------------------------------
 
@@ -988,39 +1005,6 @@ void draw_gui_sprite_v330(Bitmap *ds, int pic, int x, int y, bool use_alpha, Ble
 	draw_gui_sprite(ds, pic, x, y, use_alpha && (_G(loaded_game_file_version) >= kGameVersion_330), blend_mode);
 }
 
-// function to sort the sprites into baseline order
-bool spritelistentry_less(const SpriteListEntry &e1, const SpriteListEntry &e2) {
-	if (e1.baseline == e2.baseline) {
-		if (e1.takesPriorityIfEqual)
-			return false;
-		if (e2.takesPriorityIfEqual)
-			return true;
-	}
-	return e1.baseline < e2.baseline;
-}
-
-
-
-
-void draw_sprite_list() {
-	if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
-		for (int ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
-			if (_G(walkBehindBitmap)[ee] != nullptr) {
-				add_to_sprite_list(_G(walkBehindBitmap)[ee], _G(walkBehindLeft)[ee], _G(walkBehindTop)[ee],
-				                   _G(croom)->walkbehind_base[ee], 0, true);
-			}
-		}
-	}
-
-	std::sort(_GP(sprlist).begin(), _GP(sprlist).end(), spritelistentry_less);
-
-	if (pl_any_want_hook(AGSE_PRESCREENDRAW))
-		add_render_stage(AGSE_PRESCREENDRAW);
-
-	// copy the sorted sprites into the Things To Draw list
-	_GP(thingsToDrawList).insert(_GP(thingsToDrawList).end(), _GP(sprlist).begin(), _GP(sprlist).end());
-}
-
 // Avoid freeing and reallocating the memory if possible
 Bitmap *recycle_bitmap(Bitmap *bimp, int coldep, int wid, int hit, bool make_transparent) {
 	if (bimp != nullptr) {
@@ -1851,6 +1835,19 @@ void prepare_room_sprites() {
 
 		if ((_G(debug_flags) & DBG_NODRAWSPRITES) == 0) {
 			_G(our_eip) = 34;
+
+			if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
+				for (int ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
+					if (_G(walkBehindBitmap)[ee] != nullptr) {
+						add_to_sprite_list(_G(walkBehindBitmap)[ee], _G(walkBehindLeft)[ee], _G(walkBehindTop)[ee],
+							_G(croom)->walkbehind_base[ee], 0, true);
+					}
+				}
+			}
+
+			if (pl_any_want_hook(AGSE_PRESCREENDRAW))
+				add_render_stage(AGSE_PRESCREENDRAW);
+
 			draw_sprite_list();
 		}
 	}


Commit: 2b7e671eb7cef6e03328b3db99c8cd79572ae5ab
    https://github.com/scummvm/scummvm/commit/2b7e671eb7cef6e03328b3db99c8cd79572ae5ab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:38-07:00

Commit Message:
AGS: Remade VideoMemDDB class into BaseDDB, tidy ddb declarations

>From upstream 6faef191c6f5728d0e10fd2ed29f3adb0013496c

Changed paths:
    engines/ags/engine/gfx/ali_3d_scummvm.cpp
    engines/ags/engine/gfx/ali_3d_scummvm.h
    engines/ags/engine/gfx/ddb.h
    engines/ags/engine/gfx/gfx_driver_base.cpp
    engines/ags/engine/gfx/gfx_driver_base.h


diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 90bf5ceee7a..876ede6e096 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -225,7 +225,7 @@ void ScummVMRendererGraphicsDriver::UpdateDDBFromBitmap(IDriverDependantBitmap *
 }
 
 void ScummVMRendererGraphicsDriver::DestroyDDB(IDriverDependantBitmap *bitmap) {
-	delete bitmap;
+	delete (ALSoftwareBitmap *)bitmap;
 }
 
 void ScummVMRendererGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) {
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index 24629259882..b0e02e51252 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -57,9 +57,8 @@ enum RendererFlip {
 	FLIP_VERTICAL = 0x00000002    /**< flip vertically */
 };
 
-class ALSoftwareBitmap : public IDriverDependantBitmap {
+class ALSoftwareBitmap : public BaseDDB {
 public:
-	// NOTE by CJ:
 	// Transparency is a bit counter-intuitive
 	// 0=not transparent, 255=invisible, 1..254 barely visible .. mostly visible
 	void SetTransparency(int transparency) override {
@@ -72,23 +71,12 @@ public:
 		_stretchToWidth = width;
 		_stretchToHeight = height;
 	}
-	int GetWidth() override {
-		return _width;
-	}
-	int GetHeight() override {
-		return _height;
-	}
-	int GetColorDepth() override {
-		return _colDepth;
-	}
 	void SetLightLevel(int lightLevel) override {
 	}
 	void SetTint(int red, int green, int blue, int tintSaturation) override {
 	}
 
 	Bitmap *_bmp;
-	int _width, _height;
-	int _colDepth;
 	bool _flipped;
 	int _stretchToWidth, _stretchToHeight;
 	bool _opaque; // no mask color
diff --git a/engines/ags/engine/gfx/ddb.h b/engines/ags/engine/gfx/ddb.h
index 6b4c7e1e5e0..a057221abd3 100644
--- a/engines/ags/engine/gfx/ddb.h
+++ b/engines/ags/engine/gfx/ddb.h
@@ -23,6 +23,10 @@
 //
 // Driver-dependant bitmap interface
 //
+// TODO: split into texture object that has only tex data
+// and object describing a drawing operation, with ref to texture and
+// drawing parameters (modes, shaders, etc).
+// Then we will also be able to share one texture among multiple game entities.
 //=============================================================================
 
 #ifndef AGS_ENGINE_GFX_DDB_H
@@ -34,17 +38,19 @@ namespace Engine {
 
 class IDriverDependantBitmap {
 public:
-	virtual ~IDriverDependantBitmap() {}
-
 	virtual void SetTransparency(int transparency) = 0;  // 0-255
 	virtual void SetFlippedLeftRight(bool isFlipped) = 0;
 	virtual void SetStretch(int width, int height, bool useResampler = true) = 0;
 	virtual void SetLightLevel(int light_level) = 0;   // 0-255
 	virtual void SetTint(int red, int green, int blue, int tintSaturation) = 0;  // 0-255
 
-	virtual int GetWidth() = 0;
-	virtual int GetHeight() = 0;
-	virtual int GetColorDepth() = 0;
+	virtual int GetWidth() const = 0;
+	virtual int GetHeight() const = 0;
+	virtual int GetColorDepth() const = 0;
+
+protected:
+	IDriverDependantBitmap() {}
+	virtual ~IDriverDependantBitmap() {}
 };
 
 } // namespace Engine
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index d8ba240c482..9f73ca50c41 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -292,7 +292,7 @@ __inline void get_pixel_if_not_transparent32(const unsigned int *pixel, unsigned
 	( (((a) & 0xFF) << _vmem_a_shift_32) | (((r) & 0xFF) << _vmem_r_shift_32) | (((g) & 0xFF) << _vmem_g_shift_32) | (((b) & 0xFF) << _vmem_b_shift_32) )
 
 
-void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
+void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
         char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering) {
 	const int src_depth = bitmap->GetColorDepth();
 	bool lastPixelWasTransparent = false;
@@ -409,7 +409,7 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
 	}
 }
 
-void VideoMemoryGraphicsDriver::BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
+void VideoMemoryGraphicsDriver::BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
         char *dst_ptr, const int dst_pitch) {
 	const int src_depth = bitmap->GetColorDepth();
 	for (int y = 0; y < tile->height; y++) {
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 3b762e08fcc..e872316a576 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -173,21 +173,26 @@ struct TextureTile {
 };
 
 // Parent class for the video memory DDBs
-class VideoMemDDB : public IDriverDependantBitmap {
+class BaseDDB : public IDriverDependantBitmap {
 public:
-	int GetWidth() override {
+	int GetWidth() const override {
 		return _width;
 	}
-	int GetHeight() override {
+	int GetHeight() const override {
 		return _height;
 	}
-	int GetColorDepth() override {
+	int GetColorDepth() const override {
 		return _colDepth;
 	}
 
-	int _width, _height;
-	int _colDepth;
-	bool _opaque; // no mask color
+	int _width = 0, _height = 0;
+	int _colDepth = 0;
+	bool _hasAlpha = false; // has meaningful alpha channel
+	bool _opaque = false;   // no mask color
+
+protected:
+	BaseDDB() {}
+	virtual ~BaseDDB() {}
 };
 
 // VideoMemoryGraphicsDriver - is the parent class for the graphic drivers
@@ -228,11 +233,11 @@ protected:
 	void DestroyFxPool();
 
 	// Prepares bitmap to be applied to the texture, copies pixels to the provided buffer
-	void BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
-	                      char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering);
+	void BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
+		char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering);
 	// Same but optimized for opaque source bitmaps which ignore transparent "mask color"
-	void BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile, const VideoMemDDB *target,
-	                            char *dst_ptr, const int dst_pitch);
+	void BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
+		char *dst_ptr, const int dst_pitch);
 
 	// Stage virtual screen is used to let plugins draw custom graphics
 	// in between render stages (between room and GUI, after GUI, and so on)


Commit: ccb87178d50fe2146124fbdffbc2b183da309a2b
    https://github.com/scummvm/scummvm/commit/ccb87178d50fe2146124fbdffbc2b183da309a2b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:38-07:00

Commit Message:
AGS: Simplified add_to_sprite_list() argument list

>From upstream 172466469dca450a05ba97fab85dcf747d344b02

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/sprite_list_entry.h
    engines/ags/engine/gfx/ali_3d_scummvm.h
    engines/ags/engine/gfx/ddb.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 51e48246ad6..5ae8ad72240 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -762,12 +762,11 @@ static void clear_draw_list() {
 	_GP(thingsToDrawList).clear();
 }
 
-static void add_thing_to_draw(IDriverDependantBitmap *bmp, int x, int y, int trans) {
+static void add_thing_to_draw(IDriverDependantBitmap *bmp, int x, int y) {
 	SpriteListEntry sprite;
 	sprite.bmp = bmp;
 	sprite.x = x;
 	sprite.y = y;
-	sprite.transparent = trans;
 	_GP(thingsToDrawList).push_back(sprite);
 }
 
@@ -781,11 +780,11 @@ static void clear_sprite_list() {
 	_GP(sprlist).clear();
 }
 
-static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, bool isWalkBehind) {
+static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int baseline, bool isWalkBehind) {
 	if (spp == nullptr)
 		quit("add_to_sprite_list: attempted to draw NULL sprite");
 	// completely invisible, so don't draw it at all
-	if (trans == 255)
+	if (spp->GetTransparency() == 255)
 		return;
 
 	SpriteListEntry sprite;
@@ -793,7 +792,6 @@ static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int
 	sprite.baseline = baseline;
 	sprite.x = xx;
 	sprite.y = yy;
-	sprite.transparent = trans;
 
 	if (_G(walkBehindMethod) == DrawAsSeparateSprite)
 		sprite.takesPriorityIfEqual = !isWalkBehind;
@@ -961,7 +959,7 @@ void sort_out_char_sprite_walk_behind(int actspsIndex, int xx, int yy, int basel
 	}
 
 	if (_GP(actspswbcache)[actspsIndex].isWalkBehindHere) {
-		add_to_sprite_list(_GP(actspswbbmp)[actspsIndex], xx, yy, basel, 0, true);
+		add_to_sprite_list(_GP(actspswbbmp)[actspsIndex], xx, yy, basel, true);
 	}
 }
 
@@ -1501,7 +1499,8 @@ void prepare_objects_for_drawing() {
 				_GP(actspsbmp)[useindx]->SetLightLevel(0);
 		}
 
-		add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, false);
+		_GP(actspsbmp)[useindx]->SetTransparency(_G(objs)[aa].transparent);
+		add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, false);
 	}
 }
 
@@ -1793,7 +1792,8 @@ void prepare_characters_for_drawing() {
 		chin->actx = atxp;
 		chin->acty = atyp;
 
-		add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, false);
+		_GP(actspsbmp)[useindx]->SetTransparency(chin->transparency);
+		add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, false);
 	}
 }
 
@@ -1823,7 +1823,7 @@ void prepare_room_sprites() {
 				update_walk_behind_images();
 			}
 		}
-		add_thing_to_draw(_G(roomBackgroundBmp), 0, 0, 0);
+		add_thing_to_draw(_G(roomBackgroundBmp), 0, 0);
 	}
 	_G(current_background_is_dirty) = false; // Note this is only place where this flag is checked
 
@@ -1840,7 +1840,7 @@ void prepare_room_sprites() {
 				for (int ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
 					if (_G(walkBehindBitmap)[ee] != nullptr) {
 						add_to_sprite_list(_G(walkBehindBitmap)[ee], _G(walkBehindLeft)[ee], _G(walkBehindTop)[ee],
-							_G(croom)->walkbehind_base[ee], 0, true);
+							_G(croom)->walkbehind_base[ee], true);
 					}
 				}
 			}
@@ -1956,11 +1956,11 @@ void draw_gui_and_overlays() {
 	for (const auto &over : _GP(screenover)) {
 		// complete overlay draw in non-transparent mode
 		if (over.type == OVER_COMPLETE)
-			add_thing_to_draw(over.bmp, over.x, over.y, 0);
+			add_thing_to_draw(over.bmp, over.x, over.y);
 		else if (!is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0);
+			add_thing_to_draw(over.bmp, tdxp, tdyp);
 		}
 	}
 
@@ -2028,7 +2028,8 @@ void draw_gui_and_overlays() {
 			        (_GP(guis)[aa].PopupStyle != kGUIPopupNoAutoRemove))
 				continue;
 
-			add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency);
+			_GP(guibgbmp)[aa]->SetTransparency(_GP(guis)[aa].Transparency);
+			add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y);
 
 			// only poll if the interface is enabled (mouseovers should not
 			// work while in Wait state)
@@ -2042,7 +2043,7 @@ void draw_gui_and_overlays() {
 		if (is_over_above_gui(over.type)) {
 			int tdxp, tdyp;
 			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0);
+			add_thing_to_draw(over.bmp, tdxp, tdyp);
 		}
 	}
 
@@ -2055,24 +2056,19 @@ void put_sprite_list_on_screen(bool in_room) {
 		const auto *thisThing = &_GP(thingsToDrawList)[i];
 
 		if (thisThing->bmp != nullptr) {
+			if (thisThing->bmp->GetTransparency() == 255)
+				continue; // skip completely invisible things
 			// mark the image's region as dirty
 			invalidate_sprite(thisThing->x, thisThing->y, thisThing->bmp, in_room);
-		} else if ((thisThing->renderStage < 0) &&
-		           (thisThing->bmp == nullptr)) {
-			quit("Null pointer added to draw list");
-		}
-
-		if (thisThing->bmp != nullptr) {
-			if (thisThing->transparent <= 255) {
-				thisThing->bmp->SetTransparency(thisThing->transparent);
-			}
 
+			// push to the graphics driver
 			_G(gfxDriver)->DrawSprite(thisThing->x, thisThing->y, thisThing->bmp);
 		} else if (thisThing->renderStage >= 0) {
 			// meta entry to run the plugin hook
 			_G(gfxDriver)->DrawSprite(thisThing->renderStage, 0, nullptr);
-		} else
-			quit("Unknown entry in draw list");
+		} else {
+			quit("Null pointer added to draw list");
+		}
 	}
 
 	_G(our_eip) = 1100;
diff --git a/engines/ags/engine/ac/sprite_list_entry.h b/engines/ags/engine/ac/sprite_list_entry.h
index 382bf77c664..bed6acc9d9b 100644
--- a/engines/ags/engine/ac/sprite_list_entry.h
+++ b/engines/ags/engine/ac/sprite_list_entry.h
@@ -29,7 +29,6 @@ namespace AGS3 {
 struct SpriteListEntry {
 	Engine::IDriverDependantBitmap *bmp = nullptr;
 	AGS::Shared::Bitmap *pic = nullptr;
-	int transparent = 0;
 	int x = 0, y = 0;
 	int baseline = 0;
 	// Tells if this item should take priority during sort if z1 == z2
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index b0e02e51252..07fa98ee01d 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -61,6 +61,9 @@ class ALSoftwareBitmap : public BaseDDB {
 public:
 	// Transparency is a bit counter-intuitive
 	// 0=not transparent, 255=invisible, 1..254 barely visible .. mostly visible
+	int  GetTransparency() const override {
+		return _transparency;
+	}
 	void SetTransparency(int transparency) override {
 		_transparency = transparency;
 	}
diff --git a/engines/ags/engine/gfx/ddb.h b/engines/ags/engine/gfx/ddb.h
index a057221abd3..2945d6bb93c 100644
--- a/engines/ags/engine/gfx/ddb.h
+++ b/engines/ags/engine/gfx/ddb.h
@@ -38,6 +38,7 @@ namespace Engine {
 
 class IDriverDependantBitmap {
 public:
+	virtual int  GetTransparency() const = 0;
 	virtual void SetTransparency(int transparency) = 0;  // 0-255
 	virtual void SetFlippedLeftRight(bool isFlipped) = 0;
 	virtual void SetStretch(int width, int height, bool useResampler = true) = 0;


Commit: 46f1f776c96fda3d9d55294813d03000c2cd951f
    https://github.com/scummvm/scummvm/commit/46f1f776c96fda3d9d55294813d03000c2cd951f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:38-07:00

Commit Message:
AGS: Sort overlays along with GUI

>From upstream 6b41b1f86ab2f6840c324d98e8e96ae5c61dad9f

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/sprite_list_entry.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 5ae8ad72240..137b1ac592f 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -780,7 +780,7 @@ static void clear_sprite_list() {
 	_GP(sprlist).clear();
 }
 
-static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int baseline, bool isWalkBehind) {
+static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int zorder, bool isWalkBehind) {
 	if (spp == nullptr)
 		quit("add_to_sprite_list: attempted to draw NULL sprite");
 	// completely invisible, so don't draw it at all
@@ -789,7 +789,7 @@ static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int
 
 	SpriteListEntry sprite;
 	sprite.bmp = spp;
-	sprite.baseline = baseline;
+	sprite.zorder = zorder;
 	sprite.x = xx;
 	sprite.y = yy;
 
@@ -801,15 +801,15 @@ static void add_to_sprite_list(IDriverDependantBitmap *spp, int xx, int yy, int
 	_GP(sprlist).push_back(sprite);
 }
 
-// function to sort the sprites into baseline order
+// function to sort the sprites into zorder order
 static bool spritelistentry_less(const SpriteListEntry &e1, const SpriteListEntry &e2) {
-	if (e1.baseline == e2.baseline) {
+	if (e1.zorder == e2.zorder) {
 		if (e1.takesPriorityIfEqual)
 			return false;
 		if (e2.takesPriorityIfEqual)
 			return true;
 	}
-	return e1.baseline < e2.baseline;
+	return e1.zorder < e2.zorder;
 }
 
 // copy the sorted sprites into the Things To Draw list
@@ -1952,20 +1952,23 @@ void draw_gui_and_overlays() {
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
 		add_render_stage(AGSE_PREGUIDRAW);
 
-	// draw overlays, except text boxes and portraits
-	for (const auto &over : _GP(screenover)) {
+	clear_sprite_list();
+
+	// Add active overlays to the sprite list
+	for (auto &over : _GP(screenover)) {
+		int tdxp, tdyp;
+		get_overlay_position(over, &tdxp, &tdyp);
 		// complete overlay draw in non-transparent mode
-		if (over.type == OVER_COMPLETE)
-			add_thing_to_draw(over.bmp, over.x, over.y);
-		else if (!is_over_above_gui(over.type)) {
-			int tdxp, tdyp;
-			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp);
+		if (over.type == OVER_COMPLETE) {
+			add_to_sprite_list(over.bmp, tdxp, tdyp, INT_MIN, false);
+		} else {
+			// draw speech and portraits over GUI and the rest under GUI
+			int zorder = is_over_above_gui(over.type) ? INT_MAX : INT_MIN;
+			add_to_sprite_list(over.bmp, tdxp, tdyp, zorder, false);
 		}
 	}
 
-	// Draw GUIs - they should always be on top of overlays like
-	// speech background text
+	// Add GUIs
 	_G(our_eip) = 35;
 	if (((_G(debug_flags) & DBG_NOIFACE) == 0) && (_G(displayed_room) >= 0)) {
 		int aa;
@@ -2029,7 +2032,7 @@ void draw_gui_and_overlays() {
 				continue;
 
 			_GP(guibgbmp)[aa]->SetTransparency(_GP(guis)[aa].Transparency);
-			add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y);
+			add_to_sprite_list(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].ZOrder, false);
 
 			// only poll if the interface is enabled (mouseovers should not
 			// work while in Wait state)
@@ -2038,14 +2041,8 @@ void draw_gui_and_overlays() {
 		}
 	}
 
-	// draw speech and portraits (so that they appear over GUIs)
-	for (const auto &over : _GP(screenover)) {
-		if (is_over_above_gui(over.type)) {
-			int tdxp, tdyp;
-			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp);
-		}
-	}
+	// sort and append ui sprites to the global draw things list
+	draw_sprite_list();
 
 	_G(our_eip) = 1099;
 }
@@ -2090,7 +2087,7 @@ void GfxDriverOnInitCallback(void *data) {
 static void construct_room_view() {
 	draw_preroom_background();
 	prepare_room_sprites();
-	// reset the Baselines Changed flag now that we've drawn stuff
+	// reset the zorders Changed flag now that we've drawn stuff
 	_G(walk_behind_baselines_changed) = 0;
 
 	for (const auto &viewport : _GP(play).GetRoomViewportsZOrdered()) {
diff --git a/engines/ags/engine/ac/sprite_list_entry.h b/engines/ags/engine/ac/sprite_list_entry.h
index bed6acc9d9b..3d6d061708a 100644
--- a/engines/ags/engine/ac/sprite_list_entry.h
+++ b/engines/ags/engine/ac/sprite_list_entry.h
@@ -30,7 +30,7 @@ struct SpriteListEntry {
 	Engine::IDriverDependantBitmap *bmp = nullptr;
 	AGS::Shared::Bitmap *pic = nullptr;
 	int x = 0, y = 0;
-	int baseline = 0;
+	int zorder = 0;
 	// Tells if this item should take priority during sort if z1 == z2
 	// TODO: this is some compatibility feature - find out if may be omited and done without extra struct?
 	bool takesPriorityIfEqual = false;


Commit: 796c2dcd0e6bcc9c51d1563bd96bb86851c2d6c5
    https://github.com/scummvm/scummvm/commit/796c2dcd0e6bcc9c51d1563bd96bb86851c2d6c5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:39-07:00

Commit Message:
AGS: Overlay.ZOrder and use zorder for custom overlays

>From upstream 4be229bfbfe808384cea8ea724d72fcd6a0ca094

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/screen_overlay.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 137b1ac592f..09377f1f3f6 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1943,10 +1943,6 @@ void draw_fps(const Rect &viewport) {
 	invalidate_sprite_glob(1, yp, ddb);
 }
 
-static inline bool is_over_above_gui(int type) {
-	return type == OVER_TEXTMSG || type == OVER_PICTURE || type == OVER_TEXTSPEECH;
-}
-
 // Draw GUI and overlays of all kinds, anything outside the room space
 void draw_gui_and_overlays() {
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
@@ -1958,14 +1954,7 @@ void draw_gui_and_overlays() {
 	for (auto &over : _GP(screenover)) {
 		int tdxp, tdyp;
 		get_overlay_position(over, &tdxp, &tdyp);
-		// complete overlay draw in non-transparent mode
-		if (over.type == OVER_COMPLETE) {
-			add_to_sprite_list(over.bmp, tdxp, tdyp, INT_MIN, false);
-		} else {
-			// draw speech and portraits over GUI and the rest under GUI
-			int zorder = is_over_above_gui(over.type) ? INT_MAX : INT_MIN;
-			add_to_sprite_list(over.bmp, tdxp, tdyp, zorder, false);
-		}
+		add_to_sprite_list(over.bmp, tdxp, tdyp, over.zorder, false);
 	}
 
 	// Add GUIs
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index af73beca9ec..fe51e692612 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -156,6 +156,22 @@ ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colo
 	return sco;
 }
 
+int Overlay_GetZOrder(ScriptOverlay *scover) {
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+
+	return _GP(screenover)[ovri].zorder;
+}
+
+void Overlay_SetZOrder(ScriptOverlay *scover, int zorder) {
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+
+	_GP(screenover)[ovri].zorder = zorder;
+}
+
 //=============================================================================
 
 // Creates and registers a managed script object for existing overlay object
@@ -253,6 +269,9 @@ size_t add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic
 	over.y = y;
 	over._offsetX = pic_offx;
 	over._offsetY = pic_offy;
+	// by default draw speech and portraits over GUI, and the rest under GUI
+	over.zorder = (type == OVER_TEXTMSG || type == OVER_PICTURE || type == OVER_TEXTSPEECH) ?
+		INT_MAX : INT_MIN;
 	over.type = type;
 	over.timeout = 0;
 	over.bgSpeechForChar = -1;
@@ -392,6 +411,14 @@ RuntimeScriptValue Sc_Overlay_GetHeight(void *self, const RuntimeScriptValue *pa
 	API_OBJCALL_INT(ScriptOverlay, Overlay_GetHeight);
 }
 
+RuntimeScriptValue Sc_Overlay_GetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_INT(ScriptOverlay, Overlay_GetZOrder);
+}
+
+RuntimeScriptValue Sc_Overlay_SetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetZOrder);
+}
+
 //=============================================================================
 //
 // Exclusive API for Plugins
@@ -417,6 +444,8 @@ void RegisterOverlayAPI() {
 	ccAddExternalObjectFunction("Overlay::set_Y", Sc_Overlay_SetY);
 	ccAddExternalObjectFunction("Overlay::get_Width", Sc_Overlay_GetWidth);
 	ccAddExternalObjectFunction("Overlay::get_Height", Sc_Overlay_GetHeight);
+	ccAddExternalObjectFunction("Overlay::get_ZOrder", Sc_Overlay_GetZOrder);
+	ccAddExternalObjectFunction("Overlay::set_ZOrder", Sc_Overlay_SetZOrder);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/screen_overlay.h b/engines/ags/engine/ac/screen_overlay.h
index 4160cd18063..24aefd47740 100644
--- a/engines/ags/engine/ac/screen_overlay.h
+++ b/engines/ags/engine/ac/screen_overlay.h
@@ -46,10 +46,11 @@ using namespace AGS; // FIXME later
 struct ScreenOverlay {
 	Engine::IDriverDependantBitmap *bmp = nullptr;
 	Shared::Bitmap *pic = nullptr;
+	bool hasAlphaChannel = false;
 	int type = 0, x = 0, y = 0, timeout = 0;
 	int bgSpeechForChar = 0;
 	int associatedOverlayHandle = 0;
-	bool hasAlphaChannel = false;
+	int zorder = INT_MIN;
 	bool positionRelativeToScreen = false;
 	bool hasSerializedBitmap = false;
 	int _offsetX = 0, _offsetY = 0;


Commit: 731db80bb467290a1602d32db238d41c70c44aff
    https://github.com/scummvm/scummvm/commit/731db80bb467290a1602d32db238d41c70c44aff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:39-07:00

Commit Message:
AGS: Script API Overlay.Transparency

>From upstream c2d63eb32ec9c8653f0b0b24f7a1b4e1fc24aa89

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/screen_overlay.h


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 09377f1f3f6..7e446775295 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1952,6 +1952,10 @@ void draw_gui_and_overlays() {
 
 	// Add active overlays to the sprite list
 	for (auto &over : _GP(screenover)) {
+		if (over.transparency == 255)
+			continue; // skip fully transparent
+		over.bmp->SetTransparency(over.transparency);
+
 		int tdxp, tdyp;
 		get_overlay_position(over, &tdxp, &tdyp);
 		add_to_sprite_list(over.bmp, tdxp, tdyp, over.zorder, false);
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 6e011ac4729..d5f3b50714e 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -192,12 +192,7 @@ void GUI_SetTransparency(ScriptGUI *tehgui, int trans) {
 }
 
 int GUI_GetTransparency(ScriptGUI *tehgui) {
-	if (_GP(guis)[tehgui->id].Transparency == 0)
-		return 0;
-	if (_GP(guis)[tehgui->id].Transparency == 255)
-		return 100;
-
-	return 100 - ((_GP(guis)[tehgui->id].Transparency * 10) / 25);
+	return GfxDef::LegacyTrans255ToTrans100(_GP(guis)[tehgui->id].Transparency);
 }
 
 void GUI_Centre(ScriptGUI *sgui) {
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index fe51e692612..2811fe99fa1 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -156,6 +156,24 @@ ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colo
 	return sco;
 }
 
+int Overlay_GetTransparency(ScriptOverlay *scover) {
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+
+	return GfxDef::LegacyTrans255ToTrans100(_GP(screenover)[ovri].transparency);
+}
+
+void Overlay_SetTransparency(ScriptOverlay *scover, int trans) {
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+	if ((trans < 0) | (trans > 100))
+		quit("!SetTransparency: transparency value must be between 0 and 100");
+
+	_GP(screenover)[ovri].transparency = GfxDef::Trans100ToLegacyTrans255(trans);
+}
+
 int Overlay_GetZOrder(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
@@ -411,6 +429,14 @@ RuntimeScriptValue Sc_Overlay_GetHeight(void *self, const RuntimeScriptValue *pa
 	API_OBJCALL_INT(ScriptOverlay, Overlay_GetHeight);
 }
 
+RuntimeScriptValue Sc_Overlay_GetTransparency(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_INT(ScriptOverlay, Overlay_GetTransparency);
+}
+
+RuntimeScriptValue Sc_Overlay_SetTransparency(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetTransparency);
+}
+
 RuntimeScriptValue Sc_Overlay_GetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_INT(ScriptOverlay, Overlay_GetZOrder);
 }
@@ -444,6 +470,8 @@ void RegisterOverlayAPI() {
 	ccAddExternalObjectFunction("Overlay::set_Y", Sc_Overlay_SetY);
 	ccAddExternalObjectFunction("Overlay::get_Width", Sc_Overlay_GetWidth);
 	ccAddExternalObjectFunction("Overlay::get_Height", Sc_Overlay_GetHeight);
+	ccAddExternalObjectFunction("Overlay::get_Transparency", Sc_Overlay_GetTransparency);
+	ccAddExternalObjectFunction("Overlay::set_Transparency", Sc_Overlay_SetTransparency);
 	ccAddExternalObjectFunction("Overlay::get_ZOrder", Sc_Overlay_GetZOrder);
 	ccAddExternalObjectFunction("Overlay::set_ZOrder", Sc_Overlay_SetZOrder);
 }
diff --git a/engines/ags/engine/ac/screen_overlay.h b/engines/ags/engine/ac/screen_overlay.h
index 24aefd47740..c40a0c8d2b2 100644
--- a/engines/ags/engine/ac/screen_overlay.h
+++ b/engines/ags/engine/ac/screen_overlay.h
@@ -54,6 +54,7 @@ struct ScreenOverlay {
 	bool positionRelativeToScreen = false;
 	bool hasSerializedBitmap = false;
 	int _offsetX = 0, _offsetY = 0;
+	int transparency = 0;
 
 	void ReadFromFile(Shared::Stream *in, int32_t cmp_ver);
 	void WriteToFile(Shared::Stream *out) const;


Commit: b07b63920a7977c36b7d47905e11e8e502512626
    https://github.com/scummvm/scummvm/commit/b07b63920a7977c36b7d47905e11e8e502512626
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-15T22:28:39-07:00

Commit Message:
AGS: Serialize overlay.z and transparency

>From upstream bb07262a81a57ca6abc700af178a06e4879abdc9

Changed paths:
    engines/ags/engine/ac/screen_overlay.cpp
    engines/ags/engine/game/savegame_components.cpp


diff --git a/engines/ags/engine/ac/screen_overlay.cpp b/engines/ags/engine/ac/screen_overlay.cpp
index 2de0404ca07..546610e854e 100644
--- a/engines/ags/engine/ac/screen_overlay.cpp
+++ b/engines/ags/engine/ac/screen_overlay.cpp
@@ -45,6 +45,12 @@ void ScreenOverlay::ReadFromFile(Stream *in, int32_t cmp_ver) {
 		_offsetX = in->ReadInt32();
 		_offsetY = in->ReadInt32();
 	}
+	if (cmp_ver >= 2) {
+		zorder = in->ReadInt32();
+		transparency = in->ReadInt32();
+		in->ReadInt32(); // reserve 2 ints
+		in->ReadInt32();
+	}
 }
 
 void ScreenOverlay::WriteToFile(Stream *out) const {
@@ -62,6 +68,11 @@ void ScreenOverlay::WriteToFile(Stream *out) const {
 	// since cmp_ver = 1
 	out->WriteInt32(_offsetX);
 	out->WriteInt32(_offsetY);
+	// since cmp_ver = 2
+	out->WriteInt32(zorder);
+	out->WriteInt32(transparency);
+	out->WriteInt32(0); // reserve 2 ints
+	out->WriteInt32(0);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 80f13a7504f..d8c687b0e4b 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -755,7 +755,6 @@ HSaveError WriteOverlays(Stream *out) {
 }
 
 HSaveError ReadOverlays(Stream *in, int32_t cmp_ver, const PreservedParams &pp, RestoredData &r_data) {
-	HSaveError err;
 	size_t over_count = in->ReadInt32();
 	for (size_t i = 0; i < over_count; ++i) {
 		ScreenOverlay over;
@@ -764,7 +763,7 @@ HSaveError ReadOverlays(Stream *in, int32_t cmp_ver, const PreservedParams &pp,
 			over.pic = read_serialized_bitmap(in);
 		_GP(screenover).push_back(over);
 	}
-	return err;
+	return HSaveError::None();
 }
 
 HSaveError WriteDynamicSurfaces(Stream *out) {
@@ -1071,7 +1070,7 @@ ComponentHandler ComponentHandlers[] = {
 	},
 	{
 		"Overlays",
-		1,
+		2,
 		0,
 		WriteOverlays,
 		ReadOverlays




More information about the Scummvm-git-logs mailing list