From 209314c76a4e883fa02cd01641f2e4d18294ac41 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sun, 19 May 2019 15:05:51 +0100 Subject: [PATCH] input manager update: analog stick; added controller support to tps characer sample; --- Documentation/ScriptingAPI-Documentation.md | 7 +++ Editor/Editor.cpp | 16 ++++-- WickedEngine/wiInputManager.cpp | 54 +++++++++++++++++++++ WickedEngine/wiInputManager.h | 9 ++++ WickedEngine/wiInputManager_BindLua.cpp | 28 +++++++++++ WickedEngine/wiInputManager_BindLua.h | 1 + WickedEngine/wiVersion.cpp | 2 +- scripts/character_controller_tps.lua | 47 +++++++++++------- 8 files changed, 142 insertions(+), 22 deletions(-) diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index 1e6ffc07b..d9c45409b 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -646,6 +646,7 @@ Query input devices - GetPointer() : Vector result - SetPointer(Vector pos) - HidePointer(bool visible) +- GetAnalog(int type, opt int playerindex = 0) : Vector result -- read analog data from gamepad. type parameter must be from GAMEPAD_ANALOG values - GetTouches() : Touch result[] #### Touch @@ -704,6 +705,12 @@ Describes a touch contact point ... - [outer]GAMEPAD_14 : int +#### Gamepad Analog Codes +- [outer]GAMEPAD_ANALOG_THUMBSTICK_L : int +- [outer]GAMEPAD_ANALOG_THUMBSTICK_R : int +- [outer]GAMEPAD_ANALOG_TRIGGER_L : int +- [outer]GAMEPAD_ANALOG_TRIGGER_R : int + ### ResourceManager Stores and manages resources such as textures, sounds and shaders. - [outer]globalResources : Resource diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 9f08f4260..a460dac43 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -774,6 +774,14 @@ void EditorComponent::Update(float dt) yDif += buttonrotSpeed; } + const XMFLOAT4 leftStick = wiInputManager::getanalog(GAMEPAD_ANALOG_THUMBSTICK_L, 0); + const XMFLOAT4 rightStick = wiInputManager::getanalog(GAMEPAD_ANALOG_THUMBSTICK_R, 0); + const XMFLOAT4 rightTrigger = wiInputManager::getanalog(GAMEPAD_ANALOG_TRIGGER_R, 0); + + const float jostickrotspeed = 0.05f; + xDif += rightStick.x * jostickrotspeed; + yDif += rightStick.y * jostickrotspeed; + xDif *= cameraWnd->rotationspeedSlider->GetValue(); yDif *= cameraWnd->rotationspeedSlider->GetValue(); @@ -783,10 +791,9 @@ void EditorComponent::Update(float dt) // FPS Camera const float clampedDT = min(dt, 0.1f); // if dt > 100 millisec, don't allow the camera to jump too far... - const float speed = (wiInputManager::down(VK_SHIFT) ? 10.0f : 1.0f) * cameraWnd->movespeedSlider->GetValue() * clampedDT; + const float speed = ((wiInputManager::down(VK_SHIFT) ? 10.0f : 1.0f) + rightTrigger.x * 10.0f) * cameraWnd->movespeedSlider->GetValue() * clampedDT; static XMVECTOR move = XMVectorSet(0, 0, 0, 0); - XMVECTOR moveNew = XMVectorSet(0, 0, 0, 0); - + XMVECTOR moveNew = XMVectorSet(leftStick.x, 0, leftStick.y, 0); if (!wiInputManager::down(VK_CONTROL)) { @@ -797,8 +804,9 @@ void EditorComponent::Update(float dt) if (wiInputManager::down('S') || wiInputManager::down(GAMEPAD_BUTTON_DOWN, INPUT_TYPE_GAMEPAD)) { moveNew += XMVectorSet(0, 0, -1, 0); } if (wiInputManager::down('E') || wiInputManager::down(GAMEPAD_BUTTON_2, INPUT_TYPE_GAMEPAD)) { moveNew += XMVectorSet(0, 1, 0, 0); } if (wiInputManager::down('Q') || wiInputManager::down(GAMEPAD_BUTTON_1, INPUT_TYPE_GAMEPAD)) { moveNew += XMVectorSet(0, -1, 0, 0); } - moveNew = XMVector3Normalize(moveNew) * speed; + moveNew += XMVector3Normalize(moveNew); } + moveNew *= speed; move = XMVectorLerp(move, moveNew, 0.18f * clampedDT / 0.0166f); // smooth the movement a bit float moveLength = XMVectorGetX(XMVector3Length(move)); diff --git a/WickedEngine/wiInputManager.cpp b/WickedEngine/wiInputManager.cpp index a70b21b18..b0b6d2397 100644 --- a/WickedEngine/wiInputManager.cpp +++ b/WickedEngine/wiInputManager.cpp @@ -6,6 +6,7 @@ #include "wiHelper.h" #include "wiBackLog.h" +#include #include #include #include @@ -293,6 +294,59 @@ namespace wiInputManager #endif } + inline float deadzone(float x) + { + if ((x) > -0.24f && (x) < 0.24f) + x = 0; + if (x < -1.0f) + x = -1.0f; + if (x > 1.0f) + x = 1.0f; + return x; + } + XMFLOAT4 getanalog(GAMEPAD_ANALOG analog, short playerindex) + { + if (playerindex < (int)controllers.size()) + { + const Controller& controller = controllers[playerindex]; + + if (xinput != nullptr && controller.deviceType == Controller::XINPUT) + { + const auto& state = xinput->controllers[controller.deviceIndex].state.Gamepad; + + switch (analog) + { + case GAMEPAD_ANALOG_THUMBSTICK_L: return XMFLOAT4(deadzone((float)state.sThumbLX / 32767.0f), deadzone((float)state.sThumbLY / 32767.0f), 0, 0); + case GAMEPAD_ANALOG_THUMBSTICK_R: return XMFLOAT4(deadzone((float)state.sThumbRX / 32767.0f), deadzone((float)state.sThumbRY / 32767.0f), 0, 0); + case GAMEPAD_ANALOG_TRIGGER_L: return XMFLOAT4((float)state.bLeftTrigger / 255.0f, 0, 0, 0); + case GAMEPAD_ANALOG_TRIGGER_R: return XMFLOAT4((float)state.bRightTrigger / 255.0f, 0, 0, 0); + default: + break; + } + } + +#ifndef WINSTORE_SUPPORT + if (dinput != nullptr && controller.deviceType == Controller::DIRECTINPUT) + { + const auto& state = dinput->joyState[controller.deviceIndex]; + + switch (analog) + { + case GAMEPAD_ANALOG_THUMBSTICK_L: return XMFLOAT4(deadzone((float)state.lX / 1000.0f), deadzone(-(float)state.lY / 1000.0f), 0, 0); + case GAMEPAD_ANALOG_THUMBSTICK_R: return XMFLOAT4(deadzone((float)state.lZ / 1000.0f), deadzone((float)state.lRz / 1000.0f), 0, 0); + case GAMEPAD_ANALOG_TRIGGER_L: return XMFLOAT4((float)state.lRx / 1000.0f * 0.5f + 0.5f, 0, 0, 0); + case GAMEPAD_ANALOG_TRIGGER_R: return XMFLOAT4((float)state.lRy / 1000.0f * 0.5f + 0.5f, 0, 0, 0); + default: + break; + } + } +#endif + + } + + return XMFLOAT4(0, 0, 0, 0); + } + void AddTouch(const Touch& touch) { diff --git a/WickedEngine/wiInputManager.h b/WickedEngine/wiInputManager.h index 177aaa075..751757690 100644 --- a/WickedEngine/wiInputManager.h +++ b/WickedEngine/wiInputManager.h @@ -29,6 +29,13 @@ enum GAMEPAD_BUTTON GAMEPAD_BUTTON_13, GAMEPAD_BUTTON_14, }; +enum GAMEPAD_ANALOG +{ + GAMEPAD_ANALOG_THUMBSTICK_L, + GAMEPAD_ANALOG_THUMBSTICK_R, + GAMEPAD_ANALOG_TRIGGER_L, + GAMEPAD_ANALOG_TRIGGER_R, +}; namespace wiInputManager { @@ -50,6 +57,8 @@ namespace wiInputManager void setpointer(const XMFLOAT4& props); // hide pointer void hidepointer(bool value); + // read analog input from controllers, like thumbsticks or triggers + XMFLOAT4 getanalog(GAMEPAD_ANALOG analog, short playerIndex = 0); struct Touch { diff --git a/WickedEngine/wiInputManager_BindLua.cpp b/WickedEngine/wiInputManager_BindLua.cpp index c047019f5..961f76b94 100644 --- a/WickedEngine/wiInputManager_BindLua.cpp +++ b/WickedEngine/wiInputManager_BindLua.cpp @@ -10,6 +10,7 @@ Luna::FunctionType wiInputManager_BindLua::methods[] = { lunamethod(wiInputManager_BindLua, GetPointer), lunamethod(wiInputManager_BindLua, SetPointer), lunamethod(wiInputManager_BindLua, HidePointer), + lunamethod(wiInputManager_BindLua, GetAnalog), lunamethod(wiInputManager_BindLua, GetTouches), { NULL, NULL } }; @@ -131,6 +132,27 @@ int wiInputManager_BindLua::HidePointer(lua_State* L) wiLua::SError(L, "HidePointer(bool value) not enough arguments!"); return 0; } +int wiInputManager_BindLua::GetAnalog(lua_State* L) +{ + XMFLOAT4 result = XMFLOAT4(0, 0, 0, 0); + + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + GAMEPAD_ANALOG type = (GAMEPAD_ANALOG)wiLua::SGetInt(L, 1); + short playerindex = 0; + if (argc > 1) + { + playerindex = (short)wiLua::SGetInt(L, 2); + } + result = wiInputManager::getanalog(type, playerindex); + } + else + wiLua::SError(L, "GetAnalog(int type, opt int playerindex = 0) not enough arguments!"); + + Luna::push(L, new Vector_BindLua(XMLoadFloat4(&result))); + return 1; +} int wiInputManager_BindLua::GetTouches(lua_State* L) { auto& touches = wiInputManager::getTouches(); @@ -202,6 +224,12 @@ void wiInputManager_BindLua::Bind() wiLua::GetGlobal()->RunText("GAMEPAD_BUTTON_13 = 16"); wiLua::GetGlobal()->RunText("GAMEPAD_BUTTON_14 = 17"); + //Analog + wiLua::GetGlobal()->RunText("GAMEPAD_ANALOG_THUMBSTICK_L = 0"); + wiLua::GetGlobal()->RunText("GAMEPAD_ANALOG_THUMBSTICK_R = 1"); + wiLua::GetGlobal()->RunText("GAMEPAD_ANALOG_TRIGGER_L = 2"); + wiLua::GetGlobal()->RunText("GAMEPAD_ANALOG_TRIGGER_R = 3"); + //Touch wiLua::GetGlobal()->RunText("TOUCHSTATE_PRESSED = 0"); wiLua::GetGlobal()->RunText("TOUCHSTATE_RELEASED = 1"); diff --git a/WickedEngine/wiInputManager_BindLua.h b/WickedEngine/wiInputManager_BindLua.h index abda3a317..1fb04c903 100644 --- a/WickedEngine/wiInputManager_BindLua.h +++ b/WickedEngine/wiInputManager_BindLua.h @@ -19,6 +19,7 @@ public: int GetPointer(lua_State* L); int SetPointer(lua_State* L); int HidePointer(lua_State* L); + int GetAnalog(lua_State* L); int GetTouches(lua_State* L); static void Bind(); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 3133091bf..bd86ea296 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 26; // minor bug fixes, alterations, refactors, updates - const int revision = 29; + const int revision = 30; long GetVersion() diff --git a/scripts/character_controller_tps.lua b/scripts/character_controller_tps.lua index d45202dc4..4f4f043a3 100644 --- a/scripts/character_controller_tps.lua +++ b/scripts/character_controller_tps.lua @@ -2,11 +2,11 @@ -- This script will load a simple scene with a character that can be controlled -- -- CONTROLS: --- WASD: walk --- SHIFT: speed --- SPACE: Jump --- Right Mouse Button: rotate camera --- Scoll middle mouse: adjust camera distance +-- WASD/left thumbstick: walk +-- SHIFT/right shoulder button: speed +-- SPACE/gamepad X/gamepad button 2: Jump +-- Right Mouse Button/Right thumbstick: rotate camera +-- Scoll middle mouse/Left-Right triggers: adjust camera distance -- ESCAPE key: quit -- ENTER: reload script @@ -110,9 +110,12 @@ Character = { if(input.Down(VK_DOWN) or input.Down(string.byte('S'))) then lookDir = lookDir:Add( Vector(0,0,-1) ) end + + local analog = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_L) + lookDir = vector.Add(lookDir, Vector(analog.GetX(), 0, analog.GetY())) if(lookDir:Length()>0) then - if(input.Down(VK_LSHIFT)) then + if(input.Down(VK_LSHIFT) or input.Down(GAMEPAD_BUTTON_6, INPUT_TYPE_GAMEPAD)) then self:MoveDirection(lookDir,self.moveSpeed*2) else self:MoveDirection(lookDir,self.moveSpeed) @@ -121,19 +124,22 @@ Character = { end - if( input.Press(string.byte('J')) or input.Press(VK_SPACE) ) then + if( input.Press(string.byte('J')) or input.Press(VK_SPACE) or input.Press(GAMEPAD_BUTTON_2, INPUT_TYPE_GAMEPAD) ) then self:Jump(0.6) end + + -- Camera target control: + + -- read from gamepad analog stick: + local diff = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_R) + diff = vector.Multiply(diff, getDeltaTime() * 4) - -- mouse control + -- read from mouse: if(input.Down(VK_RBUTTON)) then local mousePosNew = input.GetPointer() local mouseDif = vector.Subtract(mousePosNew,self.savedPointerPos) mouseDif = mouseDif:Multiply(getDeltaTime() * 0.3) - local target_transform = scene.Component_GetTransform(self.target) - target_transform.Rotate(Vector(mouseDif.GetY(),mouseDif.GetX())) - self.face.SetY(0) - self.face=self.face:Normalize() + diff = vector.Add(diff, mouseDif) input.SetPointer(self.savedPointerPos) input.HidePointer(true) else @@ -141,6 +147,11 @@ Character = { input.HidePointer(false) end + local target_transform = scene.Component_GetTransform(self.target) + target_transform.Rotate(Vector(diff.GetY(),diff.GetX())) + self.face.SetY(0) + self.face=self.face:Normalize() + end, Update = function(self) @@ -238,9 +249,11 @@ ThirdPersonCamera = { Update = function(self) if(self.character ~= nil) then - -- Mouse scroll will move the camera distance: - local mouse_scroll = input.GetPointer().GetZ() -- pointer.z is the mouse wheel delta this frame - self.rest_distance_new = math.max(self.rest_distance_new - mouse_scroll, 2) -- do not allow too close using max + -- Mouse scroll or gamepad triggers will move the camera distance: + local scroll = input.GetPointer().GetZ() -- pointer.z is the mouse wheel delta this frame + scroll = scroll + input.GetAnalog(GAMEPAD_ANALOG_TRIGGER_R).GetX() + scroll = scroll - input.GetAnalog(GAMEPAD_ANALOG_TRIGGER_L).GetX() + self.rest_distance_new = math.max(self.rest_distance_new - scroll, 2) -- do not allow too close using max self.rest_distance = math.lerp(self.rest_distance, self.rest_distance_new, 0.1) -- lerp will smooth out the zooming -- We update the scene so that character's target_transform will be using up to date values @@ -336,8 +349,8 @@ runProcess(function() path.SetLightShaftsEnabled(true) main.SetActivePath(path) - local font = Font("This script is showcasing how to perform scene collision with raycasts for character and camera.\nControls:\n#####################\n\nWASD/arrows: walk\nSHIFT: movement speed\nSPACE: Jump\nRight Mouse Button: rotate camera\nScoll middle mouse: adjust camera distance\nESCAPE key: quit\nR: reload script"); - font.SetSize(20) + local font = Font("This script is showcasing how to perform scene collision with raycasts for character and camera.\nControls:\n#####################\n\nWASD/arrows/left analog stick: walk\nSHIFT/right shoulder button: movement speed\nSPACE/gamepad X/gamepad button 2: Jump\nRight Mouse Button/Right thumbstick: rotate camera\nScoll middle mouse/Left-Right triggers: adjust camera distance\nESCAPE key: quit\nR: reload script"); + font.SetSize(24) font.SetPos(Vector(10, GetScreenHeight() - 10)) font.SetAlign(WIFALIGN_LEFT, WIFALIGN_BOTTOM) font.SetColor(0xFFADA3FF)