File: object.h

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (407 lines) | stat: -rw-r--r-- 11,498 bytes parent folder | download | duplicates (3)
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
397
398
399
400
401
402
403
404
405
406
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 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 ScummVM 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 resource matching the specified type, name and subtype */
	Object *findChildWithName(Type type, const Common::String &name, int subType = -1) const;

	/** Find a child matching the template parameter type */
	template<class T>
	T *findChild(bool mustBeUnique = true) const;

	/** 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;

	/** Find a child matching the template parameter type, name and subtype */
	template<class T>
	T *findChildWithName(const Common::String &name, 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) const {
	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));
}

template<class T>
T *Object::findChildWithName(const Common::String &name, int subType) const {
	return Object::cast<T>(findChildWithName(T::TYPE, name, subType));
}

} // End of namespace Resources
} // End of namespace Stark

#endif // STARK_RESOURCES_RESOURCE_H