Skip to content

Commit

Permalink
Wired settings up to inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
shadorki committed Sep 24, 2023
1 parent ac2c757 commit 0fc5f0e
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 119 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
pip install -r requirements.txt
- name: Build with pyinstaller
run: pyinstaller --hidden-import=clr --add-binary "./owo/OWO.dll;owo" --onefile --distpath ./build --name=vrc-owo-suit main.py
run: pyinstaller --hidden-import=clr --add-binary "./owo/OWO.dll;owo" --add-data "./img/logo.png;img" --onefile --distpath ./build --name=vrc-owo-suit main.py

- name: Deploy EXE
uses: actions/upload-artifact@v3
Expand Down
81 changes: 58 additions & 23 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
import json
import params
import os
import json


class Config:
def __init__(self):
self.server_port = 9001
self.owo_ip = ""
self.intensity = 10
self.frequency = 100

self.APP_NAME = 'VRChatOWOSuit'
self.default_config = {
"server_port": 9001,
"owo_ip": "",
"should_detect_ip": True,
"should_connect_on_startup": False,
"frequency": 100,
"intensities": {
params.owo_suit_Pectoral_L: 60,
params.owo_suit_Pectoral_R: 60,
params.owo_suit_Abdominal_L: 60,
params.owo_suit_Abdominal_R: 60,
params.owo_suit_Arm_L: 60,
params.owo_suit_Arm_R: 60,
params.owo_suit_Dorsal_L: 60,
params.owo_suit_Dorsal_R: 60,
params.owo_suit_Lumbar_L: 60,
params.owo_suit_Lumbar_R: 60,
}
}
self.current_config = None

def get_by_key(self, key: str):
return self.current_config.get(key)

def update(self, key: str, nextValue):
if (key in self.current_config):
self.current_config[key] = nextValue

def read_config_from_disk(self):
appdata_path = os.environ.get('LOCALAPPDATA')
app_directory = os.path.join(appdata_path, self.APP_NAME)
print(app_directory)
os.makedirs(app_directory, exist_ok=True)
config_path = os.path.join(app_directory, 'config.json')
if os.path.exists(config_path):
with open(config_path, 'r') as file:
data = json.load(file)
return data
else:
with open(config_path, 'w') as file:
json.dump(self.default_config, file, indent=4)
return self.default_config

def write_config_to_disk(self):
if self.current_config == None:
return
appdata_path = os.environ.get('LOCALAPPDATA')
app_directory = os.path.join(appdata_path, self.APP_NAME)
os.makedirs(app_directory, exist_ok=True)
config_path = os.path.join(app_directory, 'config.json')
with open(config_path, 'w') as file:
json.dump(self.current_config, file, indent=4)

def init(self):
try:
f = open('./vrc-owo-suit.config.json')
data = json.load(f)
f.close()
if ("server_port" in data and type(data['server_port']) is int):
print(f"Using server_port {data['server_port']}.")
self.server_port = data['server_port']
if ("owo_ip" in data and type(data['owo_ip']) is str):
print(f"Using owo_ip {data['owo_ip']}.")
self.owo_ip = data['owo_ip']
if ("intensity" in data and type(data['intensity']) is int):
print(f"Using intensity {data['intensity']}.")
self.intensity = data['intensity']
if ("frequency" in data and type(data['frequency']) is int):
print(f"Using frequency {data['frequency']}.")
self.frequency = data['frequency']
except:
print("Config file not found, using default settings")
self.current_config = self.read_config_from_disk()
198 changes: 131 additions & 67 deletions gui.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import params
import config
import webbrowser
from event import Event
Expand Down Expand Up @@ -62,15 +63,37 @@ def __init__(self, config: config.Config, window_width: int, window_height: int,
Element.CONNECT_ON_STARTUP_CHECKBOX: None,
Element.CONTRIBUTE_BUTTON: None,
}
self.element_to_config_key = {
Element.SERVER_PORT_NUMBER_INPUT: "server_port",
Element.IP_ADDRESS_INPUT: "owo_ip",
Element.DETECT_IP_ADDRESS_CHECKBOX: "should_detect_ip",
Element.CONNECT_ON_STARTUP_CHECKBOX: "should_connect_on_startup",
Element.FREQUENCY_SETTING_SLIDER: "frequency",
"intensities": {
Element.LEFT_PECTORAL_SETTING_SLIDER: params.owo_suit_Pectoral_L,
Element.RIGHT_PECTORAL_SETTING_SLIDER: params.owo_suit_Pectoral_R,
Element.LEFT_ABDOMINAL_SETTING_SLIDER: params.owo_suit_Abdominal_L,
Element.RIGHT_ABDOMINAL_SETTING_SLIDER: params.owo_suit_Abdominal_R,
Element.LEFT_ARM_SETTING_SLIDER: params.owo_suit_Arm_L,
Element.RIGHT_ARM_SETTING_SLIDER: params.owo_suit_Arm_R,
Element.LEFT_DORSAL_SETTING_SLIDER: params.owo_suit_Dorsal_L,
Element.RIGHT_DORSAL_SETTING_SLIDER: params.owo_suit_Dorsal_R,
Element.LEFT_LUMBAR_SETTING_SLIDER: params.owo_suit_Lumbar_L,
Element.RIGHT_LUMBAR_SETTING_SLIDER: params.owo_suit_Lumbar_R,
}

}
self.ids_to_elements = None

