2021-04-08 14:32:07 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "CommonInputSubsystem.h"
|
2023-04-20 15:45:20 -04:00
|
|
|
#include "CommonInputPreprocessor.h"
|
2022-08-26 17:40:42 -04:00
|
|
|
#include "CommonInputPrivate.h"
|
2022-12-19 13:28:22 -05:00
|
|
|
#include "CommonInputTypeEnum.h"
|
2021-04-08 14:32:07 -04:00
|
|
|
|
2023-01-04 16:50:12 -05:00
|
|
|
#include "Engine/Engine.h"
|
|
|
|
|
#include "Engine/GameViewportClient.h"
|
|
|
|
|
#include "Engine/LocalPlayer.h"
|
2022-12-19 13:28:22 -05:00
|
|
|
#include "Engine/PlatformSettingsManager.h"
|
2023-01-04 16:50:12 -05:00
|
|
|
#include "Engine/World.h"
|
2023-02-13 20:07:50 -05:00
|
|
|
#include "EnhancedInputSubsystems.h"
|
2021-04-08 14:32:07 -04:00
|
|
|
#include "Framework/Application/IInputProcessor.h"
|
2022-10-27 13:57:18 -04:00
|
|
|
#include "Framework/Application/SlateApplication.h"
|
2021-04-08 14:32:07 -04:00
|
|
|
#include "Framework/Application/SlateUser.h"
|
2023-01-05 13:06:38 -05:00
|
|
|
#include "Misc/ConfigCacheIni.h"
|
2023-01-04 16:50:12 -05:00
|
|
|
#include "HAL/PlatformStackWalk.h"
|
2021-04-08 14:32:07 -04:00
|
|
|
#include "Widgets/SViewport.h"
|
|
|
|
|
#include "CommonInputSettings.h"
|
|
|
|
|
#include "ICommonInputModule.h"
|
|
|
|
|
|
2022-09-28 01:06:15 -04:00
|
|
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(CommonInputSubsystem)
|
|
|
|
|
|
2023-01-04 16:50:12 -05:00
|
|
|
#if !UE_BUILD_SHIPPING
|
|
|
|
|
static int32 bDumpInputTypeChangeCallstack = 0;
|
|
|
|
|
static FAutoConsoleVariableRef CVarDumpInputTypeChangeCallstack(
|
|
|
|
|
TEXT("CommonUI.bDumpInputTypeChangeCallstack"),
|
|
|
|
|
bDumpInputTypeChangeCallstack,
|
|
|
|
|
TEXT("Dump callstack when input type changes."));
|
|
|
|
|
#endif // !UE_BUILD_SHIPPING
|
|
|
|
|
|
|
|
|
|
|
2021-06-23 17:51:32 -04:00
|
|
|
FPlatformInputSupportOverrideDelegate UCommonInputSubsystem::OnPlatformInputSupportOverride;
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// UCommonInputSubsystem
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static int32 GCommonInputKeysVisible = 1;
|
|
|
|
|
static FAutoConsoleVariableRef CVarInputKeysVisible
|
|
|
|
|
(
|
|
|
|
|
TEXT("CommonInput.ShowKeys"),
|
|
|
|
|
GCommonInputKeysVisible,
|
|
|
|
|
TEXT("Should we show the keys for the current input device."),
|
|
|
|
|
ECVF_Default
|
|
|
|
|
);
|
|
|
|
|
|
2022-11-29 14:45:37 -05:00
|
|
|
bool bEnableGamepadPlatformCursor = false;
|
|
|
|
|
static const FAutoConsoleVariableRef CVarInputEnableGamepadPlatformCursor
|
|
|
|
|
(
|
|
|
|
|
TEXT("CommonInput.EnableGamepadPlatformCursor"),
|
|
|
|
|
bEnableGamepadPlatformCursor,
|
|
|
|
|
TEXT("Should the cursor be allowed to be used during gamepad input")
|
|
|
|
|
);
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
UCommonInputSubsystem* UCommonInputSubsystem::Get(const ULocalPlayer* LocalPlayer)
|
|
|
|
|
{
|
|
|
|
|
return LocalPlayer ? LocalPlayer->GetSubsystem<UCommonInputSubsystem>() : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UCommonInputSubsystem::UCommonInputSubsystem()
|
|
|
|
|
{
|
2023-04-20 19:03:27 -04:00
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
|
|
|
|
{
|
|
|
|
|
Super::Initialize(Collection);
|
|
|
|
|
|
2023-08-22 13:08:38 -04:00
|
|
|
// There is a dependency on the Enhanced Input subsystem below so we need to make sure it is available
|
|
|
|
|
// in a packaged game
|
|
|
|
|
Collection.InitializeDependency<UEnhancedInputLocalPlayerSubsystem>();
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
FCommonInputBase::GetInputSettings()->LoadData();
|
2022-02-24 14:23:31 -05:00
|
|
|
|
|
|
|
|
const UCommonInputPlatformSettings* Settings = UPlatformSettingsManager::Get().GetSettingsForPlatform<UCommonInputPlatformSettings>();
|
|
|
|
|
|
|
|
|
|
GamepadInputType = Settings->GetDefaultGamepadName();
|
|
|
|
|
CurrentInputType = LastInputType = Settings->GetDefaultInputType();
|
2021-04-08 14:32:07 -04:00
|
|
|
|
2023-04-20 15:45:20 -04:00
|
|
|
CommonInputPreprocessor = MakeInputProcessor();
|
2024-08-30 15:10:27 -04:00
|
|
|
if (FSlateApplication::IsInitialized())
|
|
|
|
|
{
|
|
|
|
|
FSlateApplication::Get().RegisterInputPreProcessor(CommonInputPreprocessor, EInputPreProcessorType::PreGame);
|
|
|
|
|
}
|
2021-04-08 14:32:07 -04:00
|
|
|
|
2021-08-16 11:05:18 -04:00
|
|
|
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UCommonInputSubsystem::Tick), 0.1f);
|
2021-04-08 14:32:07 -04:00
|
|
|
|
|
|
|
|
CVarInputKeysVisible->SetOnChangedCallback(FConsoleVariableDelegate::CreateUObject(this, &UCommonInputSubsystem::ShouldShowInputKeysChanged));
|
2022-01-31 23:46:45 -05:00
|
|
|
|
2023-02-13 20:07:50 -05:00
|
|
|
if (ICommonInputModule::Get().GetSettings().GetEnableEnhancedInputSupport())
|
|
|
|
|
{
|
|
|
|
|
if (ULocalPlayer* LocalPlayer = GetLocalPlayerChecked())
|
|
|
|
|
{
|
|
|
|
|
if (UEnhancedInputLocalPlayerSubsystem* EnhancedInputLocalPlayerSubsystem = LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
|
|
|
|
|
{
|
|
|
|
|
BroadcastInputMethodChangedEvent.BindUFunction(this, GET_FUNCTION_NAME_CHECKED(UCommonInputSubsystem, BroadcastInputMethodChanged));
|
|
|
|
|
EnhancedInputLocalPlayerSubsystem->ControlMappingsRebuiltDelegate.AddUnique(BroadcastInputMethodChangedEvent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 23:46:45 -05:00
|
|
|
SetActionDomainTable(FCommonInputBase::GetInputSettings()->GetActionDomainTable());
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::Deinitialize()
|
|
|
|
|
{
|
|
|
|
|
Super::Deinitialize();
|
2022-01-21 14:13:42 -05:00
|
|
|
if (FSlateApplication::IsInitialized())
|
|
|
|
|
{
|
|
|
|
|
FSlateApplication::Get().UnregisterInputPreProcessor(CommonInputPreprocessor);
|
|
|
|
|
}
|
2021-04-08 14:32:07 -04:00
|
|
|
CommonInputPreprocessor.Reset();
|
|
|
|
|
|
2023-02-13 20:07:50 -05:00
|
|
|
if (ICommonInputModule::Get().GetSettings().GetEnableEnhancedInputSupport())
|
|
|
|
|
{
|
|
|
|
|
if (ULocalPlayer* LocalPlayer = GetLocalPlayerChecked())
|
|
|
|
|
{
|
|
|
|
|
if (UEnhancedInputLocalPlayerSubsystem* EnhancedInputLocalPlayerSubsystem = LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
|
|
|
|
|
{
|
|
|
|
|
EnhancedInputLocalPlayerSubsystem->ControlMappingsRebuiltDelegate.Remove(BroadcastInputMethodChangedEvent);
|
|
|
|
|
BroadcastInputMethodChangedEvent.Unbind();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 11:05:18 -04:00
|
|
|
FTSTicker::GetCoreTicker().RemoveTicker(TickHandle);
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
|
2021-08-04 17:46:20 -04:00
|
|
|
FGamepadChangeDetectedEvent& UCommonInputSubsystem::GetOnGamepadChangeDetected()
|
|
|
|
|
{
|
|
|
|
|
return CommonInputPreprocessor->OnGamepadChangeDetected;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
void UCommonInputSubsystem::SetInputTypeFilter(ECommonInputType InputType, FName Reason, bool Filter)
|
|
|
|
|
{
|
|
|
|
|
CommonInputPreprocessor->SetInputTypeFilter(InputType, Reason, Filter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::GetInputTypeFilter(ECommonInputType InputType) const
|
|
|
|
|
{
|
|
|
|
|
return CommonInputPreprocessor->IsInputMethodBlocked(InputType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::AddOrRemoveInputTypeLock(FName InReason, ECommonInputType InInputType, bool bAddLock)
|
|
|
|
|
{
|
2024-10-01 18:02:11 -04:00
|
|
|
// Make sure the input is supported before locking it, otherwise remove it if it exists
|
|
|
|
|
if (bAddLock && PlatformSupportsInputType(InInputType))
|
2021-04-08 14:32:07 -04:00
|
|
|
{
|
|
|
|
|
ECommonInputType& CurrentValue = CurrentInputLocks.FindOrAdd(InReason);
|
|
|
|
|
CurrentValue = InInputType;
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("Adding Input Method Lock: %s - %d"), *InReason.ToString(), (int32)InInputType);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CurrentInputLocks.Remove(InReason);
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("Removing Input Method Lock: %s - %d"), *InReason.ToString(), (int32)InInputType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 ComputedInputLock = INDEX_NONE;
|
|
|
|
|
for (auto Entry : CurrentInputLocks)
|
|
|
|
|
{
|
|
|
|
|
// Take the most restrictive lock, e.g. Gamepad lock is more restrictive than a Keyboard/Mouse lock.
|
|
|
|
|
if (((int32)Entry.Value) > ComputedInputLock)
|
|
|
|
|
{
|
|
|
|
|
ComputedInputLock = (int32)Entry.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ComputedInputLock == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
CurrentInputLock.Reset();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CurrentInputLock = (ECommonInputType)ComputedInputLock;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-01 19:04:15 -04:00
|
|
|
const ECommonInputType PreviousInput = CurrentInputType;
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
// If a lock was put in place, lock the current input type.
|
|
|
|
|
CurrentInputType = LockInput(LastInputType);
|
|
|
|
|
|
2024-10-01 19:04:15 -04:00
|
|
|
if (CurrentInputType != PreviousInput)
|
2021-04-08 14:32:07 -04:00
|
|
|
{
|
|
|
|
|
BroadcastInputMethodChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::IsInputMethodActive(ECommonInputType InputMethod) const
|
|
|
|
|
{
|
|
|
|
|
return GetCurrentInputType() == InputMethod;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-20 15:45:20 -04:00
|
|
|
TSharedPtr<FCommonInputPreprocessor> UCommonInputSubsystem::MakeInputProcessor()
|
|
|
|
|
{
|
|
|
|
|
return MakeShared<FCommonInputPreprocessor>(*this);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
ECommonInputType UCommonInputSubsystem::LockInput(ECommonInputType InputToLock) const
|
|
|
|
|
{
|
|
|
|
|
return CurrentInputLock.Get(InputToLock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ECommonInputType UCommonInputSubsystem::GetCurrentInputType() const
|
|
|
|
|
{
|
|
|
|
|
return CurrentInputType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ECommonInputType UCommonInputSubsystem::GetDefaultInputType() const
|
|
|
|
|
{
|
CommonInput - Using the new UPlatformSettings, to store per-platform information into an NDA location when each platform is configured. These changes make it so we use the 'real' platform ini name, e.g. There's no more "PC" platform as far as the common input exists for configuring the platforms. So if you setup linux, that's another platform you'd configure. The gamepads are still wonky, they're trying to use platform ini names for gamepad names, going to refactor that so it's not coming from platform names. Made an upgrade path for the old settings that will update and then clear the old configuration. Also removed some settings that were added to DataDrivenPlatformInfo that don't make sense, and updated some platforms that never got the settings to begin with.
#review-16605256 Josh.Adams, Michael.Noland, Daren.Cheng
#fyi Josh.Adams, Michael.Noland, Daren.Cheng
[CL 16605253 by Nick Darnell in ue5-main branch]
2021-06-09 10:44:46 -04:00
|
|
|
return UCommonInputPlatformSettings::Get()->GetDefaultInputType();
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::BroadcastInputMethodChanged()
|
|
|
|
|
{
|
|
|
|
|
if (UWorld* World = GetWorld())
|
|
|
|
|
{
|
|
|
|
|
if (!World->bIsTearingDown)
|
|
|
|
|
{
|
|
|
|
|
OnInputMethodChangedNative.Broadcast(CurrentInputType);
|
|
|
|
|
OnInputMethodChanged.Broadcast(CurrentInputType);
|
|
|
|
|
LastInputMethodChangeTime = FPlatformTime::Seconds();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::CheckForInputMethodThrashing(ECommonInputType NewInputType)
|
|
|
|
|
{
|
|
|
|
|
UCommonInputSettings& InputSettings = ICommonInputModule::GetSettings();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (InputSettings.GetEnableInputMethodThrashingProtection())
|
|
|
|
|
{
|
|
|
|
|
const double Now = FPlatformTime::Seconds();
|
|
|
|
|
|
|
|
|
|
if (LastTimeInputMethodThrashingBegan + InputSettings.GetInputMethodThrashingCooldownInSeconds() > Now)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (CurrentInputLocks.Contains(TEXT("InputMethodThrashing")))
|
|
|
|
|
{
|
|
|
|
|
//Remove the thrashing lock.
|
|
|
|
|
AddOrRemoveInputTypeLock(TEXT("InputMethodThrashing"), ECommonInputType::MouseAndKeyboard, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (NewInputType)
|
|
|
|
|
{
|
|
|
|
|
case ECommonInputType::Gamepad:
|
|
|
|
|
case ECommonInputType::MouseAndKeyboard:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// Ignore any thrashing that's not exclusively between mouse and gamepad.
|
|
|
|
|
NumberOfInputMethodChangesRecently = 0;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const double ChangeDelta = (Now - LastInputMethodChangeTime);
|
|
|
|
|
if (ChangeDelta < InputSettings.GetInputMethodThrashingWindowInSeconds())
|
|
|
|
|
{
|
|
|
|
|
NumberOfInputMethodChangesRecently++;
|
|
|
|
|
if (NumberOfInputMethodChangesRecently > InputSettings.GetInputMethodThrashingLimit())
|
|
|
|
|
{
|
|
|
|
|
LastTimeInputMethodThrashingBegan = Now;
|
|
|
|
|
//Add the thrashing lock
|
|
|
|
|
AddOrRemoveInputTypeLock(TEXT("InputMethodThrashing"), ECommonInputType::MouseAndKeyboard, true);
|
|
|
|
|
NumberOfInputMethodChangesRecently = 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NumberOfInputMethodChangesRecently = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::SetCurrentInputType(ECommonInputType NewInputType)
|
|
|
|
|
{
|
2021-06-18 00:38:36 -04:00
|
|
|
if ((LastInputType != NewInputType) && PlatformSupportsInputType(NewInputType))
|
2021-04-08 14:32:07 -04:00
|
|
|
{
|
|
|
|
|
CheckForInputMethodThrashing(NewInputType);
|
|
|
|
|
|
|
|
|
|
//If we have any locks we can't change the input mode.
|
|
|
|
|
if (!CurrentInputLocks.Num())
|
|
|
|
|
{
|
|
|
|
|
LastInputType = NewInputType;
|
|
|
|
|
|
|
|
|
|
ECommonInputType LockedInput = LockInput(NewInputType);
|
|
|
|
|
|
|
|
|
|
if (LockedInput != CurrentInputType)
|
|
|
|
|
{
|
2023-01-04 16:50:12 -05:00
|
|
|
#if !UE_BUILD_SHIPPING
|
|
|
|
|
if (bDumpInputTypeChangeCallstack)
|
|
|
|
|
{
|
|
|
|
|
const uint32 DumpCallstackSize = 65535;
|
|
|
|
|
ANSICHAR DumpCallstack[DumpCallstackSize] = { 0 };
|
|
|
|
|
FString ScriptStack = FFrame::GetScriptCallstack(true /* bReturnEmpty */);
|
|
|
|
|
FPlatformStackWalk::StackWalkAndDump(DumpCallstack, DumpCallstackSize, 0);
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("--- Input Changing Callstack ---"));
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("Script Stack:\n%s"), *ScriptStack);
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("Callstack:\n%s"), ANSI_TO_TCHAR(DumpCallstack));
|
|
|
|
|
}
|
|
|
|
|
#endif // !UE_BUILD_SHIPPING
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
CurrentInputType = LockedInput;
|
|
|
|
|
|
|
|
|
|
FSlateApplication& SlateApplication = FSlateApplication::Get();
|
|
|
|
|
ULocalPlayer* LocalPlayer = GetLocalPlayerChecked();
|
|
|
|
|
bool bCursorUser = LocalPlayer && LocalPlayer->GetSlateUser() == SlateApplication.GetCursorUser();
|
|
|
|
|
|
|
|
|
|
switch (CurrentInputType)
|
|
|
|
|
{
|
|
|
|
|
case ECommonInputType::Gamepad:
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("UCommonInputSubsystem::SetCurrentInputType(): Using Gamepad"));
|
|
|
|
|
if (bCursorUser)
|
|
|
|
|
{
|
2022-11-29 14:45:37 -05:00
|
|
|
SlateApplication.UsePlatformCursorForCursorUser(bEnableGamepadPlatformCursor);
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
2024-09-19 18:04:33 -04:00
|
|
|
SlateApplication.SetGameAllowsFakingTouchEvents(false);
|
2021-04-08 14:32:07 -04:00
|
|
|
break;
|
|
|
|
|
case ECommonInputType::Touch:
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("UCommonInputSubsystem::SetCurrentInputType(): Using Touch"));
|
2024-09-19 18:04:33 -04:00
|
|
|
SlateApplication.SetGameAllowsFakingTouchEvents(true);
|
|
|
|
|
SlateApplication.SetGameIsFakingTouchEvents(LocalPlayer && LocalPlayer->ViewportClient && LocalPlayer->ViewportClient->GetUseMouseForTouch());
|
2021-04-08 14:32:07 -04:00
|
|
|
break;
|
|
|
|
|
case ECommonInputType::MouseAndKeyboard:
|
|
|
|
|
default:
|
|
|
|
|
UE_LOG(LogCommonInput, Log, TEXT("UCommonInputSubsystem::SetCurrentInputType(): Using Mouse"));
|
|
|
|
|
if (bCursorUser)
|
|
|
|
|
{
|
|
|
|
|
SlateApplication.UsePlatformCursorForCursorUser(true);
|
|
|
|
|
}
|
2024-09-19 18:04:33 -04:00
|
|
|
SlateApplication.SetGameAllowsFakingTouchEvents(false);
|
2021-04-08 14:32:07 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BroadcastInputMethodChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FName UCommonInputSubsystem::GetCurrentGamepadName() const
|
|
|
|
|
{
|
|
|
|
|
return GamepadInputType;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-17 03:41:59 -05:00
|
|
|
void UCommonInputSubsystem::SetGamepadInputType(const FName InGamepadInputType)
|
2021-04-08 14:32:07 -04:00
|
|
|
{
|
2021-06-18 00:38:36 -04:00
|
|
|
if (ensure(UCommonInputPlatformSettings::Get()->CanChangeGamepadType()))
|
2021-04-08 14:32:07 -04:00
|
|
|
{
|
2021-06-18 00:38:36 -04:00
|
|
|
GamepadInputType = InGamepadInputType;
|
|
|
|
|
|
|
|
|
|
// Send out notifications so we update our buttons
|
|
|
|
|
//BroadcastLastInputDeviceChanged();
|
|
|
|
|
BroadcastInputMethodChanged();
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::IsUsingPointerInput() const
|
|
|
|
|
{
|
|
|
|
|
bool bUsingPointerInput = false;
|
|
|
|
|
|
|
|
|
|
switch (LastInputType)
|
|
|
|
|
{
|
|
|
|
|
case ECommonInputType::MouseAndKeyboard:
|
|
|
|
|
case ECommonInputType::Touch:
|
|
|
|
|
{
|
|
|
|
|
bUsingPointerInput = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ECommonInputType::Gamepad:
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
bUsingPointerInput = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bUsingPointerInput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::ShouldShowInputKeys() const
|
|
|
|
|
{
|
|
|
|
|
return GCommonInputKeysVisible != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::Tick(float DeltaTime)
|
|
|
|
|
{
|
|
|
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_UCommonInputSubsystem_Tick);
|
|
|
|
|
|
|
|
|
|
return true; //repeat ticking
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::ShouldShowInputKeysChanged(IConsoleVariable* Var)
|
|
|
|
|
{
|
|
|
|
|
//BroadcastLastInputDeviceChanged();
|
|
|
|
|
BroadcastInputMethodChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::PlatformSupportsHardwareCursor() const
|
|
|
|
|
{
|
|
|
|
|
#if PLATFORM_DESKTOP
|
|
|
|
|
return true;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::SetCursorPosition(FVector2D NewPosition, bool bForce)
|
|
|
|
|
{
|
2023-05-16 16:40:52 -04:00
|
|
|
if (CommonInputPreprocessor)
|
|
|
|
|
{
|
|
|
|
|
CommonInputPreprocessor->bIgnoreNextMove = true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
ULocalPlayer* LocalPlayer = GetLocalPlayerChecked();
|
|
|
|
|
if (TSharedPtr<FSlateUser> SlateUser = LocalPlayer ? LocalPlayer->GetSlateUser() : nullptr)
|
|
|
|
|
{
|
|
|
|
|
UpdateCursorPosition(SlateUser.ToSharedRef(), NewPosition, bForce);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::UpdateCursorPosition(TSharedRef<FSlateUser> SlateUser, const FVector2D& NewPosition, bool bForce)
|
|
|
|
|
{
|
|
|
|
|
const FVector2D ClampedNewPosition = ClampPositionToViewport(NewPosition);
|
|
|
|
|
|
|
|
|
|
//grab the old position
|
|
|
|
|
const FVector2D OldPosition = SlateUser->GetCursorPosition();
|
|
|
|
|
|
|
|
|
|
//make sure we are actually moving
|
|
|
|
|
int32 NewIntPosX = ClampedNewPosition.X;
|
|
|
|
|
int32 NewIntPosY = ClampedNewPosition.Y;
|
|
|
|
|
int32 OldIntPosX = OldPosition.X;
|
|
|
|
|
int32 OldIntPosY = OldPosition.Y;
|
|
|
|
|
if (bForce || OldIntPosX != NewIntPosX || OldIntPosY != NewIntPosY)
|
|
|
|
|
{
|
|
|
|
|
//put the cursor in the correct spot
|
|
|
|
|
SlateUser->SetCursorPosition(NewIntPosX, NewIntPosY);
|
|
|
|
|
|
|
|
|
|
// Since the cursor may have been locked and its location clamped, get the actual new position
|
|
|
|
|
const FVector2D UpdatedPosition = SlateUser->GetCursorPosition();
|
|
|
|
|
|
|
|
|
|
FSlateApplication& SlateApp = FSlateApplication::Get();
|
|
|
|
|
|
|
|
|
|
//create a new mouse event
|
|
|
|
|
FPointerEvent MouseEvent(
|
|
|
|
|
FSlateApplicationBase::CursorPointerIndex,
|
|
|
|
|
UpdatedPosition,
|
|
|
|
|
OldPosition,
|
|
|
|
|
SlateApp.GetPressedMouseButtons(),
|
|
|
|
|
EKeys::Invalid,
|
|
|
|
|
0,
|
|
|
|
|
SlateApp.GetPlatformApplication()->GetModifierKeys()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//process the event
|
|
|
|
|
SlateApp.ProcessMouseMoveEvent(MouseEvent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::GetIsGamepadSimulatedClick() const
|
|
|
|
|
{
|
|
|
|
|
return bIsGamepadSimulatedClick;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UCommonInputSubsystem::SetIsGamepadSimulatedClick(bool bNewIsGamepadSimulatedClick)
|
|
|
|
|
{
|
|
|
|
|
if (bIsGamepadSimulatedClick != bNewIsGamepadSimulatedClick)
|
|
|
|
|
{
|
|
|
|
|
bIsGamepadSimulatedClick = bNewIsGamepadSimulatedClick;
|
|
|
|
|
UE_CLOG(bIsGamepadSimulatedClick, LogCommonInput, VeryVerbose, TEXT("UCommonInputSubsystem::SetIsGamepadSimulatedClick(): Click is being simulated"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVector2D UCommonInputSubsystem::ClampPositionToViewport(const FVector2D& InPosition) const
|
|
|
|
|
{
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (!World || !World->IsGameWorld())
|
|
|
|
|
{
|
|
|
|
|
return InPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UGameViewportClient* GameViewport = World->GetGameViewport();
|
|
|
|
|
if (!GameViewport || !GameViewport->Viewport || !GameViewport->GetWindow().IsValid())
|
|
|
|
|
{
|
|
|
|
|
return InPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedPtr<SViewport> GameViewportWidget = GameViewport->GetGameViewportWidget();
|
|
|
|
|
if (GameViewportWidget.IsValid())
|
|
|
|
|
{
|
|
|
|
|
const FGeometry& ViewportGeometry = GameViewportWidget->GetCachedGeometry();
|
|
|
|
|
FVector2D LocalPosition = ViewportGeometry.AbsoluteToLocal(InPosition);
|
|
|
|
|
LocalPosition.X = FMath::Clamp(LocalPosition.X, 1.0f, ViewportGeometry.GetLocalSize().X - 1.0f);
|
|
|
|
|
LocalPosition.Y = FMath::Clamp(LocalPosition.Y, 1.0f, ViewportGeometry.GetLocalSize().Y - 1.0f);
|
|
|
|
|
|
|
|
|
|
return ViewportGeometry.LocalToAbsolute(LocalPosition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return InPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::PlatformSupportsInputType(ECommonInputType InInputType) const
|
|
|
|
|
{
|
CommonInput - Using the new UPlatformSettings, to store per-platform information into an NDA location when each platform is configured. These changes make it so we use the 'real' platform ini name, e.g. There's no more "PC" platform as far as the common input exists for configuring the platforms. So if you setup linux, that's another platform you'd configure. The gamepads are still wonky, they're trying to use platform ini names for gamepad names, going to refactor that so it's not coming from platform names. Made an upgrade path for the old settings that will update and then clear the old configuration. Also removed some settings that were added to DataDrivenPlatformInfo that don't make sense, and updated some platforms that never got the settings to begin with.
#review-16605256 Josh.Adams, Michael.Noland, Daren.Cheng
#fyi Josh.Adams, Michael.Noland, Daren.Cheng
[CL 16605253 by Nick Darnell in ue5-main branch]
2021-06-09 10:44:46 -04:00
|
|
|
bool bPlatformSupportsInput = UCommonInputPlatformSettings::Get()->SupportsInputType(InInputType);
|
2021-04-08 14:32:07 -04:00
|
|
|
switch (InInputType)
|
|
|
|
|
{
|
2021-06-23 17:51:32 -04:00
|
|
|
case ECommonInputType::MouseAndKeyboard:
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
2022-06-03 10:35:31 -04:00
|
|
|
#if UE_COMMONINPUT_PLATFORM_KBM_REQUIRES_ATTACHED_MOUSE
|
2021-06-23 17:51:32 -04:00
|
|
|
bPlatformSupportsInput &= FSlateApplication::Get().IsMouseAttached();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ECommonInputType::Touch:
|
|
|
|
|
{
|
2023-12-20 12:40:45 -05:00
|
|
|
bPlatformSupportsInput &= !UE_COMMONINPUT_FORCE_TOUCH_SUPPORT_DISABLED;
|
2024-09-16 14:04:09 -04:00
|
|
|
#if !UE_BUILD_SHIPPING
|
2023-12-20 12:40:45 -05:00
|
|
|
// Support touch testing (testing with UseMouseForTouch setting enabled or with URemote in the editor) until touch is supported on desktop
|
|
|
|
|
bPlatformSupportsInput = true;
|
2022-07-20 12:56:39 -04:00
|
|
|
#endif
|
2021-06-23 17:51:32 -04:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ECommonInputType::Gamepad:
|
|
|
|
|
#if PLATFORM_IOS
|
|
|
|
|
{
|
|
|
|
|
bool bAllowControllers = false;
|
|
|
|
|
GConfig->GetBool(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("bAllowControllers"), bAllowControllers, GEngineIni);
|
|
|
|
|
bPlatformSupportsInput &= bAllowControllers;
|
|
|
|
|
}
|
|
|
|
|
#elif PLATFORM_ANDROID
|
|
|
|
|
{
|
|
|
|
|
bool bAllowControllers = false;
|
|
|
|
|
GConfig->GetBool(TEXT("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings"), TEXT("bAllowControllers"), bAllowControllers, GEngineIni);
|
|
|
|
|
bPlatformSupportsInput &= bAllowControllers;
|
2021-04-29 19:32:06 -04:00
|
|
|
}
|
2021-04-08 14:32:07 -04:00
|
|
|
#endif
|
2021-06-23 17:51:32 -04:00
|
|
|
break;
|
2021-04-08 14:32:07 -04:00
|
|
|
}
|
|
|
|
|
|
2021-06-23 17:51:32 -04:00
|
|
|
GetOnPlatformInputSupportOverride().Broadcast(GetLocalPlayer(), InInputType, bPlatformSupportsInput);
|
|
|
|
|
|
2021-04-08 14:32:07 -04:00
|
|
|
return bPlatformSupportsInput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UCommonInputSubsystem::IsMobileGamepadKey(const FKey& InKey)
|
|
|
|
|
{
|
|
|
|
|
// Mobile keys that can be physically present on the device
|
|
|
|
|
static TArray<FKey> PhysicalMobileKeys = {
|
|
|
|
|
EKeys::Android_Back,
|
|
|
|
|
EKeys::Android_Menu,
|
|
|
|
|
EKeys::Android_Volume_Down,
|
|
|
|
|
EKeys::Android_Volume_Up
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return PhysicalMobileKeys.Contains(InKey);
|
|
|
|
|
}
|
2022-09-28 01:06:15 -04:00
|
|
|
|