Skip to content

Commit

Permalink
ZVISION: Refactoring cursor manager into simple and full-functionally.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marisa-Chan committed Dec 4, 2013
1 parent f3e2857 commit 066cc74
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 125 deletions.
163 changes: 73 additions & 90 deletions engines/zvision/cursor_manager.cpp
Expand Up @@ -50,87 +50,59 @@ const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow
CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat)
: _engine(engine),
_pixelFormat(pixelFormat),
_cursorIsPushed(false) {
// WARNING: The index IDLE_CURSOR_INDEX is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
if (_engine->getGameId() == GID_NEMESIS) {
Common::String name(Common::String::format("%sa.zcr", _zNemCursorFileNames[IDLE_CURSOR_INDEX]));
_idleCursor = ZorkCursor(name);
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
_idleCursor = ZorkCursor(_zgiCursorFileNames[IDLE_CURSOR_INDEX]);
_cursorIsPushed(false),
_item(0),
_lastitem(0) {
for (int i = 0; i < NUM_CURSORS; i++) {
if (_engine->getGameId() == GID_NEMESIS) {
Common::String name;
name = Common::String::format("%sa.zcr", _zNemCursorFileNames[i]);
_cursors[i][0] = ZorkCursor(name); // Up cursor
name = Common::String::format("%sb.zcr", _zNemCursorFileNames[i]);
_cursors[i][1] = ZorkCursor(name); // Down cursor
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
_cursors[i][0] = ZorkCursor(_zgiCursorFileNames[i]); // Up cursor
char buffer[25];
strcpy(buffer, _zgiCursorFileNames[i]);
buffer[3] += 2;
_cursors[i][1] = ZorkCursor(buffer); // Down cursor
}
}
}

void CursorManager::initialize() {
revertToIdle();
CursorMan.showMouse(true);
}

void CursorManager::changeCursor(const Common::String &cursorName) {
changeCursor(cursorName, _cursorIsPushed);
}

void CursorManager::changeCursor(const Common::String &cursorName, bool pushed) {
if (_currentCursor.equals(cursorName) && _cursorIsPushed == pushed)
return;

if (_cursorIsPushed != pushed)
_cursorIsPushed = pushed;

if (cursorName == "idle" && !pushed) {
CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
return;
}

for (int i = 0; i < NUM_CURSORS; ++i) {
if (_engine->getGameId() == GID_NEMESIS) {
if (cursorName.equals(_cursorNames[i])) {
_currentCursor = cursorName;

// ZNem uses a/b at the end of the file to signify not pushed/pushed respectively
Common::String pushedFlag = pushed ? "b" : "a";
Common::String name = Common::String::format("%s%s.zcr", _zNemCursorFileNames[i], pushedFlag.c_str());

changeCursor(ZorkCursor(name));
return;
}
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
if (cursorName.equals(_cursorNames[i])) {
_currentCursor = cursorName;

if (!pushed) {
changeCursor(ZorkCursor(_zgiCursorFileNames[i]));
} else {
// ZGI flips not pushed/pushed between a/c and b/d
// It flips the 4th character of the name
char buffer[25];
strcpy(buffer, _zgiCursorFileNames[i]);
buffer[3] += 2;
changeCursor(ZorkCursor(buffer));
}
void CursorManager::setItemID(int id) {
if (id != _item) {
if (id) {
Common::String file;
if (_engine->getGameId() == GID_NEMESIS) {
file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'a');
_cursors[NUM_CURSORS][0] = ZorkCursor(file);
file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b');
_cursors[NUM_CURSORS][1] = ZorkCursor(file);
file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'a');
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(file);
file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'b');
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(file);
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
file = Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id);
_cursors[NUM_CURSORS][0] = ZorkCursor(file);
file = Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id);
_cursors[NUM_CURSORS][1] = ZorkCursor(file);
file = Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id);
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(file);
file = Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id);
_cursors[NUM_CURSORS + 1][1] = ZorkCursor(file);
} else
return;
}
}
_item = id;
changeCursor(CursorIndex_Idle);
}

// If we get here, something went wrong
warning("No cursor found for identifier %s", cursorName.c_str());
}

