52b19708c084426b0a9221dad9ace3c2019ad3ab
[nit.git] / lib / sdl2 / sdl2_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Basic SDL 2 features
18 module sdl2_base is pkgconfig "sdl2"
19
20 in "C header" `{
21 #include <SDL2/SDL.h>
22 `}
23
24 redef class Sys
25 # Access to the global methods of `sdl2`
26 var sdl = new SDL is lazy
27 end
28
29 # Holds the global methods of `sdl2`
30 class SDL
31 super Finalizable
32
33 # Get the `SDL` singleton
34 new do return once new SDL.internal
35
36 # TODO make this private and only called through `sys.sdl`
37 init internal do end
38
39 # Initialize the given SDL `subsystems`
40 fun initialize(subsystems: SDLInitFlags): Bool `{ return SDL_Init(subsystems); `}
41
42 # Returns the latest SDL error
43 #
44 # After calling this method, you should also call `clear_error`.
45 fun error: NativeString `{ return (char*)SDL_GetError(); `}
46
47 # Clear the SDL error
48 fun clear_error `{ SDL_ClearError(); `}
49
50 # Quit SDL
51 fun quit `{ SDL_Quit(); `}
52
53 # Was SDL initialized?
54 fun was_initialized: Bool do return not initialized_subsystems((new SDLInitFlags).everything).is_empty
55
56 # What SDL subsystems are initialized? You can use a mask of `subsystems` to restrict the query.
57 #
58 # Returns the flags of the initialized subsystems.
59 fun initialized_subsystems(subsystems: SDLInitFlags): SDLInitFlags `{ return SDL_WasInit(subsystems); `}
60
61 # The number of CPU on the system
62 fun cpu_count: Int `{ return SDL_GetCPUCount(); `}
63
64 # Amount of RAM configured on the system
65 fun system_ram: Int `{ return SDL_GetSystemRAM(); `}
66
67 # Show a simple message box
68 fun show_simple_message_box(level: SDLMessageBoxFlags, title, content: NativeString) `{
69 SDL_ShowSimpleMessageBox(level, title, content, NULL);
70 `}
71
72 redef fun finalize do if was_initialized then quit
73
74 # Function that should be called from the SDL main method
75 #
76 # This method should not normally be used, refer to the SDL source code
77 # before use.
78 fun set_main_ready `{ SDL_SetMainReady(); `}
79 end
80
81 # Flags for `sys.sdl.initialize` and related methods
82 extern class SDLInitFlags `{ Uint32 `}
83 # Get the default empty flag set
84 new `{ return 0; `}
85
86 # Add the timer subsystem
87 fun timer: SDLInitFlags `{ return self | SDL_INIT_TIMER; `}
88
89 # Add the audio subsystem
90 fun audio: SDLInitFlags `{ return self | SDL_INIT_AUDIO; `}
91
92 # Add the video subsystem
93 fun video: SDLInitFlags `{ return self | SDL_INIT_VIDEO; `}
94
95 # Add the joystick subsystem
96 #
97 # Implied by `gamecontroller`
98 fun joystick: SDLInitFlags `{ return self | SDL_INIT_JOYSTICK; `}
99
100 # Add the haptic subsystem
101 fun haptic: SDLInitFlags `{ return self | SDL_INIT_HAPTIC; `}
102
103 # Add the gamecontroller subsystem
104 fun gamecontroller: SDLInitFlags `{ return self | SDL_INIT_GAMECONTROLLER; `}
105
106 # Add the events subsystem
107 #
108 # Implied by `video` and `joystick`
109 fun events: SDLInitFlags `{ return self | SDL_INIT_EVENTS; `}
110
111 # Add all subsystems
112 fun everything: SDLInitFlags `{ return self | SDL_INIT_EVERYTHING; `}
113
114 # Is this flag set empty?
115 fun is_empty: Bool `{ return self == 0; `}
116
117 # TODO add all other is_
118 end
119
120 # A window created by SDL
121 extern class SDLWindow `{ SDL_Window * `}
122 # Create a window with the given `title`, `width` and `height`, also apply the `flags`
123 new (title: NativeString, width, height: Int, flags: SDLWindowFlags) `{
124 return SDL_CreateWindow(title,
125 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
126 width, height, flags);
127 `}
128
129 # Has this window been correctly initialized?
130 fun initialized: Bool do return not address_is_null
131
132 # Destroy this window
133 fun destroy `{ SDL_DestroyWindow(self); `}
134
135 # Get the `SDLWindowFlags` describing the status of the window
136 fun flags: SDLWindowFlags `{ return SDL_GetWindowFlags(self); `}
137
138 # Show a simple message box
139 #
140 # Similar to `sys.sdl.show_simple_message_box` but attached to this window
141 fun show_simple_message_box(level: SDLMessageBoxFlags, title, content: NativeString) `{
142 SDL_ShowSimpleMessageBox(level, title, content, self);
143 `}
144
145 # Set the icon of this window
146 fun icon=(icon: SDLSurface) `{ SDL_SetWindowIcon(self, icon); `}
147 end
148
149 # Flags for `SDLWindow::new` and returned by `SDLWindow::flags`
150 extern class SDLWindowFlags `{ Uint32 `}
151 # Get the default empty flag set
152 new `{ return 0; `}
153
154 # Add the flag requesting a fullscreen window
155 fun fullscreen: SDLWindowFlags `{ return self | SDL_WINDOW_FULLSCREEN; `}
156
157 # Add the flag requesting a fullscreen window for the current desktop
158 fun fullscreen_desktop: SDLWindowFlags `{ return self | SDL_WINDOW_FULLSCREEN_DESKTOP; `}
159
160 # Add the flag requesting a window usable with an OpenGL context
161 fun opengl: SDLWindowFlags `{ return self | SDL_WINDOW_OPENGL; `}
162
163 # Add the flag requesting a hidden window
164 fun hidden: SDLWindowFlags `{ return self | SDL_WINDOW_HIDDEN; `}
165
166 # Add the flag requesting a borderless window
167 fun borderless: SDLWindowFlags `{ return self | SDL_WINDOW_BORDERLESS; `}
168
169 # Add the flag requesting a resizable window
170 fun resizable: SDLWindowFlags `{ return self | SDL_WINDOW_RESIZABLE; `}
171
172 # Add the flag requesting a minimized window
173 fun minimized: SDLWindowFlags `{ return self | SDL_WINDOW_MINIMIZED; `}
174
175 # Add the flag requesting a maximimez window
176 fun maximized: SDLWindowFlags `{ return self | SDL_WINDOW_MAXIMIZED; `}
177
178 # Add the flag to grab the input focus
179 fun input_grabbed: SDLWindowFlags `{ return self | SDL_WINDOW_INPUT_GRABBED; `}
180
181 # Add the flag to request a window using the system High-DPI mode
182 fun allow_highdpi: SDLWindowFlags `{
183 #if SDL_VERSION_ATLEAST(2, 0, 2)
184 return self | SDL_WINDOW_ALLOW_HIGHDPI;
185 #else
186 return self;
187 #endif
188 `}
189
190 # Is the window shown?
191 #
192 # Can only be queried because it is ignored by `SDLWindow::new`
193 fun is_shown: Bool `{ return self & SDL_WINDOW_SHOWN; `}
194
195 # Does the window has the input focus?
196 #
197 # Can only be queried because it is ignored by `SDLWindow::new`
198 fun has_input_focus: Bool `{ return self & SDL_WINDOW_INPUT_FOCUS; `}
199
200 # Does the window has the mouse focus?
201 #
202 # Can only be queried because it is ignored by `SDLWindow::new`
203 fun has_mouse_focus: Bool `{ return self & SDL_WINDOW_MOUSE_FOCUS; `}
204
205 # TODO add all other `is_` methods, as needed
206 end
207
208 redef universal Int
209 # Suspend execution for `self` milliseconds
210 fun delay `{ SDL_Delay(self); `}
211 end
212
213 # A renderer, maybe software or hardware
214 extern class SDLRenderer `{ SDL_Renderer * `}
215 # Create a new `SDLRenderer` for the `window` using the `index`th renderer according to `flags`
216 #
217 # Use an `index` of `-1` to get the default renderer for the given flags.
218 new (window: SDLWindow, index: Int, flags: SDLRendererFlags) `{
219 return SDL_CreateRenderer(window, index, flags);
220 `}
221
222 # Create a new software `SDLRenderer`
223 new software(surface: SDLSurface) `{
224 return SDL_CreateSoftwareRenderer(surface);
225 `}
226
227 # Destroy this renderer
228 fun destroy `{ SDL_DestroyRenderer(self); `}
229
230 # Clear the rendering target with the current `draw_color`
231 fun clear `{ SDL_RenderClear(self); `}
232
233 # Copy the rectangle at `src` from `texture` to fill the `dst` at the rendering `target`
234 #
235 # If `dst` has a different size than `src`, the image will be stretched.
236 #
237 # If `src == null` the whole source texture will be drawn, and if
238 # `dst == null` then the texture will fill the rendering `target`.
239 fun copy(texture: SDLTexture, src, dst: nullable SDLRect)
240 do
241 if src == null then src = new SDLRect.nil
242 if dst == null then dst = new SDLRect.nil
243
244 native_copy(texture, src, dst)
245 end
246
247 private fun native_copy(texture: SDLTexture, src, dst: SDLRect) `{
248 SDL_RenderCopy(self, texture, src, dst);
249 `}
250
251 # Update the screen with all rendering since the previous call
252 fun present `{ SDL_RenderPresent(self); `}
253
254 # Get the `SDLRendererInfo` for this renderer
255 fun info_copy(out: SDLRendererInfo) `{ SDL_GetRendererInfo(self, out); `}
256
257 # Set the drawing color
258 fun draw_color=(val: SDLColor) `{
259 SDL_SetRenderDrawColor(self, val->r, val->g, val->b, val->a);
260 `}
261
262 # Get the drawing color of this renderer
263 #
264 # The returned `SDLColor` is malloced here and must be freed by the called.
265 # For a more efficient usage, it is recommended to use instead `draw_color_copy`.
266 fun draw_color: SDLColor
267 do
268 var color = new SDLColor.malloc
269 draw_color_copy color
270 return color
271 end
272
273 # Copy the drawing color of this renderer in `color`
274 fun draw_color_copy(color: SDLColor) `{
275 SDL_GetRenderDrawColor(self, &color->r, &color->g, &color->b, &color->a);
276 `}
277
278 # Fill a rectangle with the current `draw_color`
279 #
280 # If `rect.address_is_null` then fills the entire screen.
281 fun fill_rect(rect: SDLRect) `{ SDL_RenderFillRect(self, rect); `}
282
283 # Draw a rectangle with the current `draw_color`
284 fun draw_rect(rect: SDLRect) `{ SDL_RenderDrawRect(self, rect); `}
285
286 # Draw a point with the current `draw_color`
287 fun draw_point(x, y: Int) `{ SDL_RenderDrawPoint(self, x, y); `}
288
289 # Draw a line with the current `draw_color`
290 fun draw_line(x1, y1, x2, y2: Int) `{ SDL_RenderDrawLine(self, x1, y1, x2, y2); `}
291
292 # Set the viewport of this renderer
293 fun viewport=(rect: SDLRect) `{ SDL_RenderSetViewport(self, rect); `}
294
295 # Get the rendering target of this renderer
296 fun target: SDLTexture `{ return SDL_GetRenderTarget(self); `}
297
298 # Set the rendering target of this renderer
299 fun target=(val: SDLTexture) `{ SDL_SetRenderTarget(self, val); `}
300
301 # TODO add other renderer related methods:
302 #
303 # draw_rects
304 # draw_lines
305 end
306
307 # A color
308 extern class SDLColor `{ SDL_Color *`}
309 # Allocate the memory for a new `SDLColor`, it must then be freed with `free`
310 new malloc `{ return malloc(sizeof(SDL_Color)); `}
311
312 # Allocate the memory for a new `SDLColor` and fill it with `r`, `g`, `b` and `a`
313 #
314 # As with `malloc`, the new instances must then be freed with `free`.
315 new (r, g, b, a: Int)
316 do
317 var color = new SDLColor.malloc
318 color.set(r, g, b, a)
319 return color
320 end
321
322 # Set this instance's `r`, `g`, `b` and `a`
323 fun set(r, g, b, a: Int)
324 do
325 self.r = r
326 self.g = g
327 self.b = b
328 self.a = a
329 end
330
331 # The red component of this color `[0..255]`
332 fun r: Int `{ return self->r; `}
333
334 # Set the red component of this color `[0..255]`
335 fun r=(val: Int) `{ self->r = val; `}
336
337 # The green component of this color `[0..255]`
338 fun g: Int `{ return self->g; `}
339
340 # Set the green component of this color `[0..255]`
341 fun g=(val: Int) `{ self->g = val; `}
342
343 # The blue component of this color `[0..255]`
344 fun b: Int `{ return self->b; `}
345
346 # Set the blue component of this color `[0..255]`
347 fun b=(val: Int) `{ self->b = val; `}
348
349 # The alpha component of this color `[0..255]`
350 fun a: Int `{ return self->a; `}
351
352 # Set the ralpha component of this color `[0..255]`
353 fun a=(val: Int) `{ self->a = val; `}
354
355 # TODO implement the related `SDL_Palette` and related methods
356 end
357
358 # Flags for `SDLRenderer::new`
359 extern class SDLRendererFlags `{ Uint32 `}
360 # Get the default empty flag set
361 new `{ return 0; `}
362
363 # Add the flag to request a software renderer
364 fun software: SDLRendererFlags `{ return self | SDL_RENDERER_SOFTWARE; `}
365
366 # Add the flag to request an accelerated renderer
367 #
368 # This is the default option.
369 fun accelerated: SDLRendererFlags `{ return self | SDL_RENDERER_ACCELERATED; `}
370
371 # Add the flag to request a renderer where `SDLRenderer::present` is synchronized with the refresh rate
372 fun presentvsync: SDLRendererFlags `{ return self | SDL_RENDERER_PRESENTVSYNC; `}
373
374 # Add the flag to request a renderer able to render to a texture
375 fun targettexture: SDLRendererFlags `{ return self | SDL_RENDERER_TARGETTEXTURE; `}
376 end
377
378 # A bitmap surface
379 extern class SDLSurface `{ SDL_Surface * `}
380
381 # Load the BMP file at `path`
382 new load_bmp(path: NativeString) `{ return SDL_LoadBMP(path); `}
383
384 redef fun free `{ SDL_FreeSurface(self); `}
385
386 # Save this texture to a BMP file
387 fun save_bmp(path: NativeString) `{ SDL_SaveBMP(self, path); `}
388 end
389
390 # A loaded bitmap texture
391 extern class SDLTexture `{ SDL_Texture * `}
392 # Get a `SDLTexture` from a `surface`, for a given `renderer`
393 new from_surface(renderer: SDLRenderer, surface: SDLSurface) `{
394 return SDL_CreateTextureFromSurface(renderer, surface);
395 `}
396
397 # Destroy this texture
398 fun destroy `{ SDL_DestroyTexture(self); `}
399
400 # Width of this texture
401 fun width: Int `{
402 int val;
403 SDL_QueryTexture(self, NULL, NULL, &val, NULL);
404 return val;
405 `}
406
407 # Height of this texture
408 fun height: Int `{
409 int val;
410 SDL_QueryTexture(self, NULL, NULL, NULL, &val);
411 return val;
412 `}
413
414 # TODO other queries: format and access
415 end
416
417 # A rectangle
418 extern class SDLRect `{SDL_Rect *`}
419 # Get a null rectangle (on the C side), should be used only internally
420 new nil `{ return NULL; `}
421
422 # Allocate the memory for a new `SDLRect`, it must then be freed with `free`
423 new malloc`{ return malloc(sizeof(SDL_Rect)); `}
424
425 # Allocate the memory for a new `SDLRect` and fill it with `x`, `y`, `w` and `h`
426 #
427 # As with `malloc`, the new instances must then be freed with `free`.
428 new (x, y, w, h: Int)
429 do
430 var rect = new SDLRect.malloc
431 rect.set(x, y, w, h)
432 return rect
433 end
434
435 # Set this instance's `x`, `y`, `w` and `h`
436 fun set(x, y, w, h: Int)
437 do
438 self.x = x
439 self.y = y
440 self.w = w
441 self.h = h
442 end
443
444 # X coordinate of the top left corner
445 fun x: Int `{ return self->x; `}
446
447 # Set the X coordinate of the top left corner
448 fun x=(val: Int) `{ self->x = val; `}
449
450 # Y coordinate of the top left corner
451 fun y: Int `{ return self->y; `}
452
453 # Set the Y coordinate of the top left corner
454 fun y=(val: Int) `{ self->y = val; `}
455
456 # Width of this rectangle
457 fun w: Int `{ return self->w; `}
458
459 # Set the width of this rectangle
460 fun w=(val: Int) `{ self->w = val; `}
461
462 # Height of this rectangle
463 fun h: Int `{ return self->h; `}
464
465 # Set the height of this rectangle
466 fun h=(val: Int) `{ self->h = val; `}
467
468 # TODO implement other `SDLRect` related methods:
469 #
470 # SDL_EnclosePoints
471 # SDL_HasIntersection
472 # SDL_IntersectRect
473 # SDL_IntersectRectAndLine
474 # SDL_PointInRect
475 # SDL_RectEmpty
476 # SDL_RectEquals
477 # SDL_UnionRect
478 end
479
480 # A point with `x` and `y`
481 extern class SDLPoint `{SDL_Point *`}
482 # Get a null rectangle (on the C side), should be used only internally
483 new nil `{ return NULL; `}
484
485 # Allocate the memory for a new `SDLPoint`, it must the be freed with `free`
486 new malloc`{ return malloc(sizeof(SDL_Point)); `}
487
488 # Allocate the memory for a new `SDLPoint` and fill it with `x` and `y`
489 #
490 # As with `malloc`, the new instances must the be freed with `free`.
491 new (x, y: Int) do
492 var point = new SDLPoint.malloc
493 point.x = x
494 point.y = y
495 return point
496 end
497
498 # X coordinate of this point
499 fun x: Int `{ return self->x; `}
500
501 # Set the X coordinate of this point
502 fun x=(val: Int) `{ self->x = val; `}
503
504 # Y coordinate of this point
505 fun y: Int `{ return self->y; `}
506
507 # Set the Y coordinate of this point
508 fun y=(val: Int) `{ self->y = val; `}
509 end
510
511 # Flag to set the icon in `sys.sdl.show_simple_message_box` and `SDLWindow::show_simple_message_box`
512 extern class SDLMessageBoxFlags `{ Uint32 `}
513 # Request the error icon
514 new error `{ return SDL_MESSAGEBOX_ERROR; `}
515
516 # Request the warning icon
517 new warning `{ return SDL_MESSAGEBOX_WARNING; `}
518
519 # Request the information icon
520 new information `{ return SDL_MESSAGEBOX_INFORMATION; `}
521 end
522
523 # Information on a `SDLRenderer`
524 extern class SDLRendererInfo `{ SDL_RendererInfo * `}
525 # Allocate the memory for a new `SDLRenderer`, it must then be freed with `free`
526 new malloc `{ return malloc(sizeof(SDL_RendererInfo)); `}
527
528 # Name of the renderer's driver
529 fun name: NativeString `{ return (char*)self->name; `}
530
531 # Maximum texture width supported by the renderer
532 fun max_texture_width: Int `{ return self->max_texture_width; `}
533
534 # Maximum texture height supported by the renderer
535 fun max_texture_height: Int `{ return self->max_texture_height; `}
536 end