1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
|
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 STARK_RESOURCES_RESOURCE_H
#define STARK_RESOURCES_RESOURCE_H
#include "common/array.h"
#include "common/str.h"
namespace Stark {
namespace Formats {
class XRCReadStream;
}
class ResourceSerializer;
namespace Resources {
class Type {
public:
enum ResourceType {
kInvalid = 0,
kRoot = 1,
kLevel = 2,
kLocation = 3,
kLayer = 4,
kCamera = 5,
kFloor = 6,
kFloorFace = 7,
kItem = 8,
kScript = 9,
kAnimHierarchy = 10,
kAnim = 11,
kDirection = 12,
kImage = 13,
kAnimScript = 14,
kAnimScriptItem = 15,
kSoundItem = 16,
kPath = 17,
kFloorField = 18,
kBookmark = 19,
kKnowledgeSet = 20,
kKnowledge = 21,
kCommand = 22,
kPATTable = 23,
kContainer = 26,
kDialog = 27,
kSpeech = 29,
kLight = 30,
kCursor = 31, // Not sure about this one
kBonesMesh = 32,
kScroll = 33,
kFMV = 34,
kLipSync = 35,
kAnimSoundTrigger = 36,
kString = 37,
kTextureSet = 38
};
Type();
Type(ResourceType type);
ResourceType get() const;
const char *getName() const;
bool operator==(const Type &other) const {
return other._type == _type;
}
bool operator!=(const Type &other) const {
return other._type != _type;
}
bool operator==(const Type::ResourceType other) const {
return other == _type;
}
bool operator!=(const Type::ResourceType other) const {
return other != _type;
}
private:
ResourceType _type;
};
/**
* Game resource base object
*
* The in-game objects are represented using subclasses of this class.
*
* The game world is made of a tree of resources, with each level further down
* the tree adding further details. An instance of this class is a node in that
* tree.
*
* The first few tree levels are as follow:
* - Root
* - Level
* - Location
* - Layer
*
* The actual world tree is cut off in several sub-trees. There is one sub-tree
* per xarc archive. For resource management reasons the sub-trees are not merged
* in memory, the sub-trees are loaded and unloaded as needed, according to the
* current level / location.
*
* The xarc archives contain each an xrc file, which is a serialized version
* of the initial state of a resource sub-tree. The readData method is called for
* each resource by the archive loader when a resource tree is loaded to set up
* its initial state.
*
* As the game plays, modifications are made to the resources to reflect
* the game's state. When the resource sub-trees are loaded or unloaded their
* state is restored or persisted by the state provider. The saveLoad method
* is called to perform the serialization / deserialization of a resource.
* The saveLoadCurrent method is additionally called when loading or saving
* a sub-tree corresponding to the current level / location. This allows to
* persist additional data needed when restoring an active location.
*
* The OnEnterLocation and OnExitLocation methods are called by the resource
* provider when entering or leaving a level / location.
*
* The OnGameLoop method is called during the game loop.
*
*/
class Object {
public:
virtual ~Object();
/** Get the resource type */
Type getType() const { return _type; }
/** Get the resource sub type */
byte getSubType() const { return _subType; }
/** Get the resource index */
uint16 getIndex() const { return _index; }
/** Get the resource index as a string */
Common::String getIndexAsString() const { return Common::String::format("%02x", _index); }
/** Get the name of the resource */
Common::String getName() const { return _name; }
/**
* Deserialize the resource static data and initial state.
*/
virtual void readData(Formats::XRCReadStream *stream);
/**
* Persist / restore the resource state
*/
virtual void saveLoad(ResourceSerializer *serializer);
/**
* Persist / restore the resource state
*
* Called only for active locations
*/
virtual void saveLoadCurrent(ResourceSerializer *serializer);
/**
* Called when the node's initialization is complete.
*
* Allows to load additional data from file.
*/
virtual void onPostRead();
/**
* Called when the resource sub-tree is entirely loaded.
*
* Allows to load data from other nodes.
*/
virtual void onAllLoaded();
/**
* Called when entering a location
*/
virtual void onEnterLocation();
/**
* Called once per game loop
*/
virtual void onGameLoop();
/**
* Called when ResidualVM pauses or resumes the engine
*/
virtual void onEnginePause(bool pause);
/**
* Called when exiting a location
*/
virtual void onExitLocation();
/**
* Called before a resource sub-tree is unloaded.
*/
virtual void onPreDestroy();
/**
* Cast a resource, performing a type check
*/
template<class T>
static T *cast(Object *resource);
/** Find the first parent resource with the specified type */
template<class T>
T *findParent();
/** Find a child resource matching the specified type, index and subtype */
Object *findChildWithIndex(Type type, uint16 index, int subType = -1) const;
/** Find a child resource matching the specified type, order in the children list and subtype */
Object *findChildWithOrder(Type type, uint16 order, int subType = -1) const;
/** Find a child matching the template parameter type */
template<class T>
T *findChild(bool mustBeUnique = true);
/** Find a child matching the template parameter type and the specified subtype */
template<class T>
T *findChildWithSubtype(int subType, bool mustBeUnique = true) const;
/** Find a child matching the template parameter type and the specified index */
template<class T>
T *findChildWithIndex(uint16 index, int subType = -1) const;
/** Find a child matching the template parameter type, order in the children list and subtype */
template<class T>
T *findChildWithOrder(uint16 order, int subType = -1) const;
/** List children matching the template parameter type and the specified subtype */
template<class T>
Common::Array<T *> listChildren(int subType = -1) const;
/** List children recursively matching the template parameter type and the specified subtype */
template<class T>
Common::Array<T *> listChildrenRecursive(int subType = -1);
/** Add a resource to the children list */
void addChild(Object *child);
/** Print debug information for the resource */
virtual void print(uint depth = 0);
protected:
Object(Object *parent, byte subType, uint16 index, const Common::String &name);
void printWithDepth(uint depth, const Common::String &string) const;
void printDescription(uint depth) const;
virtual void printData();
Type _type;
byte _subType;
uint16 _index;
Common::String _name;
Object *_parent;
Common::Array<Object *> _children;
};
/**
* An unimplemented resource type.
*
* Used to display the raw resource data when dumping a resource tree.
* To be removed once all the resource types are implemented.
*/
class UnimplementedResource : public Object {
public:
UnimplementedResource(Object *parent, Type type, byte subType, uint16 index, const Common::String &name);
virtual ~UnimplementedResource();
protected:
void readData(Formats::XRCReadStream *stream) override;
void printData() override;
uint32 _dataLength;
byte *_data;
};
template <class T>
T* Object::cast(Object *resource) {
if (resource && resource->_type != T::TYPE) {
error("Unexpected resource type when casting resource %s instead of %s",
resource->_type.getName(), Type(T::TYPE).getName());
}
return (T *) resource;
}
template<>
Object *Object::cast<Object>(Object *resource);
template<class T>
T *Object::findParent() {
if (getType() == T::TYPE) {
return cast<T>(this);
} else if (!_parent) {
return nullptr;
} else {
return _parent->findParent<T>();
}
}
template<>
Object *Object::findParent();
template <class T>
Common::Array<T *> Object::listChildren(int subType) const {
Common::Array<T *> list;
for (uint i = 0; i < _children.size(); i++) {
if (_children[i]->getType() == T::TYPE
&& (_children[i]->getSubType() == subType || subType == -1)) {
// Found a matching child
list.push_back(Object::cast<T>(_children[i]));
}
}
return list;
}
template<class T>
Common::Array<T *> Object::listChildrenRecursive(int subType) {
Common::Array<T *> list;
for (uint i = 0; i < _children.size(); i++) {
if (_children[i]->getType() == T::TYPE
&& (_children[i]->getSubType() == subType || subType == -1)) {
// Found a matching child
list.push_back(Object::cast<T>(_children[i]));
}
// Look for matching resources in the child's children
list.push_back(_children[i]->listChildrenRecursive<T>(subType));
}
return list;
}
template<>
Common::Array<Object *> Object::listChildren<Object>(int subType) const;
template<class T>
T *Object::findChild(bool mustBeUnique) {
return findChildWithSubtype<T>(-1, mustBeUnique);
}
template <class T>
T *Object::findChildWithSubtype(int subType, bool mustBeUnique) const {
Common::Array<T *> list = listChildren<T>(subType);
if (list.empty()) {
return nullptr;
}
if (list.size() > 1 && mustBeUnique) {
error("Several children resources matching criteria type = %s, subtype = %d", Type(T::TYPE).getName(), subType);
}
return list.front();
}
template <class T>
T *Object::findChildWithIndex(uint16 index, int subType) const {
return Object::cast<T>(findChildWithIndex(T::TYPE, index, subType));
}
template <class T>
T *Object::findChildWithOrder(uint16 order, int subType) const {
return Object::cast<T>(findChildWithOrder(T::TYPE, order, subType));
}
} // End of namespace Resources
} // End of namespace Stark
#endif // STARK_RESOURCES_RESOURCE_H
|