Skip to content

Commit

Permalink
Added controller support for assets
Browse files Browse the repository at this point in the history
  • Loading branch information
Gemmstone committed Feb 11, 2024
1 parent 7570aad commit 3e7c544
Show file tree
Hide file tree
Showing 22 changed files with 2,306 additions and 216 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/venv/
/Builds/
/.idea/
/Data/keys.json
/Data/user_token.json
build.sh
build.bat
Binary file added Assets/hands/hands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/hands/thumbs/down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/hands/thumbs/hands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/hands/thumbs/idle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/hands/thumbs/left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/hands/thumbs/right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 105 additions & 2 deletions Core/Settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,27 @@ def __init__(self, parameters, exe_dir):
self.og_height = self.parameters["sizeY"]

self.posX.setValue(self.parameters["posX"])
self.posY.setValue(self.parameters["posY"])
self.posY.setValue(self.parameters["posY"] * -1)
self.posZ.setValue(self.parameters["posZ"])
self.rotation.setValue(self.parameters["rotation"])

self.originX.setValue(self.parameters.get("originX", 0))
self.originY.setValue(self.parameters.get("originY", 0) * -1)
self.deg.setValue(self.parameters.get("deg", 90))
self.deadzone.setValue(self.parameters.get("deadzone", 0.0550))
self.player.setValue(self.parameters.get("player", 0))
self.buttonCombo.setCurrentIndex(self.parameters.get("buttons", 0))

self.posBothX.setValue(self.parameters.get("posBothX", 0))
self.posBothY.setValue(self.parameters.get("posBothY", 0) * -1)
self.rotationBoth.setValue(self.parameters.get("rotationBoth", 0))
self.posLeftX.setValue(self.parameters.get("posLeftX", 0))
self.posLeftY.setValue(self.parameters.get("posLeftY", 0) * -1)
self.rotationLeft.setValue(self.parameters.get("rotationLeft", 0))
self.posRightX.setValue(self.parameters.get("posRightX", 0))
self.posRightY.setValue(self.parameters.get("posRightY", 0) * -1)
self.rotationRight.setValue(self.parameters.get("rotationRight", 0))

self.check_hotkeys()

self.sizeX.valueChanged.connect(self.maintain_aspect_ratio_w)
Expand All @@ -36,37 +54,71 @@ def __init__(self, parameters, exe_dir):
self.posY.valueChanged.connect(self.save_current)
self.posZ.valueChanged.connect(self.save_current)
self.rotation.valueChanged.connect(self.save_current)
self.originY.valueChanged.connect(self.save_current)
self.originY.valueChanged.connect(self.save_current)

self.posBothX.valueChanged.connect(self.save_current)
self.posBothY.valueChanged.connect(self.save_current)
self.rotationBoth.valueChanged.connect(self.save_current)
self.posLeftX.valueChanged.connect(self.save_current)
self.posLeftY.valueChanged.connect(self.save_current)
self.rotationLeft.valueChanged.connect(self.save_current)
self.posRightX.valueChanged.connect(self.save_current)
self.posRightY.valueChanged.connect(self.save_current)
self.rotationRight.valueChanged.connect(self.save_current)

self.deg.valueChanged.connect(self.save_current)
self.deadzone.valueChanged.connect(self.save_current)
self.player.valueChanged.connect(self.save_current)
self.buttonCombo.currentIndexChanged.connect(self.save_current)
self.setShortcut.clicked.connect(self.request_shortcut)

if "controller" not in self.parameters.keys():
self.parameters["controller"] = "ignore"

self.blinkingGroup.setChecked(self.parameters["blinking"] != "ignore")
self.talkingGroup.setChecked(self.parameters["talking"] != "ignore")
self.controllerGroup.setChecked(self.parameters["controller"] != "ignore")
self.cssGroup.setChecked(self.parameters["use_css"])

self.css.setPlainText(self.parameters["css"])

self.blinkingGroup.toggled.connect(self.hide_blinking)
self.talkingGroup.toggled.connect(self.hide_talking)
self.controllerGroup.toggled.connect(self.hide_controller)
self.cssGroup.toggled.connect(self.hide_css)

self.blinkOpen.setChecked(self.parameters["blinking"] == "blinking_open")
self.blinkClosed.setChecked(self.parameters["blinking"] == "blinking_closed")

self.display.setChecked(self.parameters.get("mode", 'display') == "display")
self.move.setChecked(self.parameters.get("mode", 'display') == "move")

self.talkOpen.setChecked(self.parameters["talking"] == "talking_open")
self.talkClosed.setChecked(self.parameters["talking"] == "talking_closed")
self.talkScreaming.setChecked(self.parameters["talking"] == "talking_screaming")

