mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 12:46:56 +00:00
40f9506163
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
353 lines
10 KiB
C++
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
|