Rename from SmartInversion to MirrorTrack, and inversion bug fixes!

Renamed all mentions of Smart Inversion to Mirror Track.
Also fixed the stare / inversion rapid cycling, yippee!
This commit is contained in:
Blabzillaweasel 2025-02-15 15:48:26 +13:00
parent f7d16212f3
commit 705fe0243c
9 changed files with 233 additions and 189 deletions

View File

@ -217,13 +217,15 @@ class EyeTrackSettingsConfig(BaseModel):
gui_OutputMultiplier: float = 1 gui_OutputMultiplier: float = 1
gui_use_module: bool = False gui_use_module: bool = False
#SmartInversionTracking #mirrortrackTracking
gui_smartinversion_enabled: bool = False gui_mirrortrack_enabled: bool = False
gui_smartinversion_select_right: bool = True gui_mirrortrack_select_right: bool = True
gui_smartinversion_frame_count: int = 30 gui_mirrortrack_cycle_count_inv: int = 20
gui_smartinversion_smoothing_rate: float = 0.025 gui_mirrortrack_cycle_count_stare: int = 20
gui_smartinversion_minthresh: float = 0.3 #gui_mirrortrack_smoothing_rate: float = 0.025
gui_smartinversion_rotation_clamp: float = 1.0 gui_mirrortrack_minthresh: float = 0.3
gui_mirrortrack_rotation_clamp: float = 0.5
gui_mirrortrack_enable_inv: bool = True
class EyeTrackConfig(BaseModel): class EyeTrackConfig(BaseModel):
version: int = 1 version: int = 1

View File

@ -38,7 +38,7 @@ from settings.algo_settings_widget import AlgoSettingsWidget
from osc.osc import OSCManager from osc.osc import OSCManager
from osc.OSCMessage import OSCMessage from osc.OSCMessage import OSCMessage
from utils.misc_utils import is_nt, resource_path from utils.misc_utils import is_nt, resource_path
from utils.smart_inversion import SmartInversion from utils.mirrortrack import mirrortrack
import cv2 import cv2
import numpy as np import numpy as np
import uuid import uuid
@ -284,7 +284,7 @@ def main():
config.register_listener_callback(osc_manager.update) config.register_listener_callback(osc_manager.update)
config.register_listener_callback(eyes[0].on_config_update) config.register_listener_callback(eyes[0].on_config_update)
config.register_listener_callback(eyes[1].on_config_update) config.register_listener_callback(eyes[1].on_config_update)
config.register_listener_callback(SmartInversion.config_update) config.register_listener_callback(mirrortrack.config_update)
osc_manager.register_listeners( osc_manager.register_listeners(
config.settings.gui_osc_recenter_address, config.settings.gui_osc_recenter_address,
@ -302,7 +302,7 @@ def main():
) )
osc_manager.start() osc_manager.start()
SmartInversion.init_config(config) mirrortrack.init_config(config)
while True: while True:
tint = 33 tint = 33

View File

@ -29,7 +29,7 @@ import time
from enum import IntEnum from enum import IntEnum
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC, resource_path from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC, resource_path
from utils.eye_falloff import velocity_falloff from utils.eye_falloff import velocity_falloff
from utils.smart_inversion import SmartInversion from utils.mirrortrack import mirrortrack
import socket import socket
import struct import struct
import threading import threading
@ -337,8 +337,8 @@ class cal:
var.past_x = out_x_mult var.past_x = out_x_mult
var.past_y = out_y_mult var.past_y = out_y_mult
if(self.settings.gui_smartinversion_enabled): if(self.settings.gui_mirrortrack_enabled):
out_x, out_y = SmartInversion.process(self.eye_id, out_x, out_y) out_x, out_y = mirrortrack.process(self.eye_id, out_x, out_y)
else: else:
out_x, out_y = velocity_falloff(self, var, out_x, out_y) out_x, out_y = velocity_falloff(self, var, out_x, out_y)

View File

