1 module cat.wheel.graphics; 2 3 import std.conv : to; 4 import std.string; 5 import bindbc.sdl; 6 7 import cat.wheel.except; 8 import cat.wheel.structs; 9 10 /** 11 * Represents a window managed by SDL 12 */ 13 class Window { 14 public: 15 16 /** 17 * Constructs a new wrapped SDL_Window struct. 18 * Params: 19 * title = The title of the window, default "" 20 * x = The initial x position of the window on the screen, from the left 21 * y = The initial y position of the window on the screen, from the top 22 * w = The initial width of the window 23 * h = The initial height of the window 24 * flags = A number of window flags to initialise the window with 25 */ 26 this( 27 string title = "", 28 int x = SDL_WINDOWPOS_UNDEFINED, 29 int y = SDL_WINDOWPOS_UNDEFINED, 30 int w = 0, 31 int h = 0, 32 SDL_WindowFlags flags = cast(SDL_WindowFlags) 0) 33 { 34 _window = SDL_CreateWindow(title.toStringz(), x, y, w, h, flags).objCheck; 35 } 36 37 ~this() nothrow { 38 SDL_DestroyWindow(_window); 39 } 40 41 /** 42 * The x position of the managed window 43 */ 44 @property int x() nothrow { 45 int *x; 46 SDL_GetWindowPosition(_window, x, null); 47 return *x; 48 } 49 50 /// 51 @property void x(int x) nothrow { 52 SDL_SetWindowPosition(_window, x, this.y); 53 } 54 55 /** 56 * The y position of the managed window 57 */ 58 @property int y() nothrow { 59 int *y; 60 SDL_GetWindowPosition(_window, null, y); 61 return *y; 62 } 63 64 /// 65 @property void y(int y) nothrow { 66 SDL_SetWindowPosition(_window, this.x, y); 67 } 68 69 /** 70 * The width of the managed window 71 */ 72 @property int width() nothrow { 73 int *w; 74 SDL_GetWindowSize(_window, w, null); 75 return *w; 76 } 77 78 /// 79 @property void width(int w) nothrow { 80 SDL_SetWindowSize(_window, w, height); 81 } 82 83 /** 84 * The height of the managed window 85 */ 86 @property int height() nothrow { 87 int *h; 88 SDL_GetWindowSize(_window, null, h); 89 return *h; 90 } 91 92 /// 93 @property void height(int h) nothrow { 94 SDL_SetWindowSize(_window, width, h); 95 } 96 97 /** 98 * The title of the managed window 99 */ 100 @property string title() nothrow { 101 return _title; 102 } 103 104 /// 105 @property void title(string t) nothrow { 106 _title = t; 107 SDL_SetWindowTitle(_window, _title.toStringz()); 108 } 109 110 /** 111 * The wrapped window 112 */ 113 @property SDL_Window* window() nothrow { 114 return _window; 115 } 116 117 private: 118 SDL_Window* _window; 119 string _title; 120 } 121 122 /// Wrapper for an SDL_Surface 123 struct Surface { 124 SDL_Surface *sdl; 125 126 ~this() { 127 if (sdl != null) SDL_FreeSurface(sdl); 128 } 129 } 130 131 class Graphics { 132 public: 133 134 /** 135 * Creates a new wrapped SDL_Renderer 136 * Params: 137 * w = The window to create the renderer for 138 * flags = The flags to look for when initialising a renderer 139 * index = The index of the renderer to initialise, leave blank (-1) for the first matching the specified flags 140 */ 141 this(Window w, SDL_RendererFlags flags = cast(SDL_RendererFlags) 0, int index = -1) { 142 _renderer = SDL_CreateRenderer(w._window, index, flags).objCheck; 143 } 144 145 /** 146 * Creates a software SDL renderer 147 * Params: 148 * s = The surface for this renderer to draw to 149 */ 150 this(Surface s) { 151 _renderer = SDL_CreateSoftwareRenderer(s.sdl).objCheck; 152 } 153 154 ~this() { 155 SDL_DestroyRenderer(_renderer); 156 } 157 158 void drawPoint(Vector2 pos) { 159 SDL_RenderDrawPoint(_renderer, pos.x, pos.y).check; 160 } 161 162 void drawPoints(Vector2[] points) { 163 SDL_Point[] sdl = new SDL_Point[points.length]; 164 for (int i = 0; i < points.length; i++) { 165 sdl[i] = cast(SDL_Point) points[i]; 166 } 167 168 SDL_RenderDrawPoints(_renderer, sdl.ptr, points.length.to!int).check; 169 } 170 171 void drawLine(Vector2 pos1, Vector2 pos2) { 172 SDL_RenderDrawLine(_renderer, pos1.x, pos1.y, pos2.x, pos2.y).check; 173 } 174 175 void drawLines(Vector2[2][] lines) { 176 SDL_Point[] sdl = new SDL_Point[lines.length * 2]; 177 for (int i = 0; i < lines.length * 2; i++) { 178 sdl[i] = cast(SDL_Point) lines[i/2][i%2]; 179 } 180 181 SDL_RenderDrawLines(_renderer, sdl.ptr, sdl.length.to!int).check; 182 } 183 184 void drawRect(Rect rect) { 185 const(SDL_Rect) c = rect.sdl; 186 SDL_RenderDrawRect(_renderer, &c).check; 187 } 188 189 void drawRects(Rect[] rects) { 190 SDL_Rect[] sdl; 191 for (int i = 0; i < rects.length; i++) { 192 sdl[i] = rects[i].sdl; 193 } 194 195 const(SDL_Rect)[] sdlc = sdl; 196 SDL_RenderDrawRects(_renderer, sdlc.ptr, sdl.length.to!int).check; 197 } 198 199 void fillRect(Rect rect) { 200 const(SDL_Rect) c = rect.sdl; 201 SDL_RenderFillRect(_renderer, &c).check; 202 } 203 204 void fillRects(Rect[] rects) { 205 SDL_Rect[] sdl; 206 for (int i = 0; i < rects.length; i++) { 207 sdl[i] = rects[i].sdl; 208 } 209 210 const(SDL_Rect)[] sdlc = sdl; 211 SDL_RenderFillRects(_renderer, sdlc.ptr, sdl.length.to!int).check; 212 } 213 214 void drawTexture(SDL_Texture* t, Rect src, Rect dest) { 215 SDL_RenderCopy(_renderer, t, &src.sdl, &dest.sdl); 216 } 217 218 SDL_Texture* createTextureFrom(Surface s) { 219 return SDL_CreateTextureFromSurface(_renderer, s.sdl).objCheck; 220 } 221 222 void render() { 223 SDL_RenderPresent(_renderer); 224 } 225 226 void clear() { 227 SDL_RenderClear(_renderer).check; 228 } 229 230 /// 231 @property clipRect() nothrow { 232 return _clipRect; 233 } 234 235 /// 236 @property clipRect(Rect clip) nothrow { 237 _clipRect = clip; 238 return SDL_RenderSetClipRect(_renderer, &_clipRect.sdl); 239 } 240 241 /// 242 @property color() nothrow { 243 return _drawColour; 244 } 245 246 /// 247 @property color(Color c) nothrow { 248 _drawColour = c; 249 return SDL_SetRenderDrawColor(_renderer, _drawColour.r, _drawColour.g, _drawColour.b, _drawColour.a); 250 } 251 252 /// The renderer 253 @property renderer() nothrow { 254 return _renderer; 255 } 256 257 private: 258 SDL_Renderer* _renderer; 259 260 Rect _clipRect; 261 Color _drawColour; 262 }