You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.7 KiB
Python
157 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import base64
|
|
import io
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
import pygame
|
|
from PIL import Image
|
|
|
|
import sdl2
|
|
import sdl2.ext
|
|
|
|
|
|
# ---------- Configuration ----------
|
|
DEFAULT_SCRIPTS_PATH = "/home/kuba/kazzite"
|
|
TITLE = "Select script"
|
|
BIG_FONT_SIZE = 100
|
|
SMALL_FONT_SIZE = 40
|
|
AXIS_DEADZONE = 0.6
|
|
HAT_REPEAT_DELAY = 0.18
|
|
FPS = 60
|
|
|
|
# ---------- Helpers ----------
|
|
|
|
def load_scripts(directory):
|
|
return [
|
|
{
|
|
"name": p.stem,
|
|
"path": str(p.resolve())
|
|
}
|
|
for p in Path(directory).iterdir()
|
|
]
|
|
|
|
# ---------- UI with SDL2 input ----------
|
|
|
|
def run_ui(scripts):
|
|
pygame.init()
|
|
|
|
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
|
|
screen_w, screen_h = screen.get_size()
|
|
pygame.display.set_caption(TITLE)
|
|
|
|
scale = min(screen_w / 3840.0, screen_h / 2160.0)
|
|
big_font = pygame.font.SysFont(None, int(BIG_FONT_SIZE * scale))
|
|
small_font = pygame.font.SysFont(None, int(SMALL_FONT_SIZE * scale))
|
|
|
|
clock = pygame.time.Clock()
|
|
selected = 0
|
|
last_nav = 0
|
|
|
|
# ---------- SDL2 joystick init ----------
|
|
if sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK) != 0:
|
|
print("SDL_Init Error:", sdl2.SDL_GetError().decode())
|
|
sys.exit(1)
|
|
|
|
joystick_count = sdl2.SDL_NumJoysticks()
|
|
sdl_joysticks = []
|
|
for i in range(joystick_count):
|
|
js = sdl2.SDL_JoystickOpen(i)
|
|
if js:
|
|
sdl_joysticks.append(js)
|
|
|
|
|
|
running = True
|
|
event = sdl2.SDL_Event()
|
|
while running:
|
|
now = time.time()
|
|
pygame.event.pump() # Update pygame keyboard events
|
|
|
|
# Handle pygame keyboard events
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
running = False
|
|
elif event.type == pygame.KEYDOWN:
|
|
if event.key == pygame.K_UP:
|
|
selected = max(0, selected - 1)
|
|
elif event.key == pygame.K_DOWN:
|
|
selected = min(len(scripts) - 1, selected + 1)
|
|
elif event.key in (pygame.K_RETURN, pygame.K_KP_ENTER):
|
|
path = scripts[selected]['path']
|
|
print(path)
|
|
running = False
|
|
elif event.key == pygame.K_ESCAPE:
|
|
print("ESCAPE")
|
|
running = False
|
|
|
|
sdl2.SDL_JoystickUpdate()
|
|
for i, js in enumerate(sdl_joysticks):
|
|
# Buttons
|
|
for b in range(sdl2.SDL_JoystickNumButtons(js)):
|
|
if sdl2.SDL_JoystickGetButton(js, b):
|
|
if b == 0: # confirm button
|
|
path = scripts[selected]['path']
|
|
print(path)
|
|
running = False
|
|
elif b == 1: # cancel button
|
|
print("CANCEL")
|
|
running = False
|
|
|
|
# Hats (D-pad)
|
|
for h in range(sdl2.SDL_JoystickNumHats(js)):
|
|
hat = sdl2.SDL_JoystickGetHat(js, h)
|
|
if hat & sdl2.SDL_HAT_UP and now - last_nav > HAT_REPEAT_DELAY:
|
|
selected = max(0, selected - 1)
|
|
last_nav = now
|
|
elif hat & sdl2.SDL_HAT_DOWN and now - last_nav > HAT_REPEAT_DELAY:
|
|
selected = min(len(scripts) - 1, selected + 1)
|
|
last_nav = now
|
|
|
|
# ---------- Render pygame UI ----------
|
|
screen.fill((10, 10, 10))
|
|
|
|
title_surf = small_font.render(TITLE, True, (230, 230, 230))
|
|
screen.blit(title_surf, ((screen_w - title_surf.get_width()) // 2, int(screen_h * 0.08)))
|
|
|
|
total = len(scripts)
|
|
item_height = int(300 * scale)
|
|
start_y = (screen_h - total * item_height) // 2
|
|
|
|
for i, script in enumerate(scripts):
|
|
y = start_y + i * item_height
|
|
color = (255, 255, 255) if i == selected else (180, 180, 180)
|
|
|
|
if i == selected:
|
|
pygame.draw.rect(screen, (50, 50, 50), (screen_w * 0.1, y - 20, screen_w * 0.8, item_height - 40), border_radius=20)
|
|
|
|
name_surf = big_font.render(script['name'], True, color)
|
|
screen.blit(name_surf, (int(screen_w * 0.4), y + item_height // 3))
|
|
|
|
pygame.display.flip()
|
|
clock.tick(FPS)
|
|
|
|
# Cleanup SDL2 joysticks
|
|
for js in sdl_joysticks:
|
|
sdl2.SDL_JoystickClose(js)
|
|
sdl2.SDL_QuitSubSystem(sdl2.SDL_INIT_JOYSTICK)
|
|
pygame.quit()
|
|
|
|
# ---------- Main ----------
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--scripts", default=str(DEFAULT_SCRIPTS_PATH))
|
|
args = parser.parse_args()
|
|
|
|
scripts = load_scripts(Path(args.scripts))
|
|
run_ui(scripts)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|