ScummVM API documentation
graphics.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 ALCACHOFA_GRAPHICS_H
23 #define ALCACHOFA_GRAPHICS_H
24 
25 #include "common/ptr.h"
26 #include "common/stream.h"
27 #include "common/serializer.h"
28 #include "common/rect.h"
29 #include "common/span.h"
30 #include "math/vector2d.h"
31 #include "graphics/managed_surface.h"
32 
33 #include "alcachofa/camera.h"
34 #include "alcachofa/common.h"
35 
36 namespace Alcachofa {
37 
50 enum class BlendMode {
51  AdditiveAlpha, // Normal objects
52  Additive, // "Effect" objects, fades
53  Multiply, // Unused in Movie Adventure
54  Alpha, // Unused in Movie Adventure (used for debugging)
55  Tinted // Used for fonts
56 };
57 
58 class Shape;
59 
60 class ITexture {
61 public:
62  ITexture(Common::Point size);
63  virtual ~ITexture() {}
64 
65  virtual void update(const Graphics::Surface &surface) = 0;
66  inline void update(const Graphics::ManagedSurface &surface) { update(surface.rawSurface()); }
67 
68  inline Common::Point size() const { return _size; }
69 
70 private:
71  Common::Point _size;
72 };
73 
74 class IRenderer {
75 public:
76  virtual ~IRenderer() {}
77 
78  virtual Common::ScopedPtr<ITexture> createTexture(int32 w, int32 h, bool withMipmaps = true) = 0;
79 
80  virtual void begin() = 0;
81  virtual void setTexture(ITexture *texture) = 0;
82  virtual void setBlendMode(BlendMode blendMode) = 0;
83  virtual void setLodBias(float lodBias) = 0;
84  virtual void setOutput(Graphics::Surface &surface) = 0;
85  virtual bool hasOutput() const = 0;
86  virtual void quad(
87  Math::Vector2d topLeft,
88  Math::Vector2d size,
89  Color color = kWhite,
90  Math::Angle rotation = Math::Angle(),
91  Math::Vector2d texMin = Math::Vector2d(0, 0),
92  Math::Vector2d texMax = Math::Vector2d(1, 1)) = 0;
93  virtual void end() = 0;
94 
95  static IRenderer *createOpenGLRenderer(Common::Point resolution);
96  static IRenderer *createOpenGLRendererClassic(Common::Point resolution);
97  static IRenderer *createOpenGLRendererShaders(Common::Point resolution);
98  static IRenderer *createTinyGLRenderer(Common::Point resolution);
99 };
100 
101 class IDebugRenderer : public virtual IRenderer {
102 public:
103  virtual void debugPolygon(
105  Color color = kDebugRed
106  ) = 0;
107  virtual void debugPolyline(
109  Color color = kDebugRed
110  ) = 0;
111 
112  virtual void debugShape(
113  const Shape &shape,
114  Color color = kDebugRed
115  );
116 
117  inline void debugPolyline(Common::Point a, Common::Point b, Color color = kDebugRed) {
118  Math::Vector2d points[] = { { (float)a.x, (float)a.y }, { (float)b.x, (float)b.y } };
119  debugPolygon({ points, 2 }, color);
120  }
121 };
122 
123 enum class AnimationFolder {
124  Animations,
125  Masks,
126  Backgrounds
127 };
128 
131  _center,
132  _offset;
133  uint32 _duration;
134 };
135 
148 protected:
149  AnimationBase(Common::String fileName, AnimationFolder folder = AnimationFolder::Animations);
150  ~AnimationBase();
151 
152  void load();
153  void loadMissingAnimation();
154  void freeImages();
155  Graphics::ManagedSurface *readImage(Common::SeekableReadStream &stream) const;
156  Common::Point imageSize(int32 imageI) const;
157  inline bool isLoaded() const { return _isLoaded; }
158 
159  static void fullBlend(
160  const Graphics::ManagedSurface &source,
161  Graphics::ManagedSurface &destination,
162  int offsetX,
163  int offsetY);
164 
165  static constexpr const uint kMaxSpriteIDs = 256;
166  Common::String _fileName;
167  AnimationFolder _folder;
168  bool _isLoaded = false;
169  uint32 _totalDuration = 0;
170 
171  int32 _spriteIndexMapping[kMaxSpriteIDs] = { 0 };
174  _spriteBases;
177  Common::Array<Common::Point> _imageOffsets;
178 };
179 
184 class Animation : private AnimationBase {
185 public:
186  Animation(Common::String fileName, AnimationFolder folder = AnimationFolder::Animations);
187 
188  void load();
189  void freeImages();
190 
191  using AnimationBase::isLoaded;
192  inline uint spriteCount() const { return _spriteBases.size(); }
193  inline uint frameCount() const { return _frames.size(); }
194  inline uint32 frameDuration(int32 frameI) const { return _frames[frameI]._duration; }
195  inline Common::Point frameCenter(int32 frameI) const { return _frames[frameI]._center; }
196  inline uint32 totalDuration() const { return _totalDuration; }
197  inline uint8 &premultiplyAlpha() { return _premultiplyAlpha; }
198  Common::Rect frameBounds(int32 frameI) const;
199  Common::Point totalFrameOffset(int32 frameI) const;
200  int32 frameAtTime(uint32 time) const;
201  int32 imageIndex(int32 frameI, int32 spriteI) const;
202  using AnimationBase::imageSize;
203  void outputRect2D(int32 frameI, float scale, Math::Vector2d &topLeft, Math::Vector2d &size) const;
204  void outputRect3D(int32 frameI, float scale, Math::Vector3d &topLeft, Math::Vector2d &size) const;
205 
206  void overrideTexture(const Graphics::ManagedSurface &surface);
207 
208  void draw2D(
209  int32 frameI,
210  Math::Vector2d topLeft,
211  float scale,
212  BlendMode blendMode,
213  Color color);
214  void draw3D(
215  int32 frameI,
216  Math::Vector3d topLeft,
217  float scale,
218  BlendMode blendMode,
219  Color color);
220  void drawEffect(
221  int32 frameI,
222  Math::Vector3d topLeft,
223  Math::Vector2d tiling,
224  Math::Vector2d texOffset,
225  BlendMode blendMode);
226 
227 private:
228  Common::Rect spriteBounds(int32 frameI, int32 spriteI) const;
229  Common::Rect maxFrameBounds() const;
230  void prerenderFrame(int32 frameI);
231 
232  int32_t _renderedFrameI = -1;
233  uint8 _premultiplyAlpha = 100,
234  _renderedPremultiplyAlpha = 255;
235 
236  Graphics::ManagedSurface _renderedSurface;
237  Common::ScopedPtr<ITexture> _renderedTexture;
238 };
239 
240 class Font : private AnimationBase {
241 public:
242  Font(Common::String fileName);
243 
244  void load();
245  void freeImages();
246  void drawCharacter(int32 imageI, Common::Point center, Color color);
247 
248  using AnimationBase::isLoaded;
249  using AnimationBase::imageSize;
250  inline uint imageCount() const { return _images.size(); }
251 
252 private:
253  Common::Array<Math::Vector2d> _texMins, _texMaxs;
255 };
256 
257 class Graphic {
258 public:
259  Graphic();
260  Graphic(Common::ReadStream &stream);
261  Graphic(const Graphic &other); // animation reference is taken, so keep other alive
262  Graphic &operator= (const Graphic &other);
263 
264  inline Common::Point &topLeft() { return _topLeft; }
265  inline int8 &order() { return _order; }
266  inline int16 &scale() { return _scale; }
267  inline float &depthScale() { return _depthScale; }
268  inline Color &color() { return _color; }
269  inline int32 &frameI() { return _frameI; }
270  inline uint32 &lastTime() { return _lastTime; }
271  inline bool isPaused() const { return _isPaused; }
272  inline bool hasAnimation() const { return _animation != nullptr; }
273  inline Animation &animation() {
274  assert(_animation != nullptr && _animation->isLoaded());
275  return *_animation;
276  }
277  inline uint8 &premultiplyAlpha() {
278  assert(_animation != nullptr);
279  return _animation->premultiplyAlpha();
280  }
281 
282  void loadResources();
283  void freeResources();
284  void update();
285  void start(bool looping);
286  void pause();
287  void reset();
288  void setAnimation(const Common::String &fileName, AnimationFolder folder);
289  void setAnimation(Animation *animation);
290  void syncGame(Common::Serializer &serializer);
291 
292 private:
293  friend class AnimationDrawRequest;
294  friend class SpecialEffectDrawRequest;
295  Common::ScopedPtr<Animation> _ownedAnimation;
296  Animation *_animation = nullptr;
297  Common::Point _topLeft;
298  int16 _scale = kBaseScale;
299  int8 _order = 0;
300  Color _color = kWhite;
301 
302  bool _isPaused = true,
303  _isLooping = true;
304  uint32 _lastTime = 0;
305  int32 _frameI = -1;
306  float _depthScale = 1.0f;
307 };
308 
310 public:
311  IDrawRequest(int8 order);
312  virtual ~IDrawRequest() {}
313 
314  inline int8 order() const { return _order; }
315  virtual void draw() = 0;
316 
317 private:
318  const int8 _order;
319 };
320 
322 public:
324  Graphic &graphic,
325  bool is3D,
326  BlendMode blendMode,
327  float lodBias = 0.0f);
329  Animation *animation,
330  int32 frameI,
331  Math::Vector2d center,
332  int8 order
333  );
334 
335  void draw() override;
336 
337 private:
338  bool _is3D;
339  Animation *_animation;
340  int32 _frameI;
341  Math::Vector3d _topLeft;
342  float _scale;
343  Color _color;
344  BlendMode _blendMode;
345  float _lodBias;
346 };
347 
349 public:
351  Graphic &graphic,
352  Common::Point topLeft,
353  Common::Point bottomRight,
354  Math::Vector2d texOffset,
355  BlendMode blendMode);
356 
357  void draw() override;
358 
359 private:
360  Animation *_animation;
361  int32 _frameI;
362  Math::Vector3d _topLeft;
363  Math::Vector2d
364  _size,
365  _texOffset;
366  BlendMode _blendMode;
367 };
368 
370 public:
372  Font &font,
373  const char *text,
374  Common::Point pos,
375  int maxWidth,
376  bool centered,
377  Color color,
378  int8 order);
379 
380  inline Common::Point size() const { return { (int16)_width, (int16)_height }; }
381  void draw() override;
382 
383 private:
384  static constexpr uint kMaxLines = 12;
386 
387  Font &_font;
388  int _posY, _height, _width;
389  Color _color;
390  Common::Span<TextLine> _lines;
391  Common::Span<int> _posX;
392  TextLine _allLines[kMaxLines];
393  int _allPosX[kMaxLines];
394 };
395 
396 enum class FadeType {
397  ToBlack,
398  ToWhite
399  // Originally there was a CrossFade, but it is unused for now and thus not implemented
400 };
401 
402 enum class PermanentFadeAction {
403  Nothing,
404  SetFaded,
405  UnsetFaded
406 };
407 
409 public:
410  FadeDrawRequest(FadeType type, float value, int8 order);
411 
412  void draw() override;
413 
414 private:
415  FadeType _type;
416  float _value;
417 };
418 
419 Task *fade(Process &process, FadeType fadeType,
420  float from, float to,
421  int32 duration, EasingType easingType,
422  int8 order,
423  PermanentFadeAction permanentFadeAction = PermanentFadeAction::Nothing);
424 
426 public:
427  BorderDrawRequest(Common::Rect rect, Color color);
428 
429  void draw() override;
430 
431 private:
432  Common::Rect _rect;
433  Color _color;
434 };
435 
437 public:
438  BumpAllocator(size_t pageSize);
439  ~BumpAllocator();
440 
441  template<typename T, typename... Args>
442  inline T *allocate(Args&&... args) {
443  return new(allocateRaw(sizeof(T), alignof(T))) T(Common::forward<Args>(args)...);
444  }
445  void *allocateRaw(size_t size, size_t align);
446  void deallocateAll();
447 
448 private:
449  void allocatePage();
450 
451  const size_t _pageSize;
452  size_t _pageI = 0, _used = 0;
453  Common::Array<void *> _pages;
454 };
455 
456 class DrawQueue {
457 public:
458  DrawQueue(IRenderer *renderer);
459 
460  template<typename T, typename... Args>
461  inline void add(Args&&... args) {
462  addRequest(_allocator.allocate<T>(Common::forward<Args>(args)...));
463  }
464  inline BumpAllocator &allocator() { return _allocator; }
465 
466  void clear();
467  void setLodBias(int8 orderFrom, int8 orderTo, float newLodBias);
468  void draw();
469 
470 private:
471  void addRequest(IDrawRequest *drawRequest);
472 
473  static constexpr const uint kMaxDrawRequestsPerOrder = 50;
474  IRenderer *const _renderer;
475  BumpAllocator _allocator;
476  IDrawRequest *_requestsPerOrder[kOrderCount][kMaxDrawRequestsPerOrder] = { { 0 } };
477  uint8 _requestsPerOrderCount[kOrderCount] = { 0 };
478  float _lodBiasPerOrder[kOrderCount] = { 0 };
479 };
480 
481 }
482 
483 #endif // ALCACHOFA_GRAPHICS_H
Definition: managed_surface.h:51
Definition: graphics.h:101
Definition: alcachofa.h:45
Definition: common.h:69
Definition: str.h:59
Definition: surface.h:67
Definition: scheduler.h:84
Definition: graphics.h:369
Definition: scheduler.h:164
Definition: graphics.h:257
Definition: graphics.h:408
Definition: rect.h:524
Definition: stream.h:745
Common::Array< uint32 > _spriteOffsets
index offset per sprite and animation frame
Definition: graphics.h:173
Definition: graphics.h:184
Definition: ptr.h:572
Definition: serializer.h:79
Definition: graphics.h:74
Definition: graphics.h:321
Graphics::Surface * scale(const Graphics::Surface &srcImage, int xSize, int ySize)
Definition: graphics.h:436
Definition: graphics.h:147
T y
Definition: rect.h:49
Definition: graphics.h:60
Definition: graphics.h:456
T x
Definition: rect.h:48
Definition: rect.h:144
const Surface & rawSurface() const
Definition: managed_surface.h:192
Definition: graphics.h:309
Definition: shape.h:118
Definition: graphics.h:240
Common::Point _offset
the offset is only used for drawing the animation frame
Definition: graphics.h:131
Definition: stream.h:385
Definition: graphics.h:425
Common::Array< Graphics::ManagedSurface * > _images
will contain nullptr for fake images
Definition: graphics.h:176
Definition: graphics.h:348
Definition: graphics.h:129
Definition: span.h:691