Skip to content

Commit

Permalink
Add pause tracking keybind & protobuf command (SlimeVR#867)
Browse files Browse the repository at this point in the history
  • Loading branch information
ButterscotchV authored Nov 18, 2023
1 parent 25bd050 commit eefe7ef
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 25 deletions.
25 changes: 20 additions & 5 deletions gui/src/components/TrackingPauseButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { SetPauseTrackingRequestT, RpcMessage } from 'solarxr-protocol';
import {
SetPauseTrackingRequestT,
RpcMessage,
TrackingPauseStateResponseT,
TrackingPauseStateRequestT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { PlayIcon } from './commons/icon/PlayIcon';
Expand All @@ -10,16 +15,26 @@ export function TrackingPauseButton(
props: React.HTMLAttributes<HTMLButtonElement>
) {
const { l10n } = useLocalization();
const { sendRPCPacket } = useWebsocketAPI();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [trackingPause, setTrackingPause] = useState(false);

const toggleTracking = () => {
const pause = new SetPauseTrackingRequestT();
pause.pauseTracking = !trackingPause;
setTrackingPause(pause.pauseTracking);
const pause = new SetPauseTrackingRequestT(!trackingPause);
sendRPCPacket(RpcMessage.SetPauseTrackingRequest, pause);
};

useRPCPacket(
RpcMessage.TrackingPauseStateResponse,
(data: TrackingPauseStateResponseT) => {
setTrackingPause(data.trackingPaused);
}
);

sendRPCPacket(
RpcMessage.TrackingPauseStateRequest,
new TrackingPauseStateRequestT()
);

return (
<BigButton
text={l10n.getString(
Expand Down
12 changes: 12 additions & 0 deletions server/core/src/main/java/dev/slimevr/Keybinding.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Keybinding implements HotkeyListener {
private static final int FULL_RESET = 1;
private static final int YAW_RESET = 2;
private static final int MOUNTING_RESET = 3;
private static final int PAUSE_TRACKING = 4;
public final VRServer server;
public final KeybindingsConfig config;

Expand Down Expand Up @@ -47,6 +48,10 @@ public Keybinding(VRServer server) {
String mountingResetBinding = this.config.getMountingResetBinding();
JIntellitype.getInstance().registerHotKey(MOUNTING_RESET, mountingResetBinding);
LogManager.info("[Keybinding] Bound reset mounting to " + mountingResetBinding);

String pauseTrackingBinding = this.config.getPauseTrackingBinding();
JIntellitype.getInstance().registerHotKey(PAUSE_TRACKING, pauseTrackingBinding);
LogManager.info("[Keybinding] Bound pause tracking to " + pauseTrackingBinding);
}
} catch (Throwable e) {
LogManager
Expand Down Expand Up @@ -76,6 +81,13 @@ public void onHotKey(int identifier) {
this.config.getMountingResetDelay()
);
}
case PAUSE_TRACKING -> {
server
.scheduleTogglePauseTracking(
resetSourceName,
this.config.getPauseTrackingDelay()
);
}
}
}
}
42 changes: 27 additions & 15 deletions server/core/src/main/java/dev/slimevr/VRServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import java.util.*
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Consumer
import kotlin.concurrent.schedule

typealias SteamBridgeProvider = (
server: VRServer,
Expand Down Expand Up @@ -297,31 +298,42 @@ class VRServer @JvmOverloads constructor(
queueTask { humanPoseManager.clearTrackersMounting(resetSourceName) }
}

fun setPauseTracking(pauseTracking: Boolean, sourceName: String?) {
queueTask { humanPoseManager.setPauseTracking(pauseTracking, sourceName) }
}

fun togglePauseTracking(sourceName: String?) {
queueTask { humanPoseManager.togglePauseTracking(sourceName) }
}

fun scheduleResetTrackersFull(resetSourceName: String?, delay: Long) {
val resetTask: TimerTask = object : TimerTask() {
override fun run() {
queueTask { humanPoseManager.resetTrackersFull(resetSourceName) }
}
timer.schedule(delay) {
queueTask { humanPoseManager.resetTrackersFull(resetSourceName) }
}
timer.schedule(resetTask, delay)
}

fun scheduleResetTrackersYaw(resetSourceName: String?, delay: Long) {
val yawResetTask: TimerTask = object : TimerTask() {
override fun run() {
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName) }
}
timer.schedule(delay) {
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName) }
}
timer.schedule(yawResetTask, delay)
}

fun scheduleResetTrackersMounting(resetSourceName: String?, delay: Long) {
val resetMountingTask: TimerTask = object : TimerTask() {
override fun run() {
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName) }
}
timer.schedule(delay) {
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName) }
}
}