@ -31,7 +31,7 @@ from settings.BaseSettings import BaseSettingsWidget
from settings.modules.GeneralSettingsModule import GeneralSettingsModule from settings.modules.GeneralSettingsModule import GeneralSettingsModule
from settings.modules.OneEuroSettingsModule import OneEuroSettingsModule from settings.modules.OneEuroSettingsModule import OneEuroSettingsModule
from settings.modules.OSCSettingsModule import OSCSettingsModule from settings.modules.OSCSettingsModule import OSCSettingsModule
from settings.modules.SmartInversionSettingsModule import SmartInversionSettingsModule from settings.modules.MirrorTrackSettingsModule import MirrorTrackSettingsModule
class SettingsWidget(BaseSettingsWidget): class SettingsWidget(BaseSettingsWidget):
@ -39,7 +39,7 @@ class SettingsWidget(BaseSettingsWidget):
settings_modules = [ settings_modules = [
GeneralSettingsModule, GeneralSettingsModule,
OneEuroSettingsModule, OneEuroSettingsModule,
SmartInversionSettingsModule, MirrorTrackSettingsModule,
OSCSettingsModule, OSCSettingsModule,
] ]
super().__init__(widget_id, main_config, settings_modules) super().__init__(widget_id, main_config, settings_modules)

View File

@ -0,0 +1,131 @@
from pydantic import AfterValidator
from typing_extensions import Annotated
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
from settings.constants import BACKGROUND_COLOR
import PySimpleGUI as sg
from settings.modules.CommonFieldValidators import try_convert_to_float
from settings.modules.CommonFieldValidators import try_convert_to_int
class MirrorTrackValidationModule(BaseValidationModel):
gui_mirrortrack_enabled: bool
gui_mirrortrack_select_right: bool
gui_mirrortrack_cycle_count_inv: Annotated[int, AfterValidator(try_convert_to_int)]
gui_mirrortrack_cycle_count_stare: Annotated[int, AfterValidator(try_convert_to_int)]
gui_mirrortrack_minthresh: Annotated[float, AfterValidator(try_convert_to_float)]
gui_mirrortrack_rotation_clamp: Annotated[float, AfterValidator(try_convert_to_float)]
gui_mirrortrack_enable_inv: bool
#gui_mirrortrack_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
class MirrorTrackSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, **kwargs):
super().__init__(config=config, widget_id=widget_id, **kwargs)
self.validation_model = MirrorTrackValidationModule
self.gui_mirrortrack_enabled = f"-gui_mirrortrack_enabled{widget_id}-"
self.gui_mirrortrack_select_right = f"-gui_mirrortrack_select_right{widget_id}-"
self.gui_mirrortrack_cycle_count_inv =f"-gui_mirrortrack_cycle_count_inv{widget_id}-"
self.gui_mirrortrack_cycle_count_stare =f"-gui_mirrortrack_cycle_count_stare{widget_id}-"
self.gui_mirrortrack_minthresh =f"-gui_mirrortrack_minthresh{widget_id}-"
self.gui_mirrortrack_rotation_clamp =f"-gui_mirrortrack_rotation_clamp{widget_id}-"
self.gui_mirrortrack_enable_inv =f"-gui_mirrortrack_enable_inv{widget_id}-"
#self.gui_mirrortrack_smoothing_rate =f"-gui_mirrortrack_smoothing_rate{widget_id}-"
def get_layout(self):
return [
[
sg.Text("MirrorTrack System:", background_color='#242224'),
],
[
sg.Checkbox(
"Enable:",
default=self.config.gui_mirrortrack_enabled,
key=self.gui_mirrortrack_enabled,
background_color="#424042",
tooltip="Enables MirrorTrack System",
),
],
[
sg.Radio(
"Use Left Eye",
"mirrortrack_selectedeye",
background_color="#424042",
tooltip="Uses the left eye as the tracked eye.",
),
sg.Radio(
"Use Right Eye",
"mirrortrack_selectedeye",
default=self.config.gui_mirrortrack_select_right,
key=self.gui_mirrortrack_select_right,
background_color="#424042",
tooltip="Uses the right eye as the tracked eye.",
)
],
[
sg.Text("Inwards Look Threshold", background_color=BACKGROUND_COLOR,tooltip=
"Sets the minimum distance of looking in that's required before state can chaned to cross-eyed."
"\n Lower value will make cross-eye detection more sensitive."
),
sg.InputText(
self.config.gui_mirrortrack_minthresh,
key=self.gui_mirrortrack_minthresh,
size=(0, 10),
),
],
[
sg.Text("Transition Cycle Count (Cross Eye)", background_color=BACKGROUND_COLOR,tooltip=
"How long it takes to detect you are cross-eyed, or no longer cross-eyed."
"\n Higher number means longer duration before changing in or out of being cross-eyed state."
),
sg.InputText(
self.config.gui_mirrortrack_cycle_count_inv,
key=self.gui_mirrortrack_cycle_count_inv,
size=(0, 10),
),
],
[
sg.Text("Transition Cycle Count (Stare Forward)", background_color=BACKGROUND_COLOR,tooltip=
"How long it takes to detect you are staring ahead, or no longer staring ahead."
"\n Higher number means longer duration before changing in or out of being in stare ahead state."
),
sg.InputText(
self.config.gui_mirrortrack_cycle_count_stare,
key=self.gui_mirrortrack_cycle_count_stare,
size=(0, 10),
),
],
#[
# sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR,tooltip=
# "How quickly eye smoothing decays when you enter or leave a cross-eyed state."
# "\nHigher number = shorter smoothing duration."
# ),
# sg.InputText(
# self.config.gui_mirrortrack_smoothing_rate,
# key=self.gui_mirrortrack_smoothing_rate,
# size=(0, 10),
# ),
#],
[
sg.Checkbox(
"Allow cross-eye:",
default=self.config.gui_mirrortrack_enable_inv,
key=self.gui_mirrortrack_enable_inv,
background_color="#424042",
tooltip="Enables cross-eye functionality",
),
],
[
sg.Text("Maximum allowed cross-eye", background_color=BACKGROUND_COLOR,tooltip=
"Defines the maximum inwards rotation that is output when cross-eyed."
"\n0 = will only look straight ahead \n0.5 = will go a little bit cross-eyed \n1 = maximum hurr durr "
),
sg.InputText(
self.config.gui_mirrortrack_rotation_clamp,
key=self.gui_mirrortrack_rotation_clamp,
size=(0, 10),
),
],
]

