implemented per scene actors clipping

so last sequence should look much better (not perfect)

svn-id: r18516
This commit is contained in:
Andrew Kurushin 2005-07-08 16:56:03 +00:00
parent 7e0033983f
commit d944bd7793
17 changed files with 195 additions and 261 deletions

View file

@ -1225,8 +1225,9 @@ void Actor::direct(int msec) {
}
void Actor::calcScreenPosition(CommonObjectData *commonObjectData) {
bool Actor::calcScreenPosition(CommonObjectData *commonObjectData) {
int beginSlope, endSlope, middle;
bool result;
if (_vm->_scene->getFlags() & kSceneFlagISO) {
_vm->_isoMap->tileCoordsToScreenPoint(commonObjectData->location, commonObjectData->screenPosition);
commonObjectData->screenScale = 256;
@ -1252,6 +1253,12 @@ void Actor::calcScreenPosition(CommonObjectData *commonObjectData) {
commonObjectData->location.toScreenPointXYZ(commonObjectData->screenPosition);
}
result = commonObjectData->screenPosition.x > -64 &&
commonObjectData->screenPosition.x < _vm->getDisplayWidth() + 64 &&
commonObjectData->screenPosition.y > -64 &&
commonObjectData->screenPosition.y < _vm->getSceneHeight() + 64;
return result;
}
uint16 Actor::hitTest(const Point &testPoint, bool skipProtagonist) {
@ -1262,17 +1269,8 @@ uint16 Actor::hitTest(const Point &testPoint, bool skipProtagonist) {
// fine to interact with. For example, the door entrance at the glass
// makers's house in ITE's ferret village.
SCENE_BGINFO bg_info;
Common::Rect sceneRect;
_vm->_scene->getBGInfo(&bg_info);
sceneRect.left = bg_info.bg_x;
sceneRect.top = bg_info.bg_y;
sceneRect.right = bg_info.bg_x + bg_info.bg_w;
sceneRect.bottom = bg_info.bg_y + bg_info.bg_h;
if (!sceneRect.contains(testPoint))
if (!_vm->_scene->getSceneClip().contains(testPoint))
return ID_NOTHING;
CommonObjectOrderList::iterator drawOrderIterator;
@ -1328,7 +1326,9 @@ void Actor::createDrawOrderList() {
continue;
_drawOrderList.pushBack(obj, compareFunction);
calcScreenPosition(obj);
if (!calcScreenPosition(obj)) {
warning("calcScreenPosition return false actorIdx=%i", i);
}
}
}
@ -1393,7 +1393,7 @@ void Actor::drawActors() {
if (_vm->_scene->getFlags() & kSceneFlagISO) {
_vm->_isoMap->drawSprite(back_buf, *spriteList, frameNumber, drawObject->location, drawObject->screenPosition, drawObject->screenScale);
} else {
_vm->_sprite->drawOccluded(back_buf, *spriteList, frameNumber, drawObject->screenPosition, drawObject->screenScale, drawObject->screenDepth);
_vm->_sprite->drawOccluded(back_buf, _vm->_scene->getSceneClip(),*spriteList, frameNumber, drawObject->screenPosition, drawObject->screenScale, drawObject->screenDepth);
}
}

View file

@ -568,7 +568,7 @@ private:
void stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, bool stopped);
void createDrawOrderList();
void calcScreenPosition(CommonObjectData *commonObjectData);
bool calcScreenPosition(CommonObjectData *commonObjectData);
bool getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber, SpriteList *&spriteList);
bool followProtagonist(ActorData *actor);

View file

@ -125,7 +125,7 @@ int Events::handleContinuous(EVENT *event) {
int event_done = 0;
BUFFER_INFO buf_info;
SCENE_BGINFO bg_info;
BGInfo bgInfo;
event_pc = ((double)event->duration - event->time) / event->duration;
@ -162,10 +162,10 @@ int Events::handleContinuous(EVENT *event) {
switch (event->op) {
case EVENT_DISSOLVE:
_vm->_render->getBufferInfo(&buf_info);
_vm->_scene->getBGInfo(&bg_info);
_vm->_scene->getBGInfo(bgInfo);
_vm->transitionDissolve(buf_info.bg_buf, buf_info.bg_buf_w,
buf_info.bg_buf_h, buf_info.bg_buf_w, bg_info.bg_buf, bg_info.bg_w,
bg_info.bg_h, bg_info.bg_p, 0, 0, 0, event_pc);
buf_info.bg_buf_h, buf_info.bg_buf_w, bgInfo.buffer, bgInfo.bounds.width(),
bgInfo.bounds.height(), 0, 0, 0, event_pc);
break;
case EVENT_DISSOLVE_BGMASK:
// we dissolve it centered.
@ -177,7 +177,7 @@ int Events::handleContinuous(EVENT *event) {
_vm->_render->getBufferInfo(&buf_info);
_vm->_scene->getBGMaskInfo(w, h, mask_buf, len);
_vm->transitionDissolve(buf_info.bg_buf, buf_info.bg_buf_w,
buf_info.bg_buf_h, buf_info.bg_buf_w, mask_buf, w, h, 0, 1,
buf_info.bg_buf_h, buf_info.bg_buf_w, mask_buf, w, h, 1,
(320 - w) / 2, (200 - h) / 2, event_pc);
break;
default:
@ -254,7 +254,7 @@ int Events::handleOneShot(EVENT *event) {
ScriptThread *sthread;
Rect rect;
static SCENE_BGINFO bginfo;
static BGInfo bgInfo;
if (event->time > 0) {
return EVENT_CONTINUE;
@ -301,29 +301,29 @@ int Events::handleOneShot(EVENT *event) {
back_buf = _vm->_gfx->getBackBuffer();
_vm->_render->getBufferInfo(&rbuf_info);
_vm->_scene->getBGInfo(&bginfo);
_vm->_scene->getBGInfo(bgInfo);
bg_pt.x = bginfo.bg_x;
bg_pt.y = bginfo.bg_y;
bg_pt.x = bgInfo.bounds.left;
bg_pt.y = bgInfo.bounds.top;
bufToBuffer(rbuf_info.bg_buf, rbuf_info.bg_buf_w, rbuf_info.bg_buf_h,
bginfo.bg_buf, bginfo.bg_w, bginfo.bg_h, NULL, &bg_pt);
bgInfo.buffer, bgInfo.bounds.width(), bgInfo.bounds.height(), NULL, &bg_pt);
// If it is inset scene then draw black border
if (bginfo.bg_w < _vm->getDisplayWidth() || bginfo.bg_h < _vm->getSceneHeight()) {
if (bgInfo.bounds.width() < _vm->getDisplayWidth() || bgInfo.bounds.height() < _vm->getSceneHeight()) {
SURFACE s;
s.pixels = rbuf_info.bg_buf;
s.w = s.pitch = rbuf_info.bg_buf_w;
s.h = rbuf_info.bg_buf_h;
s.bytesPerPixel = 1;
Common::Rect rect1(2, bginfo.bg_h + 4);
Common::Rect rect2(bginfo.bg_w + 4, 2);
Common::Rect rect3(2, bginfo.bg_h + 4);
Common::Rect rect4(bginfo.bg_w + 4, 2);
rect1.moveTo(bginfo.bg_x - 2, bginfo.bg_y - 2);
rect2.moveTo(bginfo.bg_x - 2, bginfo.bg_y - 2);
rect3.moveTo(bginfo.bg_x + bginfo.bg_w, bginfo.bg_y - 2);
rect4.moveTo(bginfo.bg_x - 2, bginfo.bg_y + bginfo.bg_h);
Common::Rect rect1(2, bgInfo.bounds.height() + 4);
Common::Rect rect2(bgInfo.bounds.width() + 4, 2);
Common::Rect rect3(2, bgInfo.bounds.height() + 4);
Common::Rect rect4(bgInfo.bounds.width() + 4, 2);
rect1.moveTo(bgInfo.bounds.left - 2, bgInfo.bounds.top - 2);
rect2.moveTo(bgInfo.bounds.left - 2, bgInfo.bounds.top - 2);
rect3.moveTo(bgInfo.bounds.right, bgInfo.bounds.top - 2);
rect4.moveTo(bgInfo.bounds.left - 2, bgInfo.bounds.bottom);
drawRect(&s, rect1, kITEColorBlack);
drawRect(&s, rect2, kITEColorBlack);

View file

@ -1060,6 +1060,8 @@ int SagaEngine::loadGame(int gameNumber) {
_gameNumber = gameNumber;
_gameDescription = &gameDescriptions[gameNumber];
_gameDisplayInfo = *_gameDescription->gameDisplayInfo;
_displayClip.right = _gameDisplayInfo.logicalWidth;
_displayClip.bottom = _gameDisplayInfo.logicalHeight;
gameFileCount = _gameDescription->filesCount;

View file

@ -396,55 +396,6 @@ int drawPolyLine(SURFACE *ds, const Point *pts, int pt_ct, int draw_color) {
return SUCCESS;
}
int getClipInfo(CLIPINFO *clipinfo) {
Common::Rect s;
int d_x, d_y;
Common::Rect clip;
if (clipinfo == NULL) {
return FAILURE;
}
if (clipinfo->dst_pt != NULL) {
d_x = clipinfo->dst_pt->x;
d_y = clipinfo->dst_pt->y;
} else {
d_x = 0;
d_y = 0;
}
// Get the clip rect.
clip.left = clipinfo->dst_rect->left;
clip.right = clipinfo->dst_rect->right;
clip.top = clipinfo->dst_rect->top;
clip.bottom = clipinfo->dst_rect->bottom;
// Adjust the rect to draw to its screen coordinates
s.left = d_x + clipinfo->src_rect->left;
s.right = d_x + clipinfo->src_rect->right;
s.top = d_y + clipinfo->src_rect->top;
s.bottom = d_y + clipinfo->src_rect->bottom;
s.clip(clip);
if (s.width() <= 0 || s.height() <= 0) {
clipinfo->nodraw = 1;
return SUCCESS;
}
clipinfo->nodraw = 0;
clipinfo->src_draw_x = s.left - clipinfo->src_rect->left - d_x;
clipinfo->src_draw_y = s.top - clipinfo->src_rect->top - d_y;
clipinfo->dst_draw_x = s.left;
clipinfo->dst_draw_y = s.top;
clipinfo->draw_w = s.width();
clipinfo->draw_h = s.height();
return SUCCESS;
}
SURFACE *Gfx::getBackBuffer() {
return &_back_buf;

View file

@ -33,20 +33,43 @@ namespace Saga {
using Common::Point;
using Common::Rect;
struct CLIPINFO {
struct ClipData {
// input members
const Rect *src_rect;
const Rect *dst_rect;
const Point *dst_pt;
Rect sourceRect;
Rect destRect;
Point destPoint;
// output members
int nodraw;
int src_draw_x;
int src_draw_y;
int dst_draw_x;
int dst_draw_y;
int draw_w;
int draw_h;
Point sourceDraw;
Point destDraw;
int width;
int height;
bool calcClip() {
Common::Rect s;
// Adjust the rect to draw to its screen coordinates
s = sourceRect;
s.left += destPoint.x;
s.right += destPoint.x;
s.top += destPoint.y;
s.bottom += destPoint.y;
s.clip(destRect);
if ((s.width() <= 0) || (s.height() <= 0)) {
return false;
}
sourceDraw.x = s.left - sourceRect.left - destPoint.x;
sourceDraw.y = s.top - sourceRect.top - destPoint.y;
destDraw.x = s.left;
destDraw.y = s.top;
width = s.width();
height = s.height();
return true;
}
};
struct PALENTRY {
@ -78,7 +101,6 @@ int drawPalette(SURFACE *dst_s);
int bufToSurface(SURFACE *ds, const byte *src, int src_w, int src_h, Rect *src_rect, Point *dst_pt);
int bufToBuffer(byte * dst_buf, int dst_w, int dst_h, const byte *src,
int src_w, int src_h, Rect *src_rect, Point *dst_pt);
int getClipInfo(CLIPINFO *clipinfo);
int drawRect(SURFACE *ds, Rect &dst_rect, int color);
int drawFrame(SURFACE *ds, const Point *p1, const Point *p2, int color);
int drawPolyLine(SURFACE *ds, const Point *pts, int pt_ct, int draw_color);

View file

@ -528,7 +528,7 @@ void Interface::drawVerbPanel(SURFACE *backBuffer, PanelButton* panelButton) {
point.x = _mainPanel.x + panelButton->xOffset;
point.y = _mainPanel.y + panelButton->yOffset;
_vm->_sprite->draw(backBuffer, _mainPanel.sprites, spriteNumber, point, 256);
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _mainPanel.sprites, spriteNumber, point, 256);
drawVerbPanelText(backBuffer, panelButton, textColor, _vm->getDisplayInfo().verbTextShadowColor);
}
@ -577,7 +577,7 @@ void Interface::draw() {
_lockedMode == kPanelMain || _lockedMode == kPanelConverse) {
leftPortraitPoint.x = _mainPanel.x + _vm->getDisplayInfo().leftPortraitXOffset;
leftPortraitPoint.y = _mainPanel.y + _vm->getDisplayInfo().leftPortraitYOffset;
_vm->_sprite->draw(backBuffer, _defPortraits, _leftPortrait, leftPortraitPoint, 256);
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _defPortraits, _leftPortrait, leftPortraitPoint, 256);
}
if (!_inMainMode && _vm->getDisplayInfo().rightPortraitXOffset >= 0) { //FIXME: should we change !_inMainMode to _panelMode == kPanelConverse ?
@ -592,7 +592,7 @@ void Interface::draw() {
if (_rightPortrait >= _scenePortraits.spriteCount)
_rightPortrait = 0;
_vm->_sprite->draw(backBuffer, _scenePortraits, _rightPortrait, rightPortraitPoint, 256);
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _scenePortraits, _rightPortrait, rightPortraitPoint, 256);
}
drawInventory(backBuffer);
@ -1345,7 +1345,7 @@ void Interface::drawStatusBar() {
rect.right = rect.left + _vm->getDisplayInfo().saveReminderWidth;
rect.bottom = rect.top + _vm->getDisplayInfo().saveReminderHeight;
_vm->_sprite->draw(backBuffer, _vm->_sprite->_mainSprites,
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _vm->_sprite->_mainSprites,
_saveReminderState == 1 ? _vm->getDisplayInfo().saveReminderFirstSpriteNumber : _vm->getDisplayInfo().saveReminderSecondSpriteNumber,
rect, 256);
@ -1561,7 +1561,7 @@ void Interface::drawInventory(SURFACE *backBuffer) {
point.x = rect.left;
point.y = rect.top;
obj = _vm->_actor->getObj(_inventory[ci]);
_vm->_sprite->draw(backBuffer, _vm->_sprite->_mainSprites, obj->spriteListResourceId, rect, 256);
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _vm->_sprite->_mainSprites, obj->spriteListResourceId, rect, 256);
ci++;
}
@ -1729,7 +1729,7 @@ void Interface::drawPanelButtonArrow(SURFACE *ds, InterfacePanel *panel, PanelBu
point.x = panel->x + panelButton->xOffset;
point.y = panel->y + panelButton->yOffset;
_vm->_sprite->draw(ds, _vm->_sprite->_mainSprites, spriteNumber, point, 256);
_vm->_sprite->draw(ds, _vm->getDisplayClip(), _vm->_sprite->_mainSprites, spriteNumber, point, 256);
}
void Interface::drawVerbPanelText(SURFACE *ds, PanelButton *panelButton, int textColor, int textShadowColor) {
@ -2113,7 +2113,7 @@ void Interface::mapPanelDrawCrossHair() {
Rect screen(_vm->getDisplayWidth(), _vm->getSceneHeight());
if (screen.contains(mapPosition)) {
_vm->_sprite->draw(backBuffer, _vm->_sprite->_mainSprites,
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _vm->_sprite->_mainSprites,
_mapPanelCrossHairState? RID_ITE_SPR_XHAIR1 : RID_ITE_SPR_XHAIR2,
mapPosition, 256);
}

View file

@ -379,7 +379,7 @@ int16 IsoMap::findMulti(int16 tileIndex, int16 absU, int16 absV, int16 absH) {
int IsoMap::draw(SURFACE *ds) {
Rect isoRect(_vm->getDisplayWidth(), _vm->getClippedSceneHeight());
Rect isoRect(_vm->_scene->getSceneClip());
drawRect(ds, isoRect, 0);
_tileClip = isoRect;
drawTiles(ds, NULL);
@ -399,7 +399,7 @@ void IsoMap::drawSprite(SURFACE *ds, SpriteList &spriteList, int spriteNumber, c
int yAlign;
const byte *spriteBuffer;
Point spritePointer;
Rect clip(_vm->getDisplayWidth(), _vm->getClippedSceneHeight());
Rect clip(_vm->_scene->getSceneClip());
_vm->_sprite->getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer);

View file

@ -267,7 +267,7 @@ void Puzzle::showPieces(void) {
int num = _piecePriority[j];
if (_puzzlePiece != num) {
_vm->_sprite->draw(backBuffer, puzzle->spriteList, num, Point(_pieceInfo[num].curX, _pieceInfo[num].curY), 256);
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), puzzle->spriteList, num, Point(_pieceInfo[num].curX, _pieceInfo[num].curY), 256);
}
}
}
@ -275,14 +275,9 @@ void Puzzle::showPieces(void) {
void Puzzle::drawCurrentPiece() {
ActorData *puzzle = _vm->_actor->getActor(_vm->_actor->actorIndexToId(ITE_ACTOR_PUZZLE));
SURFACE *backBuffer = _vm->_gfx->getBackBuffer();
SCENE_BGINFO bg_info;
_vm->_scene->getBGInfo(&bg_info);
Rect clip(bg_info.bg_x, bg_info.bg_y, bg_info.bg_x + bg_info.bg_w, bg_info.bg_y + bg_info.bg_h);
_vm->_sprite->draw(backBuffer, puzzle->spriteList, _puzzlePiece,
Point(_pieceInfo[_puzzlePiece].curX, _pieceInfo[_puzzlePiece].curY), 256, &clip);
_vm->_sprite->draw(backBuffer, _vm->_scene->getSceneClip(), puzzle->spriteList, _puzzlePiece,
Point(_pieceInfo[_puzzlePiece].curX, _pieceInfo[_puzzlePiece].curY), 256);
}
void Puzzle::movePiece(Point mousePt) {

View file

@ -165,6 +165,7 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_displayClip.left = _displayClip.top = 0;
_vm = this;
}
@ -302,6 +303,10 @@ int SagaEngine::go() {
_previousTicks = _system->getMillis();
if (ConfMan.hasKey("start_scene")) {
_scene->changeScene(ConfMan.getInt("start_scene"), 0, kTransitionNoFade);
}
else
if (ConfMan.hasKey("save_slot")) {
// First scene sets up palette
_scene->changeScene(getStartSceneNumber(), 0, kTransitionNoFade);

View file

@ -587,7 +587,7 @@ public:
int textProcessList(TEXTLIST *textlist, long ms);
int transitionDissolve(byte *dst_img, int dst_w, int dst_h, int dst_p,
const byte *src_img, int src_w, int src_h, int src_p, int flags, int x, int y,
const byte *src_img, int src_w, int src_h, int flags, int x, int y,
double percent);
int processInput(void);
@ -627,6 +627,7 @@ public:
int _gameNumber;
GameDescription *_gameDescription;
GameDisplayInfo _gameDisplayInfo;
Common::Rect _displayClip;
public:
int initGame(void);
@ -649,6 +650,7 @@ public:
int getStartSceneNumber() const { return _gameDescription->startSceneNumber; }
const Common::Rect &getDisplayClip() const { return _displayClip;}
int getDisplayWidth() const { return _gameDisplayInfo.logicalWidth; }
int getDisplayHeight() const { return _gameDisplayInfo.logicalHeight;}
int getSceneHeight() const { return _gameDisplayInfo.sceneHeight; }

View file

@ -267,32 +267,22 @@ void Scene::getSlopes(int &beginSlope, int &endSlope) {
endSlope = _vm->getSceneHeight() - _sceneDescription.endSlope;
}
int Scene::getBGInfo(SCENE_BGINFO *bginfo) {
int x, y;
assert(_initialized);
bginfo->bg_buf = _bg.buf;
bginfo->bg_buflen = _bg.buf_len;
bginfo->bg_w = _bg.w;
bginfo->bg_h = _bg.h;
bginfo->bg_p = _bg.p;
x = 0;
y = 0;
void Scene::getBGInfo(BGInfo &bgInfo) {
bgInfo.buffer = _bg.buf;
bgInfo.bufferLength = _bg.buf_len;
bgInfo.bounds.left = 0;
bgInfo.bounds.top = 0;
if (_bg.w < _vm->getDisplayWidth()) {
x = (_vm->getDisplayWidth() - _bg.w) / 2;
bgInfo.bounds.left = (_vm->getDisplayWidth() - _bg.w) / 2;
}
if (_bg.h < _vm->getSceneHeight()) {
y = (_vm->getSceneHeight() - _bg.h) / 2;
bgInfo.bounds.top = (_vm->getClippedSceneHeight() - _bg.h) / 2;
}
bginfo->bg_x = x;
bginfo->bg_y = y;
return SUCCESS;
bgInfo.bounds.setWidth(_bg.w);
bgInfo.bounds.setHeight(_bg.h);
}
int Scene::getBGPal(PALENTRY **pal) {
@ -456,7 +446,16 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
if (_sceneDescription.flags & kSceneFlagISO) {
_outsetSceneNumber = _sceneNumber;
_sceneClip.left = 0;
_sceneClip.top = 0;
_sceneClip.right = _vm->getDisplayWidth();
_sceneClip.bottom = _vm->getClippedSceneHeight();
} else {
BGInfo backGroundInfo;
getBGInfo(backGroundInfo);
_sceneClip = backGroundInfo.bounds;
if (!(_bg.w < _vm->getDisplayWidth() || _bg.h < _vm->getSceneHeight()))
_outsetSceneNumber = _sceneNumber;
}

View file

@ -43,14 +43,10 @@ enum SceneFlags {
kSceneFlagShowCursor = 2
};
struct SCENE_BGINFO {
int bg_x;
int bg_y;
int bg_w;
int bg_h;
int bg_p;
byte *bg_buf;
size_t bg_buflen;
struct BGInfo {
Rect bounds;
byte *buffer;
size_t bufferLength;
};
typedef int (SceneProc) (int, void *);
@ -232,7 +228,8 @@ class Scene {
int getFlags() const { return _sceneDescription.flags; }
int getScriptModuleNumber() const { return _sceneDescription.scriptModuleNumber; }
bool isInDemo() { return !_inGame; }
const Rect& getSceneClip() const { return _sceneClip; }
void getBGMaskInfo(int &width, int &height, byte *&buffer, size_t &bufferLength);
int isBGMaskPresent() { return _bgMask.loaded; }
int getBGMaskType(const Point &testPoint);
@ -244,7 +241,7 @@ class Scene {
int getDoorState(int doorNumber);
void initDoorsState();
int getBGInfo(SCENE_BGINFO *bginfo);
void getBGInfo(BGInfo &bgInfo);
int getBGPal(PALENTRY **pal);
void getSlopes(int &beginSlope, int &endSlope);
@ -296,7 +293,8 @@ class Scene {
SceneProc *_sceneProc;
SCENE_IMAGE _bg;
SCENE_IMAGE _bgMask;
Common::Rect _sceneClip;
int _sceneDoors[SCENE_DOORS_MAX];

View file

@ -1050,7 +1050,7 @@ void Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
frameType = thread->pop();
frameOffset = thread->pop();
debug(1, "sfPlaceActor(%d, %d, %d, %d, %d, %d)", actorId, actorLocation.x,
debug(1, "sfPlaceActor(id = %d, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actorLocation.x,
actorLocation.y, actorDirection, frameType, frameOffset);
if (_vm->getGameType() == GType_IHNM) {
@ -1241,7 +1241,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
event.data = back_buf;
event.param = 138;
event.param2 = 0;
event.param3 = _vm->getSceneHeight();
event.param3 = _vm->getClippedSceneHeight();
event.param4 = 0;
event.param5 = _vm->getDisplayWidth();
@ -1258,7 +1258,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
text_entry.color = kITEColorBrightWhite;
text_entry.effect_color = kITEColorBlack;
text_entry.text_x = _vm->getDisplayWidth() / 2;
text_entry.text_y = (_vm->getSceneHeight() - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2;
text_entry.text_y = (_vm->getClippedSceneHeight() - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2;
text_entry.font_id = MEDIUM_FONT_ID;
text_entry.flags = FONT_OUTLINE | FONT_CENTERED;
text_entry.string = thread->_strings->getString(stringId);
@ -1556,19 +1556,17 @@ void Script::sfGetActorY(SCRIPTFUNC_PARAMS) {
// Script function #62 (0x3E)
void Script::sfEraseDelta(SCRIPTFUNC_PARAMS) {
BUFFER_INFO bufferInfo;
SCENE_BGINFO backGroundInfo;
BGInfo backGroundInfo;
Point backGroundPoint;
_vm->_render->getBufferInfo(&bufferInfo);
_vm->_scene->getBGInfo(&backGroundInfo);
backGroundPoint.x = backGroundInfo.bg_x;
backGroundPoint.y = backGroundInfo.bg_y;
_vm->_scene->getBGInfo(backGroundInfo);
backGroundPoint.x = backGroundInfo.bounds.left;
backGroundPoint.y = backGroundInfo.bounds.top;
bufToBuffer(bufferInfo.bg_buf, bufferInfo.bg_buf_w, bufferInfo.bg_buf_h,
backGroundInfo.bg_buf, backGroundInfo.bg_w, backGroundInfo.bg_h,
backGroundInfo.buffer, backGroundInfo.bounds.width(), backGroundInfo.bounds.height(),
NULL, &backGroundPoint);
}
// Script function #63 (0x3F)

View file

@ -170,7 +170,7 @@ void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int
}
void Sprite::drawClip(SURFACE *ds, Rect clip, const Point &spritePointer, int width, int height, const byte *spriteBuffer) {
void Sprite::drawClip(SURFACE *ds, const Rect &clipRect, const Point &spritePointer, int width, int height, const byte *spriteBuffer) {
int clipWidth;
int clipHeight;
@ -182,22 +182,22 @@ void Sprite::drawClip(SURFACE *ds, Rect clip, const Point &spritePointer, int wi
srcRowPointer = spriteBuffer;
clipWidth = width;
if (width > (clip.right - spritePointer.x)) {
clipWidth = (clip.right - spritePointer.x);
if (width > (clipRect.right - spritePointer.x)) {
clipWidth = (clipRect.right - spritePointer.x);
}
clipHeight = height;
if (height > (clip.bottom - spritePointer.y)) {
clipHeight = (clip.bottom - spritePointer.y);
if (height > (clipRect.bottom - spritePointer.y)) {
clipHeight = (clipRect.bottom - spritePointer.y);
}
jo = 0;
io = 0;
if (spritePointer.x < clip.left) {
jo = clip.left - spritePointer.x;
if (spritePointer.x < clipRect.left) {
jo = clipRect.left - spritePointer.x;
}
if (spritePointer.y < clip.top) {
io = clip.top - spritePointer.y;
if (spritePointer.y < clipRect.top) {
io = clipRect.top - spritePointer.y;
bufRowPointer += ds->pitch * io;
srcRowPointer += width * io;
}
@ -217,60 +217,29 @@ void Sprite::drawClip(SURFACE *ds, Rect clip, const Point &spritePointer, int wi
}
}
int Sprite::draw(SURFACE *ds, SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale, Rect *clipOverride) {
void Sprite::draw(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale) {
const byte *spriteBuffer;
int width;
int height;
int xAlign;
int yAlign;
Point spritePointer;
Rect clip;
assert(_initialized);
if (clipOverride) {
clip.left = clipOverride->left;
clip.right = clipOverride->right;
clip.top = clipOverride->top;
clip.bottom = clipOverride->bottom;
} else {
clip.left = 0;
clip.right = _vm->getDisplayWidth();
clip.top = 0;
clip.bottom = _vm->getDisplayHeight();
}
getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer);
spritePointer.x = screenCoord.x + xAlign;
spritePointer.y = screenCoord.y + yAlign;
drawClip(ds, clip, spritePointer, width, height, spriteBuffer);
return SUCCESS;
drawClip(ds, clipRect, spritePointer, width, height, spriteBuffer);
}
int Sprite::draw(SURFACE *ds, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale, Rect *clipOverride) {
void Sprite::draw(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale) {
const byte *spriteBuffer;
int width;
int height;
int xAlign, spw;
int yAlign, sph;
Point spritePointer;
Rect clip;
assert(_initialized);
if (clipOverride) {
clip.left = clipOverride->left;
clip.right = clipOverride->right;
clip.top = clipOverride->top;
clip.bottom = clipOverride->bottom;
} else {
clip.left = 0;
clip.right = _vm->getDisplayWidth();
clip.top = 0;
clip.bottom = _vm->getDisplayHeight();
}
getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer);
spw = (screenRect.width() - width) / 2;
@ -283,9 +252,7 @@ int Sprite::draw(SURFACE *ds, SpriteList &spriteList, int32 spriteNumber, const
}
spritePointer.x = screenRect.left + xAlign + spw;
spritePointer.y = screenRect.top + yAlign + sph;
drawClip(ds, clip, spritePointer, width, height, spriteBuffer);
return SUCCESS;
drawClip(ds, clipRect, spritePointer, width, height, spriteBuffer);
}
bool Sprite::hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint) {
@ -316,97 +283,80 @@ bool Sprite::hitTest(SpriteList &spriteList, int spriteNumber, const Point &scre
return *srcRowPointer != 0;
}
int Sprite::drawOccluded(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth) {
void Sprite::drawOccluded(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth) {
const byte *spriteBuffer;
int x, y;
byte *dst_row_p;
const byte *src_row_p;
const byte *src_p;
byte *dst_p;
byte *mask_p;
byte *destRowPointer;
const byte *sourceRowPointer;
const byte *sourcePointer;
byte *destPointer;
byte *maskPointer;
int width;
int height;
int xAlign;
int yAlign;
Point spritePointer;
// Clipinfo variables
Rect spriteSourceRect;
Rect spriteDestRect;
CLIPINFO ci;
ClipData clipData;
// BG mask variables
int maskWidth;
int maskHeight;
byte *maskBuffer;
size_t maskBufferLength;
byte *mask_row_p;
int mask_z;
byte *maskRowPointer;
int maskZ;
assert(_initialized);
if (!_vm->_scene->isBGMaskPresent()) {
return draw(ds, spriteList, spriteNumber, screenCoord, scale);
draw(ds, clipRect, spriteList, spriteNumber, screenCoord, scale);
return;
}
_vm->_scene->getBGMaskInfo(maskWidth, maskHeight, maskBuffer, maskBufferLength);
getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer);
spritePointer.x = screenCoord.x + xAlign;
spritePointer.y = screenCoord.y + yAlign;
spriteSourceRect.left = 0;
spriteSourceRect.top = 0;
spriteSourceRect.right = width;
spriteSourceRect.bottom = height;
SCENE_BGINFO bg_info;
_vm->_scene->getBGInfo(&bg_info);
spriteDestRect.left = bg_info.bg_x;
spriteDestRect.top = bg_info.bg_y;
spriteDestRect.right = bg_info.bg_x + bg_info.bg_w;
spriteDestRect.bottom = bg_info.bg_y + bg_info.bg_h;
clipData.destPoint.x = screenCoord.x + xAlign;
clipData.destPoint.y = screenCoord.y + yAlign;
ci.dst_rect = &spriteDestRect;
ci.src_rect = &spriteSourceRect;
ci.dst_pt = &spritePointer;
clipData.sourceRect.left = 0;
clipData.sourceRect.top = 0;
clipData.sourceRect.right = width;
clipData.sourceRect.bottom = height;
getClipInfo(&ci);
clipData.destRect = clipRect;
if (ci.nodraw) {
return SUCCESS;
if (!clipData.calcClip()) {
return;
}
// Finally, draw the occluded sprite
src_row_p = spriteBuffer + ci.src_draw_x + (ci.src_draw_y * width);
sourceRowPointer = spriteBuffer + clipData.sourceDraw.x + (clipData.sourceDraw.y * width);
destRowPointer = (byte *)ds->pixels + clipData.destDraw.x + (clipData.destDraw.y * ds->pitch);
maskRowPointer = maskBuffer + clipData.destDraw.x + (clipData.destDraw.y * maskWidth);
dst_row_p = (byte *)ds->pixels + ci.dst_draw_x + (ci.dst_draw_y * ds->pitch);
mask_row_p = maskBuffer + ci.dst_draw_x + (ci.dst_draw_y * maskWidth);
for (y = 0; y < ci.draw_h; y++) {
src_p = src_row_p;
dst_p = dst_row_p;
mask_p = mask_row_p;
for (x = 0; x < ci.draw_w; x++) {
if (*src_p != 0) {
mask_z = *mask_p & SPRITE_ZMASK;
if (mask_z > depth) {
*dst_p = *src_p;
for (y = 0; y < clipData.height; y++) {
sourcePointer = sourceRowPointer;
destPointer = destRowPointer;
maskPointer = maskRowPointer;
for (x = 0; x < clipData.width; x++) {
if (*sourcePointer != 0) {
maskZ = *maskPointer & SPRITE_ZMASK;
if (maskZ > depth) {
*destPointer = *sourcePointer;
}
}
src_p++;
dst_p++;
mask_p++;
sourcePointer++;
destPointer++;
maskPointer++;
}
dst_row_p += ds->pitch;
mask_row_p += maskWidth;
src_row_p += width;
destRowPointer += ds->pitch;
maskRowPointer += maskWidth;
sourceRowPointer += width;
}
return SUCCESS;
}
void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t outLength) {

View file

@ -60,19 +60,31 @@ struct SpriteList {
}
};
class Sprite {
public:
SpriteList _mainSprites;
Sprite(SagaEngine *vm);
~Sprite(void);
// draw scaled sprite using background scene mask
void drawOccluded(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth);
// draw scaled sprite using background scene mask
void draw(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale);
// main function
void drawClip(SURFACE *ds, const Rect &clipRect, const Point &spritePointer, int width, int height, const byte *spriteBuffer);
void draw(SURFACE *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale);
int loadList(int resourceId, SpriteList &spriteList); // load or append spriteList
int draw(SURFACE *ds, SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale, Rect *clipOverride = NULL);
int draw(SURFACE *ds, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale, Rect *clipOverride = NULL);
int drawOccluded(SURFACE *ds, SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth);
bool hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint);
void getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer);
void drawClip(SURFACE *ds, Rect clip, const Point &spritePointer, int width, int height, const byte *spriteBuffer);
private:
void decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t outLength);
void scaleBuffer(const byte *src, int width, int height, int scale);

View file

@ -31,7 +31,7 @@ namespace Saga {
* If flags if set to 1, do zero masking.
*/
int SagaEngine::transitionDissolve(byte *dst_img, int dst_w, int dst_h, int dst_p, const byte *src_img,
int src_w, int src_h, int src_p, int flags, int x, int y,
int src_w, int src_h, int flags, int x, int y,
double percent) {
#define XOR_MASK 0xB400;
int pixelcount = dst_w * dst_h;