From 4b2b5e686b6ac2105f11983b2072037358d9ad7f Mon Sep 17 00:00:00 2001
From: Filippos Karapetis
Date: Tue, 16 Dec 2014 01:00:50 +0200
Subject: ZVISION: Move the mouse cursor handling code into the graphics code

---
 engines/zvision/graphics/cursors/cursor.cpp        | 122 +++++++++++++++++
 engines/zvision/graphics/cursors/cursor.h          |  79 +++++++++++
 .../zvision/graphics/cursors/cursor_manager.cpp    | 152 +++++++++++++++++++++
 engines/zvision/graphics/cursors/cursor_manager.h  | 134 ++++++++++++++++++
 4 files changed, 487 insertions(+)
 create mode 100644 engines/zvision/graphics/cursors/cursor.cpp
 create mode 100644 engines/zvision/graphics/cursors/cursor.h
 create mode 100644 engines/zvision/graphics/cursors/cursor_manager.cpp
 create mode 100644 engines/zvision/graphics/cursors/cursor_manager.h

(limited to 'engines/zvision/graphics')

diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp
new file mode 100644
index 0000000000..07323b45c4
--- /dev/null
+++ b/engines/zvision/graphics/cursors/cursor.cpp
@@ -0,0 +1,122 @@
+/* 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.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/graphics/cursors/cursor.h"
+
+#include "common/str.h"
+#include "common/file.h"
+
+namespace ZVision {
+
+ZorkCursor::ZorkCursor()
+	: _width(0),
+	  _height(0),
+	  _hotspotX(0),
+	  _hotspotY(0) {
+}
+
+ZorkCursor::ZorkCursor(const Common::String &fileName)
+	: _width(0),
+	  _height(0),
+	  _hotspotX(0),
+	  _hotspotY(0) {
+	Common::File file;
+	if (!file.open(fileName))
+		return;
+
+	uint32 magic = file.readUint32BE();
+	if (magic != MKTAG('Z', 'C', 'R', '1')) {
+		warning("%s is not a Zork Cursor file", fileName.c_str());
+		return;
+	}
+
+	_hotspotX = file.readUint16LE();
+	_hotspotY = file.readUint16LE();
+	_width = file.readUint16LE();
+	_height = file.readUint16LE();
+
+	uint dataSize = _width * _height * sizeof(uint16);
+	_surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+	uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
+	assert(bytesRead == dataSize);
+
+	// Convert to RGB 565
+	_surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+}
+
+ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName)
+	: _width(0),
+	  _height(0),
+	  _hotspotX(0),
+	  _hotspotY(0) {
+	Common::File file;
+	if (!engine->getSearchManager()->openFile(file, fileName))
+		return;
+
+	uint32 magic = file.readUint32BE();
+	if (magic != MKTAG('Z', 'C', 'R', '1')) {
+		warning("%s is not a Zork Cursor file", fileName.c_str());
+		return;
+	}
+
+	_hotspotX = file.readUint16LE();
+	_hotspotY = file.readUint16LE();
+	_width = file.readUint16LE();
+	_height = file.readUint16LE();
+
+	uint dataSize = _width * _height * sizeof(uint16);
+	_surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+	uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
+	assert(bytesRead == dataSize);
+
+	// Convert to RGB 565
+	_surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+}
+
+ZorkCursor::ZorkCursor(const ZorkCursor &other) {
+	_width = other._width;
+	_height = other._height;
+	_hotspotX = other._hotspotX;
+	_hotspotY = other._hotspotY;
+
+	_surface.copyFrom(other._surface);
+}
+
+ZorkCursor &ZorkCursor::operator=(const ZorkCursor &other) {
+	_width = other._width;
+	_height = other._height;
+	_hotspotX = other._hotspotX;
+	_hotspotY = other._hotspotY;
+
+	_surface.free();
+	_surface.copyFrom(other._surface);
+
+	return *this;
+}
+
+ZorkCursor::~ZorkCursor() {
+	_surface.free();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/cursors/cursor.h b/engines/zvision/graphics/cursors/cursor.h
new file mode 100644
index 0000000000..0c1e99411f
--- /dev/null
+++ b/engines/zvision/graphics/cursors/cursor.h
@@ -0,0 +1,79 @@
+/* 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.
+ *
+ */
+
+#ifndef ZVISION_CURSOR_H
+#define ZVISION_CURSOR_H
+
+#include "graphics/surface.h"
+#include "zvision/zvision.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+/**
+ * Utility class to parse and hold cursor data
+ * Modeled off Graphics::Cursor
+ */
+class ZorkCursor {
+public:
+	ZorkCursor();
+	ZorkCursor(const Common::String &fileName);
+	ZorkCursor(ZVision *engine, const Common::String &fileName);
+	ZorkCursor(const ZorkCursor &other);
+	~ZorkCursor();
+
+private:
+	uint16 _width;
+	uint16 _height;
+	uint16 _hotspotX;
+	uint16 _hotspotY;
+	Graphics::Surface _surface;
+
+public:
+	ZorkCursor &operator=(const ZorkCursor &other);
+
+	uint16 getWidth() const {
+		return _width;
+	}
+	uint16 getHeight() const {
+		return _height;
+	}
+	uint16 getHotspotX() const {
+		return _hotspotX;
+	}
+	uint16 getHotspotY() const {
+		return _hotspotY;
+	}
+	byte getKeyColor() const {
+		return 0;
+	}
+	const byte *getSurface() const {
+		return (const byte *)_surface.getPixels();
+	}
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp
new file mode 100644
index 0000000000..a20deb26b5
--- /dev/null
+++ b/engines/zvision/graphics/cursors/cursor_manager.cpp
@@ -0,0 +1,152 @@
+/* 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.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/graphics/cursors/cursor_manager.h"
+
+#include "zvision/zvision.h"
+
+#include "common/system.h"
+
+#include "graphics/pixelformat.h"
+#include "graphics/cursorman.h"
+
+namespace ZVision {
+
+const char *CursorManager::_cursorNames[NUM_CURSORS] = { "active", "arrow", "backward", "downarrow", "forward", "handpt", "handpu", "hdown", "hleft",
+                                                         "hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow"
+                                                       };
+
+const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac001.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr",
+                                                                "g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr"
+                                                              };
+
+const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow", "back", "down", "forw", "handpt", "handpu", "hdown", "hleft",
+                                                                 "hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up"
+                                                               };
+
+CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat)
+	: _engine(engine),
+	  _pixelFormat(pixelFormat),
+	  _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(_engine, name); // Up cursor
+			name = Common::String::format("%sb.zcr", _zNemCursorFileNames[i]);
+			_cursors[i][1] = ZorkCursor(_engine, name); // Down cursor
+		} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+			_cursors[i][0] = ZorkCursor(_engine, _zgiCursorFileNames[i]); // Up cursor
+			char buffer[25];
+			strcpy(buffer, _zgiCursorFileNames[i]);
+			buffer[3] += 2;
+			_cursors[i][1] = ZorkCursor(_engine, buffer); // Down cursor
+		}
+	}
+}
+
+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(_engine, file);
+				file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b');
+				_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
+				file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'a');
+				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+				file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'b');
+				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+			} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+				file = Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id);
+				_cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
+				file = Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id);
+				_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
+				file = Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id);
+				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+				file = Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id);
+				_cursors[NUM_CURSORS + 1][1] = ZorkCursor(_engine, file);
+			} else
+				return;
+		}
+		_item = id;
+		changeCursor(CursorIndex_Idle);
+	}
+}
+
+void CursorManager::initialize() {
+	changeCursor(_cursors[CursorIndex_Idle][_cursorIsPushed]);
+	showMouse(true);
+}
+
+void CursorManager::changeCursor(const ZorkCursor &cursor) {
+	CursorMan.replaceCursor(cursor.getSurface(), cursor.getWidth(), cursor.getHeight(), cursor.getHotspotX(), cursor.getHotspotY(), cursor.getKeyColor(), false, _pixelFormat);
+}
+
+void CursorManager::cursorDown(bool pushed) {
+	if (_cursorIsPushed == pushed)
+		return;
+
+	_cursorIsPushed = pushed;
+
+	changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
+}
+
+void CursorManager::changeCursor(int id) {
+	int _id = id;
+
+	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]);
+	}
+}
+
+int CursorManager::getCursorId(const Common::String &name) {
+	for (int i = 0; i < NUM_CURSORS; i++)
+		if (name.equals(_cursorNames[i]))
+			return i;
+	return CursorIndex_Idle;
+}
+
+void CursorManager::showMouse(bool vis) {
+	CursorMan.showMouse(vis);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/cursors/cursor_manager.h b/engines/zvision/graphics/cursors/cursor_manager.h
new file mode 100644
index 0000000000..bbfa085c23
--- /dev/null
+++ b/engines/zvision/graphics/cursors/cursor_manager.h
@@ -0,0 +1,134 @@
+/* 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.
+ *
+ */
+
+#ifndef ZVISION_CURSOR_MANAGER_H
+#define ZVISION_CURSOR_MANAGER_H
+
+#include "zvision/graphics/cursors/cursor.h"
+
+#include "common/str.h"
+
+namespace Graphics {
+struct PixelFormat;
+}
+
+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
+ * or debug console.
+ * TODO: Figure out a way to get rid of the extraneous data copying due to having to use CursorMan
+ */
+class CursorManager {
+public:
+	CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat);
+
+private:
+	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;
+	bool _cursorIsPushed;
+	int _item;
+	int _lastitem;
+	int _currentCursor;
+
+	static const char *_cursorNames[];
+	static const char *_zgiCursorFileNames[];
+	static const char *_zNemCursorFileNames[];
+
+public:
+	/** Creates the idle cursor and shows it */
+	void initialize();
+
+	/**
+	 * 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 name    Cursor name
+	 * @return        Id of cursor or idle cursor id if not found
+	 */
+
+	int getCursorId(const Common::String &name);
+
+	/**
+	 * Load cursor for item by id, and try to change cursor to item cursor if it's not 0
+	 *
+	 * @param id    Item id or 0 for no item cursor
+	 */
+
+	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);
+
+	/**
+	 * Show or hide mouse cursor.
+	 *
+	 * @param vis    Should the cursor be showed (true) or hide (false)
+	 */
+	void showMouse(bool vis);
+
+private:
+	/**
+	 * Calls CursorMan.replaceCursor() using the data in cursor
+	 *
+	 * @param cursor    The cursor to show
+	 */
+	void changeCursor(const ZorkCursor &cursor);
+};
+
+} // End of namespace ZVision
+
+#endif
-- 
cgit v1.2.3