View File

@ -1,106 +0,0 @@
from pydantic import AfterValidator
from typing_extensions import Annotated
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
from settings.constants import BACKGROUND_COLOR
import PySimpleGUI as sg
from settings.modules.CommonFieldValidators import try_convert_to_float
from settings.modules.CommonFieldValidators import try_convert_to_int
class SmartInversionValidationModule(BaseValidationModel):
gui_smartinversion_enabled: bool
gui_smartinversion_select_right: bool
gui_smartinversion_frame_count: Annotated[int, AfterValidator(try_convert_to_int)]
gui_smartinversion_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
gui_smartinversion_minthresh: Annotated[float, AfterValidator(try_convert_to_float)]
gui_smartinversion_rotation_clamp: Annotated[float, AfterValidator(try_convert_to_float)]
class SmartInversionSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, **kwargs):
super().__init__(config=config, widget_id=widget_id, **kwargs)
self.validation_model = SmartInversionValidationModule
self.gui_smartinversion_enabled = f"-gui_smartinversion_enabled{widget_id}-"
self.gui_smartinversion_select_right = f"-gui_smartinversion_select_right{widget_id}-"
self.gui_smartinversion_frame_count =f"-gui_smartinversion_frame_count{widget_id}-"
self.gui_smartinversion_smoothing_rate =f"-gui_smartinversion_smoothing_rate{widget_id}-"
self.gui_smartinversion_minthresh =f"-gui_smartinversion_minthresh{widget_id}-"
self.gui_smartinversion_rotation_clamp =f"-gui_smartinversion_rotation_clamp{widget_id}-"
def get_layout(self):
return [
[
sg.Text("Smart Inversion Tracking System:", background_color='#242224'),
],
[
sg.Checkbox(
"Enable:",
default=self.config.gui_smartinversion_enabled,
key=self.gui_smartinversion_enabled,
background_color="#424042",
tooltip="Enables Smart Inversion Tracking System",
),
sg.Radio(
"Use Left Eye",
"smartinversion_selectedeye",
background_color="#424042",
tooltip="Uses the left eye as the tracked eye.",
),
sg.Radio(
"Use Right Eye",
"smartinversion_selectedeye",
default=self.config.gui_smartinversion_select_right,
key=self.gui_smartinversion_select_right,
background_color="#424042",
tooltip="Uses the right eye as the tracked eye.",
)
],
[
sg.Text("Inwards Look Threshold", background_color=BACKGROUND_COLOR,tooltip=
"Sets the minimum distance of looking in that's required before state can chaned to cross-eyed."
"\n Lower value will make cross-eye detection more sensitive."
),
sg.InputText(
self.config.gui_smartinversion_minthresh,
key=self.gui_smartinversion_minthresh,
size=(0, 10),
),
],
[
sg.Text("Inversion Trigger Frame Count", background_color=BACKGROUND_COLOR,tooltip=
"How long it takes to detect you are cross-eyed, or no longer cross-eyed."
"\n Higher number means longer duration before changing in or out of being cross-eyed state."
),
sg.InputText(
self.config.gui_smartinversion_frame_count,
key=self.gui_smartinversion_frame_count,
size=(0, 10),
),
],
[
sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR,tooltip=
"How quickly eye smoothing decays when you enter or leave a cross-eyed state."
"\nHigher number = shorter smoothing duration."
),
sg.InputText(
self.config.gui_smartinversion_smoothing_rate,
key=self.gui_smartinversion_smoothing_rate,
size=(0, 10),
),
],
[
sg.Text("Maximum allowed cross-eye", background_color=BACKGROUND_COLOR,tooltip=
"Defines the maximum inwards rotation that is output when cross-eyed."
"\n0 = will only look straight ahead \n0.5 = will go a little bit cross-eyed \n1 = maximum hurr durr "
),
sg.InputText(
self.config.gui_smartinversion_rotation_clamp,
key=self.gui_smartinversion_rotation_clamp,
size=(0, 10),
),
],
]

