@rocketshow/designer 1.33.0 → 1.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/assets/i18n/de.json +2 -1
  2. package/assets/i18n/en.json +2 -1
  3. package/esm2022/lib/designer.component.mjs +197 -130
  4. package/esm2022/lib/designer.module.mjs +5 -2
  5. package/esm2022/lib/dropzone/dropzone.component.mjs +93 -0
  6. package/esm2022/lib/effect/effect-curve/effect-curve.component.mjs +14 -6
  7. package/esm2022/lib/fixture/fixture-capability/fixture-capability.component.mjs +5 -5
  8. package/esm2022/lib/fixture/fixture-channel/fixture-channel.component.mjs +6 -4
  9. package/esm2022/lib/fixture/fixture.component.mjs +25 -15
  10. package/esm2022/lib/fixture-pool/fixture-pool-create-from-file/fixture-pool-create-from-file.component.mjs +4 -4
  11. package/esm2022/lib/fixture-pool/fixture-pool.component.mjs +73 -21
  12. package/esm2022/lib/models/cached-fixture.mjs +1 -1
  13. package/esm2022/lib/models/fixture-matrix-pixel-group-constraints.mjs +27 -0
  14. package/esm2022/lib/models/fixture-matrix-pixel-group.mjs +12 -0
  15. package/esm2022/lib/models/fixture-matrix.mjs +25 -0
  16. package/esm2022/lib/models/fixture-mode-channel.mjs +26 -0
  17. package/esm2022/lib/models/fixture-mode.mjs +5 -2
  18. package/esm2022/lib/models/fixture-physical.mjs +14 -0
  19. package/esm2022/lib/models/fixture-profile.mjs +16 -1
  20. package/esm2022/lib/models/fixture.mjs +2 -2
  21. package/esm2022/lib/models/preset-fixture.mjs +10 -0
  22. package/esm2022/lib/models/preset.mjs +10 -1
  23. package/esm2022/lib/models/project.mjs +11 -1
  24. package/esm2022/lib/preview/models/color-changer-3d.mjs +5 -108
  25. package/esm2022/lib/preview/models/fixture-3d.mjs +125 -1
  26. package/esm2022/lib/preview/models/moving-head-3d.mjs +3 -122
  27. package/esm2022/lib/preview/preview.component.mjs +21 -16
  28. package/esm2022/lib/services/config.service.mjs +2 -1
  29. package/esm2022/lib/services/fixture.service.mjs +306 -44
  30. package/esm2022/lib/services/preset.service.mjs +92 -42
  31. package/esm2022/lib/services/preview.service.mjs +29 -60
  32. package/esm2022/lib/services/project-load.service.mjs +61 -4
  33. package/esm2022/lib/services/project.service.mjs +11 -15
  34. package/esm2022/lib/timeline/composition-settings/composition-settings.component.mjs +14 -44
  35. package/fesm2022/rocketshow-designer.mjs +1319 -758
  36. package/fesm2022/rocketshow-designer.mjs.map +1 -1
  37. package/lib/designer.component.d.ts +5 -5
  38. package/lib/designer.module.d.ts +15 -14
  39. package/lib/dropzone/dropzone.component.d.ts +24 -0
  40. package/lib/fixture/fixture.component.d.ts +4 -3
  41. package/lib/models/cached-fixture.d.ts +1 -0
  42. package/lib/models/fixture-matrix-pixel-group-constraints.d.ts +8 -0
  43. package/lib/models/fixture-matrix-pixel-group.d.ts +6 -0
  44. package/lib/models/fixture-matrix.d.ts +6 -0
  45. package/lib/models/fixture-mode-channel.d.ts +8 -0
  46. package/lib/models/fixture-mode.d.ts +3 -1
  47. package/lib/models/fixture-physical.d.ts +4 -0
  48. package/lib/models/fixture-profile.d.ts +5 -0
  49. package/lib/models/preset-fixture.d.ts +5 -0
  50. package/lib/models/preset.d.ts +2 -0
  51. package/lib/models/project.d.ts +3 -0
  52. package/lib/preview/models/color-changer-3d.d.ts +1 -11
  53. package/lib/preview/models/fixture-3d.d.ts +11 -0
  54. package/lib/preview/models/moving-head-3d.d.ts +1 -11
  55. package/lib/services/config.service.d.ts +1 -0
  56. package/lib/services/fixture.service.d.ts +12 -2
  57. package/lib/services/preset.service.d.ts +5 -2
  58. package/lib/services/preview.service.d.ts +2 -5
  59. package/lib/services/project-load.service.d.ts +5 -1
  60. package/lib/services/project.service.d.ts +2 -3
  61. package/lib/services/timeline.service.d.ts +1 -1
  62. package/lib/timeline/composition-settings/composition-settings.component.d.ts +2 -1
  63. package/package.json +1 -1
  64. package/rocketshow-designer-1.36.0.tgz +0 -0
  65. package/esm2022/lib/models/universe.mjs +0 -11
  66. package/esm2022/lib/services/universe.service.mjs +0 -23
  67. package/lib/models/universe.d.ts +0 -8
  68. package/lib/services/universe.service.d.ts +0 -9
  69. package/rocketshow-designer-1.33.0.tgz +0 -0
@@ -1,18 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, ViewChild, HostListener, Pipe, Input, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core';
2
+ import { Injectable, Component, ViewChild, HostListener, Pipe, EventEmitter, Output, Input, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core';
3
3
  import * as i2 from '@ngx-translate/core';
4
4
  import { TranslateModule } from '@ngx-translate/core';
5
5
  import * as i1$1 from 'ngx-bootstrap/modal';
6
- import * as i3 from 'ngx-toastr';
7
- import { ToastrModule } from 'ngx-toastr';
8
- import { map, finalize, mergeMap, catchError } from 'rxjs/operators';
6
+ import { map, mergeMap, finalize, catchError } from 'rxjs/operators';
9
7
  import Split from 'split.js';
10
8
  import * as THREE from 'three';
11
9
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
12
10
  import * as i1 from '@angular/common/http';
13
- import { HttpHeaders, HttpClientModule } from '@angular/common/http';
11
+ import { HttpHeaders, HttpErrorResponse, HttpClientModule } from '@angular/common/http';
12
+ import * as i3$1 from 'ngx-toastr';
13
+ import { ToastrModule } from 'ngx-toastr';
14
14
  import { of, forkJoin, Observable, Subject, timer } from 'rxjs';
15
- import * as i4 from '@angular/router';
15
+ import * as i3 from '@angular/router';
16
16
  import { RouterModule } from '@angular/router';
17
17
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
18
18
  import WaveSurfer from 'wavesurfer.js';
@@ -23,7 +23,7 @@ import { guess } from 'web-audio-beat-detector';
23
23
  import * as i5 from '@angular/common';
24
24
  import * as i5$1 from 'ngx-dropzone-wrapper';
25
25
  import { DropzoneModule } from 'ngx-dropzone-wrapper';
26
- import * as i4$1 from '@angular/forms';
26
+ import * as i4 from '@angular/forms';
27
27
  import { FormsModule } from '@angular/forms';
28
28
  import * as i12 from 'ngx-bootstrap/popover';
29
29
  import { PopoverModule } from 'ngx-bootstrap/popover';
@@ -31,7 +31,7 @@ import * as i8 from 'ngx-sortablejs-plus';
31
31
  import { SortablejsModule } from 'ngx-sortablejs-plus';
32
32
  import * as i11 from 'ngx-bootstrap/typeahead';
33
33
  import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
34
- import * as i4$2 from 'ngx-bootstrap-slider';
34
+ import * as i4$1 from 'ngx-bootstrap-slider';
35
35
  import { NgxBootstrapSliderModule } from 'ngx-bootstrap-slider';
36
36
  import * as i6 from 'ngx-bootstrap/accordion';
37
37
  import { AccordionModule } from 'ngx-bootstrap/accordion';
@@ -157,6 +157,94 @@ class FixtureChannel {
157
157
  }
158
158
  }
159
159
 
160
+ class FixtureMatrixPixelGroupConstraints {
161
+ constructor(data) {
162
+ // constraint the pixel keys directly
163
+ this.keys = [];
164
+ // constraints by coordinates
165
+ this.x = [];
166
+ this.y = [];
167
+ this.z = [];
168
+ // a name regexp-constraint
169
+ this.name = [];
170
+ if (!data) {
171
+ return;
172
+ }
173
+ if (Array.isArray(data)) {
174
+ // an array of pixel keys
175
+ this.keys = data;
176
+ }
177
+ else {
178
+ // an object of constraints
179
+ this.x = data.x;
180
+ this.y = data.y;
181
+ this.z = data.z;
182
+ this.name = data.name;
183
+ }
184
+ }
185
+ }
186
+
187
+ class FixtureMatrixPixelGroup {
188
+ constructor(isAll = false, constraints) {
189
+ this.isAll = false;
190
+ this.constraints = null;
191
+ this.isAll = isAll;
192
+ if (constraints) {
193
+ this.constraints = new FixtureMatrixPixelGroupConstraints(constraints);
194
+ }
195
+ }
196
+ }
197
+
198
+ class FixtureMatrix {
199
+ constructor(data) {
200
+ this.pixelCount = [];
201
+ this.pixelGroups = {};
202
+ if (!data) {
203
+ return;
204
+ }
205
+ if (data.pixelKeys) {
206
+ this.pixelKeys = data.pixelKeys;
207
+ }
208
+ if (data.pixelCount) {
209
+ for (const pixelCountEntry of data.pixelCount) {
210
+ this.pixelCount.push(pixelCountEntry);
211
+ }
212
+ }
213
+ if (data.pixelGroups) {
214
+ for (const property of Object.keys(data.pixelGroups)) {
215
+ const pixelGroup = new FixtureMatrixPixelGroup(data.pixelGroups[property]);
216
+ this.pixelGroups[property] = pixelGroup;
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ class FixtureModeChannel {
223
+ constructor(data) {
224
+ this.repeatFor = [];
225
+ this.templateChannels = [];
226
+ if (!data) {
227
+ return;
228
+ }
229
+ if (typeof data === 'string') {
230
+ this.name = data;
231
+ }
232
+ else if (typeof data === 'object') {
233
+ // after first saving the project, we have a FixtureModeChannel-object, even if it's just a direct channel with a name
234
+ this.name = data.name;
235
+ this.insert = data.insert;
236
+ if (Array.isArray(data.repeatFor)) {
237
+ this.repeatFor = data.repeatFor;
238
+ }
239
+ else {
240
+ this.repeatFor.push(data.repeatFor);
241
+ }
242
+ this.channelOrder = data.channelOrder;
243
+ this.templateChannels = data.templateChannels;
244
+ }
245
+ }
246
+ }
247
+
160
248
  class FixtureMode {
161
249
  constructor(data) {
162
250
  this.channels = [];
@@ -166,7 +254,23 @@ class FixtureMode {
166
254
  this.name = data.name;
167
255
  this.shortName = data.shortName;
168
256
  if (data.channels) {
169
- this.channels = data.channels;
257
+ for (const channel of data.channels) {
258
+ this.channels.push(new FixtureModeChannel(channel));
259
+ }
260
+ }
261
+ }
262
+ }
263
+
264
+ class FixturePhysical {
265
+ constructor(data) {
266
+ this.dimensions = [];
267
+ if (!data) {
268
+ return;
269
+ }
270
+ if (data.dimensions) {
271
+ for (const dimension of data.dimensions) {
272
+ this.dimensions.push(dimension);
273
+ }
170
274
  }
171
275
  }
172
276
  }
@@ -236,6 +340,7 @@ class FixtureProfile {
236
340
  this.createdFromFile = false;
237
341
  this.categories = [];
238
342
  this.availableChannels = {};
343
+ this.templateChannels = {};
239
344
  this.wheels = {};
240
345
  // All available fixture modes
241
346
  this.modes = [];
@@ -255,6 +360,12 @@ class FixtureProfile {
255
360
  else if (data.mainCategory) {
256
361
  this.categories.push(FixtureCategory[data.mainCategory]);
257
362
  }
363
+ if (data.physical) {
364
+ this.physical = new FixturePhysical(data.physical);
365
+ }
366
+ if (data.matrix) {
367
+ this.matrix = new FixtureMatrix(data.matrix);
368
+ }
258
369
  if (data.wheels) {
259
370
  for (const property of Object.keys(data.wheels)) {
260
371
  const wheel = new FixtureWheel(data.wheels[property]);
@@ -272,6 +383,12 @@ class FixtureProfile {
272
383
  this.availableChannels[property] = fixtureChannel;
273
384
  }
274
385
  }
386
+ if (data.templateChannels) {
387
+ for (const property of Object.keys(data.templateChannels)) {
388
+ const templateChannel = new FixtureChannel(data.templateChannels[property]);
389
+ this.templateChannels[property] = templateChannel;
390
+ }
391
+ }
275
392
  if (data.createdFromFile) {
276
393
  this.createdFromFile = data.createdFromFile;
277
394
  }
@@ -318,7 +435,7 @@ var Positioning;
318
435
  })(Positioning || (Positioning = {}));
319
436
  class Fixture {
320
437
  constructor(data) {
321
- this.dmxFirstChannel = 5;
438
+ this.dmxFirstChannel = 1;
322
439
  this.positioning = Positioning.topFront;
323
440
  // Only relevant when positioning = manual
324
441
  // in CM
@@ -540,10 +657,22 @@ class FixtureChannelValue {
540
657
  }
541
658
  }
542
659
 
660
+ class PresetFixture {
661
+ constructor(data) {
662
+ if (!data) {
663
+ return;
664
+ }
665
+ this.fixtureUuid = data.fixtureUuid;
666
+ this.pixelKey = data.pixelKey;
667
+ }
668
+ }
669
+
543
670
  class Preset {
544
671
  constructor(data) {
545
672
  // all related fixtures
673
+ // OBSOLETE: replaced with fixtures
546
674
  this.fixtureUuids = [];
675
+ this.fixtures = [];
547
676
  // the selected values
548
677
  this.fixtureChannelValues = [];
549
678
  this.fixtureCapabilityValues = [];
@@ -560,7 +689,13 @@ class Preset {
560
689
  }
561
690
  this.uuid = data.uuid;
562
691
  this.name = data.name;
692
+ // OBSOLETE
563
693
  this.fixtureUuids = data.fixtureUuids;
694
+ if (data.fixtures) {
695
+ for (const fixture of data.fixtures) {
696
+ this.fixtures.push(new PresetFixture(fixture));
697
+ }
698
+ }
564
699
  if (data.fixtureChannelValues) {
565
700
  for (const fixtureChannelValue of data.fixtureChannelValues) {
566
701
  this.fixtureChannelValues.push(new FixtureChannelValue(fixtureChannelValue));
@@ -633,13 +768,17 @@ class Project {
633
768
  this.previewPreset = true;
634
769
  this.compositions = [];
635
770
  this.fixtureProfiles = [];
771
+ // fixtures added to the project in a DMX universe
636
772
  this.fixtures = [];
773
+ // the fixtures and pixel keys in order to be selectable
774
+ this.presetFixtures = [];
637
775
  this.scenes = [];
638
776
  this.presets = [];
639
777
  if (!data) {
640
778
  return;
641
779
  }
642
780
  this.id = data.id;
781
+ this.version = data.version;
643
782
  this.uuid = data.uuid;
644
783
  this.name = data.name;
645
784
  this.shareToken = data.shareToken;
@@ -669,6 +808,11 @@ class Project {
669
808
  this.fixtures.push(new Fixture(fixture));
670
809
  }
671
810
  }
811
+ if (data.presetFixtures) {
812
+ for (const presetFixture of data.presetFixtures) {
813
+ this.presetFixtures.push(new PresetFixture(presetFixture));
814
+ }
815
+ }
672
816
  if (data.scenes) {
673
817
  for (const scene of data.scenes) {
674
818
  this.scenes.push(new Scene(scene));
@@ -766,39 +910,16 @@ class UserService {
766
910
  }]
767
911
  }], () => [{ type: i1.HttpClient }], null); })();
768
912
 
769
- class UuidService {
770
- constructor() { }
771
- getUuid() {
772
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
773
- // tslint:disable-next-line:no-bitwise
774
- const r = (Math.random() * 16) | 0;
775
- // tslint:disable-next-line:no-bitwise
776
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
777
- return v.toString(16);
778
- });
779
- }
780
- static { this.ɵfac = function UuidService_Factory(t) { return new (t || UuidService)(); }; }
781
- static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UuidService, factory: UuidService.ɵfac, providedIn: 'root' }); }
782
- }
783
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UuidService, [{
784
- type: Injectable,
785
- args: [{
786
- providedIn: 'root',
787
- }]
788
- }], () => [], null); })();
789
-
790
913
  class ProjectService {
791
- constructor(uuidService, http, userService, router, activatedRoute, translateService, toastrService) {
792
- this.uuidService = uuidService;
914
+ constructor(http, userService, router, activatedRoute, translateService, toastrService) {
793
915
  this.http = http;
794
916
  this.userService = userService;
795
917
  this.router = router;
796
918
  this.activatedRoute = activatedRoute;
797
919
  this.translateService = translateService;
798
920
  this.toastrService = toastrService;
799
- this.project = new Project();
800
- this.project.uuid = this.uuidService.getUuid();
801
- this.project.name = 'New Project';
921
+ // the project-file versions used in this version of the designer (older ones will be migrated, newer ones are not supported)
922
+ this.currentProjectVersion = 2;
802
923
  }
803
924
  saveApi(project) {
804
925
  return this.http.post('project', JSON.stringify(project), { headers: this.userService.getHeaders() }).pipe(map((response) => {
@@ -858,7 +979,7 @@ class ProjectService {
858
979
  return project;
859
980
  }));
860
981
  }
861
- static { this.ɵfac = function ProjectService_Factory(t) { return new (t || ProjectService)(i0.ɵɵinject(UuidService), i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(UserService), i0.ɵɵinject(i4.Router), i0.ɵɵinject(i4.ActivatedRoute), i0.ɵɵinject(i2.TranslateService), i0.ɵɵinject(i3.ToastrService)); }; }
982
+ static { this.ɵfac = function ProjectService_Factory(t) { return new (t || ProjectService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(UserService), i0.ɵɵinject(i3.Router), i0.ɵɵinject(i3.ActivatedRoute), i0.ɵɵinject(i2.TranslateService), i0.ɵɵinject(i3$1.ToastrService)); }; }
862
983
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ProjectService, factory: ProjectService.ɵfac, providedIn: 'root' }); }
863
984
  }
864
985
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectService, [{
@@ -866,7 +987,28 @@ class ProjectService {
866
987
  args: [{
867
988
  providedIn: 'root',
868
989
  }]
869
- }], () => [{ type: UuidService }, { type: i1.HttpClient }, { type: UserService }, { type: i4.Router }, { type: i4.ActivatedRoute }, { type: i2.TranslateService }, { type: i3.ToastrService }], null); })();
990
+ }], () => [{ type: i1.HttpClient }, { type: UserService }, { type: i3.Router }, { type: i3.ActivatedRoute }, { type: i2.TranslateService }, { type: i3$1.ToastrService }], null); })();
991
+
992
+ class UuidService {
993
+ constructor() { }
994
+ getUuid() {
995
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
996
+ // tslint:disable-next-line:no-bitwise
997
+ const r = (Math.random() * 16) | 0;
998
+ // tslint:disable-next-line:no-bitwise
999
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
1000
+ return v.toString(16);
1001
+ });
1002
+ }
1003
+ static { this.ɵfac = function UuidService_Factory(t) { return new (t || UuidService)(); }; }
1004
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UuidService, factory: UuidService.ɵfac, providedIn: 'root' }); }
1005
+ }
1006
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UuidService, [{
1007
+ type: Injectable,
1008
+ args: [{
1009
+ providedIn: 'root',
1010
+ }]
1011
+ }], () => [], null); })();
870
1012
 
871
1013
  class FixtureService {
872
1014
  constructor(http, projectService, translateService, toastrService, uuidService) {
@@ -887,9 +1029,21 @@ class FixtureService {
887
1029
  }
888
1030
  }
889
1031
  }
