Krita Source Code Documentation
Loading...
Searching...
No Matches
KisLayerUtils Namespace Reference

Namespaces

namespace  Private
 

Classes

struct  ActivateSelectionMask
 
struct  AddNewFrame
 
struct  CleanUpNodes
 
struct  ConvertToPaintLayerInfo
 
struct  CreateMergedLayer
 
struct  CreateMergedLayerMultiple
 
struct  DisableColorizeKeyStrokes
 
struct  DisableExtraCompositing
 
struct  DisableOnionSkins
 
struct  DisablePassThroughForHeadsOnly
 
struct  EphemeralCommandsWrapper
 
struct  FillSelectionMasks
 
struct  InitSplitAlphaSelectionMask
 
struct  InsertNode
 
struct  KeepMergedNodesSelected
 
class  KeepNodesSelectedCommand
 
class  KisSimpleUpdateCommand
 
struct  MergeDownInfo
 
struct  MergeDownInfoBase
 
struct  MergeLayers
 
struct  MergeLayersMultiple
 
struct  MergeMetaData
 
struct  MergeMultipleInfo
 
struct  MergeSelectionMasks
 
struct  RefreshDelayedUpdateLayers
 
struct  RefreshHiddenAreas
 
class  RemoveNodeHelper
 
struct  SelectGlobalSelectionMask
 
struct  SimpleAddNode
 
struct  SimpleRemoveLayers
 
struct  SplitAlphaCommand
 
struct  SplitAlphaToMaskInfo
 
struct  SwitchFrameCommand
 The SwitchFrameCommand struct Switches to frame with undo/redo support. More...
 
struct  UndoEphemeralCommands
 
struct  UploadProjectionToFrameCommand
 

Typedefs

typedef QSharedPointer< ConvertToPaintLayerInfoConvertToPaintLayerInfoSP
 
typedef QMap< int, QSet< KisNodeSP > > FrameJobs
 
typedef QSharedPointer< MergeDownInfoBaseMergeDownInfoBaseSP
 
typedef QSharedPointer< MergeDownInfoMergeDownInfoSP
 
typedef QSharedPointer< MergeMultipleInfoMergeMultipleInfoSP
 
typedef QSharedPointer< SplitAlphaToMaskInfoSplitAlphaToMaskInfoSP
 

Enumerations

enum  MergeFlag { None , SkipMergingFrames = 0x1 }
 

Functions

void addCopyOfNameTag (KisNodeSP node)
 
bool canChangeImageProfileInvisibly (KisImageSP image)
 
void changeImageDefaultProjectionColor (KisImageSP image, const KoColor &color)
 
bool checkIsChildOf (KisNodeSP node, const KisNodeList &parents)
 
bool checkIsCloneOf (KisNodeSP node, const KisNodeList &nodes)
 
template<typename T >
bool checkNodesDiffer (KisNodeList nodes, std::function< T(KisNodeSP)> checkerFunc)
 
std::future< KisNodeSPconvertToPaintLayer (KisImageSP image, KisNodeSP src)
 
int fetchLayerActiveRasterFrameID (KisNodeSP node)
 
KisTimeSpan fetchLayerActiveRasterFrameSpan (KisNodeSP node, const int time)
 
int fetchLayerActiveRasterFrameTime (KisNodeSP node)
 
QSet< int > fetchLayerFrames (KisNodeSP node)
 
QSet< int > fetchLayerFramesRecursive (KisNodeSP rootNode)
 
QSet< int > fetchLayerIdenticalRasterFrameTimes (KisNodeSP node, const int &frameTime)
 
QSet< int > fetchLayerRasterFrameTimesMatchingID (KisNodeSP node, const int frameID)
 
QSet< int > fetchLayerRasterIDsAtTimes (KisNodeSP node, const QSet< int > &times)
 
QSet< int > fetchLayerUniqueRasterTimesMatchingIDs (KisNodeSP node, QSet< int > &frameIDs)
 
void fetchSelectionMasks (KisNodeList mergedNodes, QVector< KisSelectionMaskSP > &selectionMasks)
 
QSet< int > fetchUniqueFrameTimes (KisNodeSP node, QSet< int > selectedTimes, bool filterActiveFrameID)
 
KisNodeList filterInvisibleNodes (const KisNodeList &nodes, KisNodeList *invisibleNodes, KisNodeSP *putAfter)
 
void filterMergeableNodes (KisNodeList &nodes, bool allowMasks)
 
QSet< int > filterTimesForOnlyRasterKeyedTimes (KisNodeSP node, const QSet< int > &times)
 
void filterUnlockedNodes (KisNodeList &nodes)
 
KisImageSP findImageByHierarchy (KisNodeSP node)
 
KisNodeSP findIsolationRoot (KisNodeSP node)
 
KisNodeSP findNodeByName (KisNodeSP root, const QString &name)
 
template<class T >
T * findNodeByType (KisNodeSP root)
 
KisNodeSP findNodeByUuid (KisNodeSP root, const QUuid &uuid)
 
QList< KisNodeSPfindNodesByName (KisNodeSP root, const QString &name, bool recursive, bool partialMatch)
 
KisNodeList findNodesWithProps (KisNodeSP root, const KoProperties &props, bool excludeRoot)
 
KisNodeSP findRoot (KisNodeSP node)
 
void flattenImage (KisImageSP image, KisNodeSP activeNode, MergeFlags flags)
 
void flattenLayer (KisImageSP image, KisLayerSP layer, MergeFlags flags)
 
void forceAllDelayedNodesUpdate (KisNodeSP root)
 
void forceAllHiddenOriginalsUpdate (KisNodeSP root)
 
bool hasDelayedNodeWithUpdates (KisNodeSP root)
 
void mergeDown (KisImageSP image, KisLayerSP layer, const KisMetaData::MergeStrategy *strategy, MergeFlags flags)
 
void mergeMultipleLayers (KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, MergeFlags flags)
 
void mergeMultipleLayersImpl (KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, bool flattenSingleLayer, const KUndo2MagicString &actionName, bool cleanupNodes=true, const QString layerName=QString(), MergeFlags flags=None)
 
void mergeMultipleNodes (KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, MergeFlags flags)
 
void newLayerFromVisible (KisImageSP image, KisNodeSP putAfter, MergeFlags flags)
 
template<typename NodePointer , typename Functor >
void recursiveApplyNodes (NodePointer node, Functor func)
 
KisNodeSP recursiveFindNode (KisNodeSP node, std::function< bool(KisNodeSP)> func)
 
QRect recursiveTightNodeVisibleBounds (KisNodeSP rootNode)
 
void refreshHiddenAreaAsync (KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea)
 
KisNodeList sortAndFilterAnyMergeableNodesSafe (const KisNodeList &nodes, KisImageSP image)
 
KisNodeList sortAndFilterMergeableInternalNodes (KisNodeList nodes, bool allowMasks)
 
KisNodeList sortMergeableInternalNodes (KisNodeList nodes)
 
void sortMergeableNodes (KisNodeSP root, KisNodeList &inputNodes, KisNodeList &outputNodes)
 
KisNodeList sortMergeableNodes (KisNodeSP root, KisNodeList nodes)
 
KRITAIMAGE_EXPORT void sortMergeableNodes (KisNodeSP root, QList< KisNodeSP > &inputNodes, QList< KisNodeSP > &outputNodes)
 
void splitAlphaToMask (KisImageSP image, KisNodeSP node, const QString &maskName)
 
void splitNonRemovableNodes (KisNodeList &nodesToRemove, KisNodeList &_nodesToHide)
 
bool tryMergeSelectionMasks (KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter)
 
void updateFrameJobs (FrameJobs *jobs, KisNodeSP node)
 
void updateFrameJobsNonRecursive (FrameJobs *jobs, KisNodeSP rootNode, bool frameTimesRecursive=false)
 updateFrameJobsNonRecursive updates the frame jobs non-recursively, that is, on the rootNode only.
 
void updateFrameJobsRecursive (FrameJobs *jobs, KisNodeSP rootNode)
 

Typedef Documentation

◆ ConvertToPaintLayerInfoSP

◆ FrameJobs

typedef QMap<int, QSet<KisNodeSP> > KisLayerUtils::FrameJobs

Definition at line 94 of file kis_layer_utils.h.

◆ MergeDownInfoBaseSP

◆ MergeDownInfoSP

◆ MergeMultipleInfoSP

◆ SplitAlphaToMaskInfoSP

Enumeration Type Documentation

◆ MergeFlag

Enumerator
None 
SkipMergingFrames 

Definition at line 31 of file kis_layer_utils.h.

31 {
32 None,
34 };

Function Documentation

◆ addCopyOfNameTag()

KRITAIMAGE_EXPORT void KisLayerUtils::addCopyOfNameTag ( KisNodeSP node)

Definition at line 1757 of file kis_layer_utils.cpp.

1758 {
1759 if (!KisImageConfig(true).renameDuplicatedLayers()) { return; }
1760
1761 const QString prefix = i18n("Copy of");
1762 QString newName = node->name();
1763 if (!newName.startsWith(prefix)) {
1764 newName = QString("%1 %2").arg(prefix).arg(newName);
1765 node->setName(newName);
1766 }
1767 }
void setName(const QString &name)
QString name() const

