2020-10-14 15:16:30 +02:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-12-21 12:31:32 +01:00
|
|
|
#include "twine/renderer/redraw.h"
|
2020-11-05 00:25:34 +01:00
|
|
|
#include "common/memstream.h"
|
2021-02-10 18:41:27 +01:00
|
|
|
#include "common/system.h"
|
2020-10-14 15:16:30 +02:00
|
|
|
#include "common/textconsole.h"
|
2020-10-20 23:39:31 +02:00
|
|
|
#include "graphics/surface.h"
|
2020-12-21 12:31:32 +01:00
|
|
|
#include "twine/audio/sound.h"
|
|
|
|
#include "twine/debugger/debug_scene.h"
|
2020-10-23 13:44:38 +02:00
|
|
|
#include "twine/input.h"
|
2020-12-21 12:31:32 +01:00
|
|
|
#include "twine/menu/interface.h"
|
|
|
|
#include "twine/menu/menu.h"
|
2020-12-24 15:04:57 +01:00
|
|
|
#include "twine/parser/sprite.h"
|
2020-12-21 12:31:32 +01:00
|
|
|
#include "twine/renderer/renderer.h"
|
|
|
|
#include "twine/renderer/screens.h"
|
2020-12-24 15:04:57 +01:00
|
|
|
#include "twine/resources/hqr.h"
|
2020-12-21 19:37:07 +01:00
|
|
|
#include "twine/resources/resources.h"
|
2020-12-24 15:04:57 +01:00
|
|
|
#include "twine/scene/actor.h"
|
|
|
|
#include "twine/scene/animations.h"
|
|
|
|
#include "twine/scene/collision.h"
|
|
|
|
#include "twine/scene/grid.h"
|
|
|
|
#include "twine/scene/movements.h"
|
2020-12-21 12:31:32 +01:00
|
|
|
#include "twine/scene/scene.h"
|
2020-10-14 15:16:30 +02:00
|
|
|
#include "twine/text.h"
|
|
|
|
|
|
|
|
namespace TwinE {
|
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
void Redraw::addRedrawCurrentArea(const Common::Rect &redrawArea) {
|
|
|
|
const int32 area = (redrawArea.right - redrawArea.left) * (redrawArea.bottom - redrawArea.top);
|
|
|
|
|
|
|
|
for (int32 i = 0; i < numOfRedrawBox; ++i) {
|
|
|
|
Common::Rect &rect = currentRedrawList[i];
|
|
|
|
const int32 leftValue = MIN<int32>(redrawArea.left, rect.left);
|
|
|
|
const int32 rightValue = MAX<int32>(redrawArea.right, rect.right);
|
|
|
|
const int32 topValue = MIN<int32>(redrawArea.top, rect.top);
|
|
|
|
const int32 bottomValue = MAX<int32>(redrawArea.bottom, rect.bottom);
|
|
|
|
|
|
|
|
const int32 areaValue = (rightValue - leftValue) * (bottomValue - topValue);
|
|
|
|
const int32 areaValueDiff = ((rect.right - rect.left) * (rect.bottom - rect.top) + area);
|
|
|
|
if (areaValue < areaValueDiff) {
|
|
|
|
rect.left = leftValue;
|
|
|
|
rect.top = topValue;
|
|
|
|
rect.right = rightValue;
|
2021-01-07 21:17:53 +01:00
|
|
|
rect.bottom = MIN<int32>((_engine->height() - 1), bottomValue);
|
2020-12-30 14:22:45 +01:00
|
|
|
|
|
|
|
assert(rect.left <= rect.right);
|
|
|
|
assert(rect.top <= rect.bottom);
|
2020-10-14 14:20:38 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-10-24 12:32:00 +02:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
Common::Rect &rect = currentRedrawList[numOfRedrawBox];
|
|
|
|
rect.left = redrawArea.left;
|
|
|
|
rect.top = redrawArea.top;
|
|
|
|
rect.right = redrawArea.right;
|
2021-01-07 21:17:53 +01:00
|
|
|
rect.bottom = MIN<int32>((_engine->height() - 1), redrawArea.bottom);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
assert(rect.left <= rect.right);
|
|
|
|
assert(rect.top <= rect.bottom);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
|
|
|
numOfRedrawBox++;
|
|
|
|
}
|
|
|
|
|
2020-11-25 16:59:54 +01:00
|
|
|
void Redraw::addRedrawArea(const Common::Rect &rect) {
|
2020-12-30 14:22:45 +01:00
|
|
|
if (!rect.isValidRect()) {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-25 16:59:54 +01:00
|
|
|
addRedrawArea(rect.left, rect.top, rect.right, rect.bottom);
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::addRedrawArea(int32 left, int32 top, int32 right, int32 bottom) {
|
2021-01-07 21:17:53 +01:00
|
|
|
if (left < 0) {
|
|
|
|
left = 0;
|
2020-10-24 12:42:45 +02:00
|
|
|
}
|
2021-01-07 21:17:53 +01:00
|
|
|
if (top < 0) {
|
|
|
|
top = 0;
|
2020-10-24 12:42:45 +02:00
|
|
|
}
|
2021-01-07 21:17:53 +01:00
|
|
|
if (right >= _engine->width()) {
|
|
|
|
right = (_engine->width() - 1);
|
2020-10-24 12:42:45 +02:00
|
|
|
}
|
2021-01-07 21:17:53 +01:00
|
|
|
if (bottom >= _engine->height()) {
|
|
|
|
bottom = (_engine->height() - 1);
|
2020-10-24 12:42:45 +02:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-24 12:42:45 +02:00
|
|
|
if (left > right || top > bottom) {
|
2020-10-14 14:20:38 +02:00
|
|
|
return;
|
2020-10-24 12:42:45 +02:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
Common::Rect &rect = nextRedrawList[currNumOfRedrawBox];
|
|
|
|
rect.left = left;
|
|
|
|
rect.top = top;
|
|
|
|
rect.right = right;
|
|
|
|
rect.bottom = bottom;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
|
|
|
currNumOfRedrawBox++;
|
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawCurrentArea(rect);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::moveNextAreas() {
|
2020-10-14 14:20:38 +02:00
|
|
|
numOfRedrawBox = 0;
|
|
|
|
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < currNumOfRedrawBox; i++) {
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawCurrentArea(nextRedrawList[i]);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::flipRedrawAreas() {
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < numOfRedrawBox; i++) { // redraw areas on screen
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->copyBlockPhys(currentRedrawList[i].left, currentRedrawList[i].top, currentRedrawList[i].right, currentRedrawList[i].bottom);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
numOfRedrawBox = 0;
|
|
|
|
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < currNumOfRedrawBox; i++) { //setup the redraw areas for next display
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawCurrentArea(nextRedrawList[i]);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::blitBackgroundAreas() {
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < numOfRedrawBox; i++) {
|
2020-12-13 15:27:43 +01:00
|
|
|
_engine->_interface->blitBox(currentRedrawList[i], _engine->workVideoBuffer, _engine->frontVideoBuffer);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::sortDrawingList(DrawListStruct *list, int32 listSize) {
|
2021-01-16 23:56:48 +01:00
|
|
|
if (listSize == 1) {
|
|
|
|
return;
|
|
|
|
}
|
2020-10-20 21:21:48 +02:00
|
|
|
for (int32 i = 0; i < listSize - 1; i++) {
|
|
|
|
for (int32 j = 0; j < listSize - 1 - i; j++) {
|
2020-10-14 15:16:30 +02:00
|
|
|
if (list[j + 1].posValue < list[j].posValue) {
|
2020-10-24 12:42:45 +02:00
|
|
|
DrawListStruct tempStruct;
|
2020-10-14 15:16:30 +02:00
|
|
|
memcpy(&tempStruct, &list[j + 1], sizeof(DrawListStruct));
|
|
|
|
memcpy(&list[j + 1], &list[j], sizeof(DrawListStruct));
|
2020-10-14 14:20:38 +02:00
|
|
|
memcpy(&list[j], &tempStruct, sizeof(DrawListStruct));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-07 16:58:52 +01:00
|
|
|
void Redraw::addOverlay(OverlayType type, int16 info0, int16 x, int16 y, int16 info1, OverlayPosType posType, int16 lifeTime) {
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < ARRAYSIZE(overlayList); i++) {
|
2020-10-14 14:20:38 +02:00
|
|
|
OverlayListStruct *overlay = &overlayList[i];
|
|
|
|
if (overlay->info0 == -1) {
|
|
|
|
overlay->type = type;
|
|
|
|
overlay->info0 = info0;
|
2020-10-20 21:21:48 +02:00
|
|
|
overlay->x = x;
|
|
|
|
overlay->y = y;
|
2020-10-14 14:20:38 +02:00
|
|
|
overlay->info1 = info1;
|
|
|
|
overlay->posType = posType;
|
2020-10-14 15:16:30 +02:00
|
|
|
overlay->lifeTime = _engine->lbaTime + lifeTime * 50;
|
|
|
|
break;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 22:23:30 +01:00
|
|
|
void Redraw::updateOverlayTypePosition(int16 x1, int16 y1, int16 x2, int16 y2) {
|
|
|
|
const int16 newX = x2 - x1;
|
|
|
|
const int16 newY = y2 - y1;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-24 12:42:45 +02:00
|
|
|
for (int32 i = 0; i < ARRAYSIZE(overlayList); i++) {
|
2020-10-14 14:20:38 +02:00
|
|
|
OverlayListStruct *overlay = &overlayList[i];
|
2020-12-07 16:59:29 +01:00
|
|
|
if (overlay->posType == OverlayPosType::koFollowActor) {
|
2020-10-20 21:21:48 +02:00
|
|
|
overlay->x = newX;
|
|
|
|
overlay->y = newY;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-13 22:56:46 +01:00
|
|
|
int32 Redraw::fillActorDrawingList(bool bgRedraw) {
|
2020-10-20 21:21:48 +02:00
|
|
|
int32 drawListPos = 0;
|
2020-12-13 14:09:31 +01:00
|
|
|
for (int32 modelActorPos = 0; modelActorPos < _engine->_scene->sceneNumActors; modelActorPos++) {
|
2020-10-30 20:29:10 +01:00
|
|
|
ActorStruct *actor = _engine->_scene->getActor(modelActorPos);
|
2020-10-14 14:20:38 +02:00
|
|
|
actor->dynamicFlags.bIsVisible = 0; // reset visible state
|
|
|
|
|
2021-02-25 17:06:23 +01:00
|
|
|
if (_engine->_grid->useCellingGrid != -1 && actor->pos.y > _engine->_scene->sceneZones[_engine->_grid->cellingGridIdx].topRight.y) {
|
2020-12-13 13:08:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// no redraw required
|
2020-12-13 13:25:35 +01:00
|
|
|
if (actor->staticFlags.bIsBackgrounded && !bgRedraw) {
|
2020-12-13 13:08:00 +01:00
|
|
|
// get actor position on screen
|
2021-02-25 17:52:13 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
|
2020-12-13 13:08:00 +01:00
|
|
|
|
|
|
|
// check if actor is visible on screen, otherwise don't display it
|
2021-02-26 10:18:07 +01:00
|
|
|
if (_engine->_renderer->projPos.x > -50 && _engine->_renderer->projPos.x < _engine->width() + 40 && _engine->_renderer->projPos.y > -30 && _engine->_renderer->projPos.y < _engine->height() + 100) {
|
2020-12-13 13:08:00 +01:00
|
|
|
actor->dynamicFlags.bIsVisible = 1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// if the actor isn't set as hidden
|
|
|
|
if (actor->entity == -1 || actor->staticFlags.bIsHidden) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// get actor position on screen
|
2021-02-25 17:52:13 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-26 10:18:07 +01:00
|
|
|
if ((actor->staticFlags.bUsesClipping && _engine->_renderer->projPos.x > -112 && _engine->_renderer->projPos.x < _engine->width() + 112 && _engine->_renderer->projPos.y > -50 && _engine->_renderer->projPos.y < _engine->height() + 171) ||
|
|
|
|
((!actor->staticFlags.bUsesClipping) && _engine->_renderer->projPos.x > -50 && _engine->_renderer->projPos.x < _engine->width() + 40 && _engine->_renderer->projPos.y > -30 && _engine->_renderer->projPos.y < _engine->height() + 100)) {
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-25 17:06:23 +01:00
|
|
|
int32 tmpVal = actor->pos.z + actor->pos.x - _engine->_grid->camera.x - _engine->_grid->camera.z;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 13:08:00 +01:00
|
|
|
// if actor is above another actor
|
|
|
|
if (actor->standOn != -1) {
|
|
|
|
const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
|
2021-02-25 17:06:23 +01:00
|
|
|
tmpVal = standOnActor->pos.x - _engine->_grid->camera.x + standOnActor->pos.z - _engine->_grid->camera.z + 2;
|
2020-12-13 13:08:00 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 13:08:00 +01:00
|
|
|
if (actor->staticFlags.bIsSpriteActor) {
|
2020-12-13 13:25:35 +01:00
|
|
|
drawList[drawListPos].type = DrawListType::DrawActorSprites;
|
2020-12-13 13:20:12 +01:00
|
|
|
drawList[drawListPos].actorIdx = modelActorPos;
|
2020-12-13 13:08:00 +01:00
|
|
|
if (actor->staticFlags.bUsesClipping) {
|
2021-02-25 17:12:52 +01:00
|
|
|
tmpVal = actor->lastPos.x - _engine->_grid->camera.x + actor->lastPos.z - _engine->_grid->camera.z;
|
2020-12-13 13:08:00 +01:00
|
|
|
}
|
|
|
|
} else {
|
2020-12-13 13:18:06 +01:00
|
|
|
drawList[drawListPos].type = 0;
|
2020-12-13 13:20:12 +01:00
|
|
|
drawList[drawListPos].actorIdx = modelActorPos;
|
2020-12-13 13:08:00 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 13:08:00 +01:00
|
|
|
drawList[drawListPos].posValue = tmpVal;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 13:08:00 +01:00
|
|
|
drawListPos++;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 13:08:00 +01:00
|
|
|
// if use shadows
|
|
|
|
if (_engine->cfgfile.ShadowMode != 0 && !(actor->staticFlags.bDoesntCastShadow)) {
|
|
|
|
if (actor->standOn != -1) {
|
2021-02-25 17:17:57 +01:00
|
|
|
_engine->_actor->shadowCoord.x = actor->pos.x;
|
|
|
|
_engine->_actor->shadowCoord.y = actor->pos.y - 1;
|
|
|
|
_engine->_actor->shadowCoord.z = actor->pos.z;
|
2020-12-13 13:08:00 +01:00
|
|
|
} else {
|
2021-02-25 17:06:23 +01:00
|
|
|
_engine->_movements->getShadowPosition(actor->pos.x, actor->pos.y, actor->pos.z);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
2020-12-13 13:08:00 +01:00
|
|
|
|
2021-03-02 20:50:11 +01:00
|
|
|
drawList[drawListPos].posValue = tmpVal - 1; // save the shadow entry in the drawList
|
2020-12-13 14:09:31 +01:00
|
|
|
drawList[drawListPos].type = DrawListType::DrawShadows;
|
2020-12-13 13:20:12 +01:00
|
|
|
drawList[drawListPos].actorIdx = 0;
|
2021-02-25 17:17:57 +01:00
|
|
|
drawList[drawListPos].x = _engine->_actor->shadowCoord.x;
|
|
|
|
drawList[drawListPos].y = _engine->_actor->shadowCoord.y;
|
|
|
|
drawList[drawListPos].z = _engine->_actor->shadowCoord.z;
|
2020-12-13 13:08:00 +01:00
|
|
|
drawList[drawListPos].offset = 2;
|
|
|
|
drawListPos++;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
2021-02-10 18:37:55 +01:00
|
|
|
if (inSceneryView && modelActorPos == _engine->_scene->currentlyFollowedActor) {
|
2021-02-26 10:18:07 +01:00
|
|
|
_sceneryViewX = _engine->_renderer->projPos.x;
|
|
|
|
_sceneryViewY = _engine->_renderer->projPos.y;
|
2021-02-10 18:37:55 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
return drawListPos;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:56:46 +01:00
|
|
|
int32 Redraw::fillExtraDrawingList(int32 drawListPos) {
|
2020-10-20 21:21:48 +02:00
|
|
|
for (int32 i = 0; i < EXTRA_MAX_ENTRIES; i++) {
|
2020-10-14 15:16:30 +02:00
|
|
|
ExtraListStruct *extra = &_engine->_extra->extraList[i];
|
2020-12-13 13:08:00 +01:00
|
|
|
if (extra->info0 == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (extra->type & ExtraType::TIME_IN) {
|
|
|
|
if (_engine->lbaTime - extra->spawnTime > 35) {
|
|
|
|
extra->spawnTime = _engine->lbaTime;
|
|
|
|
extra->type &= ~ExtraType::TIME_IN;
|
2021-02-25 19:32:32 +01:00
|
|
|
_engine->_sound->playSample(Samples::ItemPopup, 1, extra->pos);
|
2020-12-13 13:08:00 +01:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((extra->type & ExtraType::TIME_OUT) || (extra->type & ExtraType::FLASH) || (extra->payload.lifeTime + extra->spawnTime - 150 < _engine->lbaTime) || (!((_engine->lbaTime + extra->spawnTime) & 8))) {
|
2021-02-26 09:54:45 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(extra->pos - _engine->_grid->camera);
|
2020-12-13 13:08:00 +01:00
|
|
|
|
2021-02-26 10:18:07 +01:00
|
|
|
if (_engine->_renderer->projPos.x > -50 && _engine->_renderer->projPos.x < _engine->width() + 40 && _engine->_renderer->projPos.y > -30 && _engine->_renderer->projPos.y < _engine->height() + 100) {
|
2021-03-02 22:01:03 +01:00
|
|
|
const int16 tmpVal = extra->pos.x - _engine->_grid->camera.x + extra->pos.z - _engine->_grid->camera.z;
|
|
|
|
drawList[drawListPos].posValue = tmpVal;
|
2020-12-13 13:20:12 +01:00
|
|
|
drawList[drawListPos].actorIdx = i;
|
2020-12-13 13:25:35 +01:00
|
|
|
drawList[drawListPos].type = DrawListType::DrawExtras;
|
2020-12-13 13:08:00 +01:00
|
|
|
drawListPos++;
|
|
|
|
|
2021-02-26 09:43:07 +01:00
|
|
|
if (_engine->cfgfile.ShadowMode == 2 && !(extra->info0 & EXTRA_SPECIAL_MASK)) {
|
2021-02-25 19:32:32 +01:00
|
|
|
_engine->_movements->getShadowPosition(extra->pos.x, extra->pos.y, extra->pos.z);
|
2020-12-13 13:08:00 +01:00
|
|
|
|
2021-03-02 22:01:03 +01:00
|
|
|
drawList[drawListPos].posValue = tmpVal - 1;
|
2020-12-13 13:20:12 +01:00
|
|
|
drawList[drawListPos].actorIdx = 0;
|
2020-12-13 13:25:35 +01:00
|
|
|
drawList[drawListPos].type = DrawListType::DrawShadows;
|
2021-02-25 17:17:57 +01:00
|
|
|
drawList[drawListPos].x = _engine->_actor->shadowCoord.x;
|
|
|
|
drawList[drawListPos].y = _engine->_actor->shadowCoord.y;
|
|
|
|
drawList[drawListPos].z = _engine->_actor->shadowCoord.z;
|
2020-12-13 13:08:00 +01:00
|
|
|
drawList[drawListPos].offset = 0;
|
|
|
|
drawListPos++;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
return drawListPos;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
void Redraw::processDrawListShadows(const DrawListStruct &drawCmd) {
|
2020-12-13 22:51:09 +01:00
|
|
|
// get actor position on screen
|
2021-02-25 15:22:19 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(drawCmd.x - _engine->_grid->camera.x, drawCmd.y - _engine->_grid->camera.y, drawCmd.z - _engine->_grid->camera.z);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
int32 spriteWidth, spriteHeight;
|
|
|
|
_engine->_grid->getSpriteSize(drawCmd.offset, &spriteWidth, &spriteHeight, _engine->_resources->spriteShadowPtr);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
// calculate sprite size and position on screen
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.left = _engine->_renderer->projPos.x - (spriteWidth / 2);
|
|
|
|
renderRect.top = _engine->_renderer->projPos.y - (spriteHeight / 2);
|
|
|
|
renderRect.right = _engine->_renderer->projPos.x + (spriteWidth / 2);
|
|
|
|
renderRect.bottom = _engine->_renderer->projPos.y + (spriteHeight / 2);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-25 05:05:26 +01:00
|
|
|
_engine->_grid->drawSprite(drawCmd.offset, renderRect.left, renderRect.top, _engine->_resources->spriteShadowPtr);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-25 13:08:38 +01:00
|
|
|
const int32 tmpX = (drawCmd.x + BRICK_HEIGHT) / BRICK_SIZE;
|
|
|
|
const int32 tmpY = drawCmd.y / BRICK_HEIGHT;
|
|
|
|
const int32 tmpZ = (drawCmd.z + BRICK_HEIGHT) / BRICK_SIZE;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_grid->drawOverModelActor(tmpX, tmpY, tmpZ);
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
// show clipping area
|
|
|
|
//drawBox(_engine->_renderer->renderRect.left, _engine->_renderer->renderRect.top, _engine->_renderer->renderRect.right, _engine->_renderer->renderRect.bottom);
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
void Redraw::processDrawListActors(const DrawListStruct &drawCmd, bool bgRedraw) {
|
2020-12-22 11:24:57 +01:00
|
|
|
const int32 actorIdx = drawCmd.actorIdx;
|
|
|
|
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
2021-03-02 20:50:11 +01:00
|
|
|
if (actor->previousAnimIdx >= 0) {
|
|
|
|
const uint8 *animPtr = _engine->_resources->animTable[actor->previousAnimIdx];
|
|
|
|
const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
|
|
|
|
_engine->_animations->setModelAnimation(actor->animPosition, animData, animPtr, _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
|
|
|
|
}
|
2020-12-22 11:24:57 +01:00
|
|
|
|
2021-02-25 17:06:23 +01:00
|
|
|
const int32 x = actor->pos.x - _engine->_grid->camera.x;
|
|
|
|
const int32 y = actor->pos.y - _engine->_grid->camera.y;
|
|
|
|
const int32 z = actor->pos.z - _engine->_grid->camera.z;
|
2021-01-08 17:47:54 +01:00
|
|
|
if (!_engine->_renderer->renderIsoModel(x, y, z, ANGLE_0, actor->angle, ANGLE_0, _engine->_actor->bodyTable[actor->entity])) {
|
2020-12-13 23:08:23 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.left < 0) {
|
|
|
|
renderRect.left = 0;
|
2020-12-13 23:08:23 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.top < 0) {
|
|
|
|
renderRect.top = 0;
|
2020-12-13 23:08:23 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.right >= _engine->width()) {
|
|
|
|
renderRect.right = (_engine->width() - 1);
|
2020-12-13 23:08:23 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.bottom >= _engine->height()) {
|
|
|
|
renderRect.bottom = (_engine->height() - 1);
|
2020-12-13 23:08:23 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
|
2020-12-22 11:24:57 +01:00
|
|
|
actor->dynamicFlags.bIsVisible = 1;
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2021-02-25 17:06:23 +01:00
|
|
|
const int32 tempX = (actor->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
|
|
|
|
int32 tempY = actor->pos.y / BRICK_HEIGHT;
|
|
|
|
const int32 tempZ = (actor->pos.z + BRICK_HEIGHT) / BRICK_SIZE;
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->brickShape() != ShapeType::kNone) {
|
2020-12-13 23:08:23 +01:00
|
|
|
tempY++;
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
_engine->_grid->drawOverModelActor(tempX, tempY, tempZ);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
if (_engine->_actor->cropBottomScreen) {
|
|
|
|
renderRect.bottom = _engine->_interface->textWindow.bottom = _engine->_actor->cropBottomScreen + 10;
|
|
|
|
}
|
2020-12-13 22:51:09 +01:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-12-13 23:08:23 +01:00
|
|
|
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->staticFlags.bIsBackgrounded && bgRedraw) {
|
2020-12-30 14:22:45 +01:00
|
|
|
_engine->_interface->blitBox(_engine->_interface->textWindow, _engine->frontVideoBuffer, _engine->workVideoBuffer);
|
2020-12-13 22:51:09 +01:00
|
|
|
}
|
2020-12-22 11:25:07 +01:00
|
|
|
|
|
|
|
_engine->_debugScene->drawClip(renderRect);
|
2020-12-13 22:51:09 +01:00
|
|
|
}
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgRedraw) {
|
2020-12-13 22:51:09 +01:00
|
|
|
int32 actorIdx = drawCmd.actorIdx;
|
2020-12-22 11:24:57 +01:00
|
|
|
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
2020-12-26 11:47:51 +01:00
|
|
|
const SpriteData &spriteData = _engine->_resources->spriteData[actor->entity];
|
|
|
|
// TODO: using the raw pointer and not the SpriteData surface here is a workaround for issue https://bugs.scummvm.org/ticket/12024
|
|
|
|
const uint8 *spritePtr = _engine->_resources->spriteTable[actor->entity];
|
2020-12-13 22:51:09 +01:00
|
|
|
|
|
|
|
// get actor position on screen
|
2021-02-25 17:52:13 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
|
2020-12-13 22:51:09 +01:00
|
|
|
|
2020-12-26 11:47:51 +01:00
|
|
|
const int32 spriteWidth = spriteData.surface().w;
|
|
|
|
const int32 spriteHeight = spriteData.surface().h;
|
2020-12-13 22:51:09 +01:00
|
|
|
|
|
|
|
// calculate sprite position on screen
|
2020-12-24 15:04:57 +01:00
|
|
|
const SpriteDim *dim = _engine->_resources->spriteBoundingBox.dim(actor->entity);
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.left = _engine->_renderer->projPos.x + dim->x;
|
|
|
|
renderRect.top = _engine->_renderer->projPos.y + dim->y;
|
2020-12-13 22:51:09 +01:00
|
|
|
renderRect.right = renderRect.left + spriteWidth;
|
|
|
|
renderRect.bottom = renderRect.top + spriteHeight;
|
|
|
|
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->staticFlags.bUsesClipping) {
|
2021-02-26 10:10:30 +01:00
|
|
|
const Common::Rect rect(_engine->_renderer->projPosScreen.x + actor->cropLeft, _engine->_renderer->projPosScreen.y + actor->cropTop, _engine->_renderer->projPosScreen.x + actor->cropRight, _engine->_renderer->projPosScreen.y + actor->cropBottom);
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_interface->setClip(rect);
|
|
|
|
} else {
|
|
|
|
_engine->_interface->setClip(renderRect);
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
|
2020-12-26 11:47:51 +01:00
|
|
|
_engine->_grid->drawSprite(0, renderRect.left, renderRect.top, spritePtr);
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-22 11:24:57 +01:00
|
|
|
actor->dynamicFlags.bIsVisible = 1;
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->staticFlags.bUsesClipping) {
|
2021-02-25 17:12:52 +01:00
|
|
|
const int32 tmpX = (actor->lastPos.x + BRICK_HEIGHT) / BRICK_SIZE;
|
|
|
|
const int32 tmpY = actor->lastPos.y / BRICK_HEIGHT;
|
|
|
|
const int32 tmpZ = (actor->lastPos.z + BRICK_HEIGHT) / BRICK_SIZE;
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_grid->drawOverSpriteActor(tmpX, tmpY, tmpZ);
|
|
|
|
} else {
|
2021-02-25 17:06:23 +01:00
|
|
|
const int32 tmpX = (actor->pos.x + actor->boudingBox.x.topRight + BRICK_HEIGHT) / BRICK_SIZE;
|
|
|
|
int32 tmpY = actor->pos.y / BRICK_HEIGHT;
|
|
|
|
const int32 tmpZ = (actor->pos.z + actor->boudingBox.z.topRight + BRICK_HEIGHT) / BRICK_SIZE;
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->brickShape() != ShapeType::kNone) {
|
2020-12-13 22:51:09 +01:00
|
|
|
tmpY++;
|
2020-12-13 14:09:31 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_grid->drawOverSpriteActor(tmpX, tmpY, tmpZ);
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-22 11:24:57 +01:00
|
|
|
if (actor->staticFlags.bIsBackgrounded && bgRedraw) {
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_interface->blitBox(_engine->_interface->textWindow, _engine->frontVideoBuffer, _engine->workVideoBuffer);
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
// show clipping area
|
|
|
|
//drawBox(renderRect.left, renderRect.top, renderRect.right, renderRect.bottom);
|
|
|
|
}
|
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
void Redraw::processDrawListExtras(const DrawListStruct &drawCmd) {
|
2020-12-13 22:51:09 +01:00
|
|
|
int32 actorIdx = drawCmd.actorIdx;
|
|
|
|
ExtraListStruct *extra = &_engine->_extra->extraList[actorIdx];
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-25 19:32:32 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(extra->pos - _engine->_grid->camera);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-26 09:43:07 +01:00
|
|
|
if (extra->info0 & EXTRA_SPECIAL_MASK) {
|
2021-02-26 10:18:07 +01:00
|
|
|
_engine->_extra->drawExtraSpecial(actorIdx, _engine->_renderer->projPos.x, _engine->_renderer->projPos.y);
|
2020-12-13 22:51:09 +01:00
|
|
|
} else {
|
2020-12-24 00:09:40 +01:00
|
|
|
const SpriteData &spritePtr = _engine->_resources->spriteData[extra->info0];
|
|
|
|
const int32 spriteWidth = spritePtr.surface().w;
|
|
|
|
const int32 spriteHeight = spritePtr.surface().h;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
// calculate sprite position on screen
|
2020-12-24 15:04:57 +01:00
|
|
|
const SpriteDim *dim = _engine->_resources->spriteBoundingBox.dim(extra->info0);
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.left = _engine->_renderer->projPos.x + dim->x;
|
|
|
|
renderRect.top = _engine->_renderer->projPos.y + dim->y;
|
2020-12-13 22:51:09 +01:00
|
|
|
renderRect.right = renderRect.left + spriteWidth;
|
|
|
|
renderRect.bottom = renderRect.top + spriteHeight;
|
|
|
|
|
2020-12-24 00:11:17 +01:00
|
|
|
_engine->_grid->drawSprite(renderRect.left, renderRect.top, spritePtr);
|
2020-12-13 22:51:09 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
|
2020-12-25 13:08:38 +01:00
|
|
|
const int32 tmpX = (drawCmd.x + BRICK_HEIGHT) / BRICK_SIZE;
|
|
|
|
const int32 tmpY = drawCmd.y / BRICK_HEIGHT;
|
|
|
|
const int32 tmpZ = (drawCmd.z + BRICK_HEIGHT) / BRICK_SIZE;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
_engine->_grid->drawOverModelActor(tmpX, tmpY, tmpZ);
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 22:51:09 +01:00
|
|
|
// show clipping area
|
|
|
|
//drawBox(renderRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Redraw::processDrawList(int32 drawListPos, bool bgRedraw) {
|
|
|
|
for (int32 pos = 0; pos < drawListPos; ++pos) {
|
2020-12-13 23:08:23 +01:00
|
|
|
const DrawListStruct &drawCmd = drawList[pos];
|
2020-12-13 22:51:09 +01:00
|
|
|
const uint32 flags = drawCmd.type;
|
|
|
|
// Drawing actors
|
|
|
|
if (flags < DrawListType::DrawShadows) {
|
|
|
|
if (flags == 0) {
|
|
|
|
processDrawListActors(drawCmd, bgRedraw);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
}
|
2020-12-13 22:51:09 +01:00
|
|
|
// Drawing shadows
|
|
|
|
else if (flags == DrawListType::DrawShadows && !_engine->_actor->cropBottomScreen) {
|
|
|
|
processDrawListShadows(drawCmd);
|
|
|
|
}
|
|
|
|
// Drawing unknown
|
|
|
|
else if (flags < DrawListType::DrawActorSprites) {
|
|
|
|
// TODO reverse this part of the code
|
|
|
|
warning("Not yet reversed part of the rendering code");
|
|
|
|
}
|
|
|
|
// Drawing sprite actors, doors and entities
|
|
|
|
else if (flags == DrawListType::DrawActorSprites) {
|
|
|
|
processDrawListActorSprites(drawCmd, bgRedraw);
|
|
|
|
}
|
|
|
|
// Drawing extras
|
|
|
|
else if (flags == DrawListType::DrawExtras) {
|
|
|
|
processDrawListExtras(drawCmd);
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 14:09:31 +01:00
|
|
|
_engine->_interface->resetClip();
|
2020-12-13 22:51:09 +01:00
|
|
|
}
|
2020-12-13 14:09:31 +01:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-13 15:27:43 +01:00
|
|
|
void Redraw::renderOverlays() {
|
2020-10-20 21:21:48 +02:00
|
|
|
for (int32 i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
|
2020-10-14 14:20:38 +02:00
|
|
|
OverlayListStruct *overlay = &overlayList[i];
|
|
|
|
if (overlay->info0 != -1) {
|
|
|
|
// process position overlay
|
2020-10-14 15:16:30 +02:00
|
|
|
switch (overlay->posType) {
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayPosType::koNormal:
|
2020-10-14 15:16:30 +02:00
|
|
|
if (_engine->lbaTime >= overlay->lifeTime) {
|
2020-10-14 14:20:38 +02:00
|
|
|
overlay->info0 = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayPosType::koFollowActor: {
|
2020-10-25 12:39:40 +01:00
|
|
|
ActorStruct *actor2 = _engine->_scene->getActor(overlay->info1);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-25 17:06:23 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(actor2->pos.x - _engine->_grid->camera.x, actor2->pos.y + actor2->boudingBox.y.topRight - _engine->_grid->camera.y, actor2->pos.z - _engine->_grid->camera.z);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-26 10:18:07 +01:00
|
|
|
overlay->x = _engine->_renderer->projPos.x;
|
|
|
|
overlay->y = _engine->_renderer->projPos.y;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
if (_engine->lbaTime >= overlay->lifeTime) {
|
2020-10-14 14:20:38 +02:00
|
|
|
overlay->info0 = -1;
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// process overlay type
|
2020-10-14 15:16:30 +02:00
|
|
|
switch (overlay->type) {
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayType::koSprite: {
|
2020-12-24 00:09:40 +01:00
|
|
|
const SpriteData &spritePtr = _engine->_resources->spriteData[overlay->info0];
|
|
|
|
const int32 spriteWidth = spritePtr.surface().w;
|
|
|
|
const int32 spriteHeight = spritePtr.surface().h;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-24 15:04:57 +01:00
|
|
|
const SpriteDim *dim = _engine->_resources->spriteBoundingBox.dim(overlay->info0);
|
2020-12-21 15:32:45 +01:00
|
|
|
renderRect.left = dim->x + overlay->x;
|
|
|
|
renderRect.top = dim->y + overlay->y;
|
2020-11-25 18:20:38 +01:00
|
|
|
renderRect.right = renderRect.left + spriteWidth;
|
|
|
|
renderRect.bottom = renderRect.top + spriteHeight;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-24 00:11:17 +01:00
|
|
|
_engine->_grid->drawSprite(renderRect.left, renderRect.top, spritePtr);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayType::koNumber: {
|
2020-10-14 15:16:30 +02:00
|
|
|
char text[10];
|
2020-10-20 21:21:48 +02:00
|
|
|
snprintf(text, sizeof(text), "%d", overlay->info0);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-02 23:17:45 +01:00
|
|
|
const int32 textLength = _engine->_text->getTextSize(text);
|
|
|
|
const int32 textHeight = 48;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
renderRect.left = overlay->x - (textLength / 2);
|
|
|
|
renderRect.top = overlay->y - 24;
|
|
|
|
renderRect.right = overlay->x + (textLength / 2);
|
|
|
|
renderRect.bottom = overlay->y + textHeight;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->_text->setFontColor(overlay->info1);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_text->drawText(renderRect.left, renderRect.top, text);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayType::koNumberRange: {
|
2020-11-02 23:17:45 +01:00
|
|
|
const int32 range = _engine->_collision->getAverageValue(overlay->info1, overlay->info0, 100, overlay->lifeTime - _engine->lbaTime - 50);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-02 23:17:45 +01:00
|
|
|
char text[10];
|
2020-10-14 14:20:38 +02:00
|
|
|
sprintf(text, "%d", range);
|
|
|
|
|
2020-11-02 23:17:45 +01:00
|
|
|
const int32 textLength = _engine->_text->getTextSize(text);
|
|
|
|
const int32 textHeight = 48;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
renderRect.left = overlay->x - (textLength / 2);
|
|
|
|
renderRect.top = overlay->y - 24;
|
|
|
|
renderRect.right = overlay->x + (textLength / 2);
|
|
|
|
renderRect.bottom = overlay->y + textHeight;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-08 19:44:19 +01:00
|
|
|
_engine->_text->setFontColor(COLOR_GOLD);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_text->drawText(renderRect.left, renderRect.top, text);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayType::koInventoryItem: {
|
2020-11-02 23:17:45 +01:00
|
|
|
const int32 item = overlay->info0;
|
2020-11-25 16:59:54 +01:00
|
|
|
const Common::Rect rect(10, 10, 69, 69);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-30 14:35:12 +01:00
|
|
|
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
|
2020-11-25 16:59:54 +01:00
|
|
|
_engine->_interface->setClip(rect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-08 08:20:02 +01:00
|
|
|
uint8* bodyPtr = _engine->_resources->inventoryTable[item];
|
2020-10-14 14:20:38 +02:00
|
|
|
overlayRotation += 1; // overlayRotation += 8;
|
2021-01-08 08:20:02 +01:00
|
|
|
_engine->_renderer->renderInventoryItem(40, 40, bodyPtr, overlayRotation, 16000);
|
2020-11-25 16:59:54 +01:00
|
|
|
_engine->_menu->drawBox(rect);
|
|
|
|
addRedrawArea(rect);
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->_gameState->initEngineProjections();
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-12-07 16:59:29 +01:00
|
|
|
case OverlayType::koText: {
|
2020-10-14 15:16:30 +02:00
|
|
|
char text[256];
|
|
|
|
_engine->_text->getMenuText(overlay->info0, text, sizeof(text));
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-02 23:17:45 +01:00
|
|
|
const int32 textLength = _engine->_text->getTextSize(text);
|
|
|
|
const int32 textHeight = 48;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
renderRect.left = overlay->x - (textLength / 2);
|
|
|
|
renderRect.top = overlay->y - 24;
|
|
|
|
renderRect.right = overlay->x + (textLength / 2);
|
|
|
|
renderRect.bottom = overlay->y + textHeight;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.left < 0) {
|
|
|
|
renderRect.left = 0;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.top < 0) {
|
|
|
|
renderRect.top = 0;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.right > (_engine->width() - 1)) {
|
|
|
|
renderRect.right = (_engine->width() - 1);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2021-01-07 21:17:53 +01:00
|
|
|
if (renderRect.bottom > (_engine->height() - 1)) {
|
|
|
|
renderRect.bottom = (_engine->height() - 1);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-25 12:39:40 +01:00
|
|
|
_engine->_text->setFontColor(_engine->_scene->getActor(overlay->info1)->talkColor);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_text->drawText(renderRect.left, renderRect.top, text);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-30 14:22:45 +01:00
|
|
|
addRedrawArea(_engine->_interface->textWindow);
|
2020-10-25 12:39:40 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-13 15:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Redraw::redrawEngineActions(bool bgRedraw) {
|
2021-02-26 10:23:21 +01:00
|
|
|
int32 tmp_projPosX = _engine->_renderer->projPosScreen.x;
|
|
|
|
int32 tmp_projPosY = _engine->_renderer->projPosScreen.y;
|
2020-12-13 15:27:43 +01:00
|
|
|
|
|
|
|
_engine->_interface->resetClip();
|
|
|
|
|
|
|
|
if (bgRedraw) {
|
|
|
|
_engine->freezeTime();
|
|
|
|
if (_engine->_scene->needChangeScene != -1 && _engine->_scene->needChangeScene != -2) {
|
|
|
|
_engine->_screens->fadeOut(_engine->_screens->paletteRGBA);
|
|
|
|
}
|
|
|
|
_engine->_screens->clearScreen();
|
|
|
|
_engine->_grid->redrawGrid();
|
2021-02-26 10:23:21 +01:00
|
|
|
updateOverlayTypePosition(tmp_projPosX, tmp_projPosY, _engine->_renderer->projPosScreen.x, _engine->_renderer->projPosScreen.y);
|
2020-12-13 15:27:43 +01:00
|
|
|
_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
|
|
|
|
|
|
|
|
if (_engine->_scene->needChangeScene != -1 && _engine->_scene->needChangeScene != -2) {
|
|
|
|
_engine->_screens->fadeIn(_engine->_screens->paletteRGBA);
|
|
|
|
_engine->setPalette(_engine->_screens->paletteRGBA);
|
2021-02-28 20:28:46 +01:00
|
|
|
_engine->flip();
|
2020-12-13 15:27:43 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
blitBackgroundAreas();
|
|
|
|
}
|
|
|
|
|
2020-12-13 22:56:46 +01:00
|
|
|
int32 drawListPos = fillActorDrawingList(bgRedraw);
|
|
|
|
drawListPos = fillExtraDrawingList(drawListPos);
|
2020-12-13 15:27:43 +01:00
|
|
|
sortDrawingList(drawList, drawListPos);
|
|
|
|
|
|
|
|
currNumOfRedrawBox = 0;
|
|
|
|
processDrawList(drawListPos, bgRedraw);
|
|
|
|
|
|
|
|
if (_engine->cfgfile.Debug) {
|
|
|
|
_engine->_debugScene->displayZones();
|
|
|
|
}
|
|
|
|
|
|
|
|
renderOverlays();
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->_interface->resetClip();
|
2020-10-14 14:20:38 +02:00
|
|
|
|
|
|
|
// make celling grid fade
|
|
|
|
// need to be here to fade after drawing all actors in scene
|
2020-10-14 15:16:30 +02:00
|
|
|
if (_engine->_scene->needChangeScene == -2) {
|
2020-10-21 19:53:01 +02:00
|
|
|
_engine->crossFade(_engine->frontVideoBuffer, _engine->_screens->paletteRGBA);
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->_scene->needChangeScene = -1;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bgRedraw) {
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->flip();
|
2020-10-14 14:20:38 +02:00
|
|
|
moveNextAreas();
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->unfreezeTime();
|
2020-10-14 14:20:38 +02:00
|
|
|
} else {
|
|
|
|
flipRedrawAreas();
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
if (_engine->_screens->lockPalette) {
|
|
|
|
if (_engine->_screens->useAlternatePalette) {
|
2020-10-21 19:53:01 +02:00
|
|
|
_engine->_screens->fadeToPal(_engine->_screens->paletteRGBA);
|
2020-10-14 14:20:38 +02:00
|
|
|
} else {
|
2020-10-21 19:53:01 +02:00
|
|
|
_engine->_screens->fadeToPal(_engine->_screens->mainPaletteRGBA);
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
2020-10-22 12:42:57 +02:00
|
|
|
_engine->_screens->lockPalette = false;
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2021-02-10 18:37:55 +01:00
|
|
|
if (_engine->_redraw->inSceneryView) {
|
2020-11-19 23:41:44 +01:00
|
|
|
zoomScreenScale();
|
2020-10-14 15:16:30 +02:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::drawBubble(int32 actorIdx) {
|
2020-10-25 12:39:40 +01:00
|
|
|
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
// get actor position on screen
|
2021-02-25 17:06:23 +01:00
|
|
|
_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y + actor->boudingBox.y.topRight - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
if (actorIdx != bubbleActor) {
|
|
|
|
bubbleSpriteIndex = bubbleSpriteIndex ^ 1;
|
|
|
|
bubbleActor = actorIdx;
|
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-24 00:09:40 +01:00
|
|
|
const SpriteData &spritePtr = _engine->_resources->spriteData[bubbleSpriteIndex];
|
|
|
|
const int32 spriteWidth = spritePtr.surface().w;
|
|
|
|
const int32 spriteHeight = spritePtr.surface().h;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
// calculate sprite position on screen
|
|
|
|
if (bubbleSpriteIndex == SPRITEHQR_DIAG_BUBBLE_RIGHT) {
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.left = _engine->_renderer->projPos.x + 10;
|
2020-10-14 15:16:30 +02:00
|
|
|
} else {
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.left = _engine->_renderer->projPos.x - 10 - spriteWidth;
|
2020-10-14 15:16:30 +02:00
|
|
|
}
|
2021-02-26 10:18:07 +01:00
|
|
|
renderRect.top = _engine->_renderer->projPos.y - 20;
|
2020-11-25 18:20:38 +01:00
|
|
|
renderRect.right = spriteWidth + renderRect.left - 1;
|
|
|
|
renderRect.bottom = spriteHeight + renderRect.top - 1;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-25 18:20:38 +01:00
|
|
|
_engine->_interface->setClip(renderRect);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-25 04:58:32 +01:00
|
|
|
if (_engine->_grid->drawSprite(renderRect.left, renderRect.top, spritePtr)) {
|
2021-01-09 18:42:25 +01:00
|
|
|
_engine->copyBlockPhys(renderRect, true);
|
2020-10-14 15:16:30 +02:00
|
|
|
}
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
_engine->_interface->resetClip();
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
void Redraw::zoomScreenScale() {
|
2021-02-10 18:41:27 +01:00
|
|
|
Graphics::ManagedSurface zoomWorkVideoBuffer(_engine->workVideoBuffer);
|
|
|
|
const int maxW = zoomWorkVideoBuffer.w;
|
|
|
|
const int maxH = zoomWorkVideoBuffer.h;
|
|
|
|
const int left = CLIP<int>(_sceneryViewX - maxW / 4, 0, maxW / 2);
|
|
|
|
const int top = CLIP<int>(_sceneryViewY - maxH / 4, 0, maxH / 2);
|
|
|
|
const Common::Rect srcRect(left, top, left + maxW / 2, top + maxH / 2);
|
|
|
|
const Common::Rect& destRect = zoomWorkVideoBuffer.getBounds();
|
|
|
|
zoomWorkVideoBuffer.transBlitFrom(_engine->frontVideoBuffer, srcRect, destRect);
|
|
|
|
g_system->copyRectToScreen(zoomWorkVideoBuffer.getPixels(), zoomWorkVideoBuffer.pitch, 0, 0, zoomWorkVideoBuffer.w, zoomWorkVideoBuffer.h);
|
|
|
|
g_system->updateScreen();
|
2020-10-14 14:20:38 +02:00
|
|
|
}
|
2020-10-14 15:16:30 +02:00
|
|
|
|
|
|
|
} // namespace TwinE
|