mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 20:59:37 +08:00
refactor: 按键系统
This commit is contained in:
parent
d8c98ad7d5
commit
49e09384fa
@ -4,336 +4,342 @@ import { deleteWith, generateBinary, has, tip } from '@/plugin/utils';
|
|||||||
import { EmitableEvent, EventEmitter } from '../../common/eventEmitter';
|
import { EmitableEvent, EventEmitter } from '../../common/eventEmitter';
|
||||||
import { GameStorage } from '../storage';
|
import { GameStorage } from '../storage';
|
||||||
|
|
||||||
interface HotkeyEvent extends EmitableEvent {
|
interface HotkeyEvent extends EmitableEvent {}
|
||||||
emit: (key: KeyCode, e: KeyboardEvent, ...params: any[]) => void;
|
|
||||||
keyChange: (data: HotkeyData, before: KeyCode, after: KeyCode) => void;
|
interface AssistHoykey {
|
||||||
|
ctrl: boolean;
|
||||||
|
shift: boolean;
|
||||||
|
alt: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HotkeyData {
|
interface RegisterHotkeyData extends Partial<AssistHoykey> {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
defaults: KeyCode;
|
defaults: KeyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HotkeyData extends Required<RegisterHotkeyData> {
|
||||||
key: KeyCode;
|
key: KeyCode;
|
||||||
ctrl?: boolean;
|
func: Map<symbol, HotkeyFunc>;
|
||||||
alt?: boolean;
|
|
||||||
shift?: boolean;
|
|
||||||
group?: string;
|
|
||||||
func: (code: KeyCode, e: KeyboardEvent) => any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GroupInfo {
|
type HotkeyFunc = (code: KeyCode, ev: KeyboardEvent) => void;
|
||||||
name: string;
|
|
||||||
includes: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegisterData = Omit<HotkeyData, 'id' | 'key' | 'name'>;
|
|
||||||
|
|
||||||
export class Hotkey extends EventEmitter<HotkeyEvent> {
|
export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||||
|
static list: Hotkey[];
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
data: Record<string, HotkeyData> = {};
|
||||||
keyMap: Map<KeyCode, HotkeyData[]> = new Map();
|
keyMap: Map<KeyCode, HotkeyData[]> = new Map();
|
||||||
list: Record<string, HotkeyData> = {};
|
|
||||||
storage?: GameStorage<Record<string, KeyCode>>;
|
|
||||||
groups: Record<string, GroupInfo> = {};
|
|
||||||
|
|
||||||
constructor(id: string, storage: boolean = true) {
|
private scope: symbol = Symbol();
|
||||||
|
|
||||||
|
constructor(id: string, name: string) {
|
||||||
super();
|
super();
|
||||||
if (storage) {
|
this.id = id;
|
||||||
this.storage = new GameStorage(GameStorage.fromAuthor('AncTe', id));
|
this.name = name;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个按键操作
|
* 注册一个按键
|
||||||
* @param data 按键信息
|
* @param data 要注册的按键信息
|
||||||
*/
|
*/
|
||||||
register(id: string, name: string, data: RegisterData) {
|
register(data: RegisterHotkeyData) {
|
||||||
const key = {
|
const d: HotkeyData = {
|
||||||
id,
|
...data,
|
||||||
name,
|
ctrl: !!data.ctrl,
|
||||||
key: this.storage?.getValue(id, data.defaults) ?? data.defaults,
|
shift: !!data.shift,
|
||||||
...data
|
alt: !!data.alt,
|
||||||
|
key: data.defaults,
|
||||||
|
func: new Map()
|
||||||
};
|
};
|
||||||
this.ensureKey(key.key).push(key);
|
this.ensureMap(d.key);
|
||||||
this.list[id] = key;
|
this.data[d.id] = d;
|
||||||
return this;
|
const arr = this.keyMap.get(d.key)!;
|
||||||
|
arr.push(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置一个操作的按键
|
* 实现一个按键按下时的操作
|
||||||
* @param data 要设置的操作
|
* @param id 要实现的按键id
|
||||||
* @param key 按键
|
* @param func 按键按下时执行的函数
|
||||||
*/
|
*/
|
||||||
setKey(data: string | HotkeyData, key: KeyCode): void {
|
realize(id: string, func: HotkeyFunc) {
|
||||||
if (typeof data === 'string') {
|
const key = this.data[id];
|
||||||
data = this.list[data];
|
if (!key.func.has(this.scope)) {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot access using scope. Call use before calling realize.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const map = this.keyMap.get(data.key)!;
|
key.func.set(this.scope, func);
|
||||||
deleteWith(map, data);
|
}
|
||||||
this.ensureKey(key).push(data);
|
|
||||||
const before = data.key;
|
/**
|
||||||
|
* 使用一个symbol作为当前作用域,之后调用{@link realize}所实现的按键功能将会添加至此作用域
|
||||||
|
* @param symbol 当前作用域的symbol
|
||||||
|
*/
|
||||||
|
use(symbol: symbol) {
|
||||||
|
this.scope = symbol;
|
||||||
|
for (const key of Object.values(this.data)) {
|
||||||
|
key.func.set(symbol, () => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放一个作用域,释放后不能调用{@link realize}函数,除非重新调用{@link use}函数
|
||||||
|
* @param symbol 要释放的作用域的symbol
|
||||||
|
*/
|
||||||
|
dispose(symbol: symbol) {
|
||||||
|
for (const key of Object.values(this.data)) {
|
||||||
|
key.func.delete(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置一个按键信息
|
||||||
|
* @param id 要设置的按键的id
|
||||||
|
* @param key 要设置成的按键
|
||||||
|
* @param assist 辅助按键,三位二进制数据,从低到高依次为`ctrl` `shift` `alt`
|
||||||
|
*/
|
||||||
|
set(id: string, key: KeyCode, assist: number) {
|
||||||
|
const { ctrl, shift, alt } = this.unwarpBinary(assist);
|
||||||
|
const data = this.data[id];
|
||||||
|
const before = this.keyMap.get(data.key)!;
|
||||||
|
deleteWith(before, data);
|
||||||
|
this.ensureMap(key);
|
||||||
|
const after = this.keyMap.get(key)!;
|
||||||
|
after.push(data);
|
||||||
data.key = key;
|
data.key = key;
|
||||||
this.emit('keyChange', data, before, key);
|
data.ctrl = ctrl;
|
||||||
|
data.shift = shift;
|
||||||
|
data.alt = alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取一个按键可以触发的所有按键操作
|
* 触发一个按键
|
||||||
* @param key 要获取的按键
|
* @param key 要触发的按键
|
||||||
|
* @param assist 辅助按键,三位二进制数据,从低到高依次为`ctrl` `shift` `alt`
|
||||||
*/
|
*/
|
||||||
getData(key: KeyCode): HotkeyData[] {
|
emitKey(key: KeyCode, assist: number, ev: KeyboardEvent) {
|
||||||
return this.keyMap.get(key) ?? [];
|
const toEmit = this.keyMap.get(key);
|
||||||
}
|
if (!toEmit) return;
|
||||||
|
const { ctrl, shift, alt } = this.unwarpBinary(assist);
|
||||||
/**
|
toEmit.forEach(v => {
|
||||||
* 执行一个按键操作
|
if (ctrl === v.ctrl && shift === v.shift && alt === v.alt) {
|
||||||
* @param key 按下的按键
|
const func = v.func.get(this.scope);
|
||||||
*/
|
if (!func) {
|
||||||
emitKey(key: KeyCode, e: KeyboardEvent, ...params: any[]): any[] {
|
throw new Error(`Emit unknown scope keys.`);
|
||||||
this.emit('emit', key, e, ...params);
|
}
|
||||||
return this.getData(key).map(v => {
|
func(key, ev);
|
||||||
const assist = generateBinary([e.ctrlKey, e.altKey, e.shiftKey]);
|
|
||||||
const need = generateBinary([!!v.ctrl, !!v.alt, !!v.shift]);
|
|
||||||
if (assist & need) {
|
|
||||||
v.func(key, e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private unwarpBinary(bin: number): AssistHoykey {
|
||||||
* 按键分组
|
return {
|
||||||
* @param id 组id
|
ctrl: !!(bin & (1 << 0)),
|
||||||
* @param name 组名称
|
shift: !!(bin & (1 << 1)),
|
||||||
* @param ids 组包含的内容
|
alt: !!(bin & (1 << 2))
|
||||||
*/
|
|
||||||
group(id: string, name: string, ids: string[]) {
|
|
||||||
this.groups[id] = {
|
|
||||||
name,
|
|
||||||
includes: ids
|
|
||||||
};
|
};
|
||||||
ids.forEach(v => {
|
|
||||||
const data = this.list[v];
|
|
||||||
if (has(data.group)) {
|
|
||||||
deleteWith(this.groups[data.group].includes, v);
|
|
||||||
}
|
|
||||||
data.group = id;
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ensureMap(key: KeyCode) {
|
||||||
* 将剩余的按键组成一个组合
|
|
||||||
* @param id 组合id
|
|
||||||
* @param name 组合的名称
|
|
||||||
*/
|
|
||||||
groupRest(id: string, name: string) {
|
|
||||||
const rest = Object.values(this.list)
|
|
||||||
.filter(v => !has(v.group))
|
|
||||||
.map(v => v.id);
|
|
||||||
|
|
||||||
this.group(id, name, rest);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从一个按键控制器继承按键信息
|
|
||||||
* @param hotkey 被继承的按键
|
|
||||||
* @param cover 继承时是否覆盖同id的按键
|
|
||||||
*/
|
|
||||||
extend(hotkey: Hotkey, cover: boolean = false) {
|
|
||||||
Object.values(hotkey.list).forEach(v => {
|
|
||||||
if (v.id in this.list && !cover) return;
|
|
||||||
this.register(v.id, v.name, v);
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ensureKey(key: KeyCode) {
|
|
||||||
if (!this.keyMap.has(key)) {
|
if (!this.keyMap.has(key)) {
|
||||||
this.keyMap.set(key, []);
|
this.keyMap.set(key, []);
|
||||||
}
|
}
|
||||||
return this.keyMap.get(key)!;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id获取hotkey实例
|
||||||
|
* @param id 要获取的hotkey实例的id
|
||||||
|
*/
|
||||||
|
static get(id: string) {
|
||||||
|
return this.list.find(v => v.id === id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hotkey = new Hotkey('gameKey');
|
// export const hotkey = new Hotkey('gameKey');
|
||||||
|
|
||||||
hotkey
|
// hotkey
|
||||||
.register('book', '怪物手册', {
|
// .register('book', '怪物手册', {
|
||||||
defaults: KeyCode.KeyX,
|
// defaults: KeyCode.KeyX,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.openBook(true);
|
// core.openBook(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('save', '存档界面', {
|
// .register('save', '存档界面', {
|
||||||
defaults: KeyCode.KeyS,
|
// defaults: KeyCode.KeyS,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.save(true);
|
// core.save(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('load', '读档界面', {
|
// .register('load', '读档界面', {
|
||||||
defaults: KeyCode.KeyD,
|
// defaults: KeyCode.KeyD,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.load(true);
|
// core.load(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('undo', '回退', {
|
// .register('undo', '回退', {
|
||||||
defaults: KeyCode.KeyA,
|
// defaults: KeyCode.KeyA,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.doSL('autoSave', 'load');
|
// core.doSL('autoSave', 'load');
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('redo', '恢复', {
|
// .register('redo', '恢复', {
|
||||||
defaults: KeyCode.KeyW,
|
// defaults: KeyCode.KeyW,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.doSL('autoSave', 'reload');
|
// core.doSL('autoSave', 'reload');
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('toolbox', '道具栏', {
|
// .register('toolbox', '道具栏', {
|
||||||
defaults: KeyCode.KeyT,
|
// defaults: KeyCode.KeyT,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.openToolbox(true);
|
// core.openToolbox(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('equipbox', '装备栏', {
|
// .register('equipbox', '装备栏', {
|
||||||
defaults: KeyCode.KeyQ,
|
// defaults: KeyCode.KeyQ,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.openEquipbox(true);
|
// core.openEquipbox(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('fly', '楼层传送', {
|
// .register('fly', '楼层传送', {
|
||||||
defaults: KeyCode.KeyG,
|
// defaults: KeyCode.KeyG,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.useFly(true);
|
// core.useFly(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('turn', '勇士转向', {
|
// .register('turn', '勇士转向', {
|
||||||
defaults: KeyCode.KeyZ,
|
// defaults: KeyCode.KeyZ,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.turnHero();
|
// core.turnHero();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('getNext', '轻按', {
|
// .register('getNext', '轻按', {
|
||||||
defaults: KeyCode.Space,
|
// defaults: KeyCode.Space,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.getNextItem();
|
// core.getNextItem();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('menu', '菜单', {
|
// .register('menu', '菜单', {
|
||||||
defaults: KeyCode.Escape,
|
// defaults: KeyCode.Escape,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.openSettings(true);
|
// core.openSettings(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('replay', '录像回放', {
|
// .register('replay', '录像回放', {
|
||||||
defaults: KeyCode.KeyR,
|
// defaults: KeyCode.KeyR,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.ui._drawReplay();
|
// core.ui._drawReplay();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('restart', '开始菜单', {
|
// .register('restart', '开始菜单', {
|
||||||
defaults: KeyCode.KeyN,
|
// defaults: KeyCode.KeyN,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.confirmRestart();
|
// core.confirmRestart();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('shop', '快捷商店', {
|
// .register('shop', '快捷商店', {
|
||||||
defaults: KeyCode.KeyV,
|
// defaults: KeyCode.KeyV,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.openQuickShop(true);
|
// core.openQuickShop(true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('statistics', '数据统计', {
|
// .register('statistics', '数据统计', {
|
||||||
defaults: KeyCode.KeyB,
|
// defaults: KeyCode.KeyB,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.ui._drawStatistics();
|
// core.ui._drawStatistics();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('viewMap1', '浏览地图', {
|
// .register('viewMap1', '浏览地图', {
|
||||||
defaults: KeyCode.PageUp,
|
// defaults: KeyCode.PageUp,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.ui._drawViewMaps();
|
// core.ui._drawViewMaps();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('viewMap2', '浏览地图', {
|
// .register('viewMap2', '浏览地图', {
|
||||||
defaults: KeyCode.PageDown,
|
// defaults: KeyCode.PageDown,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.ui._drawViewMaps();
|
// core.ui._drawViewMaps();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('comment', '评论区', {
|
// .register('comment', '评论区', {
|
||||||
defaults: KeyCode.KeyP,
|
// defaults: KeyCode.KeyP,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.actions._clickGameInfo_openComments();
|
// core.actions._clickGameInfo_openComments();
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('mark', '标记怪物', {
|
// .register('mark', '标记怪物', {
|
||||||
defaults: KeyCode.KeyM,
|
// defaults: KeyCode.KeyM,
|
||||||
func: () => {
|
// func: () => {
|
||||||
// todo: refactor
|
// // todo: refactor
|
||||||
const [x, y] = flags.mouseLoc ?? [];
|
// const [x, y] = flags.mouseLoc ?? [];
|
||||||
const [mx, my] = getLocFromMouseLoc(x, y);
|
// const [mx, my] = getLocFromMouseLoc(x, y);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('skillTree', '技能树', {
|
// .register('skillTree', '技能树', {
|
||||||
defaults: KeyCode.KeyJ,
|
// defaults: KeyCode.KeyJ,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.useItem('skill1', true);
|
// core.useItem('skill1', true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('desc', '百科全书', {
|
// .register('desc', '百科全书', {
|
||||||
defaults: KeyCode.KeyH,
|
// defaults: KeyCode.KeyH,
|
||||||
func: () => {
|
// func: () => {
|
||||||
core.useItem('I560', true);
|
// core.useItem('I560', true);
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('special', '鼠标位置怪物属性', {
|
// .register('special', '鼠标位置怪物属性', {
|
||||||
defaults: KeyCode.KeyE,
|
// defaults: KeyCode.KeyE,
|
||||||
func: () => {
|
// func: () => {
|
||||||
const [x, y] = flags.mouseLoc ?? [];
|
// const [x, y] = flags.mouseLoc ?? [];
|
||||||
const [mx, my] = getLocFromMouseLoc(x, y);
|
// const [mx, my] = getLocFromMouseLoc(x, y);
|
||||||
if (core.getBlockCls(mx, my)?.startsWith('enemy')) {
|
// if (core.getBlockCls(mx, my)?.startsWith('enemy')) {
|
||||||
// mota.plugin.fixed.showFixed.value = false;
|
// // mota.plugin.fixed.showFixed.value = false;
|
||||||
mota.ui.main.open('fixedDetail', {
|
// mota.ui.main.open('fixedDetail', {
|
||||||
panel: 'special'
|
// panel: 'special'
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.register('critical', '鼠标位置怪物临界', {
|
// .register('critical', '鼠标位置怪物临界', {
|
||||||
defaults: KeyCode.KeyC,
|
// defaults: KeyCode.KeyC,
|
||||||
func: () => {
|
// func: () => {
|
||||||
const [x, y] = flags.mouseLoc ?? [];
|
// const [x, y] = flags.mouseLoc ?? [];
|
||||||
const [mx, my] = getLocFromMouseLoc(x, y);
|
// const [mx, my] = getLocFromMouseLoc(x, y);
|
||||||
if (core.getBlockCls(mx, my)?.startsWith('enemy')) {
|
// if (core.getBlockCls(mx, my)?.startsWith('enemy')) {
|
||||||
// mota.plugin.fixed.showFixed.value = false;
|
// // mota.plugin.fixed.showFixed.value = false;
|
||||||
mota.ui.main.open('fixedDetail', {
|
// mota.ui.main.open('fixedDetail', {
|
||||||
panel: 'critical'
|
// panel: 'critical'
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.group('action', '游戏操作', [
|
// .group('action', '游戏操作', [
|
||||||
'save',
|
// 'save',
|
||||||
'load',
|
// 'load',
|
||||||
'undo',
|
// 'undo',
|
||||||
'redo',
|
// 'redo',
|
||||||
'turn',
|
// 'turn',
|
||||||
'getNext',
|
// 'getNext',
|
||||||
'mark'
|
// 'mark'
|
||||||
])
|
// ])
|
||||||
.group('view', '快捷查看', [
|
// .group('view', '快捷查看', [
|
||||||
'book',
|
// 'book',
|
||||||
'toolbox',
|
// 'toolbox',
|
||||||
'equipbox',
|
// 'equipbox',
|
||||||
'fly',
|
// 'fly',
|
||||||
'menu',
|
// 'menu',
|
||||||
'replay',
|
// 'replay',
|
||||||
'shop',
|
// 'shop',
|
||||||
'statistics',
|
// 'statistics',
|
||||||
'viewMap1',
|
// 'viewMap1',
|
||||||
'viewMap2',
|
// 'viewMap2',
|
||||||
'skillTree',
|
// 'skillTree',
|
||||||
'desc',
|
// 'desc',
|
||||||
'special',
|
// 'special',
|
||||||
'critical'
|
// 'critical'
|
||||||
])
|
// ])
|
||||||
.group('system', '系统按键', ['comment'])
|
// .group('system', '系统按键', ['comment'])
|
||||||
.groupRest('unClassed', '未分类按键');
|
// .groupRest('unClassed', '未分类按键');
|
||||||
|
@ -2,6 +2,7 @@ import { Component, shallowReactive } from 'vue';
|
|||||||
import { EmitableEvent, EventEmitter } from '../../common/eventEmitter';
|
import { EmitableEvent, EventEmitter } from '../../common/eventEmitter';
|
||||||
import { KeyCode } from '@/plugin/keyCodes';
|
import { KeyCode } from '@/plugin/keyCodes';
|
||||||
import { Hotkey } from './hotkey';
|
import { Hotkey } from './hotkey';
|
||||||
|
import { generateBinary } from '@/plugin/utils';
|
||||||
|
|
||||||
interface FocusEvent<T> extends EmitableEvent {
|
interface FocusEvent<T> extends EmitableEvent {
|
||||||
focus: (before: T | null, after: T) => void;
|
focus: (before: T | null, after: T) => void;
|
||||||
@ -136,6 +137,7 @@ export class GameUi extends EventEmitter<GameUiEvent> {
|
|||||||
component: Component;
|
component: Component;
|
||||||
hotkey?: Hotkey;
|
hotkey?: Hotkey;
|
||||||
id: string;
|
id: string;
|
||||||
|
symbol: symbol = Symbol();
|
||||||
|
|
||||||
constructor(id: string, component: Component, hotkey?: Hotkey) {
|
constructor(id: string, component: Component, hotkey?: Hotkey) {
|
||||||
super();
|
super();
|
||||||
@ -206,15 +208,6 @@ export class UiController extends Focus<IndexedGameUi> {
|
|||||||
this.show = 'all';
|
this.show = 'all';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行按键操作
|
|
||||||
* @param key 按键的KeyCode
|
|
||||||
* @param e 按键操作事件
|
|
||||||
*/
|
|
||||||
emitKey(key: KeyCode, e: KeyboardEvent) {
|
|
||||||
this.focused?.ui.hotkey?.emitKey(key, e, this.focused);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据id获取到ui
|
* 根据id获取到ui
|
||||||
* @param id ui的id
|
* @param id ui的id
|
||||||
@ -274,7 +267,10 @@ export class UiController extends Focus<IndexedGameUi> {
|
|||||||
*/
|
*/
|
||||||
open(id: string, vBind?: UiVBind, vOn?: UiVOn) {
|
open(id: string, vBind?: UiVBind, vOn?: UiVOn) {
|
||||||
const ui = this.get(id);
|
const ui = this.get(id);
|
||||||
if (!ui) return -1;
|
if (!ui) {
|
||||||
|
console.warn(`Unknown UI: '${id}'.`);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
const num = this.num++;
|
const num = this.num++;
|
||||||
const bind = {
|
const bind = {
|
||||||
num,
|
num,
|
||||||
|
Loading…
Reference in New Issue
Block a user