aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/scene.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2015-05-27 20:26:40 -0400
committerPaul Gilbert2015-05-27 20:26:40 -0400
commit0d4163c6e932bed2b85843f6ab3b5066d0353df6 (patch)
treec2c23e06cf5e60cdd1bd205a421469b902646d0b /engines/sherlock/scene.cpp
parent483a72b8b840a9ebbb7009b3dcd20878d0ffad58 (diff)
downloadscummvm-rg350-0d4163c6e932bed2b85843f6ab3b5066d0353df6.tar.gz
scummvm-rg350-0d4163c6e932bed2b85843f6ab3b5066d0353df6.tar.bz2
scummvm-rg350-0d4163c6e932bed2b85843f6ab3b5066d0353df6.zip
SHERLOCK: Implemented initial background clearing of RT doBgAnim
Diffstat (limited to 'engines/sherlock/scene.cpp')
-rw-r--r--engines/sherlock/scene.cpp511
1 files changed, 307 insertions, 204 deletions
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 41aafff8c3..18690fb414 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -24,6 +24,7 @@
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/screen.h"
+#include "sherlock/tattoo/tattoo.h"
namespace Sherlock {
@@ -152,9 +153,9 @@ void ScaleZone::load(Common::SeekableReadStream &s) {
Scene *Scene::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
- return new ScalpelScene(vm);
+ return new Scalpel::ScalpelScene(vm);
else
- return new TattooScene(vm);
+ return new Tattoo::TattooScene(vm);
}
Scene::Scene(SherlockEngine *vm): _vm(vm) {
@@ -1197,20 +1198,209 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
return 1;
}
-void Scene::doBgAnim() {
+int Scene::findBgShape(const Common::Rect &r) {
+ if (!_doBgAnimDone)
+ // New frame hasn't been drawn yet
+ return -1;
+
+ for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN
+ && o._aType <= PERSON) {
+ if (r.intersects(o.getNewBounds()))
+ return idx;
+ } else if (o._type == NO_SHAPE) {
+ if (r.intersects(o.getNoShapeBounds()))
+ return idx;
+ }
+ }
+
+ return -1;
+}
+
+int Scene::checkForZones(const Common::Point &pt, int zoneType) {
+ int matches = 0;
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._aType == zoneType && o._type != INVALID) && o._type != HIDDEN) {
+ Common::Rect r = o._type == NO_SHAPE ? o.getNoShapeBounds() : o.getNewBounds();
+
+ if (r.contains(pt)) {
+ ++matches;
+ o.setFlagsAndToggles();
+ _vm->_talk->talkTo(o._use[0]._target);
+ }
+ }
+ }
+
+ return matches;
+}
+
+int Scene::whichZone(const Common::Point &pt) {
+ for (uint idx = 0; idx < _zones.size(); ++idx) {
+ if (_zones[idx].contains(pt))
+ return idx;
+ }
+
+ return -1;
+}
+
+int Scene::closestZone(const Common::Point &pt) {
+ int dist = 1000;
+ int zone = -1;
+
+ for (uint idx = 0; idx < _zones.size(); ++idx) {
+ Common::Point zc((_zones[idx].left + _zones[idx].right) / 2,
+ (_zones[idx].top + _zones[idx].bottom) / 2);
+ int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y);
+
+ if (d < dist) {
+ // Found a closer zone
+ dist = d;
+ zone = idx;
+ }
+ }
+
+ return zone;
+}
+
+void Scene::synchronize(Common::Serializer &s) {
+ if (s.isSaving())
+ saveSceneStatus();
+
+ if (s.isSaving()) {
+ s.syncAsSint16LE(_currentScene);
+ } else {
+ s.syncAsSint16LE(_goToScene);
+ _loadingSavedGame = true;
+ }
+
+ for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) {
+ for (int flag = 0; flag < 65; ++flag) {
+ s.syncAsByte(_sceneStats[sceneNum][flag]);
+ }
+ }
+}
+
+void Scene::setNPCPath(int npc) {
+ People &people = *_vm->_people;
+ Talk &talk = *_vm->_talk;
+
+ people[npc].clearNPC();
+ people[npc]._name = Common::String::format("WATS%.2dA", _currentScene);
+
+ // If we're in the middle of a script that will continue once the scene is loaded,
+ // return without calling the path script
+ if (talk._scriptMoreFlag == 1 || talk._scriptMoreFlag == 3)
+ return;
+
+ // Turn off all the NPCs, since the talk script will turn them back on as needed
+ for (uint idx = 0; idx < MAX_NPC; ++idx)
+ people[idx + 1]._type = INVALID;
+
+ // Call the path script for the scene
+ Common::String pathFile = Common::String::format("PATH%.2dA", _currentScene);
+ talk.talkTo(pathFile);
+}
+
+void Scene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Iterate through the shapes
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+ if (obj._type == ACTIVE_BG_SHAPE || (IS_SERRATED_SCALPEL && obj._type == STATIC_BG_SHAPE)) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & OBJ_BEHIND)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & OBJ_FORWARD) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+
+namespace Scalpel {
+
+void ScalpelScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Iterate through the canim list
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &obj = _canimShapes[idx];
+ if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & 1)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & 4) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+void ScalpelScene::doBgAnimCheckCursor() {
+ Inventory &inv = *_vm->_inventory;
+ Events &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (ui._menuMode == LOOK_MODE) {
+ if (mousePos.y > CONTROLS_Y1)
+ events.setCursor(ARROW);
+ else if (mousePos.y < CONTROLS_Y)
+ events.setCursor(MAGNIFY);
+ }
+
+ // Check for setting magnifying glass cursor
+ if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
+ if (inv._invMode == INVMODE_LOOK) {
+ // Only show Magnifying glass cursor if it's not on the inventory command line
+ if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
+ events.setCursor(MAGNIFY);
+ else
+ events.setCursor(ARROW);
+ } else {
+ events.setCursor(ARROW);
+ }
+ }
+
+ if (sound._diskSoundPlaying && !*sound._soundIsOn) {
+ // Loaded sound just finished playing
+ sound.freeDigiSound();
+ }
+}
+
+void ScalpelScene::doBgAnim() {
+ Scalpel::ScalpelEngine &vm = *((Scalpel::ScalpelEngine *)_vm);
Events &events = *_vm->_events;
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
- Common::Point mousePos = events.mousePos();
- events.animateCursorIfNeeded();
screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
talk._talkToAbort = false;
if (_restoreFlag) {
- if (people[AL]._type == CHARACTER)
- people[AL].checkSprite();
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
@@ -1225,8 +1415,8 @@ void Scene::doBgAnim() {
_canimShapes[idx].checkObject();
}
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->eraseMirror12();
+ if (_currentScene == 12)
+ vm.eraseMirror12();
// Restore the back buffer from the back buffer 2 in the changed area
Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
@@ -1297,8 +1487,8 @@ void Scene::doBgAnim() {
// Flag the bg shapes which need to be redrawn
checkBgShapes();
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->doMirror12();
+ if (_currentScene == 12)
+ vm.doMirror12();
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
@@ -1407,8 +1597,8 @@ void Scene::doBgAnim() {
}
}
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->flushMirror12();
+ if (_currentScene == 12)
+ vm.flushMirror12();
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
@@ -1485,199 +1675,16 @@ void Scene::doBgAnim() {
}
}
-int Scene::findBgShape(const Common::Rect &r) {
- if (!_doBgAnimDone)
- // New frame hasn't been drawn yet
- return -1;
-
- for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
- Object &o = _bgShapes[idx];
- if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN
- && o._aType <= PERSON) {
- if (r.intersects(o.getNewBounds()))
- return idx;
- } else if (o._type == NO_SHAPE) {
- if (r.intersects(o.getNoShapeBounds()))
- return idx;
- }
- }
-
- return -1;
-}
-
-int Scene::checkForZones(const Common::Point &pt, int zoneType) {
- int matches = 0;
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if ((o._aType == zoneType && o._type != INVALID) && o._type != HIDDEN) {
- Common::Rect r = o._type == NO_SHAPE ? o.getNoShapeBounds() : o.getNewBounds();
-
- if (r.contains(pt)) {
- ++matches;
- o.setFlagsAndToggles();
- _vm->_talk->talkTo(o._use[0]._target);
- }
- }
- }
-
- return matches;
-}
-
-int Scene::whichZone(const Common::Point &pt) {
- for (uint idx = 0; idx < _zones.size(); ++idx) {
- if (_zones[idx].contains(pt))
- return idx;
- }
-
- return -1;
-}
-
-int Scene::closestZone(const Common::Point &pt) {
- int dist = 1000;
- int zone = -1;
-
- for (uint idx = 0; idx < _zones.size(); ++idx) {
- Common::Point zc((_zones[idx].left + _zones[idx].right) / 2,
- (_zones[idx].top + _zones[idx].bottom) / 2);
- int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y);
-
- if (d < dist) {
- // Found a closer zone
- dist = d;
- zone = idx;
- }
- }
-
- return zone;
-}
-
-void Scene::synchronize(Common::Serializer &s) {
- if (s.isSaving())
- saveSceneStatus();
-
- if (s.isSaving()) {
- s.syncAsSint16LE(_currentScene);
- } else {
- s.syncAsSint16LE(_goToScene);
- _loadingSavedGame = true;
- }
-
- for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) {
- for (int flag = 0; flag < 65; ++flag) {
- s.syncAsByte(_sceneStats[sceneNum][flag]);
- }
- }
-}
-
-void Scene::setNPCPath(int npc) {
- People &people = *_vm->_people;
- Talk &talk = *_vm->_talk;
-
- people[npc].clearNPC();
- people[npc]._name = Common::String::format("WATS%.2dA", _currentScene);
-
- // If we're in the middle of a script that will continue once the scene is loaded,
- // return without calling the path script
- if (talk._scriptMoreFlag == 1 || talk._scriptMoreFlag == 3)
- return;
-
- // Turn off all the NPCs, since the talk script will turn them back on as needed
- for (uint idx = 0; idx < MAX_NPC; ++idx)
- people[idx + 1]._type = INVALID;
-
- // Call the path script for the scene
- Common::String pathFile = Common::String::format("PATH%.2dA", _currentScene);
- talk.talkTo(pathFile);
-}
-
-void Scene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Iterate through the shapes
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &obj = _bgShapes[idx];
- if (obj._type == ACTIVE_BG_SHAPE || (IS_SERRATED_SCALPEL && obj._type == STATIC_BG_SHAPE)) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & OBJ_BEHIND)) {
- obj._misc = BEHIND;
- } else if (obj._flags & OBJ_FORWARD) {
- obj._misc = FORWARD;
- }
- }
- }
-}
+} // End of namespace Scalpel
/*----------------------------------------------------------------*/
-void ScalpelScene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Call the base scene method to handle bg shapes
- Scene::checkBgShapes();
-
- // Iterate through the canim list
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &obj = _canimShapes[idx];
- if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & 1)) {
- obj._misc = BEHIND;
- } else if (obj._flags & 4) {
- obj._misc = FORWARD;
- }
- }
- }
-}
-
-void ScalpelScene::doBgAnim() {
- Inventory &inv = *_vm->_inventory;
- Events &events = *_vm->_events;
- Sound &sound = *_vm->_sound;
- UserInterface &ui = *_vm->_ui;
- Common::Point mousePos = events.mousePos();
-
- if (ui._menuMode == LOOK_MODE) {
- if (mousePos.y > CONTROLS_Y1)
- events.setCursor(ARROW);
- else if (mousePos.y < CONTROLS_Y)
- events.setCursor(MAGNIFY);
- }
-
- // Check for setting magnifying glass cursor
- if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
- if (inv._invMode == INVMODE_LOOK) {
- // Only show Magnifying glass cursor if it's not on the inventory command line
- if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
- events.setCursor(MAGNIFY);
- else
- events.setCursor(ARROW);
- } else {
- events.setCursor(ARROW);
- }
- }
-
- if (sound._diskSoundPlaying && !*sound._soundIsOn) {
- // Loaded sound just finished playing
- sound.freeDigiSound();
- }
-
- // Handle doing the actual drawing
- Scene::doBgAnim();
-}
-
-/*----------------------------------------------------------------*/
+namespace Tattoo {
TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) {
_arrowZone = -1;
+ _mask = _mask1 = nullptr;
+ _maskCounter = 0;
}
void TattooScene::checkBgShapes() {
@@ -1707,7 +1714,7 @@ void TattooScene::checkBgShapes() {
}
}
-void TattooScene::doBgAnim() {
+void TattooScene::doBgAnimCheckCursor() {
Events &events = *_vm->_events;
UserInterface &ui = *_vm->_ui;
Common::Point mousePos = events.mousePos();
@@ -1731,10 +1738,106 @@ void TattooScene::doBgAnim() {
events.setCursor(cursorId);
}
+}
- // Handle doing the actual drawing
- _restoreFlag = true;
- Scene::doBgAnim();
+void TattooScene::doBgAnimHandleMask() {
+ TattooEngine &vm = *((TattooEngine *)_vm);
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
+
+ static const int16 OFFSETS[16] = { -1, -2, -3, -3, -2, -1, -1, 0, 1, 2, 3, 3, 2, 1, 0, 0 };
+
+ if (_mask != nullptr) {
+ if (screen._backBuffer1.w() > screen.w())
+ screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(screen._currentScroll, 0,
+ screen._currentScroll + screen.w(), screen.h()));
+ else
+ screen.blitFrom(screen._backBuffer1);
+
+ switch (_currentScene) {
+ case 7:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (--_maskOffset.x < 0)
+ _maskOffset.x = SHERLOCK_SCREEN_WIDTH - 1;
+ }
+ break;
+
+ case 8:
+ _maskOffset.x += 2;
+ if (_maskOffset.x >= SHERLOCK_SCREEN_WIDTH)
+ _maskOffset.x = 0;
+ break;
+
+ case 18:
+ case 68:
+ ++_maskCounter;
+ if (_maskCounter / 4 >= 16)
+ _maskCounter = 0;
+
+ _maskOffset.x = OFFSETS[_maskCounter / 4];
+ break;
+
+ case 53:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (++_maskOffset.x == screen._backBuffer1.w())
+ _maskOffset.x = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ // Standard scene without mask, so call user interface to erase any UI elements as necessary
+ ui.doBgAnimRestoreUI();
+
+ // Restore background for any areas covered by characters and shapes
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx)
+ screen.restoreBackground(Common::Rect(people[idx]._oldPosition.x, people[idx]._oldPosition.y,
+ people[idx]._oldPosition.x + people[idx]._oldSize.x, people[idx]._oldPosition.y + people[idx]._oldSize.y));
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) ||
+ obj._type == HIDE_SHAPE || obj._type == REMOVE)
+ screen._backBuffer1.blitFrom(*obj._imageFrame, obj._oldPosition,
+ Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
+ obj._oldPosition.y + obj._oldSize.y));
+ }
+
+ // If credits are active, erase the area they cover
+ if (vm._creditsActive)
+ vm.eraseCredits();
+ }
+}
+
+void TattooScene::doBgAnim() {
+ doBgAnimCheckCursor();
+
+// Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+// Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ talk._talkToAbort = false;
+
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
+ _bgShapes[idx].checkObject();
+ }
}
+} // End of namespace Tattoo
+
} // End of namespace Sherlock