View File

@ -15,7 +15,7 @@ class CycleCounter:
def reset(self): def reset(self):
self.count = 0 self.count = 0
def complete(self): def is_complete(self):
if self.count >= self.max_count: if self.count >= self.max_count:
return True return True
return False return False
@ -27,4 +27,10 @@ class CycleCounter:
return True return True
def get_count(self): def get_count(self):
return self.count return self.count
def update(self,max_count):
self.max_count = max_count
def force_complete(self):
self.count = self.max_count

View File

@ -4,7 +4,7 @@ from config import EyeTrackConfig
from utils.CycleCounter import * from utils.CycleCounter import *
import threading import threading
class SmartInversion: class mirrortrack:
#Defines our possible tracking states #Defines our possible tracking states
class States(Enum): class States(Enum):
@ -15,7 +15,6 @@ class SmartInversion:
state = States.TRACKING state = States.TRACKING
#Defines our tracked positions #Defines our tracked positions
thread_lock = threading.Lock()
rx_left_x = 0.0 rx_left_x = 0.0
rx_left_y = 0.0 rx_left_y = 0.0
rx_right_x = 0.0 rx_right_x = 0.0
@ -39,7 +38,7 @@ class SmartInversion:
#Defines variables that require settings #Defines variables that require settings
@classmethod @classmethod
def init_config(cls,config: EyeTrackConfig): def init_config(cls,config: EyeTrackConfig):
if config.settings.gui_smartinversion_select_right: if config.settings.gui_mirrortrack_select_right:
cls.dom_eye = EyeId.RIGHT cls.dom_eye = EyeId.RIGHT
cls.rec_eye = EyeId.LEFT cls.rec_eye = EyeId.LEFT
cls.is_r_dom = True cls.is_r_dom = True
@ -48,35 +47,50 @@ class SmartInversion:
cls.rec_eye = EyeId.RIGHT cls.rec_eye = EyeId.RIGHT
cls.is_r_dom = False cls.is_r_dom = False
cls.inv_x_thresh = config.settings.gui_smartinversion_minthresh #Inversion related
cls.cycle_counts = config.settings.gui_smartinversion_frame_count cls.inv_is_enabled = config.settings.gui_mirrortrack_enable_inv
cls.inv_clamp = config.settings.gui_smartinversion_rotation_clamp cls.inv_x_thresh = config.settings.gui_mirrortrack_minthresh
cls.inv_clamp = config.settings.gui_mirrortrack_rotation_clamp
cls.inv_counter = CycleCounter(cls.cycle_counts*1.25) cls.cyc_counts_inv = config.settings.gui_mirrortrack_cycle_count_inv
cls.stare_counter = CycleCounter(cls.cycle_counts) cls.cyc_counts_stare = config.settings.gui_mirrortrack_cycle_count_stare
cls.cyc_counter_inv = CycleCounter(cls.cyc_counts_inv)
cls.cyc_counter_stare = CycleCounter(cls.cyc_counts_stare)
cls.thread_lock = threading.Lock()
#Receives changes in configuration and applies them accordingly #Receives changes in configuration and applies them accordingly
@classmethod @classmethod
def config_update(cls,data): def config_update(cls,data):
print(f"Smart inversion heard that some settings were changed!")
if "gui_smartinversion_select_right" in data: if "gui_mirrortrack_select_right" in data:
cls.dom_eye = EyeId.RIGHT if data["gui_smartinversion_select_right"] else EyeId.LEFT cls.dom_eye = EyeId.RIGHT if data["gui_mirrortrack_select_right"] else EyeId.LEFT
cls.rec_eye = EyeId.LEFT if data["gui_smartinversion_select_right"] else EyeId.RIGHT cls.rec_eye = EyeId.LEFT if data["gui_mirrortrack_select_right"] else EyeId.RIGHT
cls.is_r_dom = True if data["gui_smartinversion_select_right"] else False cls.is_r_dom = True if data["gui_mirrortrack_select_right"] else False
print(f"Dominant eye changed to {cls.dom_eye.name}") print(f"Dominant eye changed to {cls.dom_eye.name}")
if "gui_smartinversion_minthresh" in data: if "gui_mirrortrack_minthresh" in data:
cls.inv_x_thresh = data["gui_smartinversion_minthresh"] cls.inv_x_thresh = data["gui_mirrortrack_minthresh"]
print(f"Smart inversion transition threshold changed to {cls.inv_x_thresh}") print(f"MirrorTrack transition threshold changed to {cls.inv_x_thresh}")
if "gui_smartinversion_frame_count" in data: if "gui_mirrortrack_cycle_count_inv" in data:
cls.cycle_counts = data["gui_smartinversion_frame_count"] cls.cyc_counts_stare = data["gui_mirrortrack_cycle_count_inv"]
print(f"Smart inversion transition condition required cycle count changed to {cls.cycle_counts}") cls.cyc_counter_stare.update(cls.cyc_counts_stare)
print(f"MirrorTrack inversion transition condition required cycle count changed to {cls.cyc_counts_inv}")
if "gui_smartinversion_rotation_clamp" in data: if "gui_mirrortrack_cycle_count_stare" in data:
cls.inv_clamp = data["gui_smartinversion_rotation_clamp"] cls.cyc_counts_inv = data["gui_mirrortrack_cycle_count_stare"]
print(f"Smart inversion maximum allowed cross-eye changed to {cls.cycle_counts}") cls.cyc_counter_stare.update(cls.cyc_counts_inv)
print(f"MirrorTrack stare transition condition required cycle count changed to {cls.cyc_counts_stare}")
if "gui_mirrortrack_rotation_clamp" in data:
cls.inv_clamp = data["gui_mirrortrack_rotation_clamp"]
print(f"MirrorTrack maximum allowed cross-eye changed to {cls.inv_clamp}")
if "gui_mirrortrack_enable_inv" in data:
cls.inv_is_enabled = data["gui_mirrortrack_enable_inv"]
print(f"MirrorTrack allow cross-eye is set to {cls.inv_is_enabled}")
#Main processing function #Main processing function
@classmethod @classmethod
@ -84,7 +98,10 @@ class SmartInversion:
with cls.thread_lock: with cls.thread_lock:
cls.store_tracked_positions(eye_id,out_x,out_y) cls.store_tracked_positions(eye_id,out_x,out_y)
cls.check_for_stare() cls.check_for_stare()
cls.check_for_inversion()
if cls.inv_is_enabled:
cls.check_for_inversion()
out_x, out_y = cls.update_new_position(eye_id,out_x,out_y) out_x, out_y = cls.update_new_position(eye_id,out_x,out_y)
cls.store_processed_positions(eye_id,out_x,out_y) cls.store_processed_positions(eye_id,out_x,out_y)
return out_x, out_y return out_x, out_y
@ -125,54 +142,45 @@ class SmartInversion:
if cls.dom_is_inward() and cls.rec_is_inward(): if cls.dom_is_inward() and cls.rec_is_inward():
#Updates the counter for stare activation #Updates the counter for stare activation
if not cls.is_stare_mode() and not cls.stare_counter.complete(): if not cls.is_stare_mode() and not cls.cyc_counter_stare.is_complete():
cls.stare_counter.increase() cls.cyc_counter_stare.increase()
#Sets the state to stare if count completes #Sets the state to stare if count is_completes
elif not cls.is_stare_mode() and cls.stare_counter.complete() and not cls.bypass_stare: elif not cls.is_stare_mode() and cls.cyc_counter_stare.is_complete() and not cls.bypass_stare:
cls.set_state("STARE") cls.set_state("STARE")
print(f"State is {cls.state.name}")
elif cls.cyc_counter_stare.active():
cls.cyc_counter_stare.decrease()
if not cls.cyc_counter_stare.active():
if cls.bypass_stare:
cls.bypass_stare = False
if not cls.is_tracking_mode():
cls.set_state("TRACKING")
elif cls.is_stare_mode():
if cls.stare_counter.active():
cls.stare_counter.decrease()
if not cls.stare_counter.active():
if cls.bypass_stare:
cls.bypass_stare = False
print(f"bypass_stare disabled by check_for_stare")
cls.set_state("TRACKING")
print(f"State set to {cls.state.name}")
elif not cls.stare_counter.active():
cls.stare_counter.decrease()
@classmethod @classmethod
def check_for_inversion(cls): def check_for_inversion(cls):
if cls.dom_is_inward() and cls.rec_meets_thresh() and cls.is_stare_mode(): if cls.dom_is_inward() and cls.rec_meets_thresh() and (cls.is_stare_mode() or cls.bypass_stare):
#Updates the counter for activation #Updates the counter for activation
if not cls.is_inverted_mode() and not cls.inv_counter.complete(): if not cls.is_inverted_mode() and not cls.cyc_counter_inv.is_complete():
cls.inv_counter.increase() cls.cyc_counter_inv.increase()
#print(f"Inversion activation counter is increasing: {cls.inv_counter.get_count()}") #print(f"Inversion activation counter is increasing: {cls.cyc_counter_inv.get_count()}")
#Sets the state to inverted if enough cycles have completed #Sets the state to inverted if enough cycles have is_completed
elif not cls.is_inverted_mode() and cls.inv_counter.complete(): elif not cls.is_inverted_mode() and cls.cyc_counter_inv.is_complete():
cls.set_state("INVERTED") cls.set_state("INVERTED")
print(f"State set to {cls.state.name}")
cls.bypass_stare = True cls.bypass_stare = True
#Begins the counter for deactivation if conditions are not met #Begins the counter for deactivation if conditions are not met
elif cls.is_inverted_mode(): elif cls.cyc_counter_inv.active():
if cls.inv_counter.active(): cls.cyc_counter_inv.decrease()
cls.inv_counter.decrease()
if not cls.inv_counter.active(): if not cls.cyc_counter_inv.active():
if cls.bypass_stare: if cls.bypass_stare:
cls.bypass_stare = False cls.bypass_stare = False
print(f"bypass_stare disabled by check_for_inv") cls.cyc_counter_stare.force_complete()
cls.check_for_stare()
#Decreases the counter if conditions are not met, and inversion isn't active.
elif cls.inv_counter.active():
cls.inv_counter.decrease()
@classmethod @classmethod
def update_new_position(cls,eye_id,out_x,out_y): def update_new_position(cls,eye_id,out_x,out_y):
@ -206,6 +214,7 @@ class SmartInversion:
@classmethod @classmethod
def set_state(cls,new_state: str): def set_state(cls,new_state: str):
cls.state = cls.States[new_state] cls.state = cls.States[new_state]
print(f"State set to {cls.state.name}")
@classmethod @classmethod
def is_dominant_eye(cls,eye_id): def is_dominant_eye(cls,eye_id):
return eye_id == cls.dom_eye return eye_id == cls.dom_eye

View File

@ -75,13 +75,15 @@ def eyetrack_settings_config():
gui_vrc_native=False, gui_vrc_native=False,
gui_pupil_dilation=True, gui_pupil_dilation=True,
#Smart Inversion Tracking #MirrorTrack
gui_smartinversion_enabled=False, gui_mirrortrack_enabled=False,
gui_smartinversion_select_right=True, gui_mirrortrack_select_right=True,
gui_smartinversion_frame_count=10, gui_mirrortrack_cycle_count_inv=20,
gui_smartinversion_smoothing_rate=0.025, gui_mirrortrack_cycle_count_stare=20,
gui_smartinversion_minthresh=0.3, #gui_mirrortrack_smoothing_rate=0.025,
gui_smartinversion_rotation_clamp=1.0, gui_mirrortrack_minthresh=0.3,
gui_mirrortrack_rotation_clamp=0.3,
gui_mirrortrack_enable_inv=False
) )