diff --git a/scripts/make_cabaret_vc.py b/scripts/make_cabaret_vc.py
index 68ce04a..ab2c489 100644
--- a/scripts/make_cabaret_vc.py
+++ b/scripts/make_cabaret_vc.py
@@ -16,7 +16,8 @@ GROUP_C = [2, 3, 4, 5]
GROUP_R = [6, 7]
# Can 8ch: Dim=0, R=2, G=3, B=4
-# Mover 43ch: Focus=7, Center Bright=8; RGB heads 1–7
+# Mover 43ch: Pan/Tilt Speed=4, Focus=7, Center Bright=8; RGB heads 1–7
+MOVER_SPEED = 4
MOVER_FOCUS = 7
MOVER_DIM = 8
MOVER_R = [10, 14, 18, 22, 26, 30, 34]
@@ -69,11 +70,11 @@ POSITIONS: list[tuple[str, tuple[int, int], tuple[int, int], str]] = [
POSITION_FUNC0 = 100
PADS_FUNC = POSITION_FUNC0 + len(POSITIONS)
PADS_BG = "4282800750" # #465A6E pad grey-blue
-FIGURE8_FUNC = 110
-FIGURE8_SIDE_FUNC = 111
+FIGURE8_FLOOR_FUNC = 110
+FIGURE8_WALL_FUNC = 111
FIGURE8_MS = 12000
-FIGURE8_BG = "4282664004"
-FIGURE8_SIDE_BG = "4286611584"
+FIGURE8_FLOOR_BG = "4282664004"
+FIGURE8_WALL_BG = "4286611584"
LOOK_PAIRS: list[tuple[str, str | None]] = [
("Amber", None),
("Pink", "Amber"),
@@ -132,11 +133,13 @@ def slider(
value: int = 0,
fg: str = "Default",
cng: str = "None",
+ inverted: bool = False,
) -> str:
ch_xml = "\n".join(
f' {ch}' for fid, ch in channels
)
- return f"""
+ inv = "true" if inverted else "false"
+ return f"""
{appearance(fg=fg)}
Level
@@ -150,33 +153,6 @@ def slider(
"""
-def speed_dial(
- wid: int,
- caption: str,
- x: int,
- y: int,
- w: int,
- h: int,
- func_ids: list[int],
- *,
- time_ms: int = FIGURE8_MS,
- min_ms: int = 500,
- max_ms: int = 30000,
-) -> str:
- fn_xml = "\n".join(
- f' {fid}'
- for fid in func_ids
- )
- return f"""
-
-{appearance()}
- 2
-
-
-{fn_xml}
- """
-
-
def xypad(
wid: int,
caption: str,
@@ -401,12 +377,23 @@ def position_button_specs() -> list[tuple[str, int, str]]:
(name, POSITION_FUNC0 + i, bg)
for i, (name, _m1, _m2, bg) in enumerate(POSITIONS)
]
- + [("Fig 8", FIGURE8_FUNC, FIGURE8_BG), ("Side 8", FIGURE8_SIDE_FUNC, FIGURE8_SIDE_BG)]
+ + [
+ ("Floor 8", FIGURE8_FLOOR_FUNC, FIGURE8_FLOOR_BG),
+ ("Wall 8", FIGURE8_WALL_FUNC, FIGURE8_WALL_BG),
+ ]
)
-def figure8_bounds() -> tuple[int, int, int, int]:
- """Pan/tilt centre and amplitude covering Here–Out (not the live Now aim)."""
+def figure8_floor_center() -> tuple[int, int]:
+ """Now is the live floor aim; average both heads so the 8 stays on the ground."""
+ now = next((m1, m2) for name, m1, m2, _bg in POSITIONS if name == "Now")
+ pans = [now[0][0], now[1][0]]
+ tilts = [now[0][1], now[1][1]]
+ return (pans[0] + pans[1]) // 2, (tilts[0] + tilts[1]) // 2
+
+
+def figure8_wall_bounds() -> tuple[int, int, int, int]:
+ """Pan/tilt centre and amplitude covering Here–Out (the wall looks)."""
pans: list[int] = []
tilts: list[int] = []
for name, m1, m2, _bg in POSITIONS:
@@ -461,22 +448,29 @@ def figure8_efx_block(
def figure8_efx_xml() -> str:
- pan_c, tilt_c, pan_amp, tilt_amp = figure8_bounds()
- # Sideways ∞ is rotation 0. 90° is a vertical 8 (tilt 0 → 36 down);
- # width/height are swapped so both still fill the Here–Out box.
+ floor_pan, floor_tilt = figure8_floor_center()
+ wall_pan, wall_tilt, wall_pan_amp, wall_tilt_amp = figure8_wall_bounds()
+ # Floor 8: around Now, tilt stays on the ground. Rotation 90 = upright 8.
+ # Wall 8: Here–Out box (tilt 0–36). Rotation 0 = 8 across the wall.
return "\n".join(
[
figure8_efx_block(
- FIGURE8_FUNC, "Figure of 8", tilt_amp, pan_amp, 90, pan_c, tilt_c
+ FIGURE8_FLOOR_FUNC,
+ "Figure of 8 Floor",
+ 16,
+ 18,
+ 90,
+ floor_pan,
+ floor_tilt,
),
figure8_efx_block(
- FIGURE8_SIDE_FUNC,
- "Figure of 8 Side",
- pan_amp,
- tilt_amp,
+ FIGURE8_WALL_FUNC,
+ "Figure of 8 Walls",
+ wall_pan_amp,
+ wall_tilt_amp,
0,
- pan_c,
- tilt_c,
+ wall_pan,
+ wall_tilt,
),
]
)
@@ -554,10 +548,24 @@ def main() -> None:
max_x = 0
max_y = 0
- def place_slider(caption, x, y, w, h, channels, value=0, fg="Default", cng="None"):
+ def place_slider(
+ caption, x, y, w, h, channels, value=0, fg="Default", cng="None", inverted=False
+ ):
nonlocal wid, max_x, max_y
widgets.append(
- slider(wid, caption, x, y, w, h, channels, value=value, fg=fg, cng=cng)
+ slider(
+ wid,
+ caption,
+ x,
+ y,
+ w,
+ h,
+ channels,
+ value=value,
+ fg=fg,
+ cng=cng,
+ inverted=inverted,
+ )
)
wid += 1
max_x = max(max_x, x + w)
@@ -688,20 +696,17 @@ def main() -> None:
"4294902015",
)
x += sl_w + 2
- widgets.append(
- speed_dial(
- wid,
- "Speed",
- x,
- y0,
- sl_w,
- sl_h,
- [FIGURE8_FUNC, FIGURE8_SIDE_FUNC],
- )
+ place_slider(
+ "Speed",
+ x,
+ y0,
+ sl_w,
+ sl_h,
+ [(M1, MOVER_SPEED), (M2, MOVER_SPEED)],
+ 0,
+ "4294967295",
+ inverted=True,
)
- wid += 1
- max_x = max(max_x, x + sl_w)
- max_y = max(max_y, y0 + sl_h)
x += sl_w + 2
for name, _can_ch, mover_chs, fg, cng in RGB:
place_slider(
diff --git a/shows/cabaret.qxw b/shows/cabaret.qxw
index b5d2746..8cc8458 100644
--- a/shows/cabaret.qxw
+++ b/shows/cabaret.qxw
@@ -381,7 +381,7 @@
0,200,1,0,2,22,3,0
0,200,1,0,2,22,3,0
-
+
8
Forward
@@ -397,21 +397,21 @@
Forward
Loop
Eight
- 18
- 30
+ 16
+ 18
90
- 170
+ 77
1
0
- 18
+ 153
1
0
-
+
8
Forward
@@ -523,21 +523,25 @@
4294967295
-
+
Sunken
- Default
+ 4294967295
Default
None
Default
- 2
-
-
- 110
- 111
-
+ Level
+
+
+ 4
+ 4
+
+
+ 4294967295
+
+
@@ -736,7 +740,7 @@
Toggle
100
-