890
- getCachedFixtureByUuid(uuid) {
1032
+ fixtureUuidAndPixelKeyEquals(fixtureUuid1, fixtureUuid2, pixelKey1, pixelKey2) {
1033
+ return fixtureUuid1 === fixtureUuid2 && ((pixelKey1 == null && pixelKey2 == null) || pixelKey1 === pixelKey2);
1034
+ }
1035
+ getCachedFixtureByUuid(uuid, pixelKey) {
1036
+ for (const fixture of this.cachedFixtures) {
1037
+ if (this.fixtureUuidAndPixelKeyEquals(fixture.fixture.uuid, uuid, fixture.pixelKey, pixelKey)) {
1038
+ return fixture;
1039
+ }
1040
+ }
1041
+ // not yet found -> try searching the fixture without pixelKey for the general channels
1042
+ if (pixelKey) {
1043
+ return undefined;
1044
+ }
891
1045
  for (const fixture of this.cachedFixtures) {
892
- if (fixture.fixture.uuid === uuid) {
1046
+ if (!fixture.pixelKey && fixture.fixture.uuid === uuid) {
893
1047
  return fixture;
894
1048
  }
895
1049
  }
@@ -1099,14 +1253,6 @@ class FixtureService {
1099
1253
  }
1100
1254
  return undefined;
1101
1255
  }
1102
- // private channelInList(channels: CachedFixtureChannel[], name: string): boolean {
1103
- // for (let channel of channels) {
1104
- // if (channel.channelName === name) {
1105
- // return true;
1106
- // }
1107
- // }
1108
- // return false;
1109
- // }
1110
1256
  getChannelByName(fixture, channelName) {
1111
1257
  for (const channel of fixture.channels) {
1112
1258
  if ((channel.name && channel.name === channelName) ||
@@ -1116,51 +1262,306 @@ class FixtureService {
1116
1262
  }
1117
1263
  return undefined;
1118
1264
  }
1119
- getCachedChannels(profile, mode) {
1265
+ getChannelNameWithPixelKey(templateChannelName, pixelKey) {
1266
+ return templateChannelName.replace('$pixelKey', pixelKey);
1267
+ }
1268
+ addCachedChannel(channels, channel, templateChannelName, pixelKey, profile) {
1269
+ const cachedFixtureChannel = new CachedFixtureChannel();
1270
+ const channelName = this.getChannelNameWithPixelKey(templateChannelName, pixelKey);
1271
+ cachedFixtureChannel.channel = channel;
1272
+ cachedFixtureChannel.name = channelName;
1273
+ cachedFixtureChannel.capabilities = this.getCapabilitiesByChannel(cachedFixtureChannel.channel, channelName, profile);
1274
+ const defaultValue = this.getDefaultValueByChannel(cachedFixtureChannel.channel);
1275
+ if (defaultValue) {
1276
+ cachedFixtureChannel.defaultValue = defaultValue;
1277
+ }
1278
+ cachedFixtureChannel.maxValue = this.getMaxValueByChannel(cachedFixtureChannel.channel);
1279
+ cachedFixtureChannel.colorWheel = this.getColorWheelByChannel(cachedFixtureChannel, profile);
1280
+ channels.push(cachedFixtureChannel);
1281
+ }
1282
+ alphanumericSort(a, b) {
1283
+ return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
1284
+ }
1285
+ getAllPixelKeys(profile) {
1286
+ let result = [];
1287
+ for (let pixelKeyX of profile.matrix.pixelKeys) {
1288
+ for (let pixelKeyY of pixelKeyX) {
1289
+ for (let pixelKeyZ of pixelKeyY) {
1290
+ if (pixelKeyZ) {
1291
+ result.push(pixelKeyZ);
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ return result;
1297
+ }
1298
+ getAllPixelGroups(profile) {
1299
+ let result = [];
1300
+ for (const property of Object.keys(profile.matrix.pixelGroups)) {
1301
+ result.push(property);
1302
+ }
1303
+ return result;
1304
+ }
1305
+ getPixelKeysInOrder(profile, repeatFor) {
1306
+ let result = [];
1307
+ // could contain just a single string (e.g. 'eachPixelABC') or
1308
+ if (repeatFor.length > 1) {
1309
+ // an array of pixel (groups)
1310
+ result = repeatFor;
1311
+ }
1312
+ else if (repeatFor.length === 0) {
1313
+ return result;
1314
+ }
1315
+ else if (repeatFor[0] === 'eachPixelABC') {
1316
+ // Gets computed into an alphanumerically sorted list of all pixelKeys
1317
+ if (profile.matrix.pixelCount.length === 3) {
1318
+ for (let x = 0; x < profile.matrix.pixelCount[0]; x++) {
1319
+ for (let y = 0; y < profile.matrix.pixelCount[1]; y++) {
1320
+ for (let z = 0; z < profile.matrix.pixelCount[2]; z++) {
1321
+ result.push('Pixel ' + (x + 1) + '-' + (y + 1) + '-' + (z + 1));
1322
+ }
1323
+ }
1324
+ }
1325
+ }
1326
+ else {
1327
+ result = result.concat(this.getAllPixelKeys(profile));
1328
+ }
1329
+ result.sort(this.alphanumericSort);
1330
+ }
1331
+ else if (repeatFor[0] === 'eachPixelGroup') {
1332
+ // Gets computed into an array of all pixel group keys, ordered by appearance in the JSON file
1333
+ result = result.concat(this.getAllPixelGroups(profile));
1334
+ }
1335
+ else if (repeatFor[0] === 'eachPixelXYZ') {
1336
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1337
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1338
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1339
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1340
+ if (pixel) {
1341
+ result.push(pixel);
1342
+ }
1343
+ }
1344
+ }
1345
+ }
1346
+ }
1347
+ else if (repeatFor[0] === 'eachPixelXZY') {
1348
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1349
+ for (let z = 0; z < profile.matrix.pixelKeys[x][0].length; z++) {
1350
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1351
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1352
+ if (pixel) {
1353
+ result.push(pixel);
1354
+ }
1355
+ }
1356
+ }
1357
+ }
1358
+ }
1359
+ else if (repeatFor[0] === 'eachPixelYXZ') {
1360
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1361
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1362
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1363
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1364
+ if (pixel) {
1365
+ result.push(pixel);
1366
+ }
1367
+ }
1368
+ }
1369
+ }
1370
+ }
1371
+ else if (repeatFor[0] === 'eachPixelYZX') {
1372
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1373
+ for (let z = 0; z < profile.matrix.pixelKeys[0][y].length; z++) {
1374
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1375
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1376
+ if (pixel) {
1377
+ result.push(pixel);
1378
+ }
1379
+ }
1380
+ }
1381
+ }
1382
+ }
1383
+ else if (repeatFor[0] === 'eachPixelZXY') {
1384
+ for (let z = 0; z < profile.matrix.pixelKeys[0][0].length; z++) {
1385
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1386
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1387
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1388
+ if (pixel) {
1389
+ result.push(pixel);
1390
+ }
1391
+ }
1392
+ }
1393
+ }
1394
+ }
1395
+ else if (repeatFor[0] === 'eachPixelZYX') {
1396
+ for (let z = 0; z < profile.matrix.pixelKeys[0][0].length; z++) {
1397
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1398
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1399
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1400
+ if (pixel) {
1401
+ result.push(pixel);
1402
+ }
1403
+ }
1404
+ }
1405
+ }
1406
+ }
1407
+ return result;
1408
+ }
1409
+ getModeChannelCount(profile, mode) {
1410
+ let count = 0;
1411
+ // already calculated?
1412
+ if (mode.channelCount) {
1413
+ return mode.channelCount;
1414
+ }
1415
+ for (let channel of mode.channels) {
1416
+ if (channel.insert === 'matrixChannels') {
1417
+ if (channel.repeatFor.length > 1) {
1418
+ count += channel.repeatFor.length * channel.templateChannels.length;
1419
+ }
1420
+ else if (channel.repeatFor[0] === 'eachPixelGroup') {
1421
+ count += profile.matrix.pixelGroups.length * channel.templateChannels.length;
1422
+ }
1423
+ else if (channel.repeatFor[0].startsWith('eachPixel')) {
1424
+ if (profile.matrix.pixelCount.length === 3) {
1425
+ count +=
1426
+ profile.matrix.pixelCount[0] * profile.matrix.pixelCount[1] * profile.matrix.pixelCount[2] * channel.templateChannels.length;
1427
+ }
1428
+ else {
1429
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1430
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1431
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1432
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1433
+ if (pixel) {
1434
+ count += channel.templateChannels.length;
1435
+ }
1436
+ }
1437
+ }
1438
+ }
1439
+ }
1440
+ }
1441
+ }
1442
+ else {
1443
+ count++;
1444
+ }
1445
+ }
1446
+ mode.channelCount = count;
1447
+ return mode.channelCount;
1448
+ }
1449
+ getCachedChannels(profile, mode, pixelKey) {
1120
1450
  const channels = [];
1121
1451
  if (!mode) {
1122
1452
  return channels;
1123
1453
  }
1124
- for (const availableChannelName of Object.keys(profile.availableChannels)) {
1125
- const availableChannel = profile.availableChannels[availableChannelName];
1126
- for (const channel of mode.channels) {
1127
- // check for string channel. It can get creepy for matrix modes
1128
- if (typeof channel === 'string') {
1129
- const modeChannel = channel;
1130
- // don't check the fine channels. only add the coarse channel.
1131
- if (modeChannel === availableChannelName) {
1132
- const cachedFixtureChannel = new CachedFixtureChannel();
1133
- cachedFixtureChannel.channel = availableChannel;
1134
- cachedFixtureChannel.name = availableChannelName;
1135
- cachedFixtureChannel.capabilities = this.getCapabilitiesByChannel(cachedFixtureChannel.channel, availableChannelName, profile);
1136
- const defaultValue = this.getDefaultValueByChannel(cachedFixtureChannel.channel);
1137
- if (defaultValue) {
1138
- cachedFixtureChannel.defaultValue = defaultValue;
1454
+ for (const channel of mode.channels) {
1455
+ if (channel.name && !pixelKey) {
1456
+ // direct reference to a channel
1457
+ // don't check the fine channels. only add the coarse channel.
1458
+ let channelFound = false;
1459
+ for (const availableChannelName of Object.keys(profile.availableChannels)) {
1460
+ if (channel.name === availableChannelName) {
1461
+ const availableChannel = profile.availableChannels[availableChannelName];
1462
+ this.addCachedChannel(channels, availableChannel, availableChannelName, null, profile);
1463
+ }
1464
+ }
1465
+ // check the template channels, if not found in the available channels
1466
+ if (!channelFound) {
1467
+ for (const templateChannelName of Object.keys(profile.templateChannels)) {
1468
+ let existingPixelKeys = this.getAllPixelKeys(profile).concat(this.getAllPixelGroups(profile));
1469
+ for (const existingPixelKey of existingPixelKeys) {
1470
+ const channelName = this.getChannelNameWithPixelKey(templateChannelName, existingPixelKey);
1471
+ if (channel.name === channelName) {
1472
+ const templateChannel = profile.templateChannels[templateChannelName];
1473
+ this.addCachedChannel(channels, templateChannel, channelName, existingPixelKey, profile);
1474
+ }
1139
1475
  }
1140
- cachedFixtureChannel.maxValue = this.getMaxValueByChannel(cachedFixtureChannel.channel);
1141
- cachedFixtureChannel.colorWheel = this.getColorWheelByChannel(cachedFixtureChannel, profile);
1142
- channels.push(cachedFixtureChannel);
1143
1476
  }
1144
1477
  }
1145
- else {
1146
- // null may be passed as a placeholder for an undefined channel
1147
- channels.push(new CachedFixtureChannel());
1478
+ }
1479
+ else {
1480
+ // reference a channel through a pixel matrix
1481
+ const availablePixelKeys = this.getPixelKeysInOrder(profile, channel.repeatFor);
1482
+ if (channel.channelOrder === 'perPixel') {
1483
+ // each channel for each pixel
1484
+ for (const availablePixelKey of availablePixelKeys) {
1485
+ if (availablePixelKey === pixelKey) {
1486
+ for (const modeTemplateChannelName of channel.templateChannels) {
1487
+ for (const templateChannelName of Object.keys(profile.templateChannels)) {
1488
+ // don't check the fine channels. only add the coarse channel.
1489
+ if (modeTemplateChannelName === templateChannelName) {
1490
+ const templateChannel = profile.templateChannels[templateChannelName];
1491
+ this.addCachedChannel(channels, templateChannel, templateChannelName, availablePixelKey, profile);
1492
+ }
1493
+ }
1494
+ }
1495
+ }
1496
+ }
1497
+ }
1498
+ else if (channel.channelOrder === 'perChannel') {
1499
+ // each pixel for each channel
1500
+ for (const modeTemplateChannelName of channel.templateChannels) {
1501
+ for (const availablePixelKey of availablePixelKeys) {
1502
+ if (availablePixelKey === pixelKey) {
1503
+ for (const templateChannelName of Object.keys(profile.templateChannels)) {
1504
+ // don't check the fine channels. only add the coarse channel.
1505
+ if (modeTemplateChannelName === templateChannelName) {
1506
+ const templateChannel = profile.templateChannels[templateChannelName];
1507
+ this.addCachedChannel(channels, templateChannel, templateChannelName, availablePixelKey, profile);
1508
+ }
1509
+ }
1510
+ }
1511
+ }
1512
+ }
1148
1513
  }
1149
1514
  }
1150
1515
  }
1151
1516
  return channels;
1152
1517
  }
1518
+ fixtureGetUniquePixelKeys(fixture) {
1519
+ let pixelKeys = new Set();
1520
+ let profile = this.getProfileByUuid(fixture.profileUuid);
1521
+ let mode = this.getModeByFixture(profile, fixture);
1522
+ // add the unique pixel keys
1523
+ for (let channel of mode.channels) {
1524
+ this.getPixelKeysInOrder(profile, channel.repeatFor).forEach((str) => {
1525
+ pixelKeys.add(str);
1526
+ });
1527
+ }
1528
+ return Array.from(pixelKeys);
1529
+ }
1530
+ // does the fixture have a general channel without reference to specific pixel keys in the current mode?
1531
+ fixtureHasGeneralChannel(fixture) {
1532
+ let profile = this.getProfileByUuid(fixture.profileUuid);
1533
+ let mode = this.getModeByFixture(profile, fixture);
1534
+ // add the unique pixel keys
1535
+ for (let channel of mode.channels) {
1536
+ if (this.getPixelKeysInOrder(profile, channel.repeatFor).length === 0) {
1537
+ return true;
1538
+ }
1539
+ }
1540
+ return false;
1541
+ }
1153
1542
  updateCachedFixtures() {
1154
1543
  // calculate some frequently used values as a cache to save cpu time
1155
1544
  // afterwards
1156
1545
  this.cachedFixtures = [];
1157
1546
  for (const fixture of this.projectService.project.fixtures) {
1158
- const cachedFixture = new CachedFixture();
1159
- cachedFixture.fixture = fixture;
1160
- cachedFixture.profile = this.getProfileByUuid(fixture.profileUuid);
1161
- cachedFixture.mode = this.getModeByFixture(cachedFixture.profile, fixture);
1162
- cachedFixture.channels = this.getCachedChannels(cachedFixture.profile, cachedFixture.mode);
1163
- this.cachedFixtures.push(cachedFixture);
1547
+ if (this.fixtureHasGeneralChannel(fixture)) {
1548
+ const cachedFixture = new CachedFixture();
1549
+ cachedFixture.fixture = fixture;
1550
+ cachedFixture.profile = this.getProfileByUuid(fixture.profileUuid);
1551
+ cachedFixture.mode = this.getModeByFixture(cachedFixture.profile, fixture);
1552
+ cachedFixture.channels = this.getCachedChannels(cachedFixture.profile, cachedFixture.mode, null);
1553
+ this.cachedFixtures.push(cachedFixture);
1554
+ }
1555
+ const pixelKeys = this.fixtureGetUniquePixelKeys(fixture);
1556
+ for (let pixelKey of pixelKeys) {
1557
+ const cachedFixture = new CachedFixture();
1558
+ cachedFixture.fixture = fixture;
1559
+ cachedFixture.pixelKey = pixelKey;
1560
+ cachedFixture.profile = this.getProfileByUuid(fixture.profileUuid);
1561
+ cachedFixture.mode = this.getModeByFixture(cachedFixture.profile, fixture);
1562
+ cachedFixture.channels = this.getCachedChannels(cachedFixture.profile, cachedFixture.mode, pixelKey);
1563
+ this.cachedFixtures.push(cachedFixture);
1564
+ }
1164
1565
  }
1165
1566
  }
1166
1567
  capabilitiesMatch(type1, type2, color1, color2, wheel1, wheel2, profileUuid1, profileUuid2) {
@@ -1207,11 +1608,13 @@ class FixtureService {
1207
1608
  for (let i = 0; i < 512; i++) {
1208
1609
  let occupiedChannels = 0;
1209
1610
  for (const fixture of fixturePool) {
1611
+ const profile = this.getProfileByUuid(fixture.profileUuid);
1210
1612
  const mode = this.getModeByFixture(this.getProfileByUuid(fixture.profileUuid), fixture);
1211
- if (i >= fixture.dmxFirstChannel && i < fixture.dmxFirstChannel + mode.channels.length) {
1613
+ const channelCount = this.getModeChannelCount(profile, mode);
1614
+ if (i >= fixture.dmxFirstChannel && i < fixture.dmxFirstChannel + channelCount) {
1212
1615
  // this channel is already occupied by a fixture -> move forward to the end of the fixture
1213
- if (mode.channels.length > occupiedChannels) {
1214
- occupiedChannels = mode.channels.length - (i - fixture.dmxFirstChannel);
1616
+ if (channelCount > occupiedChannels) {
1617
+ occupiedChannels = channelCount - (i - fixture.dmxFirstChannel);
1215
1618
  }
1216
1619
  }
1217
1620
  }
@@ -1252,8 +1655,9 @@ class FixtureService {
1252
1655
  else {
1253
1656
  fixture.modeShortName = profile.modes[0].shortName || profile.modes[0].name;
1254
1657
  }
1255
- const mode = this.getModeByFixture(this.getProfileByUuid(fixture.profileUuid), fixture);
1256
- const firstChannel = this.getNextFreeDmxChannel(fixturePool, mode.channels.length);
1658
+ const mode = this.getModeByFixture(profile, fixture);
1659
+ const channelCount = this.getModeChannelCount(profile, mode);
1660
+ const firstChannel = this.getNextFreeDmxChannel(fixturePool, channelCount);
1257
1661
  if (firstChannel >= 0) {
1258
1662
  fixture.dmxFirstChannel = firstChannel;
1259
1663
  fixturePool.push(fixture);
@@ -1268,7 +1672,7 @@ class FixtureService {
1268
1672
  });
1269
1673
  }
1270
1674
  }
1271
- static { this.ɵfac = function FixtureService_Factory(t) { return new (t || FixtureService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(ProjectService), i0.ɵɵinject(i2.TranslateService), i0.ɵɵinject(i3.ToastrService), i0.ɵɵinject(UuidService)); }; }
1675
+ static { this.ɵfac = function FixtureService_Factory(t) { return new (t || FixtureService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(ProjectService), i0.ɵɵinject(i2.TranslateService), i0.ɵɵinject(i3$1.ToastrService), i0.ɵɵinject(UuidService)); }; }
1272
1676
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: FixtureService, factory: FixtureService.ɵfac, providedIn: 'root' }); }
1273
1677
  }
1274
1678
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureService, [{
@@ -1276,7 +1680,7 @@ class FixtureService {
1276
1680
  args: [{
1277
1681
  providedIn: 'root',
1278
1682
  }]
1279
- }], () => [{ type: i1.HttpClient }, { type: ProjectService }, { type: i2.TranslateService }, { type: i3.ToastrService }, { type: UuidService }], null); })();
1683
+ }], () => [{ type: i1.HttpClient }, { type: ProjectService }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: UuidService }], null); })();
1280
1684
 
1281
1685
  class PreviewMeshService {
1282
1686
  constructor() {
@@ -1364,6 +1768,7 @@ class ConfigService {
1364
1768
  this.localProfiles = false;
1365
1769
  this.intro = false;
1366
1770
  this.uniqueProjectNames = false;
1771
+ this.dropzoneChunking = true;
1367
1772
  this.menuHeightChanged = new Subject();
1368
1773
  }
1369
1774
  static { this.ɵfac = function ConfigService_Factory(t) { return new (t || ConfigService)(); }; }
@@ -1415,7 +1820,18 @@ class PresetService {
1415
1820
  }
1416
1821
  }
1417
1822
  }
