From 0f77bf0712a22bc1e8f1dd73bdad504b4829f7c0 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 21 Jun 2016 00:02:13 -0300 Subject: [PATCH] Move selected layers into the new group If the Timeline has an active selected range of layers and the user creates a new layer group, the selected layers will be be grouped as children of the new layer 'group'. --- src/app/cmd/add_layer.cpp | 3 +- src/app/cmd/configure_background.cpp | 5 ++-- src/app/cmd/move_layer.cpp | 44 +++++++++++++++++++++------- src/app/cmd/move_layer.h | 10 ++++--- src/app/commands/cmd_goto_layer.cpp | 7 ++--- src/app/commands/cmd_new_layer.cpp | 28 +++++++++++++++++- src/app/document_api.cpp | 2 +- src/doc/layer.cpp | 22 ++++++++------ src/doc/layer.h | 1 + src/doc/selected_layers.cpp | 19 ++++++++++++ src/doc/selected_layers.h | 2 ++ src/doc/sprite.cpp | 8 +++++ src/doc/sprite.h | 1 + 13 files changed, 117 insertions(+), 35 deletions(-) diff --git a/src/app/cmd/add_layer.cpp b/src/app/cmd/add_layer.cpp index 5b5fd51ba..cd512b808 100644 --- a/src/app/cmd/add_layer.cpp +++ b/src/app/cmd/add_layer.cpp @@ -66,8 +66,7 @@ void AddLayer::onRedo() void AddLayer::addLayer(Layer* group, Layer* newLayer, Layer* afterThis) { - static_cast(group)->addLayer(newLayer); - static_cast(group)->stackLayer(newLayer, afterThis); + static_cast(group)->insertLayer(newLayer, afterThis); group->incrementVersion(); Document* doc = group->sprite()->document(); diff --git a/src/app/cmd/configure_background.cpp b/src/app/cmd/configure_background.cpp index 4f835d471..190fa1c06 100644 --- a/src/app/cmd/configure_background.cpp +++ b/src/app/cmd/configure_background.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -15,6 +15,7 @@ #include "app/cmd/set_layer_flags.h" #include "app/cmd/set_layer_name.h" #include "app/cmd/set_layer_opacity.h" +#include "doc/sprite.h" namespace app { namespace cmd { @@ -33,7 +34,7 @@ ConfigureBackground::ConfigureBackground(Layer* layer) add(new cmd::SetLayerOpacity(static_cast(layer), 255)); } - add(new cmd::MoveLayer(layer, nullptr)); + add(new cmd::MoveLayer(layer, layer->sprite()->root(), nullptr)); } } // namespace cmd diff --git a/src/app/cmd/move_layer.cpp b/src/app/cmd/move_layer.cpp index e0f62fd32..820bc4117 100644 --- a/src/app/cmd/move_layer.cpp +++ b/src/app/cmd/move_layer.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -21,29 +21,51 @@ namespace cmd { using namespace doc; -MoveLayer::MoveLayer(Layer* layer, Layer* afterThis) +MoveLayer::MoveLayer(Layer* layer, + Layer* newParent, + Layer* afterThis) : m_layer(layer) + , m_oldParent(layer->parent()) , m_oldAfterThis(layer->getPrevious()) - , m_newAfterThis(afterThis) + , m_newParent(newParent) + , m_newAfterThis(afterThis == layer ? afterThis->getPrevious(): afterThis) { } void MoveLayer::onExecute() { - m_layer.layer()->parent()->stackLayer( - m_layer.layer(), - m_newAfterThis.layer()); + Layer* layer = m_layer.layer(); + Layer* afterThis = m_newAfterThis.layer(); + LayerGroup* oldParent = static_cast(m_oldParent.layer()); + LayerGroup* newParent = static_cast(m_newParent.layer()); + ASSERT(layer); + ASSERT(oldParent); + ASSERT(newParent); - m_layer.layer()->parent()->incrementVersion(); + oldParent->removeLayer(layer); + newParent->insertLayer(layer, afterThis); + + if (oldParent != newParent) + oldParent->incrementVersion(); + newParent->incrementVersion(); } void MoveLayer::onUndo() { - m_layer.layer()->parent()->stackLayer( - m_layer.layer(), - m_oldAfterThis.layer()); + Layer* layer = m_layer.layer(); + Layer* afterThis = m_oldAfterThis.layer(); + LayerGroup* oldParent = static_cast(m_oldParent.layer()); + LayerGroup* newParent = static_cast(m_newParent.layer()); + ASSERT(layer); + ASSERT(oldParent); + ASSERT(newParent); - m_layer.layer()->parent()->incrementVersion(); + newParent->removeLayer(layer); + oldParent->insertLayer(layer, afterThis); + + if (oldParent != newParent) + oldParent->incrementVersion(); + newParent->incrementVersion(); } void MoveLayer::onFireNotifications() diff --git a/src/app/cmd/move_layer.h b/src/app/cmd/move_layer.h index 6f73fc903..716828ad6 100644 --- a/src/app/cmd/move_layer.h +++ b/src/app/cmd/move_layer.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -18,7 +18,9 @@ namespace cmd { class MoveLayer : public Cmd { public: - MoveLayer(Layer* layer, Layer* afterThis); + MoveLayer(Layer* layer, + Layer* newParent, + Layer* afterThis); protected: void onExecute() override; @@ -30,8 +32,8 @@ namespace cmd { private: WithLayer m_layer; - WithLayer m_oldAfterThis; - WithLayer m_newAfterThis; + WithLayer m_oldParent, m_oldAfterThis; + WithLayer m_newParent, m_newAfterThis; }; } // namespace cmd diff --git a/src/app/commands/cmd_goto_layer.cpp b/src/app/commands/cmd_goto_layer.cpp index 47b1057e0..2ec052698 100644 --- a/src/app/commands/cmd_goto_layer.cpp +++ b/src/app/commands/cmd_goto_layer.cpp @@ -50,11 +50,8 @@ protected: int i = m_offset; while (i-- > 0) { layer = layer->getNextInWholeHierarchy(); - if (!layer) { - layer = site.sprite()->root()->firstLayer(); - while (layer->isBrowsable()) - layer = static_cast(layer)->firstLayer(); - } + if (!layer) + layer = site.sprite()->firstBrowsableLayer(); } } else if (m_offset < 0) { diff --git a/src/app/commands/cmd_new_layer.cpp b/src/app/commands/cmd_new_layer.cpp index 8896e8963..7136370ba 100644 --- a/src/app/commands/cmd_new_layer.cpp +++ b/src/app/commands/cmd_new_layer.cpp @@ -10,6 +10,7 @@ #endif #include "app/app.h" +#include "app/cmd/move_layer.h" #include "app/commands/command.h" #include "app/commands/params.h" #include "app/context_access.h" @@ -107,6 +108,7 @@ void NewLayerCommand::onExecute(Context* context) LayerGroup* parent = sprite->root(); Layer* activeLayer = writer.layer(); + SelectedLayers selLayers = writer.site()->selectedLayers(); if (activeLayer) { if (activeLayer->isGroup() && activeLayer->isExpanded() && @@ -131,11 +133,35 @@ void NewLayerCommand::onExecute(Context* context) else layer = api.newLayer(parent, name); + ASSERT(layer->parent()); + // If "top" parameter is false, create the layer above the active // one. - if (activeLayer && !m_top) + if (activeLayer && !m_top) { api.restackLayerAfter(layer, activeLayer); + // Put all selected layers inside the group + if (m_group && writer.site()->inTimeline()) { + LayerGroup* commonParent = nullptr; + std::size_t sameParents = 0; + for (Layer* l : selLayers) { + if (!commonParent || + commonParent == l->parent()) { + commonParent = l->parent(); + ++sameParents; + } + } + + if (sameParents == selLayers.size()) { + for (Layer* newChild : convert_selected_layers_into_layer_list(selLayers)) { + transaction.execute( + new cmd::MoveLayer(newChild, layer, + static_cast(layer)->lastLayer())); + } + } + } + } + transaction.commit(); } update_screen_for_document(document); diff --git a/src/app/document_api.cpp b/src/app/document_api.cpp index 89448647d..ff9879824 100644 --- a/src/app/document_api.cpp +++ b/src/app/document_api.cpp @@ -425,7 +425,7 @@ void DocumentApi::removeLayer(Layer* layer) void DocumentApi::restackLayerAfter(Layer* layer, Layer* afterThis) { - m_transaction.execute(new cmd::MoveLayer(layer, afterThis)); + m_transaction.execute(new cmd::MoveLayer(layer, layer->parent(), afterThis)); } void DocumentApi::restackLayerBefore(Layer* layer, Layer* beforeThis) diff --git a/src/doc/layer.cpp b/src/doc/layer.cpp index 767a49d8c..c4b84cf31 100644 --- a/src/doc/layer.cpp +++ b/src/doc/layer.cpp @@ -378,16 +378,8 @@ void LayerGroup::removeLayer(Layer* layer) layer->setParent(nullptr); } -void LayerGroup::stackLayer(Layer* layer, Layer* after) +void LayerGroup::insertLayer(Layer* layer, Layer* after) { - ASSERT(layer != after); - if (layer == after) - return; - - auto it = std::find(m_layers.begin(), m_layers.end(), layer); - ASSERT(it != m_layers.end()); - m_layers.erase(it); - if (after) { auto after_it = std::find(m_layers.begin(), m_layers.end(), after); ASSERT(after_it != m_layers.end()); @@ -396,6 +388,18 @@ void LayerGroup::stackLayer(Layer* layer, Layer* after) } else m_layers.insert(m_layers.begin(), layer); + + layer->setParent(this); +} + +void LayerGroup::stackLayer(Layer* layer, Layer* after) +{ + ASSERT(layer != after); + if (layer == after) + return; + + removeLayer(layer); + insertLayer(layer, after); } void LayerGroup::displaceFrames(frame_t fromThis, frame_t delta) diff --git a/src/doc/layer.h b/src/doc/layer.h index 62f659176..e10966514 100644 --- a/src/doc/layer.h +++ b/src/doc/layer.h @@ -180,6 +180,7 @@ namespace doc { void addLayer(Layer* layer); void removeLayer(Layer* layer); + void insertLayer(Layer* layer, Layer* after); void stackLayer(Layer* layer, Layer* after); Layer* firstLayer() const { return (m_layers.empty() ? nullptr: m_layers.front()); } diff --git a/src/doc/selected_layers.cpp b/src/doc/selected_layers.cpp index f2f7ce763..cf38bc300 100644 --- a/src/doc/selected_layers.cpp +++ b/src/doc/selected_layers.cpp @@ -11,6 +11,7 @@ #include "doc/selected_layers.h" #include "doc/layer.h" +#include "doc/sprite.h" namespace doc { @@ -43,4 +44,22 @@ void select_all_layers(LayerGroup* group, SelectedLayers& layers) } } +LayerList convert_selected_layers_into_layer_list(const SelectedLayers& layers) +{ + LayerList output; + + if (layers.empty()) + return output; + + for (Layer* layer = (*layers.begin())->sprite()->firstBrowsableLayer(); + layer != nullptr; + layer = layer->getNextInWholeHierarchy()) { + if (layers.find(layer) != layers.end()) { + output.push_back(layer); + } + } + + return output; +} + } // namespace doc diff --git a/src/doc/selected_layers.h b/src/doc/selected_layers.h index 32ccc1c6d..4958d610d 100644 --- a/src/doc/selected_layers.h +++ b/src/doc/selected_layers.h @@ -9,6 +9,7 @@ #pragma once #include +#include "layer_list.h" namespace doc { @@ -19,6 +20,7 @@ namespace doc { void remove_children_if_parent_is_selected(SelectedLayers& layers); void select_all_layers(LayerGroup* group, SelectedLayers& layers); + LayerList convert_selected_layers_into_layer_list(const SelectedLayers& layers); } // namespace doc diff --git a/src/doc/sprite.cpp b/src/doc/sprite.cpp index c08c7b6b3..77a8ac196 100644 --- a/src/doc/sprite.cpp +++ b/src/doc/sprite.cpp @@ -223,6 +223,14 @@ LayerIndex Sprite::firstLayer() const return LayerIndex(0); } +Layer* Sprite::firstBrowsableLayer() const +{ + Layer* layer = root()->firstLayer(); + while (layer->isBrowsable()) + layer = static_cast(layer)->firstLayer(); + return layer; +} + LayerIndex Sprite::lastLayer() const { return LayerIndex(root()->layersCount()-1); diff --git a/src/doc/sprite.h b/src/doc/sprite.h index 8147a6525..dc0d6dad4 100644 --- a/src/doc/sprite.h +++ b/src/doc/sprite.h @@ -95,6 +95,7 @@ namespace doc { LayerIndex countLayers() const; LayerIndex firstLayer() const; + Layer* firstBrowsableLayer() const; LayerIndex lastLayer() const; Layer* layer(int layerIndex) const;