mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-09-26 23:09:28 +08:00

* 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
226 lines
10 KiB
Python
226 lines
10 KiB
Python
from typing import Iterable
|
|
|
|
import PySimpleGUI as sg
|
|
|
|
from pydantic import AfterValidator
|
|
from typing_extensions import Annotated
|
|
|
|
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
|
|
from settings.modules.CommonFieldValidators import check_is_ip_address, try_convert_to_float
|
|
|
|
|
|
class VRCFTSettingsModuleValidationModel(BaseValidationModel):
|
|
gui_VRCFTModulePort: int
|
|
gui_VRCFTModuleIPAddress: Annotated[str, AfterValidator(check_is_ip_address)]
|
|
gui_ShouldEmulateEyeWiden: bool
|
|
gui_ShouldEmulateEyeSquint: bool
|
|
gui_ShouldEmulateEyebrows: bool
|
|
gui_WidenThresholdV1_min: float
|
|
gui_WidenThresholdV1_max: float
|
|
gui_WidenThresholdV2_min: float
|
|
gui_WidenThresholdV2_max: float
|
|
gui_SqueezeThresholdV1_min: float
|
|
gui_SqueezeThresholdV1_max: float
|
|
gui_SqueezeThresholdV2_min: float
|
|
gui_SqueezeThresholdV2_max: float
|
|
gui_EyebrowThresholdRising: float
|
|
gui_EyebrowThresholdLowering: float
|
|
# this is a hack. I don't like it, but that's what I gotta do to make both, Pydantic and PySimpleGUI happy
|
|
gui_OutputMultiplier: Annotated[float, AfterValidator(try_convert_to_float)]
|
|
|
|
|
|
class VRCFTSettingsModule(BaseSettingsModule):
|
|
def __init__(self, config, widget_id, **kwargs):
|
|
super().__init__(config=config, widget_id=widget_id, **kwargs)
|
|
self.validation_model = VRCFTSettingsModuleValidationModel
|
|
self.gui_VRCFTModulePort = f"-VRCFTSETTINGSPORTNUMBER{widget_id}"
|
|
self.gui_VRCFTModuleIPAddress = f"-VRCFTSETTINGSIPNUMBER{widget_id}"
|
|
self.gui_ShouldEmulateEyeWiden = f"-VRCFTSETTINGSEMULATEWIDEN{widget_id}"
|
|
self.gui_ShouldEmulateEyeSquint = f"-VRCFTSETTINGSEMULATEEYEWIDEN{widget_id}"
|
|
self.gui_ShouldEmulateEyebrows = f"-VRCFTSETTINGSEMULATEEYEBROWS{widget_id}"
|
|
self.gui_WidenThresholdV1_min = f"-VRCFTSETTINGSWIDENTHRESHOLDV1MIN{widget_id}"
|
|
self.gui_WidenThresholdV1_max = f"-VRCFTSETTINGSWIDENTHRESHOLDV1MAX{widget_id}"
|
|
self.gui_WidenThresholdV2_min = f"-VRCFTSETTINGSWIDENTHRESHOLDV2MIN{widget_id}"
|
|
self.gui_WidenThresholdV2_max = f"-VRCFTSETTINGSWIDENTHRESHOLDV2MAX{widget_id}"
|
|
self.gui_SqueezeThresholdV1_min = f"-VRCFTSETTINGSSQUEEZETHRESHOLDV1MIN{widget_id}"
|
|
self.gui_SqueezeThresholdV1_max = f"-VRCFTSETTINGSSQUEEZETHRESHOLDV1MAX{widget_id}"
|
|
self.gui_SqueezeThresholdV2_min = f"-VRCFTSETTINGSSQUEEZETHRESHOLDV2MIN{widget_id}"
|
|
self.gui_SqueezeThresholdV2_max = f"-VRCFTSETTINGSSQUEEZETHRESHOLDV2MAX{widget_id}"
|
|
self.gui_EyebrowThresholdRising = f"-VRCFTSETTINGSEYEBROWTHRESHOLDRISING{widget_id}"
|
|
self.gui_EyebrowThresholdLowering = f"-VRCFTSETTINGSEYEBROWTHRESHOLDLOWERING{widget_id}"
|
|
self.gui_OutputMultiplier = f"-VRCFTSETTINGSOUTPUTMULTIPLIER{widget_id}"
|
|
|
|
def get_layout(self) -> Iterable:
|
|
return [
|
|
[
|
|
sg.Text("Emulation selection:", background_color="#242224"),
|
|
],
|
|
[
|
|
sg.Checkbox(
|
|
"Emulate Eye Widen",
|
|
default=self.config.gui_ShouldEmulateEyeWiden,
|
|
key=self.gui_ShouldEmulateEyeWiden,
|
|
background_color="#424042",
|
|
),
|
|
sg.Checkbox(
|
|
"Emulate Eye Squint",
|
|
default=self.config.gui_ShouldEmulateEyeSquint,
|
|
key=self.gui_ShouldEmulateEyeSquint,
|
|
background_color="#424042",
|
|
),
|
|
sg.Checkbox(
|
|
"Emulate Eyebrows",
|
|
default=self.config.gui_ShouldEmulateEyebrows,
|
|
key=self.gui_ShouldEmulateEyebrows,
|
|
background_color="#424042",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("General Module Settings:", background_color="#242224"),
|
|
],
|
|
[
|
|
sg.Text("VRCFT Module listening IP", background_color="#242224"),
|
|
sg.InputText(
|
|
self.config.gui_VRCFTModuleIPAddress,
|
|
key=self.gui_VRCFTModuleIPAddress,
|
|
size=(0, 10),
|
|
tooltip="Ip on which the module should listen.",
|
|
),
|
|
sg.Text("port", background_color="#242224"),
|
|
sg.InputText(
|
|
self.config.gui_VRCFTModulePort,
|
|
key=self.gui_VRCFTModulePort,
|
|
size=(0, 10),
|
|
tooltip="UDP port on which the module should listen.",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("VRCFT Module output multiplier", background_color="#242224"),
|
|
sg.InputText(
|
|
self.config.gui_OutputMultiplier,
|
|
key=self.gui_OutputMultiplier,
|
|
size=(0, 10),
|
|
tooltip="Output multiplier adjusts the output by the given amount",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("Eye Widen thresholds:", background_color="#424042"),
|
|
],
|
|
[
|
|
sg.Text("V1 Min:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 1),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_WidenThresholdV1_min,
|
|
orientation="h",
|
|
key=self.gui_WidenThresholdV1_min,
|
|
background_color="#424042",
|
|
tooltip="Controls the point at which the emulation should start for v1 params, reacts to openness",
|
|
),
|
|
sg.Text("V1 Max:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 2),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_WidenThresholdV1_max,
|
|
orientation="h",
|
|
key=self.gui_WidenThresholdV1_max,
|
|
background_color="#424042",
|
|
tooltip="Controls the maximum range of widen emulation",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("V2 Min:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 2),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_WidenThresholdV2_min,
|
|
orientation="h",
|
|
key=self.gui_WidenThresholdV2_min,
|
|
background_color="#424042",
|
|
tooltip="Controls the point at which the emulation should start for v2 params, reacts to openness",
|
|
),
|
|
sg.Text("V2 Max:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 2),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_WidenThresholdV2_max,
|
|
orientation="h",
|
|
key=self.gui_WidenThresholdV2_max,
|
|
background_color="#424042",
|
|
tooltip="Controls the maximum range of widen emulation",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("Eye Squeeze thresholds:", background_color="#424042"),
|
|
],
|
|
[
|
|
sg.Text("V1 Min:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 1),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_SqueezeThresholdV1_min,
|
|
orientation="h",
|
|
key=self.gui_SqueezeThresholdV1_min,
|
|
background_color="#424042",
|
|
tooltip="Controls the point at which the emulation should start for v1 params, reacts to openness",
|
|
),
|
|
sg.Text("V1 Max:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 2),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_SqueezeThresholdV1_max,
|
|
orientation="h",
|
|
key=self.gui_SqueezeThresholdV1_max,
|
|
background_color="#424042",
|
|
tooltip="Controls the maximum range of squeeze emulation",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("V2 Min:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 1),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_SqueezeThresholdV2_min,
|
|
orientation="h",
|
|
key=self.gui_SqueezeThresholdV2_min,
|
|
background_color="#424042",
|
|
tooltip="Controls the point at which the emulation should start for v2 params, reacts to openness",
|
|
),
|
|
sg.Text("V2 Max:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(-2, 0),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_SqueezeThresholdV2_max,
|
|
orientation="h",
|
|
key=self.gui_SqueezeThresholdV2_max,
|
|
background_color="#424042",
|
|
tooltip="Controls the maximum range of squeeze emulation",
|
|
),
|
|
],
|
|
[
|
|
sg.Text("Eyebrow emulation Thresholds:", background_color="#424042"),
|
|
],
|
|
[
|
|
sg.Text("Rising:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 1),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_EyebrowThresholdRising,
|
|
orientation="h",
|
|
key=self.gui_EyebrowThresholdRising,
|
|
background_color="#424042",
|
|
tooltip="Controls the point at which the emulation should start, reacts to openness",
|
|
),
|
|
sg.Text("Lowering:", background_color="#424042"),
|
|
sg.Slider(
|
|
range=(0, 2),
|
|
resolution=0.01,
|
|
default_value=self.config.gui_EyebrowThresholdLowering,
|
|
orientation="h",
|
|
key=self.gui_EyebrowThresholdLowering,
|
|
background_color="#424042",
|
|
tooltip="Controls the maximum range of eyebrows emulation",
|
|
),
|
|
],
|
|
]
|