• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mcallegari / qlcplus / 19144422256

06 Nov 2025 05:33PM UTC coverage: 34.256% (-0.1%) from 34.358%
19144422256

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.62
/engine/src/efxfixture.cpp
1
/*
2
  Q Light Controller Plus
3
  efxfixture.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

8
  Licensed under the Apache License, Version 2.0 (the "License");
9
  you may not use this file except in compliance with the License.
10
  You may obtain a copy of the License at
11

12
      http://www.apache.org/licenses/LICENSE-2.0.txt
13

14
  Unless required by applicable law or agreed to in writing, software
15
  distributed under the License is distributed on an "AS IS" BASIS,
16
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
  See the License for the specific language governing permissions and
18
  limitations under the License.
19
*/
20

21
#include <QXmlStreamReader>
22
#include <QXmlStreamWriter>
23
#include <QDebug>
24
#include <math.h>
25

26
#include "genericfader.h"
27
#include "fadechannel.h"
28
#include "mastertimer.h"
29
#include "efxfixture.h"
30
#include "qlcmacros.h"
31
#include "function.h"
32
#include "universe.h"
33
#include "gradient.h"
34
#include "efx.h"
35
#include "doc.h"
36

37
/*****************************************************************************
38
 * Initialization
39
 *****************************************************************************/
40
QImage EFXFixture::m_rgbGradient = QImage();
41

42
EFXFixture::EFXFixture(const EFX* parent)
54✔
43
    : m_parent(parent)
54✔
44
    , m_head()
54✔
45
    , m_universe(Universe::invalid())
54✔
46
    , m_direction(Function::Forward)
54✔
47
    , m_startOffset(0)
54✔
48
    , m_mode(EFXFixture::PanTilt)
54✔
49

50
    , m_serialNumber(0)
54✔
51
    , m_runTimeDirection(Function::Forward)
54✔
52
    , m_done(false)
54✔
53
    , m_started(false)
54✔
54
    , m_elapsed(0)
54✔
55
    , m_currentAngle(0)
54✔
56

57
    , m_firstMsbChannel(QLCChannel::invalid())
54✔
58
    , m_firstLsbChannel(QLCChannel::invalid())
54✔
59
    , m_secondMsbChannel(QLCChannel::invalid())
54✔
60
    , m_secondLsbChannel(QLCChannel::invalid())
54✔
61
{
62
    Q_ASSERT(parent != NULL);
54✔
63

64
    if (m_rgbGradient.isNull ())
54✔
65
        m_rgbGradient = Gradient::getRGBGradient (256, 256);
3✔
66
}
54✔
67

68
void EFXFixture::copyFrom(const EFXFixture* ef)
7✔
69
{
70
    // Don't copy m_parent because it is already assigned in constructor and might
71
    // be different than $ef's
72
    m_head = ef->m_head;
7✔
73
    m_universe = ef->m_universe;
7✔
74
    m_direction = ef->m_direction;
7✔
75
    m_startOffset = ef->m_startOffset;
7✔
76
    m_mode = ef->m_mode;
7✔
77

78
    m_serialNumber = ef->m_serialNumber;
7✔
79
    m_runTimeDirection = ef->m_runTimeDirection;
7✔
80
    m_done = ef->m_done;
7✔
81
    m_started = ef->m_started;
7✔
82
    m_elapsed = ef->m_elapsed;
7✔
83
    m_currentAngle = ef->m_currentAngle;
7✔
84
}
7✔
85

86
EFXFixture::~EFXFixture()
53✔
87
{
88
}
53✔
89

90
/****************************************************************************
91
 * Public properties
92
 ****************************************************************************/
93

94
void EFXFixture::setHead(GroupHead const & head)
44✔
95
{
96
    m_head = head;
44✔
97

98
    Fixture *fxi = doc()->fixture(head.fxi);
44✔
99
    if (fxi == NULL)
44✔
100
        return;
30✔
101

102
    m_universe = fxi->universe();
14✔
103

104
    QList<Mode> modes;
14✔
105

106
    if (fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, head.head) != QLCChannel::invalid() ||
16✔
107
        fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, head.head) != QLCChannel::invalid())
