@rocketshow/designer 1.33.0 → 1.35.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 +75 -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 -14
  28. package/esm2022/lib/services/config.service.mjs +2 -1
  29. package/esm2022/lib/services/fixture.service.mjs +251 -43
  30. package/esm2022/lib/services/preset.service.mjs +91 -42
  31. package/esm2022/lib/services/preview.service.mjs +65 -64
  32. package/esm2022/lib/services/project-load.service.mjs +64 -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 +1336 -791
  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 +7 -2
  57. package/lib/services/preset.service.d.ts +4 -2
  58. package/lib/services/preview.service.d.ts +2 -4
  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.35.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,9 @@ class FixtureService {
887
1029
  }
888
1030
  }
889
1031
  }
890
- getCachedFixtureByUuid(uuid) {
1032
+ getCachedFixtureByUuid(uuid, pixelKey) {
891
1033
  for (const fixture of this.cachedFixtures) {
892
- if (fixture.fixture.uuid === uuid) {
1034
+ if (fixture.fixture.uuid === uuid && ((!fixture.pixelKey && !pixelKey) || fixture.pixelKey === pixelKey)) {
893
1035
  return fixture;
894
1036
  }
895
1037
  }
@@ -1099,14 +1241,6 @@ class FixtureService {
1099
1241
  }
1100
1242
  return undefined;
1101
1243
  }
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
1244
  getChannelByName(fixture, channelName) {
1111
1245
  for (const channel of fixture.channels) {
1112
1246
  if ((channel.name && channel.name === channelName) ||
@@ -1116,51 +1250,264 @@ class FixtureService {
1116
1250
  }
1117
1251
  return undefined;
1118
1252
  }
1119
- getCachedChannels(profile, mode) {
1253
+ addCachedChannel(channels, channel, templateChannelName, pixelKey, profile) {
1254
+ const cachedFixtureChannel = new CachedFixtureChannel();
1255
+ const channelName = templateChannelName.replace('$pixelKey', pixelKey);
1256
+ cachedFixtureChannel.channel = channel;
1257
+ cachedFixtureChannel.name = channelName;
1258
+ cachedFixtureChannel.capabilities = this.getCapabilitiesByChannel(cachedFixtureChannel.channel, channelName, profile);
1259
+ const defaultValue = this.getDefaultValueByChannel(cachedFixtureChannel.channel);
1260
+ if (defaultValue) {
1261
+ cachedFixtureChannel.defaultValue = defaultValue;
1262
+ }
1263
+ cachedFixtureChannel.maxValue = this.getMaxValueByChannel(cachedFixtureChannel.channel);
1264
+ cachedFixtureChannel.colorWheel = this.getColorWheelByChannel(cachedFixtureChannel, profile);
1265
+ channels.push(cachedFixtureChannel);
1266
+ }
1267
+ alphanumericSort(a, b) {
1268
+ return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
1269
+ }
1270
+ getPixelKeysInOrder(profile, repeatFor) {
1271
+ let result = [];
1272
+ // could contain just a single string (e.g. 'eachPixelABC') or
1273
+ if (repeatFor.length > 1) {
1274
+ // an array of pixel (groups)
1275
+ result = repeatFor;
1276
+ }
1277
+ else if (repeatFor[0] === 'eachPixelABC') {
1278
+ // Gets computed into an alphanumerically sorted list of all pixelKeys
1279
+ if (profile.matrix.pixelCount.length === 3) {
1280
+ for (let x = 0; x < profile.matrix.pixelCount[0]; x++) {
1281
+ for (let y = 0; y < profile.matrix.pixelCount[1]; y++) {
1282
+ for (let z = 0; z < profile.matrix.pixelCount[2]; z++) {
1283
+ result.push('Pixel ' + (x + 1) + '-' + (y + 1) + '-' + (z + 1));
1284
+ }
1285
+ }
1286
+ }
1287
+ }
1288
+ else {
1289
+ for (let pixelKeyX of profile.matrix.pixelKeys) {
1290
+ for (let pixelKeyY of pixelKeyX) {
1291
+ for (let pixelKeyZ of pixelKeyY) {
1292
+ if (pixelKeyZ) {
1293
+ result.push(pixelKeyZ);
1294
+ }
1295
+ }
1296
+ }
1297
+ }
1298
+ }
1299
+ result.sort(this.alphanumericSort);
1300
+ }
1301
+ else if (repeatFor[0] === 'eachPixelGroup') {
1302
+ // Gets computed into an array of all pixel group keys, ordered by appearance in the JSON file
1303
+ for (const property of Object.keys(profile.matrix.pixelGroups)) {
1304
+ result.push(property);
1305
+ }
1306
+ }
1307
+ else if (repeatFor[0] === 'eachPixelXYZ') {
1308
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1309
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1310
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1311
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1312
+ if (pixel) {
1313
+ result.push(pixel);
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+ }
1319
+ else if (repeatFor[0] === 'eachPixelXZY') {
1320
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1321
+ for (let z = 0; z < profile.matrix.pixelKeys[x][0].length; z++) {
1322
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1323
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1324
+ if (pixel) {
1325
+ result.push(pixel);
1326
+ }
1327
+ }
1328
+ }
1329
+ }
1330
+ }
1331
+ else if (repeatFor[0] === 'eachPixelYXZ') {
1332
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1333
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1334
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1335
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1336
+ if (pixel) {
1337
+ result.push(pixel);
1338
+ }
1339
+ }
1340
+ }
1341
+ }
1342
+ }
1343
+ else if (repeatFor[0] === 'eachPixelYZX') {
1344
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1345
+ for (let z = 0; z < profile.matrix.pixelKeys[0][y].length; z++) {
1346
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1347
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1348
+ if (pixel) {
1349
+ result.push(pixel);
1350
+ }
1351
+ }
1352
+ }
1353
+ }
1354
+ }
1355
+ else if (repeatFor[0] === 'eachPixelZXY') {
1356
+ for (let z = 0; z < profile.matrix.pixelKeys[0][0].length; z++) {
1357
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1358
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1359
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1360
+ if (pixel) {
1361
+ result.push(pixel);
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ }
1367
+ else if (repeatFor[0] === 'eachPixelZYX') {
1368
+ for (let z = 0; z < profile.matrix.pixelKeys[0][0].length; z++) {
1369
+ for (let y = 0; y < profile.matrix.pixelKeys[0].length; y++) {
1370
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1371
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1372
+ if (pixel) {
1373
+ result.push(pixel);
1374
+ }
1375
+ }
1376
+ }
1377
+ }
1378
+ }
1379
+ return result;
1380
+ }
1381
+ getModeChannelCount(profile, mode) {
1382
+ let count = 0;
1383
+ // already calculated?
1384
+ if (mode.channelCount) {
1385
+ return mode.channelCount;
1386
+ }
1387
+ for (let channel of mode.channels) {
1388
+ if (channel.insert === 'matrixChannels') {
1389
+ if (channel.repeatFor.length > 1) {
1390
+ count += channel.repeatFor.length * channel.templateChannels.length;
1391
+ }
1392
+ else if (channel.repeatFor[0] === 'eachPixelGroup') {
1393
+ count += profile.matrix.pixelGroups.length * channel.templateChannels.length;
1394
+ }
1395
+ else if (channel.repeatFor[0].startsWith('eachPixel')) {
1396
+ if (profile.matrix.pixelCount.length === 3) {
1397
+ count +=
1398
+ profile.matrix.pixelCount[0] * profile.matrix.pixelCount[1] * profile.matrix.pixelCount[2] * channel.templateChannels.length;
1399
+ }
1400
+ else {
1401
+ for (let x = 0; x < profile.matrix.pixelKeys.length; x++) {
1402
+ for (let y = 0; y < profile.matrix.pixelKeys[x].length; y++) {
1403
+ for (let z = 0; z < profile.matrix.pixelKeys[x][y].length; z++) {
1404
+ const pixel = profile.matrix.pixelKeys[x][y][z];
1405
+ if (pixel) {
1406
+ count += channel.templateChannels.length;
1407
+ }
1408
+ }
1409
+ }
1410
+ }
1411
+ }
1412
+ }
1413
+ }
1414
+ else {
1415
+ count++;
1416
+ }
1417
+ }
1418
+ mode.channelCount = count;
1419
+ return mode.channelCount;
1420
+ }
1421
+ getCachedChannels(profile, mode, pixelKey) {
1120
1422
  const channels = [];
1121
1423
  if (!mode) {
1122
1424
  return channels;
1123
1425
  }
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;
1426
+ for (const channel of mode.channels) {
1427
+ if (channel.name && !pixelKey) {
1428
+ // direct reference to a channel
1429
+ for (const availableChannelName of Object.keys(profile.availableChannels)) {
1130
1430
  // 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;
1431
+ if (channel.name === availableChannelName) {
1432
+ const availableChannel = profile.availableChannels[availableChannelName];
1433
+ this.addCachedChannel(channels, availableChannel, availableChannelName, null, profile);
1434
+ }
1435
+ }
1436
+ }
1437
+ else {
1438
+ // reference a channel through a pixel matrix
1439
+ const availablePixelKeys = this.getPixelKeysInOrder(profile, channel.repeatFor);
1440
+ if (channel.channelOrder === 'perPixel') {
1441
+ // each channel for each pixel
1442
+ for (const availablePixelKey of availablePixelKeys) {
1443
+ if (availablePixelKey === pixelKey) {
1444
+ for (const modeTemplateChannelName of channel.templateChannels) {
1445
+ for (const templateChannelName of Object.keys(profile.templateChannels)) {
1446
+ // don't check the fine channels. only add the coarse channel.
1447
+ if (modeTemplateChannelName === templateChannelName) {
1448
+ const templateChannel = profile.templateChannels[templateChannelName];
1449
+ this.addCachedChannel(channels, templateChannel, templateChannelName, availablePixelKey, profile);
1450
+ }
1451
+ }
1452
+ }
1139
1453
  }
1140
- cachedFixtureChannel.maxValue = this.getMaxValueByChannel(cachedFixtureChannel.channel);
1141
- cachedFixtureChannel.colorWheel = this.getColorWheelByChannel(cachedFixtureChannel, profile);
1142
- channels.push(cachedFixtureChannel);
1143
1454
  }
1144
1455
  }
1145
- else {
1146
- // null may be passed as a placeholder for an undefined channel
1147
- channels.push(new CachedFixtureChannel());
1456
+ else if (channel.channelOrder === 'perChannel') {
1457
+ // each pixel for each channel
1458
+ for (const modeTemplateChannelName of channel.templateChannels) {
1459
+ for (const availablePixelKey of availablePixelKeys) {
1460
+ if (availablePixelKey === pixelKey) {
1461
+ for (const templateChannelName of Object.keys(profile.templateChannels)) {
1462
+ // don't check the fine channels. only add the coarse channel.
1463
+ if (modeTemplateChannelName === templateChannelName) {
1464
+ const templateChannel = profile.templateChannels[templateChannelName];
1465
+ this.addCachedChannel(channels, templateChannel, templateChannelName, availablePixelKey, profile);
1466
+ }
1467
+ }
1468
+ }
1469
+ }
1470
+ }
1148
1471
  }
1149
1472
  }
1150
1473
  }
1151
1474
  return channels;
1152
1475
  }
1476
+ fixtureGetUniquePixelKeys(fixture) {
1477
+ let pixelKeys = new Set();
1478
+ let profile = this.getProfileByUuid(fixture.profileUuid);
1479
+ let mode = this.getModeByFixture(profile, fixture);
1480
+ // add the unique pixel keys
1481
+ for (let channel of mode.channels) {
1482
+ this.getPixelKeysInOrder(profile, channel.repeatFor).forEach((str) => pixelKeys.add(str));
1483
+ }
1484
+ return Array.from(pixelKeys);
1485
+ }
1153
1486
  updateCachedFixtures() {
1154
1487
  // calculate some frequently used values as a cache to save cpu time
1155
1488
  // afterwards
1156
1489
  this.cachedFixtures = [];
1157
1490
  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);
1491
+ const pixelKeys = this.fixtureGetUniquePixelKeys(fixture);
1492
+ if (pixelKeys.length > 0) {
1493
+ for (let pixelKey of pixelKeys) {
1494
+ const cachedFixture = new CachedFixture();
1495
+ cachedFixture.fixture = fixture;
1496
+ cachedFixture.pixelKey = pixelKey;
1497
+ cachedFixture.profile = this.getProfileByUuid(fixture.profileUuid);
1498
+ cachedFixture.mode = this.getModeByFixture(cachedFixture.profile, fixture);
1499
+ cachedFixture.channels = this.getCachedChannels(cachedFixture.profile, cachedFixture.mode, pixelKey);
1500
+ this.cachedFixtures.push(cachedFixture);
1501
+ }
1502
+ }
1503
+ else {
1504
+ const cachedFixture = new CachedFixture();
1505
+ cachedFixture.fixture = fixture;
1506
+ cachedFixture.profile = this.getProfileByUuid(fixture.profileUuid);
1507
+ cachedFixture.mode = this.getModeByFixture(cachedFixture.profile, fixture);
1508
+ cachedFixture.channels = this.getCachedChannels(cachedFixture.profile, cachedFixture.mode, null);
1509
+ this.cachedFixtures.push(cachedFixture);
1510
+ }
1164
1511
  }
1165
1512
  }
1166
1513
  capabilitiesMatch(type1, type2, color1, color2, wheel1, wheel2, profileUuid1, profileUuid2) {
@@ -1207,11 +1554,13 @@ class FixtureService {
1207
1554
  for (let i = 0; i < 512; i++) {
1208
1555
  let occupiedChannels = 0;
1209
1556
  for (const fixture of fixturePool) {
1557
+ const profile = this.getProfileByUuid(fixture.profileUuid);
1210
1558
  const mode = this.getModeByFixture(this.getProfileByUuid(fixture.profileUuid), fixture);
1211
- if (i >= fixture.dmxFirstChannel && i < fixture.dmxFirstChannel + mode.channels.length) {
1559
+ const channelCount = this.getModeChannelCount(profile, mode);
1560
+ if (i >= fixture.dmxFirstChannel && i < fixture.dmxFirstChannel + channelCount) {
1212
1561
  // 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);
1562
+ if (channelCount > occupiedChannels) {
1563
+ occupiedChannels = channelCount - (i - fixture.dmxFirstChannel);
1215
1564
  }
1216
1565
  }
1217
1566
  }
@@ -1252,8 +1601,9 @@ class FixtureService {
1252
1601
  else {
1253
1602
  fixture.modeShortName = profile.modes[0].shortName || profile.modes[0].name;
1254
1603
  }
1255
- const mode = this.getModeByFixture(this.getProfileByUuid(fixture.profileUuid), fixture);
1256
- const firstChannel = this.getNextFreeDmxChannel(fixturePool, mode.channels.length);
1604
+ const mode = this.getModeByFixture(profile, fixture);
1605
+ const channelCount = this.getModeChannelCount(profile, mode);
1606
+ const firstChannel = this.getNextFreeDmxChannel(fixturePool, channelCount);
1257
1607
  if (firstChannel >= 0) {
1258
1608
  fixture.dmxFirstChannel = firstChannel;
1259
1609
  fixturePool.push(fixture);
@@ -1268,7 +1618,7 @@ class FixtureService {
1268
1618
  });
1269
1619
  }
1270
1620
  }
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)); }; }
1621
+ 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
1622
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: FixtureService, factory: FixtureService.ɵfac, providedIn: 'root' }); }
1273
1623
  }
1274
1624
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureService, [{
@@ -1276,7 +1626,7 @@ class FixtureService {
1276
1626
  args: [{
1277
1627
  providedIn: 'root',
1278
1628
  }]
1279
- }], () => [{ type: i1.HttpClient }, { type: ProjectService }, { type: i2.TranslateService }, { type: i3.ToastrService }, { type: UuidService }], null); })();
1629
+ }], () => [{ type: i1.HttpClient }, { type: ProjectService }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: UuidService }], null); })();
1280
1630
 
