2018-03-17 15:36:18 +00: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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-05-21 09:30:27 +00:00
|
|
|
#include "graphics/managed_surface.h"
|
2018-03-23 19:51:13 +00:00
|
|
|
#include "graphics/palette.h"
|
2018-05-21 09:30:27 +00:00
|
|
|
|
|
|
|
#include "pink/cel_decoder.h"
|
|
|
|
#include "pink/director.h"
|
|
|
|
#include "pink/objects/actions/action_sound.h"
|
|
|
|
#include "pink/objects/actions/action_cel.h"
|
2018-06-11 20:30:50 +00:00
|
|
|
#include "pink/objects/actors/actor.h"
|
2018-03-23 19:51:13 +00:00
|
|
|
|
2018-03-17 15:36:18 +00:00
|
|
|
namespace Pink {
|
2018-06-09 12:54:21 +00:00
|
|
|
Director::Director()
|
|
|
|
: _surface(640, 480) {
|
|
|
|
_wndManager.setScreen(&_surface);
|
|
|
|
}
|
2018-03-23 19:51:13 +00:00
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::update() {
|
|
|
|
for (uint i = 0; i < _sounds.size(); ++i) {
|
|
|
|
_sounds[i]->update();
|
|
|
|
}
|
2018-06-20 10:56:23 +00:00
|
|
|
|
2018-05-22 05:03:37 +00:00
|
|
|
for (uint i = 0; i < _sprites.size(); ++i) {
|
2018-06-11 20:29:46 +00:00
|
|
|
if (_sprites[i]->needsUpdate())
|
|
|
|
_sprites[i]->update();
|
2018-05-22 05:03:37 +00:00
|
|
|
}
|
2018-03-27 10:53:03 +00:00
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
draw();
|
2018-03-23 19:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Director::addSprite(ActionCEL *sprite) {
|
2018-05-22 05:03:37 +00:00
|
|
|
_sprites.push_back(sprite);
|
|
|
|
int i;
|
|
|
|
for (i = _sprites.size() - 1; i > 0 ; --i) {
|
2018-05-22 08:58:02 +00:00
|
|
|
if (sprite->getZ() < _sprites[i - 1]->getZ())
|
2018-05-22 05:03:37 +00:00
|
|
|
_sprites[i] = _sprites[i - 1];
|
2018-05-22 08:58:02 +00:00
|
|
|
else
|
|
|
|
break;
|
2018-05-22 05:03:37 +00:00
|
|
|
}
|
|
|
|
_sprites[i] = sprite;
|
2018-03-23 19:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Director::removeSprite(ActionCEL *sprite) {
|
2018-05-22 05:03:37 +00:00
|
|
|
for (uint i = 0; i < _sprites.size(); ++i) {
|
|
|
|
if (sprite == _sprites[i]) {
|
|
|
|
_sprites.remove_at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-06-11 20:29:46 +00:00
|
|
|
_dirtyRects.push_back(sprite->getBounds());
|
2018-03-23 19:51:13 +00:00
|
|
|
}
|
2018-03-17 15:36:18 +00:00
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::removeSound(ActionSound *sound) {
|
2018-05-22 05:03:37 +00:00
|
|
|
for (uint i = 0; i < _sounds.size(); ++i) {
|
2018-06-09 12:54:21 +00:00
|
|
|
if (_sounds[i] == sound)
|
|
|
|
_sounds.remove_at(i);
|
2018-05-22 05:03:37 +00:00
|
|
|
}
|
2018-03-25 19:32:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::clear() {
|
|
|
|
_dirtyRects.push_back(Common::Rect(0, 0, 640, 480));
|
|
|
|
_sprites.resize(0);
|
2018-03-25 19:32:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::pause(bool pause) {
|
|
|
|
for (uint i = 0; i < _sprites.size() ; ++i) {
|
|
|
|
_sprites[i]->pause(pause);
|
2018-05-22 05:03:37 +00:00
|
|
|
}
|
2018-03-25 19:32:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::saveStage() {
|
|
|
|
_savedSprites = _sprites;
|
2018-05-22 05:03:37 +00:00
|
|
|
_sprites.clear();
|
2018-03-27 10:53:03 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::loadStage() {
|
|
|
|
assert(_sprites.empty());
|
|
|
|
_sprites = _savedSprites;
|
|
|
|
_savedSprites.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Actor *Director::getActorByPoint(const Common::Point point) {
|
2018-05-22 05:03:37 +00:00
|
|
|
for (int i = _sprites.size() - 1; i >= 0; --i) {
|
2018-06-11 20:30:50 +00:00
|
|
|
if (_sprites[i]->getActor()->isCursor())
|
|
|
|
continue;
|
2018-05-22 05:03:37 +00:00
|
|
|
CelDecoder *decoder = _sprites[i]->getDecoder();
|
|
|
|
const Graphics::Surface *frame = decoder->getCurrentFrame();
|
2018-06-11 20:29:46 +00:00
|
|
|
const Common::Rect &rect = _sprites[i]->getBounds();
|
2018-06-09 19:20:01 +00:00
|
|
|
if (rect.contains(point)) {
|
|
|
|
byte spritePixel = *(const byte*) frame->getBasePtr(point.x - rect.left, point.y - rect.top);
|
|
|
|
if (spritePixel != decoder->getTransparentColourIndex())
|
|
|
|
return _sprites[i]->getActor();
|
2018-06-09 12:54:21 +00:00
|
|
|
}
|
2018-05-22 05:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2018-04-02 05:57:56 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::draw() {
|
|
|
|
if (!_dirtyRects.empty()) {
|
|
|
|
mergeDirtyRects();
|
|
|
|
|
|
|
|
for (uint i = 0; i < _dirtyRects.size(); ++i) {
|
|
|
|
drawRect(_dirtyRects[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
_dirtyRects.resize(0);
|
|
|
|
_surface.update();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
g_system->updateScreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Director::mergeDirtyRects() {
|
|
|
|
Common::Array<Common::Rect>::iterator rOuter, rInner;
|
|
|
|
for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
|
|
|
|
rInner = rOuter;
|
|
|
|
while (++rInner != _dirtyRects.end()) {
|
|
|
|
if ((*rOuter).intersects(*rInner)) {
|
|
|
|
// These two rectangles overlap, so merge them
|
|
|
|
rOuter->extend(*rInner);
|
|
|
|
|
|
|
|
// remove the inner rect from the list
|
|
|
|
_dirtyRects.erase(rInner);
|
|
|
|
|
|
|
|
// move back to beginning of list
|
|
|
|
rInner = rOuter;
|
|
|
|
}
|
|
|
|
}
|
2018-05-25 18:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-11 20:29:46 +00:00
|
|
|
void Director::addDirtyRect(const Common::Rect &rect) {
|
|
|
|
_dirtyRects.push_back(rect);
|
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::addDirtyRects(ActionCEL *sprite) {
|
2018-06-11 20:29:46 +00:00
|
|
|
const Common::Rect spriteRect = sprite->getBounds();
|
2018-06-09 12:54:21 +00:00
|
|
|
const Common::List<Common::Rect> *dirtyRects = sprite->getDecoder()->getDirtyRects();
|
|
|
|
if (dirtyRects->size() > 100) {
|
|
|
|
_dirtyRects.push_back(spriteRect);
|
|
|
|
} else {
|
|
|
|
for (Common::List<Common::Rect>::const_iterator it = dirtyRects->begin(); it != dirtyRects->end(); ++it) {
|
|
|
|
Common::Rect dirtyRect = *it;
|
|
|
|
dirtyRect.translate(spriteRect.left, spriteRect.top);
|
|
|
|
_dirtyRects.push_back(dirtyRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sprite->getDecoder()->clearDirtyRects();
|
2018-06-03 11:27:58 +00:00
|
|
|
}
|
|
|
|
|
2018-06-09 12:54:21 +00:00
|
|
|
void Director::drawRect(const Common::Rect &rect) {
|
|
|
|
_surface.fillRect(rect, 0);
|
|
|
|
for (uint i = 0; i < _sprites.size(); ++i) {
|
2018-06-11 20:29:46 +00:00
|
|
|
const Common::Rect &spriteRect = _sprites[i]->getBounds();
|
2018-06-09 12:54:21 +00:00
|
|
|
Common::Rect interRect = rect.findIntersectingRect(spriteRect);
|
|
|
|
if (interRect.isEmpty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Common::Rect srcRect(interRect);
|
|
|
|
srcRect.translate(-spriteRect.left, -spriteRect.top);
|
|
|
|
_surface.transBlitFrom(*_sprites[i]->getDecoder()->getCurrentFrame(), srcRect, interRect, _sprites[i]->getDecoder()->getTransparentColourIndex());
|
|
|
|
}
|
2018-06-03 11:27:58 +00:00
|
|
|
}
|
|
|
|
|
2018-05-22 03:04:44 +00:00
|
|
|
}
|