2✔
108
        modes << PanTilt;
14✔
109

110
    if (fxi->masterIntensityChannel() != QLCChannel::invalid() ||
16✔
111
        fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head.head) != QLCChannel::invalid())
2✔
112
        modes << Dimmer;
12✔
113

114
    if (fxi->rgbChannels(head.head).size() >= 3)
14✔
115
        modes << RGB;
2✔
116

117
    if (!modes.contains(m_mode))
14✔
118
    {
119
        if (modes.size() > 0)
×
120
            m_mode = modes[0];
×
121
    }
122
}
14✔
123

124
GroupHead const & EFXFixture::head() const
941✔
125
{
126
    return m_head;
941✔
127
}
128

129
void EFXFixture::setDirection(Function::Direction dir)
18✔
130
{
131
    m_direction = dir;
18✔
132
    m_runTimeDirection = dir;
18✔
133
}
18✔
134

135
Function::Direction EFXFixture::direction() const
13✔
136
{
137
    return m_direction;
13✔
138
}
139

140
void EFXFixture::setStartOffset(int startOffset)
5✔
141
{
142
    m_startOffset = CLAMP(startOffset, 0, 359);
5✔
143
}
5✔
144

145
int EFXFixture::startOffset() const
9✔
146
{
147
    return m_startOffset;
9✔
148
}
149

150
void EFXFixture::setMode(Mode mode)
×
151
{
152
    m_mode = mode;
×
153
}
×
154

155
EFXFixture::Mode EFXFixture::mode() const
4✔
156
{
157
    return m_mode;
4✔
158
}
159

160
quint32 EFXFixture::universe()
156✔
161
{
162
    return m_universe;
156✔
163
}
164

165
bool EFXFixture::isValid() const
158✔
166
{
167
    Fixture *fxi = doc()->fixture(head().fxi);
158✔
168

169
    if (fxi == NULL)
158✔
170
        return false;
2✔
171
    else if (head().head >= fxi->heads())
156✔
172
        return false;
×
173
    else if (m_mode == PanTilt &&
468✔
174
             fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, head().head) == QLCChannel::invalid() && // Maybe a device can pan OR tilt
156✔
175
             fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, head().head) == QLCChannel::invalid())   // but not both
×
176
        return false;
×
177
    else if (m_mode == Dimmer &&
312✔
178
             fxi->masterIntensityChannel() == QLCChannel::invalid() &&
156✔
179
             fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head().head) == QLCChannel::invalid())
×
180
        return false;
×
181
    else if (m_mode == RGB && fxi->rgbChannels(head().head).size () == 0)
156✔
182
        return false;
×
183
    else
184
        return true;
156✔
185
}
186

187
void EFXFixture::durationChanged()
3✔
188
{
189
    if (m_elapsed == 0)
3✔
190
        return;
3✔
191

192
    // To avoid jumps when changing duration,
193
    // the elapsed time is rescaled to the
194
    // new duration.
195
    m_elapsed = SCALE(float(m_currentAngle),
×
196
            float(0), float(M_PI * 2),
197
            float(0), float(m_parent->loopDuration()));
198

199
    // Serial or Asymmetric propagation mode:
200
    // we must subtract the offset from the current position
201
    uint offset = timeOffset();
×
202
    if (offset)
×
203
    {
204
        if (m_elapsed < offset)
×
205
            m_elapsed += m_parent->loopDuration();
×
206
        m_elapsed -= offset;
×
207
    }
208
}
209

210
QStringList EFXFixture::modeList()
×
211
{
212
    Fixture* fxi = doc()->fixture(head().fxi);
×
213
    Q_ASSERT(fxi != NULL);
×
214

215
    QStringList modes;
×
216

217
    if (fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, head().head) != QLCChannel::invalid() ||
×
218
       fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, head().head) != QLCChannel::invalid())
×
219
        modes << KXMLQLCEFXFixtureModePanTilt;
×
220

221
    if (fxi->masterIntensityChannel() != QLCChannel::invalid() ||
×
222
       fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head().head) != QLCChannel::invalid())
×
223
        modes << KXMLQLCEFXFixtureModeDimmer;
×
224

