1 /**
2  * LibSDL2
3  */
4 module d2d.sdl2;
5 
6 public import derelict.sdl2.sdl;
7 public import derelict.sdl2.image;
8 public import derelict.sdl2.mixer;
9 public import derelict.sdl2.ttf;
10 public import derelict.sdl2.net;
11 public import d2d.math;
12 public import d2d.sdl2.Color;
13 public import d2d.sdl2.EventHandler;
14 public import d2d.sdl2.Font;
15 public import d2d.sdl2.InputSource;
16 public import d2d.sdl2.Keyboard;
17 public import d2d.sdl2.Mouse;
18 public import d2d.sdl2.Polygon;
19 public import d2d.sdl2.Renderer;
20 public import d2d.sdl2.Sound;
21 public import d2d.sdl2.Surface;
22 public import d2d.sdl2.Texture;
23 public import d2d.sdl2.Window;
24 
25 import std.conv;
26 
27 /**
28  * Loads base DerelictSDL2
29  * Function can be called many times, but load only happens once
30  */
31 void loadLibSDL(SharedLibVersion ver = SharedLibVersion(2, 0, 2)) {
32     static bool hasBeenLoaded;
33     if (hasBeenLoaded)
34         return;
35     hasBeenLoaded = true;
36     DerelictSDL2.load(ver);
37     ensureSafe(SDL_Init(SDL_INIT_EVERYTHING));
38 }
39 
40 /**
41  * Loads SDL_Image libraries
42  * Function can be called many times, but load only happens once
43  */
44 void loadLibImage() {
45     static bool hasBeenLoaded;
46     if (hasBeenLoaded)
47         return;
48     hasBeenLoaded = true;
49     DerelictSDL2Image.load();
50     IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF);
51 }
52 
53 /**
54  * Loads SDL_Mixer libraries
55  * Function can be called many times, but load only happens once
56  */
57 void loadLibMixer() {
58     static bool hasBeenLoaded;
59     if (hasBeenLoaded)
60         return;
61     hasBeenLoaded = true;
62     DerelictSDL2Mixer.load();
63     ensureSafe(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
64             MIX_DEFAULT_CHANNELS, 4096));
65 }
66 
67 /**
68  * Loads SDL_ttf libraries
69  * Function can be called many times, but load only happens once
70  */
71 void loadLibTTF() {
72     static bool hasBeenLoaded;
73     if (hasBeenLoaded)
74         return;
75     hasBeenLoaded = true;
76     DerelictSDL2ttf.load();
77     ensureSafe(TTF_Init());
78 }
79 
80 /**
81  * Takes in an integer output from an SDL function and then throws an error if the integer isn't 0
82  * Because SDL doesn't throw errors, but rather returns codes, 0 means a successful finish to a function
83  * Any non-zero output from a function means that SDL encountered an error, and this function will throw upon an SDL error
84  */
85 void ensureSafe(int output) {
86     if (output != 0) {
87         immutable string errorMessage = SDL_GetError().to!string;
88         SDL_ClearError();
89         throw new Exception(errorMessage);
90     }
91 }
92 
93 /**
94  * Takes in an object from an SDL function and then throws an error if the object is null
95  * Because SDL doesn't throw errors upon failed object creation, but constructs the object as a null, a non-null object means a successful creation
96  * Any null creation means that SDL encountered an error, and this function will throw an SDL error accordingly
97  */
98 T ensureSafe(T)(T output) {
99     ensureSafe((output is null).to!int);
100     return output;
101 }
102 
103 //Completely pointless temporary variables to get math objects into SDL structs
104 private SDL_Point tempPoint;
105 private SDL_Rect tempRect;
106 
107 /**
108  * Gets a 2d vector as an SDL_Point*
109  */
110 SDL_Point* handle(iVector vec) {
111     tempPoint = SDL_Point(vec.x, vec.y);
112     return &tempPoint;
113 }
114 
115 /**
116  * Gets a 2d axis aligned bounding box as an SDL_Rect*
117  */
118 SDL_Rect* handle(iRectangle rec) {
119     tempRect = SDL_Rect(rec.initialPoint.x, rec.initialPoint.y, rec.extent.x, rec.extent.y);
120     return &tempRect;
121 }
122 
123 /**
124  * Gets a 2d axis aligned bounding box as a polygon
125  */
126 Polygon!(T, 4) toPolygon(T)(AxisAlignedBoundingBox!(T, 2) rec) {
127     return new Polygon!(T, 4)(rec.topLeft, rec.topRight, rec.bottomRight, rec.bottomLeft);
128 }
129 
130 //Aliases 2d vectors to their commonly used presets
131 alias iVector = Vector!(int, 2);
132 alias dVector = Vector!(double, 2);
133 alias fVector = Vector!(float, 2);
134 
135 //Aliases 2d axis aligned bounding boxes to their commonly used presets
136 alias iRectangle = AxisAlignedBoundingBox!(int, 2);
137 alias dRectangle = AxisAlignedBoundingBox!(double, 2);
138 alias fRectangle = AxisAlignedBoundingBox!(float, 2);
139 
140 //Aliases 2d segments to their commonly used presets
141 alias iSegment = Segment!(int, 2);
142 alias dSegment = Segment!(double, 2);
143 alias fSegment = Segment!(float, 2);
144 
145 //Aliases 2d bezier curves to their commonly used presets
146 alias iBezierCurve = BezierCurve!(int, 2);
147 alias dBezierCurve = BezierCurve!(double, 2);
148 alias fBezierCurve = BezierCurve!(float, 2);