File size: 3,283 Bytes
9f85448 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | """Startup mode menu."""
from __future__ import annotations
import cv2
import numpy as np
import ui
WINDOW = "Hand Tracking Drawing"
ITEMS = (
("2d", "2D Drawing"),
("3d", "3D Drawing"),
("poses", "Poses"),
("translater", "Translater"),
)
W, H = 720, 480
TOP = 150
ROW_H = 56
PAD = 60
class Menu:
"""Mode selection screen."""
def __init__(self) -> None:
self.index = 0
self.click = -1
self.note = ""
def on_mouse(self, event: int, x: int, y: int, flags: int, param) -> None:
"""Track hover and clicks."""
row = (y - TOP) // ROW_H
if not 0 <= row < len(ITEMS) or not PAD <= x <= W - PAD:
return
self.index = int(row)
if event == cv2.EVENT_LBUTTONDOWN:
self.click = int(row)
def frame(self) -> np.ndarray:
"""Render menu image."""
img = np.zeros((H, W, 3), dtype=np.uint8)
ui.put_text(img, "HAND TRACKING DRAWING", (PAD, 54), 26, (255, 255, 255))
ui.put_text(img, "Select a mode", (PAD, 96), 17, (150, 150, 150))
for i, (_, label) in enumerate(ITEMS):
y = TOP + i * ROW_H
box = (PAD, y, W - PAD, y + ROW_H - 12)
if i == self.index:
cv2.rectangle(img, box[:2], box[2:], (45, 45, 45), -1)
cv2.rectangle(img, box[:2], box[2:], (200, 200, 200), 1, cv2.LINE_AA)
color = (255, 255, 255)
else:
cv2.rectangle(img, box[:2], box[2:], (70, 70, 70), 1, cv2.LINE_AA)
color = (185, 185, 185)
ui.put_text(img, f"{i + 1}) {label}", (PAD + 20, y + 12), 19, color)
ui.put_text(img, "1..4 select W S move ENTER start Q quit",
(PAD, H - 70), 16, (140, 140, 140))
if self.note:
ui.put_text(img, self.note, (PAD, H - 42), 16, (120, 120, 230))
return img
def run(self) -> str | None:
"""Show menu and return mode."""
cv2.namedWindow(WINDOW, cv2.WINDOW_NORMAL)
cv2.resizeWindow(WINDOW, W, H)
cv2.setMouseCallback(WINDOW, self.on_mouse)
while True:
cv2.imshow(WINDOW, self.frame())
key = cv2.waitKey(20) & 0xFF
if cv2.getWindowProperty(WINDOW, cv2.WND_PROP_VISIBLE) < 1:
return None
chosen = -1
if self.click >= 0:
chosen, self.click = self.click, -1
elif key in (ord("q"), 27):
cv2.destroyWindow(WINDOW)
cv2.waitKey(1)
return None
elif key in (ord("w"), 82):
self.index = (self.index - 1) % len(ITEMS)
elif key in (ord("s"), 84):
self.index = (self.index + 1) % len(ITEMS)
elif key in (13, 10, 32):
chosen = self.index
elif ord("1") <= key <= ord("0") + len(ITEMS):
chosen = key - ord("1")
if chosen < 0:
continue
self.index = chosen
name = ITEMS[chosen][0]
if name in ("2d", "3d", "poses"):
cv2.destroyWindow(WINDOW)
cv2.waitKey(1)
return name
self.note = f"{ITEMS[chosen][1]} is not available yet"
|