Skip to content

Allow partial/separate resets for feet and fingers #1441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ reset-reset_all_warning_default-v2 =

reset-full = Full Reset
reset-mounting = Reset Mounting
reset-mounting-feet = Reset Mounting Feet
reset-mounting-fingers = Reset Mounting Fingers
reset-yaw = Yaw Reset

## Serial detection stuff
Expand Down
10 changes: 10 additions & 0 deletions gui/src/components/WidgetsComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ export function WidgetsComponent() {
<ResetButton type={ResetType.Full} size="big"></ResetButton>
<ResetButton type={ResetType.Mounting} size="big"></ResetButton>
<ClearMountingButton></ClearMountingButton>
<ResetButton
type={ResetType.Mounting}
size="big"
bodyPartsToReset="feet"
></ResetButton>
<ResetButton
type={ResetType.Mounting}
size="big"
bodyPartsToReset="fingers"
></ResetButton>
<BVHButton></BVHButton>
<TrackingPauseButton></TrackingPauseButton>
<ClearDriftCompensationButton
Expand Down
64 changes: 60 additions & 4 deletions gui/src/components/home/ResetButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useLocalization } from '@fluent/react';
import { useEffect, useMemo, useRef, useState } from 'react';
import {
BodyPart,
ResetRequestT,
ResetType,
RpcMessage,
Expand All @@ -26,12 +27,14 @@ import classNames from 'classnames';
export function ResetButton({
type,
size = 'big',
bodyPartsToReset = 'default',
className,
onReseted,
}: {
className?: string;
type: ResetType;
size: 'big' | 'small';
bodyPartsToReset?: 'default' | 'feet' | 'fingers';
onReseted?: () => void;
}) {
const { l10n } = useLocalization();
Expand All @@ -50,9 +53,53 @@ export function ResetButton({
[statuses]
);

const feetBodyParts = [BodyPart.LEFT_FOOT, BodyPart.RIGHT_FOOT];
const fingerBodyParts = [
BodyPart.LEFT_THUMB_METACARPAL,
BodyPart.LEFT_THUMB_PROXIMAL,
BodyPart.LEFT_THUMB_DISTAL,
BodyPart.LEFT_INDEX_PROXIMAL,
BodyPart.LEFT_INDEX_INTERMEDIATE,
BodyPart.LEFT_INDEX_DISTAL,
BodyPart.LEFT_MIDDLE_PROXIMAL,
BodyPart.LEFT_MIDDLE_INTERMEDIATE,
BodyPart.LEFT_MIDDLE_DISTAL,
BodyPart.LEFT_RING_PROXIMAL,
BodyPart.LEFT_RING_INTERMEDIATE,
BodyPart.LEFT_RING_DISTAL,
BodyPart.LEFT_LITTLE_PROXIMAL,
BodyPart.LEFT_LITTLE_INTERMEDIATE,
BodyPart.LEFT_LITTLE_DISTAL,
BodyPart.RIGHT_THUMB_METACARPAL,
BodyPart.RIGHT_THUMB_PROXIMAL,
BodyPart.RIGHT_THUMB_DISTAL,
BodyPart.RIGHT_INDEX_PROXIMAL,
BodyPart.RIGHT_INDEX_INTERMEDIATE,
BodyPart.RIGHT_INDEX_DISTAL,
BodyPart.RIGHT_MIDDLE_PROXIMAL,
BodyPart.RIGHT_MIDDLE_INTERMEDIATE,
BodyPart.RIGHT_MIDDLE_DISTAL,
BodyPart.RIGHT_RING_PROXIMAL,
BodyPart.RIGHT_RING_INTERMEDIATE,
BodyPart.RIGHT_RING_DISTAL,
BodyPart.RIGHT_LITTLE_PROXIMAL,
BodyPart.RIGHT_LITTLE_INTERMEDIATE,
BodyPart.RIGHT_LITTLE_DISTAL,
];

const reset = () => {
const req = new ResetRequestT();
req.resetType = type;
if (bodyPartsToReset == 'default') {
// Default (server handles it)
req.bodyParts = [];
} else if (bodyPartsToReset == 'feet') {
// Feet
req.bodyParts = feetBodyParts;
} else if (bodyPartsToReset == 'fingers') {
// Fingers
req.bodyParts = fingerBodyParts;
}
sendRPCPacket(RpcMessage.ResetRequest, req);
};

Expand All @@ -75,13 +122,22 @@ export function ResetButton({
const text = useMemo(() => {
switch (type) {
case ResetType.Yaw:
return l10n.getString('reset-yaw');
return l10n.getString(
'reset-yaw' +
(bodyPartsToReset != 'default' ? '-' + bodyPartsToReset : '')
);
case ResetType.Mounting:
return l10n.getString('reset-mounting');
return l10n.getString(
'reset-mounting' +
(bodyPartsToReset != 'default' ? '-' + bodyPartsToReset : '')
);
case ResetType.Full:
return l10n.getString('reset-full');
return l10n.getString(
'reset-full' +
(bodyPartsToReset != 'default' ? '-' + bodyPartsToReset : '')
);
}
}, [type]);
}, [type, bodyPartsToReset]);

const getIcon = () => {
switch (type) {
Expand Down
22 changes: 0 additions & 22 deletions gui/src/components/settings/pages/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ interface SettingsForm {
correctionStrength: number;
};
resetsSettings: {
resetMountingFeet: boolean;
armsMountingResetMode: number;
yawResetSmoothTime: number;
saveMountingReset: boolean;
Expand Down Expand Up @@ -163,7 +162,6 @@ const defaultValues: SettingsForm = {
},
legTweaks: { correctionStrength: 0.3 },
resetsSettings: {
resetMountingFeet: false,
armsMountingResetMode: 0,
yawResetSmoothTime: 0.0,
saveMountingReset: false,
Expand Down Expand Up @@ -299,8 +297,6 @@ export function GeneralSettings() {

if (values.resetsSettings) {
const resetsSettings = new ResetsSettingsT();
resetsSettings.resetMountingFeet =
values.resetsSettings.resetMountingFeet;
resetsSettings.armsMountingResetMode =
values.resetsSettings.armsMountingResetMode;
resetsSettings.yawResetSmoothTime =
Expand Down Expand Up @@ -970,24 +966,6 @@ export function GeneralSettings() {
)}
/>
</div>
<div className="flex flex-col pt-2 pb-3">
<Typography color="secondary">
{l10n.getString(
'settings-general-fk_settings-leg_fk-reset_mounting_feet-description'
)}
</Typography>
</div>
<div className="grid sm:grid-cols-1 gap-3 pb-3">
<CheckBox
variant="toggle"
outlined
control={control}
name="resetsSettings.resetMountingFeet"
label={l10n.getString(
'settings-general-fk_settings-leg_fk-reset_mounting_feet'
)}
/>
</div>

<Typography color="secondary">
{l10n.getString(
Expand Down
13 changes: 7 additions & 6 deletions server/core/src/main/java/dev/slimevr/VRServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import java.util.*
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Consumer
import kotlin.collections.ArrayList
import kotlin.concurrent.schedule

typealias BridgeProvider = (
Expand Down Expand Up @@ -297,16 +298,16 @@ class VRServer @JvmOverloads constructor(
}
}

fun resetTrackersFull(resetSourceName: String?) {
queueTask { humanPoseManager.resetTrackersFull(resetSourceName) }
fun resetTrackersFull(resetSourceName: String?, bodyParts: List<Int> = ArrayList()) {
queueTask { humanPoseManager.resetTrackersFull(resetSourceName, bodyParts) }
}

fun resetTrackersYaw(resetSourceName: String?) {
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName) }
fun resetTrackersYaw(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName, bodyParts) }
}

fun resetTrackersMounting(resetSourceName: String?) {
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName) }
fun resetTrackersMounting(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFeetAndFingers) {
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName, bodyParts) }
}

fun clearTrackersMounting(resetSourceName: String?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ enum class ArmsResetModes(val id: Int) {

class ResetsConfig {

// Enable mounting reset for feet?
var resetMountingFeet = false

// Reset mode used for the arms
var mode = ArmsResetModes.BACK

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,37 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
fun onResetRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
val req = messageHeader.message(ResetRequest()) as? ResetRequest ?: return

if (req.resetType() == ResetType.Yaw) api.server.resetTrackersYaw(RESET_SOURCE_NAME)
if (req.resetType() == ResetType.Full) api.server.resetTrackersFull(RESET_SOURCE_NAME)
if (req.resetType() == ResetType.Mounting) api.server.resetTrackersMounting(RESET_SOURCE_NAME)
// Get the list of bodyparts we want to reset
// If empty, check in HumanSkeleton will reset all
val bodyParts = mutableListOf<Int>()
if (req.bodyPartsLength() > 0) {
val buffer = req.bodyPartsAsByteBuffer()
while (buffer.hasRemaining()) {
bodyParts.add(buffer.get().toInt())
}
}

if (req.resetType() == ResetType.Yaw) {
if (bodyParts.isEmpty()) {
api.server.resetTrackersYaw(RESET_SOURCE_NAME)
} else {
api.server.resetTrackersYaw(RESET_SOURCE_NAME, bodyParts.toList())
}
}
if (req.resetType() == ResetType.Full) {
if (bodyParts.isEmpty()) {
api.server.resetTrackersFull(RESET_SOURCE_NAME)
} else {
api.server.resetTrackersFull(RESET_SOURCE_NAME, bodyParts.toList())
}
}
if (req.resetType() == ResetType.Mounting) {
if (bodyParts.isEmpty()) {
api.server.resetTrackersMounting(RESET_SOURCE_NAME)
} else {
api.server.resetTrackersMounting(RESET_SOURCE_NAME, bodyParts.toList())
}
}
}

fun onClearMountingResetRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ public static int createArmsResetModeSettings(
return ResetsSettings
.createResetsSettings(
fbb,
resetsConfig.getResetMountingFeet(),
resetsConfig.getMode().getId(),
resetsConfig.getYawResetSmoothTime(),
resetsConfig.getSaveMountingReset(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
if (mode != null) {
resetsConfig.mode = mode
}
resetsConfig.resetMountingFeet = req.resetsSettings().resetMountingFeet()
resetsConfig.saveMountingReset = req.resetsSettings().saveMountingReset()
resetsConfig.yawResetSmoothTime = req.resetsSettings().yawResetSmoothTime()
resetsConfig.resetHmdPitch = req.resetsSettings().resetHmdPitch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import dev.slimevr.tracking.processor.config.SkeletonConfigOffsets
import dev.slimevr.tracking.processor.config.SkeletonConfigToggles
import dev.slimevr.tracking.processor.config.SkeletonConfigValues
import dev.slimevr.tracking.processor.skeleton.HumanSkeleton
import dev.slimevr.tracking.trackers.Tracker
import dev.slimevr.tracking.trackers.TrackerPosition
import dev.slimevr.tracking.trackers.TrackerRole
import dev.slimevr.tracking.trackers.TrackerStatus
import dev.slimevr.tracking.trackers.*
import dev.slimevr.trackingpause.TrackingPauseHandler
import dev.slimevr.util.ann.VRServerThread
import io.eiren.util.ann.ThreadSafe
Expand Down Expand Up @@ -482,8 +479,9 @@ class HumanPoseManager(val server: VRServer?) {
skeletonConfigManager.computeNodeOffset(node)
}

fun resetTrackersFull(resetSourceName: String?) {
skeleton.resetTrackersFull(resetSourceName)
@JvmOverloads
fun resetTrackersFull(resetSourceName: String?, bodyParts: List<Int> = ArrayList()) {
skeleton.resetTrackersFull(resetSourceName, bodyParts)
if (server != null) {
if (skeleton.headTracker == null && skeleton.neckTracker == null) {
server.vrcOSCHandler.yawAlign(IDENTITY)
Expand All @@ -498,8 +496,9 @@ class HumanPoseManager(val server: VRServer?) {
}
}

fun resetTrackersYaw(resetSourceName: String?) {
skeleton.resetTrackersYaw(resetSourceName)
@JvmOverloads
fun resetTrackersYaw(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
skeleton.resetTrackersYaw(resetSourceName, bodyParts)
if (server != null) {
if (skeleton.headTracker == null && skeleton.neckTracker == null) {
server.vrcOSCHandler.yawAlign(IDENTITY)
Expand Down Expand Up @@ -571,8 +570,9 @@ class HumanPoseManager(val server: VRServer?) {
}
}

fun resetTrackersMounting(resetSourceName: String?) {
skeleton.resetTrackersMounting(resetSourceName)
@JvmOverloads
fun resetTrackersMounting(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFeetAndFingers) {
skeleton.resetTrackersMounting(resetSourceName, bodyParts)
}

fun clearTrackersMounting(resetSourceName: String?) {
Expand Down
Loading