//////////////////////////////////////////////////////////// // // LuprexViewportClient.cpp // //////////////////////////////////////////////////////////// #include "LuprexViewportClient.h" #include "Common.h" #include "PlayerControllerBase.h" #include "Engine/GameInstance.h" #include "Framework/Application/SlateApplication.h" #include "Layout/WidgetPath.h" #include "Widgets/SViewport.h" UlxViewportClient::UlxViewportClient(const FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer) { UE_LOG(LogLuprexIntegration, Display, TEXT("UlxViewportClient constructed")); } bool UlxViewportClient::InputKey(const FInputKeyEventArgs &EventArgs) { UE_LOG(LogLuprexIntegration, Display, TEXT("UlxViewportClient::InputKey key=%s event=%d"), *EventArgs.Key.ToString(), (int32)EventArgs.Event); // Only act on left mouse button presses that bubbled up to the // viewport unhandled. Walk the widget path under the cursor and // find the nearest focusable ancestor of whatever was hit. If it // isn't the game viewport itself, hand it to the player controller // to apply on its next UpdateInputMode pass; that's the point in // the frame where we can override SViewport's own click-focus // behaviour without fighting it. if ((EventArgs.Event == IE_Pressed) && (EventArgs.Key == EKeys::LeftMouseButton)) { FSlateApplication &Slate = FSlateApplication::Get(); FVector2D MousePos = Slate.GetCursorPos(); FWidgetPath Path = Slate.LocateWindowUnderMouse( MousePos, Slate.GetInteractiveTopLevelWindows()); if (Path.IsValid()) { TSharedPtr ViewportWidget = GetGameViewportWidget(); for (int32 Idx = Path.Widgets.Num() - 1; Idx >= 0; --Idx) { TSharedRef Widget = Path.Widgets[Idx].Widget; if (!Widget->SupportsKeyboardFocus()) continue; if (ViewportWidget.IsValid() && Widget == ViewportWidget) break; if (UGameInstance *GI = GetGameInstance()) { if (AlxPlayerControllerBase *PC = Cast( GI->GetFirstLocalPlayerController(GetWorld()))) { PC->ClickToFocus(Widget); } } break; } } } return Super::InputKey(EventArgs); }