feat(KeySight+KeyFire): add KeySight and KeyFire module

This commit is contained in:
AkiChase 2024-05-18 22:53:00 +08:00
parent 8b848e5a72
commit 556e69ca46
9 changed files with 558 additions and 36 deletions

View File

@ -52,7 +52,8 @@ onActivated(async () => {
applyShortcuts(
maskElement,
store.keyMappingConfigList[store.curKeyMappingIndex],
message
message,
t
)
) {
listenToEvent();

View File

@ -6,6 +6,8 @@ import KeyCommon from "./KeyCommon.vue";
import KeySteeringWheel from "./KeySteeringWheel.vue";
import KeySkill from "./KeySkill.vue";
import KeyObservation from "./KeyObservation.vue";
import KeySight from "./KeySight.vue";
import KeyFire from "./KeyFire.vue";
import {
KeyDirectionalSkill,
KeySteeringWheel as KeyMappingSteeringWheel,
@ -115,7 +117,7 @@ function isKeyUnique(curKey: string): boolean {
return false;
set.add((keyMapping as KeyMappingSteeringWheel).key[name]);
}
} else {
} else if (keyMapping.type !== "Fire") {
if (set.has(keyMapping.key as string)) return false;
set.add(keyMapping.key as string);
}
@ -169,10 +171,11 @@ function setCurButtonKey(curKey: string) {
const curName = nameList[activeSteeringWheelButtonKeyIndex];
keyObject[curName] = curKey;
}
} else {
keyboardStore.edited = true;
} else if (keyMapping.type !== "Fire") {
keyMapping.key = curKey;
keyboardStore.edited = true;
}
keyboardStore.edited = true;
}
function handleClick(event: MouseEvent) {
@ -314,6 +317,14 @@ onBeforeRouteLeave(() => {
v-else-if="store.editKeyMappingList[index].type === 'Observation'"
:index="index"
/>
<KeySight
v-else-if="store.editKeyMappingList[index].type === 'Sight'"
:index="index"
/>
<KeyFire
v-else-if="store.editKeyMappingList[index].type === 'Fire'"
:index="index"
/>
<KeyCommon v-else :index="index" />
</template>
</div>

View File

@ -0,0 +1,250 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useGlobalStore } from "../../store/global";
import {
NIcon,
NButton,
NFormItem,
NInput,
NH4,
NInputNumber,
NCheckbox,
} from "naive-ui";
import { CloseCircle, Settings } from "@vicons/ionicons5";
import { KeyFire } from "../../keyMappingConfig";
import { useKeyboardStore } from "../../store/keyboard";
const props = defineProps<{
index: number;
}>();
const keyboardStore = useKeyboardStore();
const store = useGlobalStore();
const elementRef = ref<HTMLElement | null>(null);
const isActive = computed(
() => props.index === keyboardStore.activeButtonIndex
);
const keyMapping = computed(
() => store.editKeyMappingList[props.index] as KeyFire
);
function dragHandler(downEvent: MouseEvent) {
keyboardStore.activeButtonIndex = props.index;
keyboardStore.showButtonSettingFlag = false;
const oldX = keyMapping.value.posX;
const oldY = keyMapping.value.posY;
const element = elementRef.value;
if (element) {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const maxX = keyboardElement.clientWidth - 30;
const maxY = keyboardElement.clientHeight - 30;
const x = downEvent.clientX;
const y = downEvent.clientY;
const moveHandler = (moveEvent: MouseEvent) => {
let newX = oldX + moveEvent.clientX - x;
let newY = oldY + moveEvent.clientY - y;
newX = Math.max(30, Math.min(newX, maxX));
newY = Math.max(30, Math.min(newY, maxY));
keyMapping.value.posX = newX;
keyMapping.value.posY = newY;
};
window.addEventListener("mousemove", moveHandler);
const upHandler = () => {
window.removeEventListener("mousemove", moveHandler);
window.removeEventListener("mouseup", upHandler);
if (oldX !== keyMapping.value.posX || oldY !== keyMapping.value.posY) {
keyboardStore.edited = true;
}
};
window.addEventListener("mouseup", upHandler);
}
}
function delCurKeyMapping() {
keyboardStore.edited = true;
keyboardStore.activeButtonIndex = -1;
store.editKeyMappingList.splice(props.index, 1);
}
const settingPosX = ref(0);
const settingPosY = ref(0);
function showSetting() {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const maxWidth = keyboardElement.clientWidth - 150;
const maxHeight = keyboardElement.clientHeight - 420;
settingPosX.value = Math.min(keyMapping.value.posX + 40, maxWidth);
settingPosY.value = Math.min(keyMapping.value.posY - 30, maxHeight);
keyboardStore.showButtonSettingFlag = true;
}
</script>
<template>
<div
:class="{ active: isActive }"
:style="{
left: `${keyMapping.posX - 30}px`,
top: `${keyMapping.posY - 30}px`,
}"
@mousedown="dragHandler"
class="key-fire"
ref="elementRef"
>
<NIcon size="25">
<svg
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M562.333538 310.665846a43.716923 43.716923 0 0 0-59.746461-1.181538l-301.528615 276.440615a39.424 39.424 0 0 0-1.181539 57.265231l190.070154 190.227692a39.345231 39.345231 0 0 0 57.225846-1.339077l276.558769-301.528615a43.598769 43.598769 0 0 0-1.260307-59.707077l-160.137847-160.177231zM149.385846 663.236923a41.550769 41.550769 0 0 0-58.564923 0 41.550769 41.550769 0 0 0 0 58.525539l222.641231 222.601846a41.432615 41.432615 0 0 0 58.525538-58.564923L149.385846 663.236923zM879.143385 118.350769c-63.015385-1.851077-195.465846 8.073846-281.796923 109.331693-1.457231 2.953846-15.596308 31.586462 6.222769 53.563076l150.173538 151.000616c5.710769 5.435077 24.339692 19.298462 53.326769 2.953846 40.093538-38.4 109.686154-127.606154 108.819693-282.269538-0.787692-28.750769-26.190769-33.831385-36.745846-34.579693z"
></path>
</svg>
</NIcon>
<NButton
class="key-close-btn"
text
@click="delCurKeyMapping"
:type="isActive ? 'primary' : 'info'"
>
<template #icon>
<NIcon size="15">
<CloseCircle />
</NIcon>
</template>
</NButton>
<NButton
class="key-setting-btn"
text
@click="showSetting"
:type="isActive ? 'primary' : 'info'"
>
<template #icon>
<NIcon size="15">
<Settings />
</NIcon>
</template>
</NButton>
</div>
<div
class="key-setting"
v-if="isActive && keyboardStore.showButtonSettingFlag"
:style="{
left: `${settingPosX}px`,
top: `${settingPosY}px`,
}"
>
<NH4 prefix="bar">{{ $t("pages.KeyBoard.KeyFire.fire") }}</NH4>
<NCheckbox
@click="keyMapping.drag = !keyMapping.drag"
:checked="keyMapping.drag"
style="margin-bottom: 20px"
>{{ $t("pages.KeyBoard.KeyFire.drag") }}</NCheckbox
>
<NFormItem :label="$t('pages.KeyBoard.KeyFire.scaleX')">
<NInputNumber
v-model:value="keyMapping.scaleX"
:placeholder="$t('pages.KeyBoard.KeyFire.scalePlaceholder')"
:show-button="false"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.KeyFire.scaleY')">
<NInputNumber
v-model:value="keyMapping.scaleY"
:placeholder="$t('pages.KeyBoard.KeyFire.scalePlaceholder')"
:show-button="false"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.setting.pointerID')">
<NInputNumber
v-model:value="keyMapping.pointerId"
:min="0"
:placeholder="$t('pages.KeyBoard.setting.pointerIDPlaceholder')"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.setting.note')">
<NInput
v-model:value="keyMapping.note"
:placeholder="$t('pages.KeyBoard.setting.notePlaceholder')"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
</div>
</template>
<style scoped lang="scss">
.key-setting {
position: absolute;
display: flex;
flex-direction: column;
padding: 10px 20px;
box-sizing: border-box;
width: 150px;
height: 420px;
border-radius: 5px;
border: 2px solid var(--light-color);
background-color: var(--bg-color);
z-index: 3;
}
.key-fire {
position: absolute;
height: 60px;
width: 60px;
box-sizing: border-box;
border-radius: 50%;
border: 2px solid var(--blue-color);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 10px;
font-weight: bold;
cursor: pointer;
.n-icon {
color: var(--blue-color);
}
&:not(.active):hover {
border: 2px solid var(--light-color);
color: var(--light-color);
.n-icon {
color: var(--light-color);
}
}
.key-close-btn {
position: absolute;
left: 65px;
bottom: 45px;
}
.key-setting-btn {
position: absolute;
left: 65px;
top: 45px;
}
}
.active {
border: 2px solid var(--primary-color);
color: var(--primary-color);
z-index: 2;
.n-icon {
color: var(--primary-color);
}
}
</style>

