Skip to content

Commit

Permalink
Support color / gobo / effect wheels (#659)
Browse files Browse the repository at this point in the history
* Support wheels in schema
  - Remove old wheel capability types
  - Add new wheel capability types
  - Add fixture wheel
  - Add wheel slot types
  - Bump schema version to 11.0.0
* Migrate all fixtures
* Support wheels in model
  - Add Wheel and WheelSlot classes, update all the rest
* Update fixture test
  - Update capability types, check wheel references
  - Check that slot numbers are used correctly in capabilities
  - Fixture test: Check that AnimationGoboStart/End slots are adjacent
  - Fixture test: Warn about unused wheels / wheel slots
  - Fixture test: Warn if wheel name does not contain "wheel" or "disk"
  - Fixture test: Warn if a capability selects a slot range greater than 1
* Display wheels in fixture page
* Update import plugins
* Update Millumin and QLC+ 4.12.0 export plugins
* Update fixture editor
  - Pass channel to capability components
  - Update capability type components
  - Add components for each wheel slot type
  - Suggest wheel capabilities
  - Save wheels in backend
* Add wheel fixture features
* Make test fixtures
* Update documentation
  • Loading branch information
FloEdelmann committed Jan 14, 2019
1 parent 9b5028b commit b665703
Show file tree
Hide file tree
Showing 103 changed files with 12,177 additions and 7,518 deletions.
154 changes: 74 additions & 80 deletions docs/capability-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ To make common percentage values more readable, one can use specific keywords to
| BeamAngle | `deg`, `%` | – | – | closed | narrow | wide
| SwingAngle | `deg`, `%` | – | – | off | narrow | wide
| Parameter | (no unit), `%` | – | – | off / instant | low / slow / small / short | high / fast / big / long
| Index | (no unit) | – | – | – | – | –
| SlotNumber | (no unit) | – | – | – | – | –
| Percent | `%` | – | – | off | low | high
| Insertion | `%` | – | – | out | – | in
| IrisPercent | `%` | – | – | closed | – | open
Expand All @@ -35,14 +35,13 @@ To make common percentage values more readable, one can use specific keywords to
* [Intensity](#intensity)
* [ColorIntensity](#colorintensity)
* [ColorPreset](#colorpreset)
* [ColorWheelIndex](#colorwheelindex) / [ColorWheelRotation](#colorwheelrotation)
* [ColorTemperature](#colortemperature)
* [Pan](#pan) / [PanContinuous](#pancontinuous)
* [Tilt](#tilt) / [TiltContinuous](#tiltcontinuous)
* [PanTiltSpeed](#pantiltspeed)
* [WheelSlot](#wheelslot) / [WheelShake](#wheelshake) / [WheelSlotRotation](#wheelslotrotation) / [WheelRotation](#wheelrotation)
* [Effect](#effect) / [EffectSpeed](#effectspeed) / [EffectDuration](#effectduration) / [EffectParameter](#effectparameter)
* [SoundSensitivity](#soundsensitivity)
* [GoboIndex](#goboindex) / [GoboShake](#goboshake) / [GoboStencilRotation](#gobostencilrotation) / [GoboWheelRotation](#gobowheelrotation)
* [Focus](#focus)
* [Zoom](#zoom)
* [Iris](#iris) / [IrisEffect](#iriseffect)
Expand Down Expand Up @@ -135,31 +134,6 @@ To make common percentage values more readable, one can use specific keywords to
<td valign="top">Entity <em>ColorTemperature</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="colorwheelindex" rowspan="3">ColorWheelIndex</th>
<td valign="top">index<br><sub>:star2: required</sub></td>
<td valign="top">Entity <em>Index</em></td>
<td valign="top"><a href="#property-index">see footnote <em>index</em></a></td>
</tr>
<td valign="top">colors<br><sub>:grey_question: optional</sub></td>
<td valign="top">array of individual color beams as hex code</td>
<td valign="top"><a href="#property-colors">see footnote <em>colors</em></a></td>
</tr>
<tr>
<td valign="top">colorTemperature<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>ColorTemperature</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="colorwheelrotation" rowspan="2">ColorWheelRotation</th>
<td valign="top">speed<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationSpeed</em></td>
<td rowspan="2">either <em>speed</em> or <em>angle</em> is allowed</td>
</tr>
<tr>
<td valign="top">angle<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationAngle</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="colortemperature">ColorTemperature</th>
<td valign="top">colorTemperature<br><sub>:star2: required</sub></td>
Expand Down Expand Up @@ -200,6 +174,73 @@ To make common percentage values more readable, one can use specific keywords to
<td valign="top">duration<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>Duration</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="wheelslot" rowspan="2">WheelSlot</th>
<td valign="top">wheel<br><sub>:grey_question: optional</sub></td>
<td valign="top">Wheel name</td>
<td valign="top">Defaults to channel name</td>
</tr>
<tr>
<td valign="top">slotNumber<br><sub>:star2: required</sub></td>
<td valign="top">Entity <em>SlotNumber</em></td>
<td valign="top"><a href="#property-slotnumber">see footnote <em>slotNumber</em></a></td>
</tr>
<tr>
<th valign="top" scope="row" id="wheelshake" rowspan="4">WheelShake</th>
<td valign="top">wheel<br><sub>:grey_question: optional</sub></td>
<td valign="top">Wheel name or array of wheel names</td>
<td valign="top">Defaults to channel name. Array not allowed when <em>slotNumber</em> is set.</td>
</tr>
<tr>
<td valign="top">slotNumber<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>Slot</em></td>
<td valign="top"><a href="#property-slotnumber">see footnote <em>slotNumber</em></a></td>
</tr>
<tr>
<td valign="top">shakeSpeed<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>Speed</em></td>
<td valign="top"></td>
</tr>
<tr>
<td valign="top">shakeAngle<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>SwingAngle</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="wheelslotrotation" rowspan="4">WheelSlotRotation</th>
<td valign="top">wheel<br><sub>:grey_question: optional</sub></td>
<td valign="top">Wheel name or array of wheel names</td>
<td valign="top">Defaults to channel name. Array not allowed when <em>slotNumber</em> is set.</td>
</tr>
<tr>
<td valign="top">slotNumber<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>Slot</em></td>
<td valign="top"><a href="#property-slotnumber">see footnote <em>slotNumber</em></a></td>
</tr>
<tr>
<td valign="top">speed<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationSpeed</em></td>
<td rowspan="2">either <em>speed</em> or <em>angle</em> is allowed</td>
</tr>
<tr>
<td valign="top">angle<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationAngle</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="wheelrotation" rowspan="3">WheelRotation</th>
<td valign="top">wheel<br><sub>:grey_question: optional</sub></td>
<td valign="top">Wheel name or array of wheel names</td>
<td valign="top">Defaults to channel name.</td>
</tr>
<tr>
<td valign="top">speed<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationSpeed</em></td>
<td rowspan="2">either <em>speed</em> or <em>angle</em> is allowed</td>
</tr>
<tr>
<td valign="top">angle<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationAngle</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="effect" rowspan="7">Effect</th>
<td valign="top">effectName<br><sub>:vs: required</sub><br><sub>:feet: <a href="#must-be-stepped">must be stepped</a></sub></td>
Expand Down Expand Up @@ -259,53 +300,6 @@ To make common percentage values more readable, one can use specific keywords to
<td valign="top">Entity <em>Percent</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="goboindex" rowspan="3">GoboIndex</th>
<td valign="top">index<br><sub>:star2: required</sub></td>
<td valign="top">Entity <em>Index</em></td>
<td valign="top"><a href="#property-index">see footnote <em>index</em></a></td>
</tr>
<tr>
<td valign="top">shakeSpeed<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>Speed</em></td>
<td valign="top"></td>
</tr>
<tr>
<td valign="top">shakeAngle<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>SwingAngle</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="goboshake" rowspan="2">GoboShake</th>
<td valign="top">shakeSpeed<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>Speed</em></td>
<td valign="top"></td>
</tr>
<tr>
<td valign="top">shakeAngle<br><sub>:grey_question: optional</sub></td>
<td valign="top">Entity <em>SwingAngle</em></td>
<td valign="top"></td>
</tr>
<tr>
<th valign="top" scope="row" id="gobostencilrotation" rowspan="2">GoboStencilRotation</th>
<td valign="top">speed<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationSpeed</em></td>
<td rowspan="2">either <em>speed</em> or <em>angle</em> is allowed</td>
</tr>
<tr>
<td valign="top">angle<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationAngle</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="gobowheelrotation" rowspan="2">GoboWheelRotation</th>
<td valign="top">speed<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationSpeed</em></td>
<td rowspan="2">either <em>speed</em> or <em>angle</em> is allowed</td>
</tr>
<tr>
<td valign="top">angle<br><sub>:vs: required</sub></td>
<td valign="top">Entity <em>RotationAngle</em></td>
</tr>
<tr>
<th valign="top" scope="row" id="focus">Focus</th>
<td valign="top">distance<br><sub>:star2: required</sub></td>
Expand Down Expand Up @@ -480,15 +474,15 @@ Properties that must be stepped (they have a :feet: footsteps icon next to them)
"Individual color beams" means that one beam is visually distinguishable from the others, i.e.:

* A Red/Green/Blue/White/Amber LED produces a single color beam, as all these color components are mixed together. For a color preset "Red+Blue", `colors` should be set to `["#ff00ff"]`.
* A laser device has seperate light beams that don't mix. If red and green lasers are active, `colors` should be set to `["#ff0000", "#00ff00"]`.
* A laser device has separate light beams that don't mix. If red and green lasers are active, `colors` should be set to `["#ff0000", "#00ff00"]`.
* UV is always counted as a separate color as the ultraviolet light doesn't really mix with normal RGB colors. For a color preset "Red+Green+UV", `colors` should be set to `["#ffff00", "UV"]`.


#### Property *index*
#### Property *slotNumber*

Use zero-based numbering (e.g. `0` for open, `1` for *Color/Gobo 1*). If the capability shows a split color/gobo, use the value halfway between them (e.g. `1.5` for *Split Color/Gobo 1/2*). If all steps in between can be selected by the proportional capability, use `indexStart` and `indexEnd` (e.g. from *Color/Gobo 1* to *Color/Gobo 2*).
Use one-based numbering (e.g. `1` for *Open*, `2` for *Color/Gobo 1*). If the capability shows a split slot, use the value halfway between them (e.g. `2.5` for *Split Color/Gobo 1/2*). If all steps in between can be selected by the proportional capability, use `slotNumberStart` and `slotNumberEnd` (e.g. from *Color/Gobo 1* to *Color/Gobo 2*).

**Note:** If there are e.g. 8 gobo slots, and a capability allows gradually selecting anything between the last slot (Gobo 7) and the first (Gobo 0) in this direction, use `"indexStart": 7, "indexEnd": 8`. If you chose `"indexEnd": 0` instead, that would indicate a rotation in the other direction.
**Note:** If there are e.g. 8 slots, and a capability allows gradually selecting anything between the last slot (*Color/Gobo 7*) and the first (*Open*) in this direction, use `"slotNumberStart": 8, "slotNumberEnd": 9`. If you chose `"slotNumberEnd": 1` instead, that would indicate a rotation in the other direction (i.e. over all other Gobos). Likewise, `"slotNumberStart": 0, "slotNumberEnd": 1` is also allowed.


### How to add new capability types / type-specific properties
Expand All @@ -501,4 +495,4 @@ Use zero-based numbering (e.g. `0` for open, `1` for *Color/Gobo 1*). If the cap
* Add new types to channel type generation (in `CoarseChannel.mjs`)
* Update editor:
* Create new component in `ui/components/editor-capabilities`. Make sure it has a `defaultData` object as component data.
* Import the new component in the [capability component](../ui/components/editor-capability.vue) and register it in its `components` section.
* Import the new component in the [capability component](../ui/components/editor-capability-type-data.vue) and register it in its `components` section.
48 changes: 45 additions & 3 deletions docs/fixture-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ This document gives a high-level overview of the concepts used in the JSON forma
- [Matrices](#matrices)
- [Matrix structure](#matrix-structure)
- [Template channels](#template-channels)
- [Wheels](#wheels)
- [Using wheels in capabilities](#using-wheels-in-capabilities)
- [RDM (Remote Device Management) data](#rdm-remote-device-management-data)
- [Fixture redirects](#fixture-redirects)

Expand Down Expand Up @@ -81,7 +83,7 @@ If `constant` is `true`, the channel should be set to a static value in the oper

#### Capabilities

A channel can do different things depending on which range its DMX value currently is in. Those ranges, that can be triggered manually in many programs, are called capabilities. Choose a `type` to declare which property of the fixture is changed by this capability, e.g. `ShutterOpen`, `Intensity` or `Pan`. Depending on the type, there exist more properties that further describe the capability, like the pan angle, the strobe rate or the gobo wheel index. Most of these are physical entities that require to be entered using specific units (like `"10.5Hz"` or `"100%"`). Some entities offer keywords to replace specific percentage values, e.g. Distance: `"near"` = `"1%"`, `"far"` = `"100%"`. See the [full list of units, entities and capability types with their properties](capability-types.md). Example:
A channel can do different things depending on which range its DMX value currently is in. Those ranges that can be triggered manually in many programs are called capabilities. Choose a `type` to declare which property of the fixture is changed by this capability, e.g. `ShutterOpen`, `Intensity` or `Pan`. Depending on the type, there exist more properties that further describe the capability, like the pan angle, the strobe rate or the wheel slot number. Most of these are physical entities that require to be entered using specific units (like `"10.5Hz"` or `"100%"`). Some entities offer keywords to replace specific percentage values, e.g. Distance: `"near"` = `"1%"`, `"far"` = `"100%"`. See the [full list of units, entities and capability types with their properties](capability-types.md). Example:

```js
"availableChannels": {
Expand Down Expand Up @@ -212,7 +214,7 @@ The information how these pixels are arranged is stored in the fixture's `matrix

`null` refers to a "hole", i.e. there's no light beam, which allows for non-cubic frames. The above example represents 5 heads arranged like a "+".

Pixels can also be grouped if a fixture allows control in different fine grades, like fourths or halfs of a light bar:
Pixels can also be grouped if a fixture allows control in different fine grades, like fourths or halves of a light bar:

```js
"matrix": {
Expand Down Expand Up @@ -266,7 +268,7 @@ To reuse similar channels for each pixel or pixel group (like "Red&nbsp;1", Red&
}
```

Template channels can also introduce fine and switching channels. Specific resolved matrix channels can be overriden by available channels (e.g. if "Speed&nbsp;1" has different capabilities than "Speed&nbsp;2" until "Speed&nbsp;25"). See the [cameo Hydrabeam 300 RGBW](../fixtures/cameo/hydrambeam-300-rgbw.json) that uses these features.
Template channels can also introduce fine and switching channels. Specific resolved matrix channels can be overridden by available channels (e.g. if "Speed&nbsp;1" has different capabilities than "Speed&nbsp;2" until "Speed&nbsp;25"). See the [cameo Hydrabeam 300 RGBW](../fixtures/cameo/hydrambeam-300-rgbw.json) that uses these features.

Then, either use the resolved channel keys directly in a mode's channel list, or use a matrix channel insert block that repeats a list of template channels for a list of pixels:

Expand Down Expand Up @@ -301,6 +303,46 @@ Then, either use the resolved channel keys directly in a mode's channel list, or
- For the above [matrix structure](#matrix-structure) example, this results in `["Inner ring", "Middle ring", "Outer ring"]`.


### Wheels

Fixtures (usually moving heads) can have internal wheels, where you can select the active slot via DMX. In our fixture format, wheels are defined in the fixture's `wheels` object, where the key defines the wheel's name.

The slots in a wheel have types, similar to [capability types](capability-types.md). Depending on the type, different properties can be set on the slot.

* `Open` / `Closed`
* `Color`
- `name` (string)
- `colors` (array of hex strings)
- `colorTemperature` ([Entity](capability-types.md#possible-entities-and-keywords) *ColorTemperature*)
* `Gobo`
- `name` (string)
* `Prism`
- `name` (string)
- `facets` (integer)
* `Iris`
- `openPercent` ([Entity](capability-types.md#possible-entities-and-keywords) *IrisPercent*)
* `Frost`
- `frostIntensity` ([Entity](capability-types.md#possible-entities-and-keywords) *Percent*)
* `AnimationGoboStart`
- `name` (string)
* `AnimationGoboEnd`

Animation Gobo slots are wider than normal gobos (sometimes they fill the whole wheel); rotating the wheel over these slots creates an animation. To model the wider slots, an `AnimationGoboEnd` slot must be used directly after an `AnimationGoboStart` slot.

#### Using wheels in capabilities

In wheel-related capabilities, the `wheel` property references the wheel by its name. If the `wheel` property is not set, the channel name is used as wheel name.

`WheelSlot` capabilities select a slot from the wheel. If the capability selects the place in between two slots, the `slotNumber` property can be set to a fractional value (or be proportional as `slotNumberStart` / `slotNumberEnd`). See also [footnote *slotNumber* in the capability types documentation](capability-types.md#property-slotnumber).

`WheelShake` capabilities set the shaking (i.e. continuously rotating back and forth) of the whole wheel around the currently selected slot. A slot can also be activated directly by setting the `slotNumber` property like in `WheelSlot` capabilities.
By setting the property `isShaking` to `slot`, one can specify that only the currently selected slot rotates back and forth around its center (sometimes called *Gobo bounce effect*) instead of the whole wheel.

`WheelSlotRotation` capabilities control the rotation of the currently selected slot (i.e. Gobo, Prism, etc.). A slot can also be activated directly by setting the `slotNumber` property like in `WheelSlot` capabilities.

`WheelRotation` capabilities rotate the whole wheel, i.e. over all slots.


### RDM (Remote Device Management) data

We link to [Open Lighting's RDM database](http://rdm.openlighting.org) if possible. Thus, we need to specify the RDM manufacturer ID per manufacturer and the RDM model ID per fixture. Additionally, each mode is mapped to the respective RDM personality via the `rdmPersonalityIndex` property. To ensure compatibility, we also track, for which RDM fixture software (firmware) version the mode indices are specified.
Expand Down

0 comments on commit b665703

Please sign in to comment.