fun scheduleSetPauseTracking(pauseTracking: Boolean, sourceName: String?, delay: Long) {
timer.schedule(delay) {
queueTask { humanPoseManager.setPauseTracking(pauseTracking, sourceName) }
}
}

fun scheduleTogglePauseTracking(sourceName: String?, delay: Long) {
timer.schedule(delay) {
queueTask { humanPoseManager.togglePauseTracking(sourceName) }
}
timer.schedule(resetMountingTask, delay)
}

fun setLegTweaksEnabled(value: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ public class KeybindingsConfig {

private String mountingResetBinding = "CTRL+ALT+SHIFT+I";

private String pauseTrackingBinding = "CTRL+ALT+SHIFT+O";

private long fullResetDelay = 0L;

private long yawResetDelay = 0L;

private long mountingResetDelay = 0L;

private long pauseTrackingDelay = 0L;


public KeybindingsConfig() {
}
Expand All @@ -30,6 +34,10 @@ public String getMountingResetBinding() {
return mountingResetBinding;
}

public String getPauseTrackingBinding() {
return pauseTrackingBinding;
}

public long getFullResetDelay() {
return fullResetDelay;
}
Expand All @@ -53,4 +61,12 @@ public long getMountingResetDelay() {
public void setMountingResetDelay(long delay) {
mountingResetDelay = delay;
}

public long getPauseTrackingDelay() {
return pauseTrackingDelay;
}

public void setPauseTrackingDelay(long delay) {
pauseTrackingDelay = delay;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import dev.slimevr.protocol.rpc.setup.RPCTapSetupHandler;
import dev.slimevr.protocol.rpc.setup.RPCUtil;
import dev.slimevr.protocol.rpc.status.RPCStatusHandler;
import dev.slimevr.protocol.rpc.trackingpause.RPCTrackingPause;
import dev.slimevr.tracking.processor.config.SkeletonConfigOffsets;
import dev.slimevr.tracking.trackers.Tracker;
import dev.slimevr.tracking.trackers.TrackerPosition;
Expand Down Expand Up @@ -46,6 +47,7 @@ public RPCHandler(ProtocolAPI api) {
new RPCTapSetupHandler(this, api);
new RPCStatusHandler(this, api);
new RPCAutoBoneHandler(this, api);
new RPCTrackingPause(this, api);

registerPacketListener(RpcMessage.ResetRequest, this::onResetRequest);
registerPacketListener(
Expand Down Expand Up @@ -379,7 +381,7 @@ public void onSetPauseTrackingRequest(GenericConnection conn, RpcMessageHeader m
if (req == null)
return;

this.api.server.humanPoseManager.setPauseTracking(req.pauseTracking());
this.api.server.humanPoseManager.setPauseTracking(req.pauseTracking(), resetSourceName);
}

public void onHeightRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.slimevr.protocol.rpc.trackingpause

import com.google.flatbuffers.FlatBufferBuilder
import dev.slimevr.protocol.GenericConnection
import dev.slimevr.protocol.ProtocolAPI
import dev.slimevr.protocol.rpc.RPCHandler
import dev.slimevr.trackingpause.TrackingPauseListener
import solarxr_protocol.rpc.RpcMessage
import solarxr_protocol.rpc.RpcMessageHeader
import solarxr_protocol.rpc.TrackingPauseStateResponse
import java.nio.ByteBuffer

class RPCTrackingPause(private val rpcHandler: RPCHandler, private val api: ProtocolAPI) : TrackingPauseListener {

private val currentPauseState
get() = api.server.humanPoseManager.skeleton.getPauseTracking()

init {
rpcHandler.registerPacketListener(
RpcMessage.TrackingPauseStateRequest,
::onTrackingPauseStateRequest
)

// HumanPoseManager might not be immediately available, so queue the server
// to register the listener once it's fully initialized
api.server.queueTask {
api.server.humanPoseManager.trackingPauseHandler.addListener(this)
}
}

private fun getPauseStateResponse(trackingPaused: Boolean): ByteBuffer {
val fbb = FlatBufferBuilder(32)
val state = TrackingPauseStateResponse.createTrackingPauseStateResponse(fbb, trackingPaused)
val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.TrackingPauseStateResponse, state)
fbb.finish(outbound)
return fbb.dataBuffer()
}

private fun onTrackingPauseStateRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
conn.send(getPauseStateResponse(currentPauseState))
}

override fun onTrackingPause(trackingPaused: Boolean) {
val pauseState = getPauseStateResponse(trackingPaused)
forAllListeners { it.send(pauseState) }
}

private fun forAllListeners(action: (GenericConnection) -> Unit) {
api.apiServers.forEach {
it.apiConnections.forEach(action)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import dev.slimevr.tracking.trackers.TrackerPosition;
import dev.slimevr.tracking.trackers.TrackerRole;
import dev.slimevr.tracking.trackers.TrackerStatus;
import dev.slimevr.trackingpause.TrackingPauseHandler;
import dev.slimevr.util.ann.VRServerThread;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
Expand All @@ -36,6 +37,7 @@ public class HumanPoseManager {
private final SkeletonConfigManager skeletonConfigManager;
private HumanSkeleton skeleton;
private long timeAtLastReset;
public final TrackingPauseHandler trackingPauseHandler = new TrackingPauseHandler();

// #region Constructors
private HumanPoseManager() {
Expand Down Expand Up @@ -813,9 +815,15 @@ public float getUserHeightFromConfig() {
}
// #endregion

public void setPauseTracking(boolean pauseTracking) {
public void setPauseTracking(boolean pauseTracking, String sourceName) {
if (isSkeletonPresent())
skeleton.setPauseTracking(pauseTracking);
skeleton.setPauseTracking(pauseTracking, sourceName);
}

public boolean togglePauseTracking(String sourceName) {
if (isSkeletonPresent())
return skeleton.togglePauseTracking(sourceName);
return false;
}
// #endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -1210,12 +1210,21 @@ class HumanSkeleton(
return pauseTracking
}

fun setPauseTracking(pauseTracking: Boolean) {
fun setPauseTracking(pauseTracking: Boolean, sourceName: String?) {
if (!pauseTracking && this.pauseTracking) {
// If unpausing tracking, clear the legtweaks buffer
legTweaks.resetBuffer()
}
this.pauseTracking = pauseTracking
LogManager.info(String.format("[HumanSkeleton] ${if (pauseTracking) "Pause" else "Unpause"} tracking (%s)", sourceName))
// Report the new state of tracking pause
humanPoseManager.trackingPauseHandler.sendTrackingPauseState(pauseTracking)
}

fun togglePauseTracking(sourceName: String?): Boolean {
val newState = !pauseTracking
setPauseTracking(newState, sourceName)
return newState
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.slimevr.trackingpause

import java.util.concurrent.CopyOnWriteArrayList

class TrackingPauseHandler {
private val listeners: MutableList<TrackingPauseListener> = CopyOnWriteArrayList()

fun sendTrackingPauseState(trackingPaused: Boolean) {
listeners.forEach { it.onTrackingPause(trackingPaused) }
}

fun addListener(listener: TrackingPauseListener) {
listeners.add(listener)
}

fun removeListener(listener: TrackingPauseListener) {
listeners.removeIf { it == listener }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.slimevr.trackingpause

interface TrackingPauseListener {
fun onTrackingPause(trackingPaused: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ protected void userActionReceived(UserAction userAction) {
// TODO : Check pose field
VRServer.Companion.getInstance().resetTrackersFull(resetSourceName);
case "fast_reset" -> VRServer.Companion.getInstance().resetTrackersYaw(resetSourceName);
case "pause_tracking" -> VRServer.Companion
.getInstance()
.togglePauseTracking(resetSourceName);
}
}

Expand Down
2 changes: 1 addition & 1 deletion solarxr-protocol
Submodule solarxr-protocol updated 31 files
+1 −1 package.json
+119 −5 protocol/cpp/include/solarxr_protocol/generated/all_generated.h
+0 −26 protocol/java/src/solarxr_protocol/rpc/ArmsResetMode.java
+0 −25 protocol/java/src/solarxr_protocol/rpc/ArmsResetType.java
+3 −1 protocol/java/src/solarxr_protocol/rpc/RpcMessage.java
+8 −0 protocol/java/src/solarxr_protocol/rpc/RpcMessageHeader.java
+4 −0 protocol/java/src/solarxr_protocol/rpc/RpcMessageUnion.java
+47 −0 protocol/java/src/solarxr_protocol/rpc/TrackingPauseStateRequest.java
+16 −0 protocol/java/src/solarxr_protocol/rpc/TrackingPauseStateRequestT.java
+59 −0 protocol/java/src/solarxr_protocol/rpc/TrackingPauseStateResponse.java
+22 −0 protocol/java/src/solarxr_protocol/rpc/TrackingPauseStateResponseT.java
+0 −24 protocol/kotlin/src/solarxr_protocol/rpc/ArmsResetMode.kt
+0 −24 protocol/kotlin/src/solarxr_protocol/rpc/ArmsResetType.kt
+3 −1 protocol/kotlin/src/solarxr_protocol/rpc/RpcMessage.kt
+40 −0 protocol/kotlin/src/solarxr_protocol/rpc/TrackingPauseStateRequest.kt
+53 −0 protocol/kotlin/src/solarxr_protocol/rpc/TrackingPauseStateResponse.kt
+4 −0 protocol/rust/src/generated/mod.rs
+0 −103 protocol/rust/src/generated/solarxr_protocol/rpc/arms_reset_mode_generated.rs
+0 −103 protocol/rust/src/generated/solarxr_protocol/rpc/arms_reset_type_generated.rs
+11 −3 protocol/rust/src/generated/solarxr_protocol/rpc/rpc_message_generated.rs
+46 −0 protocol/rust/src/generated/solarxr_protocol/rpc/rpc_message_header_generated.rs
+91 −0 protocol/rust/src/generated/solarxr_protocol/rpc/tracking_pause_state_request_generated.rs
+109 −0 protocol/rust/src/generated/solarxr_protocol/rpc/tracking_pause_state_response_generated.rs
+2 −0 protocol/typescript/src/all_generated.ts
+0 −18 protocol/typescript/src/solarxr-protocol/rpc/arms-reset-mode.ts
+0 −18 protocol/typescript/src/solarxr-protocol/rpc/arms-reset-type.ts
+3 −1 protocol/typescript/src/solarxr-protocol/rpc/rpc-message-header.ts
+13 −5 protocol/typescript/src/solarxr-protocol/rpc/rpc-message.ts
+57 −0 protocol/typescript/src/solarxr-protocol/rpc/tracking-pause-state-request.ts
+75 −0 protocol/typescript/src/solarxr-protocol/rpc/tracking-pause-state-response.ts
+10 −0 schema/rpc.fbs

0 comments on commit eefe7ef

Please sign in to comment.