1749 字
9 分钟
3dcat 键鼠映射逻辑

名词释义#

按键 === 控件

数据结构#

type Solution = {
  showButton: boolean // 是否默认开启显示
  showAlias: boolean // 是否原键盘字符隐藏
  landscape: SolutionData[] // 横屏数据
  portrait: SolutionData[] // 竖屏数据
  landscapeButtonSize?: ButtonSizeType // 横屏时控件大小(初版开发时横竖屏需支持分别设置,当前版本改为统一设置)
  portraitButtonSize?: ButtonSizeType // 竖屏时控件大小(横竖屏设置情况同上)
}
type SolutionData = {
  type: ScreenDataType
  value: SolutionValue
}
type SolutionValue = {
  pos: [number, number] // 坐标,百分比
  value: number[]。// keyCode 值
  width?: number // 控件宽度,px
  height: number // 控件高度,px
  shape?: SolutionShape // 控件形状(当前为统一的粒度设置,初版开发时支持以单个控件为粒度的设置)
  alias?: string // 控件说明,只支持键盘类型数据
}
export enum ButtonSizeType {
  Small = 1,
  Middle,
  Large,
  Custom, // 自定义
}
export enum ScreenDataType {
  Normal = 1, // 键盘
  UDLR, // 带方向键摇杆
  WASD, // 带 WASD 摇杆
  Joystick, // 无文字标识摇杆Ï
  Mouse, //
}
export enum SolutionShape {
  Rectangle = 1, // 直角矩形
  Circle, // 圆角矩形
}

键盘#

  • 每个控件设置前需点击屏幕
  • 只支持最多两个控件的控件组合
  • 只支持/src/constants/keycode-map.ts 里的 KeycodeMap 变量支持的控件。
  • 以 keyCode 属性保存键盘的值
  • 不支持重复设置控件,比如说多个 s 键或多个 a + b 键
  • 控件宽度由内容撑开,渲染到屏幕后再获取控件元素宽度属性 clientWidth 将其赋值到 SolutionValue 的 width 属性上
  • 区分左右 Shift、Ctrl、Alt 控件,keyCode 属性的值以/src/constants/keycode-map.ts 里定义的六个常量的值为准
  • 不支持 Mac 端 command 、option 控件
  • 成功设置后会自动进行边界检测,若超出边界则自动弹回至控件设置区域内,产品侧考虑取消该特性
  • 控件有控件说明时,会自动撑开高度,最多支持 4 个字符
  • 只有键盘类型控件有控件说明

鼠标#

  • 左右键设置逻辑为一起设置,一起删除
  • 中键为单独设置,单独删除
  • 每种控件只能设置一个,不能设置多个
  • 成功设置后会自动进行边界检测,若超出边界则自动弹回至控件设置区域内,产品侧考虑取消该特性

摇杆#

  • 每种摇杆只能设置一个,不能设置多个
  • 成功设置后会自动进行边界检测,若超出边界则自动弹回至控件设置区域内,产品侧考虑取消该特性

预设方案#

  • 控件类型横竖屏方案为分别设置
  • 控件同步功能只同步类型、数量,不同步控件大小、控件说明、控件形状
  • 如当前方案有控件被改动过,控件大小的值自动改为自定义
  • 预设方案的增删查改,产品特性层面不作改动,各搞各的
  • 3dcat 侧旧数据的处理,自行开发适配器以适配斗龙云侧方案的数据结构

misc#

  • 3dcat 侧不少逻辑代码的处理都可归为「边界逻辑判断」、「在画布区域点击后未设置具体键盘类型控件的值就进行其它的操作」,可考虑去除或优化该部分逻辑。
  • 是否考虑键盘及鼠标类型控件宽度为固定值,即取消「撑开」的特性

SDK 端#

流程及流程图#

  • 旧版的 sdk 是在 launcher 那里调接口,再实例化控件,
  • 新版的 sdk 是在其他 UI launcher 调接口,再实例化 launcher -> 控件
sequenceDiagram
title: 3dcat-键鼠映射流程
autonumber
3DCAT前台管理 ->> + 3DCAT后端服务 : 设置键鼠映射数据(VirtualGlobalType)
推流页 ->> + 3DCAT后端服务 : 获取应用数据
3DCAT后端服务 -->> - 推流页 : 包含VirtualGlobalType
推流页 ->> 推流页 : 实例化live-cat
live-cat ->> live-cat : 清洗键鼠映射数据、位置、样式计算、默认值填充(virtual-data-repository.ts)
live-cat ->> live-cat : 渲染键鼠映射控制器
interface VirtualGlobalType {
  resolutionRatio: string
  buttonSize: ButtonSizeType
  showButton: boolean
  showAlias: boolean
  landscape: VirtualDataType[]
  portrait: VirtualDataType[]
}

