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