@rocketshow/designer 1.36.0 → 1.38.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 (26) hide show
  1. package/assets/i18n/de.json +11 -8
  2. package/assets/i18n/en.json +11 -8
  3. package/esm2022/lib/designer.component.mjs +10 -10
  4. package/esm2022/lib/fixture/fixture-capability/fixture-capability-channel/fixture-capability-channel.component.mjs +181 -33
  5. package/esm2022/lib/fixture/fixture-capability/fixture-capability.component.mjs +30 -8
  6. package/esm2022/lib/models/fixture-capability.mjs +47 -4
  7. package/esm2022/lib/preview/models/color-changer-3d.mjs +15 -27
  8. package/esm2022/lib/preview/models/fixture-3d.mjs +91 -105
  9. package/esm2022/lib/preview/models/moving-head-3d.mjs +32 -41
  10. package/esm2022/lib/preview/preview.component.mjs +4 -4
  11. package/esm2022/lib/services/fixture.service.mjs +1 -1
  12. package/esm2022/lib/services/preset.service.mjs +3 -3
  13. package/esm2022/lib/services/preview.service.mjs +19 -3
  14. package/esm2022/lib/user/user-register/user-register.component.mjs +3 -3
  15. package/fesm2022/rocketshow-designer.mjs +422 -229
  16. package/fesm2022/rocketshow-designer.mjs.map +1 -1
  17. package/lib/fixture/fixture-capability/fixture-capability-channel/fixture-capability-channel.component.d.ts +9 -2
  18. package/lib/fixture/fixture-capability/fixture-capability.component.d.ts +5 -1
  19. package/lib/models/fixture-capability.d.ts +47 -4
  20. package/lib/preview/models/color-changer-3d.d.ts +4 -5
  21. package/lib/preview/models/fixture-3d.d.ts +17 -16
  22. package/lib/preview/models/moving-head-3d.d.ts +4 -5
  23. package/lib/services/preview.service.d.ts +5 -1
  24. package/package.json +1 -1
  25. package/rocketshow-designer-1.38.0.tgz +0 -0
  26. package/rocketshow-designer-1.36.0.tgz +0 -0
@@ -119,18 +119,61 @@ class FixtureCapability {
119
119
  return;
120
120
  }
121
121
  this.type = FixtureCapabilityType[data.type];
122
- this.angleStart = data.angleStart;
123
- this.angleEnd = data.angleEnd;
124
122
  this.color = data.color;
125
123
  if (data.dmxRange) {
126
124
  this.dmxRange = data.dmxRange;
127
125
  }
128
126
  this.wheel = data.wheel;
129
127
  this.slotNumber = data.slotNumber;
128
+ this.comment = data.comment;
129
+ this.soundControlled = data.soundControlled;
130
+ this.shutterEffect = data.shutterEffect;
131
+ this.randomTiming = data.randomTiming;
132
+ this.angle = data.angle;
133
+ this.angleStart = data.angleStart;
134
+ this.angleEnd = data.angleEnd;
135
+ this.speed = data.speed;
136
+ this.speedStart = data.speedStart;
137
+ this.speedEnd = data.speedEnd;
130
138
  this.brightness = data.brightness;
131
139
  this.brightnessStart = data.brightnessStart;
132
140
  this.brightnessEnd = data.brightnessEnd;
133
- this.comment = data.comment;
141
+ this.duration = data.duration;
142
+ this.durationStart = data.durationStart;
143
+ this.durationEnd = data.durationEnd;
144
+ this.colorTemperature = data.colorTemperature;
145
+ this.colorTemperatureStart = data.colorTemperatureStart;
146
+ this.colorTemperatureEnd = data.colorTemperatureEnd;
147
+ this.soundSensitivity = data.soundSensitivity;
148
+ this.soundSensitivityStart = data.soundSensitivityStart;
149
+ this.soundSensitivityEnd = data.soundSensitivityEnd;
150
+ this.horizontalAngle = data.horizontalAngle;
151
+ this.horizontalAngleStart = data.horizontalAngleStart;
152
+ this.horizontalAngleEnd = data.horizontalAngleEnd;
153
+ this.verticalAngle = data.verticalAngle;
154
+ this.verticalAngleStart = data.verticalAngleStart;
155
+ this.verticalAngleEnd = data.verticalAngleEnd;
156
+ this.distance = data.distance;
157
+ this.distanceStart = data.distanceStart;
158
+ this.distanceEnd = data.distanceEnd;
159
+ this.openPercent = data.openPercent;
160
+ this.openPercentStart = data.openPercentStart;
161
+ this.openPercentEnd = data.openPercentEnd;
162
+ this.frostIntensity = data.frostIntensity;
163
+ this.frostIntensityStart = data.frostIntensityStart;
164
+ this.frostIntensityEnd = data.frostIntensityEnd;
165
+ this.fogOutput = data.fogOutput;
166
+ this.fogOutputStart = data.fogOutputStart;
167
+ this.fogOutputEnd = data.fogOutputEnd;
168
+ this.time = data.time;
169
+ this.timeStart = data.timeStart;
170
+ this.timeEnd = data.timeEnd;
171
+ this.insertion = data.insertion;
172
+ this.insertionStart = data.insertionStart;
173
+ this.insertionEnd = data.insertionEnd;
174
+ this.colors = data.colors;
175
+ this.colorsStart = data.colorsStart;
176
+ this.colorsEnd = data.colorsEnd;
134
177
  }
135
178
  }
136
179
 
@@ -2031,8 +2074,8 @@ class PresetService {
2031
2074
  }
2032
2075
  hasCapabilityType(type) {
2033
2076
  // there is at least one channel with at least one intensity capability
2034
- for (const projectFixture of this.selectedPreset.fixtures) {
2035
- const fixture = this.fixtureService.getCachedFixtureByUuid(projectFixture.fixtureUuid, projectFixture.pixelKey);
2077
+ for (const presetFixture of this.selectedPreset.fixtures) {
2078
+ const fixture = this.fixtureService.getCachedFixtureByUuid(presetFixture.fixtureUuid, presetFixture.pixelKey);
2036
2079
  for (const channel of fixture.channels) {
2037
2080
  if (channel.channel) {
2038
2081
  for (const capability of channel.capabilities) {
@@ -3092,6 +3135,14 @@ class PreviewService {
3092
3135
  // roughness: 0.5,
3093
3136
  // metalness: 0.5,
3094
3137
  });
3138
+ this.fixtureMaterial = new THREE.MeshLambertMaterial({
3139
+ color: 0x0d0d0d,
3140
+ emissive: 0x0d0d0d,
3141
+ });
3142
+ this.fixtureSelectedMaterial = new THREE.MeshLambertMaterial({
3143
+ color: 0xff00ff,
3144
+ emissive: 0xff00ff,
3145
+ });
3095
3146
  }
3096
3147
  getAlreadyCalculatedFixture(fixtures, fixtureIndex) {
3097
3148
  // Has this fixture already been calculated (same universe and dmx start address as a fixture before)
@@ -3350,6 +3401,10 @@ class PreviewService {
3350
3401
  }
3351
3402
  }
3352
3403
  mixEffects(timeMillis, fixtureIndex, preset, cachedFixture, values, intensityPercentage) {
3404
+ let effectTimeMillis = timeMillis;
3405
+ if (preset.region) {
3406
+ effectTimeMillis = timeMillis - preset.region.startMillis;
3407
+ }
3353
3408
  for (const effect of preset.preset.effects) {
3354
3409
  if (effect.visible) {
3355
3410
  // EffectCurve
@@ -3363,7 +3418,7 @@ class PreviewService {
3363
3418
  const fixtureChannelValue = new FixtureChannelValue();
3364
3419
  fixtureChannelValue.channelName = cachedChannel.name;
3365
3420
  fixtureChannelValue.profileUuid = cachedFixture.profile.uuid;
3366
- fixtureChannelValue.value = cachedChannel.maxValue * effectCurve.getValueAtMillis(timeMillis, fixtureIndex);
3421
+ fixtureChannelValue.value = cachedChannel.maxValue * effectCurve.getValueAtMillis(effectTimeMillis, fixtureIndex);
3367
3422
  this.mixChannelValue(values, fixtureChannelValue, intensityPercentage);
3368
3423
  }
3369
3424
  }
@@ -3378,7 +3433,7 @@ class PreviewService {
3378
3433
  const fixtureChannelValue = new FixtureChannelValue();
3379
3434
  fixtureChannelValue.channelName = cachedChannel.name;
3380
3435
  fixtureChannelValue.profileUuid = cachedFixture.profile.uuid;
3381
- fixtureChannelValue.value = cachedChannel.maxValue * effectCurve.getValueAtMillis(timeMillis, fixtureIndex);
3436
+ fixtureChannelValue.value = cachedChannel.maxValue * effectCurve.getValueAtMillis(effectTimeMillis, fixtureIndex);
3382
3437
  this.mixChannelValue(values, fixtureChannelValue, intensityPercentage);
3383
3438
  }
3384
3439
  }
@@ -3515,6 +3570,10 @@ class PreviewService {
3515
3570
  this.scene.add(mesh);
3516
3571
  this.stageMeshes.push(mesh);
3517
3572
  }
3573
+ ngOnDestroy() {
3574
+ this.fixtureMaterial.dispose();
3575
+ this.fixtureSelectedMaterial.dispose();
3576
+ }
3518
3577
  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)); }; }
3519
3578
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PreviewService, factory: PreviewService.ɵfac, providedIn: 'root' }); }
3520
3579
  }
@@ -3526,8 +3585,9 @@ class PreviewService {
3526
3585
  }], () => [{ type: PresetService }, { type: FixtureService }, { type: SceneService }, { type: TimelineService }, { type: ProjectService }], null); })();
3527
3586
 
