Split cabaret figure-8s onto the floor and the wall, and make Speed a fader.
Floor 8 stays on the live ground aim; Wall 8 uses the Here–Out box. Pan/tilt speed is a slider so it matches Bright and Focus. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+66
-61
@@ -16,7 +16,8 @@ GROUP_C = [2, 3, 4, 5]
|
|||||||
GROUP_R = [6, 7]
|
GROUP_R = [6, 7]
|
||||||
|
|
||||||
# Can 8ch: Dim=0, R=2, G=3, B=4
|
# 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_FOCUS = 7
|
||||||
MOVER_DIM = 8
|
MOVER_DIM = 8
|
||||||
MOVER_R = [10, 14, 18, 22, 26, 30, 34]
|
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
|
POSITION_FUNC0 = 100
|
||||||
PADS_FUNC = POSITION_FUNC0 + len(POSITIONS)
|
PADS_FUNC = POSITION_FUNC0 + len(POSITIONS)
|
||||||
PADS_BG = "4282800750" # #465A6E pad grey-blue
|
PADS_BG = "4282800750" # #465A6E pad grey-blue
|
||||||
FIGURE8_FUNC = 110
|
FIGURE8_FLOOR_FUNC = 110
|
||||||
FIGURE8_SIDE_FUNC = 111
|
FIGURE8_WALL_FUNC = 111
|
||||||
FIGURE8_MS = 12000
|
FIGURE8_MS = 12000
|
||||||
FIGURE8_BG = "4282664004"
|
FIGURE8_FLOOR_BG = "4282664004"
|
||||||
FIGURE8_SIDE_BG = "4286611584"
|
FIGURE8_WALL_BG = "4286611584"
|
||||||
LOOK_PAIRS: list[tuple[str, str | None]] = [
|
LOOK_PAIRS: list[tuple[str, str | None]] = [
|
||||||
("Amber", None),
|
("Amber", None),
|
||||||
("Pink", "Amber"),
|
("Pink", "Amber"),
|
||||||
@@ -132,11 +133,13 @@ def slider(
|
|||||||
value: int = 0,
|
value: int = 0,
|
||||||
fg: str = "Default",
|
fg: str = "Default",
|
||||||
cng: str = "None",
|
cng: str = "None",
|
||||||
|
inverted: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
ch_xml = "\n".join(
|
ch_xml = "\n".join(
|
||||||
f' <Channel Fixture="{fid}">{ch}</Channel>' for fid, ch in channels
|
f' <Channel Fixture="{fid}">{ch}</Channel>' for fid, ch in channels
|
||||||
)
|
)
|
||||||
return f""" <Slider Caption="{caption}" ID="{wid}" WidgetStyle="Slider" InvertedAppearance="false">
|
inv = "true" if inverted else "false"
|
||||||
|
return f""" <Slider Caption="{caption}" ID="{wid}" WidgetStyle="Slider" InvertedAppearance="{inv}">
|
||||||
<WindowState Visible="True" X="{x}" Y="{y}" Width="{w}" Height="{h}"/>
|
<WindowState Visible="True" X="{x}" Y="{y}" Width="{w}" Height="{h}"/>
|
||||||
{appearance(fg=fg)}
|
{appearance(fg=fg)}
|
||||||
<SliderMode ValueDisplayStyle="Exact" ClickAndGoType="{cng}" Monitor="true">Level</SliderMode>
|
<SliderMode ValueDisplayStyle="Exact" ClickAndGoType="{cng}" Monitor="true">Level</SliderMode>
|
||||||
@@ -150,33 +153,6 @@ def slider(
|
|||||||
</Slider>"""
|
</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' <Function FadeIn="0" FadeOut="0" Duration="6">{fid}</Function>'
|
|
||||||
for fid in func_ids
|
|
||||||
)
|
|
||||||
return f""" <SpeedDial Caption="{caption}" ID="{wid}">
|
|
||||||
<WindowState Visible="True" X="{x}" Y="{y}" Width="{w}" Height="{h}"/>
|
|
||||||
{appearance()}
|
|
||||||
<Visibility>2</Visibility>
|
|
||||||
<AbsoluteValue Minimum="{min_ms}" Maximum="{max_ms}"/>
|
|
||||||
<Time>{time_ms}</Time>
|
|
||||||
{fn_xml}
|
|
||||||
</SpeedDial>"""
|
|
||||||
|
|
||||||
|
|
||||||
def xypad(
|
def xypad(
|
||||||
wid: int,
|
wid: int,
|
||||||
caption: str,
|
caption: str,
|
||||||
@@ -401,12 +377,23 @@ def position_button_specs() -> list[tuple[str, int, str]]:
|
|||||||
(name, POSITION_FUNC0 + i, bg)
|
(name, POSITION_FUNC0 + i, bg)
|
||||||
for i, (name, _m1, _m2, bg) in enumerate(POSITIONS)
|
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]:
|
def figure8_floor_center() -> tuple[int, int]:
|
||||||
"""Pan/tilt centre and amplitude covering Here–Out (not the live Now aim)."""
|
"""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] = []
|
pans: list[int] = []
|
||||||
tilts: list[int] = []
|
tilts: list[int] = []
|
||||||
for name, m1, m2, _bg in POSITIONS:
|
for name, m1, m2, _bg in POSITIONS:
|
||||||
@@ -461,22 +448,29 @@ def figure8_efx_block(
|
|||||||
|
|
||||||
|
|
||||||
def figure8_efx_xml() -> str:
|
def figure8_efx_xml() -> str:
|
||||||
pan_c, tilt_c, pan_amp, tilt_amp = figure8_bounds()
|
floor_pan, floor_tilt = figure8_floor_center()
|
||||||
# Sideways ∞ is rotation 0. 90° is a vertical 8 (tilt 0 → 36 down);
|
wall_pan, wall_tilt, wall_pan_amp, wall_tilt_amp = figure8_wall_bounds()
|
||||||
# width/height are swapped so both still fill the Here–Out box.
|
# 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(
|
return "\n".join(
|
||||||
[
|
[
|
||||||
figure8_efx_block(
|
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_efx_block(
|
||||||
FIGURE8_SIDE_FUNC,
|
FIGURE8_WALL_FUNC,
|
||||||
"Figure of 8 Side",
|
"Figure of 8 Walls",
|
||||||
pan_amp,
|
wall_pan_amp,
|
||||||
tilt_amp,
|
wall_tilt_amp,
|
||||||
0,
|
0,
|
||||||
pan_c,
|
wall_pan,
|
||||||
tilt_c,
|
wall_tilt,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -554,10 +548,24 @@ def main() -> None:
|
|||||||
max_x = 0
|
max_x = 0
|
||||||
max_y = 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
|
nonlocal wid, max_x, max_y
|
||||||
widgets.append(
|
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
|
wid += 1
|
||||||
max_x = max(max_x, x + w)
|
max_x = max(max_x, x + w)
|
||||||
@@ -688,20 +696,17 @@ def main() -> None:
|
|||||||
"4294902015",
|
"4294902015",
|
||||||
)
|
)
|
||||||
x += sl_w + 2
|
x += sl_w + 2
|
||||||
widgets.append(
|
place_slider(
|
||||||
speed_dial(
|
"Speed",
|
||||||
wid,
|
x,
|
||||||
"Speed",
|
y0,
|
||||||
x,
|
sl_w,
|
||||||
y0,
|
sl_h,
|
||||||
sl_w,
|
[(M1, MOVER_SPEED), (M2, MOVER_SPEED)],
|
||||||
sl_h,
|
0,
|
||||||
[FIGURE8_FUNC, FIGURE8_SIDE_FUNC],
|
"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
|
x += sl_w + 2
|
||||||
for name, _can_ch, mover_chs, fg, cng in RGB:
|
for name, _can_ch, mover_chs, fg, cng in RGB:
|
||||||
place_slider(
|
place_slider(
|
||||||
|
|||||||
+20
-16
@@ -381,7 +381,7 @@
|
|||||||
<FixtureVal ID="8">0,200,1,0,2,22,3,0</FixtureVal>
|
<FixtureVal ID="8">0,200,1,0,2,22,3,0</FixtureVal>
|
||||||
<FixtureVal ID="9">0,200,1,0,2,22,3,0</FixtureVal>
|
<FixtureVal ID="9">0,200,1,0,2,22,3,0</FixtureVal>
|
||||||
</Function>
|
</Function>
|
||||||
<Function ID="110" Type="EFX" Name="Figure of 8">
|
<Function ID="110" Type="EFX" Name="Figure of 8 Floor">
|
||||||
<Fixture>
|
<Fixture>
|
||||||
<ID>8</ID>
|
<ID>8</ID>
|
||||||
<Direction>Forward</Direction>
|
<Direction>Forward</Direction>
|
||||||
@@ -397,21 +397,21 @@
|
|||||||
<Direction>Forward</Direction>
|
<Direction>Forward</Direction>
|
||||||
<RunOrder>Loop</RunOrder>
|
<RunOrder>Loop</RunOrder>
|
||||||
<Algorithm>Eight</Algorithm>
|
<Algorithm>Eight</Algorithm>
|
||||||
<Width>18</Width>
|
<Width>16</Width>
|
||||||
<Height>30</Height>
|
<Height>18</Height>
|
||||||
<Rotation>90</Rotation>
|
<Rotation>90</Rotation>
|
||||||
<Axis Name="X">
|
<Axis Name="X">
|
||||||
<Offset>170</Offset>
|
<Offset>77</Offset>
|
||||||
<Frequency>1</Frequency>
|
<Frequency>1</Frequency>
|
||||||
<Phase>0</Phase>
|
<Phase>0</Phase>
|
||||||
</Axis>
|
</Axis>
|
||||||
<Axis Name="Y">
|
<Axis Name="Y">
|
||||||
<Offset>18</Offset>
|
<Offset>153</Offset>
|
||||||
<Frequency>1</Frequency>
|
<Frequency>1</Frequency>
|
||||||
<Phase>0</Phase>
|
<Phase>0</Phase>
|
||||||
</Axis>
|
</Axis>
|
||||||
</Function>
|
</Function>
|
||||||
<Function ID="111" Type="EFX" Name="Figure of 8 Side">
|
<Function ID="111" Type="EFX" Name="Figure of 8 Walls">
|
||||||
<Fixture>
|
<Fixture>
|
||||||
<ID>8</ID>
|
<ID>8</ID>
|
||||||
<Direction>Forward</Direction>
|
<Direction>Forward</Direction>
|
||||||
@@ -523,21 +523,25 @@
|
|||||||
<Function>4294967295</Function>
|
<Function>4294967295</Function>
|
||||||
</Playback>
|
</Playback>
|
||||||
</Slider>
|
</Slider>
|
||||||
<SpeedDial Caption="Speed" ID="4">
|
<Slider Caption="Speed" ID="4" WidgetStyle="Slider" InvertedAppearance="true">
|
||||||
<WindowState Visible="True" X="654" Y="28" Width="44" Height="240"/>
|
<WindowState Visible="True" X="654" Y="28" Width="44" Height="240"/>
|
||||||
<Appearance>
|
<Appearance>
|
||||||
<FrameStyle>Sunken</FrameStyle>
|
<FrameStyle>Sunken</FrameStyle>
|
||||||
<ForegroundColor>Default</ForegroundColor>
|
<ForegroundColor>4294967295</ForegroundColor>
|
||||||
<BackgroundColor>Default</BackgroundColor>
|
<BackgroundColor>Default</BackgroundColor>
|
||||||
<BackgroundImage>None</BackgroundImage>
|
<BackgroundImage>None</BackgroundImage>
|
||||||
<Font>Default</Font>
|
<Font>Default</Font>
|
||||||
</Appearance>
|
</Appearance>
|
||||||
<Visibility>2</Visibility>
|
<SliderMode ValueDisplayStyle="Exact" ClickAndGoType="None" Monitor="true">Level</SliderMode>
|
||||||
<AbsoluteValue Minimum="500" Maximum="30000"/>
|
<Reset/>
|
||||||
<Time>12000</Time>
|
<Level LowLimit="0" HighLimit="255" Value="0">
|
||||||
<Function FadeIn="0" FadeOut="0" Duration="6">110</Function>
|
<Channel Fixture="8">4</Channel>
|
||||||
<Function FadeIn="0" FadeOut="0" Duration="6">111</Function>
|
<Channel Fixture="9">4</Channel>
|
||||||
</SpeedDial>
|
</Level>
|
||||||
|
<Playback>
|
||||||
|
<Function>4294967295</Function>
|
||||||
|
</Playback>
|
||||||
|
</Slider>
|
||||||
<Slider Caption="M R" ID="5" WidgetStyle="Slider" InvertedAppearance="false">
|
<Slider Caption="M R" ID="5" WidgetStyle="Slider" InvertedAppearance="false">
|
||||||
<WindowState Visible="True" X="700" Y="28" Width="44" Height="240"/>
|
<WindowState Visible="True" X="700" Y="28" Width="44" Height="240"/>
|
||||||
<Appearance>
|
<Appearance>
|
||||||
@@ -736,7 +740,7 @@
|
|||||||
<Action>Toggle</Action>
|
<Action>Toggle</Action>
|
||||||
<Intensity Adjust="False">100</Intensity>
|
<Intensity Adjust="False">100</Intensity>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Caption="Fig 8" ID="16" Icon="">
|
<Button Caption="Floor 8" ID="16" Icon="">
|
||||||
<WindowState Visible="True" X="82" Y="176" Width="72" Height="42"/>
|
<WindowState Visible="True" X="82" Y="176" Width="72" Height="42"/>
|
||||||
<Appearance>
|
<Appearance>
|
||||||
<FrameStyle>None</FrameStyle>
|
<FrameStyle>None</FrameStyle>
|
||||||
@@ -749,7 +753,7 @@
|
|||||||
<Action>Toggle</Action>
|
<Action>Toggle</Action>
|
||||||
<Intensity Adjust="False">100</Intensity>
|
<Intensity Adjust="False">100</Intensity>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Caption="Side 8" ID="17" Icon="">
|
<Button Caption="Wall 8" ID="17" Icon="">
|
||||||
<WindowState Visible="True" X="4" Y="224" Width="72" Height="42"/>
|
<WindowState Visible="True" X="4" Y="224" Width="72" Height="42"/>
|
||||||
<Appearance>
|
<Appearance>
|
||||||
<FrameStyle>None</FrameStyle>
|
<FrameStyle>None</FrameStyle>
|
||||||
|
|||||||
Reference in New Issue
Block a user