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
|
/* 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 NEVERHOOD_SPRITE_H
#define NEVERHOOD_SPRITE_H
#include "neverhood/neverhood.h"
#include "neverhood/entity.h"
#include "neverhood/graphics.h"
#include "neverhood/resource.h"
#include "neverhood/subtitles.h"
namespace Neverhood {
#define SetSpriteUpdate(callback) \
do { \
_spriteUpdateCb = static_cast <void (Sprite::*)(void)> (callback); \
debug(2, "SetSpriteUpdate(" #callback ")"); \
_spriteUpdateCbName = #callback; \
} while (0)
#define SetFilterX(callback) \
do { \
_filterXCb = static_cast <int16 (Sprite::*)(int16)> (callback); \
debug(2, "SetFilterX(" #callback ")"); \
} while (0)
#define SetFilterY(callback) \
do { \
_filterYCb = static_cast <int16 (Sprite::*)(int16)> (callback); \
debug(2, "SetFilterY(" #callback ")"); \
} while (0)
const int16 kDefPosition = -32768;
class Sprite : public Entity {
public:
Sprite(NeverhoodEngine *vm, int objectPriority);
void init() {}
Common::SharedPtr<BaseSurface> getSurface() { return _surface; }
virtual Common::SharedPtr<BaseSurface> getSubtitleSurface() { return nullptr; }
void updateBounds();
void setDoDeltaX(int type);
void setDoDeltaY(int type);
bool isPointInside(int16 x, int16 y);
bool checkCollision(NRect &rect);
int16 getX() const { return _x; }
int16 getY() const { return _y; }
void setX(int16 value) { _x = value; }
void setY(int16 value) { _y = value; }
uint16 getFlags() const { return _flags; }
bool isDoDeltaX() const { return _doDeltaX; }
bool isDoDeltaY() const { return _doDeltaY; }
NRect& getCollisionBounds() { return _collisionBounds; }
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
void loadDataResource(uint32 fileHash);
int16 defFilterY(int16 y);
bool getVisible() const { return _surface->getVisible(); }
void setVisible(bool value) { _surface->setVisible(value); }
NDrawRect& getDrawRect() { return _surface->getDrawRect(); }
// Some shortcuts to set the clipRect
NRect& getClipRect() { return _surface->getClipRect(); }
void setClipRect(int16 x1, int16 y1, int16 x2, int16 y2);
void setClipRect(NRect& clipRect);
void setClipRect(NDrawRect& drawRect);
protected:
void (Sprite::*_spriteUpdateCb)();
Common::String _spriteUpdateCbName; // For debugging purposes
int16 (Sprite::*_filterXCb)(int16);
int16 (Sprite::*_filterYCb)(int16);
Common::SharedPtr<BaseSurface> _surface;
int16 _x, _y;
bool _doDeltaX, _doDeltaY;
bool _needRefresh;
NDrawRect _drawOffset;
NRect _collisionBounds;
NDrawRect _collisionBoundsOffset;
uint16 _flags;
DataResource _dataResource;
void createSurface(int surfacePriority, int16 width, int16 height);
void handleSpriteUpdate() {
if (_spriteUpdateCb)
(this->*_spriteUpdateCb)();
}
int16 filterX(int16 x) {
return _filterXCb ? (this->*_filterXCb)(x) : x;
}
int16 filterY(int16 y) {
return _filterYCb ? (this->*_filterYCb)(y) : y;
}
};
enum {
kSLFDefDrawOffset = 1 << 0,
kSLFCenteredDrawOffset = 1 << 1,
kSLFDefPosition = 1 << 2,
kSLFSetPosition = 1 << 3,
kSLFDefCollisionBoundsOffset = 1 << 4
};
class StaticSprite : public Sprite {
public:
StaticSprite(NeverhoodEngine *vm, int objectPriority);
StaticSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x = kDefPosition, int16 y = kDefPosition);
void loadSprite(uint32 fileHash, uint flags = 0, int surfacePriority = 0, int16 x = kDefPosition, int16 y = kDefPosition);
void updatePosition();
protected:
SpriteResource _spriteResource;
};
#define AnimationCallback(callback) static_cast <void (AnimatedSprite::*)()> (callback)
#define GotoState(callback) gotoState(static_cast <void (AnimatedSprite::*)()> (callback))
#define NextState(callback) \
do { \
_nextStateCb = static_cast <void (AnimatedSprite::*)(void)> (callback); \
debug(2, "NextState(" #callback ")"); _nextStateCbName = #callback; \
} while (0)
#define FinalizeState(callback) setFinalizeState(static_cast <void (AnimatedSprite::*)()> (callback));
const int STICK_LAST_FRAME = -2;
class AnimatedSprite : public Sprite {
public:
AnimatedSprite(NeverhoodEngine *vm, int objectPriority);
AnimatedSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x, int16 y);
void update();
void updateDeltaXY();
void setRepl(byte oldColor, byte newColor);
void clearRepl();
uint32 getCurrAnimFileHash() const { return _currAnimFileHash; }
int16 getFrameIndex() const { return _currFrameIndex; }
int16 getFrameIndex(uint32 frameHash) { return _animResource.getFrameIndex(frameHash); }
void setNewHashListIndex(int value) { _newStickFrameIndex = value; }
void startAnimation(uint32 fileHash, int16 plFirstFrameIndex, int16 plLastFrameIndex);
Common::SharedPtr<BaseSurface> getSubtitleSurface() override { return _subtitleSurface; }
protected:
class AnimatedSpriteSubtitles : public BaseSurface {
public:
void draw() override;
AnimatedSpriteSubtitles(NeverhoodEngine *vm);
void setFrameIndex(int currFrameIndex, int lastFrameIndex);
void setHash(uint32 fileHash);
void updatePosition(const NDrawRect &parentDrawRect);
private:
Common::ScopedPtr<SubtitlePlayer> _subtitles;
int _currFrameIndex;
int _subCenterX;
};
static const int kSubtitleWidth = 320;
Common::SharedPtr<AnimatedSpriteSubtitles> _subtitleSurface;
typedef void (AnimatedSprite::*AnimationCb)();
AnimResource _animResource;
uint32 _currAnimFileHash, _newAnimFileHash, _nextAnimFileHash;
int16 _currFrameIndex, _lastFrameIndex;
int16 _plFirstFrameIndex, _plLastFrameIndex;
uint32 _plFirstFrameHash, _plLastFrameHash;
int16 _animStatus;
int16 _currFrameTicks;
int _currStickFrameIndex, _newStickFrameIndex;
uint32 _newStickFrameHash;
int16 _deltaX, _deltaY;
byte _replOldColor, _replNewColor;
bool _playBackwards, _frameChanged;
AnimationCb _finalizeStateCb;
AnimationCb _currStateCb;
AnimationCb _nextStateCb;
// For debugging purposes
Common::String _finalizeStateCbName;
Common::String _currStateCbName;
Common::String _nextStateCbName;
void init();
void updateAnim();
void updatePosition();
void updateFrameIndex();
void updateFrameInfo();
void createSurface1(uint32 fileHash, int surfacePriority);
void createShadowSurface1(const Common::SharedPtr<BaseSurface> &shadowSurface, uint32 fileHash, int surfacePriority);
void createShadowSurface(const Common::SharedPtr<BaseSurface> &shadowSurface, int16 width, int16 height, int surfacePriority);
void stopAnimation();
void startAnimationByHash(uint32 fileHash, uint32 plFirstFrameHash, uint32 plLastFrameHash);
void nextAnimationByHash(uint32 fileHash2, uint32 plFirstFrameHash, uint32 plLastFrameHash);
void setFinalizeState(AnimationCb finalizeStateCb);
void gotoState(AnimationCb currStateCb);
void gotoNextState();
};
} // End of namespace Neverhood
#endif /* NEVERHOOD_SPRITE_H */
|