diff --git a/gui/src/components/commons/KeybindRecorder.tsx b/gui/src/components/commons/KeybindRecorder.tsx index e47c31bbd..265540de1 100644 --- a/gui/src/components/commons/KeybindRecorder.tsx +++ b/gui/src/components/commons/KeybindRecorder.tsx @@ -19,9 +19,6 @@ export const KeybindRecorder = forwardRef< const [showError, setShowError] = useState(false); const [errorText, setErrorText] = useState(''); const inputRef = useRef(null); - - const { l10n } = useLocalization(); - const displayKeys = isRecording ? localKeys : keys; const activeIndex = isRecording ? displayKeys.length : -1; @@ -98,9 +95,10 @@ export const KeybindRecorder = forwardRef< const isActive = isRecording && i === activeIndex; const isInvalid = invalidSlot === i; return ( -
+
- {key ?? ''} + > + {key ?? ''} +
+
+ {i < maxKeybindLength - 1 ? '+' : ''} +
); })} + {/*
{displayKeys.length < maxKeybindLength && isRecording diff --git a/gui/src/components/commons/KeybindRecorderModal.tsx b/gui/src/components/commons/KeybindRecorderModal.tsx new file mode 100644 index 000000000..1071e0e50 --- /dev/null +++ b/gui/src/components/commons/KeybindRecorderModal.tsx @@ -0,0 +1,72 @@ +import { BaseModal } from './BaseModal'; +import { + Controller, + Control, + UseFormResetField +} from 'react-hook-form'; +import { KeybindRecorder } from './KeybindRecorder'; +import { Typography } from './Typography'; +import { Button } from './Button'; +import { useLocalization } from '@fluent/react'; + +export function KeybindRecorderModal({ + id, + control, + resetField, + name, + delay, + isVisisble, + onClose, +}: { + id?: string; + control: Control; + resetField: UseFormResetField; + name: string; + delay: string; + isVisisble: boolean; + onClose: () => void; +}) { + + const { l10n } = useLocalization(); + + return ( + +
+
+
+ + Create keybind for {l10n.getString(`settings-keybinds_${id}`)} + + ( + + )} + /> +
+ +
+
+
+
+
+ ); +} diff --git a/gui/src/components/commons/newKeybindsRow.tsx b/gui/src/components/commons/newKeybindsRow.tsx new file mode 100644 index 000000000..2d28f60ae --- /dev/null +++ b/gui/src/components/commons/newKeybindsRow.tsx @@ -0,0 +1,45 @@ +import { Typography } from './Typography'; +import './KeybindRow.scss'; +import { ReactNode } from 'react'; + +const createKeybindDisplay = (keybind: string[]): ReactNode | null => { + return keybind.map((key, i) => { + return ( +
+
+ {key ?? ''} +
+
+ {i < keybind.length - 1 ? '+' : ''} +
+
+ ); + }); +}; + +export function NewKeybindsRow({ + id, + keybind, + delay, +}: { + id?: string; + keybind?: string[]; + delay?: number; +}) { + return ( +
+ +
+
+ {keybind != null ? createKeybindDisplay(keybind) : ''} +
+
+
{delay}
+
+ ); +} diff --git a/gui/src/components/settings/pages/newKeybindSettings.tsx b/gui/src/components/settings/pages/newKeybindSettings.tsx new file mode 100644 index 000000000..a07b17bf9 --- /dev/null +++ b/gui/src/components/settings/pages/newKeybindSettings.tsx @@ -0,0 +1,158 @@ +import { KeybindRecorderModal } from '@/components/commons/KeybindRecorderModal'; +import { + SettingsPageLayout, + SettingsPagePaneLayout, +} from '@/components/settings/SettingsPageLayout'; +import { WrenchIcon } from '@/components/commons/icon/WrenchIcons'; +import { Typography } from '@/components/commons/Typography'; +import { useLocalization } from '@fluent/react'; +import './KeybindSettings.scss'; +import { Button } from '@/components/commons/Button'; +import { NewKeybindsRow } from '@/components/commons/newKeybindsRow'; +import { useWebsocketAPI } from '@/hooks/websocket-api'; +import { ReactNode, useEffect, useState } from 'react'; +import { + ChangeKeybindRequestT, + KeybindRequestT, + KeybindResponseT, + KeybindT, + RpcMessage, +} from 'solarxr-protocol'; +import { useForm } from 'react-hook-form'; + +export type KeybindForm = { + id: number; + name: string; + binding: string[]; + delay: number; +}; + +export function NewKeybindSettings() { + const { l10n } = useLocalization(); + const { sendRPCPacket, useRPCPacket } = useWebsocketAPI(); + const [isOpen, setIsOpen] = useState(false); + const [keybinds, setKeybinds] = useState(); + const [selectedKeybind, setSelectedKeybind] = useState(null); + + const { control, resetField, reset, handleSubmit, watch } = + useForm({}); + + useEffect(() => { + const subscription = watch(() => handleSubmit(onSubmit)()); + return () => subscription.unsubscribe(); + }, []); + + const onSubmit = (value: KeybindForm) => { + const changeKeybindRequest = new ChangeKeybindRequestT(); + + const keybind = new KeybindT(); + keybind.keybindId = value.id; + keybind.keybindNameId = value.name; + keybind.keybindValue = value.binding.join('+'); + keybind.keybindDelay = value.delay; + + changeKeybindRequest.keybind = keybind; + + console.log(`Onsubmit: ${keybind.keybindValue}`); + + sendRPCPacket(RpcMessage.ChangeKeybindRequest, changeKeybindRequest); + }; + + useRPCPacket(RpcMessage.KeybindResponse, ({ keybind }: KeybindResponseT) => { + if (!keybind) return; + setKeybinds(keybind); + }); + + const handleOnClick = () => { + console.log('pressed'); + }; + + const handleOpenRecorderModal = (index: number) => { + if (keybinds == null) return; + console.log('Handle open recorder modal'); + const kb = keybinds[index]; + + setSelectedKeybind(kb); + setIsOpen(true); + + reset({ + id: kb.keybindId, + name: typeof kb.keybindNameId === 'string' ? kb.keybindNameId : '', + binding: + typeof kb.keybindValue === 'string' ? kb.keybindValue.split('+') : [], + delay: kb.keybindDelay, + }); + }; + + const createKeybindRows = (): ReactNode => { + if (keybinds == null) return ''; + return keybinds.map((key, i) => { + return ( +
handleOpenRecorderModal(i)}> + +
+ ); + }); + }; + + useEffect(() => { + sendRPCPacket(RpcMessage.KeybindRequest, new KeybindRequestT()); + }, [isOpen]); + + return ( + + } id="keybinds"> + +
+ {l10n + .getString('settings-keybinds-description') + .split('\n') + .map((line, i) => ( + {line} + ))} +
+
+ + + + {createKeybindRows()} +
+ {selectedKeybind && ( + { + console.log('onclose'); + setIsOpen(false); + setSelectedKeybind(null); + }} + /> + )} +
+
+ ); +} diff --git a/server/desktop/vrconfig.yml.bak b/server/desktop/vrconfig.yml.bak new file mode 100644 index 000000000..e2bd528de --- /dev/null +++ b/server/desktop/vrconfig.yml.bak @@ -0,0 +1,171 @@ +--- +server: + trackerPort: 6969 + useMagnetometerOnAllTrackers: false +filters: + type: "prediction" + amount: 0.2 +driftCompensation: + enabled: false + prediction: false + amount: 0.8 + maxResets: 6 +oscRouter: + enabled: false + portIn: 9002 + portOut: 9000 + address: "127.0.0.1" +vrcOSC: + enabled: false + portIn: 9001 + portOut: 9000 + address: "127.0.0.1" + trackers: + right_foot: true + left_foot: true + waist: true + oscqueryEnabled: true +vmc: + enabled: false + portIn: 39540 + portOut: 39539 + address: "127.0.0.1" + anchorHip: true + vrmJson: null + mirrorTracking: false +autoBone: + cursorIncrement: 2 + minDataDistance: 1 + maxDataDistance: 1 + numEpochs: 50 + printEveryNumEpochs: 25 + initialAdjustRate: 10.0 + adjustRateDecay: 1.0 + slideErrorFactor: 1.0 + offsetSlideErrorFactor: 0.0 + footHeightOffsetErrorFactor: 0.0 + bodyProportionErrorFactor: 0.05 + heightErrorFactor: 0.0 + positionErrorFactor: 0.0 + positionOffsetErrorFactor: 0.0 + calcInitError: false + randomizeFrameOrder: true + scaleEachStep: true + sampleCount: 1500 + sampleRateMs: 20 + saveRecordings: false + useSkeletonHeight: false + randSeed: 4 + useFrameFiltering: false + maxFinalError: 0.03 +keybindings: + keybinds: + "0": + id: 0 + name: "full-reset" + binding: "CTRL+ALT+SHIFT+Y" + delay: 0.0 + "1": + id: 1 + name: "yaw-reset" + binding: "CTRL+ALT+SHIFT+U" + delay: 0.0 + "2": + id: 2 + name: "mounting-reset" + binding: "CTRL+ALT+SHIFT+I" + delay: 0.0 + "4": + id: 4 + name: "feet-mounting-reset" + binding: "CTRL+ALT+SHIFT+P" + delay: 0.0 + "3": + id: 3 + name: "pause-tracking" + binding: "CTRL+ALT+SHIFT+O" + delay: 0.0 + "5": + id: 5 + name: "test" + binding: "A+B+C+D" + delay: 2.0 +skeleton: + toggles: {} + values: {} + offsets: {} + hmdHeight: 0.0 + floorHeight: 0.0 +legTweaks: + correctionStrength: 0.3 + alwaysUseFloorclip: false +tapDetection: + yawResetDelay: 0.2 + fullResetDelay: 1.0 + mountingResetDelay: 1.0 + yawResetEnabled: true + fullResetEnabled: true + mountingResetEnabled: true + setupMode: false + yawResetTaps: 2 + fullResetTaps: 3 + mountingResetTaps: 3 + numberTrackersOverThreshold: 1 +resetsConfig: + resetMountingFeet: false + mode: "BACK" + yawResetSmoothTime: 0.0 + saveMountingReset: false + resetHmdPitch: false + lastMountingMethod: "AUTOMATIC" + yawResetDelay: 0.0 + fullResetDelay: 3.0 + mountingResetDelay: 3.0 +stayAlignedConfig: + enabled: false + standingRelaxedPose: + enabled: false + upperLegAngleInDeg: 0.0 + lowerLegAngleInDeg: 0.0 + footAngleInDeg: 0.0 + sittingRelaxedPose: + enabled: false + upperLegAngleInDeg: 0.0 + lowerLegAngleInDeg: 0.0 + footAngleInDeg: 0.0 + flatRelaxedPose: + enabled: false + upperLegAngleInDeg: 0.0 + lowerLegAngleInDeg: 0.0 + footAngleInDeg: 0.0 + setupComplete: false +hidConfig: + trackersOverHID: false +trackers: {} +bridges: + steamvr: + trackers: + right_knee: false + chest: false + right_foot: false + right_hand: false + left_foot: false + left_hand: false + waist: false + right_elbow: false + left_knee: false + hmd: false + left_elbow: false + automaticSharedTrackersToggling: true + steamvr_feeder: + trackers: {} + automaticSharedTrackersToggling: true +knownDevices: [] +overlay: + mirrored: false + visible: false +trackingChecklist: + ignoredStepsIds: [] +vrcConfig: + mutedWarnings: [] +modelVersion: "15"