1281
1631
  class PreviewMeshService {
1282
1632
  constructor() {
@@ -1364,6 +1714,7 @@ class ConfigService {
1364
1714
  this.localProfiles = false;
1365
1715
  this.intro = false;
1366
1716
  this.uniqueProjectNames = false;
1717
+ this.dropzoneChunking = true;
1367
1718
  this.menuHeightChanged = new Subject();
1368
1719
  }
1369
1720
  static { this.ɵfac = function ConfigService_Factory(t) { return new (t || ConfigService)(); }; }
@@ -1415,7 +1766,15 @@ class PresetService {
1415
1766
  }
1416
1767
  }
1417
1768
  }
1418
- fixtureIsSelected(fixture, preset) {
1769
+ getPresetFixture(preset, fixtureUuid, pixelKey) {
1770
+ for (const fixture of preset.fixtures) {
1771
+ if (fixture.fixtureUuid === fixtureUuid && ((!fixture.pixelKey && !pixelKey) || fixture.pixelKey === pixelKey)) {
1772
+ return fixture;
1773
+ }
1774
+ }
1775
+ return null;
1776
+ }
1777
+ fixtureIsSelected(fixture, pixelKey, preset) {
1419
1778
  // is the passed fixture selected in the passed/currently selected preset?
1420
1779
  if (!preset) {
1421
1780
  if (this.selectedPreset) {
@@ -1425,31 +1784,37 @@ class PresetService {
1425
1784
  return false;
1426
1785
  }
1427
1786
  }
1428
- for (const selectedFixtureUuid of preset.fixtureUuids) {
1429
- if (selectedFixtureUuid === fixture.uuid) {
1430
- return true;
1431
- }
1787
+ const presetFixture = this.getPresetFixture(preset, fixture.uuid, pixelKey);
1788
+ if (presetFixture) {
1789
+ return true;
1432
1790
  }
1433
1791
  return false;
1434
1792
  }
1435
- switchFixtureSelection(fixture) {
1793
+ switchFixtureSelection(fixture, pixelKey) {
1436
1794
  if (!this.selectedPreset) {
1437
1795
  return;
1438
1796
  }
1439
1797
  // select all fixtures at the specified start channel or unselect them,
1440
1798
  // 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);
1799
+ if (this.fixtureIsSelected(fixture, pixelKey)) {
1800
+ for (let i = this.selectedPreset.fixtures.length - 1; i >= 0; i--) {
1801
+ const projectFixture = this.fixtureService.getFixtureByUuid(this.selectedPreset.fixtures[i].fixtureUuid);
1802
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
1803
+ ((!this.selectedPreset.fixtures[i].pixelKey && !pixelKey) || this.selectedPreset.fixtures[i].pixelKey === pixelKey)) {
1804
+ this.selectedPreset.fixtures.splice(i, 1);
1446
1805
  }
1447
1806
  }
1448
1807
  }
1449
1808
  else {
1450
- for (const projectFixture of this.projectService.project.fixtures) {
1451
- if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
1452
- this.selectedPreset.fixtureUuids.push(projectFixture.uuid);
1809
+ for (const projectPresetFixture of this.projectService.project.presetFixtures) {
1810
+ if ((!projectPresetFixture.pixelKey && !pixelKey) || projectPresetFixture.pixelKey === pixelKey) {
1811
+ const projectFixture = this.fixtureService.getFixtureByUuid(projectPresetFixture.fixtureUuid);
1812
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
1813
+ const presetFixture = new PresetFixture();
1814
+ presetFixture.fixtureUuid = projectPresetFixture.fixtureUuid;
1815
+ presetFixture.pixelKey = pixelKey;
1816
+ this.selectedPreset.fixtures.push(presetFixture);
1817
+ }
1453
1818
  }
1454
1819
  }
1455
1820
  }
@@ -1459,8 +1824,23 @@ class PresetService {
1459
1824
  return;
1460
1825
  }
1461
1826
  for (const fixture of this.projectService.project.fixtures) {
1462
- if (!this.fixtureIsSelected(fixture)) {
1463
- this.selectedPreset.fixtureUuids.push(fixture.uuid);
1827
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
1828
+ if (pixelKeys.length > 0) {
1829
+ for (const pixelKey of pixelKeys) {
1830
+ if (!this.fixtureIsSelected(fixture, pixelKey)) {
1831
+ const presetFixture = new PresetFixture();
1832
+ presetFixture.fixtureUuid = fixture.uuid;
1833
+ presetFixture.pixelKey = pixelKey;
1834
+ this.selectedPreset.fixtures.push(presetFixture);
1835
+ }
1836
+ }
1837
+ }
1838
+ else {
1839
+ if (!this.fixtureIsSelected(fixture, null)) {
1840
+ const presetFixture = new PresetFixture();
1841
+ presetFixture.fixtureUuid = fixture.uuid;
1842
+ this.selectedPreset.fixtures.push(presetFixture);
1843
+ }
1464
1844
  }
1465
1845
  }
1466
1846
  }
@@ -1468,16 +1848,16 @@ class PresetService {
1468
1848
  if (!this.selectedPreset) {
1469
1849
  return;
1470
1850
  }
1471
- this.selectedPreset.fixtureUuids = [];
1851
+ this.selectedPreset.fixtures = [];
1472
1852
  }
1473
1853
  removeDeletedFixtures() {
1474
1854
  // after changing the configuration in the fixture pool, we might need to
1475
1855
  // delete some fixtures
1476
1856
  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]);
1857
+ for (let i = preset.fixtures.length - 1; i >= 0; i--) {
1858
+ const presetFixture = this.fixtureService.getFixtureByUuid(preset.fixtures[i].fixtureUuid);
1479
1859
  if (!presetFixture) {
1480
- preset.fixtureUuids.splice(i, 1);
1860
+ preset.fixtures.splice(i, 1);
1481
1861
  }
1482
1862
  }
1483
1863
  }
@@ -1486,11 +1866,15 @@ class PresetService {
1486
1866
  // after changing the configuration in the fixture pool, we might need to
1487
1867
  // select some more fixtures on the same channel as already selected ones
1488
1868
  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]);
1869
+ for (let presetFixture of preset.fixtures) {
1870
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
1491
1871
  for (const projectFixture of this.projectService.project.fixtures) {
1492
- if (projectFixture.dmxFirstChannel === presetFixture.dmxFirstChannel && !this.fixtureIsSelected(projectFixture, preset)) {
1493
- preset.fixtureUuids.push(projectFixture.uuid);
1872
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
1873
+ !this.fixtureIsSelected(projectFixture, presetFixture.pixelKey, preset)) {
1874
+ const newPresetFixture = new PresetFixture();
1875
+ newPresetFixture.fixtureUuid = projectFixture.uuid;
1876
+ newPresetFixture.pixelKey = presetFixture.pixelKey;
1877
+ preset.fixtures.push(newPresetFixture);
1494
1878
  }
1495
1879
  }
1496
1880
  }
@@ -1592,8 +1976,8 @@ class PresetService {
1592
1976
  }
1593
1977
  hasCapabilityType(type) {
1594
1978
  // 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);
1979
+ for (const projectFixture of this.selectedPreset.fixtures) {
1980
+ const fixture = this.fixtureService.getCachedFixtureByUuid(projectFixture.fixtureUuid, projectFixture.pixelKey);
1597
1981
  for (const channel of fixture.channels) {
1598
1982
  if (channel.channel) {
1599
1983
  for (const capability of channel.capabilities) {
@@ -1624,8 +2008,8 @@ class PresetService {
1624
2008
  return true;
1625
2009
  }
1626
2010
  // a color wheel is involved
1627
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1628
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
2011
+ for (const projectFixture of this.selectedPreset.fixtures) {
2012
+ const fixture = this.fixtureService.getCachedFixtureByUuid(projectFixture.fixtureUuid, projectFixture.pixelKey);
1629
2013
  for (const channel of fixture.channels) {
1630
2014
  if (channel.colorWheel) {
1631
2015
  return true;
@@ -1678,13 +2062,14 @@ class PresetService {
1678
2062
  this.projectService.project.presets.splice(highestSelectedPresetIndex, 0, preset);
1679
2063
  this.selectPreset(highestSelectedPresetIndex);
1680
2064
  }
2065
+ // return all fixture profiles used in the current preset selection
1681
2066
  getSelectedProfiles() {
1682
2067
  const profiles = [];
1683
2068
  if (!this.selectedPreset) {
1684
2069
  return profiles;
1685
2070
  }
1686
- for (const fixtureUuid of this.selectedPreset.fixtureUuids) {
1687
- const fixture = this.fixtureService.getFixtureByUuid(fixtureUuid);
2071
+ for (const presetFixture of this.selectedPreset.fixtures) {
2072
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
1688
2073
  const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
1689
2074
  if (profiles.indexOf(profile) < 0) {
1690
2075
  profiles.push(profile);
@@ -1692,24 +2077,38 @@ class PresetService {
1692
2077
  }
1693
2078
  return profiles;
1694
2079
  }
2080
+ // given a list of fixture profiles, return all available channels based on the currently selected fixtures in the preset
1695
2081
  getSelectedProfileChannels(selectedProfiles) {
1696
- const availableChannels = new Map();
1697
2082
  const calculatedProfileModes = new Map();
2083
+ const availableChannels = new Map();
2084
+ // calculate all modes for each profile
1698
2085
  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);
2086
+ const modeAndPixelKeys = [];
2087
+ // loop over the project fixtures to keep the order
2088
+ for (let projectFixture of this.projectService.project.presetFixtures) {
2089
+ for (const presetFixture of this.selectedPreset.fixtures) {
2090
+ if (projectFixture.fixtureUuid === presetFixture.fixtureUuid &&
2091
+ ((!projectFixture.pixelKey && !presetFixture.pixelKey) || projectFixture.pixelKey === presetFixture.pixelKey)) {
2092
+ const fixture = this.fixtureService.getCachedFixtureByUuid(presetFixture.fixtureUuid, presetFixture.pixelKey);
2093
+ if (fixture.profile.uuid === profile.uuid) {
2094
+ const exists = modeAndPixelKeys.some((item) => (item.mode === fixture.mode && !item.pixelKey && !fixture.pixelKey) || item.pixelKey === fixture.pixelKey);
2095
+ if (!exists) {
2096
+ modeAndPixelKeys.push({
2097
+ mode: fixture.mode,
2098
+ pixelKey: presetFixture.pixelKey,
2099
+ });
2100
+ }
2101
+ }
2102
+ }
1704
2103
  }
2104
+ calculatedProfileModes.set(profile, modeAndPixelKeys);
1705
2105
  }
1706
- calculatedProfileModes.set(profile, modes);
1707
2106
  }
1708
- // calculate all required channels from the modes
1709
- calculatedProfileModes.forEach((modes, profile) => {
2107
+ // calculate all channels from the modes
2108
+ calculatedProfileModes.forEach((modeAndPixelKeys, profile) => {
1710
2109
  const profileChannels = [];
1711
- for (const mode of modes) {
1712
- const channels = this.fixtureService.getCachedChannels(profile, mode);
2110
+ for (const modeAndPixelKey of modeAndPixelKeys) {
2111
+ const channels = this.fixtureService.getCachedChannels(profile, modeAndPixelKey.mode, modeAndPixelKey.pixelKey);
1713
2112
  for (const channel of channels) {
1714
2113
  // only add the channel, if no channel with the same name has already been added
1715
2114
  // (e.g. a fine channel)
@@ -2624,34 +3023,12 @@ class TimelineService {
2624
3023
  }]
2625
3024
  }], () => [{ type: SceneService }, { type: PresetService }, { type: ProjectService }, { type: i1.HttpClient }, { type: ConfigService }], null); })();
2626
3025
 
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
3026
  class PreviewService {
2649
- constructor(presetService, fixtureService, sceneService, timelineService, universeService, projectService) {
3027
+ constructor(presetService, fixtureService, sceneService, timelineService, projectService) {
2650
3028
  this.presetService = presetService;
2651
3029
  this.fixtureService = fixtureService;
2652
3030
  this.sceneService = sceneService;
2653
3031
  this.timelineService = timelineService;
2654
- this.universeService = universeService;
2655
3032
  this.projectService = projectService;
2656
3033
  this.doUpdateFixtureSetup = new Subject();
2657
3034
  this.stageMeshes = [];
@@ -2740,27 +3117,32 @@ class PreviewService {
2740
3117
  existingChannelValues.push(fixtureChannelValue);
2741
3118
  }
2742
3119
  // Get the fixture index inside the passed preset (used for chasing)
2743
- getFixtureIndex(preset, fixtureUuid) {
3120
+ getFixtureIndex(preset, fixtureUuid, pixelKey) {
2744
3121
  let index = 0;
2745
- const countedDmxChannels = [];
3122
+ const countedFirstDmxChannelPixelKey = [];
2746
3123
  // 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) {
2751
- return index;
2752
- }
2753
- // don't count fixtures on the same channel as already counted ones
2754
- if (!countedDmxChannels.includes(fixture.dmxFirstChannel)) {
2755
- countedDmxChannels.push(fixture.dmxFirstChannel);
2756
- index++;
2757
- }
2758
- break;
2759
- }
3124
+ for (const projectFixture of this.projectService.project.presetFixtures) {
3125
+ const presetFixture = this.presetService.getPresetFixture(preset, fixtureUuid, pixelKey);
3126
+ if (!presetFixture) {
3127
+ // Not found in the preset
3128
+ return undefined;
3129
+ }
3130
+ if (projectFixture.fixtureUuid === fixtureUuid && ((!projectFixture.pixelKey && !pixelKey) || projectFixture.pixelKey === pixelKey)) {
3131
+ return index;
3132
+ }
3133
+ const fixture = this.fixtureService.getFixtureByUuid(projectFixture.fixtureUuid);
3134
+ const firstDmxChannelAndFixtureUuid = {
3135
+ firstDmxChannel: fixture.dmxFirstChannel,
3136
+ pixelKey: projectFixture.pixelKey,
3137
+ };
3138
+ const exists = countedFirstDmxChannelPixelKey.some((item) => item.firstDmxChannel === firstDmxChannelAndFixtureUuid.firstDmxChannel &&
3139
+ ((!item.pixelKey && !firstDmxChannelAndFixtureUuid.pixelKey) || item.pixelKey === firstDmxChannelAndFixtureUuid.pixelKey));
3140
+ // don't count fixtures on the same channel as already counted ones
3141
+ if (!exists) {
3142
+ index++;
3143
+ countedFirstDmxChannelPixelKey.push(firstDmxChannelAndFixtureUuid);
2760
3144
  }
2761
3145
  }
2762
- // Not found in the preset
2763
- return undefined;
2764
3146
  }
2765
3147
  getPresetIntensity(preset, timeMillis) {
2766
3148
  // When fading is in progress (on preset or scene-level), the current preset does not
@@ -2951,7 +3333,7 @@ class PreviewService {
2951
3333
  }
2952
3334
  // return all fixture uuids with their corresponding channel values
2953
3335
  getChannelValues(timeMillis, presets) {
2954
- // Loop over all relevant presets and calc the property values from the presets (capabilities and effects)
3336
+ // Loop over all relevant presets and calc the property values from the presets (capabilities, channels and effects)
2955
3337
  const calculatedFixtures = new Map();
2956
3338
  for (let i = 0; i < this.fixtureService.cachedFixtures.length; i++) {
2957
3339
  const cachedFixture = this.fixtureService.cachedFixtures[i];
@@ -2977,7 +3359,7 @@ class PreviewService {
2977
3359
  }
2978
3360
  for (const preset of presets) {
2979
3361
  // 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);
3362
+ const fixtureIndex = this.getFixtureIndex(preset.preset, cachedFixture.fixture.uuid, cachedFixture.pixelKey);
2981
3363
  if (fixtureIndex >= 0) {
2982
3364
  // this fixture is also in the preset -> mix the required values (overwrite existing values,
2983
3365
  // if set multiple times)
@@ -2996,45 +3378,44 @@ class PreviewService {
2996
3378
  setUniverseValues(fixtures, masterDimmerValue) {
2997
3379
  // TODO only, if monitoring is enabled
2998
3380
  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
- });
3381
+ // // Reset all DMX universes
3382
+ // for (const universe of this.universeService.universes) {
3383
+ // universe.channelValues = [];
3384
+ // for (let i = 0; i < 512; i++) {
3385
+ // universe.channelValues.push(0);
3386
+ // }
3387
+ // }
3388
+ // // loop over each fixture
3389
+ // fixtures.forEach((channelValues: FixtureChannelValue[], cachedFixture: CachedFixture) => {
3390
+ // // TODO Get the correct universe for this fixture
3391
+ // const universe: Universe = this.universeService.getUniverseByUuid(cachedFixture.fixture.dmxUniverseUuid);
3392
+ // // loop over each channel for this fixture
3393
+ // for (let channelIndex = 0; channelIndex < cachedFixture.mode.channels.length; channelIndex++) {
3394
+ // const channelObj = cachedFixture.mode.channels[channelIndex];
3395
+ // if (typeof channelObj === 'string') {
3396
+ // const channelName = channelObj;
3397
+ // // match this mode channel with a channel value
3398
+ // for (const channelValue of channelValues) {
3399
+ // const channel = this.fixtureService.getChannelByName(cachedFixture, channelName);
3400
+ // if (channel && channel.channel) {
3401
+ // const fineIndex = channel.channel.fineChannelAliases.indexOf(channelName);
3402
+ // if (channel.name === channelValue.channelName || fineIndex > -1) {
3403
+ // const universeChannel = cachedFixture.fixture.dmxFirstChannel + channelIndex;
3404
+ // const dmxValue =
3405
+ // Math.floor(channelValue.value / Math.pow(256, channel.channel.fineChannelAliases.length - (fineIndex + 1))) % 256;
3406
+ // // TODO
3407
+ // break;
3408
+ // }
3409
+ // }
3410
+ // }
3411
+ // }
3412
+ // }
3413
+ // });
3031
3414
  }
3032
- fixtureIsSelected(uuid, presets) {
3415
+ fixtureIsSelected(uuid, pixelKey, presets) {
3033
3416
  for (const preset of presets) {
3034
- for (const fixtureUuid of preset.preset.fixtureUuids) {
3035
- if (fixtureUuid === uuid) {
3036
- return true;
3037
- }
3417
+ if (this.presetService.getPresetFixture(preset.preset, uuid, pixelKey)) {
3418
+ return true;
3038
3419
  }
3039
3420
  }
3040
3421
  return false;
@@ -3111,7 +3492,7 @@ class PreviewService {
3111
3492
  this.scene.add(mesh);
3112
3493
  this.stageMeshes.push(mesh);
3113
3494
  }
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)); }; }
3495
+ 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
3496
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PreviewService, factory: PreviewService.ɵfac, providedIn: 'root' }); }
3116
3497
  }
3117
3498
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PreviewService, [{
@@ -3119,11 +3500,13 @@ class PreviewService {
3119
3500
  args: [{
3120
3501
  providedIn: 'root',
3121
3502
  }]
3122
- }], () => [{ type: PresetService }, { type: FixtureService }, { type: SceneService }, { type: TimelineService }, { type: UniverseService }, { type: ProjectService }], null); })();
3503
+ }], () => [{ type: PresetService }, { type: FixtureService }, { type: SceneService }, { type: TimelineService }, { type: ProjectService }], null); })();
3123
3504
 
3124
3505
  class Fixture3d {
3125
3506
  constructor(fixtureService, fixture, scene) {
3126
3507
  this.fixtureService = fixtureService;
3508
+ this.pointLightMaxIntensity = 2;
3509
+ this.spotLightLightMaxIntensity = 10;
3127
3510
  this.fixtureHasDimmer = false;
3128
3511
  this.fixtureHasColorWheel = false;
3129
3512
  this.fixtureHasColor = false;
@@ -3156,19 +3539,42 @@ class Fixture3d {
3156
3539
  }
3157
3540
  }
3158
3541
  }
3159
- getCapabilityInValue(channel, value) {
3160
- for (const capability of channel.capabilities) {
3161
- if (capability.capability.dmxRange.length === 0 ||
3162
- (value >= capability.capability.dmxRange[0] && value <= capability.capability.dmxRange[1])) {
3163
- return capability;
3164
- }
3165
- }
3166
- return undefined;
3167
- }
3168
- // Apply the properties of the base fixture to the preview
3169
- updatePreview(channelValues, masterDimmerValue) {
3170
- // Apply default settings
3171
- if (this.fixtureHasDimmer) {
3542
+ createObjects() {
3543
+ // Add the spotlight
3544
+ this.spotLight = new THREE.SpotLight(0xffffff, 50000);
3545
+ this.spotLight.angle = 2;
3546
+ this.spotLight.penumbra = 1;
3547
+ this.spotLight.decay = 0.01;
3548
+ this.spotLight.distance = 0;
3549
+ this.spotLight.intensity = 1;
3550
+ this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3551
+ this.scene.add(this.spotLightHelper);
3552
+ const spotLightTarget = new THREE.Object3D();
3553
+ this.spotLight.target = spotLightTarget;
3554
+ this.spotlightGroup = new THREE.Object3D();
3555
+ this.spotlightGroup.add(this.spotLight);
3556
+ this.spotlightGroup.add(spotLightTarget);
3557
+ this.spotLight.position.set(0, -1.4, 0);
3558
+ spotLightTarget.position.set(0, -10, 0);
3559
+ this.createSpotLightBeam();
3560
+ // Add the point light for the surrounding light
3561
+ this.pointLight = new THREE.PointLight(0xffffff, 500, 0, 0.1);
3562
+ this.spotlightGroup.add(this.pointLight);
3563
+ this.pointLight.position.set(0, -1.4, 0);
3564
+ }
3565
+ getCapabilityInValue(channel, value) {
3566
+ for (const capability of channel.capabilities) {
3567
+ if (capability.capability.dmxRange.length === 0 ||
3568
+ (value >= capability.capability.dmxRange[0] && value <= capability.capability.dmxRange[1])) {
3569
+ return capability;
3570
+ }
3571
+ }
3572
+ return undefined;
3573
+ }
3574
+ // Apply the properties of the base fixture to the preview
3575
+ updatePreview(channelValues, masterDimmerValue) {
3576
+ // Apply default settings
3577
+ if (this.fixtureHasDimmer) {
3172
3578
  this.dimmer = 0;
3173
3579
  }
3174
3580
  else {
@@ -3230,6 +3636,22 @@ class Fixture3d {
3230
3636
  }
3231
3637
  }
3232
3638
  }
3639
+ // Apply the colors and intensities
3640
+ // Apply the dimmer value
3641
+ // Take the color into account for the beam (don't show a black beam)
3642
+ const color = new THREE.Color('rgb(' + this.colorRed + ', ' + this.colorGreen + ', ' + this.colorBlue + ')');
3643
+ const intensityColor = Math.max(this.colorRed, this.colorGreen, this.colorBlue);
3644
+ if (this.pointLight) {
3645
+ this.pointLight.color = color;
3646
+ this.pointLight.intensity = this.pointLightMaxIntensity * this.dimmer;
3647
+ }
3648
+ if (this.spotLight) {
3649
+ this.spotLight.color = color;
3650
+ this.spotLightBeam.material.uniforms.lightColor.value = color;
3651
+ this.spotLightBeam.material.uniforms.opacity.value = Math.min(intensityColor, this.dimmer);
3652
+ this.spotLight.intensity = this.spotLightLightMaxIntensity * this.dimmer;
3653
+ this.spotLightBeam.material.uniforms.spotPosition.value = this.spotlightGroup.position;
3654
+ }
3233
3655
  }
3234
3656
  updatePosition(object) {
3235
3657
  // Update the position
@@ -3263,62 +3685,66 @@ class Fixture3d {
3263
3685
  }
3264
3686
  }
3265
3687
  }
3266
- destroy() {
3267
- this.selectedMaterial.dispose();
3268
- }
3269
- }
3270
-
3271
- class ColorChanger3d extends Fixture3d {
3272
3688
  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
3689
+ const vertexShader = `
3690
+ varying vec3 vNormal;
3691
+ varying vec3 vWorldPosition;
3692
+
3693
+ void main(){
3694
+ vNormal = normalize(normalMatrix * normal);
3695
+
3696
+ vec4 worldPosition = modelMatrix * vec4(position, 1.0);
3697
+ vWorldPosition = worldPosition.xyz;
3698
+
3699
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
3700
+ }`;
3701
+ const fragmentShader = `
3702
+ varying vec3 vNormal;
3703
+ varying vec3 vWorldPosition;
3704
+
3705
+ uniform vec3 lightColor;
3706
+ uniform float opacity;
3707
+ uniform vec3 spotPosition;
3708
+ uniform float attenuation;
3709
+ uniform float anglePower;
3710
+
3711
+ void main(){
3712
+ float intensity;
3713
+
3714
+ intensity = distance(vWorldPosition, spotPosition) / attenuation;
3715
+ intensity = 1.0 - clamp(intensity, 0.0, 1.0);
3716
+
3717
+ vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
3718
+ float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
3719
+ intensity = intensity * angleIntensity * opacity;
3720
+
3721
+ gl_FragColor = vec4(lightColor, intensity);
3722
+ }`;
3300
3723
  const material = new THREE.ShaderMaterial({
3301
3724
  uniforms: {
3302
- coeficient: {
3725
+ attenuation: {
3303
3726
  type: 'f',
3304
- value: 0.3,
3727
+ value: 800.0,
3305
3728
  },
3306
- power: {
3729
+ anglePower: {
3307
3730
  type: 'f',
3308
- value: 1.3,
3731
+ value: 2,
3309
3732
  },
3310
- opacity: {
3311
- type: 'f',
3312
- value: 1.0,
3733
+ spotPosition: {
3734
+ type: 'v3',
3735
+ value: new THREE.Vector3(0, 0, 0),
3313
3736
  },
3314
- glowColor: {
3737
+ lightColor: {
3315
3738
  type: 'c',
3316
3739
  value: new THREE.Color('white'),
3317
3740
  },
3741
+ opacity: {
3742
+ type: 'f',
3743
+ value: 1.0,
3744
+ },
3318
3745
  },
3319
3746
  vertexShader,
3320
3747
  fragmentShader,
3321
- // blending: THREE.AdditiveBlending,
3322
3748
  transparent: true,
3323
3749
  depthWrite: false,
3324
3750
  });
@@ -3328,45 +3754,35 @@ class ColorChanger3d extends Fixture3d {
3328
3754
  if (this.spotLightBeam) {
3329
3755
  this.spotlightGroup.remove(this.spotLightBeam);
3330
3756
  }
3331
- // TODO update the correct angle from the profile
3757
+ // TODO set the correct angle from the profile
3332
3758
  const beamAngleDegrees = 14;
3333
- const geometry = new THREE.CylinderGeometry(0.8, beamAngleDegrees * 1.2, 100, 64, 20, false);
3759
+ const geometry = new THREE.CylinderGeometry(0.1, beamAngleDegrees * 1.2, 100, 64, 20, false);
3334
3760
  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, -geometry.parameters.height / 2, 0));
3335
3761
  geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
3336
3762
  this.atmosphereMaterial = this.atmosphereMat();
3337
3763
  this.spotLightBeam = new THREE.Mesh(geometry, this.atmosphereMaterial);
3338
3764
  this.spotLightBeam.position.set(0, -0.02, 0);
3765
+ this.spotLightBeam.receiveShadow = false;
3766
+ this.spotLightBeam.castShadow = false;
3339
3767
  this.spotlightGroup.add(this.spotLightBeam);
3340
3768
  this.spotLightBeam.rotation.x = Math.PI / 2;
3341
3769
  }
3770
+ destroy() {
3771
+ this.selectedMaterial.dispose();
3772
+ this.atmosphereMaterial.dispose();
3773
+ }
3774
+ }
3775
+
3776
+ class ColorChanger3d extends Fixture3d {
3342
3777
  createObjects() {
3778
+ super.createObjects();
3343
3779
  this.material = new THREE.MeshLambertMaterial({
3344
3780
  color: 0x0d0d0d,
3345
3781
  emissive: 0x0d0d0d,
3346
3782
  });
3347
3783
  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
3784
  this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3357
3785
  // 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
3786
  this.objectGroup.add(this.spotlightGroup);
3371
3787
  this.objectGroup.add(this.mesh);
3372
3788
  // A moving head has about 32 cm in width
@@ -3376,10 +3792,7 @@ class ColorChanger3d extends Fixture3d {
3376
3792
  }
3377
3793
  constructor(fixtureService, previewMeshService, fixture, scene) {
3378
3794
  super(fixtureService, fixture, scene);
3379
- this.pointLightMaxIntensity = 2;
3380
- this.spotLightMaxIntensity = 5;
3381
3795
  this.objectGroup = new THREE.Object3D();
3382
- this.spotlightGroup = new THREE.Object3D();
3383
3796
  forkJoin([previewMeshService.getMesh('color-changer')])
3384
3797
  .pipe(map(([colorChanger]) => {
3385
3798
  this.mesh = colorChanger;
@@ -3391,10 +3804,10 @@ class ColorChanger3d extends Fixture3d {
3391
3804
  return this.objectGroup;
3392
3805
  }
3393
3806
  updatePreview(channelValues, masterDimmerValue) {
3394
- super.updatePreview(channelValues, masterDimmerValue);
3395
3807
  if (!this.isLoaded) {
3396
3808
  return;
3397
3809
  }
3810
+ super.updatePreview(channelValues, masterDimmerValue);
3398
3811
  this.updatePosition(this.objectGroup);
3399
3812
  // Update the material
3400
3813
  if (this.lastSelected !== this.isSelected) {
@@ -3411,110 +3824,18 @@ class ColorChanger3d extends Fixture3d {
3411
3824
  this.lastSelected = this.isSelected;
3412
3825
  }
3413
3826
  // 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;
3827
+ // this.spotLightHelper.update();
3426
3828
  }
3427
3829
  destroy() {
3428
3830
  this.scene.remove(this.objectGroup);
3429
3831
  this.material.dispose();
3430
- this.atmosphereMaterial.dispose();
3832
+ this.spotLightHelper.dispose();
3431
3833
  }
3432
3834
  }
3433
3835
 
3434
3836
  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
3837
  createObjects() {
3838
+ super.createObjects();
3518
3839
  this.material = new THREE.MeshLambertMaterial({
3519
3840
  color: 0x0d0d0d,
3520
3841
  emissive: 0x0d0d0d,
@@ -3528,27 +3849,6 @@ class MovingHead3d extends Fixture3d {
3528
3849
  const headPivotGroup = new THREE.Object3D();
3529
3850
  headPivotGroup.add(this.head);
3530
3851
  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
3852
  this.headGroup.add(this.spotlightGroup);
3553
3853
  // Add the arm
3554
3854
  this.armGroup.add(this.headGroup);
@@ -3565,10 +3865,7 @@ class MovingHead3d extends Fixture3d {
3565
3865
  }
3566
3866
  constructor(fixtureService, previewMeshService, fixture, scene) {
3567
3867
  super(fixtureService, fixture, scene);
3568
- this.pointLightMaxIntensity = 2;
3569
- this.spotLightLightMaxIntensity = 10;
3570
3868
  this.headGroup = new THREE.Object3D();
3571
- this.spotlightGroup = new THREE.Object3D();
3572
3869
  this.armGroup = new THREE.Object3D();
3573
3870
  this.objectGroup = new THREE.Object3D();
3574
3871
  forkJoin([
@@ -3588,10 +3885,10 @@ class MovingHead3d extends Fixture3d {
3588
3885
  return this.objectGroup;
3589
3886
  }
3590
3887
  updatePreview(channelValues, masterDimmerValue) {
3591
- super.updatePreview(channelValues, masterDimmerValue);
3592
3888
  if (!this.isLoaded) {
3593
3889
  return;
3594
3890
  }
3891
+ super.updatePreview(channelValues, masterDimmerValue);
3595
3892
  // Apply default settings
3596
3893
  let panStart = 0;
3597
3894
  let panEnd = 255;
@@ -3646,25 +3943,11 @@ class MovingHead3d extends Fixture3d {
3646
3943
  }
3647
3944
  this.lastSelected = this.isSelected;
3648
3945
  }
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
3946
  // this.spotLightHelper.update();
3663
3947
  }
3664
3948
  destroy() {
3665
3949
  this.scene.remove(this.objectGroup);
3666
3950
  this.material.dispose();
3667
- this.atmosphereMaterial.dispose();
3668
3951
  this.spotLightHelper.dispose();
3669
3952
  }
3670
3953
  }
@@ -3680,11 +3963,15 @@ class PreviewComponent {
3680
3963
  this.projectService = projectService;
3681
3964
  this.fixtures3d = [];
3682
3965
  this.previewService.doUpdateFixtureSetup.subscribe(() => {
3683
- // synchronize the 3d-fixtures to the project fixtures
3684
3966
  this.syncFixtures();
3685
3967
  });
3968
+ this.syncFixtures();
3686
3969
  }
3970
+ // synchronize the 3d-fixtures to the project fixtures
3687
3971
  syncFixtures() {
3972
+ if (!this.previewService.scene) {
3973
+ return;
3974
+ }
3688
3975
  // remove all fixtures
3689
3976
  for (const fixture3d of this.fixtures3d) {
3690
3977
  fixture3d.destroy();
@@ -3714,16 +4001,18 @@ class PreviewComponent {
3714
4001
  updateStagePosition(positioning, xMin, xMax, yMin, yMax, zMin, zMax) {
3715
4002
  let positionCount = 0; // Number of fixtures in the same position
3716
4003
  let positionIndex = 1;
3717
- this.projectService.project.fixtures.forEach((element, index) => {
3718
- if (element.positioning === positioning) {
4004
+ this.projectService.project.presetFixtures.forEach((element, index) => {
4005
+ const fixture = this.fixtureService.getFixtureByUuid(element.fixtureUuid);
4006
+ if (fixture.positioning === positioning) {
3719
4007
  positionCount++;
3720
4008
  }
3721
4009
  });
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;
4010
+ this.projectService.project.presetFixtures.forEach((element, index) => {
4011
+ const fixture = this.fixtureService.getFixtureByUuid(element.fixtureUuid);
4012
+ if (fixture.positioning === positioning) {
4013
+ fixture.positionX = xMin + ((xMax - xMin) / (positionCount + 1)) * positionIndex;
4014
+ fixture.positionY = yMin + ((yMax - yMin) / (positionCount + 1)) * positionIndex;
4015
+ fixture.positionZ = zMin + ((zMax - zMin) / (positionCount + 1)) * positionIndex;
3727
4016
  positionIndex++;
3728
4017
  }
3729
4018
  });
@@ -3755,7 +4044,7 @@ class PreviewComponent {
3755
4044
  fixture3d.isSelected = this.fixtureService.settingsFixtureIsSelected(fixture3d.fixture.fixture);
3756
4045
  }
3757
4046
  else {
3758
- fixture3d.isSelected = this.previewService.fixtureIsSelected(fixture3d.fixture.fixture.uuid, presets);
4047
+ fixture3d.isSelected = this.previewService.fixtureIsSelected(fixture3d.fixture.fixture.uuid, fixture3d.fixture.pixelKey, presets);
3759
4048
  }
3760
4049
  }
3761
4050
  // TODO enable for monitoring the DMX universes
@@ -3811,14 +4100,14 @@ class PreviewComponent {
3811
4100
  // this.scene.fog = new THREE.FogExp2( 0x000000, 0.1 );
3812
4101
  this.previewService.scene = this.scene;
3813
4102
  // Add a little bit of ambient light
3814
- const ambient = new THREE.AmbientLight(0xffffff, 1.5);
4103
+ const ambient = new THREE.AmbientLight(0xffffff, 1.8);
3815
4104
  this.scene.add(ambient);
3816
4105
  // Create the stage dimensions
3817
4106
  this.previewService.updateStage();
3818
4107
  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);
4108
+ lights[0] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
4109
+ lights[1] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
4110
+ lights[2] = new THREE.PointLight(0xffffff, 2, 0, 0.1);
3822
4111
  lights[0].position.set(0, 2000, 0);
3823
4112
  lights[1].position.set(1000, 2000, 1000);
3824
4113
  lights[2].position.set(-1000, -2000, -1000);
@@ -3828,6 +4117,7 @@ class PreviewComponent {
3828
4117
  this.scene.add(lights[0]);
3829
4118
  this.scene.add(lights[1]);
3830
4119
  this.scene.add(lights[2]);
4120
+ this.previewService.updateFixtureSetup();
3831
4121
  }
3832
4122
  ngAfterViewInit() {
3833
4123
  this.setupRenderer();
@@ -3884,131 +4174,6 @@ class WaitDialogComponent {
3884
4174
  }], () => [], null); })();
3885
4175
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WaitDialogComponent, { className: "WaitDialogComponent" }); })();
3886
4176
 
3887
- class ProjectLoadService {
3888
- constructor(projectService, previewService, fixtureService, presetService, sceneService, modalService, uuidService, timelineService, router, activatedRoute) {
3889
- this.projectService = projectService;
3890
- this.previewService = previewService;
3891
- this.fixtureService = fixtureService;
3892
- this.presetService = presetService;
3893
- this.sceneService = sceneService;
3894
- this.modalService = modalService;
3895
- this.uuidService = uuidService;
3896
- this.timelineService = timelineService;
3897
- this.router = router;
3898
- this.activatedRoute = activatedRoute;
3899
- }
3900
- afterLoad() {
3901
- this.fixtureService.updateCachedFixtures();
3902
- this.presetService.removeDeletedFixtures();
3903
- this.previewService.updateFixtureSetup();
3904
- this.presetService.fixtureSelectionChanged.next();
3905
- this.presetService.autoOpenFirstEffect();
3906
- this.previewService.updateStage();
3907
- this.presetService.previewLive();
3908
- this.sceneService.selectPresetFromSelectedScene();
3909
- }
3910
- selectScenesPresetComposition() {
3911
- this.presetService.selectedPreset = this.presetService.getPresetByUuid(this.projectService.project.selectedPresetUuid);
3912
- this.sceneService.selectedScenes = [];
3913
- if (this.projectService.project.selectedSceneUuids) {
3914
- for (const uuid of this.projectService.project.selectedSceneUuids) {
3915
- this.sceneService.selectedScenes.push(this.sceneService.getSceneByUuid(uuid));
3916
- }
3917
- }
3918
- this.timelineService.selectedComposition = undefined;
3919
- this.timelineService.selectedCompositionIndex = undefined;
3920
- this.timelineService.destroyWaveSurfer();
3921
- for (let i = 0; i < this.projectService.project.compositions.length; i++) {
3922
- if (this.projectService.project.compositions[i].uuid === this.projectService.project.selectedCompositionUuid) {
3923
- this.timelineService.selectCompositionIndex(i);
3924
- break;
3925
- }
3926
- }
3927
- }
3928
- load(id, name, shareToken) {
3929
- const ref = this.modalService.show(WaitDialogComponent, { keyboard: false, ignoreBackdropClick: true });
3930
- return this.projectService.getProject(id, name, shareToken).pipe(map((project) => {
3931
- this.projectService.project = project;
3932
- this.selectScenesPresetComposition();
3933
- this.afterLoad();
3934
- const queryParams = {
3935
- id,
3936
- token: project.shareToken,
3937
- };
3938
- this.router.navigate([], {
3939
- relativeTo: this.activatedRoute,
3940
- queryParams,
3941
- queryParamsHandling: 'merge', // remove to replace all query params by provided
3942
- });
3943
- }), finalize(() => {
3944
- // hide the modal again because of:
3945
- // https://github.com/valor-software/ngx-bootstrap/issues/3711
3946
- setTimeout(() => {
3947
- ref.hide();
3948
- }, 250);
3949
- setTimeout(() => {
3950
- ref.hide();
3951
- }, 500);
3952
- setTimeout(() => {
3953
- ref.hide();
3954
- }, 1500);
3955
- }));
3956
- }
3957
- new() {
3958
- // create an empty new project
3959
- const project = new Project();
3960
- project.uuid = this.uuidService.getUuid();
3961
- this.projectService.project = project;
3962
- this.projectService.project.shareToken = this.uuidService.getUuid();
3963
- // Add a default scene and preset
3964
- const preset = new Preset();
3965
- preset.uuid = this.uuidService.getUuid();
3966
- preset.name = 'New Preset';
3967
- this.projectService.project.presets.push(preset);
3968
- this.presetService.selectPreset(0);
3969
- this.sceneService.addScene();
3970
- this.projectService.project.scenes[0].presetUuids.push(preset.uuid);
3971
- this.projectService.project.previewPreset = true;
3972
- this.sceneService.selectedScenes = [this.projectService.project.scenes[0]];
3973
- this.presetService.selectedPreset = this.projectService.project.presets[0];
3974
- this.timelineService.selectedComposition = undefined;
3975
- this.timelineService.selectedCompositionIndex = undefined;
3976
- this.timelineService.destroyWaveSurfer();
3977
- this.afterLoad();
3978
- const queryParams = {
3979
- id: '',
3980
- token: '',
3981
- };
3982
- this.router.navigate([], {
3983
- relativeTo: this.activatedRoute,
3984
- queryParams,
3985
- 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
4177
  class WarningDialogComponent {
4013
4178
  constructor(bsModalRef) {
4014
4179
  this.bsModalRef = bsModalRef;
@@ -4091,15 +4256,197 @@ class WarningDialogService {
4091
4256
  }));
4092
4257
  }));
4093
4258
  }
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' }); }
4259
+ static { this.ɵfac = function WarningDialogService_Factory(t) { return new (t || WarningDialogService)(i0.ɵɵinject(i1$1.BsModalService), i0.ɵɵinject(i2.TranslateService)); }; }
4260
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WarningDialogService, factory: WarningDialogService.ɵfac, providedIn: 'root' }); }
4261
+ }
4262
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogService, [{
4263
+ type: Injectable,
4264
+ args: [{
4265
+ providedIn: 'root',
4266
+ }]
4267
+ }], () => [{ type: i1$1.BsModalService }, { type: i2.TranslateService }], null); })();
4268
+
4269
+ class ProjectLoadService {
4270
+ constructor(projectService, previewService, fixtureService, presetService, sceneService, modalService, uuidService, timelineService, router, activatedRoute, warningDialogService) {
4271
+ this.projectService = projectService;
4272
+ this.previewService = previewService;
4273
+ this.fixtureService = fixtureService;
4274
+ this.presetService = presetService;
4275
+ this.sceneService = sceneService;
4276
+ this.modalService = modalService;
4277
+ this.uuidService = uuidService;
4278
+ this.timelineService = timelineService;
4279
+ this.router = router;
4280
+ this.activatedRoute = activatedRoute;
4281
+ this.warningDialogService = warningDialogService;
4282
+ }
4283
+ migrateToVersion2() {
4284
+ for (let fixture of this.projectService.project.fixtures) {
4285
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
4286
+ if (pixelKeys.length > 0) {
4287
+ for (let pixelKey of pixelKeys) {
4288
+ const projectFixture = new PresetFixture();
4289
+ projectFixture.fixtureUuid = fixture.uuid;
4290
+ projectFixture.pixelKey = pixelKey;
4291
+ this.projectService.project.presetFixtures.push(projectFixture);
4292
+ }
4293
+ }
4294
+ else {
4295
+ const projectFixture = new PresetFixture();
4296
+ projectFixture.fixtureUuid = fixture.uuid;
4297
+ this.projectService.project.presetFixtures.push(projectFixture);
4298
+ }
4299
+ }
4300
+ for (let preset of this.projectService.project.presets) {
4301
+ for (let fixtureUuid of preset.fixtureUuids) {
4302
+ const fixture = this.fixtureService.getFixtureByUuid(fixtureUuid);
4303
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
4304
+ if (pixelKeys.length > 0) {
4305
+ for (let pixelKey of pixelKeys) {
4306
+ const presetFixture = new PresetFixture();
4307
+ presetFixture.fixtureUuid = fixtureUuid;
4308
+ presetFixture.pixelKey = pixelKey;
4309
+ preset.fixtures.push(presetFixture);
4310
+ }
4311
+ }
4312
+ else {
4313
+ const presetFixture = new PresetFixture();
4314
+ presetFixture.fixtureUuid = fixtureUuid;
4315
+ preset.fixtures.push(presetFixture);
4316
+ }
4317
+ }
4318
+ }
4319
+ this.projectService.project.version = 2;
4320
+ }
4321
+ migrateFromOldProject() {
4322
+ let migrated = false;
4323
+ if (!this.projectService.project.version) {
4324
+ // Migrate from version 1
4325
+ this.migrateToVersion2();
4326
+ migrated = true;
4327
+ }
4328
+ if (migrated) {
4329
+ this.warningDialogService.show('designer.project.migrated').subscribe();
4330
+ }
4331
+ }
4332
+ afterLoad() {
4333
+ this.migrateFromOldProject();
4334
+ this.fixtureService.updateCachedFixtures();
4335
+ this.presetService.removeDeletedFixtures();
4336
+ this.previewService.updateFixtureSetup();
4337
+ this.presetService.fixtureSelectionChanged.next();
4338
+ this.presetService.autoOpenFirstEffect();
4339
+ this.previewService.updateStage();
4340
+ this.presetService.previewLive();
4341
+ this.sceneService.selectPresetFromSelectedScene();
4342
+ }
4343
+ selectScenesPresetComposition() {
4344
+ this.presetService.selectedPreset = this.presetService.getPresetByUuid(this.projectService.project.selectedPresetUuid);
4345
+ this.sceneService.selectedScenes = [];
4346
+ if (this.projectService.project.selectedSceneUuids) {
4347
+ for (const uuid of this.projectService.project.selectedSceneUuids) {
4348
+ this.sceneService.selectedScenes.push(this.sceneService.getSceneByUuid(uuid));
4349
+ }
4350
+ }
4351
+ this.timelineService.selectedComposition = undefined;
4352
+ this.timelineService.selectedCompositionIndex = undefined;
4353
+ this.timelineService.destroyWaveSurfer();
4354
+ for (let i = 0; i < this.projectService.project.compositions.length; i++) {
4355
+ if (this.projectService.project.compositions[i].uuid === this.projectService.project.selectedCompositionUuid) {
4356
+ this.timelineService.selectCompositionIndex(i);
4357
+ break;
4358
+ }
4359
+ }
4360
+ }
4361
+ load(id, name, shareToken) {
4362
+ const ref = this.modalService.show(WaitDialogComponent, { keyboard: false, ignoreBackdropClick: true });
4363
+ return this.projectService.getProject(id, name, shareToken).pipe(map((project) => {
4364
+ if (project.version > this.projectService.currentProjectVersion) {
4365
+ throw new Error('The project version ' +
4366
+ project.version +
4367
+ ' is created with a newer version of the designer. Please update your Rocket Show version to open this project.');
4368
+ }
4369
+ this.projectService.project = project;
4370
+ this.selectScenesPresetComposition();
4371
+ this.afterLoad();
4372
+ const queryParams = {
4373
+ id,
4374
+ token: project.shareToken,
4375
+ };
4376
+ this.router.navigate([], {
4377
+ relativeTo: this.activatedRoute,
4378
+ queryParams,
4379
+ queryParamsHandling: 'merge', // remove to replace all query params by provided
4380
+ });
4381
+ }), finalize(() => {
4382
+ // hide the modal again because of:
4383
+ // https://github.com/valor-software/ngx-bootstrap/issues/3711
4384
+ setTimeout(() => {
4385
+ ref.hide();
4386
+ }, 250);
4387
+ setTimeout(() => {
4388
+ ref.hide();
4389
+ }, 500);
4390
+ setTimeout(() => {
4391
+ ref.hide();
4392
+ }, 1500);
4393
+ }));
4394
+ }
4395
+ new() {
4396
+ // create an empty new project
4397
+ const project = new Project();
4398
+ project.uuid = this.uuidService.getUuid();
4399
+ project.version = this.projectService.currentProjectVersion;
4400
+ this.projectService.project = project;
4401
+ this.projectService.project.shareToken = this.uuidService.getUuid();
4402
+ // Add a default scene and preset
4403
+ const preset = new Preset();
4404
+ preset.uuid = this.uuidService.getUuid();
4405
+ preset.name = 'New Preset';
4406
+ this.projectService.project.presets.push(preset);
4407
+ this.presetService.selectPreset(0);
4408
+ this.sceneService.addScene();
4409
+ this.projectService.project.scenes[0].presetUuids.push(preset.uuid);
4410
+ this.projectService.project.previewPreset = true;
4411
+ this.sceneService.selectedScenes = [this.projectService.project.scenes[0]];
4412
+ this.presetService.selectedPreset = this.projectService.project.presets[0];
4413
+ this.timelineService.selectedComposition = undefined;
4414
+ this.timelineService.selectedCompositionIndex = undefined;
4415
+ this.timelineService.destroyWaveSurfer();
4416
+ this.afterLoad();
4417
+ const queryParams = {
4418
+ id: '',
4419
+ token: '',
4420
+ };
4421
+ this.router.navigate([], {
4422
+ relativeTo: this.activatedRoute,
4423
+ queryParams,
4424
+ queryParamsHandling: 'merge', // remove to replace all query params by provided
4425
+ });
4426
+ }
4427
+ template() {
4428
+ // load the template project with id 1
4429
+ this.load(1, null).subscribe(() => {
4430
+ this.projectService.project.id = undefined;
4431
+ });
4432
+ }
4433
+ import(data) {
4434
+ // import a project from a string
4435
+ const project = new Project(JSON.parse(data));
4436
+ project.id = undefined;
4437
+ this.projectService.project = project;
4438
+ this.selectScenesPresetComposition();
4439
+ this.afterLoad();
4440
+ }
4441
+ 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)); }; }
4442
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ProjectLoadService, factory: ProjectLoadService.ɵfac, providedIn: 'root' }); }
4096
4443
  }
4097
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WarningDialogService, [{
4444
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectLoadService, [{
4098
4445
  type: Injectable,
4099
4446
  args: [{
4100
4447
  providedIn: 'root',
4101
4448
  }]
4102
- }], () => [{ type: i1$1.BsModalService }, { type: i2.TranslateService }], null); })();
4449
+ }], () => [{ 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
4450
 
4104
4451
  class ArraySortPipe {
4105
4452
  transform(array, field) {
@@ -4310,7 +4657,7 @@ class ProjectImportComponent {
4310
4657
  handleKeyboardEvent(event) {
4311
4658
  this.ok();
4312
4659
  }
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)); }; }
4660
+ 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
4661
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ProjectImportComponent, selectors: [["lib-project-import"]], hostBindings: function ProjectImportComponent_HostBindings(rf, ctx) { if (rf & 1) {
4315
4662
  i0.ɵɵlistener("keydown.enter", function ProjectImportComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4316
4663
  } }, 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 +4690,7 @@ class ProjectImportComponent {
4343
4690
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectImportComponent, [{
4344
4691
  type: Component,
4345
4692
  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: [{
4693
+ }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: ProjectLoadService }], { handleKeyboardEvent: [{
4347
4694
  type: HostListener,
4348
4695
  args: ['document:keydown.enter', ['$event']]
4349
4696
  }] }); })();
@@ -4501,7 +4848,7 @@ class ProjectSaveComponent {
4501
4848
  i0.ɵɵproperty("disabled", ctx.loading || !ctx.projectName);
4502
4849
  i0.ɵɵadvance();
4503
4850
  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] }); }
