Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ settings-general-fk_settings-self_localization-description = Mocap Mode allows t
## Gesture control settings (tracker tapping)
settings-general-gesture_control = Gesture control
settings-general-gesture_control-subtitle = Tap based resets
settings-general-gesture_control-description = Allows for resets to be triggered by tapping a tracker. The tracker highest up on your torso is used for Yaw Reset, the tracker highest up on your left leg is used for Full Reset, and the tracker highest up on your right leg is used for Mounting Calibration. Taps must occur within the time limit of 0.3 seconds times the number of taps to be recognized.
settings-general-gesture_control-description = Allows for resets to be triggered by tapping a tracker. Taps must occur within the time limit of 0.3 seconds times the number of taps to be recognized.
# This is a unit: 3 taps, 2 taps, 1 tap
# $amount (Number) - Amount of taps (touches to the tracker's case)
settings-general-gesture_control-taps = { $amount ->
Expand All @@ -687,12 +687,17 @@ settings-general-gesture_control-trackers = { $amount ->
settings-general-gesture_control-yawResetEnabled = Enable tap to yaw reset
settings-general-gesture_control-yawResetDelay = Yaw reset delay
settings-general-gesture_control-yawResetTaps = Taps for yaw reset
settings-general-gesture_control-yawResetTracker = Yaw Reset Tracker
settings-general-gesture_control-fullResetEnabled = Enable tap to full reset
settings-general-gesture_control-fullResetDelay = Full reset delay
settings-general-gesture_control-fullResetTaps = Taps for full reset
settings-general-gesture_control-fullResetTracker = Full Reset Tracker
settings-general-gesture_control-mountingResetEnabled = Enable tap to perform mounting calibration
settings-general-gesture_control-mountingResetDelay = Mounting calibration delay
settings-general-gesture_control-mountingResetTaps = Taps for mounting calibration
settings-general-gesture_control-mountingResetTracker = Mounting Reset Tracker
settings-general-gesture_control-yawResetTracker-title = Yaw Reset Tracker
settings-general-gesture_control-fullResetTracker-title = Full Reset Tracker
# The number of trackers that can have higher acceleration before a tap is rejected
settings-general-gesture_control-numberTrackersOverThreshold = Trackers over threshold
settings-general-gesture_control-numberTrackersOverThreshold-description = Increase this value if tap detection is not working. Do not increase it above what is needed to make tap detection work as it would cause more false positives.
Expand Down
2 changes: 1 addition & 1 deletion gui/src/components/commons/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ArrowDownIcon, ArrowUpIcon } from './icon/ArrowIcons';
import { a11yClick } from '@/utils/a11y';
import { createPortal } from 'react-dom';

type DropdownItem = {
export type DropdownItem = {
value: string;
label: ReactNode;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ export function TrackersAssignPage() {
tapDetectionSettings.mountingResetDelay,
tapDetectionSettings.mountingResetEnabled,
tapDetectionSettings.mountingResetTaps,
true
true,
null,
tapDetectionSettings.yawResetTracker,
tapDetectionSettings.fullResetTracker,
tapDetectionSettings.mountingResetTracker
);

sendRPCPacket(
Expand Down
139 changes: 111 additions & 28 deletions gui/src/components/settings/pages/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SteamVRTrackersSettingT,
TapDetectionSettingsT,
HIDSettingsT,
BodyPart,
} from 'solarxr-protocol';
import { useConfig } from '@/hooks/config';
import { useWebsocketAPI } from '@/hooks/websocket-api';
Expand Down Expand Up @@ -46,6 +47,8 @@ import {
import { atom, useAtomValue, useSetAtom } from 'jotai';
import { isEqual } from '@react-hookz/deep-equal';
import { selectAtom } from 'jotai/utils';
import { Dropdown } from '@/components/commons/Dropdown';
import { ASSIGNMENT_MODES } from '@/components/onboarding/BodyAssignment';

export type SettingsForm = {
trackers: {
Expand Down Expand Up @@ -99,6 +102,9 @@ export type SettingsForm = {
fullResetTaps: number;
mountingResetTaps: number;
numberTrackersOverThreshold: number;
yawResetTracker: string;
mountingResetTracker: string;
fullResetTracker: string;
};
legTweaks: {
correctionStrength: number;
Expand Down Expand Up @@ -159,6 +165,9 @@ const defaultValues: SettingsForm = {
fullResetTaps: 3,
mountingResetTaps: 3,
numberTrackersOverThreshold: 1,
yawResetTracker: String(BodyPart.CHEST),
mountingResetTracker: String(BodyPart.RIGHT_UPPER_LEG),
fullResetTracker: String(BodyPart.LEFT_UPPER_LEG),
},
legTweaks: { correctionStrength: 0.3 },
resetsSettings: defaultResetSettings,
Expand All @@ -180,6 +189,13 @@ export function GeneralSettings() {
const { config } = useConfig();
const { currentLocales } = useLocaleConfig();

const bodyParts: { value: string; label: string }[] = Object.values(BodyPart)
.filter((v): v is BodyPart => typeof v === 'number')
.filter((v) => ASSIGNMENT_MODES['full-body'].includes(v as BodyPart))
.map((value) => ({
value: String(value),
label: l10n.getString(`body_part-${BodyPart[value]}`),
}));
const blockHandsWarning = useRef(false);
// If not null, warning will be shown, and showHandsWarning will
// hold which hands should be toggled ([leftHand, rightHand])
Expand Down Expand Up @@ -305,6 +321,15 @@ export function GeneralSettings() {
tapDetection.yawResetDelay = values.tapDetection.yawResetDelay;
tapDetection.yawResetEnabled = values.tapDetection.yawResetEnabled;
tapDetection.yawResetTaps = values.tapDetection.yawResetTaps;
tapDetection.yawResetTracker = Number(values.tapDetection.yawResetTracker);
console.log(tapDetection.yawResetTracker);
tapDetection.mountingResetTracker = Number(
values.tapDetection.mountingResetTracker
);
console.log(tapDetection.mountingResetTracker);
tapDetection.fullResetTracker = Number(
values.tapDetection.fullResetTracker
);
tapDetection.mountingResetEnabled =
values.tapDetection.mountingResetEnabled;
tapDetection.mountingResetDelay = values.tapDetection.mountingResetDelay;
Expand Down Expand Up @@ -416,6 +441,18 @@ export function GeneralSettings() {
mountingResetTaps:
settings.tapDetectionSettings.mountingResetTaps ||
defaultValues.tapDetection.mountingResetTaps,
yawResetTracker: String(
settings.tapDetectionSettings.yawResetTracker ||
defaultValues.tapDetection.yawResetTracker
),
fullResetTracker: String(
settings.tapDetectionSettings.fullResetTracker ||
defaultValues.tapDetection.fullResetTracker
),
mountingResetTracker: String(
settings.tapDetectionSettings.mountingResetTracker ||
defaultValues.tapDetection.mountingResetTracker
),
numberTrackersOverThreshold:
settings.tapDetectionSettings.numberTrackersOverThreshold ||
defaultValues.tapDetection.numberTrackersOverThreshold,
Expand Down Expand Up @@ -1208,34 +1245,80 @@ export function GeneralSettings() {
{l10n.getString('settings-general-gesture_control-description')}
</Typography>
</div>
<div className="grid sm:grid-cols-3 gap-5 pb-2">
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.yawResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-yawResetEnabled'
)}
/>
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.fullResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-fullResetEnabled'
)}
/>
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.mountingResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-mountingResetEnabled'
)}
/>
<div>
<div className="grid sm:grid-cols-3 gap-5 pb-2">
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.yawResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-yawResetEnabled'
)}
/>
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.fullResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-fullResetEnabled'
)}
/>
<CheckBox
variant="toggle"
outlined
control={control}
name="tapDetection.mountingResetEnabled"
label={l10n.getString(
'settings-general-gesture_control-mountingResetEnabled'
)}
/>
</div>
<div className="grid sm:grid-cols-3 gap-5 pb-2">
<div>
<Typography variant="section-title">
{l10n.getString(
'settings-general-gesture_control-yawResetTracker'
)}
</Typography>
<Dropdown
display="block"
control={control}
placeholder={''}
name="tapDetection.yawResetTracker"
items={bodyParts}
/>
</div>
<div>
<Typography variant="section-title">
{l10n.getString(
'settings-general-gesture_control-mountingResetTracker'
)}
</Typography>
<Dropdown
display="block"
control={control}
placeholder={''}
name="tapDetection.mountingResetTracker"
items={bodyParts}
/>
</div>
<div>
<Typography variant="section-title">
{l10n.getString(
'settings-general-gesture_control-fullResetTracker'
)}
</Typography>
<Dropdown
display="block"
control={control}
placeholder={''}
name="tapDetection.fullResetTracker"
items={bodyParts}
/>
</div>
</div>
</div>
<div className="grid sm:grid-cols-3 gap-5 pb-2">
<NumberSelector
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.slimevr.config

import com.jme3.math.FastMath
import dev.slimevr.tracking.trackers.TrackerPosition

// handles the tap detection config
// this involves the number of taps, the delay, and whether or not the feature is enabled
Expand All @@ -12,6 +12,9 @@ class TapDetectionConfig {
var yawResetEnabled = true
var fullResetEnabled = true
var mountingResetEnabled = true
var yawResetTracker = TrackerPosition.CHEST
var mountingResetTracker = TrackerPosition.RIGHT_UPPER_LEG
var fullResetTracker = TrackerPosition.LEFT_UPPER_LEG
var setupMode = false
var yawResetTaps = 2
set(yawResetTaps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ fun createTapDetectionSettings(
tapDetectionConfig.mountingResetTaps,
tapDetectionConfig.setupMode,
tapDetectionConfig.numberTrackersOverThreshold,
0,
0,
0,
tapDetectionConfig.yawResetTracker.bodyPart,
tapDetectionConfig.fullResetTracker.bodyPart,
tapDetectionConfig.mountingResetTracker.bodyPart,
)

fun createSteamVRSettings(fbb: FlatBufferBuilder, bridge: ISteamVRBridge?): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import dev.slimevr.protocol.ProtocolAPI
import dev.slimevr.protocol.rpc.RPCHandler
import dev.slimevr.tracking.processor.config.SkeletonConfigToggles
import dev.slimevr.tracking.processor.config.SkeletonConfigValues
import dev.slimevr.tracking.trackers.TrackerPosition
import dev.slimevr.tracking.trackers.TrackerRole
import solarxr_protocol.rpc.ChangeSettingsRequest
import solarxr_protocol.rpc.RpcMessage
Expand Down Expand Up @@ -159,6 +160,10 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
.mountingResetEnabled = tapDetectionSettings.mountingResetEnabled()
tapDetectionConfig.setupMode = tapDetectionSettings.setupMode()

tapDetectionConfig.yawResetTracker = TrackerPosition.getByBodyPart(tapDetectionSettings.yawResetTracker()) ?: TrackerPosition.CHEST
tapDetectionConfig.fullResetTracker = TrackerPosition.getByBodyPart(tapDetectionSettings.fullResetTracker()) ?: TrackerPosition.LEFT_UPPER_LEG
tapDetectionConfig.mountingResetTracker = TrackerPosition.getByBodyPart(tapDetectionSettings.mountingResetTracker()) ?: TrackerPosition.RIGHT_UPPER_LEG

// set number of trackers that can have high accel before taps
// are rejected
if (tapDetectionSettings.hasNumberTrackersOverThreshold()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package dev.slimevr.tracking.processor.skeleton
import dev.slimevr.VRServer
import dev.slimevr.tracking.processor.HumanPoseManager
import dev.slimevr.tracking.trackers.Tracker
import dev.slimevr.tracking.trackers.TrackerPosition
import dev.slimevr.tracking.trackers.TrackerUtils
import io.eiren.util.logging.LogManager
import java.util.concurrent.CopyOnWriteArrayList

class TapDetectionManager(
Expand Down Expand Up @@ -69,6 +72,7 @@ class TapDetectionManager(
tapDetectors.clear()
registerSingleTapDetectors()
registerResetsDetectors()
LogManager.info(yawResetTracker.toString())
}

fun update() {
Expand All @@ -88,26 +92,29 @@ class TapDetectionManager(
private val mountingResetTracker: Tracker?
get() {
return arrayOf(
skeleton.rightUpperLegTracker,
skeleton.rightLowerLegTracker,
TrackerUtils.getTrackerForSkeleton(server.allTrackers, config.mountingResetTracker),
if (config.yawResetTracker !== TrackerPosition.RIGHT_UPPER_LEG && config.fullResetTracker !== TrackerPosition.RIGHT_UPPER_LEG) skeleton.rightUpperLegTracker else null,
if (config.yawResetTracker !== TrackerPosition.RIGHT_LOWER_LEG && config.fullResetTracker !== TrackerPosition.RIGHT_LOWER_LEG) skeleton.rightLowerLegTracker else null,
).firstNotNullOfOrNull { it }
}

private val fullResetTracker: Tracker?
get() {
return arrayOf(
skeleton.leftUpperLegTracker,
skeleton.leftLowerLegTracker,
TrackerUtils.getTrackerForSkeleton(server.allTrackers, config.fullResetTracker),
if (config.yawResetTracker !== TrackerPosition.LEFT_UPPER_LEG && config.mountingResetTracker !== TrackerPosition.LEFT_UPPER_LEG) skeleton.leftUpperLegTracker else null,
if (config.yawResetTracker !== TrackerPosition.LEFT_LOWER_LEG && config.mountingResetTracker !== TrackerPosition.LEFT_LOWER_LEG) skeleton.leftLowerLegTracker else null,
).firstNotNullOfOrNull { it }
}

private val yawResetTracker: Tracker?
get() {
return arrayOf(
skeleton.upperChestTracker,
skeleton.chestTracker,
skeleton.hipTracker,
skeleton.waistTracker,
TrackerUtils.getTrackerForSkeleton(server.allTrackers, config.yawResetTracker),
if (config.fullResetTracker !== TrackerPosition.UPPER_CHEST && config.mountingResetTracker !== TrackerPosition.UPPER_CHEST) skeleton.upperChestTracker else null,
if (config.fullResetTracker !== TrackerPosition.CHEST && config.mountingResetTracker !== TrackerPosition.CHEST) skeleton.chestTracker else null,
if (config.fullResetTracker !== TrackerPosition.HIP && config.mountingResetTracker !== TrackerPosition.HIP) skeleton.hipTracker else null,
if (config.fullResetTracker !== TrackerPosition.WAIST && config.mountingResetTracker !== TrackerPosition.WAIST) skeleton.waistTracker else null,
).firstNotNullOfOrNull { it }
}

Expand Down