References KisBaseNode::name(), and KisBaseNode::setName().

◆ canChangeImageProfileInvisibly()

KRITAIMAGE_EXPORT bool KisLayerUtils::canChangeImageProfileInvisibly ( KisImageSP image)

Definition at line 2397 of file kis_layer_utils.cpp.

2398 {
2399 int numLayers = 0;
2400 bool hasNonNormalLayers = false;
2401 bool hasTransparentLayer = false;
2402
2403
2404 recursiveApplyNodes(image->root(),
2405 [&numLayers, &hasNonNormalLayers, &hasTransparentLayer, image] (KisNodeSP node) {
2406 if (!node->inherits("KisLayer")) return;
2407
2408 numLayers++;
2409
2410 if (node->exactBounds().isEmpty()) return;
2411
2412 // this is only an approximation! it is not exact!
2413 if (!hasTransparentLayer &&
2414 node->exactBounds() != image->bounds()) {
2415
2416 hasTransparentLayer = true;
2417 }
2418
2419 if (!hasNonNormalLayers &&
2420 node->compositeOpId() != COMPOSITE_OVER) {
2421
2422 hasNonNormalLayers = true;
2423 }
2424 });
2425
2426 return numLayers == 1 || (!hasNonNormalLayers && !hasTransparentLayer);
2427 }
const QString COMPOSITE_OVER
void recursiveApplyNodes(NodePointer node, Functor func)
const QString & compositeOpId() const

References COMPOSITE_OVER, KisBaseNode::compositeOpId(), recursiveApplyNodes(), and KisNodeFacade::root.

◆ changeImageDefaultProjectionColor()

KRITAIMAGE_EXPORT void KisLayerUtils::changeImageDefaultProjectionColor ( KisImageSP image,
const KoColor & color )

◆ checkIsChildOf()

KRITAIMAGE_EXPORT bool KisLayerUtils::checkIsChildOf ( KisNodeSP node,
const KisNodeList & parents )

Definition at line 1593 of file kis_layer_utils.cpp.

1594 {
1595 KisNodeList nodeParents;
1596
1597 KisNodeSP parent = node->parent();
1598 while (parent) {
1599 nodeParents << parent;
1600 parent = parent->parent();
1601 }
1602
1603 foreach(KisNodeSP perspectiveParent, parents) {
1604 if (nodeParents.contains(perspectiveParent)) {
1605 return true;
1606 }
1607 }
1608
1609 return false;
1610 }
KisNodeWSP parent
Definition kis_node.cpp:86

References KisNode::parent.

◆ checkIsCloneOf()

KRITAIMAGE_EXPORT bool KisLayerUtils::checkIsCloneOf ( KisNodeSP node,
const KisNodeList & nodes )

Returns true if: o node is a clone of some layer in nodes o node is a clone any child layer of any layer in nodes o node is a clone of a clone of a ..., that in the end points to any layer in nodes of their children.

Definition at line 1612 of file kis_layer_utils.cpp.

1613 {
1614 bool result = false;
1615
1616 KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node.data());
1617 if (clone) {
1618 KisNodeSP cloneSource = KisNodeSP(clone->copyFrom());
1619
1620 Q_FOREACH(KisNodeSP subtree, nodes) {
1621 result =
1622 recursiveFindNode(subtree,
1623 [cloneSource](KisNodeSP node) -> bool
1624 {
1625 return node == cloneSource;
1626 });
1627
1628 if (!result) {
1629 result = checkIsCloneOf(cloneSource, nodes);
1630 }
1631
1632 if (result) {
1633 break;
1634 }
1635 }
1636 }
1637
1638 return result;
1639 }
KisSharedPtr< KisNode > KisNodeSP
Definition kis_types.h:86
KisNodeSP recursiveFindNode(KisNodeSP node, std::function< bool(KisNodeSP)> func)
KisLayerSP copyFrom

References checkIsCloneOf(), KisCloneLayer::copyFrom, KisSharedPtr< T >::data(), and recursiveFindNode().

◆ checkNodesDiffer()

template<typename T >
bool KisLayerUtils::checkNodesDiffer ( KisNodeList nodes,
std::function< T(KisNodeSP)> checkerFunc )

Definition at line 220 of file kis_layer_utils.h.

221 {
222 bool valueDiffers = false;
223 bool initialized = false;
224 T currentValue = T();
225 Q_FOREACH (KisNodeSP node, nodes) {
226 if (!initialized) {
227 currentValue = checkerFunc(node);
228 initialized = true;
229 } else if (currentValue != checkerFunc(node)) {
230 valueDiffers = true;
231 break;
232 }
233 }
234 return valueDiffers;
235 }

◆ convertToPaintLayer()

KRITAIMAGE_EXPORT std::future< KisNodeSP > KisLayerUtils::convertToPaintLayer ( KisImageSP image,
KisNodeSP src )

Definition at line 2454 of file kis_layer_utils.cpp.

2455 {
2456 //Initialize all operation dependencies.
2457 ConvertToPaintLayerInfoSP info( new ConvertToPaintLayerInfo(image, src) );
2458
2459 if (!info->hasTargetNode())
2461
2462 KisImageSignalVector emitSignals;
2463 KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE, emitSignals, kundo2_i18n("Convert to a Paint Layer"));
2464
2465 applicator.applyCommand(new SimpleAddNode(info->image(), info->targetNode(), info->insertionParent(), info->insertionPutAfter()), KisStrokeJobData::BARRIER);
2466
2467 if (info->frames().count() > 0) {
2468 Q_FOREACH(const int& frame, info->frames()) {
2469 applicator.applyCommand(new SwitchFrameCommand(info->image(), frame, false, info->storage));
2470 applicator.applyCommand(new RefreshDelayedUpdateLayers(info->sourceNodes()), KisStrokeJobData::BARRIER);
2471 applicator.applyCommand(new RefreshHiddenAreas(info->image(), info->sourceNode()), KisStrokeJobData::BARRIER);
2472 applicator.applyCommand(new AddNewFrame(info->targetNode(), frame, info->sourceNode()), KisStrokeJobData::BARRIER);
2473 applicator.applyCommand(new UploadProjectionToFrameCommand(info->sourceNode(), info->targetNode(), frame));
2474 applicator.applyCommand(new SwitchFrameCommand(info->image(), frame, true, info->storage));
2475 }
2476 }
2477
2478 applicator.applyCommand(new SimpleRemoveLayers(info->toRemove(), info->image()));
2479
2480 applicator.end();
2481
2482 return kismpl::then(applicator.successfullyCompletedFuture(),
2483 [node = info->targetNode()] (std::future<bool> completed) {
2484 return completed.get() ? node : KisNodeSP();
2485 });
2486 }
auto then(std::future< T > &&future, Function &&func) -> std::future< decltype(func(std::move(future)))>
std::future< void > make_ready_future()
The SwitchFrameCommand struct Switches to frame with undo/redo support.

References KisProcessingApplicator::applyCommand(), KisStrokeJobData::BARRIER, KisProcessingApplicator::end(), kundo2_i18n(), kismpl::make_ready_future(), KisProcessingApplicator::NONE, KisProcessingApplicator::successfullyCompletedFuture(), and kismpl::then().

◆ fetchLayerActiveRasterFrameID()

int KisLayerUtils::fetchLayerActiveRasterFrameID ( KisNodeSP node)

Definition at line 2490 of file kis_layer_utils.cpp.

2491 {
2493 KisPaintDeviceSP paintDevice = node->paintDevice();
2494 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, -1);
2495
2496 if (!paintDevice->keyframeChannel()) {
2497 return -1;
2498 }
2499
2500 const int activeTime = paintDevice->keyframeChannel()->activeKeyframeTime();
2501 KisRasterKeyframeSP keyframe = paintDevice->keyframeChannel()->activeKeyframeAt<KisRasterKeyframe>(activeTime);
2503
2504 return keyframe->frameID();
2505 }
KisKeyframeSP activeKeyframeAt(int time) const
int activeKeyframeTime(int time) const
Get the time of the active keyframe. Useful for snapping any time to that of the most recent keyframe...
KisRasterKeyframeChannel * keyframeChannel() const
The KisRasterKeyframe class is a concrete subclass of KisKeyframe that wraps a physical raster image ...
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
virtual KisPaintDeviceSP paintDevice() const =0

