This commit is contained in:
Fracas 2025-04-03 14:25:46 -07:00 committed by GitHub
commit 925cc055ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 842 additions and 568 deletions

View File

@ -0,0 +1,106 @@
import openvr
import os
import sys
import json
from logging import getLogger, ERROR, WARN
from config import EyeTrackConfig
from eye import EyeId
from colorama import Fore
import PySimpleGUI as sg
class OpenVRException(Exception):
pass
class OpenVRService:
appKey: str = "etvr.etvrapp"
manifest = {
"source": "builtin",
"applications": [
{
"app_key": appKey,
"launch_type": "binary",
"binary_path_windows": sys.executable,
"is_dashboard_overlay": True,
"strings": {
"en_us": {
"name": "EyeTrackVR",
"description": "EyeTrackVR allow translating a camera feed into face tracking datas."
}
}
}
]
}
manifestPath: str = os.path.abspath("app.vrmanifest")
# Write openvr manifest file
def write_manifest() -> None:
with open(OpenVRService.manifestPath, 'w') as f:
json.dump(OpenVRService.manifest, f)
def __init__(self) -> None:
self.is_initialized: bool = False
self.logger = getLogger(__name__)
# Initialize the openvr connection if it wasn't already
def initialize(self):
if self.is_initialized:
return
try:
openvr.init(openvr.VRApplication_Background)
except openvr.error_code.InitError_Init_NoServerForBackgroundApp:
raise OpenVRException("SteamVR is not running")
except (openvr.error_code.InitError_Init_HmdNotFound,
openvr.error_code.InitError_Init_HmdNotFoundPresenceFailed):
raise OpenVRException("No headset connected")
except openvr.error_code.InitError_Init_PathRegistryNotFound:
raise OpenVRException("SteamVR might not be installed")
except Exception as e:
raise OpenVRException(f"Unknown SteamVR initialization error ({e.__class__.__name__})")
def set_autostart(self, enabled: bool):
if enabled:
self.initialize()
self.app = openvr.IVRApplications()
# Write the manifest dynamically depending on current executable path
OpenVRService.write_manifest()
try:
self.app.addApplicationManifest(OpenVRService.manifestPath)
self.app.setApplicationAutoLaunch(OpenVRService.appKey, True)
except openvr.error_code.ApplicationError_UnknownApplication:
self.logger.log(ERROR, f"{Fore.RED}[ERROR] Could not register app in SteamVR")
raise OpenVRException("Could not register SteamVR app")
except Exception as e:
raise OpenVRException(f"Unknown error enabling auto launch: {e.__class__.__name__}")
else:
if os.path.exists(OpenVRService.manifestPath):
if self.initialize():
try:
self.app.removeApplicationManifest(OpenVRService.manifestPath)
except openvr.error_code.ApplicationError_UnknownApplication:
pass
# App won't autostart if the manifest doesn't exit anymore when SteamVR starts.
os.remove(OpenVRService.manifestPath)
# Called when general settings get updated in case autostart option is modified
def on_config_update(self, data):
if "gui_openvr_autostart" in data:
try:
self.set_autostart(data["gui_openvr_autostart"])
except OpenVRException as e:
# Uncheck the autostart option if we failed to toggle it on
self.window[f"-OPENVRAUTOSTART{EyeId.SETTINGS}-"].update(False)
self.logger.log(WARN, f"{Fore.YELLOW}[WARN] Cannot enable steamvr autostart: {e.args[0]}")
sg.popup_ok(
f"Cannot enable steamvr autostart: {e.args[0]}",
title="Warning",
text_color="#ffae42",
background_color="#292929"
)
openvr_service = OpenVRService()

View File

@ -217,6 +217,8 @@ class EyeTrackSettingsConfig(BaseModel):
gui_OutputMultiplier: float = 1
gui_use_module: bool = False
gui_openvr_autostart: bool = False
class EyeTrackConfig(BaseModel):
version: int = 1

View File

