Skip to content

Commit 6e759d2

Browse files
authored
Add gobo resource handling (#1185)
* Schema version 12.2.0: - Use JSON Schema definitions in manufacturer schema - Add gobo schema - Add references to gobo resources in `Gobo` wheel slots * Model: - Embed resources into fixture JSON - Add and use Resource model class * UI: - Preview gobo images in fixture pages' wheels - Preview gobo images in fixture pages' capability tables - Improve fixture page wheel styling * Tests: - Test resource references in fixture test - Add fixture feature * Support gobo import/export in QLC+ 4.12.1 plugin * Add gobos for Showtec Phantom 50 * Update docs
1 parent 0a61c67 commit 6e759d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+943
-192
lines changed

cli/run-export-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const pluginExport = require(path.join(__dirname, `../plugins`, args.plugin, `ex
7171

7272
const outputPerFile = await Promise.all(files.map(async file => {
7373
try {
74-
await exportTest(file);
74+
await exportTest(file, files);
7575
return `${chalk.green(`[PASS]`)} ${file.name}`;
7676
}
7777
catch (err) {

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This is the developer documentation for the *Open Fixture Library*. Please follo
1111
- `fixture-features/`[Fixture features](fixture-features.md), special fixture characteristics used to determine a set of test fixtures
1212
- `model/` – Classes of the [fixture model](fixture-model.md) that help ease processing fixture data (see the [model API reference](model-api.md))
1313
* `plugins/`[Plugins](plugins.md) for export / import to / from other software's fixture formats
14+
* `resources/` – Resources (e.g. [gobos](fixture-format.md#gobo-resources)) that fixtures can use
1415
* `schemas/` – Schemas for the [fixture definitions](fixture-format.md#schema)
1516
* `server/` – Load balancer config and auto-deploy script for everyone interested
1617
* `tests/`[Unit tests](testing.md), much of them run automatically in GitHub with Travis

docs/fixture-format.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This document gives a high-level overview of the concepts used in the JSON forma
1919
- [Matrix structure](#matrix-structure)
2020
- [Template channels](#template-channels)
2121
- [Wheels](#wheels)
22+
- [Gobo resources](#gobo-resources)
2223
- [Using wheels in capabilities](#using-wheels-in-capabilities)
2324
- [RDM (Remote Device Management) data](#rdm-remote-device-management-data)
2425
- [Fixture redirects](#fixture-redirects)
@@ -329,6 +330,7 @@ The slots in a wheel have types, similar to [capability types](capability-types.
329330
- `colors` (array of hex strings)
330331
- `colorTemperature` ([Entity](capability-types.md#possible-entities-and-keywords) *ColorTemperature*)
331332
* `Gobo`
333+
- `resource` (resource reference string, see below)
332334
- `name` (string)
333335
* `Prism`
334336
- `name` (string)
@@ -343,6 +345,14 @@ The slots in a wheel have types, similar to [capability types](capability-types.
343345

344346
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.
345347

348+
#### Gobo resources
349+
350+
Gobos are referenced with a resource reference in the form `gobos/<gobo key>`.
351+
352+
Gobo resources are stored in the [`resources/gobos/`](../resources/gobos/) directory. Each one consists of a JSON file (`<gobo key>.json`) describing the gobo (with name, keywords, and a source where the gobo image was extracted from) and the gobo image itself (`<gobo key>.svg` or `<gobo key>.png`).
353+
354+
In the [`resources/gobos/aliases/`](../resources/gobos/aliases/) directory, sets of aliases can be defined as separate JSON files in which aliases are mapped to gobo keys. This is useful for plugins (e.g. the QLC+ import plugin knows which OFL gobo key to use when QLC+ gobo `Others/0001.svg` is referenced in a fixture). It also enables referencing gobos in fixture files with an alias like `gobos/aliases/<alias file>/<alias key>` (e.g. a Robe fixture could reference `gobos/aliases/robe/15020246-rafia`) to make validating the gobo information easier with a manual where product numbers are specified.
355+
346356
#### Using wheels in capabilities
347357

348358
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.

docs/fixture-model.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ export default class Fixture {
7171
// ...
7272
}
7373
```
74+
75+
## Resource references
76+
77+
Resources (e.g. gobo images) are embedded by the model into the fixture JSON, i.e. instead of returning a string, `WheelSlot.resource` will return the resource object. The relevant code is in the `embedResourcesIntoFixtureJson` function in [`lib/model.js](../lib/model.js).
78+
79+
Thus, all information needed for the fixure is still included in the fixture JSON.

docs/model-api.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Also called LSB (least significant byte) channel.</p>
4242
<dt><a href="#Range">Range</a></dt>
4343
<dd><p>Represents a range from one integer to a higher or equal integer. Primarily used for DMX ranges of capabilities.</p>
4444
</dd>
45+
<dt><a href="#Resource">Resource</a></dt>
46+
<dd><p>Information about a resource.</p>
47+
</dd>
4548
<dt><a href="#SwitchingChannel">SwitchingChannel</a> ⇐ <code><a href="#AbstractChannel">AbstractChannel</a></code></dt>
4649
<dd><p>Represents a channel that switches its behavior depending on trigger channel&#39;s value.
4750
The different behaviors are implemented as different <a href="#CoarseChannel">CoarseChannel</a>s or <a href="#FineChannel">FineChannel</a>s.</p>
@@ -2254,6 +2257,98 @@ Merge specified Range objects. Asserts that ranges don't overlap and that all ra
22542257
| --- | --- | --- |
22552258
| ranges | [<code>Array.&lt;Range&gt;</code>](#Range) | Range objects to merge into as few ranges as possible. |
22562259

2260+
<a name="Resource"></a>
2261+
2262+
## Resource
2263+
Information about a resource.
2264+
2265+
**Kind**: global class
2266+
2267+
* [Resource](#Resource)
2268+
* [new Resource(jsonObject)](#new_Resource_new)
2269+
* [.name](#Resource+name) ⇒ <code>String</code>
2270+
* [.keywords](#Resource+keywords) ⇒ <code>Array.&lt;String&gt;</code>
2271+
* [.source](#Resource+source) ⇒ <code>String</code> \| <code>null</code>
2272+
* [.key](#Resource+key) ⇒ <code>String</code>
2273+
* [.type](#Resource+type) ⇒ <code>String</code>
2274+
* [.alias](#Resource+alias) ⇒ <code>String</code> \| <code>null</code>
2275+
* [.hasImage](#Resource+hasImage) ⇒ <code>Boolean</code>
2276+
* [.imageExtension](#Resource+imageExtension) ⇒ <code>String</code> \| <code>null</code>
2277+
* [.imageMimeType](#Resource+imageMimeType) ⇒ <code>String</code> \| <code>null</code>
2278+
* [.imageData](#Resource+imageData) ⇒ <code>String</code> \| <code>null</code>
2279+
* [.imageEncoding](#Resource+imageEncoding) ⇒ <code>&#x27;base64&#x27;</code> \| <code>&#x27;utf8&#x27;</code> \| <code>null</code>
2280+
* [.imageDataUrl](#Resource+imageDataUrl) ⇒ <code>String</code> \| <code>null</code>
2281+
2282+
<a name="new_Resource_new"></a>
2283+
2284+
### new Resource(jsonObject)
2285+
Creates a new Resource instance.
2286+
2287+
2288+
| Param | Type | Description |
2289+
| --- | --- | --- |
2290+
| jsonObject | <code>Object</code> | An embedded resource object from the fixture's JSON data. |
2291+
2292+
<a name="Resource+name"></a>
2293+
2294+
### resource.name ⇒ <code>String</code>
2295+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2296+
**Returns**: <code>String</code> - The resource's name.
2297+
<a name="Resource+keywords"></a>
2298+
2299+
### resource.keywords ⇒ <code>Array.&lt;String&gt;</code>
2300+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2301+
**Returns**: <code>Array.&lt;String&gt;</code> - An array of keywords belonging to this resource.
2302+
<a name="Resource+source"></a>
2303+
2304+
### resource.source ⇒ <code>String</code> \| <code>null</code>
2305+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2306+
**Returns**: <code>String</code> \| <code>null</code> - The source this resource was taken from, or null if it's not specified.
2307+
<a name="Resource+key"></a>
2308+
2309+
### resource.key ⇒ <code>String</code>
2310+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2311+
**Returns**: <code>String</code> - The resource key.
2312+
<a name="Resource+type"></a>
2313+
2314+
### resource.type ⇒ <code>String</code>
2315+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2316+
**Returns**: <code>String</code> - The resource name, i.e. its directory.
2317+
<a name="Resource+alias"></a>
2318+
2319+
### resource.alias ⇒ <code>String</code> \| <code>null</code>
2320+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2321+
**Returns**: <code>String</code> \| <code>null</code> - The resource alias, as specified in the fixture, or null if the resource was referenced directly.
2322+
<a name="Resource+hasImage"></a>
2323+
2324+
### resource.hasImage ⇒ <code>Boolean</code>
2325+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2326+
**Returns**: <code>Boolean</code> - True if this resource has an associated image, false otherwise.
2327+
<a name="Resource+imageExtension"></a>
2328+
2329+
### resource.imageExtension ⇒ <code>String</code> \| <code>null</code>
2330+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2331+
**Returns**: <code>String</code> \| <code>null</code> - The resource image's file extension, or null if there is no image.
2332+
<a name="Resource+imageMimeType"></a>
2333+
2334+
### resource.imageMimeType ⇒ <code>String</code> \| <code>null</code>
2335+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2336+
**Returns**: <code>String</code> \| <code>null</code> - The resource image's MIME type, or null if there is no image.
2337+
<a name="Resource+imageData"></a>
2338+
2339+
### resource.imageData ⇒ <code>String</code> \| <code>null</code>
2340+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2341+
**Returns**: <code>String</code> \| <code>null</code> - The resource image data (base64 or utf8 encoded), or null if there is no image.
2342+
<a name="Resource+imageEncoding"></a>
2343+
2344+
### resource.imageEncoding ⇒ <code>&#x27;base64&#x27;</code> \| <code>&#x27;utf8&#x27;</code> \| <code>null</code>
2345+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2346+
**Returns**: <code>&#x27;base64&#x27;</code> \| <code>&#x27;utf8&#x27;</code> \| <code>null</code> - The resource image's data encoding, or null if there is no image.
2347+
<a name="Resource+imageDataUrl"></a>
2348+
2349+
### resource.imageDataUrl ⇒ <code>String</code> \| <code>null</code>
2350+
**Kind**: instance property of [<code>Resource</code>](#Resource)
2351+
**Returns**: <code>String</code> \| <code>null</code> - A data URL containing the resource image, or null if there is no image.
22572352
<a name="SwitchingChannel"></a>
22582353

22592354
## SwitchingChannel ⇐ [<code>AbstractChannel</code>](#AbstractChannel)
@@ -2540,6 +2635,7 @@ Information about a single wheel slot (or a split slot).
25402635
* [.isSplitSlot](#WheelSlot+isSplitSlot) ⇒ <code>Boolean</code>
25412636
* [.type](#WheelSlot+type) ⇒ <code>String</code>
25422637
* [.nthOfType](#WheelSlot+nthOfType) ⇒ <code>Number</code>
2638+
* [.resource](#WheelSlot+resource)[<code>Resource</code>](#Resource) \| <code>String</code> \| <code>null</code>
25432639
* [.name](#WheelSlot+name) ⇒ <code>String</code>
25442640
* [.colors](#WheelSlot+colors) ⇒ <code>Array.&lt;String&gt;</code> \| <code>null</code>
25452641
* [.colorTemperature](#WheelSlot+colorTemperature)[<code>Entity</code>](#Entity) \| <code>null</code>
@@ -2577,6 +2673,11 @@ Creates a new WheelSlot instance.
25772673
### wheelSlot.nthOfType ⇒ <code>Number</code>
25782674
**Kind**: instance property of [<code>WheelSlot</code>](#WheelSlot)
25792675
**Returns**: <code>Number</code> - The zero-based index of this slot amongst all slots with the same type in this wheel.
2676+
<a name="WheelSlot+resource"></a>
2677+
2678+
### wheelSlot.resource ⇒ [<code>Resource</code>](#Resource) \| <code>String</code> \| <code>null</code>
2679+
**Kind**: instance property of [<code>WheelSlot</code>](#WheelSlot)
2680+
**Returns**: [<code>Resource</code>](#Resource) \| <code>String</code> \| <code>null</code> - The gobo resource object if it was previously embedded, or the gobo resource reference string, or null if no resource is specified for the slot.
25802681
<a name="WheelSlot+name"></a>
25812682

25822683
### wheelSlot.name ⇒ <code>String</code>

fixtures/showtec/phantom-50-led-spot.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"meta": {
77
"authors": ["Felix Edelmann", "Flo Edelmann"],
88
"createDate": "2017-04-29",
9-
"lastModifyDate": "2018-09-04"
9+
"lastModifyDate": "2020-02-11"
1010
},
1111
"comment": "Ordercode 40187",
1212
"links": {
@@ -85,31 +85,31 @@
8585
},
8686
{
8787
"type": "Gobo",
88-
"name": "Gobo 1 Glass"
88+
"resource": "gobos/glass-red-10-circles"
8989
},
9090
{
9191
"type": "Gobo",
92-
"name": "Gobo 2 Glass"
92+
"resource": "gobos/glass-raindrops-on-window"
9393
},
9494
{
9595
"type": "Gobo",
96-
"name": "Gobo 3 Metal"
96+
"resource": "gobos/3-fold-swirl"
9797
},
9898
{
9999
"type": "Gobo",
100-
"name": "Gobo 4 Metal"
100+
"resource": "gobos/biohazard"
101101
},
102102
{
103103
"type": "Gobo",
104-
"name": "Gobo 5 Metal"
104+
"resource": "gobos/rose-petal"
105105
},
106106
{
107107
"type": "Gobo",
108-
"name": "Gobo 6 Metal"
108+
"resource": "gobos/triangle-hexagon-pattern"
109109
},
110110
{
111111
"type": "Gobo",
112-
"name": "Gobo 7 Metal"
112+
"resource": "gobos/dot-spiral"
113113
}
114114
]
115115
}

lib/fixture-features/wheels.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,20 @@ const wheelSlotTypeFeatures = wheelSlotTypes.map(type => ({
3737
)
3838
}));
3939

40-
module.exports = wheelTypeFeatures.concat(wheelSlotTypeFeatures);
40+
const resourceFeature = {
41+
id: `wheel-slot-uses-resource`,
42+
name: `Wheel slot uses resource`,
43+
description: `Whether the fixture has at least one wheel slot that references a resource`,
44+
45+
/**
46+
* @param {Fixture} fixture The Fixture instance
47+
* @returns {Boolean} true if the fixture has at least one wheel slot that references a resource
48+
*/
49+
hasFeature: fixture => fixture.wheels.some(
50+
wheel => wheel.slots.some(
51+
slot => slot.resource !== null
52+
)
53+
)
54+
};
55+
56+
module.exports = wheelTypeFeatures.concat(wheelSlotTypeFeatures, resourceFeature);

0 commit comments

Comments
 (0)