1418
- fixtureIsSelected(fixture, preset) {
1823
+ fixtureUuidAndPixelKeyEquals(fixtureUuid1, fixtureUuid2, pixelKey1, pixelKey2) {
1824
+ return fixtureUuid1 === fixtureUuid2 && ((!pixelKey1 && !pixelKey2) || pixelKey1 === pixelKey2);
1825
+ }
1826
+ getPresetFixture(preset, fixtureUuid, pixelKey) {
1827
+ for (const fixture of preset.fixtures) {
1828
+ if (this.fixtureUuidAndPixelKeyEquals(fixture.fixtureUuid, fixtureUuid, fixture.pixelKey, pixelKey)) {
1829
+ return fixture;
1830
+ }
1831
+ }
1832
+ return null;
1833
+ }
1834
+ fixtureIsSelected(fixture, pixelKey, preset) {
1419
1835
  // is the passed fixture selected in the passed/currently selected preset?
1420
1836
  if (!preset) {
1421
1837
  if (this.selectedPreset) {
@@ -1425,31 +1841,37 @@ class PresetService {
1425
1841
  return false;
1426
1842
  }
1427
1843
  }
1428
- for (const selectedFixtureUuid of preset.fixtureUuids) {
1429
- if (selectedFixtureUuid === fixture.uuid) {
1430
- return true;
1431
- }
1844
+ const presetFixture = this.getPresetFixture(preset, fixture.uuid, pixelKey);
1845
+ if (presetFixture) {
1846
+ return true;
1432
1847
  }
1433
1848
  return false;
1434
1849
  }
1435
- switchFixtureSelection(fixture) {
1850
+ switchFixtureSelection(fixture, pixelKey) {
1436
1851
  if (!this.selectedPreset) {
1437
1852
  return;
1438
1853
  }
1439
1854
  // select all fixtures at the specified start channel or unselect them,
1440
1855
  // if already selected
1441
- if (this.fixtureIsSelected(fixture)) {
1442
- for (let i = this.selectedPreset.fixtureUuids.length - 1; i >= 0; i--) {
1443
- const projectFixture = this.fixtureService.getFixtureByUuid(this.selectedPreset.fixtureUuids[i]);
1444
- if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
1445
- this.selectedPreset.fixtureUuids.splice(i, 1);
1856
+ if (this.fixtureIsSelected(fixture, pixelKey)) {
1857
+ for (let i = this.selectedPreset.fixtures.length - 1; i >= 0; i--) {
1858
+ const projectFixture = this.fixtureService.getFixtureByUuid(this.selectedPreset.fixtures[i].fixtureUuid);
1859
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
1860
+ ((!this.selectedPreset.fixtures[i].pixelKey && !pixelKey) || this.selectedPreset.fixtures[i].pixelKey === pixelKey)) {
1861
+ this.selectedPreset.fixtures.splice(i, 1);
1446
1862
  }
1447
1863
  }
1448
1864
  }
1449
1865
  else {
1450
- for (const projectFixture of this.projectService.project.fixtures) {
1451
- if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
1452
- this.selectedPreset.fixtureUuids.push(projectFixture.uuid);
1866
+ for (const projectPresetFixture of this.projectService.project.presetFixtures) {
1867
+ if ((!projectPresetFixture.pixelKey && !pixelKey) || projectPresetFixture.pixelKey === pixelKey) {
1868
+ const projectFixture = this.fixtureService.getFixtureByUuid(projectPresetFixture.fixtureUuid);
1869
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
1870
+ const presetFixture = new PresetFixture();
1871
+ presetFixture.fixtureUuid = projectPresetFixture.fixtureUuid;
1872
+ presetFixture.pixelKey = pixelKey;
1873
+ this.selectedPreset.fixtures.push(presetFixture);
1874
+ }
1453
1875
  }
1454
1876
  }
1455
1877
  }
@@ -1459,8 +1881,21 @@ class PresetService {
1459
1881
  return;
1460
1882
  }
1461
1883
  for (const fixture of this.projectService.project.fixtures) {
1462
- if (!this.fixtureIsSelected(fixture)) {
1463
- this.selectedPreset.fixtureUuids.push(fixture.uuid);
1884
+ if (this.fixtureService.fixtureHasGeneralChannel(fixture)) {
1885
+ if (!this.fixtureIsSelected(fixture, null)) {
1886
+ const presetFixture = new PresetFixture();
1887
+ presetFixture.fixtureUuid = fixture.uuid;
1888
+ this.selectedPreset.fixtures.push(presetFixture);
1889
+ }
1890
+ }
1891
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
1892
+ for (const pixelKey of pixelKeys) {
1893
+ if (!this.fixtureIsSelected(fixture, pixelKey)) {
1894
+ const presetFixture = new PresetFixture();
1895
+ presetFixture.fixtureUuid = fixture.uuid;
1896
+ presetFixture.pixelKey = pixelKey;
1897
+ this.selectedPreset.fixtures.push(presetFixture);
1898
+ }
1464
1899
  }
1465
1900
  }
1466
1901
  }
@@ -1468,16 +1903,16 @@ class PresetService {
1468
1903
  if (!this.selectedPreset) {
1469
1904
  return;
1470
1905
  }
1471
- this.selectedPreset.fixtureUuids = [];
1906
+ this.selectedPreset.fixtures = [];
1472
1907
  }
1473
1908
  removeDeletedFixtures() {
1474
1909
  // after changing the configuration in the fixture pool, we might need to
1475
1910
  // delete some fixtures
1476
1911
  for (const preset of this.projectService.project.presets) {
1477
- for (let i = preset.fixtureUuids.length - 1; i >= 0; i--) {
1478
- const presetFixture = this.fixtureService.getFixtureByUuid(preset.fixtureUuids[i]);
1912
+ for (let i = preset.fixtures.length - 1; i >= 0; i--) {
1913
+ const presetFixture = this.fixtureService.getFixtureByUuid(preset.fixtures[i].fixtureUuid);
1479
1914
  if (!presetFixture) {
1480
- preset.fixtureUuids.splice(i, 1);
1915
+ preset.fixtures.splice(i, 1);
1481
1916
  }
1482
1917
  }
1483
1918
  }
@@ -1486,11 +1921,15 @@ class PresetService {
1486
1921
  // after changing the configuration in the fixture pool, we might need to
1487
1922
  // select some more fixtures on the same channel as already selected ones
1488
1923
  for (const preset of this.projectService.project.presets) {
1489
- for (let i = preset.fixtureUuids.length - 1; i >= 0; i--) {
1490
- const presetFixture = this.fixtureService.getFixtureByUuid(preset.fixtureUuids[i]);
1924
+ for (let presetFixture of preset.fixtures) {
1925
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
1491
1926
  for (const projectFixture of this.projectService.project.fixtures) {
1492
- if (projectFixture.dmxFirstChannel === presetFixture.dmxFirstChannel && !this.fixtureIsSelected(projectFixture, preset)) {
1493
- preset.fixtureUuids.push(projectFixture.uuid);
1927
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
1928
+ !this.fixtureIsSelected(projectFixture, presetFixture.pixelKey, preset)) {
1929
+ const newPresetFixture = new PresetFixture();
1930
+ newPresetFixture.fixtureUuid = projectFixture.uuid;
1931
+ newPresetFixture.pixelKey = presetFixture.pixelKey;
1932
+ preset.fixtures.push(newPresetFixture);
1494
1933
  }
1495
1934
  }
1496
1935
  }
@@ -1592,8 +2031,8 @@ class PresetService {
1592
2031
  }
1593
2032
  hasCapabilityType(type) {
1594
2033
  // there is at least one channel with at least one intensity capability
1595
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1596
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
2034
+ for (const projectFixture of this.selectedPreset.fixtures) {
2035
+ const fixture = this.fixtureService.getCachedFixtureByUuid(projectFixture.fixtureUuid, projectFixture.pixelKey);
1597
2036
  for (const channel of fixture.channels) {
1598
2037
  if (channel.channel) {
1599
2038
  for (const capability of channel.capabilities) {
@@ -1624,8 +2063,8 @@ class PresetService {
1624
2063
  return true;
1625
2064
  }
1626
2065
  // a color wheel is involved
1627
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1628
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
2066
+ for (const projectFixture of this.selectedPreset.fixtures) {
2067
+ const fixture = this.fixtureService.getCachedFixtureByUuid(projectFixture.fixtureUuid, projectFixture.pixelKey);
1629
2068
  for (const channel of fixture.channels) {
1630
2069
  if (channel.colorWheel) {
1631
2070
  return true;
@@ -1678,13 +2117,14 @@ class PresetService {
1678
2117
  this.projectService.project.presets.splice(highestSelectedPresetIndex, 0, preset);
1679
2118
  this.selectPreset(highestSelectedPresetIndex);
1680
2119
  }
2120
+ // return all fixture profiles used in the current preset selection
1681
2121
  getSelectedProfiles() {
1682
2122
  const profiles = [];
1683
2123
  if (!this.selectedPreset) {
1684
2124
  return profiles;
1685
2125
  }
1686
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1687
- const fixture = this.fixtureService.getFixtureByUuid(fixtureUuid);
2126
+ for (const presetFixture of this.selectedPreset.fixtures) {
2127
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
1688
2128
  const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
1689
2129
  if (profiles.indexOf(profile) < 0) {
1690
2130
  profiles.push(profile);
@@ -1692,24 +2132,38 @@ class PresetService {
1692
2132
  }
1693
2133
  return profiles;
1694
2134
  }
2135
+ // given a list of fixture profiles, return all available channels based on the currently selected fixtures in the preset
1695
2136
  getSelectedProfileChannels(selectedProfiles) {
1696
- const availableChannels = new Map();
1697
2137
  const calculatedProfileModes = new Map();
2138
+ const availableChannels = new Map();
2139
+ // calculate all modes for each profile
1698
2140
  for (const profile of selectedProfiles) {
1699
- const modes = [];
1700
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1701
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
1702
- if (modes.indexOf(fixture.mode) < 0) {
1703
- modes.push(fixture.mode);
2141
+ const modeAndPixelKeys = [];
2142
+ // loop over the project fixtures to keep the order
2143
+ for (let projectFixture of this.projectService.project.presetFixtures) {
2144
+ for (const presetFixture of this.selectedPreset.fixtures) {
2145
+ if (projectFixture.fixtureUuid === presetFixture.fixtureUuid &&
2146
+ ((!projectFixture.pixelKey && !presetFixture.pixelKey) || projectFixture.pixelKey === presetFixture.pixelKey)) {
2147
+ const fixture = this.fixtureService.getCachedFixtureByUuid(presetFixture.fixtureUuid, presetFixture.pixelKey);
2148
+ if (fixture.profile.uuid === profile.uuid) {
2149
+ const exists = modeAndPixelKeys.some((item) => (item.mode === fixture.mode && !item.pixelKey && !fixture.pixelKey) || item.pixelKey === fixture.pixelKey);
2150
+ if (!exists) {
2151
+ modeAndPixelKeys.push({
2152
+ mode: fixture.mode,
2153
+ pixelKey: presetFixture.pixelKey,
2154
+ });
2155
+ }
2156
+ }
2157
+ }
1704
2158
  }
2159
+ calculatedProfileModes.set(profile, modeAndPixelKeys);
1705
2160
  }
1706
- calculatedProfileModes.set(profile, modes);
1707
2161
  }
1708
- // calculate all required channels from the modes
1709
- calculatedProfileModes.forEach((modes, profile) => {
2162
+ // calculate all channels from the modes
2163
+ calculatedProfileModes.forEach((modeAndPixelKeys, profile) => {
1710
2164
  const profileChannels = [];
1711
- for (const mode of modes) {
1712
- const channels = this.fixtureService.getCachedChannels(profile, mode);
2165
+ for (const modeAndPixelKey of modeAndPixelKeys) {
2166
+ const channels = this.fixtureService.getCachedChannels(profile, modeAndPixelKey.mode, modeAndPixelKey.pixelKey);
1713
2167
  for (const channel of channels) {
1714
2168
  // only add the channel, if no channel with the same name has already been added
1715
2169
  // (e.g. a fine channel)
@@ -2624,34 +3078,12 @@ class TimelineService {
2624
3078
  }]
2625
3079
  }], () => [{ type: SceneService }, { type: PresetService }, { type: ProjectService }, { type: i1.HttpClient }, { type: ConfigService }], null); })();
2626
3080
 
2627
- class UniverseService {
2628
- constructor() {
2629
- this.universes = [];
2630
- }
2631
- getUniverseByUuid(uuid) {
2632
- for (const universe of this.universes) {
2633
- if (universe.uuid === uuid) {
2634
- return universe;
2635
- }
2636
- }
2637
- }
2638
- static { this.ɵfac = function UniverseService_Factory(t) { return new (t || UniverseService)(); }; }
2639
- static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UniverseService, factory: UniverseService.ɵfac, providedIn: 'root' }); }
2640
- }
2641
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UniverseService, [{
2642
- type: Injectable,
2643
- args: [{
2644
- providedIn: 'root',
2645
- }]
2646
- }], () => [], null); })();
2647
-
2648
3081
  class PreviewService {
2649
- constructor(presetService, fixtureService, sceneService, timelineService, universeService, projectService) {
3082
+ constructor(presetService, fixtureService, sceneService, timelineService, projectService) {
2650
3083
  this.presetService = presetService;
2651
3084
  this.fixtureService = fixtureService;
2652
3085
  this.sceneService = sceneService;
2653
3086
  this.timelineService = timelineService;
2654
- this.universeService = universeService;
2655
3087
  this.projectService = projectService;
2656
3088
  this.doUpdateFixtureSetup = new Subject();
2657
3089
  this.stageMeshes = [];
@@ -2740,26 +3172,36 @@ class PreviewService {
2740
3172
  existingChannelValues.push(fixtureChannelValue);
2741
3173
  }
2742
3174
  // Get the fixture index inside the passed preset (used for chasing)
2743
- getFixtureIndex(preset, fixtureUuid) {
3175
+ getFixtureIndex(preset, fixtureUuid, pixelKey) {
2744
3176
  let index = 0;
2745
- const countedDmxChannels = [];
3177
+ const countedFirstDmxChannelPixelKey = [];
3178
+ if (!this.presetService.getPresetFixture(preset, fixtureUuid, pixelKey)) {
3179
+ // fixture is not in preset
3180
+ return undefined;
3181
+ }
2746
3182
  // Loop over the global fixtures to retain the order
2747
- for (const fixture of this.projectService.project.fixtures) {
2748
- for (const presetFixtureUuid of preset.fixtureUuids) {
2749
- if (presetFixtureUuid === fixture.uuid) {
2750
- if (fixture.uuid === fixtureUuid) {
3183
+ for (const projectFixture of this.projectService.project.presetFixtures) {
3184
+ for (const presetFixture of preset.fixtures) {
3185
+ if (this.presetService.fixtureUuidAndPixelKeyEquals(projectFixture.fixtureUuid, presetFixture.fixtureUuid, projectFixture.pixelKey, presetFixture.pixelKey)) {
3186
+ if (this.presetService.fixtureUuidAndPixelKeyEquals(projectFixture.fixtureUuid, fixtureUuid, projectFixture.pixelKey, pixelKey)) {
2751
3187
  return index;
2752
3188
  }
3189
+ const fixture = this.fixtureService.getFixtureByUuid(projectFixture.fixtureUuid);
3190
+ const firstDmxChannelAndFixtureUuid = {
3191
+ firstDmxChannel: fixture.dmxFirstChannel,
3192
+ pixelKey: projectFixture.pixelKey,
3193
+ };
3194
+ const exists = countedFirstDmxChannelPixelKey.some((item) => item.firstDmxChannel === firstDmxChannelAndFixtureUuid.firstDmxChannel &&
3195
+ ((!item.pixelKey && !firstDmxChannelAndFixtureUuid.pixelKey) || item.pixelKey === firstDmxChannelAndFixtureUuid.pixelKey));
2753
3196
  // don't count fixtures on the same channel as already counted ones
2754
- if (!countedDmxChannels.includes(fixture.dmxFirstChannel)) {
2755
- countedDmxChannels.push(fixture.dmxFirstChannel);
3197
+ if (!exists) {
2756
3198
  index++;
3199
+ countedFirstDmxChannelPixelKey.push(firstDmxChannelAndFixtureUuid);
2757
3200
  }
2758
3201
  break;
2759
3202
  }
2760
3203
  }
2761
3204
  }
2762
- // Not found in the preset
2763
3205
  return undefined;
2764
3206
  }
2765
3207
  getPresetIntensity(preset, timeMillis) {
@@ -2951,7 +3393,7 @@ class PreviewService {
2951
3393
  }
2952
3394
  // return all fixture uuids with their corresponding channel values
2953
3395
  getChannelValues(timeMillis, presets) {
2954
- // Loop over all relevant presets and calc the property values from the presets (capabilities and effects)
3396
+ // Loop over all relevant presets and calc the property values from the presets (capabilities, channels and effects)
2955
3397
  const calculatedFixtures = new Map();
2956
3398
  for (let i = 0; i < this.fixtureService.cachedFixtures.length; i++) {
2957
3399
  const cachedFixture = this.fixtureService.cachedFixtures[i];
@@ -2977,7 +3419,7 @@ class PreviewService {
2977
3419
  }
2978
3420
  for (const preset of presets) {
2979
3421
  // search for this fixture in the preset and get it's preset-specific index (for chasing effects)
2980
- const fixtureIndex = this.getFixtureIndex(preset.preset, cachedFixture.fixture.uuid);
3422
+ const fixtureIndex = this.getFixtureIndex(preset.preset, cachedFixture.fixture.uuid, cachedFixture.pixelKey);
2981
3423
  if (fixtureIndex >= 0) {
2982
3424
  // this fixture is also in the preset -> mix the required values (overwrite existing values,
2983
3425
  // if set multiple times)
@@ -2993,48 +3435,10 @@ class PreviewService {
2993
3435
  }
2994
3436
  return calculatedFixtures;
2995
3437
  }
2996
- setUniverseValues(fixtures, masterDimmerValue) {
2997
- // TODO only, if monitoring is enabled
2998
- return;
2999
- // Reset all DMX universes
3000
- for (const universe of this.universeService.universes) {
3001
- universe.channelValues = [];
3002
- for (let i = 0; i < 512; i++) {
3003
- universe.channelValues.push(0);
3004
- }
3005
- }
3006
- // loop over each fixture
3007
- fixtures.forEach((channelValues, cachedFixture) => {
3008
- // TODO Get the correct universe for this fixture
3009
- const universe = this.universeService.getUniverseByUuid(cachedFixture.fixture.dmxUniverseUuid);
3010
- // loop over each channel for this fixture
3011
- for (let channelIndex = 0; channelIndex < cachedFixture.mode.channels.length; channelIndex++) {
3012
- const channelObj = cachedFixture.mode.channels[channelIndex];
3013
- if (typeof channelObj === 'string') {
3014
- const channelName = channelObj;
3015
- // match this mode channel with a channel value
3016
- for (const channelValue of channelValues) {
3017
- const channel = this.fixtureService.getChannelByName(cachedFixture, channelName);
3018
- if (channel && channel.channel) {
3019
- const fineIndex = channel.channel.fineChannelAliases.indexOf(channelName);
3020
- if (channel.name === channelValue.channelName || fineIndex > -1) {
3021
- const universeChannel = cachedFixture.fixture.dmxFirstChannel + channelIndex;
3022
- const dmxValue = Math.floor(channelValue.value / Math.pow(256, channel.channel.fineChannelAliases.length - (fineIndex + 1))) % 256;
3023
- // TODO
3024
- break;
3025
- }
3026
- }
3027
- }
3028
- }
3029
- }
3030
- });
3031
- }
3032
- fixtureIsSelected(uuid, presets) {
3438
+ fixtureIsSelected(uuid, pixelKey, presets) {
3033
3439
  for (const preset of presets) {
3034
- for (const fixtureUuid of preset.preset.fixtureUuids) {
3035
- if (fixtureUuid === uuid) {
3036
- return true;
3037
- }
3440
+ if (this.presetService.getPresetFixture(preset.preset, uuid, pixelKey)) {
3441
+ return true;
3038
3442
  }
3039
3443
  }
3040
3444
  return false;
@@ -3111,7 +3515,7 @@ class PreviewService {
3111
3515
  this.scene.add(mesh);
3112
3516
  this.stageMeshes.push(mesh);
3113
3517
  }
3114
- static { this.ɵfac = function PreviewService_Factory(t) { return new (t || PreviewService)(i0.ɵɵinject(PresetService), i0.ɵɵinject(FixtureService), i0.ɵɵinject(SceneService), i0.ɵɵinject(TimelineService), i0.ɵɵinject(UniverseService), i0.ɵɵinject(ProjectService)); }; }
3518
+ static { this.ɵfac = function PreviewService_Factory(t) { return new (t || PreviewService)(i0.ɵɵinject(PresetService), i0.ɵɵinject(FixtureService), i0.ɵɵinject(SceneService), i0.ɵɵinject(TimelineService), i0.ɵɵinject(ProjectService)); }; }
3115
3519
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PreviewService, factory: PreviewService.ɵfac, providedIn: 'root' }); }
3116
3520
  }
3117
3521
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PreviewService, [{
@@ -3119,11 +3523,13 @@ class PreviewService {
3119
3523
  args: [{
3120
3524
  providedIn: 'root',
3121
3525
  }]
3122
- }], () => [{ type: PresetService }, { type: FixtureService }, { type: SceneService }, { type: TimelineService }, { type: UniverseService }, { type: ProjectService }], null); })();
3526
+ }], () => [{ type: PresetService }, { type: FixtureService }, { type: SceneService }, { type: TimelineService }, { type: ProjectService }], null); })();
3123
3527
 
3124
3528
  class Fixture3d {
3125
3529
  constructor(fixtureService, fixture, scene) {
3126
3530
  this.fixtureService = fixtureService;
3531
+ this.pointLightMaxIntensity = 2;
3532
+ this.spotLightLightMaxIntensity = 10;
3127
3533
  this.fixtureHasDimmer = false;
3128
3534
  this.fixtureHasColorWheel = false;
3129
3535
  this.fixtureHasColor = false;
@@ -3156,6 +3562,29 @@ class Fixture3d {
3156
3562
  }
3157
3563
  }
3158
3564
  }
3565
+ createObjects() {
3566
+ // Add the spotlight
3567
+ this.spotLight = new THREE.SpotLight(0xffffff, 50000);
3568
+ this.spotLight.angle = 2;
3569
+ this.spotLight.penumbra = 1;
3570
+ this.spotLight.decay = 0.01;
3571
+ this.spotLight.distance = 0;
3572
+ this.spotLight.intensity = 1;
3573
+ this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3574
+ this.scene.add(this.spotLightHelper);
3575
+ const spotLightTarget = new THREE.Object3D();
3576
+ this.spotLight.target = spotLightTarget;
3577
+ this.spotlightGroup = new THREE.Object3D();
3578
+ this.spotlightGroup.add(this.spotLight);
3579
+ this.spotlightGroup.add(spotLightTarget);
3580
+ this.spotLight.position.set(0, -1.4, 0);
3581
+ spotLightTarget.position.set(0, -10, 0);
3582
+ this.createSpotLightBeam();
3583
+ // Add the point light for the surrounding light
3584
+ this.pointLight = new THREE.PointLight(0xffffff, 500, 0, 0.1);
3585
+ this.spotlightGroup.add(this.pointLight);
3586
+ this.pointLight.position.set(0, -1.4, 0);
3587
+ }
3159
3588
  getCapabilityInValue(channel, value) {
3160
3589
  for (const capability of channel.capabilities) {
3161
3590
  if (capability.capability.dmxRange.length === 0 ||
@@ -3230,6 +3659,22 @@ class Fixture3d {
3230
3659
  }
3231
3660
  }
3232
3661
  }
3662
+ // Apply the colors and intensities
3663
+ // Apply the dimmer value
3664
+ // Take the color into account for the beam (don't show a black beam)
3665
+ const color = new THREE.Color('rgb(' + this.colorRed + ', ' + this.colorGreen + ', ' + this.colorBlue + ')');
3666
+ const intensityColor = Math.max(this.colorRed, this.colorGreen, this.colorBlue);
3667
+ if (this.pointLight) {
3668
+ this.pointLight.color = color;
3669
+ this.pointLight.intensity = this.pointLightMaxIntensity * this.dimmer;
3670
+ }
3671
+ if (this.spotLight) {
3672
+ this.spotLight.color = color;
3673
+ this.spotLightBeam.material.uniforms.lightColor.value = color;
3674
+ this.spotLightBeam.material.uniforms.opacity.value = Math.min(intensityColor, this.dimmer);
3675
+ this.spotLight.intensity = this.spotLightLightMaxIntensity * this.dimmer;
3676
+ this.spotLightBeam.material.uniforms.spotPosition.value = this.spotlightGroup.position;
3677
+ }
3233
3678
  }
3234
3679
  updatePosition(object) {
3235
3680
  // Update the position
@@ -3263,62 +3708,66 @@ class Fixture3d {
3263
3708
  }
3264
3709
  }
3265
3710
  }
3266
- destroy() {
3267
- this.selectedMaterial.dispose();
3268
- }
3269
- }
3270
-
3271
- class ColorChanger3d extends Fixture3d {
3272
3711
  atmosphereMat() {
3273
- const vertexShader = [
3274
- 'varying vec3 vVertexWorldPosition;',
3275
- 'varying vec3 vVertexNormal;',
3276
- 'void main(){',
3277
- ' vVertexNormal = normalize(normalMatrix * normal);',
3278
- ' vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;',
3279
- ' // set gl_Position',
3280
- ' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
3281
- '}',
3282
- ].join('\n');
3283
- const fragmentShader = [
3284
- 'uniform vec3 glowColor;',
3285
- 'uniform float coeficient;',
3286
- 'uniform float power;',
3287
- 'uniform float opacity;',
3288
- 'varying vec3 vVertexNormal;',
3289
- 'varying vec3 vVertexWorldPosition;',
3290
- 'void main(){',
3291
- ' vec3 worldCameraToVertex= vVertexWorldPosition - cameraPosition;',
3292
- ' vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;',
3293
- ' viewCameraToVertex = normalize(viewCameraToVertex);',
3294
- ' float intensity = pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);',
3295
- ' gl_FragColor = vec4(glowColor, intensity * opacity);',
3296
- '}',
3297
- ].join('\n');
3298
- // create custom material from the shader code above
3299
- // that is within specially labeled script tags
3712
+ const vertexShader = `
3713
+ varying vec3 vNormal;
3714
+ varying vec3 vWorldPosition;
3715
+
3716
+ void main(){
3717
+ vNormal = normalize(normalMatrix * normal);
3718
+
3719
+ vec4 worldPosition = modelMatrix * vec4(position, 1.0);
3720
+ vWorldPosition = worldPosition.xyz;
3721
+
3722
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
3723
+ }`;
3724
+ const fragmentShader = `
3725
+ varying vec3 vNormal;
3726
+ varying vec3 vWorldPosition;
3727
+
3728
+ uniform vec3 lightColor;
3729
+ uniform float opacity;
3730
+ uniform vec3 spotPosition;
3731
+ uniform float attenuation;
3732
+ uniform float anglePower;
3733
+
3734
+ void main(){
3735
+ float intensity;
3736
+
3737
+ intensity = distance(vWorldPosition, spotPosition) / attenuation;
3738
+ intensity = 1.0 - clamp(intensity, 0.0, 1.0);
3739
+
3740
+ vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
3741
+ float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
3742
+ intensity = intensity * angleIntensity * opacity;
3743
+
3744
+ gl_FragColor = vec4(lightColor, intensity);
3745
+ }`;
3300
3746
  const material = new THREE.ShaderMaterial({
3301
3747
  uniforms: {
3302
- coeficient: {
3748
+ attenuation: {
3303
3749
  type: 'f',
3304
- value: 0.3,
3750
+ value: 800.0,
3305
3751
  },
3306
- power: {
3752
+ anglePower: {
3307
3753
  type: 'f',
3308
- value: 1.3,
3754
+ value: 2,
3309
3755
  },
3310
- opacity: {
3311
- type: 'f',
3312
- value: 1.0,
3756
+ spotPosition: {
3757
+ type: 'v3',
3758
+ value: new THREE.Vector3(0, 0, 0),
3313
3759
  },
3314
- glowColor: {
3760
+ lightColor: {
3315
3761
  type: 'c',
3316
3762
  value: new THREE.Color('white'),
3317
3763
  },
3764
+ opacity: {
3765
+ type: 'f',
3766
+ value: 1.0,
3767
+ },
3318
3768
  },
3319
3769
  vertexShader,
3320
3770
  fragmentShader,
3321
- // blending: THREE.AdditiveBlending,
3322
3771
  transparent: true,
3323
3772
  depthWrite: false,
3324
3773
  });
@@ -3328,45 +3777,35 @@ class ColorChanger3d extends Fixture3d {
3328
3777
  if (this.spotLightBeam) {
3329
3778
  this.spotlightGroup.remove(this.spotLightBeam);
3330
3779
  }
3331
- // TODO update the correct angle from the profile
3780
+ // TODO set the correct angle from the profile
3332
3781
  const beamAngleDegrees = 14;
3333
- const geometry = new THREE.CylinderGeometry(0.8, beamAngleDegrees * 1.2, 100, 64, 20, false);
3782
+ const geometry = new THREE.CylinderGeometry(0.1, beamAngleDegrees * 1.2, 100, 64, 20, false);
3334
3783
  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, -geometry.parameters.height / 2, 0));
3335
3784
  geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
3336
3785
  this.atmosphereMaterial = this.atmosphereMat();
3337
3786
  this.spotLightBeam = new THREE.Mesh(geometry, this.atmosphereMaterial);
3338
3787
  this.spotLightBeam.position.set(0, -0.02, 0);
3788
+ this.spotLightBeam.receiveShadow = false;
3789
+ this.spotLightBeam.castShadow = false;
3339
3790
  this.spotlightGroup.add(this.spotLightBeam);
3340
3791
  this.spotLightBeam.rotation.x = Math.PI / 2;
3341
3792
  }
3793
+ destroy() {
3794
+ this.selectedMaterial.dispose();
3795
+ this.atmosphereMaterial.dispose();
3796
+ }
3797
+ }
3798
+
3799
+ class ColorChanger3d extends Fixture3d {
3342
3800
  createObjects() {
3801
+ super.createObjects();
3343
3802
  this.material = new THREE.MeshLambertMaterial({
3344
3803
  color: 0x0d0d0d,
3345
3804
  emissive: 0x0d0d0d,
3346
3805
  });
3347
3806
  this.mesh.material = this.material;
3348
- // Add the spotlight
3349
- this.spotLight = new THREE.SpotLight(0xffffff, 1);
3350
- this.spotLight.angle = 0.244;
3351
- this.spotLight.penumbra = 0.5;
3352
- this.spotLight.decay = 2;
3353
- this.spotLight.distance = 60000;
3354
- this.spotLight.castShadow = false;
3355
- this.spotLight.intensity = 10;
3356
3807
  this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3357
3808
  // scene.add(this.spotLightHelper);
3358
- const spotLightTarget = new THREE.Object3D();
3359
- this.spotLight.target = spotLightTarget;
3360
- this.spotlightGroup.add(this.spotLight);
3361
- this.spotlightGroup.add(spotLightTarget);
3362
- this.spotLight.position.set(0, -1.4, 0);
3363
- spotLightTarget.position.set(0, -10, 0);
3364
- // Add the point light for the surrounding light
3365
- this.pointLight = new THREE.PointLight(0xffffff, 2, 1000);
3366
- this.spotlightGroup.add(this.pointLight);
3367
- this.pointLight.position.set(0, -1.4, 0);
3368
- // Add the light beam
3369
- this.createSpotLightBeam();
3370
3809
  this.objectGroup.add(this.spotlightGroup);
3371
3810
  this.objectGroup.add(this.mesh);
3372
3811
  // A moving head has about 32 cm in width
@@ -3376,10 +3815,7 @@ class ColorChanger3d extends Fixture3d {
3376
3815
  }
3377
3816
  constructor(fixtureService, previewMeshService, fixture, scene) {
3378
3817
  super(fixtureService, fixture, scene);
3379
- this.pointLightMaxIntensity = 2;
3380
- this.spotLightMaxIntensity = 5;
3381
3818
  this.objectGroup = new THREE.Object3D();
3382
- this.spotlightGroup = new THREE.Object3D();
3383
3819
  forkJoin([previewMeshService.getMesh('color-changer')])
3384
3820
  .pipe(map(([colorChanger]) => {
3385
3821
  this.mesh = colorChanger;
@@ -3391,10 +3827,10 @@ class ColorChanger3d extends Fixture3d {
3391
3827
  return this.objectGroup;
3392
3828
  }
3393
3829
  updatePreview(channelValues, masterDimmerValue) {
3394
- super.updatePreview(channelValues, masterDimmerValue);
3395
3830
  if (!this.isLoaded) {
3396
3831
  return;
3397
3832
  }
3833
+ super.updatePreview(channelValues, masterDimmerValue);
3398
3834
  this.updatePosition(this.objectGroup);
3399
3835
  // Update the material
3400
3836
  if (this.lastSelected !== this.isSelected) {
@@ -3411,110 +3847,18 @@ class ColorChanger3d extends Fixture3d {
3411
3847
  this.lastSelected = this.isSelected;
3412
3848
  }
3413
3849
  // Update the light helpers
3414
- this.spotLightHelper.update();
3415
- // Apply the colors
3416
- const color = new THREE.Color('rgb(' + this.colorRed + ', ' + this.colorGreen + ', ' + this.colorBlue + ')');
3417
- this.pointLight.color = color;
3418
- this.spotLight.color = color;
3419
- this.spotLightBeam.material.uniforms.glowColor.value = color;
3420
- // Apply the dimmer value
3421
- // Take the color into account for the beam (don't show a black beam)
3422
- const intensityColor = Math.max(this.colorRed, this.colorGreen, this.colorBlue);
3423
- this.spotLightBeam.material.uniforms.opacity.value = Math.min(intensityColor, this.dimmer) * 0.5;
3424
- this.spotLight.intensity = this.spotLightMaxIntensity * this.dimmer;
3425
- this.pointLight.intensity = this.pointLightMaxIntensity * this.dimmer;
3850
+ // this.spotLightHelper.update();
3426
3851
  }
3427
3852
  destroy() {
3428
3853
  this.scene.remove(this.objectGroup);
3429
3854
  this.material.dispose();
3430
- this.atmosphereMaterial.dispose();
3855
+ this.spotLightHelper.dispose();
3431
3856
  }
3432
3857
  }
3433
3858
 
3434
3859
  class MovingHead3d extends Fixture3d {
3435
- atmosphereMat() {
3436
- const vertexShader = `
3437
- varying vec3 vNormal;
3438
- varying vec3 vWorldPosition;
3439
-
3440
- void main(){
3441
- vNormal = normalize(normalMatrix * normal);
3442
-
3443
- vec4 worldPosition = modelMatrix * vec4(position, 1.0);
3444
- vWorldPosition = worldPosition.xyz;
3445
-
3446
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
3447
- }`;
3448
- const fragmentShader = `
3449
- varying vec3 vNormal;
3450
- varying vec3 vWorldPosition;
3451
-
3452
- uniform vec3 lightColor;
3453
- uniform float opacity;
3454
- uniform vec3 spotPosition;
3455
- uniform float attenuation;
3456
- uniform float anglePower;
3457
-
3458
- void main(){
3459
- float intensity;
3460
-
3461
- intensity = distance(vWorldPosition, spotPosition) / attenuation;
3462
- intensity = 1.0 - clamp(intensity, 0.0, 1.0);
3463
-
3464
- vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
3465
- float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
3466
- intensity = intensity * angleIntensity * opacity;
3467
-
3468
- gl_FragColor = vec4(lightColor, intensity);
3469
- }`;
3470
- const material = new THREE.ShaderMaterial({
3471
- uniforms: {
3472
- attenuation: {
3473
- type: 'f',
3474
- value: 800.0,
3475
- },
3476
- anglePower: {
3477
- type: 'f',
3478
- value: 2,
3479
- },
3480
- spotPosition: {
3481
- type: 'v3',
3482
- value: new THREE.Vector3(0, 0, 0),
3483
- },
3484
- lightColor: {
3485
- type: 'c',
3486
- value: new THREE.Color('white'),
3487
- },
3488
- opacity: {
3489
- type: 'f',
3490
- value: 1.0,
3491
- },
3492
- },
3493
- vertexShader,
3494
- fragmentShader,
3495
- transparent: true,
3496
- depthWrite: false,
3497
- });
3498
- return material;
3499
- }
3500
- createSpotLightBeam() {
3501
- if (this.spotLightBeam) {
3502
- this.spotlightGroup.remove(this.spotLightBeam);
3503
- }
3504
- // TODO update the correct angle from the profile
3505
- const beamAngleDegrees = 14;
3506
- const geometry = new THREE.CylinderGeometry(0.1, beamAngleDegrees * 1.2, 100, 64, 20, false);
3507
- geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, -geometry.parameters.height / 2, 0));
3508
- geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
3509
- this.atmosphereMaterial = this.atmosphereMat();
3510
- this.spotLightBeam = new THREE.Mesh(geometry, this.atmosphereMaterial);
3511
- this.spotLightBeam.position.set(0, -0.02, 0);
3512
- this.spotLightBeam.receiveShadow = false;
3513
- this.spotLightBeam.castShadow = false;
3514
- this.spotlightGroup.add(this.spotLightBeam);
3515
- this.spotLightBeam.rotation.x = Math.PI / 2;
3516
- }
3517
3860
  createObjects() {
3861
+ super.createObjects();
3518
3862
  this.material = new THREE.MeshLambertMaterial({
3519
3863
  color: 0x0d0d0d,
3520
3864
  emissive: 0x0d0d0d,
@@ -3528,27 +3872,6 @@ class MovingHead3d extends Fixture3d {
3528
3872
  const headPivotGroup = new THREE.Object3D();
3529
3873
  headPivotGroup.add(this.head);
3530
3874
  this.headGroup.add(headPivotGroup);
3531
- // Add the spotlight
3532
- this.spotLight = new THREE.SpotLight(0xffffff, 50000);
3533
- this.spotLight.angle = 2;
3534
- this.spotLight.penumbra = 1;
3535
- this.spotLight.decay = 0.01;
3536
- this.spotLight.distance = 0;
3537
- this.spotLight.intensity = 1;
3538
- this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3539
- this.scene.add(this.spotLightHelper);
3540
- const spotLightTarget = new THREE.Object3D();
3541
- this.spotLight.target = spotLightTarget;
3542
- this.spotlightGroup.add(this.spotLight);
3543
- this.spotlightGroup.add(spotLightTarget);
3544
- this.spotLight.position.set(0, -1.4, 0);
3545
- spotLightTarget.position.set(0, -10, 0);
3546
- // Add the point light for the surrounding light
3547
- this.pointLight = new THREE.PointLight(0xffffff, 500, 0, 0.1);
3548
- this.spotlightGroup.add(this.pointLight);
3549
- this.pointLight.position.set(0, -1.4, 0);
3550
- // Add the light beam
3551
- this.createSpotLightBeam();
3552
3875
  this.headGroup.add(this.spotlightGroup);
3553
3876
  // Add the arm
3554
3877
  this.armGroup.add(this.headGroup);
@@ -3565,10 +3888,7 @@ class MovingHead3d extends Fixture3d {
3565
3888
  }
3566
3889
  constructor(fixtureService, previewMeshService, fixture, scene) {
3567
3890
  super(fixtureService, fixture, scene);
3568
- this.pointLightMaxIntensity = 2;
3569
- this.spotLightLightMaxIntensity = 10;
3570
3891
  this.headGroup = new THREE.Object3D();
3571
- this.spotlightGroup = new THREE.Object3D();
3572
3892
  this.armGroup = new THREE.Object3D();
3573
3893
  this.objectGroup = new THREE.Object3D();
3574
3894
  forkJoin([
@@ -3588,10 +3908,10 @@ class MovingHead3d extends Fixture3d {
3588
3908
  return this.objectGroup;
3589
3909
  }
3590
3910
  updatePreview(channelValues, masterDimmerValue) {
3591
- super.updatePreview(channelValues, masterDimmerValue);
3592
3911
  if (!this.isLoaded) {
3593
3912
  return;
3594
3913
  }
3914
+ super.updatePreview(channelValues, masterDimmerValue);
3595
3915
  // Apply default settings
3596
3916
  let panStart = 0;
3597
3917
  let panEnd = 255;
@@ -3646,25 +3966,11 @@ class MovingHead3d extends Fixture3d {
3646
3966
  }
3647
3967
  this.lastSelected = this.isSelected;
3648
3968
  }
3649
- // Apply the colors
3650
- const color = new THREE.Color('rgb(' + this.colorRed + ', ' + this.colorGreen + ', ' + this.colorBlue + ')');
3651
- this.pointLight.color = color;
3652
- this.spotLight.color = color;
3653
- this.spotLightBeam.material.uniforms.lightColor.value = color;
3654
- // Apply the dimmer value
3655
- // Take the color into account for the beam (don't show a black beam)
3656
- const intensityColor = Math.max(this.colorRed, this.colorGreen, this.colorBlue);
3657
- // console.log(Math.min(intensityColor, this.dimmer));
3658
- this.spotLightBeam.material.uniforms.opacity.value = Math.min(intensityColor, this.dimmer);
3659
- this.spotLight.intensity = this.spotLightLightMaxIntensity * this.dimmer;
3660
- this.pointLight.intensity = this.pointLightMaxIntensity * this.dimmer;
3661
- this.spotLightBeam.material.uniforms.spotPosition.value = this.objectGroup.position;
3662
3969
  // this.spotLightHelper.update();
3663
3970
  }
3664
3971
  destroy() {
3665
3972
  this.scene.remove(this.objectGroup);
3666
3973
  this.material.dispose();
3667
- this.atmosphereMaterial.dispose();
3668
3974
  this.spotLightHelper.dispose();
3669
3975
  }
3670
3976
  }
@@ -3680,11 +3986,15 @@ class PreviewComponent {
3680
3986
  this.projectService = projectService;
3681
3987
  this.fixtures3d = [];
3682
3988
  this.previewService.doUpdateFixtureSetup.subscribe(() => {
3683
- // synchronize the 3d-fixtures to the project fixtures
3684
3989
  this.syncFixtures();
3685
3990
  });
3991
+ this.syncFixtures();
3686
3992
  }
3993
+ // synchronize the 3d-fixtures to the project fixtures
3687
3994
  syncFixtures() {
3995
+ if (!this.previewService.scene) {
3996
+ return;
3997
+ }
3688
3998
  // remove all fixtures
3689
3999
  for (const fixture3d of this.fixtures3d) {
3690
4000
  fixture3d.destroy();
@@ -3714,16 +4024,18 @@ class PreviewComponent {
3714
4024
  updateStagePosition(positioning, xMin, xMax, yMin, yMax, zMin, zMax) {
3715
4025
  let positionCount = 0; // Number of fixtures in the same position
3716
4026
  let positionIndex = 1;
3717
- this.projectService.project.fixtures.forEach((element, index) => {
3718
- if (element.positioning === positioning) {
4027
+ this.projectService.project.presetFixtures.forEach((element, index) => {
4028
+ const fixture = this.fixtureService.getFixtureByUuid(element.fixtureUuid);
4029
+ if (fixture.positioning === positioning) {
3719
4030
  positionCount++;
3720
4031
  }
3721
4032
  });
3722
- this.projectService.project.fixtures.forEach((element, index) => {
3723
- if (element.positioning === positioning) {
3724
- element.positionX = xMin + ((xMax - xMin) / (positionCount + 1)) * positionIndex;
3725
- element.positionY = yMin + ((yMax - yMin) / (positionCount + 1)) * positionIndex;
3726
- element.positionZ = zMin + ((zMax - zMin) / (positionCount + 1)) * positionIndex;
4033
+ this.projectService.project.presetFixtures.forEach((element, index) => {
4034
+ const fixture = this.fixtureService.getFixtureByUuid(element.fixtureUuid);
4035
+ if (fixture.positioning === positioning) {
4036
+ fixture.positionX = xMin + ((xMax - xMin) / (positionCount + 1)) * positionIndex;
4037
+ fixture.positionY = yMin + ((yMax - yMin) / (positionCount + 1)) * positionIndex;
4038
+ fixture.positionZ = zMin + ((zMax - zMin) / (positionCount + 1)) * positionIndex;
3727
4039
  positionIndex++;
3728
4040
  }
3729
4041
  });
@@ -3755,11 +4067,9 @@ class PreviewComponent {
3755
4067
  fixture3d.isSelected = this.fixtureService.settingsFixtureIsSelected(fixture3d.fixture.fixture);
3756
4068
  }
3757
4069
  else {
3758
- fixture3d.isSelected = this.previewService.fixtureIsSelected(fixture3d.fixture.fixture.uuid, presets);
4070
+ fixture3d.isSelected = this.previewService.fixtureIsSelected(fixture3d.fixture.fixture.uuid, fixture3d.fixture.pixelKey, presets);
3759
4071
  }
3760
4072
  }
3761
- // TODO enable for monitoring the DMX universes
3762
- this.previewService.setUniverseValues(calculatedFixtures, this.projectService.project.masterDimmerValue);
3763
4073
  // Render the scene
3764
4074
  this.render();
3765
4075
  requestAnimationFrame(this.animate.bind(this));
@@ -3811,14 +4121,14 @@ class PreviewComponent {
3811
4121
  // this.scene.fog = new THREE.FogExp2( 0x000000, 0.1 );
3812
4122
  this.previewService.scene = this.scene;
3813
4123
  // Add a little bit of ambient light
3814
- const ambient = new THREE.AmbientLight(0xffffff, 1.5);
4124
+ const ambient = new THREE.AmbientLight(0xffffff, 1.8);
3815
4125
  this.scene.add(ambient);
3816
4126
  // Create the stage dimensions
3817
4127
  this.previewService.updateStage();
3818
4128
  const lights = [];
3819
- lights[0] = new THREE.PointLight(0xffffff, 1, 0, 0.1);
3820
- lights[1] = new THREE.PointLight(0xffffff, 1, 0, 0.1);
3821
- lights[2] = new THREE.PointLight(0xffffff, 1, 0, 0.1);
4129
+ lights[0] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
4130
+ lights[1] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
4131
+ lights[2] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
3822
4132
  lights[0].position.set(0, 2000, 0);
3823
4133
  lights[1].position.set(1000, 2000, 1000);
3824
4134
  lights[2].position.set(-1000, -2000, -1000);
@@ -3828,6 +4138,7 @@ class PreviewComponent {
3828
4138
  this.scene.add(lights[0]);
3829
4139
  this.scene.add(lights[1]);
3830
4140
  this.scene.add(lights[2]);
4141
+ this.previewService.updateFixtureSetup();
3831
4142
  }
3832
4143
  ngAfterViewInit() {
3833
4144
  this.setupRenderer();
@@ -3884,8 +4195,100 @@ class WaitDialogComponent {
3884
4195
  }], () => [], null); })();
3885
4196
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WaitDialogComponent, { className: "WaitDialogComponent" }); })();
3886
4197
 
4198
+ class WarningDialogComponent {
4199
+ constructor(bsModalRef) {
4200
+ this.bsModalRef = bsModalRef;
4201
+ }
4202
+ ngOnInit() {
4203
+ this.onClose = new Subject();
4204
+ }
4205
+ ok() {
4206
+ this.onClose.next(1);
4207
+ this.bsModalRef.hide();
4208
+ }
4209
+ cancel() {
4210
+ this.onClose.next(2);
4211
+ this.bsModalRef.hide();
4212
+ }
4213
+ handleKeyboardEvent(event) {
4214
+ this.ok();
4215
+ }
4216
+ static { this.ɵfac = function WarningDialogComponent_Factory(t) { return new (t || WarningDialogComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef)); }; }
4217
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WarningDialogComponent, selectors: [["lib-app-warning-dialog"]], hostBindings: function WarningDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
4218
+ i0.ɵɵlistener("keydown.enter", function WarningDialogComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4219
+ } }, decls: 21, vars: 10, consts: [[1, "card-modal"], [1, "card"], [1, "card-header"], [1, "card-body"], [1, "row"], [1, "col-auto"], [1, "mb-0"], ["aria-hidden", "true", 1, "fa", "fa-exclamation-triangle", "text-primary"], [1, "col", "pl-0"], [1, "card-footer"], [1, "d-flex", "float-right"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "button", 1, "btn", "btn-primary", 3, "click"]], template: function WarningDialogComponent_Template(rf, ctx) { if (rf & 1) {
4220
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
4221
+ i0.ɵɵtext(3);
4222
+ i0.ɵɵpipe(4, "translate");
4223
+ i0.ɵɵelementEnd();
4224
+ i0.ɵɵelementStart(5, "div", 3)(6, "div", 4)(7, "div", 5)(8, "h2", 6);
4225
+ i0.ɵɵelement(9, "i", 7);
4226
+ i0.ɵɵelementEnd()();
4227
+ i0.ɵɵelementStart(10, "div", 8)(11, "p", 6);
4228
+ i0.ɵɵtext(12);
4229
+ i0.ɵɵelementEnd()()()();
4230
+ i0.ɵɵelementStart(13, "div", 9)(14, "div", 10)(15, "a", 11);
4231
+ i0.ɵɵlistener("click", function WarningDialogComponent_Template_a_click_15_listener() { ctx.cancel(); return false; });
4232
+ i0.ɵɵtext(16);
4233
+ i0.ɵɵpipe(17, "translate");
4234
+ i0.ɵɵelementEnd();
4235
+ i0.ɵɵelementStart(18, "button", 12);
4236
+ i0.ɵɵlistener("click", function WarningDialogComponent_Template_button_click_18_listener() { ctx.ok(); return false; });
4237
+ i0.ɵɵtext(19);
4238
+ i0.ɵɵpipe(20, "translate");
4239
+ i0.ɵɵelementEnd()()()()();
4240
+ } if (rf & 2) {
4241
+ i0.ɵɵadvance(3);
4242
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(4, 4, "designer.misc.warning"), " ");
4243
+ i0.ɵɵadvance(9);
4244
+ i0.ɵɵtextInterpolate(ctx.message);
4245
+ i0.ɵɵadvance(4);
4246
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(17, 6, "designer.misc.cancel"), " ");
4247
+ i0.ɵɵadvance(3);
4248
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(20, 8, "designer.misc.ok"), " ");
4249
+ } }, dependencies: [i2.TranslatePipe] }); }
4250
+ }
4251
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogComponent, [{
4252
+ type: Component,
4253
+ args: [{ selector: 'lib-app-warning-dialog', template: "<div class=\"card-modal\">\n <div class=\"card\">\n <div class=\"card-header\">\n {{ 'designer.misc.warning' | translate }}\n </div>\n\n <div class=\"card-body\">\n <div class=\"row\">\n <div class=\"col-auto\">\n <h2 class=\"mb-0\">\n <i class=\"fa fa-exclamation-triangle text-primary\" aria-hidden=\"true\"></i>\n </h2>\n </div>\n <div class=\"col pl-0\">\n <p class=\"mb-0\">{{ message }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"card-footer\">\n <div class=\"d-flex float-right\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok(); (false)\">\n {{ 'designer.misc.ok' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n" }]
4254
+ }], () => [{ type: i1$1.BsModalRef }], { handleKeyboardEvent: [{
4255
+ type: HostListener,
4256
+ args: ['document:keydown.enter', ['$event']]
4257
+ }] }); })();
4258
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WarningDialogComponent, { className: "WarningDialogComponent" }); })();
4259
+
4260
+ class WarningDialogService {
4261
+ constructor(modalService, translateService) {
4262
+ this.modalService = modalService;
4263
+ this.translateService = translateService;
4264
+ }
4265
+ // Show a warning dialog and return true, when the user clicked OK
4266
+ show(message) {
4267
+ return this.translateService.get(message).pipe(map((result) => {
4268
+ return result;
4269
+ }), mergeMap((result) => {
4270
+ const fileDialog = this.modalService.show(WarningDialogComponent, { keyboard: false, ignoreBackdropClick: true });
4271
+ fileDialog.content.message = result;
4272
+ return fileDialog.content.onClose.pipe(map((warningResult) => {
4273
+ if (warningResult === 1) {
4274
+ return true;
4275
+ }
4276
+ return false;
4277
+ }));
4278
+ }));
4279
+ }
4280
+ static { this.ɵfac = function WarningDialogService_Factory(t) { return new (t || WarningDialogService)(i0.ɵɵinject(i1$1.BsModalService), i0.ɵɵinject(i2.TranslateService)); }; }
4281
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WarningDialogService, factory: WarningDialogService.ɵfac, providedIn: 'root' }); }
4282
+ }
4283
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogService, [{
4284
+ type: Injectable,
4285
+ args: [{
4286
+ providedIn: 'root',
4287
+ }]
4288
+ }], () => [{ type: i1$1.BsModalService }, { type: i2.TranslateService }], null); })();
4289
+
3887
4290
  class ProjectLoadService {
3888
- constructor(projectService, previewService, fixtureService, presetService, sceneService, modalService, uuidService, timelineService, router, activatedRoute) {
4291
+ constructor(projectService, previewService, fixtureService, presetService, sceneService, modalService, uuidService, timelineService, router, activatedRoute, warningDialogService) {
3889
4292
  this.projectService = projectService;
3890
4293
  this.previewService = previewService;
3891
4294
  this.fixtureService = fixtureService;
@@ -3896,8 +4299,56 @@ class ProjectLoadService {
3896
4299
  this.timelineService = timelineService;
3897
4300
  this.router = router;
3898
4301
  this.activatedRoute = activatedRoute;
4302
+ this.warningDialogService = warningDialogService;
4303
+ }
4304
+ migrateToVersion2() {
4305
+ for (let fixture of this.projectService.project.fixtures) {
4306
+ if (this.fixtureService.fixtureHasGeneralChannel(fixture)) {
4307
+ const projectFixture = new PresetFixture();
4308
+ projectFixture.fixtureUuid = fixture.uuid;
4309
+ this.projectService.project.presetFixtures.push(projectFixture);
4310
+ }
4311
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
4312
+ for (let pixelKey of pixelKeys) {
4313
+ const projectFixture = new PresetFixture();
4314
+ projectFixture.fixtureUuid = fixture.uuid;
4315
+ projectFixture.pixelKey = pixelKey;
4316
+ this.projectService.project.presetFixtures.push(projectFixture);
4317
+ }
4318
+ }
4319
+ for (let preset of this.projectService.project.presets) {
4320
+ for (let fixtureUuid of preset.fixtureUuids) {
4321
+ const fixture = this.fixtureService.getFixtureByUuid(fixtureUuid);
4322
+ if (this.fixtureService.fixtureHasGeneralChannel(fixture)) {
4323
+ const presetFixture = new PresetFixture();
4324
+ presetFixture.fixtureUuid = fixtureUuid;
4325
+ preset.fixtures.push(presetFixture);
4326
+ }
4327
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
4328
+ for (let pixelKey of pixelKeys) {
4329
+ const presetFixture = new PresetFixture();
4330
+ presetFixture.fixtureUuid = fixtureUuid;
4331
+ presetFixture.pixelKey = pixelKey;
4332
+ preset.fixtures.push(presetFixture);
4333
+ }
4334
+ }
4335
+ preset.fixtureUuids = undefined;
4336
+ }
4337
+ this.projectService.project.version = 2;
4338
+ }
4339
+ migrateFromOldProject() {
4340
+ let migrated = false;
4341
+ if (!this.projectService.project.version) {
4342
+ // Migrate from version 1
4343
+ this.migrateToVersion2();
4344
+ migrated = true;
4345
+ }
4346
+ if (migrated) {
4347
+ this.warningDialogService.show('designer.project.migrated').subscribe();
4348
+ }
3899
4349
  }
3900
4350
  afterLoad() {
4351
+ this.migrateFromOldProject();
3901
4352
  this.fixtureService.updateCachedFixtures();
3902
4353
  this.presetService.removeDeletedFixtures();
3903
4354
  this.previewService.updateFixtureSetup();
@@ -3928,6 +4379,11 @@ class ProjectLoadService {
3928
4379
  load(id, name, shareToken) {
3929
4380
  const ref = this.modalService.show(WaitDialogComponent, { keyboard: false, ignoreBackdropClick: true });
3930
4381
  return this.projectService.getProject(id, name, shareToken).pipe(map((project) => {
4382
+ if (project.version > this.projectService.currentProjectVersion) {
4383
+ throw new Error('The project version ' +
4384
+ project.version +
4385
+ ' is created with a newer version of the designer. Please update your Rocket Show version to open this project.');
4386
+ }
3931
4387
  this.projectService.project = project;
3932
4388
  this.selectScenesPresetComposition();
3933
4389
  this.afterLoad();
@@ -3958,6 +4414,7 @@ class ProjectLoadService {
3958
4414
  // create an empty new project
3959
4415
  const project = new Project();
3960
4416
  project.uuid = this.uuidService.getUuid();
4417
+ project.version = this.projectService.currentProjectVersion;
3961
4418
  this.projectService.project = project;
3962
4419
  this.projectService.project.shareToken = this.uuidService.getUuid();
3963
4420
  // Add a default scene and preset
@@ -3983,123 +4440,31 @@ class ProjectLoadService {
3983
4440
  relativeTo: this.activatedRoute,
3984
4441
  queryParams,
3985
4442
  queryParamsHandling: 'merge', // remove to replace all query params by provided
3986
- });
3987
- }
3988
- template() {
3989
- // load the template project with id 1
3990
- this.load(1, null).subscribe(() => {
3991
- this.projectService.project.id = undefined;
3992
- });
3993
- }
3994
- import(data) {
3995
- // import a project from a string
3996
- const project = new Project(JSON.parse(data));
3997
- project.id = undefined;
3998
- this.projectService.project = project;
3999
- this.selectScenesPresetComposition();
4000
- this.afterLoad();
4001
- }
4002
- static { this.ɵfac = function ProjectLoadService_Factory(t) { return new (t || ProjectLoadService)(i0.ɵɵinject(ProjectService), i0.ɵɵinject(PreviewService), i0.ɵɵinject(FixtureService), i0.ɵɵinject(PresetService), i0.ɵɵinject(SceneService), i0.ɵɵinject(i1$1.BsModalService), i0.ɵɵinject(UuidService), i0.ɵɵinject(TimelineService), i0.ɵɵinject(i4.Router), i0.ɵɵinject(i4.ActivatedRoute)); }; }
4003
- static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ProjectLoadService, factory: ProjectLoadService.ɵfac, providedIn: 'root' }); }
4004
- }
4005
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectLoadService, [{
4006
- type: Injectable,
4007
- args: [{
4008
- providedIn: 'root',
4009
- }]
4010
- }], () => [{ type: ProjectService }, { type: PreviewService }, { type: FixtureService }, { type: PresetService }, { type: SceneService }, { type: i1$1.BsModalService }, { type: UuidService }, { type: TimelineService }, { type: i4.Router }, { type: i4.ActivatedRoute }], null); })();
4011
-
4012
- class WarningDialogComponent {
4013
- constructor(bsModalRef) {
4014
- this.bsModalRef = bsModalRef;
4015
- }
4016
- ngOnInit() {
4017
- this.onClose = new Subject();
4018
- }
4019
- ok() {
4020
- this.onClose.next(1);
4021
- this.bsModalRef.hide();
4022
- }
4023
- cancel() {
4024
- this.onClose.next(2);
4025
- this.bsModalRef.hide();
4026
- }
4027
- handleKeyboardEvent(event) {
4028
- this.ok();
4443
+ });
4029
4444
  }
4030
- static { this.ɵfac = function WarningDialogComponent_Factory(t) { return new (t || WarningDialogComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef)); }; }
4031
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WarningDialogComponent, selectors: [["lib-app-warning-dialog"]], hostBindings: function WarningDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
4032
- i0.ɵɵlistener("keydown.enter", function WarningDialogComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4033
- } }, decls: 21, vars: 10, consts: [[1, "card-modal"], [1, "card"], [1, "card-header"], [1, "card-body"], [1, "row"], [1, "col-auto"], [1, "mb-0"], ["aria-hidden", "true", 1, "fa", "fa-exclamation-triangle", "text-primary"], [1, "col", "pl-0"], [1, "card-footer"], [1, "d-flex", "float-right"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "button", 1, "btn", "btn-primary", 3, "click"]], template: function WarningDialogComponent_Template(rf, ctx) { if (rf & 1) {
4034
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
4035
- i0.ɵɵtext(3);
4036
- i0.ɵɵpipe(4, "translate");
4037
- i0.ɵɵelementEnd();
4038
- i0.ɵɵelementStart(5, "div", 3)(6, "div", 4)(7, "div", 5)(8, "h2", 6);
4039
- i0.ɵɵelement(9, "i", 7);
4040
- i0.ɵɵelementEnd()();
4041
- i0.ɵɵelementStart(10, "div", 8)(11, "p", 6);
4042
- i0.ɵɵtext(12);
4043
- i0.ɵɵelementEnd()()()();
4044
- i0.ɵɵelementStart(13, "div", 9)(14, "div", 10)(15, "a", 11);
4045
- i0.ɵɵlistener("click", function WarningDialogComponent_Template_a_click_15_listener() { ctx.cancel(); return false; });
4046
- i0.ɵɵtext(16);
4047
- i0.ɵɵpipe(17, "translate");
4048
- i0.ɵɵelementEnd();
4049
- i0.ɵɵelementStart(18, "button", 12);
4050
- i0.ɵɵlistener("click", function WarningDialogComponent_Template_button_click_18_listener() { ctx.ok(); return false; });
4051
- i0.ɵɵtext(19);
4052
- i0.ɵɵpipe(20, "translate");
4053
- i0.ɵɵelementEnd()()()()();
4054
- } if (rf & 2) {
4055
- i0.ɵɵadvance(3);
4056
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(4, 4, "designer.misc.warning"), " ");
4057
- i0.ɵɵadvance(9);
4058
- i0.ɵɵtextInterpolate(ctx.message);
4059
- i0.ɵɵadvance(4);
4060
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(17, 6, "designer.misc.cancel"), " ");
4061
- i0.ɵɵadvance(3);
4062
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(20, 8, "designer.misc.ok"), " ");
4063
- } }, dependencies: [i2.TranslatePipe] }); }
4064
- }
4065
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogComponent, [{
4066
- type: Component,
4067
- args: [{ selector: 'lib-app-warning-dialog', template: "<div class=\"card-modal\">\n <div class=\"card\">\n <div class=\"card-header\">\n {{ 'designer.misc.warning' | translate }}\n </div>\n\n <div class=\"card-body\">\n <div class=\"row\">\n <div class=\"col-auto\">\n <h2 class=\"mb-0\">\n <i class=\"fa fa-exclamation-triangle text-primary\" aria-hidden=\"true\"></i>\n </h2>\n </div>\n <div class=\"col pl-0\">\n <p class=\"mb-0\">{{ message }}</p>\n </div>\n </div>\n </div>\n\n <div class=\"card-footer\">\n <div class=\"d-flex float-right\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok(); (false)\">\n {{ 'designer.misc.ok' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n" }]
4068
- }], () => [{ type: i1$1.BsModalRef }], { handleKeyboardEvent: [{
4069
- type: HostListener,
4070
- args: ['document:keydown.enter', ['$event']]
4071
- }] }); })();
4072
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WarningDialogComponent, { className: "WarningDialogComponent" }); })();
4073
-
4074
- class WarningDialogService {
4075
- constructor(modalService, translateService) {
4076
- this.modalService = modalService;
4077
- this.translateService = translateService;
4445
+ template() {
4446
+ // load the template project with id 1
4447
+ this.load(1, null).subscribe(() => {
4448
+ this.projectService.project.id = undefined;
4449
+ });
4078
4450
  }
4079
- // Show a warning dialog and return true, when the user clicked OK
4080
- show(message) {
4081
- return this.translateService.get(message).pipe(map((result) => {
4082
- return result;
4083
- }), mergeMap((result) => {
4084
- const fileDialog = this.modalService.show(WarningDialogComponent, { keyboard: false, ignoreBackdropClick: true });
4085
- fileDialog.content.message = result;
4086
- return fileDialog.content.onClose.pipe(map((warningResult) => {
4087
- if (warningResult === 1) {
4088
- return true;
4089
- }
4090
- return false;
4091
- }));
4092
- }));
4451
+ import(data) {
4452
+ // import a project from a string
4453
+ const project = new Project(JSON.parse(data));
4454
+ project.id = undefined;
4455
+ this.projectService.project = project;
4456
+ this.selectScenesPresetComposition();
4457
+ this.afterLoad();
4093
4458
  }
4094
- static { this.ɵfac = function WarningDialogService_Factory(t) { return new (t || WarningDialogService)(i0.ɵɵinject(i1$1.BsModalService), i0.ɵɵinject(i2.TranslateService)); }; }
4095
- static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WarningDialogService, factory: WarningDialogService.ɵfac, providedIn: 'root' }); }
4459
+ static { this.ɵfac = function ProjectLoadService_Factory(t) { return new (t || ProjectLoadService)(i0.ɵɵinject(ProjectService), i0.ɵɵinject(PreviewService), i0.ɵɵinject(FixtureService), i0.ɵɵinject(PresetService), i0.ɵɵinject(SceneService), i0.ɵɵinject(i1$1.BsModalService), i0.ɵɵinject(UuidService), i0.ɵɵinject(TimelineService), i0.ɵɵinject(i3.Router), i0.ɵɵinject(i3.ActivatedRoute), i0.ɵɵinject(WarningDialogService)); }; }
4460
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ProjectLoadService, factory: ProjectLoadService.ɵfac, providedIn: 'root' }); }
4096
4461
  }