View File

@ -0,0 +1,237 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useGlobalStore } from "../../store/global";
import { NIcon, NButton, NFormItem, NInput, NH4, NInputNumber } from "naive-ui";
import { CloseCircle, Settings } from "@vicons/ionicons5";
import { KeySight } from "../../keyMappingConfig";
import { useKeyboardStore } from "../../store/keyboard";
const props = defineProps<{
index: number;
}>();
const keyboardStore = useKeyboardStore();
const store = useGlobalStore();
const elementRef = ref<HTMLElement | null>(null);
const isActive = computed(
() => props.index === keyboardStore.activeButtonIndex
);
const keyMapping = computed(
() => store.editKeyMappingList[props.index] as KeySight
);
function dragHandler(downEvent: MouseEvent) {
keyboardStore.activeButtonIndex = props.index;
keyboardStore.showButtonSettingFlag = false;
const oldX = keyMapping.value.posX;
const oldY = keyMapping.value.posY;
const element = elementRef.value;
if (element) {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const maxX = keyboardElement.clientWidth - 30;
const maxY = keyboardElement.clientHeight - 30;
const x = downEvent.clientX;
const y = downEvent.clientY;
const moveHandler = (moveEvent: MouseEvent) => {
let newX = oldX + moveEvent.clientX - x;
let newY = oldY + moveEvent.clientY - y;
newX = Math.max(30, Math.min(newX, maxX));
newY = Math.max(30, Math.min(newY, maxY));
keyMapping.value.posX = newX;
keyMapping.value.posY = newY;
};
window.addEventListener("mousemove", moveHandler);
const upHandler = () => {
window.removeEventListener("mousemove", moveHandler);
window.removeEventListener("mouseup", upHandler);
if (oldX !== keyMapping.value.posX || oldY !== keyMapping.value.posY) {
keyboardStore.edited = true;
}
};
window.addEventListener("mouseup", upHandler);
}
}
function delCurKeyMapping() {
keyboardStore.edited = true;
keyboardStore.activeButtonIndex = -1;
store.editKeyMappingList.splice(props.index, 1);
}
const settingPosX = ref(0);
const settingPosY = ref(0);
function showSetting() {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const maxWidth = keyboardElement.clientWidth - 150;
const maxHeight = keyboardElement.clientHeight - 380;
settingPosX.value = Math.min(keyMapping.value.posX + 40, maxWidth);
settingPosY.value = Math.min(keyMapping.value.posY - 30, maxHeight);
keyboardStore.showButtonSettingFlag = true;
}
</script>
<template>
<div
:class="{ active: isActive }"
:style="{
left: `${keyMapping.posX - 30}px`,
top: `${keyMapping.posY - 30}px`,
}"
@mousedown="dragHandler"
class="key-sight"
ref="elementRef"
>
<NIcon size="25">
<svg
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M65.472 479.232A448 448 0 0 1 481.28 64.32V32a32 32 0 1 1 64 0v32.448a448 448 0 0 1 413.952 415.808h33.152a32 32 0 1 1 0 64h-33.28a448.064 448.064 0 0 1-414.784 413.888v33.28a32 32 0 1 1-64 0v-33.28a448.064 448.064 0 0 1-414.912-414.912H32a32 32 0 1 1 0-64h33.472z m64.192 0h94.72a32 32 0 0 1 0 64h-94.72a384.064 384.064 0 0 0 350.656 350.72V800a32 32 0 0 1 64 0v93.952a384.128 384.128 0 0 0 350.592-349.632h-94.72a32 32 0 1 1 0-64h94.848A384 384 0 0 0 545.28 128.64v94.272a32 32 0 0 1-64 0V128.512a383.744 383.744 0 0 0-351.616 350.72z m318.656 32a64 64 0 1 1 128 0 64 64 0 0 1-128 0z"
></path>
</svg>
</NIcon>
<span>{{ keyMapping.key }}</span>
<NButton
class="key-close-btn"
text
@click="delCurKeyMapping"
:type="isActive ? 'primary' : 'info'"
>
<template #icon>
<NIcon size="15">
<CloseCircle />
</NIcon>
</template>
</NButton>
<NButton
class="key-setting-btn"
text
@click="showSetting"
:type="isActive ? 'primary' : 'info'"
>
<template #icon>
<NIcon size="15">
<Settings />
</NIcon>
</template>
</NButton>
</div>
<div
class="key-setting"
v-if="isActive && keyboardStore.showButtonSettingFlag"
:style="{
left: `${settingPosX}px`,
top: `${settingPosY}px`,
}"
>
<NH4 prefix="bar">{{ $t('pages.KeyBoard.KeySight.sight') }}</NH4>
<NFormItem :label="$t('pages.KeyBoard.KeySight.scaleX')">
<NInputNumber
v-model:value="keyMapping.scaleX"
:placeholder="$t('pages.KeyBoard.KeySight.scalePlaceholder')"
:show-button="false"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.KeySight.scaleY')">
<NInputNumber
v-model:value="keyMapping.scaleY"
:placeholder="$t('pages.KeyBoard.KeySight.scalePlaceholder')"
:show-button="false"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.setting.pointerID')">
<NInputNumber
v-model:value="keyMapping.pointerId"
:min="0"
:placeholder="$t('pages.KeyBoard.setting.pointerIDPlaceholder')"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
<NFormItem :label="$t('pages.KeyBoard.setting.note')">
<NInput
v-model:value="keyMapping.note"
:placeholder="$t('pages.KeyBoard.setting.notePlaceholder')"
@update:value="keyboardStore.edited = true"
/>
</NFormItem>
</div>
</template>
<style scoped lang="scss">
.key-setting {
position: absolute;
display: flex;
flex-direction: column;
padding: 10px 20px;
box-sizing: border-box;
width: 150px;
height: 380px;
border-radius: 5px;
border: 2px solid var(--light-color);
background-color: var(--bg-color);
z-index: 3;
}
.key-sight {
position: absolute;
height: 60px;
width: 60px;
box-sizing: border-box;
border-radius: 50%;
border: 2px solid var(--blue-color);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 10px;
font-weight: bold;
cursor: pointer;
.n-icon {
color: var(--blue-color);
}
&:not(.active):hover {
border: 2px solid var(--light-color);
color: var(--light-color);
.n-icon {
color: var(--light-color);
}
}
.key-close-btn {
position: absolute;
left: 65px;
bottom: 45px;
}
.key-setting-btn {
position: absolute;
left: 65px;
top: 45px;
}
}
.active {
border: 2px solid var(--primary-color);
color: var(--primary-color);
z-index: 2;
.n-icon {
color: var(--primary-color);
}
}
</style>

