nitg-s: remove partial_types
[nit.git] / lib / mnit_linux / sdl.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2011-2013 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 # SDL display support (used in Linux for windows and inputes only)
18 module sdl is
19 c_compiler_option(exec("sdl-config", "--cflags"))
20 c_linker_option(exec("sdl-config", "--libs"), "-lSDL_ttf")
21 end
22
23 import mnit # for
24 # import display
25 # mport input_events
26
27 in "C header" `{
28 #include <unistd.h>
29 #include <SDL/SDL.h>
30 #include <SDL/SDL_syswm.h>
31 #include <SDL/SDL_image.h>
32 #include <SDL/SDL_ttf.h>
33 `}
34
35 # Represent a screen surface
36 extern SDLDisplay in "C" `{SDL_Surface *`}
37 super Display
38
39 redef type I: SDLImage
40
41 # Initialize a surface with width and height
42 new ( w, h: Int) is extern `{
43 SDL_Init(SDL_INIT_VIDEO);
44
45 if(TTF_Init()==-1) {
46 printf("TTF_Init: %s\n", TTF_GetError());
47 exit(2);
48 }
49
50 /* ignores mousemotion for performance reasons */
51 SDL_EventState( SDL_MOUSEMOTION, SDL_IGNORE );
52
53 return SDL_SetVideoMode( w, h, 24, SDL_HWSURFACE );
54 `}
55
56 # Destroy the surface
57 fun destroy is extern `{
58 if ( SDL_WasInit( SDL_INIT_VIDEO ) )
59 SDL_Quit();
60
61 if ( TTF_WasInit() )
62 TTF_Quit();
63 `}
64
65 redef fun finish is extern `{ SDL_Flip( recv ); `}
66
67 # Clear the entire window with given RGB color (integer values)
68 fun clear_int( r, g, b: Int ) is extern `{
69 SDL_FillRect( recv, NULL, SDL_MapRGB(recv->format,r,g,b) );
70 `}
71
72 redef fun width: Int is extern `{ return recv->w; `}
73 redef fun height: Int is extern `{ return recv->h; `}
74
75 # Fill a rectangle with given color
76 fun fill_rect( rect: SDLRectangle, r, g, b: Int ) is extern `{
77 SDL_FillRect( recv, rect, SDL_MapRGB(recv->format,r,g,b) );
78 `}
79
80 redef fun clear( r, g, b: Float ) is extern `{
81 Uint8 ri, gi, bi;
82 ri = (Uint8)r*255;
83 gi = (Uint8)g*255;
84 bi = (Uint8)b*255;
85 SDL_FillRect( recv, NULL, SDL_MapRGB(recv->format,ri,gi,bi) );
86 `}
87
88 fun events: Sequence[ IE ]
89 do
90 var new_event: nullable Object = null
91 var events = new List[ IE ]
92 loop
93 new_event = poll_event
94 if new_event != null then # new_event isa Event then #
95 events.add( new_event )
96 else
97 break
98 end
99 end
100 return events
101 end
102
103 private fun poll_event: nullable IE is extern import SDLKeyEvent, SDLMouseButtonEvent, SDLMouseMotionEvent, SDLQuitEvent, NativeString.to_s, SDLMouseButtonEvent.as(nullable IE), SDLMouseMotionEvent.as(nullable IE), SDLKeyEvent.as(nullable IE), SDLQuitEvent.as(nullable IE) `{
104 SDL_Event event;
105
106 SDL_PumpEvents();
107
108 if ( SDL_PollEvent(&event) )
109 {
110 switch (event.type ) {
111 case SDL_KEYDOWN:
112 case SDL_KEYUP:
113 #ifdef DEBUG
114 printf("The \"%s\" key was pressed!\n",
115 SDL_GetKeyName(event.key.keysym.sym));
116 #endif
117
118 return SDLKeyEvent_as_nullable_InputEvent(
119 new_SDLKeyEvent( NativeString_to_s(
120 SDL_GetKeyName(event.key.keysym.sym) ),
121 event.type==SDL_KEYDOWN ) );
122
123 case SDL_MOUSEMOTION:
124 #ifdef DEBUG
125 printf("Mouse moved by %d,%d to (%d,%d)\n",
126 event.motion.xrel, event.motion.yrel,
127 event.motion.x, event.motion.y);
128 #endif
129
130 return SDLMouseMotionEvent_as_nullable_InputEvent(
131 new_SDLMouseMotionEvent( event.motion.x, event.motion.y,
132 event.motion.xrel, event.motion.yrel ) );
133
134 case SDL_MOUSEBUTTONDOWN:
135 case SDL_MOUSEBUTTONUP:
136 #ifdef DEBUG
137 printf("Mouse button \"%d\" pressed at (%d,%d)\n",
138 event.button.button, event.button.x, event.button.y);
139 #endif
140 return SDLMouseButtonEvent_as_nullable_InputEvent(
141 new_SDLMouseButtonEvent( event.button.x, event.button.y,
142 event.button.button, event.type == SDL_MOUSEBUTTONDOWN ) );
143
144 case SDL_QUIT:
145 #ifdef DEBUG
146 printf("Quit event\n");
147 #endif
148 return SDLQuitEvent_as_nullable_InputEvent( new_SDLQuitEvent() );
149 }
150 }
151
152 return null_InputEvent();
153 `}
154
155 # Set the position of the cursor to x,y
156 fun warp_mouse( x,y: Int ) `{ SDL_WarpMouse( x, y ); `}
157
158 # Show or hide the cursor
159 fun show_cursor( show: Bool ) `{ SDL_ShowCursor( show ); `}
160 end
161
162 # Basic Drawing figures
163 extern SDLDrawable in "C" `{SDL_Surface*`}
164 super Drawable
165
166 redef type I: SDLImage
167
168 redef fun blit( img, x, y ) is extern `{
169 SDL_Rect dst;
170 dst.x = x;
171 dst.y = y;
172 dst.w = 0;
173 dst.h = 0;
174
175 SDL_BlitSurface( img, NULL, recv, &dst );
176 `}
177
178 redef fun blit_centered( img, x, y )
179 do
180 x = x - img.width / 2
181 y = y - img.height / 2
182 blit( img, x, y )
183 end
184 end
185
186 # A drawable Image
187 extern SDLImage in "C" `{SDL_Surface*`} # TODO remove
188 super DrawableImage
189 super SDLDrawable
190
191 # Import image from a file
192 new from_file( path: String ) is extern import String.to_cstring `{
193 SDL_Surface *image = IMG_Load( String_to_cstring( path ) );
194 return image;
195 `}
196
197
198 new partial( original: Image, clip: SDLRectangle ) is extern `{
199 return NULL;
200 `}
201
202 # Copy of an existing SDLImage
203 new copy_of( image: SDLImage ) is extern `{
204 SDL_Surface *new_image = SDL_CreateRGBSurface( image->flags, image->w, image->h, 24,
205 0, 0, 0, 0 );
206
207 SDL_Rect dst;
208 dst.x = 0;
209 dst.y = 0;
210 dst.w = image->w;
211 dst.h = image->h;
212 SDL_BlitSurface( image, NULL, new_image, &dst );
213
214 return new_image;
215 `}
216
217 # Save the image into the specified file
218 fun save_to_file( path: String ) is extern import String::to_cstring `{ `}
219
220 # Destroy the image and free the memory
221 redef fun destroy is extern `{ SDL_FreeSurface( recv ); `}
222
223 redef fun width: Int is extern `{ return recv->w; `}
224 redef fun height: Int is extern `{ return recv->h; `}
225
226 fun is_ok: Bool do return true # TODO
227 end
228
229 # A simple rectangle
230 extern SDLRectangle in "C" `{SDL_Rect*`}
231 # Constructor with x,y positions width and height of the rectangle
232 new ( x: Int, y: Int, w: Int, h: Int ) is extern `{
233 SDL_Rect *rect = malloc( sizeof( SDL_Rect ) );
234 rect->x = (Sint16)x;
235 rect->y = (Sint16)y;
236 rect->w = (Uint16)w;
237 rect->h = (Uint16)h;
238 return rect;
239 `}
240
241 fun x=( v: Int ) is extern `{ recv->x = (Sint16)v; `}
242 fun x: Int is extern `{ return recv->x; `}
243
244 fun y=( v: Int ) is extern `{ recv->y = (Sint16)v; `}
245 fun y: Int is extern `{ return recv->y; `}
246
247 fun w=( v: Int ) is extern `{ recv->w = (Uint16)v; `}
248 fun w: Int is extern `{ return recv->w; `}
249
250 fun h=( v: Int ) is extern `{ recv->h = (Uint16)v; `}
251 fun h: Int is extern `{ return recv->h; `}
252
253 fun destroy is extern `{ `}
254 end
255
256 interface SDLInputEvent
257 super InputEvent
258 end
259
260 # MouseEvent class containing the cursor position
261 class SDLMouseEvent
262 super PointerEvent
263 super SDLInputEvent
264
265 redef var x: Float
266 redef var y: Float
267
268 private init ( x, y: Float )
269 do
270 self.x = x
271 self.y = y
272 end
273 end
274
275 # MouseButtonEvent used to get information when a button is pressed/depressed
276 class SDLMouseButtonEvent
277 super SDLMouseEvent
278
279 var button: Int
280
281 redef var pressed: Bool
282 redef fun depressed: Bool do return not pressed
283
284 init ( x, y: Float, button: Int, pressed: Bool )
285 do
286 super( x, y )
287
288 self.button = button
289 self.pressed = pressed
290 end
291
292 redef fun to_s
293 do
294 if pressed then
295 return "MouseButtonEvent button {button} down at {x}, {y}"
296 else
297 return "MouseButtonEvent button {button} up at {x}, {y}"
298 end
299 end
300 end
301
302 # MouseMotionEvent to get the cursor position when the mouse is moved
303 class SDLMouseMotionEvent
304 super SDLMouseEvent
305
306 var rel_x: Float
307 var rel_y: Float
308
309 init ( x, y, rel_x, rel_y: Float )
310 do
311 super( x, y )
312
313 self.rel_x = rel_x
314 self.rel_y = rel_y
315 end
316
317 redef fun to_s do return "MouseMotionEvent at {x}, {y}"
318 end
319
320 # SDLKeyEvent for when a key is pressed
321 class SDLKeyEvent
322 super KeyEvent
323 super SDLInputEvent
324
325 var key_name: String
326 var down: Bool
327
328 init ( key_name: String, down: Bool )
329 do
330 self.key_name = key_name
331 self.down = down
332 end
333
334 redef fun to_c: nullable Char
335 do
336 if key_name.length == 1 then return key_name.chars.first
337 return null
338 end
339
340 redef fun to_s
341 do
342 if down then
343 return "KeyboardEvent key {key_name} down"
344 else
345 return "KeyboardEvent key {key_name} up"
346 end
347 end
348
349 # Return true if the key is down, false otherwise
350 redef fun is_down do return down
351
352 # Return true if the key is the up arrow
353 redef fun is_arrow_up do return key_name == "up"
354 # Return true if the key is the left arrow
355 redef fun is_arrow_left do return key_name == "left"
356 # Return true if the key is the down arrow
357 redef fun is_arrow_down do return key_name == "down"
358 # Return true if the key is the right arrow
359 redef fun is_arrow_right do return key_name == "right"
360 end
361
362 class SDLQuitEvent
363 super SDLInputEvent
364 super QuitEvent
365 end
366
367 redef class Int
368 fun delay is extern `{ SDL_Delay( recv ); `}
369 end
370
371 # Class to load and use TTF_Font
372 extern SDLFont in "C" `{TTF_Font *`}
373 # Load a font with a specified name and size
374 new ( name: String, points: Int ) is extern import String.to_cstring `{
375 char * cname = String_to_cstring( name );
376
377 TTF_Font *font = TTF_OpenFont( cname, (int)points);
378 if(!font) {
379 printf("TTF_OpenFont: %s\n", TTF_GetError());
380 exit( 1 );
381 }
382
383 return font;
384 `}
385
386 fun destroy is extern `{ TTF_CloseFont( recv ); `}
387
388 # Create a String with the specified color, return an SDLImage
389 fun render( text: String, r, g, b: Int ): SDLImage is extern import String.to_cstring `{
390 SDL_Color color;
391 SDL_Surface *text_surface;
392 char *ctext;
393
394 color.r = r;
395 color.g = g;
396 color.b = b;
397
398 ctext = String_to_cstring( text );
399 if( !(text_surface=TTF_RenderText_Blended( recv, ctext, color )) )
400 {
401 fprintf( stderr, "SDL TFF error: %s\n", TTF_GetError() );
402 exit( 1 );
403 }
404 else
405 return text_surface;
406 `}
407
408 # TODO reactivate fun below when updating libsdl_ttf to 2.0.10 or above
409 #fun outline: Int is extern # TODO check to make inline/nitside only
410 #fun outline=( v: Int ) is extern
411
412 #fun kerning: Bool is extern
413 #fun kerning=( v: Bool ) is extern
414
415 # Maximum pixel height of all glyphs of this font.
416 fun height: Int is extern `{
417 return TTF_FontHeight( recv );
418 `}
419
420 fun ascent: Int is extern `{
421 return TTF_FontAscent( recv );
422 `}
423
424 fun descent: Int is extern `{
425 return TTF_FontDescent( recv );
426 `}
427
428 # Get the recommended pixel height of a rendered line of text of the loaded font. This is usually larger than the Font.height.
429 fun line_skip: Int is extern `{
430 return TTF_FontLineSkip( recv );
431 `}
432
433 # Return true is the font used fixed width for each char
434 fun is_fixed_width: Bool is extern `{
435 return TTF_FontFaceIsFixedWidth( recv );
436 `}
437
438 # Return the family name of the font
439 fun family_name: nullable String is extern import String.to_cstring, String as nullable `{
440 char *fn = TTF_FontFaceFamilyName( recv );
441
442 if ( fn == NULL )
443 return null_String();
444 else
445 return String_as_nullable( NativeString_to_s( fn ) );
446 `}
447
448 # Return the style name of the font
449 fun style_name: nullable String is extern import String.to_cstring, String as nullable `{
450 char *sn = TTF_FontFaceStyleName( recv );
451
452 if ( sn == NULL )
453 return null_String();
454 else
455 return String_as_nullable( NativeString_to_s( sn ) );
456 `}
457
458 # Return the estimated width of a String if used with the current font
459 fun width_of( text: String ): Int is extern import NativeString.to_s `{
460 char *ctext = String_to_cstring( text );
461 int w;
462 if ( TTF_SizeText( recv, ctext, &w, NULL ) )
463 {
464 fprintf( stderr, "SDL TFF error: %s\n", TTF_GetError() );
465 exit( 1 );
466 }
467 else
468 return w;
469 `}
470 end