Initial commit
This commit is contained in:
241
engines/ultima/shared/engine/data_archive.cpp
Normal file
241
engines/ultima/shared/engine/data_archive.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/* 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 "ultima/shared/engine/data_archive.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/compression/unzip.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define DATA_FILENAME "ultima.dat"
|
||||
|
||||
class UltimaDataArchiveMember : public Common::ArchiveMember {
|
||||
private:
|
||||
Common::SharedPtr<Common::ArchiveMember> _member;
|
||||
Common::Path _publicFolder;
|
||||
Common::Path _innerfolder;
|
||||
public:
|
||||
UltimaDataArchiveMember(Common::SharedPtr<Common::ArchiveMember> member,
|
||||
const Common::Path &subfolder) :
|
||||
_member(member), _publicFolder("data/"), _innerfolder(subfolder) {
|
||||
}
|
||||
~UltimaDataArchiveMember() override {}
|
||||
Common::SeekableReadStream *createReadStream() const override {
|
||||
return _member->createReadStream();
|
||||
}
|
||||
Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
|
||||
return _member->createReadStreamForAltStream(altStreamType);
|
||||
}
|
||||
Common::Path getPathInArchive() const override {
|
||||
Common::Path name = _member->getPathInArchive();
|
||||
assert(name.isRelativeTo(_innerfolder));
|
||||
return _publicFolder.join(name.relativeTo(_innerfolder));
|
||||
}
|
||||
Common::U32String getDisplayName() const override {
|
||||
return _member->getDisplayName();
|
||||
}
|
||||
|
||||
Common::String getFileName() const override { return _member->getFileName(); }
|
||||
Common::String getName() const override { return getPathInArchive().toString('/'); }
|
||||
|
||||
bool isDirectory() const override { return _member->isDirectory(); }
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool UltimaDataArchive::load(const Common::Path &subfolder,
|
||||
int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg) {
|
||||
Common::Archive *dataArchive = nullptr;
|
||||
Common::File f;
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
Common::FSNode folder;
|
||||
if (ConfMan.hasKey("extrapath")) {
|
||||
if ((folder = Common::FSNode(ConfMan.getPath("extrapath"))).exists()
|
||||
&& (folder = folder.getChild("files")).exists()
|
||||
&& (folder = folder.getChild(subfolder.baseName())).exists()) {
|
||||
f.open(folder.getChild("version.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!f.isOpen()) {
|
||||
if (!Common::File::exists(DATA_FILENAME) ||
|
||||
(dataArchive = Common::makeZipArchive(DATA_FILENAME)) == 0 ||
|
||||
!f.open(subfolder.join("version.txt"), *dataArchive)) {
|
||||
delete dataArchive;
|
||||
errorMsg = Common::U32String::format(_("Could not locate engine data %s"), DATA_FILENAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the version
|
||||
char buffer[5];
|
||||
f.read(buffer, 4);
|
||||
buffer[4] = '\0';
|
||||
|
||||
int major = 0, minor = 0;
|
||||
if (buffer[1] == '.') {
|
||||
major = buffer[0] - '0';
|
||||
minor = atoi(&buffer[2]);
|
||||
}
|
||||
|
||||
if (major != reqMajorVersion || minor != reqMinorVersion) {
|
||||
delete dataArchive;
|
||||
errorMsg = Common::U32String::format(_("Out of date engine data. Expected %d.%d, but got version %d.%d"),
|
||||
reqMajorVersion, reqMinorVersion, major, minor);
|
||||
return false;
|
||||
}
|
||||
|
||||
// It was all validated correctly
|
||||
Common::Archive *archive;
|
||||
#ifndef RELEASE_BUILD
|
||||
if (!dataArchive)
|
||||
archive = new UltimaDataArchiveProxy(folder);
|
||||
else
|
||||
#endif
|
||||
archive = new UltimaDataArchive(dataArchive, subfolder);
|
||||
|
||||
SearchMan.add("data", archive);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool UltimaDataArchive::hasFile(const Common::Path &path) const {
|
||||
if (!path.isRelativeTo(_publicFolder))
|
||||
return false;
|
||||
|
||||
Common::Path realFilename = innerToPublic(path);
|
||||
return _zip->hasFile(realFilename);
|
||||
}
|
||||
|
||||
int UltimaDataArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
|
||||
Common::ArchiveMemberList innerList;
|
||||
int numMatches = 0;
|
||||
// Test whether we can skip filtering.
|
||||
bool matchAll = matchPathComponents && pattern == "*";
|
||||
|
||||
// First, get all zip members relevant to the current game
|
||||
_zip->listMatchingMembers(innerList, _innerfolder.appendComponent("*"), true);
|
||||
|
||||
// Modify the results to change the filename, then filter with pattern
|
||||
for (const auto &innerMember : innerList) {
|
||||
Common::ArchiveMemberPtr member = Common::ArchiveMemberPtr(
|
||||
new UltimaDataArchiveMember(innerMember, _innerfolder));
|
||||
if (matchAll || member->getPathInArchive().toString().matchString(pattern.toString(), true, matchPathComponents ? nullptr : "/")) {
|
||||
list.push_back(member);
|
||||
++numMatches;
|
||||
}
|
||||
}
|
||||
return numMatches;
|
||||
}
|
||||
|
||||
int UltimaDataArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
return listMatchingMembers(list, "*", true);
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr UltimaDataArchive::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *UltimaDataArchive::createReadStreamForMember(const Common::Path &path) const {
|
||||
if (hasFile(path)) {
|
||||
Common::Path filename = innerToPublic(path);
|
||||
return _zip->createReadStreamForMember(filename);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UltimaDataArchive::isPathDirectory(const Common::Path &path) const {
|
||||
return _zip->isPathDirectory(innerToPublic(path));
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
|
||||
const Common::ArchiveMemberPtr UltimaDataArchiveProxy::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *UltimaDataArchiveProxy::createReadStreamForMember(const Common::Path &path) const {
|
||||
if (hasFile(path))
|
||||
return getNode(path).createReadStream();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::FSNode UltimaDataArchiveProxy::getNode(const Common::Path &name) const {
|
||||
Common::Path remainingName = name.relativeTo(_publicFolder);
|
||||
Common::FSNode node = _folder;
|
||||
|
||||
Common::StringArray components = remainingName.splitComponents();
|
||||
|
||||
if (components.empty()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
for(Common::StringArray::const_iterator it = components.begin(); it != components.end() - 1; it++) {
|
||||
node = node.getChild(*it);
|
||||
if (!node.exists())
|
||||
return node;
|
||||
}
|
||||
|
||||
node = node.getChild(*(components.end() - 1));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int UltimaDataArchiveProxy::listMembers(Common::ArchiveMemberList &list) const {
|
||||
return listMatchingMembers(list, "*", true);
|
||||
}
|
||||
|
||||
int UltimaDataArchiveProxy::listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents) const {
|
||||
// Let FSDirectory adjust the filenames for us by using its prefix feature.
|
||||
// Note: dir is intentionally constructed again on each call to prevent stale entries due to caching:
|
||||
// Since this proxy class is intended for use during development, picking up modifications while the
|
||||
// game is running might be useful.
|
||||
const int maxDepth = 255; // chosen arbitrarily
|
||||
Common::FSDirectory dir(_publicFolder, _folder, maxDepth, false, false, true);
|
||||
if (matchPathComponents && pattern == "*")
|
||||
return dir.listMembers(list);
|
||||
else
|
||||
return dir.listMatchingMembers(list, pattern, matchPathComponents);
|
||||
}
|
||||
|
||||
bool UltimaDataArchiveProxy::isPathDirectory(const Common::Path &path) const {
|
||||
return getNode(path).isDirectory();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
183
engines/ultima/shared/engine/data_archive.h
Normal file
183
engines/ultima/shared/engine/data_archive.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_DATA_ARCHIVE_H
|
||||
#define ULTIMA_SHARED_ENGINE_DATA_ARCHIVE_H
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/path.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/**
|
||||
* The data archive class encapsulates access to a specific subfolder within
|
||||
* the ultima.dat data file for a game. It wraps up the subfolder so it can
|
||||
* be accessed in each game as a generic "data" subfolder. This allows the
|
||||
* individual games to simplify their data loading code.
|
||||
*/
|
||||
class UltimaDataArchive : public Common::Archive {
|
||||
private:
|
||||
Common::Archive *_zip;
|
||||
Common::Path _publicFolder;
|
||||
Common::Path _innerfolder;
|
||||
|
||||
|
||||
UltimaDataArchive(Common::Archive *zip, const Common::Path &subfolder) :
|
||||
_zip(zip), _publicFolder("data/"), _innerfolder(subfolder) {}
|
||||
|
||||
Common::Path innerToPublic(const Common::Path &filename) const {
|
||||
assert(filename.isRelativeTo(_publicFolder));
|
||||
return _innerfolder.join(filename.relativeTo(_publicFolder));
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Creates a data archive wrapper for the ultima.dat datafile.
|
||||
* Firstly, for debugging purposes, if a "files" folder exists on any path that
|
||||
* has the given subfolder, it will be used first. This will allow for setting
|
||||
* the ScummVM Extra Path to the create_ultima folder, and it will give preference
|
||||
* the files there. Otherwise, it checks for the presence of ultima.dat, and
|
||||
* if the required data is found, it returns the new archive.
|
||||
* Otherwise, returns an error message in the errorMsg field
|
||||
*/
|
||||
static bool load(const Common::Path &subfolder,
|
||||
int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg);
|
||||
public:
|
||||
~UltimaDataArchive() override {
|
||||
delete _zip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive matching the specified pattern to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of members added to list
|
||||
*/
|
||||
int listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents = false) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path)
|
||||
const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(
|
||||
const Common::Path &path) const override;
|
||||
|
||||
bool isPathDirectory(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
|
||||
/**
|
||||
* The data archive proxy class is used for debugging purposes to access engine data
|
||||
* files when the create_ultima folder is in the search path. It will allow for
|
||||
* local mucking around with the data files and committing changes without having to
|
||||
* recreate the ultima.dat file every time a change is made. ultima.dat then just has
|
||||
* to be recreated prior to a release or when the changes are completed and stable
|
||||
*/
|
||||
class UltimaDataArchiveProxy : public Common::Archive {
|
||||
friend class UltimaDataArchive;
|
||||
private:
|
||||
Common::FSNode _folder;
|
||||
const Common::Path _publicFolder;
|
||||
|
||||
UltimaDataArchiveProxy(const Common::FSNode &folder) : _folder(folder), _publicFolder("data/") {}
|
||||
|
||||
/**
|
||||
* Gets a file node from the passed filename
|
||||
*/
|
||||
Common::FSNode getNode(const Common::Path &name) const;
|
||||
public:
|
||||
~UltimaDataArchiveProxy() override {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override {
|
||||
return path.isRelativeTo(_publicFolder) && getNode(path).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all members of the Archive matching the specified pattern to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of members added to list
|
||||
*/
|
||||
int listMatchingMembers(Common::ArchiveMemberList &list,
|
||||
const Common::Path &pattern, bool matchPathComponents = false) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path)
|
||||
const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(
|
||||
const Common::Path &path) const override;
|
||||
|
||||
bool isPathDirectory(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
255
engines/ultima/shared/engine/events.cpp
Normal file
255
engines/ultima/shared/engine/events.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/* 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 "common/scummsys.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "common/events.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/system.h"
|
||||
#include "engines/util.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
EventsManager::EventsManager(EventsCallback *callback) : _callback(callback), _playTime(0),
|
||||
_gameCounter(0), _frameCounter(0), _priorFrameCounterTime(0), _buttonsDown(0),
|
||||
_specialButtons(0), _priorFrameTime(0) {
|
||||
}
|
||||
|
||||
void EventsManager::showCursor() {
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void EventsManager::hideCursor() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
bool EventsManager::isCursorVisible() {
|
||||
return CursorMan.isVisible();
|
||||
}
|
||||
|
||||
bool EventsManager::pollEvent(Common::Event &event) {
|
||||
uint32 timer = g_system->getMillis();
|
||||
|
||||
if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) {
|
||||
// Time to build up next game frame
|
||||
_priorFrameCounterTime = timer;
|
||||
nextFrame();
|
||||
}
|
||||
|
||||
// Event handling
|
||||
if (g_system->getEventManager()->pollEvent(event)) {
|
||||
if (isMouseDownEvent(event.type)) {
|
||||
setButtonDown(whichButton(event.type), true);
|
||||
_mousePos = event.mouse;
|
||||
} else if (isMouseUpEvent(event.type)) {
|
||||
setButtonDown(whichButton(event.type), false);
|
||||
_mousePos = event.mouse;
|
||||
} else if (event.type == Common::EVENT_MOUSEMOVE) {
|
||||
_mousePos = event.mouse;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYDOWN: {
|
||||
handleKbdSpecial(event.kbd);
|
||||
break;
|
||||
}
|
||||
case Common::EVENT_KEYUP:
|
||||
handleKbdSpecial(event.kbd);
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_mousePos = event.mouse;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventsManager::pollEvents() {
|
||||
Common::Event event;
|
||||
|
||||
while (pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
eventTarget()->mouseMove(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
eventTarget()->leftButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
eventTarget()->leftButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_MBUTTONDOWN:
|
||||
eventTarget()->middleButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_MBUTTONUP:
|
||||
eventTarget()->middleButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
eventTarget()->rightButtonDown(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
eventTarget()->rightButtonUp(_mousePos);
|
||||
break;
|
||||
case Common::EVENT_WHEELUP:
|
||||
case Common::EVENT_WHEELDOWN:
|
||||
eventTarget()->mouseWheel(_mousePos, event.type == Common::EVENT_WHEELUP);
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
eventTarget()->keyDown(event.kbd);
|
||||
break;
|
||||
case Common::EVENT_KEYUP:
|
||||
eventTarget()->keyUp(event.kbd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::pollEventsAndWait() {
|
||||
pollEvents();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
void EventsManager::nextFrame() {
|
||||
++_frameCounter;
|
||||
++_playTime;
|
||||
|
||||
// Handle any idle updates
|
||||
if (!_eventTargets.empty())
|
||||
eventTarget()->onIdle();
|
||||
|
||||
// Render anything pending for the screen
|
||||
Graphics::Screen *screen = _callback->getScreen();
|
||||
if (screen)
|
||||
screen->update();
|
||||
}
|
||||
|
||||
void EventsManager::setButtonDown(MouseButton button, bool isDown) {
|
||||
assert(button != BUTTON_NONE);
|
||||
|
||||
byte mask = 0;
|
||||
switch (button) {
|
||||
case BUTTON_LEFT:
|
||||
mask = MK_LBUTTON;
|
||||
break;
|
||||
case BUTTON_RIGHT:
|
||||
mask = MK_RBUTTON;
|
||||
break;
|
||||
case BUTTON_MIDDLE:
|
||||
mask = MK_MBUTTON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isDown) {
|
||||
_buttonsDown |= BUTTON_MASK(button);
|
||||
_specialButtons |= mask;
|
||||
} else {
|
||||
_buttonsDown &= ~BUTTON_MASK(button);
|
||||
_specialButtons &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 EventsManager::getTicksCount() const {
|
||||
return _frameCounter * GAME_FRAME_TIME;
|
||||
}
|
||||
|
||||
void EventsManager::sleep(uint time) {
|
||||
uint32 delayEnd = g_system->getMillis() + time;
|
||||
|
||||
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd)
|
||||
pollEventsAndWait();
|
||||
}
|
||||
|
||||
bool EventsManager::waitForPress(uint expiry) {
|
||||
uint32 delayEnd = g_system->getMillis() + expiry;
|
||||
CPressTarget pressTarget;
|
||||
addTarget(&pressTarget);
|
||||
|
||||
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd && !pressTarget._pressed) {
|
||||
pollEventsAndWait();
|
||||
}
|
||||
|
||||
removeTarget();
|
||||
return pressTarget._pressed;
|
||||
}
|
||||
|
||||
void EventsManager::setMousePos(const Point &pt) {
|
||||
g_system->warpMouse(pt.x, pt.y);
|
||||
_mousePos = pt;
|
||||
eventTarget()->mouseMove(_mousePos);
|
||||
}
|
||||
|
||||
void EventsManager::handleKbdSpecial(Common::KeyState keyState) {
|
||||
if (keyState.flags & Common::KBD_CTRL)
|
||||
_specialButtons |= MK_CONTROL;
|
||||
else
|
||||
_specialButtons &= ~MK_CONTROL;
|
||||
|
||||
if (keyState.flags & Common::KBD_SHIFT)
|
||||
_specialButtons |= MK_SHIFT;
|
||||
else
|
||||
_specialButtons &= ~MK_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
bool shouldQuit() {
|
||||
return g_engine->shouldQuit();
|
||||
}
|
||||
|
||||
bool isMouseDownEvent(Common::EventType type) {
|
||||
return type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_RBUTTONDOWN
|
||||
|| type == Common::EVENT_MBUTTONDOWN;
|
||||
}
|
||||
|
||||
bool isMouseUpEvent(Common::EventType type) {
|
||||
return type == Common::EVENT_LBUTTONUP || type == Common::EVENT_RBUTTONUP
|
||||
|| type == Common::EVENT_MBUTTONUP;
|
||||
}
|
||||
|
||||
MouseButton whichButton(Common::EventType type) {
|
||||
if (type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_LBUTTONUP)
|
||||
return BUTTON_LEFT;
|
||||
else if (type == Common::EVENT_RBUTTONDOWN || type == Common::EVENT_RBUTTONUP)
|
||||
return BUTTON_RIGHT;
|
||||
else if (type == Common::EVENT_MBUTTONDOWN || type == Common::EVENT_MBUTTONUP)
|
||||
return BUTTON_MIDDLE;
|
||||
else
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
338
engines/ultima/shared/engine/events.h
Normal file
338
engines/ultima/shared/engine/events.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_EVENTS_H
|
||||
#define ULTIMA_SHARED_ENGINE_EVENTS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/events.h"
|
||||
#include "common/stack.h"
|
||||
#include "gui/debugger.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
#define GAME_FRAME_RATE (1000 / 50)
|
||||
#define GAME_FRAME_TIME 50
|
||||
#define SCREEN_UPDATE_TIME 10
|
||||
#define BUTTON_MASK(MB) (1 << ((int)(MB) - 1))
|
||||
#define DOUBLE_CLICK_TIME 100
|
||||
|
||||
enum MouseButton {
|
||||
BUTTON_NONE = 0,
|
||||
BUTTON_LEFT = 1,
|
||||
BUTTON_RIGHT = 2,
|
||||
BUTTON_MIDDLE = 3,
|
||||
MOUSE_LAST
|
||||
};
|
||||
|
||||
enum SpecialButtons {
|
||||
MK_LBUTTON = 1, MK_RBUTTON = 2, MK_MBUTTON = 4, MK_SHIFT = 8, MK_CONTROL = 0x10
|
||||
};
|
||||
|
||||
/**
|
||||
* A base class for windows that can receive event messages
|
||||
*/
|
||||
class EventTarget {
|
||||
public:
|
||||
virtual ~EventTarget() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to handle any regular updates the game requires
|
||||
*/
|
||||
virtual void onIdle() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse/key event handlers
|
||||
*/
|
||||
virtual void mouseMove(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void leftButtonDoubleClick(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void middleButtonDoubleClick(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void rightButtonDown(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void rightButtonUp(const Common::Point &mousePos) {
|
||||
}
|
||||
virtual void mouseWheel(const Common::Point &mousePos, bool wheelUp) {
|
||||
}
|
||||
virtual void keyDown(Common::KeyState keyState) {
|
||||
}
|
||||
virtual void keyUp(Common::KeyState keyState) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An eent target used for waiting for a mouse or keypress
|
||||
*/
|
||||
class CPressTarget : public EventTarget {
|
||||
public:
|
||||
bool _pressed;
|
||||
public:
|
||||
CPressTarget() : _pressed(false) {
|
||||
}
|
||||
~CPressTarget() override {
|
||||
}
|
||||
void leftButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void middleButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void rightButtonDown(const Common::Point &mousePos) override {
|
||||
_pressed = true;
|
||||
}
|
||||
void keyDown(Common::KeyState keyState) override {
|
||||
_pressed = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract interface for engine functionality the events manager needs to access
|
||||
*/
|
||||
class EventsCallback {
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~EventsCallback() {}
|
||||
|
||||
/**
|
||||
* Get the screen
|
||||
*/
|
||||
virtual Graphics::Screen *getScreen() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class EventsManager {
|
||||
private:
|
||||
EventsCallback *_callback;
|
||||
Common::Stack<EventTarget *> _eventTargets;
|
||||
uint32 _frameCounter;
|
||||
uint32 _priorFrameTime;
|
||||
uint32 _priorFrameCounterTime;
|
||||
uint32 _gameCounter;
|
||||
uint32 _playTime;
|
||||
Point _mousePos;
|
||||
uint _specialButtons;
|
||||
uint8 _buttonsDown;
|
||||
|
||||
/**
|
||||
* Check whether it's time to display the next screen frame
|
||||
*/
|
||||
bool checkForNextFrameCounter();
|
||||
|
||||
/**
|
||||
* Return the currently active event target
|
||||
*/
|
||||
EventTarget *eventTarget() const {
|
||||
return _eventTargets.top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles setting/resettings special buttons on key up/down
|
||||
*/
|
||||
void handleKbdSpecial(Common::KeyState keyState);
|
||||
|
||||
/**
|
||||
* Sets whether a given button is depressed
|
||||
*/
|
||||
void setButtonDown(MouseButton button, bool isDown);
|
||||
protected:
|
||||
/**
|
||||
* Handles moving to the next game frame
|
||||
*/
|
||||
virtual void nextFrame();
|
||||
public:
|
||||
EventsManager(EventsCallback *callback);
|
||||
virtual ~EventsManager() {}
|
||||
|
||||
/**
|
||||
* Adds a new event target to the top of the list. It will get
|
||||
* all events generated until such time as another is pushed on
|
||||
* top of it, or the removeTarget method is called
|
||||
*/
|
||||
void addTarget(EventTarget *target) {
|
||||
_eventTargets.push(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the currently active event target
|
||||
*/
|
||||
void removeTarget() {
|
||||
_eventTargets.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the ScummVM backend for any pending events, passing out the event, if any
|
||||
*/
|
||||
|
||||
virtual bool pollEvent(Common::Event &event);
|
||||
|
||||
/**
|
||||
* Checks for any pending events. This differs from pollEvent, in that the event manager will dispatch
|
||||
* all pending events to the currently registered active event target, rather than simply returning a
|
||||
* single event like pollEvent does
|
||||
*/
|
||||
void pollEvents();
|
||||
|
||||
/**
|
||||
* Poll for events and introduce a small delay, to allow the system to
|
||||
* yield to other running programs
|
||||
*/
|
||||
void pollEventsAndWait();
|
||||
|
||||
/**
|
||||
* Return the current game frame number
|
||||
*/
|
||||
uint32 getFrameCounter() const {
|
||||
return _frameCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the elapsed playtime
|
||||
*/
|
||||
uint32 getTicksCount() const;
|
||||
|
||||
/**
|
||||
* Sleep for a specified period of time
|
||||
*/
|
||||
void sleep(uint time);
|
||||
|
||||
/**
|
||||
* Wait for a mouse or keypress
|
||||
*/
|
||||
bool waitForPress(uint expiry);
|
||||
|
||||
/**
|
||||
* Sets the mouse position
|
||||
*/
|
||||
void setMousePos(const Point &pt);
|
||||
|
||||
/*
|
||||
* Return whether a given special key is currently pressed
|
||||
*/
|
||||
bool isSpecialPressed(SpecialButtons btn) const {
|
||||
return (_specialButtons & btn) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bitset of the currently pressed special buttons
|
||||
*/
|
||||
uint getSpecialButtons() const {
|
||||
return _specialButtons;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the cursor
|
||||
*/
|
||||
virtual void setCursor(int cursorId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the mouse cursor
|
||||
*/
|
||||
void showCursor();
|
||||
|
||||
/**
|
||||
* Hide the mouse cursor
|
||||
*/
|
||||
void hideCursor();
|
||||
|
||||
/**
|
||||
* Returns if the mouse cursor is visible
|
||||
*/
|
||||
bool isCursorVisible();
|
||||
|
||||
/**
|
||||
* Gets the current total ticks
|
||||
*/
|
||||
uint32 getTicks() {
|
||||
return _frameCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total overall play time
|
||||
*/
|
||||
uint32 playTime() const {
|
||||
return _playTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current play time
|
||||
*/
|
||||
void setPlayTime(uint32 time) {
|
||||
_playTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given mouse button is pressed
|
||||
*/
|
||||
inline bool isButtonDown(MouseButton button) const {
|
||||
return (_buttonsDown & BUTTON_MASK(button)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any mouse button is pressed
|
||||
*/
|
||||
bool isButtonDown() const {
|
||||
return isButtonDown(BUTTON_LEFT) || isButtonDown(BUTTON_RIGHT) || isButtonDown(BUTTON_MIDDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mouse buttons states
|
||||
*/
|
||||
byte getButtonState() const {
|
||||
return _buttonsDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mouse position
|
||||
*/
|
||||
Common::Point getMousePos() const {
|
||||
return _mousePos;
|
||||
}
|
||||
};
|
||||
|
||||
extern bool isMouseDownEvent(Common::EventType type);
|
||||
|
||||
extern bool isMouseUpEvent(Common::EventType type);
|
||||
|
||||
extern MouseButton whichButton(Common::EventType type);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
118
engines/ultima/shared/engine/input_handler.cpp
Normal file
118
engines/ultima/shared/engine/input_handler.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 "ultima/shared/engine/input_handler.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
InputHandler::InputHandler(GameBase *game) : _game(game), _inputTranslator(nullptr), _dragging(false),
|
||||
_buttonDown(false), _lockCount(0), _abortMessage(false) {
|
||||
}
|
||||
|
||||
InputHandler::~InputHandler() {
|
||||
}
|
||||
|
||||
void InputHandler::setTranslator(InputTranslator *translator) {
|
||||
_inputTranslator = translator;
|
||||
}
|
||||
|
||||
void InputHandler::incLockCount() {
|
||||
++_lockCount;
|
||||
}
|
||||
|
||||
void InputHandler::decLockCount() {
|
||||
--_lockCount;
|
||||
assert(_lockCount >= 0);
|
||||
|
||||
if (_lockCount == 0 && _inputTranslator) {
|
||||
if (_dragging && !_inputTranslator->isMousePressed()) {
|
||||
CMouseButtonUpMsg upMsg(_mousePos, MK_LBUTTON);
|
||||
handleMessage(upMsg);
|
||||
}
|
||||
|
||||
_buttonDown = _inputTranslator->isMousePressed();
|
||||
_abortMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::handleMessage(CMessage &msg, bool respectLock) {
|
||||
if (!respectLock || _lockCount <= 0) {
|
||||
processMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::processMessage(CMessage *msg) {
|
||||
const CMouseMsg *mouseMsg = dynamic_cast<const CMouseMsg *>(msg);
|
||||
_abortMessage = false;
|
||||
dispatchMessage(msg);
|
||||
|
||||
if (_abortMessage) {
|
||||
_abortMessage = false;
|
||||
} else if (mouseMsg) {
|
||||
// Keep the game state mouse position up to date
|
||||
if (_mousePos != mouseMsg->_mousePos) {
|
||||
_mousePos = mouseMsg->_mousePos;
|
||||
}
|
||||
|
||||
// Set flag for whether a mouse button is currently being pressed
|
||||
if (mouseMsg->isButtonDownMsg())
|
||||
_buttonDown = true;
|
||||
else if (mouseMsg->isButtonUpMsg())
|
||||
_buttonDown = false;
|
||||
|
||||
// Drag events generation
|
||||
if (_dragging) {
|
||||
if (mouseMsg->isMouseMoveMsg()) {
|
||||
CMouseDragMsg moveMsg(_mousePos, mouseMsg->_buttons);
|
||||
dispatchMessage(&moveMsg);
|
||||
} else if (mouseMsg->isButtonUpMsg()) {
|
||||
_dragging = false;
|
||||
}
|
||||
} else if (_buttonDown) {
|
||||
if (!mouseMsg->isMouseMoveMsg()) {
|
||||
// Save where the drag movement started from
|
||||
_dragStartPos = _mousePos;
|
||||
} else {
|
||||
Point delta = _mousePos - _dragStartPos;
|
||||
int distance = (int)sqrt(double(delta.x * delta.x + delta.y * delta.y));
|
||||
|
||||
if (distance > 4) {
|
||||
// A drag has started
|
||||
_dragging = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler::dispatchMessage(CMessage *msg) {
|
||||
Gfx::VisualItem *view = _game->getView();
|
||||
if (view)
|
||||
msg->execute(view);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
78
engines/ultima/shared/engine/input_handler.h
Normal file
78
engines/ultima/shared/engine/input_handler.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_INPUT_HANDLER_H
|
||||
#define ULTIMA_SHARED_ENGINE_INPUT_HANDLER_H
|
||||
|
||||
#include "ultima/shared/engine/input_translator.h"
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class GameBase;
|
||||
|
||||
class InputHandler {
|
||||
private:
|
||||
/**
|
||||
* Process and dispatch a passed message
|
||||
*/
|
||||
void processMessage(CMessage *msg);
|
||||
|
||||
/**
|
||||
* Dispatches a message to the project
|
||||
*/
|
||||
void dispatchMessage(CMessage *msg);
|
||||
public:
|
||||
GameBase *_game;
|
||||
InputTranslator *_inputTranslator;
|
||||
bool _dragging;
|
||||
bool _buttonDown;
|
||||
Point _mousePos;
|
||||
Point _dragStartPos;
|
||||
int _lockCount;
|
||||
bool _abortMessage;
|
||||
public:
|
||||
InputHandler(GameBase *game);
|
||||
~InputHandler();
|
||||
|
||||
void setTranslator(InputTranslator *translator);
|
||||
|
||||
/**
|
||||
* Increment the lock count
|
||||
*/
|
||||
void incLockCount();
|
||||
|
||||
/**
|
||||
* Decrement the lock count on the input handler
|
||||
*/
|
||||
void decLockCount();
|
||||
|
||||
/**
|
||||
* Handles a genereated mouse message
|
||||
*/
|
||||
void handleMessage(CMessage &msg, bool respectLock = true);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
123
engines/ultima/shared/engine/input_translator.cpp
Normal file
123
engines/ultima/shared/engine/input_translator.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/* 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 "ultima/shared/engine/input_handler.h"
|
||||
#include "ultima/shared/engine/input_translator.h"
|
||||
#include "ultima/shared/engine/events.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
InputTranslator::InputTranslator(InputHandler *inputHandler) :
|
||||
_inputHandler(inputHandler) {
|
||||
inputHandler->setTranslator(this);
|
||||
}
|
||||
|
||||
int InputTranslator::getButtons(int special) const {
|
||||
int buttons = 0;
|
||||
if (special & MK_LBUTTON)
|
||||
buttons |= MB_LEFT;
|
||||
if (special & MK_MBUTTON)
|
||||
buttons |= MB_MIDDLE;
|
||||
if (special & MK_RBUTTON)
|
||||
buttons |= MB_RIGHT;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
void InputTranslator::mouseMove(int special, const Point &pt) {
|
||||
CMouseMoveMsg msg(pt, getButtons(special));
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::mouseDrag(int special, const Point &pt) {
|
||||
CMouseDragMsg msg(pt, getButtons(special));
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::leftButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_LEFT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::middleButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_MIDDLE);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonDown(int special, const Point &pt) {
|
||||
CMouseButtonDownMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonUp(int special, const Point &pt) {
|
||||
CMouseButtonUpMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::mouseWheel(bool wheelUp, const Point &pt) {
|
||||
CMouseWheelMsg msg(pt, wheelUp);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::rightButtonDoubleClick(int special, const Point &pt) {
|
||||
CMouseDoubleClickMsg msg(pt, MB_RIGHT);
|
||||
_inputHandler->handleMessage(msg);
|
||||
}
|
||||
|
||||
void InputTranslator::keyDown(const Common::KeyState &keyState) {
|
||||
CKeypressMsg pressMsg(keyState);
|
||||
_inputHandler->handleMessage(pressMsg);
|
||||
|
||||
if (keyState.ascii >= 32 && keyState.ascii <= 127) {
|
||||
CKeyCharMsg charMsg(keyState.ascii);
|
||||
_inputHandler->handleMessage(charMsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputTranslator::isMousePressed() const {
|
||||
return g_vm->_events->getSpecialButtons() & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON);
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
67
engines/ultima/shared/engine/input_translator.h
Normal file
67
engines/ultima/shared/engine/input_translator.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_INPUT_TRANSLATOR_H
|
||||
#define ULTIMA_SHARED_ENGINE_INPUT_TRANSLATOR_H
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class InputHandler;
|
||||
|
||||
class InputTranslator {
|
||||
private:
|
||||
/**
|
||||
* Converts the special buttons bitset into a buttons bitset
|
||||
*/
|
||||
int getButtons(int special) const;
|
||||
public:
|
||||
InputHandler *_inputHandler;
|
||||
public:
|
||||
InputTranslator(InputHandler *inputHandler);
|
||||
|
||||
void mouseMove(int special, const Point &pt);
|
||||
void mouseDrag(int special, const Point &pt);
|
||||
void leftButtonDown(int special, const Point &pt);
|
||||
void leftButtonUp(int special, const Point &pt);
|
||||
void leftButtonDoubleClick(int special, const Point &pt);
|
||||
void middleButtonDown(int special, const Point &pt);
|
||||
void middleButtonUp(int special, const Point &pt);
|
||||
void middleButtonDoubleClick(int special, const Point &pt);
|
||||
void rightButtonDown(int special, const Point &pt);
|
||||
void rightButtonUp(int special, const Point &pt);
|
||||
void mouseWheel(bool wheelUp, const Point &pt);
|
||||
void rightButtonDoubleClick(int special, const Point &pt);
|
||||
void keyDown(const Common::KeyState &keyState);
|
||||
|
||||
/**
|
||||
* Returns true if any mouse button is currently pressed
|
||||
*/
|
||||
bool isMousePressed() const;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
121
engines/ultima/shared/engine/messages.cpp
Normal file
121
engines/ultima/shared/engine/messages.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/* 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 "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/early/ultima_early.h"
|
||||
#include "ultima/shared/early/game_base.h"
|
||||
#include "ultima/shared/gfx/screen.h"
|
||||
#include "ultima/shared/early/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
CMessage::CMessage() : BaseObject() {
|
||||
}
|
||||
|
||||
bool CMessage::execute(TreeItem *target, const ClassDef *classDef, int flags) {
|
||||
// If no target was specified, then there's nothing to do
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
TreeItem *item = target;
|
||||
TreeItem *nextItem = nullptr;
|
||||
do {
|
||||
if (flags & MSGFLAG_SCAN)
|
||||
nextItem = item->scan(target);
|
||||
|
||||
if (!classDef || item->isInstanceOf(*classDef)) {
|
||||
bool handled = perform(item);
|
||||
|
||||
if (handled) {
|
||||
result = true;
|
||||
if (flags & MSGFLAG_BREAK_IF_HANDLED)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
item = nextItem;
|
||||
} while (nextItem);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMessage::execute(const Common::String &target, const ClassDef *classDef, int flags) {
|
||||
// Scan for the target by name
|
||||
GameBase *game = g_vm->_game;
|
||||
for (TreeItem *treeItem = game; treeItem; treeItem = treeItem->scan(game)) {
|
||||
if (!treeItem->getName().compareToIgnoreCase(target))
|
||||
return execute(treeItem, classDef, flags);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const MSGMAP_ENTRY *CMessage::findMapEntry(const TreeItem *treeItem, const ClassDef &classDef) {
|
||||
// Iterate through the class and any parent classes
|
||||
for (const MSGMAP *msgMap = treeItem->getMessageMap(); msgMap->pFnGetBaseMap;
|
||||
msgMap = msgMap->pFnGetBaseMap()) {
|
||||
// Iterate through the map entries for this class
|
||||
for (const MSGMAP_ENTRY *entry = msgMap->lpEntries;
|
||||
entry->_classDef != nullptr; ++entry) {
|
||||
// Check if the class or any of it's ancesotrs is handled by this entry
|
||||
for (ClassDef def = (*entry->_classDef)(); def.hasParent(); def = def.parent()) {
|
||||
if (def == classDef)
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::perform(TreeItem *treeItem) {
|
||||
const MSGMAP_ENTRY *entry = findMapEntry(treeItem, getType());
|
||||
return entry && (*treeItem.*(entry->_fn))(this);
|
||||
}
|
||||
|
||||
bool CMessage::supports(const TreeItem *treeItem, const ClassDef &classDef) {
|
||||
return findMapEntry(treeItem, classDef) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isMouseMsg() const {
|
||||
return dynamic_cast<const CMouseMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isButtonDownMsg() const {
|
||||
return dynamic_cast<const CMouseButtonDownMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isButtonUpMsg() const {
|
||||
return dynamic_cast<const CMouseButtonUpMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isMouseMoveMsg() const {
|
||||
return dynamic_cast<const CMouseMoveMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
bool CMessage::isDoubleClickMsg() const {
|
||||
return dynamic_cast<const CMouseDoubleClickMsg *>(this) != nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
407
engines/ultima/shared/engine/messages.h
Normal file
407
engines/ultima/shared/engine/messages.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_MESSAGES_H
|
||||
#define ULTIMA_SHARED_ENGINE_MESSAGES_H
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "common/events.h"
|
||||
#include "ultima/shared/core/rect.h"
|
||||
#include "ultima/shared/core/base_object.h"
|
||||
#include "ultima/shared/core/tree_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
enum MessageFlag {
|
||||
MSGFLAG_SCAN = 1,
|
||||
MSGFLAG_BREAK_IF_HANDLED = 2,
|
||||
MSGFLAG_CLASS_DEF = 4
|
||||
};
|
||||
|
||||
class CMessage;
|
||||
namespace Gfx {
|
||||
class VisualItem;
|
||||
class TextInput;
|
||||
class Popup;
|
||||
}
|
||||
|
||||
#define MESSAGEDEF(theClass) \
|
||||
static ClassDef type() { return ClassDef(#theClass, &CMessage::type); } \
|
||||
virtual ClassDef getType() const { return type(); }
|
||||
#define MESSAGEDEFP(theClass, baseClass) \
|
||||
static ClassDef type() { return ClassDef(#theClass, &baseClass::type); } \
|
||||
virtual ClassDef getType() const { return type(); }
|
||||
|
||||
#define MESSAGE0(NAME) \
|
||||
class NAME: public CMessage { \
|
||||
public: NAME() : CMessage() {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE1(NAME, F1, N1, V1) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; \
|
||||
NAME(F1 N1 = V1) : CMessage(), _##N1(N1) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE2(NAME, F1, N1, V1, F2, N2, V2) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2) : CMessage(), _##N1(N1), _##N2(N2) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE3(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; F3 _##N3; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2, F3 N3 = V3) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
#define MESSAGE4(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3, F4, N4, V4) \
|
||||
class NAME: public CMessage { \
|
||||
public: F1 _##N1; F2 _##N2; F3 _##N3; F4 _##N4; \
|
||||
NAME(F1 N1 = V1, F2 N2 = V2, F3 N3 = V3, F4 N4 = V4) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3), _##N4(N4) {} \
|
||||
MESSAGEDEF(NAME); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for all messages
|
||||
*/
|
||||
class CMessage : public BaseObject {
|
||||
private:
|
||||
/**
|
||||
* Find a map entry that supports the given class
|
||||
*/
|
||||
static const MSGMAP_ENTRY *findMapEntry(const TreeItem *treeItem, const ClassDef &classDef);
|
||||
public:
|
||||
MESSAGEDEFP(CMessage, BaseObject);
|
||||
CMessage();
|
||||
|
||||
/**
|
||||
* Executes the message, passing it on to the designated target,
|
||||
* and optionally it's children
|
||||
*/
|
||||
bool execute(TreeItem *target, const ClassDef *classDef = nullptr,
|
||||
int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED);
|
||||
|
||||
/**
|
||||
* Executes the message, passing it on to the designated target,
|
||||
* and optionally it's children
|
||||
*/
|
||||
bool execute(const Common::String &target, const ClassDef *classDef = nullptr,
|
||||
int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED);
|
||||
|
||||
/**
|
||||
* Makes the passed item execute the message
|
||||
*/
|
||||
virtual bool perform(TreeItem *treeItem);
|
||||
|
||||
/**
|
||||
* Returns true if the passed item supports the specified message class
|
||||
*/
|
||||
static bool supports(const TreeItem *treeItem, const ClassDef &classDef);
|
||||
|
||||
virtual bool isMouseMsg() const;
|
||||
virtual bool isButtonDownMsg() const;
|
||||
virtual bool isButtonUpMsg() const;
|
||||
virtual bool isMouseMoveMsg() const;
|
||||
virtual bool isDoubleClickMsg() const;
|
||||
};
|
||||
|
||||
|
||||
enum CMouseButton {
|
||||
MB_LEFT = 1, MB_MIDDLE = 2, MB_RIGHT = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for the different mouse notifications
|
||||
*/
|
||||
class CMouseMsg : public CMessage {
|
||||
public:
|
||||
int _buttons;
|
||||
Point _mousePos;
|
||||
public:
|
||||
MESSAGEDEF(CMouseMsg);
|
||||
|
||||
CMouseMsg() : _buttons(0) {}
|
||||
CMouseMsg(const Point &pt, int buttons) :
|
||||
_mousePos(pt), _buttons(buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse movement
|
||||
*
|
||||
*/
|
||||
class CMouseMoveMsg : public CMouseMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseMoveMsg, CMouseMsg);
|
||||
CMouseMoveMsg() : CMouseMsg() {}
|
||||
CMouseMoveMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies of a mouse drag operation
|
||||
*/
|
||||
class CMouseDragMsg : public CMouseMoveMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseDragMsg, CMouseMoveMsg);
|
||||
CMouseDragMsg() : CMouseMoveMsg() {}
|
||||
CMouseDragMsg(const Point &pt, int buttons) : CMouseMoveMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for mouse button notifications
|
||||
*/
|
||||
class CMouseButtonMsg : public CMouseMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonMsg, CMouseMsg);
|
||||
CMouseButtonMsg() : CMouseMsg() {}
|
||||
CMouseButtonMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse button down
|
||||
*/
|
||||
class CMouseButtonDownMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonDownMsg, CMouseButtonMsg);
|
||||
CMouseButtonDownMsg() : CMouseButtonMsg() {}
|
||||
CMouseButtonDownMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse button release
|
||||
*/
|
||||
class CMouseButtonUpMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseButtonUpMsg, CMouseButtonMsg);
|
||||
CMouseButtonUpMsg() : CMouseButtonMsg() {}
|
||||
CMouseButtonUpMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse wheel action
|
||||
*/
|
||||
class CMouseWheelMsg : public CMouseMsg {
|
||||
public:
|
||||
bool _wheelUp;
|
||||
public:
|
||||
MESSAGEDEFP(CMouseWheelMsg, CMouseMsg);
|
||||
CMouseWheelMsg() : CMouseMsg(), _wheelUp(false) {}
|
||||
CMouseWheelMsg(const Point &pt, bool wheelUp) :
|
||||
CMouseMsg(pt, 0), _wheelUp(wheelUp) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a mouse double-click
|
||||
*/
|
||||
class CMouseDoubleClickMsg : public CMouseButtonMsg {
|
||||
public:
|
||||
MESSAGEDEFP(CMouseDuobleClickMsg, CMouseButtonMsg);
|
||||
CMouseDoubleClickMsg() : CMouseButtonMsg() {}
|
||||
CMouseDoubleClickMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to notify that a rendering frame has finished, occurring at GAME_FRAME_RATE times every second
|
||||
*/
|
||||
MESSAGE1(CFrameMsg, uint, ticks, 0);
|
||||
|
||||
/**
|
||||
* Notifies a game view is being hidden
|
||||
*/
|
||||
MESSAGE2(CHideMsg, Gfx::VisualItem *, view, (Gfx::VisualItem *)nullptr, bool, fadeOut, false);
|
||||
|
||||
/**
|
||||
* Show a prompt in the info area, and get a keypress for a command
|
||||
*/
|
||||
MESSAGE1(CInfoGetCommandKeypress, TreeItem *, responder, (TreeItem *)nullptr);
|
||||
|
||||
/**
|
||||
* Get a keypress in the info area
|
||||
*/
|
||||
MESSAGE1(CInfoGetKeypress, TreeItem *, responder, (TreeItem *)nullptr);
|
||||
|
||||
/**
|
||||
* Get a text input in the input area
|
||||
*/
|
||||
MESSAGE3(CInfoGetInput, TreeItem *, responder, (TreeItem *)nullptr, bool, isNumeric, false, size_t, maxCharacters, 10);
|
||||
|
||||
/**
|
||||
* Adds text strings to the info area
|
||||
*/
|
||||
MESSAGE3(CInfoMsg, Common::String, text, "", bool, newLine, true, bool, replaceLine, false);
|
||||
|
||||
/**
|
||||
* Signals an unknown/unhandled keypress
|
||||
*/
|
||||
MESSAGE0(CHuhMsg);
|
||||
|
||||
/**
|
||||
* Signals a single standard ASCII keypress
|
||||
*/
|
||||
MESSAGE1(CKeyCharMsg, int, key, 32);
|
||||
|
||||
/**
|
||||
* Signals a keypress
|
||||
*/
|
||||
MESSAGE1(CKeypressMsg, Common::KeyState, keyState, Common::KeyState());
|
||||
|
||||
/**
|
||||
* Called when a popup is finally shown
|
||||
*/
|
||||
MESSAGE1(CPopupShownMsg, Gfx::Popup *, view, (Gfx::Popup *)nullptr);
|
||||
|
||||
/**
|
||||
* Called when a popup is hidden
|
||||
*/
|
||||
MESSAGE1(CPopupHiddenMsg, Gfx::Popup *, view, (Gfx::Popup *)nullptr);
|
||||
|
||||
/**
|
||||
* Called when a game view is shown
|
||||
*/
|
||||
MESSAGE2(CShowMsg, Gfx::VisualItem *, view, (Gfx::VisualItem *)nullptr, bool, fadeIn, false);
|
||||
|
||||
/**
|
||||
* Used when text input is finished, to pass the text back to the owning view
|
||||
*/
|
||||
MESSAGE2(CTextInputMsg, Common::String, text, "", bool, escaped, false);
|
||||
|
||||
/**
|
||||
* Used when character input is finished, to pass the text back to the owning view
|
||||
*/
|
||||
MESSAGE1(CCharacterInputMsg, Common::KeyState, keyState, Common::KeyState());
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Used to trigger a party movement
|
||||
*/
|
||||
MESSAGE1(CMoveMsg, int, direction, 0);
|
||||
|
||||
/**
|
||||
* Used to trigger an attack
|
||||
*/
|
||||
MESSAGE1(CAttackMsg, int, direction, 0);
|
||||
|
||||
/**
|
||||
* Used to trigger a board action
|
||||
*/
|
||||
MESSAGE0(CBoardMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a cast action
|
||||
*/
|
||||
MESSAGE0(CCastMsg);
|
||||
|
||||
/**
|
||||
* Climb up or down
|
||||
*/
|
||||
MESSAGE0(CClimbMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a drop action
|
||||
*/
|
||||
MESSAGE0(CDropMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an Enter action
|
||||
*/
|
||||
MESSAGE0(CEnterMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an exit action
|
||||
*/
|
||||
MESSAGE0(CExitTransportMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a fire action
|
||||
*/
|
||||
MESSAGE0(CFireMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a Get action
|
||||
*/
|
||||
MESSAGE0(CGetMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a HyperJump action
|
||||
*/
|
||||
MESSAGE0(CHyperJumpMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an inform action
|
||||
*/
|
||||
MESSAGE0(CInformMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an open action
|
||||
*/
|
||||
MESSAGE0(COpenMsg);
|
||||
|
||||
/**
|
||||
* Pass a turn
|
||||
*/
|
||||
MESSAGE0(CPassMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a quit (save) action
|
||||
*/
|
||||
MESSAGE0(CQuitMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a ready item/weapon/spell action
|
||||
*/
|
||||
MESSAGE0(CReadyMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a stats action
|
||||
*/
|
||||
MESSAGE0(CStatsMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a steal action
|
||||
*/
|
||||
MESSAGE0(CStealMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a Transact action
|
||||
*/
|
||||
MESSAGE0(CTransactMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger an Unlock action
|
||||
*/
|
||||
MESSAGE0(CUnlockMsg);
|
||||
|
||||
/**
|
||||
* Used to trigger a view change action
|
||||
*/
|
||||
MESSAGE0(CViewChangeMsg);
|
||||
|
||||
/**
|
||||
* Used to signal an end of turn
|
||||
*/
|
||||
MESSAGE0(CEndOfTurnMsg);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
265
engines/ultima/shared/engine/resources.cpp
Normal file
265
engines/ultima/shared/engine/resources.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/* 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 "ultima/shared/engine/resources.h"
|
||||
#include "ultima/shared/early/font_resources.h"
|
||||
#include "common/endian.h"
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
#include "ultima/ultima1/core/resources.h"
|
||||
#endif
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
bool Resources::open() {
|
||||
// Save locally constructred resources to the archive manager for access
|
||||
Shared::FontResources sharedFonts(this);
|
||||
sharedFonts.save();
|
||||
#ifndef RELEASE_BUILD
|
||||
Ultima1::GameResources u1Data(this);
|
||||
u1Data.save();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Resources::addResource(const Common::Path &name, const byte *data, size_t size) {
|
||||
// Add a new entry to the local resources list for the passed data
|
||||
_localResources.push_back(LocalResource());
|
||||
LocalResource &lr = _localResources[_localResources.size() - 1];
|
||||
|
||||
lr._name = name;
|
||||
lr._data.resize(size);
|
||||
Common::copy(data, data + size, &lr._data[0]);
|
||||
}
|
||||
|
||||
bool Resources::hasFile(const Common::Path &path) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx)
|
||||
if (_localResources[idx]._name.equalsIgnoreCase(path))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int Resources::listMembers(Common::ArchiveMemberList &list) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx) {
|
||||
list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_localResources[idx]._name, *this)));
|
||||
}
|
||||
|
||||
return _localResources.size();
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr Resources::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *Resources::createReadStreamForMember(const Common::Path &path) const {
|
||||
for (uint idx = 0; idx < _localResources.size(); ++idx) {
|
||||
const LocalResource &lr = _localResources[idx];
|
||||
if (lr._name.equalsIgnoreCase(path))
|
||||
return new Common::MemoryReadStream(&lr._data[0], lr._data.size());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void Resources::FileResource::load(File &f) {
|
||||
_name = f.readString();
|
||||
_offset = f.readUint32LE();
|
||||
_size = f.readUint16LE();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
ResourceFile::ResourceFile(const Common::Path &filename) : _filename(filename), _bufferP(_buffer) {
|
||||
Common::fill(_buffer, _buffer + STRING_BUFFER_SIZE, 0);
|
||||
}
|
||||
|
||||
void ResourceFile::load() {
|
||||
_file.open(_filename);
|
||||
synchronize();
|
||||
_file.close();
|
||||
}
|
||||
|
||||
void ResourceFile::syncString(const char *&str) {
|
||||
str = _bufferP;
|
||||
do {
|
||||
*_bufferP = _file.readByte();
|
||||
} while (*_bufferP++);
|
||||
|
||||
assert(_bufferP < (_buffer + STRING_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
void ResourceFile::syncStrings(const char **str, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
|
||||
void ResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumber(int &val) {
|
||||
val = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers(int *vals, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, count3, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2 * count3; ++idx)
|
||||
vals[idx] = _file.readSint32LE();
|
||||
}
|
||||
|
||||
void ResourceFile::syncBytes(byte *vals, size_t count) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count, 0, 0, 0));
|
||||
_file.read(vals, count);
|
||||
}
|
||||
|
||||
void ResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) {
|
||||
uint tag = _file.readUint32LE();
|
||||
assert(tag == MKTAG(count1, count2, 0, 0));
|
||||
_file.read(vals, count1 * count2);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
void LocalResourceFile::save() {
|
||||
synchronize();
|
||||
_file.finalize();
|
||||
_owner->addResource(_filename, _file.getData(), _file.size());
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncString(const char *&str) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncString(str);
|
||||
} else {
|
||||
_file.writeString(str);
|
||||
_file.writeByte('\0');
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncStrings(const char **str, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncStrings(str, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncStrings2D(const char **str, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncStrings2D(str, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
syncString(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumber(int &val) {
|
||||
if (!_owner)
|
||||
ResourceFile::syncNumber(val);
|
||||
else
|
||||
_file.writeUint32LE(val);
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers(int *vals, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers(vals, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
for (size_t idx = 0; idx < count; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers2D(int *vals, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers2D(vals, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncNumbers3D(vals, count1, count2, count3);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, count3, 0));
|
||||
for (size_t idx = 0; idx < count1 * count2 * count3; ++idx)
|
||||
_file.writeUint32LE(vals[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncBytes(byte *vals, size_t count) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncBytes(vals, count);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count, 0, 0, 0));
|
||||
_file.write(vals, count);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalResourceFile::syncBytes2D(byte *vals, size_t count1, size_t count2) {
|
||||
if (!_owner) {
|
||||
ResourceFile::syncBytes2D(vals, count1, count2);
|
||||
} else {
|
||||
_file.writeUint32LE(MKTAG(count1, count2, 0, 0));
|
||||
_file.write(vals, count1 * count2);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
196
engines/ultima/shared/engine/resources.h
Normal file
196
engines/ultima/shared/engine/resources.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_SHARED_ENGINE_RESOURCES_H
|
||||
#define ULTIMA_SHARED_ENGINE_RESOURCES_H
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/archive.h"
|
||||
#include "common/array.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/str.h"
|
||||
#include "common/serializer.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
|
||||
#define STRING_BUFFER_SIZE 32768
|
||||
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
class Resources;
|
||||
|
||||
/**
|
||||
* Base class for classes that exposes a set of strings, arrays, and other data from a resource
|
||||
*/
|
||||
class ResourceFile {
|
||||
private:
|
||||
File _file;
|
||||
char _buffer[STRING_BUFFER_SIZE];
|
||||
char *_bufferP;
|
||||
protected:
|
||||
Common::Path _filename;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ResourceFile(const Common::Path &filename);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ResourceFile() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the data for the resource
|
||||
*/
|
||||
virtual void synchronize() = 0;
|
||||
|
||||
virtual void syncString(const char *&str);
|
||||
virtual void syncStrings(const char **str, size_t count);
|
||||
virtual void syncStrings2D(const char **str, size_t count1, size_t count2);
|
||||
virtual void syncNumber(int &val);
|
||||
virtual void syncNumbers(int *vals, size_t count);
|
||||
virtual void syncNumbers2D(int *vals, size_t count1, size_t count2);
|
||||
virtual void syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3);
|
||||
virtual void syncBytes(byte *vals, size_t count);
|
||||
virtual void syncBytes2D(byte *vals, size_t count1, size_t count2);
|
||||
public:
|
||||
/**
|
||||
* Loads in a resource
|
||||
*/
|
||||
void load();
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived base class for resources that have their contents within the executable rather than a data file.
|
||||
* This will allow the data for a particular Ultima game to be gradually built up without repeatedly
|
||||
* regenerating a data file. Once a game has been properly tested, then it can be moved out.
|
||||
*/
|
||||
class LocalResourceFile : public ResourceFile {
|
||||
private:
|
||||
Common::MemoryWriteStreamDynamic _file;
|
||||
Resources *_owner;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
LocalResourceFile(const Common::Path &filename) : ResourceFile(filename), _owner(nullptr), _file(DisposeAfterUse::YES) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
LocalResourceFile(Resources *owner, const Common::Path &filename) : ResourceFile(filename),
|
||||
_owner(owner), _file(DisposeAfterUse::YES) {}
|
||||
|
||||
/**
|
||||
* Return true if in saving mode
|
||||
*/
|
||||
bool isSaving() const { return _owner != nullptr; }
|
||||
|
||||
void syncString(const char *&str) override;
|
||||
void syncStrings(const char **str, size_t count) override;
|
||||
void syncStrings2D(const char **str, size_t count1, size_t count2) override;
|
||||
void syncNumber(int &val) override;
|
||||
void syncNumbers(int *vals, size_t count) override;
|
||||
void syncNumbers2D(int *vals, size_t count1, size_t count2) override;
|
||||
void syncNumbers3D(int *vals, size_t count1, size_t count2, size_t count3) override;
|
||||
void syncBytes(byte *vals, size_t count) override;
|
||||
void syncBytes2D(byte *vals, size_t count1, size_t count2) override;
|
||||
public:
|
||||
/**
|
||||
* Write out the resource to the in-memory resource store
|
||||
*/
|
||||
void save();
|
||||
};
|
||||
|
||||
/**
|
||||
* Resources manager
|
||||
*/
|
||||
class Resources : public Common::Archive {
|
||||
struct LocalResource {
|
||||
Common::Path _name;
|
||||
Common::Array<byte> _data;
|
||||
};
|
||||
struct FileResource {
|
||||
Common::Path _name;
|
||||
size_t _offset, _size;
|
||||
|
||||
/**
|
||||
* Load an index entry from the datafile
|
||||
*/
|
||||
void load(File &f);
|
||||
};
|
||||
private:
|
||||
Common::Array<LocalResource> _localResources;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Resources() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the resources for the engine
|
||||
* @returns False if setup failed
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Adds a resource created in memory to the ScummVM archive manager, so that it can be
|
||||
* later opened like a normal file. Just as it will when eventually shifted to the
|
||||
* data file for the engine
|
||||
*/
|
||||
void addResource(const Common::Path &name, const byte *data, size_t size);
|
||||
|
||||
// Archive implementation
|
||||
/**
|
||||
* Check if a member with the given name is present in the Archive.
|
||||
* Patterns are not allowed, as this is meant to be a quick File::exists()
|
||||
* replacement.
|
||||
*/
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Add all members of the Archive to list.
|
||||
* Must only append to list, and not remove elements from it.
|
||||
*
|
||||
* @return the number of names added to list
|
||||
*/
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
|
||||
/**
|
||||
* Returns a ArchiveMember representation of the given file.
|
||||
*/
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
|
||||
|
||||
/**
|
||||
* Create a stream bound to a member with the specified name in the
|
||||
* archive. If no member with this name exists, 0 is returned.
|
||||
* @return the newly created input stream
|
||||
*/
|
||||
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user