2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-06-04 15:42:48 -04:00
# include "InputRouter.h"
2022-09-24 13:57:58 -04:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(InputRouter)
2019-06-04 15:42:48 -04:00
2019-10-01 20:41:42 -04:00
# define LOCTEXT_NAMESPACE "UInputRouter"
2019-06-04 15:42:48 -04:00
UInputRouter : : UInputRouter ( )
{
ActiveLeftCapture = nullptr ;
ActiveLeftCaptureOwner = nullptr ;
ActiveRightCapture = nullptr ;
ActiveRightCaptureOwner = nullptr ;
ActiveKeyboardCapture = nullptr ;
ActiveKeyboardCaptureOwner = nullptr ;
bAutoInvalidateOnHover = false ;
bAutoInvalidateOnCapture = false ;
ActiveInputBehaviors = NewObject < UInputBehaviorSet > ( this , " InputBehaviors " ) ;
}
void UInputRouter : : Initialize ( IToolsContextTransactionsAPI * TransactionsAPIIn )
{
this - > TransactionsAPI = TransactionsAPIIn ;
}
void UInputRouter : : Shutdown ( )
{
this - > TransactionsAPI = nullptr ;
}
void UInputRouter : : RegisterSource ( IInputBehaviorSource * Source )
{
ActiveInputBehaviors - > Add ( Source - > GetInputBehaviors ( ) , Source ) ;
}
void UInputRouter : : DeregisterSource ( IInputBehaviorSource * Source )
{
ActiveInputBehaviors - > RemoveBySource ( Source ) ;
}
2021-03-11 10:50:57 -04:00
bool UInputRouter : : PostInputEvent ( const FInputDeviceState & Input )
2019-06-04 15:42:48 -04:00
{
if ( ActiveInputBehaviors - > IsEmpty ( ) )
{
2021-03-11 10:50:57 -04:00
return false ;
2019-06-04 15:42:48 -04:00
}
if ( Input . IsFromDevice ( EInputDevices : : Mouse ) )
{
PostInputEvent_Mouse ( Input ) ;
2022-12-12 13:41:02 -05:00
LastMouseInputState = Input ;
2021-03-11 10:50:57 -04:00
return HasActiveMouseCapture ( ) ;
2019-06-04 15:42:48 -04:00
}
else if ( Input . IsFromDevice ( EInputDevices : : Keyboard ) )
{
2022-12-12 13:41:02 -05:00
// if we are actively capturing Mouse and the key event is from a modifier key,
// we want to update those modifiers
if ( ( HasActiveMouseCapture ( ) | | ActiveLeftHoverCapture ! = nullptr )
& & Input . Keyboard . ActiveKey . Button . IsModifierKey ( ) )
{
if ( ( LastMouseInputState . bAltKeyDown ! = Input . bAltKeyDown ) | |
( LastMouseInputState . bShiftKeyDown ! = Input . bShiftKeyDown ) | |
( LastMouseInputState . bCtrlKeyDown ! = Input . bCtrlKeyDown ) | |
( LastMouseInputState . bCmdKeyDown ! = Input . bCmdKeyDown ) )
{
LastMouseInputState . SetModifierKeyStates ( Input . bShiftKeyDown , Input . bAltKeyDown , Input . bCtrlKeyDown , Input . bCmdKeyDown ) ;
2023-01-20 11:49:29 -05:00
// cannot call PostInputEvent_Mouse() to propagate modifier key state update because if
// there is no active capture it may result in one starting!
//PostInputEvent_Mouse(LastMouseInputState);
if ( ActiveLeftCapture ! = nullptr )
{
HandleCapturedMouseInput ( Input ) ;
}
else
{
2023-10-13 19:25:57 -04:00
bool bHoverStateUpdated = UpdateExistingHoverCaptureIfPresent ( Input ) ;
2023-01-20 11:49:29 -05:00
if ( bHoverStateUpdated & & bAutoInvalidateOnHover )
{
TransactionsAPI - > PostInvalidation ( ) ;
}
}
2022-12-12 13:41:02 -05:00
}
}
2019-06-04 15:42:48 -04:00
PostInputEvent_Keyboard ( Input ) ;
2021-03-11 10:50:57 -04:00
return ( ActiveKeyboardCapture ! = nullptr ) ;
2019-06-04 15:42:48 -04:00
}
else
{
unimplemented ( ) ;
2019-10-01 20:41:42 -04:00
TransactionsAPI - > DisplayMessage ( LOCTEXT ( " PostInputEventMessage " , " UInteractiveToolManager::PostInputEvent - input device is not currently supported. " ) , EToolMessageLevel : : Internal ) ;
2021-03-11 10:50:57 -04:00
return false ;
2019-06-04 15:42:48 -04:00
}
}
//
// Keyboard event handling
//
void UInputRouter : : PostInputEvent_Keyboard ( const FInputDeviceState & Input )
{
if ( ActiveKeyboardCapture ! = nullptr )
{
HandleCapturedKeyboardInput ( Input ) ;
}
else
{
ActiveKeyboardCaptureData = FInputCaptureData ( ) ;
CheckForKeyboardCaptures ( Input ) ;
}
}
void UInputRouter : : CheckForKeyboardCaptures ( const FInputDeviceState & Input )
{
TArray < FInputCaptureRequest > CaptureRequests ;
ActiveInputBehaviors - > CollectWantsCapture ( Input , CaptureRequests ) ;
if ( CaptureRequests . Num ( ) = = 0 )
{
return ;
}
CaptureRequests . StableSort ( ) ;
bool bAccepted = false ;
for ( int i = 0 ; i < CaptureRequests . Num ( ) & & bAccepted = = false ; + + i )
{
FInputCaptureUpdate Result =
CaptureRequests [ i ] . Source - > BeginCapture ( Input , EInputCaptureSide : : Left ) ;
if ( Result . State = = EInputCaptureState : : Begin )
{
ActiveKeyboardCapture = Result . Source ;
ActiveKeyboardCaptureOwner = CaptureRequests [ i ] . Owner ;
ActiveKeyboardCaptureData = Result . Data ;
bAccepted = true ;
}
}
}
void UInputRouter : : HandleCapturedKeyboardInput ( const FInputDeviceState & Input )
{
if ( ActiveKeyboardCapture = = nullptr )
{
return ;
}
FInputCaptureUpdate Result =
ActiveKeyboardCapture - > UpdateCapture ( Input , ActiveKeyboardCaptureData ) ;
if ( Result . State = = EInputCaptureState : : End )
{
ActiveKeyboardCapture = nullptr ;
ActiveKeyboardCaptureOwner = nullptr ;
ActiveKeyboardCaptureData = FInputCaptureData ( ) ;
}
else if ( Result . State ! = EInputCaptureState : : Continue )
{
2019-10-01 20:41:42 -04:00
TransactionsAPI - > DisplayMessage ( LOCTEXT ( " HandleCapturedKeyboardInputMessage " , " UInteractiveToolManager::HandleCapturedKeyboardInput - unexpected capture state! " ) , EToolMessageLevel : : Internal ) ;
2019-06-04 15:42:48 -04:00
}
if ( bAutoInvalidateOnCapture )
{
TransactionsAPI - > PostInvalidation ( ) ;
}
}
//
// Mouse event handling
//
void UInputRouter : : PostInputEvent_Mouse ( const FInputDeviceState & Input )
{
if ( ActiveLeftCapture ! = nullptr )
{
HandleCapturedMouseInput ( Input ) ;
}
else
{
ActiveLeftCaptureData = FInputCaptureData ( ) ;
CheckForMouseCaptures ( Input ) ;
}
// update hover if nobody is capturing
2019-10-01 20:41:42 -04:00
if ( ActiveLeftCapture = = nullptr )
2019-06-04 15:42:48 -04:00
{
2019-10-01 20:41:42 -04:00
bool bHoverStateUpdated = ProcessMouseHover ( Input ) ;
if ( bHoverStateUpdated & & bAutoInvalidateOnHover )
2019-06-04 15:42:48 -04:00
{
TransactionsAPI - > PostInvalidation ( ) ;
}
}
}
void UInputRouter : : PostHoverInputEvent ( const FInputDeviceState & Input )
{
2019-10-01 20:41:42 -04:00
bool bHoverStateUpdated = ProcessMouseHover ( Input ) ;
if ( bHoverStateUpdated & & bAutoInvalidateOnHover )
2019-06-04 15:42:48 -04:00
{
TransactionsAPI - > PostInvalidation ( ) ;
}
}
bool UInputRouter : : HasActiveMouseCapture ( ) const
{
return ( ActiveLeftCapture ! = nullptr ) ;
}
void UInputRouter : : CheckForMouseCaptures ( const FInputDeviceState & Input )
{
TArray < FInputCaptureRequest > CaptureRequests ;
ActiveInputBehaviors - > CollectWantsCapture ( Input , CaptureRequests ) ;
if ( CaptureRequests . Num ( ) = = 0 )
{
return ;
}
CaptureRequests . StableSort ( ) ;
bool bAccepted = false ;
for ( int i = 0 ; i < CaptureRequests . Num ( ) & & bAccepted = = false ; + + i )
{
FInputCaptureUpdate Result =
CaptureRequests [ i ] . Source - > BeginCapture ( Input , EInputCaptureSide : : Left ) ;
if ( Result . State = = EInputCaptureState : : Begin )
{
2019-10-01 20:41:42 -04:00
// end outstanding hover
TerminateHover ( EInputCaptureSide : : Left ) ;
2019-06-04 15:42:48 -04:00
ActiveLeftCapture = Result . Source ;
ActiveLeftCaptureOwner = CaptureRequests [ i ] . Owner ;
ActiveLeftCaptureData = Result . Data ;
bAccepted = true ;
}
}
}
void UInputRouter : : HandleCapturedMouseInput ( const FInputDeviceState & Input )
{
if ( ActiveLeftCapture = = nullptr )
{
return ;
}
// have active capture - give it this event
FInputCaptureUpdate Result =
ActiveLeftCapture - > UpdateCapture ( Input , ActiveLeftCaptureData ) ;
if ( Result . State = = EInputCaptureState : : End )
{
ActiveLeftCapture = nullptr ;
ActiveLeftCaptureOwner = nullptr ;
ActiveLeftCaptureData = FInputCaptureData ( ) ;
}
else if ( Result . State ! = EInputCaptureState : : Continue )
{
2019-10-01 20:41:42 -04:00
TransactionsAPI - > DisplayMessage ( LOCTEXT ( " HandleCapturedMouseInputMessage " , " UInteractiveToolManager::HandleCapturedMouseInput - unexpected capture state! " ) , EToolMessageLevel : : Internal ) ;
2019-06-04 15:42:48 -04:00
}
if ( bAutoInvalidateOnCapture )
{
TransactionsAPI - > PostInvalidation ( ) ;
}
}
2019-10-01 20:41:42 -04:00
void UInputRouter : : TerminateHover ( EInputCaptureSide Side )
{
if ( Side = = EInputCaptureSide : : Left & & ActiveLeftHoverCapture ! = nullptr )
{
ActiveLeftHoverCapture - > EndHoverCapture ( ) ;
ActiveLeftHoverCapture = nullptr ;
ActiveLeftCaptureOwner = nullptr ;
}
}
2023-10-13 19:25:57 -04:00
// Returns true if hover state is updated
bool UInputRouter : : UpdateExistingHoverCaptureIfPresent ( const FInputDeviceState & Input )
{
if ( ActiveLeftHoverCapture ! = nullptr )
{
FInputCaptureUpdate Result = ActiveLeftHoverCapture - > UpdateHoverCapture ( Input ) ;
if ( Result . State = = EInputCaptureState : : End )
{
TerminateHover ( EInputCaptureSide : : Left ) ;
return true ;
}
}
return false ;
}
2019-10-01 20:41:42 -04:00
bool UInputRouter : : ProcessMouseHover ( const FInputDeviceState & Input )
{
TArray < FInputCaptureRequest > CaptureRequests ;
ActiveInputBehaviors - > CollectWantsHoverCapture ( Input , CaptureRequests ) ;
if ( CaptureRequests . Num ( ) = = 0 )
{
if ( ActiveLeftHoverCapture ! = nullptr )
{
TerminateHover ( EInputCaptureSide : : Left ) ;
return true ;
}
return false ;
}
2023-10-13 19:25:57 -04:00
UInputBehavior * PreviousCapture = ActiveLeftHoverCapture ;
2019-10-01 20:41:42 -04:00
CaptureRequests . StableSort ( ) ;
// if we have an active hover, either update it, or terminate if we got a new best hit
2023-10-13 19:25:57 -04:00
if ( CaptureRequests [ 0 ] . Source = = ActiveLeftHoverCapture )
2019-10-01 20:41:42 -04:00
{
2023-10-13 19:25:57 -04:00
UpdateExistingHoverCaptureIfPresent ( Input ) ;
// We don't return early because the update may have ended the hover, so we may need a replacement.
}
else
{
TerminateHover ( EInputCaptureSide : : Left ) ; // does nothing if no capture present
2019-10-01 20:41:42 -04:00
}
2023-10-13 19:25:57 -04:00
// See if we need a new capture
if ( ActiveLeftHoverCapture = = nullptr )
2019-10-01 20:41:42 -04:00
{
2023-10-13 19:25:57 -04:00
for ( int i = 0 ; i < CaptureRequests . Num ( ) ; + + i )
2019-10-01 20:41:42 -04:00
{
2023-10-13 19:25:57 -04:00
FInputCaptureUpdate Result =
CaptureRequests [ i ] . Source - > BeginHoverCapture ( Input , EInputCaptureSide : : Left ) ;
if ( Result . State = = EInputCaptureState : : Begin )
{
ActiveLeftHoverCapture = Result . Source ;
ActiveLeftHoverCaptureOwner = CaptureRequests [ i ] . Owner ;
// We say that the hover state has been modified, despite the fact that it's theoretically possible
// to end up with the same ActiveLeftHoverCapture if behaviors do some unpleasant things like claim
// that they want capture and then refuse it on BeginHoverCapture, or terminate capture in an update
// but then accept it on BeginHoverCapture...
return true ;
}
2019-10-01 20:41:42 -04:00
}
}
2023-10-13 19:25:57 -04:00
return PreviousCapture ! = ActiveLeftHoverCapture ;
2019-10-01 20:41:42 -04:00
}
2019-06-04 15:42:48 -04:00
void UInputRouter : : ForceTerminateAll ( )
{
if ( ActiveKeyboardCapture ! = nullptr )
{
ActiveKeyboardCapture - > ForceEndCapture ( ActiveKeyboardCaptureData ) ;
ActiveKeyboardCapture = nullptr ;
ActiveKeyboardCaptureOwner = nullptr ;
ActiveKeyboardCaptureData = FInputCaptureData ( ) ;
}
if ( ActiveLeftCapture ! = nullptr )
{
ActiveLeftCapture - > ForceEndCapture ( ActiveLeftCaptureData ) ;
ActiveLeftCapture = nullptr ;
ActiveLeftCaptureOwner = nullptr ;
ActiveLeftCaptureData = FInputCaptureData ( ) ;
}
if ( ActiveRightCapture ! = nullptr )
{
ActiveRightCapture - > ForceEndCapture ( ActiveRightCaptureData ) ;
ActiveRightCapture = nullptr ;
ActiveRightCaptureOwner = nullptr ;
ActiveRightCaptureData = FInputCaptureData ( ) ;
}
2019-10-01 20:41:42 -04:00
if ( ActiveLeftHoverCapture ! = nullptr )
{
TerminateHover ( EInputCaptureSide : : Left ) ;
}
2019-06-04 15:42:48 -04:00
}
void UInputRouter : : ForceTerminateSource ( IInputBehaviorSource * Source )
{
if ( ActiveKeyboardCapture ! = nullptr & & ActiveKeyboardCaptureOwner = = Source )
{
ActiveKeyboardCapture - > ForceEndCapture ( ActiveKeyboardCaptureData ) ;
ActiveKeyboardCapture = nullptr ;
ActiveKeyboardCaptureOwner = nullptr ;
ActiveKeyboardCaptureData = FInputCaptureData ( ) ;
}
if ( ActiveLeftCapture ! = nullptr & & ActiveLeftCaptureOwner = = Source )
{
ActiveLeftCapture - > ForceEndCapture ( ActiveLeftCaptureData ) ;
ActiveLeftCapture = nullptr ;
ActiveLeftCaptureOwner = nullptr ;
ActiveLeftCaptureData = FInputCaptureData ( ) ;
}
if ( ActiveRightCapture ! = nullptr & & ActiveRightCaptureOwner = = Source )
{
ActiveRightCapture - > ForceEndCapture ( ActiveRightCaptureData ) ;
ActiveRightCapture = nullptr ;
ActiveRightCaptureOwner = nullptr ;
ActiveRightCaptureData = FInputCaptureData ( ) ;
}
2019-10-01 20:41:42 -04:00
if ( ActiveLeftHoverCapture ! = nullptr & & ActiveLeftHoverCaptureOwner = = Source )
{
TerminateHover ( EInputCaptureSide : : Left ) ;
}
2019-06-04 15:42:48 -04:00
}
2019-10-01 20:41:42 -04:00
2020-09-01 14:07:48 -04:00
# undef LOCTEXT_NAMESPACE
2022-09-24 13:57:58 -04:00