Skip to content

Commit

Permalink
[Update] Resizeable window, scrollable tracker list, multiple tracker…
Browse files Browse the repository at this point in the history
… address
  • Loading branch information
Z4urce committed Nov 23, 2024
1 parent 8350d89 commit 38a642d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 21 deletions.
20 changes: 18 additions & 2 deletions BridgeApp/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,21 @@ def get_multiplier(model: str):
class TrackerConfig(BaseModel):
# serial: str
enabled: bool = True # Not yet used
address: str = "/avatar/parameters/..."
address: str = "" # Deprecated
address_list: List[str] = []
multiplier_override: float = 1.0
pattern_override: str = "None"
battery_threshold: int = 20

def get_address_str(self):
if len(self.address_list) == 0:
self.address_list.append("/avatar/parameters/...")

result = ";".join(self.address_list)
return result

def set_address(self, value):
self.address_list = value.split(';')

def set_vibration_multiplier(self, value):
if value is None:
Expand Down Expand Up @@ -69,7 +80,7 @@ def __init__(self, pattern: str, str_min: int, str_max: int, speed: int, **data:


class AppConfig(BaseModel):
version: int = 1
version: int = 2
server_type: int = 0
server_ip: str = "127.0.0.1"
server_port: int = 9001
Expand All @@ -94,6 +105,11 @@ def check_integrity(self):
new_config.address = self.tracker_to_osc[key]
self.tracker_config_dict[key] = new_config
self.tracker_to_osc.clear()

for serial, tracker_config in self.tracker_config_dict.items():
if tracker_config.address:
tracker_config.set_address(tracker_config.address)
tracker_config.address = ''

def init_pattern_config(self):
self.pattern_config_list.clear()
Expand Down
42 changes: 30 additions & 12 deletions BridgeApp/app_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from app_config import AppConfig, PatternConfig
from app_pattern import VibrationPattern

WINDOW_NAME = "Haptic Pancake Bridge v0.6.0a"
WINDOW_NAME = "Haptic Pancake Bridge v0.7.0a"

LIST_SERVER_TYPE = ["OSC (VRChat)", "WebSocket (Resonite)"]

Expand Down Expand Up @@ -45,9 +45,10 @@ def __init__(self, app_config: AppConfig, tracker_test_event,
self.config = app_config
self.shutting_down = False
self.window = None
self.layout_dirty = False
self.trackers = []
self.osc_status_bar = sg.Text('', key=KEY_OSC_STATUS_BAR)
self.tracker_frame = sg.Column([], key=KEY_LAYOUT_TRACKERS)
self.tracker_frame = sg.Column([], key=KEY_LAYOUT_TRACKERS, scrollable=True, vertical_scroll_only=True, expand_y=True, size=(406,270))
self.layout = []
self.build_layout()

Expand Down Expand Up @@ -111,7 +112,7 @@ def device_row(self, tracker_serial, tracker_model, additional_layout, icon=None
string = f"{icon} {tracker_serial} {tracker_model}"

dev_config = self.config.get_tracker_config(tracker_serial)
address = dev_config.address
address = dev_config.get_address_str()
vib_multiplier = dev_config.multiplier_override
battery_threshold = dev_config.battery_threshold

Expand Down Expand Up @@ -188,11 +189,12 @@ def add_target(self, tracker_serial, tracker_model, layout):
print(f"[GUI] Tracker {tracker_serial} is already on the list. Skipping...")
return

row = [self.tracker_row(tracker_serial, tracker_model)]
# row = [self.tracker_row(tracker_serial, tracker_model)]
if self.window is not None:
self.window.extend_layout(self.window[KEY_LAYOUT_TRACKERS], row)
self.window.extend_layout(self.tracker_frame, layout)
self.refresh()
else:
self.tracker_frame.layout(row)
self.tracker_frame.layout(layout)

self.trackers.append(tracker_serial)

Expand All @@ -209,7 +211,7 @@ def add_footer(self):
tooltip="Add an external feedback device"), ])
self.layout.append([sg.HSep()])
self.layout.append(
[sg.Text("Made by Z4urce", enable_events=True, font='Default 8 underline', key=KEY_OPEN_URL)])
[sg.Text("Made by Zelus (Z4urce)", enable_events=True, font='Default 8 underline', key=KEY_OPEN_URL), sg.Sizegrip()])