4097
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogService, [{
4462
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectLoadService, [{
4098
4463
  type: Injectable,
4099
4464
  args: [{
4100
4465
  providedIn: 'root',
4101
4466
  }]
4102
- }], () => [{ type: i1$1.BsModalService }, { type: i2.TranslateService }], null); })();
4467
+ }], () => [{ type: ProjectService }, { type: PreviewService }, { type: FixtureService }, { type: PresetService }, { type: SceneService }, { type: i1$1.BsModalService }, { type: UuidService }, { type: TimelineService }, { type: i3.Router }, { type: i3.ActivatedRoute }, { type: WarningDialogService }], null); })();
4103
4468
 
4104
4469
  class ArraySortPipe {
4105
4470
  transform(array, field) {
@@ -4310,7 +4675,7 @@ class ProjectImportComponent {
4310
4675
  handleKeyboardEvent(event) {
4311
4676
  this.ok();
4312
4677
  }
4313
- static { this.ɵfac = function ProjectImportComponent_Factory(t) { return new (t || ProjectImportComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3.ToastrService), i0.ɵɵdirectiveInject(ProjectLoadService)); }; }
4678
+ static { this.ɵfac = function ProjectImportComponent_Factory(t) { return new (t || ProjectImportComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3$1.ToastrService), i0.ɵɵdirectiveInject(ProjectLoadService)); }; }
4314
4679
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ProjectImportComponent, selectors: [["lib-project-import"]], hostBindings: function ProjectImportComponent_HostBindings(rf, ctx) { if (rf & 1) {
4315
4680
  i0.ɵɵlistener("keydown.enter", function ProjectImportComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4316
4681
  } }, decls: 13, vars: 9, consts: [[1, "modal-header"], [1, "modal-title", "pull-left"], ["type", "button", "aria-label", "Close", 1, "close", "pull-right", 3, "click"], ["aria-hidden", "true"], [1, "modal-body"], [3, "error", "config", "useDropzoneClass", "message"], [1, "modal-footer"], ["type", "button", 1, "btn", "btn-primary", 3, "click"]], template: function ProjectImportComponent_Template(rf, ctx) { if (rf & 1) {
@@ -4343,7 +4708,7 @@ class ProjectImportComponent {
4343
4708
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectImportComponent, [{
4344
4709
  type: Component,
4345
4710
  args: [{ selector: 'lib-project-import', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.project.import-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"bsModalRef.hide()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Dropzone -->\n <dropzone [config]=\"dropzoneConfig\" [useDropzoneClass]=\"'false'\" [message]=\"uploadMessage\" (error)=\"onUploadError($event)\"></dropzone>\n</div>\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
4346
- }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3.ToastrService }, { type: ProjectLoadService }], { handleKeyboardEvent: [{
4711
+ }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: ProjectLoadService }], { handleKeyboardEvent: [{
4347
4712
  type: HostListener,
4348
4713
  args: ['document:keydown.enter', ['$event']]
4349
4714
  }] }); })();
@@ -4501,7 +4866,7 @@ class ProjectSaveComponent {
4501
4866
  i0.ɵɵproperty("disabled", ctx.loading || !ctx.projectName);
4502
4867
  i0.ɵɵadvance();
4503
4868
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(22, 14, "designer.misc.ok"), " ");
4504
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe, ArraySortPipe] }); }
4869
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe, ArraySortPipe] }); }
4505
4870
  }