self.controllerButtons.setChecked("controller_buttons" in self.parameters["controller"])
self.controllerWheel.setChecked("controller_wheel" in self.parameters["controller"])

self.blinkOpen.toggled.connect(self.save_current)
self.blinkClosed.toggled.connect(self.save_current)
self.talkOpen.toggled.connect(self.save_current)
self.talkClosed.toggled.connect(self.save_current)
self.talkScreaming.toggled.connect(self.save_current)
self.controllerButtons.toggled.connect(self.save_current)
self.controllerWheel.toggled.connect(self.save_current)

self.display.toggled.connect(self.save_current)
self.move.toggled.connect(self.save_current)

self.css.textChanged.connect(self.css_finished_edit)

self.saveDefault.clicked.connect(self.save_default)

self.hide_blinking()
self.hide_talking()
self.hide_controller()
self.hide_css()

def check_hotkeys(self):
Expand Down Expand Up @@ -107,6 +159,16 @@ def hide_talking(self):
"QGroupBox::title{border-bottom-left-radius: 9px;border-bottom-right-radius: 9px;}")
self.save_current()

def hide_controller(self):
if self.controllerGroup.isChecked():
self.frame_6.show()
self.controllerGroup.setStyleSheet("")
else:
self.frame_6.hide()
self.controllerGroup.setStyleSheet(
"QGroupBox::title{border-bottom-left-radius: 9px;border-bottom-right-radius: 9px;}")
self.save_current()

def hide_css(self):
if self.cssGroup.isChecked():
self.frame_5.show()
Expand All @@ -123,13 +185,40 @@ def save(self):
self.parameters["sizeX"] = self.sizeX.value()
self.parameters["sizeY"] = self.sizeY.value()
self.parameters["posX"] = self.posX.value()
self.parameters["posY"] = self.posY.value()
self.parameters["posY"] = self.posY.value() * -1
self.parameters["posZ"] = self.posZ.value()
self.parameters["originX"] = self.originX.value()
self.parameters["originY"] = self.originY.value() * -1
self.parameters["deg"] = self.deg.value()
self.parameters["deadzone"] = self.deadzone.value()
self.parameters["player"] = self.player.value()
self.parameters["buttons"] = self.buttonCombo.currentIndex()

self.parameters['mode'] = 'display' if self.display.isChecked() else 'move'

if self.display.isChecked():
self.frame_10.show()
self.tabWidget.hide()
else:
self.frame_10.hide()
self.tabWidget.show()

self.parameters['posBothX'] = self.posBothX.value()
self.parameters['posBothY'] = self.posBothY.value() * -1
self.parameters['rotationBoth'] = self.rotationBoth.value()
self.parameters['posLeftX'] = self.posLeftX.value()
self.parameters['posLeftY'] = self.posLeftY.value() * -1
self.parameters['rotationLeft'] = self.rotationLeft.value()
self.parameters['posRightX'] = self.posRightX.value()
self.parameters['posRightY'] = self.posRightY.value() * -1
self.parameters['rotationRight'] = self.rotationRight.value()

self.parameters["use_css"] = True if self.cssGroup.isChecked() else False
self.parameters["css"] = self.css.toPlainText()
self.parameters["rotation"] = self.rotation.value()
self.parameters["blinking"] = self.getBlinking() if self.blinkingGroup.isChecked() else "ignore"
self.parameters["talking"] = self.getTalking() if self.talkingGroup.isChecked() else "ignore"
self.parameters["controller"] = self.getController() if self.controllerGroup.isChecked() else ["ignore"]

def save_current(self):
self.save()
Expand All @@ -144,6 +233,20 @@ def getBlinking(self):
return "blinking_open"
return "blinking_closed"

def getController(self):
checked = []
if self.controllerButtons.isChecked():
self.frame_8.show()
checked.append("controller_buttons")
else:
self.frame_8.hide()
if self.controllerWheel.isChecked():
self.frame_7.show()
checked.append("controller_wheel")
else:
self.frame_7.hide()
return checked if checked else ["ignore"]

def getTalking(self):
if self.talkOpen.isChecked():
return "talking_open"
Expand Down
24 changes: 15 additions & 9 deletions Core/ShortcutsManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from twitchAPI.twitch import Twitch
from twitchAPI.helper import first
from PyQt6.QtGui import QIcon
from aiohttp.client_exceptions import ClientConnectionError
import os.path
import asyncio
import json
Expand Down Expand Up @@ -90,17 +91,22 @@ async def on_gifted_sub(self, data: ChannelSubscriptionGiftEvent):
)

async def _run(self):
await self.authorize()
user = await first(self.twitch.get_users())
await self.listen(user)
auth = await self.authorize()
if auth:
user = await first(self.twitch.get_users())
await self.listen(user)