4851
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe, ArraySortPipe] }); }
4505
4852
  }
4506
4853
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectSaveComponent, [{
4507
4854
  type: Component,
@@ -4564,7 +4911,7 @@ class ProjectShareComponent {
4564
4911
  i0.ɵɵproperty("ngModel", ctx.shareLink);
4565
4912
  i0.ɵɵadvance(3);
4566
4913
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(17, 8, "designer.misc.ok"));
4567
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
4914
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
4568
4915
  }
4569
4916
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProjectShareComponent, [{
4570
4917
  type: Component,
@@ -4764,7 +5111,7 @@ class FixturePoolCreateFromFileComponent {
4764
5111
  handleKeyboardEvent(event) {
4765
5112
  this.ok();
4766
5113
  }
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)); }; }
5114
+ 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
5115
  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
5116
  i0.ɵɵlistener("keydown.enter", function FixturePoolCreateFromFileComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
4770
5117
  } }, 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 +5126,12 @@ class FixturePoolCreateFromFileComponent {
4779
5126
  i0.ɵɵelementEnd()()();
4780
5127
  i0.ɵɵelementStart(7, "div", 4)(8, "dropzone", 5);
4781
5128
  i0.ɵɵlistener("error", function FixturePoolCreateFromFileComponent_Template_dropzone_error_8_listener($event) { return ctx.onUploadError($event); });
4782
- i0.ɵɵelementEnd()();
5129
+ i0.ɵɵelementEnd();
4783
5130
  i0.ɵɵelementStart(9, "div", 6)(10, "button", 7);
4784
5131
  i0.ɵɵlistener("click", function FixturePoolCreateFromFileComponent_Template_button_click_10_listener() { return ctx.ok(); });
4785
5132
  i0.ɵɵtext(11);
4786
5133
  i0.ɵɵpipe(12, "translate");
4787
- i0.ɵɵelementEnd()();
5134
+ i0.ɵɵelementEnd()()();
4788
5135
  } if (rf & 2) {
4789
5136
  i0.ɵɵadvance(2);
4790
5137
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 5, "designer.fixture-pool.create-fixture-from-profile-file-dialog-title"));
@@ -4796,8 +5143,8 @@ class FixturePoolCreateFromFileComponent {
4796
5143
  }
