/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "VirtualGamepad_precompiled.h" #include "InputDeviceVirtualGamepad.h" #include "VirtualGamepadButtonRequestBus.h" #include "VirtualGamepadThumbStickRequestBus.h" #include <AzFramework/Input/Devices/Touch/InputDeviceTouch.h> //////////////////////////////////////////////////////////////////////////////////////////////////// namespace VirtualGamepad { using namespace AzFramework; //////////////////////////////////////////////////////////////////////////////////////////////// const InputDeviceId InputDeviceVirtualGamepad::Id("virtual_gamepad"); //////////////////////////////////////////////////////////////////////////////////////////////// bool InputDeviceVirtualGamepad::IsVirtualGamepadDevice(const InputDeviceId& inputDeviceId) { return (inputDeviceId.GetNameCrc32() == Id.GetNameCrc32()); } //////////////////////////////////////////////////////////////////////////////////////////////// InputDeviceVirtualGamepad::InputDeviceVirtualGamepad( const AZStd::unordered_set<AZStd::string>& buttonNames, const AZStd::unordered_set<AZStd::string>& thumbStickNames) : InputDevice(Id) , m_allChannelsById() , m_buttonChannelsByName() , m_thumbStickAxis1DChannelsByName() , m_thumbStickAxis2DChannelsByName() , m_thumbStickDirectionChannelsByName() { // Create all button input channels for (const AZStd::string& buttonName : buttonNames) { CreateButtonChannel(buttonName); } // Create all thumb-stick input channels for (const AZStd::string& thumbStickName : thumbStickNames) { CreateThumbStickAxis2DChannel(thumbStickName); CreateThumbStickAxis1DChannel(thumbStickName + "_x"); CreateThumbStickAxis1DChannel(thumbStickName + "_y"); CreateThumbStickDirectionChannel(thumbStickName + "_u"); CreateThumbStickDirectionChannel(thumbStickName + "_d"); CreateThumbStickDirectionChannel(thumbStickName + "_l"); CreateThumbStickDirectionChannel(thumbStickName + "_r"); } } //////////////////////////////////////////////////////////////////////////////////////////////// InputDeviceVirtualGamepad::~InputDeviceVirtualGamepad() { // Destroy all thumb-stick direction input channels for (const auto& channelByName : m_thumbStickDirectionChannelsByName) { delete channelByName.second; } // Destroy all thumb-stick 2D axis input channels for (const auto& channelByName : m_thumbStickAxis2DChannelsByName) { delete channelByName.second; } // Destroy all thumb-stick 1D axis input channels for (const auto& channelByName : m_thumbStickAxis1DChannelsByName) { delete channelByName.second; } // Destroy all button input channels for (const auto& channelByName : m_buttonChannelsByName) { delete channelByName.second; } } //////////////////////////////////////////////////////////////////////////////////////////////// const InputDevice::InputChannelByIdMap& InputDeviceVirtualGamepad::GetInputChannelsById() const { return m_allChannelsById; } //////////////////////////////////////////////////////////////////////////////////////////////// bool InputDeviceVirtualGamepad::IsSupported() const { // Touch input must be supported const InputDevice* inputDevice = nullptr; InputDeviceRequestBus::EventResult(inputDevice, InputDeviceTouch::Id, &InputDeviceRequests::GetInputDevice); return inputDevice && inputDevice->IsSupported(); } //////////////////////////////////////////////////////////////////////////////////////////////// bool InputDeviceVirtualGamepad::IsConnected() const { // Touch input must be connected const InputDevice* inputDevice = nullptr; InputDeviceRequestBus::EventResult(inputDevice, InputDeviceTouch::Id, &InputDeviceRequests::GetInputDevice); return inputDevice && inputDevice->IsConnected(); } //////////////////////////////////////////////////////////////////////////////////////////////// void InputDeviceVirtualGamepad::TickInputDevice() { for (const auto& buttonChannelByName : m_buttonChannelsByName) { bool isButtonPressed = false; VirtualGamepadButtonRequestBus::EventResult(isButtonPressed, buttonChannelByName.first, &VirtualGamepadButtonRequests::IsPressed); buttonChannelByName.second->ProcessRawInputEvent(isButtonPressed); } for (const auto& thumbStickAxis2DChannelByName : m_thumbStickAxis2DChannelsByName) { const AZStd::string& thumbStickName = thumbStickAxis2DChannelByName.first; AZ::Vector2 axisValues(0.0f, 0.0f); VirtualGamepadThumbStickRequestBus::EventResult(axisValues, thumbStickName, &VirtualGamepadThumbStickRequests::GetCurrentAxisValuesNormalized); thumbStickAxis2DChannelByName.second->ProcessRawInputEvent(axisValues); m_thumbStickAxis1DChannelsByName[thumbStickName + "_x"]->ProcessRawInputEvent(axisValues.GetX()); m_thumbStickAxis1DChannelsByName[thumbStickName + "_y"]->ProcessRawInputEvent(axisValues.GetY()); const float upValue = AZ::GetClamp(axisValues.GetY(), 0.0f, 1.0f); const float downValue = AZ::GetClamp(axisValues.GetY(), -1.0f, 0.0f); const float leftValue = AZ::GetClamp(axisValues.GetX(), -1.0f, 0.0f); const float rightValue = AZ::GetClamp(axisValues.GetX(), 0.0f, 1.0f); m_thumbStickDirectionChannelsByName[thumbStickName + "_u"]->ProcessRawInputEvent(upValue); m_thumbStickDirectionChannelsByName[thumbStickName + "_d"]->ProcessRawInputEvent(downValue); m_thumbStickDirectionChannelsByName[thumbStickName + "_l"]->ProcessRawInputEvent(leftValue); m_thumbStickDirectionChannelsByName[thumbStickName + "_r"]->ProcessRawInputEvent(rightValue); } } //////////////////////////////////////////////////////////////////////////////////////////////// void InputDeviceVirtualGamepad::CreateButtonChannel(const AZStd::string& channelName) { const InputChannelId channelId(channelName.c_str()); InputChannelDigital* channel = aznew InputChannelDigital(channelId, *this); m_allChannelsById[channelId] = channel; m_buttonChannelsByName[channelName] = channel; } //////////////////////////////////////////////////////////////////////////////////////////////// void InputDeviceVirtualGamepad::CreateThumbStickAxis1DChannel(const AZStd::string& channelName) { const InputChannelId channelId(channelName.c_str()); InputChannelAxis1D* channel = aznew InputChannelAxis1D(channelId, *this); m_allChannelsById[channelId] = channel; m_thumbStickAxis1DChannelsByName[channelName] = channel; } //////////////////////////////////////////////////////////////////////////////////////////////// void InputDeviceVirtualGamepad::CreateThumbStickAxis2DChannel(const AZStd::string& channelName) { const InputChannelId channelId(channelName.c_str()); InputChannelAxis2D* channel = aznew InputChannelAxis2D(channelId, *this); m_allChannelsById[channelId] = channel; m_thumbStickAxis2DChannelsByName[channelName] = channel; } //////////////////////////////////////////////////////////////////////////////////////////////// void InputDeviceVirtualGamepad::CreateThumbStickDirectionChannel(const AZStd::string& channelName) { const InputChannelId channelId(channelName.c_str()); InputChannelAnalog* channel = aznew InputChannelAnalog(channelId, *this); m_allChannelsById[channelId] = channel; m_thumbStickDirectionChannelsByName[channelName] = channel; } } // namespace VirtualGamepad