motionlab/panel.py
0xrsydn 6591138bbf Python/OpenCV proof of concept plus first native Swift port
Snapshot before the Python POC is removed. The POC (main.py, effects.py,
panel.py, shaders.py, effects/*.glsl, flake.nix) is the reference for the
native app under native/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:26:47 +07:00

61 lines
2.4 KiB
Python

"""Control panel drawn straight onto the output canvas: click a layer to toggle it, drag its sliders."""
import cv2
BG = (26, 24, 22)
TRACK = (52, 48, 46)
FG = (228, 228, 228)
DIM = (125, 125, 125)
ACCENT = (255, 176, 64)
FONT = cv2.FONT_HERSHEY_SIMPLEX
class Panel:
WIDTH = 260
def __init__(self, layers):
self.layers = layers
self.hits = [] # (x0, y0, x1, y1, target, bar_x0, bar_x1), rebuilt on every draw
self.drag = None
def draw(self, canvas, x0, status):
h = canvas.shape[0]
canvas[:, x0:] = BG
self.hits = []
x, right = x0 + 14, x0 + self.WIDTH - 14
cv2.putText(canvas, "MOTIONLAB", (x, 26), FONT, 0.55, FG, 1, cv2.LINE_AA)
cv2.putText(canvas, status, (x + 124, 26), FONT, 0.4, DIM, 1, cv2.LINE_AA)
y = 44
for layer in self.layers:
on = layer.enabled
cv2.rectangle(canvas, (x, y), (x + 12, y + 12), ACCENT if on else DIM, -1 if on else 1)
cv2.putText(canvas, layer.name, (x + 22, y + 11), FONT, 0.48, FG if on else DIM, 1, cv2.LINE_AA)
self.hits.append((x0, y - 5, x0 + self.WIDTH, y + 17, layer, 0, 0))
y += 22
if not on:
continue
bar = x + 100
for name, p in layer.params.items():
cv2.putText(canvas, name, (x + 4, y + 8), FONT, 0.36, DIM, 1, cv2.LINE_AA)
cv2.rectangle(canvas, (bar, y), (right, y + 8), TRACK, -1)
cv2.rectangle(canvas, (bar, y), (bar + int((right - bar) * p.norm), y + 8), ACCENT, -1)
self.hits.append((bar - 8, y - 4, right + 8, y + 12, p, bar, right))
y += 16
y += 4
cv2.putText(canvas, "[h] panel [s] shot [r] rec [q] quit", (x, h - 12), FONT, 0.36, DIM, 1, cv2.LINE_AA)
def on_mouse(self, event, mx, my, flags, _):
if event == cv2.EVENT_LBUTTONDOWN:
for x0, y0, x1, y1, target, bar_x0, bar_x1 in self.hits:
if x0 <= mx < x1 and y0 <= my < y1:
if bar_x1:
self.drag = (target, bar_x0, bar_x1)
else:
target.enabled = not target.enabled
break
elif event == cv2.EVENT_LBUTTONUP:
self.drag = None
if self.drag and event in (cv2.EVENT_LBUTTONDOWN, cv2.EVENT_MOUSEMOVE):
param, bar_x0, bar_x1 = self.drag
param.norm = (mx - bar_x0) / (bar_x1 - bar_x0)