References KisKeyframeChannel::activeKeyframeAt(), KisKeyframeChannel::activeKeyframeTime(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchLayerActiveRasterFrameSpan()

KRITAIMAGE_EXPORT KisTimeSpan KisLayerUtils::fetchLayerActiveRasterFrameSpan ( KisNodeSP node,
const int time )

Definition at line 2520 of file kis_layer_utils.cpp.

2521 {
2523 KisPaintDeviceSP paintDevice = node->paintDevice();
2525 if (!paintDevice->keyframeChannel()) {
2526 return KisTimeSpan::infinite(0);
2527 }
2528
2529 return paintDevice->keyframeChannel()->affectedFrames(time);
2530 }
virtual KisTimeSpan affectedFrames(int time) const
Get the set of frames affected by any changes to the value or content of the active keyframe at the g...
static KisTimeSpan infinite(int start)

References KisKeyframeChannel::affectedFrames(), KisTimeSpan::infinite(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchLayerActiveRasterFrameTime()

KRITAIMAGE_EXPORT int KisLayerUtils::fetchLayerActiveRasterFrameTime ( KisNodeSP node)

Definition at line 2507 of file kis_layer_utils.cpp.

2508 {
2510 KisPaintDeviceSP paintDevice = node->paintDevice();
2511 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, -1);
2512
2513 if (!paintDevice->keyframeChannel()) {
2514 return -1;
2515 }
2516
2517 return paintDevice->keyframeChannel()->activeKeyframeTime();
2518 }

References KisKeyframeChannel::activeKeyframeTime(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchLayerFrames()

KRITAIMAGE_EXPORT QSet< int > KisLayerUtils::fetchLayerFrames ( KisNodeSP node)

Definition at line 1375 of file kis_layer_utils.cpp.

1375 {
1376 QSet<int> frames;
1377 Q_FOREACH(KisKeyframeChannel *channel, node->keyframeChannels()) {
1378 if (!channel) {
1379 continue;
1380 }
1381
1382 KisRasterKeyframeChannel *rasterChan = dynamic_cast<KisRasterKeyframeChannel*>(channel);
1383 if (rasterChan) {
1384 frames.unite(rasterChan->allKeyframeTimes());
1385 continue;
1386 }
1387
1388 KisScalarKeyframeChannel *scalarChan = dynamic_cast<KisScalarKeyframeChannel*>(channel);
1389 if (scalarChan) {
1390 const int initialKeyframe = scalarChan->firstKeyframeTime();
1391
1392 if (initialKeyframe == -1) {
1393 continue;
1394 }
1395
1396 const int lastKeyframe = scalarChan->lastKeyframeTime();
1397 KisTimeSpan currentSpan = scalarChan->identicalFrames(initialKeyframe);
1398 while (!currentSpan.isInfinite() && currentSpan.isValid() && currentSpan.start() < lastKeyframe) {
1399 frames.insert(currentSpan.start());
1400 currentSpan = scalarChan->identicalFrames(currentSpan.end() + 1);
1401 }
1402
1403 frames.insert(lastKeyframe);
1404 }
1405
1406 }
1407
1408 return frames;
1409 }
KisKeyframeChannel stores and manages KisKeyframes. Maps units of time to virtual keyframe values....
QSet< int > allKeyframeTimes() const
Get a set of all integer times that map to a keyframe.
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
The KisScalarKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisSca...
virtual KisTimeSpan identicalFrames(int time) const override
Get a span of times for which the channel gives identical results compared to frame at a given time....
int start() const
bool isInfinite() const
int end() const
bool isValid() const
QMap< QString, KisKeyframeChannel * > keyframeChannels

References KisKeyframeChannel::allKeyframeTimes(), KisTimeSpan::end(), KisKeyframeChannel::firstKeyframeTime(), KisScalarKeyframeChannel::identicalFrames(), KisTimeSpan::isInfinite(), KisTimeSpan::isValid(), KisBaseNode::keyframeChannels, KisKeyframeChannel::lastKeyframeTime(), and KisTimeSpan::start().

◆ fetchLayerFramesRecursive()

KRITAIMAGE_EXPORT QSet< int > KisLayerUtils::fetchLayerFramesRecursive ( KisNodeSP rootNode)

Definition at line 1411 of file kis_layer_utils.cpp.

1411 {
1412 if (!rootNode->visible()) return QSet<int>();
1413
1414 QSet<int> frames = fetchLayerFrames(rootNode);
1415
1416 KisNodeSP node = rootNode->firstChild();
1417 while(node) {
1418 frames |= fetchLayerFramesRecursive(node);
1419 node = node->nextSibling();
1420 }
1421
1422 return frames;
1423 }
QSet< int > fetchLayerFrames(KisNodeSP node)
QSet< int > fetchLayerFramesRecursive(KisNodeSP rootNode)
virtual bool visible(bool recursive=false) const
KisNodeSP firstChild() const
Definition kis_node.cpp:361
KisNodeSP nextSibling() const
Definition kis_node.cpp:408

References fetchLayerFrames(), fetchLayerFramesRecursive(), KisNode::firstChild(), KisNode::nextSibling(), and KisBaseNode::visible().

◆ fetchLayerIdenticalRasterFrameTimes()

KRITAIMAGE_EXPORT QSet< int > KisLayerUtils::fetchLayerIdenticalRasterFrameTimes ( KisNodeSP node,
const int & frameTime )

Definition at line 2532 of file kis_layer_utils.cpp.

2533 {
2534 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(node, QSet<int>());
2535 KisPaintDeviceSP paintDevice = node->paintDevice();
2536 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, QSet<int>());
2537 if (!paintDevice->keyframeChannel()) {
2538 return QSet<int>();
2539 }
2540
2541 return paintDevice->keyframeChannel()->clonesOf(node.data(), frameTime);
2542 }

References KisRasterKeyframeChannel::clonesOf(), KisSharedPtr< T >::data(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchLayerRasterFrameTimesMatchingID()

QSet< int > KisLayerUtils::fetchLayerRasterFrameTimesMatchingID ( KisNodeSP node,
const int frameID )

Definition at line 2545 of file kis_layer_utils.cpp.

2545 {
2546 KIS_ASSERT(node);
2547 KisRasterKeyframeChannel* rasterChannel = dynamic_cast<KisRasterKeyframeChannel*>(node->getKeyframeChannel(KisKeyframeChannel::Raster.id(), false));
2548
2549 if (!rasterChannel) {
2550 return QSet<int>();
2551 }
2552
2553 return rasterChannel->timesForFrameID(frameID);
2554 }
static const KoID Raster
QSet< int > timesForFrameID(int frameID) const
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
KisKeyframeChannel * getKeyframeChannel(const QString &id, bool create)

References KisBaseNode::getKeyframeChannel(), KIS_ASSERT, KisKeyframeChannel::Raster, and KisRasterKeyframeChannel::timesForFrameID().

◆ fetchLayerRasterIDsAtTimes()

QSet< int > KisLayerUtils::fetchLayerRasterIDsAtTimes ( KisNodeSP node,
const QSet< int > & times )

Definition at line 2556 of file kis_layer_utils.cpp.

2557 {
2558 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(node, QSet<int>());
2559 KisPaintDeviceSP paintDevice = node->paintDevice();
2560 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, QSet<int>());
2561 if (!paintDevice->keyframeChannel()) {
2562 return QSet<int>();
2563 }
2564
2565 QSet<int> frameIDs;
2566
2567 Q_FOREACH( const int& frame, times ) {
2569 frameIDs << raster->frameID();
2570 }
2571
2572 return frameIDs;
2573 }

References KisKeyframeChannel::activeKeyframeAt(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchLayerUniqueRasterTimesMatchingIDs()

QSet< int > KisLayerUtils::fetchLayerUniqueRasterTimesMatchingIDs ( KisNodeSP node,
QSet< int > & frameIDs )

Definition at line 2587 of file kis_layer_utils.cpp.

2588 {
2589 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(node, QSet<int>());
2590 KisPaintDeviceSP paintDevice = node->paintDevice();
2591 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, QSet<int>());
2592 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice->framesInterface(), QSet<int>());
2593
2594 QSet<int> uniqueTimes;
2595
2596 Q_FOREACH( const int& id, frameIDs) {
2597 QSet<int> times = fetchLayerRasterFrameTimesMatchingID(node, id);
2598 if (times.count() > 0) {
2599 uniqueTimes.insert(*times.begin());
2600 }
2601 }
2602
2603 return uniqueTimes;
2604 }
KisPaintDeviceFramesInterface * framesInterface()
QSet< int > fetchLayerRasterFrameTimesMatchingID(KisNodeSP node, const int frameID)