async def authorize(self):
self.twitch = await Twitch(self.APP_ID, self.APP_SECRET)
helper = UserAuthenticationStorageHelper(
self.twitch, self.TARGET_SCOPES,
storage_path=os.path.normpath(f"Data{os.path.sep}user_token.json")
)
await helper.bind()
try:
self.twitch = await Twitch(self.APP_ID, self.APP_SECRET)
helper = UserAuthenticationStorageHelper(
self.twitch, self.TARGET_SCOPES,
storage_path=os.path.normpath(f"Data{os.path.sep}user_token.json")
)
await helper.bind()
return True
except ClientConnectionError:
return False

async def listen(self, user):
self.eventsub = EventSubWebsocket(self.twitch)
Expand Down
42 changes: 40 additions & 2 deletions Core/Viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,42 @@ def handle_runtime_html(self, runtime_page, soup, image_div, image_list):

if image_list is not None:
for layer in sorted(image_list, key=lambda x: x['posZ']):
controller_wheel_div = soup.new_tag('div', style=f"""
position: absolute !important;
transform-origin: calc(50% + {layer.get('originX', 0)}px) calc(50% + {layer.get('originY', 0)}px);
transform: rotate(0deg);
""")
controller_wheel_div['class'] = ["controller_wheel" if "controller_wheel" in layer.get('controller', ["ignore"]) else "ignore"]
controller_wheel_div['player'] = layer.get("player", 1) - 1
controller_wheel_div['deg'] = layer.get('deg', -90)
controller_wheel_div['deadzone'] = layer.get("deadzone", 0.0550)

controller_buttons_div = soup.new_tag('div', style=f"""
position: absolute !important;
left: calc(50% + {layer.get('posIdleX', 0)}px);
top: calc(50% + {layer.get('posIdleY', 0)}px);
transform: rotate({layer.get('rotationIdle', 0)}deg);
display: {("block" if layer.get("buttons", 0) == 0 else "none") if layer.get("mode", 'display') else "block"};
""")

controller_buttons_div['class'] = ["controller_buttons" if "controller_buttons" in layer.get('controller', ["ignore"]) else "ignore"]
controller_buttons_div['player'] = layer.get("player", 1) - 1

controller_buttons_div['mode'] = layer.get("mode", 'display')
controller_buttons_div['buttons'] = layer.get("buttons", 0)

controller_buttons_div['posBothX'] = layer.get("posBothX", 0)
controller_buttons_div['posBothY'] = layer.get("posBothY", 0)
controller_buttons_div['rotationBoth'] = layer.get("rotationBoth", 0)

controller_buttons_div['posLeftX'] = layer.get("posLeftX", 0)
controller_buttons_div['posLeftY'] = layer.get("posLeftY", 0)
controller_buttons_div['rotationLeft'] = layer.get("rotationLeft", 0)

controller_buttons_div['posRightX'] = layer.get("posRightX", 0)
controller_buttons_div['posRightY'] = layer.get("posRightY", 0)
controller_buttons_div['rotationRight'] = layer.get("rotationRight", 0)

img_tag = soup.new_tag('img', src=f"../{layer['route']}", style=f"""
position: absolute !important;
left: calc(50% + {layer['posX']}px);
Expand All @@ -76,10 +112,12 @@ def handle_runtime_html(self, runtime_page, soup, image_div, image_list):
""")
img_tag['class'] = [layer['blinking'], layer['talking']]

image_div.append(img_tag)
controller_buttons_div.append(img_tag)
controller_wheel_div.append(controller_buttons_div)

image_div.append(controller_wheel_div)

beautiful_html = soup.prettify()
with open('Viewer/viewer.html', 'w') as html_file:
html_file.write(beautiful_html)

self.reload()
5 changes: 3 additions & 2 deletions Core/audioManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,6 @@ def update_volume(self, volume):
self.activeAudio.emit(self.active_audio_signal)

def check_inactivity(self):
print("No audio data received for a while. Restarting the stream.")
self.update_audio_stream(force=True)
if not self.mute.isChecked():
print("No audio data received for a while. Restarting the stream.")
self.update_audio_stream(force=True)
2 changes: 1 addition & 1 deletion Data/current.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"Assets/right eye/right eye_058.png",
"Assets/left eye/left eye_001.png",
"Assets/left eye/left eye_058.png",
"Assets/hands/hands_118.png",
"Assets/hands/hands_017.png",
"Assets/hairbows/hairbows_360.png",
"Assets/ahoge/ahoge_027.png",
"Assets/bangs/bangs_171.png",
Expand Down
6 changes: 6 additions & 0 deletions Data/keys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"twitch": {
"client": "",
"secret": ""
}
}
Loading

0 comments on commit 3e7c544

Please sign in to comment.