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
43namespace Video {
44class SmackerDecoder;
45}
46
47namespace Hadesch {
48
49class PodImage;
50class HadeschEngine;
51class TagFile;
52
53static const int kDefaultSpeed = 100;
54
56public:
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
68private:
69 int getLen();
71 int _msperframe;
72 int _startms;
73 int _first;
74 int _last;
75 bool _loop;
76};
77
78class LayerId {
79public:
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
108private:
109 Common::String _name;
110 int _idx;
111 Common::String _qualifier;
112};
113
114struct 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
125public:
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;
137private:
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) {
152 res.soundName = s;
153 res.transcript = t;
154 return res;
155 }
156};
157
159public:
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,
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,
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,
218 Common::Point offset = Common::Point(0, 0));
219 void playAnim(const LayerId &animName, int zValue,
220 PlayAnimParams params,
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,
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
311private:
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 {
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;
394 Common::HashMap<int, int> _countQueuedSubtitles;
395 TextTable _assetMap;
396 bool _mouseEnabled;
397
398 int _finalFade, _finalFadeSpeed;
399 EventHandlerWrapper _finalFadeCallback;
400};
401
402static const int kVideoWidth = 640;
403static const int kVideoHeight = 480;
404#define kOffsetRightRoom (Common::Point(kVideoWidth, 0))
405#define kZeroPoint (Common::Point(10, 50))
406
407struct PrePoint {
408 int x, y;
409
410 Common::Point get() const {
411 return Common::Point(x, y);
412 }
413};
414
415}
416#endif
SoundType
Definition: mixer.h:73
Definition: audiostream.h:109
Definition: mixer.h:49
Definition: array.h:52
Definition: hashmap.h:85
Definition: stream.h:745
Definition: ptr.h:159
Definition: str.h:59
Definition: ustr.h:57
Definition: event.h:34
Definition: hotzone.h:54
Definition: video.h:78
Definition: video.h:124
Definition: pod_image.h:35
Definition: video.h:55
Definition: table.h:43
Definition: video.h:158
Definition: rect.h:144
Definition: video.h:114
Definition: video.h:407
Definition: video.h:146