References fetchLayerRasterFrameTimesMatchingID(), KisPaintDevice::framesInterface(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ fetchSelectionMasks()

void KisLayerUtils::fetchSelectionMasks ( KisNodeList mergedNodes,
QVector< KisSelectionMaskSP > & selectionMasks )

Definition at line 66 of file kis_layer_utils.cpp.

67 {
68 foreach (KisNodeSP node, mergedNodes) {
69
70 Q_FOREACH(KisNodeSP child, node->childNodes(QStringList("KisSelectionMask"), KoProperties())) {
71
72 KisSelectionMaskSP mask = qobject_cast<KisSelectionMask*>(child.data());
73 if (mask) {
74 selectionMasks.append(mask);
75 }
76 }
77 }
78 }
QList< KisNodeSP > childNodes(const QStringList &nodeTypes, const KoProperties &properties) const
Definition kis_node.cpp:439

References KisNode::childNodes(), and KisSharedPtr< T >::data().

◆ fetchUniqueFrameTimes()

KRITAIMAGE_EXPORT QSet< int > KisLayerUtils::fetchUniqueFrameTimes ( KisNodeSP node,
QSet< int > selectedTimes,
bool filterActiveFrameID )

Definition at line 2606 of file kis_layer_utils.cpp.

2607 {
2608 if (selectedTimes.isEmpty() || !node->supportsKeyframeChannel(KisKeyframeChannel::Raster.id()))
2609 return selectedTimes;
2610
2611 // Convert a set of selected keyframe times into set of selected "frameIDs"...
2612 QSet<int> selectedFrameIDs = KisLayerUtils::fetchLayerRasterIDsAtTimes(node, selectedTimes);
2613
2614 if (filterActiveFrameID) {
2615 // Current frame was already filtered e.g. during filter preview in `KisFilterManager::apply`...
2616 // So let's remove it...
2617 const int currentActiveFrameID = KisLayerUtils::fetchLayerActiveRasterFrameID(node);
2618 selectedFrameIDs.remove(currentActiveFrameID);
2619 }
2620
2621 // Convert frameIDs to any arbitrary frame time associated with the frameID...
2622 QSet<int> uniqueFrameTimes = node->paintDevice()->framesInterface() ? KisLayerUtils::fetchLayerUniqueRasterTimesMatchingIDs(node, selectedFrameIDs) : QSet<int>();
2623
2624 return uniqueFrameTimes;
2625 }
QString id() const
Definition KoID.cpp:63
int fetchLayerActiveRasterFrameID(KisNodeSP node)
QSet< int > fetchLayerUniqueRasterTimesMatchingIDs(KisNodeSP node, QSet< int > &frameIDs)
QSet< int > fetchLayerRasterIDsAtTimes(KisNodeSP node, const QSet< int > &times)
virtual bool supportsKeyframeChannel(const QString &id)

References fetchLayerActiveRasterFrameID(), fetchLayerRasterIDsAtTimes(), fetchLayerUniqueRasterTimesMatchingIDs(), KisPaintDevice::framesInterface(), KoID::id(), KisBaseNode::paintDevice(), KisKeyframeChannel::Raster, and KisBaseNode::supportsKeyframeChannel().

◆ filterInvisibleNodes()

KisNodeList KisLayerUtils::filterInvisibleNodes ( const KisNodeList & nodes,
KisNodeList * invisibleNodes,
KisNodeSP * putAfter )

When a layer is invisible and user-locked we should just skip it and do neither merge nor remove it.

Definition at line 1786 of file kis_layer_utils.cpp.

1787 {
1788 KIS_ASSERT_RECOVER(invisibleNodes) { return nodes; }
1789 KIS_ASSERT_RECOVER(putAfter) { return nodes; }
1790
1791 KisNodeList visibleNodes;
1792 int putAfterIndex = -1;
1793
1794 Q_FOREACH(KisNodeSP node, nodes) {
1795 if (node->visible()) {
1796 visibleNodes << node;
1797 } else if (node->userLocked()) {
1802 } else {
1803 *invisibleNodes << node;
1804
1805 if (node == *putAfter) {
1806 putAfterIndex = visibleNodes.size() - 1;
1807 }
1808 }
1809 }
1810
1811 if (!visibleNodes.isEmpty() && putAfterIndex >= 0) {
1812 putAfterIndex = qBound(0, putAfterIndex, visibleNodes.size() - 1);
1813 *putAfter = visibleNodes[putAfterIndex];
1814 }
1815
1816 return visibleNodes;
1817 }
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
bool userLocked() const

References KIS_ASSERT_RECOVER, KisBaseNode::userLocked(), and KisBaseNode::visible().

◆ filterMergeableNodes()

KRITAIMAGE_EXPORT void KisLayerUtils::filterMergeableNodes ( KisNodeList & nodes,
bool allowMasks )

Definition at line 1641 of file kis_layer_utils.cpp.

1642 {
1643 KisNodeList::iterator it = nodes.begin();
1644
1645 while (it != nodes.end()) {
1646 if ((!allowMasks && !qobject_cast<KisLayer*>(it->data())) ||
1647 checkIsChildOf(*it, nodes)) {
1648 //qDebug() << "Skipping node" << ppVar((*it)->name());
1649 it = nodes.erase(it);
1650 } else {
1651 ++it;
1652 }
1653 }
1654 }
bool checkIsChildOf(KisNodeSP node, const KisNodeList &parents)

References checkIsChildOf().

◆ filterTimesForOnlyRasterKeyedTimes()

KRITAIMAGE_EXPORT QSet< int > KisLayerUtils::filterTimesForOnlyRasterKeyedTimes ( KisNodeSP node,
const QSet< int > & times )

Definition at line 2575 of file kis_layer_utils.cpp.

2576 {
2578 KisPaintDeviceSP paintDevice = node->paintDevice();
2579 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(paintDevice, times);
2580 if (!paintDevice->keyframeChannel()) {
2581 return times;
2582 }
2583
2584 return paintDevice->keyframeChannel()->allKeyframeTimes().intersect(times);
2585 }

References KisKeyframeChannel::allKeyframeTimes(), KisPaintDevice::keyframeChannel(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, and KisBaseNode::paintDevice().

◆ filterUnlockedNodes()

KRITAIMAGE_EXPORT void KisLayerUtils::filterUnlockedNodes ( KisNodeList & nodes)

Definition at line 1819 of file kis_layer_utils.cpp.

1820 {
1821 KisNodeList::iterator it = nodes.begin();
1822
1823 while (it != nodes.end()) {
1824 if ((*it)->userLocked()) {
1825 it = nodes.erase(it);
1826 } else {
1827 ++it;
1828 }
1829 }
1830 }

◆ findImageByHierarchy()

KRITAIMAGE_EXPORT KisImageSP KisLayerUtils::findImageByHierarchy ( KisNodeSP node)

Definition at line 2319 of file kis_layer_utils.cpp.

2320 {
2321 while (node) {
2322 const KisLayer *layer = dynamic_cast<const KisLayer*>(node.data());
2323 if (layer) {
2324 return layer->image();
2325 }
2326
2327 node = node->parent();
2328 }
2329
2330 return 0;
2331 }
KisImageWSP image

References KisSharedPtr< T >::data(), KisBaseNode::image, and KisNode::parent.

◆ findIsolationRoot()

KRITAIMAGE_EXPORT KisNodeSP KisLayerUtils::findIsolationRoot ( KisNodeSP node)

Definition at line 2276 of file kis_layer_utils.cpp.

2277 {
2278 KisImageSP image = node->image();
2279 if (image)
2280 return image->isolationRootNode();
2281 return nullptr;
2282 }
KisNodeSP isolationRootNode() const

References KisBaseNode::image, and KisImage::isolationRootNode().

◆ findNodeByName()

KRITAIMAGE_EXPORT KisNodeSP KisLayerUtils::findNodeByName ( KisNodeSP root,
const QString & name )

Definition at line 2268 of file kis_layer_utils.cpp.

2269 {
2270 return recursiveFindNode(root,
2271 [name] (KisNodeSP node) {
2272 return node->name() == name;
2273 });
2274 }

References KisBaseNode::name(), and recursiveFindNode().

◆ findNodeByType()

template<class T >
T * KisLayerUtils::findNodeByType ( KisNodeSP root)

Definition at line 275 of file kis_layer_utils.h.

275 {
276 return dynamic_cast<T*>(recursiveFindNode(root, [] (KisNodeSP node) {
277 return bool(dynamic_cast<T*>(node.data()));
278 }).data());
279 }

References KisSharedPtr< T >::data(), and recursiveFindNode().

◆ findNodeByUuid()

KRITAIMAGE_EXPORT KisNodeSP KisLayerUtils::findNodeByUuid ( KisNodeSP root,
const QUuid & uuid )

Recursively searches for a node with specified Uuid

Definition at line 2242 of file kis_layer_utils.cpp.

2243 {
2244 return recursiveFindNode(root,
2245 [uuid] (KisNodeSP node) {
2246 return node->uuid() == uuid;
2247 });
2248 }
QUuid uuid() const

References recursiveFindNode(), and KisBaseNode::uuid().

◆ findNodesByName()

KRITAIMAGE_EXPORT QList< KisNodeSP > KisLayerUtils::findNodesByName ( KisNodeSP root,
const QString & name,
bool recursive,
bool partialMatch )

Definition at line 2250 of file kis_layer_utils.cpp.

2251 {
2252 KisNodeList nodeList;
2253 KisNodeSP child = root->firstChild();
2254
2255 while (child) {
2256 if (name.isEmpty() || (!partialMatch && child->name() == name) || (partialMatch && child->name().contains(name, Qt::CaseInsensitive))) {
2257 nodeList << child;
2258 }
2259 if (recursive && child->childCount() > 0) {
2260 nodeList << findNodesByName(child, name, recursive, partialMatch);
2261 }
2262 child = child->nextSibling();
2263 }
2264
2265 return nodeList;
2266 }
quint32 childCount() const
Definition kis_node.cpp:414

References KisNode::childCount(), findNodesByName(), KisNode::firstChild(), KisBaseNode::name(), and KisNode::nextSibling().

◆ findNodesWithProps()

KRITAIMAGE_EXPORT KisNodeList KisLayerUtils::findNodesWithProps ( KisNodeSP root,
const KoProperties & props,
bool excludeRoot )

Definition at line 1769 of file kis_layer_utils.cpp.

1770 {
1771 KisNodeList nodes;
1772
1773 if ((!excludeRoot || root->parent()) && root->check(props)) {
1774 nodes << root;
1775 }
1776
1777 KisNodeSP node = root->firstChild();
1778 while (node) {
1779 nodes += findNodesWithProps(node, props, excludeRoot);
1780 node = node->nextSibling();
1781 }
1782
1783 return nodes;
1784 }
bool check(const KoProperties &properties) const

References KisBaseNode::check(), findNodesWithProps(), KisNode::firstChild(), KisNode::nextSibling(), and KisNode::parent.

◆ findRoot()

KRITAIMAGE_EXPORT KisNodeSP KisLayerUtils::findRoot ( KisNodeSP node)

Definition at line 2387 of file kis_layer_utils.cpp.

2388 {
2389 if (!node) return node;
2390
2391 while (node->parent()) {
2392 node = node->parent();
2393 }
2394 return node;
2395 }

References KisNode::parent.

◆ flattenImage()

KRITAIMAGE_EXPORT void KisLayerUtils::flattenImage ( KisImageSP image,
KisNodeSP activeNode,
MergeFlags flags )

Definition at line 2192 of file kis_layer_utils.cpp.

2193 {
2194 if (!activeNode) {
2195 activeNode = image->root()->lastChild();
2196 }
2197
2198
2199 KisNodeList mergedNodes;
2200 mergedNodes << image->root();
2201
2202 mergeMultipleLayersImpl(image, mergedNodes, activeNode,
2203 true, kundo2_i18n("Flatten Image"),
2204 true, QString(),
2205 flags);
2206 }
KisNodeSP lastChild() const
Definition kis_node.cpp:367

References kundo2_i18n(), KisNode::lastChild(), mergeMultipleLayersImpl(), and KisNodeFacade::root.

◆ flattenLayer()

KRITAIMAGE_EXPORT void KisLayerUtils::flattenLayer ( KisImageSP image,
KisLayerSP layer,
MergeFlags flags )

Definition at line 2178 of file kis_layer_utils.cpp.

2179 {
2180 if (!layer->childCount() && !layer->layerStyle())
2181 return;
2182
2183 KisNodeList mergedNodes;
2184 mergedNodes << layer;
2185
2186 mergeMultipleLayersImpl(image, mergedNodes, layer,
2187 true, kundo2_i18n("Flatten Layer"),
2188 true, QString(),
2189 flags);
2190 }
void mergeMultipleLayersImpl(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, bool flattenSingleLayer, const KUndo2MagicString &actionName, bool cleanupNodes=true, const QString layerName=QString(), MergeFlags flags=None)
KisPSDLayerStyleSP layerStyle
Definition kis_layer.cc:171

References KisNode::childCount(), kundo2_i18n(), KisLayer::layerStyle, and mergeMultipleLayersImpl().

◆ forceAllDelayedNodesUpdate()

KRITAIMAGE_EXPORT void KisLayerUtils::forceAllDelayedNodesUpdate ( KisNodeSP root)

Definition at line 2284 of file kis_layer_utils.cpp.

2285 {
2287 [] (KisNodeSP node) {
2288 KisDelayedUpdateNodeInterface *delayedUpdate =
2289 dynamic_cast<KisDelayedUpdateNodeInterface*>(node.data());
2290 if (delayedUpdate) {
2291 delayedUpdate->forceUpdateTimedNode();
2292 }
2293 });
2294 }
The KisDelayedUpdateNodeInterface class is an interface for nodes that delay their real updates with ...
virtual void forceUpdateTimedNode()=0
forceUpdateTimedNode forces the node to regenerate its project. The update might be asynchronous,...

References KisSharedPtr< T >::data(), KisDelayedUpdateNodeInterface::forceUpdateTimedNode(), and recursiveApplyNodes().

◆ forceAllHiddenOriginalsUpdate()

KRITAIMAGE_EXPORT void KisLayerUtils::forceAllHiddenOriginalsUpdate ( KisNodeSP root)

Definition at line 2307 of file kis_layer_utils.cpp.

2308 {
2310 [] (KisNodeSP node) {
2311 KisCroppedOriginalLayerInterface *croppedUpdate =
2312 dynamic_cast<KisCroppedOriginalLayerInterface*>(node.data());
2313 if (croppedUpdate) {
2314 croppedUpdate->forceUpdateHiddenAreaOnOriginal();
2315 }
2316 });
2317 }
virtual void forceUpdateHiddenAreaOnOriginal()=0

