Browse Source

Haptic Rumble support 954

JimMarlowe 9 years ago
parent
commit
cbe2347b1d

+ 2 - 1
Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -238,7 +238,8 @@ Graphics::Graphics(Context* context) :
     ResetCachedState();
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE);
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
+		| SDL_INIT_TIMER | SDL_INIT_HAPTIC ); // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);

+ 2 - 1
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -280,7 +280,8 @@ Graphics::Graphics(Context* context) :
     SetTextureUnitMappings();
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE);
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
+		| SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);

+ 3 - 1
Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp

@@ -268,7 +268,8 @@ Graphics::Graphics(Context* context_) :
     ResetCachedState();
 
     // Initialize SDL now. Graphics should be the first SDL-using subsystem to be created
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE);
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE
+		| SDL_INIT_TIMER | SDL_INIT_HAPTIC );  // ATOMIC BEGIN  HAPTIC  //ATOMIC END
 
     // Register Graphics library object factories
     RegisterGraphicsLibrary(context_);
@@ -2429,6 +2430,7 @@ void Graphics::Restore()
 void Graphics::MarkFBODirty()
 {
     impl_->fboDirty_ = true;
+
 }
 
 void Graphics::SetVBO(unsigned object)

+ 107 - 0
Source/Atomic/Input/Input.cpp