void CursorManager::changeCursor(int id, bool active, bool pushed) {
Common::String file;
if (_engine->getGameId() == GID_NEMESIS) {
file = Common::String::format("%2.2d%s%c.zcr", id, active ? "act" : "idle", pushed ? 'b' : 'a');
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
file = Common::String::format("g0b%cc%2.2x1.zcr", active ? (pushed ? 'd' : 'c') : (pushed ? 'b' : 'a') , id);
} else
return;

if (_currentCursor.equals(file))
return;

_currentCursor = file;

changeCursor(ZorkCursor(file));
void CursorManager::initialize() {
changeCursor(_cursors[CursorIndex_Idle][_cursorIsPushed]);
showMouse(true);
}

void CursorManager::changeCursor(const ZorkCursor &cursor) {
Expand All @@ -141,31 +113,42 @@ void CursorManager::cursorDown(bool pushed) {
if (_cursorIsPushed == pushed)
return;

changeCursor(_currentCursor, pushed);
}
_cursorIsPushed = pushed;

void CursorManager::setLeftCursor() {
changeCursor("leftarrow");
changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
}

void CursorManager::setRightCursor() {
changeCursor("rightarrow");
}
void CursorManager::changeCursor(int id) {
int _id = id;

void CursorManager::setUpCursor() {
changeCursor("zuparrow");
if (_item &&
(_id == CursorIndex_Active ||
_id == CursorIndex_Idle ||
_id == CursorIndex_HandPu)) {

if (_id == CursorIndex_Idle)
_id = CursorIndex_ItemIdle;
else
_id = CursorIndex_ItemAct;
}

if (_currentCursor != _id ||
((_id == CursorIndex_ItemAct || _id == CursorIndex_ItemIdle) && _lastitem != _item)) {
_currentCursor = _id;
_lastitem = _item;
changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
}
}

void CursorManager::setDownCursor() {
changeCursor("downarrow");
int CursorManager::getCursorId(Common::String &name) {
for (int i = 0; i < NUM_CURSORS; i++)
if (name.equals(_cursorNames[i]))
return i;
return CursorIndex_Idle;
}

void CursorManager::revertToIdle() {
_currentCursor = "idle";
if (!_cursorIsPushed)
CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
else
changeCursor(_currentCursor, _cursorIsPushed);
void CursorManager::showMouse(bool vis) {
CursorMan.showMouse(vis);
}

} // End of namespace ZVision
73 changes: 46 additions & 27 deletions engines/zvision/cursor_manager.h
Expand Up @@ -36,6 +36,21 @@ namespace ZVision {

class ZVision;

/**
* Mostly usable cursors
*/
enum CursorIndex {
CursorIndex_Active = 0,
CursorIndex_DownArr = 3,
CursorIndex_HandPu = 6,
CursorIndex_Idle = 11,
CursorIndex_Left = 12,
CursorIndex_Right = 13,
CursorIndex_UpArr = 17,
CursorIndex_ItemIdle = 18,
CursorIndex_ItemAct = 19
};

/**
* Class to manage cursor changes. The actual changes have to be done
* through CursorMan. Otherwise the cursor will disappear after GMM
Expand All @@ -47,17 +62,17 @@ class CursorManager {
CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat);

private:
enum {
NUM_CURSORS = 18,
// WARNING: The index 11 is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
IDLE_CURSOR_INDEX = 11
};
static const int NUM_CURSORS = 18;

// 18 default cursors in up/down states, +2 for items idle/act cursors
ZorkCursor _cursors[NUM_CURSORS + 2][2];

ZVision *_engine;
const Graphics::PixelFormat *_pixelFormat;
ZorkCursor _idleCursor;
Common::String _currentCursor;
bool _cursorIsPushed;
int _item;
int _lastitem;
int _currentCursor;

static const char *_cursorNames[];
static const char *_zgiCursorFileNames[];
Expand All @@ -68,39 +83,43 @@ class CursorManager {
void initialize();

/**
* Parses a cursor name into a cursor file then creates and shows that cursor.
* It will use the current _isCursorPushed state to choose the correct cursor
* Change cursor to specified cursor ID. If item setted to not 0 and cursor id idle/acrive/handpu change cursor to item.
*
* @param id Wanted cursor id.
*/

void changeCursor(int id);

/**
* Return founded id for string contains cursor name
*
* @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
* @param name Cursor name
* @return Id of cursor or idle cursor id if not found
*/
void changeCursor(const Common::String &cursorName);

int getCursorId(Common::String &name);

/**
* Parses a cursor name into a cursor file then creates and shows that cursor.
* Load cursor for item by id, and try to change cursor to item cursor if it's not 0
*
* @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
* @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
* @param id Item id or 0 for no item cursor
*/
void changeCursor(const Common::String &cursorName, bool pushed);

void changeCursor(int id, bool active, bool pushed);
void setItemID(int id);

/**
* Change the cursor to a certain push state. If the cursor is already in the specified push state, nothing will happen.
*
* @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
*/
void cursorDown(bool pushed);

/** Set the cursor to 'Left Arrow'. It will retain the current _isCursorPushed state */
void setLeftCursor();
/** Set the cursor to 'Right Arrow'. It will retain the current _isCursorPushed state */
void setRightCursor();
/** Set the cursor to 'Up Arrow'. It will retain the current _isCursorPushed state */
void setUpCursor();
/** Set the cursor to 'Down Arrow'. It will retain the current _isCursorPushed state */
void setDownCursor();

/** Set the cursor to 'Idle'. It will retain the current _isCursorPushed state */
void revertToIdle();
/**
* Show or hide mouse cursor.
*
* @param vis Should the cursor be showed (true) or hide (false)
*/
void showMouse(bool vis);

private:
/**
Expand Down
10 changes: 5 additions & 5 deletions engines/zvision/events.cpp
Expand Up @@ -150,14 +150,14 @@ void ZVision::onMouseMove(const Common::Point &pos) {
// We use fixed point math to get better accuracy
Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.left)) - MAX_ROTATION_SPEED;
_renderManager->setBackgroundVelocity(velocity.toInt());
_cursorManager->setLeftCursor();
_cursorManager->changeCursor(CursorIndex_Left);
cursorWasChanged = true;
} else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) {
// Linear function of distance to the right edge (y = mx)
// We use fixed point math to get better accuracy
Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET);
_renderManager->setBackgroundVelocity(velocity.toInt());
_cursorManager->setRightCursor();
_cursorManager->changeCursor(CursorIndex_Right);
cursorWasChanged = true;
} else {
_renderManager->setBackgroundVelocity(0);
Expand All @@ -168,14 +168,14 @@ void ZVision::onMouseMove(const Common::Point &pos) {
// We use fixed point math to get better accuracy
Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - MAX_ROTATION_SPEED;
_renderManager->setBackgroundVelocity(velocity.toInt());
_cursorManager->setUpCursor();
_cursorManager->changeCursor(CursorIndex_UpArr);
cursorWasChanged = true;
} else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) {
// Linear function of distance to the bottom edge (y = mx)
// We use fixed point math to get better accuracy
Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET);
_renderManager->setBackgroundVelocity(velocity.toInt());
_cursorManager->setDownCursor();
_cursorManager->changeCursor(CursorIndex_DownArr);
cursorWasChanged = true;
} else {
_renderManager->setBackgroundVelocity(0);
Expand All @@ -186,7 +186,7 @@ void ZVision::onMouseMove(const Common::Point &pos) {
}

if (!cursorWasChanged) {
_cursorManager->revertToIdle();
_cursorManager->changeCursor(CursorIndex_Idle);
}
}

Expand Down
2 changes: 1 addition & 1 deletion engines/zvision/lever_control.cpp
Expand Up @@ -239,7 +239,7 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
}
}
} else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_cursorName);
_engine->getCursorManager()->changeCursor(_engine->getCursorManager()->getCursorId(_cursorName));
cursorWasChanged = true;
}

Expand Down
2 changes: 1 addition & 1 deletion engines/zvision/push_toggle_control.cpp
Expand Up @@ -88,7 +88,7 @@ bool PushToggleControl::onMouseMove(const Common::Point &screenSpacePos, const C
return false;

if (_hotspot.contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_hoverCursor);
_engine->getCursorManager()->changeCursor(_engine->getCursorManager()->getCursorId(_hoverCursor));
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion engines/zvision/script_manager.cpp
Expand Up @@ -511,7 +511,7 @@ void ScriptManager::do_changeLocation() {
_activeControls = &nodeview._controls;

// Revert to the idle cursor
_engine->getCursorManager()->revertToIdle();
_engine->getCursorManager()->changeCursor(CursorIndex_Idle);

// Reset the background velocity
_engine->getRenderManager()->setBackgroundVelocity(0);
Expand Down
2 changes: 2 additions & 0 deletions engines/zvision/zvision.cpp
Expand Up @@ -143,6 +143,8 @@ Common::Error ZVision::run() {
uint32 currentTime = _clock.getLastMeasuredTime();
uint32 deltaTime = _clock.getDeltaTime();

_cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem));

processEvents();

// Call _renderManager->update() first so the background renders
Expand Down

0 comments on commit 066cc74

Please sign in to comment.