From ab76c6218883c3b8db18a08b4fac813497cea1d0 Mon Sep 17 00:00:00 2001 From: bosnichd Date: Wed, 3 Nov 2021 09:07:00 -0600 Subject: [PATCH] Allow input devices to be constructed with a custom implementation. (#5217) * Allow input devices to be constructed with a custom implementation. This augments the existing functionality that allows for an input device implementation to be swapped out at runtime, Signed-off-by: bosnichd * Updates based on review feedback, and fix for clang builds. Signed-off-by: bosnichd * Update based on review feedback, and change the InputDeviceImplementationRequest bus to use the same ImplementationFactory type alias. Signed-off-by: bosnichd --- .../Buses/Requests/InputDeviceRequestBus.h | 18 +++++------------- .../Devices/Gamepad/InputDeviceGamepad.cpp | 13 ++++++++++--- .../Input/Devices/Gamepad/InputDeviceGamepad.h | 15 +++++++++++++++ .../Devices/Keyboard/InputDeviceKeyboard.cpp | 9 +++++---- .../Devices/Keyboard/InputDeviceKeyboard.h | 13 ++++++++++++- .../Input/Devices/Motion/InputDeviceMotion.cpp | 9 +++++---- .../Input/Devices/Motion/InputDeviceMotion.h | 13 ++++++++++++- .../Input/Devices/Mouse/InputDeviceMouse.cpp | 9 +++++---- .../Input/Devices/Mouse/InputDeviceMouse.h | 13 ++++++++++++- .../Input/Devices/Touch/InputDeviceTouch.cpp | 9 +++++---- .../Input/Devices/Touch/InputDeviceTouch.h | 13 ++++++++++++- .../InputDeviceVirtualKeyboard.cpp | 9 +++++---- .../InputDeviceVirtualKeyboard.h | 13 ++++++++++++- 13 files changed, 115 insertions(+), 41 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Input/Buses/Requests/InputDeviceRequestBus.h b/Code/Framework/AzFramework/AzFramework/Input/Buses/Requests/InputDeviceRequestBus.h index 147ff7f0b8..74e2459ab6 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Buses/Requests/InputDeviceRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Buses/Requests/InputDeviceRequestBus.h @@ -229,17 +229,13 @@ namespace AzFramework //! Alias for the EBus implementation of this interface using Bus = AZ::EBus>; - //////////////////////////////////////////////////////////////////////////////////////////// - //! Alias for the function type used to create the custom implementations - using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&); - //////////////////////////////////////////////////////////////////////////////////////////// //! Set a custom implementation for this input device type, either for a specific instance //! by addressing the call to an InputDeviceId, or for all existing instances by broadcast. //! Passing InputDeviceType::Implementation::Create as the argument will create the default //! device implementation, while passing nullptr will delete any existing implementation. - //! \param[in] createFunction Pointer to the function that will create the implementation. - virtual void SetCustomImplementation(CreateFunctionType createFunction) = 0; + //! \param[in] implementationFactory Pointer to the function that creates the implementation. + virtual void SetCustomImplementation(typename InputDeviceType::ImplementationFactory implementationFactory) = 0; }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -267,18 +263,14 @@ namespace AzFramework AZ_DISABLE_COPY_MOVE(InputDeviceImplementationRequestHandler); protected: - //////////////////////////////////////////////////////////////////////////////////////////// - //! Alias for the function type used to create the custom implementations - using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&); - //////////////////////////////////////////////////////////////////////////////////////////// //! \ref InputDeviceImplementationRequest::SetCustomImplementation - AZ_INLINE void SetCustomImplementation(CreateFunctionType createFunction) override + AZ_INLINE void SetCustomImplementation(typename InputDeviceType::ImplementationFactory implementationFactory) override { AZStd::unique_ptr newImplementation; - if (createFunction) + if (implementationFactory) { - newImplementation.reset(createFunction(m_inputDevice)); + newImplementation.reset(implementationFactory(m_inputDevice)); } m_inputDevice.SetImplementation(AZStd::move(newImplementation)); } diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.cpp index 51aa008519..9759a95733 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.cpp @@ -94,7 +94,14 @@ namespace AzFramework //////////////////////////////////////////////////////////////////////////////////////////////// InputDeviceGamepad::InputDeviceGamepad(AZ::u32 index) - : InputDevice(InputDeviceId(Name, index)) + : InputDeviceGamepad(InputDeviceId(Name, index)) // Delegated constructor + { + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + InputDeviceGamepad::InputDeviceGamepad(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_allChannelsById() , m_buttonChannelsById() , m_triggerChannelsById() @@ -144,8 +151,8 @@ namespace AzFramework m_thumbStickDirectionChannelsById[channelId] = channel; } - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); // Connect to the haptic feedback request bus InputHapticFeedbackRequestBus::Handler::BusConnect(GetInputDeviceId()); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h index 286b4f0df3..7be498830b 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad.h @@ -182,6 +182,14 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceGamepad&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor explicit InputDeviceGamepad(); @@ -191,6 +199,13 @@ namespace AzFramework //! \param[in] index Index of the game-pad device explicit InputDeviceGamepad(AZ::u32 index); + //////////////////////////////////////////////////////////////////////////////////////////// + //! Constructor + //! \param[in] inputDeviceId Id of the input device + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceGamepad(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory = &Implementation::Create); + //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying AZ_DISABLE_COPY_MOVE(InputDeviceGamepad); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.cpp index d1117ea895..2a76cc6e1b 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.cpp @@ -182,8 +182,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - InputDeviceKeyboard::InputDeviceKeyboard(AzFramework::InputDeviceId id) - : InputDevice(id) + InputDeviceKeyboard::InputDeviceKeyboard(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_modifierKeyStates(AZStd::make_shared()) , m_allChannelsById() , m_keyChannelsById() @@ -203,8 +204,8 @@ namespace AzFramework m_keyChannelsById[channelId] = channel; } - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); // Connect to the text entry request bus InputTextEntryRequestBus::Handler::BusConnect(GetInputDeviceId()); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h index e3c21ec326..c0c2f5d92b 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h @@ -370,9 +370,20 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceKeyboard&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor - InputDeviceKeyboard(AzFramework::InputDeviceId id = Id); + //! \param[in] inputDeviceId Optional override of the default input device id + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceKeyboard(const InputDeviceId& inputDeviceId = Id, + ImplementationFactory implementationFactory = &Implementation::Create); //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.cpp index c144f63d2c..d4057bc5d3 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.cpp @@ -60,8 +60,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - InputDeviceMotion::InputDeviceMotion() - : InputDevice(Id) + InputDeviceMotion::InputDeviceMotion(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_allChannelsById() , m_accelerationChannelsById() , m_rotationRateChannelsById() @@ -107,8 +108,8 @@ namespace AzFramework m_orientationChannelsById[channelId] = channel; } - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); // Connect to the motion sensor request bus InputMotionSensorRequestBus::Handler::BusConnect(GetInputDeviceId()); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.h index 872bd1cfa0..f0fc976963 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Motion/InputDeviceMotion.h @@ -126,9 +126,20 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceMotion&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor - InputDeviceMotion(); + //! \param[in] inputDeviceId Optional override of the default input device id + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceMotion(const InputDeviceId& inputDeviceId = Id, + ImplementationFactory implementationFactory = &Implementation::Create); //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.cpp index e9af4cc4ce..39504d9352 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.cpp @@ -67,8 +67,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - InputDeviceMouse::InputDeviceMouse(AzFramework::InputDeviceId id) - : InputDevice(id) + InputDeviceMouse::InputDeviceMouse(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_allChannelsById() , m_buttonChannelsById() , m_movementChannelsById() @@ -97,8 +98,8 @@ namespace AzFramework m_cursorPositionChannel = aznew InputChannelDeltaWithSharedPosition2D(SystemCursorPosition, *this, m_cursorPositionData2D); m_allChannelsById[SystemCursorPosition] = m_cursorPositionChannel; - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); // Connect to the system cursor request bus InputSystemCursorRequestBus::Handler::BusConnect(GetInputDeviceId()); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.h index 3b35e03f1b..3c519a3edb 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Mouse/InputDeviceMouse.h @@ -122,9 +122,20 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceMouse&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor - explicit InputDeviceMouse(AzFramework::InputDeviceId id = Id); + //! \param[in] inputDeviceId Optional override of the default input device id + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceMouse(const InputDeviceId& inputDeviceId = Id, + ImplementationFactory implementationFactory = &Implementation::Create); //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.cpp index be850e9289..2695e3bb08 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.cpp @@ -59,8 +59,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - InputDeviceTouch::InputDeviceTouch() - : InputDevice(Id) + InputDeviceTouch::InputDeviceTouch(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_allChannelsById() , m_touchChannelsById() , m_pimpl(nullptr) @@ -75,8 +76,8 @@ namespace AzFramework m_touchChannelsById[channelId] = channel; } - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); } //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.h index d21834c22a..12b8aded4b 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/Touch/InputDeviceTouch.h @@ -77,9 +77,20 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceTouch&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor - InputDeviceTouch(); + //! \param[in] inputDeviceId Optional override of the default input device id + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceTouch(const InputDeviceId& inputDeviceId = Id, + ImplementationFactory implementationFactory = &Implementation::Create); //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.cpp b/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.cpp index f3024f11ab..bcbdeaa478 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.cpp @@ -51,8 +51,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - InputDeviceVirtualKeyboard::InputDeviceVirtualKeyboard() - : InputDevice(Id) + InputDeviceVirtualKeyboard::InputDeviceVirtualKeyboard(const InputDeviceId& inputDeviceId, + ImplementationFactory implementationFactory) + : InputDevice(inputDeviceId) , m_allChannelsById() , m_pimpl() , m_implementationRequestHandler(*this) @@ -65,8 +66,8 @@ namespace AzFramework m_commandChannelsById[channelId] = channel; } - // Create the platform specific implementation - m_pimpl.reset(Implementation::Create(*this)); + // Create the platform specific or custom implementation + m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr); // Connect to the text entry request bus InputTextEntryRequestBus::Handler::BusConnect(GetInputDeviceId()); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.h b/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.h index 6f62c3ec61..abe1312733 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard.h @@ -69,9 +69,20 @@ namespace AzFramework // Reflection static void Reflect(AZ::ReflectContext* context); + //////////////////////////////////////////////////////////////////////////////////////////// + // Foward declare the internal Implementation class so it can be passed into the constructor + class Implementation; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Alias for the function type used to create a custom implementation for this input device + using ImplementationFactory = Implementation*(InputDeviceVirtualKeyboard&); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor - InputDeviceVirtualKeyboard(); + //! \param[in] inputDeviceId Optional override of the default input device id + //! \param[in] implementationFactory Optional override of the default Implementation::Create + explicit InputDeviceVirtualKeyboard(const InputDeviceId& inputDeviceId = Id, + ImplementationFactory implementationFactory = &Implementation::Create); //////////////////////////////////////////////////////////////////////////////////////////// // Disable copying