diff options
author | Borja Lorente | 2016-06-22 00:47:53 +0200 |
---|---|---|
committer | Borja Lorente | 2016-08-14 18:32:46 +0200 |
commit | 0743e9531b5ef871e17cd7ca88966ea2c07b7147 (patch) | |
tree | bcdb310d791ae610a2e3c6a1424987d7e3f2d385 | |
parent | 4d8f8fd36bdb9b1f807f4da04c9e3e4c3438dbfa (diff) | |
download | scummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.tar.gz scummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.tar.bz2 scummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.zip |
MACVENTURE: Implemente dynamic object drawing
-rw-r--r-- | engines/macventure/gui.cpp | 108 | ||||
-rw-r--r-- | engines/macventure/gui.h | 25 | ||||
-rw-r--r-- | engines/macventure/image.cpp | 4 | ||||
-rw-r--r-- | engines/macventure/image.h | 15 | ||||
-rw-r--r-- | engines/macventure/macventure.cpp | 113 | ||||
-rw-r--r-- | engines/macventure/macventure.h | 11 | ||||
-rw-r--r-- | engines/macventure/module.mk | 2 | ||||
-rw-r--r-- | engines/macventure/world.cpp | 2 |
8 files changed, 199 insertions, 81 deletions
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index 90d57aafc2..e202b82d3e 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -86,6 +86,16 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) { Gui::~Gui() { + if (_windowData) + delete _windowData; + + if (_controlData) + delete _controlData; + + Common::HashMap<ObjID, ImageAsset*>::const_iterator it = _assets.begin(); + for (; it != _assets.end(); it++) { + delete it->_value; + } } void Gui::draw() { @@ -104,6 +114,10 @@ void Gui::drawTitle() { warning("drawTitle hasn't been tested yet"); } +void Gui::drawExit(ObjID id) { + warning("Unimplemented method: drawExit"); +} + bool Gui::processEvent(Common::Event &event) { bool processed = false; if (event.type == Common::EVENT_LBUTTONDOWN) { @@ -164,7 +178,7 @@ void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array originx = originx > childPos.x ? childPos.x : originx; originy = originy > childPos.y ? childPos.y : originy; } - data.children.push_back(child); + data.children.push_back(DrawableObject(child, kBlitDirect)); } } if (originx != 0x7fff) data.bounds.left = originx; @@ -172,6 +186,20 @@ void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array if (ref != kMainGameWindow) data.updateScroll = true; } +void Gui::addChild(WindowReference target, ObjID child) { + findWindowData(target).children.push_back(DrawableObject(child, kBlitDirect)); +} + +void Gui::removeChild(WindowReference target, ObjID child) { + WindowData data = findWindowData(target); + uint index = 0; + for (;index < data.children.size(); index++) { + if (data.children[index].obj == child) break; + } + + data.children.remove_at(index); +} + void Gui::initGUI() { _screen.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8()); _wm.setScreen(&_screen); @@ -230,6 +258,7 @@ void Gui::initWindows() { _selfWindow->setCallback(selfWindowCallback, this); loadBorder(_selfWindow, "border_self_inac.bmp", false); loadBorder(_selfWindow, "border_self_act.bmp", true); + findWindowData(kSelfWindow).children.push_back(DrawableObject(1, kBlitDirect)); // Exits Window _exitsWindow = _wm.addWindow(false, true, true); @@ -443,7 +472,6 @@ void Gui::drawWindows() { drawCommandsWindow(); drawMainGameWindow(); - drawSelfWindow(); } void Gui::drawCommandsWindow() { @@ -460,8 +488,7 @@ void Gui::drawCommandsWindow() { data.bounds.right - data.bounds.left, kColorBlack, Graphics::kTextAlignCenter); - } - else { + } else { Common::List<CommandButton>::const_iterator it = _controlData->begin(); for (; it != _controlData->end(); ++it) { CommandButton button = *it; @@ -474,32 +501,15 @@ void Gui::drawCommandsWindow() { void Gui::drawMainGameWindow() { Graphics::ManagedSurface *srf = _mainGameWindow->getSurface(); BorderBounds border = borderBounds(getWindowData(kMainGameWindow).type); - srf->fillRect( - Common::Rect( - border.leftOffset * 2, - border.topOffset * 2, - srf->w - (border.rightOffset * 3), - srf->h - (border.bottomOffset * 3)), - kColorBlack); - - WindowData &data = findWindowData(kMainGameWindow); - for (Common::Array<ObjID>::const_iterator it = data.children.begin(); it != data.children.end(); it++) { - Common::Point pos = _engine->getObjPosition(*it); - srf->fillRect( - Common::Rect( - border.leftOffset * 2 + pos.x, - border.topOffset * 2 + pos.y, - 5, - 5), - kColorBlack); - } - // Tests - ImageAsset testBg(3, _graphics); - testBg.blitInto(srf, border.leftOffset * 2, border.topOffset * 2, kBlitDirect); + ImageAsset bg(3, _graphics); + bg.blitInto( + _mainGameWindow->getSurface(), + border.leftOffset * 2, + border.topOffset * 2, + kBlitDirect); - //ImageAsset testImg(428, _graphics); - //testImg.blitInto(srf, border.leftOffset * 2 + 10,border.topOffset * 2 + 10, kBlitBIC); + drawObjectsInWindow(kMainGameWindow, _mainGameWindow->getSurface()); } @@ -515,6 +525,27 @@ void Gui::drawSelfWindow() { kColorWhite); } +void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * surface) { + WindowData &data = findWindowData(kMainGameWindow); + BorderBounds border = borderBounds(data.type); + Common::Point pos; + ObjID child; + BlitMode mode; + for (Common::Array<DrawableObject>::const_iterator it = data.children.begin(); it != data.children.end(); it++) { + child = (*it).obj; + mode = (BlitMode)(*it).mode; + pos = _engine->getObjPosition(child); + if (!_assets.contains(child)) { + _assets[child] = new ImageAsset(child, _graphics); + } + _assets[child]->blitInto( + surface, + border.leftOffset * 2 + pos.x, + border.topOffset * 2 + pos.y, + mode); + } +} + WindowData & Gui::findWindowData(WindowReference reference) { assert(_windowData); @@ -631,7 +662,7 @@ void Gui::handleMenuAction(MenuAction action) { } void Gui::updateWindow(WindowReference winID, bool containerOpen) { - if (winID > 0x90) return; + if (winID > 0x90 || winID == kNoWindow) return; if (winID == kSelfWindow || containerOpen) { if (winID == kMainGameWindow) { drawMainGameWindow(); @@ -639,9 +670,21 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) { warning("Unimplemented: fill window with background"); } WindowData &data = findWindowData(winID); - Common::Array<ObjID> children = data.children; - for (Common::Array<ObjID>::const_iterator it = children.begin(); it != children.end(); it++) { - warning("Unimplemented: draw object %x", *it); + Common::Array<DrawableObject> &children = data.children; + for (uint i = 0; i < children.size(); i++) { + uint flag = 0; + ObjID child = children[i].obj; + BlitMode mode; + bool off = _engine->isObjVisible(child); + if (!off || _engine->isObjClickable(child)) { + mode = kBlitBIC; + if (_engine->isObjSelected(child)) { + mode = kBlitOR; + } else if (off || flag) { + mode = kBlitXOR; + } + children[i] = DrawableObject(child, mode); + } } if (data.type == kZoomDoc && data.updateScroll) { warning("Unimplemented: update scroll"); @@ -682,7 +725,6 @@ WindowReference Gui::createInventoryWindow() { bool Gui::tryCloseWindow(WindowReference winID) { WindowData data = findWindowData(winID); - Graphics::MacWindow *wind; if (winID < 0x80) { // Inventory window warning("Window closing not implemented"); } else { diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index 404c18e808..2e8b6e20a2 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -39,7 +39,9 @@ using namespace Graphics::MacWindowConstants; class MacVentureEngine; typedef uint32 ObjID; -//namespace MacVentureMenuActions { +class CommandButton; +class ImageAsset; + enum MenuAction { kMenuActionAbout, kMenuActionNew, @@ -60,6 +62,7 @@ enum MenuAction { //} using namespace MacVentureMenuActions; enum WindowReference { + kNoWindow = 0, kCommandsWindow = 0x80, kMainGameWindow = 0x81, kOutConsoleWindow = 0x82, @@ -83,6 +86,16 @@ enum MVWindowType { kRDoc10 = 0x16 }; + +struct DrawableObject { + ObjID obj; + byte mode; + DrawableObject(ObjID id, byte md) { + obj = id; + mode = md; + } +}; + struct WindowData { Common::Rect bounds; MVWindowType type; @@ -91,7 +104,7 @@ struct WindowData { WindowReference refcon; uint8 titleLength; Common::String title; - Common::Array<ObjID> children; + Common::Array<DrawableObject> children; bool updateScroll; }; @@ -139,6 +152,7 @@ public: void draw(); void drawMenu(); void drawTitle(); + void drawExit(ObjID id); bool processEvent(Common::Event &event); void handleMenuAction(MenuAction action); void updateWindow(WindowReference winID, bool containerOpen); @@ -164,6 +178,9 @@ public: void setWindowTitle(WindowReference winID, Common::String string); void updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array<ObjID> &children); + void addChild(WindowReference target, ObjID child); + void removeChild(WindowReference target, ObjID child); + // Ugly switches BorderBounds borderBounds(MVWindowType type); @@ -188,10 +205,10 @@ private: // Attributes Graphics::Menu *_menu; Container *_graphics; + Common::HashMap<ObjID, ImageAsset*> _assets; private: // Methods - // Initializers void initGUI(); void initWindows(); @@ -209,6 +226,8 @@ private: // Methods void drawMainGameWindow(); void drawSelfWindow(); + void drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface *surface); + // Finders WindowData& findWindowData(WindowReference reference); diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index 46d440c957..47b755a829 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -318,9 +318,9 @@ byte ImageAsset::walkHuff(const PPICHuff & huff, Common::BitStream & stream) { } void ImageAsset::blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y, BlitMode mode) { - debug("Blitting image %x ", _id); if (mode == kBlitDirect) { blitDirect(target, x, y, _imgData); + return; } if (_container->getItemByteSize(_mask)) { // Has mask @@ -344,7 +344,7 @@ void ImageAsset::blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y, } } if (_container->getItemByteSize(_id) && mode > 0) { - blitXOR(target, x, y, _maskData); + blitXOR(target, x, y, _imgData); } } diff --git a/engines/macventure/image.h b/engines/macventure/image.h index 21e544a76e..eb52da83ad 100644 --- a/engines/macventure/image.h +++ b/engines/macventure/image.h @@ -31,6 +31,14 @@ namespace MacVenture { typedef uint32 ObjID; class Container; + +enum BlitMode { + kBlitDirect = 0, + kBlitBIC = 1, + kBlitOR = 2, + kBlitXOR = 3 +}; + enum GraphicsEncoding { kPPIC0 = 0, kPPIC1 = 1, @@ -44,13 +52,6 @@ struct PPICHuff { uint8 symbols[17]; }; -enum BlitMode { - kBlitDirect = 0, - kBlitBIC = 1, - kBlitOR = 2, - kBlitXOR = 3 -}; - class ImageAsset { public: ImageAsset(ObjID original, Container *container); diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp index 9bdb99d12f..87b5d51327 100644 --- a/engines/macventure/macventure.cpp +++ b/engines/macventure/macventure.cpp @@ -115,13 +115,15 @@ Common::Error MacVentureEngine::run() { if (_prepared) { _prepared = false; + if (!_halted) + updateState(); + if (_cmdReady || _halted) { _halted = false; if (runScriptEngine()) { _halted = true; _paused = true; - } - else { + } else { _paused = false; if (!updateState()) { updateControls(); @@ -131,10 +133,9 @@ Common::Error MacVentureEngine::run() { if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) { endGame(); - } - - _gui->draw(); + } } + _gui->draw(); g_system->updateScreen(); g_system->delayMillis(50); @@ -210,7 +211,7 @@ void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID) { obj.exitx = _world->getObjAttr(objID, kAttrExitX); obj.exity = _world->getObjAttr(objID, kAttrExitY); obj.hidden = _world->getObjAttr(objID, kAttrHiddenExit); - obj.offsecreen = _world->getObjAttr(objID, kAttrInvisible); + obj.offscreen = _world->getObjAttr(objID, kAttrInvisible); obj.invisible = _world->getObjAttr(objID, kAttrUnclickable); _objQueue.push_back(obj); } @@ -224,7 +225,7 @@ void MacVentureEngine::enqueueText(TextQueueID type, ObjID target, ObjID source, _textQueue.push_back(newText); } -void MacVentureEngine::printTexts() { +bool MacVentureEngine::printTexts() { warning("printTexts: unimplemented"); for (uint i = 0; i < _textQueue.size(); i++) { QueuedText text = _textQueue.front(); @@ -232,12 +233,15 @@ void MacVentureEngine::printTexts() { switch (text.id) { case kTextNumber: debug("Print Number: %d", text.asset); + gameChanged(); break; case kTextNewLine: debug("Print Newline: "); + gameChanged(); break; case kTextPlain: debug("Print Plain Text: %s", _world->getText(text.asset).c_str()); + gameChanged(); break; } } @@ -326,7 +330,8 @@ void MacVentureEngine::endGame() { bool MacVentureEngine::updateState() { runObjQueue(); - return true; + bool wait = printTexts(); + return wait; } void MacVentureEngine::revert() { @@ -359,7 +364,7 @@ void MacVentureEngine::runObjQueue() { closeObject(obj.object); break; case 0x7: - checkObject(obj.object); + checkObject(obj); break; case 0x8: reflectSwap(obj.object); @@ -428,40 +433,68 @@ void MacVentureEngine::closeObject(ObjID objID) { return; } -void MacVentureEngine::checkObject(ObjID objID) { +void MacVentureEngine::checkObject(QueuedObject old) { //warning("checkObject: unimplemented"); bool hasChanged = false; debug("Check Object[%d] parent[%d] x[%d] y[%d]", - objID, - _world->getObjAttr(objID, kAttrParentObject), - _world->getObjAttr(objID, kAttrPosX), - _world->getObjAttr(objID, kAttrPosY)); + old.object, + _world->getObjAttr(old.object, kAttrParentObject), + _world->getObjAttr(old.object, kAttrPosX), + _world->getObjAttr(old.object, kAttrPosY)); //bool incoming = isIncomingObj(objID); //if (incoming) removeIncoming(objID); - if (objID == 1) { - if (_world->getObjAttr(objID, kAttrParentObject) != 0) { - enqueueObject(kSetToPlayerParent, objID); - } - } - _gui->updateWindow(findParentWindow(objID), true); - - WindowReference win = getObjWindow(objID); - ObjID parent = objID; + ObjID id = old.object; + if (id == 1) { + if (old.parent != _world->getObjAttr(id, kAttrParentObject)) { + enqueueObject(kSetToPlayerParent, id); + } + if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) || + old.invisible != _world->getObjAttr(id, kAttrUnclickable)) { + updateWindow(findParentWindow(id)); + } + } else if (old.parent != _world->getObjAttr(id, kAttrParentObject) || + old.x != _world->getObjAttr(id, kAttrPosX) || + old.y != _world->getObjAttr(id, kAttrPosY)) { + WindowReference oldWin = getObjWindow(old.parent); + if (oldWin) { + _gui->removeChild(oldWin, id); + hasChanged = true; + } + + WindowReference newWin = getObjWindow(id); + if (newWin) { + _gui->addChild(newWin, id); + hasChanged = true; + } + } else if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) || + old.invisible != _world->getObjAttr(id, kAttrUnclickable)) { + updateWindow(findParentWindow(id)); + } + + if (_world->getObjAttr(id, kAttrIsExit)) { + if (hasChanged || + old.hidden != _world->getObjAttr(id, kAttrHiddenExit) || + old.exitx != _world->getObjAttr(id, kAttrExitX) || + old.exity != _world->getObjAttr(id, kAttrExitY)) + _gui->drawExit(id); + } + WindowReference win = getObjWindow(id); + ObjID cur = id; ObjID root = _world->getObjAttr(1, kAttrParentObject); - while (parent != root) { - if (parent == 0 || !_world->getObjAttr(parent, kAttrContainerOpen)) break; - parent = _world->getObjAttr(parent, kAttrParentObject); + while (cur != root) { + if (cur == 0 || !_world->getObjAttr(cur, kAttrContainerOpen)) break; + cur = _world->getObjAttr(cur, kAttrParentObject); } - if (parent == root) { + if (cur == root) { if (win) return; - enqueueObject(kOpenWindow, objID); + enqueueObject(kOpenWindow, id); //open } else { if (!win) return; - enqueueObject(kCloseWindow, objID); + enqueueObject(kCloseWindow, id); //close } // Update children - Common::Array<ObjID> children = _world->getChildren(objID, true); + Common::Array<ObjID> children = _world->getChildren(id, true); for (uint i = 0; i < children.size(); i++) { enqueueObject(kUpdateObject, children[i]); } @@ -543,6 +576,19 @@ Common::Point MacVentureEngine::getObjPosition(ObjID objID) { return Common::Point(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY)); } +bool MacVentureEngine::isObjVisible(ObjID objID) { + return _world->getObjAttr(objID, kAttrInvisible) == 0; +} + +bool MacVentureEngine::isObjClickable(ObjID objID) { + return _world->getObjAttr(objID, kAttrUnclickable) == 0; +} + +bool MacVentureEngine::isObjSelected(ObjID objID) { + warning("Unimplemented: isObjSelected"); + return false; +} + WindowReference MacVentureEngine::getObjWindow(ObjID objID) { switch (objID) { case 0xfffc: return kExitsWindow; @@ -555,7 +601,12 @@ WindowReference MacVentureEngine::getObjWindow(ObjID objID) { } WindowReference MacVentureEngine::findObjWindow(ObjID objID) { - return kMainGameWindow; + // This is a bit of a hack, we take advantage of the consecutive nature of references + for (uint i = kCommandsWindow; i <= kDiplomaWindow; i++) { + const WindowData &data = _gui->getWindowData((WindowReference)i); + if (data.refcon == objID) { return data.refcon; } + } + return kNoWindow; } WindowReference MacVentureEngine::findParentWindow(ObjID objID) { diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h index a23dbecd30..7e6f362a8c 100644 --- a/engines/macventure/macventure.h +++ b/engines/macventure/macventure.h @@ -133,7 +133,7 @@ struct QueuedObject { uint exitx; uint exity; bool hidden; - bool offsecreen; + bool offscreen; bool invisible; }; @@ -175,7 +175,7 @@ public: void enqueueText(TextQueueID type, ObjID target, ObjID source, ObjID text); void runObjQueue(); - void printTexts(); + bool printTexts(); void focusObjWin(ObjID objID); void updateWindow(WindowReference winID); @@ -190,7 +190,11 @@ public: uint32 randBetween(uint32 min, uint32 max); uint32 getInvolvedObjects(); + // Attributes consult Common::Point getObjPosition(ObjID objID); + bool isObjVisible(ObjID objID); + bool isObjClickable(ObjID objID); + bool isObjSelected(ObjID objID); WindowReference getObjWindow(ObjID objID); WindowReference findObjWindow(ObjID objID); @@ -212,7 +216,7 @@ private: void focusObjectWindow(ObjID objID); void openObject(ObjID objID); void closeObject(ObjID objID); - void checkObject(ObjID objID); + void checkObject(QueuedObject objID); void reflectSwap(ObjID objID); void toggleExits(); void zoomObject(ObjID objID); @@ -252,6 +256,7 @@ private: // Attributes bool _gameChanged; Common::Array<QueuedObject> _objQueue; + Common::Array<QueuedObject> _inQueue; Common::Array<QueuedObject> _soundQueue; Common::Array<QueuedText> _textQueue; diff --git a/engines/macventure/module.mk b/engines/macventure/module.mk index efd5a693be..022b8d7c32 100644 --- a/engines/macventure/module.mk +++ b/engines/macventure/module.mk @@ -1,13 +1,13 @@ MODULE := engines/macventure MODULE_OBJS := \ + image.o \ detection.o \ gui.o \ object.o \ text.o \ world.o \ script.o \ - image.o \ macventure.o MODULE_DIRS += \ diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp index 7a93773386..2ee7bae92f 100644 --- a/engines/macventure/world.cpp +++ b/engines/macventure/world.cpp @@ -122,7 +122,7 @@ Common::Array<ObjID> World::getChildren(ObjID objID, bool recursive) { res.push_back(getChildren(child, false)); child = _relations[child * 2 + 1]; } - return Common::Array<ObjID>(); + return res; } Attribute World::getGlobal(uint32 attrID) { |