225
    if (fxi->rgbChannels(head().head).size() >= 3)
×
226
        modes << KXMLQLCEFXFixtureModeRGB;
×
227

228
    return modes;
×
229
}
×
230

231
QString EFXFixture::modeToString(Mode mode)
×
232
{
233
    switch (mode)
×
234
    {
235
        default:
×
236
        case PanTilt:
237
            return QString(KXMLQLCEFXFixtureModePanTilt);
×
238
        case Dimmer:
×
239
            return QString(KXMLQLCEFXFixtureModeDimmer);
×
240
        case RGB:
×
241
            return QString(KXMLQLCEFXFixtureModeRGB);
×
242
    }
243
}
244

245
EFXFixture::Mode EFXFixture::stringToMode(const QString& str)
×
246
{
247
    if (str == QString(KXMLQLCEFXFixtureModePanTilt))
×
248
        return PanTilt;
×
249
    else if (str == QString(KXMLQLCEFXFixtureModeDimmer))
×
250
        return Dimmer;
×
251
    else if (str == QString(KXMLQLCEFXFixtureModeRGB))
×
252
        return RGB;
×
253
    else
254
        return PanTilt;
×
255
}
256

257
/*****************************************************************************
258
 * Load & Save
259
 *****************************************************************************/
260

261
bool EFXFixture::loadXML(QXmlStreamReader &root)
13✔
262
{
263
    if (root.name() != KXMLQLCEFXFixture)
13✔
264
    {
265
        qWarning("EFX Fixture node not found!");
1✔
266
        return false;
1✔
267
    }
268

269
    GroupHead head;
12✔
270
    head.head = 0;
12✔
271

272
    /* New file format contains sub tags */
273
    while (root.readNextStartElement())
38✔
274
    {
275
        if (root.name() == KXMLQLCEFXFixtureID)
26✔
276
        {
277
            /* Fixture ID */
278
            head.fxi = root.readElementText().toInt();
12✔
279
        }
280
        else if (root.name() == KXMLQLCEFXFixtureHead)
14✔
281
        {
282
            /* Fixture Head */
283
            head.head = root.readElementText().toInt();
1✔
284
        }
285
        else if (root.name() == KXMLQLCEFXFixtureMode)
13✔
286
        {
287
            /* Fixture Mode */
288
            setMode ((Mode) root.readElementText().toInt());
×
289
        }
290
        else if (root.name() == KXMLQLCEFXFixtureDirection)
13✔
291
        {
292
            /* Direction */
293
            Function::Direction dir = Function::stringToDirection(root.readElementText());
12✔
294
            setDirection(dir);
12✔
295
        }
296
        else if (root.name() == KXMLQLCEFXFixtureStartOffset)
1✔
297
        {
298
            /* Start offset */
299
            setStartOffset(root.readElementText().toInt());
×
300
        }
301
        else if (root.name() == KXMLQLCEFXFixtureIntensity)
1✔
302
        {
303
            /* Intensity - LEGACY */
304
            root.skipCurrentElement();
×
305
        }
306
        else
307
        {
308
            qWarning() << "Unknown EFX Fixture tag:" << root.name();
1✔
309
            root.skipCurrentElement();
1✔
310
        }
311
    }
312

313
    if (head.fxi != Fixture::invalidId())
12✔
314
       setHead(head);
12✔
315

316
    return true;
12✔
317
}
12✔
318

319
bool EFXFixture::saveXML(QXmlStreamWriter *doc) const
4✔
320
{
321
    Q_ASSERT(doc != NULL);
4✔
322

323
    /* EFXFixture */
324
    doc->writeStartElement(KXMLQLCEFXFixture);
8✔
325

326
    /* Fixture ID */
327
    doc->writeTextElement(KXMLQLCEFXFixtureID, QString("%1").arg(head().fxi));
8✔
328
    /* Fixture Head */
329
    doc->writeTextElement(KXMLQLCEFXFixtureHead, QString("%1").arg(head().head));
8✔
330
    /* Mode */
331
    doc->writeTextElement(KXMLQLCEFXFixtureMode, QString::number(mode()));
8✔
332
    /* Direction */
333
    doc->writeTextElement(KXMLQLCEFXFixtureDirection, Function::directionToString(m_direction));
8✔
334
    /* Start offset */
335
    doc->writeTextElement(KXMLQLCEFXFixtureStartOffset, QString::number(startOffset()));
8✔
336

337
    /* End the <Fixture> tag */
338
    doc->writeEndElement();
4✔
339

340
    return true;
4✔
341
}
342

