Last active
March 18, 2024 19:02
-
-
Save sinbad/9b8f8007fb1e55f1a952cce2d12aaac1 to your computer and use it in GitHub Desktop.
Revisions
-
sinbad renamed this gist
Aug 26, 2020 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
sinbad revised this gist
Aug 26, 2020 . 2 changed files with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes.File renamed without changes. -
sinbad revised this gist
Aug 26, 2020 . 1 changed file with 0 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,4 @@ #include "InputModeDetector.h" #include "Input/Events.h" FInputModeDetector::FInputModeDetector() -
sinbad revised this gist
Aug 26, 2020 . 1 changed file with 2 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -72,13 +72,11 @@ EInputMode FInputModeDetector::GetLastInputMode(int PlayerIndex) void FInputModeDetector::ProcessKeyOrButton(int PlayerIndex, FKey Key) { if (Key.IsGamepadKey()) { SetMode(PlayerIndex, EInputMode::Gamepad); } else if (Key.IsMouseButton()) { // Assuming mice don't have analog buttons! SetMode(PlayerIndex, EInputMode::Mouse); @@ -89,7 +87,6 @@ void FInputModeDetector::ProcessKeyOrButton(int PlayerIndex, FKey Key) // Assuming keyboards don't have analog buttons! SetMode(PlayerIndex, EInputMode::Keyboard); } } void FInputModeDetector::SetMode(int PlayerIndex, EInputMode NewMode) -
sinbad renamed this gist
Aug 26, 2020 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
sinbad created this gist
Aug 26, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,50 @@ // You probably want to do this from your GameInstance subclass ... // Namespace level in header DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode); ... // In class declaration: protected: TSharedPtr<FInputModeDetector> InputDetector; public: /// Event raised when input mode changed between gamepad / keyboard / mouse UPROPERTY(BlueprintAssignable) FOnInputModeChanged OnInputModeChanged; UFUNCTION(BlueprintCallable) EInputMode GetLastInputModeUsed(int PlayerIndex = 0) const { return InputDetector->GetLastInputMode(PlayerIndex); } UFUNCTION(BlueprintCallable) bool LastInputWasGamePad(int PlayerIndex = 0) const { return GetLastInputModeUsed(PlayerIndex) == EInputMode::Gamepad; } ... // In source // Do this at startup somewhere void MyExampleGameInstance::CreateInputDetector() { if (!InputDetector.IsValid()) { InputDetector = MakeShareable(new FInputModeDetector()); FSlateApplication::Get().RegisterInputPreProcessor(InputDetector); InputDetector->OnInputModeChanged.BindUObject(this, &USnukaGameInstance::OnInputDetectorModeChanged); } } // Do this at shutdown void MyExampleGameInstance::DestroyInputDetector() { if (InputDetector.IsValid()) { FSlateApplication::Get().UnregisterInputPreProcessor(InputDetector); InputDetector.Reset(); } } void MyExampleGameInstance::OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode) { // Propagate dynamic multicast event, everyone else should listen on this OnInputModeChanged.Broadcast(PlayerIndex, NewMode); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,106 @@ #include "InputModeDetector.h" #include "InputHelper.h" #include "Input/Events.h" FInputModeDetector::FInputModeDetector() { // 4 local players should be plenty usually (will expand if necessary) LastInputModeByPlayer.Init(EInputMode::Mouse, 4); } bool FInputModeDetector::HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& InKeyEvent) { // Key down also registers for gamepad buttons ProcessKeyOrButton(InKeyEvent.GetUserIndex(), InKeyEvent.GetKey()); // Don't consume return false; } bool FInputModeDetector::HandleAnalogInputEvent(FSlateApplication& SlateApp, const FAnalogInputEvent& InAnalogInputEvent) { if (InAnalogInputEvent.GetAnalogValue() > GamepadAxisThreshold) SetMode(InAnalogInputEvent.GetUserIndex(), EInputMode::Gamepad); // Don't consume return false; } bool FInputModeDetector::HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent) { FVector2D Dist = MouseEvent.GetScreenSpacePosition() - MouseEvent.GetLastScreenSpacePosition(); if (FMath::Abs(Dist.X) > MouseMoveThreshold || FMath::Abs(Dist.Y) > MouseMoveThreshold) { SetMode(MouseEvent.GetUserIndex(), EInputMode::Mouse); } // Don't consume return false; } bool FInputModeDetector::HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent) { // We don't care which button SetMode(MouseEvent.GetUserIndex(), EInputMode::Mouse); // Don't consume return false; } bool FInputModeDetector::HandleMouseWheelOrGestureEvent(FSlateApplication& SlateApp, const FPointerEvent& InWheelEvent, const FPointerEvent* InGestureEvent) { SetMode(InWheelEvent.GetUserIndex(), EInputMode::Mouse); // Don't consume return false; } void FInputModeDetector::Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> Cursor) { // Required, but do nothing } EInputMode FInputModeDetector::GetLastInputMode(int PlayerIndex) { if (PlayerIndex >= 0 && PlayerIndex < LastInputModeByPlayer.Num()) return LastInputModeByPlayer[PlayerIndex]; // Assume default if never told return DefaultInputMode; } void FInputModeDetector::ProcessKeyOrButton(int PlayerIndex, FKey Key) { bool bGamepad = Key.IsGamepadKey(); if (bGamepad) { SetMode(PlayerIndex, EInputMode::Gamepad); } else if (UInputHelper::IsMouse(Key)) { // Assuming mice don't have analog buttons! SetMode(PlayerIndex, EInputMode::Mouse); } else { // We assume anything that's not mouse and not gamepad is a keyboard // Assuming keyboards don't have analog buttons! SetMode(PlayerIndex, EInputMode::Keyboard); } } void FInputModeDetector::SetMode(int PlayerIndex, EInputMode NewMode) { if (NewMode != EInputMode::Unknown && NewMode != GetLastInputMode(PlayerIndex)) { if (PlayerIndex >= LastInputModeByPlayer.Num()) LastInputModeByPlayer.SetNum(PlayerIndex + 1); LastInputModeByPlayer[PlayerIndex] = NewMode; OnInputModeChanged.ExecuteIfBound(PlayerIndex, NewMode); UE_LOG(LogTemp, Warning, TEXT("Input mode for player %d changed: %s"), PlayerIndex, *UEnum::GetValueAsString(NewMode)); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,70 @@ #pragma once #include "CoreMinimal.h" #include "InputCoreTypes.h" #include "Framework/Application/IInputProcessor.h" #include "UObject/ObjectMacros.h" // for UENUM UENUM(BlueprintType) enum class EInputMode : uint8 { Mouse, Keyboard, Gamepad, Unknown }; DECLARE_DELEGATE_TwoParams(FOnInputModeForPlayerChanged, int /* PlayerIndex */, EInputMode) /** * This class should be registered as an input processor in order to capture all input events & detect * what kind of devices are being used. We can't use PlayerController to do this reliably because in UMG * mode, all the mouse move events are consumed by Slate and you never see them, so it's not possible to * detect when the user moved a mouse. * * This class should be instantiated and used from some UObject of your choice, e.g. your GameInstance class, * something like this: * * InputDetector = MakeShareable(new FInputModeDetector()); * FSlateApplication::Get().RegisterInputPreProcessor(InputDetector); * InputDetector->OnInputModeChanged.BindUObject(this, &UMyGameInstance::OnInputDetectorModeChanged); * * Note how the OnInputModeChanged on this object is a simple delegate, not a dynamic multicast etc, because * this is not a UObject. You should relay the input mode event changed through the owner if you want to distribute * the information further. */ class PROJECT_API FInputModeDetector : public IInputProcessor, public TSharedFromThis<FInputModeDetector> { protected: TArray<EInputMode> LastInputModeByPlayer; public: EInputMode DefaultInputMode = EInputMode::Mouse; float MouseMoveThreshold = 1; float GamepadAxisThreshold = 0.2; // Single delegate caller, owner should propagate if they want (this isn't a UObject) FOnInputModeForPlayerChanged OnInputModeChanged; FInputModeDetector(); virtual bool HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& InKeyEvent) override; virtual bool HandleAnalogInputEvent(FSlateApplication& SlateApp, const FAnalogInputEvent& InAnalogInputEvent) override; virtual bool HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent) override; virtual bool HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent) override; virtual bool HandleMouseWheelOrGestureEvent(FSlateApplication& SlateApp, const FPointerEvent& InWheelEvent, const FPointerEvent* InGestureEvent) override; virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> Cursor) override; EInputMode GetLastInputMode(int PlayerIndex = 0); protected: void ProcessKeyOrButton(int PlayerIndex, FKey Key); void SetMode(int PlayerIndex, EInputMode NewMode); };