4797
5144
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixturePoolCreateFromFileComponent, [{
4798
5145
  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: [{
5146
+ 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" }]
5147
+ }], () => [{ type: i1$1.BsModalRef }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: FixtureService }, { type: ProjectService }], { handleKeyboardEvent: [{
4801
5148
  type: HostListener,
4802
5149
  args: ['document:keydown.enter', ['$event']]
4803
5150
  }] }); })();
@@ -4902,9 +5249,10 @@ function FixturePoolComponent_div_66_option_13_Template(rf, ctx) { if (rf & 1) {
4902
5249
  i0.ɵɵelementEnd();
4903
5250
  } if (rf & 2) {
4904
5251
  const mode_r10 = ctx.$implicit;
5252
+ const ctx_r2 = i0.ɵɵnextContext(2);
4905
5253
  i0.ɵɵproperty("ngValue", mode_r10.shortName || mode_r10.name);
4906
5254
  i0.ɵɵadvance();
4907
- i0.ɵɵtextInterpolate3(" ", mode_r10.name, " - ", mode_r10.channels.length, " ", i0.ɵɵpipeBind1(2, 4, "designer.fixture-pool.channels"), " ");
5255
+ i0.ɵɵtextInterpolate3(" ", mode_r10.name, " - ", ctx_r2.fixtureService.getModeChannelCount(ctx_r2.selectedFixtureProfile, mode_r10), " ", i0.ɵɵpipeBind1(2, 4, "designer.fixture-pool.channels"), " ");
4908
5256
  } }