@ -37,7 +37,8 @@ from settings.general_settings_widget import SettingsWidget
from settings.algo_settings_widget import AlgoSettingsWidget
from osc.osc import OSCManager
from osc.OSCMessage import OSCMessage
from utils.misc_utils import is_nt, resource_path
from utils.misc_utils import is_nt, is_macos, resource_path
import cv2
import numpy as np
import uuid
@ -226,6 +227,19 @@ def main():
config.save()
cancellation_event = threading.Event()
# Start openvr service if autostart with openvr option is enabled
# Allow the app to be closed when SteamVR closes
if config.settings.gui_openvr_autostart and not is_macos:
from OVR.OpenVRService import openvr_service, OpenVRException
try:
openvr_service.initialize()
except OpenVRException:
pass
config.register_listener_callback(openvr_service.on_config_update)
# Check to see if we can connect to our video source first. If not, bring up camera finding
# dialog.
try:
@ -284,6 +298,7 @@ def main():
config.register_listener_callback(eyes[0].on_config_update)
config.register_listener_callback(eyes[1].on_config_update)
osc_manager.register_listeners(
config.settings.gui_osc_recenter_address,
[
@ -332,7 +347,10 @@ def main():
# First off, check for any events from the GUI
window = create_window(config, settings, eyes)
# Allow openvr service to access the windows to dynamically update the settings (uncheck autostart box)
if not is_macos:
openvr_service.window = window
while True:
event, values = window.read(timeout=tint) # this higher timeout saves some cpu usage

View File

@ -1,6 +1,7 @@
# -*- mode: python ; coding: utf-8 -*-
import sys ; sys.setrecursionlimit(sys.getrecursionlimit() * 5)
import openvr
block_cipher = None
@ -9,7 +10,10 @@ resources=[("Audio/*", "Audio"), ("Images/*", "Images/"), ("pye3d/refraction_mod
a = Analysis(
['eyetrackapp.py'],
pathex=[],
binaries=[],
binaries=[
(os.path.abspath(openvr.__file__ + "\\..\\libopenvr_api_32.dll"), "openvr"),
(os.path.abspath(openvr.__file__ + "\\..\\libopenvr_api_64.dll"), "openvr"),
],
datas=resources,
hiddenimports=['cv2', 'numpy', 'PySimpleGui', 'pkg_resources.extern'],
hookspath=[],

View File

@ -12,6 +12,7 @@ class GeneralSettingsValidationModel(BaseValidationModel):
gui_right_eye_dominant: bool
gui_left_eye_dominant: bool
gui_eye_dominant_diff_thresh: float
gui_openvr_autostart: bool
class GeneralSettingsModule(BaseSettingsModule):
@ -26,6 +27,7 @@ class GeneralSettingsModule(BaseSettingsModule):
self.gui_left_eye_dominant = f"-LEFTEYEDOMINANT{widget_id}-"
self.gui_right_eye_dominant = f"-RIGHTEYEDOMINANT{widget_id}-"
self.gui_update_check = f"-UPDATECHECK{widget_id}-"
self.gui_openvr_autostart = f"-OPENVRAUTOSTART{widget_id}-"
# gui_right_eye_dominant: bool = False
# gui_left_eye_dominant: bool = False
@ -69,6 +71,15 @@ class GeneralSettingsModule(BaseSettingsModule):
tooltip="Toggle update check on launch.",
),
],
[
sg.Checkbox(
"Start and stop with SteamVR",
default=self.config.gui_openvr_autostart,
key=self.gui_openvr_autostart,
background_color="#424042",
tooltip="Start the EyeTrackVR app when SteamVR starts, Stop the EyeTrackVRApp when SteamVR stops. Needs SteamVR running to be enabled",
),
],
[
sg.Text("Eye Falloff Settings:", background_color="#242224"),
],

View File

@ -1,11 +1,11 @@
import os
import typing
import sys
from pathlib import Path
from typing import Union
is_nt = True if os.name == "nt" else False
is_macos = True if os.uname().sysname == "Darwin" else False
def PlaySound(*args, **kwargs):

1258
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,9 @@ pyserial = "^3.5"
winotify = [
{ version = "^1.1.0", platform = 'win32' }
]
openvr = [
{ version = "^2.5.101", platform = 'win32' }
]
onnxruntime = "^1.13.1"
colorama = "^0.4.6"
taskipy = "^1.10.4"