UE4 输入系统详解一、 UE4如何获取win系统输入消息

UE4 输入系统详解一、 UE4如何获取win系统输入消息

UE4版本:4.253

按键输入

1、当我们按下键盘时输入时,FEngineLoop::Tick()里的每个tick执行的PumpMessages函数输送按键消息

WindowsPlatformApplicationMisc.cpp
void FWindowsPlatformApplicationMisc::PumpMessages(bool bFromMainLoop)
{
   
   //{…忽略代码}
	WinPumpMessages();
	//{…忽略代码}
}

static void WinPumpMessages()
{
   
	{
   
		MSG Msg;
		while( PeekMessage(&Msg,NULL,0,0,PM_REMOVE) )
		{
   
			TranslateMessage( &Msg );
			DispatchMessage( &Msg );
		}
	}
}
PeekMessage,读取消息,非阻塞式获取输入消息。
TranslateMessage,转换消息,将虚拟键消息转换成字符消息。
DispatchMessage,发送消息,该函数调度一个消息给窗口程序。

2、然后FWindowsApplication在AppWndProc处接受Windows传进的message;

LRESULT CALLBACK FWindowsApplication::AppWndProc(HWND hwnd, uint32 msg, WPARAM wParam, LPARAM lParam)
{
   
	ensure( IsInGameThread() );

	return WindowsApplication->ProcessMessage( hwnd, msg, wParam, lParam );
}

3、ProcessMessage()根据Message的类型对Message分类处理然后执行DeferMessage()。

4、DeferMessage()检查消息是否需要延迟处理;延迟处理则放入处理延迟处理列表TArray DeferredMessages;否则立即执行ProcessDeferredMessage()。

5、ProcessDeferredMessage()根据Message类型调用MessageHandler的不同方法开始处理事件,如鼠标双击OnMouseDoubleClick (),W键按下OnKeyDown(),则分别执行:
MessageHandler->OnMouseDoubleClick( CurrentNativeEventWindowPtr,EMouseButtons::Left );
MessageHandler->OnKeyDown( ActualKey, CharCode, bIsRepeat );

6、转到FSlateApplication
FSlateApplication根据不同按键的做不同的处理,如按下W键则执行OnKeyDown(),然后各自找出当前所有FWidgetPath、然后对于每个FWidgetPath里的Widget生成FReply响应,并执行Widget里面对应的处理事件的方法。就是当我们在场景中按下w是向前走,但在聊天那里按下w则是输入字符”w”。

bool FSlateApplication::OnKeyDown( const int32 KeyCode, const uint32 CharacterCode, const bool IsRepeat ) 
{
   
	FKey const Key = FInputKeyManager::Get().GetKeyFromCodes( KeyCode, CharacterCode );
	FKeyEvent KeyEvent(Key, PlatformApplication->GetModifierKeys(), GetUserIndexForKeyboard(), IsRepeat, CharacterCode, KeyCode);

	return ProcessKeyDownEvent( KeyEvent );
}

7、当在编辑器里的场景(PIE)中输入W键时,FSceneViewport会响应输入事件。

FReply FSceneViewport::OnKeyDown( const FGeometry& InGeometry, const FKeyEvent& InKeyEvent )
{
   
	//{…}
	//省略了判断代码
	if (!ViewportClient->InputKey(FInputKeyEventArgs(this, InKeyEvent.GetUserIndex(), Key, InKeyEvent.IsRepeat() ? IE_Repeat : IE_Pressed, 1.0f, false)))
	{
   
		CurrentReplyState = FReply::Unhandled();
	}
}

8、本次我是在场景中输入W键(控制角色向前移动),转到FSceneViewportWidget里面对应的处理事件。
然后执行FViewportClient::InputKey(),被派生类UGameViewportClient重写。

bool UGameViewportClient::InputKey(const FInputKeyEventArgs& EventArgs)
{
   
	//{…}
	//省略代码
	bResult = TargetPlayer->PlayerController->InputKey(EventArgs.Key, EventArgs.Event, EventArgs.AmountDepressed, EventArgs.IsGamepad());
	}

9、把按键信息发给PlayerController,然后交给UPlayerInput处理。

bool APlayerController::InputKey(FKey Key, EInputEvent EventType, float AmountDepressed, bool bGamepad)
{
   
	//省略代码
	bResult = PlayerInput->InputKey(Key, EventType, AmountDepressed, bGamepad);
}

获取按键输入消息

轴输入

轴输入指的是鼠标的X轴和Y轴的滑动(PS:按键也是有轴输入的)。
1、当我们按下键盘时输入时,FEngineLoop::Tick()里的每个tick执行FSlateApplication::FinishedInputThisFrame()函数处理输入累积值

void FSlateApplication::FinishedInputThisFrame()
{
   
   	///代码省略…
	///判断是否有主动捕获的Slate,有的话则遍历主动捕获的Widget处理累积值
	if (User.HasAnyCapture())
	{
   
	for (const TSharedRef<SWidget>& Captor : User.GetCaptorWidgets())
	{
   
		Captor->OnFinishedPointerInput();
	}
}
///遍历每个指针所在的最后一个Widget处理累积值
else
{
   
	for (
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值