Index: /trunk/nv/detail/io_event_list.inc
===================================================================
--- /trunk/nv/detail/io_event_list.inc	(revision 183)
+++ /trunk/nv/detail/io_event_list.inc	(revision 184)
@@ -2,4 +2,8 @@
 NV_IO_EVENT( EV_MOUSE_BUTTON )
 NV_IO_EVENT( EV_MOUSE_MOVE )
+NV_IO_EVENT( EV_JOY_BUTTON )
+NV_IO_EVENT( EV_JOY_AXIS )
+NV_IO_EVENT( EV_JOY_HAT )
+NV_IO_EVENT( EV_JOY_BALL )
 NV_IO_EVENT( EV_ACTIVE )
 NV_IO_EVENT( EV_RESIZE )
Index: /trunk/nv/io_event.hh
===================================================================
--- /trunk/nv/io_event.hh	(revision 183)
+++ /trunk/nv/io_event.hh	(revision 184)
@@ -95,4 +95,46 @@
 	};
 
+	struct joy_button_event
+	{
+		/// Joystick ID
+		sint32 id;
+		/// Button that is affected
+		uint8 button;
+		/// True if pressed
+		bool pressed;
+	};
+
+	struct joy_axis_event
+	{
+		/// Joystick ID
+		sint32 id;
+		/// Axis ID
+		uint8 axis;
+		/// Value
+		sint16 value;
+	};
+
+	struct joy_hat_event
+	{
+		/// Joystick ID
+		sint32 id;
+		/// Hat ID
+		uint8 hat;
+		/// Value
+		sint16 value;
+	};
+
+	struct joy_ball_event
+	{
+		/// Joystick ID
+		sint32 id;
+		/// Ball ID
+		uint8 ball;
+		/// Relative X
+		sint16 rx;
+		/// Relative Y
+		sint16 ry;
+	};
+
 	struct resize_event
 	{
@@ -124,4 +166,8 @@
 			mouse_button_event mbutton;
 			mouse_move_event   mmove;
+			joy_button_event   jbutton;
+			joy_axis_event     jaxis;
+			joy_hat_event      jhat;
+			joy_ball_event     jball;
 			resize_event       resize;
 			active_event       active;
Index: /trunk/src/gl/gl_device.cc
===================================================================
--- /trunk/src/gl/gl_device.cc	(revision 183)
+++ /trunk/src/gl/gl_device.cc	(revision 184)
@@ -25,5 +25,5 @@
 	m_info = NULL;
 
-	if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
+	if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0 )
 	{
 		NV_LOG( LOG_CRITICAL, "Video initialization failed: " << SDL_GetError( ) );
Index: /trunk/src/gl/gl_window.cc
===================================================================
--- /trunk/src/gl/gl_window.cc	(revision 183)
+++ /trunk/src/gl/gl_window.cc	(revision 184)
@@ -132,4 +132,41 @@
 }
 