343
/****************************************************************************
344
 * Run-time properties
345
 ****************************************************************************/
346

347
const Doc* EFXFixture::doc() const
521✔
348
{
349
    Q_ASSERT(m_parent != NULL);
521✔
350
    return m_parent->doc();
521✔
351
}
352

353
void EFXFixture::setSerialNumber(int number)
13✔
354
{
355
    m_serialNumber = number;
13✔
356
}
13✔
357

358
int EFXFixture::serialNumber() const
2✔
359
{
360
    return m_serialNumber;
2✔
361
}
362

363
void EFXFixture::reset()
10✔
364
{
365
    m_done = false;
10✔
366
    m_runTimeDirection = m_direction;
10✔
367
    m_started = false;
10✔
368
    m_elapsed = 0;
10✔
369
    m_currentAngle = 0;
10✔
370
}
10✔
371

372
bool EFXFixture::isDone() const
206✔
373
{
374
    return m_done;
206✔
375
}
376

377
uint EFXFixture::timeOffset() const
152✔
378
{
379
    if (m_parent->propagationMode() == EFX::Asymmetric ||
304✔
380
        m_parent->propagationMode() == EFX::Serial)
152✔
381
    {
382
        return m_parent->loopDuration() / (m_parent->fixtures().size() + 1) * serialNumber();
×
383
    }
384
    else
385
    {
386
        return 0;
152✔
387
    }
388
}
389

390
/*****************************************************************************
391
 * Running
392
 *****************************************************************************/
393

394
void EFXFixture::start(QSharedPointer<GenericFader> fader)
7✔
395
{
396
    Fixture *fxi = doc()->fixture(head().fxi);
7✔
397

398
    /* Cache channels to reduce processing while running */
399
    switch (m_mode)
7✔
400
    {
401
        case PanTilt:
7✔
402
        {
403
            m_firstMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, head().head);
7✔
404
            m_firstLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, head().head);
7✔
405
            m_secondMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, head().head);
7✔
406
            m_secondLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, head().head);
7✔
407

408
            /* Check for non-contiguous channels */
409
            if ((m_firstLsbChannel != QLCChannel::invalid() && m_firstLsbChannel - m_firstMsbChannel != 1) ||
13✔
410
                (m_secondLsbChannel != QLCChannel::invalid() && m_secondLsbChannel - m_secondMsbChannel != 1))
6✔
411
            {
412
                fader->setHandleSecondary(false);
1✔
413
            }
414
        }
415
        break;
7✔
416

417
        case RGB:
×
418
        break;
×
419

420
        case Dimmer:
×
421
        {
422
            m_firstMsbChannel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head().head);
×
423
            if (m_firstMsbChannel != QLCChannel::invalid())
×
424
            {
425
                m_firstLsbChannel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::LSB, head().head);
×
426

427
                /* Check for non-contiguous channels */
428
                if (m_firstLsbChannel != QLCChannel::invalid() && m_firstLsbChannel - m_firstMsbChannel != 1)
×
429
                {
430
                    fader->setHandleSecondary(false);
×
431
                }
432
            }
433
            else
434
            {
435
                m_firstMsbChannel = fxi->masterIntensityChannel();
×
436
            }
437
        }
438
        break;
×
439
    }
440
    m_started = true;
7✔
441
}
7✔
442

443
void EFXFixture::stop()
5✔
444
{
445
    m_started = false;
5✔
446
}
5✔
447

