From 40933c06e119c61d03dd6693ce12dc1f0dc4f4b3 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Thu, 30 Dec 2010 19:45:13 +0000 Subject: [PATCH] Primitive support for gamepad camera movement This was SVN commit r8844. --- binaries/data/config/default.cfg | 9 ++++ source/graphics/GameView.cpp | 36 +++++++++++++ source/lib/sysdep/os/win/wsdl.cpp | 29 +++++++++++ source/lib/sysdep/os/win/wsdl.h | 14 +++++ source/ps/GameSetup/GameSetup.cpp | 3 ++ source/ps/Joystick.cpp | 86 +++++++++++++++++++++++++++++++ source/ps/Joystick.h | 50 ++++++++++++++++++ 7 files changed, 227 insertions(+) create mode 100644 source/ps/Joystick.cpp create mode 100644 source/ps/Joystick.h diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index c06cdcd183..22be9b235e 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -173,3 +173,12 @@ hotkey.chat = Return ; Toggle chat window hotkey.profile.toggle = "F11" ; Enable/disable real-time profiler hotkey.profile.save = "Shift+F11" ; Save current profiler data to logs/profile.txt +; EXPERIMENTAL: joystick/gamepad settings +joystick.enable = false +joystick.deadzone = 8192 +joystick.camera.pan.x = 0 +joystick.camera.pan.y = 1 +joystick.camera.rotate.x = 3 +joystick.camera.rotate.y = 2 +joystick.camera.zoom.in = 5 +joystick.camera.zoom.out = 4 diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index 3bb2f24bdd..b59bc485fa 100644 --- a/source/graphics/GameView.cpp +++ b/source/graphics/GameView.cpp @@ -42,6 +42,7 @@ #include "ps/Game.h" #include "ps/Globals.h" #include "ps/Hotkey.h" +#include "ps/Joystick.h" #include "ps/Loader.h" #include "ps/LoaderThunks.h" #include "ps/Profile.h" @@ -176,6 +177,12 @@ public: ViewZoomMin(0), ViewZoomMax(0), ViewZoomDefault(0), + JoystickPanX(-1), + JoystickPanY(-1), + JoystickRotateX(-1), + JoystickRotateY(-1), + JoystickZoomIn(-1), + JoystickZoomOut(-1), PosX(0, 0, 0.01f), PosY(0, 0, 0.01f), @@ -264,6 +271,12 @@ public: float ViewZoomMin; float ViewZoomMax; float ViewZoomDefault; + int JoystickPanX; + int JoystickPanY; + int JoystickRotateX; + int JoystickRotateY; + int JoystickZoomIn; + int JoystickZoomOut; //////////////////////////////////////// // Camera Controls State @@ -375,6 +388,13 @@ int CGameView::Initialize() CFG_GET_SYS_VAL("view.zoom.max", Float, m->ViewZoomMax); CFG_GET_SYS_VAL("view.zoom.default", Float, m->ViewZoomDefault); + CFG_GET_SYS_VAL("joystick.camera.pan.x", Int, m->JoystickPanX); + CFG_GET_SYS_VAL("joystick.camera.pan.y", Int, m->JoystickPanY); + CFG_GET_SYS_VAL("joystick.camera.rotate.x", Int, m->JoystickRotateX); + CFG_GET_SYS_VAL("joystick.camera.rotate.y", Int, m->JoystickRotateY); + CFG_GET_SYS_VAL("joystick.camera.zoom.in", Int, m->JoystickZoomIn); + CFG_GET_SYS_VAL("joystick.camera.zoom.out", Int, m->JoystickZoomOut); + CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosX.m_Smoothness); CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosY.m_Smoothness); CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosZ.m_Smoothness); @@ -647,6 +667,22 @@ void CGameView::Update(float DeltaTime) if (HotkeyIsPressed("camera.down")) moveForward -= m->ViewScrollSpeed * DeltaTime; + if (g_Joystick.IsEnabled()) + { + // This could all be improved with extra speed and sensitivity settings + // (maybe use pow to allow finer control?), and inversion settings + + moveRightward += g_Joystick.GetAxisValue(m->JoystickPanX) * m->ViewScrollSpeed * DeltaTime; + moveForward -= g_Joystick.GetAxisValue(m->JoystickPanY) * m->ViewScrollSpeed * DeltaTime; + + m->RotateX.AddSmoothly(g_Joystick.GetAxisValue(m->JoystickRotateX) * m->ViewRotateXSpeed * DeltaTime); + m->RotateY.AddSmoothly(-g_Joystick.GetAxisValue(m->JoystickRotateY) * m->ViewRotateYSpeed * DeltaTime); + + // Use a +1 bias for zoom because I want this to work with trigger buttons that default to -1 + m->Zoom.AddSmoothly((g_Joystick.GetAxisValue(m->JoystickZoomIn) + 1.0f) / 2.0f * m->ViewZoomSpeed * DeltaTime); + m->Zoom.AddSmoothly(-(g_Joystick.GetAxisValue(m->JoystickZoomOut) + 1.0f) / 2.0f * m->ViewZoomSpeed * DeltaTime); + } + if (moveRightward || moveForward) { // Break out of following mode when the user starts scrolling diff --git a/source/lib/sysdep/os/win/wsdl.cpp b/source/lib/sysdep/os/win/wsdl.cpp index f0ea4cc614..d4519fb25f 100644 --- a/source/lib/sysdep/os/win/wsdl.cpp +++ b/source/lib/sysdep/os/win/wsdl.cpp @@ -684,6 +684,35 @@ int SDL_EnableUNICODE(int UNUSED(enable)) } +//---------------------------------------------------------------------------- +// joystick + +int SDL_NumJoysticks() +{ + return 0; +} + +int SDL_JoystickEventState(int UNUSED(state)) +{ + return 0; +} + +SDL_Joystick* SDL_JoystickOpen(int UNUSED(device_index)) +{ + return NULL; +} + +int SDL_JoystickNumAxes(SDL_Joystick* UNUSED(joystick)) +{ + return 0; +} + +Sint16 SDL_JoystickGetAxis(SDL_Joystick* UNUSED(joystick), int UNUSED(axis)) +{ + return 0; +} + + //---------------------------------------------------------------------------- // app activation diff --git a/source/lib/sysdep/os/win/wsdl.h b/source/lib/sysdep/os/win/wsdl.h index e05eb5f30d..848482e153 100644 --- a/source/lib/sysdep/os/win/wsdl.h +++ b/source/lib/sysdep/os/win/wsdl.h @@ -33,6 +33,7 @@ typedef u8 Uint8; typedef u16 Uint16; +typedef i16 Sint16; typedef u32 Uint32; @@ -40,6 +41,7 @@ typedef u32 Uint32; #define SDL_INIT_VIDEO 0 #define SDL_INIT_AUDIO 0 #define SDL_INIT_TIMER 0 +#define SDL_INIT_JOYSTICK 0 #define SDL_INIT_NOPARACHUTE 0 LIB_API int SDL_Init(Uint32 flags); @@ -139,6 +141,18 @@ LIB_API Uint8 SDL_GetMouseState(int* x, int* y); LIB_API Uint8* SDL_GetKeyState(int* num_keys); +// +// joystick +// + +typedef void* SDL_Joystick; +int SDL_NumJoysticks(); +int SDL_JoystickEventState(int state); +SDL_Joystick* SDL_JoystickOpen(int device_index); +int SDL_JoystickNumAxes(SDL_Joystick* joystick); +Sint16 SDL_JoystickGetAxis(SDL_Joystick* joystick, int axis); + + // // byte swapping // diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index e31c314287..d7ba6ceaf9 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -44,6 +44,7 @@ #include "ps/Game.h" #include "ps/Globals.h" #include "ps/Hotkey.h" +#include "ps/Joystick.h" #include "ps/Loader.h" #include "ps/Overlay.h" #include "ps/Profile.h" @@ -528,6 +529,8 @@ static void InitInput() { SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + g_Joystick.Initialise(); + // register input handlers // This stack is constructed so the first added, will be the last // one called. This is important, because each of the handlers diff --git a/source/ps/Joystick.cpp b/source/ps/Joystick.cpp new file mode 100644 index 0000000000..93f69f1e99 --- /dev/null +++ b/source/ps/Joystick.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2010 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "Joystick.h" + +#include "lib/external_libraries/sdl.h" +#include "ps/CLogger.h" +#include "ps/ConfigDB.h" + +CJoystick g_Joystick; + +CJoystick::CJoystick() : + m_Joystick(NULL), m_Deadzone(0) +{ +} + +void CJoystick::Initialise() +{ + bool joystickEnable = false; + CFG_GET_USER_VAL("joystick.enable", Bool, joystickEnable); + if (!joystickEnable) + return; + + CFG_GET_USER_VAL("joystick.deadzone", Int, m_Deadzone); + + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) + { + LOGERROR(L"InitInput: failed to initialise joystick"); + return; + } + + int numJoysticks = SDL_NumJoysticks(); + + LOGMESSAGE(L"Found %d joystick(s)", numJoysticks); + + for (int i = 0; i < numJoysticks; ++i) + LOGMESSAGE(L"Joystick %d: %s", i, SDL_JoystickName(i)); + + if (numJoysticks) + { + SDL_JoystickEventState(SDL_ENABLE); + + // Always pick the first joystick, and assume that's the right one + m_Joystick = SDL_JoystickOpen(0); + } +} + +bool CJoystick::IsEnabled() +{ + return (m_Joystick != NULL); +} + +float CJoystick::GetAxisValue(int axis) +{ + if (!m_Joystick || axis < 0 || axis >= SDL_JoystickNumAxes(m_Joystick)) + return 0.f; + + int16_t val = SDL_JoystickGetAxis(m_Joystick, axis); + + // Normalize values into the range [-1, +1] excluding the deadzone around 0 + float norm; + if (val > m_Deadzone) + norm = (val - m_Deadzone) / (float)(32767 - m_Deadzone); + else if (val < -m_Deadzone) + norm = (val + m_Deadzone) / (float)(32767 - m_Deadzone); + else + norm = 0.f; + + return norm; +} diff --git a/source/ps/Joystick.h b/source/ps/Joystick.h new file mode 100644 index 0000000000..fe1aa2b6cd --- /dev/null +++ b/source/ps/Joystick.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2010 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_JOYSTICK +#define INCLUDED_JOYSTICK + +#include "lib/external_libraries/sdl.h" + +class CJoystick +{ +public: + CJoystick(); + + /** + * Initialises joystick support. + */ + void Initialise(); + + /** + * Returns true if initialised and the joystick is present and enabled by configuration. + */ + bool IsEnabled(); + + /** + * Returns current value of the given joystick axis, in the range [-1, +1]. + */ + float GetAxisValue(int axis); + +private: + SDL_Joystick* m_Joystick; + int m_Deadzone; +}; + +extern CJoystick g_Joystick; + +#endif // INCLUDED_JOYSTICK