Add support to move layer groups with the move tool

Related to #1172, #1318, #454
This commit is contained in:
David Capello 2016-11-30 19:58:04 -03:00
parent 1378275364
commit 2e457fecad
5 changed files with 91 additions and 34 deletions

View File

@ -65,6 +65,12 @@ void DocumentRange::endRange(Layer* toLayer, frame_t toFrame)
selectFrameRange(m_selectingFromFrame, toFrame);
}
void DocumentRange::selectLayers(const SelectedLayers& selLayers)
{
for (auto layer : selLayers)
m_selectedLayers.insert(layer);
}
bool DocumentRange::contains(Layer* layer) const
{
if (enabled())

View File

@ -37,11 +37,9 @@ namespace app {
void displace(layer_t layerDelta, frame_t frameDelta);
bool contains(Layer* layer) const;
bool contains(frame_t frame) const {
return m_selectedFrames.contains(frame);
}
bool contains(Layer* layer, frame_t frame) const {
return contains(layer) && contains(frame);
}
@ -50,6 +48,8 @@ namespace app {
void startRange(Layer* fromLayer, frame_t fromFrame, Type type);
void endRange(Layer* toLayer, frame_t toFrame);
void selectLayers(const SelectedLayers& selLayers);
frame_t firstFrame() const { return m_selectedFrames.firstFrame(); }
frame_t lastFrame() const { return m_selectedFrames.lastFrame(); }

View File

@ -33,10 +33,51 @@ namespace app {
using namespace ui;
MovingCelCollect::MovingCelCollect(Editor* editor, Layer* layer)
: m_mainCel(nullptr)
{
ASSERT(editor);
if (layer && layer->isImage())
m_mainCel = layer->cel(editor->frame());
DocumentRange range = App::instance()->timeline()->range();
if (!range.enabled()) {
range.startRange(editor->layer(), editor->frame(), DocumentRange::kCels);
range.endRange(editor->layer(), editor->frame());
}
DocumentRange range2 = range;
for (Layer* layer : range.selectedLayers()) {
if (layer && layer->isGroup()) {
LayerList childrenList;
static_cast<LayerGroup*>(layer)->allLayers(childrenList);
SelectedLayers selChildren;
for (auto layer : childrenList)
selChildren.insert(layer);
range2.selectLayers(selChildren);
}
}
// Record start positions of all cels in selected range
for (Cel* cel : get_unique_cels(editor->sprite(), range2)) {
Layer* layer = cel->layer();
ASSERT(layer);
if (layer && layer->isMovable() && !layer->isBackground())
m_celList.push_back(cel);
}
}
MovingCelState::MovingCelState(Editor* editor,
MouseMessage* msg,
const HandleType handle)
const HandleType handle,
const MovingCelCollect& collect)
: m_reader(UIContext::instance(), 500)
, m_cel(nullptr)
, m_celList(collect.celList())
, m_celOffset(0.0, 0.0)
, m_celScale(1.0, 1.0)
, m_canceled(false)
@ -46,28 +87,19 @@ MovingCelState::MovingCelState(Editor* editor,
{
ContextWriter writer(m_reader, 500);
Document* document = editor->document();
auto range = App::instance()->timeline()->range();
LayerImage* layer = static_cast<LayerImage*>(editor->layer());
ASSERT(layer->isImage());
m_cel = layer->cel(editor->frame());
ASSERT(m_cel); // The cel cannot be null
if (!range.enabled())
range = DocumentRange(m_cel);
ASSERT(!m_celList.empty());
m_cel = collect.mainCel();
if (m_cel)
m_celMainSize = m_cel->boundsF().size();
// Record start positions of all cels in selected range
for (Cel* cel : get_unique_cels(writer.sprite(), range)) {
for (Cel* cel : m_celList) {
Layer* layer = cel->layer();
ASSERT(layer);
if (layer && layer->isMovable() && !layer->isBackground()) {
m_celList.push_back(cel);
if (cel->layer()->isReference()) {
if (layer->isReference()) {
m_celStarts.push_back(cel->boundsF());
m_hasReference = true;
}

View File

@ -23,11 +23,26 @@ namespace doc {
namespace app {
class Editor;
class MovingCelCollect {
public:
MovingCelCollect(Editor* editor, Layer* layer);
bool empty() const { return m_celList.empty(); }
Cel* mainCel() const { return m_mainCel; }
const CelList& celList() const { return m_celList; }
private:
Cel* m_mainCel;
CelList m_celList;
};
class MovingCelState : public StandbyState {
public:
MovingCelState(Editor* editor,
ui::MouseMessage* msg,
const HandleType handle);
const HandleType handle,
const MovingCelCollect& collect);
virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;

View File

@ -204,7 +204,7 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
}
}
if (layer && layer->isImage()) {
if (layer) {
// TODO we should be able to move the `Background' with tiled mode
if (layer->isBackground()) {
StatusBar::instance()->showTip(1000,
@ -218,24 +218,28 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
StatusBar::instance()->showTip(1000,
"Layer '%s' is locked", layer->name().c_str());
}
else if (!layer->cel(editor->frame())) {
StatusBar::instance()->showTip(1000,
"Cel is empty, nothing to move");
}
else {
try {
// Change to MovingCelState
HandleType handle = MoveHandle;
if (resizeCelBounds(editor).contains(msg->position()))
handle = ScaleSEHandle;
MovingCelState* newState = new MovingCelState(editor, msg, handle);
editor->setState(EditorStatePtr(newState));
MovingCelCollect collect(editor, layer);
if (collect.empty()) {
StatusBar::instance()->showTip(
1000, "Nothing to move");
}
catch (const LockedDocumentException&) {
// TODO break the background task that is locking this sprite
StatusBar::instance()->showTip(1000,
"Sprite is used by a backup/data recovery task");
else {
try {
// Change to MovingCelState
HandleType handle = MoveHandle;
if (resizeCelBounds(editor).contains(msg->position()))
handle = ScaleSEHandle;
MovingCelState* newState = new MovingCelState(
editor, msg, handle, collect);
editor->setState(EditorStatePtr(newState));
}
catch (const LockedDocumentException&) {
// TODO break the background task that is locking this sprite
StatusBar::instance()->showTip(
1000, "Sprite is used by a backup/data recovery task");
}
}
}
}