diff --git a/src/app/commands/cmd_goto_layer.cpp b/src/app/commands/cmd_goto_layer.cpp index 924319a8c..a62b85756 100644 --- a/src/app/commands/cmd_goto_layer.cpp +++ b/src/app/commands/cmd_goto_layer.cpp @@ -48,7 +48,7 @@ protected: if (m_offset > 0) { int i = m_offset; while (i-- > 0) { - layer = layer->getNextInWholeHierarchy(); + layer = layer->getNextBrowsable(); if (!layer) layer = site.sprite()->firstBrowsableLayer(); } @@ -56,7 +56,7 @@ protected: else if (m_offset < 0) { int i = m_offset; while (i++ < 0) { - layer = layer->getPreviousInWholeHierarchy(); + layer = layer->getPreviousBrowsable(); if (!layer) layer = site.sprite()->root()->lastLayer(); } diff --git a/src/app/document_api.cpp b/src/app/document_api.cpp index 4e877ab7f..4a7e158bc 100644 --- a/src/app/document_api.cpp +++ b/src/app/document_api.cpp @@ -495,7 +495,7 @@ Layer* DocumentApi::duplicateLayerAfter(Layer* sourceLayer, LayerGroup* parent, Layer* DocumentApi::duplicateLayerBefore(Layer* sourceLayer, LayerGroup* parent, Layer* beforeLayer) { ASSERT(parent); - Layer* afterThis = (beforeLayer ? beforeLayer->getPreviousInWholeHierarchy(): nullptr); + Layer* afterThis = (beforeLayer ? beforeLayer->getPreviousBrowsable(): nullptr); Layer* newLayer = duplicateLayerAfter(sourceLayer, parent, afterThis); if (newLayer) restackLayerBefore(newLayer, parent, beforeLayer); diff --git a/src/app/document_range.cpp b/src/app/document_range.cpp index d2eba5782..7820c469e 100644 --- a/src/app/document_range.cpp +++ b/src/app/document_range.cpp @@ -127,7 +127,7 @@ void DocumentRange::selectLayerRange(Layer* fromLayer, Layer* toLayer) goNext = true; break; } - it = it->getNextInWholeHierarchy(); + it = it->getNextBrowsable(); } if (!goNext) { @@ -137,7 +137,7 @@ void DocumentRange::selectLayerRange(Layer* fromLayer, Layer* toLayer) goPrev = true; break; } - it = it->getPreviousInWholeHierarchy(); + it = it->getPreviousBrowsable(); } } } @@ -149,9 +149,9 @@ void DocumentRange::selectLayerRange(Layer* fromLayer, Layer* toLayer) break; if (goNext) - it = it->getNextInWholeHierarchy(); + it = it->getNextBrowsable(); else if (goPrev) - it = it->getPreviousInWholeHierarchy(); + it = it->getPreviousBrowsable(); else break; } while (it); diff --git a/src/app/util/clipboard.cpp b/src/app/util/clipboard.cpp index b423c9de2..9ed920b0d 100644 --- a/src/app/util/clipboard.cpp +++ b/src/app/util/clipboard.cpp @@ -357,7 +357,7 @@ void paste() DocumentRange dstRange; dstRange.startRange(dstLayer, dstFrameFirst, DocumentRange::kCels); for (layer_t i=1; igetPreviousInWholeHierarchy(); + dstLayer = dstLayer->getPreviousBrowsable(); if (dstLayer == nullptr) break; } diff --git a/src/doc/cels_range.cpp b/src/doc/cels_range.cpp index 79582fbfc..91911a2e3 100644 --- a/src/doc/cels_range.cpp +++ b/src/doc/cels_range.cpp @@ -41,7 +41,7 @@ CelsRange::iterator::iterator(const Sprite* sprite, , m_flags(flags) { // Get first cel - Layer* layer = sprite->root()->firstLayer(); + Layer* layer = sprite->root()->firstLayerInWholeHierarchy(); while (layer && !m_cel) { if (layer->isImage()) { m_frameIterator = m_selFrames.begin(); diff --git a/src/doc/layer.cpp b/src/doc/layer.cpp index e9f389c9e..deb629b53 100644 --- a/src/doc/layer.cpp +++ b/src/doc/layer.cpp @@ -74,7 +74,7 @@ Layer* Layer::getNext() const return nullptr; } -Layer* Layer::getPreviousInWholeHierarchy() const +Layer* Layer::getPreviousBrowsable() const { // Go to children if (isBrowsable()) @@ -93,12 +93,52 @@ Layer* Layer::getPreviousInWholeHierarchy() const return parent->getPrevious(); } +Layer* Layer::getNextBrowsable() const +{ + // Go to next layer + if (Layer* next = getNext()) { + // Go to children + while (next->isBrowsable()) { + Layer* firstChild = static_cast(next)->firstLayer(); + if (!firstChild) + break; + next = firstChild; + } + return next; + } + + // Go to parent + if (m_sprite && parent() != m_sprite->root()) + return m_parent; + + return nullptr; +} + +Layer* Layer::getPreviousInWholeHierarchy() const +{ + // Go to children + if (isGroup() && static_cast(this)->layersCount() > 0) + return static_cast(this)->lastLayer(); + + // Go to previous layer + if (Layer* prev = getPrevious()) + return prev; + + // Go to previous layer in the parent + LayerGroup* parent = this->parent(); + while (parent != sprite()->root() && + !parent->getPrevious()) { + parent = parent->parent(); + } + return parent->getPrevious(); +} + Layer* Layer::getNextInWholeHierarchy() const { // Go to next layer if (Layer* next = getNext()) { // Go to children - while (next->isBrowsable()) { + while (next->isGroup() && static_cast(next)->layersCount() > 0) { Layer* firstChild = static_cast(next)->firstLayer(); if (!firstChild) break; @@ -357,6 +397,18 @@ int LayerGroup::getMemSize() const return size; } +Layer* LayerGroup::firstLayerInWholeHierarchy() const +{ + Layer* layer = firstLayer(); + if (layer) { + while (layer->isGroup() && + static_cast(layer)->layersCount() > 0) { + layer = static_cast(layer)->firstLayer(); + } + } + return layer; +} + void LayerGroup::allLayers(LayerList& list) const { for (Layer* child : m_layers) { diff --git a/src/doc/layer.h b/src/doc/layer.h index 8bf1a9135..e82611af3 100644 --- a/src/doc/layer.h +++ b/src/doc/layer.h @@ -62,6 +62,9 @@ namespace doc { Layer* getPrevious() const; Layer* getNext() const; + Layer* getPreviousBrowsable() const; + Layer* getNextBrowsable() const; + Layer* getPreviousInWholeHierarchy() const; Layer* getNextInWholeHierarchy() const; @@ -187,6 +190,7 @@ namespace doc { void stackLayer(Layer* layer, Layer* after); Layer* firstLayer() const { return (m_layers.empty() ? nullptr: m_layers.front()); } + Layer* firstLayerInWholeHierarchy() const; Layer* lastLayer() const { return (m_layers.empty() ? nullptr: m_layers.back()); } void allLayers(LayerList& list) const; diff --git a/src/doc/selected_layers.cpp b/src/doc/selected_layers.cpp index 610e11046..4ed95553c 100644 --- a/src/doc/selected_layers.cpp +++ b/src/doc/selected_layers.cpp @@ -62,7 +62,7 @@ LayerList SelectedLayers::toLayerList() const for (Layer* layer = (*begin())->sprite()->firstBrowsableLayer(); layer != nullptr; - layer = layer->getNextInWholeHierarchy()) { + layer = layer->getNextBrowsable()) { if (contains(layer)) output.push_back(layer); } @@ -114,11 +114,11 @@ retry:; if (layerDelta > 0) { for (layer_t i=0; layer && igetNextInWholeHierarchy(); + layer = layer->getNextBrowsable(); } else if (layerDelta < 0) { for (layer_t i=0; layer && i>layerDelta; --i) { - layer = layer->getPreviousInWholeHierarchy(); + layer = layer->getPreviousBrowsable(); } }