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
2 changes: 2 additions & 0 deletions gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ settings-general-tracker_mechanics-trackers_over_usb = Trackers over USB
settings-general-tracker_mechanics-trackers_over_usb-description =
Enables receiving HID tracker data over USB. Make sure connected trackers have <b>connection over HID</b> enabled!
settings-general-tracker_mechanics-trackers_over_usb-enabled-label = Allow HID trackers to connect directly over USB
settings-general-tracker_mechanics-timeout_duration = Timeout duration
settings-general-tracker_mechanics-timeout_duration-description = How long until a tracker is marked as 'disconnected' when the connection is lost.

settings-stay_aligned = Stay Aligned
settings-stay_aligned-description = Stay Aligned reduces drift by gradually adjusting your trackers to match your relaxed poses.
Expand Down
4 changes: 4 additions & 0 deletions gui/src/components/commons/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const InputInside = forwardRef<
value,
error,
variant = 'primary',
...props
},
ref
) {
Expand Down Expand Up @@ -100,6 +101,7 @@ export const InputInside = forwardRef<
value={computedValue} // Do we want that behaviour ?
disabled={disabled}
ref={ref}
{...props}
/>
{type === 'password' && (
<div
Expand Down Expand Up @@ -129,6 +131,7 @@ export const Input = <T extends FieldValues = FieldValues>({
disabled,
variant = 'primary',
rules,
...props
}: {
rules?: UseControllerProps<T, FieldPath<T>>['rules'];
control: Control<T>;
Expand Down Expand Up @@ -157,6 +160,7 @@ export const Input = <T extends FieldValues = FieldValues>({
onChange={onChange}
ref={ref}
name={name}
{...props}
/>
)}
/>
Expand Down
46 changes: 45 additions & 1 deletion gui/src/components/settings/pages/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import {
SteamVRTrackersSettingT,
TapDetectionSettingsT,
HIDSettingsT,
TimeoutSettingsT,
} from 'solarxr-protocol';
import { useConfig } from '@/hooks/config';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { useLocaleConfig } from '@/i18n/config';
import { Input } from '@/components/commons/Input';
import { CheckBox } from '@/components/commons/Checkbox';
import { SteamIcon } from '@/components/commons/icon/SteamIcon';
import { WrenchIcon } from '@/components/commons/icon/WrenchIcons';
Expand Down Expand Up @@ -108,6 +110,9 @@ export type SettingsForm = {
hidSettings: {
trackersOverHID: boolean;
};
timeout: {
duration: number;
};
};

const defaultValues: SettingsForm = {
Expand Down Expand Up @@ -164,6 +169,7 @@ const defaultValues: SettingsForm = {
resetsSettings: defaultResetSettings,
stayAligned: defaultStayAlignedSettings,
hidSettings: { trackersOverHID: false },
timeout: { duration: 3.0 },
};

const settingsAtom = atom(new SettingsResponseT());
Expand Down Expand Up @@ -301,6 +307,10 @@ export function GeneralSettings() {
hidSettings.trackersOverHid = values.hidSettings.trackersOverHID;
settings.hidSettings = hidSettings;

const timeout = new TimeoutSettingsT();
timeout.duration = values.timeout.duration;
settings.timeout = timeout;

if (values.resetsSettings) {
settings.resetsSettings = loadResetSettings(values.resetsSettings);
}
Expand Down Expand Up @@ -419,6 +429,12 @@ export function GeneralSettings() {
};
}

if (settings.timeout) {
formData.timeout = {
duration: settings.timeout.duration,
};
}

reset({ ...getValues(), ...formData });
}, [settings]);

Expand Down Expand Up @@ -455,7 +471,10 @@ export function GeneralSettings() {
setHandsWarning(false);
}}
/>
<form className="flex flex-col gap-2 w-full">
<form
className="flex flex-col gap-2 w-full"
onSubmit={(e) => e.preventDefault()}
>
<SettingsPagePaneLayout icon={<SteamIcon />} id="steamvr">
<>
<Typography variant="main-title">
Expand Down Expand Up @@ -733,6 +752,31 @@ export function GeneralSettings() {
'settings-general-tracker_mechanics-trackers_over_usb-enabled-label'
)}
/>
<div className="flex flex-col pt-5 pb-3">
<Typography variant="section-title">
{l10n.getString(
'settings-general-tracker_mechanics-timeout_duration'
)}
</Typography>
<div className="flex flex-col">
<Typography>
{l10n.getString(
'settings-general-tracker_mechanics-timeout_duration-description'
)}
</Typography>
</div>
</div>
<div className="grid gap-3">
<Input
type="number"
control={control}
name="timeout.duration"
label=""
min={1}
max={1000000000000000}
step="any"
/>
Comment on lines +770 to +778
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use a NumberSelector?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to be able to type into it

</div>
</>
</SettingsPagePaneLayout>
<SettingsPagePaneLayout icon={<WrenchIcon />} id="fksettings">
Expand Down
22 changes: 22 additions & 0 deletions server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.slimevr.config

import dev.slimevr.VRServer
import dev.slimevr.tracking.trackers.Tracker

class TimeoutConfig {
// Timeout duration in seconds
var duration = 3.0f

fun updateTimeoutDuration() {
if (this.duration.isNaN() || this.duration.isInfinite()) {
this.duration = 3.0f
}
if (this.duration < 1f) {
this.duration = 1f
}
if (this.duration > 1000000000000000f) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea was that it's a floating point setting which is being multiplied by 1000 and turned into a "Long", so I put an upper bound to prevent potential overflow

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it long then maybe...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe, but if it was a long, it would be in ms, which I think typing values in milliseconds in the ui would be weird.

I could make it so the server stores the number as a long, and the gui uses floats but performs all of the conversion before sending it, but from what I understand the solarxr stuff allows other apps to also listen to the same messages, in which case receiving a time in seconds as a float is 'nicer' than milliseconds as a long in my opinion

this.duration = 1000000000000000f
}
Tracker.DISCONNECT_MS = (this.duration * 1000L).toLong() + Tracker.TIMEOUT_MS
}
}
2 changes: 2 additions & 0 deletions server/core/src/main/java/dev/slimevr/config/VRConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class VRConfig {

val filters: FiltersConfig = FiltersConfig()

val timeout: TimeoutConfig = TimeoutConfig()

val driftCompensation: DriftCompensationConfig = DriftCompensationConfig()

val oscRouter: OSCConfig = OSCConfig()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dev.slimevr.config.ResetsConfig
import dev.slimevr.config.SkeletonConfig
import dev.slimevr.config.StayAlignedConfig
import dev.slimevr.config.TapDetectionConfig
import dev.slimevr.config.TimeoutConfig
import dev.slimevr.config.VMCConfig
import dev.slimevr.config.VRCOSCConfig
import dev.slimevr.filtering.TrackerFilters.Companion.getByConfigkey
Expand All @@ -32,6 +33,7 @@ import solarxr_protocol.rpc.SettingsResponse
import solarxr_protocol.rpc.StayAlignedSettings
import solarxr_protocol.rpc.SteamVRTrackersSetting
import solarxr_protocol.rpc.TapDetectionSettings
import solarxr_protocol.rpc.TimeoutSettings
import solarxr_protocol.rpc.VMCOSCSettings
import solarxr_protocol.rpc.VRCOSCSettings
import solarxr_protocol.rpc.settings.LegTweaksSettings
Expand Down Expand Up @@ -421,7 +423,10 @@ fun createSettingsResponse(fbb: FlatBufferBuilder, server: VRServer): Int {
server.configManager.vrConfig.stayAlignedConfig,
),
createHIDSettings(fbb, server.configManager.vrConfig.hidConfig),
0,
createTimeoutSettings(
fbb,
server.configManager.vrConfig.timeout,
),
)
}

