scummvm/engines/sword1/mouse.cpp
Marcus Comstedt 40f9506163 The default keycolor for mouse pointers used to be 255.
This makes sense as a default for CLUT8 modes, but not really
for anything else.  As part of the gsoc2009-16bit merge, the
default was changed to "all ones", with extra code in the SDL
backend to truncate this to the depth of the mode.  However,
"all ones" (white) still isn't a very useful default for RGB modes.
So rather than jumping through hoops to provide a bad default,
it's better to remove the default altogether.  Engines which relied
on the old default of 255 have been updated to specify it explicitly.

svn-id: r47118
2010-01-07 15:07:36 +00:00

353 lines
10 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/system.h"
#include "graphics/cursorman.h"
#include "sword1/mouse.h"
#include "sword1/menu.h"
#include "sword1/screen.h"
#include "sword1/logic.h"
#include "sword1/resman.h"
#include "sword1/objectman.h"
#include "sword1/sworddefs.h"
#include "sword1/swordres.h"
#include "sword1/menu.h"
#include "sword1/sword1.h"
namespace Sword1 {
Mouse::Mouse(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
_resMan = pResMan;
_objMan = pObjMan;
_system = system;
_currentPtr = NULL;
}
Mouse::~Mouse() {
setLuggage(0, 0);
setPointer(0, 0);
for (uint8 cnt = 0; cnt < 17; cnt++) // close mouse cursor resources
_resMan->resClose(MSE_POINTER + cnt);
}
void Mouse::initialize() {
_numObjs = 0;
Logic::_scriptVars[MOUSE_STATUS] = 0; // mouse off and unlocked
_getOff = 0;
_inTopMenu = false;
_lastState = 0;
_mouseOverride = false;
_currentPtrId = _currentLuggageId = 0;
for (uint8 cnt = 0; cnt < 17; cnt++) // force res manager to keep mouse
_resMan->resOpen(MSE_POINTER + cnt); // cursors in memory all the time
CursorMan.showMouse(false);
createPointer(0, 0);
}
void Mouse::controlPanel(bool on) { // true on entering cpanel, false when leaving
static uint32 savedPtrId = 0;
if (on) {
savedPtrId = _currentPtrId;
_mouseOverride = true;
setLuggage(0, 0);
setPointer(MSE_POINTER, 0);
} else {
_currentPtrId = savedPtrId;
_mouseOverride = false;
setLuggage(_currentLuggageId, 0);
setPointer(_currentPtrId, 0);
}
}
void Mouse::useLogicAndMenu(Logic *pLogic, Menu *pMenu) {
_logic = pLogic;
_menu = pMenu;
}
void Mouse::addToList(int id, Object *compact) {
_objList[_numObjs].id = id;
_objList[_numObjs].compact = compact;
_numObjs++;
}
void Mouse::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.
_state = _lastState | eventFlags;
_lastState = 0;
} else if (eventFlags)
_lastState = eventFlags;
// if we received both, mouse down and mouse up event in this cycle, resort them so that
// we'll receive the up event in the next one.
if ((_state & MOUSE_DOWN_MASK) && (_state & MOUSE_UP_MASK)) {
_lastState = _state & MOUSE_UP_MASK;
_state &= MOUSE_DOWN_MASK;
}
_mouse.x = x;
_mouse.y = y;
if (!(Logic::_scriptVars[MOUSE_STATUS] & 1)) { // no human?
_numObjs = 0;
return; // no human, so we don't want the mouse engine
}
if (!Logic::_scriptVars[TOP_MENU_DISABLED]) {
if (y < 40) { // okay, we are in the top menu.
if (!_inTopMenu) { // are we just entering it?
if (!Logic::_scriptVars[OBJECT_HELD])
_menu->fnStartMenu();
setPointer(MSE_POINTER, 0);
}
_menu->checkTopMenu();
_inTopMenu = true;
} else if (_inTopMenu) { // we're not in the menu. did we just leave it?
if (!Logic::_scriptVars[OBJECT_HELD])
_menu->fnEndMenu();
_inTopMenu = false;
}
} else if (_inTopMenu) {
_menu->fnEndMenu();
_inTopMenu = false;
}
Logic::_scriptVars[MOUSE_X] = Logic::_scriptVars[SCROLL_OFFSET_X] + x + 128;
Logic::_scriptVars[MOUSE_Y] = Logic::_scriptVars[SCROLL_OFFSET_Y] + y + 128 - 40;
//-
int32 touchedId = 0;
uint16 clicked = 0;
if (y > 40) {
for (uint16 priority = 0; (priority < 10) && (!touchedId); priority++) {
for (uint16 cnt = 0; (cnt < _numObjs) && (!touchedId); cnt++) {
if ((_objList[cnt].compact->o_priority == priority) &&
(Logic::_scriptVars[MOUSE_X] >= (uint32)_objList[cnt].compact->o_mouse_x1) &&
(Logic::_scriptVars[MOUSE_X] <= (uint32)_objList[cnt].compact->o_mouse_x2) &&
(Logic::_scriptVars[MOUSE_Y] >= (uint32)_objList[cnt].compact->o_mouse_y1) &&
(Logic::_scriptVars[MOUSE_Y] <= (uint32)_objList[cnt].compact->o_mouse_y2)) {
touchedId = _objList[cnt].id;
clicked = cnt;
}
}
}
if (touchedId != (int)Logic::_scriptVars[SPECIAL_ITEM]) { //the mouse collision situation has changed in one way or another
Logic::_scriptVars[SPECIAL_ITEM] = touchedId;
if (_getOff) { // there was something else selected before, run its get-off script
_logic->runMouseScript(NULL, _getOff);
_getOff = 0;
}
if (touchedId) { // there's something new selected, now.
if (_objList[clicked].compact->o_mouse_on) //run its get on
_logic->runMouseScript(_objList[clicked].compact, _objList[clicked].compact->o_mouse_on);
_getOff = _objList[clicked].compact->o_mouse_off; //setup get-off for later
}
}
} else
Logic::_scriptVars[SPECIAL_ITEM] = 0;
if (_state & MOUSE_DOWN_MASK) {
if (_inTopMenu) {
if (Logic::_scriptVars[SECOND_ITEM])
_logic->runMouseScript(NULL, _menu->_objectDefs[Logic::_scriptVars[SECOND_ITEM]].useScript);
if (Logic::_scriptVars[MENU_LOOKING])
_logic->cfnPresetScript(NULL, -1, PLAYER, SCR_menu_look, 0, 0, 0, 0);
}
Logic::_scriptVars[MOUSE_BUTTON] = _state & MOUSE_DOWN_MASK;
if (Logic::_scriptVars[SPECIAL_ITEM]) {
Object *compact = _objMan->fetchObject(Logic::_scriptVars[SPECIAL_ITEM]);
_logic->runMouseScript(compact, compact->o_mouse_click);
}
}
_numObjs = 0;
}
uint16 Mouse::testEvent() {
return _state;
}
void Mouse::createPointer(uint32 ptrId, uint32 luggageId) {
if (_currentPtr) {
free(_currentPtr);
_currentPtr = NULL;
}
if (ptrId) {
MousePtr *lugg = NULL;
MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId);
uint16 noFrames = _resMan->getLEUint16(ptr->numFrames);
uint16 ptrSizeX = _resMan->getLEUint16(ptr->sizeX);
uint16 ptrSizeY = _resMan->getLEUint16(ptr->sizeY);
uint16 luggSizeX = 0;
uint16 luggSizeY = 0;
uint16 resSizeX;
uint16 resSizeY;
if (SwordEngine::isPsx()) //PSX pointers are half height
ptrSizeY *= 2;
if (luggageId) {
lugg = (MousePtr*)_resMan->openFetchRes(luggageId);
luggSizeX = _resMan->getLEUint16(lugg->sizeX);
luggSizeY = _resMan->getLEUint16(lugg->sizeY);
if (SwordEngine::isPsx())
luggSizeY *= 2;
resSizeX = MAX(ptrSizeX, (uint16)((ptrSizeX / 2) + luggSizeX));
resSizeY = MAX(ptrSizeY, (uint16)((ptrSizeY / 2) + luggSizeY));
} else {
resSizeX = ptrSizeX;
resSizeY = ptrSizeY;
}
_currentPtr = (MousePtr*)malloc(sizeof(MousePtr) + resSizeX * resSizeY * noFrames);
_currentPtr->hotSpotX = _resMan->getLEUint16(ptr->hotSpotX);
_currentPtr->hotSpotY = _resMan->getLEUint16(ptr->hotSpotY);
_currentPtr->numFrames = noFrames;
_currentPtr->sizeX = resSizeX;
_currentPtr->sizeY = resSizeY;
uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr);
memset(ptrData, 255, resSizeX * resSizeY * noFrames);
if (luggageId) {
uint8 *dstData = ptrData + resSizeX - luggSizeX;
for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) {
uint8 *luggSrc = (uint8*)lugg + sizeof(MousePtr);
dstData += (resSizeY - luggSizeY) * resSizeX;
for (uint32 cnty = 0; cnty < (uint32)(SwordEngine::isPsx() ? luggSizeY / 2 : luggSizeY); cnty++) {
for (uint32 cntx = 0; cntx < luggSizeX; cntx++)
if (luggSrc[cntx])
dstData[cntx] = luggSrc[cntx];
if (SwordEngine::isPsx()) {
dstData += resSizeX;
for (uint32 cntx = 0; cntx < luggSizeX; cntx++)
if (luggSrc[cntx])
dstData[cntx] = luggSrc[cntx];
}
dstData += resSizeX;
luggSrc += luggSizeX;
}
}
_resMan->resClose(luggageId);
}
uint8 *dstData = ptrData;
uint8 *srcData = (uint8*)ptr + sizeof(MousePtr);
for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) {
for (uint32 cnty = 0; cnty < (uint32)(SwordEngine::isPsx() ? ptrSizeY / 2 : ptrSizeY); cnty++) {
for (uint32 cntx = 0; cntx < ptrSizeX; cntx++)
if (srcData[cntx])
dstData[cntx] = srcData[cntx];
if (SwordEngine::isPsx()) {
dstData +=resSizeX;
for (uint32 cntx = 0; cntx < ptrSizeX; cntx++)
if (srcData[cntx])
dstData[cntx] = srcData[cntx];
}
srcData += ptrSizeX;
dstData += resSizeX;
}
dstData += (resSizeY - ptrSizeY) * resSizeX;
}
_resMan->resClose(ptrId);
}
}
void Mouse::setPointer(uint32 resId, uint32 rate) {
_currentPtrId = resId;
_frame = 0;
createPointer(resId, _currentLuggageId);
if ((resId == 0) || (!(Logic::_scriptVars[MOUSE_STATUS] & 1) && (!_mouseOverride))) {
CursorMan.showMouse(false);
} else {
animate();
CursorMan.showMouse(true);
}
}
void Mouse::setLuggage(uint32 resId, uint32 rate) {
_currentLuggageId = resId;
_frame = 0;
createPointer(_currentPtrId, resId);
}
void Mouse::animate() {
if ((Logic::_scriptVars[MOUSE_STATUS] == 1) || (_mouseOverride && _currentPtr)) {
_frame = (_frame + 1) % _currentPtr->numFrames;
uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr);
ptrData += _frame * _currentPtr->sizeX * _currentPtr->sizeY;
CursorMan.replaceCursor(ptrData, _currentPtr->sizeX, _currentPtr->sizeY, _currentPtr->hotSpotX, _currentPtr->hotSpotY, 255);
}
}
void Mouse::fnNoHuman() {
if (Logic::_scriptVars[MOUSE_STATUS] & 2) // locked, can't do anything
return ;
Logic::_scriptVars[MOUSE_STATUS] = 0; // off & unlocked
setLuggage(0, 0);
setPointer(0, 0);
}
void Mouse::fnAddHuman() {
if (Logic::_scriptVars[MOUSE_STATUS] & 2) // locked, can't do anything
return ;
Logic::_scriptVars[MOUSE_STATUS] = 1;
Logic::_scriptVars[SPECIAL_ITEM] = 0;
_getOff = SCR_std_off;
setPointer(MSE_POINTER, 0);
}
void Mouse::fnBlankMouse() {
setPointer(0, 0);
}
void Mouse::fnNormalMouse() {
setPointer(MSE_POINTER, 0);
}
void Mouse::fnLockMouse() {
Logic::_scriptVars[MOUSE_STATUS] |= 2;
}
void Mouse::fnUnlockMouse() {
Logic::_scriptVars[MOUSE_STATUS] &= 1;
}
void Mouse::giveCoords(uint16 *x, uint16 *y) {
*x = _mouse.x;
*y = _mouse.y;
}
} // End of namespace Sword1