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 NEVERHOOD_SPRITE_H
24 #define NEVERHOOD_SPRITE_H
25 
26 #include "neverhood/neverhood.h"
27 #include "neverhood/entity.h"
28 #include "neverhood/graphics.h"
29 #include "neverhood/resource.h"
30 
31 namespace Neverhood {
32 
33 #define SetSpriteUpdate(callback)											\
34 	do {																	\
35 		_spriteUpdateCb = static_cast <void (Sprite::*)(void)> (callback);	\
36 		debug(2, "SetSpriteUpdate(" #callback ")");							\
37 		_spriteUpdateCbName = #callback;									\
38 	} while (0)
39 
40 #define SetFilterX(callback)												\
41 	do {																	\
42 		_filterXCb = static_cast <int16 (Sprite::*)(int16)> (callback);		\
43 		debug(2, "SetFilterX(" #callback ")");								\
44 	} while (0)
45 
46 #define SetFilterY(callback)												\
47 	do {																	\
48 		_filterYCb = static_cast <int16 (Sprite::*)(int16)> (callback);		\
49 		debug(2, "SetFilterY(" #callback ")");								\
50 	} while (0)
51 
52 const int16 kDefPosition = -32768;
53 
54 class Sprite : public Entity {
55 public:
56 	Sprite(NeverhoodEngine *vm, int objectPriority);
57 	~Sprite() override;
init()58 	void init() {}
getSurface()59 	BaseSurface *getSurface() { return _surface; }
60 	void updateBounds();
61 	void setDoDeltaX(int type);
62 	void setDoDeltaY(int type);
63 	bool isPointInside(int16 x, int16 y);
64 	bool checkCollision(NRect &rect);
getX()65 	int16 getX() const { return _x; }
getY()66 	int16 getY() const { return _y; }
setX(int16 value)67 	void setX(int16 value) { _x = value; }
setY(int16 value)68 	void setY(int16 value) { _y = value; }
getFlags()69 	uint16 getFlags() const { return _flags; }
isDoDeltaX()70 	bool isDoDeltaX() const { return _doDeltaX; }
isDoDeltaY()71 	bool isDoDeltaY() const { return _doDeltaY; }
getCollisionBounds()72 	NRect& getCollisionBounds() { return _collisionBounds; }
73 	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
74 	void loadDataResource(uint32 fileHash);
75 	int16 defFilterY(int16 y);
getVisible()76 	bool getVisible() const { return _surface->getVisible(); }
setVisible(bool value)77 	void setVisible(bool value) { _surface->setVisible(value); }
getDrawRect()78 	NDrawRect& getDrawRect() { return _surface->getDrawRect(); }
79 	// Some shortcuts to set the clipRect
getClipRect()80 	NRect& getClipRect() { return _surface->getClipRect(); }
81 	void setClipRect(int16 x1, int16 y1, int16 x2, int16 y2);
82 	void setClipRect(NRect& clipRect);
83 	void setClipRect(NDrawRect& drawRect);
84 protected:
85 	void (Sprite::*_spriteUpdateCb)();
86 	Common::String _spriteUpdateCbName; // For debugging purposes
87 	int16 (Sprite::*_filterXCb)(int16);
88 	int16 (Sprite::*_filterYCb)(int16);
89 	BaseSurface *_surface;
90 	int16 _x, _y;
91 	bool _doDeltaX, _doDeltaY;
92 	bool _needRefresh;
93 	NDrawRect _drawOffset;
94 	NRect _collisionBounds;
95 	NDrawRect _collisionBoundsOffset;
96 	uint16 _flags;
97 	DataResource _dataResource;
98 	void createSurface(int surfacePriority, int16 width, int16 height);
handleSpriteUpdate()99 	void handleSpriteUpdate() {
100 		if (_spriteUpdateCb)
101 			(this->*_spriteUpdateCb)();
102 	}
filterX(int16 x)103 	int16 filterX(int16 x) {
104 		return _filterXCb ? (this->*_filterXCb)(x) : x;
105 	}
filterY(int16 y)106 	int16 filterY(int16 y) {
107 		return _filterYCb ? (this->*_filterYCb)(y) : y;
108 	}
109 };
110 
111 enum {
112 	kSLFDefDrawOffset				= 1 << 0,
113 	kSLFCenteredDrawOffset			= 1 << 1,
114 	kSLFDefPosition					= 1 << 2,
115 	kSLFSetPosition					= 1 << 3,
116 	kSLFDefCollisionBoundsOffset	= 1 << 4
117 };
118 
119 class StaticSprite : public Sprite {
120 public:
121 	StaticSprite(NeverhoodEngine *vm, int objectPriority);
122 	StaticSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x = kDefPosition, int16 y = kDefPosition);
123 	void loadSprite(uint32 fileHash, uint flags = 0, int surfacePriority = 0, int16 x = kDefPosition, int16 y = kDefPosition);
124 	void updatePosition();
125 protected:
126 	SpriteResource _spriteResource;
127 };
128 
129 #define AnimationCallback(callback) static_cast <void (AnimatedSprite::*)()> (callback)
130 #define GotoState(callback) gotoState(static_cast <void (AnimatedSprite::*)()> (callback))
131 #define NextState(callback)															\
132 	do {																			\
133 		_nextStateCb = static_cast <void (AnimatedSprite::*)(void)> (callback);		\
134 		debug(2, "NextState(" #callback ")"); _nextStateCbName = #callback;			\
135 	} while (0)
136 #define FinalizeState(callback) setFinalizeState(static_cast <void (AnimatedSprite::*)()> (callback));
137 
138 const int STICK_LAST_FRAME = -2;
139 
140 class AnimatedSprite : public Sprite {
141 public:
142 	AnimatedSprite(NeverhoodEngine *vm, int objectPriority);
143 	AnimatedSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x, int16 y);
144 	void update();
145 	void updateDeltaXY();
146 	void setRepl(byte oldColor, byte newColor);
147 	void clearRepl();
getCurrAnimFileHash()148 	uint32 getCurrAnimFileHash() const { return _currAnimFileHash; }
getFrameIndex()149 	int16 getFrameIndex() const { return _currFrameIndex; }
getFrameIndex(uint32 frameHash)150 	int16 getFrameIndex(uint32 frameHash) { return _animResource.getFrameIndex(frameHash); }
setNewHashListIndex(int value)151 	void setNewHashListIndex(int value) { _newStickFrameIndex = value; }
152 	void startAnimation(uint32 fileHash, int16 plFirstFrameIndex, int16 plLastFrameIndex);
153 protected:
154 	typedef void (AnimatedSprite::*AnimationCb)();
155 	AnimResource _animResource;
156 	uint32 _currAnimFileHash, _newAnimFileHash, _nextAnimFileHash;
157 	int16 _currFrameIndex, _lastFrameIndex;
158 	int16 _plFirstFrameIndex, _plLastFrameIndex;
159 	uint32 _plFirstFrameHash, _plLastFrameHash;
160 	int16 _animStatus;
161 	int16 _currFrameTicks;
162 	int _currStickFrameIndex, _newStickFrameIndex;
163 	uint32 _newStickFrameHash;
164 	int16 _deltaX, _deltaY;
165 	byte _replOldColor, _replNewColor;
166 	bool _playBackwards, _frameChanged;
167 	AnimationCb _finalizeStateCb;
168 	AnimationCb _currStateCb;
169 	AnimationCb _nextStateCb;
170 	// For debugging purposes
171 	Common::String _finalizeStateCbName;
172 	Common::String _currStateCbName;
173 	Common::String _nextStateCbName;
174 	void init();
175 	void updateAnim();
176 	void updatePosition();
177 	void updateFrameIndex();
178 	void updateFrameInfo();
179 	void createSurface1(uint32 fileHash, int surfacePriority);
180 	void createShadowSurface1(BaseSurface *shadowSurface, uint32 fileHash, int surfacePriority);
181 	void createShadowSurface(BaseSurface *shadowSurface, int16 width, int16 height, int surfacePriority);
182 	void stopAnimation();
183 	void startAnimationByHash(uint32 fileHash, uint32 plFirstFrameHash, uint32 plLastFrameHash);
184 	void nextAnimationByHash(uint32 fileHash2, uint32 plFirstFrameHash, uint32 plLastFrameHash);
185 	void setFinalizeState(AnimationCb finalizeStateCb);
186 	void gotoState(AnimationCb currStateCb);
187 	void gotoNextState();
188 };
189 
190 } // End of namespace Neverhood
191 
192 #endif /* NEVERHOOD_SPRITE_H */
193