diff --git a/sword1/logic.cpp b/sword1/logic.cpp index 2ec07775898..9b89cbf92d8 100644 --- a/sword1/logic.cpp +++ b/sword1/logic.cpp @@ -1049,7 +1049,6 @@ int SwordLogic::fnISpeak(BsObject *cpt, int32 id, int32 cdt, int32 textNo, int32 cdt = GEOSTDLCDT; // workaround for missing animation when examining spr = GEOSTDL; // the conductor on the train roof } - _mouse->flushEvents(); // prevent player from accidently clicking text away within first three frames cpt->o_logic = LOGIC_speech; // first setup the talk animation @@ -1348,7 +1347,6 @@ int SwordLogic::fnWalk(BsObject *cpt, int32 id, int32 x, int32 y, int32 dir, int cpt->o_down_flag = 1; // 1 means okay. // if both mouse buttons were pressed on an exit => skip george's walk if ((id == GEORGE) && (_mouse->testEvent() == MOUSE_BOTH_BUTTONS)) { - _mouse->flushEvents(); int32 target = _scriptVars[CLICK_ID]; // exceptions: compacts that use hand pointers but are not actually exits if ((target != LEFT_SCROLL_POINTER) && (target != RIGHT_SCROLL_POINTER) && diff --git a/sword1/menu.cpp b/sword1/menu.cpp index 15f3942e61a..f085a549644 100644 --- a/sword1/menu.cpp +++ b/sword1/menu.cpp @@ -127,9 +127,10 @@ uint8 SwordMenu::checkMenuClick(uint8 menuType) { if (_objects[cnt]->wasClicked(x, y)) if (mouseEvent & BS1L_BUTTON_DOWN) { if (SwordLogic::_scriptVars[OBJECT_HELD]) { - if (SwordLogic::_scriptVars[OBJECT_HELD] == _menuList[cnt]) + if (SwordLogic::_scriptVars[OBJECT_HELD] == _menuList[cnt]) { + _mouse->setLuggage(0, 0); SwordLogic::_scriptVars[OBJECT_HELD] = 0; // reselected => deselect it - else { // the player is clicking another item on this one. + } else { // the player is clicking another item on this one. // run its use-script, if there is one SwordLogic::_scriptVars[SECOND_ITEM] = _menuList[cnt]; } @@ -138,8 +139,10 @@ uint8 SwordMenu::checkMenuClick(uint8 menuType) { refreshMenus = true; } else if (mouseEvent & BS1L_BUTTON_UP) { if (SwordLogic::_scriptVars[OBJECT_HELD] == _menuList[cnt]) { + _mouse->setLuggage(_objectDefs[_menuList[cnt]].luggageIconRes, 0); return cnt + 1; } else { + _mouse->setLuggage(0, 0); SwordLogic::_scriptVars[OBJECT_HELD] = 0; refreshMenus = true; } diff --git a/sword1/mouse.cpp b/sword1/mouse.cpp index a55cc395d71..5412dd1ebe0 100644 --- a/sword1/mouse.cpp +++ b/sword1/mouse.cpp @@ -35,35 +35,35 @@ SwordMouse::SwordMouse(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) { _resMan = pResMan; _objMan = pObjMan; _system = system; + _currentPtr = NULL; } void SwordMouse::initialize(void) { _numObjs = 0; SwordLogic::_scriptVars[MOUSE_STATUS] = 0; // mouse off and unlocked _getOff = 0; - _specialPtrId = 0; _inTopMenu = false; _mouseOverride = false; + _currentPtrId = _currentLuggageId = 0; - for (uint8 cnt = 0; cnt < 17; cnt++) - _pointers[cnt] = (MousePtr*)_resMan->mouseResOpen(MSE_POINTER + cnt); + for (uint8 cnt = 0; cnt < 17; cnt++) // force res manager to keep mouse + _resMan->resOpen(MSE_POINTER + cnt); // cursors in memory all the time + + createPointer(0, 0); } void SwordMouse::controlPanel(bool on) { // true on entering cpanel, false when leaving - static uint32 savedPtrId = 0, savedSpecialId = 0; + static uint32 savedPtrId = 0; if (on) { savedPtrId = _currentPtrId; - savedSpecialId = _specialPtrId; _mouseOverride = true; + setLuggage(0, 0); setPointer(MSE_POINTER, 0); } else { _currentPtrId = savedPtrId; - _specialPtrId = savedSpecialId; _mouseOverride = false; - if (_specialPtrId) - setPointer(_specialPtrId, 0); - else - setPointer(_currentPtrId + MSE_POINTER, 0); + setLuggage(_currentLuggageId, 0); + setPointer(_currentPtrId, 0); } } @@ -78,10 +78,6 @@ void SwordMouse::addToList(int id, BsObject *compact) { _numObjs++; } -void SwordMouse::flushEvents(void) { - _lastState = _state = 0; -} - void SwordMouse::engine(uint16 x, uint16 y, uint16 eventFlags) { _state = 0; // all mouse events are flushed after one cycle. if (_lastState) { // delay all events by one cycle to notice L_button + R_button clicks correctly. @@ -100,13 +96,6 @@ void SwordMouse::engine(uint16 x, uint16 y, uint16 eventFlags) { _mouseX = x; _mouseY = y; if (!(SwordLogic::_scriptVars[MOUSE_STATUS] & 1)) { // no human? - // if the mouse is turned off, I want the menu automatically removed, - // except while in conversation, while examining a menu object or while combining two menu objects! - /*if ((!subject_status)&&(!menu_looking)&&(!second_icon)) - { - HideMenu(TOP_MENU); - menu_status=0; - }*/ _numObjs = 0; return; // no human, so we don't want the mouse engine } @@ -177,44 +166,88 @@ uint16 SwordMouse::testEvent(void) { return _state; } -void SwordMouse::setLuggage(uint32 resId, uint32 rate) { - warning("stub: SwordMouse::setLuggage(%d, %d)", resId, rate); +void SwordMouse::createPointer(uint32 ptrId, uint32 luggageId) { + if (_currentPtr) { + free(_currentPtr); + _currentPtr = NULL; + } + if (ptrId) { + MousePtr *lugg = NULL; + MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId); + uint16 resSizeX = FROM_LE_16(ptr->sizeX); + uint16 resSizeY = FROM_LE_16(ptr->sizeY); + uint16 noFrames = FROM_LE_16(ptr->numFrames); + if (luggageId) { + lugg = (MousePtr*)_resMan->openFetchRes(luggageId); + resSizeX = MAX(resSizeX, (uint16)((resSizeX / 2) + FROM_LE_16(lugg->sizeX))); + resSizeY = MAX(resSizeY, (uint16)((resSizeY / 2) + FROM_LE_16(lugg->sizeY))); + } + _currentPtr = (MousePtr*)malloc(sizeof(MousePtr) + resSizeX * resSizeY * noFrames); + _currentPtr->hotSpotX = FROM_LE_16(ptr->hotSpotX); + _currentPtr->hotSpotY = FROM_LE_16(ptr->hotSpotY); + _currentPtr->numFrames = noFrames; + _currentPtr->sizeX = resSizeX; + _currentPtr->sizeY = resSizeY; + uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr); + memset(ptrData, 255, resSizeX * resSizeY * noFrames); + uint8 *dstData = ptrData; + uint8 *srcData = (uint8*)ptr + sizeof(MousePtr); + for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) { + for (uint32 cnty = 0; cnty < FROM_LE_16(ptr->sizeY); cnty++) { + for (uint32 cntx = 0; cntx < FROM_LE_16(ptr->sizeX); cntx++) + if (srcData[cntx]) + dstData[cntx] = srcData[cntx]; + srcData += FROM_LE_16(ptr->sizeX); + dstData += resSizeX; + } + dstData += (resSizeY - FROM_LE_16(ptr->sizeY)) * resSizeX; + } + if (luggageId) { + dstData = ptrData + resSizeX - FROM_LE_16(lugg->sizeX); + for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) { + uint8 *luggSrc = (uint8*)lugg + sizeof(MousePtr); + dstData += (resSizeY - FROM_LE_16(lugg->sizeY)) * resSizeX; + for (uint32 cnty = 0; cnty < FROM_LE_16(lugg->sizeY); cnty++) { + for (uint32 cntx = 0; cntx < FROM_LE_16(lugg->sizeX); cntx++) + if (luggSrc[cntx]) + dstData[cntx] = luggSrc[cntx]; + dstData += resSizeX; + luggSrc += FROM_LE_16(lugg->sizeX); + } + } + _resMan->resClose(luggageId); + } + _resMan->resClose(ptrId); + } } void SwordMouse::setPointer(uint32 resId, uint32 rate) { - if (_specialPtrId) { - _resMan->resClose(_specialPtrId); - _specialPtrId = 0; - } + _currentPtrId = resId; _frame = 0; + createPointer(resId, _currentLuggageId); + if ((resId == 0) || (!(SwordLogic::_scriptVars[MOUSE_STATUS] & 1) && (!_mouseOverride))) { _system->set_mouse_cursor(NULL, 0, 0, 0, 0); _system->show_mouse(false); } else { - if (resId <= MSE_ARROW9) - _currentPtrId = resId - MSE_POINTER; - else { - _currentPtrId = 0; - _specialPtrId = resId; - _specialPtr = (MousePtr*)_resMan->mouseResOpen(resId); - } animate(); _system->show_mouse(true); } } -void SwordMouse::animate(void) { - MousePtr *currentPtr; - if ((SwordLogic::_scriptVars[MOUSE_STATUS] == 1) || _mouseOverride) { - if (_specialPtrId) - currentPtr = _specialPtr; - else - currentPtr = _pointers[_currentPtrId]; +void SwordMouse::setLuggage(uint32 resId, uint32 rate) { + _currentLuggageId = resId; + _frame = 0; + createPointer(_currentPtrId, resId); +} - _frame = (_frame + 1) % currentPtr->numFrames; - uint16 size = currentPtr->sizeX * currentPtr->sizeY; - _system->set_mouse_cursor(currentPtr->data + 0x30 + _frame * size, currentPtr->sizeX, currentPtr->sizeY, currentPtr->hotSpotX, currentPtr->hotSpotY); +void SwordMouse::animate(void) { + if ((SwordLogic::_scriptVars[MOUSE_STATUS] == 1) || _mouseOverride) { + _frame = (_frame + 1) % _currentPtr->numFrames; + uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr); + ptrData += _frame * _currentPtr->sizeX * _currentPtr->sizeY; + _system->set_mouse_cursor(ptrData, _currentPtr->sizeX, _currentPtr->sizeY, _currentPtr->hotSpotX, _currentPtr->hotSpotY); } } @@ -230,11 +263,9 @@ void SwordMouse::fnAddHuman(void) { if (SwordLogic::_scriptVars[MOUSE_STATUS] & 2) // locked, can't do anything return ; SwordLogic::_scriptVars[MOUSE_STATUS] = 1; - SwordLogic::_scriptVars[SPECIAL_ITEM] = 0; // _scriptVars is unsigned... + SwordLogic::_scriptVars[SPECIAL_ITEM] = 0; _getOff = SCR_std_off; setPointer(MSE_POINTER, 0); - _mouseCount = 3; - } void SwordMouse::fnBlankMouse(void) { diff --git a/sword1/mouse.h b/sword1/mouse.h index c96aad63ebe..92424a0fbf2 100644 --- a/sword1/mouse.h +++ b/sword1/mouse.h @@ -51,7 +51,7 @@ struct MousePtr { uint16 sizeY; uint16 hotSpotX; uint16 hotSpotY; - uint8 data[2]; // arbitrary number. + uint8 dummyData[0x30]; } GCC_PACK; #if !defined(__GNUC__) @@ -75,7 +75,7 @@ public: void animate(void); void engine(uint16 x, uint16 y, uint16 eventFlags); uint16 testEvent(void); - void flushEvents(void); + //void flushEvents(void); void giveCoords(uint16 *x, uint16 *y); void fnNoHuman(void); void fnAddHuman(void); @@ -85,7 +85,7 @@ public: void fnUnlockMouse(void); void controlPanel(bool on); private: - MousePtr *_pointers[17]; + void createPointer(uint32 ptrId, uint32 luggageId); OSystem *_system; SwordLogic *_logic; SwordMenu *_menu; @@ -94,13 +94,15 @@ private: ObjectMan *_objMan; uint16 _mouseX, _mouseY; - uint32 _currentPtrId, _frame; - uint8 _mouseCount; + uint32 _currentPtrId, _currentLuggageId, _frame; + MousePtr *_currentPtr; + //uint8 _mouseCount; uint16 _numObjs; uint16 _lastState, _state; uint32 _getOff; - uint32 _specialPtrId; // for special mouse cursors which aren't in the _pointers[] array. - MousePtr *_specialPtr; + //uint32 _specialPtrId; // for special mouse cursors which aren't in the _pointers[] array. + //MousePtr *_specialPtr; + //MousePtr *_pointers[17]; bool _inTopMenu, _mouseOverride; };