From 517aceefcb397ccda476dc7e2b02d6da5595e4fd Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 30 Jun 2016 08:41:25 +0200 Subject: MACVENTURE: Add scene transition --- engines/macventure/gui.cpp | 280 +++++++++++++++++++++++--------------- engines/macventure/gui.h | 32 +++-- engines/macventure/image.cpp | 8 +- engines/macventure/macventure.cpp | 44 +++++- engines/macventure/macventure.h | 5 +- engines/macventure/world.cpp | 14 +- 6 files changed, 246 insertions(+), 137 deletions(-) diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index 7cae246ab1..15d573b6a8 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -110,12 +110,42 @@ Gui::~Gui() { if (_controlData) delete _controlData; + if (_exitsData) + delete _exitsData; + Common::HashMap::const_iterator it = _assets.begin(); for (; it != _assets.end(); it++) { delete it->_value; } } +void Gui::initGUI() { + _screen.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8()); + _wm.setScreen(&_screen); + + // Menu + _menu = _wm.addMenu(); + if (!loadMenus()) + error("Could not load menus"); + _menu->setCommandsCallback(menuCommandsCallback, this); + _menu->calcDimensions(); + + loadGraphics(); + + if (!loadWindows()) + error("Could not load windows"); + + initWindows(); + + assignObjReferences(); + + if (!loadControls()) + error("Could not load controls"); + + draw(); + +} + void Gui::draw() { // Will be performance-improved after the milestone @@ -138,15 +168,11 @@ void Gui::drawTitle() { warning("drawTitle hasn't been tested yet"); } -void Gui::drawExit(ObjID id) { - findWindowData(kExitsWindow).children.push_back(DrawableObject(id, kBlitDirect)); -} - void Gui::clearControls() { if (!_controlData) return; - Common::List::iterator it = _controlData->begin(); + Common::Array::iterator it = _controlData->begin(); for (; it != _controlData->end(); ++it) { it->unselect(); } @@ -228,33 +254,6 @@ void Gui::removeChild(WindowReference target, ObjID child) { data.children.remove_at(index); } -void Gui::initGUI() { - _screen.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8()); - _wm.setScreen(&_screen); - - // Menu - _menu = _wm.addMenu(); - if (!loadMenus()) - error("Could not load menus"); - _menu->setCommandsCallback(menuCommandsCallback, this); - _menu->calcDimensions(); - - loadGraphics(); - - if (!loadWindows()) - error("Could not load windows"); - - initWindows(); - - assignObjReferences(); - - if (!loadControls()) - error("Could not load controls"); - - draw(); - -} - void Gui::initWindows() { // Game Controls Window @@ -282,7 +281,7 @@ void Gui::initWindows() { loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", true); // Self Window - _selfWindow = _wm.addWindow(false, true, true); + _selfWindow = _wm.addWindow(false, true, false); _selfWindow->setDimensions(getWindowData(kSelfWindow).bounds); _selfWindow->setActive(false); _selfWindow->setCallback(selfWindowCallback, this); @@ -290,7 +289,7 @@ void Gui::initWindows() { loadBorder(_selfWindow, "border_no_scroll_inac.bmp", true); // Exits Window - _exitsWindow = _wm.addWindow(false, true, true); + _exitsWindow = _wm.addWindow(false, false, false); _exitsWindow->setDimensions(getWindowData(kExitsWindow).bounds); _exitsWindow->setActive(false); _exitsWindow->setCallback(exitsWindowCallback, this); @@ -475,7 +474,8 @@ bool Gui::loadControls() { Common::SeekableReadStream *res; Common::MacResIDArray::const_iterator iter; - _controlData = new Common::List(); + _controlData = new Common::Array(); + _exitsData = new Common::Array(); if ((resArray = _resourceManager->getResIDArray(MKTAG('C', 'N', 'T', 'L'))).size() == 0) return false; @@ -541,7 +541,7 @@ void Gui::drawCommandsWindow() { kColorBlack, Graphics::kTextAlignCenter); } else { - Common::List::const_iterator it = _controlData->begin(); + Common::Array::const_iterator it = _controlData->begin(); for (; it != _controlData->end(); ++it) { CommandButton button = *it; if (button.getData().refcon != kControlExitBox) @@ -553,22 +553,22 @@ void Gui::drawCommandsWindow() { void Gui::drawMainGameWindow() { const WindowData &data = getWindowData(kMainGameWindow); BorderBounds border = borderBounds(data.type); + ObjID objRef = data.objRef; _mainGameWindow->setDirty(true); - //if (data.titleLength > 0) - // drawWindowTitle(kMainGameWindow, srf); - - if (!_assets.contains(3)) { - _assets[3] = new ImageAsset(3, _graphics); - } + if (data.objRef > 0 && data.objRef < 2000) { + if (!_assets.contains(objRef)) { + _assets[objRef] = new ImageAsset(objRef, _graphics); + } - _assets[3]->blitInto( - _mainGameWindow->getSurface(), - border.leftOffset, - border.topOffset, - kBlitDirect); + _assets[objRef]->blitInto( + _mainGameWindow->getSurface(), + border.leftOffset, + border.topOffset, + kBlitDirect); + } drawObjectsInWindow(kMainGameWindow, _mainGameWindow->getSurface()); findWindow(kMainGameWindow)->setDirty(true); @@ -603,34 +603,20 @@ void Gui::drawInventories() { } void Gui::drawExitsWindow() { - WindowData &data = findWindowData(kExitsWindow); - BorderBounds border = borderBounds(data.type); + Graphics::ManagedSurface *srf = _exitsWindow->getSurface(); + BorderBounds border = borderBounds(getWindowData(kExitsWindow).type); + srf->fillRect(Common::Rect( border.leftOffset, border.topOffset, srf->w + border.rightOffset, srf->h + border.bottomOffset), kColorWhite); - // For each obj in the main window, if it is an exit, we draw it - WindowData &objData = findWindowData(kMainGameWindow); - Common::Point pos; - ObjID child; - //BlitMode mode; - Common::Rect exit; - for (uint i = 0; i < objData.children.size(); i++) { - child = objData.children[i].obj; - //mode = (BlitMode)objData.children[i].mode; - pos = _engine->getObjExitPosition(child); - pos.x += border.leftOffset; - pos.y += border.topOffset; - exit = Common::Rect(pos.x, pos.y, pos.x + kExitButtonWidth, pos.y + kExitButtonHeight); - if (_engine->isObjExit(child)) { - if (_engine->isObjSelected(child)) - srf->fillRect(exit, kColorGreen); - - srf->fillRect(exit, kColorGreen); - } + Common::Array::const_iterator it = _exitsData->begin(); + for (; it != _exitsData->end(); ++it) { + CommandButton button = *it; + button.draw(*_exitsWindow->getSurface()); } findWindow(kExitsWindow)->setDirty(true); @@ -719,6 +705,92 @@ void Gui::drawDraggedObject() { } } + +void Gui::updateWindow(WindowReference winID, bool containerOpen) { + if (winID == kSelfWindow || containerOpen) { + WindowData &data = findWindowData(winID); + if (winID == kCommandsWindow) { + Common::Array::iterator it = _controlData->begin(); + for (; it != _controlData->end(); ++it) { + it->unselect(); + } + } + Common::Array &children = data.children; + for (uint i = 0; i < children.size(); i++) { + uint flag = 0; + ObjID child = children[i].obj; + BlitMode mode = kBlitDirect; + bool off = !_engine->isObjVisible(child); + if (flag || !off || !_engine->isObjClickable(child)) { + mode = kBlitBIC; + if (off || flag) { + mode = kBlitXOR; + } + else if (_engine->isObjSelected(child)) { + mode = kBlitOR; + } + children[i] = DrawableObject(child, mode); + } + else { + children[i] = DrawableObject(child, kBlitXOR); + } + } + if (winID == kMainGameWindow) { + drawMainGameWindow(); + } + else { + Graphics::MacWindow *winRef = findWindow(winID); + winRef->getSurface()->fillRect(data.bounds, kColorGray); + } + if (data.type == kZoomDoc && data.updateScroll) { + warning("Unimplemented: update scroll"); + } + } +} + +void Gui::unselectExits() { + Common::Array::const_iterator it = _exitsData->begin(); + for (; it != _exitsData->end(); ++it) { + CommandButton button = *it; + button.unselect(); + } +} + +void Gui::updateExit(ObjID obj) { + if (!_engine->isObjExit(obj)) return; + + BorderBounds border = borderBounds(getWindowData(kExitsWindow).type); + + int ctl = -1; + int i = 0; + Common::Array::const_iterator it = _exitsData->begin(); + for (;it != _exitsData->end(); it++) { + if (it->getData().refcon == obj) + ctl = i; + else + i++; + } + + if (ctl != -1) + _exitsData->remove_at(ctl); + + if (!_engine->isHiddenExit(obj) && + _engine->getParent(obj) == _engine->getParent(1)) + { + ControlData data; + data.titleLength = 0; + data.refcon = obj; + Common::Point pos = _engine->getObjExitPosition(obj); + pos.x = border.leftOffset; + pos.y = border.topOffset; + data.bounds = Common::Rect(pos.x, pos.y, pos.x + kExitButtonWidth, pos.y + kExitButtonHeight); + data.visible = true; + + _exitsData->push_back(CommandButton(data, this)); + } +} + + WindowData & Gui::findWindowData(WindowReference reference) { assert(_windowData); @@ -894,46 +966,6 @@ void menuCommandsCallback(int action, Common::String &text, void *data) { g->handleMenuAction((MenuAction)action); } -void Gui::updateWindow(WindowReference winID, bool containerOpen) { - if (winID == kNoWindow) return; - if (winID == kSelfWindow || containerOpen) { - WindowData &data = findWindowData(winID); - if (winID == kCommandsWindow) { - Common::List::iterator it = _controlData->begin(); - for (; it != _controlData->end(); ++it) { - it->unselect(); - } - } - Common::Array &children = data.children; - for (uint i = 0; i < children.size(); i++) { - uint flag = 0; - ObjID child = children[i].obj; - BlitMode mode = kBlitDirect; - bool off = !_engine->isObjVisible(child); - if (flag || !off || !_engine->isObjClickable(child)) { - mode = kBlitBIC; - if (off || flag) { - mode = kBlitXOR; - } else if (_engine->isObjSelected(child)) { - mode = kBlitOR; - } - children[i] = DrawableObject(child, mode); - } else { - children[i] = DrawableObject(child, kBlitXOR); - } - } - if (winID == kMainGameWindow) { - drawMainGameWindow(); - } - else { - Graphics::MacWindow *winRef = findWindow(winID); - winRef->getSurface()->fillRect(data.bounds, kColorGray); - } - if (data.type == kZoomDoc && data.updateScroll) { - warning("Unimplemented: update scroll"); - } - } -} void Gui::invertWindowColors(WindowReference winID) { Graphics::ManagedSurface *srf = findWindow(winID)->getSurface(); @@ -1006,7 +1038,7 @@ bool Gui::processCommandEvents(WindowClick click, Common::Event &event) { if (!_controlData) return false; - Common::List::iterator it = _controlData->begin(); + Common::Array::iterator it = _controlData->begin(); for (; it != _controlData->end(); ++it) { if (it->isInsideBounds(position)) { it->select(); @@ -1064,8 +1096,32 @@ bool MacVenture::Gui::processSelfEvents(WindowClick click, Common::Event & event } bool MacVenture::Gui::processExitsEvents(WindowClick click, Common::Event & event) { - if (_engine->needsClickToContinue()) - return true; + if (event.type == Common::EVENT_LBUTTONUP) { + if (_engine->needsClickToContinue()) { + return true; + } + + Common::Point position( + event.mouse.x - _exitsWindow->getDimensions().left, + event.mouse.y - _exitsWindow->getDimensions().top); + + CommandButton data; + if (!_exitsData) + return false; + + Common::Array::iterator it = _exitsData->begin(); + for (; it != _exitsData->end(); ++it) { + if (it->isInsideBounds(position)) { + it->select(); + data = *it; + } + else { + it->unselect(); + } + } + + _engine->handleObjectSelect(data.getData().refcon, kExitsWindow, event); + } return getWindowData(kExitsWindow).visible; } @@ -1118,7 +1174,7 @@ BorderBounds Gui::borderBounds(MVWindowType type) { case MacVenture::kPlainDBox: return BorderBounds(6, 6, 6, 6); case MacVenture::kAltBox: - //return BorderBounds(8, 9, 11, 10); // For now, I'll stick to the original bmp, it's gorgeous + return BorderBounds(8, 9, 11, 10); // For now, I'll stick to the original bmp, it's gorgeous break; case MacVenture::kNoGrowDoc: return BorderBounds(1, 17, 1, 1); diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index 73c4318408..dd08173d3c 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -129,7 +129,7 @@ struct ControlData { uint16 scrollMax; uint16 scrollMin; uint16 cdef; - uint32 refcon; + uint32 refcon; // If exits window, then the obj id. Otherwise, the control type uint8 titleLength; char* title; uint16 border; @@ -159,7 +159,7 @@ public: void draw(); void drawMenu(); void drawTitle(); - void drawExit(ObjID id); + void clearControls(); bool processEvent(Common::Event &event); void handleMenuAction(MenuAction action); @@ -195,6 +195,9 @@ public: void addChild(WindowReference target, ObjID child); void removeChild(WindowReference target, ObjID child); + void unselectExits(); + void updateExit(ObjID id); + // Ugly switches BorderBounds borderBounds(MVWindowType type); @@ -207,7 +210,8 @@ private: // Attributes Graphics::MacWindowManager _wm; Common::List *_windowData; - Common::List *_controlData; + Common::Array *_controlData; + Common::Array *_exitsData; Graphics::MacWindow *_controlsWindow; Graphics::MacWindow *_mainGameWindow; @@ -290,16 +294,18 @@ public: surface.fillRect(_data.bounds, colorFill); surface.frameRect(_data.bounds, kColorBlack); - const Graphics::Font &font = _gui->getCurrentFont(); - Common::String title(_data.title); - font.drawString( - &surface, - title, - _data.bounds.left, - _data.bounds.top, - _data.bounds.right - _data.bounds.left, - colorText, - Graphics::kTextAlignCenter); + if (_data.titleLength > 0) { + const Graphics::Font &font = _gui->getCurrentFont(); + Common::String title(_data.title); + font.drawString( + &surface, + title, + _data.bounds.left, + _data.bounds.top, + _data.bounds.right - _data.bounds.left, + colorText, + Graphics::kTextAlignCenter); + } } bool isInsideBounds(const Common::Point point) const { diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index d880e142bb..1aae1727ef 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -77,7 +77,13 @@ ImageAsset::~ImageAsset() { void ImageAsset::decodePPIC(ObjID id, Common::Array &data) { ObjID realID = id; uint32 size = _container->getItemByteSize(id); - if (size == 2 || size == 0) { + if (size < 2) { + _rowBytes = 0; + _bitHeight = 0; + _bitHeight = 0; + return; + } + if (size == 2) { realID = _container->getItem(id)->readUint16BE(); } Common::BitStream32BEMSB stream(_container->getItem(realID), true); diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp index 8624159a95..08b5ec90c1 100644 --- a/engines/macventure/macventure.cpp +++ b/engines/macventure/macventure.cpp @@ -174,7 +174,7 @@ void MacVentureEngine::requestUnpause() { void MacVentureEngine::selectControl(ControlReference id) { ControlAction action = referenceToAction(id); - debug(4, "Select control %x", action); + debug(2, "Select control %x", action); _selectedControl = action; } @@ -190,7 +190,7 @@ void MacVentureEngine::activateCommand(ControlReference id) { _activeControl = kNoCommand; _activeControl = action; } - debug(4, "Activating Command %x... Command %x is active", action, _activeControl); + debug(2, "Activating Command %x... Command %x is active", action, _activeControl); refreshReady(); } @@ -520,6 +520,17 @@ void MacVentureEngine::unselectObject(ObjID objID) { } } + +void MacVentureEngine::updateExits() { + // exitWin.killControls(); + _gui->unselectExits(); + + Common::Array exits = _world->getChildren(_world->getObjAttr(1, kAttrParentObject), true); + for (uint i = 0; i < exits.size(); i++) + _gui->updateExit(exits[i]); + +} + int MacVentureEngine::findObjectInArray(ObjID objID, const Common::Array &list) { // Find the object in the current selection bool found = false; @@ -542,7 +553,7 @@ Common::String MacVentureEngine::getPrefixString(uint flag, ObjID obj) { if (ndx) { return _decodingNamingArticles->getString(ndx); } else { - return Common::String("missigno "); + return Common::String("m1551gn0 "); } } @@ -551,7 +562,20 @@ Common::String MacVentureEngine::getNoun(ObjID ndx) { } void MacVentureEngine::highlightExit(ObjID objID) { - warning("highlightExit: unimplemented"); + //ObjID ctl = _gui->getWinChild(obj); + /*if (ctl) { + if (findObjectInArray(obj, _selectedObjs) != -1) + _gui->selectExit(ctl); + else + _gui->unselectExit(ctl); + } + if (obj == _world->getObjAttr(1, kAttrParentObject)) { + if (findObjectInArray(obj, _selectedObjs) != -1) + _gui->selectExit(obj); + else + _gui->unselectExit(obj); + }*/ + //updateWindow(findParentWindow(obj)); } void MacVentureEngine::selectPrimaryObject(ObjID objID) { @@ -587,7 +611,7 @@ void MacVentureEngine::openObject(ObjID objID) { if (objID == _world->getObjAttr(1, kAttrParentObject)) { _gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true)); _gui->updateWindow(kMainGameWindow, _world->getObjAttr(objID, kAttrContainerOpen)); - //_gui->drawExits(); + updateExits(); _gui->setWindowTitle(kMainGameWindow, _world->getText(objID, objID, objID)); // it ignores source and target in the original } else { // Open inventory window Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY)); @@ -649,7 +673,7 @@ void MacVentureEngine::checkObject(QueuedObject old) { old.hidden != _world->getObjAttr(id, kAttrHiddenExit) || old.exitx != _world->getObjAttr(id, kAttrExitX) || old.exity != _world->getObjAttr(id, kAttrExitY)) - _gui->drawExit(id); + _gui->updateExit(id); } WindowReference win = getObjWindow(id); ObjID cur = id; @@ -787,12 +811,20 @@ bool MacVentureEngine::isObjExit(ObjID objID) { return _world->getObjAttr(objID, kAttrIsExit); } +bool MacVentureEngine::isHiddenExit(ObjID objID) { + return _world->getObjAttr(objID, kAttrHiddenExit); +} + Common::Point MacVentureEngine::getObjExitPosition(ObjID objID) { uint x = _world->getObjAttr(objID, kAttrExitX); uint y = _world->getObjAttr(objID, kAttrExitY); return Common::Point(x, y); } +ObjID MacVentureEngine::getParent(ObjID objID) { + return _world->getObjAttr(objID, kAttrParentObject); +} + Common::Rect MacVentureEngine::getObjBounds(ObjID objID) { Common::Point pos = getObjPosition(objID); uint w = _gui->getObjWidth(objID); // This shouldn't go here diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h index 28c3bf9ad3..9ecfbc0fd7 100644 --- a/engines/macventure/macventure.h +++ b/engines/macventure/macventure.h @@ -205,7 +205,10 @@ public: bool isObjClickable(ObjID objID); bool isObjSelected(ObjID objID); bool isObjExit(ObjID objID); + bool isHiddenExit(ObjID objID); Common::Point getObjExitPosition(ObjID objID); + ObjID getParent(ObjID objID); + // Encapsulation HACK Common::Rect getObjBounds(ObjID objID); @@ -232,7 +235,7 @@ private: void unselectObject(ObjID objID); void highlightExit(ObjID objID); void selectPrimaryObject(ObjID objID); - + void updateExits(); // Object queue methods void focusObjectWindow(ObjID objID); diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp index 8e83f91057..670f39902c 100644 --- a/engines/macventure/world.cpp +++ b/engines/macventure/world.cpp @@ -43,17 +43,23 @@ World::~World() { uint32 World::getObjAttr(ObjID objID, uint32 attrID) { uint32 res; uint32 index = _engine->getGlobalSettings().attrIndices[attrID]; + // HACK, but if I try to initialize it in the else clause, it goes out of scope and segfaults + Common::SeekableReadStream *objStream = _objectConstants->getItem(objID); if (!(index & 0x80)) { // It's not a constant res = _saveGame->getAttr(objID, index); } else { - Common::SeekableReadStream *objStream = _objectConstants->getItem(objID); index &= 0x7F; - objStream->skip((index * 2) - 1); - res = objStream->readUint16BE(); + if (objStream->size() == 0) return 0; + // Look for the right attribute inside the object + objStream->skip(index * 2); + res = objStream->readByte() << 8; + res |= objStream->readByte(); } res &= _engine->getGlobalSettings().attrMasks[attrID]; res >>= _engine->getGlobalSettings().attrShifts[attrID]; - debug(11, "Attribute %x from object %x is %x", attrID, objID, res); + if (res & 0x8000) + res = -((res ^ 0xffff) + 1); + debug(3, "Attribute %x from object %x is %x", attrID, objID, res); return res; } -- cgit v1.2.3