4506
4871
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectSaveComponent, [{
4507
4872
  type: Component,
@@ -4564,7 +4929,7 @@ class ProjectShareComponent {
4564
4929
  i0.ɵɵproperty("ngModel", ctx.shareLink);
4565
4930
  i0.ɵɵadvance(3);
4566
4931
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(17, 8, "designer.misc.ok"));
4567
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
4932
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
4568
4933
  }
4569
4934
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectShareComponent, [{
4570
4935
  type: Component,
@@ -4764,7 +5129,7 @@ class FixturePoolCreateFromFileComponent {
4764
5129
  handleKeyboardEvent(event) {
4765
5130
  this.ok();
4766
5131
  }
4767
- static { this.ɵfac = function FixturePoolCreateFromFileComponent_Factory(t) { return new (t || FixturePoolCreateFromFileComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3.ToastrService), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(ProjectService)); }; }
5132
+ static { this.ɵfac = function FixturePoolCreateFromFileComponent_Factory(t) { return new (t || FixturePoolCreateFromFileComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3$1.ToastrService), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(ProjectService)); }; }
4768
5133
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixturePoolCreateFromFileComponent, selectors: [["lib-fixture-pool-create-from-file"]], hostBindings: function FixturePoolCreateFromFileComponent_HostBindings(rf, ctx) { if (rf & 1) {
4769
5134
  i0.ɵɵlistener("keydown.enter", function FixturePoolCreateFromFileComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4770
5135
  } }, decls: 13, vars: 9, consts: [[1, "modal-header"], [1, "modal-title", "pull-left"], ["type", "button", "aria-label", "Close", 1, "close", "pull-right", 3, "click"], ["aria-hidden", "true"], [1, "modal-body"], [3, "error", "config", "useDropzoneClass", "message"], [1, "modal-footer"], ["type", "button", 1, "btn", "btn-primary", 3, "click"]], template: function FixturePoolCreateFromFileComponent_Template(rf, ctx) { if (rf & 1) {
@@ -4779,12 +5144,12 @@ class FixturePoolCreateFromFileComponent {
4779
5144
  i0.ɵɵelementEnd()()();
4780
5145
  i0.ɵɵelementStart(7, "div", 4)(8, "dropzone", 5);
4781
5146
  i0.ɵɵlistener("error", function FixturePoolCreateFromFileComponent_Template_dropzone_error_8_listener($event) { return ctx.onUploadError($event); });
4782
- i0.ɵɵelementEnd()();
5147
+ i0.ɵɵelementEnd();
4783
5148
  i0.ɵɵelementStart(9, "div", 6)(10, "button", 7);
4784
5149
  i0.ɵɵlistener("click", function FixturePoolCreateFromFileComponent_Template_button_click_10_listener() { return ctx.ok(); });
4785
5150
  i0.ɵɵtext(11);
4786
5151
  i0.ɵɵpipe(12, "translate");
4787
- i0.ɵɵelementEnd()();
5152
+ i0.ɵɵelementEnd()()();
4788
5153
  } if (rf & 2) {
4789
5154
  i0.ɵɵadvance(2);
4790
5155
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 5, "designer.fixture-pool.create-fixture-from-profile-file-dialog-title"));
@@ -4796,8 +5161,8 @@ class FixturePoolCreateFromFileComponent {
4796
5161
  }
4797
5162
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixturePoolCreateFromFileComponent, [{
4798
5163
  type: Component,
4799
- args: [{ selector: 'lib-fixture-pool-create-from-file', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.create-fixture-from-profile-file-dialog-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"bsModalRef.hide()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Dropzone -->\n <dropzone [config]=\"dropzoneConfig\" [useDropzoneClass]=\"'false'\" [message]=\"uploadMessage\" (error)=\"onUploadError($event)\"></dropzone>\n</div>\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
4800
- }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3.ToastrService }, { type: FixtureService }, { type: ProjectService }], { handleKeyboardEvent: [{
5164
+ args: [{ selector: 'lib-fixture-pool-create-from-file', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.create-fixture-from-profile-file-dialog-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"bsModalRef.hide()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Dropzone -->\n <dropzone [config]=\"dropzoneConfig\" [useDropzoneClass]=\"'false'\" [message]=\"uploadMessage\" (error)=\"onUploadError($event)\"></dropzone>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n </div>\n</div>\n" }]
5165
+ }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: FixtureService }, { type: ProjectService }], { handleKeyboardEvent: [{
4801
5166
  type: HostListener,
4802
5167
  args: ['document:keydown.enter', ['$event']]
4803
5168
  }] }); })();
@@ -4902,9 +5267,10 @@ function FixturePoolComponent_div_66_option_13_Template(rf, ctx) { if (rf & 1) {
4902
5267
  i0.ɵɵelementEnd();
4903
5268
  } if (rf & 2) {
4904
5269
  const mode_r10 = ctx.$implicit;
5270
+ const ctx_r2 = i0.ɵɵnextContext(2);
4905
5271
  i0.ɵɵproperty("ngValue", mode_r10.shortName || mode_r10.name);
4906
5272
  i0.ɵɵadvance();
4907
- i0.ɵɵtextInterpolate3(" ", mode_r10.name, " - ", mode_r10.channels.length, " ", i0.ɵɵpipeBind1(2, 4, "designer.fixture-pool.channels"), " ");
5273
+ i0.ɵɵtextInterpolate3(" ", mode_r10.name, " - ", ctx_r2.fixtureService.getModeChannelCount(ctx_r2.selectedFixtureProfile, mode_r10), " ", i0.ɵɵpipeBind1(2, 4, "designer.fixture-pool.channels"), " ");
4908
5274
  } }
4909
5275
  function FixturePoolComponent_div_66_option_20_Template(rf, ctx) { if (rf & 1) {
4910
5276
  i0.ɵɵelementStart(0, "option", 72);
@@ -5038,7 +5404,9 @@ class FixturePoolComponent {
5038
5404
  this.fixtureService.loadProfileByUuid(searchProfile.uuid).subscribe(() => {
5039
5405
  const profile = this.fixtureService.getProfileByUuid(searchProfile.uuid);
5040
5406
  const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
5041
- this.selectFixture(newFixture);
5407
+ if (newFixture) {
5408
+ this.selectFixture(newFixture);
5409
+ }
5042
5410
  });
5043
5411
  }
5044
5412
  addCopy(originalFixture) {
@@ -5081,8 +5449,10 @@ class FixturePoolComponent {
5081
5449
  }
5082
5450
  channelOccupied(index) {
5083
5451
  for (const fixture of this.fixturePool) {
5084
- const mode = this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(fixture.profileUuid), fixture);
5085
- if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + mode.channels.length) {
5452
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5453
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5454
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5455
+ if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
5086
5456
  return true;
5087
5457
  }
5088
5458
  }
@@ -5098,8 +5468,10 @@ class FixturePoolComponent {
5098
5468
  }
5099
5469
  channelOccupiedEnd(index) {
5100
5470
  for (const fixture of this.fixturePool) {
5101
- const mode = this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(fixture.profileUuid), fixture);
5102
- if (index === fixture.dmxFirstChannel + mode.channels.length - 1) {
5471
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5472
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5473
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5474
+ if (index === fixture.dmxFirstChannel + channelCount - 1) {
5103
5475
  return true;
5104
5476
  }
5105
5477
  }
@@ -5108,8 +5480,10 @@ class FixturePoolComponent {
5108
5480
  channelOverlapped(index) {
5109
5481
  let occupiedFixture;
5110
5482
  for (const fixture of this.fixturePool) {
5111
- const mode = this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(fixture.profileUuid), fixture);
5112
- if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + mode.channels.length) {
5483
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5484
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5485
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5486
+ if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
5113
5487
  if (occupiedFixture) {
5114
5488
  if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel || occupiedFixture.modeShortName !== fixture.modeShortName) {
5115
5489
  // fixtures are allowed to overlap, if they start at the same channel and
@@ -5131,8 +5505,10 @@ class FixturePoolComponent {
5131
5505
  // find a dragging fixture and select it, but don't change the selection, if the
5132
5506
  // currently selected fixture might also be selected (on overlapped fixtures)
5133
5507
  for (const fixture of this.fixturePool) {
5134
- const mode = this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(fixture.profileUuid), fixture);
5135
- if (selectedIndex >= fixture.dmxFirstChannel && selectedIndex <= fixture.dmxFirstChannel + mode.channels.length - 1) {
5508
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5509
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5510
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5511
+ if (selectedIndex >= fixture.dmxFirstChannel && selectedIndex <= fixture.dmxFirstChannel + channelCount - 1) {
5136
5512
  if (this.selectedFixture === fixture) {
5137
5513
  newSelectedFixture = fixture;
5138
5514
  break;
@@ -5155,8 +5531,10 @@ class FixturePoolComponent {
5155
5531
  return false;
5156
5532
  }
5157
5533
  if (index >= this.selectedFixture.dmxFirstChannel) {
5158
- const mode = this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(this.selectedFixture.profileUuid), this.selectedFixture);
5159
- if (index < this.selectedFixture.dmxFirstChannel + mode.channels.length) {
5534
+ const profile = this.fixtureService.getProfileByUuid(this.selectedFixture.profileUuid);
5535
+ const mode = this.fixtureService.getModeByFixture(profile, this.selectedFixture);
5536
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5537
+ if (index < this.selectedFixture.dmxFirstChannel + channelCount) {
5160
5538
  return true;
5161
5539
  }
5162
5540
  }
@@ -5169,15 +5547,15 @@ class FixturePoolComponent {
5169
5547
  this.channelDragOffset = undefined;
5170
5548
  }
5171
5549
  channelMouseOver(event) {
5550
+ if (!this.channelDragFixture) {
5551
+ return;
5552
+ }
5172
5553
  // perform dragging
5173
5554
  const selectedIndex = event.target.dataset.index;
5174
- if (this.channelDragFixture &&
5175
- selectedIndex - this.channelDragOffset >= 0 &&
5176
- selectedIndex -
5177
- this.channelDragOffset +
5178
- this.fixtureService.getModeByFixture(this.fixtureService.getProfileByUuid(this.channelDragFixture.profileUuid), this.channelDragFixture).channels.length -
5179
- 1 <=
5180
- 511) {
5555
+ const profile = this.fixtureService.getProfileByUuid(this.channelDragFixture.profileUuid);
5556
+ const mode = this.fixtureService.getModeByFixture(profile, this.selectedFixture);
5557
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5558
+ if (selectedIndex - this.channelDragOffset >= 0 && selectedIndex - this.channelDragOffset + channelCount - 1 <= 511) {
5181
5559
  this.channelDragFixture.dmxFirstChannel = selectedIndex - this.channelDragOffset;
5182
5560
  }
5183
5561
  }
@@ -5194,6 +5572,44 @@ class FixturePoolComponent {
5194
5572
  }
5195
5573
  }
5196
5574
  this.projectService.project.fixtures = this.fixturePool;
5575
+ // remove deleted fixtures from preset fixtures
5576
+ for (let i = this.projectService.project.presetFixtures.length - 1; i >= 0; i--) {
5577
+ let found = false;
5578
+ const presetFixture = this.projectService.project.presetFixtures[i];
5579
+ for (let fixture of this.projectService.project.fixtures) {
5580
+ if (presetFixture.fixtureUuid === fixture.uuid) {
5581
+ found = true;
5582
+ break;
5583
+ }
5584
+ }
5585
+ if (!found) {
5586
+ this.projectService.project.presetFixtures.splice(i, 1);
5587
+ }
5588
+ }
5589
+ // add the new fixtures to the preset fixtures
5590
+ for (let fixture of this.projectService.project.fixtures) {
5591
+ let found = false;
5592
+ for (let presetFixture of this.projectService.project.presetFixtures) {
5593
+ if (presetFixture.fixtureUuid === fixture.uuid) {
5594
+ found = true;
5595
+ break;
5596
+ }
5597
+ }
5598
+ if (!found) {
5599
+ if (this.fixtureService.fixtureHasGeneralChannel(fixture)) {
5600
+ const presetFixture = new PresetFixture();
5601
+ presetFixture.fixtureUuid = fixture.uuid;
5602
+ this.projectService.project.presetFixtures.push(presetFixture);
5603
+ }
5604
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
5605
+ for (let pixelKey of pixelKeys) {
5606
+ const presetFixture = new PresetFixture();
5607
+ presetFixture.fixtureUuid = fixture.uuid;
5608
+ presetFixture.pixelKey = pixelKey;
5609
+ this.projectService.project.presetFixtures.push(presetFixture);
5610
+ }
5611
+ }
5612
+ }
5197
5613
  this.fixtureService.updateCachedFixtures();
5198
5614
  this.presetService.removeDeletedFixtures();
5199
5615
  this.previewService.updateFixtureSetup();
@@ -5241,7 +5657,7 @@ class FixturePoolComponent {
5241
5657
  handleKeyboardEvent(event) {
5242
5658
  this.ok();
5243
5659
  }
5244
- static { this.ɵfac = function FixturePoolComponent_Factory(t) { return new (t || FixturePoolComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(UuidService), i0.ɵɵdirectiveInject(ProjectService), i0.ɵɵdirectiveInject(PreviewService), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3.ToastrService), i0.ɵɵdirectiveInject(PresetService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(i1$1.BsModalService)); }; }
5660
+ static { this.ɵfac = function FixturePoolComponent_Factory(t) { return new (t || FixturePoolComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(UuidService), i0.ɵɵdirectiveInject(ProjectService), i0.ɵɵdirectiveInject(PreviewService), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i3$1.ToastrService), i0.ɵɵdirectiveInject(PresetService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(i1$1.BsModalService)); }; }
5245
5661
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixturePoolComponent, selectors: [["lib-app-fixture-pool"]], hostBindings: function FixturePoolComponent_HostBindings(rf, ctx) { if (rf & 1) {
5246
5662
  i0.ɵɵlistener("mouseup", function FixturePoolComponent_mouseup_HostBindingHandler($event) { return ctx.mouseUp($event); }, false, i0.ɵɵresolveWindow)("keydown.enter", function FixturePoolComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
5247
5663
  } }, decls: 74, vars: 37, consts: [[1, "modal-header"], [1, "modal-title", "pull-left"], ["type", "button", "aria-label", "Close", 1, "close", "pull-right", 3, "click"], ["aria-hidden", "true"], [1, "modal-body"], [1, "row"], [1, "col-6"], ["type", "text", "id", "searchSet", 1, "form-control", "input-block", "mb-3", 3, "input", "placeholder"], [1, "card", "border-secondary", "w-100", 2, "height", "200px"], [1, "card-body", "p-0", "w-100"], [1, "list-group", "list-group-flush", "w-100"], ["class", "list-group-item flex-column align-items-start d-flex", 4, "ngIf"], ["class", "list-group-item", 4, "ngFor", "ngForOf"], [1, "d-inline-block", "mb-0", "mt-2"], ["href", "https://open-fixture-library.org/", "target", "_blank"], ["href", "https://open-fixture-library.org/fixture-editor", "target", "_blank", "role", "button", 1, "mt-2", "btn", "btn-secondary", "btn-sm", "float-right"], ["aria-hidden", "true", 1, "fa", "fa-file-o"], ["type", "button", "class", "mr-2 mt-2 btn btn-secondary btn-sm float-right", "role", "button", 3, "disabled", "click", 4, "ngIf"], ["type", "button", "role", "button", 1, "btn", "btn-secondary", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-plus"], [1, "form-group", "row"], [1, "col-lg-4", "col-form-label"], [1, "col-lg-8"], [1, "custom-select"], [1, "card", "border-secondary", 2, "height", "235px"], [1, "card-body", "p-0"], [1, "list-group", "list-group-flush", 3, "sortablejs"], ["class", "list-group-item", "style", "cursor: pointer", 3, "active", "click", 4, "ngFor", "ngForOf"], [1, "row", "mt-3"], [1, "col"], ["id", "myTab", "role", "tablist", 1, "nav", "nav-tabs", "mb-4"], [1, "nav-item"], ["id", "sets-tab", "data-toggle", "tab", "href", "#dmx", "role", "tab", 1, "nav-link", "active"], ["aria-hidden", "true", 1, "icon-ola"], ["id", "compositions-tab", "data-toggle", "tab", "href", "#settings", "role", "tab", 1, "nav-link"], ["aria-hidden", "true", 1, "fa", "fa-cog"], ["id", "myTabContent", 1, "tab-content"], ["id", "dmx", "role", "tabpanel", 1, "tab-pane", "show", "active"], ["class", "dmx-channel", "placement", "top", "triggers", "mouseenter:mouseleave", 3, "dmx-channel-occupied", "dmx-channel-occupied-start", "dmx-channel-occupied-end", "dmx-channel-selected", "dmx-channel-overlapped", "popover", "mousedown", "mouseover", 4, "ngFor", "ngForOf"], ["id", "settings", "role", "tabpanel", 1, "tab-pane"], [4, "ngIf"], [1, "modal-footer"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "button", 1, "btn", "btn-primary", 3, "click"], [1, "list-group-item", "flex-column", "align-items-start", "d-flex"], [1, "mb-0", "mx-auto"], [1, "fa", "fa-spinner", "fa-pulse", "fa-fw"], [1, "list-group-item"], [1, "col-10", "col-auto", "my-auto", "pl-2"], [1, "mb-0"], [1, "col-2", "my-auto"], ["href", "#", "role", "button", 1, "btn", "btn-primary", "btn-sm", "float-right", 3, "click"], ["type", "button", "role", "button", 1, "mr-2", "mt-2", "btn", "btn-secondary", "btn-sm", "float-right", 3, "click", "disabled"], ["class", "fa fa-spinner fa-pulse fa-fw", "aria-hidden", "true", 4, "ngIf"], ["class", "fa fa-download fa-fw", "aria-hidden", "true", 4, "ngIf"], ["aria-hidden", "true", 1, "fa", "fa-spinner", "fa-pulse", "fa-fw"], ["aria-hidden", "true", 1, "fa", "fa-download", "fa-fw"], [1, "list-group-item", 2, "cursor", "pointer", 3, "click"], [1, "col-auto", "list-sort-handle", "my-auto", 2, "cursor", "move", "cursor", "-webkit-grabbing"], ["aria-hidden", "true", 1, "fa", "fa-bars"], [1, "col-auto", "flex-grow", "pl-0", "my-auto"], [1, "col-auto", "my-auto"], ["aria-hidden", "true", 1, "fa", "fa-minus"], ["placement", "top", "triggers", "mouseenter:mouseleave", 1, "dmx-channel", 3, "mousedown", "mouseover", "popover"], [1, "d-flex", "w-100", "dmx-channel-text"], [1, "m-auto", 2, "font-size", "11px"], ["for", "fixtureName", 1, "col-lg-3", "col-form-label"], [1, "col-lg-9"], ["type", "text", "maxlength", "200", "id", "fixtureName", 1, "form-control", 3, "ngModelChange", "ngModel"], [1, "col-lg-3", "col-form-label"], [1, "custom-select", 3, "ngModelChange", "ngModel"], [3, "ngValue", 4, "ngFor", "ngForOf"], [3, "ngValue"]], template: function FixturePoolComponent_Template(rf, ctx) { if (rf & 1) {
@@ -5349,12 +5765,12 @@ class FixturePoolComponent {
5349
5765
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(70, 33, "designer.misc.cancel"), " ");
5350
5766
  i0.ɵɵadvance(3);
5351
5767
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(73, 35, "designer.misc.ok"));
5352
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.MaxLengthValidator, i4$1.NgModel, i12.PopoverDirective, i8.SortablejsDirective, i2.TranslatePipe, ArraySortPipe], styles: [".list-group-item[_ngcontent-%COMP%]{padding:.3rem 1.25rem}.dmx-channel[_ngcontent-%COMP%]{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied[_ngcontent-%COMP%]{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start[_ngcontent-%COMP%]{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end[_ngcontent-%COMP%]{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected[_ngcontent-%COMP%]{background-color:#fd7e14}.dmx-channel-overlapped[_ngcontent-%COMP%]{background-color:red;border:1px solid red;cursor:move}.card[_ngcontent-%COMP%]{overflow:auto}"] }); }
5768
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.MaxLengthValidator, i4.NgModel, i12.PopoverDirective, i8.SortablejsDirective, i2.TranslatePipe, ArraySortPipe], styles: [".list-group-item[_ngcontent-%COMP%]{padding:.3rem 1.25rem}.dmx-channel[_ngcontent-%COMP%]{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied[_ngcontent-%COMP%]{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start[_ngcontent-%COMP%]{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end[_ngcontent-%COMP%]{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected[_ngcontent-%COMP%]{background-color:#fd7e14}.dmx-channel-overlapped[_ngcontent-%COMP%]{background-color:red;border:1px solid red;cursor:move}.card[_ngcontent-%COMP%]{overflow:auto}"] }); }
5353
5769
  }
5354
5770
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixturePoolComponent, [{
5355
5771
  type: Component,
5356
- args: [{ selector: 'lib-app-fixture-pool', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n <a *ngIf=\"loadingProfiles\" class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n\n <div class=\"list-group-item\" *ngFor=\"let profile of filteredProfiles | sort: 'uuid'\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n <button\n *ngIf=\"configService.localProfiles\"\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n <i *ngIf=\"updatingProfiles\" class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n <i *ngIf=\"!updatingProfiles\" class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <select class=\"custom-select\">\n <option>Universe 1</option>\n </select>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n <div\n class=\"list-group-item\"\n *ngFor=\"let fixture of fixturePool\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n <div\n *ngFor=\"let channel of dmxChannels; let i = index\"\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n <div *ngIf=\"selectedFixture && selectedFixtureProfile\">\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n <option *ngFor=\"let mode of selectedFixtureProfile.modes\" [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ mode.channels.length }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n </select>\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n <option *ngFor=\"let channel of dmxChannels; let i = index\" [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n </select>\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
5357
- }], () => [{ type: i1$1.BsModalRef }, { type: FixtureService }, { type: UuidService }, { type: ProjectService }, { type: PreviewService }, { type: i2.TranslateService }, { type: i3.ToastrService }, { type: PresetService }, { type: ConfigService }, { type: i1$1.BsModalService }], { mouseUp: [{
5772
+ args: [{ selector: 'lib-app-fixture-pool', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n <a *ngIf=\"loadingProfiles\" class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n\n <div class=\"list-group-item\" *ngFor=\"let profile of filteredProfiles | sort : 'uuid'\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n <button\n *ngIf=\"configService.localProfiles\"\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n <i *ngIf=\"updatingProfiles\" class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n <i *ngIf=\"!updatingProfiles\" class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <select class=\"custom-select\">\n <option>Universe 1</option>\n </select>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n <div\n class=\"list-group-item\"\n *ngFor=\"let fixture of fixturePool\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n <div\n *ngFor=\"let channel of dmxChannels; let i = index\"\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n <div *ngIf=\"selectedFixture && selectedFixtureProfile\">\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n <option *ngFor=\"let mode of selectedFixtureProfile.modes\" [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n </select>\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n <option *ngFor=\"let channel of dmxChannels; let i = index\" [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n </select>\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
5773
+ }], () => [{ type: i1$1.BsModalRef }, { type: FixtureService }, { type: UuidService }, { type: ProjectService }, { type: PreviewService }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: PresetService }, { type: ConfigService }, { type: i1$1.BsModalService }], { mouseUp: [{
5358
5774
  type: HostListener,
5359
5775
  args: ['window:mouseup', ['$event']]
5360
5776
  }], handleKeyboardEvent: [{
@@ -5669,7 +6085,7 @@ class UserLoginComponent {
5669
6085
  i0.ɵɵproperty("ngIf", ctx.loggingIn);
5670
6086
  i0.ɵɵadvance();
5671
6087
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(38, 23, "designer.user.login"), " ");
5672
- } }, dependencies: [i5.NgIf, i4$1.ɵNgNoValidate, i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgControlStatusGroup, i4$1.RequiredValidator, i4$1.NgModel, i4$1.NgForm, i2.TranslatePipe] }); }
6088
+ } }, dependencies: [i5.NgIf, i4.ɵNgNoValidate, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgControlStatusGroup, i4.RequiredValidator, i4.NgModel, i4.NgForm, i2.TranslatePipe] }); }
5673
6089
  }
5674
6090
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserLoginComponent, [{
5675
6091
  type: Component,
@@ -5879,7 +6295,7 @@ class UserRegisterComponent {
5879
6295
  i0.ɵɵproperty("ngIf", ctx.registering);
5880
6296
  i0.ɵɵadvance();
5881
6297
  i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(64, 40, "designer.user.register"), " ");
5882
- } }, dependencies: [i5.NgIf, i4$1.ɵNgNoValidate, i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgControlStatusGroup, i4$1.RequiredValidator, i4$1.NgModel, i4$1.NgForm, i2.TranslatePipe] }); }
6298
+ } }, dependencies: [i5.NgIf, i4.ɵNgNoValidate, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgControlStatusGroup, i4.RequiredValidator, i4.NgModel, i4.NgForm, i2.TranslatePipe] }); }
5883
6299
  }
5884
6300
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserRegisterComponent, [{
5885
6301
  type: Component,
@@ -5918,6 +6334,91 @@ class UserEnsureLoginService {
5918
6334
  }]
5919
6335
  }], () => [{ type: UserService }, { type: i1$1.BsModalService }, { type: ConfigService }], null); })();
5920
6336
 
6337
+ class DropzoneComponent {
6338
+ set url(value) {
6339
+ this._url = value;
6340
+ this.updateConfig();
6341
+ }
6342
+ set acceptedFiles(value) {
6343
+ this._acceptedFiles = value;
6344
+ this.updateConfig();
6345
+ }
6346
+ set maxFiles(value) {
6347
+ this._maxFiles = value;
6348
+ this.updateConfig();
6349
+ }
6350
+ constructor(translateService, configService) {
6351
+ this.translateService = translateService;
6352
+ this.configService = configService;
6353
+ this.error = new EventEmitter();
6354
+ this.success = new EventEmitter();
6355
+ this.addedFile = new EventEmitter();
6356
+ this._maxFiles = undefined;
6357
+ this.translateService
6358
+ .get('designer.misc.dropzone-message')
6359
+ .pipe(map((result) => {
6360
+ this.uploadMessage = '<h3 class="mb-0"><i class="fa fa-cloud-upload"></i></h3>' + result;
6361
+ }))
6362
+ .subscribe();
6363
+ this.updateConfig();
6364
+ }
6365
+ updateConfig() {
6366
+ this.dropzoneConfig = {
6367
+ url: this.configService.restUrl + this._url,
6368
+ paramName: 'file',
6369
+ addRemoveLinks: false,
6370
+ maxFilesize: null /* unlimited */,
6371
+ acceptedFiles: this._acceptedFiles,
6372
+ timeout: 0,
6373
+ chunking: this.configService.dropzoneChunking,
6374
+ forceChunking: this.configService.dropzoneChunking,
6375
+ parallelUploads: 1,
6376
+ maxFiles: this._maxFiles,
6377
+ previewTemplate: `
6378
+ <div class="dz-preview dz-file-preview">
6379
+ <!-- The attachment details -->
6380
+ <div class="dz-details" style="text-align: left">
6381
+ <i class="fa fa-file-o"></i> <span data-dz-name></span> <small><span class="label label-default file-size" data-dz-size></span></small>
6382
+ </div>
6383
+
6384
+ <!--div class="mt-5">
6385
+ <span data-dz-errormessage></span>
6386
+ </div-->
6387
+
6388
+ <div class="progress mt-4 mb-1" style="height: 10px">
6389
+ <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width:0%;" data-dz-uploadprogress></div>
6390
+ </div>
6391
+ </div>
6392
+ `,
6393
+ };
6394
+ }
6395
+ static { this.ɵfac = function DropzoneComponent_Factory(t) { return new (t || DropzoneComponent)(i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(ConfigService)); }; }
6396
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DropzoneComponent, selectors: [["app-dropzone"]], inputs: { url: "url", acceptedFiles: "acceptedFiles", maxFiles: "maxFiles" }, outputs: { error: "error", success: "success", addedFile: "addedFile" }, decls: 1, vars: 3, consts: [[3, "error", "success", "addedFile", "config", "useDropzoneClass", "message"]], template: function DropzoneComponent_Template(rf, ctx) { if (rf & 1) {
6397
+ i0.ɵɵelementStart(0, "dropzone", 0);
6398
+ i0.ɵɵlistener("error", function DropzoneComponent_Template_dropzone_error_0_listener($event) { return ctx.error.emit($event); })("success", function DropzoneComponent_Template_dropzone_success_0_listener($event) { return ctx.success.emit($event); })("addedFile", function DropzoneComponent_Template_dropzone_addedFile_0_listener($event) { return ctx.addedFile.emit($event); });
6399
+ i0.ɵɵelementEnd();
6400
+ } if (rf & 2) {
6401
+ i0.ɵɵproperty("config", ctx.dropzoneConfig)("useDropzoneClass", "false")("message", ctx.uploadMessage);
6402
+ } }, dependencies: [i5$1.DropzoneComponent] }); }
6403
+ }
6404
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropzoneComponent, [{
6405
+ type: Component,
6406
+ args: [{ selector: 'app-dropzone', template: "<dropzone\n [config]=\"dropzoneConfig\"\n [useDropzoneClass]=\"'false'\"\n [message]=\"uploadMessage\"\n (error)=\"error.emit($event)\"\n (success)=\"success.emit($event)\"\n (addedFile)=\"addedFile.emit($event)\"\n></dropzone>\n" }]
6407
+ }], () => [{ type: i2.TranslateService }, { type: ConfigService }], { error: [{
6408
+ type: Output
6409
+ }], success: [{
6410
+ type: Output
6411
+ }], addedFile: [{
6412
+ type: Output
6413
+ }], url: [{
6414
+ type: Input
6415
+ }], acceptedFiles: [{
6416
+ type: Input
6417
+ }], maxFiles: [{
6418
+ type: Input
6419
+ }] }); })();
6420
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DropzoneComponent, { className: "DropzoneComponent" }); })();
6421
+
5921
6422
  function CompositionSettingsComponent_div_22_div_4_Template(rf, ctx) { if (rf & 1) {
5922
6423
  i0.ɵɵelementStart(0, "div");
5923
6424
  i0.ɵɵtext(1);
@@ -5977,8 +6478,8 @@ function CompositionSettingsComponent_div_22_Template(rf, ctx) { if (rf & 1) {
5977
6478
  i0.ɵɵtemplate(4, CompositionSettingsComponent_div_22_div_4_Template, 3, 3, "div", 19)(5, CompositionSettingsComponent_div_22_div_5_Template, 2, 1, "div", 19);
5978
6479
  i0.ɵɵelementEnd()();
5979
6480
  i0.ɵɵtemplate(6, CompositionSettingsComponent_div_22_ul_6_Template, 11, 6, "ul", 20);
5980
- i0.ɵɵelementStart(7, "div", 21)(8, "div", 22)(9, "dropzone", 23);
5981
- i0.ɵɵlistener("error", function CompositionSettingsComponent_div_22_Template_dropzone_error_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadError($event)); })("success", function CompositionSettingsComponent_div_22_Template_dropzone_success_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadSuccess($event)); })("queuecomplete", function CompositionSettingsComponent_div_22_Template_dropzone_queuecomplete_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onQueueComplete($event)); })("addedfile", function CompositionSettingsComponent_div_22_Template_dropzone_addedfile_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onAddedFile($event)); });
6481
+ i0.ɵɵelementStart(7, "div", 21)(8, "div", 22)(9, "app-dropzone", 23);
6482
+ i0.ɵɵlistener("error", function CompositionSettingsComponent_div_22_Template_app_dropzone_error_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadError($event)); })("success", function CompositionSettingsComponent_div_22_Template_app_dropzone_success_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadSuccess($event)); })("queuecomplete", function CompositionSettingsComponent_div_22_Template_app_dropzone_queuecomplete_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onQueueComplete($event)); })("addedfile", function CompositionSettingsComponent_div_22_Template_app_dropzone_addedfile_9_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onAddedFile($event)); });
5982
6483
  i0.ɵɵelementEnd()();
5983
6484
  i0.ɵɵelementStart(10, "div", 24)(11, "input", 25);
5984
6485
  i0.ɵɵpipe(12, "translate");
@@ -5997,11 +6498,11 @@ function CompositionSettingsComponent_div_22_Template(rf, ctx) { if (rf & 1) {
5997
6498
  i0.ɵɵadvance();
5998
6499
  i0.ɵɵproperty("ngIf", ctx_r1.configService.enableMediaLibrary);
5999
6500
  i0.ɵɵadvance(3);
6000
- i0.ɵɵproperty("config", ctx_r1.dropzoneConfig)("useDropzoneClass", "false")("message", ctx_r1.uploadMessage);
6501
+ i0.ɵɵproperty("url", ctx_r1.getDropzoneUrl())("acceptedFiles", "audio/*");
6001
6502
  i0.ɵɵadvance(2);
6002
- i0.ɵɵpropertyInterpolate("placeholder", i0.ɵɵpipeBind1(12, 8, "designer.misc.search"));
6503
+ i0.ɵɵpropertyInterpolate("placeholder", i0.ɵɵpipeBind1(12, 7, "designer.misc.search"));
6003
6504
  i0.ɵɵadvance(5);
6004
- i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind2(17, 10, ctx_r1.filteredExistingFiles, "name"));
6505
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind2(17, 9, ctx_r1.filteredExistingFiles, "name"));
6005
6506
  } }
6006
6507
  class CompositionSettingsComponent {
6007
6508
  constructor(bsModalRef, timelineService, configService, translateService, http, warningDialogService, toastrService, projectService) {
@@ -6020,40 +6521,6 @@ class CompositionSettingsComponent {
6020
6521
  this.uploading = false;
6021
6522
  }
6022
6523
  ngOnInit() {
6023
- const projectId = this.projectService.project.id ? this.projectService.project.id : '';
6024
- this.dropzoneConfig = {
6025
- url: this.configService.restUrl + 'file/upload?compositionUuid=' + this.composition.uuid + '&projectId=' + projectId,
6026
- addRemoveLinks: false,
6027
- maxFilesize: 100 /* 100 MB */,
6028
- acceptedFiles: 'audio/*',
6029
- timeout: 0,
6030
- parallelUploads: 1,
6031
- previewTemplate: `
6032
- <div class="dz-preview dz-file-preview">
6033
- <!-- The attachment details -->
6034
- <div class="dz-details" style="text-align: left">
6035
- <i class="fa fa-file-o"></i> <span data-dz-name></span> <small>
6036
- <span class="label label-default file-size" data-dz-size></span></small>
6037
- </div>
6038
-
6039
- <!--div class="mt-5">
6040
- <span data-dz-errormessage></span>
6041
- </div-->
6042
-
6043
- <div class="progress mt-4 mb-1" style="height: 10px">
6044
- <div class="progress-bar progress-bar-striped progress-bar-animated"
6045
- role="progressbar" style="width:0%;" data-dz-uploadprogress>
6046
- </div>
6047
- </div>
6048
- </div>
6049
- `,
6050
- };
6051
- this.translateService
6052
- .get('designer.misc.dropzone-message')
6053
- .pipe(map((result) => {
6054
- this.uploadMessage = '<h3 class="mb-0"><i class="fa fa-cloud-upload"></i></h3>' + result;
6055
- }))
6056
- .subscribe();
6057
6524
  this.loadFiles();
6058
6525
  if (this.timelineService.externalCompositionsAvailable) {
6059
6526
  this.timelineService.getExternalCompositionNames().subscribe((compositionNames) => {
@@ -6061,6 +6528,10 @@ class CompositionSettingsComponent {
6061
6528
  });
6062
6529
  }
6063
6530
  }
6531
+ getDropzoneUrl() {
6532
+ const projectId = this.projectService.project.id ? this.projectService.project.id : '';
6533
+ return 'file/upload?compositionUuid=' + this.composition.uuid + '&projectId=' + projectId;
6534
+ }
6064
6535
  ok() {
6065
6536
  this.onClose.next(1);
6066
6537
  this.bsModalRef.hide();
@@ -6154,10 +6625,10 @@ class CompositionSettingsComponent {
6154
6625
  }))
6155
6626
  .subscribe();
6156
6627
  }
6157
- static { this.ɵfac = function CompositionSettingsComponent_Factory(t) { return new (t || CompositionSettingsComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(TimelineService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i1.HttpClient), i0.ɵɵdirectiveInject(WarningDialogService), i0.ɵɵdirectiveInject(i3.ToastrService), i0.ɵɵdirectiveInject(ProjectService)); }; }
6628
+ static { this.ɵfac = function CompositionSettingsComponent_Factory(t) { return new (t || CompositionSettingsComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(TimelineService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i1.HttpClient), i0.ɵɵdirectiveInject(WarningDialogService), i0.ɵɵdirectiveInject(i3$1.ToastrService), i0.ɵɵdirectiveInject(ProjectService)); }; }
6158
6629
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CompositionSettingsComponent, selectors: [["lib-app-composition-settings"]], hostBindings: function CompositionSettingsComponent_HostBindings(rf, ctx) { if (rf & 1) {
6159
6630
  i0.ɵɵlistener("keydown.enter", function CompositionSettingsComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
6160
- } }, decls: 30, vars: 21, consts: [[1, "modal-header"], [1, "modal-title", "pull-left"], ["type", "button", "aria-label", "Close", 1, "close", "pull-right", 3, "click"], ["aria-hidden", "true"], [1, "modal-body"], [1, "form-group", "row"], [1, "col-lg-4", "col-form-label"], [1, "col-lg-8", "d-flex"], ["type", "text", 1, "form-control", 3, "ngModelChange", "ngModel", "typeahead"], [1, "custom-select", 3, "ngModelChange", "ngModel"], ["value", "audio"], ["class", "row", 4, "ngIf"], [1, "modal-footer"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "button", 1, "btn", "btn-primary", 3, "click", "disabled"], [1, "row"], [1, "px-3", "w-100"], [1, "card", "border-secondary", "mb-3"], [1, "card-body"], [4, "ngIf"], ["class", "nav nav-tabs mb-3", "id", "myTab", "role", "tablist", 4, "ngIf"], ["id", "myTabContent", 1, "tab-content"], ["id", "upload", "role", "tabpanel", 1, "tab-pane", "fade", "show", "active"], [3, "error", "success", "queuecomplete", "addedfile", "config", "useDropzoneClass", "message"], ["id", "media-library", "role", "tabpanel", 1, "tab-pane", "fade"], ["type", "text", "id", "searchFileList", 1, "form-control", "input-block", "mb-3", 3, "input", "placeholder"], [1, "card", "border-secondary", 2, "height", "200px", "overflow-y", "scroll"], [1, "card-body", "p-0"], [1, "list-group", "list-group-flush"], ["class", "list-group-item", "href", "#", 3, "active", "click", 4, "ngFor", "ngForOf"], ["id", "myTab", "role", "tablist", 1, "nav", "nav-tabs", "mb-3"], [1, "nav-item"], ["id", "upload-tab", "data-toggle", "tab", "href", "#upload", "role", "tab", 1, "nav-link", "active"], ["aria-hidden", "true", 1, "fa", "fa-upload"], ["id", "media-library-tab", "data-toggle", "tab", "href", "#media-library", "role", "tab", 1, "nav-link"], ["aria-hidden", "true", 1, "fa", "fa-folder-o"], ["href", "#", 1, "list-group-item", 3, "click"], [1, "col-auto", "my-auto", "flex-grow", "text-break-word"], [1, "col-auto", "my-auto", "pl-0", "text-danger", "float-right", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-trash-o"]], template: function CompositionSettingsComponent_Template(rf, ctx) { if (rf & 1) {
6631
+ } }, decls: 30, vars: 21, consts: [[1, "modal-header"], [1, "modal-title", "pull-left"], ["type", "button", "aria-label", "Close", 1, "close", "pull-right", 3, "click"], ["aria-hidden", "true"], [1, "modal-body"], [1, "form-group", "row"], [1, "col-lg-4", "col-form-label"], [1, "col-lg-8", "d-flex"], ["type", "text", 1, "form-control", 3, "ngModelChange", "ngModel", "typeahead"], [1, "custom-select", 3, "ngModelChange", "ngModel"], ["value", "audio"], ["class", "row", 4, "ngIf"], [1, "modal-footer"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "button", 1, "btn", "btn-primary", 3, "click", "disabled"], [1, "row"], [1, "px-3", "w-100"], [1, "card", "border-secondary", "mb-3"], [1, "card-body"], [4, "ngIf"], ["class", "nav nav-tabs mb-3", "id", "myTab", "role", "tablist", 4, "ngIf"], ["id", "myTabContent", 1, "tab-content"], ["id", "upload", "role", "tabpanel", 1, "tab-pane", "fade", "show", "active"], [3, "error", "success", "queuecomplete", "addedfile", "url", "acceptedFiles"], ["id", "media-library", "role", "tabpanel", 1, "tab-pane", "fade"], ["type", "text", "id", "searchFileList", 1, "form-control", "input-block", "mb-3", 3, "input", "placeholder"], [1, "card", "border-secondary", 2, "height", "200px", "overflow-y", "scroll"], [1, "card-body", "p-0"], [1, "list-group", "list-group-flush"], ["class", "list-group-item", "href", "#", 3, "active", "click", 4, "ngFor", "ngForOf"], ["id", "myTab", "role", "tablist", 1, "nav", "nav-tabs", "mb-3"], [1, "nav-item"], ["id", "upload-tab", "data-toggle", "tab", "href", "#upload", "role", "tab", 1, "nav-link", "active"], ["aria-hidden", "true", 1, "fa", "fa-upload"], ["id", "media-library-tab", "data-toggle", "tab", "href", "#media-library", "role", "tab", 1, "nav-link"], ["aria-hidden", "true", 1, "fa", "fa-folder-o"], ["href", "#", 1, "list-group-item", 3, "click"], [1, "col-auto", "my-auto", "flex-grow", "text-break-word"], [1, "col-auto", "my-auto", "pl-0", "text-danger", "float-right", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-trash-o"]], template: function CompositionSettingsComponent_Template(rf, ctx) { if (rf & 1) {
6161
6632
  i0.ɵɵelementStart(0, "div", 0)(1, "h4", 1);
6162
6633
  i0.ɵɵtext(2);
6163
6634
  i0.ɵɵelementEnd();
@@ -6183,7 +6654,7 @@ class CompositionSettingsComponent {
6183
6654
  i0.ɵɵtext(20);
6184
6655
  i0.ɵɵpipe(21, "translate");
6185
6656
  i0.ɵɵelementEnd()()()();
6186
- i0.ɵɵtemplate(22, CompositionSettingsComponent_div_22_Template, 18, 13, "div", 11);
6657
+ i0.ɵɵtemplate(22, CompositionSettingsComponent_div_22_Template, 18, 12, "div", 11);
6187
6658
  i0.ɵɵelementEnd();
6188
6659
  i0.ɵɵelementStart(23, "div", 12)(24, "a", 13);
6189
6660
  i0.ɵɵlistener("click", function CompositionSettingsComponent_Template_a_click_24_listener() { ctx.cancel(); return false; });
@@ -6216,12 +6687,12 @@ class CompositionSettingsComponent {
6216
6687
  i0.ɵɵproperty("disabled", ctx.uploading);
6217
6688
  i0.ɵɵadvance();
6218
6689
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(29, 19, "designer.misc.ok"));
6219
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i11.TypeaheadDirective, i5$1.DropzoneComponent, i2.TranslatePipe, ArraySortPipe] }); }
6690
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i11.TypeaheadDirective, DropzoneComponent, i2.TranslatePipe, ArraySortPipe] }); }
6220
6691
  }
