1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2011-2013 Alexis Laferrière <alexis.laf@xymus.net>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # SDL display support (used in Linux for windows and inputes only)
19 c_compiler_option
(exec
("sdl-config", "--cflags"))
20 c_linker_option
(exec
("sdl-config", "--libs"), "-lSDL_image -lSDL_ttf")
28 #include <SDL/SDL_syswm.h>
29 #include <SDL/SDL_image.h>
30 #include <SDL/SDL_ttf.h>
33 # Represent a screen surface
34 extern class SDLDisplay `{SDL_Surface *`}
37 redef type I: SDLImage
39 # Initialize a surface with width and height
40 new (w, h: Int) import enable_mouse_motion_events `{
41 SDL_Init(SDL_INIT_VIDEO);
44 printf
("TTF_Init: %s\n", TTF_GetError());
48 SDL_Surface *self = SDL_SetVideoMode(w
, h
, 24, SDL_HWSURFACE);
50 if (!SDLDisplay_enable_mouse_motion_events(self)) {
51 /* ignores mousemotion
for performance reasons
*/
52 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
58 # Indicates wether we want the SDL mouse motion event (or only clicks).
59 # Disabled by defaut for performance reason. To activate, redef this method
61 fun enable_mouse_motion_events: Bool do return false
65 if (SDL_WasInit(SDL_INIT_VIDEO))
72 redef fun finish `{ SDL_Flip(recv); `}
74 # Clear the entire window with given RGB color (integer values)
75 fun clear_int
(r
, g
, b
: Int) `{
76 SDL_FillRect(recv, NULL, SDL_MapRGB(recv->format,r,g,b));
79 redef fun width
: Int `{ return recv->w; `}
80 redef fun height: Int `{ return recv->h; `}
82 # Fill a rectangle with given color
83 fun fill_rect
(rect
: SDLRectangle, r
, g
, b
: Int) `{
84 SDL_FillRect(recv, rect, SDL_MapRGB(recv->format,r,g,b));
87 redef fun clear
(r
, g
, b
: Float) `{
92 SDL_FillRect(recv, NULL, SDL_MapRGB(recv->format,ri,gi,bi));
95 # SDL events since the last call to this method
96 fun events
: Sequence[SDLInputEvent]
98 var events
= new Array[SDLInputEvent]
100 var new_event
= poll_event
101 if new_event
== null then break
107 private fun poll_event
: nullable SDLInputEvent import SDLKeyEvent, SDLMouseButtonEvent, SDLMouseMotionEvent, SDLQuitEvent, NativeString.to_s
, SDLMouseButtonEvent.as(nullable SDLInputEvent), SDLMouseMotionEvent.as(nullable SDLInputEvent), SDLKeyEvent.as(nullable SDLInputEvent), SDLQuitEvent.as(nullable SDLInputEvent) `{
112 if (SDL_PollEvent(&event))
114 switch (event.type) {
118 printf("The \"%s\" key was pressed!\n",
119 SDL_GetKeyName(event.key.keysym.sym));
122 return SDLKeyEvent_as_nullable_SDLInputEvent(
123 new_SDLKeyEvent(NativeString_to_s(
124 SDL_GetKeyName(event.key.keysym.sym)),
125 event.type==SDL_KEYDOWN));
127 case SDL_MOUSEMOTION:
129 printf("Mouse moved by %d,%d to (%d,%d)\n",
130 event.motion.xrel, event.motion.yrel,
131 event.motion.x, event.motion.y);
134 return SDLMouseMotionEvent_as_nullable_SDLInputEvent(
135 new_SDLMouseMotionEvent(event.motion.x, event.motion.y,
136 event.motion.xrel, event.motion.yrel, SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1)));
138 case SDL_MOUSEBUTTONDOWN:
139 case SDL_MOUSEBUTTONUP:
141 printf("Mouse button \"%d\" pressed at (%d,%d)\n",
142 event.button.button, event.button.x, event.button.y);
144 return SDLMouseButtonEvent_as_nullable_SDLInputEvent(
145 new_SDLMouseButtonEvent(event.button.x, event.button.y,
146 event.button.button, event.type == SDL_MOUSEBUTTONDOWN));
150 printf("Quit event\n");
152 return SDLQuitEvent_as_nullable_SDLInputEvent(new_SDLQuitEvent());
156 return null_SDLInputEvent();
159 # Set the position of the cursor to x,y
160 fun warp_mouse
(x
,y
: Int) `{ SDL_WarpMouse(x, y); `}
162 # Show or hide the cursor
163 fun show_cursor(show: Bool) `{ SDL_ShowCursor(show); `}
166 # Basic Drawing figures
167 extern class SDLDrawable `{SDL_Surface*`}
170 redef type I: SDLImage
172 redef fun blit(img, x, y) do native_blit(img, x.to_i, y.to_i)
173 private fun native_blit(img: I, x, y: Int) `{
180 SDL_BlitSurface(img
, NULL, recv
, &dst
);
183 redef fun blit_centered(img, x, y)
185 x = x - img.width / 2
186 y = y - img.height / 2
192 extern class SDLImage
196 # Import image from a file
197 new from_file(path: String) import String.to_cstring `{
198 SDL_Surface *image
= IMG_Load(String_to_cstring(path
));
202 # Copy of an existing SDLImage
203 new copy_of(image: SDLImage) `{
204 SDL_Surface *new_image
= SDL_CreateRGBSurface(
205 image-
>flags
, image-
>w
, image-
>h
, 24,
213 SDL_BlitSurface(image
, NULL, new_image
, &dst
);
218 # Save the image into the specified file
219 fun save_to_file(path: String) import String.to_cstring `{ `}
221 # Destroy the image and free the memory
222 redef fun destroy
`{ SDL_FreeSurface(recv); `}
224 redef fun width: Int `{ return recv->w; `}
225 redef fun height
: Int `{ return recv->h; `}
227 fun is_ok: Bool do return not address_is_null
231 extern class SDLRectangle `{SDL_Rect*`}
232 # Constructor with x,y positions width and height of the rectangle
233 new (x
: Int, y
: Int, w
: Int, h
: Int) `{
234 SDL_Rect *rect = malloc(sizeof(SDL_Rect));
242 fun x
=(v
: Int) `{ recv->x = (Sint16)v; `}
243 fun x: Int `{ return recv->x; `}
245 fun y
=(v
: Int) `{ recv->y = (Sint16)v; `}
246 fun y: Int `{ return recv->y; `}
248 fun w
=(v
: Int) `{ recv->w = (Uint16)v; `}
249 fun w: Int `{ return recv->w; `}
251 fun h
=(v
: Int) `{ recv->h = (Uint16)v; `}
252 fun h: Int `{ return recv->h; `}
255 interface SDLInputEvent
259 # MouseEvent class containing the cursor position
267 private init (x
, y
: Float)
274 # MouseButtonEvent used to get information when a button is pressed/depressed
275 class SDLMouseButtonEvent
280 redef var pressed
: Bool
281 redef fun depressed
: Bool do return not pressed
283 # Is this event raised by the left button?
284 fun is_left_button
: Bool do return button
== 1
286 # Is this event raised by the right button?
287 fun is_right_button
: Bool do return button
== 2
289 # Is this event raised by the middle button?
290 fun is_middle_button
: Bool do return button
== 3
292 # Is this event raised by the wheel going down?
293 fun is_down_wheel
: Bool do return button
== 4
295 # Is this event raised by the wheel going up?
296 fun is_up_wheel
: Bool do return button
== 5
298 # Is this event raised by the wheel?
299 fun is_wheel
: Bool do return is_down_wheel
or is_up_wheel
301 init (x
, y
: Float, button
: Int, pressed
: Bool)
306 self.pressed
= pressed
312 return "MouseButtonEvent button {button} down at {x}, {y}"
314 return "MouseButtonEvent button {button} up at {x}, {y}"
319 # MouseMotionEvent to get the cursor position when the mouse is moved
320 class SDLMouseMotionEvent
326 redef var pressed
: Bool
327 redef fun depressed
: Bool do return not pressed
329 init (x
, y
, rel_x
, rel_y
: Float, pressed
: Bool)
335 self.pressed
= pressed
338 redef fun to_s
do return "MouseMotionEvent at {x}, {y}"
341 # SDLKeyEvent for when a key is pressed
349 init (key_name
: String, down
: Bool)
351 self.key_name
= key_name
355 redef fun to_c
: nullable Char
357 if key_name
.length
== 1 then return key_name
.chars
.first
364 return "KeyboardEvent key {key_name} down"
366 return "KeyboardEvent key {key_name} up"
370 # Return true if the key is down, false otherwise
371 redef fun is_down
do return down
373 # Return true if the key is the up arrow
374 redef fun is_arrow_up
do return key_name
== "up"
375 # Return true if the key is the left arrow
376 redef fun is_arrow_left
do return key_name
== "left"
377 # Return true if the key is the down arrow
378 redef fun is_arrow_down
do return key_name
== "down"
379 # Return true if the key is the right arrow
380 redef fun is_arrow_right
do return key_name
== "right"
389 fun delay
`{ SDL_Delay(recv); `}
392 # Class to load and use TTF_Font
393 extern class SDLFont `{TTF_Font *`}
394 # Load a font with a specified name and size
395 new (name
: String, points
: Int) import String.to_cstring
`{
396 char * cname = String_to_cstring(name);
398 TTF_Font *font = TTF_OpenFont(cname, (int)points);
400 printf("TTF_OpenFont: %s\n", TTF_GetError());
407 fun destroy
`{ TTF_CloseFont(recv); `}
409 # Create a String with the specified color, return an SDLImage
410 fun render(text: String, r, g, b: Int): SDLImage import String.to_cstring `{
412 SDL_Surface *text_surface
;
419 ctext
= String_to_cstring(text
);
420 if(!(text_surface
=TTF_RenderText_Blended(recv
, ctext
, color
)))
422 fprintf
(stderr
, "SDL TFF error: %s\n", TTF_GetError());
429 # TODO reactivate fun below when updating libsdl_ttf to 2.0.10 or above
430 #fun outline: Int # TODO check to make inline/nitside only
431 #fun outline=(v: Int) is extern
433 #fun kerning: Bool is extern
434 #fun kerning=(v: Bool) is extern
436 # Maximum pixel height of all glyphs of this font.
438 return TTF_FontHeight(recv
);
442 return TTF_FontAscent(recv
);
446 return TTF_FontDescent(recv
);
449 # Get the recommended pixel height of a rendered line of text of the loaded font. This is usually larger than the Font.height.
450 fun line_skip: Int `{
451 return TTF_FontLineSkip(recv
);
454 # Return true is the font used fixed width for each char
455 fun is_fixed_width: Bool `{
456 return TTF_FontFaceIsFixedWidth(recv
);
459 # Return the family name of the font
460 fun family_name: nullable String import String.to_cstring, String.as nullable `{
461 char
*fn
= TTF_FontFaceFamilyName(recv
);
464 return null_String
();
466 return String_as_nullable(NativeString_to_s(fn
));
469 # Return the style name of the font
470 fun style_name: nullable String import String.to_cstring, String.as nullable `{
471 char
*sn
= TTF_FontFaceStyleName(recv
);
474 return null_String
();
476 return String_as_nullable(NativeString_to_s(sn
));
479 # Return the estimated width of a String if used with the current font
480 fun width_of(text: String): Int import NativeString.to_s `{
481 char
*ctext
= String_to_cstring(text
);
483 if (TTF_SizeText(recv
, ctext
, &w
, NULL))
485 fprintf
(stderr
, "SDL TFF error: %s\n", TTF_GetError());
493 # Information on the SDL window
494 # Used in other modules to get window handle
495 extern class SDLSystemWindowManagerInfo `{SDL_SysWMinfo *`}
498 SDL_SysWMinfo *val = malloc(sizeof(SDL_SysWMinfo));
500 SDL_VERSION(&val->version);
502 if(SDL_GetWMInfo(val) <= 0) {
503 printf("Unable to get window handle");
510 # Returns the handle of this window on a X11 window system
511 fun x11_window_handle
: Pointer `{
512 return (void*)recv->info.x11.window;