From bfd1b62063040c970894fbf81d9dca9c3d4088d0 Mon Sep 17 00:00:00 2001 From: whiterandrek Date: Sat, 9 Jun 2018 15:54:21 +0300 Subject: PINK: change drawing method --- engines/pink/director.cpp | 179 +++++++++++++++++----------- engines/pink/director.h | 30 +++-- engines/pink/objects/actions/action_cel.cpp | 3 +- engines/pink/pink.cpp | 8 +- 4 files changed, 132 insertions(+), 88 deletions(-) diff --git a/engines/pink/director.cpp b/engines/pink/director.cpp index 0f208c66e5..dd8e870b8d 100644 --- a/engines/pink/director.cpp +++ b/engines/pink/director.cpp @@ -29,53 +29,34 @@ #include "pink/objects/actions/action_cel.h" namespace Pink { -Director::Director(OSystem *system) - : _system(system), showBounds(1) {} +Director::Director() + : _surface(640, 480) { + _wndManager.setScreen(&_surface); +} -void Director::draw() { - _system->fillScreen(0); +void Director::update() { + static uint32 time = g_system->getMillis(); + static uint32 times = 0; + + for (uint i = 0; i < _sounds.size(); ++i) { + _sounds[i]->update(); + } for (uint i = 0; i < _sprites.size(); ++i) { - drawSprite(_sprites[i]); + _sprites[i]->update(); } - _system->updateScreen(); -} -void Director::drawSprite(ActionCEL *sprite) { - CelDecoder *decoder = sprite->getDecoder(); - const Graphics::Surface *surface; - if (decoder->needsUpdate()) - surface = decoder->decodeNextFrame(); - else - surface = decoder->getCurrentFrame(); - - int h = surface->h; - if (surface->h + decoder->getY() > 480) - h = 480 - decoder->getY(); - int w = surface->w; - if (surface->w + decoder->getX() > 640) - w = 640 - decoder->getX(); - - if (!showBounds) { - Graphics::Surface *screen = _system->lockScreen(); - - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - uint16 spritePixelColourIndex = *(byte*)surface->getBasePtr(x, y); - if (spritePixelColourIndex != decoder->getTransparentColourIndex()) { - *(byte *) screen->getBasePtr(decoder->getX() + x, decoder->getY() + y) = spritePixelColourIndex; - } - } - } - _system->unlockScreen(); - } - else - _system->copyRectToScreen(surface->getPixels(), surface->pitch, - decoder->getX(), decoder->getY(), - w, h); + draw(); + times++; + if (g_system->getMillis() - time >= 1000) { + debug("FPS: %u ", times); + sum += times; + count++; + time = g_system->getMillis(); + times = 0; + } } - void Director::addSprite(ActionCEL *sprite) { _sprites.push_back(sprite); int i; @@ -86,6 +67,7 @@ void Director::addSprite(ActionCEL *sprite) { break; } _sprites[i] = sprite; + _dirtyRects.push_back(sprite->getDecoder()->getRectangle()); } void Director::removeSprite(ActionCEL *sprite) { @@ -95,65 +77,120 @@ void Director::removeSprite(ActionCEL *sprite) { break; } } + _dirtyRects.push_back(sprite->getDecoder()->getRectangle()); } -void Director::setPallette(const byte *pallete) { - _system->getPaletteManager()->setPalette(pallete, 0, 256); -} - -void Director::update() { +void Director::removeSound(ActionSound *sound) { for (uint i = 0; i < _sounds.size(); ++i) { - _sounds[i]->update(); - } - for (uint i = 0; i < _sprites.size(); ++i) { - _sprites[i]->update(); + if (_sounds[i] == sound) + _sounds.remove_at(i); } } -void Director::addSound(ActionSound *sound) { - _sounds.push_back(sound); +void Director::clear() { + _dirtyRects.push_back(Common::Rect(0, 0, 640, 480)); + _sprites.resize(0); } -void Director::removeSound(ActionSound *sound) { - for (uint i = 0; i < _sounds.size(); ++i) { - if (_sounds[i] == sound) - _sounds.remove_at(i); +void Director::pause(bool pause) { + for (uint i = 0; i < _sprites.size() ; ++i) { + _sprites[i]->pause(pause); } } -void Director::clear() { +void Director::saveStage() { + _savedSprites = _sprites; _sprites.clear(); } -Actor *Director::getActorByPoint(Common::Point point) { +void Director::loadStage() { + assert(_sprites.empty()); + _sprites = _savedSprites; + _savedSprites.clear(); +} + +Actor *Director::getActorByPoint(const Common::Point point) { for (int i = _sprites.size() - 1; i >= 0; --i) { CelDecoder *decoder = _sprites[i]->getDecoder(); const Graphics::Surface *frame = decoder->getCurrentFrame(); - Common::Rect &rect = decoder->getRectangle(); - if (rect.contains(point) && - *(byte*)frame->getBasePtr(point.x - rect.left, point.y - rect.top) - != decoder->getTransparentColourIndex()) + const Common::Rect &rect = decoder->getRectangle(); + byte spritePixel = *(const byte*) frame->getBasePtr(point.x - rect.left, point.y - rect.top); + if (rect.contains(point) && spritePixel != decoder->getTransparentColourIndex()) { return _sprites[i]->getActor(); + } } return nullptr; } -void Director::pause(bool pause) { - for (uint i = 0; i < _sprites.size() ; ++i) { - _sprites[i]->getDecoder()->pauseVideo(pause); +void Director::draw() { + for (uint i = 0; i < _sprites.size(); ++i) { + if (_sprites[i]->getDecoder()->needsUpdate()) { + _sprites[i]->getDecoder()->decodeNextFrame(); + addDirtyRects(_sprites[i]); + } + } + + 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::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; + } + } } } -void Director::saveStage() { - _savedSprites = _sprites; - _sprites.clear(); +void Director::addDirtyRects(ActionCEL *sprite) { + const Common::Rect spriteRect = sprite->getDecoder()->getRectangle(); + const Common::List *dirtyRects = sprite->getDecoder()->getDirtyRects(); + if (dirtyRects->size() > 100) { + _dirtyRects.push_back(spriteRect); + } else { + for (Common::List::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(); } -void Director::loadStage() { - assert(_sprites.empty()); - _sprites = _savedSprites; - _savedSprites.clear(); +void Director::drawRect(const Common::Rect &rect) { + _surface.fillRect(rect, 0); + for (uint i = 0; i < _sprites.size(); ++i) { + const Common::Rect &spriteRect = _sprites[i]->getDecoder()->getRectangle(); + 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()); + } } } diff --git a/engines/pink/director.h b/engines/pink/director.h index 4574305098..4902c54328 100644 --- a/engines/pink/director.h +++ b/engines/pink/director.h @@ -27,26 +27,27 @@ #include "common/rect.h" #include "common/system.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/screen.h" + namespace Pink { class Actor; class ActionCEL; class ActionSound; -class CelDecoder; class Director { public: - Director(OSystem *system); - Actor *getActorByPoint(Common::Point point); + Director(); - void draw(); void update(); + void setPallette(const byte *pallete) { g_system->getPaletteManager()->setPalette(pallete, 0, 256); } + void addSprite(ActionCEL *sprite); void removeSprite(ActionCEL *sprite); - void setPallette(const byte *pallete); - void addSound(ActionSound* sound); + void addSound(ActionSound* sound) { _sounds.push_back(sound); }; void removeSound(ActionSound* sound); void clear(); @@ -56,11 +57,22 @@ public: void saveStage(); void loadStage(); - bool showBounds; + Actor *getActorByPoint(const Common::Point point); + + Graphics::MacWindowManager &getWndManager() { return _wndManager; }; + + uint32 count = 0; + uint32 sum = 0; private: - void drawSprite(ActionCEL *sprite); - OSystem *_system; + void draw(); + void addDirtyRects(ActionCEL *sprite); + void mergeDirtyRects(); + void drawRect(const Common::Rect &rect); + + Graphics::Screen _surface; + Graphics::MacWindowManager _wndManager; + Common::Array _dirtyRects; Common::Array _sprites; Common::Array _savedSprites; Common::Array _sounds; diff --git a/engines/pink/objects/actions/action_cel.cpp b/engines/pink/objects/actions/action_cel.cpp index e6f262f390..a5f0e1f610 100644 --- a/engines/pink/objects/actions/action_cel.cpp +++ b/engines/pink/objects/actions/action_cel.cpp @@ -59,9 +59,8 @@ bool ActionCEL::initPalette(Director *director) { void ActionCEL::start() { if (!_decoder) _decoder = _actor->getPage()->loadCel(_fileName); - _actor->getPage()->getGame()->getDirector()->addSprite(this); - this->onStart(); + _actor->getPage()->getGame()->getDirector()->addSprite(this); } void ActionCEL::end() { diff --git a/engines/pink/pink.cpp b/engines/pink/pink.cpp index 53407e6f66..eaeadbcd2e 100644 --- a/engines/pink/pink.cpp +++ b/engines/pink/pink.cpp @@ -41,7 +41,7 @@ namespace Pink { Pink::PinkEngine::PinkEngine(OSystem *system, const ADGameDescription *desc) : Engine(system), _console(nullptr), _rnd("pink"), _desc(*desc), _bro(nullptr), _module(nullptr), - _director(_system), _pdaMgr(this) { + _director(), _pdaMgr(this) { debug("PinkEngine constructed"); DebugMan.addDebugChannel(kPinkDebugGeneral, "general", "General issues"); @@ -117,9 +117,6 @@ Common::Error Pink::PinkEngine::run() { _actor->onLeftButtonClick(event.mouse); break; case Common::EVENT_KEYDOWN: - if (event.kbd.keycode == Common::KEYCODE_d) - _director.showBounds = !_director.showBounds; - else _actor->onKeyboardButtonClick(event.kbd.keycode); break; // don't know why it is used in original @@ -132,8 +129,7 @@ Common::Error Pink::PinkEngine::run() { _actor->update(); _director.update(); - _director.draw(); - _system->delayMillis(5); + _system->delayMillis(10); } return Common::kNoError; -- cgit v1.2.3