References KisSharedPtr< T >::data(), KisCroppedOriginalLayerInterface::forceUpdateHiddenAreaOnOriginal(), and recursiveApplyNodes().

◆ hasDelayedNodeWithUpdates()

KRITAIMAGE_EXPORT bool KisLayerUtils::hasDelayedNodeWithUpdates ( KisNodeSP root)

Definition at line 2296 of file kis_layer_utils.cpp.

2297 {
2298 return recursiveFindNode(root,
2299 [] (KisNodeSP node) {
2300 KisDelayedUpdateNodeInterface *delayedUpdate =
2301 dynamic_cast<KisDelayedUpdateNodeInterface*>(node.data());
2302
2303 return delayedUpdate ? delayedUpdate->hasPendingTimedUpdates() : false;
2304 });
2305 }
virtual bool hasPendingTimedUpdates() const =0

References KisSharedPtr< T >::data(), KisDelayedUpdateNodeInterface::hasPendingTimedUpdates(), and recursiveFindNode().

◆ mergeDown()

KRITAIMAGE_EXPORT void KisLayerUtils::mergeDown ( KisImageSP image,
KisLayerSP layer,
const KisMetaData::MergeStrategy * strategy,
MergeFlags flags )
See also
a comment in mergeMultipleLayersImpl()

Save the original time before we start switching is with asynchronous SwitchFrameCommand.

When switching frames we need to update the entire image, not only the new extent of the layer, hence we pass refresh_entire_image to the command to make sure that the entire image bounds rect is added to the update rect

If source layer is not animated, then just merge that into the current frame to avoid unintentional destruction of the animation on the layer below. To merge the source into all the frames, just make the source animated.

See https://bugs.kde.org/show_bug.cgi?id=475550

Definition at line 1468 of file kis_layer_utils.cpp.

1469 {
1470 if (!layer->prevSibling()) return;
1471
1472 // XXX: this breaks if we allow free mixing of masks and layers
1473 KisLayerSP prevLayer = qobject_cast<KisLayer*>(layer->prevSibling().data());
1474
1475 while (prevLayer && prevLayer->isFakeNode()) {
1476 prevLayer = qobject_cast<KisLayer*>(prevLayer->prevSibling().data());
1477 }
1478
1479 if (!prevLayer) return;
1480
1481 if (!layer->visible() && !prevLayer->visible()) {
1482 return;
1483 }
1484
1485 KisImageSignalVector emitSignals;
1486 KisProcessingApplicator applicator(image, 0,
1488 emitSignals,
1489 kundo2_i18n("Merge Down"));
1490
1491 if (layer->visible() && prevLayer->visible()) {
1492 MergeDownInfoSP info(new MergeDownInfo(image, prevLayer, layer, flags));
1493
1494 // disable key strokes on all colorize masks, all onion skins on
1495 // paint layers and wait until update is finished with a barrier
1496 applicator.applyCommand(new DisableColorizeKeyStrokes(info));
1497 applicator.applyCommand(new DisableOnionSkins(info));
1498 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER);
1499
1500 applicator.applyCommand(new KeepMergedNodesSelected(info, false));
1501 applicator.applyCommand(new FillSelectionMasks(info));
1502 applicator.applyCommand(new CreateMergedLayer(info), KisStrokeJobData::BARRIER);
1503
1504 // NOTE: shape layer may have emitted spontaneous jobs during layer creation,
1505 // wait for them to complete!
1506 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER);
1507 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER);
1508
1509 // in two-layer mode we disable pass through only when the destination layer
1510 // is not a group layer
1511 applicator.applyCommand(new DisablePassThroughForHeadsOnly(info, true));
1512 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER);
1513
1514 if (info->frames.size() > 0) {
1519 const int currentTimeOnStart = info->image->animationInterface()->currentTime();
1520
1521 foreach (int frame, info->frames) {
1522 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, false, info->storage));
1523
1524 applicator.applyCommand(new AddNewFrame(info, frame));
1531 applicator.applyCommand(new RefreshHiddenAreas(info, RefreshHiddenAreas::refresh_entire_image));
1532 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER);
1533
1542 const bool skipMergingSourceLayer = !layer->isAnimated() &&
1543 frame != currentTimeOnStart;
1544
1545 applicator.applyCommand(new MergeLayers(info, skipMergingSourceLayer), KisStrokeJobData::BARRIER);
1546
1547 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, true, info->storage), KisStrokeJobData::BARRIER);
1548 }
1549 } else {
1550 applicator.applyCommand(new RefreshHiddenAreas(info));
1551 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER);
1552 applicator.applyCommand(new MergeLayers(info, false), KisStrokeJobData::BARRIER);
1553 }
1554
1555 applicator.applyCommand(new MergeMetaData(info, strategy), KisStrokeJobData::BARRIER);
1556 applicator.applyCommand(new CleanUpNodes(info, layer),
1559 applicator.applyCommand(new KeepMergedNodesSelected(info, true));
1560 } else if (layer->visible()) {
1561 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(),
1562 layer, KisNodeSP(),
1563 image, false));
1564
1565 applicator.applyCommand(
1566 new SimpleRemoveLayers(KisNodeList() << prevLayer,
1567 image),
1570
1571 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(),
1572 KisNodeSP(), layer,
1573 image, true));
1574 } else if (prevLayer->visible()) {
1575 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(),
1576 layer, KisNodeSP(),
1577 image, false));
1578
1579 applicator.applyCommand(
1580 new SimpleRemoveLayers(KisNodeList() << layer,
1581 image),
1584
1585 applicator.applyCommand(new KeepNodesSelectedCommand(KisNodeList(), KisNodeList(),
1586 KisNodeSP(), prevLayer,
1587 image, true));
1588 }
1589
1590 applicator.end();
1591 }
QList< KisNodeSP > KisNodeList
Definition kis_types.h:264
QSharedPointer< MergeDownInfo > MergeDownInfoSP
bool isAnimated() const
virtual bool isFakeNode() const
KisNodeSP prevSibling() const
Definition kis_node.cpp:402

