UE5 CommonUI的使用(附源码版)


注:此处使用版本是UE5.4,不爱看源码的朋友跳过往后翻就行,不影响使用

前言

为啥UE5要推CommonUI?

用过原生的UserWidget的朋友,应该都清楚,UE的UI输入都来自于Focus的UI,当遇到主机游戏上,要频繁切UI,切输入的时候,老会发现当前的UI没有Focus,导致界面按钮没输入,然后卡死。又或者鼠标上切到外部,再切回来的时候,会发现Focus又丢失掉了,当你点了Viewport时候,会发现输入跑到了GameViewPort上,整体UI也就丢失了输入。包括它的输入,蓝图WidgetTree里面的UI接收输入时候,它的WidgetTree拥有者,也会接收到输入,没有PlayerController里面的输入的Consume操作。当然,还有很多风格化(样式),手柄导航等诸多考校,大家可以去阅读官方文档:

官网

快速配置

配置Game Viewport Client Class

Project Setting->All Settings下搜索Game Viewport Client Class,将视口切换成CommonGameViewportClient(CommonGameViewportClient包含了有关输入内容)
在这里插入图片描述

CommonGameViewportClient源代码

跳过

.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Engine/GameViewportClient.h"
#include "CommonGameViewportClient.generated.h"

class FReply;

DECLARE_DELEGATE_FourParams(FOnRerouteInputDelegate, FInputDeviceId /* InputDeviceId */, FKey /* Key */, EInputEvent /* EventType */, FReply& /* Reply */);
DECLARE_DELEGATE_FourParams(FOnRerouteAxisDelegate, FInputDeviceId /* InputDeviceId */, FKey /* Key */, float /* Delta */, FReply& /* Reply */);
DECLARE_DELEGATE_FiveParams(FOnRerouteTouchDelegate, int32 /* ControllerId */, uint32 /* TouchId */, ETouchType::Type /* TouchType */, const FVector2D& /* TouchLocation */, FReply& /* Reply */);

/**
* CommonUI Viewport to reroute input to UI first. Needed to allow CommonUI to route / handle inputs.
*/
UCLASS(Within = Engine, transient, config = Engine)
class COMMONUI_API UCommonGameViewportClient : public UGameViewportClient
{
   
	GENERATED_BODY()

public:

	UCommonGameViewportClient(FVTableHelper& Helper);
	virtual ~UCommonGameViewportClient();

	// UGameViewportClient interface begin
	virtual bool InputKey(const FInputKeyEventArgs& EventArgs) override;
	virtual bool InputAxis(FViewport* InViewport, FInputDeviceId InputDevice, FKey Key, float Delta, float DeltaTime, int32 NumSamples, bool bGamepad) override;
	virtual bool InputTouch(FViewport* InViewport, int32 ControllerId, uint32 Handle, ETouchType::Type Type, const FVector2D& TouchLocation, float Force, FDateTime DeviceTimestamp, uint32 TouchpadIndex) override;
	// UGameViewportClient interface end

	FOnRerouteInputDelegate& OnRerouteInput() {
    return RerouteInput; }
	FOnRerouteAxisDelegate& OnRerouteAxis() {
    return RerouteAxis; }
	FOnRerouteTouchDelegate& OnRerouteTouch() {
    return RerouteTouch; }

	FOnRerouteInputDelegate& OnRerouteBlockedInput() {
    return RerouteBlockedInput; }

	/** Default Handler for Key input. */
	UE_DEPRECATED(5.1, "This version of HandleRerouteInput has been deprecated. Please use the version that takes an FInputDeviceId instead")
	virtual void HandleRerouteInput(int32 ControllerId, FKey Key, EInputEvent EventType, FReply& Reply);

	/** Default Handler for Key input. */
	virtual void HandleRerouteInput(FInputDeviceId DeviceId, FKey Key, EInputEvent EventType, FReply& Reply);

	/** Default Handler for Axis input. */
	UE_DEPRECATED(5.1, "This version of HandleRerouteAxis has been deprecated. Please use the version that takes an FInputDeviceId instead")
	virtual void HandleRerouteAxis(int32 ControllerId, FKey Key, float Delta, FReply& Reply);

	/** Default Handler for Axis input. */
	virtual void HandleRerouteAxis(FInputDeviceId DeviceId, FKey Key, float Delta, FReply& Reply);

