Skip to content

Commit a6b9090

Browse files
committed
Add controller input support.
1 parent c944ffe commit a6b9090

File tree

6 files changed

+10700
-8983
lines changed

6 files changed

+10700
-8983
lines changed

server/core/src/main/java/dev/slimevr/tracking/trackers/Tracker.kt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Tracker @JvmOverloads constructor(
4141
trackerNum: Int? = null,
4242
val hasPosition: Boolean = false,
4343
val hasRotation: Boolean = false,
44+
val hasControls: Boolean = false,
4445
val hasAcceleration: Boolean = false,
4546
/**
4647
* User can change TrackerPosition, mounting...
@@ -106,6 +107,13 @@ class Tracker @JvmOverloads constructor(
106107
// SlimeVR: +z backward, +x right, +y up
107108
private var _acceleration = Vector3.NULL
108109
private var _magVector = Vector3.NULL
110+
private var _analogueThumbstick = Vector3.NULL
111+
private var _button1 = false
112+
private var _button2 = false
113+
private var _menuRecenterButton = false
114+
private var _stickClickButton = false
115+
private var _trigger = 0f
116+
private var _grip = 0f
109117
var position = Vector3.NULL
110118
val resetsHandler: TrackerResetsHandler = TrackerResetsHandler(this)
111119
val filteringHandler: TrackerFilteringHandler = TrackerFilteringHandler()
@@ -447,4 +455,68 @@ class Tracker @JvmOverloads constructor(
447455
fun resetFilteringQuats(reference: Quaternion) {
448456
filteringHandler.resetMovingAverage(getAdjustedRotation(), reference)
449457
}
458+
/**
459+
* Sets the first button of the tracker.
460+
*/
461+
fun setButton1(button1: Boolean) {
462+
this._button1 = button1
463+
}
464+
fun getButton1(): Boolean {
465+
return this._button1
466+
}
467+
/**
468+
* Sets the second button of the tracker.
469+
*/
470+
fun setButton2(button2: Boolean) {
471+
this._button2 = button2
472+
}
473+
fun getButton2(): Boolean {
474+
return this._button2
475+
}
476+
/**
477+
* Sets the menu/recenter button of the tracker.
478+
*/
479+
fun setMenuRecenterButton(menuRecenterButton: Boolean) {
480+
this._menuRecenterButton = menuRecenterButton
481+
}
482+
fun getMenuRecenterButton(): Boolean {
483+
return this._menuRecenterButton
484+
}
485+
486+
/**
487+
* Sets the stick click button of the tracker.
488+
*/
489+
fun setStickClickButton(stickClickButton: Boolean) {
490+
this._stickClickButton = stickClickButton
491+
}
492+
fun getStickClickButton(): Boolean {
493+
return this._stickClickButton
494+
}
495+
/**
496+
* Sets the grip of the tracker.
497+
*/
498+
fun setGrip(grip: Float) {
499+
this._grip = grip
500+
}
501+
fun getGrip(): Float {
502+
return this._grip
503+
}
504+
/**
505+
* Sets the grip of the tracker.
506+
*/
507+
fun setTrigger(trigger: Float) {
508+
this._trigger = trigger
509+
}
510+
fun getTrigger(): Float {
511+
return this._trigger
512+
}
513+
/**
514+
* Sets the thumbstick the tracker.
515+
*/
516+
fun setThumbstick(analogueThumbstick: Vector3) {
517+
this._analogueThumbstick = analogueThumbstick
518+
}
519+
fun getThumbstick(): Vector3 {
520+
return this._analogueThumbstick
521+
}
450522
}

server/core/src/main/java/dev/slimevr/tracking/trackers/udp/TrackersUDPServer.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
557557
name = "Pause tracking toggle"
558558
VRServer.instance.togglePauseTracking(RESET_SOURCE_NAME)
559559
}
560+
560561
}
561562

562563
LogManager.info(
@@ -608,6 +609,68 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
608609
// dont call dataTick here as this is just position update
609610
}
610611

