22 int numberOfSkins = 0;
36 return offset > 0 ? fo[qAbs(offset) - 1] : bo[qAbs(offset) - 1];
50 while (!channel->
keyframeAt(outFrame).isNull()) {
52 if (colorLabelFilter.isEmpty()) {
55 if (colorLabelFilter.contains(channel->
keyframeAt(outFrame)->colorLabel())) {
67 keyframe->writeFrameToDevice(gcFrame.
device());
84 backwardOpacities.resize(numberOfSkins);
85 forwardOpacities.resize(numberOfSkins);
90 for (
int i = 0; i < numberOfSkins; i++) {
94 backwardOpacities[i] = scaleFactor * backwardState * config.
onionSkinOpacity(-(i + 1));
95 forwardOpacities[i] = scaleFactor * forwardState * config.
onionSkinOpacity(i + 1);
102 int prevActiveTime,
int prevIgnoredTime,
103 int nowActiveTime,
int nowIgnoredTime);
115 m_d->refreshConfig();
123 return m_d->configSeqNo;
128 m_d->colorLabelFilter = colors;
133 return m_d->colorLabelFilter;
163 for (
int offset = 1; offset <=
m_d->numberOfSkins; offset++) {
167 if (!backKeyframe.isNull()) {
168 m_d->tryCompositeFrame(backKeyframe, gcFrame, gcDest, backwardTintDevice,
m_d->skinOpacity(-offset),
rect);
171 if (!forwardKeyframe.isNull()) {
172 m_d->tryCompositeFrame(forwardKeyframe, gcFrame, gcDest, forwardTintDevice,
m_d->skinOpacity(offset),
rect);
183 if (!channel)
return rect;
198 int keyframeTimeBack;
207 keyframeTimeBack = keyframeTimeFwd = time;
209 for (
int offset = 1; offset <=
m_d->numberOfSkins; offset++) {
243 int prevActiveTime,
int prevIgnoredTime,
244 int nowActiveTime,
int nowIgnoredTime)
248 std::vector<int> skinsBefore;
249 std::vector<int> skinsAfter;
252 std::vector<int> skinsLeft;
253 std::vector<int> skinsRight;
255 int keyframeTimeBck = activeTime;
256 int keyframeTimeFwd = activeTime;
258 auto addNextFrame = [channel,
this, ignoredFrame] (
int offset,
int &startTime, std::vector<int> &skins,
bool backwards) {
262 }
while (keyframe && startTime == ignoredFrame);
265 skins.push_back(startTime);
270 addNextFrame(offset, keyframeTimeBck, skinsLeft,
true);
271 addNextFrame(offset, keyframeTimeFwd, skinsRight,
false);
274 std::reverse(skinsLeft.begin(), skinsLeft.end());
275 skinsLeft.reserve(skinsLeft.size() + skinsRight.size());
276 std::copy(skinsRight.begin(), skinsRight.end(), std::back_inserter(skinsLeft));
281 skinsBefore = fetchSkins(channel, prevActiveTime, prevIgnoredTime);
282 skinsAfter = fetchSkins(channel, nowActiveTime, nowIgnoredTime);
284 std::vector<int> changedSkins;
286 std::set_symmetric_difference(skinsBefore.begin(), skinsBefore.end(),
287 skinsAfter.begin(), skinsAfter.end(),
288 std::back_inserter(changedSkins));
294 for (
auto it = changedSkins.begin(); it != changedSkins.end(); ++it) {
313 int prevActiveTime = -1;
315 if (currentActiveTime == addedTime) {
318 prevActiveTime = currentActiveTime;
321 rect =
m_d->updateExtentOnFrameChange(channel,
322 prevActiveTime, addedTime,
323 currentActiveTime, -1);
330 m_d->refreshConfig();
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
const quint8 OPACITY_TRANSPARENT_U8
const QString COMPOSITE_BEHIND
virtual int currentTime() const =0
int numberOfOnionSkins() const
QColor onionSkinTintColorBackward() const
int onionSkinOpacity(int offset, bool requestDefault=false) const
int onionSkinTintFactor() const
bool onionSkinState(int offset) const
QColor onionSkinTintColorForward() const
KisKeyframeChannel stores and manages KisKeyframes. Maps units of time to virtual keyframe values....
int previousKeyframeTime(const int time) const
int firstKeyframeTime() const
KisKeyframeSP keyframeAt(int time) const
Get a keyframe at specified time. Used primarily when the value of a given keyframe is needed.
int activeKeyframeTime(int time) const
Get the time of the active keyframe. Useful for snapping any time to that of the most recent keyframe...
int nextKeyframeTime(const int time) const
QRect calculateFullExtent(const KisPaintDeviceSP device)
void sigOnionSkinChanged()
QScopedPointer< Private > m_d
QRect calculateExtent(const KisPaintDeviceSP device, int time)
void setColorLabelFilter(QSet< int > colors)
QSet< int > colorLabelFilter()
~KisOnionSkinCompositor() override
QRect updateExtentOnAddition(const KisPaintDeviceSP device, int addedTime)
void composite(const KisPaintDeviceSP sourceDevice, KisPaintDeviceSP targetDevice, const QRect &rect)
static KisOnionSkinCompositor * instance()
KisRasterKeyframeChannel * keyframeChannel() const
void setDefaultPixel(const KoColor &defPixel)
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void setOpacityU8(quint8 opacity)
Set the opacity which is used in painting (like filling polygons)
void setChannelFlags(QBitArray channelFlags)
void setCompositeOpId(const KoCompositeOp *op)
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
QRect frameExtents(KisKeyframeSP keyframe)
The KisRasterKeyframe class is a concrete subclass of KisKeyframe that wraps a physical raster image ...
QBitArray channelFlags(bool color=true, bool alpha=false) const
const KoCompositeOp * compositeOp(const QString &id, const KoColorSpace *srcSpace=nullptr) const
#define KIS_SAFE_ASSERT_RECOVER(cond)
QSet< int > colorLabelFilter
QRect updateExtentOnFrameChange(KisRasterKeyframeChannel *channel, int prevActiveTime, int prevIgnoredTime, int nowActiveTime, int nowIgnoredTime)
void tryCompositeFrame(KisRasterKeyframeSP keyframe, KisPainter &gcFrame, KisPainter &gcDest, KisPaintDeviceSP tintSource, int opacity, const QRect &rect)
int skinOpacity(int offset)
QVector< int > backwardOpacities
KisRasterKeyframeSP getNextFrameToComposite(KisKeyframeChannel *channel, int &outFrame, bool backwards)
KisPaintDeviceSP setUpTintDevice(const QColor &tintColor, const KoColorSpace *colorSpace)
QVector< int > forwardOpacities