diff options
author | Paul Gilbert | 2015-05-27 20:26:40 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-05-27 20:26:40 -0400 |
commit | 0d4163c6e932bed2b85843f6ab3b5066d0353df6 (patch) | |
tree | c2c23e06cf5e60cdd1bd205a421469b902646d0b /engines/sherlock/scene.cpp | |
parent | 483a72b8b840a9ebbb7009b3dcd20878d0ffad58 (diff) | |
download | scummvm-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.cpp | 511 |
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 |