448
void EFXFixture::nextStep(QList<Universe *> universes, QSharedPointer<GenericFader> fader)
202✔
449
{
450
    // Nothing to do
451
    if (m_parent->loopDuration() == 0)
202✔
452
        return;
50✔
453

454
    // Bail out without doing anything if this fixture is ready (after single-shot)
455
    // or it has no pan&tilt channels (not valid).
456
    if (m_done == true || isValid() == false)
152✔
457
        return;
×
458

459
    m_elapsed += MasterTimer::tick();
152✔
460

461
    // Check time wrapping
462
    if (m_elapsed > m_parent->loopDuration())
152✔
463
    {
464
        if (m_parent->runOrder() == Function::PingPong)
2✔
465
        {
466
            /* Reverse direction for ping-pong EFX. */
467
            if (m_runTimeDirection == Function::Forward)
×
468
                m_runTimeDirection = Function::Backward;
×
469
            else
470
                m_runTimeDirection = Function::Forward;
×
471
        }
472
        else if (m_parent->runOrder() == Function::SingleShot)
2✔
473
        {
474
            /* De-initialize the fixture and mark as ready. */
475
            m_done = true;
1✔
476
            stop();
1✔
477
        }
478

479
        m_elapsed = 0;
2✔
480
    }
481

482
    // Bail out without doing anything if this fixture is waiting for its turn.
483
    if (m_parent->propagationMode() == EFX::Serial && m_elapsed < timeOffset() && !m_started)
152✔
484
        return;
×
485

486
    // Fade in
487
    if (m_started == false)
152✔
488
        start(fader);
3✔
489

490
    // Scale from elapsed time in relation to overall duration to a point in a circle
491
    uint pos = (m_elapsed + timeOffset()) % m_parent->loopDuration();
152✔
492
    m_currentAngle = SCALE(float(pos),
152✔
493
                           float(0), float(m_parent->loopDuration()),
494
                           float(0), float(M_PI * 2));
495

496
    float valX = 0;
152✔
497
    float valY = 0;
152✔
498

499
    m_parent->calculatePoint(m_runTimeDirection, m_startOffset, m_currentAngle, &valX, &valY);
152✔
500

501
    /* Set target values on faders/universes */
502
    switch (m_mode)
152✔
503
    {
504
        case PanTilt:
152✔
505
            setPointPanTilt(universes, fader, valX, valY);
152✔
506
        break;
152✔
507

508
        case RGB:
×
509
            setPointRGB(universes, fader, valX, valY);
×
510
        break;
×
511

512
        case Dimmer:
×
513
            //Use Y for coherence with RGB gradient.
514
            setPointDimmer(universes, fader, valY);
×
515
        break;
×
516
    }
517
}
518

519
void EFXFixture::updateFaderValues(FadeChannel *fc, quint32 value)
312✔
520
{
521
    fc->setStart(fc->current());
312✔
522
    fc->setTarget(value);
312✔
523
    fc->setElapsed(0);
312✔
524
    fc->setReady(false);
312✔
525
    fc->setFadeTime(0);
312✔
526
}
312✔
527

528
void EFXFixture::setPointPanTilt(QList<Universe *> universes, QSharedPointer<GenericFader> fader,
156✔
529
                                 float pan, float tilt)