3528
3587
  class Fixture3d {
3529
- constructor(fixtureService, fixture, scene) {
3588
+ constructor(fixtureService, previewService, fixture, scene, hasSpotLight = false) {
3530
3589
  this.fixtureService = fixtureService;
3590
+ this.previewService = previewService;
3531
3591
  this.pointLightMaxIntensity = 2;
3532
3592
  this.spotLightLightMaxIntensity = 10;
3533
3593
  this.fixtureHasDimmer = false;
@@ -3536,13 +3596,10 @@ class Fixture3d {
3536
3596
  this.dimmer = 0;
3537
3597
  this.isSelected = false;
3538
3598
  this.isLoaded = false;
3599
+ this.hasSpotLight = false;
3539
3600
  this.fixture = fixture;
3540
3601
  this.scene = scene;
3541
- // TODO Don't create it for each fixture but pass it from the preview service
3542
- this.selectedMaterial = new THREE.MeshLambertMaterial({
3543
- color: 0xff00ff,
3544
- emissive: 0xff00ff,
3545
- });
3602
+ this.hasSpotLight = hasSpotLight;
3546
3603
  // evaluate, various capabilities of this fixture
3547
3604
  for (const cachedChannel of this.fixture.channels) {
3548
3605
  if (cachedChannel.channel) {
@@ -3562,28 +3619,88 @@ class Fixture3d {
3562
3619
  }
3563
3620
  }
3564
3621
  }
3622
+ createSpotlightMaterial() {
3623
+ const vertexShader = `
3624
+ varying vec3 vNormal;
3625
+ varying vec3 vWorldPosition;
3626
+
3627
+ void main(){
3628
+ vNormal = normalize(normalMatrix * normal);
3629
+
3630
+ vec4 worldPosition = modelMatrix * vec4(position, 1.0);
3631
+ vWorldPosition = worldPosition.xyz;
3632
+
3633
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
3634
+ }`;
3635
+ const fragmentShader = `
3636
+ varying vec3 vNormal;
3637
+ varying vec3 vWorldPosition;
3638
+
3639
+ uniform vec3 lightColor;
3640
+ uniform float opacity;
3641
+ uniform vec3 spotPosition;
3642
+ uniform float attenuation;
3643
+ uniform float anglePower;
3644
+
3645
+ void main(){
3646
+ float intensity;
3647
+
3648
+ intensity = distance(vWorldPosition, spotPosition) / attenuation;
3649
+ intensity = 1.0 - clamp(intensity, 0.0, 1.0);
3650
+
3651
+ vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
3652
+ float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
3653
+ intensity = intensity * angleIntensity * opacity;
3654
+
3655
+ gl_FragColor = vec4(lightColor, intensity);
3656
+ }`;
3657
+ this.spotlightMaterial = new THREE.ShaderMaterial({
3658
+ uniforms: {
3659
+ attenuation: {
3660
+ type: 'f',
3661
+ value: 800.0,
3662
+ },
3663
+ anglePower: {
3664
+ type: 'f',
3665
+ value: 2,
3666
+ },
3667
+ spotPosition: {
3668
+ type: 'v3',
3669
+ value: new THREE.Vector3(0, 0, 0),
3670
+ },
3671
+ lightColor: {
3672
+ type: 'c',
3673
+ value: new THREE.Color('white'),
3674
+ },
3675
+ opacity: {
3676
+ type: 'f',
3677
+ value: 1.0,
3678
+ },
3679
+ },
3680
+ vertexShader,
3681
+ fragmentShader,
3682
+ transparent: true,
3683
+ depthWrite: false,
3684
+ });
3685
+ }
3565
3686
  createObjects() {
3566
- // Add the spotlight
3567
- this.spotLight = new THREE.SpotLight(0xffffff, 50000);
3568
- this.spotLight.angle = 2;
3569
- this.spotLight.penumbra = 1;
3570
- this.spotLight.decay = 0.01;
3571
- this.spotLight.distance = 0;
3572
- this.spotLight.intensity = 1;
3573
- this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3574
- this.scene.add(this.spotLightHelper);
3575
- const spotLightTarget = new THREE.Object3D();
3576
- this.spotLight.target = spotLightTarget;
3577
- this.spotlightGroup = new THREE.Object3D();
3578
- this.spotlightGroup.add(this.spotLight);
3579
- this.spotlightGroup.add(spotLightTarget);
3580
- this.spotLight.position.set(0, -1.4, 0);
3581
- spotLightTarget.position.set(0, -10, 0);
3582
- this.createSpotLightBeam();
3583
- // Add the point light for the surrounding light
3584
- this.pointLight = new THREE.PointLight(0xffffff, 500, 0, 0.1);
3585
- this.spotlightGroup.add(this.pointLight);
3586
- this.pointLight.position.set(0, -1.4, 0);
3687
+ if (this.hasSpotLight) {
3688
+ this.createSpotlightMaterial();
3689
+ this.spotLight = new THREE.SpotLight(0xffffff, 50000);
3690
+ this.spotLight.angle = 2;
3691
+ this.spotLight.penumbra = 1;
3692
+ this.spotLight.decay = 0.01;
3693
+ this.spotLight.distance = 0;
3694
+ this.spotLight.intensity = 1;
3695
+ const spotLightTarget = new THREE.Object3D();
3696
+ this.spotLight.target = spotLightTarget;
3697
+ this.spotlightGroup = new THREE.Object3D();
3698
+ this.spotlightGroup.add(this.spotLight);
3699
+ this.spotlightGroup.add(spotLightTarget);
3700
+ this.spotLight.position.set(0, -1.4, 0);
3701
+ spotLightTarget.position.set(0, -10, 0);
3702
+ this.createSpotLightBeam();
3703
+ }
3587
3704
  }
3588
3705
  getCapabilityInValue(channel, value) {
3589
3706
  for (const capability of channel.capabilities) {
@@ -3664,11 +3781,7 @@ class Fixture3d {
3664
3781
  // Take the color into account for the beam (don't show a black beam)
3665
3782
  const color = new THREE.Color('rgb(' + this.colorRed + ', ' + this.colorGreen + ', ' + this.colorBlue + ')');
3666
3783
  const intensityColor = Math.max(this.colorRed, this.colorGreen, this.colorBlue);
3667
- if (this.pointLight) {
3668
- this.pointLight.color = color;
3669
- this.pointLight.intensity = this.pointLightMaxIntensity * this.dimmer;
3670
- }
3671
- if (this.spotLight) {
3784
+ if (this.hasSpotLight) {
3672
3785
  this.spotLight.color = color;
3673
3786
  this.spotLightBeam.material.uniforms.lightColor.value = color;
3674
3787
  this.spotLightBeam.material.uniforms.opacity.value = Math.min(intensityColor, this.dimmer);
@@ -3708,82 +3821,13 @@ class Fixture3d {
3708
3821
  }
3709
3822
  }
3710
3823
  }
3711
- atmosphereMat() {
3712
- const vertexShader = `
3713
- varying vec3 vNormal;
3714
- varying vec3 vWorldPosition;
3715
-
3716
- void main(){
3717
- vNormal = normalize(normalMatrix * normal);
3718
-
3719
- vec4 worldPosition = modelMatrix * vec4(position, 1.0);
3720
- vWorldPosition = worldPosition.xyz;
3721
-
3722
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
3723
- }`;
3724
- const fragmentShader = `
3725
- varying vec3 vNormal;
3726
- varying vec3 vWorldPosition;
3727
-
3728
- uniform vec3 lightColor;
3729
- uniform float opacity;
3730
- uniform vec3 spotPosition;
3731
- uniform float attenuation;
3732
- uniform float anglePower;
3733
-
3734
- void main(){
3735
- float intensity;
3736
-
3737
- intensity = distance(vWorldPosition, spotPosition) / attenuation;
3738
- intensity = 1.0 - clamp(intensity, 0.0, 1.0);
3739
-
3740
- vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
3741
- float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
3742
- intensity = intensity * angleIntensity * opacity;
3743
-
3744
- gl_FragColor = vec4(lightColor, intensity);
3745
- }`;
3746
- const material = new THREE.ShaderMaterial({
3747
- uniforms: {
3748
- attenuation: {
3749
- type: 'f',
3750
- value: 800.0,
3751
- },
3752
- anglePower: {
3753
- type: 'f',
3754
- value: 2,
3755
- },
3756
- spotPosition: {
3757
- type: 'v3',
3758
- value: new THREE.Vector3(0, 0, 0),
3759
- },
3760
- lightColor: {
3761
- type: 'c',
3762
- value: new THREE.Color('white'),
3763
- },
3764
- opacity: {
3765
- type: 'f',
3766
- value: 1.0,
3767
- },
3768
- },
3769
- vertexShader,
3770
- fragmentShader,
3771
- transparent: true,
3772
- depthWrite: false,
3773
- });
3774
- return material;
3775
- }
3776
3824
  createSpotLightBeam() {
3777
- if (this.spotLightBeam) {
3778
- this.spotlightGroup.remove(this.spotLightBeam);
3779
- }
3780
3825
  // TODO set the correct angle from the profile
3781
3826
  const beamAngleDegrees = 14;
3782
3827
  const geometry = new THREE.CylinderGeometry(0.1, beamAngleDegrees * 1.2, 100, 64, 20, false);
3783
3828
  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, -geometry.parameters.height / 2, 0));
3784
3829
  geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
3785
- this.atmosphereMaterial = this.atmosphereMat();
3786
- this.spotLightBeam = new THREE.Mesh(geometry, this.atmosphereMaterial);
3830
+ this.spotLightBeam = new THREE.Mesh(geometry, this.spotlightMaterial);
3787
3831
  this.spotLightBeam.position.set(0, -0.02, 0);
3788
3832
  this.spotLightBeam.receiveShadow = false;
3789
3833
  this.spotLightBeam.castShadow = false;
@@ -3791,30 +3835,17 @@ class Fixture3d {
3791
3835
  this.spotLightBeam.rotation.x = Math.PI / 2;
3792
3836
  }
3793
3837
  destroy() {
3794
- this.selectedMaterial.dispose();
3795
- this.atmosphereMaterial.dispose();
3838
+ if (this.hasSpotLight) {
3839
+ this.spotlightMaterial.dispose();
3840
+ }
3796
3841
  }
3797
3842
  }
3798
3843
 
3799
3844
  class ColorChanger3d extends Fixture3d {
3800
- createObjects() {
3801
- super.createObjects();
3802
- this.material = new THREE.MeshLambertMaterial({
3803
- color: 0x0d0d0d,
3804
- emissive: 0x0d0d0d,
3805
- });
3806
- this.mesh.material = this.material;
3807
- this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
3808
- // scene.add(this.spotLightHelper);
3809
- this.objectGroup.add(this.spotlightGroup);
3810
- this.objectGroup.add(this.mesh);
3811
- // A moving head has about 32 cm in width
3812
- this.objectGroup.scale.multiplyScalar(9);
3813
- this.scene.add(this.objectGroup);
3814
- this.isLoaded = true;
3815
- }
3816
- constructor(fixtureService, previewMeshService, fixture, scene) {
3817
- super(fixtureService, fixture, scene);
3845
+ constructor(fixtureService, previewService, previewMeshService, fixture, scene) {
3846
+ super(fixtureService, previewService, fixture, scene, true);
3847
+ this.fixtureService = fixtureService;
3848
+ this.previewService = previewService;
3818
3849
  this.objectGroup = new THREE.Object3D();
3819
3850
  forkJoin([previewMeshService.getMesh('color-changer')])
3820
3851
  .pipe(map(([colorChanger]) => {
@@ -3823,8 +3854,14 @@ class ColorChanger3d extends Fixture3d {
3823
3854
  }))
3824
3855
  .subscribe();
3825
3856
  }
3826
- getObject() {
3827
- return this.objectGroup;
3857
+ createObjects() {
3858
+ super.createObjects();
3859
+ this.mesh.material = this.previewService.fixtureMaterial;
3860
+ this.objectGroup.add(this.spotlightGroup);
3861
+ this.objectGroup.add(this.mesh);
3862
+ this.objectGroup.scale.multiplyScalar(9);
3863
+ this.scene.add(this.objectGroup);
3864
+ this.isLoaded = true;
3828
3865
  }
3829
3866
  updatePreview(channelValues, masterDimmerValue) {
3830
3867
  if (!this.isLoaded) {
@@ -3836,36 +3873,48 @@ class ColorChanger3d extends Fixture3d {
3836
3873
  if (this.lastSelected !== this.isSelected) {
3837
3874
  if (this.isSelected) {
3838
3875
  for (const child of this.mesh.children) {
3839
- child.material = this.selectedMaterial;
3876
+ child.material = this.previewService.fixtureSelectedMaterial;
3840
3877
  }
3841
3878
  }
3842
3879
  else {
3843
3880
  for (const child of this.mesh.children) {
3844
- child.material = this.material;
3881
+ child.material = this.previewService.fixtureMaterial;
3845
3882
  }
3846
3883
  }
3847
3884
  this.lastSelected = this.isSelected;
3848
3885
  }
3849
- // Update the light helpers
3850
- // this.spotLightHelper.update();
3851
3886
  }
3852
3887
  destroy() {
3853
3888
  this.scene.remove(this.objectGroup);
3854
- this.material.dispose();
3855
- this.spotLightHelper.dispose();
3856
3889
  }
3857
3890
  }
3858
3891
 
3859
3892
  class MovingHead3d extends Fixture3d {
3893
+ constructor(fixtureService, previewService, previewMeshService, fixture, scene) {
3894
+ super(fixtureService, previewService, fixture, scene, true);
3895
+ this.fixtureService = fixtureService;
3896
+ this.previewService = previewService;
3897
+ this.headGroup = new THREE.Object3D();
3898
+ this.armGroup = new THREE.Object3D();
3899
+ this.objectGroup = new THREE.Object3D();
3900
+ forkJoin([
3901
+ previewMeshService.getMesh('moving_head_socket'),
3902
+ previewMeshService.getMesh('moving_head_arm'),
3903
+ previewMeshService.getMesh('moving_head_head'),
3904
+ ])
3905
+ .pipe(map(([socket, arm, head]) => {
3906
+ this.socket = socket;
3907
+ this.arm = arm;
3908
+ this.head = head;
3909
+ this.createObjects();
3910
+ }))
3911
+ .subscribe();
3912
+ }
3860
3913
  createObjects() {
3861
3914
  super.createObjects();
3862
- this.material = new THREE.MeshLambertMaterial({
3863
- color: 0x0d0d0d,
3864
- emissive: 0x0d0d0d,
3865
- });
3866
- this.socket.material = this.material;
3867
- this.arm.material = this.material;
3868
- this.head.material = this.material;
3915
+ this.socket.material = this.previewService.fixtureMaterial;
3916
+ this.arm.material = this.previewService.fixtureMaterial;
3917
+ this.head.material = this.previewService.fixtureMaterial;
3869
3918
  // Add the head
3870
3919
  this.head.scale.multiplyScalar(0.9);
3871
3920
  this.head.position.set(-0.1, 0, 0);
@@ -3886,32 +3935,12 @@ class MovingHead3d extends Fixture3d {
3886
3935
  this.scene.add(this.objectGroup);
3887
3936
  this.isLoaded = true;
3888
3937
  }
3889
- constructor(fixtureService, previewMeshService, fixture, scene) {
3890
- super(fixtureService, fixture, scene);
3891
- this.headGroup = new THREE.Object3D();
3892
- this.armGroup = new THREE.Object3D();
3893
- this.objectGroup = new THREE.Object3D();
3894
- forkJoin([
3895
- previewMeshService.getMesh('moving_head_socket'),
3896
- previewMeshService.getMesh('moving_head_arm'),
3897
- previewMeshService.getMesh('moving_head_head'),
3898
- ])
3899
- .pipe(map(([socket, arm, head]) => {
3900
- this.socket = socket;
3901
- this.arm = arm;
3902
- this.head = head;
3903
- this.createObjects();
3904
- }))
3905
- .subscribe();
3906
- }
3907
- getObject() {
3908
- return this.objectGroup;
3909
- }
3910
3938
  updatePreview(channelValues, masterDimmerValue) {
3911
3939
  if (!this.isLoaded) {
3912
3940
  return;
3913
3941
  }
3914
3942
  super.updatePreview(channelValues, masterDimmerValue);
3943
+ this.updatePosition(this.objectGroup);
3915
3944
  // Apply default settings
3916
3945
  let panStart = 0;
3917
3946
  let panEnd = 255;
@@ -3940,38 +3969,33 @@ class MovingHead3d extends Fixture3d {
3940
3969
  }
3941
3970
  }
3942
3971
  }
3943
- this.updatePosition(this.objectGroup);
3944
3972
  // calculate the y/x rotation in radiants based on pan/tilt (0-1) respecting the max pan/tilt
3945
3973
  this.armGroup.rotation.y = THREE.MathUtils.degToRad(panEnd * this.pan + panStart) - THREE.MathUtils.degToRad(panEnd / 2);
3946
3974
  this.headGroup.rotation.x = THREE.MathUtils.degToRad(tiltEnd * this.tilt + tiltStart) - THREE.MathUtils.degToRad(tiltEnd / 2);
3947
- // Update the angle (only on change, because it's expensive)
3975
+ // Update the angle only on change, because it's expensive
3948
3976
  // TODO update the correct angle from the profile
3949
3977
  const beamAngleDregrees = 14;
3950
3978
  if (this.lastBeamAngleDegrees !== beamAngleDregrees) {
3951
3979
  this.spotLight.angle = THREE.MathUtils.degToRad(beamAngleDregrees);
3952
- this.createSpotLightBeam();
3953
3980
  this.lastBeamAngleDegrees = beamAngleDregrees;
3954
3981
  }
3955
3982
  // Update the material
3956
3983
  if (this.lastSelected !== this.isSelected) {
3957
3984
  if (this.isSelected) {
3958
- this.socket.material = this.selectedMaterial;
3959
- this.arm.material = this.selectedMaterial;
3960
- this.head.material = this.selectedMaterial;
3985
+ this.socket.material = this.previewService.fixtureSelectedMaterial;
3986
+ this.arm.material = this.previewService.fixtureSelectedMaterial;
3987
+ this.head.material = this.previewService.fixtureSelectedMaterial;
3961
3988
  }
3962
3989
  else {
3963
- this.socket.material = this.material;
3964
- this.arm.material = this.material;
3965
- this.head.material = this.material;
3990
+ this.socket.material = this.previewService.fixtureMaterial;
3991
+ this.arm.material = this.previewService.fixtureMaterial;
3992
+ this.head.material = this.previewService.fixtureMaterial;
3966
3993
  }
3967
3994
  this.lastSelected = this.isSelected;
3968
3995
  }
3969
- // this.spotLightHelper.update();
3970
3996
  }
3971
3997
  destroy() {
3972
3998
  this.scene.remove(this.objectGroup);
3973
- this.material.dispose();
3974
- this.spotLightHelper.dispose();
3975
3999
  }
3976
4000
  }
3977
4001
 
@@ -4004,13 +4028,13 @@ class PreviewComponent {
4004
4028
  for (const fixture of this.fixtureService.cachedFixtures) {
4005
4029
  switch (fixture.profile.categories[0]) {
4006
4030
  case FixtureCategory['Moving Head']:
4007
- this.fixtures3d.push(new MovingHead3d(this.fixtureService, this.previewMeshService, fixture, this.scene));
4031
+ this.fixtures3d.push(new MovingHead3d(this.fixtureService, this.previewService, this.previewMeshService, fixture, this.scene));
4008
4032
  break;
4009
4033
  case FixtureCategory['Color Changer']:
4010
- this.fixtures3d.push(new ColorChanger3d(this.fixtureService, this.previewMeshService, fixture, this.scene));
4034
+ this.fixtures3d.push(new ColorChanger3d(this.fixtureService, this.previewService, this.previewMeshService, fixture, this.scene));
4011
4035
  break;
4012
4036
  case FixtureCategory['Blinder']:
4013
- this.fixtures3d.push(new ColorChanger3d(this.fixtureService, this.previewMeshService, fixture, this.scene));
4037
+ this.fixtures3d.push(new ColorChanger3d(this.fixtureService, this.previewService, this.previewMeshService, fixture, this.scene));
4014
4038
  break;
4015
4039
  }
4016
4040
  }
@@ -6183,7 +6207,7 @@ class UserRegisterComponent {
6183
6207
  static { this.ɵfac = function UserRegisterComponent_Factory(t) { return new (t || UserRegisterComponent)(i0.ɵɵdirectiveInject(i1$1.BsModalRef), i0.ɵɵdirectiveInject(i1$1.BsModalService), i0.ɵɵdirectiveInject(UserService)); }; }
6184
6208
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserRegisterComponent, selectors: [["lib-user-register"]], hostBindings: function UserRegisterComponent_HostBindings(rf, ctx) { if (rf & 1) {
6185
6209
  i0.ɵɵlistener("keydown.enter", function UserRegisterComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleKeyboardEvent($event); }, false, i0.ɵɵresolveDocument);
6186
- } }, decls: 65, vars: 42, consts: [[3, "ngSubmit"], [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"], ["class", "alert alert-success", "role", "alert", 4, "ngIf"], [1, "form-group", "row"], ["for", "username", 1, "col-sm-4", "col-form-label"], [1, "col-sm-8"], [1, "input-group"], [1, "input-group-prepend"], [1, "input-group-text"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-user"], ["required", "", "name", "username", "type", "text", "id", "username", "placeholder", "The Cool Guy", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel"], ["for", "email", 1, "col-sm-4", "col-form-label"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-envelope-o"], ["required", "", "name", "email", "type", "email", "id", "email", "placeholder", "email@example.com", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel"], ["for", "password", 1, "col-sm-4", "col-form-label"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-lock"], ["required", "", "name", "password", "type", "password", "id", "password", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel", "placeholder"], ["for", "passwordRepeat", 1, "col-sm-4", "col-form-label"], ["required", "", "name", "passwordRepeat", "type", "password", "id", "passwordRepeat", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel", "placeholder"], ["class", "alert alert-primary", "role", "alert", 4, "ngIf"], ["href", "#", 3, "click"], [1, "mt-3", "mb-0", 2, "text-align", "center"], [1, "modal-footer"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "submit", 1, "btn", "btn-primary", 3, "disabled"], ["class", "fa fa-spinner fa-pulse fa-fw", 4, "ngIf"], ["role", "alert", 1, "alert", "alert-success"], ["role", "alert", 1, "alert", "alert-primary"], [1, "fa", "fa-spinner", "fa-pulse", "fa-fw"]], template: function UserRegisterComponent_Template(rf, ctx) { if (rf & 1) {
6210
+ } }, decls: 65, vars: 42, consts: [[3, "ngSubmit"], [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"], ["class", "alert alert-success", "role", "alert", 4, "ngIf"], [1, "form-group", "row"], ["for", "username", 1, "col-sm-4", "col-form-label"], [1, "col-sm-8"], [1, "input-group"], [1, "input-group-prepend"], [1, "input-group-text"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-user"], ["required", "", "name", "username", "type", "text", "id", "username", "placeholder", "John Doe", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel"], ["for", "email", 1, "col-sm-4", "col-form-label"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-envelope-o"], ["required", "", "name", "email", "type", "email", "id", "email", "placeholder", "email@example.com", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel"], ["for", "password", 1, "col-sm-4", "col-form-label"], ["aria-hidden", "true", 1, "fa", "fa-fw", "fa-lock"], ["required", "", "name", "password", "type", "password", "id", "password", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel", "placeholder"], ["for", "passwordRepeat", 1, "col-sm-4", "col-form-label"], ["required", "", "name", "passwordRepeat", "type", "password", "id", "passwordRepeat", 1, "form-control", 3, "ngModelChange", "disabled", "ngModel", "placeholder"], ["class", "alert alert-primary", "role", "alert", 4, "ngIf"], ["href", "#", 3, "click"], [1, "mt-3", "mb-0", 2, "text-align", "center"], [1, "modal-footer"], ["href", "#", "role", "button", 1, "mr-3", "my-auto", 3, "click"], ["type", "submit", 1, "btn", "btn-primary", 3, "disabled"], ["class", "fa fa-spinner fa-pulse fa-fw", 4, "ngIf"], ["role", "alert", 1, "alert", "alert-success"], ["role", "alert", 1, "alert", "alert-primary"], [1, "fa", "fa-spinner", "fa-pulse", "fa-fw"]], template: function UserRegisterComponent_Template(rf, ctx) { if (rf & 1) {
6187
6211
  i0.ɵɵelementStart(0, "form", 0);
6188
6212
  i0.ɵɵlistener("ngSubmit", function UserRegisterComponent_Template_form_ngSubmit_0_listener() { return ctx.register(); });
6189
6213
  i0.ɵɵelementStart(1, "div", 1)(2, "h4", 2);
@@ -6299,7 +6323,7 @@ class UserRegisterComponent {
6299
6323
  }
6300
6324
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserRegisterComponent, [{
6301
6325
  type: Component,
6302
- args: [{ selector: 'lib-user-register', template: "<form (ngSubmit)=\"register()\">\n <div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.user.register-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 *ngIf=\"subject\" class=\"alert alert-success\" role=\"alert\">\n {{ 'designer.user.login-required' | translate }}\n </div>\n <div class=\"form-group row\">\n <label for=\"username\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.username' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-user\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"username\"\n [(ngModel)]=\"username\"\n type=\"text\"\n class=\"form-control\"\n id=\"username\"\n placeholder=\"The Cool Guy\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"email\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.email' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-envelope-o\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"email\"\n [(ngModel)]=\"email\"\n type=\"email\"\n class=\"form-control\"\n id=\"email\"\n placeholder=\"email@example.com\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"password\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.password' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-lock\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"password\"\n [(ngModel)]=\"password\"\n type=\"password\"\n class=\"form-control\"\n id=\"password\"\n placeholder=\"{{ 'designer.user.password' | translate }}\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"passwordRepeat\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.password-repeat' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-lock\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"passwordRepeat\"\n [(ngModel)]=\"passwordRepeat\"\n type=\"password\"\n class=\"form-control\"\n id=\"passwordRepeat\"\n placeholder=\"{{ 'designer.user.password' | translate }}\"\n />\n </div>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"alert alert-primary\" role=\"alert\">\n {{ 'designer.user.error.' + error | translate }}\n </div>\n <a href=\"#\" (click)=\"login(); (false)\">\n <p class=\"mt-3 mb-0\" style=\"text-align: center\">{{ 'designer.user.already-have-account' | translate }}</p>\n </a>\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]=\"registering\" type=\"submit\" class=\"btn btn-primary\">\n <i *ngIf=\"registering\" class=\"fa fa-spinner fa-pulse fa-fw\"> </i>{{ 'designer.user.register' | translate }}\n </button>\n </div>\n</form>\n" }]
6326
+ args: [{ selector: 'lib-user-register', template: "<form (ngSubmit)=\"register()\">\n <div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.user.register-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 *ngIf=\"subject\" class=\"alert alert-success\" role=\"alert\">\n {{ 'designer.user.login-required' | translate }}\n </div>\n <div class=\"form-group row\">\n <label for=\"username\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.username' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-user\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"username\"\n [(ngModel)]=\"username\"\n type=\"text\"\n class=\"form-control\"\n id=\"username\"\n placeholder=\"John Doe\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"email\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.email' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-envelope-o\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"email\"\n [(ngModel)]=\"email\"\n type=\"email\"\n class=\"form-control\"\n id=\"email\"\n placeholder=\"email@example.com\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"password\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.password' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-lock\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"password\"\n [(ngModel)]=\"password\"\n type=\"password\"\n class=\"form-control\"\n id=\"password\"\n placeholder=\"{{ 'designer.user.password' | translate }}\"\n />\n </div>\n </div>\n </div>\n <div class=\"form-group row\">\n <label for=\"passwordRepeat\" class=\"col-sm-4 col-form-label\">{{ 'designer.user.password-repeat' | translate }}</label>\n <div class=\"col-sm-8\">\n <div class=\"input-group\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\"><i class=\"fa fa-fw fa-lock\" aria-hidden=\"true\"></i></div>\n </div>\n <input\n required\n [disabled]=\"registering\"\n name=\"passwordRepeat\"\n [(ngModel)]=\"passwordRepeat\"\n type=\"password\"\n class=\"form-control\"\n id=\"passwordRepeat\"\n placeholder=\"{{ 'designer.user.password' | translate }}\"\n />\n </div>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"alert alert-primary\" role=\"alert\">\n {{ 'designer.user.error.' + error | translate }}\n </div>\n <a href=\"#\" (click)=\"login(); (false)\">\n <p class=\"mt-3 mb-0\" style=\"text-align: center\">{{ 'designer.user.already-have-account' | translate }}</p>\n </a>\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]=\"registering\" type=\"submit\" class=\"btn btn-primary\">\n <i *ngIf=\"registering\" class=\"fa fa-spinner fa-pulse fa-fw\"> </i>{{ 'designer.user.register' | translate }}\n </button>\n </div>\n</form>\n" }]
6303
6327
  }], () => [{ type: i1$1.BsModalRef }, { type: i1$1.BsModalService }, { type: UserService }], { handleKeyboardEvent: [{
6304
6328
  type: HostListener,
6305
6329
  args: ['document:keydown.enter', ['$event']]
@@ -8217,13 +8241,13 @@ function FixtureCapabilityComponent_div_2_Template(rf, ctx) { if (rf & 1) {
8217
8241
  const ctx_r2 = i0.ɵɵnextContext();
8218
8242
  i0.ɵɵclassProp("h-100", ctx_r2.isChrome());
8219
8243
  i0.ɵɵadvance();
8220
- i0.ɵɵproperty("ngIf", ctx_r2.presetService.hasCapabilityDimmer());
8244
+ i0.ɵɵproperty("ngIf", ctx_r2.hasCapabilityDimmer);
8221
8245
  i0.ɵɵadvance();
8222
- i0.ɵɵproperty("ngIf", ctx_r2.presetService.hasCapabilityColorOrColorWheel());
8246
+ i0.ɵɵproperty("ngIf", ctx_r2.hasCapabilityColorOrColorWheel);
8223
8247
  i0.ɵɵadvance();
8224
8248
  i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(4, 6, ctx_r2.colorWheelChannels));
8225
8249
  i0.ɵɵadvance(2);
8226
- i0.ɵɵproperty("ngIf", ctx_r2.presetService.hasCapabilityPanTilt());
8250
+ i0.ɵɵproperty("ngIf", ctx_r2.hasCapabilityPanTilt);
8227
8251
  } }
8228
8252
  function FixtureCapabilityComponent_div_3_Template(rf, ctx) { if (rf & 1) {
8229
8253
  i0.ɵɵelementStart(0, "div", 10)(1, "p", 11);
@@ -8243,6 +8267,15 @@ function FixtureCapabilityComponent_div_4_Template(rf, ctx) { if (rf & 1) {
8243
8267
  i0.ɵɵadvance(2);
8244
8268
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 1, "designer.fixture.no-fixtures-selected"));
8245
8269
  } }
8270
+ function FixtureCapabilityComponent_div_5_Template(rf, ctx) { if (rf & 1) {
8271
+ i0.ɵɵelementStart(0, "div", 10)(1, "p", 11);
8272
+ i0.ɵɵtext(2);
8273
+ i0.ɵɵpipe(3, "translate");
8274
+ i0.ɵɵelementEnd()();
8275
+ } if (rf & 2) {
8276
+ i0.ɵɵadvance(2);
8277
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 1, "designer.fixture.no-capabilities-available"));
8278
+ } }
8246
8279
  class FixtureCapabilityComponent {
8247
8280
  constructor(presetService, fixtureService, changeDetectorRef, projectService, introService) {
8248
8281
  this.presetService = presetService;
@@ -8252,6 +8285,9 @@ class FixtureCapabilityComponent {
8252
8285
  this.introService = introService;
8253
8286
  // map containing the profile and the channel name containing the wheel
8254
8287
  this.colorWheelChannels = new Map();
8288
+ this.hasCapabilityDimmer = false;
8289
+ this.hasCapabilityColorOrColorWheel = false;
8290
+ this.hasCapabilityPanTilt = false;
8255
8291
  this.fixtureSelectionChangedSubscription = this.presetService.fixtureSelectionChanged.subscribe(() => {
8256
8292
  this.update();
8257
8293
  });
@@ -8262,7 +8298,9 @@ class FixtureCapabilityComponent {
8262
8298
  this.changeDetectorRef.detectChanges();
8263
8299
  });
8264
8300
  }
8265
- ngOnInit() { }
8301
+ ngOnInit() {
8302
+ this.update();
8303
+ }
8266
8304
  ngOnDestroy() {
8267
8305
  this.fixtureSelectionChangedSubscription.unsubscribe();
8268
8306
  this.previewSelectionChangedSubscription.unsubscribe();
@@ -8300,8 +8338,14 @@ class FixtureCapabilityComponent {
8300
8338
  }
8301
8339
  }
8302
8340
  }
8341
+ updateCapabilities() {
8342
+ this.hasCapabilityDimmer = this.presetService.hasCapabilityDimmer();
8343
+ this.hasCapabilityColorOrColorWheel = this.presetService.hasCapabilityColorOrColorWheel();
8344
+ this.hasCapabilityPanTilt = this.presetService.hasCapabilityPanTilt();
8345
+ }
8303
8346
  update() {
8304
8347
  this.updateColorWheels();
8348
+ this.updateCapabilities();
8305
8349
  this.changeDetectorRef.detectChanges();
8306
8350
  }
8307
8351
  isChrome() {
@@ -8311,9 +8355,9 @@ class FixtureCapabilityComponent {
8311
8355
  return false;
8312
8356
  }
8313
8357
  static { this.ɵfac = function FixtureCapabilityComponent_Factory(t) { return new (t || FixtureCapabilityComponent)(i0.ɵɵdirectiveInject(PresetService), i0.ɵɵdirectiveInject(FixtureService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(ProjectService), i0.ɵɵdirectiveInject(IntroService)); }; }
8314
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixtureCapabilityComponent, selectors: [["lib-app-fixture-capability"]], decls: 5, vars: 5, consts: [[1, "card", "border-secondary", "panel", "h-100"], [1, "card-body", "capability-container", "d-flex", "h-100", 2, "overflow-y", "hidden"], ["class", "row m-0 pl-3", 3, "h-100", 4, "ngIf"], ["class", "m-auto", 4, "ngIf"], [1, "row", "m-0", "pl-3"], ["class", "col col-auto p-0 my-3 mr-3", "style", "height: calc(100% - 2rem)", 4, "ngIf"], ["class", "col col-auto p-0 my-3 mr-3", "style", "height: calc(100% - 2rem)", 4, "ngFor", "ngForOf"], [1, "col", "col-auto", "p-0", "my-3", "mr-3"], [1, "col", "col-auto", "p-0", "my-3", "mr-3", 2, "height", "calc(100% - 2rem)"], [3, "profile", "channel", "wheelIndex", "showContainer"], [1, "m-auto"], [1, "m-auto", 2, "color", "#717171"]], template: function FixtureCapabilityComponent_Template(rf, ctx) { if (rf & 1) {
8358
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixtureCapabilityComponent, selectors: [["lib-app-fixture-capability"]], decls: 6, vars: 6, consts: [[1, "card", "border-secondary", "panel", "h-100"], [1, "card-body", "capability-container", "d-flex", "h-100", 2, "overflow-y", "hidden"], ["class", "row m-0 pl-3", 3, "h-100", 4, "ngIf"], ["class", "m-auto", 4, "ngIf"], [1, "row", "m-0", "pl-3"], ["class", "col col-auto p-0 my-3 mr-3", "style", "height: calc(100% - 2rem)", 4, "ngIf"], ["class", "col col-auto p-0 my-3 mr-3", "style", "height: calc(100% - 2rem)", 4, "ngFor", "ngForOf"], [1, "col", "col-auto", "p-0", "my-3", "mr-3"], [1, "col", "col-auto", "p-0", "my-3", "mr-3", 2, "height", "calc(100% - 2rem)"], [3, "profile", "channel", "wheelIndex", "showContainer"], [1, "m-auto"], [1, "m-auto", 2, "color", "#717171"]], template: function FixtureCapabilityComponent_Template(rf, ctx) { if (rf & 1) {
8315
8359
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
8316
- i0.ɵɵtemplate(2, FixtureCapabilityComponent_div_2_Template, 8, 8, "div", 2)(3, FixtureCapabilityComponent_div_3_Template, 4, 3, "div", 3)(4, FixtureCapabilityComponent_div_4_Template, 4, 3, "div", 3);
8360
+ i0.ɵɵtemplate(2, FixtureCapabilityComponent_div_2_Template, 8, 8, "div", 2)(3, FixtureCapabilityComponent_div_3_Template, 4, 3, "div", 3)(4, FixtureCapabilityComponent_div_4_Template, 4, 3, "div", 3)(5, FixtureCapabilityComponent_div_5_Template, 4, 3, "div", 3);
8317
8361
  i0.ɵɵelementEnd()();
8318
8362
  } if (rf & 2) {
8319
8363
  i0.ɵɵclassProp("card-intro-active", ctx.introService.showStep("capabilities"));
@@ -8323,11 +8367,13 @@ class FixtureCapabilityComponent {
8323
8367
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length == 0);
8324
8368
  i0.ɵɵadvance();
8325
8369
  i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length == 0);
8370
+ i0.ɵɵadvance();
8371
+ i0.ɵɵproperty("ngIf", ctx.projectService.project.fixtures.length > 0 && ctx.presetService.selectedPreset && ctx.presetService.selectedPreset.fixtures.length > 0 && !ctx.hasCapabilityColorOrColorWheel && !ctx.hasCapabilityPanTilt);
8326
8372
  } }, dependencies: [i5.NgForOf, i5.NgIf, FixtureCapabilityColorComponent, FixtureCapabilityDimmerComponent, FixtureCapabilityPanTiltComponent, FixtureCapabilityColorWheelComponent, i5.KeyValuePipe, i2.TranslatePipe], changeDetection: 0 }); }
8327
8373
  }
8328
8374
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityComponent, [{
8329
8375
  type: Component,
8330
- args: [{ selector: 'lib-app-fixture-capability', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card border-secondary panel h-100\" [class.card-intro-active]=\"introService.showStep('capabilities')\">\n <div class=\"card-body capability-container d-flex h-100\" style=\"overflow-y: hidden\">\n <!-- h-100 needs to be applied in chrome to avoid performance issues with many layouts (reflows)\n during sliding. But the class must not be applied e.g. in Safari, because the bottom margin is not correct\n anymore afterwards. -->\n <div *ngIf=\"presetService.selectedPreset\" class=\"row m-0 pl-3\" [class.h-100]=\"isChrome()\">\n <!-- Dimmer -->\n <!-- the height attribute is required to avoid performance issues with many layouts (reflows)\n in Chrome during sliding -->\n <div *ngIf=\"presetService.hasCapabilityDimmer()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-dimmer></lib-app-fixture-capability-dimmer>\n </div>\n\n <!-- Color -->\n <!-- Also show for color wheel fixtures to approx. the color -->\n <div *ngIf=\"presetService.hasCapabilityColorOrColorWheel()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-color></lib-app-fixture-capability-color>\n </div>\n\n <!-- Color wheels -->\n <div\n *ngFor=\"let entry of colorWheelChannels | keyvalue; let i = index\"\n class=\"col col-auto p-0 my-3 mr-3\"\n style=\"height: calc(100% - 2rem)\"\n >\n <lib-app-fixture-capability-color-wheel\n [profile]=\"entry.key\"\n [channel]=\"entry.value\"\n [wheelIndex]=\"i\"\n [showContainer]=\"colorWheelChannels.size > 1\"\n ></lib-app-fixture-capability-color-wheel>\n </div>\n\n <!-- Pan/Tilt -->\n <div *ngIf=\"presetService.hasCapabilityPanTilt()\" class=\"col col-auto p-0 my-3 mr-3\" style=\"height: calc(100% - 2rem)\">\n <lib-app-fixture-capability-pan-tilt></lib-app-fixture-capability-pan-tilt>\n </div>\n\n <!-- Fix spacing at the end -->\n <div class=\"col col-auto p-0 my-3 mr-3\">&nbsp;</div>\n </div>\n\n <div *ngIf=\"projectService.project.fixtures.length == 0\" class=\"m-auto\">\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures' | translate }}</p>\n </div>\n\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 && presetService.selectedPreset && presetService.selectedPreset.fixtures.length == 0\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-fixtures-selected' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
8376
+ 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=\"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=\"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=\"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\n <div\n *ngIf=\"\n projectService.project.fixtures.length > 0 &&\n presetService.selectedPreset &&\n presetService.selectedPreset.fixtures.length > 0 &&\n !hasCapabilityColorOrColorWheel &&\n !hasCapabilityPanTilt\n \"\n class=\"m-auto\"\n >\n <p class=\"m-auto\" style=\"color: #717171\">{{ 'designer.fixture.no-capabilities-available' | translate }}</p>\n </div>\n </div>\n</div>\n" }]
8331
8377
  }], () => [{ type: PresetService }, { type: FixtureService }, { type: i0.ChangeDetectorRef }, { type: ProjectService }, { type: IntroService }], null); })();
8332
8378
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FixtureCapabilityComponent, { className: "FixtureCapabilityComponent" }); })();
8333
8379
 
@@ -9974,11 +10020,49 @@ class MasterDimmerComponent {
9974
10020
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MasterDimmerComponent, { className: "MasterDimmerComponent" }); })();
9975
10021
 
9976
10022
  const _c0$2 = ["sliderValue"];
9977
- function FixtureCapabilityChannelComponent_div_9_div_1_span_6_Template(rf, ctx) { if (rf & 1) {
10023
+ function FixtureCapabilityChannelComponent_div_9_div_1_span_5_Template(rf, ctx) { if (rf & 1) {
10024
+ i0.ɵɵelementStart(0, "span");
10025
+ i0.ɵɵtext(1);
10026
+ i0.ɵɵelementEnd();
10027
+ } if (rf & 2) {
10028
+ const capability_r3 = i0.ɵɵnextContext().$implicit;
10029
+ const ctx_r1 = i0.ɵɵnextContext(2);
10030
+ i0.ɵɵadvance();
10031
+ i0.ɵɵtextInterpolate1(" (", ctx_r1.getDescription(capability_r3), ")");
10032
+ } }
10033
+ function FixtureCapabilityChannelComponent_div_9_div_1_div_7_Template(rf, ctx) { if (rf & 1) {
10034
+ i0.ɵɵelement(0, "div", 20);
10035
+ } if (rf & 2) {
10036
+ const color_r4 = ctx.$implicit;
10037
+ i0.ɵɵstyleProp("background-color", color_r4);
10038
+ } }
10039
+ function FixtureCapabilityChannelComponent_div_9_div_1_small_8_Template(rf, ctx) { if (rf & 1) {
10040
+ i0.ɵɵelementStart(0, "small");
10041
+ i0.ɵɵtext(1);
10042
+ i0.ɵɵelementEnd();
10043
+ } if (rf & 2) {
10044
+ const capability_r3 = i0.ɵɵnextContext().$implicit;
10045
+ const ctx_r1 = i0.ɵɵnextContext(2);
10046
+ i0.ɵɵadvance();
10047
+ i0.ɵɵtextInterpolate2(" (", ctx_r1.getDescriptionStart(capability_r3), " to ", ctx_r1.getDescriptionEnd(capability_r3), ")");
10048
+ } }
10049
+ function FixtureCapabilityChannelComponent_div_9_div_1_span_9_Template(rf, ctx) { if (rf & 1) {
9978
10050
  i0.ɵɵelementStart(0, "span");
9979
10051
  i0.ɵɵtext(1, " - ");
9980
10052
  i0.ɵɵelementEnd();
9981
10053
  } }
10054
+ function FixtureCapabilityChannelComponent_div_9_div_1_i_11_Template(rf, ctx) { if (rf & 1) {
10055
+ i0.ɵɵelement(0, "i", 21);
10056
+ i0.ɵɵpipe(1, "translate");
10057
+ } if (rf & 2) {
10058
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(1, 1, "designer.fixture.capability-sound-controlled"));
10059
+ } }
10060
+ function FixtureCapabilityChannelComponent_div_9_div_1_i_12_Template(rf, ctx) { if (rf & 1) {
10061
+ i0.ɵɵelement(0, "i", 22);
10062
+ i0.ɵɵpipe(1, "translate");
10063
+ } if (rf & 2) {
10064
+ i0.ɵɵpropertyInterpolate("popover", i0.ɵɵpipeBind1(1, 1, "designer.fixture.capability-random-timing"));
10065
+ } }
9982
10066
  function FixtureCapabilityChannelComponent_div_9_div_1_Template(rf, ctx) { if (rf & 1) {
9983
10067
  const _r1 = i0.ɵɵgetCurrentView();
9984
10068
  i0.ɵɵelementStart(0, "div", 5)(1, "input", 14);
@@ -9988,31 +10072,44 @@ function FixtureCapabilityChannelComponent_div_9_div_1_Template(rf, ctx) { if (r
9988
10072
  i0.ɵɵelementStart(2, "label", 15);
9989
10073
  i0.ɵɵtext(3);
9990
10074
  i0.ɵɵpipe(4, "translate");
9991
- i0.ɵɵelementStart(5, "small");
9992
- i0.ɵɵtemplate(6, FixtureCapabilityChannelComponent_div_9_div_1_span_6_Template, 2, 0, "span", 16);
9993
- i0.ɵɵtext(7);
9994
- i0.ɵɵelementEnd()()();
10075
+ i0.ɵɵtemplate(5, FixtureCapabilityChannelComponent_div_9_div_1_span_5_Template, 2, 1, "span", 16);
10076
+ i0.ɵɵelementStart(6, "small");
10077
+ i0.ɵɵtemplate(7, FixtureCapabilityChannelComponent_div_9_div_1_div_7_Template, 1, 2, "div", 17)(8, FixtureCapabilityChannelComponent_div_9_div_1_small_8_Template, 2, 2, "small", 16)(9, FixtureCapabilityChannelComponent_div_9_div_1_span_9_Template, 2, 0, "span", 16);
10078
+ i0.ɵɵtext(10);
10079
+ i0.ɵɵelementEnd();
10080
+ i0.ɵɵtemplate(11, FixtureCapabilityChannelComponent_div_9_div_1_i_11_Template, 2, 3, "i", 18)(12, FixtureCapabilityChannelComponent_div_9_div_1_i_12_Template, 2, 3, "i", 19);
10081
+ i0.ɵɵelementEnd()();
9995
10082
  } if (rf & 2) {
9996
10083
  const capability_r3 = ctx.$implicit;
9997
- const i_r4 = ctx.index;
10084
+ const i_r5 = ctx.index;
9998
10085
  const ctx_r1 = i0.ɵɵnextContext(2);
9999
10086
  i0.ɵɵadvance();
10000
10087
  i0.ɵɵpropertyInterpolate1("name", "capabilityGeneric", ctx_r1.capabilityIndex, "Option");
10001
- i0.ɵɵpropertyInterpolate2("id", "capabilityGeneric", ctx_r1.capabilityIndex, "Option", i_r4, "");
10088
+ i0.ɵɵpropertyInterpolate2("id", "capabilityGeneric", ctx_r1.capabilityIndex, "Option", i_r5, "");
10002
10089
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedCapability);
10003
10090
  i0.ɵɵproperty("value", capability_r3);
10004
10091
  i0.ɵɵadvance();
10005
- i0.ɵɵpropertyInterpolate2("for", "capabilityGeneric", ctx_r1.capabilityIndex, "Option", i_r4, "");
10092
+ i0.ɵɵpropertyInterpolate2("for", "capabilityGeneric", ctx_r1.capabilityIndex, "Option", i_r5, "");
10093
+ i0.ɵɵadvance();
10094
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(4, 18, "designer.fixtureCapabilityType." + capability_r3.capability.type), "");
10095
+ i0.ɵɵadvance(2);
10096
+ i0.ɵɵproperty("ngIf", ctx_r1.getDescription(capability_r3));
10097
+ i0.ɵɵadvance(2);
10098
+ i0.ɵɵproperty("ngForOf", capability_r3.capability.colors);
10099
+ i0.ɵɵadvance();
10100
+ i0.ɵɵproperty("ngIf", ctx_r1.getDescriptionStart(capability_r3));
10006
10101
  i0.ɵɵadvance();
10007
- i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(4, 13, "designer.fixtureCapabilityType." + capability_r3.capability.type), "");
10008
- i0.ɵɵadvance(3);
10009
10102
  i0.ɵɵproperty("ngIf", capability_r3.capability.comment);
10010
10103
  i0.ɵɵadvance();
10011
10104
  i0.ɵɵtextInterpolate1(" ", capability_r3.capability.comment, "");
10105
+ i0.ɵɵadvance();
10106
+ i0.ɵɵproperty("ngIf", capability_r3.capability.soundControlled);
10107
+ i0.ɵɵadvance();
10108
+ i0.ɵɵproperty("ngIf", capability_r3.capability.randomTiming);
10012
10109
  } }
10013
10110
  function FixtureCapabilityChannelComponent_div_9_Template(rf, ctx) { if (rf & 1) {
10014
10111
  i0.ɵɵelementStart(0, "div", 12);
10015
- i0.ɵɵtemplate(1, FixtureCapabilityChannelComponent_div_9_div_1_Template, 8, 15, "div", 13);
10112
+ i0.ɵɵtemplate(1, FixtureCapabilityChannelComponent_div_9_div_1_Template, 13, 20, "div", 13);
10016
10113
  i0.ɵɵelementEnd();
10017
10114
  } if (rf & 2) {
10018
10115
  const ctx_r1 = i0.ɵɵnextContext();
@@ -10020,20 +10117,30 @@ function FixtureCapabilityChannelComponent_div_9_Template(rf, ctx) { if (rf & 1)
10020
10117
  i0.ɵɵproperty("ngForOf", ctx_r1._channel.capabilities);
10021
10118
  } }
10022
10119
  function FixtureCapabilityChannelComponent_div_10_Template(rf, ctx) { if (rf & 1) {
10023
- const _r5 = i0.ɵɵgetCurrentView();
10024
- i0.ɵɵelementStart(0, "div", 17)(1, "div", 18)(2, "input", 19, 0);
10025
- i0.ɵɵlistener("ngModelChange", function FixtureCapabilityChannelComponent_div_10_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setValue($event)); });
10120
+ const _r6 = i0.ɵɵgetCurrentView();
10121
+ i0.ɵɵelementStart(0, "div", 23)(1, "div", 24)(2, "input", 25, 0);
10122
+ i0.ɵɵlistener("ngModelChange", function FixtureCapabilityChannelComponent_div_10_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setValue($event)); });
10123
+ i0.ɵɵelementEnd()();
10124
+ i0.ɵɵelementStart(4, "div", 26);
10125
+ i0.ɵɵtext(5);
10126
+ i0.ɵɵelementEnd();
10127
+ i0.ɵɵelementStart(6, "div", 27)(7, "mv-slider", 28, 1);
10128
+ i0.ɵɵlistener("change", function FixtureCapabilityChannelComponent_div_10_Template_mv_slider_change_7_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setValue($event.newValue)); });
10129
+ i0.ɵɵelementEnd()();
10130
+ i0.ɵɵelementStart(9, "div", 29);
10131
+ i0.ɵɵtext(10);
10026
10132
  i0.ɵɵelementEnd()();
10027
- i0.ɵɵelementStart(4, "div", 20)(5, "mv-slider", 21, 1);
10028
- i0.ɵɵlistener("change", function FixtureCapabilityChannelComponent_div_10_Template_mv_slider_change_5_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setValue($event.newValue)); });
10029
- i0.ɵɵelementEnd()()();
10030
10133
  } if (rf & 2) {
10031
10134
  const ctx_r1 = i0.ɵɵnextContext();
10032
10135
  i0.ɵɵclassProp("pl-0", (ctx_r1._channel.capabilities == null ? null : ctx_r1._channel.capabilities.length) > 1);
10033
10136
  i0.ɵɵadvance(2);
10034
10137
  i0.ɵɵproperty("ngModel", ctx_r1.templateValue);
10035
10138
  i0.ɵɵadvance(3);
10139
+ i0.ɵɵtextInterpolate(ctx_r1.descriptionEnd);
10140
+ i0.ɵɵadvance(2);
10036
10141
  i0.ɵɵproperty("value", ctx_r1.templateValue)("orientation", "vertical")("reversed", true)("tooltip", "hide")("min", ctx_r1.rangeMin)("max", ctx_r1.rangeMax)("step", 1);
10142
+ i0.ɵɵadvance(3);
10143
+ i0.ɵɵtextInterpolate(ctx_r1.descriptionStart);
10037
10144
  } }
