-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSDLWrapper.h
209 lines (150 loc) · 4.51 KB
/
SDLWrapper.h
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
#pragma once
// C++ wrapper for SDL.
// This is really just for fun and to make things look more object-y,
// but there is no deeper reason at all.
#include "SDL.h"
#include <cstdint>
#include <stdexcept>
#include <optional>
#include <functional>
namespace SDL {
//---
class OkAble
{
public:
virtual bool Ok() const = 0;
};
//---
class Library : public virtual OkAble
{
public:
Library(uint32_t initFlags = SDL_INIT_EVERYTHING);
Library(const Library& src) = delete;
~Library();
bool Ok() const { return ok; }
private:
bool ok = false;
};
//---
class EventLoop
{
public:
EventLoop(Library &libSDL_);
~EventLoop();
void Run();
/// Pushes a user event (with user-defined meaning) to the event stream.
void PushUserEvent(int code, void* data1 = nullptr, void* data2 = nullptr);
/// Flag to set to true to leave Run().
bool quitRequested = false;
std::function<void(void)> OnRedraw;
std::function<void(const SDL_KeyboardEvent&)> OnKey;
std::function<void(const SDL_MouseMotionEvent&)> OnMouseMotion;
std::function<void(const SDL_MouseButtonEvent&)> OnMouseButton;
std::function<void(const SDL_UserEvent&)> OnUserEvent;
std::function<void(int, int)> OnWindowResized;
protected:
Library &libSDL;
};
//---
class Rect : public SDL_Rect
{
public:
/**
* Constructor, initializes everything to 0.
*/
Rect() { x = 0; y = 0; w = 0; h = 0; }
/**
* Constructor, sets explicitly both position (X, Y) and width and height (W, H).
*/
Rect(int x_, int y_, int w_, int h_)
{
x = x_; y = y_; w = w_; h = h_;
}
/**
* Sets the rectangle position (X, Y) and its width and height (W, H).
*/
Rect &SetXYWH(int x_, int y_, int w_, int h_)
{
x = x_; y = y_; w = w_; h = h_;
return *this;
}
operator SDL_Rect*() { return this; }
operator SDL_Rect const*() const { return this; }
};
//---
/// Base class for objects that wrap another object using its pointer.
template<class T>
class PtrWrapper : public virtual OkAble
{
public:
/// Returns a pointer to the wrapped object (null if the wrapper is invalid).
T* GetWrapped() { return wrapped; }
/// Const-variant of GetWrapped().
const T* GetWrapped() const { return wrapped; }
/// For automatical unwrapping when passing to a function that expects the pointer to the underlying object.
operator T*() { return wrapped; }
/// Const-variant of operator T*().
operator const T*() { return wrapped; }
/// Basic implementation of Ok(), checks whether the wrapped object exists.
bool Ok() const { return (wrapped != nullptr); }
protected:
/// Pointer to the wrapped object (plain pointer as it usually needs special allocation/freeing calls anyway).
T* wrapped = nullptr;
};
//---
class Surface : public PtrWrapper<SDL_Surface>
{
public:
/// Constructor, equivalent to SDL_CreateRGBSurfaceWithFormat().
Surface(int width, int height, int depth, uint32_t format);
Surface(const Surface& surface) = delete;
/// Destructor, calls Discard().
~Surface();
/// Frees the wrapped object (with SDL_FreeSurface()), leaving the wrapper invalid.
void Discard();
SDL_PixelFormat* GetFormat() const { return wrapped ? wrapped->format : nullptr; }
void* GetPixels() { return wrapped ? wrapped->pixels : 0; }
int GetWidth() const { return wrapped ? wrapped->w : 0; }
int GetHeight() const { return wrapped ? wrapped->h : 0; }
int GetPitch() const { return wrapped ? wrapped->pitch : 0; }
/// Blits a rectangle of pixels from this surface to the target surface.
bool Blit(const SDL::Rect& srcRect, SDL::Surface& dest, SDL::Rect& destRect) const;
};
//---
class Texture : public PtrWrapper<SDL_Texture>
{
public:
Texture(SDL_Renderer* renderer, Surface& src);
~Texture();
};
//---
class Renderer : public PtrWrapper<SDL_Renderer>
{
public:
Renderer(SDL_Window* window, int index, uint32_t flags);
~Renderer();
};
//---
/// Wraps SDL_Timer, allows to use a C++ lambda as the payload function.
class Timer
{
public:
enum class Type {
kOneShot = 0, ///< Triggered only once.
kRepeated = 1 ///< Triggered repeatedly in specified intervals.
};
Timer(Timer::Type type, uint32_t interval, std::function<void(void)> payload);
Timer(const Timer &src) = delete;
~Timer();
protected:
/// ID of the SDL timer.
SDL_TimerID timerId = 0;
/// SDL callback that ensures calling our payload function.
static uint32_t CallPayload(uint32_t interval, void* indirectThis);
/// The interval set in the constructor.
uint32_t interval = 0;
Timer::Type type;
/// The payload, called when the timer elapses (probably in a different thread).
std::function<void(void)> payload;
};
} // namespace SDL