{
    "effectName": "Moving Head",
    "properties": [
        {
            "id": "MHPan",
            "label": "Pan (deg)",
            "description": "The horizontal pan angle in degrees for the moving head fixture. Controls left/right beam positioning.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -1800,
            "max": 1800,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHTilt",
            "label": "Tilt (deg)",
            "description": "The vertical tilt angle in degrees for the moving head fixture. Controls up/down beam positioning.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -1800,
            "max": 1800,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHPanOffset",
            "label": "Fan Pan",
            "description": "Pan offset in degrees applied incrementally across grouped fixtures, fanning them apart horizontally. Creates a spread effect when multiple heads are grouped.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -1800,
            "max": 1800,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHTiltOffset",
            "label": "Fan Tilt",
            "description": "Tilt offset in degrees applied incrementally across grouped fixtures, fanning them apart vertically. Creates a spread effect when multiple heads are grouped.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -1800,
            "max": 1800,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHGroupings",
            "label": "Groupings",
            "description": "Number of fixture groupings for fan offset distribution. Fixtures within the same group share the same pan/tilt, with fan offsets applied between groups.",
            "type": "int",
            "controlType": "slider",
            "default": 1,
            "min": 1,
            "max": 6,
            "valueCurve": true
        },
        {
            "id": "MHCycles",
            "label": "Cycles",
            "description": "Number of full movement cycles to complete over the effect duration. Controls how many times a pathing animation repeats.",
            "type": "float",
            "controlType": "slider",
            "default": 0.1,
            "min": 0,
            "max": 100,
            "divisor": 10
        },
        {
            "id": "MHPathDef",
            "label": "MHPathDef",
            "description": "Encoded definition string for the movement path. Defines waypoints and curves that the moving head beam follows over time.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MHFixtures",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad-only fixture selection: eight toggles for Moving Head slots 1-8. Each toggle flips the matching MH*_Settings entry between active and empty. Position slider changes (Pan / Tilt / Offsets / Groupings / Cycles) automatically re-sync into every active fixture, as do the Pattern, shutter and Link settings. Colour, dimmer intensity, waypoint path drawing and parametric patterns each have their own tab."
        },
        {
            "id": "MHIpadInfo",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad-only explanatory banner for the Moving Head inspector."
        },
        {
            "id": "MHColorRow",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad single-colour authoring: SwiftUI ColorPicker writes a single HSV triple into the active fixtures' Color: command."
        },
        {
            "id": "MHColorWheelRow",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad colour-wheel picker for colour-wheel fixtures: a strip of the model's wheel slots that writes a single-colour Wheel: command. Hidden for RGB/CMYW fixtures."
        },
        {
            "id": "MHDimmerRow",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad dimmer intensity authoring: a flat-ramp 0..100% slider that writes a constant Dimmer: command into the active fixtures."
        },
        {
            "id": "MHPathRow",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad waypoint path editor: a touch Canvas that draws Bezier (line / quadratic / cubic) waypoint paths plus path presets, writing the same Path: command desktop's Effect Assist reads."
        },
        {
            "id": "MHPathScale",
            "label": "Scale",
            "description": "Scales the size of the movement path. Positive values enlarge the path, negative values shrink it, and zero uses the default size.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -100,
            "max": 100,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHTimeOffset",
            "label": "Time Offset",
            "description": "Shifts the starting point in time along the movement path. Use to stagger multiple fixtures following the same path at different phases.",
            "type": "float",
            "controlType": "slider",
            "default": 0.0,
            "min": -1000,
            "max": 1000,
            "divisor": 10,
            "valueCurve": true
        },
        {
            "id": "MHIgnorePan",
            "label": "Ignore Pan",
            "description": "When enabled, the pan component of the path is ignored, keeping the fixture at its current horizontal position while only tilt changes.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "MHIgnoreTilt",
            "label": "Ignore Tilt",
            "description": "When enabled, the tilt component of the path is ignored, keeping the fixture at its current vertical position while only pan changes.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "AUTO_SHUTTER",
            "label": "Auto Shutter",
            "description": "When enabled, the fixture shutter automatically opens when the dimmer is above zero and closes when the dimmer is zero, preventing unwanted light leaks during repositioning.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "MHShutterEnable",
            "label": "Enable Shutter",
            "description": "Holds the fixture shutter open at the model's Shutter On value for the whole effect. Auto Shutter still takes over when it is active.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "MHPatternEnable",
            "label": "Enable Pattern",
            "description": "Drives Pan/Tilt from a parametric shape generator instead of (or on top of) the waypoint path.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "MHPattern",
            "label": "Shape",
            "description": "Parametric shape the beam traces over the effect duration. Modelled on QLC+ EFX shapes.",
            "type": "enum",
            "controlType": "choice",
            "default": "Circle",
            "options": [
                "Circle",
                "Eight",
                "Line",
                "Line2",
                "Diamond",
                "Square",
                "SquareChoppy",
                "SquareTrue",
                "Leaf",
                "Lissajous"
            ]
        },
        {
            "id": "MHPatternWidth",
            "label": "Width",
            "description": "Half-width of the pattern in pan degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 90,
            "min": 0,
            "max": 180
        },
        {
            "id": "MHPatternHeight",
            "label": "Height",
            "description": "Half-height of the pattern in tilt degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 45,
            "min": 0,
            "max": 180
        },
        {
            "id": "MHPatternXOffset",
            "label": "X Offset",
            "description": "Pan-axis centre of the pattern in degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": -180,
            "max": 180
        },
        {
            "id": "MHPatternYOffset",
            "label": "Y Offset",
            "description": "Tilt-axis centre of the pattern in degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": -180,
            "max": 180
        },
        {
            "id": "MHPatternRotation",
            "label": "Rotation",
            "description": "Rotates the whole pattern about its centre, in degrees. Animate it with a value curve to spin the shape over the effect.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": 0,
            "max": 360,
            "valueCurve": true,
            "vcMin": 0,
            "vcMax": 360
        },
        {
            "id": "MHPatternStartOffset",
            "label": "Start Offset",
            "description": "Shifts where along the shape the beam starts, in degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": 0,
            "max": 360
        },
        {
            "id": "MHPatternPhaseOffset",
            "label": "Head Spread",
            "description": "Staggers grouped fixtures along the shape so they chase each other around it. Only meaningful for a model group.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": -360,
            "max": 360
        },
        {
            "id": "MHPatternXFreq",
            "label": "X Frequency",
            "description": "Lissajous only: pan-axis frequency multiplier.",
            "type": "int",
            "controlType": "slider",
            "default": 2,
            "min": 0,
            "max": 32
        },
        {
            "id": "MHPatternYFreq",
            "label": "Y Frequency",
            "description": "Lissajous only: tilt-axis frequency multiplier.",
            "type": "int",
            "controlType": "slider",
            "default": 3,
            "min": 0,
            "max": 32
        },
        {
            "id": "MHPatternXPhase",
            "label": "X Phase",
            "description": "Lissajous only: pan-axis phase in degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 90,
            "min": 0,
            "max": 360
        },
        {
            "id": "MHPatternYPhase",
            "label": "Y Phase",
            "description": "Lissajous only: tilt-axis phase in degrees.",
            "type": "int",
            "controlType": "slider",
            "default": 0,
            "min": 0,
            "max": 360
        },
        {
            "id": "MHLinkToNext",
            "label": "Link end position to next Moving Head effect",
            "description": "Snaps every active head's Pan/Tilt to where the next Moving Head effect on this row starts, and forces the Dimmer to 0 so the head moves into position dark.",
            "type": "bool",
            "controlType": "checkbox",
            "default": false
        },
        {
            "id": "MHLinkRow",
            "label": "",
            "type": "string",
            "controlType": "custom",
            "platform": "ipad",
            "default": "",
            "description": "iPad Link tab body: per-head sync preview plus a Re-sync button, mirroring desktop's StaticText_MHLinkPreview."
        },
        {
            "id": "MH1_Settings",
            "label": "MH1_Settings",
            "description": "Per-fixture override settings for moving head fixture 1. Stores individual pan, tilt, and other parameters that differ from the group defaults.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH2_Settings",
            "label": "MH2_Settings",
            "description": "Per-fixture override settings for moving head fixture 2.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH3_Settings",
            "label": "MH3_Settings",
            "description": "Per-fixture override settings for moving head fixture 3.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH4_Settings",
            "label": "MH4_Settings",
            "description": "Per-fixture override settings for moving head fixture 4.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH5_Settings",
            "label": "MH5_Settings",
            "description": "Per-fixture override settings for moving head fixture 5.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH6_Settings",
            "label": "MH6_Settings",
            "description": "Per-fixture override settings for moving head fixture 6.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH7_Settings",
            "label": "MH7_Settings",
            "description": "Per-fixture override settings for moving head fixture 7.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        },
        {
            "id": "MH8_Settings",
            "label": "MH8_Settings",
            "description": "Per-fixture override settings for moving head fixture 8.",
            "type": "string",
            "controlType": "text",
            "platform": "desktop",
            "default": ""
        }
    ],
    "groups": [
        {
            "type": "tabs",
            "tabs": [
                {
                    "label": "Color",
                    "properties": [
                        "MHColorRow"
                    ]
                },
                {
                    "label": "ColorWheel",
                    "properties": [
                        "AUTO_SHUTTER"
                    ]
                }
            ],
            "settingKey": "E_NOTEBOOK2"
        },
        {
            "type": "tabs",
            "tabs": [
                {
                    "label": "Position",
                    "properties": [
                        "MHIpadInfo",
                        "MHFixtures",
                        "MHPan",
                        "MHTilt",
                        "MHPanOffset",
                        "MHTiltOffset",
                        "MHGroupings",
                        "MHCycles"
                    ]
                },
                {
                    "label": "Dimmer",
                    "properties": [
                        "MHDimmerRow"
                    ]
                },
                {
                    "label": "Pathing",
                    "properties": [
                        "MHPathRow",
                        "MHPathDef",
                        "MHPathScale",
                        "MHTimeOffset",
                        "MHIgnorePan",
                        "MHIgnoreTilt"
                    ]
                },
                {
                    "label": "Pattern",
                    "properties": [
                        "MHPatternEnable",
                        "MHPattern",
                        "MHPatternWidth",
                        "MHPatternHeight",
                        "MHPatternXOffset",
                        "MHPatternYOffset",
                        "MHPatternRotation",
                        "MHPatternStartOffset",
                        "MHPatternPhaseOffset",
                        "MHPatternXFreq",
                        "MHPatternYFreq",
                        "MHPatternXPhase",
                        "MHPatternYPhase"
                    ]
                },
                {
                    "label": "Control",
                    "properties": [
                        "AUTO_SHUTTER",
                        "MHShutterEnable"
                    ]
                },
                {
                    "label": "Link",
                    "properties": [
                        "MHLinkToNext",
                        "MHLinkRow"
                    ]
                },
                {
                    "label": "Status",
                    "properties": []
                }
            ],
            "settingKey": "E_NOTEBOOK1"
        }
    ],
    "visibilityRules": [
        {
            "when": {
                "property": "MHPatternEnable",
                "equals": true
            },
            "enable": [
                "MHPattern",
                "MHPatternWidth",
                "MHPatternHeight",
                "MHPatternXOffset",
                "MHPatternYOffset",
                "MHPatternRotation",
                "MHPatternStartOffset",
                "MHPatternPhaseOffset",
                "MHPatternXFreq",
                "MHPatternYFreq",
                "MHPatternXPhase",
                "MHPatternYPhase"
            ]
        },
        {
            "when": {
                "property": "MHPattern",
                "equals": "Lissajous"
            },
            "enable": [
                "MHPatternXFreq",
                "MHPatternYFreq",
                "MHPatternXPhase",
                "MHPatternYPhase"
            ]
        }
    ]
}