View File

@ -185,7 +185,7 @@ function showSetting() {
) as HTMLElement;
// setting
const maxWidth = keyboardElement.clientWidth - 200;
const maxHeight = keyboardElement.clientHeight - 420;
const maxHeight = keyboardElement.clientHeight - 430;
settingPosX.value = Math.min(keyMapping.value.posX + 40, maxWidth);
settingPosY.value = Math.min(keyMapping.value.posY - 30, maxHeight);
updateRangeIndicator(keyboardElement);
@ -374,7 +374,7 @@ function updateRangeIndicator(element?: HTMLElement) {
padding: 10px 20px;
box-sizing: border-box;
width: 200px;
height: 420px;
height: 430px;
border-radius: 5px;
border: 2px solid var(--light-color);
background-color: var(--bg-color);

View File

@ -23,6 +23,7 @@ import {
} from "./keyMappingConfig";
import { useGlobalStore } from "./store/global";
import { LogicalPosition, getCurrent } from "@tauri-apps/api/window";
import { useI18n } from "vue-i18n";
function clientxToPosx(clientx: number) {
return clientx < 70
@ -649,7 +650,7 @@ function addSightShortcuts(
sightKeyMapping: KeySight,
fireKeyMapping?: KeyFire
) {
// TODO 2. i18n 3. 单独函数,同时配合可视化组件 4. 组件配置中唯一
// TODO 3. 可视化组件 4. 组件配置中唯一
const appWindow = getCurrent();
let mouseLock = false;
@ -803,7 +804,7 @@ function addSightShortcuts(
await appWindow.setCursorVisible(false);
maskElement.addEventListener("mouseleave", moveLeaveHandler);
mouseLock = true;
msgReactive = message.info(`鼠标已锁定, 按 ${key} 键解锁`, {
msgReactive = message.info(t("pages.Mask.sightMode", [key]), {
duration: 0,
});
@ -911,6 +912,7 @@ let mouseX = 0;
let mouseY = 0;
let maskElement: HTMLElement;
let message: ReturnType<typeof useMessage>;
let t: ReturnType<typeof useI18n>["t"];
const downKeyMap: Map<string, boolean> = new Map();
const downKeyCBMap: Map<string, () => Promise<void>> = new Map();
@ -1304,6 +1306,19 @@ function applyKeyMappingConfigShortcuts(
}
);
break;
case "Sight":
asType<KeySight>(item);
let fireKeyMapping;
for (const keyMapping of keyMappingConfig.list) {
if (keyMapping.type === "Fire") {
fireKeyMapping = keyMapping;
break;
}
}
addSightShortcuts(relativeSize, item, fireKeyMapping);
break;
case "Fire":
break;
default:
console.error("Invalid item type: ", item);
break;
@ -1382,35 +1397,13 @@ export function updateScreenSizeAndMaskArea(
export function applyShortcuts(
element: HTMLElement,
keyMappingConfig: KeyMappingConfig,
messageAPI: ReturnType<typeof useMessage>
messageAPI: ReturnType<typeof useMessage>,
i18nT: ReturnType<typeof useI18n>["t"]
) {
maskElement = element;
message = messageAPI;
t = i18nT;
addClickShortcuts("M0", 0);
const relativeSize = { w: 1280, h: 720 };
const sightKeyMapping = {
type: "Sight" as "Sight",
key: "KeyH",
pointerId: 0,
note: "准星键",
posX: 640,
posY: 360,
scaleX: 1,
scaleY: 1,
};
const fireKeyMapping = {
type: "Fire" as "Fire",
pointerId: 2,
note: "开火键",
posX: 300,
posY: 300,
drag: true,
scaleX: 0.5,
scaleY: 0.2,
};
addSightShortcuts(relativeSize, sightKeyMapping, fireKeyMapping);
return applyKeyMappingConfigShortcuts(keyMappingConfig);
}

View File

@ -61,7 +61,8 @@
"title": "Controlled device not found",
"content": "Please go to the device page to control any device",
"positiveText": "To control"
}
},
"sightMode": "Mouse is locked, press {0} to unlock"
},
"Setting": {
"tabs": {
@ -218,6 +219,19 @@
"SteeringWheel": {
"steeringWheel": "SteeringWheel",
"offset": "Offset"
},
"KeySight": {
"sight": "Front sight",
"scaleX": "Horizontal sensitivity",
"scalePlaceholder": "Please enter sensitivity",
"scaleY": "Vertical sensitivity"
},
"KeyFire": {
"fire": "Fire",
"drag": "Drag to cast",
"scaleX": "Horizontal sensitivity",
"scalePlaceholder": "Please enter sensitivity",
"scaleY": "Vertical sensitivity"
}
}
},

View File

@ -61,7 +61,8 @@
"content": "请前往设备页面,控制任意设备",
"positiveText": "去控制"
},
"inputBoxPlaceholder": "输入文本后按Enter/Esc"
"inputBoxPlaceholder": "输入文本后按Enter/Esc",
"sightMode": "鼠标已锁定, 按 {0} 键解锁"
},
"Setting": {
"tabs": {
@ -218,6 +219,19 @@
"SteeringWheel": {
"steeringWheel": "键盘行走",
"offset": "偏移"
},
"KeySight": {
"sight": "准星",
"scaleX": "水平灵敏度",
"scaleY": "垂直灵敏度",
"scalePlaceholder": "请输入灵敏度"
},
"KeyFire": {
"fire": "开火",
"drag": "拖动施法",
"scaleX": "水平灵敏度",
"scaleY": "垂直灵敏度",
"scalePlaceholder": "请输入灵敏度"
}
}
},

View File

@ -105,7 +105,9 @@ export type KeyMapping =
| KeyObservation
| KeyMacro
| KeyCancelSkill
| KeyTap;
| KeyTap
| KeySight
| KeyFire;
export type KeyCommon = KeyMacro | KeyCancelSkill | KeyTap;