mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
The implementation of Overlay_SetText() was rewritten in aaf6144 , with a purpose of replacing only the internal image of overlay, but not going all the way of removing/creating a new overlay into the same slot. In addition to the initial reasons, it became even more essential after the overlay storage optimization (see merge commit 77b8264), as overlay system now records free ids on overlay removal. As recreating overlay with exact same id would now require extra hacks into overlay logic. Unfortunately, an old SetTextOverlay() function was forgotten about, and it still doing this remove/create way of resetting a text. This results in engine wrongly considering certain ids to be free, while they are already taken. This commit fixes this by making SetTextOverlay delegate to the new Overlay_SetText() algorithm instead. From upstream 4caf0765ef36b4ebc2fb609f99a36a56d0736255
686 lines
26 KiB
C++
686 lines
26 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/std/algorithm.h"
|
|
#include "ags/engine/ac/overlay.h"
|
|
#include "ags/shared/ac/common.h"
|
|
#include "ags/shared/ac/sprite_cache.h"
|
|
#include "ags/shared/ac/view.h"
|
|
#include "ags/engine/ac/character.h"
|
|
#include "ags/engine/ac/character_extras.h"
|
|
#include "ags/engine/ac/display.h"
|
|
#include "ags/engine/ac/draw.h"
|
|
#include "ags/shared/ac/game_setup_struct.h"
|
|
#include "ags/engine/ac/game_state.h"
|
|
#include "ags/engine/ac/global_overlay.h"
|
|
#include "ags/engine/ac/global_translation.h"
|
|
#include "ags/engine/ac/runtime_defines.h"
|
|
#include "ags/engine/ac/screen_overlay.h"
|
|
#include "ags/engine/ac/string.h"
|
|
#include "ags/engine/ac/dynobj/dynobj_manager.h"
|
|
#include "ags/engine/debugging/debug_log.h"
|
|
#include "ags/engine/gfx/graphics_driver.h"
|
|
#include "ags/shared/gfx/bitmap.h"
|
|
#include "ags/engine/script/runtime_script_value.h"
|
|
#include "ags/shared/debugging/out.h"
|
|
#include "ags/engine/script/script_api.h"
|
|
#include "ags/engine/script/script_runtime.h"
|
|
#include "ags/globals.h"
|
|
|
|
namespace AGS3 {
|
|
|
|
using namespace AGS::Shared;
|
|
using namespace AGS::Engine;
|
|
|
|
void Overlay_Remove(ScriptOverlay *sco) {
|
|
sco->Remove();
|
|
}
|
|
|
|
void Overlay_SetText(ScriptOverlay *scover, int width, int fontid, int text_color, const char *text) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!Overlay.SetText: invalid overlay ID specified");
|
|
Overlay_SetText(*over, over->x, over->y, width, fontid, text_color, text);
|
|
}
|
|
|
|
void Overlay_SetText(ScreenOverlay &over, int x, int y, int width, int fontid, int text_color, const char *text) {
|
|
// TODO: find a nice way to refactor and share these code pieces
|
|
// from CreateTextOverlay
|
|
width = data_to_game_coord(width);
|
|
// allow DisplaySpeechBackground to be shrunk
|
|
int allow_shrink = (x == OVR_AUTOPLACE) ? 1 : 0;
|
|
|
|
// from Overlay_CreateTextCore
|
|
if (width < 8) width = _GP(play).GetUIViewport().GetWidth() / 2;
|
|
|
|
if (text_color == 0) text_color = 16;
|
|
|
|
// Recreate overlay image
|
|
int dummy_x = x, dummy_y = y, adj_x = x, adj_y = y;
|
|
bool has_alpha = false;
|
|
// NOTE: we pass text_color negated to let optionally use textwindow (if applicable)
|
|
// this is a generic ugliness of _display_main args, need to refactor later.
|
|
Bitmap *image = create_textual_image(get_translation(text), -text_color, 0, dummy_x, dummy_y, adj_x, adj_y,
|
|
width, fontid, allow_shrink, has_alpha);
|
|
|
|
// Update overlay properties
|
|
over.SetImage(std::unique_ptr<Bitmap>(image), has_alpha, adj_x - dummy_x, adj_y - dummy_y);
|
|
}
|
|
|
|
int Overlay_GetX(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
Point pos = get_overlay_position(*over);
|
|
return game_to_data_coord(pos.X);
|
|
}
|
|
|
|
void Overlay_SetX(ScriptOverlay *scover, int newx) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
over->x = data_to_game_coord(newx);
|
|
}
|
|
|
|
int Overlay_GetY(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
Point pos = get_overlay_position(*over);
|
|
return game_to_data_coord(pos.Y);
|
|
}
|
|
|
|
void Overlay_SetY(ScriptOverlay *scover, int newy) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
over->y = data_to_game_coord(newy);
|
|
}
|
|
|
|
int Overlay_GetGraphic(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return over->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;
|
|
}
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
over->SetSpriteNum(slot);
|
|
}
|
|
|
|
bool Overlay_InRoom(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return over->IsRoomLayer();
|
|
}
|
|
|
|
int Overlay_GetWidth(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return game_to_data_coord(over->scaleWidth);
|
|
}
|
|
|
|
int Overlay_GetHeight(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return game_to_data_coord(over->scaleHeight);
|
|
}
|
|
|
|
int Overlay_GetGraphicWidth(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return game_to_data_coord(over->GetGraphicSize().Width);
|
|
}
|
|
|
|
int Overlay_GetGraphicHeight(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
return game_to_data_coord(over->GetGraphicSize().Height);
|
|
}
|
|
|
|
void Overlay_SetScaledSize(ScreenOverlay &over, int width, int height) {
|
|
data_to_game_coords(&width, &height);
|
|
if (width < 1 || height < 1) {
|
|
debug_script_warn("Overlay.SetSize: invalid dimensions: %d x %d", width, height);
|
|
return;
|
|
}
|
|
if ((width == over.scaleWidth) && (height == over.scaleHeight))
|
|
return; // no change
|
|
over.scaleWidth = width;
|
|
over.scaleHeight = height;
|
|
over.MarkChanged();
|
|
}
|
|
|
|
void Overlay_SetWidth(ScriptOverlay *scover, int width) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
Overlay_SetScaledSize(*over, width, game_to_data_coord(over->scaleHeight));
|
|
}
|
|
|
|
void Overlay_SetHeight(ScriptOverlay *scover, int height) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
Overlay_SetScaledSize(*over, game_to_data_coord(over->scaleWidth), height);
|
|
}
|
|
|
|
int Overlay_GetValid(ScriptOverlay *scover) {
|
|
if (scover->overlayId == -1)
|
|
return 0;
|
|
|
|
if (!IsOverlayValid(scover->overlayId)) {
|
|
scover->overlayId = -1;
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
ScreenOverlay *Overlay_CreateGraphicCore(bool room_layer, int x, int y, int slot, bool transparent, bool clone) {
|
|
if (!_GP(spriteset).DoesSpriteExist(slot)) {
|
|
debug_script_warn("Overlay.CreateGraphical: sprite %d is invalid", slot);
|
|
return nullptr;
|
|
}
|
|
|
|
data_to_game_coords(&x, &y);
|
|
size_t overid;
|
|
// We clone only dynamic sprites, because it makes no sense to clone normal ones
|
|
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,
|
|
(_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,
|
|
const char *text, int disp_type, int allow_shrink) {
|
|
if (width < 8) width = _GP(play).GetUIViewport().GetWidth() / 2;
|
|
if (x < 0) x = _GP(play).GetUIViewport().GetWidth() / 2 - width / 2;
|
|
if (text_color == 0) text_color = 16;
|
|
return display_main(x, y, width, text, disp_type, font, -text_color, 0, allow_shrink, false, room_layer);
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateGraphicalImpl(bool room_layer, int x, int y, int slot, bool transparent, bool clone) {
|
|
auto *over = Overlay_CreateGraphicCore(room_layer, x, y, slot, transparent, clone);
|
|
return over ? create_scriptoverlay(*over) : nullptr;
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateGraphical4(int x, int y, int slot, bool transparent) {
|
|
return Overlay_CreateGraphical(x, y, slot, transparent, true /* clone */);
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateGraphical(int x, int y, int slot, bool transparent, bool clone) {
|
|
return Overlay_CreateGraphicalImpl(false, x, y, slot, transparent, clone);
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateRoomGraphical(int x, int y, int slot, bool transparent, bool clone) {
|
|
return Overlay_CreateGraphicalImpl(true, x, y, slot, transparent, clone);
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateTextualImpl(bool room_layer, int x, int y, int width, int font, int colour, const char *text) {
|
|
data_to_game_coords(&x, &y);
|
|
width = data_to_game_coord(width);
|
|
auto *over = Overlay_CreateTextCore(room_layer, x, y, width, font, colour, text, DISPLAYTEXT_NORMALOVERLAY, 0);
|
|
return over ? create_scriptoverlay(*over) : nullptr;
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colour, const char *text) {
|
|
return Overlay_CreateTextualImpl(false, x, y, width, font, colour, text);
|
|
}
|
|
|
|
ScriptOverlay *Overlay_CreateRoomTextual(int x, int y, int width, int font, int colour, const char *text) {
|
|
return Overlay_CreateTextualImpl(true, x, y, width, font, colour, text);
|
|
}
|
|
|
|
int Overlay_GetTransparency(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
return GfxDef::LegacyTrans255ToTrans100(over->transparency);
|
|
}
|
|
|
|
void Overlay_SetTransparency(ScriptOverlay *scover, int trans) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
if ((trans < 0) | (trans > 100))
|
|
quit("!SetTransparency: transparency value must be between 0 and 100");
|
|
|
|
over->transparency = GfxDef::Trans100ToLegacyTrans255(trans);
|
|
}
|
|
|
|
int Overlay_GetZOrder(ScriptOverlay *scover) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
return over->zorder;
|
|
}
|
|
|
|
void Overlay_SetZOrder(ScriptOverlay *scover, int zorder) {
|
|
auto *over = get_overlay(scover->overlayId);
|
|
if (!over)
|
|
quit("!invalid overlay ID specified");
|
|
|
|
over->zorder = zorder;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
// Creates and registers a managed script object for existing overlay object
|
|
// optionally adds an internal engine reference to prevent object's disposal
|
|
ScriptOverlay *create_scriptoverlay(ScreenOverlay &over, bool internal_ref) {
|
|
ScriptOverlay *scover = new ScriptOverlay();
|
|
scover->overlayId = over.type;
|
|
int handl = ccRegisterManagedObject(scover, scover);
|
|
over.associatedOverlayHandle = handl; // save the handle for access
|
|
if (internal_ref) // requested additional ref
|
|
ccAddObjectReference(handl);
|
|
return scover;
|
|
}
|
|
|
|
// Invalidates existing script object to let user know that previous overlay is gone,
|
|
// and releases engine's internal reference (script object may exist while there are user refs)
|
|
static void invalidate_and_subref(ScreenOverlay &over) {
|
|
if (over.associatedOverlayHandle <= 0)
|
|
return; // invalid handle
|
|
|
|
ScriptOverlay *scover = const_cast<ScriptOverlay*>((const ScriptOverlay*)ccGetObjectAddressFromHandle(over.associatedOverlayHandle));
|
|
if (scover) {
|
|
scover->overlayId = -1; // invalidate script object
|
|
ccReleaseObjectReference(over.associatedOverlayHandle);
|
|
}
|
|
over.associatedOverlayHandle = 0; // reset internal handle
|
|
}
|
|
|
|
// Frees overlay resources and tell to dispose script object if there are no refs left
|
|
static void dispose_overlay(ScreenOverlay &over) {
|
|
over.SetImage(nullptr);
|
|
// invalidate script object and dispose it if there are no more refs
|
|
if (over.associatedOverlayHandle > 0) {
|
|
ScriptOverlay *scover = (ScriptOverlay *)ccGetObjectAddressFromHandle(over.associatedOverlayHandle);
|
|
if (scover) scover->overlayId = -1;
|
|
ccAttemptDisposeObject(over.associatedOverlayHandle);
|
|
}
|
|
}
|
|
|
|
void remove_screen_overlay(int type) {
|
|
if (type < 0 || static_cast<uint32_t>(type) >= _GP(screenover).size() || _GP(screenover)[type].type < 0)
|
|
return; // something is wrong
|
|
|
|
ScreenOverlay &over = _GP(screenover)[type];
|
|
// TODO: move these custom settings outside of this function
|
|
if (over.type == _GP(play).complete_overlay_on) {
|
|
_GP(play).complete_overlay_on = 0;
|
|
} else if (over.type == _GP(play).text_overlay_on) { // release internal ref for speech text
|
|
invalidate_and_subref(over);
|
|
_GP(play).speech_text_schandle = 0;
|
|
_GP(play).text_overlay_on = 0;
|
|
} else if (over.type == OVER_PICTURE) { // release internal ref for speech face
|
|
invalidate_and_subref(over);
|
|
_GP(play).speech_face_schandle = 0;
|
|
_G(face_talking) = -1;
|
|
} else if (over.bgSpeechForChar >= 0) { // release internal ref for bg speech
|
|
invalidate_and_subref(over);
|
|
}
|
|
dispose_overlay(over);
|
|
|
|
// Don't erase vector elements, instead set invalid and record free index
|
|
_GP(screenover)[type] = ScreenOverlay();
|
|
if (type >= OVER_FIRSTFREE)
|
|
_GP(over_free_ids).push(type);
|
|
|
|
reset_drawobj_for_overlay(type);
|
|
|
|
// If all overlays have been removed, reset creation index (helps vs overflows)
|
|
_GP(play).overlay_count--;
|
|
if (_GP(play).overlay_count == 0)
|
|
_GP(play).overlay_creation_id = 0;
|
|
}
|
|
|
|
void remove_all_overlays() {
|
|
for (auto &over : _GP(screenover))
|
|
remove_screen_overlay(over.type);
|
|
}
|
|
|
|
ScreenOverlay *get_overlay(int type) {
|
|
return (type >= 0 && static_cast<uint32_t>(type) < _GP(screenover).size() && _GP(screenover)[type].type >= 0) ? &_GP(screenover)[type] : nullptr;
|
|
}
|
|
|
|
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 a free ID
|
|
if (_GP(over_free_ids).size() > 0) {
|
|
type = _GP(over_free_ids).front();
|
|
_GP(over_free_ids).pop();
|
|
} else {
|
|
type = std::max((uint)OVER_FIRSTFREE, _GP(screenover).size());
|
|
}
|
|
}
|
|
|
|
if (_GP(screenover).size() <= static_cast<uint32_t>(type))
|
|
_GP(screenover).resize(type + 1);
|
|
ScreenOverlay over;
|
|
over.type = type;
|
|
over.creation_id = _GP(play).overlay_creation_id++;
|
|
if (piccy) {
|
|
over.SetImage(std::unique_ptr<Bitmap>(piccy), has_alpha, pic_offx, pic_offy);
|
|
} else {
|
|
over.SetSpriteNum(sprnum, pic_offx, pic_offy);
|
|
}
|
|
over.x = x;
|
|
over.y = y;
|
|
// 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;
|
|
over.timeout = 0;
|
|
over.bgSpeechForChar = -1;
|
|
over.associatedOverlayHandle = 0;
|
|
over.SetRoomLayer(roomlayer);
|
|
// TODO: move these custom settings outside of this function
|
|
if (type == OVER_COMPLETE) _GP(play).complete_overlay_on = type;
|
|
else if (type == OVER_TEXTMSG || type == OVER_TEXTSPEECH) {
|
|
_GP(play).text_overlay_on = type;
|
|
// only make script object for blocking speech now, because messagebox blocks all script
|
|
// and therefore cannot be accessed, so no practical reason for that atm
|
|
if (type == OVER_TEXTSPEECH) {
|
|
create_scriptoverlay(over, true);
|
|
_GP(play).speech_text_schandle = over.associatedOverlayHandle;
|
|
}
|
|
} else if (type == OVER_PICTURE) {
|
|
create_scriptoverlay(over, true);
|
|
_GP(play).speech_face_schandle = over.associatedOverlayHandle;
|
|
}
|
|
over.MarkChanged();
|
|
_GP(screenover)[type] = std::move(over);
|
|
_GP(play).overlay_count++;
|
|
return type;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
if (over.x == OVR_AUTOPLACE) {
|
|
const Rect &ui_view = _GP(play).GetUIViewport();
|
|
// auto place on character
|
|
int charid = over.y;
|
|
|
|
auto view = FindNearestViewport(charid);
|
|
const int charpic = _GP(views)[_GP(game).chars[charid].view].loops[_GP(game).chars[charid].loop].frames[0].pic;
|
|
const int height = (_GP(charextra)[charid].height < 1) ? _GP(game).SpriteInfos[charpic].Height : _GP(charextra)[charid].height;
|
|
const Point screenpt = view->RoomToScreen(
|
|
data_to_game_coord(_GP(game).chars[charid].x),
|
|
data_to_game_coord(_GP(charextra)[charid].GetEffectiveY(&_GP(game).chars[charid])) - height).first;
|
|
const Size pic_size = over.GetGraphicSize();
|
|
int tdxp = std::max(0, screenpt.X - pic_size.Width / 2);
|
|
int tdyp = screenpt.Y - get_fixed_pixel_size(5);
|
|
tdyp -= pic_size.Height;
|
|
tdyp = std::max(5, tdyp);
|
|
|
|
if ((tdxp + pic_size.Width) >= ui_view.GetWidth())
|
|
tdxp = (ui_view.GetWidth() - pic_size.Width) - 1;
|
|
if (_GP(game).chars[charid].room != _G(displayed_room)) {
|
|
tdxp = ui_view.GetWidth() / 2 - pic_size.Width / 2;
|
|
tdyp = ui_view.GetHeight() / 2 - pic_size.Height / 2;
|
|
}
|
|
return Point(tdxp, tdyp);
|
|
} else {
|
|
// Note: the internal offset is only needed when x,y coordinates are specified
|
|
// and only in the case where the overlay is using a GUI. See issue #1098
|
|
int tdxp = over.x + over.offsetX;
|
|
int tdyp = over.y + over.offsetY;
|
|
if (over.IsRoomRelative())
|
|
return _GP(play).RoomToScreen(tdxp, tdyp);
|
|
return Point(tdxp, tdyp);
|
|
}
|
|
}
|
|
|
|
void restore_overlays() {
|
|
// Will have to readjust free ids records, as overlays may be restored in any random slots
|
|
while (!_GP(over_free_ids).empty()) {
|
|
_GP(over_free_ids).pop();
|
|
}
|
|
for (size_t i = 0; i < _GP(screenover).size(); ++i) {
|
|
auto &over = _GP(screenover)[i];
|
|
if (over.type >= 0) {
|
|
over.MarkChanged(); // force recreate texture on next draw
|
|
} else if (i >= OVER_FIRSTFREE) {
|
|
_GP(over_free_ids).push(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<ScreenOverlay> &get_overlays() {
|
|
return _GP(screenover);
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// Script API Functions
|
|
//
|
|
//=============================================================================
|
|
|
|
// ScriptOverlay* (int x, int y, int slot, int transparent)
|
|
RuntimeScriptValue Sc_Overlay_CreateGraphical4(const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_SCALL_OBJAUTO_PINT3_PBOOL(ScriptOverlay, Overlay_CreateGraphical4);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_CreateGraphical(const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_SCALL_OBJAUTO_PINT3_PBOOL2(ScriptOverlay, Overlay_CreateGraphical);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_CreateRoomGraphical(const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_SCALL_OBJAUTO_PINT3_PBOOL2(ScriptOverlay, Overlay_CreateRoomGraphical);
|
|
}
|
|
|
|
// ScriptOverlay* (int x, int y, int width, int font, int colour, const char* text, ...)
|
|
RuntimeScriptValue Sc_Overlay_CreateTextual(const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_SCALL_SCRIPT_SPRINTF(Overlay_CreateTextual, 6);
|
|
ScriptOverlay *overlay = Overlay_CreateTextual(params[0].IValue, params[1].IValue, params[2].IValue,
|
|
params[3].IValue, params[4].IValue, scsf_buffer);
|
|
return RuntimeScriptValue().SetScriptObject(overlay, overlay);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_CreateRoomTextual(const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_SCALL_SCRIPT_SPRINTF(Overlay_CreateRoomTextual, 6);
|
|
ScriptOverlay *overlay = Overlay_CreateRoomTextual(params[0].IValue, params[1].IValue, params[2].IValue,
|
|
params[3].IValue, params[4].IValue, scsf_buffer);
|
|
return RuntimeScriptValue().SetScriptObject(overlay, overlay);
|
|
}
|
|
|
|
// void (ScriptOverlay *scover, int wii, int fontid, int clr, char*texx, ...)
|
|
RuntimeScriptValue Sc_Overlay_SetText(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_SCRIPT_SPRINTF(Overlay_SetText, 4);
|
|
Overlay_SetText((ScriptOverlay *)self, params[0].IValue, params[1].IValue, params[2].IValue, scsf_buffer);
|
|
return RuntimeScriptValue((int32_t)0);
|
|
}
|
|
|
|
// void (ScriptOverlay *sco)
|
|
RuntimeScriptValue Sc_Overlay_Remove(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_VOID(ScriptOverlay, Overlay_Remove);
|
|
}
|
|
|
|
// int (ScriptOverlay *scover)
|
|
RuntimeScriptValue Sc_Overlay_GetValid(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetValid);
|
|
}
|
|
|
|
// int (ScriptOverlay *scover)
|
|
RuntimeScriptValue Sc_Overlay_GetX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetX);
|
|
}
|
|
|
|
// void (ScriptOverlay *scover, int newx)
|
|
RuntimeScriptValue Sc_Overlay_SetX(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetX);
|
|
}
|
|
|
|
// int (ScriptOverlay *scover)
|
|
RuntimeScriptValue Sc_Overlay_GetY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetY);
|
|
}
|
|
|
|
// void (ScriptOverlay *scover, int newy)
|
|
RuntimeScriptValue Sc_Overlay_SetY(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
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);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_GetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetWidth);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_SetWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetWidth);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_GetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetHeight);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_SetHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetHeight);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_GetGraphicWidth(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetGraphicWidth);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_GetGraphicHeight(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_INT(ScriptOverlay, Overlay_GetGraphicHeight);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
RuntimeScriptValue Sc_Overlay_SetZOrder(void *self, const RuntimeScriptValue *params, int32_t param_count) {
|
|
API_OBJCALL_VOID_PINT(ScriptOverlay, Overlay_SetZOrder);
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// Exclusive variadic API implementation for Plugins
|
|
//
|
|
//=============================================================================
|
|
|
|
ScriptOverlay *ScPl_Overlay_CreateRoomTextual(int x, int y, int width, int font, int colour, const char *text, ...) {
|
|
API_PLUGIN_SCRIPT_SPRINTF(text);
|
|
return Overlay_CreateRoomTextual(x, y, width, font, colour, scsf_buffer);
|
|
}
|
|
|
|
// void (ScriptOverlay *scover, int wii, int fontid, int clr, char*texx, ...)
|
|
void ScPl_Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int clr, char *texx, ...) {
|
|
API_PLUGIN_SCRIPT_SPRINTF(texx);
|
|
Overlay_SetText(scover, wii, fontid, clr, scsf_buffer);
|
|
}
|
|
|
|
void RegisterOverlayAPI() {
|
|
ScFnRegister overlay_api[] = {
|
|
{"Overlay::CreateGraphical^4", API_FN_PAIR(Overlay_CreateGraphical4)},
|
|
{"Overlay::CreateGraphical^5", API_FN_PAIR(Overlay_CreateGraphical)},
|
|
{"Overlay::CreateTextual^106", Sc_Overlay_CreateTextual},
|
|
{"Overlay::CreateRoomGraphical^5", API_FN_PAIR(Overlay_CreateRoomGraphical)},
|
|
{"Overlay::CreateRoomTextual^106", Sc_Overlay_CreateRoomTextual},
|
|
|
|
{"Overlay::SetText^104", Sc_Overlay_SetText},
|
|
{"Overlay::Remove^0", API_FN_PAIR(Overlay_Remove)},
|
|
{"Overlay::get_Valid", API_FN_PAIR(Overlay_GetValid)},
|
|
{"Overlay::get_X", API_FN_PAIR(Overlay_GetX)},
|
|
{"Overlay::set_X", API_FN_PAIR(Overlay_SetX)},
|
|
{"Overlay::get_Y", API_FN_PAIR(Overlay_GetY)},
|
|
{"Overlay::set_Y", API_FN_PAIR(Overlay_SetY)},
|
|
{"Overlay::get_Graphic", API_FN_PAIR(Overlay_GetGraphic)},
|
|
{"Overlay::set_Graphic", API_FN_PAIR(Overlay_SetGraphic)},
|
|
{"Overlay::get_InRoom", API_FN_PAIR(Overlay_InRoom)},
|
|
{"Overlay::get_Width", API_FN_PAIR(Overlay_GetWidth)},
|
|
{"Overlay::set_Width", API_FN_PAIR(Overlay_SetWidth)},
|
|
{"Overlay::get_Height", API_FN_PAIR(Overlay_GetHeight)},
|
|
{"Overlay::set_Height", API_FN_PAIR(Overlay_SetHeight)},
|
|
{"Overlay::get_GraphicWidth", API_FN_PAIR(Overlay_GetGraphicWidth)},
|
|
{"Overlay::get_GraphicHeight", API_FN_PAIR(Overlay_GetGraphicHeight)},
|
|
{"Overlay::get_Transparency", API_FN_PAIR(Overlay_GetTransparency)},
|
|
{"Overlay::set_Transparency", API_FN_PAIR(Overlay_SetTransparency)},
|
|
{"Overlay::get_ZOrder", API_FN_PAIR(Overlay_GetZOrder)},
|
|
{"Overlay::set_ZOrder", API_FN_PAIR(Overlay_SetZOrder)},
|
|
};
|
|
|
|
ccAddExternalFunctions361(overlay_api);
|
|
}
|
|
|
|
} // namespace AGS3
|