4909
5257
  function FixturePoolComponent_div_66_option_20_Template(rf, ctx) { if (rf & 1) {
4910
5258
  i0.ɵɵelementStart(0, "option", 72);
@@ -5038,7 +5386,9 @@ class FixturePoolComponent {
5038
5386
  this.fixtureService.loadProfileByUuid(searchProfile.uuid).subscribe(() => {
5039
5387
  const profile = this.fixtureService.getProfileByUuid(searchProfile.uuid);
5040
5388
  const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
5041
- this.selectFixture(newFixture);
5389
+ if (newFixture) {
5390
+ this.selectFixture(newFixture);
5391
+ }
5042
5392
  });
5043
5393
  }
5044
5394
  addCopy(originalFixture) {
@@ -5081,8 +5431,10 @@ class FixturePoolComponent {
5081
5431
  }
5082
5432
  channelOccupied(index) {
5083
5433
  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) {
5434
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5435
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5436
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5437
+ if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
5086
5438
  return true;
5087
5439
  }
5088
5440
  }
@@ -5098,8 +5450,10 @@ class FixturePoolComponent {
5098
5450
  }
5099
5451
  channelOccupiedEnd(index) {
5100
5452
  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) {
5453
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5454
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5455
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5456
+ if (index === fixture.dmxFirstChannel + channelCount - 1) {
5103
5457
  return true;
5104
5458
  }
5105
5459
  }
@@ -5108,8 +5462,10 @@ class FixturePoolComponent {
5108
5462
  channelOverlapped(index) {
5109
5463
  let occupiedFixture;
5110
5464
  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) {
5465
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5466
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5467
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5468
+ if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
5113
5469
  if (occupiedFixture) {
5114
5470
  if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel || occupiedFixture.modeShortName !== fixture.modeShortName) {
5115
5471
  // fixtures are allowed to overlap, if they start at the same channel and
@@ -5131,8 +5487,10 @@ class FixturePoolComponent {
5131
5487
  // find a dragging fixture and select it, but don't change the selection, if the
5132
5488
  // currently selected fixture might also be selected (on overlapped fixtures)
5133
5489
  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) {
5490
+ const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
5491
+ const mode = this.fixtureService.getModeByFixture(profile, fixture);
5492
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5493
+ if (selectedIndex >= fixture.dmxFirstChannel && selectedIndex <= fixture.dmxFirstChannel + channelCount - 1) {
5136
5494
  if (this.selectedFixture === fixture) {
5137
5495
  newSelectedFixture = fixture;
5138
5496
  break;
@@ -5155,8 +5513,10 @@ class FixturePoolComponent {
5155
5513
  return false;
5156
5514
  }
5157
5515
  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) {
5516
+ const profile = this.fixtureService.getProfileByUuid(this.selectedFixture.profileUuid);
5517
+ const mode = this.fixtureService.getModeByFixture(profile, this.selectedFixture);
5518
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5519
+ if (index < this.selectedFixture.dmxFirstChannel + channelCount) {
5160
5520
  return true;
5161
5521
  }
5162
5522
  }
@@ -5169,15 +5529,15 @@ class FixturePoolComponent {
5169
5529
  this.channelDragOffset = undefined;
5170
5530
  }
5171
5531
  channelMouseOver(event) {
5532
+ if (!this.channelDragFixture) {
5533
+ return;
5534
+ }
5172
5535
  // perform dragging
5173
5536
  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) {
5537
+ const profile = this.fixtureService.getProfileByUuid(this.channelDragFixture.profileUuid);
5538
+ const mode = this.fixtureService.getModeByFixture(profile, this.selectedFixture);
5539
+ const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5540
+ if (selectedIndex - this.channelDragOffset >= 0 && selectedIndex - this.channelDragOffset + channelCount - 1 <= 511) {
5181
5541
  this.channelDragFixture.dmxFirstChannel = selectedIndex - this.channelDragOffset;
5182
5542
  }
5183
5543
  }
@@ -5194,6 +5554,46 @@ class FixturePoolComponent {
5194
5554
  }
5195
5555
  }
5196
5556
  this.projectService.project.fixtures = this.fixturePool;
5557
+ // remove deleted fixtures from preset fixtures
5558
+ for (let i = this.projectService.project.presetFixtures.length - 1; i >= 0; i--) {
5559
+ let found = false;
5560
+ const presetFixture = this.projectService.project.presetFixtures[i];
5561
+ for (let fixture of this.projectService.project.fixtures) {
5562
+ if (presetFixture.fixtureUuid === fixture.uuid) {
5563
+ found = true;
5564
+ break;
5565
+ }
5566
+ }
5567
+ if (!found) {
5568
+ this.projectService.project.presetFixtures.splice(i, 1);
5569
+ }
5570
+ }
5571
+ // add the new fixtures to the preset fixtures
5572
+ for (let fixture of this.projectService.project.fixtures) {
5573
+ let found = false;
5574
+ for (let presetFixture of this.projectService.project.presetFixtures) {
5575
+ if (presetFixture.fixtureUuid === fixture.uuid) {
5576
+ found = true;
5577
+ break;
5578
+ }
5579
+ }
5580
+ if (!found) {
5581
+ const pixelKeys = this.fixtureService.fixtureGetUniquePixelKeys(fixture);
5582
+ if (pixelKeys.length > 0) {
5583
+ for (let pixelKey of pixelKeys) {
5584
+ const presetFixture = new PresetFixture();
5585
+ presetFixture.fixtureUuid = fixture.uuid;
5586
+ presetFixture.pixelKey = pixelKey;
5587
+ this.projectService.project.presetFixtures.push(presetFixture);
5588
+ }
5589
+ }
5590
+ else {
5591
+ const presetFixture = new PresetFixture();
5592
+ presetFixture.fixtureUuid = fixture.uuid;
5593
+ this.projectService.project.presetFixtures.push(presetFixture);
5594
+ }
5595
+ }
5596
+ }
5197
5597
  this.fixtureService.updateCachedFixtures();
5198
5598
  this.presetService.removeDeletedFixtures();
5199
5599
  this.previewService.updateFixtureSetup();
@@ -5241,7 +5641,7 @@ class FixturePoolComponent {
5241
5641
  handleKeyboardEvent(event) {
5242
5642
  this.ok();
5243
5643
  }
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)); }; }
5644
+ 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
5645
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixturePoolComponent, selectors: [["lib-app-fixture-pool"]], hostBindings: function FixturePoolComponent_HostBindings(rf, ctx) { if (rf & 1) {
5246
5646
  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
5647
  } }, 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 +5749,12 @@ class FixturePoolComponent {
5349
5749
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(70, 33, "designer.misc.cancel"), " ");
5350
5750
  i0.ɵɵadvance(3);
5351
5751
  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}"] }); }
5752
+ } }, 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
5753
  }
5354
5754
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixturePoolComponent, [{
5355
5755
  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: [{
5756
+ 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"] }]
5757
+ }], () => [{ 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
5758
  type: HostListener,
5359
5759
  args: ['window:mouseup', ['$event']]
5360
5760
  }], handleKeyboardEvent: [{
@@ -5669,7 +6069,7 @@ class UserLoginComponent {
5669
6069
  i0.ɵɵproperty("ngIf", ctx.loggingIn);
5670
6070
  i0.ɵɵadvance();
5671
6071
  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] }); }
6072
+ } }, dependencies: [i5.NgIf, i4.ɵNgNoValidate, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgControlStatusGroup, i4.RequiredValidator, i4.NgModel, i4.NgForm, i2.TranslatePipe] }); }
5673
6073
  }
5674
6074
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserLoginComponent, [{
5675
6075
  type: Component,
@@ -5879,7 +6279,7 @@ class UserRegisterComponent {
5879
6279
  i0.ɵɵproperty("ngIf", ctx.registering);
5880
6280
  i0.ɵɵadvance();
5881
6281
  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] }); }
6282
+ } }, dependencies: [i5.NgIf, i4.ɵNgNoValidate, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgControlStatusGroup, i4.RequiredValidator, i4.NgModel, i4.NgForm, i2.TranslatePipe] }); }
5883
6283
  }
5884
6284
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserRegisterComponent, [{
5885
6285
  type: Component,
@@ -5918,6 +6318,91 @@ class UserEnsureLoginService {
5918
6318
  }]
5919
6319
  }], () => [{ type: UserService }, { type: i1$1.BsModalService }, { type: ConfigService }], null); })();
5920
6320
 
