Very big keybinds server refactor

This commit is contained in:
HannahPadd
2026-03-27 15:49:19 +01:00
parent 2ef6a3172d
commit 13e1265a51
10 changed files with 152 additions and 232 deletions

View File

@@ -56,6 +56,8 @@ import { ElectronContextC, provideElectron } from './hooks/electron';
import { AppLocalizationProvider } from './i18n/config';
import { openUrl } from './hooks/crossplatform';
import { UdevRulesModal } from './components/onboarding/UdevRulesModal';
import { NewKeybindSettings } from './components/settings/pages/newKeybindSettings';
import { NewKeybindsRow } from './components/commons/newKeybindsRow';
export const GH_REPO = 'SlimeVR/SlimeVR-Server';
export const VersionContext = createContext('');
@@ -141,7 +143,7 @@ function Layout() {
<Route path="interface" element={<InterfaceSettings />} />
<Route path="interface/home" element={<HomeScreenSettings />} />
<Route path="advanced" element={<AdvancedSettings />} />
<Route path="keybinds" element={<KeybindSettings />} />
<Route path="keybinds" element={<NewKeybindSettings />} />
</Route>
<Route
path="/onboarding"

View File

@@ -2,8 +2,7 @@ import { useLocalization } from '@fluent/react';
import { useState, forwardRef, useRef } from 'react';
import { Typography } from './Typography';
const excludedKeys = ['CONTROL', ' ', 'SPACE', 'ALT', 'META'];
const keyOffset = 2;
const excludedKeys = [' ', 'SPACE', 'META'];
const maxKeybindLength = 4;
export const KeybindRecorder = forwardRef<
@@ -62,14 +61,14 @@ export const KeybindRecorder = forwardRef<
}
setIsRecording(false);
setShowError(false);
if (displayKeys.length == keyOffset) {
if (displayKeys.length === maxKeybindLength) {
onKeysChange(oldKeys);
setLocalKeys(oldKeys);
}
};
const handleOnFocus = () => {
const initialKeys = ['CTRL', 'ALT'];
const initialKeys: string[] = [];
setOldKeys(keys);
setLocalKeys(initialKeys);
onKeysChange(initialKeys);
@@ -92,8 +91,8 @@ export const KeybindRecorder = forwardRef<
onBlur={handleOnBlur}
onKeyDown={handleKeyDown}
/>
<div className="flex gap-2 min-h-[42px] items-center px-3 py-2 rounded-lg bg-background-80">
<div className="flex flex-grow gap-2 min-w-[180px]">
<div className="flex gap-2 min-h-[42px] items-center">
<div className="flex flex-grow gap-2 justify-center">
{Array.from({ length: maxKeybindLength }).map((_, i) => {
const key = displayKeys[i];
const isActive = isRecording && i === activeIndex;
@@ -102,8 +101,8 @@ export const KeybindRecorder = forwardRef<
<div
key={i}
className={`
px-2 py-1 rounded-md text-sm min-w-[32px] text-center
${key ? 'bg-accent-background-50' : 'bg-accent-background-50/30'}
rounded-md min-w-[50px] min-h-[50px] text-lg flex items-center justify-center hover:ring-2 hover:ring-accent
${key ? 'bg-background-90' : 'bg-background-80'}
${
isInvalid
? 'keyslot-invalid ring-2 ring-red-600'
@@ -118,11 +117,13 @@ export const KeybindRecorder = forwardRef<
);
})}
</div>
{/*
<div className="w-40 flex-shrink-0 text-accent-background-10 text-right text-sm font-medium">
{displayKeys.length < maxKeybindLength && isRecording
? l10n.getString('settings-keybinds_now-recording')
: l10n.getString('settings-keybinds_record-keybind')}
</div>
*/}
</div>
</div>
);

View File

@@ -2,12 +2,14 @@ import { Controller, Control, UseFormResetField } from 'react-hook-form';
import { Button } from './Button';
import { NumberSelector } from './NumberSelector';
import { KeybindRecorder } from './KeybindRecorder';
import { KeybindRecorderModal } from './KeybindRecorderModal';
import { useLocaleConfig } from '@/i18n/config';
import { Typography } from './Typography';
import './KeybindRow.scss';
export function KeybindRow({
id,
label,
control,
resetField,
name,
@@ -44,15 +46,24 @@ export function KeybindRow({
/>
)}
/>
<NumberSelector
control={control}
name={delay}
valueLabelFormat={(value) => secondsFormat.format(value)}
min={0}
max={10}
step={0.2}
/>
<div className='max-w-[45px]'>
<KeybindRecorderModal
id=""
label={label}
control={control}
resetField={resetField}
name={name}
delay={delay}
isVisisble={true}
/>
<NumberSelector
control={control}
name={delay}
valueLabelFormat={(value) => secondsFormat.format(value)}
min={0}
max={10}
step={0.2}
/>
<div className="max-w-[45px]">
<Button
id="settings-keybinds_reset-button"
variant="primary"

View File

@@ -59,7 +59,7 @@ export function UdevRulesModal() {
};
return (
<BaseModal isOpen={showUdevWarning} appendClasses={'w-full max-w-2xl'}>
<BaseModal isOpen={showUdevWarning} appendClasses='w-full max-w-2xl'>
<div className="flex w-full h-full flex-col gap-4">
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-2">

View File

@@ -255,6 +255,7 @@ export function KeybindSettings() {
<div />
<KeybindRow
id="settings-keybinds_full-reset"
label='Full Reset'
control={control}
resetField={resetField}
name="bindings.fullResetBinding"

View File

@@ -11,6 +11,7 @@ import io.eiren.util.OperatingSystem
import io.eiren.util.OperatingSystem.Companion.currentPlatform
import io.eiren.util.ann.AWTThread
import io.eiren.util.logging.LogManager
import solarxr_protocol.rpc.KeybindId
class Keybinding @AWTThread constructor(val server: VRServer) : HotkeyListener {
val config: KeybindingsConfig = server.configManager.vrConfig.keybindings
@@ -21,30 +22,10 @@ class Keybinding @AWTThread constructor(val server: VRServer) : HotkeyListener {
if (JIntellitype.getInstance() != null) {
JIntellitype.getInstance().addHotKeyListener(this)
val fullResetBinding = config.fullResetBinding
JIntellitype.getInstance()
.registerHotKey(FULL_RESET, fullResetBinding)
LogManager.info("[Keybinding] Bound full reset to $fullResetBinding")
val yawResetBinding = config.yawResetBinding
JIntellitype.getInstance()
.registerHotKey(YAW_RESET, yawResetBinding)
LogManager.info("[Keybinding] Bound yaw reset to $yawResetBinding")
val mountingResetBinding = config.mountingResetBinding
JIntellitype.getInstance()
.registerHotKey(MOUNTING_RESET, mountingResetBinding)
LogManager.info("[Keybinding] Bound reset mounting to $mountingResetBinding")
val feetMountingResetBinding = config.feetMountingResetBinding
JIntellitype.getInstance()
.registerHotKey(FEET_MOUNTING_RESET, feetMountingResetBinding)
LogManager.info("[Keybinding] Bound feet reset mounting to $feetMountingResetBinding")
val pauseTrackingBinding = config.pauseTrackingBinding
JIntellitype.getInstance()
.registerHotKey(PAUSE_TRACKING, pauseTrackingBinding)
LogManager.info("[Keybinding] Bound pause tracking to $pauseTrackingBinding")
config.keybinds.forEach { (i, keybind) ->
JIntellitype.getInstance()
.registerHotKey(keybind.id, keybind.binding)
}
}
} catch (e: Throwable) {
LogManager
@@ -75,28 +56,33 @@ class Keybinding @AWTThread constructor(val server: VRServer) : HotkeyListener {
globalShortcutsHandler.onShortcutActivated = { shortcutId ->
when (shortcutId) {
"FULL_RESET" -> {
server.scheduleResetTrackersFull(RESET_SOURCE_NAME, config.fullResetDelay.toLong())
val delay = config.keybinds[KeybindId.FULL_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersFull(RESET_SOURCE_NAME, delay)
}
"YAW_RESET" -> {
server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, config.yawResetDelay.toLong())
val delay = config.keybinds[KeybindId.YAW_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, delay)
}
"MOUNTING_RESET" -> {
val delay = config.keybinds[KeybindId.MOUNTING_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
config.mountingResetDelay.toLong(),
delay
)
}
"FEET_MOUNTING_RESET" -> {
val delay = config.keybinds[KeybindId.FEET_MOUNTING_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
config.feetMountingResetDelay.toLong(),
delay,
TrackerUtils.feetsBodyParts,
)
}
"PAUSE_TRACKING" -> {
val delay = config.keybinds[KeybindId.PAUSE_TRACKING]?.delay?.toLong() ?: 0L
server.scheduleTogglePauseTracking(
RESET_SOURCE_NAME,
config.pauseTrackingDelay.toLong(),
delay
)
}
}
@@ -107,27 +93,40 @@ class Keybinding @AWTThread constructor(val server: VRServer) : HotkeyListener {
@AWTThread
override fun onHotKey(identifier: Int) {
when (identifier) {
FULL_RESET -> server.scheduleResetTrackersFull(RESET_SOURCE_NAME, config.fullResetDelay.toLong())
FULL_RESET -> {
val delay = config.keybinds[KeybindId.FULL_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersFull(RESET_SOURCE_NAME, delay)
}
YAW_RESET -> {
val delay = config.keybinds[KeybindId.YAW_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, delay)
}
YAW_RESET -> server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, config.yawResetDelay.toLong())
MOUNTING_RESET -> {
val delay = config.keybinds[KeybindId.FEET_MOUNTING_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
delay,
TrackerUtils.feetsBodyParts,
)
}
MOUNTING_RESET -> server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
config.mountingResetDelay.toLong(),
)
FEET_MOUNTING_RESET -> {
val delay = config.keybinds[KeybindId.FEET_MOUNTING_RESET]?.delay?.toLong() ?: 0L
server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
delay,
TrackerUtils.feetsBodyParts,
)
}
FEET_MOUNTING_RESET -> server.scheduleResetTrackersMounting(
RESET_SOURCE_NAME,
config.feetMountingResetDelay.toLong(),
TrackerUtils.feetsBodyParts,
)
PAUSE_TRACKING ->
server
.scheduleTogglePauseTracking(
RESET_SOURCE_NAME,
config.pauseTrackingDelay.toLong(),
)
PAUSE_TRACKING -> {
val delay = config.keybinds[KeybindId.PAUSE_TRACKING]?.delay?.toLong() ?: 0L
server.scheduleTogglePauseTracking(
RESET_SOURCE_NAME,
delay
)
}
}
}

View File

@@ -1,106 +1,59 @@
package dev.slimevr.config;
package dev.slimevr.config
public class KeybindingsConfig {
import solarxr_protocol.rpc.KeybindId
private String fullResetBinding = "CTRL+ALT+SHIFT+Y";
class KeybindingsConfig {
val keybinds: MutableMap<Int, KeybindData> = mutableMapOf()
private String yawResetBinding = "CTRL+ALT+SHIFT+U";
private String mountingResetBinding = "CTRL+ALT+SHIFT+I";
private String feetMountingResetBinding = "CTRL+ALT+SHIFT+P";
private String pauseTrackingBinding = "CTRL+ALT+SHIFT+O";
private float fullResetDelay = 0L;
private float yawResetDelay = 0L;
private float mountingResetDelay = 0L;
private float feetMountingResetDelay = 0L;
private float pauseTrackingDelay = 0L;
public KeybindingsConfig() {}
public String getFullResetBinding() {
return fullResetBinding;
}
public void setFullResetBinding(String fullResetBinding) {
this.fullResetBinding = fullResetBinding;
}
public String getYawResetBinding() {
return yawResetBinding;
}
public void setYawResetBinding(String yawResetBinding) {
this.yawResetBinding = yawResetBinding;
}
public String getMountingResetBinding() {
return mountingResetBinding;
}
public void setMountingResetBinding(String mountingResetBinding) {
this.mountingResetBinding = mountingResetBinding;
}
public String getFeetMountingResetBinding() {
return feetMountingResetBinding;
}
public void setFeetMountingResetBinding(String feetMountingResetBinding) {
this.feetMountingResetBinding = feetMountingResetBinding;
}
public String getPauseTrackingBinding() {
return pauseTrackingBinding;
}
public void setPauseTrackingBinding(String pauseTrackingBinding) {
this.pauseTrackingBinding = pauseTrackingBinding;
}
public float getFullResetDelay() {
return fullResetDelay;
}
public void setFullResetDelay(float delay) {
fullResetDelay = delay;
}
public float getYawResetDelay() {
return yawResetDelay;
}
public void setYawResetDelay(float delay) {
yawResetDelay = delay;
}
public float getMountingResetDelay() {
return mountingResetDelay;
}
public void setMountingResetDelay(float delay) {
mountingResetDelay = delay;
}
public float getFeetMountingResetDelay() {
return feetMountingResetDelay;
}
public void setFeetMountingResetDelay(float delay) {
feetMountingResetDelay = delay;
}
public float getPauseTrackingDelay() {
return pauseTrackingDelay;
}
public void setPauseTrackingDelay(float delay) {
pauseTrackingDelay = delay;
init {
keybinds[KeybindId.FULL_RESET] =
KeybindData(
KeybindId.FULL_RESET,
"full-reset",
"CTRL+ALT+SHIFT+Y",
0f
)
keybinds[KeybindId.YAW_RESET] =
KeybindData(
KeybindId.YAW_RESET,
"yaw-reset",
"CTRL+ALT+SHIFT+U",
0f
)
keybinds[KeybindId.MOUNTING_RESET] =
KeybindData(
KeybindId.MOUNTING_RESET,
"mounting-reset",
"CTRL+ALT+SHIFT+I",
0f
)
keybinds[KeybindId.FEET_MOUNTING_RESET] =
KeybindData(
KeybindId.FEET_MOUNTING_RESET,
"feet-mounting-reset",
"CTRL+ALT+SHIFT+P",
0f
)
keybinds[KeybindId.PAUSE_TRACKING] =
KeybindData(
KeybindId.PAUSE_TRACKING,
"pause-tracking",
"CTRL+ALT+SHIFT+O",
0f
)
keybinds[KeybindId.TEST] =
KeybindData(
KeybindId.TEST,
"test",
"A+B+C+D",
2f
)
}
}
data class KeybindData(
var id: Int,
var name: String,
var binding: String,
var delay: Float
)

View File

@@ -1,13 +1,9 @@
package dev.slimevr.keybind
import dev.slimevr.VRServer
import dev.slimevr.config.KeybindingsConfig
import solarxr_protocol.rpc.Keybind
import solarxr_protocol.rpc.KeybindName
import solarxr_protocol.rpc.KeybindT
import java.util.concurrent.CopyOnWriteArrayList
class KeybindHandler(val vrServer: VRServer) {
private val listeners: MutableList<KeybindListener> = CopyOnWriteArrayList()
var keybinds: MutableList<KeybindT> = mutableListOf()
@@ -17,7 +13,7 @@ class KeybindHandler(val vrServer: VRServer) {
}
fun sendKeybinds(KeybindName: String) {
this.listeners.forEach { it.sendKeybind()}
this.listeners.forEach { it.sendKeybind() }
}
fun addListener(listener: KeybindListener) {
@@ -30,43 +26,19 @@ class KeybindHandler(val vrServer: VRServer) {
private fun createKeybinds() {
keybinds.clear()
keybinds.add(
KeybindT().apply {
keybindName = KeybindName.FULL_RESET
keybindValue = vrServer.configManager.vrConfig.keybindings.fullResetBinding
keybindDelay = vrServer.configManager.vrConfig.keybindings.fullResetDelay
},
)
keybinds.add(
KeybindT().apply {
keybindName = KeybindName.YAW_RESET
keybindValue = vrServer.configManager.vrConfig.keybindings.yawResetBinding
keybindDelay = vrServer.configManager.vrConfig.keybindings.yawResetDelay
},
)
keybinds.add(
KeybindT().apply {
keybindName = KeybindName.MOUNTING_RESET
keybindValue = vrServer.configManager.vrConfig.keybindings.mountingResetBinding
keybindDelay = vrServer.configManager.vrConfig.keybindings.mountingResetDelay
},
)
keybinds.add(
KeybindT().apply {
keybindName = KeybindName.PAUSE_TRACKING
keybindValue = vrServer.configManager.vrConfig.keybindings.pauseTrackingBinding
keybindDelay = vrServer.configManager.vrConfig.keybindings.pauseTrackingDelay
},
)
keybinds.add(
KeybindT().apply {
keybindName = KeybindName.PAUSE_TRACKING
keybindValue = vrServer.configManager.vrConfig.keybindings.feetMountingResetBinding
keybindDelay = vrServer.configManager.vrConfig.keybindings.feetMountingResetDelay
}
)
vrServer.configManager.vrConfig.keybindings.keybinds.forEach { (i, keybind) ->
keybinds.add(
KeybindT().apply {
keybindId = keybind.id
keybindNameId = keybind.name
keybindValue = keybind.binding
keybindDelay = keybind.delay
},
)
}
}
//TODO: Maybe recreating all the keybinds isn't the best idea?
// TODO: Maybe recreating all the keybinds isn't the best idea?
fun updateKeybinds() {
createKeybinds()
}

View File

@@ -1,13 +1,14 @@
package dev.slimevr.protocol.rpc.keybinds
import com.google.flatbuffers.FlatBufferBuilder
import dev.slimevr.config.KeybindData
import dev.slimevr.keybind.KeybindListener
import dev.slimevr.protocol.GenericConnection
import dev.slimevr.protocol.rpc.RPCHandler
import dev.slimevr.protocol.ProtocolAPI
import jdk.internal.joptsimple.internal.Messages.message
import solarxr_protocol.rpc.ChangeKeybindRequest
import solarxr_protocol.rpc.KeybindName
import solarxr_protocol.rpc.KeybindId
import solarxr_protocol.rpc.KeybindRequest
import solarxr_protocol.rpc.KeybindResponse
import solarxr_protocol.rpc.KeybindResponseT
@@ -55,24 +56,12 @@ class RPCKeybindHandler(
println("Received Keybinds Change request")
val req = (messageHeader.message(ChangeKeybindRequest()) as ChangeKeybindRequest).unpack()
keybindingConfig.fullResetBinding = req.keybind[KeybindName.FULL_RESET].keybindValue
keybindingConfig.fullResetDelay = req.keybind[KeybindName.FULL_RESET].keybindDelay
keybindingConfig.yawResetBinding = req.keybind[KeybindName.YAW_RESET].keybindValue
keybindingConfig.yawResetDelay = req.keybind[KeybindName.YAW_RESET].keybindDelay
keybindingConfig.mountingResetBinding = req.keybind[KeybindName.MOUNTING_RESET].keybindValue
keybindingConfig.mountingResetDelay = req.keybind[KeybindName.MOUNTING_RESET].keybindDelay
keybindingConfig.pauseTrackingBinding = req.keybind[KeybindName.PAUSE_TRACKING].keybindValue
keybindingConfig.pauseTrackingDelay = req.keybind[KeybindName.PAUSE_TRACKING].keybindDelay
keybindingConfig.feetMountingResetBinding = req.keybind[KeybindName.FEET_MOUNTING_RESET].keybindValue
keybindingConfig.feetMountingResetDelay = req.keybind[KeybindName.FEET_MOUNTING_RESET].keybindDelay
keybindingConfig.keybinds[req.keybind.keybindId] = KeybindData(req.keybind.keybindId, req.keybind.keybindNameId, req.keybind.keybindValue, req.keybind.keybindDelay)
api.server.configManager.saveConfig()
api.server.keybindHandler.updateKeybinds()
}
override fun onKeybindUpdate() {
/*
val fbb = FlatBufferBuilder(32)
@@ -92,12 +81,4 @@ class RPCKeybindHandler(
override fun sendKeybind() {
}
companion object {
const val FULL_RESET = KeybindName.FULL_RESET
const val YAW_RESET = KeybindName.YAW_RESET
const val MOUNTING_RESET = KeybindName.MOUNTING_RESET
const val PAUSE_TRACKING = KeybindName.PAUSE_TRACKING
const val FEET_MOUNTING_RESET = KeybindName.FEET_MOUNTING_RESET
}
}