diff options
author | Borja Lorente | 2016-06-23 23:21:24 +0200 |
---|---|---|
committer | Borja Lorente | 2016-08-14 18:37:46 +0200 |
commit | ba5ed7fc88a69da782f3df18698837a67a59eb6b (patch) | |
tree | 998728703466844f22fa1ac109efa6315c1572ac | |
parent | ec7eb7cb5bec5174f7fd3446824280ab44050f5e (diff) | |
download | scummvm-rg350-ba5ed7fc88a69da782f3df18698837a67a59eb6b.tar.gz scummvm-rg350-ba5ed7fc88a69da782f3df18698837a67a59eb6b.tar.bz2 scummvm-rg350-ba5ed7fc88a69da782f3df18698837a67a59eb6b.zip |
MACVENTURE: Major push in functionality and rendering
-rw-r--r-- | engines/macventure/gui.cpp | 401 | ||||
-rw-r--r-- | engines/macventure/gui.h | 30 | ||||
-rw-r--r-- | engines/macventure/image.cpp | 84 | ||||
-rw-r--r-- | engines/macventure/image.h | 2 | ||||
-rw-r--r-- | engines/macventure/macventure.cpp | 132 | ||||
-rw-r--r-- | engines/macventure/macventure.h | 9 | ||||
-rw-r--r-- | engines/macventure/script.cpp | 55 |
7 files changed, 478 insertions, 235 deletions
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index f1eb8b63e6..d4fd337557 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -106,6 +106,8 @@ void Gui::draw() { drawWindows(); _wm.draw(); + + //drawWindowTitle(kMainGameWindow, _mainGameWindow->getSurface()); } void Gui::drawMenu() { @@ -117,7 +119,17 @@ void Gui::drawTitle() { } void Gui::drawExit(ObjID id) { - warning("Unimplemented method: drawExit"); + findWindowData(kExitsWindow).children.push_back(DrawableObject(id, kBlitDirect)); +} + +void Gui::clearControls() { + if (!_controlData) + return; + + Common::List<CommandButton>::iterator it = _controlData->begin(); + for (; it != _controlData->end(); ++it) { + it->unselect(); + } } const WindowData& Gui::getWindowData(WindowReference reference) { @@ -234,44 +246,65 @@ void Gui::initWindows() { _mainGameWindow->setDimensions(getWindowData(kMainGameWindow).bounds); _mainGameWindow->setActive(false); _mainGameWindow->setCallback(mainGameWindowCallback, this); - loadBorder(_mainGameWindow, "border_command.bmp", false); - loadBorder(_mainGameWindow, "border_command.bmp", true); + loadBorder(_mainGameWindow, "border_no_scroll_inac.bmp", false); + loadBorder(_mainGameWindow, "border_no_scroll_act.bmp", true); // In-game Output Console _outConsoleWindow = _wm.addWindow(false, true, true); _outConsoleWindow->setDimensions(Common::Rect(20, 20, 120, 120)); _outConsoleWindow->setActive(false); _outConsoleWindow->setCallback(outConsoleWindowCallback, this); - loadBorder(_outConsoleWindow, "border_command.bmp", false); + loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", false); + loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", true); // Self Window _selfWindow = _wm.addWindow(false, true, true); _selfWindow->setDimensions(getWindowData(kSelfWindow).bounds); _selfWindow->setActive(false); _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)); + loadBorder(_selfWindow, "border_no_scroll_inac.bmp", false); + loadBorder(_selfWindow, "border_no_scroll_inac.bmp", true); // Exits Window _exitsWindow = _wm.addWindow(false, true, true); _exitsWindow->setDimensions(getWindowData(kExitsWindow).bounds); _exitsWindow->setActive(false); _exitsWindow->setCallback(exitsWindowCallback, this); - loadBorder(_exitsWindow, "border_title_inac.bmp", false); - loadBorder(_exitsWindow, "border_title_inac.bmp", true); + loadBorder(_exitsWindow, "border_no_scroll_inac.bmp", false); + loadBorder(_exitsWindow, "border_no_scroll_act.bmp", true); + +} + +WindowReference Gui::createInventoryWindow() { + Graphics::MacWindow *newWindow = _wm.addWindow(true, true, true); + WindowData newData; + GlobalSettings settings = _engine->getGlobalSettings(); + newData.refcon = (WindowReference)ABS(_inventoryWindows.size()); // This is a hack + + if (_windowData->back().refcon < 0x80) { // There is already another inventory window + newData.bounds = _windowData->back().bounds; // Inventory windows are always last + newData.bounds.translate(newData.bounds.left + settings.invOffsetX, newData.bounds.top + settings.invOffsetY); + } + else { + newData.bounds = Common::Rect( + settings.invLeft, + settings.invTop, + settings.invLeft + settings.invWidth, + settings.invTop + settings.invHeight); + } + newData.type = kZoomDoc; + newData.hasCloseBox = true; + newData.visible = true; + _windowData->push_back(newData); - // Diploma Window (we can go without it for now) - /* - _diplomaWindow = _wm.addWindow(false, true, true); - _diplomaWindow->setDimensions(getWindowData(kDiplomaWindow).bounds); - _diplomaWindow->setActive(false); - _diplomaWindow->setCallback(diplomaWindowCallback, this); - loadBorder(_diplomaWindow, "border_command.bmp", false); - // Render invisible for now - _diplomaWindow->getSurface()->fillRect(_diplomaWindow->getSurface()->getBounds(), kColorGreen2); - */ + newWindow->setDimensions(newData.bounds); + newWindow->setCallback(inventoryWindowCallback, this); + loadBorder(newWindow, "border_no_scroll_inac.bmp", false); + loadBorder(newWindow, "border_no_scroll_act.bmp", true); + _inventoryWindows.push_back(newWindow); + debug("Create new inventory window. Reference: %d", newData.refcon); + return newData.refcon; } void Gui::loadBorder(Graphics::MacWindow * target, Common::String filename, bool active) { @@ -464,11 +497,14 @@ void Gui::drawWindows() { drawCommandsWindow(); drawMainGameWindow(); + drawSelfWindow(); + drawInventories(); + drawExitsWindow(); } void Gui::drawCommandsWindow() { - if (_engine->isPaused()) { + if (_engine->needsClickToContinue()) { Graphics::ManagedSurface *srf = _controlsWindow->getSurface(); WindowData data = getWindowData(kCommandsWindow); uint16 border = borderBounds(data.type).topOffset; @@ -493,51 +529,113 @@ void Gui::drawCommandsWindow() { void Gui::drawMainGameWindow() { Graphics::ManagedSurface *srf = _mainGameWindow->getSurface(); - BorderBounds border = borderBounds(getWindowData(kMainGameWindow).type); + const WindowData &data = getWindowData(kMainGameWindow); + BorderBounds border = borderBounds(data.type); _mainGameWindow->setDirty(true); + //if (data.titleLength > 0) + // drawWindowTitle(kMainGameWindow, srf); + if (!_assets.contains(3)) { _assets[3] = new ImageAsset(3, _graphics); } _assets[3]->blitInto( _mainGameWindow->getSurface(), - border.leftOffset * 2, - border.topOffset * 2, + border.leftOffset, + border.topOffset, kBlitDirect); drawObjectsInWindow(kMainGameWindow, _mainGameWindow->getSurface()); - } void Gui::drawSelfWindow() { - Graphics::ManagedSurface *srf = _selfWindow->getSurface(); - BorderBounds border = borderBounds(getWindowData(kSelfWindow).type); + drawObjectsInWindow(kSelfWindow, _selfWindow->getSurface()); + if (_engine->isObjSelected(1)) invertWindowColors(kSelfWindow); +} + +void Gui::drawInventories() { + Common::List<WindowData>::const_iterator it = _windowData->begin(); + while (it != _windowData->end() && (*it).refcon >= 0x80) { + it++; + } + Graphics::ManagedSurface *srf; + while (it != _windowData->end()) { + srf = _inventoryWindows[(*it).refcon]->getSurface(); + BorderBounds border = borderBounds((*it).type); + srf->fillRect(Common::Rect( + border.leftOffset, + border.topOffset, + srf->w + border.rightOffset, + srf->h + border.bottomOffset), kColorWhite); + drawObjectsInWindow((*it).refcon, _inventoryWindows[(*it).refcon]->getSurface()); + it++; + } +} + +void Gui::drawExitsWindow() { + WindowData &data = findWindowData(kExitsWindow); + BorderBounds border = borderBounds(data.type); + Graphics::ManagedSurface *srf = _exitsWindow->getSurface(); + srf->fillRect(Common::Rect( + border.leftOffset, + border.topOffset, + srf->w + border.rightOffset, + srf->h + border.bottomOffset), kColorWhite); + + drawObjectsInWindow(kExitsWindow, _exitsWindow->getSurface()); } void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * surface) { - WindowData &data = findWindowData(kMainGameWindow); + WindowData &data = findWindowData(target); 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; + + if (data.children.size() == 0) return; + + Common::Point forbidden(0, 0); + for (uint i = 0; i < data.children.size(); i++) { + child = data.children[i].obj; + mode = (BlitMode)data.children[i].mode; pos = _engine->getObjPosition(child); - if (!_assets.contains(child)) { - _assets[child] = new ImageAsset(child, _graphics); + + if (pos != forbidden || child < 600) { // Small HACK until I figre out where the last garbage child in main game window comes from + if (!_assets.contains(child)) { + _assets[child] = new ImageAsset(child, _graphics); + } + + _assets[child]->blitInto( + surface, + border.leftOffset + pos.x, + border.topOffset + pos.y, + mode); } - _assets[child]->blitInto( - surface, - border.leftOffset * 2 + pos.x, - border.topOffset * 2 + pos.y, - mode); - - // To be deleted, this is a big hack, but it doesn't work without it. - _wm.draw(); + } + + findWindow(data.refcon)->setDirty(true); + +} + +void Gui::drawWindowTitle(WindowReference target, Graphics::ManagedSurface * surface) { + WindowData &data = findWindowData(target); + BorderBounds border = borderBounds(data.type); + + uint left = 10;//getCurrentFont().getStringWidth(data.title) - 10; + uint right = 30;//getCurrentFont().getStringWidth(data.title) + 10; + + surface->fillRect(Common::Rect(left, 0, right, border.topOffset - 1), kColorGray); + getCurrentFont().drawString( + surface, + data.title, + 0, + right, + right - left, + kColorBlack, + Graphics::kTextAlignCenter); } WindowData & Gui::findWindowData(WindowReference reference) { @@ -554,56 +652,29 @@ WindowData & Gui::findWindowData(WindowReference reference) { error("Could not locate the desired window data"); } - -/* CALLBACKS */ - -bool commandsWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processCommandEvents(click, event); -} - -bool mainGameWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processMainGameEvents(click, event); -} - -bool outConsoleWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processOutConsoleEvents(click, event); -} - -bool selfWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processSelfEvents(click, event); -} - -bool exitsWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processExitsEvents(click, event); -} - -bool diplomaWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processDiplomaEvents(click, event); -} - -bool inventoryWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { - Gui *g = (Gui*)gui; - - return g->processInventoryEvents(click, event); +Graphics::MacWindow * Gui::findWindow(WindowReference reference) { + if (reference < 0x80) { // It's an inventory window + return _inventoryWindows[reference]; + } + switch (reference) { + case MacVenture::kNoWindow: + return nullptr; + case MacVenture::kCommandsWindow: + return _controlsWindow; + case MacVenture::kMainGameWindow: + return _mainGameWindow; + case MacVenture::kOutConsoleWindow: + return _outConsoleWindow; + case MacVenture::kSelfWindow: + return _selfWindow; + case MacVenture::kExitsWindow: + return _exitsWindow; + case MacVenture::kDiplomaWindow: + return _diplomaWindow; + } + return nullptr; } -void menuCommandsCallback(int action, Common::String &text, void *data) { - Gui *g = (Gui *)data; - - g->handleMenuAction((MenuAction)action); -} /* HANDLERS */ void Gui::handleMenuAction(MenuAction action) { @@ -655,15 +726,66 @@ void Gui::handleMenuAction(MenuAction action) { } } +/* CALLBACKS */ + +bool commandsWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + return g->processCommandEvents(click, event); +} + +bool mainGameWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + return g->processMainGameEvents(click, event); +} + +bool outConsoleWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + return g->processOutConsoleEvents(click, event); +} + +bool selfWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + + return g->processSelfEvents(click, event); +} + +bool exitsWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + + return g->processExitsEvents(click, event); +} + +bool diplomaWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + + return g->processDiplomaEvents(click, event); +} + +bool inventoryWindowCallback(Graphics::WindowClick click, Common::Event &event, void *gui) { + Gui *g = (Gui*)gui; + + return g->processInventoryEvents(click, event); +} + +void menuCommandsCallback(int action, Common::String &text, void *data) { + Gui *g = (Gui *)data; + + g->handleMenuAction((MenuAction)action); +} + void Gui::updateWindow(WindowReference winID, bool containerOpen) { - if (winID > 0x90 || winID == kNoWindow) return; + if (winID == kNoWindow) return; if (winID == kSelfWindow || containerOpen) { - if (winID == kMainGameWindow) { - drawMainGameWindow(); + WindowData &data = findWindowData(winID); + if (winID == kCommandsWindow) { + Common::List<CommandButton>::iterator it = _controlData->begin(); + for (; it != _controlData->end(); ++it) { + it->unselect(); + } } else { - warning("Unimplemented: fill window with background"); + Graphics::MacWindow *winRef = findWindow(winID); + winRef->getSurface()->fillRect(data.bounds, kColorGray); } - WindowData &data = findWindowData(winID); Common::Array<DrawableObject> &children = data.children; for (uint i = 0; i < children.size(); i++) { uint flag = 0; @@ -680,41 +802,24 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) { children[i] = DrawableObject(child, mode); } } + if (winID == kMainGameWindow) { + drawMainGameWindow(); + } if (data.type == kZoomDoc && data.updateScroll) { warning("Unimplemented: update scroll"); } } } -WindowReference Gui::createInventoryWindow() { - Graphics::MacWindow *newWindow = _wm.addWindow(true, true, true); - WindowData newData; - GlobalSettings settings = _engine->getGlobalSettings(); - newData.refcon = (WindowReference)ABS(_inventoryWindows.size()); // This is a hack - - if (_windowData->back().refcon < 0x80) { // There is already another inventory window - newData.bounds = _windowData->back().bounds; // Inventory windows are always last - newData.bounds.translate(newData.bounds.left + settings.invOffsetX, newData.bounds.top + settings.invOffsetY); - } else { - newData.bounds = Common::Rect( - settings.invLeft, - settings.invTop, - settings.invLeft + settings.invWidth, - settings.invTop + settings.invHeight); +void Gui::invertWindowColors(WindowReference winID) { + Graphics::ManagedSurface *srf = findWindow(winID)->getSurface(); + for (uint y = 0; y < srf->h; y++) { + for (uint x = 0; x < srf->w; x++) { + byte p = *(byte *)srf->getBasePtr(x, y); + *(byte *)srf->getBasePtr(x, y) = + (p == kColorWhite) ? kColorBlack : kColorGray; + } } - newData.type = kZoomDoc; - newData.hasCloseBox = true; - newData.visible = true; - _windowData->push_back(newData); - - newWindow->setDimensions(newData.bounds); - newWindow->setCallback(inventoryWindowCallback, this); - loadBorder(newWindow, "border_self_inac.bmp", false); - loadBorder(newWindow, "border_self_act.bmp", true); - _inventoryWindows.push_back(newWindow); - - debug(3, "Create new inventory window. Reference: %d", newData.refcon); - return newData.refcon; } bool Gui::tryCloseWindow(WindowReference winID) { @@ -729,30 +834,41 @@ bool Gui::tryCloseWindow(WindowReference winID) { bool Gui::processEvent(Common::Event &event) { bool processed = false; - if (event.type == Common::EVENT_LBUTTONDOWN) { - debug("Click on the ui"); + if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP) { + _engine->updateDelta(event.mouse); + processed = true; } - return (processed || _wm.processEvent(event)); + processed |= _wm.processEvent(event); + return (processed); } bool Gui::processCommandEvents(WindowClick click, Common::Event &event) { if (event.type == Common::EVENT_LBUTTONUP) { - if (_engine->isPaused()) + if (_engine->needsClickToContinue()) { + _engine->activateCommand(kControlClickToContinue); return true; + } Common::Point position( event.mouse.x - _controlsWindow->getDimensions().left, event.mouse.y - _controlsWindow->getDimensions().top); CommandButton data; - Common::List<CommandButton>::const_iterator it = _controlData->begin(); + if (!_controlData) + return false; + + Common::List<CommandButton>::iterator it = _controlData->begin(); for (; it != _controlData->end(); ++it) { if (it->isInsideBounds(position)) { - debug(4, "Command active: %s", it->getData().title); + it->select(); data = *it; } + else { + it->unselect(); + } } + _engine->selectControl((ControlReference)data.getData().refcon); _engine->activateCommand((ControlReference)data.getData().refcon); _engine->refreshReady(); @@ -762,6 +878,9 @@ bool Gui::processCommandEvents(WindowClick click, Common::Event &event) { } bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event & event) { + if (_engine->needsClickToContinue()) + return true; + if (click == kBorderInner && event.type == Common::EVENT_LBUTTONUP) { WindowData &data = findWindowData(kMainGameWindow); ObjID child; @@ -769,36 +888,52 @@ bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event & e Common::Point pos; 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); - pos.x += data.bounds.left; - pos.y += data.bounds.top; - if (_assets[child]->isPointInside(pos, event.mouse)) { + pos.x += _mainGameWindow->getDimensions().left; + pos.y += _mainGameWindow->getDimensions().top; + pos = event.mouse - pos; + if (_assets.contains(child) && _assets[child]->isPointInside(pos)) { // select the first object clicked _engine->selectObject(child); - return true; } } } return false; } bool MacVenture::Gui::processOutConsoleEvents(WindowClick click, Common::Event & event) { + if (_engine->needsClickToContinue()) + return true; + return getWindowData(kOutConsoleWindow).visible; } bool MacVenture::Gui::processSelfEvents(WindowClick click, Common::Event & event) { - return getWindowData(kSelfWindow).visible; + if (_engine->needsClickToContinue()) + return true; + + if (event.type == Common::EVENT_LBUTTONUP) { + _engine->selectObject(1); + } + return true; } bool MacVenture::Gui::processExitsEvents(WindowClick click, Common::Event & event) { + if (_engine->needsClickToContinue()) + return true; return getWindowData(kExitsWindow).visible; } bool MacVenture::Gui::processDiplomaEvents(WindowClick click, Common::Event & event) { + if (_engine->needsClickToContinue()) + return true; + return getWindowData(kDiplomaWindow).visible; } bool Gui::processInventoryEvents(WindowClick click, Common::Event & event) { + if (_engine->needsClickToContinue()) + return true; + return false; } diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index 2e8b6e20a2..b7d5d52b83 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -117,7 +117,8 @@ enum ControlReference { kControlOperate = 5, kControlGo = 6, kControlHit = 7, - kControlConsume = 8 + kControlConsume = 8, + kControlClickToContinue = 9 }; struct ControlData { @@ -153,9 +154,11 @@ public: void drawMenu(); void drawTitle(); void drawExit(ObjID id); + void clearControls(); bool processEvent(Common::Event &event); void handleMenuAction(MenuAction action); void updateWindow(WindowReference winID, bool containerOpen); + void invertWindowColors(WindowReference winID); WindowReference createInventoryWindow(); bool tryCloseWindow(WindowReference winID); @@ -225,11 +228,15 @@ private: // Methods void drawCommandsWindow(); void drawMainGameWindow(); void drawSelfWindow(); + void drawInventories(); + void drawExitsWindow(); void drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface *surface); + void drawWindowTitle(WindowReference target, Graphics::ManagedSurface *surface); // Finders WindowData& findWindowData(WindowReference reference); + Graphics::MacWindow *findWindow(WindowReference reference); }; @@ -249,12 +256,16 @@ public: CommandButton(ControlData data, Gui *g) { _data = data; _gui = g; + _selected = false; } ~CommandButton() {} void draw(Graphics::ManagedSurface &surface) const { - surface.fillRect(_data.bounds, kColorWhite); + uint colorFill = _selected ? kColorBlack : kColorWhite; + uint colorText = _selected ? kColorWhite : kColorBlack; + + surface.fillRect(_data.bounds, colorFill); surface.frameRect(_data.bounds, kColorBlack); const Graphics::Font &font = _gui->getCurrentFont(); @@ -265,7 +276,7 @@ public: _data.bounds.left, _data.bounds.top, _data.bounds.right - _data.bounds.left, - kColorBlack, + colorText, Graphics::kTextAlignCenter); } @@ -277,7 +288,20 @@ public: return _data; } + void select() { + _selected = true; + } + + void unselect() { + _selected = false; + } + + bool isSelected() { + return _selected; + } + private: + bool _selected; ControlData _data; Gui *_gui; }; diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index de4e3ba12e..54d19c9fd2 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -311,40 +311,47 @@ byte ImageAsset::walkHuff(const PPICHuff & huff, Common::BitStream & stream) { void ImageAsset::blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y, BlitMode mode) { if (mode == kBlitDirect) { blitDirect(target, x, y, _imgData); - return; - } - - if (_container->getItemByteSize(_mask)) { // Has mask - switch (mode) { - case MacVenture::kBlitBIC: - blitBIC(target, x, y, _maskData); - break; - case MacVenture::kBlitOR: - blitOR(target, x, y, _maskData); - break; - } - } else if (_container->getItemByteSize(_id)) { - switch (mode) { - case MacVenture::kBlitBIC: - target->fillRect(Common::Rect(x, y, x + _bitWidth, y + _bitHeight * 2), kColorWhite); - break; - case MacVenture::kBlitOR: - target->fillRect(Common::Rect(x, y, x + _bitWidth, y + _bitHeight * 2), kColorBlack); - break; + } else if (mode < kBlitXOR){ + if (_container->getItemByteSize(_mask)) { // Has mask + switch (mode) { + case MacVenture::kBlitBIC: + blitBIC(target, x, y, _maskData); + break; + case MacVenture::kBlitOR: + blitOR(target, x, y, _maskData); + break; + default: + break; + } + } else if (_container->getItemByteSize(_id)) { + switch (mode) { + case MacVenture::kBlitBIC: + target->fillRect(Common::Rect(x, y, x + _bitWidth, y + _bitHeight * 2), kColorWhite); + break; + case MacVenture::kBlitOR: + target->fillRect(Common::Rect(x, y, x + _bitWidth, y + _bitHeight * 2), kColorBlack); + break; + default: + break; + } } - } - if (_container->getItemByteSize(_id) && mode > 0) { - blitXOR(target, x, y, _imgData); - } + if (_container->getItemByteSize(_id) && mode > 0) { + blitXOR(target, x, y, _imgData); + } + } } -bool ImageAsset::isPointInside(Common::Point myPos, Common::Point click) { - Common::Rect bounds(myPos.x, myPos.y, myPos.x + _bitWidth, myPos.y + _bitHeight); - return bounds.contains(click); +bool ImageAsset::isPointInside(Common::Point point) { + if (point.x >= _bitWidth || point.y >= _bitHeight) return false; + if (_maskData.empty()) return false; + // We see if the point lands on the mask. + uint pix = _maskData[(point.y * _rowBytes) + (point.x >> 3)] & (1 << (7 - (point.x & 7))); + return pix != 0; } void ImageAsset::blitDirect(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array<byte>& data) { + /* if (_bitWidth == 0 || _bitHeight == 0) return; uint w = _bitWidth; uint h = _bitHeight; @@ -355,19 +362,21 @@ void ImageAsset::blitDirect(Graphics::ManagedSurface * target, uint32 ox, uint32 if (w + ox >= target->w) w = target->w - ox; if (h + oy >= target->h) h = target->h - oy; if (w == 0 || h == 0) return; + */ - for (uint y = 0;y < _bitHeight; y++) { + for (uint y = 0; y < _bitHeight; y++) { uint bmpofs = y * _rowBytes; byte pix = 0; for (uint x = 0; x < _bitWidth; x++) { pix = data[bmpofs + (x >> 3)] & (1 << (7 - (x & 7))); pix = pix ? kColorBlack : kColorWhite; - if (pix) *((byte *)target->getBasePtr(ox + x, oy + y)) = pix; + *((byte *)target->getBasePtr(ox + x, oy + y)) = pix; } } } void ImageAsset::blitBIC(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array<byte> &data) { + /* if (_bitWidth == 0 || _bitHeight == 0) return; uint w = _bitWidth; uint h = _bitHeight; @@ -378,19 +387,19 @@ void ImageAsset::blitBIC(Graphics::ManagedSurface * target, uint32 ox, uint32 oy if (w + ox >= target->w) w = target->w - ox; if (h + oy >= target->h) h = target->h - oy; if (w == 0 || h == 0) return; - - for (uint y = 0;y < h; y++) { + */ + for (uint y = 0; y < _bitHeight; y++) { uint bmpofs = y * _rowBytes; byte pix = 0; - for (uint x = 0; x < w; x++) { - pix = data[bmpofs + (x >> 3)] & (1 << (7 - (x & 7))); - + for (uint x = 0; x < _bitWidth; x++) { + pix = data[bmpofs + (x >> 3)] & (1 << (7 - (x & 7))); if (pix) *((byte *)target->getBasePtr(ox + x, oy + y)) = kColorWhite; } } } void ImageAsset::blitOR(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array<byte> &data) { + /* if (_bitWidth == 0 || _bitHeight == 0) return; uint w = _bitWidth; uint h = _bitHeight; @@ -401,8 +410,8 @@ void ImageAsset::blitOR(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, if (w + ox >= target->w) w = target->w - ox; if (h + oy >= target->h) h = target->h - oy; if (w == 0 || h == 0) return; - - for (uint y = 0;y < _bitHeight; y++) { + */ + for (uint y = 0; y < _bitHeight; y++) { uint bmpofs = y * _rowBytes; byte pix = 0; for (uint x = 0; x < _bitWidth; x++) { @@ -414,6 +423,7 @@ void ImageAsset::blitOR(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, } void ImageAsset::blitXOR(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array<byte> &data) { + /* if (_bitWidth == 0 || _bitHeight == 0) return; uint w = _bitWidth; uint h = _bitHeight; @@ -424,7 +434,7 @@ void ImageAsset::blitXOR(Graphics::ManagedSurface * target, uint32 ox, uint32 oy if (w + ox >= target->w) w = target->w - ox; if (h + oy >= target->h) h = target->h - oy; if (w == 0 || h == 0) return; - + */ for (uint y = 0;y < _bitHeight; y++) { uint bmpofs = y * _rowBytes; byte pix = 0; diff --git a/engines/macventure/image.h b/engines/macventure/image.h index 0a3ea50ef1..adce9a54a2 100644 --- a/engines/macventure/image.h +++ b/engines/macventure/image.h @@ -59,7 +59,7 @@ public: void blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y, BlitMode mode); - bool isPointInside(Common::Point myPos, Common::Point click); + bool isPointInside(Common::Point point); private: void decodePPIC(ObjID id, Common::Array<byte> &data); diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp index 8d367c7174..572677a7f6 100644 --- a/engines/macventure/macventure.cpp +++ b/engines/macventure/macventure.cpp @@ -100,45 +100,55 @@ Common::Error MacVentureEngine::run() { _cmdReady = false; _haltedAtEnd = false; _haltedInSelection = false; + _clickToContinue = true; + _gameState = kGameStateInit; + _destObject = 0; + _prepared = true; //if !savegame _cmdReady = true; _selectedControl = kStartOrResume; ObjID playerParent = _world->getObjAttr(1, kAttrParentObject); _currentSelection.push_back(playerParent);// Push the parent of the player - _world->setObjAttr(playerParent, 6, 1); + _world->setObjAttr(playerParent, kAttrContainerOpen, 1); - _prepared = true; - while (!(_gameState == kGameStateQuitting)) { + _gui->addChild(kSelfWindow, 1); + _gui->updateWindow(kSelfWindow, false); + + while (_gameState != kGameStateQuitting) { processEvents(); - if (_prepared) { - _prepared = false; - - if (!_halted) - updateState(); - - if (_cmdReady || _halted) { - _halted = false; - if (runScriptEngine()) { - _halted = true; - _paused = true; - } else { - _paused = false; - if (!updateState()) { - updateControls(); + if (_gameState != kGameStateQuitting) { + + if (_prepared) { + _prepared = false; + + if (!_halted) + updateState(); + + if (_cmdReady || _halted) { + _halted = false; + if (runScriptEngine()) { + _halted = true; + _paused = true; } + else { + _paused = false; + if (!updateState()) { + updateControls(); + } + } + } + + if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) { + endGame(); } } + _gui->draw(); - if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) { - endGame(); - } + g_system->updateScreen(); + g_system->delayMillis(50); } - _gui->draw(); - - g_system->updateScreen(); - g_system->delayMillis(50); } return Common::kNoError; @@ -161,6 +171,11 @@ void MacVentureEngine::selectControl(ControlReference id) { } void MacVentureEngine::activateCommand(ControlReference id) { + if (id == kControlClickToContinue) { + _clickToContinue = false; + _paused = true; + return; + } ControlAction action = referenceToAction(id); if (action != _activeControl) { if (_activeControl) @@ -168,6 +183,7 @@ void MacVentureEngine::activateCommand(ControlReference id) { _activeControl = action; } debug(4, "Activating Command %x... Command %x is active", action, _activeControl); + refreshReady(); } void MacVentureEngine::refreshReady() { @@ -201,9 +217,16 @@ void MacVentureEngine::loseGame() { _gameState = kGameStateLosing; } -void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID) { +void MacVentureEngine::clickToContinue() { + _clickToContinue = true; +} + +void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID, ObjID target) { QueuedObject obj; obj.id = type; + + if (type == kUpdateWindow) { obj.target = target; } + if (type != kHightlightExits) { obj.object = objID; obj.parent = _world->getObjAttr(objID, kAttrParentObject); @@ -257,7 +280,12 @@ void MacVentureEngine::selectObject(ObjID objID) { else i++; } - if (!found) _currentSelection.push_back(objID); + if (!found) { + _currentSelection.push_back(objID); + debug("Object %d selected", objID); + } else { + debug("Object %d already selected", objID); + } found = false; i = 0; @@ -266,7 +294,15 @@ void MacVentureEngine::selectObject(ObjID objID) { else i++; } - if (!found) _selectedObjs.push_back(objID); + if (!found) _selectedObjs.push_back(objID); +} + +void MacVentureEngine::updateDelta(Common::Point newPos) { + Common::Point newDelta = newPos - _deltaPoint; + debug(4, "Update delta: Old(%d, %d), New(%d, %d)", + _deltaPoint.x, _deltaPoint.y, + newDelta.x, newDelta.y); + _deltaPoint = newDelta; } void MacVentureEngine::focusObjWin(ObjID objID) { @@ -357,11 +393,11 @@ bool MacVentureEngine::updateState() { } void MacVentureEngine::revert() { - warning("revert: unimplemented"); + _gui->invertWindowColors(kMainGameWindow); + preparedToRun(); } void MacVentureEngine::runObjQueue() { - warning("runObjQueue: not fully implemented"); while (!_objQueue.empty()) { uint32 biggest = 0; uint32 index = 0; @@ -389,7 +425,7 @@ void MacVentureEngine::runObjQueue() { checkObject(obj); break; case 0x8: - reflectSwap(obj.object); + reflectSwap(obj.object, obj.target); break; case 0xc: _world->setObjAttr(_gui->getWindowData(kMainGameWindow).refcon, kAttrContainerOpen, 0); @@ -408,6 +444,7 @@ void MacVentureEngine::runObjQueue() { void MacVentureEngine::updateControls() { if (_activeControl) _activeControl = kNoCommand; + _gui->clearControls(); toggleExits(); resetVars(); } @@ -434,7 +471,7 @@ void MacVentureEngine::openObject(ObjID objID) { debug("openObject: %d", objID); if (getObjWindow(objID)) return; if (objID == _world->getObjAttr(1, kAttrParentObject)) { - _gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true)); // FIXME: Find better name + _gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true)); _gui->updateWindow(kMainGameWindow, _world->getObjAttr(objID, kAttrContainerOpen)); //_gui->drawExits(); _gui->setWindowTitle(kMainGameWindow, _world->getText(objID)); @@ -522,12 +559,30 @@ void MacVentureEngine::checkObject(QueuedObject old) { } } -void MacVentureEngine::reflectSwap(ObjID objID) { - warning("reflectSwap: unimplemented"); +void MacVentureEngine::reflectSwap(ObjID fromID, ObjID toID) { + warning("reflectSwap: untested"); + WindowReference from = getObjWindow(fromID); + WindowReference to = getObjWindow(toID); + WindowReference tmp = to; + if (!to) { + tmp = from; + } + if (tmp) { + Common::String newTitle = _world->getText(toID); + _gui->setWindowTitle(tmp, newTitle); + _gui->updateWindowInfo(tmp, toID, _world->getChildren(toID, true)); + updateWindow(tmp); + } } void MacVentureEngine::toggleExits() { warning("toggleExits: unimplemented"); + while (!_selectedObjs.empty()) { + ObjID obj = _selectedObjs.front(); + _selectedObjs.remove_at(0); + // Todo: highlight exit + updateWindow(findParentWindow(obj)); + } } void MacVentureEngine::zoomObject(ObjID objID) { @@ -565,6 +620,10 @@ bool MacVentureEngine::isPaused() { return _paused; } +bool MacVentureEngine::needsClickToContinue() { + return _clickToContinue; +} + Common::String MacVentureEngine::getCommandsPausedString() const { return Common::String("Click to continue"); } @@ -607,7 +666,10 @@ bool MacVentureEngine::isObjClickable(ObjID objID) { } bool MacVentureEngine::isObjSelected(ObjID objID) { - warning("Unimplemented: isObjSelected"); + Common::Array<ObjID>::const_iterator it; + for (it = _currentSelection.begin(); it != _currentSelection.end(); it++) { + if (*it == objID) return true; + } return false; } diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h index c45069c06c..c19021d4c5 100644 --- a/engines/macventure/macventure.h +++ b/engines/macventure/macventure.h @@ -135,6 +135,7 @@ struct QueuedObject { bool hidden; bool offscreen; bool invisible; + ObjID target; // For swapping }; enum TextQueueID { @@ -167,22 +168,25 @@ public: void gameChanged(); void winGame(); void loseGame(); + void clickToContinue(); bool updateState(); void revert(); - void enqueueObject(ObjectQueueID type, ObjID objID); + void enqueueObject(ObjectQueueID type, ObjID objID, ObjID target = 0); void enqueueText(TextQueueID type, ObjID target, ObjID source, ObjID text); void runObjQueue(); bool printTexts(); void selectObject(ObjID objID); + void updateDelta(Common::Point newPos); void focusObjWin(ObjID objID); void updateWindow(WindowReference winID); // Data retrieval bool isPaused(); + bool needsClickToContinue(); Common::String getCommandsPausedString() const; const GlobalSettings& getGlobalSettings() const; Common::String getFilePath(FilePathID id) const; @@ -218,7 +222,7 @@ private: void openObject(ObjID objID); void closeObject(ObjID objID); void checkObject(QueuedObject objID); - void reflectSwap(ObjID objID); + void reflectSwap(ObjID fromID, ObjID toID); void toggleExits(); void zoomObject(ObjID objID); @@ -255,6 +259,7 @@ private: // Attributes bool _paused, _halted, _cmdReady, _prepared; bool _haltedAtEnd, _haltedInSelection; bool _gameChanged; + bool _clickToContinue; Common::Array<QueuedObject> _objQueue; Common::Array<QueuedObject> _inQueue; diff --git a/engines/macventure/script.cpp b/engines/macventure/script.cpp index f7550360c8..bf9339fe76 100644 --- a/engines/macventure/script.cpp +++ b/engines/macventure/script.cpp @@ -41,9 +41,6 @@ ScriptEngine::~ScriptEngine() { } bool ScriptEngine::runControl(ControlAction action, ObjID source, ObjID destination, Common::Point delta) { - //debug(7, "SCRIPT: Running control %d from obj %d into obj %d, at delta (%d, %d)", - // action, source, destination, delta.x, delta.y); - EngineFrame frame; frame.action = action; frame.src = source; @@ -108,24 +105,37 @@ bool ScriptEngine::execFrame(bool execAll) { } doFamily = true; } - } - - //Handle saves - /* + } - uint highest; - uint high; + // Halted in saves if (frame->haltedInSaves) { - frame->haltedInSaves = false; - } - - - do { - highest = 0; - for (uint i = 0; i < frame->haltedInSaves.size) + frame->haltedInSaves = false; + if (resumeFunc(frame)) { + frame->haltedInSaves = true; + return true; + } } - */ + uint highest = 0; + uint localHigh = 0; + do { // Saved function calls + highest = 0; + for (uint i = 0; i <frame->saves.size(); i++) + { + if (highest < frame->saves[i].rank) { + highest = frame->saves[i].rank; + localHigh = i; + } + } + if (highest) { + frame->saves[localHigh].rank = 0; + if (loadScript(frame, frame->saves[localHigh].func)) { + frame->haltedInSaves = true; + return true; + } + } + } while (highest); + _frames.remove_at(0); return false; } @@ -907,7 +917,7 @@ void ScriptEngine::opbdFOOB(EngineState * state, EngineFrame * frame) { void ScriptEngine::opbeSWOB(EngineState * state, EngineFrame * frame) { ObjID from = state->pop(); ObjID to = state->pop(); - _engine->enqueueObject(kUpdateWindow, to); + _engine->enqueueObject(kUpdateWindow, from, to); _world->setObjAttr(to, kAttrContainerOpen, _world->getObjAttr(from, 6)); _world->setObjAttr(from, kAttrContainerOpen, 0); Common::Array<ObjID> children = _world->getChildren(from, true); @@ -1057,7 +1067,7 @@ void ScriptEngine::opd9SLEEP(EngineState * state, EngineFrame * frame) { void ScriptEngine::opdaCLICK(EngineState * state, EngineFrame * frame) { _engine->updateState(); - //_engine->clickToContinue(); + _engine->clickToContinue(); } void ScriptEngine::opdbROBQ(EngineState * state, EngineFrame * frame) { @@ -1083,13 +1093,11 @@ void ScriptEngine::opdfFMAI(EngineState * state, EngineFrame * frame) { } void ScriptEngine::ope0CHGR(EngineState * state, EngineFrame * frame) { - word txt = state->pop(); - op00NOOP(0xe0); + state->pop(); } void ScriptEngine::ope1CHSO(EngineState * state, EngineFrame * frame) { - word txt = state->pop(); - op00NOOP(0xe1); + state->pop(); } void ScriptEngine::ope2MDIV(EngineState * state, EngineFrame * frame) { @@ -1108,7 +1116,6 @@ void ScriptEngine::ope3UPOB(EngineState * state, EngineFrame * frame) { void ScriptEngine::ope4PLEV(EngineState * state, EngineFrame * frame) { state->push(0); - op00NOOP(0xe4); } void ScriptEngine::ope5WEV(EngineState * state, EngineFrame * frame) { |