From c3c9fa4183c3eeb2f8126cf5d3ed8dde10cbab16 Mon Sep 17 00:00:00 2001 From: Felix Edelmann Date: Thu, 6 Jun 2019 17:11:55 +0200 Subject: [PATCH] Beam position (#922) * Add BeamPosition type to schema, docs, model and editor * Bump schema version to 12.1.0 * Update capability type order * Fix Laser fixtures, also by using BeamPosition * Make test fixtures --- docs/capability-types.md | 27 +- docs/model-api.md | 12 + fixtures/glp/impression-laser.json | 18 +- fixtures/jb-systems/twin-effect-laser.json | 55 +-- fixtures/laserworld/cs-1000rgb.json | 12 +- fixtures/laserworld/ds-1000rgb.json | 339 ++++++++++++++--- fixtures/sun-star/g-2011-nova.json | 20 +- lib/model/Capability.mjs | 40 +- lib/model/CoarseChannel.mjs | 4 +- lib/model/Entity.mjs | 5 + plugins/ecue/import.js | 3 +- plugins/plugins.json | 2 +- schemas/capability.json | 101 +++-- schemas/definitions.json | 14 + schemas/fixture-redirect.json | 2 +- schemas/fixture.json | 2 +- schemas/manufacturers.json | 2 +- tests/test-fixtures.json | 27 +- tests/test-fixtures.md | 355 +++++++++--------- .../editor-capabilities/BeamPosition.vue | 91 +++++ ui/components/editor-capability-type-data.vue | 8 +- ...-proportional-capability-data-switcher.vue | 4 + 22 files changed, 807 insertions(+), 336 deletions(-) create mode 100644 ui/components/editor-capabilities/BeamPosition.vue diff --git a/docs/capability-types.md b/docs/capability-types.md index caac6faa5f..6307ce33ac 100644 --- a/docs/capability-types.md +++ b/docs/capability-types.md @@ -18,6 +18,8 @@ To make common percentage values more readable, one can use specific keywords to | FogOutput | `m^3/min`, `%` | – | – | off | weak | strong | RotationAngle | `deg`, `%` | – | – | – | – | – | BeamAngle | `deg`, `%` | – | – | closed | narrow | wide +| HorizontalAngle | `deg`, `%` | left | – | center | – | right +| VerticalAngle | `deg`, `%` | top | – | center | – | bottom | SwingAngle | `deg`, `%` | – | – | off | narrow | wide | Parameter | (no unit), `%` | – | – | off / instant | low / slow / small / short | high / fast / big / long | SlotNumber | (no unit) | – | – | – | – | – @@ -42,6 +44,7 @@ To make common percentage values more readable, one can use specific keywords to * [WheelSlot](#wheelslot) / [WheelShake](#wheelshake) / [WheelSlotRotation](#wheelslotrotation) / [WheelRotation](#wheelrotation) * [Effect](#effect) / [EffectSpeed](#effectspeed) / [EffectDuration](#effectduration) / [EffectParameter](#effectparameter) * [SoundSensitivity](#soundsensitivity) +* [BeamAngle](#beamangle) / [BeamPosition](#beamposition) * [Focus](#focus) * [Zoom](#zoom) * [Iris](#iris) / [IrisEffect](#iriseffect) @@ -50,7 +53,7 @@ To make common percentage values more readable, one can use specific keywords to * [BladeInsertion](#bladeinsertion) / [BladeRotation](#bladerotation) / [BladeSystemRotation](#bladesystemrotation) * [Fog](#fog) / [FogOutput](#fogoutput) / [FogType](#fogtype) -* Generic types: [BeamAngle](#beamangle) / [Rotation](#rotation) / [Speed](#speed) / [Time](#time) / [Maintenance](#maintenance) / [Generic](#generic) +* Generic types: [Rotation](#rotation) / [Speed](#speed) / [Time](#time) / [Maintenance](#maintenance) / [Generic](#generic) @@ -276,6 +279,22 @@ To make common percentage values more readable, one can use specific keywords to + + + + + + + + + + + + + + + + @@ -417,12 +436,6 @@ To make common percentage values more readable, one can use specific keywords to - - - - - - diff --git a/docs/model-api.md b/docs/model-api.md index 13f01c4e3c..b1024c0862 100644 --- a/docs/model-api.md +++ b/docs/model-api.md @@ -192,6 +192,8 @@ A capability represents a range of a channel. * [.slotNumber](#Capability+slotNumber) ⇒ [array.<Entity>](#Entity) \| null * [.wheelSlot](#Capability+wheelSlot) ⇒ [array.<WheelSlot>](#WheelSlot) \| null * [.angle](#Capability+angle) ⇒ [array.<Entity>](#Entity) \| null + * [.horizontalAngle](#Capability+horizontalAngle) ⇒ [array.<Entity>](#Entity) \| null + * [.verticalAngle](#Capability+verticalAngle) ⇒ [array.<Entity>](#Entity) \| null * [.colorTemperature](#Capability+colorTemperature) ⇒ [array.<Entity>](#Entity) \| null * [.soundSensitivity](#Capability+soundSensitivity) ⇒ [array.<Entity>](#Entity) \| null * [.shakeAngle](#Capability+shakeAngle) ⇒ [array.<Entity>](#Entity) \| null @@ -398,6 +400,16 @@ Use only in `WheelShake` capabilities! ### capability.angle ⇒ [array.<Entity>](#Entity) \| null **Kind**: instance property of [Capability](#Capability) **Returns**: [array.<Entity>](#Entity) \| null - Start and end angle values. Defaults to null. + + +### capability.horizontalAngle ⇒ [array.<Entity>](#Entity) \| null +**Kind**: instance property of [Capability](#Capability) +**Returns**: [array.<Entity>](#Entity) \| null - Start and end horizontal angle values. Defaults to null. + + +### capability.verticalAngle ⇒ [array.<Entity>](#Entity) \| null +**Kind**: instance property of [Capability](#Capability) +**Returns**: [array.<Entity>](#Entity) \| null - Start and end vertical angle values. Defaults to null. ### capability.colorTemperature ⇒ [array.<Entity>](#Entity) \| null diff --git a/fixtures/glp/impression-laser.json b/fixtures/glp/impression-laser.json index 5bb1363a4d..e9d80786b4 100644 --- a/fixtures/glp/impression-laser.json +++ b/fixtures/glp/impression-laser.json @@ -423,8 +423,7 @@ "capability": { "type": "BeamAngle", "angleStart": "0deg", - "angleEnd": "40deg", - "helpWanted": "Is this the correct direction?" + "angleEnd": "40deg" } }, "Y Size": { @@ -432,8 +431,7 @@ "capability": { "type": "BeamAngle", "angleStart": "0deg", - "angleEnd": "40deg", - "helpWanted": "Is this the correct direction?" + "angleEnd": "40deg" } }, "Rotation": { @@ -446,17 +444,17 @@ "X Position": { "defaultValue": 128, "capability": { - "type": "Pan", - "angleStart": "0deg", - "angleEnd": "40deg" + "type": "BeamPosition", + "horizontalAngleStart": "0deg", + "horizontalAngleEnd": "40deg" } }, "Y Position": { "defaultValue": 128, "capability": { - "type": "Tilt", - "angleStart": "0deg", - "angleEnd": "40deg" + "type": "BeamPosition", + "verticalAngleStart": "0deg", + "verticalAngleEnd": "40deg" } }, "Visible Points": { diff --git a/fixtures/jb-systems/twin-effect-laser.json b/fixtures/jb-systems/twin-effect-laser.json index 407fbe90bf..c65ad5f602 100644 --- a/fixtures/jb-systems/twin-effect-laser.json +++ b/fixtures/jb-systems/twin-effect-laser.json @@ -420,10 +420,9 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "Rotation", - "angleStart": "0%", - "angleEnd": "100%", - "comment": "128 different fixed positions on X-axis" + "type": "BeamPosition", + "horizontalAngleStart": "0%", + "horizontalAngleEnd": "100%" }, { "dmxRange": [128, 191], @@ -443,10 +442,9 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "Rotation", - "angleStart": "0%", - "angleEnd": "100%", - "comment": "128 different fixed positions on Y-axis" + "type": "BeamPosition", + "verticalAngleStart": "0%", + "verticalAngleEnd": "100%" }, { "dmxRange": [128, 191], @@ -466,18 +464,19 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "Effect", - "effectName": "0º to 359º fixed positions around X axis" + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "359deg" }, { "dmxRange": [128, 191], - "type": "Effect", - "effectName": "CW rolling around X axis" + "type": "Rotation", + "speed": "fast CW" }, { "dmxRange": [192, 255], - "type": "Effect", - "effectName": "CCW rolling around X axis" + "type": "Rotation", + "speed": "fast CCW" } ] }, @@ -485,18 +484,19 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "Effect", - "effectName": "0º to 359º fixed positions around Y axis" + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "359deg" }, { "dmxRange": [128, 191], - "type": "Effect", - "effectName": "CW rolling around Y axis" + "type": "Rotation", + "speed": "fast CW" }, { "dmxRange": [192, 255], - "type": "Effect", - "effectName": "CCW rolling around Y axis" + "type": "Rotation", + "speed": "fast CCW" } ] }, @@ -504,18 +504,19 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "Effect", - "effectName": "0º to 359º fixed positions around Z axis" + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "359deg" }, { "dmxRange": [128, 191], - "type": "Effect", - "effectName": "CW rolling around Z axis" + "type": "Rotation", + "speed": "fast CW" }, { "dmxRange": [192, 255], - "type": "Effect", - "effectName": "CCW rolling around Z axis" + "type": "Rotation", + "speed": "fast CCW" } ] }, @@ -705,7 +706,7 @@ "capabilities": [ { "dmxRange": [0, 127], - "type": "BeamAngle", + "type": "Zoom", "angleStart": "wide", "angleEnd": "narrow", "comment": "Pattern size" diff --git a/fixtures/laserworld/cs-1000rgb.json b/fixtures/laserworld/cs-1000rgb.json index 5ffcf890a2..e2fbbe53eb 100644 --- a/fixtures/laserworld/cs-1000rgb.json +++ b/fixtures/laserworld/cs-1000rgb.json @@ -49,17 +49,17 @@ "Horizontal Movement": { "defaultValue": "50%", "capability": { - "type": "Pan", - "angleStart": "0deg", - "angleEnd": "40deg" + "type": "BeamPosition", + "horizontalAngleStart": "0deg", + "horizontalAngleEnd": "40deg" } }, "Vertical Movement": { "defaultValue": "50%", "capability": { - "type": "Tilt", - "angleStart": "0deg", - "angleEnd": "40deg" + "type": "BeamPosition", + "verticalAngleStart": "0deg", + "verticalAngleEnd": "40deg" } }, "Manual Zoom": { diff --git a/fixtures/laserworld/ds-1000rgb.json b/fixtures/laserworld/ds-1000rgb.json index a657cd3ab7..f41f7004b0 100644 --- a/fixtures/laserworld/ds-1000rgb.json +++ b/fixtures/laserworld/ds-1000rgb.json @@ -9,7 +9,7 @@ }, "links": { "manual": [ - "https://www.laserworld.com/en/support/downloads/download/83-laserworld-diode-series/1765-laserworld-manual-diode-series-ds-1000rgb-2018-04.html" + "https://www.laserworld.com/en/support/downloads/download/83-laserworld-diode-series/1764-laserworld-manual-diode-series-2018-04.html" ], "productPage": [ "https://www.laserworld.com/shop/laserworld-lasers/diode-series/laserworld-ds-1000rgb-show-laser-light" @@ -34,80 +34,293 @@ }, { "dmxRange": [64, 127], - "type": "Maintenance", - "comment": "Sound Mode" + "type": "Effect", + "effectName": "Sound mode", + "soundControlled": true }, { - "dmxRange": [128, 191], - "type": "Maintenance", - "comment": "Auto Mode" + "dmxRange": [128, 159], + "type": "Effect", + "effectName": "Auto mode (beam patterns)" + }, + { + "dmxRange": [160, 191], + "type": "Effect", + "effectName": "Auto mode (graphics)" }, { "dmxRange": [192, 255], - "type": "Maintenance", + "type": "NoFunction", "comment": "DMX Mode" } ] }, "Pattern Selection": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 87], + "type": "Effect", + "effectName": "Graphics patterns" + }, + { + "dmxRange": [88, 253], + "type": "Effect", + "effectName": "Beam patterns" + }, + { + "dmxRange": [254, 255], + "type": "Maintenance", + "comment": "Laser Off" + } + ] }, "Strobe Effect": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 0], + "type": "NoFunction" + }, + { + "dmxRange": [1, 255], + "type": "ShutterStrobe", + "shutterEffect": "Strobe", + "speedStart": "fast", + "speedEnd": "slow" + } + ] }, "Horizontal Movement": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 0], + "type": "BeamPosition", + "horizontalAngle": "center" + }, + { + "dmxRange": [1, 167], + "type": "BeamPosition", + "horizontalAngleStart": "left", + "horizontalAngleEnd": "right" + }, + { + "dmxRange": [168, 188], + "type": "Effect", + "effectName": "Movement rightwards", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [189, 209], + "type": "Effect", + "effectName": "Movement leftwards", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [210, 254], + "type": "Effect", + "effectName": "Movement rightwards/leftwards alternating", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [255, 255], + "type": "BeamPosition", + "horizontalAngle": "center" + } + ] }, "Vertical Movement": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 0], + "type": "BeamPosition", + "verticalAngle": "center" + }, + { + "dmxRange": [1, 167], + "type": "BeamPosition", + "verticalAngleStart": "top", + "verticalAngleEnd": "bottom" + }, + { + "dmxRange": [168, 188], + "type": "Effect", + "effectName": "Movement downwards", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [189, 209], + "type": "Effect", + "effectName": "Movement upwards", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [210, 254], + "type": "Effect", + "effectName": "Movement downwards/upwards alternating", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [255, 255], + "type": "BeamPosition", + "verticalAngle": "center" + } + ] }, "Zoom": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 0], + "type": "NoFunction" + }, + { + "dmxRange": [1, 167], + "type": "Zoom", + "angleStart": "narrow", + "angleEnd": "wide" + }, + { + "dmxRange": [168, 188], + "type": "Effect", + "effectName": "Increasing angle", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [189, 209], + "type": "Effect", + "effectName": "Decreasing angle", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [210, 254], + "type": "Effect", + "effectName": "Alternate decreasing/increasing angle", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [255, 255], + "type": "Effect", + "effectName": "Opposite zoom of X- and Y-axis" + } + ] }, "Rotation Y-axis": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 150], + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "360deg", + "helpWanted": "Correct angle?" + }, + { + "dmxRange": [151, 255], + "type": "Rotation", + "speedStart": "slow CW", + "speedEnd": "fast CW" + } + ] }, "Rotation X-axis": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 150], + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "360deg", + "helpWanted": "Correct angle?" + }, + { + "dmxRange": [151, 255], + "type": "Rotation", + "speedStart": "slow CW", + "speedEnd": "fast CW" + } + ] }, - "Circular Movement": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "Rotation Z-axis": { + "capabilities": [ + { + "dmxRange": [0, 180], + "type": "Rotation", + "angleStart": "0deg", + "angleEnd": "360deg", + "helpWanted": "Correct angle?" + }, + { + "dmxRange": [181, 217], + "type": "Rotation", + "speedStart": "slow CW", + "speedEnd": "fast CW" + }, + { + "dmxRange": [218, 255], + "type": "Rotation", + "speedStart": "slow CCW", + "speedEnd": "fast CCW" + } + ] }, - "Dot Effect": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "Blanking": { + "capabilities": [ + { + "dmxRange": [0, 70], + "type": "NoFunction" + }, + { + "dmxRange": [71, 139], + "type": "Effect", + "effectName": "Dot visibility", + "speedStart": "fast", + "speedEnd": "slow" + }, + { + "dmxRange": [140, 209], + "type": "Effect", + "effectName": "Dashed Lines" + }, + { + "dmxRange": [210, 255], + "type": "Effect", + "effectName": "Point selection" + } + ] }, "Wave Movement": { - "capability": { - "type": "Generic", - "helpWanted": "What are the capabilities of this channel?" - } + "capabilities": [ + { + "dmxRange": [0, 0], + "type": "NoFunction" + }, + { + "dmxRange": [1, 127], + "type": "Effect", + "effectName": "Wave positioning", + "parameterStart": "0%", + "parameterEnd": "100%" + }, + { + "dmxRange": [128, 191], + "type": "Effect", + "effectName": "Wave movement", + "speedStart": "slow", + "speedEnd": "fast" + }, + { + "dmxRange": [192, 255], + "type": "Effect", + "effectName": "Wave movement", + "speedStart": "slow reverse", + "speedEnd": "fast reverse" + } + ] }, "Color Selection": { "capabilities": [ @@ -148,20 +361,34 @@ "comment": "Magenta" }, { - "dmxRange": [120, 139], + "dmxRange": [120, 138], "type": "ColorPreset", "colors": ["#00ffff"], "comment": "Cyan" }, { - "dmxRange": [140, 248], + "dmxRange": [139, 164], + "type": "ColorPreset", + "comment": "Multi-color" + }, + { + "dmxRange": [165, 248], "type": "Effect", - "effectName": "Color Stipple" + "effectPreset": "ColorJump", + "speedStart": "fast", + "speedEnd": "slow" }, { - "dmxRange": [249, 255], + "dmxRange": [249, 254], "type": "Effect", - "effectName": "Color Animation" + "effectName": "Changing multi-color", + "speedStart": "fast", + "speedEnd": "slow" + }, + { + "dmxRange": [255, 255], + "type": "ColorPreset", + "comment": "Multi-color without red" } ] } @@ -179,8 +406,8 @@ "Zoom", "Rotation Y-axis", "Rotation X-axis", - "Circular Movement", - "Dot Effect", + "Rotation Z-axis", + "Blanking", "Wave Movement", "Color Selection" ] diff --git a/fixtures/sun-star/g-2011-nova.json b/fixtures/sun-star/g-2011-nova.json index 3cd0cb5e05..0b56a1652c 100644 --- a/fixtures/sun-star/g-2011-nova.json +++ b/fixtures/sun-star/g-2011-nova.json @@ -381,22 +381,22 @@ } ] }, - "Pan": { + "Horizontal Position": { "defaultValue": "50%", "precedence": "LTP", "capability": { - "type": "Pan", - "angleStart": "-15.5deg", - "angleEnd": "15.5deg" + "type": "BeamPosition", + "horizontalAngleStart": "-15.5deg", + "horizontalAngleEnd": "15.5deg" } }, - "Tilt": { + "Vertical Position": { "defaultValue": "50%", "precedence": "LTP", "capability": { - "type": "Tilt", - "angleStart": "-15.5deg", - "angleEnd": "15.5deg" + "type": "BeamPosition", + "verticalAngleStart": "-15.5deg", + "verticalAngleEnd": "15.5deg" } }, "Effect Speed": { @@ -423,8 +423,8 @@ "channels": [ "Mode", "Programs", - "Pan", - "Tilt", + "Horizontal Position", + "Vertical Position", "Effect Speed", "Rotation Speed" ] diff --git a/lib/model/Capability.mjs b/lib/model/Capability.mjs index 4835d34b9f..8c304bb195 100644 --- a/lib/model/Capability.mjs +++ b/lib/model/Capability.mjs @@ -3,7 +3,7 @@ import Range from './Range.mjs'; import { scaleDmxRange } from '../scale-dmx-values.mjs'; -const START_END_ENTITIES = [`speed`, `duration`, `time`, `brightness`, `slotNumber`, `angle`, `colorTemperature`, `soundSensitivity`, `shakeAngle`, `shakeSpeed`, `distance`, `openPercent`, `frostIntensity`, `insertion`, `fogOutput`, `parameter`]; +const START_END_ENTITIES = [`speed`, `duration`, `time`, `brightness`, `slotNumber`, `angle`, `horizontalAngle`, `verticalAngle`, `colorTemperature`, `soundSensitivity`, `shakeAngle`, `shakeSpeed`, `distance`, `openPercent`, `frostIntensity`, `insertion`, `fogOutput`, `parameter`]; const namePerType = { NoFunction: cap => cap.comment || `No function`, @@ -137,6 +137,21 @@ const namePerType = { EffectDuration: cap => appendInBrackets(`Effect duration ${startEndToString(cap.duration)}`, cap.comment), EffectParameter: cap => `${cap.comment || `Effect parameter`} ${startEndToString(cap.parameter)}`, SoundSensitivity: cap => appendInBrackets(`Sound sensitivity ${startEndToString(cap.soundSensitivity)}`, cap.comment), + BeamAngle: cap => appendInBrackets(`Beam ${startEndToString(cap.angle, `angle`, true)}`, cap.comment), + BeamPosition: cap => { + if (cap.horizontalAngle && cap.verticalAngle) { + return appendInBrackets(`Beam position (${startEndToString(cap.horizontalAngle)}, ${startEndToString(cap.verticalAngle)})`, cap.comment); + } + + const orientation = cap.horizontalAngle ? `Horizontal` : `Vertical`; + const angleStartEnd = cap[`${orientation.toLowerCase()}Angle`]; + + const hasOrientationKeyword = angleStartEnd.some( + entity => entity.keyword !== null && entity.keyword !== `center` + ); + const prefix = hasOrientationKeyword ? `Beam position` : `${orientation} beam position`; + return appendInBrackets(`${prefix} ${startEndToString(angleStartEnd)}`, cap.comment); + }, Focus: cap => appendInBrackets(`Focus ${startEndToString(cap.distance, `distance`)}`, cap.comment), Zoom: cap => appendInBrackets(`Zoom ${startEndToString(cap.angle, `beam angle`)}`, cap.comment), Iris: cap => appendInBrackets(`Iris ${startEndToString(cap.openPercent, `open`)}`, cap.comment), @@ -189,7 +204,6 @@ const namePerType = { }, FogOutput: cap => appendInBrackets(`Fog output ${startEndToString(cap.fogOutput)}`, cap.comment), FogType: cap => appendInBrackets(`Fog type: ${cap.fogType}`, cap.comment), - BeamAngle: cap => appendInBrackets(`Beam ${startEndToString(cap.angle, `angle`, true)}`, cap.comment), Rotation: cap => { const speedOrAngle = cap.speed !== null ? `speed` : `angle`; return appendInBrackets(`Rotation ${startEndToString(cap[speedOrAngle], speedOrAngle, true)}`, cap.comment); @@ -737,6 +751,28 @@ class Capability { return this._cache.angle; } + /** + * @returns {array.|null} Start and end horizontal angle values. Defaults to null. + */ + get horizontalAngle() { + if (!(`horizontalAngle` in this._cache)) { + this._cache.horizontalAngle = this._getStartEndArray(`horizontalAngle`); + } + + return this._cache.horizontalAngle; + } + + /** + * @returns {array.|null} Start and end vertical angle values. Defaults to null. + */ + get verticalAngle() { + if (!(`verticalAngle` in this._cache)) { + this._cache.verticalAngle = this._getStartEndArray(`verticalAngle`); + } + + return this._cache.verticalAngle; + } + /** * @returns {array.|null} Start and end colorTemperature values. Defaults to null. */ diff --git a/lib/model/CoarseChannel.mjs b/lib/model/CoarseChannel.mjs index 158196aaa1..e629eed0bd 100644 --- a/lib/model/CoarseChannel.mjs +++ b/lib/model/CoarseChannel.mjs @@ -36,9 +36,9 @@ const channelTypeConstraints = { }, 'Shutter': [`ShutterStrobe`, `BladeInsertion`, `BladeRotation`, `BladeSystemRotation`], 'Fog': [`Fog`, `FogOutput`, `FogType`], - 'Speed': [`StrobeSpeed`, `StrobeDuration`, `PanTiltSpeed`, `EffectSpeed`, `EffectDuration`, `PrismRotation`, `Rotation`, `Speed`, `Time`, `WheelSlotRotation`, `WheelRotation`, `WheelShake`], + 'Speed': [`StrobeSpeed`, `StrobeDuration`, `PanTiltSpeed`, `EffectSpeed`, `EffectDuration`, `BeamAngle`, `BeamPosition`, `PrismRotation`, `Rotation`, `Speed`, `Time`, `WheelSlotRotation`, `WheelRotation`, `WheelShake`], 'Maintenance': [`Maintenance`], - 'Intensity': [`Intensity`, `BeamAngle`, `Generic`], + 'Intensity': [`Intensity`, `Generic`], 'NoFunction': [`NoFunction`] }; diff --git a/lib/model/Entity.mjs b/lib/model/Entity.mjs index 44aa3f259d..99eb557f4d 100644 --- a/lib/model/Entity.mjs +++ b/lib/model/Entity.mjs @@ -23,6 +23,11 @@ const KEYWORDS = { 'CTB': 100, 'weak': 1, 'strong': 100, + 'left': -100, + 'top': -100, + 'center': 0, + 'right': 100, + 'bottom': 100, 'closed': 0, 'narrow': 1, 'wide': 100, diff --git a/plugins/ecue/import.js b/plugins/ecue/import.js index b205247fd1..2c8542764a 100644 --- a/plugins/ecue/import.js +++ b/plugins/ecue/import.js @@ -447,6 +447,8 @@ function addChannelToFixture(ecueChannel, fixture, warningsArray) { WheelSlotRotation: /\bgobo rot(?:ation)?\b/, WheelRotation: /wheel rot(?:ation)?\b/, WheelSlot: /\bgobo\b/, + BeamAngle: /\bbeam angle\b/, + BeamPosition: /\b(beam|horizontal|vertical) position\b/, Focus: /\bfocus\b/, Zoom: /\bzoom\b/, IrisEffect: /\biris effect\b/, @@ -461,7 +463,6 @@ function addChannelToFixture(ecueChannel, fixture, warningsArray) { FogOutput: /\bfog output\b/, FogType: /\bfog type\b/, Fog: /\bfog\b/, - BeamAngle: /\bbeam angle\b/, Rotation: /\brotation\b/, Speed: /\bspeed\b/, Time: /\btime\b/, diff --git a/plugins/plugins.json b/plugins/plugins.json index bbcbcb76aa..b4ad27db99 100644 --- a/plugins/plugins.json +++ b/plugins/plugins.json @@ -40,7 +40,7 @@ }, "ofl": { "name": "Open Fixture Library JSON", - "exportPluginVersion": "12.0.0", + "exportPluginVersion": "12.1.0", "exportTests": [] }, "op-z": { diff --git a/schemas/capability.json b/schemas/capability.json index e05973686f..7989be296c 100644 --- a/schemas/capability.json +++ b/schemas/capability.json @@ -35,6 +35,8 @@ "EffectDuration", "EffectParameter", "SoundSensitivity", + "BeamAngle", + "BeamPosition", "Focus", "Zoom", "Iris", @@ -49,7 +51,6 @@ "Fog", "FogOutput", "FogType", - "BeamAngle", "Rotation", "Speed", "Time", @@ -905,6 +906,75 @@ "additionalProperties": false } }, + { + "if": { + "properties": { + "type": { "const": "BeamAngle" } + } + }, + "then": { + "properties": { + "dmxRange": {}, + "type": {}, + "angle": { "$ref": "definitions.json#/entities/beamAngle" }, + "angleStart": { "$ref": "definitions.json#/entities/beamAngle" }, + "angleEnd": { "$ref": "definitions.json#/entities/beamAngle" }, + "comment": {}, + "helpWanted": {}, + "menuClick": {}, + "switchChannels": {} + }, + "oneOf": [ + { "required": ["angle"] }, + { "required": ["angleStart"] } + ], + "dependencies": { + "angleStart": ["angleEnd"], + "angleEnd": ["angleStart"] + }, + "additionalProperties": false + } + }, + { + "if": { + "properties": { + "type": { "const": "BeamPosition" } + } + }, + "then": { + "properties": { + "dmxRange": {}, + "type": {}, + "horizontalAngle": { "$ref": "definitions.json#/entities/horizontalAngle" }, + "horizontalAngleStart": { "$ref": "definitions.json#/entities/horizontalAngle" }, + "horizontalAngleEnd": { "$ref": "definitions.json#/entities/horizontalAngle" }, + "verticalAngle": { "$ref": "definitions.json#/entities/verticalAngle" }, + "verticalAngleStart": { "$ref": "definitions.json#/entities/verticalAngle" }, + "verticalAngleEnd": { "$ref": "definitions.json#/entities/verticalAngle" }, + "comment": {}, + "helpWanted": {}, + "menuClick": {}, + "switchChannels": {} + }, + "anyOf": [ + { "oneOf": [ + { "required": ["horizontalAngle"] }, + { "required": ["horizontalAngleStart"] } + ] }, + { "oneOf": [ + { "required": ["verticalAngle"] }, + { "required": ["verticalAngleStart"] } + ] } + ], + "dependencies": { + "horizontalAngleStart": ["horizontalAngleEnd"], + "horizontalAngleEnd": ["horizontalAngleStart"], + "verticalAngleStart": ["verticalAngleEnd"], + "verticalAngleEnd": ["verticalAngleStart"] + }, + "additionalProperties": false + } + }, { "if": { "properties": { @@ -1326,35 +1396,6 @@ "additionalProperties": false } }, - { - "if": { - "properties": { - "type": { "const": "BeamAngle" } - } - }, - "then": { - "properties": { - "dmxRange": {}, - "type": {}, - "angle": { "$ref": "definitions.json#/entities/beamAngle" }, - "angleStart": { "$ref": "definitions.json#/entities/beamAngle" }, - "angleEnd": { "$ref": "definitions.json#/entities/beamAngle" }, - "comment": {}, - "helpWanted": {}, - "menuClick": {}, - "switchChannels": {} - }, - "oneOf": [ - { "required": ["angle"] }, - { "required": ["angleStart"] } - ], - "dependencies": { - "angleStart": ["angleEnd"], - "angleEnd": ["angleStart"] - }, - "additionalProperties": false - } - }, { "if": { "properties": { diff --git a/schemas/definitions.json b/schemas/definitions.json index 62ef4200a3..afa29cfdc4 100644 --- a/schemas/definitions.json +++ b/schemas/definitions.json @@ -198,6 +198,20 @@ { "enum": ["closed", "narrow", "wide"] } ] }, + "horizontalAngle": { + "oneOf": [ + { "$ref": "#/units/degrees" }, + { "$ref": "#/units/percent" }, + { "enum": ["left", "center", "right"] } + ] + }, + "verticalAngle": { + "oneOf": [ + { "$ref": "#/units/degrees" }, + { "$ref": "#/units/percent" }, + { "enum": ["top", "center", "bottom"] } + ] + }, "swingAngle": { "oneOf": [ { "$ref": "#/units/degrees" }, diff --git a/schemas/fixture-redirect.json b/schemas/fixture-redirect.json index 99474e0a25..542f5f8f03 100644 --- a/schemas/fixture-redirect.json +++ b/schemas/fixture-redirect.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/master/schemas/fixture-redirect.json", - "version": "12.0.0", + "version": "12.1.0", "type": "object", "properties": { diff --git a/schemas/fixture.json b/schemas/fixture.json index 08dd826190..a7fea9c621 100644 --- a/schemas/fixture.json +++ b/schemas/fixture.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/master/schemas/fixture.json", - "version": "12.0.0", + "version": "12.1.0", "type": "object", "properties": { diff --git a/schemas/manufacturers.json b/schemas/manufacturers.json index f915c19420..96955588b5 100644 --- a/schemas/manufacturers.json +++ b/schemas/manufacturers.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/master/schemas/manufacturers.json", - "version": "12.0.0", + "version": "12.1.0", "type": "object", "propertyNames": { diff --git a/tests/test-fixtures.json b/tests/test-fixtures.json index c39ff18672..eaf694284f 100644 --- a/tests/test-fixtures.json +++ b/tests/test-fixtures.json @@ -153,6 +153,29 @@ "reused-channels" ] }, + { + "man": "glp", + "key": "impression-laser", + "name": "impression Laser", + "features": [ + "capability-type-NoFunction", + "capability-type-ShutterStrobe", + "capability-type-Intensity", + "capability-type-ColorPreset", + "capability-type-Pan", + "capability-type-Tilt", + "capability-type-Effect", + "capability-type-EffectSpeed", + "capability-type-BeamAngle", + "capability-type-BeamPosition", + "capability-type-Zoom", + "capability-type-Rotation", + "capability-type-Maintenance", + "fine-channel-alias", + "floating-point-weight", + "multiple-categories" + ] + }, { "man": "lixada", "key": "mini-moving-head-rgbw", @@ -193,12 +216,12 @@ "capability-type-WheelSlotRotation", "capability-type-WheelRotation", "capability-type-Effect", + "capability-type-BeamAngle", "capability-type-Focus", "capability-type-Zoom", "capability-type-Frost", "capability-type-Prism", "capability-type-PrismRotation", - "capability-type-BeamAngle", "capability-type-Maintenance", "fine-channel-alias", "floating-point-weight", @@ -355,9 +378,9 @@ "capability-type-ColorIntensity", "capability-type-Tilt", "capability-type-Effect", + "capability-type-BeamAngle", "capability-type-Zoom", "capability-type-BladeRotation", - "capability-type-BeamAngle", "capability-type-Rotation", "capability-type-Maintenance", "duplicate-channel-names", diff --git a/tests/test-fixtures.md b/tests/test-fixtures.md index 12c7754316..25046003cb 100644 --- a/tests/test-fixtures.md +++ b/tests/test-fixtures.md @@ -9,119 +9,121 @@ generated by [`cli/make-test-fixtures.js`](../cli/make-test-fixtures.js). 4. [*cameo* Hydrabeam 300 RGBW](../fixtures/cameo/hydrabeam-300-rgbw.json) 5. [*Chauvet DJ* SlimPAR Pro H USB](../fixtures/chauvet-dj/slimpar-pro-h-usb.json) 6. [*Generic* Pan/Tilt Fader](../fixtures/generic/pan-tilt.json) -7. [*Lixada* Mini Moving Head RGBW](../fixtures/lixada/mini-moving-head-rgbw.json) -8. [*Martin* MAC Axiom Hybrid](../fixtures/martin/mac-axiom-hybrid.json) -9. [*Martin* MAC Encore Performance](../fixtures/martin/mac-encore-performance.json) -10. [*Martin* MAC Viper AirFX](../fixtures/martin/mac-viper-airfx.json) -11. [*Martin* Mania SCX500](../fixtures/martin/mania-scx500.json) -12. [*MDG* theONE Atmospheric Generator](../fixtures/mdg/theone-atmospheric-generator.json) -13. [*Minuit Une* M-Carré](../fixtures/minuit-une/m-carre.json) -14. [*Prolights* DIAMOND19](../fixtures/prolights/diamond19.json) -15. [*Robe* ROBIN Viva CMY](../fixtures/robe/robin-viva-cmy.json) -16. [*TMB* Solaris Flare](../fixtures/tmb/solaris-flare.json) +7. [*GLP* impression Laser](../fixtures/glp/impression-laser.json) +8. [*Lixada* Mini Moving Head RGBW](../fixtures/lixada/mini-moving-head-rgbw.json) +9. [*Martin* MAC Axiom Hybrid](../fixtures/martin/mac-axiom-hybrid.json) +10. [*Martin* MAC Encore Performance](../fixtures/martin/mac-encore-performance.json) +11. [*Martin* MAC Viper AirFX](../fixtures/martin/mac-viper-airfx.json) +12. [*Martin* Mania SCX500](../fixtures/martin/mania-scx500.json) +13. [*MDG* theONE Atmospheric Generator](../fixtures/mdg/theone-atmospheric-generator.json) +14. [*Minuit Une* M-Carré](../fixtures/minuit-une/m-carre.json) +15. [*Prolights* DIAMOND19](../fixtures/prolights/diamond19.json) +16. [*Robe* ROBIN Viva CMY](../fixtures/robe/robin-viva-cmy.json) +17. [*TMB* Solaris Flare](../fixtures/tmb/solaris-flare.json) -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|- -**Capability type NoFunction** [[1]](#user-content-footnote-1) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ -**Capability type ShutterStrobe** [[2]](#user-content-footnote-2) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ -**Capability type StrobeSpeed** [[3]](#user-content-footnote-3) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ -**Capability type StrobeDuration** [[4]](#user-content-footnote-4) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ -**Capability type Intensity** [[5]](#user-content-footnote-5) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ -**Capability type ColorIntensity** [[6]](#user-content-footnote-6) | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ -**Capability type ColorPreset** [[7]](#user-content-footnote-7) | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ -**Capability type ColorTemperature** [[8]](#user-content-footnote-8) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ -**Capability type Pan** [[9]](#user-content-footnote-9) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ -**Capability type PanContinuous** [[10]](#user-content-footnote-10) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type Tilt** [[11]](#user-content-footnote-11) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ -**Capability type TiltContinuous** [[12]](#user-content-footnote-12) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type PanTiltSpeed** [[13]](#user-content-footnote-13) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ -**Capability type WheelSlot** [[14]](#user-content-footnote-14) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type WheelShake** [[15]](#user-content-footnote-15) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Capability type WheelSlotRotation** [[16]](#user-content-footnote-16) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type WheelRotation** [[17]](#user-content-footnote-17) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type Effect** [[18]](#user-content-footnote-18) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ -**Capability type EffectSpeed** [[19]](#user-content-footnote-19) | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ -**Capability type EffectDuration** [[20]](#user-content-footnote-20) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type EffectParameter** [[21]](#user-content-footnote-21) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type SoundSensitivity** [[22]](#user-content-footnote-22) | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type Focus** [[23]](#user-content-footnote-23) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type Zoom** [[24]](#user-content-footnote-24) | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ -**Capability type Iris** [[25]](#user-content-footnote-25) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type IrisEffect** [[26]](#user-content-footnote-26) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type Frost** [[27]](#user-content-footnote-27) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type FrostEffect** [[28]](#user-content-footnote-28) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type Prism** [[29]](#user-content-footnote-29) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type PrismRotation** [[30]](#user-content-footnote-30) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Capability type BladeInsertion** [[31]](#user-content-footnote-31) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type BladeRotation** [[32]](#user-content-footnote-32) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**Capability type BladeSystemRotation** [[33]](#user-content-footnote-33) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type Fog** [[34]](#user-content-footnote-34) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ -**Capability type FogOutput** [[35]](#user-content-footnote-35) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ -**Capability type FogType** [[36]](#user-content-footnote-36) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ -**Capability type BeamAngle** [[37]](#user-content-footnote-37) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**Capability type Rotation** [[38]](#user-content-footnote-38) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ -**Capability type Speed** [[39]](#user-content-footnote-39) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ -**Capability type Time** [[40]](#user-content-footnote-40) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Capability type Maintenance** [[41]](#user-content-footnote-41) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ -**Capability type Generic** [[42]](#user-content-footnote-42) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ -**Duplicate channel names** | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ -**Fine channels (16bit)** [[43]](#user-content-footnote-43) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ -**Fine channels (>16bit)** [[44]](#user-content-footnote-44) | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Fine channel capabilities** [[45]](#user-content-footnote-45) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Fine before coarse** [[46]](#user-content-footnote-46) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Fine not-adjacent after coarse** [[47]](#user-content-footnote-47) | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Floating point dimensions** [[48]](#user-content-footnote-48) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**Floating point weight** | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ -**Floating point power** | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Floating point color temperature** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Floating point lumens** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Floating point lens degrees** | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Many modes** [[49]](#user-content-footnote-49) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ -**Uses pixelKeys** [[50]](#user-content-footnote-50) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ -**Uses pixelCount** [[51]](#user-content-footnote-51) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ -**Uses pixelGroups** [[52]](#user-content-footnote-52) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ -**Uses pixelGroup number constraints** [[53]](#user-content-footnote-53) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ -**Uses pixelGroup string constraints** [[54]](#user-content-footnote-54) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Custom matrix layout** [[55]](#user-content-footnote-55) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ -**Fine matrix channel** [[56]](#user-content-footnote-56) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Switching matrix channel** [[57]](#user-content-footnote-57) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Matrix channel overridden** [[58]](#user-content-footnote-58) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Matrix channel used directly** [[59]](#user-content-footnote-59) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ -**Multiple categories** | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ -**Multiple Focuses** [[60]](#user-content-footnote-60) | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**No physical** | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**`null` channels** [[61]](#user-content-footnote-61) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**Physical override** [[62]](#user-content-footnote-62) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**RDM** [[63]](#user-content-footnote-63) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ -**Fixture redirect reason FixtureRenamed** [[64]](#user-content-footnote-64) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ -**Fixture redirect reason SameAsDifferentBrand** [[65]](#user-content-footnote-65) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Reused channels** [[66]](#user-content-footnote-66) | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ -**Switching channels** [[67]](#user-content-footnote-67) | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Switches fine channels** [[68]](#user-content-footnote-68) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ -**Switching channel at different positions** [[69]](#user-content-footnote-69) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ -**Wheel type Open** [[70]](#user-content-footnote-70) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel type Closed** [[71]](#user-content-footnote-71) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel type Color** [[72]](#user-content-footnote-72) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Wheel type Gobo** [[73]](#user-content-footnote-73) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Wheel type Prism** [[74]](#user-content-footnote-74) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel type Iris** [[75]](#user-content-footnote-75) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel type Frost** [[76]](#user-content-footnote-76) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel type AnimationGobo** [[77]](#user-content-footnote-77) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel slot type Open** [[78]](#user-content-footnote-78) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Wheel slot type Closed** [[79]](#user-content-footnote-79) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel slot type Color** [[80]](#user-content-footnote-80) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Wheel slot type Gobo** [[81]](#user-content-footnote-81) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ -**Wheel slot type Prism** [[82]](#user-content-footnote-82) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 -**Wheel slot type Iris** [[83]](#user-content-footnote-83) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel slot type Frost** [[84]](#user-content-footnote-84) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel slot type AnimationGoboStart** [[85]](#user-content-footnote-85) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ -**Wheel slot type AnimationGoboEnd** [[86]](#user-content-footnote-86) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|- +**Capability type NoFunction** [[1]](#user-content-footnote-1) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ +**Capability type ShutterStrobe** [[2]](#user-content-footnote-2) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ +**Capability type StrobeSpeed** [[3]](#user-content-footnote-3) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ +**Capability type StrobeDuration** [[4]](#user-content-footnote-4) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ +**Capability type Intensity** [[5]](#user-content-footnote-5) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ +**Capability type ColorIntensity** [[6]](#user-content-footnote-6) | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ +**Capability type ColorPreset** [[7]](#user-content-footnote-7) | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ +**Capability type ColorTemperature** [[8]](#user-content-footnote-8) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ +**Capability type Pan** [[9]](#user-content-footnote-9) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ +**Capability type PanContinuous** [[10]](#user-content-footnote-10) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type Tilt** [[11]](#user-content-footnote-11) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ +**Capability type TiltContinuous** [[12]](#user-content-footnote-12) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type PanTiltSpeed** [[13]](#user-content-footnote-13) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ +**Capability type WheelSlot** [[14]](#user-content-footnote-14) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type WheelShake** [[15]](#user-content-footnote-15) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Capability type WheelSlotRotation** [[16]](#user-content-footnote-16) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type WheelRotation** [[17]](#user-content-footnote-17) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type Effect** [[18]](#user-content-footnote-18) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ +**Capability type EffectSpeed** [[19]](#user-content-footnote-19) | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ +**Capability type EffectDuration** [[20]](#user-content-footnote-20) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type EffectParameter** [[21]](#user-content-footnote-21) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type SoundSensitivity** [[22]](#user-content-footnote-22) | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type BeamAngle** [[23]](#user-content-footnote-23) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**Capability type BeamPosition** [[24]](#user-content-footnote-24) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type Focus** [[25]](#user-content-footnote-25) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type Zoom** [[26]](#user-content-footnote-26) | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ +**Capability type Iris** [[27]](#user-content-footnote-27) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type IrisEffect** [[28]](#user-content-footnote-28) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type Frost** [[29]](#user-content-footnote-29) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type FrostEffect** [[30]](#user-content-footnote-30) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Capability type Prism** [[31]](#user-content-footnote-31) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type PrismRotation** [[32]](#user-content-footnote-32) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type BladeInsertion** [[33]](#user-content-footnote-33) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type BladeRotation** [[34]](#user-content-footnote-34) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**Capability type BladeSystemRotation** [[35]](#user-content-footnote-35) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type Fog** [[36]](#user-content-footnote-36) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ +**Capability type FogOutput** [[37]](#user-content-footnote-37) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ +**Capability type FogType** [[38]](#user-content-footnote-38) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ +**Capability type Rotation** [[39]](#user-content-footnote-39) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ +**Capability type Speed** [[40]](#user-content-footnote-40) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ +**Capability type Time** [[41]](#user-content-footnote-41) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Capability type Maintenance** [[42]](#user-content-footnote-42) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ +**Capability type Generic** [[43]](#user-content-footnote-43) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ +**Duplicate channel names** | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ +**Fine channels (16bit)** [[44]](#user-content-footnote-44) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Fine channels (>16bit)** [[45]](#user-content-footnote-45) | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Fine channel capabilities** [[46]](#user-content-footnote-46) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Fine before coarse** [[47]](#user-content-footnote-47) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Fine not-adjacent after coarse** [[48]](#user-content-footnote-48) | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Floating point dimensions** [[49]](#user-content-footnote-49) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**Floating point weight** | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ +**Floating point power** | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Floating point color temperature** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Floating point lumens** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Floating point lens degrees** | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Many modes** [[50]](#user-content-footnote-50) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ +**Uses pixelKeys** [[51]](#user-content-footnote-51) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ +**Uses pixelCount** [[52]](#user-content-footnote-52) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ +**Uses pixelGroups** [[53]](#user-content-footnote-53) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ +**Uses pixelGroup number constraints** [[54]](#user-content-footnote-54) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Uses pixelGroup string constraints** [[55]](#user-content-footnote-55) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ +**Custom matrix layout** [[56]](#user-content-footnote-56) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ +**Fine matrix channel** [[57]](#user-content-footnote-57) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Switching matrix channel** [[58]](#user-content-footnote-58) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Matrix channel overridden** [[59]](#user-content-footnote-59) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Matrix channel used directly** [[60]](#user-content-footnote-60) | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ +**Multiple categories** | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ +**Multiple Focuses** [[61]](#user-content-footnote-61) | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**No physical** | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**`null` channels** [[62]](#user-content-footnote-62) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**Physical override** [[63]](#user-content-footnote-63) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**RDM** [[64]](#user-content-footnote-64) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ +**Fixture redirect reason FixtureRenamed** [[65]](#user-content-footnote-65) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ +**Fixture redirect reason SameAsDifferentBrand** [[66]](#user-content-footnote-66) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Reused channels** [[67]](#user-content-footnote-67) | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Switching channels** [[68]](#user-content-footnote-68) | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ +**Switches fine channels** [[69]](#user-content-footnote-69) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ +**Switching channel at different positions** [[70]](#user-content-footnote-70) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ +**Wheel type Open** [[71]](#user-content-footnote-71) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel type Closed** [[72]](#user-content-footnote-72) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel type Color** [[73]](#user-content-footnote-73) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Wheel type Gobo** [[74]](#user-content-footnote-74) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Wheel type Prism** [[75]](#user-content-footnote-75) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel type Iris** [[76]](#user-content-footnote-76) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel type Frost** [[77]](#user-content-footnote-77) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel type AnimationGobo** [[78]](#user-content-footnote-78) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type Open** [[79]](#user-content-footnote-79) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Wheel slot type Closed** [[80]](#user-content-footnote-80) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type Color** [[81]](#user-content-footnote-81) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +**Wheel slot type Gobo** [[82]](#user-content-footnote-82) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ +*Fixture number* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 +**Wheel slot type Prism** [[83]](#user-content-footnote-83) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type Iris** [[84]](#user-content-footnote-84) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type Frost** [[85]](#user-content-footnote-85) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type AnimationGoboStart** [[86]](#user-content-footnote-86) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ +**Wheel slot type AnimationGoboEnd** [[87]](#user-content-footnote-87) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ ## Footnotes @@ -147,67 +149,68 @@ generated by [`cli/make-test-fixtures.js`](../cli/make-test-fixtures.js). **[20]**: Whether the fixture has at least one capability of type 'EffectDuration' **[21]**: Whether the fixture has at least one capability of type 'EffectParameter' **[22]**: Whether the fixture has at least one capability of type 'SoundSensitivity' -**[23]**: Whether the fixture has at least one capability of type 'Focus' -**[24]**: Whether the fixture has at least one capability of type 'Zoom' -**[25]**: Whether the fixture has at least one capability of type 'Iris' -**[26]**: Whether the fixture has at least one capability of type 'IrisEffect' -**[27]**: Whether the fixture has at least one capability of type 'Frost' -**[28]**: Whether the fixture has at least one capability of type 'FrostEffect' -**[29]**: Whether the fixture has at least one capability of type 'Prism' -**[30]**: Whether the fixture has at least one capability of type 'PrismRotation' -**[31]**: Whether the fixture has at least one capability of type 'BladeInsertion' -**[32]**: Whether the fixture has at least one capability of type 'BladeRotation' -**[33]**: Whether the fixture has at least one capability of type 'BladeSystemRotation' -**[34]**: Whether the fixture has at least one capability of type 'Fog' -**[35]**: Whether the fixture has at least one capability of type 'FogOutput' -**[36]**: Whether the fixture has at least one capability of type 'FogType' -**[37]**: Whether the fixture has at least one capability of type 'BeamAngle' -**[38]**: Whether the fixture has at least one capability of type 'Rotation' -**[39]**: Whether the fixture has at least one capability of type 'Speed' -**[40]**: Whether the fixture has at least one capability of type 'Time' -**[41]**: Whether the fixture has at least one capability of type 'Maintenance' -**[42]**: Whether the fixture has at least one capability of type 'Generic' -**[43]**: Whether a channel defines exactly one fine channel alias -**[44]**: Whether a channel defines two or more fine channel aliases -**[45]**: Whether a channel with fine channel aliases has capabilities -**[46]**: Fine channel used in a mode before its coarse channel -**[47]**: Coarse channel with fine channels are not directly after each other -**[48]**: In fixture physical or in a mode's physical override. See [#133](https://github.com/OpenLightingProject/open-fixture-library/issues/133). -**[49]**: True if the fixture has more than 15 modes. -**[50]**: The fixture has a matrix and has set the pixelKeys individually. -**[51]**: The fixture has a matrix and has set the pixelCount property. -**[52]**: The fixture has a matrix and has set pixelGroups. -**[53]**: The fixture has a matrix and has set pixelGroups using number constraint syntax. -**[54]**: The fixture has a matrix and has set pixelGroups using string constraint syntax. -**[55]**: The fixture has a matrix and it uses null pixelKeys – it is no line, rectangle or cube. -**[56]**: The fixture repeats fine channels for matrix pixels. -**[57]**: The fixture repeats switching channels for matrix pixels. -**[58]**: An available channel overrides a specific matrix channel (at a specific pixel). -**[59]**: If a mode contains a resolved matrix channel key in its raw channel list or if a non-matrix switching channel switches to a matrix channel. -**[60]**: True if multiple Pan / Tilt channels are used in some mode. -**[61]**: Channel list of a mode contains null, so it has an unused channel -**[62]**: Whether at least one mode uses the 'physical' property -**[63]**: Whether an RDM model ID is set -**[64]**: Whether the fixture is a fixture redirect with reason 'FixtureRenamed' -**[65]**: Whether the fixture is a fixture redirect with reason 'SameAsDifferentBrand' -**[66]**: Whether there is at least one channel that is used in different modes -**[67]**: Whether at least one channel defines switching channel aliases -**[68]**: Whether at least one switching channel switches fine channels -**[69]**: Whether there is a switching channel that is used at different positions in different modes -**[70]**: Whether the fixture has at least one wheel of type 'Open' -**[71]**: Whether the fixture has at least one wheel of type 'Closed' -**[72]**: Whether the fixture has at least one wheel of type 'Color' -**[73]**: Whether the fixture has at least one wheel of type 'Gobo' -**[74]**: Whether the fixture has at least one wheel of type 'Prism' -**[75]**: Whether the fixture has at least one wheel of type 'Iris' -**[76]**: Whether the fixture has at least one wheel of type 'Frost' -**[77]**: Whether the fixture has at least one wheel of type 'AnimationGobo' -**[78]**: Whether the fixture has at least one wheel slot of type 'Open' -**[79]**: Whether the fixture has at least one wheel slot of type 'Closed' -**[80]**: Whether the fixture has at least one wheel slot of type 'Color' -**[81]**: Whether the fixture has at least one wheel slot of type 'Gobo' -**[82]**: Whether the fixture has at least one wheel slot of type 'Prism' -**[83]**: Whether the fixture has at least one wheel slot of type 'Iris' -**[84]**: Whether the fixture has at least one wheel slot of type 'Frost' -**[85]**: Whether the fixture has at least one wheel slot of type 'AnimationGoboStart' -**[86]**: Whether the fixture has at least one wheel slot of type 'AnimationGoboEnd' +**[23]**: Whether the fixture has at least one capability of type 'BeamAngle' +**[24]**: Whether the fixture has at least one capability of type 'BeamPosition' +**[25]**: Whether the fixture has at least one capability of type 'Focus' +**[26]**: Whether the fixture has at least one capability of type 'Zoom' +**[27]**: Whether the fixture has at least one capability of type 'Iris' +**[28]**: Whether the fixture has at least one capability of type 'IrisEffect' +**[29]**: Whether the fixture has at least one capability of type 'Frost' +**[30]**: Whether the fixture has at least one capability of type 'FrostEffect' +**[31]**: Whether the fixture has at least one capability of type 'Prism' +**[32]**: Whether the fixture has at least one capability of type 'PrismRotation' +**[33]**: Whether the fixture has at least one capability of type 'BladeInsertion' +**[34]**: Whether the fixture has at least one capability of type 'BladeRotation' +**[35]**: Whether the fixture has at least one capability of type 'BladeSystemRotation' +**[36]**: Whether the fixture has at least one capability of type 'Fog' +**[37]**: Whether the fixture has at least one capability of type 'FogOutput' +**[38]**: Whether the fixture has at least one capability of type 'FogType' +**[39]**: Whether the fixture has at least one capability of type 'Rotation' +**[40]**: Whether the fixture has at least one capability of type 'Speed' +**[41]**: Whether the fixture has at least one capability of type 'Time' +**[42]**: Whether the fixture has at least one capability of type 'Maintenance' +**[43]**: Whether the fixture has at least one capability of type 'Generic' +**[44]**: Whether a channel defines exactly one fine channel alias +**[45]**: Whether a channel defines two or more fine channel aliases +**[46]**: Whether a channel with fine channel aliases has capabilities +**[47]**: Fine channel used in a mode before its coarse channel +**[48]**: Coarse channel with fine channels are not directly after each other +**[49]**: In fixture physical or in a mode's physical override. See [#133](https://github.com/OpenLightingProject/open-fixture-library/issues/133). +**[50]**: True if the fixture has more than 15 modes. +**[51]**: The fixture has a matrix and has set the pixelKeys individually. +**[52]**: The fixture has a matrix and has set the pixelCount property. +**[53]**: The fixture has a matrix and has set pixelGroups. +**[54]**: The fixture has a matrix and has set pixelGroups using number constraint syntax. +**[55]**: The fixture has a matrix and has set pixelGroups using string constraint syntax. +**[56]**: The fixture has a matrix and it uses null pixelKeys – it is no line, rectangle or cube. +**[57]**: The fixture repeats fine channels for matrix pixels. +**[58]**: The fixture repeats switching channels for matrix pixels. +**[59]**: An available channel overrides a specific matrix channel (at a specific pixel). +**[60]**: If a mode contains a resolved matrix channel key in its raw channel list or if a non-matrix switching channel switches to a matrix channel. +**[61]**: True if multiple Pan / Tilt channels are used in some mode. +**[62]**: Channel list of a mode contains null, so it has an unused channel +**[63]**: Whether at least one mode uses the 'physical' property +**[64]**: Whether an RDM model ID is set +**[65]**: Whether the fixture is a fixture redirect with reason 'FixtureRenamed' +**[66]**: Whether the fixture is a fixture redirect with reason 'SameAsDifferentBrand' +**[67]**: Whether there is at least one channel that is used in different modes +**[68]**: Whether at least one channel defines switching channel aliases +**[69]**: Whether at least one switching channel switches fine channels +**[70]**: Whether there is a switching channel that is used at different positions in different modes +**[71]**: Whether the fixture has at least one wheel of type 'Open' +**[72]**: Whether the fixture has at least one wheel of type 'Closed' +**[73]**: Whether the fixture has at least one wheel of type 'Color' +**[74]**: Whether the fixture has at least one wheel of type 'Gobo' +**[75]**: Whether the fixture has at least one wheel of type 'Prism' +**[76]**: Whether the fixture has at least one wheel of type 'Iris' +**[77]**: Whether the fixture has at least one wheel of type 'Frost' +**[78]**: Whether the fixture has at least one wheel of type 'AnimationGobo' +**[79]**: Whether the fixture has at least one wheel slot of type 'Open' +**[80]**: Whether the fixture has at least one wheel slot of type 'Closed' +**[81]**: Whether the fixture has at least one wheel slot of type 'Color' +**[82]**: Whether the fixture has at least one wheel slot of type 'Gobo' +**[83]**: Whether the fixture has at least one wheel slot of type 'Prism' +**[84]**: Whether the fixture has at least one wheel slot of type 'Iris' +**[85]**: Whether the fixture has at least one wheel slot of type 'Frost' +**[86]**: Whether the fixture has at least one wheel slot of type 'AnimationGoboStart' +**[87]**: Whether the fixture has at least one wheel slot of type 'AnimationGoboEnd' diff --git a/ui/components/editor-capabilities/BeamPosition.vue b/ui/components/editor-capabilities/BeamPosition.vue new file mode 100644 index 0000000000..779c15561f --- /dev/null +++ b/ui/components/editor-capabilities/BeamPosition.vue @@ -0,0 +1,91 @@ + + + diff --git a/ui/components/editor-capability-type-data.vue b/ui/components/editor-capability-type-data.vue index b49d950a1e..b280ed7836 100644 --- a/ui/components/editor-capability-type-data.vue +++ b/ui/components/editor-capability-type-data.vue @@ -49,16 +49,18 @@ import editorCapabilityPan from '~/components/editor-capabilities/Pan.vue'; import editorCapabilityPanContinuous from '~/components/editor-capabilities/PanContinuous.vue'; import editorCapabilityTilt from '~/components/editor-capabilities/Tilt.vue'; import editorCapabilityTiltContinuous from '~/components/editor-capabilities/TiltContinuous.vue'; +import editorCapabilityPanTiltSpeed from '~/components/editor-capabilities/PanTiltSpeed.vue'; import editorCapabilityWheelSlot from '~/components/editor-capabilities/WheelSlot.vue'; import editorCapabilityWheelShake from '~/components/editor-capabilities/WheelShake.vue'; import editorCapabilityWheelSlotRotation from '~/components/editor-capabilities/WheelSlotRotation.vue'; import editorCapabilityWheelRotation from '~/components/editor-capabilities/WheelRotation.vue'; -import editorCapabilityPanTiltSpeed from '~/components/editor-capabilities/PanTiltSpeed.vue'; import editorCapabilityEffect from '~/components/editor-capabilities/Effect.vue'; import editorCapabilityEffectSpeed from '~/components/editor-capabilities/EffectSpeed.vue'; import editorCapabilityEffectDuration from '~/components/editor-capabilities/EffectDuration.vue'; import editorCapabilityEffectParameter from '~/components/editor-capabilities/EffectParameter.vue'; import editorCapabilitySoundSensitivity from '~/components/editor-capabilities/SoundSensitivity.vue'; +import editorCapabilityBeamAngle from '~/components/editor-capabilities/BeamAngle.vue'; +import editorCapabilityBeamPosition from '~/components/editor-capabilities/BeamPosition.vue'; import editorCapabilityFocus from '~/components/editor-capabilities/Focus.vue'; import editorCapabilityZoom from '~/components/editor-capabilities/Zoom.vue'; import editorCapabilityIris from '~/components/editor-capabilities/Iris.vue'; @@ -73,7 +75,6 @@ import editorCapabilityBladeSystemRotation from '~/components/editor-capabilitie import editorCapabilityFog from '~/components/editor-capabilities/Fog.vue'; import editorCapabilityFogOutput from '~/components/editor-capabilities/FogOutput.vue'; import editorCapabilityFogType from '~/components/editor-capabilities/FogType.vue'; -import editorCapabilityBeamAngle from '~/components/editor-capabilities/BeamAngle.vue'; import editorCapabilityRotation from '~/components/editor-capabilities/Rotation.vue'; import editorCapabilitySpeed from '~/components/editor-capabilities/Speed.vue'; import editorCapabilityTime from '~/components/editor-capabilities/Time.vue'; @@ -105,6 +106,8 @@ export default { 'app-editor-capability-EffectDuration': editorCapabilityEffectDuration, 'app-editor-capability-EffectParameter': editorCapabilityEffectParameter, 'app-editor-capability-SoundSensitivity': editorCapabilitySoundSensitivity, + 'app-editor-capability-BeamAngle': editorCapabilityBeamAngle, + 'app-editor-capability-BeamPosition': editorCapabilityBeamPosition, 'app-editor-capability-Focus': editorCapabilityFocus, 'app-editor-capability-Zoom': editorCapabilityZoom, 'app-editor-capability-Iris': editorCapabilityIris, @@ -119,7 +122,6 @@ export default { 'app-editor-capability-Fog': editorCapabilityFog, 'app-editor-capability-FogOutput': editorCapabilityFogOutput, 'app-editor-capability-FogType': editorCapabilityFogType, - 'app-editor-capability-BeamAngle': editorCapabilityBeamAngle, 'app-editor-capability-Rotation': editorCapabilityRotation, 'app-editor-capability-Speed': editorCapabilitySpeed, 'app-editor-capability-Time': editorCapabilityTime, diff --git a/ui/components/editor-proportional-capability-data-switcher.vue b/ui/components/editor-proportional-capability-data-switcher.vue index c315cd6f15..83f4705569 100644 --- a/ui/components/editor-proportional-capability-data-switcher.vue +++ b/ui/components/editor-proportional-capability-data-switcher.vue @@ -266,6 +266,10 @@ export default { }, hasStartEnd: { get() { + if (this.propertyDataStepped === null && this.propertyDataStart === null) { + throw new Error(`Stepped and start value are both null. At least one of them should have a value, e.g. an empty string.`); + } + return this.propertyDataStepped === null; }, set(shouldHaveStartEnd) {
Entity Percent
BeamAngleangle
:star2: required
Entity BeamAngle
BeamPositionhorizontalAngle
:star2: required
Entity HorizontalAngleat least one of horizontalAngle or verticalAngle is required
verticalAngle
:star2: required
Entity VerticalAngle
EffectSpeed speed
:star2: required
Fog or Haze
BeamAngleangle
:star2: required
Entity BeamAngle
Rotation speed
:vs: required