6221
6692
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CompositionSettingsComponent, [{
6222
6693
  type: Component,
6223
- args: [{ selector: 'lib-app-composition-settings', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ composition.name }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"bsModalRef.hide()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.timeline.composition-name' | translate }}</label>\n <div class=\"col-lg-8 d-flex\">\n <input\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"composition.name\"\n (ngModelChange)=\"composition.name = $event\"\n [typeahead]=\"existingCompositionNames\"\n />\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.timeline.composition-sync-type' | translate }}</label>\n <div class=\"col-lg-8 d-flex\">\n <select class=\"custom-select\" [ngModel]=\"composition.syncType\" (ngModelChange)=\"composition.syncType = $event\">\n <!-- TODO -->\n <!-- <option value=\"none\">{{ 'designer.timeline.composition-sync-type-none' | translate }}</option> -->\n <option value=\"audio\">{{ 'designer.timeline.composition-sync-type-audio' | translate }}</option>\n </select>\n </div>\n </div>\n\n <div *ngIf=\"composition.syncType == 'audio'\" class=\"row\">\n <div class=\"px-3 w-100\">\n <!-- Selected file -->\n <div class=\"card border-secondary mb-3\">\n <div class=\"card-body\">\n <!-- No file selected -->\n <div *ngIf=\"!composition.audioFileName\">\n {{ 'designer.timeline.composition-no-file-selected' | translate }}\n </div>\n\n <!-- A file is selected -->\n <div *ngIf=\"composition.audioFileName\">\n {{ composition.audioFileName }}\n </div>\n </div>\n </div>\n\n <!-- Choose file -->\n <ul *ngIf=\"configService.enableMediaLibrary\" class=\"nav nav-tabs mb-3\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"upload-tab\" data-toggle=\"tab\" href=\"#upload\" role=\"tab\">\n <i class=\"fa fa-upload\" aria-hidden=\"true\"></i>\n {{ 'designer.timeline.composition-file-upload' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"media-library-tab\" data-toggle=\"tab\" href=\"#media-library\" role=\"tab\">\n <i class=\"fa fa-folder-o\" aria-hidden=\"true\"></i>\n {{ 'designer.timeline.composition-file-library' | translate }}\n </a>\n </li>\n </ul>\n\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- Upload -->\n <div class=\"tab-pane fade show active\" id=\"upload\" role=\"tabpanel\">\n <!-- Dropzone -->\n <dropzone\n [config]=\"dropzoneConfig\"\n [useDropzoneClass]=\"'false'\"\n [message]=\"uploadMessage\"\n (error)=\"onUploadError($event)\"\n (success)=\"onUploadSuccess($event)\"\n (queuecomplete)=\"onQueueComplete($event)\"\n (addedfile)=\"onAddedFile($event)\"\n ></dropzone>\n </div>\n\n <!-- Media library -->\n <div class=\"tab-pane fade\" id=\"media-library\" role=\"tabpanel\">\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchFileList\"\n placeholder=\"{{ 'designer.misc.search' | translate }}\"\n (input)=\"filterExistingFiles($event.target.value)\"\n />\n\n <div class=\"card border-secondary\" style=\"height: 200px; overflow-y: scroll\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\">\n <a\n *ngFor=\"let existingFile of filteredExistingFiles | sort: 'name'\"\n class=\"list-group-item\"\n [class.active]=\"composition.audioFileName == existingFile\"\n href=\"#\"\n (click)=\"selectExistingFile(existingFile); (false)\"\n >\n <div class=\"row\">\n <div class=\"col-auto my-auto flex-grow text-break-word\">\n {{ existingFile }}\n </div>\n\n <div class=\"col-auto my-auto pl-0 text-danger float-right\" (click)=\"deleteFile(existingFile); (false)\">\n <i class=\"fa fa-trash-o\" aria-hidden=\"true\"></i>\n </div>\n </div>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button [disabled]=\"uploading\" type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
6224
- }], () => [{ type: i1$1.BsModalRef }, { type: TimelineService }, { type: ConfigService }, { type: i2.TranslateService }, { type: i1.HttpClient }, { type: WarningDialogService }, { type: i3.ToastrService }, { type: ProjectService }], { handleKeyboardEvent: [{
6694
+ args: [{ selector: 'lib-app-composition-settings', template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ composition.name }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"bsModalRef.hide()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.timeline.composition-name' | translate }}</label>\n <div class=\"col-lg-8 d-flex\">\n <input\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"composition.name\"\n (ngModelChange)=\"composition.name = $event\"\n [typeahead]=\"existingCompositionNames\"\n />\n </div>\n </div>\n\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.timeline.composition-sync-type' | translate }}</label>\n <div class=\"col-lg-8 d-flex\">\n <select class=\"custom-select\" [ngModel]=\"composition.syncType\" (ngModelChange)=\"composition.syncType = $event\">\n <!-- TODO -->\n <!-- <option value=\"none\">{{ 'designer.timeline.composition-sync-type-none' | translate }}</option> -->\n <option value=\"audio\">{{ 'designer.timeline.composition-sync-type-audio' | translate }}</option>\n </select>\n </div>\n </div>\n\n <div *ngIf=\"composition.syncType == 'audio'\" class=\"row\">\n <div class=\"px-3 w-100\">\n <!-- Selected file -->\n <div class=\"card border-secondary mb-3\">\n <div class=\"card-body\">\n <!-- No file selected -->\n <div *ngIf=\"!composition.audioFileName\">\n {{ 'designer.timeline.composition-no-file-selected' | translate }}\n </div>\n\n <!-- A file is selected -->\n <div *ngIf=\"composition.audioFileName\">\n {{ composition.audioFileName }}\n </div>\n </div>\n </div>\n\n <!-- Choose file -->\n <ul *ngIf=\"configService.enableMediaLibrary\" class=\"nav nav-tabs mb-3\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"upload-tab\" data-toggle=\"tab\" href=\"#upload\" role=\"tab\">\n <i class=\"fa fa-upload\" aria-hidden=\"true\"></i>\n {{ 'designer.timeline.composition-file-upload' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"media-library-tab\" data-toggle=\"tab\" href=\"#media-library\" role=\"tab\">\n <i class=\"fa fa-folder-o\" aria-hidden=\"true\"></i>\n {{ 'designer.timeline.composition-file-library' | translate }}\n </a>\n </li>\n </ul>\n\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- Upload -->\n <div class=\"tab-pane fade show active\" id=\"upload\" role=\"tabpanel\">\n <app-dropzone\n [url]=\"getDropzoneUrl()\"\n [acceptedFiles]=\"'audio/*'\"\n (error)=\"onUploadError($event)\"\n (success)=\"onUploadSuccess($event)\"\n (queuecomplete)=\"onQueueComplete($event)\"\n (addedfile)=\"onAddedFile($event)\"\n ></app-dropzone>\n </div>\n\n <!-- Media library -->\n <div class=\"tab-pane fade\" id=\"media-library\" role=\"tabpanel\">\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchFileList\"\n placeholder=\"{{ 'designer.misc.search' | translate }}\"\n (input)=\"filterExistingFiles($event.target.value)\"\n />\n\n <div class=\"card border-secondary\" style=\"height: 200px; overflow-y: scroll\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\">\n <a\n *ngFor=\"let existingFile of filteredExistingFiles | sort : 'name'\"\n class=\"list-group-item\"\n [class.active]=\"composition.audioFileName == existingFile\"\n href=\"#\"\n (click)=\"selectExistingFile(existingFile); (false)\"\n >\n <div class=\"row\">\n <div class=\"col-auto my-auto flex-grow text-break-word\">\n {{ existingFile }}\n </div>\n\n <div class=\"col-auto my-auto pl-0 text-danger float-right\" (click)=\"deleteFile(existingFile); (false)\">\n <i class=\"fa fa-trash-o\" aria-hidden=\"true\"></i>\n </div>\n </div>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button [disabled]=\"uploading\" type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
6695
+ }], () => [{ type: i1$1.BsModalRef }, { type: TimelineService }, { type: ConfigService }, { type: i2.TranslateService }, { type: i1.HttpClient }, { type: WarningDialogService }, { type: i3$1.ToastrService }, { type: ProjectService }], { handleKeyboardEvent: [{
6225
6696
  type: HostListener,
6226
6697
  args: ['document:keydown.enter', ['$event']]
6227
6698
  }] }); })();
@@ -6423,7 +6894,7 @@ class TimelineGridComponent {
6423
6894
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 23, "designer.misc.cancel"), " ");
6424
6895
  i0.ɵɵadvance(3);
6425
6896
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(38, 25, "designer.misc.ok"));
6426
- } }, dependencies: [i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
6897
+ } }, dependencies: [i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
6427
6898
  }
6428
6899
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimelineGridComponent, [{
6429
6900
  type: Component,
@@ -6801,7 +7272,7 @@ class TimelineComponent {
6801
7272
  i0.ɵɵproperty("ngIf", ctx.timelineService.selectedComposition);
6802
7273
  i0.ɵɵadvance();
6803
7274
  i0.ɵɵproperty("ngIf", ctx.projectService.project.compositions.length == 0);
6804
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i12.PopoverDirective, i2.TranslatePipe] }); }
7275
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i12.PopoverDirective, i2.TranslatePipe] }); }
6805
7276
  }
6806
7277
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimelineComponent, [{
6807
7278
  type: Component,
@@ -6950,7 +7421,7 @@ class SceneSettingsComponent {
6950
7421
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(52, 29, "designer.misc.cancel"), " ");
6951
7422
  i0.ɵɵadvance(3);
6952
7423
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(55, 31, "designer.misc.ok"));
6953
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
7424
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
6954
7425
  }
6955
7426
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SceneSettingsComponent, [{
6956
7427
  type: Component,
@@ -7058,7 +7529,7 @@ class SceneComponent {
7058
7529
  function FixtureComponent_div_12_div_1_Template(rf, ctx) { if (rf & 1) {
7059
7530
  const _r1 = i0.ɵɵgetCurrentView();
7060
7531
  i0.ɵɵelementStart(0, "div", 12)(1, "div", 13);
7061
- i0.ɵɵlistener("click", function FixtureComponent_div_12_div_1_Template_div_click_1_listener($event) { const item_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.selectFixture($event, item_r2)); });
7532
+ i0.ɵɵlistener("click", function FixtureComponent_div_12_div_1_Template_div_click_1_listener($event) { const presetFixture_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.selectFixture($event, presetFixture_r2)); });
7062
7533
  i0.ɵɵelementStart(2, "div", 14);
7063
7534
  i0.ɵɵelement(3, "i", 15);
7064
7535
  i0.ɵɵelementEnd();
@@ -7070,15 +7541,15 @@ function FixtureComponent_div_12_div_1_Template(rf, ctx) { if (rf & 1) {
7070
7541
  i0.ɵɵtext(8);
7071
7542
  i0.ɵɵelementEnd()()();
7072
7543
  } if (rf & 2) {
7073
- const item_r2 = ctx.$implicit;
7544
+ const presetFixture_r2 = ctx.$implicit;
7074
7545
  const ctx_r2 = i0.ɵɵnextContext(2);
7075
- i0.ɵɵclassProp("inactive-list-item", !ctx_r2.fixtureIsSelected(item_r2));
7546
+ i0.ɵɵclassProp("inactive-list-item", !ctx_r2.fixtureIsSelected(presetFixture_r2));
7076
7547
  i0.ɵɵadvance(5);
7077
- i0.ɵɵproperty("ngModel", ctx_r2.fixtureIsSelected(item_r2));
7548
+ i0.ɵɵproperty("ngModel", ctx_r2.fixtureIsSelected(presetFixture_r2));
7078
7549
  i0.ɵɵadvance(2);
7079
- i0.ɵɵclassMapInterpolate1("icon-", ctx_r2.fixtureService.getFixtureIconClass(ctx_r2.fixtureService.getProfileByUuid(item_r2.profileUuid)), " mr-1");
7550
+ i0.ɵɵclassMapInterpolate1("icon-", ctx_r2.fixtureService.getFixtureIconClass(ctx_r2.fixtureService.getProfileByUuid(ctx_r2.fixtureService.getFixtureByUuid(presetFixture_r2.fixtureUuid).profileUuid)), " mr-1");
7080
7551
  i0.ɵɵadvance();
7081
- i0.ɵɵtextInterpolate1(" ", item_r2.name, " ");
7552
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.fixtureName(presetFixture_r2), " ");
7082
7553
  } }
7083
7554
  function FixtureComponent_div_12_Template(rf, ctx) { if (rf & 1) {
7084
7555
  i0.ɵɵelementStart(0, "div", 10);
@@ -7086,9 +7557,9 @@ function FixtureComponent_div_12_Template(rf, ctx) { if (rf & 1) {
7086
7557
  i0.ɵɵelementEnd();
7087
7558
  } if (rf & 2) {
7088
7559
  const ctx_r2 = i0.ɵɵnextContext();
7089
- i0.ɵɵproperty("sortablejs", ctx_r2.projectService.project.fixtures);
7560
+ i0.ɵɵproperty("sortablejs", ctx_r2.projectService.project.presetFixtures);
7090
7561
  i0.ɵɵadvance();
7091
- i0.ɵɵproperty("ngForOf", ctx_r2.projectService.project.fixtures);
7562
+ i0.ɵɵproperty("ngForOf", ctx_r2.projectService.project.presetFixtures);
7092
7563
  } }
7093
7564
  function FixtureComponent_div_13_Template(rf, ctx) { if (rf & 1) {
7094
7565
  const _r4 = i0.ɵɵgetCurrentView();
@@ -7111,15 +7582,25 @@ class FixtureComponent {
7111
7582
  this.introService = introService;
7112
7583
  }
7113
7584
  ngOnInit() { }
7114
- fixtureIsSelected(fixture) {
7585
+ fixtureName(presetFixture) {
7586
+ let name;
7587
+ name = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid).name;
7588
+ if (presetFixture.pixelKey) {
7589
+ name += ' - ' + presetFixture.pixelKey;
7590
+ }
7591
+ return name;
7592
+ }
7593
+ fixtureIsSelected(presetFixture) {
7594
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
7115
7595
  if (this.fixtureService.settingsSelection) {
7116
7596
  return this.fixtureService.settingsFixtureIsSelected(fixture);
7117
7597
  }
7118
7598
  else {
7119
- return this.presetService.fixtureIsSelected(fixture);
7599
+ return this.presetService.fixtureIsSelected(fixture, presetFixture.pixelKey);
7120
7600
  }
7121
7601
  }
7122
- selectFixture(event, fixture) {
7602
+ selectFixture(event, presetFixture) {
7603
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
7123
7604
  if (this.fixtureService.settingsSelection) {
7124
7605
  // select fixtures for the settings
7125
7606
  this.fixtureService.switchSettingsFixtureSelection(fixture);
@@ -7127,7 +7608,7 @@ class FixtureComponent {
7127
7608
  }
7128
7609
  else {
7129
7610
  // select fixtures for the current preset
7130
- this.presetService.switchFixtureSelection(fixture);
7611
+ this.presetService.switchFixtureSelection(fixture, presetFixture.pixelKey);
7131
7612
  this.presetService.fixtureSelectionChanged.next();
7132
7613
  this.presetService.previewLive();
7133
7614
  }
@@ -7168,12 +7649,12 @@ class FixtureComponent {
7168
7649
  i0.ɵɵadvance(12);
7169
7650
  i0.ɵɵproperty("ngIf", ctx.presetService.selectedPreset);
7170
7651
  i0.ɵɵadvance();
7171
- i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
7172
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
7652
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.presetFixtures.length == 0);
7653
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
7173
7654
  }
7174
7655
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureComponent, [{
7175
7656
  type: Component,
7176
- args: [{ selector: 'lib-app-fixture', template: "<div class=\"card border-secondary h-100 panel\" [class.card-intro-active]=\"introService.showStep('fixtures')\">\n <div class=\"card-header d-flex\">\n <div>Fixtures</div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"selectNone(); (false)\"\n ><i class=\"fa fa-square-o fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"selectAll(); (false)\"\n ><i class=\"fa fa-check-square-o fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"openFixturePool(); (false)\"\n ><i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of fixtures -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"list-group\" [sortablejs]=\"projectService.project.fixtures\">\n <div\n class=\"list-group-item\"\n *ngFor=\"let item of projectService.project.fixtures\"\n [class.inactive-list-item]=\"!fixtureIsSelected(item)\"\n >\n <div class=\"row d-flex\" (click)=\"selectFixture($event, item)\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"active\" [ngModel]=\"fixtureIsSelected(item)\" />\n </div>\n <div>\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(item.profileUuid)) }} mr-1\"></span>\n {{ item.name }}\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"w-100 h-100 d-flex p-3 text-center\">\n <a href=\"#\" class=\"m-auto\" (click)=\"openFixturePool(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i> {{ 'designer.fixture.no-fixtures' | translate }}</a\n >\n </div>\n </div>\n</div>\n" }]
7657
+ args: [{ selector: 'lib-app-fixture', template: "<div class=\"card border-secondary h-100 panel\" [class.card-intro-active]=\"introService.showStep('fixtures')\">\n <div class=\"card-header d-flex\">\n <div>Fixtures</div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"selectNone(); (false)\"\n ><i class=\"fa fa-square-o fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"selectAll(); (false)\"\n ><i class=\"fa fa-check-square-o fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"openFixturePool(); (false)\"\n ><i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of fixtures -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"list-group\" [sortablejs]=\"projectService.project.presetFixtures\">\n <div\n class=\"list-group-item\"\n *ngFor=\"let presetFixture of projectService.project.presetFixtures\"\n [class.inactive-list-item]=\"!fixtureIsSelected(presetFixture)\"\n >\n <div class=\"row d-flex\" (click)=\"selectFixture($event, presetFixture)\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"active\" [ngModel]=\"fixtureIsSelected(presetFixture)\" />\n </div>\n <div>\n <span\n class=\"icon-{{\n fixtureService.getFixtureIconClass(\n fixtureService.getProfileByUuid(fixtureService.getFixtureByUuid(presetFixture.fixtureUuid).profileUuid)\n )\n }} mr-1\"\n ></span>\n {{ fixtureName(presetFixture) }}\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"projectService.project.presetFixtures.length == 0\" class=\"w-100 h-100 d-flex p-3 text-center\">\n <a href=\"#\" class=\"m-auto\" (click)=\"openFixturePool(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i> {{ 'designer.fixture.no-fixtures' | translate }}</a\n >\n </div>\n </div>\n</div>\n" }]
7177
7658
  }], () => [{ type: ProjectService }, { type: PresetService }, { type: FixturePoolService }, { type: FixtureService }, { type: IntroService }], null); })();
7178
7659
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureComponent, { className: "FixtureComponent" }); })();
7179
7660
 
@@ -7307,7 +7788,7 @@ class FixtureCapabilityColorComponent {
7307
7788
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 5, "designer.fixture.capability-color"));
7308
7789
  i0.ɵɵadvance(3);
7309
7790
  i0.ɵɵtwoWayProperty("ngModel", ctx.color);
7310
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
7791
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
7311
7792
  }
7312
7793
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityColorComponent, [{
7313
7794
  type: Component,
@@ -7378,7 +7859,7 @@ class FixtureCapabilityDimmerComponent {
7378
7859
  i0.ɵɵproperty("ngModel", ctx.getValueText() >= 0 ? ctx.getValueText() : 0);
7379
7860
  i0.ɵɵadvance(2);
7380
7861
  i0.ɵɵproperty("value", ctx.getValue() >= 0 ? ctx.getValue() : 0)("orientation", "vertical")("reversed", true)("tooltip", "hide")("min", 0)("max", 1)("step", 0.001);
7381
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent] }); }
7862
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent] }); }
7382
7863
  }
7383
7864
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityDimmerComponent, [{
7384
7865
  type: Component,
@@ -7489,7 +7970,7 @@ class FixtureCapabilityPanTiltComponent {
7489
7970
  i0.ɵɵproperty("ngModel", ctx.getValueTextTilt() >= 0 ? ctx.getValueTextTilt() : 0);
7490
7971
  i0.ɵɵadvance(2);
7491
7972
  i0.ɵɵproperty("value", ctx.getValueTilt() >= 0 ? ctx.getValueTilt() : 0)("orientation", "vertical")("reversed", true)("tooltip", "hide")("min", 0)("max", 1)("step", 0.001);
7492
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i2.TranslatePipe] }); }
7973
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
7493
7974
  }
7494
7975
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityPanTiltComponent, [{
7495
7976
  type: Component,
@@ -7682,7 +8163,7 @@ class FixtureCapabilityColorWheelComponent {
7682
8163
  i0.ɵɵproperty("ngIf", ctx.showContainer);
7683
8164
  i0.ɵɵadvance();
7684
8165
  i0.ɵɵproperty("ngIf", ctx.wheel);
7685
- } }, dependencies: [i5.NgForOf, i5.NgIf, i5.NgStyle, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe], styles: [".color[_ngcontent-%COMP%]{box-sizing:border-box;width:50px;height:50px;border:solid 1px #ced4da;cursor:pointer}.color-selected[_ngcontent-%COMP%]{border-width:3px;border-color:#fff}.color-selected-inner[_ngcontent-%COMP%]{border:solid 1px black;height:100%;width:100%}"] }); }
8166
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i5.NgStyle, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe], styles: [".color[_ngcontent-%COMP%]{box-sizing:border-box;width:50px;height:50px;border:solid 1px #ced4da;cursor:pointer}.color-selected[_ngcontent-%COMP%]{border-width:3px;border-color:#fff}.color-selected-inner[_ngcontent-%COMP%]{border:solid 1px black;height:100%;width:100%}"] }); }
7686
8167
  }
7687
8168
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityColorWheelComponent, [{
7688
8169
  type: Component,
@@ -7799,8 +8280,8 @@ class FixtureCapabilityComponent {
7799
8280
  if (!this.presetService.selectedPreset) {
7800
8281
  return;
7801
8282
  }
7802
- for (const fixtureUuid of this.presetService.selectedPreset.fixtureUuids) {
7803
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
8283
+ for (const preserFixture of this.presetService.selectedPreset.fixtures) {
8284
+ const fixture = this.fixtureService.getCachedFixtureByUuid(preserFixture.fixtureUuid, preserFixture.pixelKey);
7804
8285
  for (const channel of fixture.channels) {
7805
8286
  for (const capability of channel.capabilities) {
7806
8287
  if (capability.wheel && capability.wheelSlots && capability.wheelSlots.length > 0) {
@@ -7841,12 +8322,12 @@ class FixtureCapabilityComponent {
7841
8322
  i0.ɵɵadvance();
7842
8323
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
7843
8324
  i0.ɵɵadvance();
7844
- i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtureUuids.length == 0);
8325
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length == 0);
7845
8326
  } }, dependencies: [i5.NgForOf, i5.NgIf, FixtureCapabilityColorComponent, FixtureCapabilityDimmerComponent, FixtureCapabilityPanTiltComponent, FixtureCapabilityColorWheelComponent, i5.KeyValuePipe, i2.TranslatePipe], changeDetection: 0 }); }
7846
8327
  }
7847
8328
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityComponent, [{
7848
8329
  type: Component,
7849
- args: [{ selector: 'lib-app-fixture-capability', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card border-secondary panel h-100\" [class.card-intro-active]=\"introService.showStep('capabilities')\">\n <div class=\"card-body capability-container d-flex h-100\" style=\"overflow-y: hidden\">\n <!-- h-100 needs to be applied in chrome to avoid performance issues with many layouts (reflows)\n during sliding. But the class must not be applied e.g. in Safari, because the bottom margin is not correct\n anymore afterwards. -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"row m-0 pl-3\" [class.h-100]=\"isChrome()\">\n <!-- Dimmer -->\n <!-- the height attribute is required to avoid performance issues with many layouts (reflows)\n in Chrome during sliding -->\n <div *ngIf=\"presetService.hasCapabilityDimmer()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-dimmer></lib-app-fixture-capability-dimmer>\n </div>\n\n <!-- Color -->\n <!-- Also show for color wheel fixtures to approx. the color -->\n <div *ngIf=\"presetService.hasCapabilityColorOrColorWheel()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-color></lib-app-fixture-capability-color>\n </div>\n\n <!-- Color wheels -->\n <div\n *ngFor=\"let entry of colorWheelChannels | keyvalue; let i = index\"\n class=\"col col-auto p-0 my-3 mr-3\"\n style=\"height: calc(100% - 2rem)\"\n >\n <lib-app-fixture-capability-color-wheel\n [profile]=\"entry.key\"\n [channel]=\"entry.value\"\n [wheelIndex]=\"i\"\n [showContainer]=\"colorWheelChannels.size > 1\"\n ></lib-app-fixture-capability-color-wheel>\n </div>\n\n <!-- Pan/Tilt -->\n <div *ngIf=\"presetService.hasCapabilityPanTilt()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-pan-tilt></lib-app-fixture-capability-pan-tilt>\n </div>\n\n <!-- Fix spacing at the end -->\n <div class=\"col col-auto p-0 my-3 mr-3\">&nbsp;</div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"m-auto\">\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures' | translate }}</p>\n </div>\n\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 && presetService.selectedPreset && presetService.selectedPreset.fixtureUuids.length == 0\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures-selected' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
8330
+ args: [{ selector: 'lib-app-fixture-capability', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card border-secondary panel h-100\" [class.card-intro-active]=\"introService.showStep('capabilities')\">\n <div class=\"card-body capability-container d-flex h-100\" style=\"overflow-y: hidden\">\n <!-- h-100 needs to be applied in chrome to avoid performance issues with many layouts (reflows)\n during sliding. But the class must not be applied e.g. in Safari, because the bottom margin is not correct\n anymore afterwards. -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"row m-0 pl-3\" [class.h-100]=\"isChrome()\">\n <!-- Dimmer -->\n <!-- the height attribute is required to avoid performance issues with many layouts (reflows)\n in Chrome during sliding -->\n <div *ngIf=\"presetService.hasCapabilityDimmer()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-dimmer></lib-app-fixture-capability-dimmer>\n </div>\n\n <!-- Color -->\n <!-- Also show for color wheel fixtures to approx. the color -->\n <div *ngIf=\"presetService.hasCapabilityColorOrColorWheel()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-color></lib-app-fixture-capability-color>\n </div>\n\n <!-- Color wheels -->\n <div\n *ngFor=\"let entry of colorWheelChannels | keyvalue; let i = index\"\n class=\"col col-auto p-0 my-3 mr-3\"\n style=\"height: calc(100% - 2rem)\"\n >\n <lib-app-fixture-capability-color-wheel\n [profile]=\"entry.key\"\n [channel]=\"entry.value\"\n [wheelIndex]=\"i\"\n [showContainer]=\"colorWheelChannels.size > 1\"\n ></lib-app-fixture-capability-color-wheel>\n </div>\n\n <!-- Pan/Tilt -->\n <div *ngIf=\"presetService.hasCapabilityPanTilt()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-pan-tilt></lib-app-fixture-capability-pan-tilt>\n </div>\n\n <!-- Fix spacing at the end -->\n <div class=\"col col-auto p-0 my-3 mr-3\">&nbsp;</div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"m-auto\">\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures' | translate }}</p>\n </div>\n\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 && presetService.selectedPreset && presetService.selectedPreset.fixtures.length == 0\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures-selected' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
7850
8331
  }], () => [{ type: PresetService }, { type: FixtureService }, { type: i0.ChangeDetectorRef }, { type: ProjectService }, { type: IntroService }], null); })();
7851
8332
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureCapabilityComponent, { className: "FixtureCapabilityComponent" }); })();
7852
8333
 