612+
is UDPPacket66ControllerButton -> {
613+
if (connection == null) return
614+
var name = ""
615+
tracker = connection?.getTracker(packet.sensorId)
616+
if (tracker == null) return
617+
// If sensorOffset was applied to accel correctly, the axes will already
618+
// be correct for SlimeVR
619+
620+
when (packet.type) {
621+
UDPPacket66ControllerButton.BUTTON_1_HELD -> {
622+
name = "Button 1 Pressed"
623+
tracker.setButton1(true)
624+
}
625+
UDPPacket66ControllerButton.BUTTON_1_UNHELD -> {
626+
name = "Button 1 Unpressed"
627+
tracker.setButton1(false)
628+
}
629+
UDPPacket66ControllerButton.BUTTON_2_HELD -> {
630+
name = "Button 2 Pressed"
631+
tracker.setButton2(true)
632+
}
633+
UDPPacket66ControllerButton.BUTTON_2_UNHELD -> {
634+
name = "Button 2 Unpressed"
635+
tracker.setButton2(false)
636+
}
637+
UDPPacket66ControllerButton.MENU_RECENTER_HELD -> {
638+
name = "Menu/Recenter Pressed"
639+
tracker.setMenuRecenterButton(true)
640+
}
641+
UDPPacket66ControllerButton.MENU_RECENTER_UNHELD -> {
642+
name = "Menu/Recenter Unpressed"
643+
tracker.setMenuRecenterButton(false)
644+
}
645+
UDPPacket66ControllerButton.STICK_CLICK_HELD -> {
646+
name = "Stick Click Pressed"
647+
tracker.setStickClickButton(true)
648+
}
649+
UDPPacket66ControllerButton.STICK_CLICK_UNHELD -> {
650+
name = "Stick Click Unpressed"
651+
tracker.setStickClickButton(false)
652+
}
653+
}
654+
655+
LogManager.info(
656+
"[TrackerServer] User action from ${connection.descriptiveName} received. $name performed.",
657+
)
658+
}
659+
is UDPPacket67Thumbstick -> {
660+
tracker = connection?.getTracker(packet.sensorId)
661+
if(tracker == null) return
662+
tracker.setThumbstick(packet.analogueThumbstick);
663+
}
664+
is UDPPacket68Trigger -> {
665+
tracker = connection?.getTracker(packet.sensorId)
666+
if(tracker == null) return
667+
tracker.setTrigger(packet.trigger);
668+
}
669+
is UDPPacket69Grip -> {
670+
tracker = connection?.getTracker(packet.sensorId)
671+
if(tracker == null) return
672+
tracker.setTrigger(packet.grip);
673+
}
611674
is UDPPacket200ProtocolChange -> {}
612675
}
613676
}

server/core/src/main/java/dev/slimevr/tracking/trackers/udp/UDPPacket.kt

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,80 @@ data class UDPPacket4Acceleration(var acceleration: Vector3 = Vector3.NULL) :
153153
override var sensorId = 0
154154
override fun readData(buf: ByteBuffer) {
155155
acceleration = Vector3(UDPUtils.getSafeBufferFloat(buf), UDPUtils.getSafeBufferFloat(buf), UDPUtils.getSafeBufferFloat(buf))
156+
sensorId = try {
157+
buf.get().toInt() and 0xFF
158+
} catch (e: BufferUnderflowException) {
159+
// for owo track app
160+
0
161+
}
162+
}
163+
}
156164

