-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathanimationlayer.h
More file actions
265 lines (202 loc) · 5.85 KB
/
animationlayer.h
File metadata and controls
265 lines (202 loc) · 5.85 KB
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
#pragma once
#include "animationloader.h"
#include "datatypes.h"
#include <QBitmap>
#include <QDebug>
#include <QLabel>
#include <QPropertyAnimation>
#include <QTimer>
// #define DEBUG_MOVIE
#ifdef DEBUG_MOVIE
#include <QElapsedTimer>
#endif
class AOApplication;
// "Brief" explanation of what the hell this is:
//
// AOLayer handles all animations both inside and outside
// the viewport. It was originally devised as a layering
// system, but turned into a full refactor of the existing
// animation code.
//
// AOLayer has six subclasses, all of which differ mainly in
// how they handle path resolution.
//
// - BackgroundLayer: self-explanatory, handles files found in base/background
// - CharLayer: handles all the "wonderful" quirks of character path resolution
// - SplashLayer: handles elements that can either be provided by a misc/ directory
// or by the theme - speedlines, shouts, WT/CE, et cetera
// - EffectLayer: this is basically a dummy layer since effects do their own wonky
// path resolution in a different file
// - InterfaceLayer: handles UI elements like the chat arrow and the music display
// - StickerLayer: Crystalwarrior really wanted this. Handles "stickers," whatever those are.
//
// For questions comments or concerns, bother someone else
namespace kal
{
class AnimationLayer : public QLabel
{
Q_OBJECT
public:
explicit AnimationLayer(QWidget *parent = nullptr);
virtual ~AnimationLayer();
QString fileName();
void setFileName(QString fileName);
void startPlayback();
void stopPlayback();
void restartPlayback();
void pausePlayback(bool enabled);
QSize frameSize();
int frameCount();
int currentFrameNumber();
void jumpToFrame(int number);
bool isPlayOnce();
void setPlayOnce(bool enabled);
void setStretchToFit(bool enabled);
void setResetCacheWhenStopped(bool enabled);
void setFlipped(bool enabled);
void setResizeMode(RESIZE_MODE mode);
void setMinimumDurationPerFrame(int duration);
void setMaximumDurationPerFrame(int duration);
public Q_SLOTS:
void setMaskingRect(QRect rect);
Q_SIGNALS:
void startedPlayback();
void stoppedPlayback(); /* Is emitted whenever playback is stopped, whether by user or by reaching the end */
void finishedPlayback(); /* Is emitted only when playback reaches the end */
void frameNumberChanged(int frameNumber);
protected:
void resizeEvent(QResizeEvent *event) override;
private:
QString m_file_name;
bool m_play_once = false;
bool m_stretch_to_fit = false;
bool m_reset_cache_when_stopped = false;
bool m_flipped = false;
int m_minimum_duration = 0;
int m_maximum_duration = 0;
RESIZE_MODE m_resize_mode = AUTO_RESIZE_MODE;
Qt::TransformationMode m_transformation_mode = Qt::FastTransformation;
AnimationLoader *m_loader = nullptr;
QSize m_frame_size;
QRect m_frame_rect;
QRect m_mask_rect_hint;
QRect m_mask_rect;
QSize m_scaled_frame_size;
bool m_processing = false;
bool m_pause = false;
QTimer *m_ticker = nullptr;
bool m_first_frame = false;
int m_frame_number = 0;
int m_target_frame_number = -1;
int m_frame_count = 0;
AnimationFrame m_current_frame;
void createLoader();
void deleteLoader();
void resetData();
void calculateFrameGeometry();
void finishPlayback();
void prepareNextTick();
void displayCurrentFrame();
private Q_SLOTS:
void frameTicker();
};
class CharacterAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
enum EmoteType
{
NoEmoteType,
PreEmote,
IdleEmote,
TalkEmote,
PostEmote,
};
enum EffectType
{
SfxEffect,
ShakeEffect,
FlashEffect,
};
class FrameEffect
{
public:
QString emote_name;
EffectType type = SfxEffect;
QString file_name;
};
CharacterAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadCharacterEmote(QString character, QString fileName, EmoteType emoteType, int durationLimit = 0);
void setFrameEffects(QStringList data);
Q_SIGNALS:
void finishedPreOrPostEmotePlayback();
void soundEffect(QString sfx);
void shakeEffect();
void flashEffect();
private:
AOApplication *ao_app;
QString m_character;
QString m_emote;
QString m_resolved_emote;
EmoteType m_emote_type = NoEmoteType;
QTimer *m_duration_timer = nullptr;
int m_duration = 0;
QMap<int, QList<FrameEffect>> m_effects;
void startTimeLimit();
private Q_SLOTS:
void onPlaybackStopped();
void onPlaybackFinished();
void onDurationLimitReached();
void notifyFrameEffect(int frame);
void notifyEmotePlaybackFinished();
};
class BackgroundAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
BackgroundAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadAndPlayAnimation(QString fileName);
private:
AOApplication *ao_app;
};
class SplashAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
SplashAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadAndPlayAnimation(QString fileName, QString character, QString miscellaneous);
private:
AOApplication *ao_app;
};
class EffectAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
EffectAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadAndPlayAnimation(QString fileName, bool repeat = false);
void setHideWhenStopped(bool enabled);
private:
AOApplication *ao_app;
bool m_hide_when_stopped = false;
private Q_SLOTS:
void maybeHide();
};
class InterfaceAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
InterfaceAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadAndPlayAnimation(QString fileName, QString miscName);
private:
AOApplication *ao_app;
};
class StickerAnimationLayer : public AnimationLayer
{
Q_OBJECT
public:
StickerAnimationLayer(AOApplication *ao_app, QWidget *parent = nullptr);
void loadAndPlayAnimation(QString fileName);
private:
AOApplication *ao_app;
};
} // namespace kal