ScummVM API documentation
video.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  * Copyright 2020 Google
21  *
22  */
23 
24 #ifndef HADESCH_VIDEOROOM_H
25 #define HADESCH_VIDEOROOM_H
26 
27 #include "common/scummsys.h"
28 #include "common/array.h"
29 #include "audio/audiostream.h"
30 #include "audio/mixer.h"
31 #include "common/rect.h"
32 #include "common/ptr.h"
33 #include "hadesch/pod_file.h"
34 #include "hadesch/pod_image.h"
35 #include "common/hashmap.h"
36 #include "common/str.h"
37 #include "hadesch/enums.h"
38 #include "hadesch/event.h"
39 #include "hadesch/hotzone.h"
40 #include "hadesch/table.h"
41 #include "common/queue.h"
42 
43 namespace Video {
44 class SmackerDecoder;
45 }
46 
47 namespace Hadesch {
48 
49 class PodImage;
50 class HadeschEngine;
51 class TagFile;
52 
53 static const int kDefaultSpeed = 100;
54 
55 class Renderable {
56 public:
58  const PodImage &getFrame(int time);
59  void startAnimation(int startms, int msperframe,
60  bool loop, int first, int last);
61  bool isAnimationFinished(int time);
62  void selectFrame(int frame);
63  int getAnimationFrameNum(int time);
64  int getNumFrames() {
65  return _images.size();
66  }
67 
68 private:
69  int getLen();
71  int _msperframe;
72  int _startms;
73  int _first;
74  int _last;
75  bool _loop;
76 };
77 
78 class LayerId {
79 public:
80  LayerId(const Common::String &name) {
81  _name = name;
82  _idx = -1;
83  }
84 
85  LayerId() {
86  _idx = -1;
87  }
88 
89  LayerId(const char *name) {
90  _name = name;
91  _idx = -1;
92  }
93 
94  LayerId(const Common::String &name, int idx, const Common::String &qualifier) {
95  _qualifier = qualifier;
96  _name = name;
97  _idx = idx;
98  }
99 
100  Common::String getFilename() const {
101  return _name;
102  }
103 
104  Common::String getDebug() const;
105 
106  bool operator== (const LayerId &b) const;
107 
108 private:
109  Common::String _name;
110  int _idx;
111  Common::String _qualifier;
112 };
113 
114 struct Animation {
115  Audio::SoundHandle _soundHandle;
116  LayerId _animName;
117  EventHandlerWrapper _callbackEvent;
118  bool _finished;
119  bool _keepLastFrame;
120  bool _skippable;
121  int _subtitleID;
122 };
123 
125 public:
126  static PlayAnimParams loop();
127  static PlayAnimParams keepLastFrame();
128  static PlayAnimParams disappear();
129  bool getKeepLastFrame();
130  bool isLoop();
131  int getSpeed();
132  int getFirstFrame();
133  int getLastFrame();
134  PlayAnimParams partial(int first, int last) const;
135  PlayAnimParams speed(int msperframe) const;
136  PlayAnimParams backwards() const;
137 private:
138  PlayAnimParams(bool loop, bool keepLastFrame);
139  bool _loop;
140  bool _keepLastFrame;
141  int _firstFrame;
142  int _lastFrame;
143  int _msperframe;
144 };
145 
147  const char *soundName;
148  const char *transcript;
149 
150  static TranscribedSound make(const char *s, const char *t) {
151  TranscribedSound res;
152  res.soundName = s;
153  res.transcript = t;
154  return res;
155  }
156 };
157 
158 class VideoRoom {
159 public:
160  VideoRoom(const Common::String &dir, const Common::String &pod,
161  const Common::String &assetMapFile);
162  ~VideoRoom();
163 
164  void nextFrame(Common::SharedPtr<GfxContext> context, int time, bool stopVideo);
165  uint getWidth();
166  uint getHeight();
167  int getCursor();
168 
169  // Hotzones and mouse
170  void setHotzoneEnabled(const Common::String &name, bool enabled);
171  void enableHotzone(const Common::String &name);
172  void disableHotzone(const Common::String &name);
173  void pushHotZones(const Common::String &hotzoneFile, bool enable = true,
174  Common::Point offset = Common::Point(0, 0));
175  void popHotZones();
176  void loadHotZones(const Common::String &hotzoneFile, bool enable = true,
177  Common::Point offset = Common::Point(0, 0));
178  void computeHotZone(int time, Common::Point mousePos);
179  Common::String getHotZone();
180  void setHotZoneOffset(const Common::String &name, Common::Point offset);
181  Common::String mapClick(Common::Point mousePos);
182  void enableMouse() {
183  _mouseEnabled = true;
184  }
185  void disableMouse() {
186  _mouseEnabled = false;
187  }
188  bool isMouseEnabled() {
189  return _mouseEnabled;
190  }
191  int getCursorAnimationFrame(int time);
192 
193  // Animations and layers
194  void setLayerEnabled(const LayerId &name, bool enabled);
195  void setLayerParallax(const LayerId &name, int val);
196  void setColorScale(const LayerId &name, int val);
197  void setScale(const LayerId &name, int val);
198  int getNumFrames(const LayerId &animName);
199 
200  // Main animation API
201  void playAnimWithSpeech(const LayerId &animName,
202  const TranscribedSound &sound,
203  int zValue,
204  PlayAnimParams params,
205  EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
206  Common::Point offset = Common::Point(0, 0));
207  void playAnimWithSFX(const LayerId &animName,
208  const Common::String &soundName,
209  int zValue,
210  PlayAnimParams params,
211  EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
212  Common::Point offset = Common::Point(0, 0));
213  void playAnimWithMusic(const LayerId &animName,
214  const Common::String &soundName,
215  int zValue,
216  PlayAnimParams params,
217  EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
218  Common::Point offset = Common::Point(0, 0));
219  void playAnim(const LayerId &animName, int zValue,
220  PlayAnimParams params,
221  EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
222  Common::Point offset = Common::Point(0, 0));
223 
224  void stopAnim(const LayerId &animName);
225  // Like stopAnim but also remove layer altogether
226  void purgeAnim(const LayerId &animName);
227  bool isAnimationFinished(const LayerId &name, int time);
228  void addStaticLayer(const LayerId &name, int zValue, Common::Point offset = Common::Point(0, 0));
229  void selectFrame(const LayerId &name, int zValue, int val, Common::Point offset = Common::Point(0, 0));
230  bool doesLayerExist(const LayerId &name);
231  PodImage getLayerFrame(const LayerId &name);
232  int getAnimFrameNum(const LayerId &name);
233  void dumpLayers();
234 
235  // Convenience wrappers
236  void playAnimLoop(const LayerId &animName, int zValue, Common::Point offset = Common::Point(0, 0));
237  void playAnimKeepLastFrame(const LayerId &animName, int zValue, EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
238  Common::Point offset = Common::Point(0, 0));
239 
240  // Videos
241  void playVideo(const Common::String &name, int zValue,
242  EventHandlerWrapper callbackEvent = EventHandlerWrapper(),
243  Common::Point offset = Common::Point(0, 0));
244  void cancelVideo();
245  bool isVideoPlaying();
246 
247  // Panning
248  void panLeftAnim(EventHandlerWrapper callbackEvent = EventHandlerWrapper());
249  void panRightAnim(EventHandlerWrapper callbackEvent = EventHandlerWrapper());
250  void panRightInstant();
251  void setPannable(bool pannable);
252  void setUserPanCallback(EventHandlerWrapper leftStart,
253  EventHandlerWrapper leftEnd,
254  EventHandlerWrapper rightStart,
255  EventHandlerWrapper rightEnd);
256  bool isPanLeft() {
257  return _pan == 0;
258  }
259 
260  bool isPanRight() {
261  return _pan == 640;
262  }
263 
264  // Hero belt
265  void enableHeroBelt() {
266  _heroBeltEnabled = true;
267  }
268  void disableHeroBelt() {
269  _heroBeltEnabled = false;
270  }
271  bool isHeroBeltEnabled() {
272  return _heroBeltEnabled;
273  }
274 
275  // Font
276  void renderString(const Common::String &font, const Common::U32String &str,
277  Common::Point startPos, int zVal, int fontDelta = 0, const Common::String &extraId = "letter");
278  void renderStringCentered(const Common::String &font, const Common::U32String &str,
279  Common::Point centerPos, int zVal, int fontDelta = 0, const Common::String &extraId = "letter");
280  void hideString(const Common::String &font, size_t maxLen, const Common::String &extraId = "letter");
281  int computeStringWidth(const Common::String &font, const Common::U32String &str, int fontDelta = 0);
282 
283  // Misc
284  void playSFX(const Common::String &soundName,
285  EventHandlerWrapper callbackEvent = EventHandlerWrapper());
286  void playMusic(const Common::String &soundName,
287  EventHandlerWrapper callbackEvent = EventHandlerWrapper());
288  void playSFXLoop(const Common::String &soundName);
289  void playMusicLoop(const Common::String &soundName);
290  void playSpeech(const TranscribedSound &sound,
291  EventHandlerWrapper callbackEvent = EventHandlerWrapper());
292  void playStatueSMK(StatueId id, const LayerId &animName, int zValue,
293  const Common::Array<Common::String> &smkNames,
294  int startOfLoop, int startOfEnd,
295  Common::Point offset = Common::Point(0, 0));
296  Common::SeekableReadStream *openFile(const Common::String &name);
297  void fadeOut(int ms, const EventHandlerWrapper &callback);
298  void resetFade();
299  void resetLayers();
300  void drag(const Common::String &name, int frame, Common::Point hotspot);
301  PodImage *getDragged();
302  void clearDrag();
303  void pause();
304  void unpause();
305  void finish();
306  void cancelAllSubtitles();
307  void setViewportOffset(Common::Point vp) {
308  _viewportOffset = vp;
309  }
310 
311 private:
312  struct Layer {
314  LayerId name;
315  Common::Point offset;
316  bool isEnabled;
317  int genCounter;
318  int zValue;
319  int parallax;
320  int colorScale; // From 0 to 0x100
321  int scale; // From 0 to 100
322  };
323 
324  struct SubtitleLine {
325  Common::U32String line;
326  int32 maxTime;
327  int ID;
328  };
329 
330  void playAnimWithSoundInternal(const LayerId &animName,
331  const Common::String &soundName,
332  Audio::Mixer::SoundType soundType,
333  int zValue,
334  PlayAnimParams params,
335  EventHandlerWrapper callbackEvent,
336  Common::Point offset,
337  int subID = -1);
338  void playSubtitles(const char *text, int subID);
339  void addLayer(Renderable *renderable, const LayerId &name,
340  int zValue,
341  bool isEnabled = true, Common::Point offset = Common::Point(0, 0));
342  void startAnimationInternal(const LayerId &name, int zValue, int msperframe, bool loop,
343  bool fixedFrame, int first, int last, Common::Point offset);
344  Audio::RewindableAudioStream *getAudioStream(const Common::String &soundName);
345  Common::String mapAsset(const Common::String &name);
346  Common::String mapAsset(const LayerId &name);
347  void addAnimLayerInternal(const LayerId &name, int zValue, Common::Point offset = Common::Point(0, 0));
348  void playSoundInternal(const Common::String &soundName, EventHandlerWrapper callbackEvent, bool loop,
349  bool skippable, Audio::Mixer::SoundType soundType, int subtitleID = -1);
350  static int layerComparator (const Layer &a, const Layer &b);
351  void loadFontWidth(const Common::String &font);
352 
353  uint _videoW, _videoH;
354  Common::Point _videoOffset, _videoSurfOffset;
355  Common::SharedPtr<byte> _videoPixels;
356  byte _videoPalette[256 * 3];
357 
358  HotZoneArray _hotZones;
359  Common::Array<HotZoneArray> _hotZoneStack;
361  int _layerGenCounter;
362 
363  int _startHotTime;
364  int _hotZone;
365  int _cursor;
366  // We need to keep cursor pointer valid for at
367  // least one more frame. Hence use circular buffer
368  PodImage _draggedImage[5];
369  int _draggingPtr;
370  bool _isDragging;
371  int _pan, _panSpeed;
372  EventHandlerWrapper _panCallback;
373  EventHandlerWrapper _userPanStartLeftCallback;
374  EventHandlerWrapper _userPanStartRightCallback;
375  EventHandlerWrapper _userPanEndLeftCallback;
376  EventHandlerWrapper _userPanEndRightCallback;
377 
378  bool _pannable;
379  bool _leftEdge;
380  bool _rightEdge;
381  bool _heroBeltEnabled;
382  int _edgeStartTime;
383  Common::String _smkPath;
384  Common::String _podPath;
385 
387  Common::Point _viewportOffset;
389  EventHandlerWrapper _videoDecoderEndEvent;
390  int _videoZ;
393  Common::Queue<SubtitleLine> _subtitles;
394  Common::HashMap<int, int> _countQueuedSubtitles;
395  TextTable _assetMap;
396  bool _mouseEnabled;
397 
398  int _finalFade, _finalFadeSpeed;
399  EventHandlerWrapper _finalFadeCallback;
400 };
401 
402 static const int kVideoWidth = 640;
403 static const int kVideoHeight = 480;
404 #define kOffsetRightRoom (Common::Point(kVideoWidth, 0))
405 #define kZeroPoint (Common::Point(10, 50))
406 
407 struct PrePoint {
408  int x, y;
409 
410  Common::Point get() const {
411  return Common::Point(x, y);
412  }
413 };
414 
415 }
416 #endif
Definition: str.h:59
Definition: event.h:34
Definition: ambient.h:30
Definition: video.h:55
Definition: array.h:52
Definition: video.h:124
Definition: video.h:407
Definition: video.h:78
Definition: pod_image.h:35
Definition: stream.h:745
Definition: hotzone.h:54
Definition: video.h:158
Definition: mixer.h:49
Graphics::Surface * scale(const Graphics::Surface &srcImage, int xSize, int ySize)
SoundType
Definition: mixer.h:62
Definition: hashmap.h:85
Definition: ustr.h:57
Definition: table.h:43
Definition: rect.h:45
Definition: array.h:518
Definition: audiostream.h:109
Definition: video.h:146
Definition: video.h:114
Definition: ptr.h:159
Definition: avi_frames.h:36