Expand Down Expand Up @@ -457,3 +462,12 @@ fun createHIDSettings(
fbb,
config.trackersOverHID,
)

fun createTimeoutSettings(
fbb: FlatBufferBuilder,
timeoutConfig: TimeoutConfig,
): Int = TimeoutSettings
.createTimeoutSettings(
fbb,
timeoutConfig.duration,
)
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
config.trackersOverHID = requestConfig.trackersOverHid()
}

if (req.timeout() != null) {
val timeoutConfig = api.server.configManager
.vrConfig
.timeout
timeoutConfig.duration = req.timeout().duration()
timeoutConfig.updateTimeoutDuration()
}

api.server.configManager.saveConfig()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ import io.github.axisangles.ktmath.Quaternion
import io.github.axisangles.ktmath.Vector3
import kotlin.properties.Delegates

const val TIMEOUT_MS = 2_000L
const val DISCONNECT_MS = 3_000L + TIMEOUT_MS

/**
* Generic tracker class for input and output tracker,
* with flags on instantiation.
Expand Down Expand Up @@ -103,6 +100,11 @@ class Tracker @JvmOverloads constructor(
*/
val usesSleep: Boolean = false,
) {
companion object {
const val TIMEOUT_MS = 2_000L
var DISCONNECT_MS = 3_000L + TIMEOUT_MS
}

private val timer = BufferedTimer(1f)
private var timeAtLastUpdate: Long = System.currentTimeMillis()
private var timeScheduledSleep: Long = Long.MAX_VALUE
Expand Down