@@ -8196,7 +8677,7 @@ class FixtureSettingsPositionComponent {
8196
8677
  i0.ɵɵproperty("ngIf", ctx.fixtureService.selectedSettingsFixtures.length > 0);
8197
8678
  i0.ɵɵadvance();
8198
8679
  i0.ɵɵproperty("ngIf", ctx.fixtureService.selectedSettingsFixtures.length == 0);
8199
- } }, dependencies: [i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i2.TranslatePipe] }); }
8680
+ } }, dependencies: [i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
8200
8681
  }
8201
8682
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureSettingsPositionComponent, [{
8202
8683
  type: Component,
@@ -8338,7 +8819,7 @@ class FixtureSettingsStageComponent {
8338
8819
  i0.ɵɵproperty("tooltip", "hide")("value", ctx.projectService.project.stagePillarWidthCm)("min", 1)("max", 200)("step", 5);
8339
8820
  i0.ɵɵadvance(2);
8340
8821
  i0.ɵɵproperty("ngModel", ctx.projectService.project.stagePillarWidthCm);
8341
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i2.TranslatePipe] }); }
8822
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
8342
8823
  }
8343
8824
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureSettingsStageComponent, [{
8344
8825
  type: Component,
@@ -8533,12 +9014,20 @@ class EffectCurveComponent {
8533
9014
  }
8534
9015
  getPhasingCount() {
8535
9016
  let count = 0;
8536
- const countedDmxChannels = [];
8537
- for (const fixtureUuid of this.presetService.selectedPreset.fixtureUuids) {
8538
- const fixture = this.fixtureService.getFixtureByUuid(fixtureUuid);
8539
- if (!countedDmxChannels.includes(fixture.dmxFirstChannel)) {
9017
+ const countedFirstDmxChannelPixelKey = [];
9018
+ for (const presetFixture of this.presetService.selectedPreset.fixtures) {
9019
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
9020
+ const firstDmxChannelAndFixtureUuid = {
9021
+ firstDmxChannel: fixture.dmxFirstChannel,
9022
+ pixelKey: presetFixture.pixelKey,
9023
+ };
9024
+ const exists = countedFirstDmxChannelPixelKey.some((item) => item.firstDmxChannel === firstDmxChannelAndFixtureUuid.firstDmxChannel &&
9025
+ ((!item.pixelKey && !firstDmxChannelAndFixtureUuid.pixelKey) || item.pixelKey === firstDmxChannelAndFixtureUuid.pixelKey));
9026
+ // don't count it, if it has the same DMX address and pixel key (if available),
9027
+ // as an already counted one
9028
+ if (!exists) {
8540
9029
  count++;
8541
- countedDmxChannels.push(fixture.dmxFirstChannel);
9030
+ countedFirstDmxChannelPixelKey.push(firstDmxChannelAndFixtureUuid);
8542
9031
  }
8543
9032
  }
8544
9033
  return count;
@@ -8919,7 +9408,7 @@ class EffectCurveComponent {
8919
9408
  i0.ɵɵproperty("ngIf", ctx.availableProfiles.length > 1);
8920
9409
  i0.ɵɵadvance();
8921
9410
  i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(77, 81, ctx.availableChannels));
8922
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.NgSelectOption, i4$1.ɵNgSelectMultipleOption, i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.SelectControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i12.PopoverDirective, i5.AsyncPipe, i5.KeyValuePipe, i2.TranslatePipe], styles: [".curve-grid[_ngcontent-%COMP%]{background-color:#000;border:1px solid white}.applying-to[_ngcontent-%COMP%]{overflow-y:scroll;height:130px!important;background-color:#222;border:1px solid white;padding:.5rem}.applying-to[_ngcontent-%COMP%] .form-check[_ngcontent-%COMP%]:last-child{margin-bottom:.5rem}"] }); }
9411
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i12.PopoverDirective, i5.AsyncPipe, i5.KeyValuePipe, i2.TranslatePipe], styles: [".curve-grid[_ngcontent-%COMP%]{background-color:#000;border:1px solid white}.applying-to[_ngcontent-%COMP%]{overflow-y:scroll;height:130px!important;background-color:#222;border:1px solid white;padding:.5rem}.applying-to[_ngcontent-%COMP%] .form-check[_ngcontent-%COMP%]:last-child{margin-bottom:.5rem}"] }); }
8923
9412
  }
8924
9413
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EffectCurveComponent, [{
8925
9414
  type: Component,
@@ -9301,7 +9790,7 @@ class PresetSettingsComponent {
9301
9790
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(72, 43, "designer.misc.cancel"), " ");
9302
9791
  i0.ɵɵadvance(3);
9303
9792
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(75, 45, "designer.misc.ok"));
9304
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
9793
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
9305
9794
  }
9306
9795
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PresetSettingsComponent, [{
9307
9796
  type: Component,
@@ -9418,7 +9907,7 @@ class PresetComponent {
9418
9907
  i0.ɵɵproperty("sortablejs", ctx.projectService.project.presets);
9419
9908
  i0.ɵɵadvance();
9420
9909
  i0.ɵɵproperty("ngForOf", ctx.projectService.project.presets);
9421
- } }, dependencies: [i5.NgForOf, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
9910
+ } }, dependencies: [i5.NgForOf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
9422
9911
  }
9423
9912
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PresetComponent, [{
9424
9913
  type: Component,
@@ -9476,7 +9965,7 @@ class MasterDimmerComponent {
9476
9965
  i0.ɵɵproperty("value", ctx.projectService == null ? null : ctx.projectService.project == null ? null : ctx.projectService.project.masterDimmerValue)("orientation", "horizontal")("tooltip", "hide")("min", 0)("max", 1)("step", 0.001);
9477
9966
  i0.ɵɵadvance(2);
9478
9967
  i0.ɵɵproperty("ngModel", ctx.getValue());
9479
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent] }); }
9968
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent] }); }
9480
9969
  }
9481
9970
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MasterDimmerComponent, [{
9482
9971
  type: Component,
@@ -9679,7 +10168,7 @@ class FixtureCapabilityChannelComponent {
9679
10168
  i0.ɵɵproperty("ngIf", (ctx._channel.capabilities == null ? null : ctx._channel.capabilities.length) > 1);
9680
10169
  i0.ɵɵadvance();
9681
10170
  i0.ɵɵproperty("ngIf", ctx.capabilityHasRange());
9682
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.RadioControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i2.TranslatePipe], changeDetection: 0 }); }
10171
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.RadioControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe], changeDetection: 0 }); }
9683
10172
  }
9684
10173
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityChannelComponent, [{
9685
10174
  type: Component,
@@ -9795,7 +10284,9 @@ class FixtureChannelComponent {
9795
10284
  this.calculateProfiles();
9796
10285
  });
9797
10286
  }
9798
- ngOnInit() { }
10287
+ ngOnInit() {
10288
+ this.calculateProfiles();
10289
+ }
9799
10290
  ngOnDestroy() {
9800
10291
  this.fixtureSelectionChangedSubscription.unsubscribe();
9801
10292
  this.previewSelectionChangedSubscription.unsubscribe();
@@ -9837,12 +10328,12 @@ class FixtureChannelComponent {
9837
10328
  i0.ɵɵadvance();
9838
10329
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
9839
10330
  i0.ɵɵadvance();
9840
- i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtureUuids.length == 0);
9841
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, FixtureCapabilityChannelComponent, i5.KeyValuePipe, i2.TranslatePipe] }); }
10331
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length == 0);
10332
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, FixtureCapabilityChannelComponent, i5.KeyValuePipe, i2.TranslatePipe] }); }
9842
10333
  }
9843
10334
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureChannelComponent, [{
9844
10335
  type: Component,
9845
- args: [{ selector: 'lib-app-fixture-channel', template: "<div class=\"card border-secondary panel h-100\">\n <div class=\"card-body capability-container d-flex h-100\" style=\"overflow-y: hidden\">\n <!-- h-100 needs to be applied in chrome to avoid performance issues with many layouts (reflows)\n during sliding. But the class must not be applied e.g. in Safari, because the bottom margin is not correct\n anymore afterwards. -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"row m-0 pl-3\" [class.h-100]=\"isChrome()\">\n <!-- profile selection -->\n <div\n *ngIf=\"profiles.length > 1\"\n class=\"col col-auto p-3 my-3 mr-3\"\n style=\"height: calc(100% - 2rem); border: solid 1px #444; border-right: none\"\n >\n <div *ngFor=\"let profile of profiles; let i = index\" class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"capabilityFilter{{ i }}\"\n [ngModel]=\"selectedProfiles.indexOf(profile) >= 0\"\n (ngModelChange)=\"changeProfileSelection($event, profile)\"\n />\n <label class=\"form-check-label\" for=\"capabilityFilter{{ i }}\">\n {{ profile.name }}\n </label>\n </div>\n </div>\n\n <!-- all channel capabilities -->\n <ng-container *ngFor=\"let entry of channelCapabilities | keyvalue; let i = index\">\n <div *ngFor=\"let capability of entry.value; let j = index\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-channel [profile]=\"entry.key\" [channel]=\"capability\" [capabilityIndex]=\"i * 10000 + j\">\n </lib-app-fixture-capability-channel>\n </div>\n </ng-container>\n\n <!-- fix spacing at the end -->\n <div class=\"col col-auto p-0 my-3 mr-3\">&nbsp;</div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"m-auto\">\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures' | translate }}</p>\n </div>\n\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 && presetService.selectedPreset && presetService.selectedPreset.fixtureUuids.length == 0\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures-selected' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
10336
+ args: [{ selector: 'lib-app-fixture-channel', template: "<div class=\"card border-secondary panel h-100\">\n <div class=\"card-body capability-container d-flex h-100\" style=\"overflow-y: hidden\">\n <!-- h-100 needs to be applied in chrome to avoid performance issues with many layouts (reflows)\n during sliding. But the class must not be applied e.g. in Safari, because the bottom margin is not correct\n anymore afterwards. -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"row m-0 pl-3\" [class.h-100]=\"isChrome()\">\n <!-- profile selection -->\n <div\n *ngIf=\"profiles.length > 1\"\n class=\"col col-auto p-3 my-3 mr-3\"\n style=\"height: calc(100% - 2rem); border: solid 1px #444; border-right: none\"\n >\n <div *ngFor=\"let profile of profiles; let i = index\" class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"capabilityFilter{{ i }}\"\n [ngModel]=\"selectedProfiles.indexOf(profile) >= 0\"\n (ngModelChange)=\"changeProfileSelection($event, profile)\"\n />\n <label class=\"form-check-label\" for=\"capabilityFilter{{ i }}\">\n {{ profile.name }}\n </label>\n </div>\n </div>\n\n <!-- all channel capabilities -->\n <ng-container *ngFor=\"let entry of channelCapabilities | keyvalue; let i = index\">\n <div *ngFor=\"let capability of entry.value; let j = index\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-channel [profile]=\"entry.key\" [channel]=\"capability\" [capabilityIndex]=\"i * 10000 + j\">\n </lib-app-fixture-capability-channel>\n </div>\n </ng-container>\n\n <!-- fix spacing at the end -->\n <div class=\"col col-auto p-0 my-3 mr-3\">&nbsp;</div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"m-auto\">\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures' | translate }}</p>\n </div>\n\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 && presetService.selectedPreset && presetService.selectedPreset.fixtures.length == 0\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures-selected' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
9846
10337
  }], () => [{ type: PresetService }, { type: i0.ChangeDetectorRef }, { type: ProjectService }], null); })();
9847
10338
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureChannelComponent, { className: "FixtureChannelComponent" }); })();
9848
10339
 
