EyeTrackVR/EyeTrackApp/settings/modules/OSCSettingsModule.py
Lorow 7e41a65aac
Feature/etvr module support (#106)
* initial changes

* Mostly clean up, refactor registering listeners to make sense, backport tests

* Add initial implementation of VRCFTModuleSender

* Add basic GUI for the modules settings

* Fix tooltip descriptions

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* Fix type validation bugs, fix typos

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* Add checkbox to switch to ETVR Module

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* Black stuff

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* Remove coverage by default

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* Fix timeout in tests

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* HEAVY WIP: Refactor native output,

NOTE:

I brought back the entire old OSC implementation as a live reference, this will be removed once I'm done.

This also lays ground for other modes as they're pretty similar

# TODO:
# - there's ghosts in the machine - vrc osc is not working properly
# - min/maxing will require field combinators in the modules lmao

* HEAVY WIP: Refactor v1 params output,

# TODO:
# - min/maxing will require field combinators in the modules lmao

* HEAVY WIP: Refactor v2 params output

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Finish refactoring v2 and v1, fixup tests, refactor native

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Add tests for v1 params

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Add tests for native params

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Fix OSC not getting up after config reset. Remove reset command, config sends everything changed anyway, sunset the idea of using single client and thus simplify the code a bit

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Rename gui_PortNumber to gui_VRCFTModulePort for readability

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Cleanup EyeID usage

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Cleanup osc after rebase

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Make VRChatOSCSender a bit more readable

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Remove unsued VRChatOSCReceiver, this is taken care of by generic OSCReceiver

# TODO:
# - min/maxing will require field combinators in the modules lmao

* Commit crimes with try_convert_to_float to make osc, pysimplegui and pydantic happy

* Cleanup after merge

* Disable emulation by default

* Fix OSCReceiver crashing on unknown addresses

* Adjust VRCFT Module settings to look better in game

* Fix recalibrate and recenter for OSC only working for the right eye

* Fix save and restart button not restarting the tracking

* Fix broken tracking on v1 params for eye_x, clean up implementation

* Fix regular value being passed to OSC listeners instead of OSCMessage

* Add a TODO, probably to be ignored

* Add support for custom ETVR VRCFT Module listening address
2024-07-04 20:51:19 +02:00

138 lines
5.4 KiB
Python

from pydantic import model_validator
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
from settings.constants import BACKGROUND_COLOR
import PySimpleGUI as sg
class OSCValidationModel(BaseValidationModel):
gui_osc_port: int
gui_osc_address: str
gui_ROSC: bool
gui_osc_receiver_port: int
gui_osc_recenter_address: str
gui_osc_recalibrate_address: str
gui_vrc_native: bool
gui_osc_vrcft_v1: bool
gui_osc_vrcft_v2: bool
gui_use_module: bool
@model_validator(mode="after")
def check_osc_vrcft_versions(self):
if self.gui_osc_vrcft_v1 and self.gui_osc_vrcft_v2:
raise ValueError("Only one version of VRCFT params can be turned on")
return self
@model_validator(mode="after")
def check_osc_output_mode(self):
if self.gui_vrc_native and any([self.gui_osc_vrcft_v1, self.gui_osc_vrcft_v2]):
raise ValueError("Either VRCNative or VRCFT output can be active at a time")
return self
class OSCSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, **kwargs):
super().__init__(config=config, widget_id=widget_id, **kwargs)
self.validation_model = OSCValidationModel
self.gui_osc_address = f"-OSCADDRESS{widget_id}-"
self.gui_osc_port = f"-OSCPORT{widget_id}-"
self.gui_ROSC = f"-ROSC{widget_id}-"
self.gui_osc_receiver_port = f"OSCRECEIVERPORT{widget_id}-"
self.gui_osc_recenter_address = f"OSCRECENTERADDRESS{widget_id}-"
self.gui_osc_recalibrate_address = f"OSCRECALIBRATEADDRESS{widget_id}-"
self.gui_vrc_native = f"-VRCNATIVE{widget_id}-"
self.gui_osc_vrcft_v1 = f"-OSCVRCFTV1{widget_id}-"
self.gui_osc_vrcft_v2 = f"-OSCVRCFTV2{widget_id}-"
self.gui_use_module = f"-OSCUSEMODULE{widget_id}-"
def get_layout(self):
return [
[
sg.Text("OSC Settings:", background_color="#242224"),
],
[
sg.Checkbox(
"Use ETVR VRCFT Module",
default=self.config.gui_use_module,
key=self.gui_use_module,
background_color="#424042",
tooltip="Toggle output to VRCFT Module or just regular OSC port",
),
],
[
sg.Checkbox(
"VRC Native Eyetracking",
default=self.config.gui_vrc_native,
key=self.gui_vrc_native,
background_color="#424042",
tooltip="Toggle VRCFT output or VRC native",
),
sg.Checkbox(
"VRCFT v1",
default=self.config.gui_osc_vrcft_v1,
key=self.gui_osc_vrcft_v1,
background_color="#424042",
tooltip="Toggle VRCFT's v1 Eyetracking format.",
),
sg.Checkbox(
"VRCFT v2 (UE)",
default=self.config.gui_osc_vrcft_v2,
key=self.gui_osc_vrcft_v2,
background_color="#424042",
tooltip="Toggle VRCFT's v2 (UE) Eyetracking format.",
),
],
[
sg.Text("Address:", background_color=BACKGROUND_COLOR),
sg.InputText(
self.config.gui_osc_address,
key=self.gui_osc_address,
size=(0, 20),
tooltip="IP address we send OSC data to.",
),
sg.Text("Port:", background_color=BACKGROUND_COLOR),
sg.InputText(
self.config.gui_osc_port,
key=self.gui_osc_port,
size=(0, 10),
tooltip="OSC port we send data to.",
),
],
[
sg.Text("Receive functions", background_color=BACKGROUND_COLOR),
sg.Checkbox(
"",
default=self.config.gui_ROSC,
key=self.gui_ROSC,
background_color=BACKGROUND_COLOR,
size=(0, 10),
tooltip="Toggle OSC receive functions.",
),
],
[
sg.Text("Receiver Port:", background_color=BACKGROUND_COLOR),
sg.InputText(
self.config.gui_osc_receiver_port,
key=self.gui_osc_receiver_port,
size=(0, 10),
tooltip="Port we receive OSC data from (used to recalibrate or recenter app from within VRChat.",
),
sg.Text("Recenter Address:", background_color=BACKGROUND_COLOR),
sg.InputText(
self.config.gui_osc_recenter_address,
key=self.gui_osc_recenter_address,
size=(0, 10),
tooltip="OSC Address used for recentering your eye.",
),
],
[
sg.Text("Recalibrate Address:", background_color=BACKGROUND_COLOR),
sg.InputText(
self.config.gui_osc_recalibrate_address,
key=self.gui_osc_recalibrate_address,
size=(0, 10),
tooltip="OSC address we use for recalibrating your eye",
),
],
]