ScummVM API documentation
elements.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  */
21 
22 #ifndef MTROPOLIS_ELEMENTS_H
23 #define MTROPOLIS_ELEMENTS_H
24 
25 #include "graphics/fontman.h"
26 #include "graphics/palette.h"
27 
28 #include "mtropolis/data.h"
29 #include "mtropolis/runtime.h"
30 #include "mtropolis/render.h"
31 #include "mtropolis/coroutine_protos.h"
32 
33 namespace Video {
34 
35 class VideoDecoder;
36 
37 } // End of namespace Video
38 
39 namespace MTropolis {
40 
41 class AudioPlayer;
42 class CachedAudio;
43 class CachedImage;
44 class CachedMToon;
45 struct AudioMetadata;
46 struct ElementLoaderContext;
47 struct MToonMetadata;
48 
49 enum MediaState {
50  kMediaStatePlaying,
51  kMediaStatePlayingLastFrame,
52  kMediaStateStopped,
53  kMediaStatePaused,
54 };
55 
56 class GraphicElement : public VisualElement {
57 public:
59  ~GraphicElement();
60 
61  bool load(ElementLoaderContext &context, const Data::GraphicElement &data);
62 
63  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
64  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
65 
66  void render(Window *window) override;
67 
68  Common::SharedPtr<Structural> shallowClone() const override;
69  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
70 
71 #ifdef MTROPOLIS_DEBUG_ENABLE
72  const char *debugGetTypeName() const override { return "Graphic Element"; }
73  SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
74 #endif
75 
76 private:
77  GraphicElement(const GraphicElement &other);
78 
79  bool _cacheBitmap;
80 
82 };
83 
85 public:
86  virtual ~MovieResizeFilter();
87 
88  virtual Common::SharedPtr<Graphics::ManagedSurface> scaleFrame(const Graphics::Surface &surface, uint32 timestamp) const = 0;
89 };
90 
92 public:
93  MovieElement();
94  ~MovieElement();
95 
96  bool load(ElementLoaderContext &context, const Data::MovieElement &data);
97 
98  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
99  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
100 
101  VThreadState asyncConsumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
102 
103  void activate() override;
104  void deactivate() override;
105 
106  bool canAutoPlay() const override;
107  void queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying) override;
108 
109  void render(Window *window) override;
110  void playMedia(Runtime *runtime, Project *project) override;
111  void tryAutoSetName(Runtime *runtime, Project *project) override;
112 
113  void setResizeFilter(const Common::SharedPtr<MovieResizeFilter> &filter);
114 
115  Common::SharedPtr<Structural> shallowClone() const override;
116  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
117 
118 #ifdef MTROPOLIS_DEBUG_ENABLE
119  const char *debugGetTypeName() const override { return "Movie Element"; }
120  SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
121 
122  void debugSkipMovies() override;
123 #endif
124 
125 protected:
126  void onPauseStateChanged() override;
127  void onSegmentUnloaded(int segmentIndex) override;
128 
130  CORO_DEFINE_RETURN_TYPE(void);
131  CORO_DEFINE_PARAMS_3(MovieElement *, self, Runtime *, runtime, Common::SharedPtr<MessageProperties>, msg);
132  };
133 
134 private:
135  IntRange computeRealRange() const;
136 
137  void stopSubtitles();
138 
139  void initFallbackPalette();
140 
141  MiniscriptInstructionOutcome scriptSetRange(MiniscriptThread *thread, const DynamicValue &value);
142  MiniscriptInstructionOutcome scriptSetRangeStart(MiniscriptThread *thread, const DynamicValue &value);
143  MiniscriptInstructionOutcome scriptSetRangeEnd(MiniscriptThread *thread, const DynamicValue &value);
144  MiniscriptInstructionOutcome scriptRangeWriteRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib);
145  MiniscriptInstructionOutcome scriptSetVolume(MiniscriptThread *thread, const DynamicValue &value);
146  MiniscriptInstructionOutcome scriptSetTimestamp(MiniscriptThread *thread, const DynamicValue &value);
147 
148  MiniscriptInstructionOutcome scriptSetRangeTyped(MiniscriptThread *thread, const IntRange &range);
149 
150  struct StartPlayingCoroutine {
151  CORO_DEFINE_RETURN_TYPE(void);
152  CORO_DEFINE_PARAMS_2(MovieElement *, self, Runtime *, runtime);
153  };
154 
155  struct SeekToTimeCoroutine {
156  CORO_DEFINE_RETURN_TYPE(void);
157  CORO_DEFINE_PARAMS_3(MovieElement *, self, Runtime *, runtime, uint32, timestamp);
158  };
159 
160  bool _cacheBitmap;
161  bool _alternate;
162  bool _playEveryFrame;
163  bool _reversed;
164  //bool _haveFiredAtLastCel;
165  //bool _haveFiredAtFirstCel;
166  bool _shouldPlayIfNotPaused;
167  bool _needsReset; // If true, then the video position was reset by a seek or stop and decoding must be restarted even if the target state is the same as the play state.
168  MediaState _currentPlayState;
169  uint32 _assetID;
170 
172  uint32 _maxTimestamp;
173  uint32 _timeScale;
174  uint32 _currentTimestamp;
175  int32 _volume;
176  IntRange _playRange;
177 
178  const Graphics::Surface *_displayFrame;
181 
183  Common::SharedPtr<PlayMediaSignaller> _playMediaSignaller;
184 
186 
187  Common::Array<int> _damagedFrames;
188 
189  Common::ScopedPtr<Graphics::Palette> _fallbackPalette;
190 };
191 
192 class ImageElement : public VisualElement {
193 public:
194  ImageElement();
195  ~ImageElement();
196 
197  bool load(ElementLoaderContext &context, const Data::ImageElement &data);
198 
199  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
200  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
201 
202  void activate() override;
203  void deactivate() override;
204 
205  void tryAutoSetName(Runtime *runtime, Project *project) override;
206 
207  void render(Window *window) override;
208 
209  Common::SharedPtr<Structural> shallowClone() const override;
210  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
211 
212 #ifdef MTROPOLIS_DEBUG_ENABLE
213  const char *debugGetTypeName() const override { return "Image Element"; }
214  SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
215  void debugInspect(IDebugInspectionReport *report) const override;
216 #endif
217 
218 private:
219  MiniscriptInstructionOutcome scriptSetFlushPriority(MiniscriptThread *thread, const DynamicValue &value);
220 
221  bool _cacheBitmap;
222  uint32 _assetID;
223 
224  Common::SharedPtr<CachedImage> _cachedImage;
225 
226  Common::String _text; // ...???
227 };
228 
230 public:
231  MToonElement();
232  ~MToonElement();
233 
234  bool load(ElementLoaderContext &context, const Data::MToonElement &data);
235 
236  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
237  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
238 
239  VThreadState asyncConsumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
240 
241  void activate() override;
242  void deactivate() override;
243 
244  void tryAutoSetName(Runtime *runtime, Project *project) override;
245 
246  bool canAutoPlay() const override;
247 
248  void render(Window *window) override;
249 
250  bool isMouseCollisionAtPoint(int32 relativeX, int32 relativeY) const override;
251 
252  Common::Rect getRelativeCollisionRect() const override;
253 
254  Common::SharedPtr<Structural> shallowClone() const override;
255  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
256 
257 #ifdef MTROPOLIS_DEBUG_ENABLE
258  const char *debugGetTypeName() const override { return "mToon Element"; }
259  SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
260  void debugInspect(IDebugInspectionReport *report) const override;
261 #endif
262 
263 private:
264  MToonElement(const MToonElement &other);
265 
266  struct MToonConsumeCommandCoroutine {
267  CORO_DEFINE_RETURN_TYPE(void);
268  CORO_DEFINE_PARAMS_3(MToonElement *, self, Runtime *, runtime, Common::SharedPtr<MessageProperties>, msg);
269  };
270 
271  struct StartPlayingCoroutine {
272  CORO_DEFINE_RETURN_TYPE(void);
273  CORO_DEFINE_PARAMS_2(MToonElement *, self, Runtime *, runtime);
274  };
275 
276  struct StopPlayingCoroutine {
277  CORO_DEFINE_RETURN_TYPE(void);
278  CORO_DEFINE_PARAMS_2(MToonElement *, self, Runtime *, runtime);
279  };
280 
281  struct ChangeFrameCoroutine {
282  CORO_DEFINE_RETURN_TYPE(void);
283  CORO_DEFINE_PARAMS_3(MToonElement *, self, Runtime *, runtime, uint32, frame);
284  };
285 
286  void playMedia(Runtime *runtime, Project *project) override;
287  MiniscriptInstructionOutcome scriptSetRate(MiniscriptThread *thread, const DynamicValue &value);
288  MiniscriptInstructionOutcome scriptSetCel(MiniscriptThread *thread, const DynamicValue &value);
289  MiniscriptInstructionOutcome scriptSetRange(MiniscriptThread *thread, const DynamicValue &value);
290  MiniscriptInstructionOutcome scriptSetRangeStart(MiniscriptThread *thread, const DynamicValue &value);
291  MiniscriptInstructionOutcome scriptSetRangeEnd(MiniscriptThread *thread, const DynamicValue &value);
292 
293  MiniscriptInstructionOutcome scriptRangeWriteRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib);
294  MiniscriptInstructionOutcome scriptSetRangeTyped(MiniscriptThread *thread, const IntRange &value);
295  MiniscriptInstructionOutcome scriptSetRangeTyped(MiniscriptThread *thread, const Common::Point &value);
296  MiniscriptInstructionOutcome scriptSetRangeTyped(MiniscriptThread *thread, const Label &value);
297 
298  void onPauseStateChanged() override;
299 
300  bool _cacheBitmap;
301 
302  // If set, then carry over residual frame time and display at the desired rate. If not set, reset residual each frame for smoother animation.
303  bool _maintainRate;
304 
305  uint32 _assetID;
306  int32 _rateTimes100000;
307  int32 _flushPriority;
308  uint32 _celStartTimeMSec;
309  bool _isPlaying; // Is actually rolling media, this is only set by playMedia because it needs to start after scene transition
310 
311  // Stop state works independently of pause/hidden even though it has similar effect:
312  // If an mToon is stopped, then it it is always hidden and will not play until a Play
313  // command is received.
314  //
315  // Also, MTI depends on not firing Stopped commands if the mToon is already stopped,
316  // otherwise the cannon scene in the Hispaniola will get stuck in an infinite loop due
317  // to Stopped
318  bool _isStopped;
319 
321  uint32 _renderedFrame;
322 
324  Common::SharedPtr<CachedMToon> _cachedMToon;
325  Common::SharedPtr<PlayMediaSignaller> _playMediaSignaller;
326 
327  // NOTE: To produce proper behavior, these are not sanitized until playMedia. render must tolerate invalid values without changing them.
328  IntRange _playRange;
329  int32 _cel;
330 
331  bool _hasIssuedRenderWarning;
332 };
333 
335 public:
337  ~TextLabelElement();
338 
339  bool isTextLabel() const override;
340 
341  bool load(ElementLoaderContext &context, const Data::TextLabelElement &data);
342 
343  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
344  bool readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) override;
345  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
346  MiniscriptInstructionOutcome writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) override;
347 
348  void activate() override;
349  void deactivate() override;
350 
351  void render(Window *window) override;
352 
353  void setTextStyle(uint16 macFontID, const Common::String &fontFamilyName, uint size, TextAlignment alignment, const TextStyleFlags &styleFlags);
354 
355  Graphics::FontManager::FontUsage getDefaultUsageForMacFont(uint16 macFontID, uint size);
356  Graphics::FontManager::FontUsage getDefaultUsageForNamedFont(const Common::String &fontFamilyName, uint size);
357 
358  Common::SharedPtr<Structural> shallowClone() const override;
359  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
360 
361 #ifdef MTROPOLIS_DEBUG_ENABLE
362  const char *debugGetTypeName() const override { return "Text Label Element"; }
363  SupportStatus debugGetSupportStatus() const override { return kSupportStatusPartial; }
364 #endif
365 
366 private:
367  TextLabelElement(const TextLabelElement &other);
368 
369  struct TextLabelLineWriteInterface {
370  static MiniscriptInstructionOutcome write(MiniscriptThread *thread, const DynamicValue &dest, void *objectRef, uintptr ptrOrOffset);
371  static MiniscriptInstructionOutcome refAttrib(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib);
372  static MiniscriptInstructionOutcome refAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib, const DynamicValue &index);
373  };
374 
375  MiniscriptInstructionOutcome scriptSetText(MiniscriptThread *thread, const DynamicValue &value);
376  MiniscriptInstructionOutcome scriptSetLine(MiniscriptThread *thread, size_t lineIndex, const DynamicValue &value);
377 
378  bool findLineRange(size_t lineNum, uint32 &outStartPos, uint32 &outEndPos) const;
379  size_t countLines() const;
380 
381  bool _cacheBitmap;
382  bool _needsRender;
383 
384  bool _isBitmap;
385  uint32 _assetID;
386 
387  Common::String _text;
388  uint16 _macFontID;
389  Common::String _fontFamilyName;
390  uint _size;
391  TextAlignment _alignment;
392  TextStyleFlags _styleFlags;
393 
394  Common::Array<MacFormattingSpan> _macFormattingSpans;
395 
396  // NOTE: This may be a surface loaded from data, so it must not be altered.
397  // If you need to render again, recreate the surface. If you want to change
398  // this behavior, please add a flag indicating that it is from the asset.
400 };
401 
403 public:
404  SoundElement();
405  ~SoundElement();
406 
407  bool load(ElementLoaderContext &context, const Data::SoundElement &data);
408 
409  bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
410  MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
411 
412  VThreadState asyncConsumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
413 
414  void activate() override;
415  void deactivate() override;
416 
417  bool canAutoPlay() const override;
418 
419  void playMedia(Runtime *runtime, Project *project) override;
420  void tryAutoSetName(Runtime *runtime, Project *project) override;
421 
422  bool resolveMediaMarkerLabel(const Label &label, int32 &outResolution) const override;
423 
424  Common::SharedPtr<Structural> shallowClone() const override;
425  void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
426 
427 #ifdef MTROPOLIS_DEBUG_ENABLE
428  const char *debugGetTypeName() const override { return "Sound Element"; }
429  SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
430  void debugInspect(IDebugInspectionReport *report) const override;
431 #endif
432 
433 private:
434  SoundElement(const SoundElement &other);
435 
436  void initSubtitles();
437  void stopPlayer();
438 
439  MiniscriptInstructionOutcome scriptSetLoop(MiniscriptThread *thread, const DynamicValue &value);
440  MiniscriptInstructionOutcome scriptSetVolume(MiniscriptThread *thread, const DynamicValue &value);
441  MiniscriptInstructionOutcome scriptSetBalance(MiniscriptThread *thread, const DynamicValue &value);
442  MiniscriptInstructionOutcome scriptSetAsset(MiniscriptThread *thread, const DynamicValue &value);
443 
444  struct SoundElementConsumeCommandCoroutine {
445  CORO_DEFINE_RETURN_TYPE(void);
446  CORO_DEFINE_PARAMS_3(SoundElement *, self, Runtime *, runtime, Common::SharedPtr<MessageProperties>, msg);
447  };
448 
449  struct StartPlayingCoroutine {
450  CORO_DEFINE_RETURN_TYPE(void);
451  CORO_DEFINE_PARAMS_2(SoundElement *, self, Runtime *, runtime);
452  };
453 
454  struct StopPlayingCoroutine {
455  CORO_DEFINE_RETURN_TYPE(void);
456  CORO_DEFINE_PARAMS_2(SoundElement *, self, Runtime *, runtime);
457  };
458 
459  void setLoop(bool loop);
460  void setVolume(uint16 volume);
461  void setBalance(int16 balance);
462 
463  uint16 _leftVolume;
464  uint16 _rightVolume;
465  int16 _balance;
466  uint32 _assetID;
467 
468  Common::SharedPtr<CachedAudio> _cachedAudio;
471  uint64 _startTime;
472  uint64 _finishTime;
473  uint64 _startTimestamp; // Time in the sound corresponding to the start time
474  uint64 _cueCheckTime;
475  bool _shouldPlayIfNotPaused;
476  bool _needsReset;
477 
478  Common::SharedPtr<PlayMediaSignaller> _playMediaSignaller;
479 
480  Common::SharedPtr<SubtitlePlayer> _subtitlePlayer;
481 };
482 
483 } // End of namespace MTropolis
484 
485 #endif
Definition: runtime.h:816
Definition: str.h:59
Definition: surface.h:67
Definition: runtime.h:330
Definition: data.h:820
Definition: render.h:53
Definition: elements.h:91
Definition: rect.h:144
Definition: elements.h:192
Definition: runtime.h:1575
Definition: runtime.h:2373
Definition: element_factory.h:30
Definition: runtime.h:2390
Definition: miniscript.h:421
Definition: runtime.h:2827
Definition: data.h:917
Definition: runtime.h:544
Definition: elements.h:402
Definition: render.h:93
Definition: runtime.h:351
Definition: runtime.h:2118
Definition: elements.h:229
Definition: debug.h:59
Definition: data.h:886
Definition: rect.h:45
Definition: data.h:777
Definition: runtime.h:2994
Definition: elements.h:84
Definition: actions.h:25
Definition: data.h:798
Definition: elements.h:334
Definition: data.h:858
Definition: ptr.h:159
Definition: avi_frames.h:36
Definition: elements.h:56
Definition: runtime.h:2472