References KisProcessingApplicator::applyCommand(), KisStrokeJobData::BARRIER, KisSharedPtr< T >::data(), KisProcessingApplicator::end(), KisStrokeJobData::EXCLUSIVE, KisBaseNode::isAnimated(), KisBaseNode::isFakeNode(), kundo2_i18n(), KisProcessingApplicator::NONE, KisNode::prevSibling(), KisLayerUtils::RefreshHiddenAreas::refresh_entire_image, KisStrokeJobData::SEQUENTIAL, and KisBaseNode::visible().

◆ mergeMultipleLayers()

KRITAIMAGE_EXPORT void KisLayerUtils::mergeMultipleLayers ( KisImageSP image,
KisNodeList mergedNodes,
KisNodeSP putAfter,
MergeFlags flags )

Definition at line 2062 of file kis_layer_utils.cpp.

2063 {
2064 mergeMultipleLayersImpl(image, mergedNodes, putAfter,
2065 false, kundo2_i18n("Merge Selected Nodes"),
2066 true, QString(),
2067 flags);
2068 }

References kundo2_i18n(), and mergeMultipleLayersImpl().

◆ mergeMultipleLayersImpl()

void KisLayerUtils::mergeMultipleLayersImpl ( KisImageSP image,
KisNodeList mergedNodes,
KisNodeSP putAfter,
bool flattenSingleLayer,
const KUndo2MagicString & actionName,
bool cleanupNodes = true,
const QString layerName = QString(),
MergeFlags flags = None )

There might be two approaches for merging multiple layers:

1) Consider the selected nodes as a distinct "group" and merge them as if they were isolated from the rest of the image. The key point of this approach is that the look of the image will change, when merging "weird" layers, like adjustment layers or layers with non-normal blending mode.

2) Merge layers in a way to keep the look of the image as unchanged as possible. With this approach one uses a few heuristics:

  • when merging multiple layers with non-normal (but equal) blending mode, first merge these layers together using Normal blending mode, then set blending mode of the result to the original blending mode
  • when merging multiple layers with different blending modes or layer styles, they are first rasterized, and then laid over each other with their own composite op. The blending mode of the final layer is set to Normal, so the user could clearly see that he should choose the correct blending mode.

Krita uses the second approach: after merge operation, the image should look as if nothing has happened (if it is technically possible).

We have reached the root of the layer hierarchy and didn't manage to find a node that was editable enough for putting our merged result into it. That shouldn't happen in normal circumstances, unless the user chose to make the root layer visible and lock it manually.

When switching frames we need to update the entire image, not only the new extent of the layer, hence we pass refresh_entire_image to the command to make sure that the entire image bounds rect is added to the update rect

Definition at line 1919 of file kis_layer_utils.cpp.

1923 {
1924 if (!putAfter) {
1925 putAfter = mergedNodes.first();
1926 }
1927
1928 filterMergeableNodes(mergedNodes);
1929 {
1930 KisNodeList tempNodes;
1931 std::swap(mergedNodes, tempNodes);
1932 sortMergeableNodes(image->root(), tempNodes, mergedNodes);
1933 }
1934
1935 if (mergedNodes.size() <= 1 &&
1936 (!flattenSingleLayer && mergedNodes.size() == 1)) return;
1937
1938 KisImageSignalVector emitSignals;
1939 emitSignals << ComplexNodeReselectionSignal(KisNodeSP(), KisNodeList(), KisNodeSP(), mergedNodes);
1940
1941
1942
1943 KisNodeList originalNodes = mergedNodes;
1944 KisNodeList invisibleNodes;
1945 mergedNodes = filterInvisibleNodes(originalNodes, &invisibleNodes, &putAfter);
1946
1947 if (mergedNodes.isEmpty()) return;
1948
1949
1950 // make sure we don't add the new layer into a locked group
1952 while (putAfter->parent() && !putAfter->parent()->isEditable()) {
1953 putAfter = putAfter->parent();
1954 }
1955
1963 if (!putAfter->parent()) {
1964 return;
1965 }
1966
1967 KisProcessingApplicator applicator(image, 0,
1969 emitSignals,
1970 actionName);
1971
1972
1973 if (!invisibleNodes.isEmpty() && cleanupNodes) {
1974
1975 /* If the putAfter node is invisible,
1976 * we should instead pick one of the nodes
1977 * to be merged to avoid a null putAfter
1978 * after we remove all invisible layers from
1979 * the image.
1980 * (The assumption is that putAfter is among
1981 * the layers to merge, so if it's invisible,
1982 * it's going to be removed)
1983 */
1984 if (!putAfter->visible()){
1985 putAfter = mergedNodes.first();
1986 }
1987
1988 applicator.applyCommand(
1989 new SimpleRemoveLayers(invisibleNodes,
1990 image),
1993 }
1994
1995 if (mergedNodes.size() > 1 || invisibleNodes.isEmpty()) {
1996 MergeMultipleInfoSP info(new MergeMultipleInfo(image, mergedNodes, flags));
1997
1998 // disable key strokes on all colorize masks, all onion skins on
1999 // paint layers and wait until update is finished with a barrier
2000 //
2001 // when doing "new layer from visible" we should undo these changes
2002 // before the action stops, because the source layers are **not**
2003 // removed as a result of this action
2004 applicator.applyCommand(
2005 new EphemeralCommandsWrapper(info,
2006 {
2007 new DisableColorizeKeyStrokes(info),
2008 new DisableOnionSkins(info),
2009 new DisablePassThroughForHeadsOnly(info)
2010 },
2011 cleanupNodes));
2012 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER);
2013
2014 applicator.applyCommand(new KeepMergedNodesSelected(info, putAfter, false));
2015 applicator.applyCommand(new FillSelectionMasks(info));
2016 applicator.applyCommand(new CreateMergedLayerMultiple(info, layerName), KisStrokeJobData::BARRIER);
2017 applicator.applyCommand(new EphemeralCommandsWrapper(info, { new DisableExtraCompositing(info) } , cleanupNodes));
2018 applicator.applyCommand(new KUndo2Command(), KisStrokeJobData::BARRIER);
2019
2020 if (!info->frames.isEmpty()) {
2021 foreach (int frame, info->frames) {
2022 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, false, info->storage));
2023
2024 applicator.applyCommand(new AddNewFrame(info, frame));
2031 applicator.applyCommand(new RefreshHiddenAreas(info, RefreshHiddenAreas::refresh_entire_image));
2032 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER);
2033 applicator.applyCommand(new MergeLayersMultiple(info), KisStrokeJobData::BARRIER);
2034
2035 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, true, info->storage));
2036 }
2037 } else {
2038 applicator.applyCommand(new RefreshHiddenAreas(info));
2039 applicator.applyCommand(new RefreshDelayedUpdateLayers(info), KisStrokeJobData::BARRIER);
2040 applicator.applyCommand(new MergeLayersMultiple(info), KisStrokeJobData::BARRIER);
2041 }
2042
2043 //applicator.applyCommand(new MergeMetaData(info, strategy), KisStrokeJobData::BARRIER);
2044 if (cleanupNodes){
2045 applicator.applyCommand(new CleanUpNodes(info, putAfter, flattenSingleLayer),
2048 } else {
2049 applicator.applyCommand(new UndoEphemeralCommands(info));
2050 applicator.applyCommand(new InsertNode(info, putAfter),
2053 }
2054
2055 applicator.applyCommand(new KeepMergedNodesSelected(info, putAfter, true));
2056 }
2057
2058 applicator.end();
2059
2060 }
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
KisNodeList filterInvisibleNodes(const KisNodeList &nodes, KisNodeList *invisibleNodes, KisNodeSP *putAfter)
QSharedPointer< MergeMultipleInfo > MergeMultipleInfoSP
bool isEditable(bool checkVisibility=true) const

