diff --git a/automation.py b/automation.py index 953e133..1fd673a 100644 --- a/automation.py +++ b/automation.py @@ -1,14 +1,22 @@ import uinput import time +import asyncio import evdev +import queue from evdev import InputDevice, categorize, ecodes from evdev import UInput, ecodes as e import threading from threading import Thread import sys from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt5.QtGui import QPalette, QColor +import signal -device_path = '/dev/input/event5' # You can find this with `evtest` +event_queue = queue.Queue() + +global app, overlay + +device_paths = [('/dev/input/event1', {"KEY_F20", "KEY_F24"}), ('/dev/input/event22', {}), ('/dev/input/event5', {})] key_events = [ uinput.KEY_A, uinput.KEY_B, uinput.KEY_C, uinput.KEY_D, uinput.KEY_E, @@ -16,7 +24,8 @@ key_events = [ uinput.KEY_K, uinput.KEY_L, uinput.KEY_M, uinput.KEY_N, uinput.KEY_O, uinput.KEY_P, uinput.KEY_Q, uinput.KEY_R, uinput.KEY_S, uinput.KEY_T, uinput.KEY_U, uinput.KEY_V, uinput.KEY_W, uinput.KEY_X, uinput.KEY_Y, - uinput.KEY_Z, + uinput.KEY_Z, uinput.KEY_ESC, uinput.KEY_F20, uinput.KEY_F21, uinput.KEY_F22, + uinput.KEY_F23, uinput.KEY_F24, uinput.KEY_ENTER, uinput.KEY_COMMA, @@ -42,8 +51,6 @@ def left_click(): mouse.syn() def place_tower(): - keyboard.emit_click(uinput.KEY_Z) - time.sleep(0.05) left_click() time.sleep(0.05) mouse.write(e.EV_REL, e.REL_Y, -10) @@ -52,60 +59,128 @@ def place_tower(): left_click() time.sleep(0.1) -def upgrade_tower(): - for i in range(2): +def upgrade_top(amount = 1): + for i in range(amount): + keyboard.emit_click(uinput.KEY_COMMA) + time.sleep(0.05) + +def upgrade_middle(amount = 1): + for i in range(amount): keyboard.emit_click(uinput.KEY_DOT) time.sleep(0.05) - for i in range(2): + +def upgrade_bottom(amount = 1): + for i in range(amount): keyboard.emit_click(uinput.KEY_SLASH) time.sleep(0.05) -def listen_for_keypress(): - dev = InputDevice(device_path) - print(f"Listening on {dev.name} ({device_path})") +def upgrade_tower(): + # for i in range(0): + # keyboard.emit_click(uinput.KEY_DOT) + # time.sleep(0.05) + for i in range(3): + keyboard.emit_click(uinput.KEY_SLASH) + time.sleep(0.05) + keyboard.emit_click(uinput.KEY_ESC) + time.sleep(0.05) + keyboard.emit_click(uinput.KEY_C) + time.sleep(0.05) - for event in dev.read_loop(): +async def listen_for_keypress(path, keys): + dev = InputDevice(path) + print(f"Listening on {dev.name} ({path})") + + async for event in dev.async_read_loop(): if event.type == ecodes.EV_KEY: key_event = categorize(event) - if key_event.keycode == 'KEY_F9' and key_event.keystate == 0: - place_tower() - upgrade_tower() + if key_event.keycode in keys and key_event.keystate == 0: + event_queue.put((dev.name, key_event.keycode)) class Overlay(QtWidgets.QWidget): def __init__(self): super().__init__() + # self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True) + self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents, True) + # self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True) self.setWindowFlags( QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint | - QtCore.Qt.Tool # Makes window not appear in taskbar + QtCore.Qt.Tool ) - self.setAttribute(QtCore.Qt.WA_TranslucentBackground) - self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents) # Click-through + self.setStyleSheet("background-color: #788178;") self.label = QtWidgets.QLabel("Mode: 1", self) - self.label.setStyleSheet("color: white; font-size: 24px; background: rgba(0,0,0,0.5); padding: 10px;") + self.label.setStyleSheet("color: white; font-size: 12px; padding: 4px;") self.label.move(50, 50) - self.resize(200, 100) + layout = QtWidgets.QVBoxLayout(self) + layout.setContentsMargins(2, 2, 2, 2) # Very small margins + layout.addWidget(self.label) + self.setLayout(layout) + self.adjustSize() - def update_mode(self, mode_num): + # self.resize(200, 100) + self.move(0, 0) + + # def paintEvent(self, event): + # painter = QtGui.QPainter(self) + # painter.setOpacity(0.1) + # painter.setBrush(QtCore.Qt.white) + # painter.setPen(QtGui.QPen(QtCore.Qt.white)) + # painter.drawRect(self.rect()) + # super().paintEvent(event) + + def update_mode(self, mode_num: int): self.label.setText(f"Mode: {mode_num}") +async def main(): + tasks = [asyncio.create_task(listen_for_keypress(tpl[0], tpl[1])) for tpl in device_paths] + + await asyncio.gather(*tasks) + +def start_async(): + asyncio.run(main()) + +def qt5(): + global app, overlay + app = QtWidgets.QApplication([]) + overlay = Overlay() + overlay.show() + + def update_loop(): + mode = 1 + while True: + time.sleep(2) + mode = (mode % 3) + 1 + # QtCore.QMetaObject.invokeMethod(overlay, "update_mode", QtCore.Qt.QueuedConnection, QtCore.Q_ARG(int, mode)) + + Thread(target=update_loop, daemon=True).start() + app.exec() + + +def command_processor(): + while True: + try: + device_name, key_event = event_queue.get(timeout=1) + print(f"Processing event from {device_name}: {key_event}") + + if key_event == "KEY_F24": + global app, overlay + app.quit() + sys.exit(0) + except queue.Empty: + continue + except Exception as e: + print(f"Error processing queue item: {e}") + if __name__ == "__main__": + global app, overlay try: - app = QtWidgets.QApplication(sys.argv) - overlay = Overlay() - overlay.show() - - def update_loop(): - mode = 1 - while True: - time.sleep(2) - mode = (mode % 3) + 1 - QtCore.QMetaObject.invokeMethod(overlay, "update_mode", QtCore.Qt.QueuedConnection, QtCore.Q_ARG(int, mode)) - - Thread(target=update_loop, daemon=True).start() - # listen_for_keypress() + Thread(target=command_processor, daemon=True).start() + Thread(target=start_async, daemon=True).start() + qt5() except KeyboardInterrupt: print("Goodbye!") - sys.exit(app.exec_()) + app.quit() + sys.exit(0) + # sys.exit(app.exec_()) diff --git a/default.nix b/default.nix index 7b29cab..6da9786 100644 --- a/default.nix +++ b/default.nix @@ -1,13 +1,31 @@ let pkgs = import {}; in pkgs.mkShell { - packages = [ - pkgs.git - (pkgs.python3.withPackages (python-pkgs: [ - python-pkgs.requests - python-pkgs.python-uinput - python-pkgs.evdev - python-pkgs.pyqt5 - ])) + nativeBuildInputs = with pkgs; [ qt5.qttools.dev python3Packages.autopep8 python3Packages.flake8 ]; + propagatedBuildInputs = with pkgs; [ + (python3.withPackages (ps: with ps; [ + pyqt5 + evdev + python-uinput + ])) ]; + + packages = with pkgs; [ + git + (python3.withPackages (python-pkgs: with python-pkgs; [ + requests + python-uinput + evdev + pyqt5 + ])) + python3Packages.pyqt5 + python3Packages.pip + libsForQt5.qt5.qtbase + libsForQt5.qt5.qtx11extras + qt5.qtbase + qt5.wrapQtAppsHook + qt5.qtx11extras + ]; + + QT_QPA_PLATFORM_PLUGIN_PATH="${pkgs.qt5.qtbase.bin}/lib/qt-${pkgs.qt5.qtbase.version}/plugins"; } diff --git a/qt_test.py b/qt_test.py new file mode 100644 index 0000000..8cb39b7 --- /dev/null +++ b/qt_test.py @@ -0,0 +1,36 @@ +from PyQt5 import QtWidgets, QtCore, QtGui +import sys + + +class TransparentScene(QtWidgets.QGraphicsScene): + def __init__(self): + super().__init__() + text = self.addText("Mode: 1") + text.setDefaultTextColor(QtGui.QColor("white")) + # Add a semi-transparent background rect + rect = self.addRect(text.boundingRect().adjusted(-10, -10, 10, 10), + QtGui.QPen(QtCore.Qt.NoPen), + QtGui.QBrush(QtGui.QColor(0, 0, 0, 128))) + rect.setZValue(-1) # Put behind text + + +class TransparentView(QtWidgets.QGraphicsView): + def __init__(self): + super().__init__() + scene = TransparentScene() + self.setScene(scene) + self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint) + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) + self.setStyleSheet("background: transparent;") + self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.setRenderHint(QtGui.QPainter.Antialiasing) + self.setFrameShape(QtWidgets.QFrame.NoFrame) + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + view = TransparentView() + view.resize(200, 100) + view.show() + sys.exit(app.exec_())