def handle_connect_callback(self, sender, app_data):
self.on_connect_clicked.dispatch(sender, app_data)

def handle_disconnect_callback(self, sender, app_data):
self.on_disconnect_clicked.dispatch(sender, app_data)

def handle_save_settings_callback(self, sender, app_data):
self.on_save_settings_clicked.dispatch(sender, app_data)
def handle_save_settings_callback(self):
self.config.write_config_to_disk()
self.print_terminal("Settings Saved!")

def handle_clear_console_callback(self, sender, app_data):
self.on_clear_console_clicked.dispatch(sender, app_data)
Expand All @@ -81,6 +104,19 @@ def handle_intensity_change(self, sender, app_data):
# figure out how to get these values from sender and app data
self.on_intensity_change.dispatch(parameter, value)

def handle_input_change(self, sender, app_data):
element = self.ids_to_elements.get(sender)
config_key = self.element_to_config_key.get(element)
# this implies its an intensity
if config_key is None:
intensities_map = self.element_to_config_key.get("intensities")
config_key = intensities_map.get(element)
intensities = self.config.get_by_key("intensities")
intensities[config_key] = app_data
self.config.update("intensities", intensities)
return
self.config.update(config_key, app_data)

def handle_contribute_callback(self, sender, app_data):
webbrowser.open("https://github.com/uzair-ashraf/vrc-owo-suit")

Expand Down Expand Up @@ -132,9 +168,89 @@ def add_listeners(self) -> None:
self.on_clear_console_clicked.add_listener(self.on_clear_console)

def create_owo_suit_ip_address_input(self):
owo_ip = self.config.get_by_key("owo_ip") or ""
dpg.add_text("OWO Suit IP Address")
self.elements[Element.IP_ADDRESS_INPUT] = dpg.add_input_text(
width=-1)
self.elements[Element.IP_ADDRESS_INPUT] = dpg.add_input_text(default_value=owo_ip,
width=-1, callback=self.handle_input_change)

def create_detect_address_checkbox(self):
should_detect_ip = self.config.get_by_key("should_detect_ip")
self.elements[Element.DETECT_IP_ADDRESS_CHECKBOX] = dpg.add_checkbox(
label="Automatically Detect IP Address", default_value=should_detect_ip, callback=self.handle_input_change)

def create_server_port_input(self):
server_port = self.config.get_by_key("server_port") or 9001
dpg.add_text("Server Port Number")
self.elements[Element.SERVER_PORT_NUMBER_INPUT] = dpg.add_input_int(default_value=server_port,
width=-1, callback=self.handle_input_change)

