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 <bosnichd@amazon.com>

* Updates based on review feedback, and fix for clang builds.

Signed-off-by: bosnichd <bosnichd@amazon.com>

* Update based on review feedback, and change the InputDeviceImplementationRequest bus to use the same ImplementationFactory type alias.

Signed-off-by: bosnichd <bosnichd@amazon.com>
This commit is contained in:
bosnichd
2021-11-03 09:07:00 -06:00
committed by GitHub
parent b3301414ad
commit ab76c62188
13 changed files with 115 additions and 41 deletions
@@ -229,17 +229,13 @@ namespace AzFramework
//! Alias for the EBus implementation of this interface
using Bus = AZ::EBus<InputDeviceImplementationRequest<InputDeviceType>>;
////////////////////////////////////////////////////////////////////////////////////////////
//! 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<InputDeviceType>::SetCustomImplementation
AZ_INLINE void SetCustomImplementation(CreateFunctionType createFunction) override
AZ_INLINE void SetCustomImplementation(typename InputDeviceType::ImplementationFactory implementationFactory) override
{
AZStd::unique_ptr<typename InputDeviceType::Implementation> newImplementation;
if (createFunction)
if (implementationFactory)
{
newImplementation.reset(createFunction(m_inputDevice));
newImplementation.reset(implementationFactory(m_inputDevice));
}
m_inputDevice.SetImplementation(AZStd::move(newImplementation));
}
@@ -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());
@@ -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);
@@ -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<ModifierKeyStates>())
, 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());
@@ -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
@@ -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());
@@ -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
@@ -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());
@@ -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
@@ -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);
}
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -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
@@ -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());
@@ -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