def update_osc_status_bar(self, message, is_error=False):
text_color = 'red' if is_error else 'green'
Expand All @@ -223,15 +225,31 @@ def update_osc_status_bar(self, message, is_error=False):
except Exception as e:
print("[GUI] Failed to update server status bar.")

def refresh(self):
self.tracker_frame.contents_changed()
self.tracker_frame.set_vscroll_position(1)
self.window.refresh()
self.layout_dirty = True

def run(self):
if self.window is None:
self.window = sg.Window(WINDOW_NAME, self.layout)

self.window = sg.Window(WINDOW_NAME, self.layout, keep_on_top=False, finalize=True, alpha_channel=0.9, icon=b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TpVIrDhYVcchQnezgB+JYqlgEC6Wt0KqDyaVf0KQhSXFxFFwLDn4sVh1cnHV1cBUEwQ8QZwcnRRcp8X9NoUWMB8f9eHfvcfcOEOplpppdEUDVLCMZi4qZ7Kroe0UvBjEEPyYlZurx1GIaruPrHh6+3oV5lvu5P0efkjMZ4BGJI0w3LOIN4tlNS+e8TxxkRUkhPieeMOiCxI9clx1+41xossAzg0Y6OU8cJBYLHSx3MCsaKvEMcUhRNcoXMg4rnLc4q+Uqa92TvzCQ01ZSXKc5ihiWEEcCImRUUUIZFsK0aqSYSNJ+1MU/0vQnyCWTqwRGjgVUoEJq+sH/4He3Zn56ykkKRIHuF9v+GAN8u0CjZtvfx7bdOAG8z8CV1vZX6sDcJ+m1thY6Avq3gYvrtibvAZc7wPCTLhlSU/LSFPJ54P2MvikLDNwC/jWnt9Y+Th+ANHW1fAMcHALjBcped3l3T2dv/55p9fcD3S9y0apk9h0AAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfoCxYXCzDoJVaPAAACuElEQVQ4y2WTTW8bdRDGfzO767f1xnGcJiSNVNoKqMoJgRBCwifuIHFFuSDRTwDi2CNfgC/gGxfElV6ockEISAJBiAJ5KVnqxk7idbx+ie39DwcngaqH0Wj0HJ756ZmRjz7940Ym0nCe1DMVnArZRbn/d+85bcMJ6744GqrUzYFimIAamMF5P8GCAC1GqAMDlFk3qItKQ9WsrmaoGd32LjYeMeg0edj4mOP9Hzj4/ku2v77PJO3MtPZj1GYmYlb31c1ch2ct5uZW6XZikpN9Rr02v377BenRNsuvvkfa2sUP5wlKFbJhDy1FmAm+GpiD6XkfRFGDfD7infc/p9XcobTwGbmoRpq2sKBI8VqNXjemUCijAr6YXa2kCL74RHOrEORYufkW5vk4haJlOAQFyDLUAAeqzhBn5IOQwMsxGfUo5MqMBwm++IjLmPQTovk1PFFGyVPCygpqhphdIBiUS4t0zg5ZWrqL84RcWL2KraTgVPEWb5KmLQIvT+bsWYThIKF1+BO9XpPDg+9YufU2raPfqCy/zOnJHvlyFcmVyMhYq65h/yGAOGA64cmjBxzHW/Tbf5Ec/c5Z6xFh+RphtESvfUAn3mFh+Q5yEbuYoZc3oAbVxZc4T2KiuRcYnP7N3dc/JCzVZjpGLiiyv/kVl6bqDPnk3o51ksc0n25SrFwn85TxdIRXiBi7Mc5Tpm5CYX6F5uGP5Mo1BoMON974AK8YzRCycUpn9yHd5i9M0xO6/2xzGm9ynsSEpRrZ8Ixee4+9b+5TrqzSP96buV8ieA5eefMeMh7Re/IzleqLyGSEOkcn3iKJt+i3/qR2612GpzGlcBFPfdSBL8bG/MLtulMhfO06mQoWBLMIRXCesnZn+sxnLtkUTzww2/AxWw+8fMOJ1NUv4Lzn39lXIVOu5kAFJ7rhnK3/C07bcJ2GHOyzAAAAAElFTkSuQmCC')
self.window.set_resizable(False, True)

# Update Layout if it's changed.
if self.layout_dirty:
self.refresh()
print('Refreshing layout...')

# We make sure the layout update is called only when it's changed.
self.layout_dirty = False

# This is the main GUI loop. The code will halt here until the next event.
event, values = self.window.read()

# Update Values
self.update_values(values)

# React to Event
if event == sg.WIN_CLOSED or event == 'Exit': # if user closes window or clicks cancel
self.shutting_down = True
Expand All @@ -246,7 +264,7 @@ def run(self):
if event == KEY_BTN_REFRESH:
self.refresh_trackers_event()
if event == KEY_OPEN_URL:
webbrowser.open("https://github.com/Z4urce/VRC-Haptic-Pancake")
webbrowser.open("https://hapticpancake.com/")

return True

Expand All @@ -272,7 +290,7 @@ def update_tracker_config(self, values, tracker: str):
# Update Tracker OSC Addresses
key = (KEY_OSC_ADDRESS, tracker)
if key in values:
self.config.get_tracker_config(tracker).address = values[key]
self.config.get_tracker_config(tracker).set_address(values[key])

# Update Tracker vibration
key = (KEY_VIB_STR_OVERRIDE, tracker)
Expand Down
18 changes: 11 additions & 7 deletions BridgeApp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
vr: OpenVRTracker = None
config: AppConfig = None
gui: GUIRenderer = None
external_id: int = 0


def main():
Expand Down Expand Up @@ -78,32 +79,35 @@ def refresh_tracker_list():
gui.add_tracker(device.serial, device.model)

# Debug tracker (Uncomment this for debug purposes)
# gui.add_tracker(99, "T35T-53R1AL", "Test Model 1.0")
# gui.add_tracker("T35T-53R1AL", "Test Model 1.0")
print("[Main] Tracker list refreshed")


def add_external_target(external_type):
print(external_type)
global external_id
external_id += 1
print(external_type + '; ' + str(external_id))

sound_emu = "EMUSND"
text_emu = "EMUTXT"
serial_com = "SERIALCOM"
network = "NETWORK"
serial = "-"+str(external_id)

if external_type.endswith(sound_emu):
gui.add_external_device(sound_emu+"-1", "Sound Target")
gui.add_external_device(sound_emu+serial, "Sound Target")
if external_type.endswith(text_emu):
gui.add_external_device(text_emu+"-1", "Text Target")
gui.add_external_device(text_emu+serial, "Text Target")
if external_type.endswith(serial_com):
gui.add_external_device(serial_com+"-1", "Serial Target")
gui.add_external_device(serial_com+serial, "Serial Target")
if external_type.endswith(network):
gui.add_external_device(network+"-1", "Network Target")
gui.add_external_device(network+serial, "Network Target")


def param_received(address, value):
# value is the floating value (0..1) that determines how intense the feedback should be
for serial, tracker_config in config.tracker_config_dict.items():
if tracker_config.address == address:
if address in tracker_config.address_list:
vr.set_strength(serial, value)


Expand Down

0 comments on commit 38a642d

Please sign in to comment.