	/** Default Handler for Touch input. */
	virtual void HandleRerouteTouch(int32 ControllerId, uint32 TouchId, ETouchType::Type TouchType, const FVector2D& TouchLocation, FReply& Reply);

protected:
	
	/** Console window & fullscreen shortcut have higher priority than UI */
	virtual bool IsKeyPriorityAboveUI(const FInputKeyEventArgs& EventArgs);

	FOnRerouteInputDelegate RerouteInput;
	FOnRerouteAxisDelegate RerouteAxis;
	FOnRerouteTouchDelegate RerouteTouch;

	FOnRerouteInputDelegate RerouteBlockedInput;
};

#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2
#include "CoreMinimal.h"
#include "Input/Reply.h"
#include "InputCoreTypes.h"
#include "InputKeyEventArgs.h"
#include "UObject/ObjectMacros.h"
#endif

.cpp

// Copyright Epic Games, Inc. All Rights Reserved.

#include "CommonGameViewportClient.h"
#include "Engine/Console.h"
#include "Engine/GameInstance.h"
#include "Engine/LocalPlayer.h"
#include "InputKeyEventArgs.h"

#if WITH_EDITOR
#endif // WITH_EDITOR

#include "Input/CommonUIActionRouterBase.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(CommonGameViewportClient)

#define LOCTEXT_NAMESPACE ""

static const FName NAME_Typing = FName(TEXT("Typing"));
static const FName NAME_Open = FName(TEXT("Open"));

UCommonGameViewportClient::UCommonGameViewportClient(FVTableHelper& Helper) : Super(Helper)
{
   
}

UCommonGameViewportClient::~UCommonGameViewportClient()
{
   
}

bool UCommonGameViewportClient::InputKey(const FInputKeyEventArgs& InEventArgs)
{
   
	FInputKeyEventArgs EventArgs = InEventArgs;

	if (IsKeyPriorityAboveUI(EventArgs))
	{
   
		return true;
	}

	// Check override before UI
	if (OnOverrideInputKey().IsBound())
	{
   
		if (OnOverrideInputKey().Execute(EventArgs))
		{
   
			return true;
		}
	}

	// The input is fair game for handling - the UI gets first dibs
#if !UE_BUILD_SHIPPING
	if (ViewportConsole && !ViewportConsole->ConsoleState.IsEqual(NAME_Typing) && !ViewportConsole->ConsoleState.IsEqual(NAME_Open))
#endif
	{
   		
		FReply Result = FReply::Unhandled();
		if (!OnRerouteInput().ExecuteIfBound(EventArgs.InputDevice, EventArgs.Key, EventArgs.Event, Result))
		{
   
			HandleRerouteInput(EventArgs.InputDevice, EventArgs.Key, EventArgs.Event, Result);
		}

		if (Result.IsEventHandled())
		{
   
			return true;
		}
	}

	return Super::InputKey(EventArgs);
}

bool UCommonGameViewportClient::InputAxis(FViewport* InViewport, FInputDeviceId InputDevice, FKey Key, float Delta, float DeltaTime, int32 NumSamples, bool bGamepad)
{
   
	FReply RerouteResult = FReply::Unhandled();

	if (!OnRerouteAxis().ExecuteIfBound(InputDevice, Key, Delta, RerouteResult))
	{
   
		HandleRerouteAxis(InputDevice, Key, Delta, RerouteResult);
	}

	if (RerouteResult.IsEventHandled())
	{
   
		return true;
	}
	return Super::InputAxis(InViewport, InputDevice, Key, Delta, DeltaTime, NumSamples, bGamepad);
}

bool UCommonGameViewportClient::InputTouch(FViewport* InViewport, int32 ControllerId, uint32 Handle, ETouchType::Type Type, const FVector2D& TouchLocation, float Force, FDateTime DeviceTimestamp, uint32 TouchpadIndex)
{
   
#if !UE_BUILD_SHIPPING
	if (ViewportConsole != NULL && (ViewportConsole->ConsoleState != NAME_Typing) && (ViewportConsole->ConsoleState != NAME_Open))
#endif
	{
   
		FReply Result = FReply::Unhandled();
		if (!OnRerouteTouch().ExecuteIfBound(ControllerId, Handle, Type, TouchLocation, Result))
		{
   
			HandleRerouteTouch(ControllerId, Handle, Type, TouchLocation, Result);
		}

		if (Result.IsEventHandled())
		{
   
			return true;
		}
	}

	return Super::InputTouch(InViewport, ControllerId
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值