1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef DRACI_ANIMATION_H
24 #define DRACI_ANIMATION_H
25 
26 #include "common/array.h"
27 #include "common/list.h"
28 #include "common/rect.h"
29 #include "draci/sprite.h"
30 
31 namespace Draci {
32 
33 /**
34   * Animation IDs for those animations that don't have their IDs
35   * specified in the data files.
36   */
37 enum {
38 	kOverlayImage = -1,
39 	kWalkingMapOverlay = -2,
40 	kWalkingShortestPathOverlay = -3,
41 	kWalkingObliquePathOverlay = -4,
42 	kTitleText = -5,
43 	kSpeechText = -6,
44 	kInventorySprite = -7,
45 	kDialogueLinesID = -8,
46 	kUnused = -12,
47 	kInventoryItemsID = -13
48 };
49 
50 /**
51   * Used by overlays as a neutral index that won't get
52   * released with the GPL Release command.
53   */
54 enum { kIgnoreIndex = -2 };
55 
56 class DraciEngine;
57 class Surface;
58 struct SoundSample;
59 
60 class Animation {
61 
62 typedef void (Animation::* AnimationCallback)();
63 
64 public:
65 	Animation(DraciEngine *v, int id, uint z, bool playing);
66 	~Animation();
67 
getZ()68 	uint getZ() const { return _z; }
setZ(uint z)69 	void setZ(uint z) { _z = z; }
70 
setID(int id)71 	void setID(int id) { _id = id; }
getID()72 	int getID() const { return _id; }
73 
74 	void nextFrame(bool force);
75 	void drawFrame(Surface *surface);
76 
77 	void addFrame(Drawable *frame, const SoundSample *sample);
78 	void replaceFrame(int i, Drawable *frame, const SoundSample *sample);
79 	const Drawable *getConstCurrentFrame() const;
80 	Drawable *getCurrentFrame();
81 	Drawable *getFrame(int frameNum);
82 	void setCurrentFrame(uint frame);
currentFrameNum()83 	uint currentFrameNum() const { return _currentFrame; }
getFrameCount()84 	uint getFrameCount() const { return _frames.size(); }
85 	void makeLastFrameRelative(int x, int y);
86 	void clearShift();
87 
isPlaying()88 	bool isPlaying() const { return _playing; }
89 	void setPlaying(bool playing);
90 
isPaused()91 	bool isPaused() const { return _paused; }
setPaused(bool paused)92 	void setPaused(bool paused) { _paused = paused; }
93 
isLooping()94 	bool isLooping() const { return _looping; }
95 	void setLooping(bool looping);
96 
setIsRelative(bool value)97 	void setIsRelative(bool value) { _isRelative = value; }
isRelative()98 	bool isRelative() const { return _isRelative; }
99 	void setRelative(int relx, int rely);
getRelativeX()100 	int getRelativeX() const { return _displacement.relX; }
getRelativeY()101 	int getRelativeY() const { return _displacement.relY; }
getDisplacement()102 	const Displacement &getDisplacement() const { return _displacement; }	// displacement of the whole animation
103 	Displacement getCurrentFrameDisplacement() const;	// displacement of the current frame (includes _shift)
104 	Common::Point getCurrentFramePosition() const;	// with displacement and shift applied
105 
supportsQuickAnimation(bool val)106 	void supportsQuickAnimation(bool val) { _canBeQuick = val; }
107 
getIndex()108 	int getIndex() const { return _index; }
setIndex(int index)109 	void setIndex(int index) { _index = index; }
110 
111 	void setScaleFactors(double scaleX, double scaleY);
getScaleX()112 	double getScaleX() const { return _displacement.extraScaleX; }
getScaleY()113 	double getScaleY() const { return _displacement.extraScaleY; }
114 
115 	void markDirtyRect(Surface *surface) const;
116 
117 	// Animation callbacks.  They can only do simple things, such as
118 	// setting the value of some variable or stopping an animation.  In
119 	// particular, they cannot run sub-loops or anything like that, because
120 	// the callback is called at an arbitrary time without much control
121 	// over what the state of the rest of the program is.
registerCallback(AnimationCallback callback)122 	void registerCallback(AnimationCallback callback) { _callback = callback; }
123 
doNothing()124 	void doNothing() {}
125 	void exitGameLoop();
126 	void tellWalkingState();
127 
128 	void play();
129 	void stop();
130 	void del();
131 
132 private:
133 	uint nextFrameNum() const;
134 	void deleteFrames();
135 
136 	/** Internal animation ID
137 	  * (as specified in the data files and the bytecode)
138 	  */
139 	int _id;
140 
141 	/** The recency index of an animation, i.e. the most recently added animation has
142 	  * the highest index. Some script commands need this.
143 	  */
144 	int _index;
145 
146 	uint _currentFrame;
147 	uint _z;
148 	Common::Point _shift;	// partial sum of _relativeShifts from the beginning of the animation until the current frame
149 	bool _hasChangedFrame;
150 
151 	Displacement _displacement;
152 	bool _isRelative;
153 
154 	uint _tick;
155 	bool _playing;
156 	bool _looping;
157 	bool _paused;
158 
159 	bool _canBeQuick;
160 
161 	/** Array of frames of the animation.  The animation object owns these pointers.
162 	 */
163 	Common::Array<Drawable *> _frames;
164 	Common::Array<Common::Point> _relativeShifts;
165 	/** Array of samples played during the animation.  The animation
166 	 * object doesn't own these pointers, but they are stored in the
167 	 * cache.
168 	 */
169 	Common::Array<const SoundSample *> _samples;
170 
171 	AnimationCallback _callback;
172 
173 	DraciEngine *_vm;
174 };
175 
176 
177 class AnimationManager {
178 
179 public:
AnimationManager(DraciEngine * vm)180 	AnimationManager(DraciEngine *vm) : _vm(vm), _lastIndex(-1), _animationPauseCounter(0) {}
~AnimationManager()181 	~AnimationManager() { deleteAll(); }
182 
183 	void insert(Animation *anim, bool allocateIndex);
184 	Animation *load(uint animNum);
185 
186 	void pauseAnimations();
187 	void unpauseAnimations();
188 
189 	void deleteAnimation(Animation *anim);
190 	void deleteOverlays();
191 	void deleteAll();
192 
193 	void drawScene(Surface *surf);
194 
195 	Animation *getAnimation(int id);
196 
getLastIndex()197 	int getLastIndex() const { return _lastIndex; }
198 	void deleteAfterIndex(int index);
199 
200 	const Animation *getTopAnimation(int x, int y) const;
201 
202 private:
203 	void sortAnimations();
204 
205 	DraciEngine *_vm;
206 
207 	/** List of animation objects, maintained sorted by decreasing Z-coordinates.
208 	 * The animation manager owns the pointers.
209 	 */
210 	Common::List<Animation *> _animations;
211 
212 	/** The index of the most recently added animation.
213 	  * See Animation::_index for details.
214 	  */
215 	int _lastIndex;
216 
217 	/** How many times the animations are paused.
218 	 * Needed because the animations can be paused once by entering the
219 	 * inventory and then again by entering the game menu.  When they are
220 	 * unpaused the first time, they should be kept paused. */
221 	int _animationPauseCounter;
222 };
223 
224 } // End of namespace Draci
225 
226 #endif // DRACI_ANIMATION_H
227