横竖屏#

  • 需要读取 core 中的 orientationLock 属性,自动旋转全部算为横屏。否则以终端容器方向为主。
  • 受: 1、手机系统层面的屏幕锁定功能 2、应用是否处于全屏状态 3、当前应用的自动全屏开关是否开启 影响。
  • 当处于应用处于全屏状态时,为横屏;
  • 当不处于全屏状态时,若屏幕锁定功能未开启,则随手机当前陀螺仪检测状态来显示横竖屏控件;
  • 另外,当自动全屏开关开启时,在应用初始化时,点击屏幕会自动进入全屏状态(此时也就是显示横屏控件)。

键盘#

  • 单键
  • 组合键(目前最高支持两个键值)
  • 分常规组合键及非常规组合键
  • 常规组合键:其中一个键带 ctrl、shift、alt、(n/c/s)lock,另一个键是除这几个键之外的其它键,这个时候是在一个 Comine 事件中发送的;检测两个键值中的 alt、shift 等功能键的布尔值,同步更新 Keyboard 实例化字段,并轮训发送两个键值。
  • 非常规组合键:比如 a + z,则视为两个 Single 事件,分开发送

鼠标#

  • 仅用于鼠标左中右键状态切换。若未映射鼠标,屏幕触发事件(手指点击拖动等)将默认为鼠标左键。
  • 额外处理:改变 RunningState fakeTouchType 类型
class Keyboard {
  constructor(
    private keycode: number,
    private alt: boolean,
    private shift: boolean,
    private ctrl: boolean,
    private nlock: boolean,
    private clock: boolean,
    private slock: boolean,
    private down: boolean,
  ) { }
}

摇杆#

  • 三种摇杆前端均支持全向摇杆(假全方向,实际是 WASD 摇杆,只是与 WASD 摇杆有 UI 差异)
  • 节点机端支持全方位,demo 已跑通,当在双手柄(左右手柄)操作时,需将左右两个手柄的实时操作数据放到同一个数据结构下再进行节点端的发送,否则会出现后发送手柄的操作数据覆盖前发送手柄的操作数据
enum JoyStickType {
  'ONLY_HANDLE',
  'TEXT_HANDLE',
  'DIRECTION_HANDLE',
}

{
  [JoyStickType.ONLY_HANDLE]: {
    topKeycode: 87,
    rightKeycode: 68,
    bottomKeycode: 83,
    leftKeycode: 65,
  },
  [JoyStickType.TEXT_HANDLE]: {
    topKeycode: 87,
    rightKeycode: 68,
    bottomKeycode: 83,
    leftKeycode: 65,
  },
  [JoyStickType.DIRECTION_HANDLE]: {
    topKeycode: 38,
    rightKeycode: 39,
    bottomKeycode: 40,
    leftKeycode: 37,
  },
}

class Keyboard {
  constructor(
    private keycode: number,
    private alt: boolean,
    private shift: boolean,
    private ctrl: boolean,
    private nlock: boolean,
    private clock: boolean,
    private slock: boolean,
    private down: boolean,
  ) { }
}

样式#

  • 与编辑器端不同,是两套独立开发的控件,UI 有差异,控件内排版大致相同

预设方案#

  • 3dcat 侧旧数据的处理,自行开发适配器以适配斗龙云侧方案的数据结构

Todo#

  1. 全方向摇杆(单机单并发)
  • 支持左右两个摇杆
  • 支持两个摇杆同步数据
 class GamepadInput {
  constructor(
    private gamepadType: GamepadType = GamepadType.GamepadXbox,
    private gamepadUser: number = 0,
    private buttons: number,
    private leftTrigger: number,
    private rightTrigger: number,
    private leftThumbX: number,
    private leftThumbY: number,
    private rightThumbX: number,
    private rightThumbY: number,
  ) { }
}
  • React 控件 -> Svelte 控件
  • 博客 mermaid 实现
3dcat 键鼠映射逻辑
https://www.hzhi.top/posts/3dcat-keyboard-mapping/
作者
Jim的独立博客
发布于
2023-08-14
许可协议
CC BY-NC-SA 4.0