165+
data class UDPPacket66ControllerButton(var type: Int = 0) :
166+
UDPPacket(66),
167+
SensorSpecificPacket {
168+
override var sensorId = 0
169+
override fun readData(buf: ByteBuffer) {
170+
type = try {
171+
buf.get().toInt() and 0xFF
172+
} catch (e: BufferUnderflowException) {
173+
0
174+
}
175+
sensorId = try {
176+
buf.get().toInt() and 0xFF
177+
} catch (e: BufferUnderflowException) {
178+
// for owo track app
179+
0
180+
}
181+
}
182+
companion object {
183+
const val BUTTON_1_HELD = 1
184+
const val BUTTON_1_UNHELD = 2
185+
const val BUTTON_2_HELD = 3
186+
const val BUTTON_2_UNHELD = 4
187+
const val MENU_RECENTER_HELD = 5
188+
const val MENU_RECENTER_UNHELD = 6
189+
const val STICK_CLICK_HELD = 7
190+
const val STICK_CLICK_UNHELD = 8
191+
}
192+
}
193+
194+
data class UDPPacket67Thumbstick(var analogueThumbstick: Vector3 = Vector3.NULL) :
195+
UDPPacket(67),
196+
SensorSpecificPacket {
197+
override var sensorId = 0
198+
override fun readData(buf: ByteBuffer) {
199+
analogueThumbstick = Vector3(UDPUtils.getSafeBufferFloat(buf), UDPUtils.getSafeBufferFloat(buf), 0f)
200+
sensorId = try {
201+
buf.get().toInt() and 0xFF
202+
} catch (e: BufferUnderflowException) {
203+
// for owo track app
204+
0
205+
}
206+
}
207+
}
208+
209+
data class UDPPacket68Trigger(var trigger: Float = 0f) :
210+
UDPPacket(68),
211+
SensorSpecificPacket {
212+
override var sensorId = 0
213+
override fun readData(buf: ByteBuffer) {
214+
trigger = UDPUtils.getSafeBufferFloat(buf)
215+
sensorId = try {
216+
buf.get().toInt() and 0xFF
217+
} catch (e: BufferUnderflowException) {
218+
// for owo track app
219+
0
220+
}
221+
}
222+
}
223+
224+
data class UDPPacket69Grip(var grip: Float = 0f) :
225+
UDPPacket(69),
226+
SensorSpecificPacket {
227+
override var sensorId = 0
228+
override fun readData(buf: ByteBuffer) {
229+
grip = UDPUtils.getSafeBufferFloat(buf)
157230
sensorId = try {
158231
buf.get().toInt() and 0xFF
159232
} catch (e: BufferUnderflowException) {

server/core/src/main/java/dev/slimevr/tracking/trackers/udp/UDPProtocolParser.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class UDPProtocolParser {
118118
PACKET_FLEX_DATA -> UDPPacket26FlexData()
119119
PACKET_POSITION -> UDPPacket27Position()
120120
PACKET_PROTOCOL_CHANGE -> UDPPacket200ProtocolChange()
121+
PACKET_CONTROLLER_BUTTON -> UDPPacket66ControllerButton()
122+
PACKET_THUMBSTICK -> UDPPacket67Thumbstick()
123+
PACKET_TRIGGER -> UDPPacket68Trigger()
124+
PACKET_GRIP -> UDPPacket69Grip()
121125
else -> null
122126
}
123127

@@ -157,6 +161,10 @@ class UDPProtocolParser {
157161
const val PACKET_BUNDLE = 100
158162
const val PACKET_BUNDLE_COMPACT = 101
159163
const val PACKET_PROTOCOL_CHANGE = 200
164+
const val PACKET_CONTROLLER_BUTTON = 66
165+
const val PACKET_THUMBSTICK = 67
166+
const val PACKET_TRIGGER = 68
167+
const val PACKET_GRIP = 69
160168
private val HANDSHAKE_BUFFER = ByteArray(64)
161169
private val bundlePackets = ArrayList<UDPPacket>(128)
162170

server/desktop/src/main/java/dev/slimevr/desktop/platform/ProtobufBridge.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ abstract class ProtobufBridge(@JvmField protected val bridgeName: String) : ISte
9797
for (tracker in sharedTrackers) {
9898
writeTrackerUpdate(tracker)
9999
writeBatteryUpdate(tracker)
100+
writeControllerInputUpdate(tracker)
100101
}
101102
}
102103

@@ -120,6 +121,23 @@ abstract class ProtobufBridge(@JvmField protected val bridgeName: String) : ISte
120121
}
121122
sendMessage(ProtobufMessage.newBuilder().setPosition(builder).build())
122123
}
124+
protected fun writeControllerInputUpdate(localTracker: Tracker?) {
125+
val builder = ProtobufMessages.ControllerInput.newBuilder().setTrackerId(
126+
localTracker!!.id,
127+
)
128+
if (localTracker.hasControls) {
129+
val thumbstick = localTracker.getThumbstick()
130+
builder.setThumbstickX(thumbstick.x)
131+
builder.setThumbstickY(thumbstick.y)
132+
builder.setButton1(localTracker.getButton1())
133+
builder.setButton2(localTracker.getButton2())
134+
builder.setMenuRecenter(localTracker.getMenuRecenterButton())
135+
builder.setStickClick(localTracker.getStickClickButton())
136+
builder.setTrigger(localTracker.getTrigger())
137+
builder.setGrip(localTracker.getGrip())
138+
}
139+
sendMessage(ProtobufMessage.newBuilder().setControllerInput(builder).build())
140+
}
123141

124142
@VRServerThread
125143
protected open fun writeBatteryUpdate(localTracker: Tracker) {

0 commit comments

Comments
 (0)