6321
+ class DropzoneComponent {
6322
+ set url(value) {
6323
+ this._url = value;
6324
+ this.updateConfig();
6325
+ }
6326
+ set acceptedFiles(value) {
6327
+ this._acceptedFiles = value;
6328
+ this.updateConfig();
6329
+ }
6330
+ set maxFiles(value) {
6331
+ this._maxFiles = value;
6332
+ this.updateConfig();
6333
+ }
6334
+ constructor(translateService, configService) {
6335
+ this.translateService = translateService;
6336
+ this.configService = configService;
6337
+ this.error = new EventEmitter();
6338
+ this.success = new EventEmitter();
6339
+ this.addedFile = new EventEmitter();
6340
+ this._maxFiles = undefined;
6341
+ this.translateService
6342
+ .get('designer.misc.dropzone-message')
6343
+ .pipe(map((result) => {
6344
+ this.uploadMessage = '<h3 class="mb-0"><i class="fa fa-cloud-upload"></i></h3>' + result;
6345
+ }))
6346
+ .subscribe();
6347
+ this.updateConfig();
6348
+ }
6349
+ updateConfig() {
6350
+ this.dropzoneConfig = {
6351
+ url: this.configService.restUrl + this._url,
6352
+ paramName: 'file',
6353
+ addRemoveLinks: false,
6354
+ maxFilesize: null /* unlimited */,
6355
+ acceptedFiles: this._acceptedFiles,
6356
+ timeout: 0,
6357
+ chunking: this.configService.dropzoneChunking,
6358
+ forceChunking: this.configService.dropzoneChunking,
6359
+ parallelUploads: 1,
6360
+ maxFiles: this._maxFiles,
6361
+ previewTemplate: `
6362
+ <div class="dz-preview dz-file-preview">
6363
+ <!-- The attachment details -->
6364
+ <div class="dz-details" style="text-align: left">
6365
+ <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>
6366
+ </div>
6367
+
6368
+ <!--div class="mt-5">
6369
+ <span data-dz-errormessage></span>
6370
+ </div-->
6371
+
6372
+ <div class="progress mt-4 mb-1" style="height: 10px">
6373
+ <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width:0%;" data-dz-uploadprogress></div>
6374
+ </div>
6375
+ </div>
6376
+ `,
6377
+ };
6378
+ }
6379
+ static { this.ɵfac = function DropzoneComponent_Factory(t) { return new (t || DropzoneComponent)(i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(ConfigService)); }; }
6380
+ 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) {
6381
+ i0.ɵɵelementStart(0, "dropzone", 0);
6382
+ 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); });
6383
+ i0.ɵɵelementEnd();
6384
+ } if (rf & 2) {
6385
+ i0.ɵɵproperty("config", ctx.dropzoneConfig)("useDropzoneClass", "false")("message", ctx.uploadMessage);
6386
+ } }, dependencies: [i5$1.DropzoneComponent] }); }
6387
+ }
6388
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropzoneComponent, [{
6389
+ type: Component,
6390
+ 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" }]
6391
+ }], () => [{ type: i2.TranslateService }, { type: ConfigService }], { error: [{
6392
+ type: Output
6393
+ }], success: [{
6394
+ type: Output
6395
+ }], addedFile: [{
6396
+ type: Output
6397
+ }], url: [{
6398
+ type: Input
6399
+ }], acceptedFiles: [{
6400
+ type: Input
6401
+ }], maxFiles: [{
6402
+ type: Input
6403
+ }] }); })();
6404
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DropzoneComponent, { className: "DropzoneComponent" }); })();
6405
+
5921
6406
  function CompositionSettingsComponent_div_22_div_4_Template(rf, ctx) { if (rf & 1) {
5922
6407
  i0.ɵɵelementStart(0, "div");
5923
6408
  i0.ɵɵtext(1);
@@ -5977,8 +6462,8 @@ function CompositionSettingsComponent_div_22_Template(rf, ctx) { if (rf & 1) {
5977
6462
  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
6463
  i0.ɵɵelementEnd()();
5979
6464
  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)); });
6465
+ i0.ɵɵelementStart(7, "div", 21)(8, "div", 22)(9, "app-dropzone", 23);
6466
+ 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
6467
  i0.ɵɵelementEnd()();
5983
6468
  i0.ɵɵelementStart(10, "div", 24)(11, "input", 25);
5984
6469
  i0.ɵɵpipe(12, "translate");
@@ -5997,11 +6482,11 @@ function CompositionSettingsComponent_div_22_Template(rf, ctx) { if (rf & 1) {
5997
6482
  i0.ɵɵadvance();
5998
6483
  i0.ɵɵproperty("ngIf", ctx_r1.configService.enableMediaLibrary);
5999
6484
  i0.ɵɵadvance(3);
6000
- i0.ɵɵproperty("config", ctx_r1.dropzoneConfig)("useDropzoneClass", "false")("message", ctx_r1.uploadMessage);
6485
+ i0.ɵɵproperty("url", ctx_r1.getDropzoneUrl())("acceptedFiles", "audio/*");
6001
6486
  i0.ɵɵadvance(2);
6002
- i0.ɵɵpropertyInterpolate("placeholder", i0.ɵɵpipeBind1(12, 8, "designer.misc.search"));
6487
+ i0.ɵɵpropertyInterpolate("placeholder", i0.ɵɵpipeBind1(12, 7, "designer.misc.search"));
6003
6488
  i0.ɵɵadvance(5);
6004
- i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind2(17, 10, ctx_r1.filteredExistingFiles, "name"));
6489
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind2(17, 9, ctx_r1.filteredExistingFiles, "name"));
6005
6490
  } }
6006
6491
  class CompositionSettingsComponent {
6007
6492
  constructor(bsModalRef, timelineService, configService, translateService, http, warningDialogService, toastrService, projectService) {
@@ -6020,40 +6505,6 @@ class CompositionSettingsComponent {
6020
6505
  this.uploading = false;
6021
6506
  }
6022
6507
  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
6508
  this.loadFiles();
6058
6509
  if (this.timelineService.externalCompositionsAvailable) {
6059
6510
  this.timelineService.getExternalCompositionNames().subscribe((compositionNames) => {
@@ -6061,6 +6512,10 @@ class CompositionSettingsComponent {
6061
6512
  });
6062
6513
  }
6063
6514
  }
6515
+ getDropzoneUrl() {
6516
+ const projectId = this.projectService.project.id ? this.projectService.project.id : '';
6517
+ return 'file/upload?compositionUuid=' + this.composition.uuid + '&projectId=' + projectId;
6518
+ }
6064
6519
  ok() {
6065
6520
  this.onClose.next(1);
6066
6521
  this.bsModalRef.hide();
@@ -6154,10 +6609,10 @@ class CompositionSettingsComponent {
6154
6609
  }))
6155
6610
  .subscribe();
6156
6611
  }
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)); }; }
6612
+ 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
6613
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CompositionSettingsComponent, selectors: [["lib-app-composition-settings"]], hostBindings: function CompositionSettingsComponent_HostBindings(rf, ctx) { if (rf & 1) {
6159
6614
  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) {
6615
+ } }, 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
6616
  i0.ɵɵelementStart(0, "div", 0)(1, "h4", 1);
6162
6617
  i0.ɵɵtext(2);
6163
6618
  i0.ɵɵelementEnd();
@@ -6183,7 +6638,7 @@ class CompositionSettingsComponent {
6183
6638
  i0.ɵɵtext(20);
6184
6639
  i0.ɵɵpipe(21, "translate");
6185
6640
  i0.ɵɵelementEnd()()()();
6186
- i0.ɵɵtemplate(22, CompositionSettingsComponent_div_22_Template, 18, 13, "div", 11);
6641
+ i0.ɵɵtemplate(22, CompositionSettingsComponent_div_22_Template, 18, 12, "div", 11);
6187
6642
  i0.ɵɵelementEnd();
6188
6643
  i0.ɵɵelementStart(23, "div", 12)(24, "a", 13);
6189
6644
  i0.ɵɵlistener("click", function CompositionSettingsComponent_Template_a_click_24_listener() { ctx.cancel(); return false; });
@@ -6216,12 +6671,12 @@ class CompositionSettingsComponent {
6216
6671
  i0.ɵɵproperty("disabled", ctx.uploading);
6217
6672
  i0.ɵɵadvance();
6218
6673
  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] }); }
6674
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i11.TypeaheadDirective, DropzoneComponent, i2.TranslatePipe, ArraySortPipe] }); }
6220
6675
  }
6221
6676
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CompositionSettingsComponent, [{
6222
6677
  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: [{
6678
+ 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" }]
6679
+ }], () => [{ type: i1$1.BsModalRef }, { type: TimelineService }, { type: ConfigService }, { type: i2.TranslateService }, { type: i1.HttpClient }, { type: WarningDialogService }, { type: i3$1.ToastrService }, { type: ProjectService }], { handleKeyboardEvent: [{
6225
6680
  type: HostListener,
6226
6681
  args: ['document:keydown.enter', ['$event']]
6227
6682
  }] }); })();
@@ -6423,7 +6878,7 @@ class TimelineGridComponent {
6423
6878
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 23, "designer.misc.cancel"), " ");
6424
6879
  i0.ɵɵadvance(3);
6425
6880
  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] }); }
6881
+ } }, dependencies: [i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
6427
6882
  }
6428
6883
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimelineGridComponent, [{
6429
6884
  type: Component,
@@ -6801,7 +7256,7 @@ class TimelineComponent {
6801
7256
  i0.ɵɵproperty("ngIf", ctx.timelineService.selectedComposition);
6802
7257
  i0.ɵɵadvance();
6803
7258
  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] }); }
7259
+ } }, 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
7260
  }
6806
7261
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimelineComponent, [{
6807
7262
  type: Component,
@@ -6950,7 +7405,7 @@ class SceneSettingsComponent {
6950
7405
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(52, 29, "designer.misc.cancel"), " ");
6951
7406
  i0.ɵɵadvance(3);
6952
7407
  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] }); }
7408
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
6954
7409
  }
6955
7410
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SceneSettingsComponent, [{
6956
7411
  type: Component,
@@ -7058,7 +7513,7 @@ class SceneComponent {
7058
7513
  function FixtureComponent_div_12_div_1_Template(rf, ctx) { if (rf & 1) {
7059
7514
  const _r1 = i0.ɵɵgetCurrentView();
7060
7515
  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)); });
7516
+ 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
7517
  i0.ɵɵelementStart(2, "div", 14);
7063
7518
  i0.ɵɵelement(3, "i", 15);
7064
7519
  i0.ɵɵelementEnd();
@@ -7070,15 +7525,15 @@ function FixtureComponent_div_12_div_1_Template(rf, ctx) { if (rf & 1) {
7070
7525
  i0.ɵɵtext(8);
7071
7526
  i0.ɵɵelementEnd()()();
7072
7527
  } if (rf & 2) {
7073
- const item_r2 = ctx.$implicit;
7528
+ const presetFixture_r2 = ctx.$implicit;
7074
7529
  const ctx_r2 = i0.ɵɵnextContext(2);
7075
- i0.ɵɵclassProp("inactive-list-item", !ctx_r2.fixtureIsSelected(item_r2));
7530
+ i0.ɵɵclassProp("inactive-list-item", !ctx_r2.fixtureIsSelected(presetFixture_r2));
7076
7531
  i0.ɵɵadvance(5);
7077
- i0.ɵɵproperty("ngModel", ctx_r2.fixtureIsSelected(item_r2));
7532
+ i0.ɵɵproperty("ngModel", ctx_r2.fixtureIsSelected(presetFixture_r2));
7078
7533
  i0.ɵɵadvance(2);
7079
- i0.ɵɵclassMapInterpolate1("icon-", ctx_r2.fixtureService.getFixtureIconClass(ctx_r2.fixtureService.getProfileByUuid(item_r2.profileUuid)), " mr-1");
7534
+ i0.ɵɵclassMapInterpolate1("icon-", ctx_r2.fixtureService.getFixtureIconClass(ctx_r2.fixtureService.getProfileByUuid(ctx_r2.fixtureService.getFixtureByUuid(presetFixture_r2.fixtureUuid).profileUuid)), " mr-1");
7080
7535
  i0.ɵɵadvance();
7081
- i0.ɵɵtextInterpolate1(" ", item_r2.name, " ");
7536
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.fixtureName(presetFixture_r2), " ");
7082
7537
  } }
7083
7538
  function FixtureComponent_div_12_Template(rf, ctx) { if (rf & 1) {
7084
7539
  i0.ɵɵelementStart(0, "div", 10);
@@ -7086,9 +7541,9 @@ function FixtureComponent_div_12_Template(rf, ctx) { if (rf & 1) {
7086
7541
  i0.ɵɵelementEnd();
7087
7542
  } if (rf & 2) {
7088
7543
  const ctx_r2 = i0.ɵɵnextContext();
7089
- i0.ɵɵproperty("sortablejs", ctx_r2.projectService.project.fixtures);
7544
+ i0.ɵɵproperty("sortablejs", ctx_r2.projectService.project.presetFixtures);
7090
7545
  i0.ɵɵadvance();
7091
- i0.ɵɵproperty("ngForOf", ctx_r2.projectService.project.fixtures);
7546
+ i0.ɵɵproperty("ngForOf", ctx_r2.projectService.project.presetFixtures);
7092
7547
  } }
7093
7548
  function FixtureComponent_div_13_Template(rf, ctx) { if (rf & 1) {
7094
7549
  const _r4 = i0.ɵɵgetCurrentView();
@@ -7111,15 +7566,25 @@ class FixtureComponent {
7111
7566
  this.introService = introService;
7112
7567
  }
7113
7568
  ngOnInit() { }
7114
- fixtureIsSelected(fixture) {
7569
+ fixtureName(presetFixture) {
7570
+ let name;
7571
+ name = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid).name;
7572
+ if (presetFixture.pixelKey) {
7573
+ name += ' - ' + presetFixture.pixelKey;
7574
+ }
7575
+ return name;
7576
+ }
7577
+ fixtureIsSelected(presetFixture) {
7578
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
7115
7579
  if (this.fixtureService.settingsSelection) {
7116
7580
  return this.fixtureService.settingsFixtureIsSelected(fixture);
7117
7581
  }
7118
7582
  else {
7119
- return this.presetService.fixtureIsSelected(fixture);
7583
+ return this.presetService.fixtureIsSelected(fixture, presetFixture.pixelKey);
7120
7584
  }
7121
7585
  }
7122
- selectFixture(event, fixture) {
7586
+ selectFixture(event, presetFixture) {
7587
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
7123
7588
  if (this.fixtureService.settingsSelection) {
7124
7589
  // select fixtures for the settings
7125
7590
  this.fixtureService.switchSettingsFixtureSelection(fixture);
@@ -7127,7 +7592,7 @@ class FixtureComponent {
7127
7592
  }
7128
7593
  else {
7129
7594
  // select fixtures for the current preset
7130
- this.presetService.switchFixtureSelection(fixture);
7595
+ this.presetService.switchFixtureSelection(fixture, presetFixture.pixelKey);
7131
7596
  this.presetService.fixtureSelectionChanged.next();
7132
7597
  this.presetService.previewLive();
7133
7598
  }
@@ -7168,12 +7633,12 @@ class FixtureComponent {
7168
7633
  i0.ɵɵadvance(12);
7169
7634
  i0.ɵɵproperty("ngIf", ctx.presetService.selectedPreset);
7170
7635
  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] }); }
7636
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.presetFixtures.length == 0);
7637
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
7173
7638
  }
7174
7639
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureComponent, [{
7175
7640
  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" }]
7641
+ 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
7642
  }], () => [{ type: ProjectService }, { type: PresetService }, { type: FixturePoolService }, { type: FixtureService }, { type: IntroService }], null); })();
7178
7643
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureComponent, { className: "FixtureComponent" }); })();
7179
7644
 
@@ -7307,7 +7772,7 @@ class FixtureCapabilityColorComponent {
7307
7772
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 5, "designer.fixture.capability-color"));
7308
7773
  i0.ɵɵadvance(3);
7309
7774
  i0.ɵɵtwoWayProperty("ngModel", ctx.color);
7310
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i2.TranslatePipe] }); }
7775
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
7311
7776
  }
7312
7777
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityColorComponent, [{
7313
7778
  type: Component,
@@ -7378,7 +7843,7 @@ class FixtureCapabilityDimmerComponent {
7378
7843
  i0.ɵɵproperty("ngModel", ctx.getValueText() >= 0 ? ctx.getValueText() : 0);
7379
7844
  i0.ɵɵadvance(2);
7380
7845
  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] }); }
7846
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent] }); }
7382
7847
  }
7383
7848
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityDimmerComponent, [{
7384
7849
  type: Component,
@@ -7489,7 +7954,7 @@ class FixtureCapabilityPanTiltComponent {
7489
7954
  i0.ɵɵproperty("ngModel", ctx.getValueTextTilt() >= 0 ? ctx.getValueTextTilt() : 0);
7490
7955
  i0.ɵɵadvance(2);
7491
7956
  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] }); }