10038
10145
  class FixtureCapabilityChannelComponent {
10039
10146
  set channel(value) {
@@ -10042,11 +10149,12 @@ class FixtureCapabilityChannelComponent {
10042
10149
  }
10043
10150
  constructor(presetService) {
10044
10151
  this.presetService = presetService;
10045
- this.rangeMin = 0;
10046
- this.rangeMax = 0;
10047
10152
  this.defaultValue = 0;
10048
10153
  this.value = 0;
10049
10154
  this.templateValue = 0;
10155
+ this.hasRange = false;
10156
+ this.rangeMin = 0;
10157
+ this.rangeMax = 0;
10050
10158
  }
10051
10159
  updateChannel() {
10052
10160
  this.selectedCapability = this._channel.capabilities[0];
@@ -10054,25 +10162,107 @@ class FixtureCapabilityChannelComponent {
10054
10162
  this.calculateTemplateValue();
10055
10163
  if (this.value >= 0) {
10056
10164
  for (const capability of this._channel.capabilities) {
10057
- if (capability.capability.dmxRange.length > 0 && capability.centerValue === this.value) {
10165
+ if (capability.capability.dmxRange.length > 0 &&
10166
+ capability.capability.dmxRange[0] <= this.value &&
10167
+ this.value <= capability.capability.dmxRange[1]) {
10058
10168
  this.selectedCapability = capability;
10059
10169
  break;
10060
10170
  }
10061
10171
  }
10062
10172
  }
10173
+ this.defaultValue = this.getDefaultValue();
10174
+ this.description = this.getDescription(this.selectedCapability);
10175
+ this.hasRange = this.capabilityHasRange();
10063
10176
  this.rangeMin = this.getRangeMin();
10064
10177
  this.rangeMax = this.getRangeMax();
10065
- this.defaultValue = this.getDefaultValue();
10178
+ this.descriptionStart = this.getDescriptionStart(this.selectedCapability);
10179
+ this.descriptionEnd = this.getDescriptionEnd(this.selectedCapability);
10066
10180
  }
10067
10181
  capabilityHasRange() {
10068
- if (this._channel.capabilities && this._channel.capabilities.length === 1) {
10182
+ if (this._channel?.capabilities?.length === 1) {
10183
+ // TODO does this work in all cases? if we have no option, it's always a range?
10069
10184
  return true;
10070
10185
  }
10071
- if (this.selectedCapability && this.selectedCapability.capability.angleStart) {
10186
+ if (this.selectedCapability?.capability.angleStart ||
10187
+ this.selectedCapability?.capability.speedStart ||
10188
+ this.selectedCapability?.capability.brightnessStart ||
10189
+ this.selectedCapability?.capability.durationStart ||
10190
+ this.selectedCapability?.capability.colorTemperatureStart ||
10191
+ this.selectedCapability?.capability.soundSensitivityStart ||
10192
+ this.selectedCapability?.capability.horizontalAngleStart ||
10193
+ this.selectedCapability?.capability.verticalAngleStart ||
10194
+ this.selectedCapability?.capability.distanceStart ||
10195
+ this.selectedCapability?.capability.openPercentStart ||
10196
+ this.selectedCapability?.capability.frostIntensityStart ||
10197
+ this.selectedCapability?.capability.fogOutputStart ||
10198
+ this.selectedCapability?.capability.timeStart ||
10199
+ this.selectedCapability?.capability.insertionStart ||
10200
+ this.selectedCapability?.capability.colorsStart) {
10072
10201
  return true;
10073
10202
  }
10074
10203
  return false;
10075
10204
  }
10205
+ getDescriptionStart(capability) {
10206
+ if (!capability || !capability.capability) {
10207
+ return '';
10208
+ }
10209
+ return (capability.capability.angleStart ||
10210
+ capability.capability.speedStart ||
10211
+ capability.capability.brightnessStart ||
10212
+ capability.capability.durationStart ||
10213
+ capability.capability.colorTemperatureStart ||
10214
+ capability.capability.soundSensitivityStart ||
10215
+ capability.capability.horizontalAngleStart ||
10216
+ capability.capability.verticalAngleStart ||
10217
+ capability.capability.distanceStart ||
10218
+ capability.capability.openPercentStart ||
10219
+ capability.capability.frostIntensityStart ||
10220
+ capability.capability.fogOutputStart ||
10221
+ capability.capability.timeStart ||
10222
+ capability.capability.insertionStart ||
10223
+ capability.capability.colorsStart)?.toString();
10224
+ }
10225
+ getDescriptionEnd(capability) {
10226
+ if (!capability || !capability.capability) {
10227
+ return '';
10228
+ }
10229
+ return (capability.capability.angleEnd ||
10230
+ capability.capability.speedEnd ||
10231
+ capability.capability.brightnessEnd ||
10232
+ capability.capability.durationEnd ||
10233
+ capability.capability.colorTemperatureEnd ||
10234
+ capability.capability.soundSensitivityEnd ||
10235
+ capability.capability.horizontalAngleEnd ||
10236
+ capability.capability.verticalAngleEnd ||
10237
+ capability.capability.distanceEnd ||
10238
+ capability.capability.openPercentEnd ||
10239
+ capability.capability.frostIntensityEnd ||
10240
+ capability.capability.fogOutputEnd ||
10241
+ capability.capability.timeEnd ||
10242
+ capability.capability.insertionEnd ||
10243
+ capability.capability.colorsEnd)?.toString();
10244
+ }
10245
+ getDescription(capability) {
10246
+ if (!capability || !capability.capability) {
10247
+ return '';
10248
+ }
10249
+ return (capability.capability.slotNumber ||
10250
+ capability.capability.shutterEffect ||
10251
+ capability.capability.angle ||
10252
+ capability.capability.speed ||
10253
+ capability.capability.brightness ||
10254
+ capability.capability.duration ||
10255
+ capability.capability.colorTemperature ||
10256
+ capability.capability.soundSensitivity ||
10257
+ capability.capability.horizontalAngle ||
10258
+ capability.capability.verticalAngle ||
10259
+ capability.capability.distance ||
10260
+ capability.capability.openPercent ||
10261
+ capability.capability.frostIntensity ||
10262
+ capability.capability.fogOutput ||
10263
+ capability.capability.time ||
10264
+ capability.capability.insertion)?.toString();
10265
+ }
10076
10266
  getRangeMin() {
10077
10267
  if (this.selectedCapability.capability.dmxRange.length > 0) {
10078
10268
  return this.selectedCapability.capability.dmxRange[0];
@@ -10090,7 +10280,7 @@ class FixtureCapabilityChannelComponent {
10090
10280
  if (isNaN(value)) {
10091
10281
  return;
10092
10282
  }
10093
- if (!ignoreCapabilityRange && (value < this.getRangeMin() || value > this.getRangeMax())) {
10283
+ if (!ignoreCapabilityRange && (value < this.rangeMin || value > this.rangeMax)) {
10094
10284
  return;
10095
10285
  }
10096
10286
  this.value = value;
@@ -10102,7 +10292,9 @@ class FixtureCapabilityChannelComponent {
10102
10292
  // TODO use the same technique in the dimmer/pan/tilt/color sliders
10103
10293
  if (!this.valueSetTimer) {
10104
10294
  this.valueSetTimer = setTimeout(() => {
10105
- this.sliderValue.nativeElement.value = this.value;
10295
+ if (this.sliderValue) {
10296
+ this.sliderValue.nativeElement.value = this.value;
10297
+ }
10106
10298
  this.valueSetTimer = undefined;
10107
10299
  }, 30);
10108
10300
  }
@@ -10132,12 +10324,13 @@ class FixtureCapabilityChannelComponent {
10132
10324
  }
10133
10325
  capabilitySelected() {
10134
10326
  // select the center value of the selected capability
10135
- if (this.capabilityHasRange) {
10327
+ if (this.capabilityHasRange()) {
10136
10328
  this.setValue(this.selectedCapability.capability.dmxRange[0], true);
10137
10329
  }
10138
10330
  else {
10139
10331
  this.setValue(this.selectedCapability.centerValue, true);
10140
10332
  }
10333
+ this.updateChannel();
10141
10334
  }
10142
10335
  static { this.ɵfac = function FixtureCapabilityChannelComponent_Factory(t) { return new (t || FixtureCapabilityChannelComponent)(i0.ɵɵdirectiveInject(PresetService)); }; }
10143
10336
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FixtureCapabilityChannelComponent, selectors: [["lib-app-fixture-capability-channel"]], viewQuery: function FixtureCapabilityChannelComponent_Query(rf, ctx) { if (rf & 1) {
@@ -10145,7 +10338,7 @@ class FixtureCapabilityChannelComponent {
10145
10338
  } if (rf & 2) {
10146
10339
  let _t;
10147
10340
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.sliderValue = _t.first);
10148
- } }, inputs: { profile: "profile", channel: "channel", capabilityIndex: "capabilityIndex" }, decls: 11, vars: 10, consts: [["sliderValue", ""], ["slider", ""], [1, "card", "border-secondary", "h-100", 2, "min-height", "200px"], [1, "card-header"], [1, "my-auto"], [1, "form-check"], ["type", "checkbox", 1, "form-check-input", 3, "ngModelChange", "id", "ngModel"], [1, "form-check-label", 3, "for"], [1, "card-body", "h-100", "d-flex", 2, "flex-direction", "column", "overflow", "hidden"], [1, "row", "h-100"], ["class", "col mr-3", "style", "overflow-y: auto", 4, "ngIf"], ["class", "col col-auto d-flex mx-auto", "style", "flex-direction: column", 3, "pl-0", 4, "ngIf"], [1, "col", "mr-3", 2, "overflow-y", "auto"], ["class", "form-check", 4, "ngFor", "ngForOf"], ["type", "radio", 1, "form-check-input", 3, "ngModelChange", "change", "ngModel", "name", "id", "value"], [1, "form-check-label", 2, "max-width", "200px", 3, "for"], [4, "ngIf"], [1, "col", "col-auto", "d-flex", "mx-auto", 2, "flex-direction", "column"], [1, "mb-4", "w-100", "d-flex"], ["type", "text", 1, "mx-auto", 2, "width", "45px", "height", "20px", "text-align", "center", "font-size", "12px", "font-family", "monospace", 3, "ngModelChange", "ngModel"], [1, "h-100", "w-100", "d-flex"], [1, "mx-auto", 2, "height", "100%", 3, "change", "value", "orientation", "reversed", "tooltip", "min", "max", "step"]], template: function FixtureCapabilityChannelComponent_Template(rf, ctx) { if (rf & 1) {
10341
+ } }, inputs: { profile: "profile", channel: "channel", capabilityIndex: "capabilityIndex" }, decls: 11, vars: 10, consts: [["sliderValue", ""], ["slider", ""], [1, "card", "border-secondary", "h-100", 2, "min-height", "200px"], [1, "card-header"], [1, "my-auto"], [1, "form-check"], ["type", "checkbox", 1, "form-check-input", 3, "ngModelChange", "id", "ngModel"], [1, "form-check-label", 3, "for"], [1, "card-body", "h-100", "d-flex", 2, "flex-direction", "column", "overflow", "hidden"], [1, "row", "h-100"], ["class", "col mr-3", "style", "overflow-y: auto", 4, "ngIf"], ["class", "col col-auto d-flex mx-auto", "style", "flex-direction: column", 3, "pl-0", 4, "ngIf"], [1, "col", "mr-3", 2, "overflow-y", "auto"], ["class", "form-check", 4, "ngFor", "ngForOf"], ["type", "radio", 1, "form-check-input", 3, "ngModelChange", "change", "ngModel", "name", "id", "value"], [1, "form-check-label", 2, "max-width", "200px", 3, "for"], [4, "ngIf"], ["class", "color", 3, "background-color", 4, "ngFor", "ngForOf"], ["class", "fa fa-microphone pl-1", "container", "body", "placement", "top", "triggers", "mouseenter:mouseleave", "aria-hidden", "true", 3, "popover", 4, "ngIf"], ["class", "fa fa-random pl-1", "container", "body", "placement", "top", "triggers", "mouseenter:mouseleave", "aria-hidden", "true", 3, "popover", 4, "ngIf"], [1, "color"], ["container", "body", "placement", "top", "triggers", "mouseenter:mouseleave", "aria-hidden", "true", 1, "fa", "fa-microphone", "pl-1", 3, "popover"], ["container", "body", "placement", "top", "triggers", "mouseenter:mouseleave", "aria-hidden", "true", 1, "fa", "fa-random", "pl-1", 3, "popover"], [1, "col", "col-auto", "d-flex", "mx-auto", 2, "flex-direction", "column"], [1, "mb-2", "w-100", "d-flex"], ["type", "text", 1, "mx-auto", 2, "width", "45px", "height", "20px", "text-align", "center", "font-size", "12px", "font-family", "monospace", 3, "ngModelChange", "ngModel"], [1, "mx-auto", "mb-2"], [1, "h-100", "w-100", "d-flex"], [1, "mx-auto", 2, "height", "100%", 3, "change", "value", "orientation", "reversed", "tooltip", "min", "max", "step"], [1, "mx-auto", "mt-2"]], template: function FixtureCapabilityChannelComponent_Template(rf, ctx) { if (rf & 1) {
10149
10342
  i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4)(3, "div", 5)(4, "input", 6);
10150
10343
  i0.ɵɵlistener("ngModelChange", function FixtureCapabilityChannelComponent_Template_input_ngModelChange_4_listener($event) { return ctx.changeActive($event); });
10151
10344
  i0.ɵɵelementEnd();
@@ -10153,7 +10346,7 @@ class FixtureCapabilityChannelComponent {
10153
10346
  i0.ɵɵtext(6);
10154
10347
  i0.ɵɵelementEnd()()()();
10155
10348
  i0.ɵɵelementStart(7, "div", 8)(8, "div", 9);
10156
- i0.ɵɵtemplate(9, FixtureCapabilityChannelComponent_div_9_Template, 2, 1, "div", 10)(10, FixtureCapabilityChannelComponent_div_10_Template, 7, 10, "div", 11);
10349
+ i0.ɵɵtemplate(9, FixtureCapabilityChannelComponent_div_9_Template, 2, 1, "div", 10)(10, FixtureCapabilityChannelComponent_div_10_Template, 11, 12, "div", 11);
10157
10350
  i0.ɵɵelementEnd()()();
10158
10351
  } if (rf & 2) {
10159
10352
  i0.ɵɵclassProp("capability-deactivated", ctx.value == undefined);
@@ -10167,12 +10360,12 @@ class FixtureCapabilityChannelComponent {
10167
10360
  i0.ɵɵadvance(3);
10168
10361
  i0.ɵɵproperty("ngIf", (ctx._channel.capabilities == null ? null : ctx._channel.capabilities.length) > 1);
10169
10362
  i0.ɵɵadvance();
10170
- i0.ɵɵproperty("ngIf", ctx.capabilityHasRange());
10171
- } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.RadioControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i2.TranslatePipe], changeDetection: 0 }); }
10363
+ i0.ɵɵproperty("ngIf", ctx.hasRange);
10364
+ } }, dependencies: [i5.NgForOf, i5.NgIf, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.RadioControlValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.SliderComponent, i12.PopoverDirective, i2.TranslatePipe], styles: [".color[_ngcontent-%COMP%]{display:inline-block;margin-left:5px;border-radius:50%;width:12px;height:12px;border:1px white solid;vertical-align:middle}"], changeDetection: 0 }); }
10172
10365
  }
10173
10366
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FixtureCapabilityChannelComponent, [{
10174
10367
  type: Component,
10175
- args: [{ selector: 'lib-app-fixture-capability-channel', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card border-secondary h-100\" [class.capability-deactivated]=\"value == undefined\" style=\"min-height: 200px\">\n <div class=\"card-header\">\n <div class=\"my-auto\">\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"capabilityGeneric{{ capabilityIndex }}Active\"\n [ngModel]=\"value != undefined\"\n (ngModelChange)=\"changeActive($event)\"\n />\n <label class=\"form-check-label\" for=\"capabilityGeneric{{ capabilityIndex }}Active\">\n {{ _channel?.name }}\n </label>\n </div>\n </div>\n </div>\n\n <div class=\"card-body h-100 d-flex\" style=\"flex-direction: column; overflow: hidden\">\n <div class=\"row h-100\">\n <!-- display all options, if there is more than one -->\n <div *ngIf=\"_channel.capabilities?.length > 1\" class=\"col mr-3\" style=\"overflow-y: auto\">\n <div *ngFor=\"let capability of _channel.capabilities; let i = index\" class=\"form-check\">\n <input\n [(ngModel)]=\"selectedCapability\"\n (change)=\"capabilitySelected()\"\n class=\"form-check-input\"\n type=\"radio\"\n name=\"capabilityGeneric{{ capabilityIndex }}Option\"\n id=\"capabilityGeneric{{ capabilityIndex }}Option{{ i }}\"\n [value]=\"capability\"\n />\n <label style=\"max-width: 200px\" class=\"form-check-label\" for=\"capabilityGeneric{{ capabilityIndex }}Option{{ i }}\">\n {{ 'designer.fixtureCapabilityType.' + capability.capability.type | translate\n }}<small><span *ngIf=\"capability.capability.comment\"> - </span> {{ capability.capability.comment }}</small>\n </label>\n </div>\n </div>\n\n <!-- display a slider to select the value for the currently selected capability, if it has a range -->\n <div\n *ngIf=\"capabilityHasRange()\"\n class=\"col col-auto d-flex mx-auto\"\n [class.pl-0]=\"_channel.capabilities?.length > 1\"\n style=\"flex-direction: column\"\n >\n <div class=\"mb-4 w-100 d-flex\">\n <input\n #sliderValue\n class=\"mx-auto\"\n type=\"text\"\n [ngModel]=\"templateValue\"\n (ngModelChange)=\"setValue($event)\"\n style=\"width: 45px; height: 20px; text-align: center; font-size: 12px; font-family: monospace\"\n />\n </div>\n\n <div class=\"h-100 w-100 d-flex\">\n <mv-slider\n #slider\n class=\"mx-auto\"\n [value]=\"templateValue\"\n (change)=\"setValue($event.newValue)\"\n [orientation]=\"'vertical'\"\n [reversed]=\"true\"\n style=\"height: 100%\"\n [tooltip]=\"'hide'\"\n [min]=\"rangeMin\"\n [max]=\"rangeMax\"\n [step]=\"1\"\n ></mv-slider>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
10368
+ args: [{ selector: 'lib-app-fixture-capability-channel', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card border-secondary h-100\" [class.capability-deactivated]=\"value == undefined\" style=\"min-height: 200px\">\n <div class=\"card-header\">\n <div class=\"my-auto\">\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"capabilityGeneric{{ capabilityIndex }}Active\"\n [ngModel]=\"value != undefined\"\n (ngModelChange)=\"changeActive($event)\"\n />\n <label class=\"form-check-label\" for=\"capabilityGeneric{{ capabilityIndex }}Active\">\n {{ _channel?.name }}\n </label>\n </div>\n </div>\n </div>\n\n <div class=\"card-body h-100 d-flex\" style=\"flex-direction: column; overflow: hidden\">\n <div class=\"row h-100\">\n <!-- display all options, if there is more than one -->\n <div *ngIf=\"_channel.capabilities?.length > 1\" class=\"col mr-3\" style=\"overflow-y: auto\">\n <div *ngFor=\"let capability of _channel.capabilities; let i = index\" class=\"form-check\">\n <input\n [(ngModel)]=\"selectedCapability\"\n (change)=\"capabilitySelected()\"\n class=\"form-check-input\"\n type=\"radio\"\n name=\"capabilityGeneric{{ capabilityIndex }}Option\"\n id=\"capabilityGeneric{{ capabilityIndex }}Option{{ i }}\"\n [value]=\"capability\"\n />\n <label style=\"max-width: 200px\" class=\"form-check-label\" for=\"capabilityGeneric{{ capabilityIndex }}Option{{ i }}\">\n {{ 'designer.fixtureCapabilityType.' + capability.capability.type | translate\n }}<span *ngIf=\"getDescription(capability)\"> ({{ getDescription(capability) }})</span\n ><small\n ><div *ngFor=\"let color of capability.capability.colors\" class=\"color\" [style.background-color]=\"color\"></div>\n <small *ngIf=\"getDescriptionStart(capability)\">\n ({{ getDescriptionStart(capability) }} to {{ getDescriptionEnd(capability) }})</small\n >\n <span *ngIf=\"capability.capability.comment\"> - </span> {{ capability.capability.comment }}</small\n >\n <i\n *ngIf=\"capability.capability.soundControlled\"\n class=\"fa fa-microphone pl-1\"\n popover=\"{{ 'designer.fixture.capability-sound-controlled' | translate }}\"\n container=\"body\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n aria-hidden=\"true\"\n ></i>\n <i\n *ngIf=\"capability.capability.randomTiming\"\n class=\"fa fa-random pl-1\"\n popover=\"{{ 'designer.fixture.capability-random-timing' | translate }}\"\n container=\"body\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n aria-hidden=\"true\"\n ></i>\n </label>\n </div>\n </div>\n\n <!-- display a slider to select the value for the currently selected capability, if it has a range -->\n <div\n *ngIf=\"hasRange\"\n class=\"col col-auto d-flex mx-auto\"\n [class.pl-0]=\"_channel.capabilities?.length > 1\"\n style=\"flex-direction: column\"\n >\n <div class=\"mb-2 w-100 d-flex\">\n <input\n #sliderValue\n class=\"mx-auto\"\n type=\"text\"\n [ngModel]=\"templateValue\"\n (ngModelChange)=\"setValue($event)\"\n style=\"width: 45px; height: 20px; text-align: center; font-size: 12px; font-family: monospace\"\n />\n </div>\n\n <div class=\"mx-auto mb-2\">{{ descriptionEnd }}</div>\n\n <div class=\"h-100 w-100 d-flex\">\n <mv-slider\n #slider\n class=\"mx-auto\"\n [value]=\"templateValue\"\n (change)=\"setValue($event.newValue)\"\n [orientation]=\"'vertical'\"\n [reversed]=\"true\"\n style=\"height: 100%\"\n [tooltip]=\"'hide'\"\n [min]=\"rangeMin\"\n [max]=\"rangeMax\"\n [step]=\"1\"\n ></mv-slider>\n </div>\n\n <div class=\"mx-auto mt-2\">{{ descriptionStart }}</div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".color{display:inline-block;margin-left:5px;border-radius:50%;width:12px;height:12px;border:1px white solid;vertical-align:middle}\n"] }]
10176
10369
  }], () => [{ type: PresetService }], { sliderValue: [{
10177
10370
  type: ViewChild,
10178
10371
  args: ['sliderValue', { static: false }]
@@ -10763,16 +10956,16 @@ class DesignerComponent {
10763
10956
  .subscribe();
10764
10957
  }
10765
10958
  projectSave() {
10766
- if (this.projectService.project.name) {
10767
- // this project has been saved before -> just save it again
10768
- this.projectService.save(this.projectService.project);
10769
- }
10770
- else {
10771
- // this project has not yet been saved -> show the save as-dialog
10772
- this.userEnsureLoginService.login().subscribe(() => {
10959
+ this.userEnsureLoginService.login().subscribe(() => {
10960
+ if (this.projectService.project.name) {
10961
+ // this project has been saved before -> just save it again
10962
+ this.projectService.save(this.projectService.project);
10963
+ }
10964
+ else {
10965
+ // this project has not yet been saved -> show the save as-dialog
10773
10966
  this.modalService.show(ProjectSaveComponent, { keyboard: true, ignoreBackdropClick: false });
10774
- });
10775
- }
10967
+ }
10968
+ });
10776
10969
  }
10777
10970
  projectSaveAs() {
10778
10971
  this.userEnsureLoginService.login().subscribe(() => {