From 499ebc0b54c79e89f4ee38628cea1f64cdf40bf2 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 24 Jun 2016 21:00:06 +0200 Subject: MACVENTURE: Script engine fixes --- engines/macventure/gui.cpp | 36 ++++++-- engines/macventure/gui.h | 8 +- engines/macventure/image.cpp | 8 ++ engines/macventure/image.h | 3 + engines/macventure/macventure.cpp | 183 +++++++++++++++++++++++++++++++------- engines/macventure/macventure.h | 14 ++- engines/macventure/script.cpp | 35 +++++--- engines/macventure/script.h | 13 ++- 8 files changed, 239 insertions(+), 61 deletions(-) (limited to 'engines') diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index d4fd337557..d43be9b269 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -248,6 +248,7 @@ void Gui::initWindows() { _mainGameWindow->setCallback(mainGameWindowCallback, this); loadBorder(_mainGameWindow, "border_no_scroll_inac.bmp", false); loadBorder(_mainGameWindow, "border_no_scroll_act.bmp", true); + findWindowData(kMainGameWindow).objRef = 3; // In-game Output Console _outConsoleWindow = _wm.addWindow(false, true, true); @@ -264,6 +265,7 @@ void Gui::initWindows() { _selfWindow->setCallback(selfWindowCallback, this); loadBorder(_selfWindow, "border_no_scroll_inac.bmp", false); loadBorder(_selfWindow, "border_no_scroll_inac.bmp", true); + findWindowData(kMainGameWindow).objRef = 0; // Exits Window _exitsWindow = _wm.addWindow(false, true, true); @@ -273,9 +275,10 @@ void Gui::initWindows() { loadBorder(_exitsWindow, "border_no_scroll_inac.bmp", false); loadBorder(_exitsWindow, "border_no_scroll_act.bmp", true); + } -WindowReference Gui::createInventoryWindow() { +WindowReference Gui::createInventoryWindow(ObjID objRef) { Graphics::MacWindow *newWindow = _wm.addWindow(true, true, true); WindowData newData; GlobalSettings settings = _engine->getGlobalSettings(); @@ -295,6 +298,7 @@ WindowReference Gui::createInventoryWindow() { newData.type = kZoomDoc; newData.hasCloseBox = true; newData.visible = true; + newData.objRef = objRef; _windowData->push_back(newData); newWindow->setDimensions(newData.bounds); @@ -528,7 +532,6 @@ void Gui::drawCommandsWindow() { } void Gui::drawMainGameWindow() { - Graphics::ManagedSurface *srf = _mainGameWindow->getSurface(); const WindowData &data = getWindowData(kMainGameWindow); BorderBounds border = borderBounds(data.type); @@ -612,12 +615,18 @@ void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * border.leftOffset + pos.x, border.topOffset + pos.y, mode); + + if (_engine->isObjSelected(child)) + _assets[child]->blitInto( + surface, + border.leftOffset + pos.x, + border.topOffset + pos.y, + kBlitOR); } } findWindow(data.refcon)->setDirty(true); - } void Gui::drawWindowTitle(WindowReference target, Graphics::ManagedSurface * surface) { @@ -782,6 +791,9 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) { for (; it != _controlData->end(); ++it) { it->unselect(); } + } + if (winID == kMainGameWindow) { + drawMainGameWindow(); } else { Graphics::MacWindow *winRef = findWindow(winID); winRef->getSurface()->fillRect(data.bounds, kColorGray); @@ -802,9 +814,6 @@ 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"); } @@ -832,6 +841,16 @@ bool Gui::tryCloseWindow(WindowReference winID) { return true; } +uint Gui::getObjWidth(ObjID obj) { + if (!_assets.contains(obj)) return 0; + return _assets[obj]->getWidth(); +} + +uint Gui::getObjHeight(ObjID obj) { + if (!_assets.contains(obj)) return 0; + return _assets[obj]->getHeight(); +} + bool Gui::processEvent(Common::Event &event) { bool processed = false; if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP) { @@ -884,7 +903,6 @@ bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event & e if (click == kBorderInner && event.type == Common::EVENT_LBUTTONUP) { WindowData &data = findWindowData(kMainGameWindow); ObjID child; - BlitMode mode; Common::Point pos; for (Common::Array::const_iterator it = data.children.begin(); it != data.children.end(); it++) { child = (*it).obj; @@ -894,7 +912,7 @@ bool MacVenture::Gui::processMainGameEvents(WindowClick click, Common::Event & e pos = event.mouse - pos; if (_assets.contains(child) && _assets[child]->isPointInside(pos)) { // select the first object clicked - _engine->selectObject(child); + _engine->handleObjectSelect(child, kMainGameWindow, event); } } } @@ -912,7 +930,7 @@ bool MacVenture::Gui::processSelfEvents(WindowClick click, Common::Event & event return true; if (event.type == Common::EVENT_LBUTTONUP) { - _engine->selectObject(1); + _engine->handleObjectSelect(1, kSelfWindow, event); } return true; } diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index b7d5d52b83..1da1b103dd 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -99,6 +99,7 @@ struct DrawableObject { struct WindowData { Common::Rect bounds; MVWindowType type; + ObjID objRef; uint16 visible; uint16 hasCloseBox; WindowReference refcon; @@ -160,9 +161,12 @@ public: void updateWindow(WindowReference winID, bool containerOpen); void invertWindowColors(WindowReference winID); - WindowReference createInventoryWindow(); + WindowReference createInventoryWindow(ObjID objRef); bool tryCloseWindow(WindowReference winID); + uint getObjWidth(ObjID obj); + uint getObjHeight(ObjID obj); + // Event processors bool processCommandEvents(WindowClick click, Common::Event &event); bool processMainGameEvents(WindowClick click, Common::Event &event); @@ -172,6 +176,8 @@ public: bool processDiplomaEvents(WindowClick click, Common::Event &event); bool processInventoryEvents(WindowClick click, Common::Event &event); + //bool processClickObject(ObjID obj, WindowReference win, Common::Event event, bool canDrag); + const WindowData& getWindowData(WindowReference reference); const Graphics::Font& getCurrentFont(); diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index 54d19c9fd2..323b8a1089 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -350,6 +350,14 @@ bool ImageAsset::isPointInside(Common::Point point) { return pix != 0; } +uint ImageAsset::getWidth() { + return _bitWidth; +} + +uint ImageAsset::getHeight() { + return _bitWidth; +} + void ImageAsset::blitDirect(Graphics::ManagedSurface * target, uint32 ox, uint32 oy, const Common::Array& data) { /* if (_bitWidth == 0 || _bitHeight == 0) return; diff --git a/engines/macventure/image.h b/engines/macventure/image.h index adce9a54a2..52f0dfa591 100644 --- a/engines/macventure/image.h +++ b/engines/macventure/image.h @@ -61,6 +61,9 @@ public: bool isPointInside(Common::Point point); + uint getWidth(); + uint getHeight(); + private: void decodePPIC(ObjID id, Common::Array &data); diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp index 572677a7f6..21496cd8b2 100644 --- a/engines/macventure/macventure.cpp +++ b/engines/macventure/macventure.cpp @@ -41,7 +41,7 @@ MacVentureEngine::MacVentureEngine(OSystem *syst, const ADGameDescription *gameD _gameDescription = gameDesc; _rnd = new Common::RandomSource("macventure"); - _debugger= NULL; + _debugger = NULL; _gui = NULL; debug("MacVenture::MacVentureEngine()"); @@ -96,7 +96,7 @@ Common::Error MacVentureEngine::run() { _scriptEngine = new ScriptEngine(this, _world); _paused = false; - _halted = true; + _halted = false; _cmdReady = false; _haltedAtEnd = false; _haltedInSelection = false; @@ -114,7 +114,7 @@ Common::Error MacVentureEngine::run() { _gui->addChild(kSelfWindow, 1); _gui->updateWindow(kSelfWindow, false); - + while (_gameState != kGameStateQuitting) { processEvents(); @@ -227,7 +227,7 @@ void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID, ObjID targ if (type == kUpdateWindow) { obj.target = target; } - if (type != kHightlightExits) { + if (type != kHightlightExits) { obj.object = objID; obj.parent = _world->getObjAttr(objID, kAttrParentObject); obj.x = _world->getObjAttr(objID, kAttrPosX); @@ -267,34 +267,62 @@ bool MacVentureEngine::printTexts() { case kTextPlain: debug("Print Plain Text: %s", _world->getText(text.asset).c_str()); gameChanged(); - break; + break; } } + return false; } -void MacVentureEngine::selectObject(ObjID objID) { - bool found = false; - uint i = 0; - while (i < _currentSelection.size() && !found) { - if (_currentSelection[i] == objID) found = true; - else i++; - } - - if (!found) { - _currentSelection.push_back(objID); - debug("Object %d selected", objID); - } else { - debug("Object %d already selected", objID); +void MacVentureEngine::handleObjectSelect(ObjID objID, WindowReference win, Common::Event event) { + if (win == kExitsWindow) { + win = kMainGameWindow; } - found = false; - i = 0; - while (i < _selectedObjs.size() && !found) { - if (_selectedObjs[i] == objID) found = true; - else i++; - } + bool canDrag = (objID && !_world->getObjAttr(objID, kAttrInvisible)); + + const WindowData &windata = _gui->getWindowData(win); - if (!found) _selectedObjs.push_back(objID); + if (event.kbd.flags & Common::KBD_SHIFT) { + // Do shift ;) + } + else { + if (_selectedControl && _currentSelection.size() > 0 && getInvolvedObjects() > 1) { + if (objID == 0) + selectPrimaryObject(windata.objRef); + else + selectPrimaryObject(objID); + preparedToRun(); + } + else { + if (objID == 0) { + unselectAll(); + //if (windata.type == kAnimateBack) { + //doLasso(win, event, canDrag); + //} + //else { + objID = win; + //} + } + if (objID > 0) { + int i = findObjectInArray(objID, _currentSelection); + + /*if (event.type == Common::EVENT isDoubleClick(event)) { // no double click for now + if (!found) + unSelectAll(); + selectObj(obj); + doubleClickObject(obj, win, event, canDrag); + } else {*/ + if (i >= 0) + unselectAll(); + selectObject(objID); + if (getInvolvedObjects() == 1) + _cmdReady = true; + preparedToRun(); + //singleClickObject(objID, win, event, canDrag); + //} + } + } + } } void MacVentureEngine::updateDelta(Common::Point newPos) { @@ -373,7 +401,11 @@ bool MacVenture::MacVentureEngine::runScriptEngine() { if (_selectedControl == 1) _gameChanged = false; +<<<<<<< HEAD else if (_gameState == kGameStateInit || _gameState == kGameStatePlaying){ +======= + else if (_gameState == kGameStateInit || _gameState == kGameStatePlaying) { +>>>>>>> 088fc4d... MACVENTURE: Script engine fixes if (_scriptEngine->runControl(kTick, _selectedControl, _destObject, _deltaPoint)) { _haltedAtEnd = true; return true; @@ -445,7 +477,7 @@ void MacVentureEngine::updateControls() { if (_activeControl) _activeControl = kNoCommand; _gui->clearControls(); - toggleExits(); + toggleExits(); resetVars(); } @@ -458,6 +490,70 @@ void MacVentureEngine::resetVars() { _cmdReady = false; } +void MacVentureEngine::unselectAll() { + while (!_currentSelection.empty()) { + unselectObject(_currentSelection.front()); + //_currentSelection.remove_at(0); + } +} + +void MacVentureEngine::selectObject(ObjID objID) { + if (!_currentSelection.empty()) { + if (findParentWindow(objID) != findParentWindow(_currentSelection[0])) + unselectAll(); + } + if (findObjectInArray(objID, _currentSelection) == -1) + _currentSelection.push_back(objID); + if (findObjectInArray(objID, _selectedObjs) == -1) { + _selectedObjs.push_back(objID); + highlightExit(objID); + } +} + +void MacVentureEngine::unselectObject(ObjID objID) { + int idxCur = findObjectInArray(objID, _currentSelection); + int idxSel = findObjectInArray(objID, _selectedObjs); + if (idxCur != -1) _currentSelection.remove_at(idxCur); + if (idxSel != -1) { + _selectedObjs.remove_at(idxSel); + highlightExit(objID); + } +} + +int MacVentureEngine::findObjectInArray(ObjID objID, const Common::Array &list) { + // Find the object in the current selection + bool found = false; + uint i = 0; + while (i < list.size() && !found) { + if (list[i] == objID) found = true; + else i++; + } + // HACK, should use iterator + return found ? i : -1; +} + +void MacVentureEngine::highlightExit(ObjID objID) { + warning("highlightExit: unimplemented"); +} + +void MacVentureEngine::selectPrimaryObject(ObjID objID) { + if (objID == _destObject) return; + int idx; + if (_destObject > 0 && + (idx = findObjectInArray(_destObject, _selectedObjs)) != -1 && + findObjectInArray(_destObject, _currentSelection) == -1) + { + _selectedObjs.remove_at(idx); + highlightExit(_destObject); + } + _destObject = objID; + if (findObjectInArray(_destObject, _selectedObjs) == -1) { + _selectedObjs.push_back(_destObject); + highlightExit(_destObject); + } + _cmdReady = true; +} + void MacVentureEngine::focusObjectWindow(ObjID objID) { if (objID) { WindowReference win = getObjWindow(objID); @@ -479,7 +575,7 @@ void MacVentureEngine::openObject(ObjID objID) { Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY)); //getParentWin(obj).localToGlobal(p); //globalToDesktop(p); - WindowReference invID = _gui->createInventoryWindow(); + WindowReference invID = _gui->createInventoryWindow(objID); _gui->setWindowTitle(invID, _world->getText(objID)); _gui->updateWindowInfo(invID, objID, _world->getChildren(objID, true)); _gui->updateWindow(invID, _world->getObjAttr(objID, kAttrContainerOpen)); @@ -576,11 +672,10 @@ void MacVentureEngine::reflectSwap(ObjID fromID, ObjID toID) { } void MacVentureEngine::toggleExits() { - warning("toggleExits: unimplemented"); while (!_selectedObjs.empty()) { ObjID obj = _selectedObjs.front(); _selectedObjs.remove_at(0); - // Todo: highlight exit + highlightExit(obj); updateWindow(findParentWindow(obj)); } } @@ -666,11 +761,33 @@ bool MacVentureEngine::isObjClickable(ObjID objID) { } bool MacVentureEngine::isObjSelected(ObjID objID) { - Common::Array::const_iterator it; - for (it = _currentSelection.begin(); it != _currentSelection.end(); it++) { - if (*it == objID) return true; + int idx = findObjectInArray(objID, _currentSelection); + return idx != -1; +} + +Common::Rect MacVentureEngine::getObjBounds(ObjID objID) { + Common::Point pos = getObjPosition(objID); + uint w = _gui->getObjWidth(objID); // This shouldn't go here + uint h = _gui->getObjHeight(objID); + return Common::Rect(pos.x, pos.y, pos.x + w, pos.y + h); +} + +uint MacVentureEngine::getOverlapPercent(ObjID one, ObjID other) { + //not the same parent? 0 overlap + if (_world->getObjAttr(one, kAttrParentObject) != + _world->getObjAttr(other, kAttrParentObject)) + return 0; + + Common::Rect oneBounds = getObjBounds(one); + Common::Rect otherBounds = getObjBounds(other); + if (otherBounds.intersects(oneBounds) || + oneBounds.intersects(otherBounds)) + { + uint areaOne = oneBounds.width() * oneBounds.height(); + uint areaOther = otherBounds.width() * otherBounds.height(); + return (areaOther * 100 / areaOne) | 0; } - return false; + return 0; } WindowReference MacVentureEngine::getObjWindow(ObjID objID) { diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h index c19021d4c5..4671c2a881 100644 --- a/engines/macventure/macventure.h +++ b/engines/macventure/macventure.h @@ -179,7 +179,7 @@ public: void runObjQueue(); bool printTexts(); - void selectObject(ObjID objID); + void handleObjectSelect(ObjID objID, WindowReference win, Common::Event event); void updateDelta(Common::Point newPos); void focusObjWin(ObjID objID); void updateWindow(WindowReference winID); @@ -201,6 +201,10 @@ public: bool isObjClickable(ObjID objID); bool isObjSelected(ObjID objID); + // Encapsulation HACK + Common::Rect getObjBounds(ObjID objID); + uint getOverlapPercent(ObjID one, ObjID other); + WindowReference getObjWindow(ObjID objID); WindowReference findObjWindow(ObjID objID); WindowReference findParentWindow(ObjID objID); @@ -217,6 +221,14 @@ private: void updateControls(); void resetVars(); + void unselectAll(); + void selectObject(ObjID objID); + void unselectObject(ObjID objID); + int findObjectInArray(ObjID objID, const Common::Array &list); + void highlightExit(ObjID objID); + void selectPrimaryObject(ObjID objID); + + // Object queue methods void focusObjectWindow(ObjID objID); void openObject(ObjID objID); diff --git a/engines/macventure/script.cpp b/engines/macventure/script.cpp index bf9339fe76..4c00054bb6 100644 --- a/engines/macventure/script.cpp +++ b/engines/macventure/script.cpp @@ -136,32 +136,37 @@ bool ScriptEngine::execFrame(bool execAll) { } } while (highest); - _frames.remove_at(0); + _frames.pop_front(); return false; } bool ScriptEngine::loadScript(EngineFrame * frame, uint32 scriptID) { - frame->scripts.push_back(ScriptAsset(scriptID, _scripts)); + if (_scripts->getItemByteSize(scriptID) > 0) { + debug(3, "SCRIPT: Loading function %d", scriptID); + // Insert the new script at the front + frame->scripts.push_front(ScriptAsset(scriptID, _scripts)); + return runFunc(frame); + } return false; } bool ScriptEngine::resumeFunc(EngineFrame * frame) { bool fail = runFunc(frame); if (fail) return fail; - frame->scripts.remove_at(0); + frame->scripts.pop_front(); if (frame->scripts.size()) return resumeFunc(frame); return false; } bool ScriptEngine::runFunc(EngineFrame *frame) { - debug(3, "SCRIPT: I'm running the function"); ScriptAsset &script = frame->scripts.front(); + debug(3, "SCRIPT: Executing function %d", script.getId()); EngineState *state = &frame->state; byte op; while (script.hasNext()) { op = script.fetch(); - debug(3, "SCRIPT: I'm running operation %x", op); + debug(3, "SCRIPT: I'm running operation %d", op); if (!(op & 0x80)) { state->push(op); } else { @@ -857,7 +862,7 @@ void ScriptEngine::opb5BNEB(EngineState * state, EngineFrame * frame, ScriptAsse void ScriptEngine::opb6CLAT(EngineState * state, EngineFrame * frame) { word rank = state->pop(); word func = state->pop(); - frame->saves.push_back(FunCall(rank, func)); + frame->saves.push_back(FunCall(func, rank)); } void ScriptEngine::opb7CCA(EngineState * state, EngineFrame * frame) { @@ -904,9 +909,11 @@ void ScriptEngine::opbbFORK(EngineState * state, EngineFrame * frame) { void ScriptEngine::opbcCALL(EngineState * state, EngineFrame * frame, ScriptAsset &script) { word id = state->pop(); ScriptAsset newfun = ScriptAsset(id, _scripts); - frame->scripts.remove_at(0); - frame->scripts.insert_at(0, newfun); + ScriptAsset current = script; + loadScript(frame, id); + frame->scripts.pop_front(); script = frame->scripts.front(); + debug(3, "SCRIPT: Return from fuction %d", id); } void ScriptEngine::opbdFOOB(EngineState * state, EngineFrame * frame) { @@ -1019,17 +1026,15 @@ void ScriptEngine::opd0P1(EngineState * state, EngineFrame * frame) { void ScriptEngine::opd1GOBD(EngineState * state, EngineFrame * frame) { word obj = state->pop(); - Common::Rect bounds(0, 0, 1, 1); //= _world->getObjBounds(obj); + Common::Rect bounds = _engine->getObjBounds(obj); state->push(bounds.width()); state->push(bounds.height()); - op00NOOP(0xd1); } void ScriptEngine::opd2GOVP(EngineState * state, EngineFrame * frame) { word b = state->pop(); word a = state->pop(); - state->push(0);//_world->getOverlapPercent(b, a)); - op00NOOP(0xd2); + state->push(_engine->getOverlapPercent(b, a)); } void ScriptEngine::opd3CAPC(EngineState * state, EngineFrame * frame) { @@ -1138,11 +1143,11 @@ void ScriptEngine::op00NOOP(byte op) { - ScriptAsset::ScriptAsset(ObjID id, Container * container) { _id = id; _container = container; _ip = 0x0; + loadInstructions(); } void ScriptAsset::reset() { @@ -1163,6 +1168,10 @@ void ScriptAsset::branch(word amount) { _ip += amount; } +ObjID ScriptAsset::getId() { + return _id; +} + void ScriptAsset::loadInstructions() { uint32 amount = _container->getItemByteSize(_id); Common::SeekableReadStream *res = _container->getItem(_id); diff --git a/engines/macventure/script.h b/engines/macventure/script.h index 178e054e05..1a143cffd0 100644 --- a/engines/macventure/script.h +++ b/engines/macventure/script.h @@ -63,6 +63,8 @@ public: bool hasNext(); void branch(word amount); + ObjID getId(); + private: void loadInstructions(); @@ -82,12 +84,12 @@ public: } void push(word data) { + sp--; stack[sp] = unneg16(data); - sp--; } word pop() { - byte v = stack[sp]; + word v = stack[sp]; sp++; return v; } @@ -102,6 +104,9 @@ public: void clear() { sp = 0x80; + for (int i = 0; i < sp; i++) { + stack[i] = 0; + } } word size() { @@ -139,7 +144,7 @@ struct EngineFrame { int x; int y; EngineState state; - Common::Array scripts; + Common::List scripts; Common::Array saves; uint32 familyIdx; @@ -288,7 +293,7 @@ private: private: MacVentureEngine *_engine; World *_world; - Common::Array _frames; + Common::List _frames; Container *_scripts; }; -- cgit v1.2.3