Add new input device processor
This commit is contained in:
105
Source/Integration/InputDeviceTracker.cpp
Normal file
105
Source/Integration/InputDeviceTracker.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
#include "InputDeviceTracker.h"
|
||||||
|
#include "Framework/Application/SlateApplication.h"
|
||||||
|
#include "GenericPlatform/GenericApplicationMessageHandler.h"
|
||||||
|
#include "InputCoreTypes.h"
|
||||||
|
|
||||||
|
// Last observed device classification. Read with no
|
||||||
|
// synchronization; updates happen on the game thread
|
||||||
|
// from Slate's input pipeline, and stale reads on
|
||||||
|
// other threads are acceptable for this use case.
|
||||||
|
//
|
||||||
|
static ElxControllerType GLastControllerType = ElxControllerType::KeyboardMouse;
|
||||||
|
|
||||||
|
// Keywords identifying a PlayStation-family gamepad.
|
||||||
|
// Matched case-insensitively against the InputDeviceName
|
||||||
|
// and HardwareDeviceIdentifier fields of the current
|
||||||
|
// FInputDeviceScope.
|
||||||
|
//
|
||||||
|
static const TCHAR* const PlaystationKeywords[] = {
|
||||||
|
TEXT("Playstation"),
|
||||||
|
TEXT("PS3"),
|
||||||
|
TEXT("PS4"),
|
||||||
|
TEXT("PS5"),
|
||||||
|
TEXT("PS6"),
|
||||||
|
TEXT("PS7"),
|
||||||
|
TEXT("Dualsense"),
|
||||||
|
TEXT("Dualshock"),
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool ContainsAnyPlaystationKeyword(const FString& Haystack)
|
||||||
|
{
|
||||||
|
for (const TCHAR* Keyword : PlaystationKeywords)
|
||||||
|
{
|
||||||
|
if (Haystack.Contains(Keyword, ESearchCase::IgnoreCase))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classifies the active gamepad by scanning the current
|
||||||
|
// FInputDeviceScope. Defaults to Xbox; switches to
|
||||||
|
// PlayStation only on a keyword match.
|
||||||
|
//
|
||||||
|
ElxControllerType ClassifyGamepadFromScope()
|
||||||
|
{
|
||||||
|
const FInputDeviceScope* Scope = FInputDeviceScope::GetCurrent();
|
||||||
|
if (Scope != nullptr)
|
||||||
|
{
|
||||||
|
if (ContainsAnyPlaystationKeyword(Scope->InputDeviceName.ToString()) ||
|
||||||
|
ContainsAnyPlaystationKeyword(Scope->HardwareDeviceIdentifier))
|
||||||
|
{
|
||||||
|
return ElxControllerType::PlayStationGamepad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ElxControllerType::XboxGamepad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FInputDeviceTrackerProcessor::HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& KeyEvent)
|
||||||
|
{
|
||||||
|
if (KeyEvent.GetKey().IsGamepadKey())
|
||||||
|
{
|
||||||
|
GLastControllerType = ClassifyGamepadFromScope();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLastControllerType = ElxControllerType::KeyboardMouse;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FInputDeviceTrackerProcessor::HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent)
|
||||||
|
{
|
||||||
|
GLastControllerType = ElxControllerType::KeyboardMouse;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxInputDeviceTracker::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
|
{
|
||||||
|
Super::Initialize(Collection);
|
||||||
|
if (FSlateApplication::IsInitialized())
|
||||||
|
{
|
||||||
|
Processor = MakeShared<FInputDeviceTrackerProcessor>();
|
||||||
|
FSlateApplication::Get().RegisterInputPreProcessor(Processor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxInputDeviceTracker::Deinitialize()
|
||||||
|
{
|
||||||
|
if (Processor.IsValid() && FSlateApplication::IsInitialized())
|
||||||
|
{
|
||||||
|
FSlateApplication::Get().UnregisterInputPreProcessor(Processor);
|
||||||
|
}
|
||||||
|
Processor.Reset();
|
||||||
|
Super::Deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ElxControllerType UlxInputDeviceTracker::GetLastControllerType()
|
||||||
|
{
|
||||||
|
return GLastControllerType;
|
||||||
|
}
|
||||||
63
Source/Integration/InputDeviceTracker.h
Normal file
63
Source/Integration/InputDeviceTracker.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// InputDeviceTracker.h
|
||||||
|
//
|
||||||
|
// Tracks the most recently used input device, classifying
|
||||||
|
// it as keyboard/mouse, Xbox gamepad, or PlayStation
|
||||||
|
// gamepad. The subsystem registers a Slate input
|
||||||
|
// preprocessor that watches button-down events; analog
|
||||||
|
// and mouse-move events are ignored. Read the current
|
||||||
|
// classification via the static accessor.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Subsystems/GameInstanceSubsystem.h"
|
||||||
|
#include "Framework/Application/IInputProcessor.h"
|
||||||
|
#include "Common.h"
|
||||||
|
#include "InputDeviceTracker.generated.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// FInputDeviceTrackerProcessor
|
||||||
|
//
|
||||||
|
// Slate input preprocessor. Updates the device-class
|
||||||
|
// static on each button-down event. Never consumes
|
||||||
|
// events (always returns false).
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FInputDeviceTrackerProcessor : public IInputProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> Cursor) override {}
|
||||||
|
virtual bool HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& KeyEvent) override;
|
||||||
|
virtual bool HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// UlxInputDeviceTracker
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UCLASS(MinimalAPI)
|
||||||
|
class UlxInputDeviceTracker : public UGameInstanceSubsystem
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||||
|
virtual void Deinitialize() override;
|
||||||
|
|
||||||
|
// Returns the classification of the most recently used
|
||||||
|
// input device. Defaults to KeyboardMouse until the
|
||||||
|
// first gamepad button event is observed.
|
||||||
|
//
|
||||||
|
static ElxControllerType GetLastControllerType();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TSharedPtr<FInputDeviceTrackerProcessor> Processor;
|
||||||
|
};
|
||||||
@@ -31,6 +31,7 @@ public class Integration : ModuleRules
|
|||||||
"UMG",
|
"UMG",
|
||||||
"UMGEditor",
|
"UMGEditor",
|
||||||
"EditorSubsystem",
|
"EditorSubsystem",
|
||||||
|
"ApplicationCore",
|
||||||
});
|
});
|
||||||
|
|
||||||
PrivateDependencyModuleNames.Add("Slate");
|
PrivateDependencyModuleNames.Add("Slate");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "PromptWidget.h"
|
#include "PromptWidget.h"
|
||||||
|
#include "InputDeviceTracker.h"
|
||||||
#include "UtilityLibrary.h"
|
#include "UtilityLibrary.h"
|
||||||
#include "PlayerControllerBase.h"
|
#include "PlayerControllerBase.h"
|
||||||
#include "InputAction.h"
|
#include "InputAction.h"
|
||||||
@@ -194,7 +195,7 @@ void UlxPromptWidget::SetKeysFromBindings(const UInputMappingContext* InputMappi
|
|||||||
|
|
||||||
bool UlxPromptWidget::OnTick(float DeltaTime)
|
bool UlxPromptWidget::OnTick(float DeltaTime)
|
||||||
{
|
{
|
||||||
ElxControllerType Type = UlxUtilityLibrary::DetectControllerType(GetOwningLocalPlayer());
|
ElxControllerType Type = UlxInputDeviceTracker::GetLastControllerType();
|
||||||
if (ControllerType != Type)
|
if (ControllerType != Type)
|
||||||
{
|
{
|
||||||
ControllerType = Type;
|
ControllerType = Type;
|
||||||
@@ -207,7 +208,7 @@ TSharedRef<SWidget> UlxPromptWidget::RebuildWidget()
|
|||||||
{
|
{
|
||||||
if (!IsDesignTime())
|
if (!IsDesignTime())
|
||||||
{
|
{
|
||||||
ControllerType = UlxUtilityLibrary::DetectControllerType(GetOwningLocalPlayer());
|
ControllerType = UlxInputDeviceTracker::GetLastControllerType();
|
||||||
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UlxPromptWidget::OnTick));
|
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UlxPromptWidget::OnTick));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include "EnhancedInputComponent.h"
|
#include "EnhancedInputComponent.h"
|
||||||
#include "Animation/AnimSequenceBase.h"
|
#include "Animation/AnimSequenceBase.h"
|
||||||
#include "GameFramework/Pawn.h"
|
#include "GameFramework/Pawn.h"
|
||||||
#include "GameFramework/InputDeviceSubsystem.h"
|
|
||||||
#include "GameFramework/InputSettings.h"
|
#include "GameFramework/InputSettings.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -278,17 +277,3 @@ void UlxUtilityLibrary::ValidateLuaExpr(
|
|||||||
Status = w.ValidateLuaExpr(Code, ErrorMessage);
|
Status = w.ValidateLuaExpr(Code, ErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElxControllerType UlxUtilityLibrary::DetectControllerType(ULocalPlayer *Player)
|
|
||||||
{
|
|
||||||
UInputDeviceSubsystem *IDS = GEngine->GetEngineSubsystem<UInputDeviceSubsystem>();
|
|
||||||
if (!IDS) return ElxControllerType::KeyboardMouse;
|
|
||||||
|
|
||||||
FName Id = IDS->GetMostRecentlyUsedHardwareDevice(Player->GetPlatformUserId()).HardwareDeviceIdentifier;
|
|
||||||
|
|
||||||
if (Id == TEXT("ps3") || Id == TEXT("ps4") || Id == TEXT("ps5")) return ElxControllerType::PlayStationGamepad;
|
|
||||||
if (Id == TEXT("xbox360") || Id == TEXT("xboxone")) return ElxControllerType::XboxGamepad;
|
|
||||||
|
|
||||||
// Unknown or unrecognized device — assume keyboard/mouse
|
|
||||||
return ElxControllerType::KeyboardMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -179,9 +179,4 @@ public:
|
|||||||
//
|
//
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Utility")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Utility")
|
||||||
static void ValidateLuaExpr(ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code);
|
static void ValidateLuaExpr(ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code);
|
||||||
|
|
||||||
// Determine what type of controller the game is currently using
|
|
||||||
//
|
|
||||||
UFUNCTION(BlueprintCallable, category="Luprex|Utility")
|
|
||||||
static ElxControllerType DetectControllerType(ULocalPlayer *Player);
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user