{
  "createdWith": "Open Stage Control",
  "version": "1.30.3",
  "type": "session",
  "content": {
    "type": "root",
    "lock": false,
    "id": "root",
    "visible": true,
    "interaction": true,
    "comments": "",
    "width": "auto",
    "height": "auto",
    "colorText": "auto",
    "colorWidget": "auto",
    "alphaFillOn": "auto",
    "borderRadius": "auto",
    "padding": "auto",
    "html": "",
    "css": "",
    "colorBg": "auto",
    "layout": "default",
    "justify": "start",
    "gridTemplate": "",
    "contain": true,
    "scroll": true,
    "innerPadding": true,
    "tabsPosition": "top",
    "hideMenu": false,
    "variables": "@{parent.variables}",
    "traversing": false,
    "value": "",
    "default": "",
    "linkId": "",
    "address": "auto",
    "preArgs": "",
    "typeTags": "",
    "decimals": 2,
    "target": "192.168.1.46:9000",
    "ignoreDefaults": false,
    "bypass": false,
    "onCreate": "",
    "onValue": "",
    "onTouch": "",
    "onPreload": "",
    "widgets": [
      {
        "type": "xy",
        "top": 120,
        "left": 120,
        "lock": false,
        "id": "fisheye_pan_tilt",
        "visible": true,
        "interaction": true,
        "comments": "XY control for Fisheye Reproject pan and tilt.",
        "width": 460,
        "height": 250,
        "expand": false,
        "colorText": "auto",
        "colorWidget": "auto",
        "colorStroke": "auto",
        "colorFill": "auto",
        "alphaStroke": "auto",
        "alphaFillOff": "auto",
        "alphaFillOn": "auto",
        "lineWidth": "auto",
        "borderRadius": "auto",
        "padding": "auto",
        "html": "",
        "css": "",
        "pips": true,
        "snap": false,
        "spring": true,
        "rangeX": {
          "min": -1,
          "max": 1
        },
        "rangeY": {
          "min": 1,
          "max": -1
        },
        "logScaleX": false,
        "logScaleY": false,
        "sensitivity": 1,
        "value": [
          0,
          0
        ],
        "default": [
          0,
          0
        ],
        "linkId": "",
        "address": "/VideoShaderToys/fisheye-reproject/xy",
        "preArgs": "",
        "typeTags": "",
        "decimals": "3f",
        "target": "192.168.1.46:9000",
        "ignoreDefaults": false,
        "bypass": true,
        "onCreate": "var state = globalThis.__fisheyePanTiltStick = globalThis.__fisheyePanTiltStick || {};\nstate.target = '192.168.1.46:9000';\nstate.panAddress = '/VideoShaderToys/fisheye-reproject/panDegrees';\nstate.tiltAddress = '/VideoShaderToys/fisheye-reproject/tiltDegrees';\nstate.minPan = -60;\nstate.maxPan = 60;\nstate.minTilt = -45;\nstate.maxTilt = 45;\nstate.pan = 0;\nstate.tilt = 0;\nstate.stickX = 0;\nstate.stickY = 0;\nstate.tickMs = 16;\nstate.stepPan = 0.75;\nstate.stepTilt = 0.75;\nstate.deadzone = 0.14;\nstate.applyCurve = function(input) {\n  var amount = Math.abs(input);\n  if (amount <= state.deadzone) {\n    return 0;\n  }\n  var normalized = (amount - state.deadzone) / (1 - state.deadzone);\n  var softened = normalized * normalized * (3 - (2 * normalized));\n  return (input < 0 ? -1 : 1) * softened;\n};\nif (state.timer) {\n  clearInterval(state.timer);\n  state.timer = null;\n}",
        "onValue": "var state = globalThis.__fisheyePanTiltStick = globalThis.__fisheyePanTiltStick || {};\nvar stickX = Array.isArray(value) ? Number(value[0]) : 0;\nvar stickY = Array.isArray(value) ? Number(value[1]) : 0;\nstate.stickX = isFinite(stickX) ? state.applyCurve(stickX) : 0;\nstate.stickY = isFinite(stickY) ? state.applyCurve(stickY) : 0;",
        "onTouch": "var state = globalThis.__fisheyePanTiltStick = globalThis.__fisheyePanTiltStick || {};\nif (value) {\n  if (!state.timer) {\n    state.timer = setInterval(function() {\n      if (!state.stickX && !state.stickY) {\n        return;\n      }\n      state.pan = Math.max(state.minPan, Math.min(state.maxPan, state.pan + (state.stickX * state.stepPan)));\n      state.tilt = Math.max(state.minTilt, Math.min(state.maxTilt, state.tilt + (state.stickY * state.stepTilt)));\n      send(state.target, state.panAddress, {type: 'f', value: state.pan});\n      send(state.target, state.tiltAddress, {type: 'f', value: state.tilt});\n    }, state.tickMs);\n  }\n} else {\n  state.stickX = 0;\n  state.stickY = 0;\n  if (state.timer) {\n    clearInterval(state.timer);\n    state.timer = null;\n  }\n}",
        "pointSize": 20,
        "ephemeral": false,
        "label": "",
        "stepsX": false,
        "stepsY": false,
        "clipX": "",
        "clipY": "",
        "axisLock": "",
        "doubleTap": false
      },
      {
        "type": "fader",
        "top": 120,
        "left": 570,
        "lock": false,
        "id": "fader_1",
        "visible": true,
        "interaction": true,
        "comments": "",
        "width": 90,
        "height": 250,
        "expand": false,
        "colorText": "auto",
        "colorWidget": "auto",
        "colorStroke": "auto",
        "colorFill": "auto",
        "alphaStroke": "auto",
        "alphaFillOff": "auto",
        "alphaFillOn": "auto",
        "lineWidth": "auto",
        "borderRadius": "auto",
        "padding": "auto",
        "html": "",
        "css": "",
        "design": "default",
        "knobSize": "auto",
        "colorKnob": "auto",
        "horizontal": false,
        "pips": false,
        "dashed": false,
        "gradient": [],
        "snap": false,
        "touchZone": "all",
        "spring": true,
        "doubleTap": false,
        "range": {
          "min": -1,
          "max": 1
        },
        "logScale": false,
        "sensitivity": 1,
        "steps": "",
        "origin": "auto",
        "value": 0,
        "default": 0,
        "linkId": "",
        "address": "/VideoShaderToys/fisheye-reproject/virtualFovDegrees",
        "preArgs": "",
        "typeTags": "",
        "decimals": "3f",
        "target": "192.168.1.46:9000",
        "ignoreDefaults": false,
        "bypass": true,
        "onCreate": "var state = globalThis.__fisheyeFovStick = globalThis.__fisheyeFovStick || {};\nstate.target = '192.168.1.46:9000';\nstate.address = '/VideoShaderToys/fisheye-reproject/virtualFovDegrees';\nstate.minFov = 10;\nstate.maxFov = 100;\nstate.fov = 90;\nstate.stick = 0;\nstate.tickMs = 16;\nstate.stepFov = 0.6;\nstate.deadzone = 0.14;\nstate.applyCurve = function(input) {\n  var amount = Math.abs(input);\n  if (amount <= state.deadzone) {\n    return 0;\n  }\n  var normalized = (amount - state.deadzone) / (1 - state.deadzone);\n  var softened = normalized * normalized * (3 - (2 * normalized));\n  return (input < 0 ? -1 : 1) * softened;\n};\nif (state.timer) {\n  clearInterval(state.timer);\n  state.timer = null;\n}",
        "onValue": "var state = globalThis.__fisheyeFovStick = globalThis.__fisheyeFovStick || {};\nvar stick = Number(value);\nstate.stick = isFinite(stick) ? state.applyCurve(stick) : 0;",
        "onTouch": "var state = globalThis.__fisheyeFovStick = globalThis.__fisheyeFovStick || {};\nif (value) {\n  if (!state.timer) {\n    state.timer = setInterval(function() {\n      if (!state.stick) {\n        return;\n      }\n      state.fov = Math.max(state.minFov, Math.min(state.maxFov, state.fov - (state.stick * state.stepFov)));\n      send(state.target, state.address, {type: 'f', value: state.fov});\n    }, state.tickMs);\n  }\n} else {\n  state.stick = 0;\n  if (state.timer) {\n    clearInterval(state.timer);\n    state.timer = null;\n  }\n}"
      }
    ],
    "tabs": []
  }
}
