zoukankan      html  css  js  c++  java
  • UE4-快捷键-按键监听事件

    前言

    • 在Actor中可以直接在Keyboard Event中选择相应的键盘按键触发事件:
      • Actor: 键盘响应事件
      • Keyboard Event:

    问题背景

    • 读取json数据生成WB(Widget Blueprint)
    • 键盘快键键响应事件 == 点击(On Click)WB事件
    • 上面在Actor中可以直接选择事件,但是我的需求是键盘快捷键响应 与 WB绑定的On Click事件 等同。

    目的

    • 将用户的按键输入事件传递到UMG中,在UMG中响应逻辑。

    当然也可以选择有输入组件能力的角色进行事件传递,但这处理起来很麻烦,我们需要角色持有UMG的对象指针,并且需要维护数据对象。

    解决思路

    1. 构建UMG
    2. 将UMG添加到视口
    3. 在用户输入事件列表中注册输入事件
    4. 在UMG中绑定输入事件

    • 上述思路,个人是通过读取Json文件循环创建。1~2步骤按照个人需求实现
    • 用户输入事件注册:
      • Edit——>Project Settings——>Engine——>input
      • 右侧选择Action Mappings,添加KeyName和ActionName
      • 在项目用户输入列表中加入如下输入事件
      • InputEventRegister
    • 在UMG中加入如下蓝图内容
      ListenforInputActionEvent

    • 注意
    • UMG中只能响应Action事件,如果需要响应Axis事件需要自行编写逻辑
    • 勾选Consume则事件只传递到当前UMG,不会向下传递,如果需要向下传递,可去掉节点中的勾
    • Action Name是在用户输入事件列表中注册的名称

    C++实现

    1. UE4提供了UInputKeySelector控件,可以通过鼠标点击激活快捷键输入,然后点击键盘上按键,可以通过将设置的快捷键,显示出来

    2. 设置快捷键的根本思路,通过移除在InputSettings上一个AxisMap或者ActionMap,然后把新的AxisMap或者ActionMap添加进InputSettings

    3. 关键性代码:

      void UI_Option::RebindActionMapping(const FName KeyName, const FKey Key)
      {
      	if (KeyName.IsValid())
      	{
      		TArray<struct FInputActionKeyMapping> ActionMappings = UInputSettings::GetInputSettings()->GetActionMappings();
      
      		for (int32 ActionIndex = 0; ActionIndex < ActionMappings.Num(); ++ActionIndex)
      		{
      			if (ActionMappings[ActionIndex].ActionName == KeyName)
      			{
      				UInputSettings::GetInputSettings()->RemoveActionMapping(ActionMappings[ActionIndex]);
      				FInputActionKeyMapping ActionMap;
      				ActionMap.ActionName = KeyName;
      				ActionMap.Key = Key;
      				UInputSettings::GetInputSettings()->AddActionMapping(ActionMap);
      			}
      		}
      	}
      	UInputSettings::GetInputSettings()->SaveKeyMappings();
      	UInputSettings::GetInputSettings()->ForceRebuildKeymaps();
      }
      
      void UI_Option::RebindAxisMapping(const FName KeyName, const FKey Key)
      {
      	if (KeyName.IsValid())
      	{
      		TArray<struct FInputAxisKeyMapping> AxisMappings = UInputSettings::GetInputSettings()->GetAxisMappings();
      
      		for (int32 AxisIndex = 0; AxisIndex < AxisMappings.Num(); ++AxisIndex)
      		{
      			if (AxisMappings[AxisIndex].AxisName == KeyName)
      			{
      				UInputSettings::GetInputSettings()->RemoveAxisMapping(AxisMappings[AxisIndex]);
      				FInputAxisKeyMapping  AxisMap;
      				AxisMap.AxisName = KeyName;
      				AxisMap.Key = Key;
      				UInputSettings::GetInputSettings()->AddAxisMapping(AxisMap);
      			}
      		}
      	}
      	UInputSettings::GetInputSettings()->SaveKeyMappings();
      	UInputSettings::GetInputSettings()->ForceRebuildKeymaps();
      	
      }
    4. 整体思路

      • 先把ue4 项目设置里Input设置的ActionName和AxisName以及他的绑定Key用一种数据结构存储起来【如果考虑组合键也要把组合键的关系存起来】
      • 在考虑存储数据结构时,要考虑按键【泛指:键盘,手柄】不能冲突,所以在重置一个功能的按键【L】时首先要把输入设置中与按键【L】相关的设置为无效的(当然,当你检测到输入按键【L】有其他功能在使用时,也可以弹提示框警告,然后拒绝重置操作,在这里讨论直接让输入生效,并且使用该快捷键的其他功能快捷键失效)
      • 在考虑数据结构时,需要存储并更新原来的ActionName或AxisName与key的绑定关系
      • 在真正保存应用修改时,执行绑定关系
      • 在考虑数据结构时,需要保存修改后的快捷键设置状态,如果把(1)-(4)考虑的数据结构,和保存数据融合在一起,则显得不够优雅,并且在使用UGameplayStatics::SaveGameToSlot进行保存时,还需要进行数据处理,因为你没必要保存重置、更新功能的方法,所以要与保存的数据进行分离,并且要支持多端输入,保存的最好是一个对应功能Key的数组
      • 功能性结构,与保存数据结构如何关联,增加一个功能如何快速增加快捷键;在考虑这个问题时,有两种方式,一种是函数式,一种是宏;使用宏调试不能正确跳转,建议使用函数式,当点保存时,把新的值写进本地,否者,重新读本地值,重新刷新界面,判定是否更改,可以对比内存值与本地值进行对比;
  • 相关阅读:
    MongoDB下配置用户权限
    (CF)Codeforces445A DZY Loves Chessboard(纯实现题)
    C语言概述
    C#中值类型和引用类型的差别浅记
    Qt5官方demo解析集30——Extending QML
    汉澳sinox通过ndis执行windows驱动程序
    linux设备驱动归纳总结(三):4.ioctl的实现【转】
    linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现【转】
    linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write【转】
    linux设备驱动归纳总结(三):1.字符型设备之设备申请【转】
  • 原文地址:https://www.cnblogs.com/yblackd/p/14533375.html
Copyright © 2011-2022 走看看