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