+static bool sdl_joy_button_event_to_io_event( const SDL_JoyButtonEvent& jb, io_event& jevent )
+{
+	jevent.type            = EV_JOY_BUTTON;
+	jevent.jbutton.id      = jb.which;
+	jevent.jbutton.button  = jb.button;
+	jevent.jbutton.pressed = (jb.type == SDL_PRESSED);
+	return true;
+}
+
+static bool sdl_joy_axis_event_to_io_event( const SDL_JoyAxisEvent& ja, io_event& jevent )
+{
+	jevent.type          = EV_JOY_AXIS;
+	jevent.jaxis.id      = ja.which;
+	jevent.jaxis.axis    = ja.axis;
+	jevent.jaxis.value   = ja.value;
+	return true;
+}
+
+static bool sdl_joy_hat_event_to_io_event( const SDL_JoyHatEvent& jh, io_event& jevent )
+{
+	jevent.type          = EV_JOY_HAT;
+	jevent.jhat.id       = jh.which;
+	jevent.jhat.hat      = jh.hat;
+	jevent.jhat.value    = jh.value;
+	return true;
+}
+
+static bool sdl_joy_ball_event_to_io_event( const SDL_JoyBallEvent& jb, io_event& jevent )
+{
+	jevent.type          = EV_JOY_HAT;
+	jevent.jball.id      = jb.which;
+	jevent.jball.ball    = jb.ball;
+	jevent.jball.rx      = jb.xrel;
+	jevent.jball.ry      = jb.yrel;
+	return true;
+}
+
 static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent )
 {
@@ -156,9 +193,9 @@
 	case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
 	case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
-	case SDL_JOYAXISMOTION   : return false;
-	case SDL_JOYBALLMOTION   : return false;
-	case SDL_JOYHATMOTION    : return false;
-	case SDL_JOYBUTTONDOWN   : return false;
-	case SDL_JOYBUTTONUP     : return false;
+	case SDL_JOYAXISMOTION   : return sdl_joy_axis_event_to_io_event( e.jaxis, ioevent ); 
+	case SDL_JOYBALLMOTION   : return sdl_joy_ball_event_to_io_event( e.jball, ioevent ); 
+	case SDL_JOYHATMOTION    : return sdl_joy_hat_event_to_io_event( e.jhat, ioevent ); 
+	case SDL_JOYBUTTONDOWN   : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
+	case SDL_JOYBUTTONUP     : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
 	default : return false;
 	}
@@ -183,4 +220,15 @@
 	}
 
+// 	NV_LOG( LOG_INFO, "Joystick count : " << SDL_NumJoysticks() );
+// 	SDL_Joystick* j = SDL_JoystickOpen(0);
+// 	if (j)
+// 	{
+// 		NV_LOG( LOG_INFO, "Joystick Name: " << SDL_JoystickNameForIndex(0) );
+// 		NV_LOG( LOG_INFO, "Joystick Number of Axes: " << SDL_JoystickNumAxes(j));
+// 		NV_LOG( LOG_INFO, "Joystick Number of Buttons: " << SDL_JoystickNumButtons(j));
+// 		NV_LOG( LOG_INFO, "Joystick Number of Balls: " << SDL_JoystickNumBalls(j));
+// 	}
+
+
 	m_context = new gl_context( m_device, m_handle );
 	m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) );
Index: /trunk/src/io_event.cc
===================================================================
--- /trunk/src/io_event.cc	(revision 183)
+++ /trunk/src/io_event.cc	(revision 184)
@@ -94,4 +94,33 @@
 	db->create_type<mouse_move_event>("mouse_move_event").fields( mouse_move_fields );
 
+	type_field joy_button_fields[] = {
+		type_field( "id",      &joy_button_event::id ),
+		type_field( "button",  &joy_button_event::button ),
+		type_field( "pressed", &joy_button_event::pressed ),
+	};
+	db->create_type<joy_button_event>("joy_button_event").fields( joy_button_fields );
+
+	type_field joy_axis_fields[] = {
+		type_field( "id",      &joy_axis_event::id ),
+		type_field( "axis",    &joy_axis_event::axis ),
+		type_field( "value",   &joy_axis_event::value ),
+	};
+	db->create_type<joy_axis_event>("joy_axis_event").fields( joy_axis_fields );
+
+	type_field joy_hat_fields[] = {
+		type_field( "id",      &joy_hat_event::id ),
+		type_field( "hat",     &joy_hat_event::hat ),
+		type_field( "value",   &joy_hat_event::value ),
+	};
+	db->create_type<joy_hat_event>("joy_hat_event").fields( joy_hat_fields );
+
+	type_field joy_ball_fields[] = {
+		type_field( "id",      &joy_ball_event::id ),
+		type_field( "ball",    &joy_ball_event::ball ),
+		type_field( "rx",      &joy_ball_event::rx ),
+		type_field( "ry",      &joy_ball_event::ry ),
+	};
+	db->create_type<joy_ball_event>("joy_ball_event").fields( joy_ball_fields );
+
 	type_field system_fields[] = {
 		type_field( "sys_type", &system_event::sys_type ),
