aboutsummaryrefslogtreecommitdiff
path: root/include/aolayer.h
blob: 6265cec61e44c0c5109fb0cb8b2180772bd806af (plain)
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
#ifndef AOLAYER_H
#define AOLAYER_H

#include <QDebug>
#include <QElapsedTimer>
#include <QImageReader>
#include <QLabel>
#include <QTimer>
#include <QBitmap>

class AOApplication;

class AOLayer : public QLabel {
  Q_OBJECT

public:
  AOLayer(QWidget *p_parent, AOApplication *p_ao_app);

  QString filename;    // file name without extension, i.e. "witnesstestimony"
  int static_duration; // time in ms for static images to be displayed, if
                       // applicable. set to 0 for infinite
  int max_duration;    // maximum duration in ms, image will be culled if it is
                       // exceeded. set this to 0 for infinite duration
  bool play_once = false; // Whether to loop this animation or not
  bool cull_image = true; // if we're done playing this animation, should we
                          // hide it? also controls durational culling
  Qt::TransformationMode transform_mode = Qt::FastTransformation; // transformation mode to use for this image
  bool stretch = false; // Should we stretch/squash this image to fill the screen?

  // Set the movie's image to provided paths, preparing for playback.
  void start_playback(QString p_image);

  void set_play_once(bool p_play_once);
  void set_cull_image(bool p_cull_image);
  void set_static_duration(int p_static_duration);
  void set_max_duration(int p_max_duration);

  // Stop the movie, clearing the image
  void stop();

  // Set the m_flipped variable to true/false
  void set_flipped(bool p_flipped) { m_flipped = p_flipped; }

  // Set the movie's playback speed (between 10% and 1000%)
  void set_speed(int modifier) { speed = qMax(10, qMin(modifier, 1000)); }

  // Move the label itself around
  void move(int ax, int ay);

  // This is somewhat pointless now as there's no "QMovie" object to resize, aka
  // no "combo" to speak of
  void combo_resize(int w, int h);

  // Return the frame delay adjusted for speed
  int get_frame_delay(int delay);

  // iterate through a list of paths and return the first entry that exists. if
  // none exist, return NULL (safe because we check again for existence later)
  QString find_image(QList<QString> p_list);

protected:
  AOApplication *ao_app;
  QVector<QPixmap> movie_frames;
  QVector<int> movie_delays;

  QTimer *preanim_timer;
  QTimer *shfx_timer;
  QTimer *ticker;
  QString last_path;
  QImageReader m_reader;

  QElapsedTimer actual_time;

  // Usually used to turn seconds into milliseconds such as for [Time] tag in
  // char.ini
  const int tick_ms = 60;

  // These are the X and Y values before they are fixed based on the sprite's
  // width.
  int x = 0;
  int y = 0;
  // These are the width and height values before they are fixed based on the
  // sprite's width.
  int f_w = 0;
  int f_h = 0;

  int frame = 0;
  int max_frames = 0;
  int last_max_frames = 0;

  int speed = 100;

  bool m_flipped = false;
  // Are we loading this from the same frame we left off on? TODO: actually make
  // this work
  bool continuous = false;
  // Whether or not to forcibly bypass the simple check done by start_playback
  // and use the existent value of continuous instead
  bool force_continuous = false;

  int duration = 0;

  // Start playback of the movie (if animated).
  void play();

  // Freeze the movie at the current frame.
  void freeze();

  // Retreive a pixmap adjused for mirroring/aspect ratio shenanigans from a
  // provided QImage
  QPixmap get_pixmap(QImage image);

  // Set the movie's frame to provided pixmap
  void set_frame(QPixmap f_pixmap);

signals:
  void done();

protected slots:
  virtual void preanim_done();
  void shfx_timer_done();
  virtual void movie_ticker();
};

class BackgroundLayer : public AOLayer {
  Q_OBJECT
public:
  BackgroundLayer(QWidget *p_parent, AOApplication *p_ao_app);
  void load_image(QString p_filename);
};

class ForegroundLayer : public AOLayer {
  Q_OBJECT
public:
  ForegroundLayer(QWidget *p_parent, AOApplication *p_ao_app);
  QString miscname; //'misc' folder to search. we fetch this based on p_charname below
  void load_image(QString p_filename, QString p_charname);
};

class CharLayer : public AOLayer {
  Q_OBJECT
public:
  CharLayer(QWidget *p_parent, AOApplication *p_ao_app);
  QString current_emote = ""; // name of the emote we're using
  bool is_preanim;     // equivalent to the old play_once, if true we don't want
                       // to loop this
  QString prefix = ""; // prefix, left blank if it's a preanim

  void load_image(QString p_filename, QString p_charname, int p_duration, bool p_is_preanim);
  void play(); // overloaded so we can play effects

  // networked frame fx string
  QStringList network_strings;

private:
  QString last_char;        // name of the last character we used
  QString last_emote;       // name of the last animation we used
  QString last_prefix;      // prefix of the last animation we played
  bool was_preanim = false; // whether is_preanim was true last time

  // Effects such as sfx, screenshakes and realization flashes are stored in
  // here. QString entry format: "sfx^[sfx_name]", "shake", "flash". The program
  // uses the QVector index as reference.
  QVector<QVector<QString>> movie_effects;

  // used for effect loading
  QString m_char = "";
  QString m_emote = "";

  // overloaded for effects reasons
  void start_playback(QString p_image);

  // Initialize the frame-specific effects from the char.ini
  void load_effects();

  // Initialize the frame-specific effects from the provided network_strings,
  // this is only initialized if network_strings has size more than 0.
  void load_network_effects();

  // Play a frame-specific effect, if there's any defined for that specific
  // frame.
  void play_frame_effect(int p_frame);

private slots:
  void preanim_done() override; // overridden so we don't accidentally cull characters
  void movie_ticker() override; // overridden so we can play effects

signals:
  void shake();
  void flash();
  void play_sfx(QString sfx);
};

class InterjectionLayer : public AOLayer {
  Q_OBJECT
public:
  InterjectionLayer(QWidget *p_parent, AOApplication *p_ao_app);
  void load_image(QString p_filename, QString p_charname, QString p_miscname);
};

class EffectLayer : public AOLayer {
  Q_OBJECT
public:
  EffectLayer(QWidget *p_parent, AOApplication *p_ao_app);
  void load_image(QString p_filename, bool p_looping);
};

class InterfaceLayer : public AOLayer {
  Q_OBJECT
public:
  InterfaceLayer(QWidget *p_parent, AOApplication *p_ao_app);
  void load_image(QString p_filename, QString p_miscname);
};

class StickerLayer : public AOLayer {
  Q_OBJECT
public:
  StickerLayer(QWidget *p_parent, AOApplication *p_ao_app);
  void load_image(QString p_charname);
};
#endif // AOLAYER_H