Merge: Nitsmell : Adding new code smells and print console updated
[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`, returns `false` on error
40 fun initialize(subsystems: SDLInitFlags): Bool `{ return SDL_Init(subsystems) == 0; `}
41
42 # Returns the latest SDL error
43 #
44 # After calling this method, you should also call `clear_error`.
45 fun error: CString `{ 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: CString) `{
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
80 # Show or hide the cursor
81 fun show_cursor=(val: Bool) `{ SDL_ShowCursor(val? SDL_ENABLE: SDL_DISABLE); `}
82
83 # Is the cursor visible?
84 fun show_cursor: Bool `{ return SDL_ShowCursor(SDL_QUERY); `}
85
86 # Collect only relative mouse events and hide cursor
87 #
88 # Check `relative_mouse_mode` to see if the mode could be applied,
89 # if not, see `error`.
90 fun relative_mouse_mode=(value: Bool) `{
91 SDL_SetRelativeMouseMode(value);
92 `}
93
94 # Hide cursor and collect only relative mouse events?
95 fun relative_mouse_mode: Bool `{
96 return SDL_GetRelativeMouseMode();
97 `}
98 end
99
100 # Flags for `sys.sdl.initialize` and related methods
101 extern class SDLInitFlags `{ Uint32 `}
102 # Get the default empty flag set
103 new `{ return 0; `}
104
105 # Add the timer subsystem
106 fun timer: SDLInitFlags `{ return self | SDL_INIT_TIMER; `}
107
108 # Add the audio subsystem
109 fun audio: SDLInitFlags `{ return self | SDL_INIT_AUDIO; `}
110
111 # Add the video subsystem
112 fun video: SDLInitFlags `{ return self | SDL_INIT_VIDEO; `}
113
114 # Add the joystick subsystem
115 #
116 # Implied by `gamecontroller`
117 fun joystick: SDLInitFlags `{ return self | SDL_INIT_JOYSTICK; `}
118
119 # Add the haptic subsystem
120 fun haptic: SDLInitFlags `{ return self | SDL_INIT_HAPTIC; `}
121
122 # Add the gamecontroller subsystem
123 fun gamecontroller: SDLInitFlags `{ return self | SDL_INIT_GAMECONTROLLER; `}
124
125 # Add the events subsystem
126 #
127 # Implied by `video` and `joystick`
128 fun events: SDLInitFlags `{ return self | SDL_INIT_EVENTS; `}
129
130 # Add all subsystems
131 fun everything: SDLInitFlags `{ return self | SDL_INIT_EVERYTHING; `}
132
133 # Is this flag set empty?
134 fun is_empty: Bool `{ return self == 0; `}
135
136 # TODO add all other is_
137 end
138
139 # A window created by SDL
140 extern class SDLWindow `{ SDL_Window * `}
141 # Create a window with the given `title`, `width` and `height`, also apply the `flags`
142 new (title: CString, width, height: Int, flags: SDLWindowFlags) `{
143 return SDL_CreateWindow(title,
144 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
145 width, height, flags);
146 `}
147
148 # Has this window been correctly initialized?
149 fun initialized: Bool do return not address_is_null
150
151 # Destroy this window
152 fun destroy `{ SDL_DestroyWindow(self); `}
153
154 # Get the `SDLWindowFlags` describing the status of the window
155 fun flags: SDLWindowFlags `{ return SDL_GetWindowFlags(self); `}
156
157 # Show a simple message box
158 #
159 # Similar to `sys.sdl.show_simple_message_box` but attached to this window
160 fun show_simple_message_box(level: SDLMessageBoxFlags, title, content: CString) `{
161 SDL_ShowSimpleMessageBox(level, title, content, self);
162 `}
163
164 # Set the icon of this window
165 fun icon=(icon: SDLSurface) `{ SDL_SetWindowIcon(self, icon); `}
166 end
167
168 # Flags for `SDLWindow::new` and returned by `SDLWindow::flags`
169 extern class SDLWindowFlags `{ Uint32 `}
170 # Get the default empty flag set
171 new `{ return 0; `}
172
173 # Add the flag requesting a fullscreen window
174 fun fullscreen: SDLWindowFlags `{ return self | SDL_WINDOW_FULLSCREEN; `}
175
176 # Add the flag requesting a fullscreen window for the current desktop
177 fun fullscreen_desktop: SDLWindowFlags `{ return self | SDL_WINDOW_FULLSCREEN_DESKTOP; `}
178
179 # Add the flag requesting a window usable with an OpenGL context
180 fun opengl: SDLWindowFlags `{ return self | SDL_WINDOW_OPENGL; `}
181
182 # Add the flag requesting a hidden window
183 fun hidden: SDLWindowFlags `{ return self | SDL_WINDOW_HIDDEN; `}
184
185 # Add the flag requesting a borderless window
186 fun borderless: SDLWindowFlags `{ return self | SDL_WINDOW_BORDERLESS; `}
187
188 # Add the flag requesting a resizable window
189 fun resizable: SDLWindowFlags `{ return self | SDL_WINDOW_RESIZABLE; `}
190
191 # Add the flag requesting a minimized window
192 fun minimized: SDLWindowFlags `{ return self | SDL_WINDOW_MINIMIZED; `}
193
194 # Add the flag requesting a maximimez window
195 fun maximized: SDLWindowFlags `{ return self | SDL_WINDOW_MAXIMIZED; `}
196
197 # Add the flag to grab the input focus
198 fun input_grabbed: SDLWindowFlags `{ return self | SDL_WINDOW_INPUT_GRABBED; `}
199
200 # Add the flag to request a window using the system High-DPI mode
201 fun allow_highdpi: SDLWindowFlags `{
202 #if SDL_VERSION_ATLEAST(2, 0, 2)
203 return self | SDL_WINDOW_ALLOW_HIGHDPI;
204 #else
205 return self;
206 #endif
207 `}
208
209 # Is the window shown?
210 #
211 # Can only be queried because it is ignored by `SDLWindow::new`
212 fun is_shown: Bool `{ return self & SDL_WINDOW_SHOWN; `}
213
214 # Does the window has the input focus?
215 #
216 # Can only be queried because it is ignored by `SDLWindow::new`
217 fun has_input_focus: Bool `{ return self & SDL_WINDOW_INPUT_FOCUS; `}
218
219 # Does the window has the mouse focus?
220 #
221 # Can only be queried because it is ignored by `SDLWindow::new`
222 fun has_mouse_focus: Bool `{ return self & SDL_WINDOW_MOUSE_FOCUS; `}
223
224 # TODO add all other `is_` methods, as needed
225 end
226
227 redef universal Int
228 # Suspend execution for `self` milliseconds
229 fun delay `{ SDL_Delay(self); `}
230 end
231
232 # A renderer, maybe software or hardware
233 extern class SDLRenderer `{ SDL_Renderer * `}
234 # Create a new `SDLRenderer` for the `window` using the `index`th renderer according to `flags`
235 #
236 # Use an `index` of `-1` to get the default renderer for the given flags.
237 new (window: SDLWindow, index: Int, flags: SDLRendererFlags) `{
238 return SDL_CreateRenderer(window, index, flags);
239 `}
240
241 # Create a new software `SDLRenderer`
242 new software(surface: SDLSurface) `{
243 return SDL_CreateSoftwareRenderer(surface);
244 `}
245
246 # Destroy this renderer
247 fun destroy `{ SDL_DestroyRenderer(self); `}
248
249 # Clear the rendering target with the current `draw_color`
250 fun clear `{ SDL_RenderClear(self); `}
251
252 # Copy the rectangle at `src` from `texture` to fill the `dst` at the rendering `target`
253 #
254 # If `dst` has a different size than `src`, the image will be stretched.
255 #
256 # If `src == null` the whole source texture will be drawn, and if
257 # `dst == null` then the texture will fill the rendering `target`.
258 fun copy(texture: SDLTexture, src, dst: nullable SDLRect)
259 do
260 if src == null then src = new SDLRect.nil
261 if dst == null then dst = new SDLRect.nil
262
263 native_copy(texture, src, dst)
264 end
265
266 private fun native_copy(texture: SDLTexture, src, dst: SDLRect) `{
267 SDL_RenderCopy(self, texture, src, dst);
268 `}
269
270 # Update the screen with all rendering since the previous call
271 fun present `{ SDL_RenderPresent(self); `}
272
273 # Get the `SDLRendererInfo` for this renderer
274 fun info_copy(out: SDLRendererInfo) `{ SDL_GetRendererInfo(self, out); `}
275
276 # Set the drawing color
277 fun draw_color=(val: SDLColor) `{
278 SDL_SetRenderDrawColor(self, val->r, val->g, val->b, val->a);
279 `}
280
281 # Get the drawing color of this renderer
282 #
283 # The returned `SDLColor` is malloced here and must be freed by the called.
284 # For a more efficient usage, it is recommended to use instead `draw_color_copy`.
285 fun draw_color: SDLColor
286 do
287 var color = new SDLColor.malloc
288 draw_color_copy color
289 return color
290 end
291
292 # Copy the drawing color of this renderer in `color`
293 fun draw_color_copy(color: SDLColor) `{
294 SDL_GetRenderDrawColor(self, &color->r, &color->g, &color->b, &color->a);
295 `}
296
297 # Fill a rectangle with the current `draw_color`
298 #
299 # If `rect.address_is_null` then fills the entire screen.
300 fun fill_rect(rect: SDLRect) `{ SDL_RenderFillRect(self, rect); `}
301
302 # Draw a rectangle with the current `draw_color`
303 fun draw_rect(rect: SDLRect) `{ SDL_RenderDrawRect(self, rect); `}
304
305 # Draw a point with the current `draw_color`
306 fun draw_point(x, y: Int) `{ SDL_RenderDrawPoint(self, x, y); `}
307
308 # Draw a line with the current `draw_color`
309 fun draw_line(x1, y1, x2, y2: Int) `{ SDL_RenderDrawLine(self, x1, y1, x2, y2); `}
310
311 # Set the viewport of this renderer
312 fun viewport=(rect: SDLRect) `{ SDL_RenderSetViewport(self, rect); `}
313
314 # Get the rendering target of this renderer
315 fun target: SDLTexture `{ return SDL_GetRenderTarget(self); `}
316
317 # Set the rendering target of this renderer
318 fun target=(val: SDLTexture) `{ SDL_SetRenderTarget(self, val); `}
319
320 # TODO add other renderer related methods:
321 #
322 # draw_rects
323 # draw_lines
324 end
325
326 # A color
327 extern class SDLColor `{ SDL_Color *`}
328 # Allocate the memory for a new `SDLColor`, it must then be freed with `free`
329 new malloc `{ return malloc(sizeof(SDL_Color)); `}
330
331 # Allocate the memory for a new `SDLColor` and fill it with `r`, `g`, `b` and `a`
332 #
333 # As with `malloc`, the new instances must then be freed with `free`.
334 new (r, g, b, a: Int)
335 do
336 var color = new SDLColor.malloc
337 color.set(r, g, b, a)
338 return color
339 end
340
341 # Set this instance's `r`, `g`, `b` and `a`
342 fun set(r, g, b, a: Int)
343 do
344 self.r = r
345 self.g = g
346 self.b = b
347 self.a = a
348 end
349
350 # The red component of this color `[0..255]`
351 fun r: Int `{ return self->r; `}
352
353 # Set the red component of this color `[0..255]`
354 fun r=(val: Int) `{ self->r = val; `}
355
356 # The green component of this color `[0..255]`
357 fun g: Int `{ return self->g; `}
358
359 # Set the green component of this color `[0..255]`
360 fun g=(val: Int) `{ self->g = val; `}
361
362 # The blue component of this color `[0..255]`
363 fun b: Int `{ return self->b; `}
364
365 # Set the blue component of this color `[0..255]`
366 fun b=(val: Int) `{ self->b = val; `}
367
368 # The alpha component of this color `[0..255]`
369 fun a: Int `{ return self->a; `}
370
371 # Set the ralpha component of this color `[0..255]`
372 fun a=(val: Int) `{ self->a = val; `}
373
374 # TODO implement the related `SDL_Palette` and related methods
375 end
376
377 # Flags for `SDLRenderer::new`
378 extern class SDLRendererFlags `{ Uint32 `}
379 # Get the default empty flag set
380 new `{ return 0; `}
381
382 # Add the flag to request a software renderer
383 fun software: SDLRendererFlags `{ return self | SDL_RENDERER_SOFTWARE; `}
384
385 # Add the flag to request an accelerated renderer
386 #
387 # This is the default option.
388 fun accelerated: SDLRendererFlags `{ return self | SDL_RENDERER_ACCELERATED; `}
389
390 # Add the flag to request a renderer where `SDLRenderer::present` is synchronized with the refresh rate
391 fun presentvsync: SDLRendererFlags `{ return self | SDL_RENDERER_PRESENTVSYNC; `}
392
393 # Add the flag to request a renderer able to render to a texture
394 fun targettexture: SDLRendererFlags `{ return self | SDL_RENDERER_TARGETTEXTURE; `}
395 end
396
397 # A bitmap surface
398 extern class SDLSurface `{ SDL_Surface * `}
399
400 # Load the BMP file at `path`
401 new load_bmp(path: CString) `{ return SDL_LoadBMP(path); `}
402
403 redef fun free `{ SDL_FreeSurface(self); `}
404
405 # Save this texture to a BMP file
406 fun save_bmp(path: CString) `{ SDL_SaveBMP(self, path); `}
407
408 # Format of the pixels
409 fun format: SDL_PixelFormat `{ return self->format; `}
410
411 # Width in pixels
412 fun w: Int `{ return self->w; `}
413
414 # Height in pixels
415 fun h: Int `{ return self->h; `}
416
417 # Bytes in a row of pixels
418 fun pitch: Int `{ return self->pitch; `}
419
420 # Pointer to pixel data
421 fun pixels: Pointer `{ return self->pixels; `}
422 end
423
424 # Pixel format information
425 extern class SDL_PixelFormat `{ SDL_PixelFormat * `}
426 # Number of significant bits in a pixel
427 fun bits_per_pixel: Int `{ return self->BitsPerPixel; `}
428
429 # Number of bytes required to hold a pixel
430 fun bytes_per_pixel: Int `{ return self->BytesPerPixel; `}
431
432 # Mask of the location of the red component
433 fun rmask: UInt32 `{ return self->Rmask; `}
434
435 # Mask of the location of the green component
436 fun gmask: UInt32 `{ return self->Gmask; `}
437
438 # Mask of the location of the blue component
439 fun bmask: UInt32 `{ return self->Bmask; `}
440
441 # Mask of the location of the alpha component
442 fun amask: UInt32 `{ return self->Amask; `}
443 end
444
445 # A loaded bitmap texture
446 extern class SDLTexture `{ SDL_Texture * `}
447 # Get a `SDLTexture` from a `surface`, for a given `renderer`
448 new from_surface(renderer: SDLRenderer, surface: SDLSurface) `{
449 return SDL_CreateTextureFromSurface(renderer, surface);
450 `}
451
452 # Destroy this texture
453 fun destroy `{ SDL_DestroyTexture(self); `}
454
455 # Width of this texture
456 fun width: Int `{
457 int val;
458 SDL_QueryTexture(self, NULL, NULL, &val, NULL);
459 return val;
460 `}
461
462 # Height of this texture
463 fun height: Int `{
464 int val;
465 SDL_QueryTexture(self, NULL, NULL, NULL, &val);
466 return val;
467 `}
468
469 # TODO other queries: format and access
470 end
471
472 # A rectangle
473 extern class SDLRect `{SDL_Rect *`}
474 # Get a null rectangle (on the C side), should be used only internally
475 new nil `{ return NULL; `}
476
477 # Allocate the memory for a new `SDLRect`, it must then be freed with `free`
478 new malloc`{ return malloc(sizeof(SDL_Rect)); `}
479
480 # Allocate the memory for a new `SDLRect` and fill it with `x`, `y`, `w` and `h`
481 #
482 # As with `malloc`, the new instances must then be freed with `free`.
483 new (x, y, w, h: Int)
484 do
485 var rect = new SDLRect.malloc
486 rect.set(x, y, w, h)
487 return rect
488 end
489
490 # Set this instance's `x`, `y`, `w` and `h`
491 fun set(x, y, w, h: Int)
492 do
493 self.x = x
494 self.y = y
495 self.w = w
496 self.h = h
497 end
498
499 # X coordinate of the top left corner
500 fun x: Int `{ return self->x; `}
501
502 # Set the X coordinate of the top left corner
503 fun x=(val: Int) `{ self->x = val; `}
504
505 # Y coordinate of the top left corner
506 fun y: Int `{ return self->y; `}
507
508 # Set the Y coordinate of the top left corner
509 fun y=(val: Int) `{ self->y = val; `}
510
511 # Width of this rectangle
512 fun w: Int `{ return self->w; `}
513
514 # Set the width of this rectangle
515 fun w=(val: Int) `{ self->w = val; `}
516
517 # Height of this rectangle
518 fun h: Int `{ return self->h; `}
519
520 # Set the height of this rectangle
521 fun h=(val: Int) `{ self->h = val; `}
522
523 # TODO implement other `SDLRect` related methods:
524 #
525 # SDL_EnclosePoints
526 # SDL_HasIntersection
527 # SDL_IntersectRect
528 # SDL_IntersectRectAndLine
529 # SDL_PointInRect
530 # SDL_RectEmpty
531 # SDL_RectEquals
532 # SDL_UnionRect
533 end
534
535 # A point with `x` and `y`
536 extern class SDLPoint `{SDL_Point *`}
537 # Get a null rectangle (on the C side), should be used only internally
538 new nil `{ return NULL; `}
539
540 # Allocate the memory for a new `SDLPoint`, it must the be freed with `free`
541 new malloc`{ return malloc(sizeof(SDL_Point)); `}
542
543 # Allocate the memory for a new `SDLPoint` and fill it with `x` and `y`
544 #
545 # As with `malloc`, the new instances must the be freed with `free`.
546 new (x, y: Int) do
547 var point = new SDLPoint.malloc
548 point.x = x
549 point.y = y
550 return point
551 end
552
553 # X coordinate of this point
554 fun x: Int `{ return self->x; `}
555
556 # Set the X coordinate of this point
557 fun x=(val: Int) `{ self->x = val; `}
558
559 # Y coordinate of this point
560 fun y: Int `{ return self->y; `}
561
562 # Set the Y coordinate of this point
563 fun y=(val: Int) `{ self->y = val; `}
564 end
565
566 # Flag to set the icon in `sys.sdl.show_simple_message_box` and `SDLWindow::show_simple_message_box`
567 extern class SDLMessageBoxFlags `{ Uint32 `}
568 # Request the error icon
569 new error `{ return SDL_MESSAGEBOX_ERROR; `}
570
571 # Request the warning icon
572 new warning `{ return SDL_MESSAGEBOX_WARNING; `}
573
574 # Request the information icon
575 new information `{ return SDL_MESSAGEBOX_INFORMATION; `}
576 end
577
578 # Information on a `SDLRenderer`
579 extern class SDLRendererInfo `{ SDL_RendererInfo * `}
580 # Allocate the memory for a new `SDLRenderer`, it must then be freed with `free`
581 new malloc `{ return malloc(sizeof(SDL_RendererInfo)); `}
582
583 # Name of the renderer's driver
584 fun name: CString `{ return (char*)self->name; `}
585
586 # Maximum texture width supported by the renderer
587 fun max_texture_width: Int `{ return self->max_texture_width; `}
588
589 # Maximum texture height supported by the renderer
590 fun max_texture_height: Int `{ return self->max_texture_height; `}
591 end