def create_frequency_slider(self):
frequency = self.config.get_by_key("frequency")
dpg.add_text("Frequency Settings")
self.elements[Element.FREQUENCY_SETTING_SLIDER] = dpg.add_slider_int(
min_value=0,
max_value=100,
width=-1,
default_value=frequency,
callback=self.handle_input_change
)

def create_intensity_settings(self):
dpg.add_text("Intensity Settings")
element_labels = {
Element.LEFT_PECTORAL_SETTING_SLIDER: "Left Pectoral",
Element.RIGHT_PECTORAL_SETTING_SLIDER: "Right Pectoral",
Element.LEFT_ABDOMINAL_SETTING_SLIDER: "Left Abdominal",
Element.RIGHT_ABDOMINAL_SETTING_SLIDER: "Right Abdominal",
Element.LEFT_ARM_SETTING_SLIDER: "Left Arm",
Element.RIGHT_ARM_SETTING_SLIDER: "Right Arm",
Element.LEFT_DORSAL_SETTING_SLIDER: "Left Dorsal",
Element.RIGHT_DORSAL_SETTING_SLIDER: "Right Dorsal",
Element.LEFT_LUMBAR_SETTING_SLIDER: "Left Lumbar",
Element.RIGHT_LUMBAR_SETTING_SLIDER: "Right Lumbar",
}
for element, label in element_labels.items():
self.create_intensity_slider(element, label)

def create_intensity_slider(self, element: Element, label: str):
intensities_map = self.element_to_config_key.get("intensities")
config_key = intensities_map.get(element)
intensities = self.config.get_by_key("intensities")
default_value = intensities.get(config_key) or 0
self.elements[element] = dpg.add_slider_int(default_value=default_value, min_value=0, width=-120,
max_value=100, label=label, callback=self.handle_input_change)

def create_logs_output(self):
dpg.add_text("Logs")
self.elements[Element.TERMINAL_WINDOW_INPUT] = dpg.add_input_text(
multiline=True, readonly=True, height=90, width=-1)

def create_button_group(self):
with dpg.group(horizontal=True):
self.elements[Element.CONNECT_BUTTON] = dpg.add_button(label="Connect",
callback=self.handle_connect_callback)
self.elements[Element.SAVE_SETTINGS_BUTTON] = dpg.add_button(label="Save Settings",
callback=self.handle_save_settings_callback)
self.elements[Element.CLEAR_CONSOLE_BUTTON] = dpg.add_button(label="Clear Console",
callback=self.handle_clear_console_callback)

def create_connect_startup_checkbox(self):
should_connect_on_startup = self.config.get_by_key(
"should_connect_on_startup"
)
self.elements[Element.CONNECT_ON_STARTUP_CHECKBOX] = dpg.add_checkbox(
default_value=should_connect_on_startup,
label="Automatically Connect on Startup",
callback=self.handle_input_change
)

def create_footer(self):
with dpg.group(width=-1):
self.elements[Element.CONTRIBUTE_BUTTON] = dpg.add_button(
label="\t\t\t\t Created by Shadoki.\nThis application is not affiliated with VRChat or OWO.\n\t\t\t\t Want to contribute?",
width=-1,
callback=self.handle_contribute_callback
)

def init(self):
dpg.create_context()
Expand All @@ -143,81 +259,29 @@ def init(self):
handle_centered_image = self.create_centered_image(
"logo", self.logo_path)
dpg.add_spacer(height=20)

dpg.add_text("OWO Suit IP Address")
self.elements[Element.IP_ADDRESS_INPUT] = dpg.add_input_text(
width=-1)
self.elements[Element.DETECT_IP_ADDRESS_CHECKBOX] = dpg.add_checkbox(
label="Automatically Detect IP Address")
self.create_owo_suit_ip_address_input()
self.create_detect_address_checkbox()
dpg.add_spacer(height=20)

dpg.add_text("Server Port Number")
self.elements[Element.SERVER_PORT_NUMBER_INPUT] = dpg.add_input_int(
width=-1)
self.create_server_port_input()
dpg.add_spacer(height=20)

