mirror of
https://github.com/motajs/template.git
synced 2026-11-01 06:04:30 +08:00
refactor: 按键系统的部分实现
This commit is contained in:
1 parent
3f7afb635e
commit
88c4f5112c
14 files changed
+158
-561
No files matched your search
@@ -1,4 +1,4 @@
|
||||
export * from './choices';
|
||||
export * from '../../../../src/client/ui/choices';
|
||||
export * from './floorSelect';
|
||||
export * from './icons';
|
||||
export * from './input';
|
||||
|
||||
@@ -17,7 +17,7 @@ import { linear } from 'mutate-animate';
|
||||
import { Background, Selection } from './misc';
|
||||
import { GameUI, IUIController, SetupComponentOptions } from '@motajs/system';
|
||||
import { KeyCode } from '@motajs/client-base';
|
||||
import { IGameUIPropsBase } from '../types';
|
||||
import { IGameUIPropsBase } from '../../../client-modules/src/types';
|
||||
|
||||
export interface InputProps extends DefaultProps, Partial<TextContentProps> {
|
||||
/** 输入框的提示内容 */
|
||||
@@ -142,7 +142,7 @@ export const Input = defineComponent<InputProps, InputEmits, keyof InputEmits>(
|
||||
} else {
|
||||
ele = document.createElement('input');
|
||||
}
|
||||
// See file://./../../../../../src/styles.less
|
||||
// See src/styles.less
|
||||
ele.classList.add('motajs-input-element');
|
||||
listenInput();
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ import { clamp } from 'lodash-es';
|
||||
// @ts-expect-error render/renderer 按 D-54 留在实现层,本文件已移入系统层,按 D-59 暂以标注记录,不反向引用、不解耦
|
||||
import { using } from '../renderer';
|
||||
import { cosh, CurveMode } from '@motajs/animate';
|
||||
import { IGameUIPropsBase } from '../types';
|
||||
import { IGameUIPropsBase } from '../../../client-modules/src/types';
|
||||
|
||||
interface ProgressProps extends DefaultProps {
|
||||
/** 进度条的位置 */
|
||||
|
||||
@@ -5,6 +5,7 @@ export * from './layout';
|
||||
export * from './map';
|
||||
export * from './material';
|
||||
export * from './save';
|
||||
export * from './use';
|
||||
|
||||
export * from './shared';
|
||||
export * from './types';
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { IHotkeyEmitInfo, IHotkeySystem } from '@motajs/system';
|
||||
import { IHotkeyUsing } from './types';
|
||||
import { getCurrentInstance, onMounted, onUnmounted } from 'vue';
|
||||
import { logger } from '@motajs/common';
|
||||
|
||||
class HotkeyUsing implements IHotkeyUsing {
|
||||
/** 作用域 Promise */
|
||||
private readonly scopePromise: Promise<symbol>;
|
||||
|
||||
/** 当前是否已经挂载 */
|
||||
private mounted: boolean = false;
|
||||
/** 当前按键作用域 */
|
||||
private keyScope: symbol | null = null;
|
||||
/** 当前的按键实现对象 */
|
||||
private impl: Map<string, (info: IHotkeyEmitInfo) => void> = new Map();
|
||||
|
||||
constructor(
|
||||
readonly system: IHotkeySystem,
|
||||
clearImpl: boolean
|
||||
) {
|
||||
const { promise, resolve } = Promise.withResolvers<symbol>();
|
||||
this.scopePromise = promise;
|
||||
|
||||
onMounted(() => {
|
||||
this.mounted = true;
|
||||
const scope = system.enterScope(clearImpl);
|
||||
this.keyScope = scope;
|
||||
resolve(scope);
|
||||
for (const [command, func] of this.impl) {
|
||||
system.implement(command, func);
|
||||
}
|
||||
this.impl.clear();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (this.keyScope) {
|
||||
system.leaveScope(this.keyScope);
|
||||
} else {
|
||||
logger.warn(211);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
scope(): Promise<symbol> {
|
||||
return this.scopePromise;
|
||||
}
|
||||
|
||||
implement(command: string, func: (info: IHotkeyEmitInfo) => void): this {
|
||||
if (this.mounted) {
|
||||
this.system.implement(command, func);
|
||||
} else {
|
||||
this.impl.set(command, func);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成仅在当前组件的生命周期中生效的按键指令对象,必须在 Vue 组件中调用,否则会返回 `null`
|
||||
* @param system 按键系统
|
||||
* @param clearImpl 是否清空上一个作用域的按键实现,默认清空。不清空时,上一个作用域的按键实现依旧在新作用域生效,
|
||||
* 若清空,则不会生效,只有当当前的作用域被释放后才会继续生效。
|
||||
*/
|
||||
export function useKey(
|
||||
system: IHotkeySystem,
|
||||
clearImpl: boolean = true
|
||||
): IHotkeyUsing | null {
|
||||
const instance = getCurrentInstance();
|
||||
if (!instance) return null;
|
||||
return new HotkeyUsing(system, clearImpl);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './hotkey';
|
||||
export * from './types';
|
||||
@@ -0,0 +1,15 @@
|
||||
import { IHotkeyEmitInfo } from '@motajs/system';
|
||||
|
||||
export interface IHotkeyUsing {
|
||||
/**
|
||||
* 获取本次 `using` 所使用的按键作用域
|
||||
*/
|
||||
scope(): Promise<symbol>;
|
||||
|
||||
/**
|
||||
* 实现按键指令
|
||||
* @param command 按键指令
|
||||
* @param func 按键指令触发时执行的函数
|
||||
*/
|
||||
implement(command: string, func: (info: IHotkeyEmitInfo) => void): this;
|
||||
}
|
||||
@@ -1,526 +0,0 @@
|
||||
import { KeyCode } from '@motajs/client-base';
|
||||
import { gameKey, HotkeyJSON } from '@motajs/system';
|
||||
import { GameStorage } from '@motajs/legacy-system';
|
||||
|
||||
export const mainScope = Symbol.for('@key_main');
|
||||
|
||||
// todo: 读取上一个手动存档,存档至下一个存档栏
|
||||
// ----- Register
|
||||
gameKey
|
||||
//#region 游戏按键
|
||||
.group('game', '游戏按键')
|
||||
.register({
|
||||
id: 'moveUp',
|
||||
name: '上移',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveDown',
|
||||
name: '下移',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveLeft',
|
||||
name: '左移',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: 'moveRight',
|
||||
name: '右移',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
//#region ui界面
|
||||
.group('ui', 'ui界面')
|
||||
.register({
|
||||
id: 'book',
|
||||
name: '怪物手册',
|
||||
defaults: KeyCode.KeyX
|
||||
})
|
||||
.register({
|
||||
id: 'save',
|
||||
name: '存档界面',
|
||||
defaults: KeyCode.KeyS
|
||||
})
|
||||
.register({
|
||||
id: 'load',
|
||||
name: '读档界面',
|
||||
defaults: KeyCode.KeyD
|
||||
})
|
||||
.register({
|
||||
id: 'toolbox',
|
||||
name: '道具栏',
|
||||
defaults: KeyCode.KeyT
|
||||
})
|
||||
.register({
|
||||
id: 'equipbox',
|
||||
name: '装备栏',
|
||||
defaults: KeyCode.KeyQ
|
||||
})
|
||||
.register({
|
||||
id: 'fly',
|
||||
name: '楼层传送',
|
||||
defaults: KeyCode.KeyG
|
||||
})
|
||||
.register({
|
||||
id: 'menu',
|
||||
name: '菜单',
|
||||
defaults: KeyCode.Escape
|
||||
})
|
||||
.register({
|
||||
id: 'replay',
|
||||
name: '录像回放',
|
||||
defaults: KeyCode.KeyR
|
||||
})
|
||||
.register({
|
||||
id: 'shop',
|
||||
name: '快捷商店',
|
||||
defaults: KeyCode.KeyV
|
||||
})
|
||||
.register({
|
||||
id: 'statistics',
|
||||
name: '数据统计',
|
||||
defaults: KeyCode.KeyB
|
||||
})
|
||||
.register({
|
||||
id: 'viewMap_1',
|
||||
name: '浏览地图_1',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
.register({
|
||||
id: 'viewMap_2',
|
||||
name: '浏览地图_2',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
//#region 功能按键
|
||||
.group('function', '功能按键')
|
||||
.register({
|
||||
id: 'undo_1',
|
||||
name: '回退_1',
|
||||
defaults: KeyCode.KeyA
|
||||
})
|
||||
.register({
|
||||
id: 'undo_2',
|
||||
name: '回退_2',
|
||||
defaults: KeyCode.Digit5
|
||||
})
|
||||
.register({
|
||||
id: 'redo_1',
|
||||
name: '恢复_1',
|
||||
defaults: KeyCode.KeyW
|
||||
})
|
||||
.register({
|
||||
id: 'redo_2',
|
||||
name: '恢复_2',
|
||||
defaults: KeyCode.Digit6
|
||||
})
|
||||
.register({
|
||||
id: 'turn',
|
||||
name: '勇士转向',
|
||||
defaults: KeyCode.KeyZ
|
||||
})
|
||||
.register({
|
||||
id: 'getNext_1',
|
||||
name: '轻按_1',
|
||||
defaults: KeyCode.Space
|
||||
})
|
||||
.register({
|
||||
id: 'getNext_2',
|
||||
name: '轻按_2',
|
||||
defaults: KeyCode.Digit7
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_1',
|
||||
name: '切换/保存套装_1',
|
||||
defaults: KeyCode.Digit1,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_2',
|
||||
name: '切换/保存套装_2',
|
||||
defaults: KeyCode.Digit2,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_3',
|
||||
name: '切换/保存套装_3',
|
||||
defaults: KeyCode.Digit3,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_4',
|
||||
name: '切换/保存套装_4',
|
||||
defaults: KeyCode.Digit4,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_5',
|
||||
name: '切换/保存套装_5',
|
||||
defaults: KeyCode.Digit5,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_6',
|
||||
name: '切换/保存套装_6',
|
||||
defaults: KeyCode.Digit6,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_7',
|
||||
name: '切换/保存套装_7',
|
||||
defaults: KeyCode.Digit7,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_8',
|
||||
name: '切换/保存套装_8',
|
||||
defaults: KeyCode.Digit8,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_9',
|
||||
name: '切换/保存套装_9',
|
||||
defaults: KeyCode.Digit9,
|
||||
alt: true
|
||||
})
|
||||
.register({
|
||||
id: 'quickEquip_0',
|
||||
name: '切换/保存套装_0',
|
||||
defaults: KeyCode.Digit0,
|
||||
alt: true
|
||||
})
|
||||
//#region 系统按键
|
||||
.group('system', '系统按键')
|
||||
.register({
|
||||
id: 'restart',
|
||||
name: '回到开始界面',
|
||||
defaults: KeyCode.KeyN
|
||||
})
|
||||
.register({
|
||||
id: 'comment',
|
||||
name: '评论区',
|
||||
defaults: KeyCode.KeyP
|
||||
})
|
||||
.register({
|
||||
id: 'debug',
|
||||
name: '调试模式',
|
||||
defaults: KeyCode.F8
|
||||
})
|
||||
//#region 通用按键
|
||||
.group('general', '通用按键')
|
||||
.register({
|
||||
id: 'exit_1',
|
||||
name: '退出ui界面_1',
|
||||
defaults: KeyCode.KeyX
|
||||
})
|
||||
.register({
|
||||
id: 'exit_2',
|
||||
name: '退出ui界面_2',
|
||||
defaults: KeyCode.Escape
|
||||
})
|
||||
.register({
|
||||
id: 'confirm_1',
|
||||
name: '确认_1',
|
||||
defaults: KeyCode.Enter
|
||||
})
|
||||
.register({
|
||||
id: 'confirm_2',
|
||||
name: '确认_2',
|
||||
defaults: KeyCode.Space
|
||||
})
|
||||
.register({
|
||||
id: 'confirm_3',
|
||||
name: '确认_3',
|
||||
defaults: KeyCode.KeyC
|
||||
})
|
||||
//#region 开始界面
|
||||
.group('@ui_start', '开始界面')
|
||||
.register({
|
||||
id: '@start_up',
|
||||
name: '上移光标',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@start_down',
|
||||
name: '下移光标',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
//#region 怪物手册
|
||||
.group('@ui_book', '怪物手册')
|
||||
.register({
|
||||
id: '@book_up',
|
||||
name: '上移光标',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@book_down',
|
||||
name: '下移光标',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@book_pageDown_1',
|
||||
name: '下移5个怪物_1',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
.register({
|
||||
id: '@book_pageDown_2',
|
||||
name: '下移5个怪物_2',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@book_pageUp_1',
|
||||
name: '上移5个怪物_1',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@book_pageUp_2',
|
||||
name: '上移5个怪物_2',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
//#region 道具栏
|
||||
.group('@ui_toolbox', '道具栏')
|
||||
.register({
|
||||
id: '@toolbox_right',
|
||||
name: '光标右移',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
.register({
|
||||
id: '@toolbox_left',
|
||||
name: '光标左移',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@toolbox_up',
|
||||
name: '光标上移',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@toolbox_down',
|
||||
name: '光标下移',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
//#region 商店
|
||||
.group('@ui_shop', '商店')
|
||||
.register({
|
||||
id: '@shop_up',
|
||||
name: '上移光标',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@shop_down',
|
||||
name: '下移光标',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@shop_add',
|
||||
name: '增加购买量',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
.register({
|
||||
id: '@shop_min',
|
||||
name: '减少购买量',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
//#region 楼层传送
|
||||
.group('@ui_fly', '楼层传送')
|
||||
.register({
|
||||
id: '@fly_left',
|
||||
name: '左移地图',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_right',
|
||||
name: '右移地图',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_up',
|
||||
name: '上移地图',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_down',
|
||||
name: '下移地图',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_last',
|
||||
name: '上一张地图',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@fly_next',
|
||||
name: '下一张地图',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
//#region 传统楼传
|
||||
.group('@ui_fly_tradition', '楼层传送-传统按键')
|
||||
.register({
|
||||
id: '@fly_down_t',
|
||||
name: '上一张地图',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_up_t',
|
||||
name: '下一张地图',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_left_t_1',
|
||||
name: '前10张地图_1',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_left_t_2',
|
||||
name: '前10张地图_2',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@fly_right_t_1',
|
||||
name: '后10张地图_1',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
.register({
|
||||
id: '@fly_right_t_2',
|
||||
name: '后10张地图_2',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
// #region 存档界面
|
||||
.group('@ui_save', '存档界面')
|
||||
.register({
|
||||
id: '@save_pageUp',
|
||||
name: '向后翻页',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
.register({
|
||||
id: '@save_pageDown',
|
||||
name: '向前翻页',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@save_up',
|
||||
name: '选择框向上',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_down',
|
||||
name: '选择框向下',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_left',
|
||||
name: '选择框向左',
|
||||
defaults: KeyCode.LeftArrow
|
||||
})
|
||||
.register({
|
||||
id: '@save_right',
|
||||
name: '选择框向右',
|
||||
defaults: KeyCode.RightArrow
|
||||
})
|
||||
//#region 浏览地图
|
||||
.group('@ui_viewMap', '浏览地图')
|
||||
.register({
|
||||
id: '@viewMap_up_1',
|
||||
name: '下一层地图_1',
|
||||
defaults: KeyCode.UpArrow
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_up_2',
|
||||
name: '下一层地图_2',
|
||||
defaults: KeyCode.PageUp
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_1',
|
||||
name: '上一层地图_1',
|
||||
defaults: KeyCode.DownArrow
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_2',
|
||||
name: '上一层地图_2',
|
||||
defaults: KeyCode.PageDown
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_up_ten',
|
||||
name: '下十层地图',
|
||||
defaults: KeyCode.UpArrow,
|
||||
ctrl: true
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_down_ten',
|
||||
name: '上十层地图',
|
||||
defaults: KeyCode.DownArrow,
|
||||
ctrl: true
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_book',
|
||||
name: '怪物手册',
|
||||
defaults: KeyCode.KeyX
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_fly',
|
||||
name: '传送至',
|
||||
defaults: KeyCode.KeyG
|
||||
})
|
||||
.register({
|
||||
id: '@viewMap_reset',
|
||||
name: '重置视角',
|
||||
defaults: KeyCode.KeyR
|
||||
});
|
||||
// #endregion
|
||||
|
||||
gameKey.enable();
|
||||
gameKey.use(mainScope);
|
||||
|
||||
//#region 按键实现
|
||||
|
||||
gameKey
|
||||
.when(
|
||||
() =>
|
||||
!core.status.lockControl && !core.isMoving() && !core.isReplaying()
|
||||
)
|
||||
.realize('book', () => {
|
||||
core.openBook(true);
|
||||
})
|
||||
.realize('toolbox', () => {
|
||||
core.openToolbox(true);
|
||||
})
|
||||
.realize('equipbox', () => {
|
||||
core.openEquipbox(true);
|
||||
})
|
||||
.realize('fly', () => {
|
||||
core.useFly(true);
|
||||
})
|
||||
.realize('shop', () => {
|
||||
core.openQuickShop(true);
|
||||
})
|
||||
.realize('undo', () => {
|
||||
core.doSL('autoSave', 'load');
|
||||
})
|
||||
.realize('redo', () => {
|
||||
core.doSL('autoSave', 'reload');
|
||||
})
|
||||
.realize('turn', () => {
|
||||
core.turnHero();
|
||||
})
|
||||
.realize('getNext', () => {
|
||||
core.getNextItem();
|
||||
})
|
||||
.realize('restart', () => {
|
||||
core.confirmRestart();
|
||||
})
|
||||
.realize('comment', () => {
|
||||
core.actions._clickGameInfo_openComments();
|
||||
})
|
||||
.realize('debug', () => {
|
||||
core.debug();
|
||||
});
|
||||
|
||||
// ----- Storage
|
||||
const keyStorage = new GameStorage<Record<string, HotkeyJSON>>(
|
||||
GameStorage.fromAuthor('AncTe', 'gameKey')
|
||||
);
|
||||
keyStorage.data = {};
|
||||
keyStorage.read();
|
||||
gameKey.on('set', (id, key, assist) => {
|
||||
keyStorage.setValue(id, { key, assist });
|
||||
});
|
||||
gameKey.fromJSON(keyStorage.toJSON());
|
||||
@@ -1,2 +1 @@
|
||||
export * from './move';
|
||||
export * from './hotkey';
|
||||
@@ -301,6 +301,8 @@
|
||||
"208": "Duplicate hotkey command group name: $1, old one will be overwritten.",
|
||||
"209": "Cannot load key combinations for hotkey command '$1' since no command named it.",
|
||||
"210": "Cannot add duplicate hotkey command '$1' to group '$2'.",
|
||||
"211": "Expected a hotkey scope stored for a vue component, but no scope was found. This seems like a internal bug of engine, please report.",
|
||||
"212": "Duplicate implements for hotkey command '$1', old one will be overwritten. This probably caused by unclearing implementation config, please check.",
|
||||
"1001": "Event(setBlock): Unknown tile '$1' when setting block."
|
||||
}
|
||||
}
|
||||
@@ -141,9 +141,29 @@ export class HotkeySystem implements IHotkeySystem, IExcitable<number> {
|
||||
|
||||
//#region 作用域
|
||||
|
||||
enterScope(): symbol {
|
||||
/**
|
||||
* 获取下一个作用域的实现映射
|
||||
* @param clear 是否清空作用域实现
|
||||
*/
|
||||
private nextScopeImpl(
|
||||
clear: boolean
|
||||
): Map<IHotkeyCommand, (info: IHotkeyEmitInfo) => void> {
|
||||
const now = this.getScope();
|
||||
if (!now) return new Map();
|
||||
if (clear) {
|
||||
return new Map();
|
||||
} else {
|
||||
return new Map(now.implements);
|
||||
}
|
||||
}
|
||||
|
||||
enterScope(clearImpl: boolean = true): symbol {
|
||||
const symbol = Symbol();
|
||||
this.scopes.push({ symbol, condition: null, implements: new Map() });
|
||||
this.scopes.push({
|
||||
symbol,
|
||||
condition: null,
|
||||
implements: this.nextScopeImpl(clearImpl)
|
||||
});
|
||||
this.holdingCmds.clear();
|
||||
this.waitTimeout.clear();
|
||||
return symbol;
|
||||
@@ -191,6 +211,9 @@ export class HotkeySystem implements IHotkeySystem, IExcitable<number> {
|
||||
logger.warn(202, command);
|
||||
return this;
|
||||
}
|
||||
if (scope.implements.has(obj)) {
|
||||
logger.warn(212, command);
|
||||
}
|
||||
scope.implements.set(obj, func);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -159,8 +159,9 @@ export interface IHotkeySystem {
|
||||
|
||||
/**
|
||||
* 进入新的按键作用域
|
||||
* @param clearImpl 是否清空上一个作用域的按键实现,默认清空
|
||||
*/
|
||||
enterScope(): symbol;
|
||||
enterScope(clearImpl?: boolean): symbol;
|
||||
|
||||
/**
|
||||
* 离开按键作用域
|
||||
|
||||
@@ -10,7 +10,7 @@ export function initializeHotkey(state: IClientCore) {
|
||||
//#region 通用按键
|
||||
|
||||
hotkey.setGroup('common', '通用按键', [
|
||||
system.addCommand('@common/ok', '确认', {
|
||||
system.addCommand('@common/confirm', '确认', {
|
||||
defaults: [[KeyCode.Enter], [KeyCode.Space], [KeyCode.KeyC]],
|
||||
priority: 0
|
||||
}),
|
||||
@@ -25,6 +25,14 @@ export function initializeHotkey(state: IClientCore) {
|
||||
system.addCommand('@common/select-down', '下移选择光标', {
|
||||
defaults: [[KeyCode.DownArrow]],
|
||||
priority: 0
|
||||
}),
|
||||
system.addCommand('@common/select-left', '左移选择光标', {
|
||||
defaults: [[KeyCode.LeftArrow]],
|
||||
priority: 0
|
||||
}),
|
||||
system.addCommand('@common/select-right', '右移选择光标', {
|
||||
defaults: [[KeyCode.RightArrow]],
|
||||
priority: 0
|
||||
})
|
||||
]);
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { ElementLocator, Font } from '@motajs/render';
|
||||
import { computed, defineComponent, reactive, ref } from 'vue';
|
||||
import { Background, Selection } from './misc';
|
||||
import { TextContent, TextContentProps } from './textbox';
|
||||
import { TextAlign } from './textboxTyper';
|
||||
import { Page, PageExpose } from './page';
|
||||
import { Background, Selection } from '@user/client-base';
|
||||
import {
|
||||
TextContent,
|
||||
TextContentProps,
|
||||
TextAlign,
|
||||
Page,
|
||||
PageExpose
|
||||
} from '@user/client-base';
|
||||
import { GameUI, IUIController, SetupComponentOptions } from '@motajs/system';
|
||||
// @ts-expect-error render/use.ts 按 D-54 留在实现层,本文件已移入系统层,按 D-68 暂以标注记录,不反向引用、不解耦
|
||||
import { useKey } from '../use';
|
||||
import { sleep } from 'mutate-animate';
|
||||
import { DefaultProps } from '@motajs/render-vue';
|
||||
import { IGameUIPropsBase } from '../types';
|
||||
import { IGameUIPropsBase, useKey } from '@user/client-base';
|
||||
|
||||
export interface ConfirmBoxProps extends DefaultProps, TextContentProps {
|
||||
export interface ConfirmBoxProps extends IGameUIPropsBase, TextContentProps {
|
||||
/** 确认框的提示文本内容 */
|
||||
text: string;
|
||||
/** 确认框对话框的宽度 */
|
||||
@@ -36,8 +37,8 @@ export interface ConfirmBoxProps extends DefaultProps, TextContentProps {
|
||||
color?: CanvasStyle;
|
||||
/** 对话框边框颜色,当未设置 winskin 时生效 */
|
||||
border?: CanvasStyle;
|
||||
/** 按键作用域,如果需要同作用域按键,那么需要传入 */
|
||||
scope?: symbol;
|
||||
/** 是否使用全新的按键作用域,此时选择框的按键作用域不会包含原本的按键指令实现,默认会使用全新作用域 */
|
||||
freshScope?: boolean;
|
||||
}
|
||||
|
||||
export type ConfirmBoxEmits = {
|
||||
@@ -59,7 +60,7 @@ const confirmBoxProps = {
|
||||
'defaultYes',
|
||||
'color',
|
||||
'border',
|
||||
'scope'
|
||||
'freshScope'
|
||||
],
|
||||
emits: ['no', 'yes']
|
||||
} satisfies SetupComponentOptions<
|
||||
@@ -149,13 +150,13 @@ export const ConfirmBox = defineComponent<
|
||||
noSize.value = [width, height];
|
||||
};
|
||||
|
||||
const [key] = useKey(false, props.scope);
|
||||
key.realize('confirm', () => {
|
||||
const key = useKey(props.state.hotkey.system, props.freshScope ?? true)!;
|
||||
key.implement('@common/confirm', () => {
|
||||
if (selected.value) emit('yes');
|
||||
else emit('no');
|
||||
});
|
||||
key.realize('moveLeft', () => void (selected.value = true));
|
||||
key.realize('moveRight', () => void (selected.value = false));
|
||||
key.implement('@common/select-left', () => void (selected.value = true));
|
||||
key.implement('@common/select-right', () => void (selected.value = false));
|
||||
|
||||
return () => (
|
||||
<container loc={loc.value}>
|
||||
@@ -215,7 +216,7 @@ export type ChoiceItem<T extends ChoiceKey = ChoiceKey> = [
|
||||
text: string
|
||||
];
|
||||
|
||||
export interface ChoicesProps extends DefaultProps, TextContentProps {
|
||||
export interface ChoicesProps extends IGameUIPropsBase, TextContentProps {
|
||||
/** 选项数组 */
|
||||
choices: ChoiceItem[];
|
||||
/** 选择框对话框的位置 */
|
||||
@@ -248,8 +249,8 @@ export interface ChoicesProps extends DefaultProps, TextContentProps {
|
||||
interval?: number;
|
||||
/** 默认选中的选项索引 */
|
||||
selected?: number;
|
||||
/** 按键作用域,如果需要同作用域按键,那么需要传入,例如系统设置 UI */
|
||||
scope?: symbol;
|
||||
/** 是否使用全新的按键作用域,此时选择框的按键作用域不会包含原本的按键指令实现,默认会使用全新作用域 */
|
||||
freshScope?: boolean;
|
||||
}
|
||||
|
||||
export type ChoicesEmits = {
|
||||
@@ -274,7 +275,7 @@ const choicesProps = {
|
||||
'pad',
|
||||
'interval',
|
||||
'selected',
|
||||
'scope'
|
||||
'freshScope'
|
||||
],
|
||||
emits: ['choose']
|
||||
} satisfies SetupComponentOptions<
|
||||
@@ -473,8 +474,8 @@ export const Choices = defineComponent<
|
||||
selected.value = 0;
|
||||
};
|
||||
|
||||
const [key] = useKey(false, props.scope);
|
||||
key.realize('moveUp', () => {
|
||||
const key = useKey(props.state.hotkey.system, props.freshScope)!;
|
||||
key.implement('moveUp', () => {
|
||||
if (selected.value === 0) {
|
||||
if (pageCom.value?.now() !== 0) {
|
||||
pageCom.value?.movePage(-1);
|
||||
@@ -484,7 +485,7 @@ export const Choices = defineComponent<
|
||||
selected.value--;
|
||||
}
|
||||
});
|
||||
key.realize('moveDown', () => {
|
||||
key.implement('moveDown', () => {
|
||||
const page = pageCom.value?.now() ?? 0;
|
||||
if (selected.value === choiceCountPerPage.value - 1) {
|
||||
if (page < pages.value - 1) {
|
||||
@@ -498,9 +499,9 @@ export const Choices = defineComponent<
|
||||
}
|
||||
}
|
||||
});
|
||||
key.realize('moveLeft', () => pageCom.value?.movePage(-1));
|
||||
key.realize('moveRight', () => pageCom.value?.movePage(1));
|
||||
key.realize('confirm', () => {
|
||||
key.implement('moveLeft', () => pageCom.value?.movePage(-1));
|
||||
key.implement('moveRight', () => pageCom.value?.movePage(1));
|
||||
key.implement('confirm', () => {
|
||||
const page = pageCom.value?.now() ?? 0;
|
||||
const index = page * choiceCountPerPage.value + selected.value;
|
||||
emit('choose', props.choices[index][0]);
|
||||
Reference in new issue
Block a user