References KisProcessingApplicator::applyCommand(), KisStrokeJobData::BARRIER, KisProcessingApplicator::end(), KisStrokeJobData::EXCLUSIVE, filterInvisibleNodes(), filterMergeableNodes(), KisBaseNode::isEditable(), KIS_SAFE_ASSERT_RECOVER_RETURN, KisProcessingApplicator::NONE, KisNode::parent, KisLayerUtils::RefreshHiddenAreas::refresh_entire_image, KisNodeFacade::root, KisStrokeJobData::SEQUENTIAL, sortMergeableNodes(), and KisBaseNode::visible().

◆ mergeMultipleNodes()

KRITAIMAGE_EXPORT void KisLayerUtils::mergeMultipleNodes ( KisImageSP image,
KisNodeList mergedNodes,
KisNodeSP putAfter,
MergeFlags flags = None )

Same as mergeMultipleLayers() but tries to merge masks with tryMergeSelectionMasks() first.

Definition at line 2070 of file kis_layer_utils.cpp.

2071 {
2072 if (!tryMergeSelectionMasks(image, mergedNodes, putAfter)) {
2073 mergeMultipleLayers(image, mergedNodes, putAfter, flags);
2074 }
2075 }
bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image)
void mergeMultipleLayers(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter, MergeFlags flags)

References mergeMultipleLayers(), and tryMergeSelectionMasks().

◆ newLayerFromVisible()

KRITAIMAGE_EXPORT void KisLayerUtils::newLayerFromVisible ( KisImageSP image,
KisNodeSP putAfter,
MergeFlags flags )

Definition at line 2077 of file kis_layer_utils.cpp.

2078 {
2079 KisNodeList mergedNodes;
2080 mergedNodes << image->root();
2081
2082 mergeMultipleLayersImpl(image, mergedNodes, putAfter,
2083 true, kundo2_i18n("New From Visible"),
2084 false, i18nc("New layer created from all the visible layers", "Visible"),
2085 flags);
2086 }

References kundo2_i18n(), mergeMultipleLayersImpl(), and KisNodeFacade::root.

◆ recursiveApplyNodes()

template<typename NodePointer , typename Functor >
void KisLayerUtils::recursiveApplyNodes ( NodePointer node,
Functor func )

Applies func to node and all its children recursively

Definition at line 241 of file kis_layer_utils.h.

242 {
243 func(node);
244
245 node = node->firstChild();
246 while (node) {
247 recursiveApplyNodes(node, func);
248 node = node->nextSibling();
249 }
250 }

References recursiveApplyNodes().

◆ recursiveFindNode()

KRITAIMAGE_EXPORT KisNodeSP KisLayerUtils::recursiveFindNode ( KisNodeSP node,
std::function< bool(KisNodeSP)> func )

Walks through node and all its children recursively until func returns true. When func returns true, the node is considered to be found, the search is stopped and the found node is returned to the caller.

Definition at line 2224 of file kis_layer_utils.cpp.

2225 {
2226 if (func(node)) {
2227 return node;
2228 }
2229
2230 node = node->firstChild();
2231 while (node) {
2232 KisNodeSP resultNode = recursiveFindNode(node, func);
2233 if (resultNode) {
2234 return resultNode;
2235 }
2236 node = node->nextSibling();
2237 }
2238
2239 return 0;
2240 }

References KisNode::firstChild(), KisNode::nextSibling(), and recursiveFindNode().

◆ recursiveTightNodeVisibleBounds()

KRITAIMAGE_EXPORT QRect KisLayerUtils::recursiveTightNodeVisibleBounds ( KisNodeSP rootNode)

Definition at line 2378 of file kis_layer_utils.cpp.

2379 {
2380 QRect exactBounds;
2381 recursiveApplyNodes(rootNode, [&exactBounds] (KisNodeSP node) {
2382 exactBounds |= node->projectionPlane()->tightUserVisibleBounds();
2383 });
2384 return exactBounds;
2385 }
virtual KisAbstractProjectionPlaneSP projectionPlane() const
Definition kis_node.cpp:240

References KisNode::projectionPlane(), and recursiveApplyNodes().

◆ refreshHiddenAreaAsync()

KRITAIMAGE_EXPORT void KisLayerUtils::refreshHiddenAreaAsync ( KisImageSP image,
KisNodeSP rootNode,
const QRect & preparedArea )

Definition at line 2374 of file kis_layer_utils.cpp.

2374 {
2375 Private::refreshHiddenAreaAsync(image, rootNode, preparedArea, QRect());
2376 }

References KisLayerUtils::Private::refreshHiddenAreaAsync().

◆ sortAndFilterAnyMergeableNodesSafe()

KRITAIMAGE_EXPORT KisNodeList KisLayerUtils::sortAndFilterAnyMergeableNodesSafe ( const KisNodeList & nodes,
KisImageSP image )

Definition at line 1733 of file kis_layer_utils.cpp.

1733 {
1734 KisNodeList filteredNodes = nodes;
1735 KisNodeList sortedNodes;
1736
1737 KisLayerUtils::filterMergeableNodes(filteredNodes, true);
1738
1739 bool haveExternalNodes = false;
1740 Q_FOREACH (KisNodeSP node, nodes) {
1741 if (node->graphListener() != image->root()->graphListener()) {
1742 haveExternalNodes = true;
1743 break;
1744 }
1745 }
1746
1747 if (!haveExternalNodes) {
1748 KisLayerUtils::sortMergeableNodes(image->root(), filteredNodes, sortedNodes);
1749 } else {
1750 sortedNodes = filteredNodes;
1751 }
1752
1753 return sortedNodes;
1754 }
void sortMergeableNodes(KisNodeSP root, KisNodeList &inputNodes, KisNodeList &outputNodes)
void filterMergeableNodes(KisNodeList &nodes, bool allowMasks)
KisNodeGraphListener * graphListener
Definition kis_node.cpp:87

References filterMergeableNodes(), KisNode::graphListener, KisNodeFacade::root, and sortMergeableNodes().

◆ sortAndFilterMergeableInternalNodes()

KRITAIMAGE_EXPORT KisNodeList KisLayerUtils::sortAndFilterMergeableInternalNodes ( KisNodeList nodes,
bool allowMasks )

Definition at line 1688 of file kis_layer_utils.cpp.

1689 {
1690 KIS_SAFE_ASSERT_RECOVER(!nodes.isEmpty()) { return nodes; }
1691
1692 KisNodeSP root;
1693 Q_FOREACH(KisNodeSP node, nodes) {
1694 KisNodeSP localRoot = node;
1695 while (localRoot->parent()) {
1696 localRoot = localRoot->parent();
1697 }
1698
1699 if (!root) {
1700 root = localRoot;
1701 }
1702 KIS_SAFE_ASSERT_RECOVER(root == localRoot) { return nodes; }
1703 }
1704
1705 KisNodeList result;
1706 sortMergeableNodes(root, nodes, result);
1707 filterMergeableNodes(result, allowMasks);
1708 return result;
1709 }
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126

References filterMergeableNodes(), KIS_SAFE_ASSERT_RECOVER, KisNode::parent, and sortMergeableNodes().

◆ sortMergeableInternalNodes()

KRITAIMAGE_EXPORT KisNodeList KisLayerUtils::sortMergeableInternalNodes ( KisNodeList nodes)

Definition at line 1711 of file kis_layer_utils.cpp.

1712 {
1713 KIS_SAFE_ASSERT_RECOVER(!nodes.isEmpty()) { return nodes; }
1714
1715 KisNodeSP root;
1716 Q_FOREACH(KisNodeSP node, nodes) {
1717 KisNodeSP localRoot = node;
1718 while (localRoot->parent()) {
1719 localRoot = localRoot->parent();
1720 }
1721
1722 if (!root) {
1723 root = localRoot;
1724 }
1725 KIS_SAFE_ASSERT_RECOVER(root == localRoot) { return nodes; }
1726 }
1727
1728 KisNodeList result;
1729 sortMergeableNodes(root, nodes, result);
1730 return result;
1731 }

References KIS_SAFE_ASSERT_RECOVER, KisNode::parent, and sortMergeableNodes().

◆ sortMergeableNodes() [1/3]

void KisLayerUtils::sortMergeableNodes ( KisNodeSP root,
KisNodeList & inputNodes,
KisNodeList & outputNodes )

By the end of recursion inputNodes must be empty

Definition at line 1656 of file kis_layer_utils.cpp.

1657 {
1658 KisNodeList::iterator it = std::find(inputNodes.begin(), inputNodes.end(), root);
1659
1660 if (it != inputNodes.end()) {
1661 outputNodes << *it;
1662 inputNodes.erase(it);
1663 }
1664
1665 if (inputNodes.isEmpty()) {
1666 return;
1667 }
1668
1669 KisNodeSP child = root->firstChild();
1670 while (child) {
1671 sortMergeableNodes(child, inputNodes, outputNodes);
1672 child = child->nextSibling();
1673 }
1674
1678 KIS_ASSERT_RECOVER_NOOP(root->parent() || inputNodes.isEmpty());
1679 }
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97
KisNodeListSP inputNodes(KisImageSP image, InputLayerMode inputMode, KisNodeSP currentNode)

