mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 20:59:37 +08:00
feat: 自定义按键
This commit is contained in:
parent
1e58dbe411
commit
770e38202c
@ -59,22 +59,22 @@ function resize() {
|
|||||||
if (has(props.right)) right.style.flexBasis = `${props.right}%`;
|
if (has(props.right)) right.style.flexBasis = `${props.right}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function key(e: KeyboardEvent) {
|
// function key(e: KeyboardEvent) {
|
||||||
const c = keycode(e.keyCode);
|
// const c = keycode(e.keyCode);
|
||||||
if (c === KeyCode.Escape || c === KeyCode.KeyX) emits('close');
|
// if (c === KeyCode.Escape || c === KeyCode.KeyX) emits('close');
|
||||||
}
|
// }
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
resize();
|
resize();
|
||||||
|
|
||||||
await sleep(50);
|
await sleep(50);
|
||||||
// if (mota.plugin.ui.transition.value) await sleep(600);
|
// if (mota.plugin.ui.transition.value) await sleep(600);
|
||||||
document.addEventListener('keyup', key);
|
// document.addEventListener('keyup', key);
|
||||||
});
|
});
|
||||||
onUpdated(resize);
|
onUpdated(resize);
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
document.removeEventListener('keyup', key);
|
// document.removeEventListener('keyup', key);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -15,7 +15,10 @@ gameKey
|
|||||||
.register({
|
.register({
|
||||||
id: 'book',
|
id: 'book',
|
||||||
name: '怪物手册',
|
name: '怪物手册',
|
||||||
defaults: KeyCode.KeyX
|
defaults: KeyCode.KeyX,
|
||||||
|
ctrl: true,
|
||||||
|
shift: true,
|
||||||
|
alt: true
|
||||||
})
|
})
|
||||||
.register({
|
.register({
|
||||||
id: 'save',
|
id: 'save',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type { SettingComponent, SettingComponentProps } from '../setting';
|
import type { SettingComponent, SettingComponentProps } from '../setting';
|
||||||
import { Button, InputNumber } from 'ant-design-vue';
|
import { Button, InputNumber } from 'ant-design-vue';
|
||||||
import { mainUi } from './ui';
|
import { mainUi } from './ui';
|
||||||
|
import { gameKey } from './hotkey';
|
||||||
|
|
||||||
interface Components {
|
interface Components {
|
||||||
DefaultSetting: SettingComponent;
|
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);
|
const ui = mainUi.get(id);
|
||||||
mainUi.showEnd();
|
mainUi.showEnd();
|
||||||
ui.once('close', () => {
|
ui.once('close', () => {
|
||||||
mainUi.showAll();
|
mainUi.showAll();
|
||||||
});
|
});
|
||||||
mainUi.open(id);
|
mainUi.open(id, vBind);
|
||||||
}
|
}
|
||||||
|
|
||||||
function HotkeySetting(props: SettingComponentProps) {
|
function HotkeySetting(props: SettingComponentProps) {
|
||||||
@ -86,7 +87,11 @@ function HotkeySetting(props: SettingComponentProps) {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="large"
|
size="large"
|
||||||
onClick={() => showSpecialSetting('hotkey')}
|
onClick={() =>
|
||||||
|
showSpecialSetting('hotkey', {
|
||||||
|
hotkey: gameKey
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
快捷键设置
|
快捷键设置
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -15,7 +15,8 @@ mainUi.register(
|
|||||||
new GameUi('fixedDetail', UI.FixedDetail),
|
new GameUi('fixedDetail', UI.FixedDetail),
|
||||||
new GameUi('shop', UI.Shop),
|
new GameUi('shop', UI.Shop),
|
||||||
new GameUi('achievement', UI.Achievement),
|
new GameUi('achievement', UI.Achievement),
|
||||||
new GameUi('bgm', UI.BgmList)
|
new GameUi('bgm', UI.BgmList),
|
||||||
|
new GameUi('hotkey', UI.Hotkey)
|
||||||
// todo: 把游戏主 div 加入到 mainUi 里面
|
// todo: 把游戏主 div 加入到 mainUi 里面
|
||||||
);
|
);
|
||||||
mainUi.showAll();
|
mainUi.showAll();
|
||||||
|
@ -389,7 +389,7 @@ mainSetting
|
|||||||
new MotaSetting()
|
new MotaSetting()
|
||||||
.register('autoSkill', '自动切换技能', true, COM.BooleanSetting)
|
.register('autoSkill', '自动切换技能', true, COM.BooleanSetting)
|
||||||
.register('fixed', '定点查看', true, COM.BooleanSetting)
|
.register('fixed', '定点查看', true, COM.BooleanSetting)
|
||||||
.register('hotkey', '快捷键', false, COM.BooleanSetting)
|
.register('hotkey', '快捷键', false, COM.HotkeySetting)
|
||||||
.setDisplayFunc('hotkey', () => '')
|
.setDisplayFunc('hotkey', () => '')
|
||||||
.register('toolbar', '自定义工具栏', false, COM.BooleanSetting)
|
.register('toolbar', '自定义工具栏', false, COM.BooleanSetting)
|
||||||
.setDisplayFunc('toolbar', () => '')
|
.setDisplayFunc('toolbar', () => '')
|
||||||
|
229
src/ui/hotkey.vue
Normal file
229
src/ui/hotkey.vue
Normal 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>
|
@ -19,3 +19,4 @@ export { default as StatusBar } from './statusBar.vue';
|
|||||||
export { default as Studied } from './studied.vue';
|
export { default as Studied } from './studied.vue';
|
||||||
export { default as Study } from './study.vue';
|
export { default as Study } from './study.vue';
|
||||||
export { default as Toolbox } from './toolbox.vue';
|
export { default as Toolbox } from './toolbox.vue';
|
||||||
|
export { default as Hotkey } from './hotkey.vue';
|
||||||
|
@ -83,11 +83,14 @@ import Scroll from '../components/scroll.vue';
|
|||||||
import { isMobile } from '../plugin/use';
|
import { isMobile } from '../plugin/use';
|
||||||
import { sleep } from 'mutate-animate';
|
import { sleep } from 'mutate-animate';
|
||||||
import { KeyCode } from '../plugin/keyCodes';
|
import { KeyCode } from '../plugin/keyCodes';
|
||||||
|
import { gameKey } from '@/core/main/init/hotkey';
|
||||||
|
import { GameUi } from '@/core/main/custom/ui';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
info?: MotaSetting;
|
info?: MotaSetting;
|
||||||
text?: SettingText;
|
text?: SettingText;
|
||||||
num: number;
|
num: number;
|
||||||
|
ui: GameUi;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const setting = props.info ?? mainSetting;
|
const setting = props.info ?? mainSetting;
|
||||||
@ -143,19 +146,13 @@ function exit() {
|
|||||||
mota.ui.main.close(props.num);
|
mota.ui.main.close(props.num);
|
||||||
}
|
}
|
||||||
|
|
||||||
function key(e: KeyboardEvent) {
|
gameKey.use(props.ui.symbol);
|
||||||
const c = keycode(e.keyCode);
|
gameKey.realize('exit', () => {
|
||||||
if (c === KeyCode.Escape || c === KeyCode.KeyX) exit();
|
exit();
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await sleep(50);
|
|
||||||
// if (mota.plugin.ui.transition.value) await sleep(600);
|
|
||||||
document.addEventListener('keyup', key);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
document.removeEventListener('keyup', key);
|
gameKey.dispose(props.ui.symbol);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user