Files
2026-02-02 04:50:13 +01:00

172 lines
4.1 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "asylum/system/cursor.h"
#include "asylum/system/graphics.h"
#include "asylum/asylum.h"
#include "graphics/cursorman.h"
namespace Asylum {
const uint32 CURSOR_UPDATE_TICKS = 100;
Cursor::Cursor(AsylumEngine *engine) : _vm(engine),
_cursorRes(nullptr), _nextTick(0), _frameStep(0),
_graphicResourceId(kResourceNone), _currentFrame(0), _lastFrameIndex(0), _counter(0), _animation(kCursorAnimationNone),
_forceHide(false) {
}
Cursor::~Cursor() {
delete _cursorRes;
}
void Cursor::hide() const {
CursorMan.showMouse(false);
}
void Cursor::show() const {
if (!_forceHide)
CursorMan.showMouse(true);
}
void Cursor::set(ResourceId resourceId, int32 cnt, CursorAnimation anim, int32 frames) {
bool wasHidden = isHidden();
hide();
delete _cursorRes;
_cursorRes = new GraphicResource(_vm, resourceId);
// Set next update
_nextTick = _vm->getTick() + CURSOR_UPDATE_TICKS;
// Get frame count
if (frames >= 0)
_lastFrameIndex = (uint32)frames;
else
_lastFrameIndex = _cursorRes->count() - 1;
this->_graphicResourceId = resourceId;
this->_animation = anim;
this->_counter = cnt;
_currentFrame = 0;
_frameStep = 1;
// Do not animate if no frames (and the other way around)
if (_lastFrameIndex == 0 || anim == kCursorAnimationNone) {
_lastFrameIndex = 0;
_animation = kCursorAnimationNone;
}
if (_lastFrameIndex >= _cursorRes->count())
_lastFrameIndex = _cursorRes->count() - 1;
update();
if (!wasHidden)
show();
}
void Cursor::update() {
if (!_cursorRes)
error("[Cursor::update] Cursor resources not initialized properly!");
Common::Point hotspot = getHotspot(_currentFrame);
GraphicFrame *frame = _cursorRes->getFrame(_currentFrame);
CursorMan.replaceCursor(frame->surface, hotspot.x, hotspot.y, 0);
}
void Cursor::animate() {
if (isHidden() || !_animation || _nextTick > _vm->getTick())
return;
bool notifyHandler = false;
int32 frame = 0;
if (_animation == kCursorAnimationLinear) {
if (_currentFrame == _lastFrameIndex) {
_currentFrame = frame = 0;
} else {
_currentFrame += _frameStep;
frame = _currentFrame;
}
} else if (_animation == kCursorAnimationMirror) {
_currentFrame += _frameStep;
frame = _currentFrame;
if (_currentFrame == 0 || _currentFrame == _lastFrameIndex)
_frameStep = -_frameStep;
}
if (frame == 0) {
if (_counter != -1) {
--_counter;
if (!_counter) {
_animation = kCursorAnimationNone;
notifyHandler = true;
}
}
}
_nextTick = _vm->getTick() + CURSOR_UPDATE_TICKS;
if (notifyHandler)
_vm->notify(EVENT_ASYLUM_CURSOR);
update();
}
Common::Point Cursor::getHotspot(uint32 frameIndex) {
if (!_cursorRes)
error("[Cursor::getHotspot] Cursor resource not initialized properly");
Common::Point point;
uint32 resFlags = _cursorRes->getData().flags;
if (BYTE1(resFlags) & 0x10) {
// XXX removed a check for frameIndex >= 0 as it will always
// evaluate to true since frameIndex is unsigned
if (frameIndex > _cursorRes->count()) {
GraphicFrame *frame = _cursorRes->getFrame(_currentFrame);
point.x = frame->x;
point.y = frame->y;
}
}
return point;
}
bool Cursor::isHidden() const {
return !CursorMan.isVisible();
}
const Common::Point Cursor::position() const {
return g_system->getEventManager()->getMousePos();
}
} // end of namespace Asylum