[Scummvm-git-logs] scummvm master -> 1607b2530bf3e43d5bd6636843821277978a8d0d

dreammaster noreply at scummvm.org
Sun May 8 18:39:43 UTC 2022


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

Summary:
3ac6998a98 AGS: Support Overlays not copying the image, but storing a sprite id
a8ebf2b41b AGS: Added "clone" parameter to Overlay.CreateGraphical()
f782f0f2b2 AGS: Implemented Overlay.Graphic
c143ceb01b AGS: Tidied and fixed InputBox to work with SDL2 input
a123a7473f AGS: Updated build version (3.6.0.25)
1607b2530b AGS: Fixed script errors when non-obligatory callbacks are missing


Commit: 3ac6998a98792b1b7835010707f56e45c0df0343
    https://github.com/scummvm/scummvm/commit/3ac6998a98792b1b7835010707f56e45c0df0343
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Support Overlays not copying the image, but storing a sprite id

>From upstream fd14bd4075bd9e6a577235f2434275b260250c46

Changed paths:
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/overlay.h
    engines/ags/engine/ac/screen_overlay.cpp
    engines/ags/engine/ac/screen_overlay.h
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/game/savegame_v321.cpp
    engines/ags/engine/main/update.cpp


diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 59c2a2c257d..5660172d894 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2114,13 +2114,13 @@ static void construct_overlays() {
 		if (has_changed) {
 			// For software mode - prepare transformed bitmap if necessary
 			Bitmap *use_bmp = is_software_mode ?
-				transform_sprite(over.pic, over.HasAlphaChannel(), _GP(overlaybmp)[i], Size(over.scaleWidth, over.scaleHeight)) :
-				over.pic;
+				transform_sprite(over.GetImage(), over.HasAlphaChannel(), _GP(overlaybmp)[i], Size(over.scaleWidth, over.scaleHeight)) :
+				over.GetImage();
 
 			if ((_G(walkBehindMethod) == DrawOverCharSprite) && over.IsRoomLayer()) {
 				if (use_bmp != _GP(overlaybmp)[i].get()) {
-					recycle_bitmap(_GP(overlaybmp)[i], over.pic->GetColorDepth(), over.pic->GetWidth(), over.pic->GetHeight(), true);
-					_GP(overlaybmp)[i]->Blit(over.pic);
+					recycle_bitmap(_GP(overlaybmp)[i], use_bmp->GetColorDepth(), use_bmp->GetWidth(), use_bmp->GetHeight(), true);
+					_GP(overlaybmp)[i]->Blit(use_bmp);
 				}
 				Point pos = get_overlay_position(over);
 				walkbehinds_cropout(_GP(overlaybmp)[i].get(), pos.X, pos.Y, over.zorder);
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index dbe8a6daef6..39e30e30a58 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -126,14 +126,14 @@ int Overlay_GetGraphicWidth(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
-	return game_to_data_coord(_GP(screenover)[ovri].pic->GetWidth());
+	return game_to_data_coord(_GP(screenover)[ovri].GetImage()->GetWidth());
 }
 
 int Overlay_GetGraphicHeight(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
-	return game_to_data_coord(_GP(screenover)[ovri].pic->GetHeight());
+	return game_to_data_coord(_GP(screenover)[ovri].GetImage()->GetHeight());
 }
 
 void Overlay_SetScaledSize(ScreenOverlay &over, int width, int height) {
@@ -177,11 +177,17 @@ int Overlay_GetValid(ScriptOverlay *scover) {
 
 ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent) {
 	data_to_game_coords(&x, &y);
-	Bitmap *screeno = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[slot].Width, _GP(game).SpriteInfos[slot].Height, _GP(game).GetColorDepth());
-	screeno->Blit(_GP(spriteset)[slot], 0, 0, transparent ? kBitmap_Transparency : kBitmap_Copy);
-	size_t nse = add_screen_overlay(room_layer, x, y, OVER_CUSTOM, screeno,
-		(_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
-	return nse < SIZE_MAX ? &_GP(screenover)[nse] : nullptr;
+	size_t overid;
+	// We clone only dynamic sprites, because it makes no sense to clone normal ones
+	if ((_GP(game).SpriteInfos[slot].Flags & SPF_DYNAMICALLOC) != 0) {
+		Bitmap *screeno = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[slot].Width, _GP(game).SpriteInfos[slot].Height, _GP(game).GetColorDepth());
+		screeno->Blit(_GP(spriteset)[slot], 0, 0, transparent ? kBitmap_Transparency : kBitmap_Copy);
+		overid = add_screen_overlay(room_layer, x, y, OVER_CUSTOM, screeno,
+			(_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
+	} else {
+		overid = add_screen_overlay(room_layer, x, y, OVER_CUSTOM, slot);
+	}
+	return overid < SIZE_MAX ? &_GP(screenover)[overid] : nullptr;
 }
 
 ScreenOverlay *Overlay_CreateTextCore(bool room_layer, int x, int y, int width, int font, int text_color,
@@ -276,8 +282,7 @@ static void invalidate_and_subref(ScreenOverlay &over, ScriptOverlay **scover) {
 
 // Frees overlay resources and tell to dispose script object if there are no refs left
 static void dispose_overlay(ScreenOverlay &over) {
-	delete over.pic;
-	over.pic = nullptr;
+	over.SetImage(nullptr);
 	if (over.ddb != nullptr)
 		_G(gfxDriver)->DestroyDDB(over.ddb);
 	over.ddb = nullptr;
@@ -326,12 +331,8 @@ int find_overlay_of_type(int type) {
 	}
 	return -1;
 }
-
-size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy, bool alphaChannel) {
-	return add_screen_overlay(roomlayer, x, y, type, piccy, 0, 0, alphaChannel);
-}
-
-size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel) {
+size_t add_screen_overlay_impl(bool roomlayer, int x, int y, int type, int sprnum, Bitmap *piccy,
+	int pic_offx, int pic_offy, bool has_alpha) {
 	if (type == OVER_CUSTOM) {
 		// find an unused custom ID; TODO: find a better approach!
 		for (int id = OVER_CUSTOM + 1; (size_t)id <= _GP(screenover).size() + OVER_CUSTOM + 1; ++id) {
@@ -340,16 +341,21 @@ size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy,
 			}
 		}
 	}
-
 	ScreenOverlay over;
-	over.pic = piccy;
+	if (piccy) {
+		over.SetImage(piccy);
+		over.SetAlphaChannel(has_alpha);
+	} else {
+		over.SetSpriteNum(sprnum);
+		over.SetAlphaChannel((_GP(game).SpriteInfos[sprnum].Flags & SPF_ALPHACHANNEL) != 0);
+	}
 	over.ddb = nullptr; // is generated during first draw pass
 	over.x = x;
 	over.y = y;
 	over.offsetX = pic_offx;
 	over.offsetY = pic_offy;
-	over.scaleWidth = piccy->GetWidth();
-	over.scaleHeight = piccy->GetHeight();
+	over.scaleWidth = over.GetImage()->GetWidth();
+	over.scaleHeight = over.GetImage()->GetHeight();
 	// by default draw speech and portraits over GUI, and the rest under GUI
 	over.zorder = (roomlayer || type == OVER_TEXTMSG || type == OVER_PICTURE || type == OVER_TEXTSPEECH) ?
 		INT_MAX : INT_MIN;
@@ -357,7 +363,6 @@ size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy,
 	over.timeout = 0;
 	over.bgSpeechForChar = -1;
 	over.associatedOverlayHandle = 0;
-	over.SetAlphaChannel(alphaChannel);
 	over.SetRoomLayer(roomlayer);
 	// TODO: move these custom settings outside of this function
 	if (type == OVER_COMPLETE) _GP(play).complete_overlay_on = type;
@@ -370,12 +375,23 @@ size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy,
 	} else if (type == OVER_PICTURE) {
 		_GP(play).speech_face_scover = create_scriptoverlay(over, true);
 	}
-
 	over.MarkChanged();
 	_GP(screenover).push_back(std::move(over));
 	return _GP(screenover).size() - 1;
 }
 
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, int sprnum) {
+	return add_screen_overlay_impl(roomlayer, x, y, type, sprnum, nullptr, 0, 0, false);
+}
+
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Bitmap *piccy, bool has_alpha) {
+	return add_screen_overlay_impl(roomlayer, x, y, type, -1, piccy, 0, 0, has_alpha);
+}
+
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool has_alpha) {
+	return add_screen_overlay_impl(roomlayer, x, y, type, -1, piccy, pic_offx, pic_offy, has_alpha);
+}
+
 Point get_overlay_position(const ScreenOverlay &over) {
 	if (over.IsRoomLayer()) {
 		return Point(over.x + over.offsetX, over.y + over.offsetY);
@@ -392,16 +408,17 @@ Point get_overlay_position(const ScreenOverlay &over) {
 		Point screenpt = view->RoomToScreen(
 			data_to_game_coord(_GP(game).chars[charid].x),
 			data_to_game_coord(_GP(game).chars[charid].get_effective_y()) - height).first;
-		int tdxp = MAX(0, screenpt.X - over.pic->GetWidth() / 2);
+		Bitmap *pic = over.GetImage();
+		int tdxp = std::max(0, screenpt.X - pic->GetWidth() / 2);
 		int tdyp = screenpt.Y - get_fixed_pixel_size(5);
-		tdyp -= over.pic->GetHeight();
-		tdyp = MAX(5, tdyp);
+		tdyp -= pic->GetHeight();
+		tdyp = std::max(5, tdyp);
 
-		if ((tdxp + over.pic->GetWidth()) >= ui_view.GetWidth())
-			tdxp = (ui_view.GetWidth() - over.pic->GetWidth()) - 1;
+		if ((tdxp + pic->GetWidth()) >= ui_view.GetWidth())
+			tdxp = (ui_view.GetWidth() - pic->GetWidth()) - 1;
 		if (_GP(game).chars[charid].room != _G(displayed_room)) {
-			tdxp = ui_view.GetWidth() / 2 - over.pic->GetWidth() / 2;
-			tdyp = ui_view.GetHeight() / 2 - over.pic->GetHeight() / 2;
+			tdxp = ui_view.GetWidth() / 2 - pic->GetWidth() / 2;
+			tdyp = ui_view.GetHeight() / 2 - pic->GetHeight() / 2;
 		}
 		return Point(tdxp, tdyp);
 	} else {
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index 48d277b07bd..4bc2fdf6b9c 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -53,8 +53,9 @@ int  find_overlay_of_type(int type);
 void remove_screen_overlay(int type);
 // Calculates overlay position in its respective layer (screen or room)
 Point get_overlay_position(const ScreenOverlay &over);
-size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Shared::Bitmap *piccy, bool alphaChannel = false);
-size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool alphaChannel = false);
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, int sprnum);
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Shared::Bitmap *piccy, bool has_alpha);
+size_t add_screen_overlay(bool roomlayer, int x, int y, int type, Shared::Bitmap *piccy, int pic_offx, int pic_offy, bool has_alpha);
 void remove_screen_overlay_index(size_t over_idx);
 // Creates and registers a managed script object for // Creates and registers a managed script object for existing overlay object;
 // optionally adds an internal engine reference to prevent object's disposal
diff --git a/engines/ags/engine/ac/screen_overlay.cpp b/engines/ags/engine/ac/screen_overlay.cpp
index 928aa3c9385..1727d95b169 100644
--- a/engines/ags/engine/ac/screen_overlay.cpp
+++ b/engines/ags/engine/ac/screen_overlay.cpp
@@ -19,18 +19,39 @@
  *
  */
 
+#include "ags/lib/std/utility.h"
 #include "ags/engine/ac/screen_overlay.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/shared/util/stream.h"
+#include "ags/globals.h"
 
 namespace AGS3 {
 
-using AGS::Shared::Stream;
+using namespace AGS::Shared;
+
+Bitmap *ScreenOverlay::GetImage() const {
+	return IsSpriteReference() ?
+		_GP(spriteset)[_sprnum] :
+		_pic.get();
+}
+
+void ScreenOverlay::SetImage(Shared::Bitmap *pic) {
+	_flags &= ~kOver_SpriteReference;
+	_pic.reset(pic);
+	_sprnum = -1;
+}
+
+void ScreenOverlay::SetSpriteNum(int sprnum) {
+	_flags |= kOver_SpriteReference;
+	_pic.reset();
+	_sprnum = sprnum;
+}
 
 void ScreenOverlay::ReadFromFile(Stream *in, bool &has_bitmap, int32_t cmp_ver) {
-	pic = nullptr;
+	_pic.reset();
 	ddb = nullptr;
 	in->ReadInt32(); // ddb 32-bit pointer value (nasty legacy format)
-	has_bitmap = in->ReadInt32() != 0;
+	int pic = in->ReadInt32();
 	type = in->ReadInt32();
 	x = in->ReadInt32();
 	y = in->ReadInt32();
@@ -56,11 +77,22 @@ void ScreenOverlay::ReadFromFile(Stream *in, bool &has_bitmap, int32_t cmp_ver)
 		scaleWidth = in->ReadInt32();
 		scaleHeight = in->ReadInt32();
 	}
+
+	if (_flags & kOver_SpriteReference) {
+		_sprnum = pic;
+		has_bitmap = false;
+	} else {
+		_sprnum = -1;
+		has_bitmap = pic != 0;
+	}
 }
 
 void ScreenOverlay::WriteToFile(Stream *out) const {
 	out->WriteInt32(0); // ddb 32-bit pointer value (nasty legacy format)
-	out->WriteInt32(pic ? 1 : 0); // has bitmap
+	if (_flags & kOver_SpriteReference)
+		out->WriteInt32(_sprnum); // sprite reference
+	else
+		out->WriteInt32(_pic ? 1 : 0); // has bitmap
 	out->WriteInt32(type);
 	out->WriteInt32(x);
 	out->WriteInt32(y);
diff --git a/engines/ags/engine/ac/screen_overlay.h b/engines/ags/engine/ac/screen_overlay.h
index 2425f98be8b..f38f730dcd9 100644
--- a/engines/ags/engine/ac/screen_overlay.h
+++ b/engines/ags/engine/ac/screen_overlay.h
@@ -20,10 +20,14 @@
  */
 
  // ScreenOverlay is a simple sprite container with no advanced functions.
+// May contain owned bitmap or reference persistent sprite's id, similar to how
+// other game objects do that.
+// May logically exist either on UI or room layer.
 
 #ifndef AGS_ENGINE_AC_SCREEN_OVERLAY_H
 #define AGS_ENGINE_AC_SCREEN_OVERLAY_H
 
+#include "ags/lib/std/memory.h"
 #include "ags/shared/core/types.h"
 
 namespace AGS3 {
@@ -47,22 +51,13 @@ using namespace AGS; // FIXME later
 enum OverlayFlags {
 	kOver_AlphaChannel = 0x0001,
 	kOver_PositionAtRoomXY = 0x0002, // room-relative position, may be in ui
-	kOver_RoomLayer = 0x0004         // work in room layer (as opposed to UI)
+	kOver_RoomLayer = 0x0004,        // work in room layer (as opposed to UI)
+	kOver_SpriteReference = 0x0008   // reference persistent sprite
 };
 
-// Overlay class.
-// TODO: currently overlay creates and stores its own bitmap, even if
-// created using existing sprite. As a side-effect, changing that sprite
-// (if it were a dynamic one) will not affect overlay (unlike other objects).
-// For future perfomance optimization it may be desired to store sprite index
-// instead; but that would mean that overlay will have to receive sprite
-// changes. For backward compatibility there may be a game switch that
-// forces it to make a copy.
 struct ScreenOverlay {
 	// Texture
 	Engine::IDriverDependantBitmap *ddb = nullptr;
-	// Original bitmap
-	Shared::Bitmap *pic = nullptr;
 	int type = 0, timeout = 0;
 	// Note that x,y are overlay's properties, that define its position in script;
 	// but real drawn position is x + offsetX, y + offsetY;
@@ -79,6 +74,9 @@ struct ScreenOverlay {
 	bool HasAlphaChannel() const {
 		return (_flags & kOver_AlphaChannel) != 0;
 	}
+	bool IsSpriteReference() const {
+		return (_flags & kOver_SpriteReference) != 0;
+	}
 	bool IsRoomRelative() const {
 		return (_flags & kOver_PositionAtRoomXY) != 0;
 	}
@@ -95,7 +93,14 @@ struct ScreenOverlay {
 		on ? _flags |= (kOver_RoomLayer | kOver_PositionAtRoomXY) :
 			_flags &= ~(kOver_RoomLayer | kOver_PositionAtRoomXY);
 	}
-
+	// Gets actual overlay's image, whether owned by overlay or by a sprite reference
+	Shared::Bitmap *GetImage() const;
+	// Get sprite reference id, or -1 if none set
+	int GetSpriteNum() const {
+		return _sprnum;
+	}
+	void SetImage(Shared::Bitmap *pic);
+	void SetSpriteNum(int sprnum);
 	// Tells if Overlay has graphically changed recently
 	bool HasChanged() const {
 		return _hasChanged;
@@ -115,6 +120,8 @@ struct ScreenOverlay {
 private:
 	int _flags = 0; // OverlayFlags
 	bool _hasChanged = false;
+	std::shared_ptr<Shared::Bitmap> _pic; // owned bitmap
+	int _sprnum = -1; // sprite reference
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 11c0cf89593..f0ce10426d7 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -759,10 +759,10 @@ HSaveError ReadDynamicSprites(Stream *in, int32_t /*cmp_ver*/, const PreservedPa
 }
 
 HSaveError WriteOverlays(Stream *out) {
-	out->WriteInt32(_GP(screenover).size());
 	for (const auto &over : _GP(screenover)) {
 		over.WriteToFile(out);
-		serialize_bitmap(over.pic, out);
+		if (!over.IsSpriteReference())
+			serialize_bitmap(over.GetImage(), out);
 	}
 	return HSaveError::None();
 }
@@ -774,12 +774,12 @@ HSaveError ReadOverlays(Stream *in, int32_t cmp_ver, const PreservedParams & /*p
 		bool has_bitmap;
 		over.ReadFromFile(in, has_bitmap, cmp_ver);
 		if (has_bitmap)
-			over.pic = read_serialized_bitmap(in);
+			over.SetImage(read_serialized_bitmap(in));
 		if (over.scaleWidth <= 0 || over.scaleHeight <= 0) {
-			over.scaleWidth = over.pic->GetWidth();
-			over.scaleHeight = over.pic->GetHeight();
+			over.scaleWidth = over.GetImage()->GetWidth();
+			over.scaleHeight = over.GetImage()->GetHeight();
 		}
-		_GP(screenover).push_back(over);
+		_GP(screenover).push_back(std::move(over));
 	}
 	return HSaveError::None();
 }
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 6c50d338d98..b2f329f96b8 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -287,7 +287,7 @@ static void restore_game_overlays(Stream *in) {
 	ReadOverlays_Aligned(in, has_bitmap, num_overs);
 	for (size_t i = 0; i < num_overs; ++i) {
 		if (has_bitmap[i])
-			_GP(screenover)[i].pic = read_serialized_bitmap(in);
+			_GP(screenover)[i].SetImage(read_serialized_bitmap(in));
 	}
 }
 
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index 3e93fd7d6f6..648021e3dac 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -383,6 +383,7 @@ void update_sierra_speech() {
 			int view_frame_x = 0;
 			int view_frame_y = 0;
 
+			Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].GetImage();
 			if (_GP(game).options[OPT_SPEECHTYPE] == 3) {
 				// QFG4-style fullscreen dialog
 				if (_G(facetalk_qfg4_override_placement_x)) {
@@ -391,14 +392,13 @@ void update_sierra_speech() {
 				if (_G(facetalk_qfg4_override_placement_y)) {
 					view_frame_y = _GP(play).speech_portrait_y;
 				} else {
-					view_frame_y = (_GP(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
+					view_frame_y = (frame_pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
 				}
-				_GP(screenover)[_G(face_talking)].pic->Clear(0);
+				frame_pic->Clear(0);
 			} else {
-				_GP(screenover)[_G(face_talking)].pic->ClearTransparent();
+				frame_pic->ClearTransparent();
 			}
 
-			Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].pic;
 			const ViewFrame *face_vf = &_GP(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);


Commit: a8ebf2b41b1a5b721e6edec29dd6079985985e61
    https://github.com/scummvm/scummvm/commit/a8ebf2b41b1a5b721e6edec29dd6079985985e61
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Added "clone" parameter to Overlay.CreateGraphical()

>From upstream 2a7adfb6a3424017913c9a6c240525029debf1e0

Changed paths:
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_overlay.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/overlay.h


diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 3fcb319b723..4fe72fbdfbd 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -1361,6 +1361,11 @@ void game_sprite_updated(int sprnum) {
 			_GP(guislider)[i].MarkChanged();
 		}
 	}
+	// overlays
+	for (auto &over : _GP(screenover)) {
+		if (over.GetSpriteNum() == sprnum)
+			over.MarkChanged();
+	}
 }
 
 void game_sprite_deleted(int sprnum) {
@@ -1412,6 +1417,11 @@ void game_sprite_deleted(int sprnum) {
 			}
 		}
 	}
+	// overlays
+	for (auto &over : _GP(screenover)) {
+		if (over.GetSpriteNum() == sprnum)
+			over.SetSpriteNum(0);
+	}
 }
 
 //=============================================================================
diff --git a/engines/ags/engine/ac/global_overlay.cpp b/engines/ags/engine/ac/global_overlay.cpp
index 81bce47e535..e4150854d3e 100644
--- a/engines/ags/engine/ac/global_overlay.cpp
+++ b/engines/ags/engine/ac/global_overlay.cpp
@@ -36,8 +36,8 @@ void RemoveOverlay(int ovrid) {
 	remove_screen_overlay(ovrid);
 }
 
-int CreateGraphicOverlay(int xx, int yy, int slott, int trans) {
-	auto *over = Overlay_CreateGraphicCore(false, xx, yy, slott, trans);
+int CreateGraphicOverlay(int x, int y, int slott, int trans) {
+	auto *over = Overlay_CreateGraphicCore(false, x, y, slott, trans != 0, true); // always clone
 	return over ? over->type : 0;
 }
 
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 39e30e30a58..e4990fc6aa2 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -175,11 +175,11 @@ int Overlay_GetValid(ScriptOverlay *scover) {
 	return 1;
 }
 
-ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent) {
+ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent, bool clone) {
 	data_to_game_coords(&x, &y);
 	size_t overid;
 	// We clone only dynamic sprites, because it makes no sense to clone normal ones
-	if ((_GP(game).SpriteInfos[slot].Flags & SPF_DYNAMICALLOC) != 0) {
+	if (clone && (_GP(game).SpriteInfos[slot].Flags & SPF_DYNAMICALLOC) != 0) {
 		Bitmap *screeno = BitmapHelper::CreateTransparentBitmap(_GP(game).SpriteInfos[slot].Width, _GP(game).SpriteInfos[slot].Height, _GP(game).GetColorDepth());
 		screeno->Blit(_GP(spriteset)[slot], 0, 0, transparent ? kBitmap_Transparency : kBitmap_Copy);
 		overid = add_screen_overlay(room_layer, x, y, OVER_CUSTOM, screeno,
@@ -198,13 +198,13 @@ ScreenOverlay *Overlay_CreateTextCore(bool room_layer, int x, int y, int width,
 	return _display_main(x, y, width, text, disp_type, font, -text_color, 0, allow_shrink, false);
 }
 
-ScriptOverlay *Overlay_CreateGraphicalEx(bool room_layer, int x, int y, int slot, int transparent) {
-	auto *over = Overlay_CreateGraphicCore(room_layer, x, y, slot, transparent != 0);
+ScriptOverlay *Overlay_CreateGraphicalEx(bool room_layer, int x, int y, int slot, int transparent, bool clone) {
+	auto *over = Overlay_CreateGraphicCore(room_layer, x, y, slot, transparent != 0, clone);
 	return over ? create_scriptoverlay(*over) : nullptr;
 }
 
 ScriptOverlay *Overlay_CreateGraphical(int x, int y, int slot, int transparent) {
-	auto *over = Overlay_CreateGraphicCore(false, x, y, slot, transparent != 0);
+	auto *over = Overlay_CreateGraphicCore(false, x, y, slot, transparent != 0, true); // always clone
 	return over ? create_scriptoverlay(*over) : nullptr;
 }
 
@@ -451,14 +451,21 @@ void recreate_overlay_ddbs() {
 RuntimeScriptValue Sc_Overlay_CreateGraphical(const RuntimeScriptValue *params, int32_t param_count) {
 	ASSERT_PARAM_COUNT(FUNCTION, 4);
 	ScriptOverlay *overlay = Overlay_CreateGraphicalEx(false, params[0].IValue, params[1].IValue, params[2].IValue,
-		params[3].IValue);
+		params[3].IValue, true); // always clone image
+	return RuntimeScriptValue().SetDynamicObject(overlay, overlay);
+}
+
+RuntimeScriptValue Sc_Overlay_CreateGraphicalRef(const RuntimeScriptValue *params, int32_t param_count) {
+	ASSERT_PARAM_COUNT(FUNCTION, 5);
+	ScriptOverlay *overlay = Overlay_CreateGraphicalEx(false, params[0].IValue, params[1].IValue, params[2].IValue,
+		params[3].IValue, params[4].GetAsBool());
 	return RuntimeScriptValue().SetDynamicObject(overlay, overlay);
 }
 
 RuntimeScriptValue Sc_Overlay_CreateRoomGraphical(const RuntimeScriptValue *params, int32_t param_count) {
-	ASSERT_PARAM_COUNT(FUNCTION, 4);
+	ASSERT_PARAM_COUNT(FUNCTION, 5);
 	ScriptOverlay *overlay = Overlay_CreateGraphicalEx(true, params[0].IValue, params[1].IValue, params[2].IValue,
-		params[3].IValue);
+		params[3].IValue, params[4].GetAsBool());
 	return RuntimeScriptValue().SetDynamicObject(overlay, overlay);
 }
 
@@ -573,8 +580,9 @@ void ScPl_Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int clr, c
 
 void RegisterOverlayAPI() {
 	ccAddExternalStaticFunction("Overlay::CreateGraphical^4", Sc_Overlay_CreateGraphical);
+	ccAddExternalStaticFunction("Overlay::CreateGraphical^5", Sc_Overlay_CreateGraphicalRef);
 	ccAddExternalStaticFunction("Overlay::CreateTextual^106", Sc_Overlay_CreateTextual);
-	ccAddExternalStaticFunction("Overlay::CreateRoomGraphical^4", Sc_Overlay_CreateRoomGraphical);
+	ccAddExternalStaticFunction("Overlay::CreateRoomGraphical^5", Sc_Overlay_CreateRoomGraphical);
 	ccAddExternalStaticFunction("Overlay::CreateRoomTextual^106", Sc_Overlay_CreateRoomTextual);
 	ccAddExternalObjectFunction("Overlay::SetText^104", Sc_Overlay_SetText);
 	ccAddExternalObjectFunction("Overlay::Remove^0", Sc_Overlay_Remove);
diff --git a/engines/ags/engine/ac/overlay.h b/engines/ags/engine/ac/overlay.h
index 4bc2fdf6b9c..f9b3cd507d1 100644
--- a/engines/ags/engine/ac/overlay.h
+++ b/engines/ags/engine/ac/overlay.h
@@ -45,7 +45,7 @@ void Overlay_SetY(ScriptOverlay *scover, int newy);
 int  Overlay_GetValid(ScriptOverlay *scover);
 ScriptOverlay *Overlay_CreateGraphical(int x, int y, int slot, int transparent);
 ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char *text);
-ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent);
+ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent, bool clone);
 ScreenOverlay *Overlay_CreateTextCore(bool room_layer, int x, int y, int width, int font, int text_color,
 	const char *text, int disp_type, int allow_shrink);
 


Commit: f782f0f2b29c5bf651cc734c75ae71018e1b9f87
    https://github.com/scummvm/scummvm/commit/f782f0f2b29c5bf651cc734c75ae71018e1b9f87
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Implemented Overlay.Graphic

>From upstream b3ca7d110664f29f54c11315400486a0fc11d33a

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


diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index e4990fc6aa2..a236892a8bc 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -101,6 +101,24 @@ void Overlay_SetY(ScriptOverlay *scover, int newy) {
 	_GP(screenover)[ovri].y = data_to_game_coord(newy);
 }
 
+int Overlay_GetGraphic(ScriptOverlay *scover) {
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+	return _GP(screenover)[ovri].GetSpriteNum();
+}
+
+void Overlay_SetGraphic(ScriptOverlay *scover, int slot) {
+	if (!_GP(spriteset).DoesSpriteExist(slot)) {
+		debug_script_warn("Overlay.SetGraphic: sprite %d is invalid", slot);
+		slot = 0;
+	}
+	int ovri = find_overlay_of_type(scover->overlayId);
+	if (ovri < 0)
+		quit("!invalid overlay ID specified");
+	_GP(screenover)[ovri].SetSpriteNum(slot);
+}
+
 bool Overlay_InRoom(ScriptOverlay *scover) {
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
@@ -354,8 +372,6 @@ size_t add_screen_overlay_impl(bool roomlayer, int x, int y, int type, int sprnu
 	over.y = y;
 	over.offsetX = pic_offx;
 	over.offsetY = pic_offy;
-	over.scaleWidth = over.GetImage()->GetWidth();
-	over.scaleHeight = over.GetImage()->GetHeight();
 	// by default draw speech and portraits over GUI, and the rest under GUI
 	over.zorder = (roomlayer || type == OVER_TEXTMSG || type == OVER_PICTURE || type == OVER_TEXTSPEECH) ?
 		INT_MAX : INT_MIN;
@@ -521,6 +537,14 @@ RuntimeScriptValue Sc_Overlay_SetY(void *self, const RuntimeScriptValue *params,
 	API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetY);
 }
 
+RuntimeScriptValue Sc_Overlay_GetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_INT(ScriptOverlay, Overlay_GetGraphic);
+}
+
+RuntimeScriptValue Sc_Overlay_SetGraphic(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetGraphic);
+}
+
 RuntimeScriptValue Sc_Overlay_InRoom(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_BOOL(ScriptOverlay, Overlay_InRoom);
 }
@@ -591,6 +615,8 @@ void RegisterOverlayAPI() {
 	ccAddExternalObjectFunction("Overlay::set_X", Sc_Overlay_SetX);
 	ccAddExternalObjectFunction("Overlay::get_Y", Sc_Overlay_GetY);
 	ccAddExternalObjectFunction("Overlay::set_Y", Sc_Overlay_SetY);
+	ccAddExternalObjectFunction("Overlay::get_Graphic", Sc_Overlay_GetGraphic);
+	ccAddExternalObjectFunction("Overlay::set_Graphic", Sc_Overlay_SetGraphic);
 	ccAddExternalObjectFunction("Overlay::get_InRoom", Sc_Overlay_InRoom);
 	ccAddExternalObjectFunction("Overlay::get_Width", Sc_Overlay_GetWidth);
 	ccAddExternalObjectFunction("Overlay::set_Width", Sc_Overlay_SetWidth);
diff --git a/engines/ags/engine/ac/screen_overlay.cpp b/engines/ags/engine/ac/screen_overlay.cpp
index 1727d95b169..8a286b47b0c 100644
--- a/engines/ags/engine/ac/screen_overlay.cpp
+++ b/engines/ags/engine/ac/screen_overlay.cpp
@@ -39,12 +39,28 @@ void ScreenOverlay::SetImage(Shared::Bitmap *pic) {
 	_flags &= ~kOver_SpriteReference;
 	_pic.reset(pic);
 	_sprnum = -1;
+	offsetX = offsetY = 0;
+	scaleWidth = scaleHeight = 0;
+	const auto *img = GetImage();
+	if (img) {
+		scaleWidth = img->GetWidth();
+		scaleHeight = img->GetHeight();
+	}
+	MarkChanged();
 }
 
 void ScreenOverlay::SetSpriteNum(int sprnum) {
 	_flags |= kOver_SpriteReference;
 	_pic.reset();
 	_sprnum = sprnum;
+	offsetX = offsetY = 0;
+	scaleWidth = scaleHeight = 0;
+	const auto *img = GetImage();
+	if (img) {
+		scaleWidth = img->GetWidth();
+		scaleHeight = img->GetHeight();
+	}
+	MarkChanged();
 }
 
 void ScreenOverlay::ReadFromFile(Stream *in, bool &has_bitmap, int32_t cmp_ver) {


Commit: c143ceb01b19e7bc40a5d55512489029ab7e7efe
    https://github.com/scummvm/scummvm/commit/c143ceb01b19e7bc40a5d55512489029ab7e7efe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Tidied and fixed InputBox to work with SDL2 input

>From upstream adec08a02664c0ab35ab358ca255ca6f2e3801b1

Changed paths:
    engines/ags/engine/gui/csci_dialog.cpp
    engines/ags/engine/gui/my_textbox.cpp


diff --git a/engines/ags/engine/gui/csci_dialog.cpp b/engines/ags/engine/gui/csci_dialog.cpp
index ca49b26d7c8..089992feddd 100644
--- a/engines/ags/engine/gui/csci_dialog.cpp
+++ b/engines/ags/engine/gui/csci_dialog.cpp
@@ -137,6 +137,7 @@ int CSCIWaitMessage(CSCIMessage *cscim) {
 		KeyInput ki;
 		if (run_service_key_controls(ki) && !_GP(play).IsIgnoringInput()) {
 			int keywas = ki.Key;
+			int uchar = ki.UChar;
 			if (keywas == eAGSKeyCodeReturn) {
 				cscim->id = finddefaultcontrol(CNF_DEFAULT);
 				cscim->code = CM_COMMAND;
@@ -147,7 +148,7 @@ int CSCIWaitMessage(CSCIMessage *cscim) {
 			else if ((keywas >= eAGSKeyCodeUpArrow) & (keywas <= eAGSKeyCodePageDown) & (finddefaultcontrol(CNT_LISTBOX) >= 0))
 				_G(vobjs)[finddefaultcontrol(CNT_LISTBOX)]->processmessage(CTB_KEYPRESS, keywas, 0);
 			else if (finddefaultcontrol(CNT_TEXTBOX) >= 0)
-				_G(vobjs)[finddefaultcontrol(CNT_TEXTBOX)]->processmessage(CTB_KEYPRESS, keywas, 0);
+				_G(vobjs)[finddefaultcontrol(CNT_TEXTBOX)]->processmessage(CTB_KEYPRESS, keywas, uchar);
 
 			if (cscim->id < 0) {
 				cscim->code = CM_KEYPRESS;
diff --git a/engines/ags/engine/gui/my_textbox.cpp b/engines/ags/engine/gui/my_textbox.cpp
index 98ba424a20b..0737aeb6ff4 100644
--- a/engines/ags/engine/gui/my_textbox.cpp
+++ b/engines/ags/engine/gui/my_textbox.cpp
@@ -59,28 +59,35 @@ int MyTextBox::pressedon(int /*mx*/, int /*my*/) {
 }
 
 int MyTextBox::processmessage(int mcode, int wParam, NumberPtr lParam) {
+
 	if (mcode == CTB_SETTEXT) {
-		strcpy(text, (char *)lParam._ptr);
+		snprintf(text, sizeof(text), "%s", (const char *)lParam._ptr);
 		needredraw = 1;
 	} else if (mcode == CTB_GETTEXT)
-		strcpy((char *)lParam._ptr, text);
+		strcpy((char *)lParam._ptr, text); // FIXME! dangerous
 	else if (mcode == CTB_KEYPRESS) {
+		// NOTE: this deprecated control does not support UTF-8
+		//int key = wParam;
+		int uchar = lParam;
+		size_t len = strlen(text);
 		if (wParam == eAGSKeyCodeBackspace) {
-			if (text[0] != 0)
-				text[strlen(text) - 1] = 0;
-
-			drawandmouse();
-		} else if (strlen(text) >= TEXTBOX_MAXLEN - 1)
-			;
-		else if (get_text_width(text, _G(cbuttfont)) >= wid - 5)
-			;
-		else if (wParam > 127)
-			;  // font only has 128 chars
-		else {
-			text[strlen(text) + 1] = 0;
-			text[strlen(text)] = wParam;
+			if (len > 0)
+				text[len - 1] = 0;
 			drawandmouse();
+			return 0;
 		}
+
+		if (len >= TEXTBOX_MAXLEN - 1)
+			return 0; // buffer full;
+		if (uchar == 0)
+			return 0; // not a textual event
+		if ((uchar >= 128) && (!font_supports_extended_characters(_G(cbuttfont))))
+			return 0; // unsupported letter
+		if (get_text_width(text, _G(cbuttfont)) >= wid - 5)
+			return 0; // not enough control space
+		text[len] = uchar;
+		text[len + 1] = 0;
+		drawandmouse();
 	} else
 		return -1;
 


Commit: a123a7473f9034c837fee3b13e280c1d04d4e35a
    https://github.com/scummvm/scummvm/commit/a123a7473f9034c837fee3b13e280c1d04d4e35a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Updated build version (3.6.0.25)

>From upstream 7e426edb3530e9d89120f614c33e52ddf13881d9

Changed paths:
    engines/ags/shared/core/def_version.h


diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 280071ee0f1..bfdda2ca64c 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
 #ifndef AGS_SHARED_CORE_DEFVERSION_H
 #define AGS_SHARED_CORE_DEFVERSION_H
 
-#define ACI_VERSION_STR      "3.6.0.24"
+#define ACI_VERSION_STR      "3.6.0.25"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3.6.0.24
+#define ACI_VERSION_MSRC_DEF  3.6.0.25
 #endif
 
 #define SPECIAL_VERSION ""


Commit: 1607b2530bf3e43d5bd6636843821277978a8d0d
    https://github.com/scummvm/scummvm/commit/1607b2530bf3e43d5bd6636843821277978a8d0d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-05-08T11:37:49-07:00

Commit Message:
AGS: Fixed script errors when non-obligatory callbacks are missing

>From upstream 29aaa19d712c3edf5701c648833283011c2f7298

Changed paths:
    engines/ags/engine/script/script.cpp
    engines/ags/shared/script/cc_common.cpp
    engines/ags/shared/script/cc_common.h


diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 75dbe6a1a62..56161a4d6f4 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -343,13 +343,21 @@ static int PrepareTextScript(ccInstance *sci, const char **tsname) {
 
 int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, const RuntimeScriptValue *params) {
 	int oldRestoreCount = _G(gameHasBeenRestored);
+	// TODO: research why this is really necessary, and refactor to avoid such hacks!
+	// First, save the current ccError state
+	// This is necessary because we might be attempting
+	// to run Script B, while Script A is still running in the
+	// background.
+	// If CallInstance here has an error, it would otherwise
+	// also abort Script A because ccError is a global variable.
+	ScriptError cachedCcError = cc_get_error();
 
 	cc_clear_error();
 	int toret = PrepareTextScript(sci, &tsname);
 	if (toret) {
+		cc_error(cachedCcError);
 		return -18;
 	}
-
 	cc_clear_error();
 	toret = _G(curscript)->inst->CallScriptFunction(tsname, numParam, params);
 
@@ -367,6 +375,9 @@ int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, cons
 
 	_G(post_script_cleanup_stack)--;
 
+	// restore cached error state
+	cc_error(cachedCcError);
+
 	// if the game has been restored, ensure that any further scripts are not run
 	if ((oldRestoreCount != _G(gameHasBeenRestored)) && (_G(eventClaimed) == EVENT_INPROGRESS))
 		_G(eventClaimed) = EVENT_CLAIMED;
diff --git a/engines/ags/shared/script/cc_common.cpp b/engines/ags/shared/script/cc_common.cpp
index 76bc36a3415..1c7af24d48d 100644
--- a/engines/ags/shared/script/cc_common.cpp
+++ b/engines/ags/shared/script/cc_common.cpp
@@ -74,4 +74,8 @@ void cc_error(const char *descr, ...) {
 	_GP(ccError).Line = _G(currentline);
 }
 
+void cc_error(const ScriptError &err) {
+	_GP(ccError) = err;
+}
+
 } // namespace AGS3
diff --git a/engines/ags/shared/script/cc_common.h b/engines/ags/shared/script/cc_common.h
index e2a2b6cc242..19c758a29fa 100644
--- a/engines/ags/shared/script/cc_common.h
+++ b/engines/ags/shared/script/cc_common.h
@@ -55,6 +55,7 @@ void cc_clear_error();
 bool cc_has_error();
 const ScriptError &cc_get_error();
 void cc_error(const char *, ...);
+void cc_error(const ScriptError &err);
 // Project-dependent script error formatting
 AGS::Shared::String cc_format_error(const AGS::Shared::String &message);
 




More information about the Scummvm-git-logs mailing list