@@ -9938,9 +10429,9 @@ class IntroComponent {
9938
10429
  const _c0 = a0 => ({ height: a0 });
9939
10430
  function DesignerComponent_li_52_Template(rf, ctx) { if (rf & 1) {
9940
10431
  const _r1 = i0.ɵɵgetCurrentView();
9941
- i0.ɵɵelementStart(0, "li", 54)(1, "a", 55);
10432
+ i0.ɵɵelementStart(0, "li", 38)(1, "a", 39);
9942
10433
  i0.ɵɵlistener("click", function DesignerComponent_li_52_Template_a_click_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.projectShare(); return i0.ɵɵresetView(false); });
9943
- i0.ɵɵelement(2, "i", 56);
10434
+ i0.ɵɵelement(2, "i", 40);
9944
10435
  i0.ɵɵtext(3);
9945
10436
  i0.ɵɵpipe(4, "translate");
9946
10437
  i0.ɵɵelementEnd()();
@@ -9951,15 +10442,15 @@ function DesignerComponent_li_52_Template(rf, ctx) { if (rf & 1) {
9951
10442
  function DesignerComponent_li_53_Template(rf, ctx) { if (rf & 1) {
9952
10443
  const _r3 = i0.ɵɵgetCurrentView();
9953
10444
  i0.ɵɵelementStart(0, "li", 3)(1, "a", 14);
9954
- i0.ɵɵelement(2, "i", 57);
10445
+ i0.ɵɵelement(2, "i", 41);
9955
10446
  i0.ɵɵtext(3);
9956
10447
  i0.ɵɵpipe(4, "translate");
9957
10448
  i0.ɵɵelementEnd();
9958
- i0.ɵɵelementStart(5, "div", 58)(6, "a", 59);
10449
+ i0.ɵɵelementStart(5, "div", 42)(6, "a", 43);
9959
10450
  i0.ɵɵlistener("click", function DesignerComponent_li_53_Template_a_click_6_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchLanguage("en"); return i0.ɵɵresetView(false); });
9960
10451
  i0.ɵɵtext(7, "English");
9961
10452
  i0.ɵɵelementEnd();
9962
- i0.ɵɵelementStart(8, "a", 59);
10453
+ i0.ɵɵelementStart(8, "a", 43);
9963
10454
  i0.ɵɵlistener("click", function DesignerComponent_li_53_Template_a_click_8_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.switchLanguage("de"); return i0.ɵɵresetView(false); });
9964
10455
  i0.ɵɵtext(9, "Deutsch");
9965
10456
  i0.ɵɵelementEnd()()();
@@ -9969,9 +10460,9 @@ function DesignerComponent_li_53_Template(rf, ctx) { if (rf & 1) {
9969
10460
  } }
9970
10461
  function DesignerComponent_li_54_Template(rf, ctx) { if (rf & 1) {
9971
10462
  const _r4 = i0.ɵɵgetCurrentView();
9972
- i0.ɵɵelementStart(0, "li", 60)(1, "a", 61);
10463
+ i0.ɵɵelementStart(0, "li", 44)(1, "a", 45);
9973
10464
  i0.ɵɵlistener("click", function DesignerComponent_li_54_Template_a_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.userRegister(); return i0.ɵɵresetView(false); });
9974
- i0.ɵɵelement(2, "i", 62);
10465
+ i0.ɵɵelement(2, "i", 46);
9975
10466
  i0.ɵɵtext(3);
9976
10467
  i0.ɵɵpipe(4, "translate");
9977
10468
  i0.ɵɵelementEnd()();
@@ -9982,12 +10473,12 @@ function DesignerComponent_li_54_Template(rf, ctx) { if (rf & 1) {
9982
10473
  function DesignerComponent_li_55_Template(rf, ctx) { if (rf & 1) {
9983
10474
  const _r5 = i0.ɵɵgetCurrentView();
9984
10475
  i0.ɵɵelementStart(0, "li", 3)(1, "a", 14);
9985
- i0.ɵɵelement(2, "i", 62);
10476
+ i0.ɵɵelement(2, "i", 46);
9986
10477
  i0.ɵɵtext(3);
9987
10478
  i0.ɵɵelementEnd();
9988
- i0.ɵɵelementStart(4, "div", 58)(5, "a", 59);
10479
+ i0.ɵɵelementStart(4, "div", 42)(5, "a", 43);
9989
10480
  i0.ɵɵlistener("click", function DesignerComponent_li_55_Template_a_click_5_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.userService.logout(); return i0.ɵɵresetView(false); });
9990
- i0.ɵɵelement(6, "i", 63);
10481
+ i0.ɵɵelement(6, "i", 47);
9991
10482
  i0.ɵɵtext(7);
9992
10483
  i0.ɵɵpipe(8, "translate");
9993
10484
  i0.ɵɵelementEnd()()();
@@ -9998,6 +10489,81 @@ function DesignerComponent_li_55_Template(rf, ctx) { if (rf & 1) {
9998
10489
  i0.ɵɵadvance(4);
9999
10490
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(8, 2, "designer.navigation.logout"), "");
10000
10491
  } }
10492
+ function DesignerComponent_lib_app_scene_59_Template(rf, ctx) { if (rf & 1) {
10493
+ i0.ɵɵelement(0, "lib-app-scene");
10494
+ } }
10495
+ function DesignerComponent_lib_app_preset_61_Template(rf, ctx) { if (rf & 1) {
10496
+ i0.ɵɵelement(0, "lib-app-preset");
10497
+ } }
10498
+ function DesignerComponent_div_63_Template(rf, ctx) { if (rf & 1) {
10499
+ i0.ɵɵelementStart(0, "div", 48)(1, "div", 49);
10500
+ i0.ɵɵelement(2, "lib-app-preview", 50);
10501
+ i0.ɵɵelementEnd()();
10502
+ } if (rf & 2) {
10503
+ const ctx_r1 = i0.ɵɵnextContext();
10504
+ i0.ɵɵclassProp("card-intro-active", ctx_r1.introService.showStep("preview"));
10505
+ } }
10506
+ function DesignerComponent_div_65_Template(rf, ctx) { if (rf & 1) {
10507
+ const _r6 = i0.ɵɵgetCurrentView();
10508
+ i0.ɵɵelementStart(0, "div", 51)(1, "div", 52)(2, "a", 53);
10509
+ i0.ɵɵpipe(3, "translate");
10510
+ i0.ɵɵlistener("click", function DesignerComponent_div_65_Template_a_click_2_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTab("capabilities")); });
10511
+ i0.ɵɵelement(4, "i", 54);
10512
+ i0.ɵɵelementEnd();
10513
+ i0.ɵɵelementStart(5, "a", 55);
10514
+ i0.ɵɵpipe(6, "translate");
10515
+ i0.ɵɵlistener("click", function DesignerComponent_div_65_Template_a_click_5_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTab("channels")); });
10516
+ i0.ɵɵelement(7, "i", 56);
10517
+ i0.ɵɵelementEnd();
10518
+ i0.ɵɵelementStart(8, "a", 57);
10519
+ i0.ɵɵpipe(9, "translate");
10520
+ i0.ɵɵlistener("click", function DesignerComponent_div_65_Template_a_click_8_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTab("effects")); });
10521
+ i0.ɵɵelement(10, "i", 58);
10522
+ i0.ɵɵelementEnd();
10523
+ i0.ɵɵelementStart(11, "a", 59);
10524
+ i0.ɵɵpipe(12, "translate");
10525
+ i0.ɵɵlistener("click", function DesignerComponent_div_65_Template_a_click_11_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTab("settings")); });
10526
+ i0.ɵɵelement(13, "i", 60);
10527
+ i0.ɵɵelementEnd()()();
10528
+ } if (rf & 2) {
10529
+ i0.ɵɵadvance(2);
10530
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(3, 4, "designer.misc.capabilities"));
10531
+ i0.ɵɵadvance(3);
10532
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(6, 6, "designer.misc.channels"));
10533
+ i0.ɵɵadvance(3);
10534
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(9, 8, "designer.misc.effects"));
10535
+ i0.ɵɵadvance(3);
10536
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(12, 10, "designer.misc.settings"));
10537
+ } }
10538
+ function DesignerComponent_div_67_Template(rf, ctx) { if (rf & 1) {
10539
+ i0.ɵɵelementStart(0, "div", 61)(1, "div", 62)(2, "div", 63)(3, "div", 64);
10540
+ i0.ɵɵelement(4, "lib-app-fixture-capability");
10541
+ i0.ɵɵelementEnd();
10542
+ i0.ɵɵelementStart(5, "div", 65);
10543
+ i0.ɵɵelement(6, "lib-app-fixture-channel");
10544
+ i0.ɵɵelementEnd();
10545
+ i0.ɵɵelementStart(7, "div", 66);
10546
+ i0.ɵɵelement(8, "lib-app-effect");
10547
+ i0.ɵɵelementEnd();
10548
+ i0.ɵɵelementStart(9, "div", 67);
10549
+ i0.ɵɵelement(10, "lib-app-fixture-settings");
10550
+ i0.ɵɵelementEnd()()()();
10551
+ } }
10552
+ function DesignerComponent_lib_app_fixture_69_Template(rf, ctx) { if (rf & 1) {
10553
+ i0.ɵɵelement(0, "lib-app-fixture");
10554
+ } }
10555
+ function DesignerComponent_lib_app_master_dimmer_71_Template(rf, ctx) { if (rf & 1) {
10556
+ i0.ɵɵelement(0, "lib-app-master-dimmer");
10557
+ } }
10558
+ function DesignerComponent_lib_app_timeline_73_Template(rf, ctx) { if (rf & 1) {
10559
+ i0.ɵɵelement(0, "lib-app-timeline");
10560
+ } }
10561
+ function DesignerComponent_lib_app_master_dimmer_76_Template(rf, ctx) { if (rf & 1) {
10562
+ i0.ɵɵelement(0, "lib-app-master-dimmer");
10563
+ } }
10564
+ function DesignerComponent_lib_app_scene_78_Template(rf, ctx) { if (rf & 1) {
10565
+ i0.ɵɵelement(0, "lib-app-scene");
10566
+ } }
10001
10567
  class DesignerComponent {
10002
10568
  set menuHeightPx(value) {
10003
10569
  this.configService.menuHeightPx = value;
@@ -10037,7 +10603,10 @@ class DesignerComponent {
10037
10603
  set uniqueProjectNames(value) {
10038
10604
  this.configService.uniqueProjectNames = value;
10039
10605
  }
10040
- constructor(translateService, projectService, configService, fixturePoolService, hotkeyTargetExcludeService, modalService, userService, userEnsureLoginService, toastrService, projectLoadService, warningDialogService, errorDialogService, fixtureService, timelineService, introService) {
10606
+ set dropzoneChunking(value) {
10607
+ this.configService.dropzoneChunking = value;
10608
+ }
10609
+ constructor(translateService, projectService, configService, fixturePoolService, hotkeyTargetExcludeService, modalService, userService, userEnsureLoginService, projectLoadService, warningDialogService, errorDialogService, fixtureService, timelineService, introService) {
10041
10610
  this.translateService = translateService;
10042
10611
  this.projectService = projectService;
10043
10612
  this.configService = configService;
@@ -10046,7 +10615,6 @@ class DesignerComponent {
10046
10615
  this.modalService = modalService;
10047
10616
  this.userService = userService;
10048
10617
  this.userEnsureLoginService = userEnsureLoginService;
10049
- this.toastrService = toastrService;
10050
10618
  this.projectLoadService = projectLoadService;
10051
10619
  this.warningDialogService = warningDialogService;
10052
10620
  this.errorDialogService = errorDialogService;
@@ -10062,6 +10630,27 @@ class DesignerComponent {
10062
10630
  this.calcTotalMenuHeight();
10063
10631
  });
10064
10632
  }
10633
+ loadError(response) {
10634
+ console.error(response);
10635
+ let msg = 'designer.project.open-error';
10636
+ let error;
10637
+ if (response instanceof HttpErrorResponse) {
10638
+ error = response && response.error ? response.error.error : 'unknown';
10639
+ if (error === 'no-permission') {
10640
+ msg = 'designer.project.open-no-permission-error';
10641
+ error = undefined;
10642
+ }
10643
+ else {
10644
+ msg = 'designer.project.open-error';
10645
+ }
10646
+ }
10647
+ else {
10648
+ error = response && response.message ? response.message : 'unknown';
10649
+ }
10650
+ this.errorDialogService.show(msg, error).subscribe(() => {
10651
+ this.projectLoadService.new();
10652
+ });
10653
+ }
10065
10654
  ngOnInit() {
10066
10655
  if (localStorage.getItem('language')) {
10067
10656
  this.translateService.use(localStorage.getItem('language'));
@@ -10080,29 +10669,14 @@ class DesignerComponent {
10080
10669
  shareToken = '';
10081
10670
  }
10082
10671
  this.projectLoadService.load(Number.parseInt(projectId, 10), projectName, shareToken).subscribe(() => { }, (response) => {
10083
- let error = response && response.error ? response.error.error : 'unknown';
10084
- let msg = '';
10085
- if (error === 'no-permission') {
10086
- msg = 'designer.project.open-no-permission-error';
10087
- error = undefined;
10088
- }
10089
- else {
10090
- msg = 'designer.project.open-error';
10091
- }
10092
- this.errorDialogService.show(msg, error).subscribe(() => {
10093
- this.projectLoadService.new();
10094
- });
10672
+ this.loadError(response);
10095
10673
  });
10096
10674
  }
10097
10675
  else if ((this.userService.isLoggedIn() || !this.configService.loginAvailable) &&
10098
10676
  (this.userService.getAutoLoadProjectId() || this.userService.getAutoLoadProjectName())) {
10099
10677
  // restore the last saved project
10100
10678
  this.projectLoadService.load(this.userService.getAutoLoadProjectId(), this.userService.getAutoLoadProjectName()).subscribe(() => { }, (response) => {
10101
- const msg = 'designer.project.open-error';
10102
- const error = response && response.error ? response.error.error : 'unknown';
10103
- this.errorDialogService.show(msg, error).subscribe(() => {
10104
- this.projectLoadService.new();
10105
- });
10679
+ this.loadError(response);
10106
10680
  });
10107
10681
  }
10108
10682
  else {
@@ -10130,7 +10704,7 @@ class DesignerComponent {
10130
10704
  // Set up the splitter
10131
10705
  setTimeout(() => {
10132
10706
  Split(['#row1', '#row2', '#row3'], {
10133
- sizes: [42, 38, 20],
10707
+ sizes: [42, 40, 18],
10134
10708
  direction: 'vertical',
10135
10709
  cursor: 'row-resize',
10136
10710
  snapOffset: 0,
@@ -10138,13 +10712,13 @@ class DesignerComponent {
10138
10712
  onDrag: this.onResize.bind(this),
10139
10713
  });
10140
10714
  Split(['#scenes', '#presets', '#preview'], {
10141
- sizes: [15, 15, 70],
10715
+ sizes: [20, 20, 60],
10142
10716
  snapOffset: 0,
10143
10717
  gutterSize: this.splitGutterSizePx,
10144
10718
  onDrag: this.onResize.bind(this),
10145
10719
  });
10146
10720
  Split(['#capabilities', '#fixtures', '#masterDimmer'], {
10147
- sizes: [74, 18, 8],
10721
+ sizes: [70, 24, 6],
10148
10722
  snapOffset: 0,
10149
10723
  gutterSize: this.splitGutterSizePx,
10150
10724
  onDrag: this.onResize.bind(this),
@@ -10267,7 +10841,7 @@ class DesignerComponent {
10267
10841
  this.translateService.use(language);
10268
10842
  localStorage.setItem('language', language);
10269
10843
  }
10270
- static { this.ɵfac = function DesignerComponent_Factory(t) { return new (t || DesignerComponent)(i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(ProjectService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(FixturePoolService), i0.ɵɵdirectiveInject(HotkeyTargetExcludeService), i0.ɵɵdirectiveInject(i1$1.BsModalService), i0.ɵɵdirectiveInject(UserService), i0.ɵɵdirectiveInject(UserEnsureLoginService), i0.ɵɵdirectiveInject(i3.ToastrService), i0.ɵɵdirectiveInject(ProjectLoadService), i0.ɵɵdirectiveInject(WarningDialogService), i0.ɵɵdirectiveInject(ErrorDialogService), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(TimelineService), i0.ɵɵdirectiveInject(IntroService)); }; }
10844
+ static { this.ɵfac = function DesignerComponent_Factory(t) { return new (t || DesignerComponent)(i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(ProjectService), i0.ɵɵdirectiveInject(ConfigService), i0.ɵɵdirectiveInject(FixturePoolService), i0.ɵɵdirectiveInject(HotkeyTargetExcludeService), i0.ɵɵdirectiveInject(i1$1.BsModalService), i0.ɵɵdirectiveInject(UserService), i0.ɵɵdirectiveInject(UserEnsureLoginService), i0.ɵɵdirectiveInject(ProjectLoadService), i0.ɵɵdirectiveInject(WarningDialogService), i0.ɵɵdirectiveInject(ErrorDialogService), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(TimelineService), i0.ɵɵdirectiveInject(IntroService)); }; }
10271
10845
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DesignerComponent, selectors: [["lib-designer"]], viewQuery: function DesignerComponent_Query(rf, ctx) { if (rf & 1) {
10272
10846
  i0.ɵɵviewQuery(PreviewComponent, 5);
10273
10847
  i0.ɵɵviewQuery(TimelineComponent, 5);
@@ -10277,7 +10851,7 @@ class DesignerComponent {
10277
10851
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.timelineComponent = _t.first);
10278
10852
  } }, hostBindings: function DesignerComponent_HostBindings(rf, ctx) { if (rf & 1) {
10279
10853
  i0.ɵɵlistener("keydown", function DesignerComponent_keydown_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
10280
- } }, inputs: { menuHeightPx: "menuHeightPx", externalCompositionsAvailable: "externalCompositionsAvailable", restUrl: "restUrl", enableMediaLibrary: "enableMediaLibrary", loginAvailable: "loginAvailable", shareAvailable: "shareAvailable", languageSwitch: "languageSwitch", newProjectTemplate: "newProjectTemplate", livePreview: "livePreview", localProfiles: "localProfiles", intro: "intro", uniqueProjectNames: "uniqueProjectNames" }, decls: 105, vars: 57, consts: [["id", "designer", 3, "ngStyle"], [1, "navbar", "navbar-expand-lg", "navbar-light", "bg-light", "border-secondary", 2, "border-bottom", "1px solid #444", "height", "20px", "z-index", "9999"], [1, "navbar-nav", "mr-auto"], [1, "nav-item", "dropdown"], ["href", "#", "id", "fileDropdown", "data-toggle", "dropdown", "aria-haspopup", "true", "aria-expanded", "false", 1, "nav-link", "dropdown-toggle"], ["aria-labelledby", "fileDropdown", 1, "dropdown-menu"], ["href", "#", 1, "dropdown-item", "d-none", "d-md-block", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-file-o"], ["href", "#", 1, "dropdown-item", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-folder-open-o"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-floppy-o"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-download"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-external-link"], [1, "nav-item", "dropdown", "d-none", "d-md-block"], ["href", "#", "id", "settingsDropdown", "data-toggle", "dropdown", "aria-haspopup", "true", "aria-expanded", "false", 1, "nav-link", "dropdown-toggle"], ["aria-labelledby", "settingsDropdown", 1, "dropdown-menu"], ["href", "https://rocketshow.net/support/", "target", "_blank", 1, "dropdown-item"], [1, "navbar-nav"], ["class", "nav-item d-none d-md-flex", "data-toggle", "collapse", 4, "ngIf"], ["class", "nav-item dropdown", 4, "ngIf"], ["class", "nav-item", "data-toggle", "collapse", 4, "ngIf"], [1, "h-100", "d-none", "d-md-block"], ["id", "row1", 1, "split", "split-vertical", "clearfix", "pt-3", "pl-3"], ["id", "scenes", 1, "split", "split-horizontal", "h-100"], ["id", "presets", 1, "split", "split-horizontal", "h-100"], ["id", "preview", 1, "split", "split-horizontal", "h-100", "pr-3"], [1, "card", "border-secondary", "h-100"], [1, "card-body", "p-0", "h-100"], [1, "h-100"], ["id", "row2", 1, "split", "split-vertical", "clearfix", "px-3", "d-flex", 2, "flex-direction", "row"], [1, "col", "col-auto", "p-0", 2, "margin-right", "-1px"], ["id", "v-pills-tab", "role", "tablist", "aria-orientation", "vertical", 1, "nav", "flex-column", "nav-pills"], ["id", "v-pills-capabilities-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-capabilities", "role", "tab", "aria-controls", "v-pills-capabilities", "aria-selected", "true", 1, "nav-link", "px-3", "active", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-bolt", "fa-fw"], ["id", "v-pills-channels-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-channels", "role", "tab", "aria-controls", "v-pills-channels", "aria-selected", "false", 1, "nav-link", "px-3", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-sliders", "fa-fw"], ["id", "v-pills-effects-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-effects", "role", "tab", "aria-controls", "v-pills-effects", "aria-selected", "false", 1, "nav-link", "px-3", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-magic", "fa-fw"], ["id", "v-pills-settings-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-settings", "role", "tab", "aria-controls", "v-pills-settings", "aria-selected", "false", 1, "nav-link", "px-3", 2, "border-top", "1px solid #444", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-cog", "fa-fw"], ["id", "capabilities", 1, "split", "split-horizontal", "h-100", 2, "padding-left", "1rem"], [1, "row", "h-100"], [1, "col", "pl-0", "h-100"], ["id", "v-pills-tabContent", 1, "tab-content", "h-100"], ["id", "v-pills-capabilities", "role", "tabpanel", 1, "tab-pane", "h-100", "show", "active"], ["id", "v-pills-channels", "role", "tabpanel", 1, "tab-pane", "h-100", "show"], ["id", "v-pills-effects", "role", "tabpanel", "aria-labelledby", "v-pills-profile-tab", 1, "tab-pane", "h-100"], ["id", "v-pills-settings", "role", "tabpanel", "aria-labelledby", "v-pills-home-tab", 1, "tab-pane", "h-100"], ["id", "fixtures", 1, "split", "split-horizontal", "h-100"], ["id", "masterDimmer", 1, "split", "split-horizontal", "h-100"], ["id", "row3", 1, "split", "split-vertical", "clearfix", "px-3", "pb-3", 2, "padding-bottom", "20px"], [1, "d-md-none", "p-3"], [1, "mt-3"], [1, "d-none", "d-md-flex"], ["data-toggle", "collapse", 1, "nav-item", "d-none", "d-md-flex"], ["routerLinkActive", "active", 1, "nav-link", "text-primary", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-share-alt"], ["aria-hidden", "true", 1, "fa", "fa-globe"], ["aria-labelledby", "settingsDropdown", 1, "dropdown-menu", "dropdown-menu-right"], ["href", "#", "target", "_blank", 1, "dropdown-item", 3, "click"], ["data-toggle", "collapse", 1, "nav-item"], ["routerLinkActive", "active", 1, "nav-link", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-user"], ["aria-hidden", "true", 1, "fa", "fa-sign-out"]], template: function DesignerComponent_Template(rf, ctx) { if (rf & 1) {
10854
+ } }, inputs: { menuHeightPx: "menuHeightPx", externalCompositionsAvailable: "externalCompositionsAvailable", restUrl: "restUrl", enableMediaLibrary: "enableMediaLibrary", loginAvailable: "loginAvailable", shareAvailable: "shareAvailable", languageSwitch: "languageSwitch", newProjectTemplate: "newProjectTemplate", livePreview: "livePreview", localProfiles: "localProfiles", intro: "intro", uniqueProjectNames: "uniqueProjectNames", dropzoneChunking: "dropzoneChunking" }, decls: 80, vars: 53, consts: [["id", "designer", 3, "ngStyle"], [1, "navbar", "navbar-expand-lg", "navbar-light", "bg-light", "border-secondary", 2, "border-bottom", "1px solid #444", "height", "20px", "z-index", "9999"], [1, "navbar-nav", "mr-auto"], [1, "nav-item", "dropdown"], ["href", "#", "id", "fileDropdown", "data-toggle", "dropdown", "aria-haspopup", "true", "aria-expanded", "false", 1, "nav-link", "dropdown-toggle"], ["aria-labelledby", "fileDropdown", 1, "dropdown-menu"], ["href", "#", 1, "dropdown-item", "d-none", "d-md-block", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-file-o"], ["href", "#", 1, "dropdown-item", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-folder-open-o"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-floppy-o"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-download"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-external-link"], [1, "nav-item", "dropdown", "d-none", "d-md-block"], ["href", "#", "id", "settingsDropdown", "data-toggle", "dropdown", "aria-haspopup", "true", "aria-expanded", "false", 1, "nav-link", "dropdown-toggle"], ["aria-labelledby", "settingsDropdown", 1, "dropdown-menu"], ["href", "https://rocketshow.net/support/", "target", "_blank", 1, "dropdown-item"], [1, "navbar-nav"], ["class", "nav-item d-none d-md-flex", "data-toggle", "collapse", 4, "ngIf"], ["class", "nav-item dropdown", 4, "ngIf"], ["class", "nav-item", "data-toggle", "collapse", 4, "ngIf"], [1, "h-100", "d-none", "d-md-block"], ["id", "row1", 1, "split", "split-vertical", "clearfix", "pt-3", "pl-3"], ["id", "scenes", 1, "split", "split-horizontal", "h-100"], [4, "ngIf"], ["id", "presets", 1, "split", "split-horizontal", "h-100"], ["id", "preview", 1, "split", "split-horizontal", "h-100", "pr-3"], ["class", "card border-secondary h-100", 3, "card-intro-active", 4, "ngIf"], ["id", "row2", 1, "split", "split-vertical", "clearfix", "px-3", "d-flex", 2, "flex-direction", "row"], ["class", "col col-auto p-0", "style", "margin-right: -1px", 4, "ngIf"], ["id", "capabilities", 1, "split", "split-horizontal", "h-100", 2, "padding-left", "1rem"], ["class", "row h-100", 4, "ngIf"], ["id", "fixtures", 1, "split", "split-horizontal", "h-100"], ["id", "masterDimmer", 1, "split", "split-horizontal", "h-100"], ["id", "row3", 1, "split", "split-vertical", "clearfix", "px-3", "pb-3", 2, "padding-bottom", "20px"], [1, "d-md-none", "p-3"], [1, "mt-3"], [1, "d-none", "d-md-flex"], ["data-toggle", "collapse", 1, "nav-item", "d-none", "d-md-flex"], ["routerLinkActive", "active", 1, "nav-link", "text-primary", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-share-alt"], ["aria-hidden", "true", 1, "fa", "fa-globe"], ["aria-labelledby", "settingsDropdown", 1, "dropdown-menu", "dropdown-menu-right"], ["href", "#", "target", "_blank", 1, "dropdown-item", 3, "click"], ["data-toggle", "collapse", 1, "nav-item"], ["routerLinkActive", "active", 1, "nav-link", 3, "click"], ["aria-hidden", "true", 1, "fa", "fa-user"], ["aria-hidden", "true", 1, "fa", "fa-sign-out"], [1, "card", "border-secondary", "h-100"], [1, "card-body", "p-0", "h-100"], [1, "h-100"], [1, "col", "col-auto", "p-0", 2, "margin-right", "-1px"], ["id", "v-pills-tab", "role", "tablist", "aria-orientation", "vertical", 1, "nav", "flex-column", "nav-pills"], ["id", "v-pills-capabilities-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-capabilities", "role", "tab", "aria-controls", "v-pills-capabilities", "aria-selected", "true", 1, "nav-link", "px-3", "active", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-bolt", "fa-fw"], ["id", "v-pills-channels-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-channels", "role", "tab", "aria-controls", "v-pills-channels", "aria-selected", "false", 1, "nav-link", "px-3", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-sliders", "fa-fw"], ["id", "v-pills-effects-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-effects", "role", "tab", "aria-controls", "v-pills-effects", "aria-selected", "false", 1, "nav-link", "px-3", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-magic", "fa-fw"], ["id", "v-pills-settings-tab", "container", "body", "placement", "right", "triggers", "mouseenter:mouseleave", "data-toggle", "pill", "href", "#v-pills-settings", "role", "tab", "aria-controls", "v-pills-settings", "aria-selected", "false", 1, "nav-link", "px-3", 2, "border-top", "1px solid #444", 3, "click", "popover"], ["aria-hidden", "true", 1, "fa", "fa-cog", "fa-fw"], [1, "row", "h-100"], [1, "col", "pl-0", "h-100"], ["id", "v-pills-tabContent", 1, "tab-content", "h-100"], ["id", "v-pills-capabilities", "role", "tabpanel", 1, "tab-pane", "h-100", "show", "active"], ["id", "v-pills-channels", "role", "tabpanel", 1, "tab-pane", "h-100", "show"], ["id", "v-pills-effects", "role", "tabpanel", "aria-labelledby", "v-pills-profile-tab", 1, "tab-pane", "h-100"], ["id", "v-pills-settings", "role", "tabpanel", "aria-labelledby", "v-pills-home-tab", 1, "tab-pane", "h-100"]], template: function DesignerComponent_Template(rf, ctx) { if (rf & 1) {
10281
10855
  i0.ɵɵelementStart(0, "div", 0)(1, "nav", 1)(2, "ul", 2)(3, "li", 3)(4, "a", 4);
10282
10856
  i0.ɵɵtext(5);
10283
10857
  i0.ɵɵpipe(6, "translate");
@@ -10344,88 +10918,61 @@ class DesignerComponent {
10344
10918
  i0.ɵɵtemplate(52, DesignerComponent_li_52_Template, 5, 3, "li", 18)(53, DesignerComponent_li_53_Template, 10, 3, "li", 19)(54, DesignerComponent_li_54_Template, 5, 3, "li", 20)(55, DesignerComponent_li_55_Template, 9, 4, "li", 19);
10345
10919
  i0.ɵɵelementEnd()();
10346
10920
  i0.ɵɵelementStart(56, "div", 21)(57, "div", 22)(58, "div", 23);
10347
- i0.ɵɵelement(59, "lib-app-scene");
10348
- i0.ɵɵelementEnd();
10349
- i0.ɵɵelementStart(60, "div", 24);
10350
- i0.ɵɵelement(61, "lib-app-preset");
10351
- i0.ɵɵelementEnd();
10352
- i0.ɵɵelementStart(62, "div", 25)(63, "div", 26)(64, "div", 27);
10353
- i0.ɵɵelement(65, "lib-app-preview", 28);
10354
- i0.ɵɵelementEnd()()()();
10355
- i0.ɵɵelementStart(66, "div", 29)(67, "div", 30)(68, "div", 31)(69, "a", 32);
10356
- i0.ɵɵpipe(70, "translate");
10357
- i0.ɵɵlistener("click", function DesignerComponent_Template_a_click_69_listener() { return ctx.openTab("capabilities"); });
10358
- i0.ɵɵelement(71, "i", 33);
10359
- i0.ɵɵelementEnd();
10360
- i0.ɵɵelementStart(72, "a", 34);
10361
- i0.ɵɵpipe(73, "translate");
10362
- i0.ɵɵlistener("click", function DesignerComponent_Template_a_click_72_listener() { return ctx.openTab("channels"); });
10363
- i0.ɵɵelement(74, "i", 35);
10364
- i0.ɵɵelementEnd();
10365
- i0.ɵɵelementStart(75, "a", 36);
10366
- i0.ɵɵpipe(76, "translate");
10367
- i0.ɵɵlistener("click", function DesignerComponent_Template_a_click_75_listener() { return ctx.openTab("effects"); });
10368
- i0.ɵɵelement(77, "i", 37);
10369
- i0.ɵɵelementEnd();
10370
- i0.ɵɵelementStart(78, "a", 38);
10371
- i0.ɵɵpipe(79, "translate");
10372
- i0.ɵɵlistener("click", function DesignerComponent_Template_a_click_78_listener() { return ctx.openTab("settings"); });
10373
- i0.ɵɵelement(80, "i", 39);
10374
- i0.ɵɵelementEnd()()();
10375
- i0.ɵɵelementStart(81, "div", 40)(82, "div", 41)(83, "div", 42)(84, "div", 43)(85, "div", 44);
10376
- i0.ɵɵelement(86, "lib-app-fixture-capability");
10921
+ i0.ɵɵtemplate(59, DesignerComponent_lib_app_scene_59_Template, 1, 0, "lib-app-scene", 24);
10377
10922
  i0.ɵɵelementEnd();
10378
- i0.ɵɵelementStart(87, "div", 45);
10379
- i0.ɵɵelement(88, "lib-app-fixture-channel");
10923
+ i0.ɵɵelementStart(60, "div", 25);
10924
+ i0.ɵɵtemplate(61, DesignerComponent_lib_app_preset_61_Template, 1, 0, "lib-app-preset", 24);
10380
10925
  i0.ɵɵelementEnd();
10381
- i0.ɵɵelementStart(89, "div", 46);
10382
- i0.ɵɵelement(90, "lib-app-effect");
10926
+ i0.ɵɵelementStart(62, "div", 26);
10927
+ i0.ɵɵtemplate(63, DesignerComponent_div_63_Template, 3, 2, "div", 27);
10928
+ i0.ɵɵelementEnd()();
10929
+ i0.ɵɵelementStart(64, "div", 28);
10930
+ i0.ɵɵtemplate(65, DesignerComponent_div_65_Template, 14, 12, "div", 29);
10931
+ i0.ɵɵelementStart(66, "div", 30);
10932
+ i0.ɵɵtemplate(67, DesignerComponent_div_67_Template, 11, 0, "div", 31);
10383
10933
  i0.ɵɵelementEnd();
10384
- i0.ɵɵelementStart(91, "div", 47);
10385
- i0.ɵɵelement(92, "lib-app-fixture-settings");
10386
- i0.ɵɵelementEnd()()()()();
10387
- i0.ɵɵelementStart(93, "div", 48);
10388
- i0.ɵɵelement(94, "lib-app-fixture");
10934
+ i0.ɵɵelementStart(68, "div", 32);
10935
+ i0.ɵɵtemplate(69, DesignerComponent_lib_app_fixture_69_Template, 1, 0, "lib-app-fixture", 24);
10389
10936
  i0.ɵɵelementEnd();
10390
- i0.ɵɵelementStart(95, "div", 49);
10391
- i0.ɵɵelement(96, "lib-app-master-dimmer");
10937
+ i0.ɵɵelementStart(70, "div", 33);
10938
+ i0.ɵɵtemplate(71, DesignerComponent_lib_app_master_dimmer_71_Template, 1, 0, "lib-app-master-dimmer", 24);
10392
10939
  i0.ɵɵelementEnd()();
10393
- i0.ɵɵelementStart(97, "div", 50);
10394
- i0.ɵɵelement(98, "lib-app-timeline");
10940
+ i0.ɵɵelementStart(72, "div", 34);
10941
+ i0.ɵɵtemplate(73, DesignerComponent_lib_app_timeline_73_Template, 1, 0, "lib-app-timeline", 24);
10395
10942
  i0.ɵɵelementEnd()();
10396
- i0.ɵɵelementStart(99, "div", 51)(100, "div");
10397
- i0.ɵɵelement(101, "lib-app-master-dimmer");
10943
+ i0.ɵɵelementStart(74, "div", 35)(75, "div");
10944
+ i0.ɵɵtemplate(76, DesignerComponent_lib_app_master_dimmer_76_Template, 1, 0, "lib-app-master-dimmer", 24);
10398
10945
  i0.ɵɵelementEnd();
10399
- i0.ɵɵelementStart(102, "div", 52);
10400
- i0.ɵɵelement(103, "lib-app-scene");
10946
+ i0.ɵɵelementStart(77, "div", 36);
10947
+ i0.ɵɵtemplate(78, DesignerComponent_lib_app_scene_78_Template, 1, 0, "lib-app-scene", 24);
10401
10948
  i0.ɵɵelementEnd()()();
10402
- i0.ɵɵelement(104, "lib-app-intro", 53);
10949
+ i0.ɵɵelement(79, "lib-app-intro", 37);
10403
10950
  } if (rf & 2) {
10404
- i0.ɵɵproperty("ngStyle", i0.ɵɵpureFunction1(55, _c0, "calc(100% - " + ctx.totalMenuHeightPx + "px)"));
10951
+ i0.ɵɵproperty("ngStyle", i0.ɵɵpureFunction1(51, _c0, "calc(100% - " + ctx.totalMenuHeightPx + "px)"));
10405
10952
  i0.ɵɵadvance(5);
10406
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(6, 23, "designer.navigation.project"), " ");
10953
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(6, 27, "designer.navigation.project"), " ");
10407
10954
  i0.ɵɵadvance(5);
10408
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(11, 25, "designer.navigation.project-new"), "");
10955
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(11, 29, "designer.navigation.project-new"), "");
10409
10956
  i0.ɵɵadvance(4);
10410
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(15, 27, "designer.navigation.project-open"), "");
10957
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(15, 31, "designer.navigation.project-open"), "");
10411
10958
  i0.ɵɵadvance(4);
10412
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(19, 29, "designer.navigation.project-save"), "");
10959
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(19, 33, "designer.navigation.project-save"), "");
10413
10960
  i0.ɵɵadvance(4);
10414
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(23, 31, "designer.navigation.project-save-as"), "");
10961
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(23, 35, "designer.navigation.project-save-as"), "");
10415
10962
  i0.ɵɵadvance(4);
10416
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(27, 33, "designer.navigation.project-import"), "");
10963
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(27, 37, "designer.navigation.project-import"), "");
10417
10964
  i0.ɵɵadvance(4);
10418
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(31, 35, "designer.navigation.project-export"), "");
10965
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(31, 39, "designer.navigation.project-export"), "");
10419
10966
  i0.ɵɵadvance(4);
10420
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 37, "designer.navigation.settings"), " ");
10967
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 41, "designer.navigation.settings"), " ");
10421
10968
  i0.ɵɵadvance(4);
10422
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(39, 39, "designer.navigation.fixture-pool"));
10969
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(39, 43, "designer.navigation.fixture-pool"));
10423
10970
  i0.ɵɵadvance(4);
10424
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(43, 41, "designer.navigation.help"), " ");
10971
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(43, 45, "designer.navigation.help"), " ");
10425
10972
  i0.ɵɵadvance(4);
10426
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(47, 43, "designer.navigation.reset-intro"));
10973
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(47, 47, "designer.navigation.reset-intro"));
10427
10974
  i0.ɵɵadvance(3);
10428
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(50, 45, "designer.navigation.support"));
10975
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(50, 49, "designer.navigation.support"));
10429
10976
  i0.ɵɵadvance(3);
10430
10977
  i0.ɵɵproperty("ngIf", ctx.configService.shareAvailable);
10431
10978
  i0.ɵɵadvance();
@@ -10434,22 +10981,32 @@ class DesignerComponent {
10434
10981
  i0.ɵɵproperty("ngIf", ctx.configService.loginAvailable && !ctx.userService.isLoggedIn());
10435
10982
  i0.ɵɵadvance();
10436
10983
  i0.ɵɵproperty("ngIf", ctx.configService.loginAvailable && ctx.userService.isLoggedIn());
10437
- i0.ɵɵadvance(8);
10438
- i0.ɵɵclassProp("card-intro-active", ctx.introService.showStep("preview"));
10439
- i0.ɵɵadvance(6);
10440
- i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(70, 47, "designer.misc.capabilities"));
10441
- i0.ɵɵadvance(3);
10442
- i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(73, 49, "designer.misc.channels"));
10443
- i0.ɵɵadvance(3);
10444
- i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(76, 51, "designer.misc.effects"));
10984
+ i0.ɵɵadvance(4);
10985
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10986
+ i0.ɵɵadvance(2);
10987
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10988
+ i0.ɵɵadvance(2);
10989
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10990
+ i0.ɵɵadvance(2);
10991
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10992
+ i0.ɵɵadvance(2);
10993
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10994
+ i0.ɵɵadvance(2);
10995
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10996
+ i0.ɵɵadvance(2);
10997
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10998
+ i0.ɵɵadvance(2);
10999
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10445
11000
  i0.ɵɵadvance(3);
10446
- i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(79, 53, "designer.misc.settings"));
10447
- } }, dependencies: [i4.RouterLinkActive, i5.NgIf, i5.NgStyle, i12.PopoverDirective, PreviewComponent, SceneComponent, TimelineComponent, FixtureComponent, FixtureCapabilityComponent, FixtureSettingsComponent, EffectComponent, PresetComponent, MasterDimmerComponent, FixtureChannelComponent, IntroComponent, i2.TranslatePipe], styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}\n"], encapsulation: 2 }); }
11001
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
11002
+ i0.ɵɵadvance(2);
11003
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
11004
+ } }, dependencies: [i3.RouterLinkActive, i5.NgIf, i5.NgStyle, i12.PopoverDirective, PreviewComponent, SceneComponent, TimelineComponent, FixtureComponent, FixtureCapabilityComponent, FixtureSettingsComponent, EffectComponent, PresetComponent, MasterDimmerComponent, FixtureChannelComponent, IntroComponent, i2.TranslatePipe], styles: ["body{font-size:14px}.modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}\n"], encapsulation: 2 }); }
10448
11005
  }
10449
11006
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DesignerComponent, [{
10450
11007
  type: Component,
10451
- args: [{ selector: 'lib-designer', encapsulation: ViewEncapsulation.None, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n <li *ngIf=\"configService.shareAvailable\" class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n\n <li *ngIf=\"configService.languageSwitch\" class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n </div>\n </li>\n\n <li *ngIf=\"configService.loginAvailable && !userService.isLoggedIn()\" class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n\n <li *ngIf=\"configService.loginAvailable && userService.isLoggedIn()\" class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n <lib-app-scene></lib-app-scene>\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n <lib-app-preset></lib-app-preset>\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n <div class=\"card border-secondary h-100\" [class.card-intro-active]=\"introService.showStep('preview')\">\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n <div class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n <div class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n <lib-app-fixture></lib-app-fixture>\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n <lib-app-master-dimmer></lib-app-master-dimmer>\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n <lib-app-timeline></lib-app-timeline>\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n <lib-app-master-dimmer></lib-app-master-dimmer>\n </div>\n\n <div class=\"mt-3\">\n <lib-app-scene></lib-app-scene>\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}\n"] }]
10452
- }], () => [{ type: i2.TranslateService }, { type: ProjectService }, { type: ConfigService }, { type: FixturePoolService }, { type: HotkeyTargetExcludeService }, { type: i1$1.BsModalService }, { type: UserService }, { type: UserEnsureLoginService }, { type: i3.ToastrService }, { type: ProjectLoadService }, { type: WarningDialogService }, { type: ErrorDialogService }, { type: FixtureService }, { type: TimelineService }, { type: IntroService }], { menuHeightPx: [{
11008
+ args: [{ selector: 'lib-designer', encapsulation: ViewEncapsulation.None, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n <li *ngIf=\"configService.shareAvailable\" class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n\n <li *ngIf=\"configService.languageSwitch\" class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n </div>\n </li>\n\n <li *ngIf=\"configService.loginAvailable && !userService.isLoggedIn()\" class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n\n <li *ngIf=\"configService.loginAvailable && userService.isLoggedIn()\" class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n <lib-app-scene *ngIf=\"projectService.project\"></lib-app-scene>\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n <lib-app-preset *ngIf=\"projectService.project\"></lib-app-preset>\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n <div\n *ngIf=\"projectService.project\"\n class=\"card border-secondary h-100\"\n [class.card-intro-active]=\"introService.showStep('preview')\"\n >\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n <div *ngIf=\"projectService.project\" class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n <div *ngIf=\"projectService.project\" class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n <lib-app-fixture *ngIf=\"projectService.project\"></lib-app-fixture>\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n <lib-app-master-dimmer *ngIf=\"projectService.project\"></lib-app-master-dimmer>\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n <lib-app-timeline *ngIf=\"projectService.project\"></lib-app-timeline>\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n <lib-app-master-dimmer *ngIf=\"projectService.project\"></lib-app-master-dimmer>\n </div>\n\n <div class=\"mt-3\">\n <lib-app-scene *ngIf=\"projectService.project\"></lib-app-scene>\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: ["body{font-size:14px}.modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}\n"] }]
11009
+ }], () => [{ type: i2.TranslateService }, { type: ProjectService }, { type: ConfigService }, { type: FixturePoolService }, { type: HotkeyTargetExcludeService }, { type: i1$1.BsModalService }, { type: UserService }, { type: UserEnsureLoginService }, { type: ProjectLoadService }, { type: WarningDialogService }, { type: ErrorDialogService }, { type: FixtureService }, { type: TimelineService }, { type: IntroService }], { menuHeightPx: [{
10453
11010
  type: Input
10454
11011
  }], externalCompositionsAvailable: [{
10455
11012
  type: Input
@@ -10473,6 +11030,8 @@ class DesignerComponent {
10473
11030
  type: Input
10474
11031
  }], uniqueProjectNames: [{
10475
11032
  type: Input
11033
+ }], dropzoneChunking: [{
11034
+ type: Input
10476
11035
  }], previewComponent: [{
10477
11036
  type: ViewChild,
10478
11037
  args: [PreviewComponent]
@@ -10545,6 +11104,7 @@ class DesignerModule {
10545
11104
  SceneSettingsComponent,
10546
11105
  ProjectSaveComponent,
10547
11106
  FixturePoolCreateFromFileComponent,
11107
+ DropzoneComponent,
10548
11108
  ],
10549
11109
  imports: [
10550
11110
  RouterModule.forRoot([], {}),
@@ -10602,7 +11162,8 @@ class DesignerModule {
10602
11162
  PresetSettingsComponent,
10603
11163
  SceneSettingsComponent,
10604
11164
  ProjectSaveComponent,
10605
- FixturePoolCreateFromFileComponent], imports: [i4.RouterModule, BrowserModule,
11165
+ FixturePoolCreateFromFileComponent,
11166
+ DropzoneComponent], imports: [i3.RouterModule, BrowserModule,
10606
11167
  BrowserAnimationsModule,
10607
11168
  HttpClientModule,
10608
11169
  FormsModule,
@@ -10612,7 +11173,7 @@ class DesignerModule {
10612
11173
  PopoverModule,
10613
11174
  TypeaheadModule,
10614
11175
  SortablejsModule,
10615
- DropzoneModule, i3.ToastrModule], exports: [DesignerComponent] }); })();
11176
+ DropzoneModule, i3$1.ToastrModule], exports: [DesignerComponent] }); })();
10616
11177
 
10617
11178
  /*
10618
11179
  * Public API Surface of designer