# Sliders with labels coming before
dpg.add_text("Frequency Settings")
self.elements[Element.FREQUENCY_SETTING_SLIDER] = dpg.add_slider_int(
min_value=0, max_value=100, width=-1)
self.create_frequency_slider()
dpg.add_spacer(height=20)

dpg.add_text("Intensity Settings")
with dpg.group():
self.elements[Element.LEFT_PECTORAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Left Pectoral")
self.elements[Element.RIGHT_PECTORAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Right Pectoral")
with dpg.group():
self.elements[Element.LEFT_ABDOMINAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Left Abdominal")
self.elements[Element.RIGHT_ABDOMINAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Right Abdominal")
with dpg.group():
self.elements[Element.LEFT_ARM_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Left Arm")
self.elements[Element.RIGHT_ARM_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Right Arm")
with dpg.group():
self.elements[Element.LEFT_DORSAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Left Dorsal")
self.elements[Element.RIGHT_DORSAL_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Right Dorsal")
with dpg.group():
self.elements[Element.LEFT_LUMBAR_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Left Lumbar")
self.elements[Element.RIGHT_LUMBAR_SETTING_SLIDER] = dpg.add_slider_int(min_value=0, width=-120,
max_value=100, label="Right Lumbar")
self.create_intensity_settings()
dpg.add_spacer(height=20)

# Terminal-like output
dpg.add_text("Logs")
self.elements[Element.TERMINAL_WINDOW_INPUT] = dpg.add_input_text(multiline=True, readonly=True,
default_value="...", height=90, width=-1)

self.create_logs_output()
dpg.add_spacer(height=20)

with dpg.group(horizontal=True):
self.elements[Element.CONNECT_BUTTON] = dpg.add_button(label="Connect",
callback=self.handle_connect_callback)
self.elements[Element.SAVE_SETTINGS_BUTTON] = dpg.add_button(label="Save Settings",
callback=self.handle_save_settings_callback)
self.elements[Element.CLEAR_CONSOLE_BUTTON] = dpg.add_button(label="Clear Console",
callback=self.handle_clear_console_callback)
self.create_button_group()
dpg.add_spacer(height=20)
self.elements[Element.CONNECT_ON_STARTUP_CHECKBOX] = dpg.add_checkbox(
label="Automatically Connect on Startup")

self.create_connect_startup_checkbox()
dpg.add_spacer(height=20)
self.create_footer()

with dpg.group(width=-1):
self.elements[Element.CONTRIBUTE_BUTTON] = dpg.add_button(label="\t\t\t\t Created by Shadoki.\nThis application is not affiliated with VRChat or OWO.\n\t\t\t\t Want to contribute?",
width=-1, callback=self.handle_contribute_callback)
self.add_listeners()
dpg.create_viewport(title='VRChat OWO Suit',
width=self.window_width, height=self.window_height)
dpg.set_viewport_resize_callback(handle_centered_image)

self.ids_to_elements = {
value: key for key, value in self.elements.items()}
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("MAIN_WINDOW", True)
Expand Down
11 changes: 7 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@
try:
cfg = Config()
cfg.init()
gui = Gui(config=cfg, window_width = 550, window_height = 1000, logo_path="./img/logo.png")
gui = Gui(config=cfg, window_width=550,
window_height=1000, logo_path="./img/logo.png")
gui.init()
owo_suit = OWOSuit(cfg.owo_ip, cfg.frequency, cfg.intensity, gui=gui)
owo_suit = OWOSuit(config=cfg, gui=gui)
owo_suit.init()
dispatcher = Dispatcher()
owo_suit.map_parameters(dispatcher)

server_port = cfg.get_by_key("server_port")

osc_server = ThreadingOSCUDPServer(
("127.0.0.1", cfg.server_port), dispatcher, asyncio.new_event_loop())
("127.0.0.1", server_port), dispatcher, asyncio.new_event_loop())
threading.Thread(target=lambda: osc_server.serve_forever(2),
daemon=True).start()
threading.Thread(target=owo_suit.watch,
Expand All @@ -30,4 +34,3 @@
finally:
if gui is not None:
gui.cleanup()

Loading

0 comments on commit 0fc5f0e

Please sign in to comment.