feat: no gui mode working

This commit is contained in:
Prohurtz 2024-07-22 18:07:27 -05:00
parent e6ab12e30e
commit 4ae620eece
3 changed files with 448 additions and 417 deletions

View File

@ -115,20 +115,104 @@ class CameraWidget:
self.capture_queue, self.capture_queue,
) )
self.hover = None
# cartesian co-ordinates in widget space are used during selection
self.xy0 = None
self.xy1 = None
self.cartesian_needs_update = False
# polar co-ordinates from the image center are the canonical representation
self.cr, self.ca = None, None
self.roi_size = None
self.clip_size = None
self.clip_pos = None
self.padded_size = None
self.img_pos = None
self.roi_image_center = None
self.is_mouse_up = True
self.hover_pos = None
self.in_roi_mode = False
self.movavg_fps_queue = deque(maxlen=120)
self.movavg_bps_queue = deque(maxlen=120)
def get_widget_layout(self):
self.widget_layout = [
[
sg.Text("Camera Address", background_color="#424042"),
sg.InputText(
self.config.capture_source,
key=self.gui_camera_addr,
tooltip="Enter the IP address or UVC port of your camera. (Include the 'http://')",
),
],
[
sg.Button(
"Save and Restart Tracking",
key=self.gui_save_tracking_button,
button_color="#6f4ca1",
),
],
[
sg.Button(
"Tracking Mode",
key=self.gui_tracking_button,
button_color="#6f4ca1",
tooltip="Go here to track your eye.",
),
sg.Button(
"Cropping Mode",
key=self.gui_roi_button,
button_color="#6f4ca1",
tooltip="Go here to crop out your eye.",
),
],
[
sg.Text("Rotation", background_color="#424042"),
sg.Slider(
range=(0, 360),
default_value=self.config.rotation_angle,
orientation="h",
key=self.gui_rotation_slider,
background_color="#424042",
tooltip="Adjust the rotation of your cameras, make them level.",
),
],
[
sg.Column(
self.tracking_layout,
key=self.gui_tracking_layout,
background_color="#424042",
),
sg.Column(
self.roi_layout,
key=self.gui_roi_layout,
background_color="#424042",
visible=False,
),
],
]
def get_roi_layout(self):
self.roi_layout = [ self.roi_layout = [
[ [
# sg.Button( # sg.Button(
# "Mark Out", # "Mark Out",
# key=self.gui_mask_markup, # key=self.gui_mask_markup,
# button_color="#6f4ca1", # button_color="#6f4ca1",
# tooltip="Mark out stuff that is not your eye.", # tooltip="Mark out stuff that is not your eye.",
# ), # ),
# sg.Button( # sg.Button(
# "Lighten", # "Lighten",
# key=self.gui_mask_lighten, # key=self.gui_mask_lighten,
# button_color="#6f4ca1", # button_color="#6f4ca1",
# tooltip="Lighten shadowed areas.", # tooltip="Lighten shadowed areas.",
# ), # ),
sg.Checkbox( sg.Checkbox(
"Camera Widget Padding", "Camera Widget Padding",
default=self.config.gui_rotation_ui_padding, default=self.config.gui_rotation_ui_padding,
@ -151,6 +235,7 @@ class CameraWidget:
], ],
] ]
def get_tracking_layout(self):
# Define the window's contents # Define the window's contents
self.tracking_layout = [ self.tracking_layout = [
[ [
@ -208,82 +293,11 @@ class CameraWidget:
], ],
] ]
self.widget_layout = [
[
sg.Text("Camera Address", background_color="#424042"),
sg.InputText(
self.config.capture_source,
key=self.gui_camera_addr,
tooltip="Enter the IP address or UVC port of your camera. (Include the 'http://')",
),
],
[
sg.Button(
"Save and Restart Tracking",
key=self.gui_save_tracking_button,
button_color="#6f4ca1",
),
],
[
sg.Button(
"Tracking Mode",
key=self.gui_tracking_button,
button_color="#6f4ca1",
tooltip="Go here to track your eye.",
),
sg.Button(
"Cropping Mode",
key=self.gui_roi_button,
button_color="#6f4ca1",
tooltip="Go here to crop out your eye.",
),
],
[
sg.Text("Rotation", background_color="#424042"),
sg.Slider(
range=(0, 360),
default_value=self.config.rotation_angle,
orientation="h",
key=self.gui_rotation_slider,
background_color="#424042",
tooltip="Adjust the rotation of your cameras, make them level.",
),
],
[
sg.Column(
self.tracking_layout,
key=self.gui_tracking_layout,
background_color="#424042",
),
sg.Column(
self.roi_layout,
key=self.gui_roi_layout,
background_color="#424042",
visible=False,
),
],
]
self.hover = None def update_layouts(self):
self.get_roi_layout()
# cartesian co-ordinates in widget space are used during selection self.get_tracking_layout()
self.xy0 = None self.get_widget_layout()
self.xy1 = None
self.cartesian_needs_update = False
# polar co-ordinates from the image center are the canonical representation
self.cr, self.ca = None, None
self.roi_size = None
self.clip_size = None
self.clip_pos = None
self.padded_size = None
self.img_pos = None
self.roi_image_center = None
self.is_mouse_up = True
self.hover_pos = None
self.in_roi_mode = False
self.movavg_fps_queue = deque(maxlen=120)
self.movavg_bps_queue = deque(maxlen=120)
def _movavg_fps(self, next_fps): def _movavg_fps(self, next_fps):
self.movavg_fps_queue.append(next_fps) self.movavg_fps_queue.append(next_fps)
@ -417,6 +431,7 @@ class CameraWidget:
self.main_config.save() self.main_config.save()
if event == self.gui_tracking_button: if event == self.gui_tracking_button:
self.get_tracking_layout()
print("\033[94m[INFO] Moving to tracking mode\033[0m") print("\033[94m[INFO] Moving to tracking mode\033[0m")
self.in_roi_mode = False self.in_roi_mode = False
self.camera.set_output_queue(self.capture_queue) self.camera.set_output_queue(self.capture_queue)
@ -424,6 +439,7 @@ class CameraWidget:
window[self.gui_tracking_layout].update(visible=True) window[self.gui_tracking_layout].update(visible=True)
if event == self.gui_roi_button: if event == self.gui_roi_button:
self.get_roi_layout()
print("\033[94m[INFO] Move to roi mode\033[0m") print("\033[94m[INFO] Move to roi mode\033[0m")
self.in_roi_mode = True self.in_roi_mode = True
self.camera.set_output_queue(self.roi_queue) self.camera.set_output_queue(self.roi_queue)

View File

@ -41,6 +41,8 @@ from utils.misc_utils import is_nt, resource_path
import time import time
import cv2 import cv2
import numpy as np import numpy as np
import uuid
if is_nt: if is_nt:
from winotify import Notification from winotify import Notification
@ -50,23 +52,159 @@ os.system("color") # init ANSI color
# https://github.com/opencv/opencv/issues/17687 # https://github.com/opencv/opencv/issues/17687
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
WINDOW_NAME = "EyeTrackApp" WINDOW_NAME = "EyeTrackApp"
RIGHT_EYE_NAME = "-RIGHTEYEWIDGET-"
LEFT_EYE_NAME = "-LEFTEYEWIDGET-"
SETTINGS_NAME = "-SETTINGSWIDGET-"
ALGO_SETTINGS_NAME = "-ALGOSETTINGSWIDGET-"
VRCFT_MODULE_SETTINGS_NAME = "-VRCFTSETTINGSWIDGET-"
LEFT_EYE_RADIO_NAME = "-LEFTEYERADIO-"
RIGHT_EYE_RADIO_NAME = "-RIGHTEYERADIO-"
BOTH_EYE_RADIO_NAME = "-BOTHEYERADIO-"
SETTINGS_RADIO_NAME = "-SETTINGSRADIO-"
ALGO_SETTINGS_RADIO_NAME = "-ALGOSETTINGSRADIO-"
VRCFT_MODULE_SETTINGS_RADIO_NAME = "-VRCFTSETTINGSRADIO-"
GUIOFF_RADIO_NAME = "-GUIOFF-"
page_url = "https://github.com/RedHawk989/EyeTrackVR/releases/latest" page_url = "https://github.com/RedHawk989/EyeTrackVR/releases/latest"
appversion = "EyeTrackApp 0.2.0 BETA 13" appversion = "EyeTrackApp 0.2.0 BETA 13"
class KeyManager:
def __init__(self):
self.update_keys()
def update_keys(self):
unique_id = str(uuid.uuid4())
self.RIGHT_EYE_NAME = f"-RIGHTEYEWIDGET{unique_id}-"
self.LEFT_EYE_NAME = f"-LEFTEYEWIDGET{unique_id}-"
self.SETTINGS_NAME = f"-SETTINGSWIDGET{unique_id}-"
self.ALGO_SETTINGS_NAME = f"-ALGOSETTINGSWIDGET{unique_id}-"
self.VRCFT_MODULE_SETTINGS_NAME = f"-VRCFTSETTINGSWIDGET{unique_id}-"
self.LEFT_EYE_RADIO_NAME = f"-LEFTEYERADIO{unique_id}-"
self.RIGHT_EYE_RADIO_NAME = f"-RIGHTEYERADIO{unique_id}-"
self.BOTH_EYE_RADIO_NAME = f"-BOTHEYERADIO{unique_id}-"
self.SETTINGS_RADIO_NAME = f"-SETTINGSRADIO{unique_id}-"
self.ALGO_SETTINGS_RADIO_NAME = f"-ALGOSETTINGSRADIO{unique_id}-"
self.VRCFT_MODULE_SETTINGS_RADIO_NAME = f"-VRCFTSETTINGSRADIO{unique_id}-"
self.GUIOFF_RADIO_NAME = f"-GUIOFF{unique_id}-"
# Create an instance of the KeyManager
key_manager = KeyManager()
def create_window(config, settings, eyes):
key_manager.update_keys()
for eye in eyes:
eye.update_layouts()
layout = [
[
sg.Radio(
"Left Eye",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.LEFT),
key=key_manager.LEFT_EYE_RADIO_NAME,
),
sg.Radio(
"Right Eye",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.RIGHT),
key=key_manager.RIGHT_EYE_RADIO_NAME,
),
sg.Radio(
"Both Eyes",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.BOTH),
key=key_manager.BOTH_EYE_RADIO_NAME,
),
sg.Radio(
"Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.SETTINGS),
key=key_manager.SETTINGS_RADIO_NAME,
),
sg.Radio(
"Algo Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.ALGOSETTINGS),
key=key_manager.ALGO_SETTINGS_RADIO_NAME,
),
],
[
sg.Radio(
"VRCFT Module Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.VRCFTMODULESETTINGS),
key=key_manager.VRCFT_MODULE_SETTINGS_RADIO_NAME,
),
sg.Radio(
"GUI OFF",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.GUIOFF),
key=key_manager.GUIOFF_RADIO_NAME,
),
],
[
sg.Column(
eyes[1].widget_layout,
vertical_alignment="top",
key=key_manager.LEFT_EYE_NAME,
visible=(config.eye_display_id in [EyeId.LEFT, EyeId.BOTH]),
background_color="#424042",
),
sg.Column(
eyes[0].widget_layout,
vertical_alignment="top",
key=key_manager.RIGHT_EYE_NAME,
visible=(config.eye_display_id in [EyeId.RIGHT, EyeId.BOTH]),
background_color="#424042",
),
sg.Column(
settings[0].get_layout(),
vertical_alignment="top",
key=key_manager.SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.SETTINGS]),
background_color="#424042",
),
sg.Column(
settings[1].get_layout(),
vertical_alignment="top",
key=key_manager.ALGO_SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.ALGOSETTINGS]),
background_color="#424042",
),
sg.Column(
settings[2].get_layout(),
vertical_alignment="top",
key=key_manager.VRCFT_MODULE_SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.VRCFTMODULESETTINGS]),
background_color="#424042",
),
],
]
if config.eye_display_id in [EyeId.LEFT, EyeId.BOTH]:
eyes[1].start()
if config.eye_display_id in [EyeId.RIGHT, EyeId.BOTH]:
eyes[0].start()
if config.eye_display_id in [EyeId.SETTINGS]:
settings[0].start()
if config.eye_display_id in [EyeId.ALGOSETTINGS]:
settings[1].start()
if config.eye_display_id in [EyeId.VRCFTMODULESETTINGS]:
settings[2].start()
# the eye's needs to be running before it is passed to the OSC
# Create the window
return sg.Window(
f"{appversion}",
layout,
icon=resource_path("Images/logo.ico"),
background_color="#292929")
def main(): def main():
# Get Configuration # Get Configuration
config: EyeTrackConfig = EyeTrackConfig.load() config: EyeTrackConfig = EyeTrackConfig.load()
@ -147,279 +285,206 @@ def main():
osc_manager.start() osc_manager.start()
layout = [ # window = create_window(config, settings, eyes)
[
sg.Radio(
"Left Eye",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.LEFT),
key=LEFT_EYE_RADIO_NAME,
),
sg.Radio(
"Right Eye",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.RIGHT),
key=RIGHT_EYE_RADIO_NAME,
),
sg.Radio(
"Both Eyes",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.BOTH),
key=BOTH_EYE_RADIO_NAME,
),
sg.Radio(
"Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.SETTINGS),
key=SETTINGS_RADIO_NAME,
),
sg.Radio(
"Algo Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.ALGOSETTINGS),
key=ALGO_SETTINGS_RADIO_NAME,
),
],
[
sg.Radio(
"VRCFT Module Settings",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.VRCFTMODULESETTINGS),
key=VRCFT_MODULE_SETTINGS_RADIO_NAME,
),
sg.Radio(
"GUI OFF",
"EYESELECTRADIO",
background_color="#292929",
default=(config.eye_display_id == EyeId.GUIOFF),
key=GUIOFF_RADIO_NAME,
),
],
[
sg.Column(
eyes[1].widget_layout,
vertical_alignment="top",
key=LEFT_EYE_NAME,
visible=(config.eye_display_id in [EyeId.LEFT, EyeId.BOTH]),
background_color="#424042",
),
sg.Column(
eyes[0].widget_layout,
vertical_alignment="top",
key=RIGHT_EYE_NAME,
visible=(config.eye_display_id in [EyeId.RIGHT, EyeId.BOTH]),
background_color="#424042",
),
sg.Column(
settings[0].get_layout(),
vertical_alignment="top",
key=SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.SETTINGS]),
background_color="#424042",
),
sg.Column(
settings[1].get_layout(),
vertical_alignment="top",
key=ALGO_SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.ALGOSETTINGS]),
background_color="#424042",
),
sg.Column(
settings[2].get_layout(),
vertical_alignment="top",
key=VRCFT_MODULE_SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.VRCFTMODULESETTINGS]),
background_color="#424042",
),
],
]
if config.eye_display_id in [EyeId.LEFT, EyeId.BOTH]:
eyes[1].start()
if config.eye_display_id in [EyeId.RIGHT, EyeId.BOTH]:
eyes[0].start()
if config.eye_display_id in [EyeId.SETTINGS]:
settings[0].start()
if config.eye_display_id in [EyeId.ALGOSETTINGS]:
settings[1].start()
if config.eye_display_id in [EyeId.VRCFTMODULESETTINGS]:
settings[2].start()
# the eye's needs to be running before it is passed to the OSC
# Create the window
window = sg.Window(
f"{appversion}",
layout,
icon=resource_path("Images/logo.ico"),
background_color="#292929",
)
while True: while True:
print('main loop')
if config.settings.gui_disable_gui: if config.settings.gui_disable_gui:
timeout = 10 #TODO: test this on windows, on mac im not seeing a negitive side effect print('ee')
layout = [[sg.Button("Enable GUI")]] layoutg = [
[sg.Button('Enable GUI')]
]
# Create the window # Create the window
window = sg.Window("Simple Button", layout) windowg = sg.Window('Simple Window', layoutg)
# Event loop to process events and get the values of the inputs # Event loop
while True: while True:
event, values = window.read()
# If user closes window or clicks the button, break the loop eventg, valuesg = windowg.read()
if event == sg.WINDOW_CLOSED:
if eventg == sg.WINDOW_CLOSED:
break break
elif event == "Enable GUI": elif eventg == 'Enable GUI':
print("Button clicked!")
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
config.save() config.save()
print('GUI Enabled')
break break
# Close the window # Close the window
window.close() windowg.close()
print('close')
else:
timeout = 1
# GUI Render loop
while True:
# First off, check for any events from the GUI # First off, check for any events from the GUI
event, values = window.read(timeout=timeout) # this higher timeout saves some cpu usage window = create_window(config, settings, eyes)
print('new window')
while True:
event, values = window.read(timeout=1) # this higher timeout saves some cpu usage
# If we're in either mode and someone hits q, quit immediately # If we're in either mode and someone hits q, quit immediately
if event == "Exit" or event == sg.WIN_CLOSED: if event == "Exit" or event == sg.WIN_CLOSED and not config.settings.gui_disable_gui:
for eye in eyes: print(event == "Exit", event == sg.WIN_CLOSED, config.settings.gui_disable_gui)
eye.stop() for eye in eyes:
cancellation_event.set() eye.stop()
osc_manager.shutdown() cancellation_event.set()
print("\033[94m[INFO] Exiting EyeTrackApp\033[0m") osc_manager.shutdown()
os._exit(0) # I do not like this, but for now this fixes app hang on close print("\033[94m[INFO] Exiting EyeTrackApp\033[0m")
return window.close()
os._exit(0) # I do not like this, but for now this fixes app hang on close
return
if values[RIGHT_EYE_RADIO_NAME] and config.eye_display_id != EyeId.RIGHT: if values[key_manager.RIGHT_EYE_RADIO_NAME] and config.eye_display_id != EyeId.RIGHT:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
eyes[0].start() eyes[0].start()
eyes[1].stop() eyes[1].stop()
settings[0].stop() settings[0].stop()
settings[1].stop() settings[1].stop()
settings[2].stop() settings[2].stop()
window[RIGHT_EYE_NAME].update(visible=True) window[key_manager.RIGHT_EYE_NAME].update(visible=True)
window[LEFT_EYE_NAME].update(visible=False) window[key_manager.LEFT_EYE_NAME].update(visible=False)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.RIGHT config.eye_display_id = EyeId.RIGHT
config.settings.tracker_single_eye = 2 config.settings.tracker_single_eye = 2
config.save() config.save()
elif values[LEFT_EYE_RADIO_NAME] and config.eye_display_id != EyeId.LEFT: elif values[key_manager.LEFT_EYE_RADIO_NAME] and config.eye_display_id != EyeId.LEFT:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
settings[0].stop() settings[0].stop()
settings[1].stop() settings[1].stop()
settings[2].stop() settings[2].stop()
eyes[0].stop() eyes[0].stop()
eyes[1].start() eyes[1].start()
window[RIGHT_EYE_NAME].update(visible=False) window[key_manager.RIGHT_EYE_NAME].update(visible=False)
window[LEFT_EYE_NAME].update(visible=True) window[key_manager.LEFT_EYE_NAME].update(visible=True)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.LEFT config.eye_display_id = EyeId.LEFT
config.settings.tracker_single_eye = 1 config.settings.tracker_single_eye = 1
config.save() config.save()
elif values[BOTH_EYE_RADIO_NAME] and config.eye_display_id != EyeId.BOTH: elif values[key_manager.BOTH_EYE_RADIO_NAME] and config.eye_display_id != EyeId.BOTH:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
settings[0].stop() settings[0].stop()
settings[1].stop() settings[1].stop()
settings[2].stop() settings[2].stop()
eyes[1].start() eyes[1].start()
eyes[0].start() eyes[0].start()
window[LEFT_EYE_NAME].update(visible=True) window[key_manager.LEFT_EYE_NAME].update(visible=True)
window[RIGHT_EYE_NAME].update(visible=True) window[key_manager.RIGHT_EYE_NAME].update(visible=True)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.BOTH config.eye_display_id = EyeId.BOTH
config.settings.tracker_single_eye = 0 config.settings.tracker_single_eye = 0
config.save() config.save()
elif values[SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.SETTINGS: elif values[key_manager.SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.SETTINGS:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
eyes[0].stop() eyes[0].stop()
eyes[1].stop() eyes[1].stop()
settings[1].stop() settings[1].stop()
settings[0].start() settings[0].start()
settings[2].stop() settings[2].stop()
window[RIGHT_EYE_NAME].update(visible=False) window[key_manager.RIGHT_EYE_NAME].update(visible=False)
window[LEFT_EYE_NAME].update(visible=False) window[key_manager.LEFT_EYE_NAME].update(visible=False)
window[SETTINGS_NAME].update(visible=True) window[key_manager.SETTINGS_NAME].update(visible=True)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.SETTINGS config.eye_display_id = EyeId.SETTINGS
config.save() config.save()
elif values[ALGO_SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.ALGOSETTINGS: elif values[key_manager.ALGO_SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.ALGOSETTINGS:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
eyes[0].stop() eyes[0].stop()
eyes[1].stop() eyes[1].stop()
settings[0].stop() settings[0].stop()
settings[1].start() settings[1].start()
settings[2].stop() settings[2].stop()
window[RIGHT_EYE_NAME].update(visible=False) window[key_manager.RIGHT_EYE_NAME].update(visible=False)
window[LEFT_EYE_NAME].update(visible=False) window[key_manager.LEFT_EYE_NAME].update(visible=False)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=True) window[key_manager.ALGO_SETTINGS_NAME].update(visible=True)
config.eye_display_id = EyeId.ALGOSETTINGS config.eye_display_id = EyeId.ALGOSETTINGS
config.save() config.save()
elif values[VRCFT_MODULE_SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.VRCFTMODULESETTINGS: elif values[key_manager.VRCFT_MODULE_SETTINGS_RADIO_NAME] and config.eye_display_id != EyeId.VRCFTMODULESETTINGS:
config.settings.gui_disable_gui = False config.settings.gui_disable_gui = False
eyes[0].stop() eyes[0].stop()
eyes[1].stop() eyes[1].stop()
settings[0].stop() settings[0].stop()
settings[1].stop() settings[1].stop()
settings[2].start() settings[2].start()
window[RIGHT_EYE_NAME].update(visible=False) window[key_manager.RIGHT_EYE_NAME].update(visible=False)
window[LEFT_EYE_NAME].update(visible=False) window[key_manager.LEFT_EYE_NAME].update(visible=False)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=True) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=True)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.VRCFTMODULESETTINGS config.eye_display_id = EyeId.VRCFTMODULESETTINGS
config.save() config.save()
elif values[GUIOFF_RADIO_NAME] and config.eye_display_id != EyeId.GUIOFF: elif values[key_manager.GUIOFF_RADIO_NAME] and config.eye_display_id != EyeId.GUIOFF:
config.settings.gui_disable_gui = True config.settings.gui_disable_gui = True
# eyes[0].stop() # eyes[0].stop()
# eyes[1].stop() # eyes[1].stop()
settings[0].stop() settings[0].stop()
settings[1].stop() settings[1].stop()
settings[2].stop() settings[2].stop()
window[RIGHT_EYE_NAME].update(visible=False) window[key_manager.RIGHT_EYE_NAME].update(visible=False)
window[LEFT_EYE_NAME].update(visible=False) window[key_manager.LEFT_EYE_NAME].update(visible=False)
window[SETTINGS_NAME].update(visible=False) window[key_manager.SETTINGS_NAME].update(visible=False)
window[VRCFT_MODULE_SETTINGS_NAME].update(visible=False) window[key_manager.VRCFT_MODULE_SETTINGS_NAME].update(visible=False)
window[ALGO_SETTINGS_NAME].update(visible=False) window[key_manager.ALGO_SETTINGS_NAME].update(visible=False)
config.eye_display_id = EyeId.GUIOFF config.eye_display_id = EyeId.GUIOFF
config.save() config.save()
break window.close()
break
else:
# Otherwise, render all
for eye in eyes:
if eye.started():
eye.render(window, event, values)
for setting in settings:
if setting.started():
setting.render(window, event, values)
# while True:
# print('main loop')
# if config.settings.gui_disable_gui:
# layoutg = [[sg.Button("Enable GUI")]]
# Create the window
# windowc = sg.Window("Simple Button", layoutg)
# Event loop to process events and get the values of the inputs
# while True:
# eventg, valuesg = windowc.read()
#
# If user closes window or clicks the button, break the loop
# if eventg == sg.WINDOW_CLOSED:
# break
# elif eventg == "Enable GUI":
# config.settings.gui_disable_gui = False
# config.save()
# break
# Close the window
# windowc.close()
# else:
# print('main loop')
# run_window(config, settings, eyes)
else:
# Otherwise, render all
for eye in eyes:
if eye.started():
eye.render(window, event, values)
for setting in settings:
if setting.started():
setting.render(window, event, values)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -3,70 +3,32 @@ from typing import Iterable
import PySimpleGUI as sg import PySimpleGUI as sg
from colorama import Fore from colorama import Fore
from config import EyeTrackConfig, EyeTrackSettingsConfig
from threading import Event from threading import Event
from eye import EyeId from eye import EyeId
from config import EyeTrackConfig, EyeTrackSettingsConfig
class BaseSettingsWidget: class BaseSettingsWidget:
def __init__( def __init__(self, widget_id: EyeId, main_config: EyeTrackConfig, settings_modules: Iterable):
self, self.widget_id = widget_id
widget_id: EyeId,
main_config: EyeTrackConfig,
settings_modules: Iterable,
):
# we put the last time an error was printed in the past so whenever a newone appears
self.last_error_printout = datetime.now() - timedelta(seconds=20)
self.error_printout_timeout = 2
self.gui_general_settings_layout = f"-GENERALSETTINGSLAYOUT{widget_id}-"
self.reset_button_key = f"RESET_SETTINGS{widget_id}"
self.is_saving = False
self.main_config = main_config self.main_config = main_config
self.config = main_config.settings self.config = main_config.settings
self.last_error_printout = datetime.now() - timedelta(seconds=20)
self.error_printout_timeout = 2
self.reset_button_key = f"RESET_SETTINGS{widget_id}"
self.is_saving = False
self.initialized_modules = self._initialize_modules(settings_modules=settings_modules, widget_id=widget_id) self.initialized_modules = self._initialize_modules(settings_modules=settings_modules, widget_id=widget_id)
self.cancellation_event = Event()
self.general_settings_layout = []
for module in self.initialized_modules:
self.general_settings_layout.extend(module.get_layout())
self.widget_layout = [
[
sg.Column(
self.general_settings_layout,
key=self.gui_general_settings_layout,
background_color="#424042",
),
],
[
sg.Text("", background_color="#424042"),
],
[
sg.Button(
"Reset settings to default",
key=self.reset_button_key,
button_color="#c40e23",
)
],
]
self.cancellation_event = (
Event()
) # Set the event until start is called, otherwise we can block if shutdown is called.
self.cancellation_event.set() self.cancellation_event.set()
def started(self): def started(self):
return not self.cancellation_event.is_set() return not self.cancellation_event.is_set()
def start(self): def start(self):
# If we're already running, bail
if not self.cancellation_event.is_set(): if not self.cancellation_event.is_set():
return return
self.cancellation_event.clear() self.cancellation_event.clear()
def stop(self): def stop(self):
# If we're not running yet, bail
if self.cancellation_event.is_set(): if self.cancellation_event.is_set():
return return
self.cancellation_event.set() self.cancellation_event.set()
@ -80,58 +42,47 @@ class BaseSettingsWidget:
elapsed_seconds = (datetime.now() - self.last_error_printout).seconds elapsed_seconds = (datetime.now() - self.last_error_printout).seconds
if elapsed_seconds > self.error_printout_timeout: if elapsed_seconds > self.error_printout_timeout:
self.last_error_printout = now self.last_error_printout = now
messages = [f"{Fore.RED}[ERROR]{Fore.RESET} {error['msg']} \n" for module_errors in errors for error in module_errors]
messages = []
for module_errors in errors:
for error in module_errors:
messages.append(f"{Fore.RED}[ERROR]{Fore.RESET} {error['msg']} \n")
print("".join(messages)) print("".join(messages))
def render(self, window, event, values): def render(self, window, event, values):
validated_data, errors = {}, [] validated_data, errors = {}, []
# we might want to think about event driven architecture here eventually, validate only
# if anything changes instead of checking for changes
for module in self.initialized_modules: for module in self.initialized_modules:
module_validated_data = module.validate(values) module_validated_data = module.validate(values)
if module_validated_data.changes: if module_validated_data.changes:
validated_data.update(module_validated_data.changes) validated_data.update(module_validated_data.changes)
if module_validated_data.errors: if module_validated_data.errors:
errors.append(module_validated_data.errors) errors.append(module_validated_data.errors)
if not errors and validated_data and not self.is_saving: if not errors and validated_data and not self.is_saving:
self.is_saving = True self.is_saving = True
self._update_and_save_config(validated_data) self._update_and_save_config(validated_data)
if errors: if errors:
self._handle_errors(errors) self._handle_errors(errors)
self.handle_events(event, window) self.handle_events(event, window)
def _initialize_modules(self, settings_modules, widget_id): def _initialize_modules(self, settings_modules, widget_id):
return [ return [module(config=self.config, settings=self.main_config, widget_id=widget_id) for module in settings_modules]
module(
config=self.config,
settings=self.main_config,
widget_id=widget_id,
)
for module in settings_modules
]
def get_layout(self) -> Iterable: def get_layout(self) -> Iterable:
return self.widget_layout general_settings_layout = []
for module in self.initialized_modules:
general_settings_layout.extend(module.get_layout())
widget_layout = [
[sg.Column(general_settings_layout, key=f"-GENERALSETTINGSLAYOUT{self.widget_id}-", background_color="#424042")],
[sg.Text("", background_color="#424042")],
[sg.Button("Reset settings to default", key=self.reset_button_key, button_color="#c40e23")]
]
return widget_layout
def handle_events(self, event, window): def handle_events(self, event, window):
if event == "__TIMEOUT__": if event == "__TIMEOUT__":
return return
if event == self.reset_button_key: if event == self.reset_button_key:
self.reset_config(window) self.reset_config(window)
def reset_config(self, window): def reset_config(self, window):
default_values = {} default_values = {}
base_settings = EyeTrackSettingsConfig() base_settings = EyeTrackSettingsConfig()
print(f"\033[92m[INFO] Resetting config to defaults\033[0m") print(f"\033[92m[INFO] Resetting config to defaults\033[0m")
for module in self.initialized_modules: for module in self.initialized_modules:
for key in module.get_key_for_panel_defaults(): for key in module.get_key_for_panel_defaults():
@ -140,5 +91,4 @@ class BaseSettingsWidget:
default_values[key] = default_val default_values[key] = default_val
window[widget_key].update(default_val) window[widget_key].update(default_val)
print(f"\033[92m[INFO] Config reset, saving\033[0m") print(f"\033[92m[INFO] Config reset, saving\033[0m")
self._update_and_save_config(default_values) self._update_and_save_config(default_values)