530
{
531
    if (fader.isNull())
156✔
532
        return;
×
533

534
    Universe *uni = universes[universe()];
156✔
535

536
    //qDebug() << "Pan value: " << pan << ", tilt value:" << tilt;
537

538
    /* Check for outbound values */
539
    if (pan < 0)
156✔
540
        pan = 0;
×
541

542
    if (tilt < 0)
156✔
543
        tilt = 0;
×
544

545
    /* Write full 16bit point data to universes */
546
    if (m_firstMsbChannel != QLCChannel::invalid())
156✔
547
    {
548
        quint32 panValue = quint32(pan);
155✔
549
        FadeChannel *fc = fader->getChannelFader(doc(), uni, head().fxi, m_firstMsbChannel);
155✔
550
        if (m_firstLsbChannel != QLCChannel::invalid())
155✔
551
        {
552
            if (fader->handleSecondary())
1✔
553
            {
554
                fc = fader->getChannelFader(doc(), uni, head().fxi, m_firstLsbChannel);
×
555
                panValue = (panValue << 8) + quint32((pan - floor(pan)) * float(UCHAR_MAX));
×
556
            }
557
            else
558
            {
559
                FadeChannel *lsbFc = fader->getChannelFader(doc(), uni, head().fxi, m_firstLsbChannel);
1✔
560
                updateFaderValues(lsbFc, quint32((pan - floor(pan)) * float(UCHAR_MAX)));
1✔
561
            }
562
        }
563
        if (m_parent->isRelative())
155✔
564
            fc->addFlag(FadeChannel::Relative);
×
565

566
        updateFaderValues(fc, panValue);
155✔
567
    }
568
    if (m_secondMsbChannel != QLCChannel::invalid())
156✔
569
    {
570
        quint32 tiltValue = quint32(tilt);
155✔
571
        FadeChannel *fc = fader->getChannelFader(doc(), uni, head().fxi, m_secondMsbChannel);
155✔
572
        if (m_secondLsbChannel != QLCChannel::invalid())
155✔
573
        {
574
            if (fader->handleSecondary())
1✔
575
            {
576
                fc = fader->getChannelFader(doc(), uni, head().fxi, m_secondLsbChannel);
×
577
                tiltValue = (tiltValue << 8) + quint32((tilt - floor(tilt)) * float(UCHAR_MAX));
×
578
            }
579
            else
580
            {
581
                FadeChannel *lsbFc = fader->getChannelFader(doc(), uni, head().fxi, m_secondLsbChannel);
1✔
582
                updateFaderValues(lsbFc, quint32((tilt - floor(tilt)) * float(UCHAR_MAX)));
1✔
583
            }
584
        }
585
        if (m_parent->isRelative())
155✔
586
            fc->addFlag(FadeChannel::Relative);
×
587

588
        updateFaderValues(fc, tiltValue);
155✔
589
    }
590
}
591

592
void EFXFixture::setPointDimmer(QList<Universe *> universes, QSharedPointer<GenericFader> fader, float dimmer)
×
593
{
594
    if (fader.isNull())
×
595
        return;
×
596

597
    Universe *uni = universes[universe()];
×
598

599
    /* Don't write dimmer data directly to universes but use FadeChannel to avoid steps at EFX loop restart */
600
    if (m_firstMsbChannel != QLCChannel::invalid())
×
601
    {
602
        quint32 dimmerValue = quint32(dimmer);
×
603
        FadeChannel *fc = fader->getChannelFader(doc(), uni, head().fxi, m_firstMsbChannel);
×
604

605
        if (m_firstLsbChannel != QLCChannel::invalid())
×
606
        {
607
            if (fader->handleSecondary())
×
608
            {
609
                fc = fader->getChannelFader(doc(), uni, head().fxi, m_firstLsbChannel);
×
610
                dimmerValue = (dimmerValue << 8) + quint32((dimmer - floor(dimmer)) * float(UCHAR_MAX));
×
611
            }
612
        }
613
        updateFaderValues(fc, dimmerValue);
×
614
    }
615
}
616

617
void EFXFixture::setPointRGB(QList<Universe *> universes, QSharedPointer<GenericFader> fader, float x, float y)
×
618
{
619
    if (fader.isNull())
×
620
        return;
×
621

622
    Fixture* fxi = doc()->fixture(head().fxi);
×
623
    Q_ASSERT(fxi != NULL);
×
624
    Universe *uni = universes[universe()];
×
625

626
    QVector<quint32> rgbChannels = fxi->rgbChannels(head().head);
×
627

628
    /* Don't write dimmer data directly to universes but use FadeChannel to avoid steps at EFX loop restart */
629
    if (rgbChannels.size() >= 3 && !fader.isNull())
×
630
    {
631
        QColor pixel = m_rgbGradient.pixel(x, y);
×
632

633
        FadeChannel *fc = fader->getChannelFader(doc(), uni, fxi->id(), rgbChannels[0]);
×
634
        updateFaderValues(fc, pixel.red());
×
635
        fc = fader->getChannelFader(doc(), uni, fxi->id(), rgbChannels[1]);
×
636
        updateFaderValues(fc, pixel.green());
×
637
        fc = fader->getChannelFader(doc(), uni, fxi->id(), rgbChannels[2]);
×
638
        updateFaderValues(fc, pixel.blue());
×
639
    }
640
}
×
641

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc