feat: 自定义按键

This commit is contained in:
unanmed 2023-11-19 23:37:37 +08:00
parent 1e58dbe411
commit 770e38202c
8 changed files with 258 additions and 22 deletions

View File

@ -59,22 +59,22 @@ function resize() {
if (has(props.right)) right.style.flexBasis = `${props.right}%`;
}
function key(e: KeyboardEvent) {
const c = keycode(e.keyCode);
if (c === KeyCode.Escape || c === KeyCode.KeyX) emits('close');
}
// function key(e: KeyboardEvent) {
// const c = keycode(e.keyCode);
// if (c === KeyCode.Escape || c === KeyCode.KeyX) emits('close');
// }
onMounted(async () => {
resize();
await sleep(50);
// if (mota.plugin.ui.transition.value) await sleep(600);
document.addEventListener('keyup', key);
// document.addEventListener('keyup', key);
});
onUpdated(resize);
onUnmounted(() => {
document.removeEventListener('keyup', key);
// document.removeEventListener('keyup', key);
});
</script>

View File

@ -15,7 +15,10 @@ gameKey
.register({
id: 'book',
name: '怪物手册',
defaults: KeyCode.KeyX
defaults: KeyCode.KeyX,
ctrl: true,
shift: true,
alt: true
})
.register({
id: 'save',

View File

@ -1,6 +1,7 @@
import type { SettingComponent, SettingComponentProps } from '../setting';
import { Button, InputNumber } from 'ant-design-vue';
import { mainUi } from './ui';
import { gameKey } from './hotkey';
interface Components {
DefaultSetting: SettingComponent;
@ -70,13 +71,13 @@ function NumberSetting(props: SettingComponentProps) {
);
}
function showSpecialSetting(id: string) {
function showSpecialSetting(id: string, vBind?: any) {
const ui = mainUi.get(id);
mainUi.showEnd();
ui.once('close', () => {
mainUi.showAll();
});
mainUi.open(id);
mainUi.open(id, vBind);
}
function HotkeySetting(props: SettingComponentProps) {
@ -86,7 +87,11 @@ function HotkeySetting(props: SettingComponentProps) {
<Button
type="primary"
size="large"
onClick={() => showSpecialSetting('hotkey')}
onClick={() =>
showSpecialSetting('hotkey', {
hotkey: gameKey
})
}
>
</Button>

View File

@ -15,7 +15,8 @@ mainUi.register(
new GameUi('fixedDetail', UI.FixedDetail),
new GameUi('shop', UI.Shop),
new GameUi('achievement', UI.Achievement),
new GameUi('bgm', UI.BgmList)
new GameUi('bgm', UI.BgmList),
new GameUi('hotkey', UI.Hotkey)
// todo: 把游戏主 div 加入到 mainUi 里面
);
mainUi.showAll();

View File

@ -389,7 +389,7 @@ mainSetting
new MotaSetting()
.register('autoSkill', '自动切换技能', true, COM.BooleanSetting)
.register('fixed', '定点查看', true, COM.BooleanSetting)
.register('hotkey', '快捷键', false, COM.BooleanSetting)
.register('hotkey', '快捷键', false, COM.HotkeySetting)
.setDisplayFunc('hotkey', () => '')
.register('toolbar', '自定义工具栏', false, COM.BooleanSetting)
.setDisplayFunc('toolbar', () => '')

229
src/ui/hotkey.vue Normal file
View File

@ -0,0 +1,229 @@
<template>
<Column @close="close" :left="30">
<template #left>
<div id="hotkey-group">
<span
class="hotkey-group-one selectable"
v-for="(name, group) of groupName"
:selected="selectedGroup === group"
@click="selectedGroup = group"
>
{{ name }}
</span>
</div>
</template>
<template #right>
<div id="hotkey-data">
<div class="hotkey-one" v-for="(data, id) of show">
<span class="hotkey-one-name"> {{ data.name }} </span>
<div class="hotkey-one-set">
<span
v-for="key of data.keys"
class="hotkey-one-set-item"
:selected="
data.id === selectedKey.id &&
key.index === selectedKey.index
"
@click="select(data.id, key.index)"
>
{{ getKeyShow(key.key, key.assist) }}
</span>
</div>
</div>
</div>
</template>
</Column>
</template>
<script lang="ts" setup>
import { Hotkey } from '@/core/main/custom/hotkey';
import { GameUi } from '@/core/main/custom/ui';
import Column from '@/components/colomn.vue';
import { mainUi } from '@/core/main/init/ui';
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue';
import { KeyCode, KeyCodeUtils } from '@/plugin/keyCodes';
import { generateBinary, keycode } from '@/plugin/utils';
import { cloneDeep } from 'lodash-es';
import { gameKey } from '@/core/main/init/hotkey';
interface HotkeyKeys {
index: number;
key: KeyCode;
/** 从低到高依次为 `ctrl` `shift` `alt` */
assist: number;
}
interface HotkeySetting {
id: string;
name: string;
keys: HotkeyKeys[];
}
interface SelectedKey {
id: string;
index: number;
}
const props = defineProps<{
num: number;
ui: GameUi;
hotkey: Hotkey;
}>();
const hotkey = props.hotkey;
function close() {
mainUi.close(props.num);
}
const selectedGroup = ref('ui');
const keyData = generateData();
const show = computed(() => {
return keyData[selectedGroup.value];
});
const groupName = cloneDeep(hotkey.groupName);
delete groupName.none;
const selectedKey: SelectedKey = reactive({
id: 'none',
index: -1
});
function generateData() {
const res: Record<string, Record<string, HotkeySetting>> = {};
for (const [group, data] of Object.entries(hotkey.groups)) {
if (group === 'none') continue;
res[group] = {};
const d = res[group];
data.forEach(v => {
const split = v.split('_');
const isMulti = /^\d+$/.test(split.at(-1)!);
const id = isMulti ? split.slice(0, -1).join('_') : v;
const index = isMulti ? parseInt(split.at(-1)!) : -1;
const key = hotkey.data[v];
d[id] ??= {
id,
name: isMulti
? key.name.split('_').slice(0, -1).join('_')
: key.name,
keys: reactive([])
};
d[id].keys.push({
index,
key: key.key,
assist: generateBinary([key.ctrl, key.shift, key.alt])
});
});
}
return res;
}
function unwarpAssist(assist: number) {
let res = '';
if (assist & (1 << 0)) {
res += 'Ctrl + ';
}
if (assist & (1 << 1)) {
res += 'Shift + ';
}
if (assist & (1 << 2)) {
res += 'Alt + ';
}
return res;
}
function getKeyShow(key: KeyCode, assist: number) {
return unwarpAssist(assist) + KeyCodeUtils.toString(key);
}
function select(id: string, index: number) {
selectedKey.id = id;
selectedKey.index = index;
}
function keyup(e: KeyboardEvent) {
if (selectedKey.id === 'none') return;
const code = keycode(e.keyCode);
if (
code === KeyCode.Ctrl ||
code === KeyCode.Shift ||
code === KeyCode.Alt
) {
return;
}
const assist = generateBinary([e.ctrlKey, e.shiftKey, e.altKey]);
const id =
selectedKey.index === -1
? selectedKey.id
: `${selectedKey.id}_${selectedKey.index}`;
hotkey.set(id, code, assist);
const key = keyData[selectedGroup.value][selectedKey.id].keys.find(
v => v.index === selectedKey.index
);
if (key) {
key.key = code;
key.assist = assist;
}
selectedKey.id = 'none';
selectedKey.index = -1;
}
// ban other keys
gameKey.disable();
console.log(gameKey.enabled);
onMounted(() => {
document.addEventListener('keyup', keyup);
});
onUnmounted(() => {
gameKey.enable();
document.removeEventListener('keyup', keyup);
});
</script>
<style lang="less" scoped>
#hotkey-group {
display: flex;
flex-direction: column;
}
.hotkey-group-one {
margin: 2px 0;
}
.hotkey-one {
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 2% 3%;
white-space: nowrap;
}
.hotkey-one-set {
display: flex;
flex-direction: column;
width: 50%;
text-overflow: clip;
align-items: end;
text-align: end;
.hotkey-one-set-item {
background-color: #4446;
padding: 0 5%;
margin: 1% 0;
width: 100%;
border: 1px solid transparent;
}
.hotkey-one-set-item[selected='true'] {
color: gold;
border: 1px solid gold;
}
}
</style>

View File

@ -19,3 +19,4 @@ export { default as StatusBar } from './statusBar.vue';
export { default as Studied } from './studied.vue';
export { default as Study } from './study.vue';
export { default as Toolbox } from './toolbox.vue';
export { default as Hotkey } from './hotkey.vue';

View File

@ -83,11 +83,14 @@ import Scroll from '../components/scroll.vue';
import { isMobile } from '../plugin/use';
import { sleep } from 'mutate-animate';
import { KeyCode } from '../plugin/keyCodes';
import { gameKey } from '@/core/main/init/hotkey';
import { GameUi } from '@/core/main/custom/ui';
const props = defineProps<{
info?: MotaSetting;
text?: SettingText;
num: number;
ui: GameUi;
}>();
const setting = props.info ?? mainSetting;
@ -143,19 +146,13 @@ function exit() {
mota.ui.main.close(props.num);
}
function key(e: KeyboardEvent) {
const c = keycode(e.keyCode);
if (c === KeyCode.Escape || c === KeyCode.KeyX) exit();
}
onMounted(async () => {
await sleep(50);
// if (mota.plugin.ui.transition.value) await sleep(600);
document.addEventListener('keyup', key);
gameKey.use(props.ui.symbol);
gameKey.realize('exit', () => {
exit();
});
onUnmounted(() => {
document.removeEventListener('keyup', key);
gameKey.dispose(props.ui.symbol);
});
</script>