References KisNode::firstChild(), KIS_ASSERT_RECOVER_NOOP, KisNode::nextSibling(), KisNode::parent, and sortMergeableNodes().

◆ sortMergeableNodes() [2/3]

KRITAIMAGE_EXPORT KisNodeList KisLayerUtils::sortMergeableNodes ( KisNodeSP root,
KisNodeList nodes )

Definition at line 1681 of file kis_layer_utils.cpp.

1682 {
1683 KisNodeList result;
1684 sortMergeableNodes(root, nodes, result);
1685 return result;
1686 }

References sortMergeableNodes().

◆ sortMergeableNodes() [3/3]

KRITAIMAGE_EXPORT void KisLayerUtils::sortMergeableNodes ( KisNodeSP root,
QList< KisNodeSP > & inputNodes,
QList< KisNodeSP > & outputNodes )

◆ splitAlphaToMask()

KRITAIMAGE_EXPORT void KisLayerUtils::splitAlphaToMask ( KisImageSP image,
KisNodeSP node,
const QString & maskName )

Definition at line 2429 of file kis_layer_utils.cpp.

2430 {
2431 SplitAlphaToMaskInfoSP info( new SplitAlphaToMaskInfo(node->image(), node, maskName) );
2432
2433 KisImageSignalVector emitSignals;
2434 KisProcessingApplicator applicator(image, 0,
2436 emitSignals,
2437 kundo2_i18n("Split Alpha into a Mask"));
2438
2439 applicator.applyCommand(new SimpleAddNode(info->image, info->getMask(), info->node), KisStrokeJobData::BARRIER);
2440 applicator.applyCommand(new InitSplitAlphaSelectionMask(info));
2441 if (info->frames.count() > 0) {
2442 Q_FOREACH(const int& frame, info->frames) {
2443 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, false, info->storage));
2444 applicator.applyCommand(new AddNewFrame(info->getMask(), frame, info->node));
2445 applicator.applyCommand(new SplitAlphaCommand(info), KisStrokeJobData::BARRIER);
2446 applicator.applyCommand(new SwitchFrameCommand(info->image, frame, true, info->storage));
2447 }
2448 } else {
2449 applicator.applyCommand(new SplitAlphaCommand(info), KisStrokeJobData::BARRIER);
2450 }
2451 applicator.end();
2452 }

References KisProcessingApplicator::applyCommand(), KisStrokeJobData::BARRIER, KisProcessingApplicator::end(), KisBaseNode::image, kundo2_i18n(), and KisProcessingApplicator::NONE.

◆ splitNonRemovableNodes()

void KisLayerUtils::splitNonRemovableNodes ( KisNodeList & nodesToRemove,
KisNodeList & _nodesToHide )

Definition at line 1142 of file kis_layer_utils.cpp.

1143 {
1144 QSet<KisNodeSP> nodesToHide;
1145 QSet<KisNodeSP> extraNodesToRemove;
1146
1147 for (auto it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) {
1148 KisNodeSP root = *it;
1150
1151 if (!root->isEditable(false)) {
1152 nodesToHide.insert(root);
1153 } else {
1154 bool rootNeedsCarefulRemoval = false;
1155
1156 recursiveApplyNodes(root,
1157 [root, &nodesToHide, &rootNeedsCarefulRemoval] (KisNodeSP node) {
1158 if (!node->isEditable(false)) {
1159 while (node != root) {
1160 nodesToHide.insert(node);
1161 node = node->parent();
1162 KIS_SAFE_ASSERT_RECOVER_BREAK(node);
1163 }
1164 nodesToHide.insert(root);
1165 rootNeedsCarefulRemoval = true;
1166 }
1167 });
1168
1169 if (rootNeedsCarefulRemoval) {
1171 [&extraNodesToRemove] (KisNodeSP node) {
1172 extraNodesToRemove.insert(node);
1173 });
1174 }
1175 }
1176 }
1177 nodesToRemove += KisNodeList(extraNodesToRemove.begin(), extraNodesToRemove.end());
1178 KritaUtils::filterContainer<KisNodeList>(nodesToRemove,
1179 [nodesToHide](KisNodeSP node) {
1180 return !nodesToHide.contains(node);
1181 });
1182 _nodesToHide = KisNodeList(nodesToHide.begin(), nodesToHide.end());
1183 }
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KisBaseNode::isEditable(), KIS_SAFE_ASSERT_RECOVER_NOOP, recursiveApplyNodes(), and KisBaseNode::visible().

◆ tryMergeSelectionMasks()

KRITAIMAGE_EXPORT bool KisLayerUtils::tryMergeSelectionMasks ( KisImageSP image,
KisNodeList mergedNodes,
KisNodeSP putAfter )

Definition at line 2139 of file kis_layer_utils.cpp.

2140 {
2141 QList<KisSelectionMaskSP> selectionMasks;
2142
2143 for (auto it = mergedNodes.begin(); it != mergedNodes.end(); /*noop*/) {
2144 KisSelectionMaskSP mask = dynamic_cast<KisSelectionMask*>(it->data());
2145 if (!mask) {
2146 it = mergedNodes.erase(it);
2147 } else {
2148 selectionMasks.append(mask);
2149 ++it;
2150 }
2151 }
2152
2153 if (mergedNodes.isEmpty()) return false;
2154
2155 KisLayerSP parentLayer = qobject_cast<KisLayer*>(selectionMasks.first()->parent().data());
2156 KIS_ASSERT_RECOVER(parentLayer) { return 0; }
2157
2158 KisImageSignalVector emitSignals;
2159
2160 KisProcessingApplicator applicator(image, 0,
2162 emitSignals,
2163 kundo2_i18n("Merge Selection Masks"));
2164
2165 MergeMultipleInfoSP info(new MergeMultipleInfo(image, mergedNodes, None));
2166
2167
2168 applicator.applyCommand(new MergeSelectionMasks(info, putAfter));
2169 applicator.applyCommand(new CleanUpNodes(info, putAfter),
2172 applicator.applyCommand(new ActivateSelectionMask(info));
2173 applicator.end();
2174
2175 return true;
2176 }

References KisProcessingApplicator::applyCommand(), KisProcessingApplicator::end(), KisStrokeJobData::EXCLUSIVE, KIS_ASSERT_RECOVER, kundo2_i18n(), None, KisProcessingApplicator::NONE, and KisStrokeJobData::SEQUENTIAL.

◆ updateFrameJobs()

void KisLayerUtils::updateFrameJobs ( FrameJobs * jobs,
KisNodeSP node )

Definition at line 1425 of file kis_layer_utils.cpp.

1425 {
1426 QSet<int> frames = fetchLayerFrames(node);
1427 frames = fetchUniqueFrameTimes(node, frames, false);
1428
1429 if (frames.isEmpty()) {
1430 (*jobs)[0].insert(node);
1431 } else {
1432 foreach (int frame, frames) {
1433 (*jobs)[frame].insert(node);
1434 }
1435 }
1436 }
QSet< int > fetchUniqueFrameTimes(KisNodeSP node, QSet< int > selectedTimes, bool filterActiveFrameID)

References fetchLayerFrames(), and fetchUniqueFrameTimes().

◆ updateFrameJobsNonRecursive()

void KisLayerUtils::updateFrameJobsNonRecursive ( FrameJobs * jobs,
KisNodeSP rootNode,
bool frameTimesRecursive = false )

updateFrameJobsNonRecursive updates the frame jobs non-recursively, that is, on the rootNode only.

Parameters
frameTimesRecursive– whether to make the frame times themselves recursive, or to only use the frames on the root node.

Definition at line 1448 of file kis_layer_utils.cpp.

1449 {
1450 if (frameTimesRecursive) {
1451 QSet<int> frames = fetchLayerFramesRecursive(rootNode);
1452
1453 if (frames.isEmpty()) {
1454 (*jobs)[0].insert(rootNode);
1455 } else {
1456 foreach (int frame, frames) {
1457 (*jobs)[frame].insert(rootNode);
1458 }
1459 }
1460 } else {
1461 updateFrameJobs(jobs, rootNode);
1462 }
1463 }
void updateFrameJobs(FrameJobs *jobs, KisNodeSP node)

References fetchLayerFramesRecursive(), and updateFrameJobs().

◆ updateFrameJobsRecursive()

void KisLayerUtils::updateFrameJobsRecursive ( FrameJobs * jobs,
KisNodeSP rootNode )

Definition at line 1438 of file kis_layer_utils.cpp.

1438 {
1439 updateFrameJobs(jobs, rootNode);
1440
1441 KisNodeSP node = rootNode->firstChild();
1442 while(node) {
1443 updateFrameJobsRecursive(jobs, node);
1444 node = node->nextSibling();
1445 }
1446 }
void updateFrameJobsRecursive(FrameJobs *jobs, KisNodeSP rootNode)

References KisNode::firstChild(), KisNode::nextSibling(), updateFrameJobs(), and updateFrameJobsRecursive().