7957
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
7493
7958
  }
7494
7959
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityPanTiltComponent, [{
7495
7960
  type: Component,
@@ -7682,7 +8147,7 @@ class FixtureCapabilityColorWheelComponent {
7682
8147
  i0.ɵɵproperty("ngIf", ctx.showContainer);
7683
8148
  i0.ɵɵadvance();
7684
8149
  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%}"] }); }
8150
+ } }, 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
8151
  }
7687
8152
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityColorWheelComponent, [{
7688
8153
  type: Component,
@@ -7799,8 +8264,8 @@ class FixtureCapabilityComponent {
7799
8264
  if (!this.presetService.selectedPreset) {
7800
8265
  return;
7801
8266
  }
7802
- for (const fixtureUuid of this.presetService.selectedPreset.fixtureUuids) {
7803
- const fixture = this.fixtureService.getCachedFixtureByUuid(fixtureUuid);
8267
+ for (const preserFixture of this.presetService.selectedPreset.fixtures) {
8268
+ const fixture = this.fixtureService.getCachedFixtureByUuid(preserFixture.fixtureUuid, preserFixture.pixelKey);
7804
8269
  for (const channel of fixture.channels) {
7805
8270
  for (const capability of channel.capabilities) {
7806
8271
  if (capability.wheel && capability.wheelSlots && capability.wheelSlots.length > 0) {
@@ -7841,12 +8306,12 @@ class FixtureCapabilityComponent {
7841
8306
  i0.ɵɵadvance();
7842
8307
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
7843
8308
  i0.ɵɵadvance();
7844
- i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtureUuids.length == 0);
8309
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length == 0);
7845
8310
  } }, dependencies: [i5.NgForOf, i5.NgIf, FixtureCapabilityColorComponent, FixtureCapabilityDimmerComponent, FixtureCapabilityPanTiltComponent, FixtureCapabilityColorWheelComponent, i5.KeyValuePipe, i2.TranslatePipe], changeDetection: 0 }); }
7846
8311
  }
7847
8312
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityComponent, [{
7848
8313
  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" }]
8314
+ 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
8315
  }], () => [{ type: PresetService }, { type: FixtureService }, { type: i0.ChangeDetectorRef }, { type: ProjectService }, { type: IntroService }], null); })();
7851
8316
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureCapabilityComponent, { className: "FixtureCapabilityComponent" }); })();
7852
8317
 
@@ -8196,7 +8661,7 @@ class FixtureSettingsPositionComponent {
8196
8661
  i0.ɵɵproperty("ngIf", ctx.fixtureService.selectedSettingsFixtures.length > 0);
8197
8662
  i0.ɵɵadvance();
8198
8663
  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] }); }
8664
+ } }, dependencies: [i5.NgIf, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
8200
8665
  }
8201
8666
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureSettingsPositionComponent, [{
8202
8667
  type: Component,
@@ -8338,7 +8803,7 @@ class FixtureSettingsStageComponent {
8338
8803
  i0.ɵɵproperty("tooltip", "hide")("value", ctx.projectService.project.stagePillarWidthCm)("min", 1)("max", 200)("step", 5);
8339
8804
  i0.ɵɵadvance(2);
8340
8805
  i0.ɵɵproperty("ngModel", ctx.projectService.project.stagePillarWidthCm);
8341
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent, i2.TranslatePipe] }); }
8806
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe] }); }
8342
8807
  }
8343
8808
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureSettingsStageComponent, [{
8344
8809
  type: Component,
@@ -8533,12 +8998,20 @@ class EffectCurveComponent {
8533
8998
  }
8534
8999
  getPhasingCount() {
8535
9000
  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)) {
9001
+ const countedFirstDmxChannelPixelKey = [];
9002
+ for (const presetFixture of this.presetService.selectedPreset.fixtures) {
9003
+ const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
9004
+ const firstDmxChannelAndFixtureUuid = {
9005
+ firstDmxChannel: fixture.dmxFirstChannel,
9006
+ pixelKey: presetFixture.pixelKey,
9007
+ };
9008
+ const exists = countedFirstDmxChannelPixelKey.some((item) => item.firstDmxChannel === firstDmxChannelAndFixtureUuid.firstDmxChannel &&
9009
+ ((!item.pixelKey && !firstDmxChannelAndFixtureUuid.pixelKey) || item.pixelKey === firstDmxChannelAndFixtureUuid.pixelKey));
9010
+ // don't count it, if it has the same DMX address and pixel key (if available),
9011
+ // as an already counted one
9012
+ if (!exists) {
8540
9013
  count++;
8541
- countedDmxChannels.push(fixture.dmxFirstChannel);
9014
+ countedFirstDmxChannelPixelKey.push(firstDmxChannelAndFixtureUuid);
8542
9015
  }
8543
9016
  }
8544
9017
  return count;
@@ -8919,7 +9392,7 @@ class EffectCurveComponent {
8919
9392
  i0.ɵɵproperty("ngIf", ctx.availableProfiles.length > 1);
8920
9393
  i0.ɵɵadvance();
8921
9394
  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}"] }); }
9395
+ } }, 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
9396
  }
8924
9397
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EffectCurveComponent, [{
8925
9398
  type: Component,
@@ -9301,7 +9774,7 @@ class PresetSettingsComponent {
9301
9774
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(72, 43, "designer.misc.cancel"), " ");
9302
9775
  i0.ɵɵadvance(3);
9303
9776
  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] }); }
9777
+ } }, dependencies: [i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i2.TranslatePipe] }); }
9305
9778
  }
9306
9779
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PresetSettingsComponent, [{
9307
9780
  type: Component,
@@ -9418,7 +9891,7 @@ class PresetComponent {
9418
9891
  i0.ɵɵproperty("sortablejs", ctx.projectService.project.presets);
9419
9892
  i0.ɵɵadvance();
9420
9893
  i0.ɵɵproperty("ngForOf", ctx.projectService.project.presets);
9421
- } }, dependencies: [i5.NgForOf, i4$1.CheckboxControlValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
9894
+ } }, dependencies: [i5.NgForOf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, i8.SortablejsDirective, i2.TranslatePipe] }); }
9422
9895
  }
9423
9896
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PresetComponent, [{
9424
9897
  type: Component,
@@ -9476,7 +9949,7 @@ class MasterDimmerComponent {
9476
9949
  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
9950
  i0.ɵɵadvance(2);
9478
9951
  i0.ɵɵproperty("ngModel", ctx.getValue());
9479
- } }, dependencies: [i4$1.DefaultValueAccessor, i4$1.NgControlStatus, i4$1.NgModel, i4$2.SliderComponent] }); }
9952
+ } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent] }); }
9480
9953
  }
9481
9954
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MasterDimmerComponent, [{
9482
9955
  type: Component,
@@ -9679,7 +10152,7 @@ class FixtureCapabilityChannelComponent {
9679
10152
  i0.ɵɵproperty("ngIf", (ctx._channel.capabilities == null ? null : ctx._channel.capabilities.length) > 1);
9680
10153
  i0.ɵɵadvance();
9681
10154
  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 }); }
10155
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.RadioControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe], changeDetection: 0 }); }
9683
10156
  }
9684
10157
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityChannelComponent, [{
9685
10158
  type: Component,
@@ -9795,7 +10268,9 @@ class FixtureChannelComponent {
9795
10268
  this.calculateProfiles();
9796
10269
  });
9797
10270
  }
9798
- ngOnInit() { }
10271
+ ngOnInit() {
10272
+ this.calculateProfiles();
10273
+ }
9799
10274
  ngOnDestroy() {
9800
10275
  this.fixtureSelectionChangedSubscription.unsubscribe();
9801
10276
  this.previewSelectionChangedSubscription.unsubscribe();
@@ -9837,12 +10312,12 @@ class FixtureChannelComponent {
9837
10312
  i0.ɵɵadvance();
9838
10313
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
9839
10314
  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] }); }
10315
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length == 0);
10316
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.CheckboxControlValueAccessor, i4.NgControlStatus, i4.NgModel, FixtureCapabilityChannelComponent, i5.KeyValuePipe, i2.TranslatePipe] }); }
9842
10317
  }
9843
10318
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureChannelComponent, [{
9844
10319
  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" }]
10320
+ 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
10321
  }], () => [{ type: PresetService }, { type: i0.ChangeDetectorRef }, { type: ProjectService }], null); })();
9847
10322
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureChannelComponent, { className: "FixtureChannelComponent" }); })();
9848
10323
 
