Skip to content

Commit

Permalink
SHERLOCK: Properly restrict scene drawing to scene area
Browse files Browse the repository at this point in the history
  • Loading branch information
dreammaster committed Apr 30, 2015
1 parent 56f43ef commit 00fd812
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 40 deletions.
8 changes: 0 additions & 8 deletions engines/sherlock/graphics.cpp
Expand Up @@ -164,14 +164,6 @@ void Surface::fillRect(const Common::Rect &r, byte color) {
addDirtyRect(r);
}

/**
* Return a sub-area of the surface as a new surface object. The surfaces
* are shared in common, so changes in the sub-surface affects the original.
*/
Surface Surface::getSubArea(const Common::Rect &r) {
return Surface(*this, r);
}

/**
* Clips the given source bounds so the passed destBounds will be entirely on-screen
*/
Expand Down
2 changes: 0 additions & 2 deletions engines/sherlock/graphics.h
Expand Up @@ -55,8 +55,6 @@ class Surface : public Graphics::Surface {

void fillRect(int x1, int y1, int x2, int y2, byte color);
void fillRect(const Common::Rect &r, byte color);

Surface getSubArea(const Common::Rect &r);
};

} // End of namespace Sherlock
Expand Down
1 change: 0 additions & 1 deletion engines/sherlock/map.cpp
Expand Up @@ -442,7 +442,6 @@ void Map::updateMap(bool flushScreen) {
*/
void Map::walkTheStreets() {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
bool reversePath = false;
Common::Array<Common::Point> tempPath;

Expand Down
53 changes: 27 additions & 26 deletions engines/sherlock/scene.cpp
Expand Up @@ -716,10 +716,11 @@ int Scene::toggleObject(const Common::String &name) {
void Scene::updateBackground() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
Surface surface = screen._backBuffer1.getSubArea(
Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
Sprite &player = people[AL];

// Restrict drawing window
screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));

// Update Holmes if he's turned on
if (people._holmesOn)
player.adjustSprite();
Expand All @@ -731,26 +732,26 @@ void Scene::updateBackground() {
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND)
surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
}

// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND)
surface.transBlitFrom(*_canimShapes[idx]._imageFrame,
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame,
_canimShapes[idx]._position, _canimShapes[idx]._flags & 2);
}

// Draw all active shapes which are normal and behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND)
surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
}

// Draw all canimations which are normal and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND)
surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
_canimShapes[idx]._flags & 2);
}

Expand All @@ -760,22 +761,22 @@ void Scene::updateBackground() {
player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT ||
player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT;

surface.transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100,
screen._backBuffer->transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100,
player._position.y / 100 - player.frameHeight()), flipped);
}

// Draw all static and active shapes that are NORMAL and are in front of the player
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == NORMAL_FORWARD)
surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
}

// Draw all static and active canimations that are NORMAL and are in front of the player
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
_canimShapes[idx]._misc == NORMAL_FORWARD)
surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
_canimShapes[idx]._flags & 2);
}

Expand All @@ -787,14 +788,14 @@ void Scene::updateBackground() {

if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == FORWARD)
surface.transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
}

// Draw all static and active canimations that are forward
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
_canimShapes[idx]._misc == FORWARD)
surface.transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
_canimShapes[idx]._flags & 2);
}
}
Expand Down Expand Up @@ -1079,8 +1080,8 @@ void Scene::doBgAnim() {
Sound &sound = *_vm->_sound;
Talk &talk = *_vm->_talk;
UserInterface &ui = *_vm->_ui;
Surface surface = screen._backBuffer1.getSubArea(Common::Rect(0, 0,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));

screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
int cursorId = events.getCursor();
Common::Point mousePos = events.mousePos();

Expand Down Expand Up @@ -1150,7 +1151,7 @@ void Scene::doBgAnim() {
if (people[AL]._type == CHARACTER)
screen.restoreBackground(bounds);
else if (people[AL]._type == REMOVE)
screen._backBuffer1.blitFrom(screen._backBuffer2, pt, bounds);
screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds);

for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
Expand All @@ -1169,7 +1170,7 @@ void Scene::doBgAnim() {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) {
// Restore screen area
screen._backBuffer1.blitFrom(screen._backBuffer2, o._position,
screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
Common::Rect(o._position.x, o._position.y,
o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));

Expand Down Expand Up @@ -1218,29 +1219,29 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}

// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}
}

// Draw all active shapes which are HAPPEN and behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}

// Draw all canimations which are NORMAL and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}
}

Expand All @@ -1253,50 +1254,50 @@ void Scene::doBgAnim() {
bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT ||
people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT ||
people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT;
screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame,
screen._backBuffer->transBlitFrom(*people[AL]._imageFrame,
Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped);
}

// Draw all static and active shapes are NORMAL and are in front of the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}

// Draw all static and active canimations that are NORMAL and are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) {
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}
}

// Draw all static and active shapes that are in front of the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}

// Draw any active portrait
if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
screen._backBuffer1.transBlitFrom(*people._portrait._imageFrame,
screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
people._portrait._position, people._portrait._flags & 2);

// Draw all static and active canimations that are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}
}

// Draw all NO_SHAPE shapes which have flag bit 0 clear
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && (o._flags & 1) == 0)
screen._backBuffer1.transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
}

// Bring the newly built picture to the screen
Expand Down
26 changes: 23 additions & 3 deletions engines/sherlock/screen.cpp
Expand Up @@ -39,6 +39,10 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR
Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0);
Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0);
setFont(1);

// Set dummy surface used for restricted scene drawing
_sceneSurface.format = Graphics::PixelFormat::createFormatCLUT8();
_sceneSurface.pitch = SHERLOCK_SCREEN_WIDTH;
}

Screen::~Screen() {
Expand Down Expand Up @@ -469,15 +473,31 @@ void Screen::makePanel(const Common::Rect &r) {
_backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM);
}

/**
* Sets the active back buffer pointer to a restricted sub-area of the first back buffer
*/
void Screen::setDisplayBounds(const Common::Rect &r) {
// TODO: See if needed
assert(r.left == 0 && r.top == 0);
_sceneSurface.setPixels(_backBuffer1.getPixels());
_sceneSurface.w = r.width();
_sceneSurface.h = r.height();

_backBuffer = &_sceneSurface;
}

/**
* Resets the active buffer pointer to point back to the full first back buffer
*/
void Screen::resetDisplayBounds() {
setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
_backBuffer = &_backBuffer1;
}

/**
* Return the size of the current display window
*/
Common::Rect Screen::getDisplayBounds() {
return Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w, _sceneSurface.h) :
Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}

/**
Expand Down
1 change: 1 addition & 0 deletions engines/sherlock/screen.h
Expand Up @@ -65,6 +65,7 @@ class Screen : public Surface {
uint32 _transitionSeed;
ImageFile *_font;
int _fontHeight;
Surface _sceneSurface;

void mergeDirtyRects();

Expand Down

0 comments on commit 00fd812

Please sign in to comment.