@@ -312,6 +312,9 @@ void JoystickState::Initialize(unsigned numButtons, unsigned numAxes, unsigned n
 
 void JoystickState::Reset()
 {
+// ATOMIC BEGIN
+    StopRumble();
+// ATOMIC END    
     for (unsigned i = 0; i < buttons_.Size(); ++i)
     {
         buttons_[i] = false;
@@ -323,6 +326,87 @@ void JoystickState::Reset()
         hats_[i] = HAT_CENTER;
 }
 
+// ATOMIC BEGIN
+
+/// Initialize the Rumble section of SDL Haptics
+/// if an error occurs, unset the canRumble_ to stop further init attempts, until Reset is called.
+bool JoystickState::StartRumble()
+{
+    if ( haptic_ == NULL && canRumble_ )
+    {
+        const char *hname = SDL_HapticName(joystickID_);
+        haptic_ = SDL_HapticOpen(joystickID_);
+        if (haptic_ == NULL)
+        {
+            ATOMIC_LOGERRORF( "Unable to access haptic device[%d] %s", joystickID_, hname );
+            canRumble_ = false;
+            return false;
+        }
+
+        SDL_ClearError();
+
+        if ( SDL_HapticRumbleSupported(haptic_) == SDL_FALSE)
+        {
+            ATOMIC_LOGERRORF( "The device `%s` does not support haptic operations", joystickID_, hname );
+            SDL_HapticClose(haptic_);
+            haptic_ = NULL;   
+            canRumble_ = false;
+            return false;
+        }
+
+        SDL_ClearError();
+
+        if ( SDL_HapticRumbleInit(haptic_) != 0)
+        {
+            ATOMIC_LOGERRORF( "Failed to initialize rumble: %s", SDL_GetError());
+            canRumble_ = false;
+            return false;
+        }
+    }
+    return true;
+}
+
+/// clean up rumble 
+void JoystickState::StopRumble()
+{
+    if ( haptic_ )
+    {
+        SDL_HapticRumbleStop(haptic_);
+        SDL_HapticClose(haptic_);        
+        haptic_ = NULL;
+    }
+    canRumble_ = true;
+}
+
+///  return if the joystick or game controller supports the force feedback rumble.
+bool JoystickState::IsRumble()
+{
+    if ( canRumble_ )
+        if ( !StartRumble() ) 
+            return false;
+    
+    if ( haptic_ )
+    {
+        return SDL_HapticRumbleSupported(haptic_);
+    }
+    return false;
+}
+
+/// rumble player, strength is from 0.0 to 1.0, length is in milliseconds, 1000 is equal to 1 second.
+void JoystickState::DoRumble( float strength, unsigned int len)
+{
+    StartRumble();  // lazy initialization
+ 
+    if ( haptic_ && canRumble_ )
+    {
+        float stren1 = Clamp (strength, 0.0f, 1.0f ); 
+        if (SDL_HapticRumblePlay(haptic_, stren1, len ) != 0 )
+            ATOMIC_LOGINFOF( "Failed to play rumble: %s\n", SDL_GetError() );
+    }
+ }
+// ATOMIC END    
+    
+
 Input::Input(Context* context) :
     Object(context),
     mouseButtonDown_(0),
@@ -1510,6 +1594,13 @@ void Input::Initialize()
 
     graphics_ = graphics;
 
+// ATOMIC BEGIN
+    //  get user gamecontroller configs for SDL
+    FileSystem* fs = GetSubsystem<FileSystem>();
+    const String configName = fs->GetUserDocumentsDir() + "/gamecontrollerdb.txt"; 
+    SDL_GameControllerAddMappingsFromFile(configName.CString());
+// ATOMIC END
+
     // In external window mode only visible mouse is supported
     if (graphics_->GetExternalWindow())
         mouseVisible_ = true;
@@ -1715,6 +1806,22 @@ void Input::PushTouchIndex(int touchID)
     if (!inserted)
         availableTouchIDs_.Push(index);
 }
+// ATOMIC BEGIN
+bool Input::GetJoystickRumble(unsigned int id)
+{
+    JoystickState *jss = GetJoystick((SDL_JoystickID)id);
+    if (jss)
+        return jss->IsRumble();
+    return false;
+}
+
+void Input::JoystickRumble(unsigned int id, float strength, unsigned int length)
+{
+    JoystickState *jss = GetJoystick((SDL_JoystickID)id);
+    if (jss)
+        jss->DoRumble( strength, length);
+}
+// ATOMIC END
 
 void Input::SendInputFocusEvent()
 {

+ 21 - 1
Source/Atomic/Input/Input.h

@@ -80,7 +80,12 @@ struct JoystickState
 {
     /// Construct with defaults.
     JoystickState() :
-        joystick_(0), controller_(0)
+        joystick_(0), joystickID_(0), controller_(0),
+// ATOMIC BEGIN
+        haptic_(0),
+        canRumble_(true),
+// ATOMIC END
+        name_()
     {
     }
 
@@ -113,6 +118,14 @@ struct JoystickState
     /// Return hat position.
     int GetHatPosition(unsigned index) const { return index < hats_.Size() ? hats_[index] : HAT_CENTER; }
 
+    // ATOMIC BEGIN
+    /// Haptic aka Rumble support
+    bool StartRumble();
+    void StopRumble();
+    bool IsRumble();
+    void DoRumble( float strength, unsigned int length); 
+    // ATOMIC END
+
     /// SDL joystick.
     SDL_Joystick* joystick_;
     /// SDL joystick instance ID.
@@ -120,6 +133,9 @@ struct JoystickState
     /// SDL game controller.
     SDL_GameController* controller_;
     // ATOMIC BEGIN
+    /// Haptic support
+    SDL_Haptic *haptic_;
+    bool canRumble_;
     /// UI element containing the screen joystick.
     // UIElement* screenJoystick_;
     // ATOMIC END
@@ -307,6 +323,10 @@ public:
 // ATOMIC BEGIN
     void SimulateButtonDown(int button);
     void SimulateButtonUp(int button);
+    
+    bool GetJoystickRumble(unsigned int id);  /// return if rumble is supported on game controller
+    void JoystickRumble(unsigned int id, float strength, unsigned int length); /// produce rumble
+
 // ATOMIC END
 
 private:

+ 1 - 0
Source/Atomic/Input/InputEvents.h

@@ -29,6 +29,7 @@
 #include <SDL/include/SDL_gamecontroller.h>
 #include <SDL/include/SDL_keycode.h>
 #include <SDL/include/SDL_mouse.h>
+#include <SDL/include/SDL_haptic.h>
 // ATOMIC END
 
 namespace Atomic