@@ -9938,9 +10413,9 @@ class IntroComponent {
9938
10413
  const _c0 = a0 => ({ height: a0 });
9939
10414
  function DesignerComponent_li_52_Template(rf, ctx) { if (rf & 1) {
9940
10415
  const _r1 = i0.ɵɵgetCurrentView();
9941
- i0.ɵɵelementStart(0, "li", 54)(1, "a", 55);
10416
+ i0.ɵɵelementStart(0, "li", 38)(1, "a", 39);
9942
10417
  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);
10418
+ i0.ɵɵelement(2, "i", 40);
9944
10419
  i0.ɵɵtext(3);
9945
10420
  i0.ɵɵpipe(4, "translate");
9946
10421
  i0.ɵɵelementEnd()();
@@ -9951,15 +10426,15 @@ function DesignerComponent_li_52_Template(rf, ctx) { if (rf & 1) {
9951
10426
  function DesignerComponent_li_53_Template(rf, ctx) { if (rf & 1) {
9952
10427
  const _r3 = i0.ɵɵgetCurrentView();
9953
10428
  i0.ɵɵelementStart(0, "li", 3)(1, "a", 14);
9954
- i0.ɵɵelement(2, "i", 57);
10429
+ i0.ɵɵelement(2, "i", 41);
9955
10430
  i0.ɵɵtext(3);
9956
10431
  i0.ɵɵpipe(4, "translate");
9957
10432
  i0.ɵɵelementEnd();
9958
- i0.ɵɵelementStart(5, "div", 58)(6, "a", 59);
10433
+ i0.ɵɵelementStart(5, "div", 42)(6, "a", 43);
9959
10434
  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
10435
  i0.ɵɵtext(7, "English");
9961
10436
  i0.ɵɵelementEnd();
9962
- i0.ɵɵelementStart(8, "a", 59);
10437
+ i0.ɵɵelementStart(8, "a", 43);
9963
10438
  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
10439
  i0.ɵɵtext(9, "Deutsch");
9965
10440
  i0.ɵɵelementEnd()()();
@@ -9969,9 +10444,9 @@ function DesignerComponent_li_53_Template(rf, ctx) { if (rf & 1) {
9969
10444
  } }
9970
10445
  function DesignerComponent_li_54_Template(rf, ctx) { if (rf & 1) {
9971
10446
  const _r4 = i0.ɵɵgetCurrentView();
9972
- i0.ɵɵelementStart(0, "li", 60)(1, "a", 61);
10447
+ i0.ɵɵelementStart(0, "li", 44)(1, "a", 45);
9973
10448
  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);
10449
+ i0.ɵɵelement(2, "i", 46);
9975
10450
  i0.ɵɵtext(3);
9976
10451
  i0.ɵɵpipe(4, "translate");
9977
10452
  i0.ɵɵelementEnd()();
@@ -9982,12 +10457,12 @@ function DesignerComponent_li_54_Template(rf, ctx) { if (rf & 1) {
9982
10457
  function DesignerComponent_li_55_Template(rf, ctx) { if (rf & 1) {
9983
10458
  const _r5 = i0.ɵɵgetCurrentView();
9984
10459
  i0.ɵɵelementStart(0, "li", 3)(1, "a", 14);
9985
- i0.ɵɵelement(2, "i", 62);
10460
+ i0.ɵɵelement(2, "i", 46);
9986
10461
  i0.ɵɵtext(3);
9987
10462
  i0.ɵɵelementEnd();
9988
- i0.ɵɵelementStart(4, "div", 58)(5, "a", 59);
10463
+ i0.ɵɵelementStart(4, "div", 42)(5, "a", 43);
9989
10464
  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);
10465
+ i0.ɵɵelement(6, "i", 47);
9991
10466
  i0.ɵɵtext(7);
9992
10467
  i0.ɵɵpipe(8, "translate");
9993
10468
  i0.ɵɵelementEnd()()();
@@ -9998,6 +10473,81 @@ function DesignerComponent_li_55_Template(rf, ctx) { if (rf & 1) {
9998
10473
  i0.ɵɵadvance(4);
9999
10474
  i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(8, 2, "designer.navigation.logout"), "");
10000
10475
  } }
10476
+ function DesignerComponent_lib_app_scene_59_Template(rf, ctx) { if (rf & 1) {
10477
+ i0.ɵɵelement(0, "lib-app-scene");
10478
+ } }
10479
+ function DesignerComponent_lib_app_preset_61_Template(rf, ctx) { if (rf & 1) {
10480
+ i0.ɵɵelement(0, "lib-app-preset");
10481
+ } }
10482
+ function DesignerComponent_div_63_Template(rf, ctx) { if (rf & 1) {
10483
+ i0.ɵɵelementStart(0, "div", 48)(1, "div", 49);
10484
+ i0.ɵɵelement(2, "lib-app-preview", 50);
10485
+ i0.ɵɵelementEnd()();
10486
+ } if (rf & 2) {
10487
+ const ctx_r1 = i0.ɵɵnextContext();
10488
+ i0.ɵɵclassProp("card-intro-active", ctx_r1.introService.showStep("preview"));
10489
+ } }
10490
+ function DesignerComponent_div_65_Template(rf, ctx) { if (rf & 1) {
10491
+ const _r6 = i0.ɵɵgetCurrentView();
10492
+ i0.ɵɵelementStart(0, "div", 51)(1, "div", 52)(2, "a", 53);
10493
+ i0.ɵɵpipe(3, "translate");
10494
+ 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")); });
10495
+ i0.ɵɵelement(4, "i", 54);
10496
+ i0.ɵɵelementEnd();
10497
+ i0.ɵɵelementStart(5, "a", 55);
10498
+ i0.ɵɵpipe(6, "translate");
10499
+ 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")); });
10500
+ i0.ɵɵelement(7, "i", 56);
10501
+ i0.ɵɵelementEnd();
10502
+ i0.ɵɵelementStart(8, "a", 57);
10503
+ i0.ɵɵpipe(9, "translate");
10504
+ 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")); });
10505
+ i0.ɵɵelement(10, "i", 58);
10506
+ i0.ɵɵelementEnd();
10507
+ i0.ɵɵelementStart(11, "a", 59);
10508
+ i0.ɵɵpipe(12, "translate");
10509
+ 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")); });
10510
+ i0.ɵɵelement(13, "i", 60);
10511
+ i0.ɵɵelementEnd()()();
10512
+ } if (rf & 2) {
10513
+ i0.ɵɵadvance(2);
10514
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(3, 4, "designer.misc.capabilities"));
10515
+ i0.ɵɵadvance(3);
10516
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(6, 6, "designer.misc.channels"));
10517
+ i0.ɵɵadvance(3);
10518
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(9, 8, "designer.misc.effects"));
10519
+ i0.ɵɵadvance(3);
10520
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(12, 10, "designer.misc.settings"));
10521
+ } }
10522
+ function DesignerComponent_div_67_Template(rf, ctx) { if (rf & 1) {
10523
+ i0.ɵɵelementStart(0, "div", 61)(1, "div", 62)(2, "div", 63)(3, "div", 64);
10524
+ i0.ɵɵelement(4, "lib-app-fixture-capability");
10525
+ i0.ɵɵelementEnd();
10526
+ i0.ɵɵelementStart(5, "div", 65);
10527
+ i0.ɵɵelement(6, "lib-app-fixture-channel");
10528
+ i0.ɵɵelementEnd();
10529
+ i0.ɵɵelementStart(7, "div", 66);
10530
+ i0.ɵɵelement(8, "lib-app-effect");
10531
+ i0.ɵɵelementEnd();
10532
+ i0.ɵɵelementStart(9, "div", 67);
10533
+ i0.ɵɵelement(10, "lib-app-fixture-settings");
10534
+ i0.ɵɵelementEnd()()()();
10535
+ } }
10536
+ function DesignerComponent_lib_app_fixture_69_Template(rf, ctx) { if (rf & 1) {
10537
+ i0.ɵɵelement(0, "lib-app-fixture");
10538
+ } }
10539
+ function DesignerComponent_lib_app_master_dimmer_71_Template(rf, ctx) { if (rf & 1) {
10540
+ i0.ɵɵelement(0, "lib-app-master-dimmer");
10541
+ } }
10542
+ function DesignerComponent_lib_app_timeline_73_Template(rf, ctx) { if (rf & 1) {
10543
+ i0.ɵɵelement(0, "lib-app-timeline");
10544
+ } }
10545
+ function DesignerComponent_lib_app_master_dimmer_76_Template(rf, ctx) { if (rf & 1) {
10546
+ i0.ɵɵelement(0, "lib-app-master-dimmer");
10547
+ } }
10548
+ function DesignerComponent_lib_app_scene_78_Template(rf, ctx) { if (rf & 1) {
10549
+ i0.ɵɵelement(0, "lib-app-scene");
10550
+ } }
10001
10551
  class DesignerComponent {
10002
10552
  set menuHeightPx(value) {
10003
10553
  this.configService.menuHeightPx = value;
@@ -10037,7 +10587,10 @@ class DesignerComponent {
10037
10587
  set uniqueProjectNames(value) {
10038
10588
  this.configService.uniqueProjectNames = value;
10039
10589
  }
10040
- constructor(translateService, projectService, configService, fixturePoolService, hotkeyTargetExcludeService, modalService, userService, userEnsureLoginService, toastrService, projectLoadService, warningDialogService, errorDialogService, fixtureService, timelineService, introService) {
10590
+ set dropzoneChunking(value) {
10591
+ this.configService.dropzoneChunking = value;
10592
+ }
10593
+ constructor(translateService, projectService, configService, fixturePoolService, hotkeyTargetExcludeService, modalService, userService, userEnsureLoginService, projectLoadService, warningDialogService, errorDialogService, fixtureService, timelineService, introService) {
10041
10594
  this.translateService = translateService;
10042
10595
  this.projectService = projectService;
10043
10596
  this.configService = configService;
@@ -10046,7 +10599,6 @@ class DesignerComponent {
10046
10599
  this.modalService = modalService;
10047
10600
  this.userService = userService;
10048
10601
  this.userEnsureLoginService = userEnsureLoginService;
10049
- this.toastrService = toastrService;
10050
10602
  this.projectLoadService = projectLoadService;
10051
10603
  this.warningDialogService = warningDialogService;
10052
10604
  this.errorDialogService = errorDialogService;
@@ -10062,6 +10614,27 @@ class DesignerComponent {
10062
10614
  this.calcTotalMenuHeight();
10063
10615
  });
10064
10616
  }
10617
+ loadError(response) {
10618
+ console.error(response);
10619
+ let msg = 'designer.project.open-error';
10620
+ let error;
10621
+ if (response instanceof HttpErrorResponse) {
10622
+ error = response && response.error ? response.error.error : 'unknown';
10623
+ if (error === 'no-permission') {
10624
+ msg = 'designer.project.open-no-permission-error';
10625
+ error = undefined;
10626
+ }
10627
+ else {
10628
+ msg = 'designer.project.open-error';
10629
+ }
10630
+ }
10631
+ else {
10632
+ error = response && response.message ? response.message : 'unknown';
10633
+ }
10634
+ this.errorDialogService.show(msg, error).subscribe(() => {
10635
+ this.projectLoadService.new();
10636
+ });
10637
+ }
10065
10638
  ngOnInit() {
10066
10639
  if (localStorage.getItem('language')) {
10067
10640
  this.translateService.use(localStorage.getItem('language'));
@@ -10080,29 +10653,14 @@ class DesignerComponent {
10080
10653
  shareToken = '';
10081
10654
  }
10082
10655
  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
- });
10656
+ this.loadError(response);
10095
10657
  });
10096
10658
  }
10097
10659
  else if ((this.userService.isLoggedIn() || !this.configService.loginAvailable) &&
10098
10660
  (this.userService.getAutoLoadProjectId() || this.userService.getAutoLoadProjectName())) {
10099
10661
  // restore the last saved project
10100
10662
  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
- });
10663
+ this.loadError(response);
10106
10664
  });
10107
10665
  }
10108
10666
  else {
@@ -10130,7 +10688,7 @@ class DesignerComponent {
10130
10688
  // Set up the splitter
10131
10689
  setTimeout(() => {
10132
10690
  Split(['#row1', '#row2', '#row3'], {
10133
- sizes: [42, 38, 20],
10691
+ sizes: [42, 40, 18],
10134
10692
  direction: 'vertical',
10135
10693
  cursor: 'row-resize',
10136
10694
  snapOffset: 0,
@@ -10138,13 +10696,13 @@ class DesignerComponent {
10138
10696
  onDrag: this.onResize.bind(this),
10139
10697
  });
10140
10698
  Split(['#scenes', '#presets', '#preview'], {
10141
- sizes: [15, 15, 70],
10699
+ sizes: [20, 20, 60],
10142
10700
  snapOffset: 0,
10143
10701
  gutterSize: this.splitGutterSizePx,
10144
10702
  onDrag: this.onResize.bind(this),
10145
10703
  });
10146
10704
  Split(['#capabilities', '#fixtures', '#masterDimmer'], {
10147
- sizes: [74, 18, 8],
10705
+ sizes: [70, 24, 6],
10148
10706
  snapOffset: 0,
10149
10707
  gutterSize: this.splitGutterSizePx,
10150
10708
  onDrag: this.onResize.bind(this),
@@ -10267,7 +10825,7 @@ class DesignerComponent {
10267
10825
  this.translateService.use(language);
10268
10826
  localStorage.setItem('language', language);
10269
10827
  }
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)); }; }
10828
+ 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
10829
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DesignerComponent, selectors: [["lib-designer"]], viewQuery: function DesignerComponent_Query(rf, ctx) { if (rf & 1) {
10272
10830
  i0.ɵɵviewQuery(PreviewComponent, 5);
10273
10831
  i0.ɵɵviewQuery(TimelineComponent, 5);
@@ -10277,7 +10835,7 @@ class DesignerComponent {
10277
10835
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.timelineComponent = _t.first);
10278
10836
  } }, hostBindings: function DesignerComponent_HostBindings(rf, ctx) { if (rf & 1) {
10279
10837
  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) {
10838
+ } }, 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
10839
  i0.ɵɵelementStart(0, "div", 0)(1, "nav", 1)(2, "ul", 2)(3, "li", 3)(4, "a", 4);
10282
10840
  i0.ɵɵtext(5);
10283
10841
  i0.ɵɵpipe(6, "translate");
@@ -10344,88 +10902,61 @@ class DesignerComponent {
10344
10902
  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
10903
  i0.ɵɵelementEnd()();
10346
10904
  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");
10905
+ i0.ɵɵtemplate(59, DesignerComponent_lib_app_scene_59_Template, 1, 0, "lib-app-scene", 24);
10377
10906
  i0.ɵɵelementEnd();
10378
- i0.ɵɵelementStart(87, "div", 45);
10379
- i0.ɵɵelement(88, "lib-app-fixture-channel");
10907
+ i0.ɵɵelementStart(60, "div", 25);
10908
+ i0.ɵɵtemplate(61, DesignerComponent_lib_app_preset_61_Template, 1, 0, "lib-app-preset", 24);
10380
10909
  i0.ɵɵelementEnd();
10381
- i0.ɵɵelementStart(89, "div", 46);
10382
- i0.ɵɵelement(90, "lib-app-effect");
10910
+ i0.ɵɵelementStart(62, "div", 26);
10911
+ i0.ɵɵtemplate(63, DesignerComponent_div_63_Template, 3, 2, "div", 27);
10912
+ i0.ɵɵelementEnd()();
10913
+ i0.ɵɵelementStart(64, "div", 28);
10914
+ i0.ɵɵtemplate(65, DesignerComponent_div_65_Template, 14, 12, "div", 29);
10915
+ i0.ɵɵelementStart(66, "div", 30);
10916
+ i0.ɵɵtemplate(67, DesignerComponent_div_67_Template, 11, 0, "div", 31);
10383
10917
  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");
10918
+ i0.ɵɵelementStart(68, "div", 32);
10919
+ i0.ɵɵtemplate(69, DesignerComponent_lib_app_fixture_69_Template, 1, 0, "lib-app-fixture", 24);
10389
10920
  i0.ɵɵelementEnd();
10390
- i0.ɵɵelementStart(95, "div", 49);
10391
- i0.ɵɵelement(96, "lib-app-master-dimmer");
10921
+ i0.ɵɵelementStart(70, "div", 33);
10922
+ i0.ɵɵtemplate(71, DesignerComponent_lib_app_master_dimmer_71_Template, 1, 0, "lib-app-master-dimmer", 24);
10392
10923
  i0.ɵɵelementEnd()();
10393
- i0.ɵɵelementStart(97, "div", 50);
10394
- i0.ɵɵelement(98, "lib-app-timeline");
10924
+ i0.ɵɵelementStart(72, "div", 34);
10925
+ i0.ɵɵtemplate(73, DesignerComponent_lib_app_timeline_73_Template, 1, 0, "lib-app-timeline", 24);
10395
10926
  i0.ɵɵelementEnd()();
10396
- i0.ɵɵelementStart(99, "div", 51)(100, "div");
10397
- i0.ɵɵelement(101, "lib-app-master-dimmer");
10927
+ i0.ɵɵelementStart(74, "div", 35)(75, "div");
10928
+ i0.ɵɵtemplate(76, DesignerComponent_lib_app_master_dimmer_76_Template, 1, 0, "lib-app-master-dimmer", 24);
10398
10929
  i0.ɵɵelementEnd();
10399
- i0.ɵɵelementStart(102, "div", 52);
10400
- i0.ɵɵelement(103, "lib-app-scene");
10930
+ i0.ɵɵelementStart(77, "div", 36);
10931
+ i0.ɵɵtemplate(78, DesignerComponent_lib_app_scene_78_Template, 1, 0, "lib-app-scene", 24);
10401
10932
  i0.ɵɵelementEnd()()();
10402
- i0.ɵɵelement(104, "lib-app-intro", 53);
10933
+ i0.ɵɵelement(79, "lib-app-intro", 37);
10403
10934
  } if (rf & 2) {
10404
- i0.ɵɵproperty("ngStyle", i0.ɵɵpureFunction1(55, _c0, "calc(100% - " + ctx.totalMenuHeightPx + "px)"));
10935
+ i0.ɵɵproperty("ngStyle", i0.ɵɵpureFunction1(51, _c0, "calc(100% - " + ctx.totalMenuHeightPx + "px)"));
10405
10936
  i0.ɵɵadvance(5);
10406
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(6, 23, "designer.navigation.project"), " ");
10937
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(6, 27, "designer.navigation.project"), " ");
10407
10938
  i0.ɵɵadvance(5);
10408
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(11, 25, "designer.navigation.project-new"), "");
10939
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(11, 29, "designer.navigation.project-new"), "");
10409
10940
  i0.ɵɵadvance(4);
10410
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(15, 27, "designer.navigation.project-open"), "");
10941
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(15, 31, "designer.navigation.project-open"), "");
10411
10942
  i0.ɵɵadvance(4);
10412
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(19, 29, "designer.navigation.project-save"), "");
10943
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(19, 33, "designer.navigation.project-save"), "");
10413
10944
  i0.ɵɵadvance(4);
10414
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(23, 31, "designer.navigation.project-save-as"), "");
10945
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(23, 35, "designer.navigation.project-save-as"), "");
10415
10946
  i0.ɵɵadvance(4);
10416
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(27, 33, "designer.navigation.project-import"), "");
10947
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(27, 37, "designer.navigation.project-import"), "");
10417
10948
  i0.ɵɵadvance(4);
10418
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(31, 35, "designer.navigation.project-export"), "");
10949
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(31, 39, "designer.navigation.project-export"), "");
10419
10950
  i0.ɵɵadvance(4);
10420
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 37, "designer.navigation.settings"), " ");
10951
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(35, 41, "designer.navigation.settings"), " ");
10421
10952
  i0.ɵɵadvance(4);
10422
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(39, 39, "designer.navigation.fixture-pool"));
10953
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(39, 43, "designer.navigation.fixture-pool"));
10423
10954
  i0.ɵɵadvance(4);
10424
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(43, 41, "designer.navigation.help"), " ");
10955
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(43, 45, "designer.navigation.help"), " ");
10425
10956
  i0.ɵɵadvance(4);
10426
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(47, 43, "designer.navigation.reset-intro"));
10957
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(47, 47, "designer.navigation.reset-intro"));
10427
10958
  i0.ɵɵadvance(3);
10428
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(50, 45, "designer.navigation.support"));
10959
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(50, 49, "designer.navigation.support"));
10429
10960
  i0.ɵɵadvance(3);
10430
10961
  i0.ɵɵproperty("ngIf", ctx.configService.shareAvailable);
10431
10962
  i0.ɵɵadvance();
@@ -10434,22 +10965,32 @@ class DesignerComponent {
10434
10965
  i0.ɵɵproperty("ngIf", ctx.configService.loginAvailable && !ctx.userService.isLoggedIn());
10435
10966
  i0.ɵɵadvance();
10436
10967
  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"));
10968
+ i0.ɵɵadvance(4);
10969
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10970
+ i0.ɵɵadvance(2);
10971
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10972
+ i0.ɵɵadvance(2);
10973
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10974
+ i0.ɵɵadvance(2);
10975
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10976
+ i0.ɵɵadvance(2);
10977
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10978
+ i0.ɵɵadvance(2);
10979
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10980
+ i0.ɵɵadvance(2);
10981
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10982
+ i0.ɵɵadvance(2);
10983
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10445
10984
  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 }); }
10985
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10986
+ i0.ɵɵadvance(2);
10987
+ i0.ɵɵproperty("ngIf", ctx.projectService.project);
10988
+ } }, 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
10989
  }
10449
10990
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DesignerComponent, [{
10450
10991
  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: [{
10992
+ 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"] }]
10993
+ }], () => [{ 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
10994
  type: Input
10454
10995
  }], externalCompositionsAvailable: [{
10455
10996
  type: Input
@@ -10473,6 +11014,8 @@ class DesignerComponent {
10473
11014
  type: Input
10474
11015
  }], uniqueProjectNames: [{
10475
11016
  type: Input
11017
+ }], dropzoneChunking: [{
11018
+ type: Input
10476
11019
  }], previewComponent: [{
10477
11020
  type: ViewChild,
10478
11021
  args: [PreviewComponent]
@@ -10545,6 +11088,7 @@ class DesignerModule {
10545
11088
  SceneSettingsComponent,
10546
11089
  ProjectSaveComponent,
10547
11090
  FixturePoolCreateFromFileComponent,
11091
+ DropzoneComponent,
10548
11092
  ],
10549
11093
  imports: [
10550
11094
  RouterModule.forRoot([], {}),
@@ -10602,7 +11146,8 @@ class DesignerModule {
10602
11146
  PresetSettingsComponent,
10603
11147
  SceneSettingsComponent,
10604
11148
  ProjectSaveComponent,
10605
- FixturePoolCreateFromFileComponent], imports: [i4.RouterModule, BrowserModule,
11149
+ FixturePoolCreateFromFileComponent,
11150
+ DropzoneComponent], imports: [i3.RouterModule, BrowserModule,
10606
11151
  BrowserAnimationsModule,
10607
11152
  HttpClientModule,
10608
11153
  FormsModule,
@@ -10612,7 +11157,7 @@ class DesignerModule {
10612
11157
  PopoverModule,
10613
11158
  TypeaheadModule,
10614
11159
  SortablejsModule,
10615
- DropzoneModule, i3.ToastrModule], exports: [DesignerComponent] }); })();
11160
+ DropzoneModule, i3$1.ToastrModule], exports: [DesignerComponent] }); })();
10616
11161
 
10617
11162
  /*
10618
11163
  * Public API Surface of designer