mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-07 10:21:30 +00:00
Generate selection boundaries automatically after transactions
Now Transaction::commit() will regenerate mask boundaries automatically if in the middle of the transaction the document selection was modified. This is the first step to finally remove update_screen_for_document() and any kind of manual screen refresh. This will be useful for scripting functions that modify the selection too, because we wouldn't need to regenerate the selection boundaries automatically from the script or from app.refresh() Lua function. Related to #378
This commit is contained in:
parent
668b29193a
commit
7594ebf25b
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -27,6 +28,7 @@ void DeselectMask::onExecute()
|
|||||||
Doc* doc = document();
|
Doc* doc = document();
|
||||||
m_oldMask.reset(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr);
|
m_oldMask.reset(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr);
|
||||||
doc->setMaskVisible(false);
|
doc->setMaskVisible(false);
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeselectMask::onUndo()
|
void DeselectMask::onUndo()
|
||||||
@ -35,6 +37,7 @@ void DeselectMask::onUndo()
|
|||||||
|
|
||||||
doc->setMask(m_oldMask.get());
|
doc->setMask(m_oldMask.get());
|
||||||
doc->setMaskVisible(true);
|
doc->setMaskVisible(true);
|
||||||
|
doc->notifySelectionChanged();
|
||||||
|
|
||||||
m_oldMask.reset();
|
m_oldMask.reset();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -37,8 +38,8 @@ void FlipMask::onUndo()
|
|||||||
|
|
||||||
void FlipMask::swap()
|
void FlipMask::swap()
|
||||||
{
|
{
|
||||||
Doc* document = this->document();
|
Doc* doc = this->document();
|
||||||
Mask* mask = document->mask();
|
Mask* mask = doc->mask();
|
||||||
|
|
||||||
ASSERT(mask->bitmap());
|
ASSERT(mask->bitmap());
|
||||||
if (!mask->bitmap())
|
if (!mask->bitmap())
|
||||||
@ -48,6 +49,8 @@ void FlipMask::swap()
|
|||||||
doc::algorithm::flip_image(mask->bitmap(),
|
doc::algorithm::flip_image(mask->bitmap(),
|
||||||
mask->bitmap()->bounds(), m_flipType);
|
mask->bitmap()->bounds(), m_flipType);
|
||||||
mask->unfreeze();
|
mask->unfreeze();
|
||||||
|
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cmd
|
} // namespace cmd
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -32,6 +33,7 @@ void ReselectMask::onExecute()
|
|||||||
}
|
}
|
||||||
|
|
||||||
doc->setMaskVisible(true);
|
doc->setMaskVisible(true);
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReselectMask::onUndo()
|
void ReselectMask::onUndo()
|
||||||
@ -41,6 +43,7 @@ void ReselectMask::onUndo()
|
|||||||
m_oldMask.reset(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr);
|
m_oldMask.reset(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr);
|
||||||
|
|
||||||
doc->setMaskVisible(false);
|
doc->setMaskVisible(false);
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ReselectMask::onMemSize() const
|
size_t ReselectMask::onMemSize() const
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -16,14 +17,14 @@
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace cmd {
|
namespace cmd {
|
||||||
|
|
||||||
SetMask::SetMask(Doc* doc, Mask* newMask)
|
SetMask::SetMask(Doc* doc, const Mask* newMask)
|
||||||
: WithDocument(doc)
|
: WithDocument(doc)
|
||||||
, m_oldMask(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr)
|
, m_oldMask(doc->isMaskVisible() ? new Mask(*doc->mask()): nullptr)
|
||||||
, m_newMask(newMask && !newMask->isEmpty() ? new Mask(*newMask): nullptr)
|
, m_newMask(newMask && !newMask->isEmpty() ? new Mask(*newMask): nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMask::setNewMask(Mask* newMask)
|
void SetMask::setNewMask(const Mask* newMask)
|
||||||
{
|
{
|
||||||
m_newMask.reset(newMask ? new Mask(*newMask): nullptr);
|
m_newMask.reset(newMask ? new Mask(*newMask): nullptr);
|
||||||
setMask(m_newMask.get());
|
setMask(m_newMask.get());
|
||||||
@ -46,7 +47,7 @@ size_t SetMask::onMemSize() const
|
|||||||
(m_newMask ? m_newMask->getMemSize(): 0);
|
(m_newMask ? m_newMask->getMemSize(): 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMask::setMask(Mask* mask)
|
void SetMask::setMask(const Mask* mask)
|
||||||
{
|
{
|
||||||
Doc* doc = document();
|
Doc* doc = document();
|
||||||
|
|
||||||
@ -59,6 +60,8 @@ void SetMask::setMask(Mask* mask)
|
|||||||
doc->setMask(&empty);
|
doc->setMask(&empty);
|
||||||
doc->setMaskVisible(false);
|
doc->setMaskVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cmd
|
} // namespace cmd
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -25,10 +26,10 @@ namespace cmd {
|
|||||||
class SetMask : public Cmd
|
class SetMask : public Cmd
|
||||||
, public WithDocument {
|
, public WithDocument {
|
||||||
public:
|
public:
|
||||||
SetMask(Doc* doc, Mask* newMask);
|
SetMask(Doc* doc, const Mask* newMask);
|
||||||
|
|
||||||
// Used to change the new mask used in the onRedo()
|
// Used to change the new mask used in the onRedo()
|
||||||
void setNewMask(Mask* newMask);
|
void setNewMask(const Mask* newMask);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
@ -36,7 +37,7 @@ namespace cmd {
|
|||||||
size_t onMemSize() const override;
|
size_t onMemSize() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setMask(Mask* mask);
|
void setMask(const Mask* mask);
|
||||||
|
|
||||||
std::unique_ptr<Mask> m_oldMask;
|
std::unique_ptr<Mask> m_oldMask;
|
||||||
std::unique_ptr<Mask> m_newMask;
|
std::unique_ptr<Mask> m_newMask;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -38,6 +39,8 @@ void SetMaskPosition::setMaskPosition(const gfx::Point& pos)
|
|||||||
Doc* doc = document();
|
Doc* doc = document();
|
||||||
doc->mask()->setOrigin(pos.x, pos.y);
|
doc->mask()->setOrigin(pos.x, pos.y);
|
||||||
doc->resetTransformation();
|
doc->resetTransformation();
|
||||||
|
|
||||||
|
doc->notifySelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cmd
|
} // namespace cmd
|
||||||
|
@ -352,8 +352,6 @@ void CanvasSizeCommand::onExecute(Context* context)
|
|||||||
MID(1, y2-y1, DOC_SPRITE_MAX_HEIGHT)));
|
MID(1, y2-y1, DOC_SPRITE_MAX_HEIGHT)));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
doc->generateMaskBoundaries();
|
|
||||||
|
|
||||||
#ifdef ENABLE_UI
|
#ifdef ENABLE_UI
|
||||||
if (context->isUIAvailable())
|
if (context->isUIAvailable())
|
||||||
update_screen_for_document(doc);
|
update_screen_for_document(doc);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -74,7 +75,6 @@ void CropSpriteCommand::onExecute(Context* context)
|
|||||||
document->getApi(tx).cropSprite(sprite, bounds);
|
document->getApi(tx).cropSprite(sprite, bounds);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
}
|
}
|
||||||
document->generateMaskBoundaries();
|
|
||||||
|
|
||||||
#ifdef ENABLE_UI
|
#ifdef ENABLE_UI
|
||||||
if (context->isUIAvailable())
|
if (context->isUIAvailable())
|
||||||
@ -112,7 +112,6 @@ void AutocropSpriteCommand::onExecute(Context* context)
|
|||||||
document->getApi(tx).trimSprite(sprite);
|
document->getApi(tx).trimSprite(sprite);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
}
|
}
|
||||||
document->generateMaskBoundaries();
|
|
||||||
|
|
||||||
#ifdef ENABLE_UI
|
#ifdef ENABLE_UI
|
||||||
if (context->isUIAvailable())
|
if (context->isUIAvailable())
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -47,7 +48,6 @@ void DeselectMaskCommand::onExecute(Context* context)
|
|||||||
tx(new cmd::DeselectMask(document));
|
tx(new cmd::DeselectMask(document));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
}
|
}
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -222,8 +223,6 @@ void FlipCommand::onExecute(Context* context)
|
|||||||
(m_flipType == doc::algorithm::FlipVertical ?
|
(m_flipType == doc::algorithm::FlipVertical ?
|
||||||
sprite->height() - mask->bounds().y2():
|
sprite->height() - mask->bounds().y2():
|
||||||
mask->bounds().y))));
|
mask->bounds().y))));
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -96,7 +97,6 @@ void InvertMaskCommand::onExecute(Context* context)
|
|||||||
tx(new cmd::SetMask(document, mask.get()));
|
tx(new cmd::SetMask(document, mask.get()));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -80,7 +81,6 @@ void LoadMaskCommand::onExecute(Context* context)
|
|||||||
tx(new cmd::SetMask(document, mask.get()));
|
tx(new cmd::SetMask(document, mask.get()));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -50,10 +51,8 @@ void MaskAllCommand::onExecute(Context* context)
|
|||||||
|
|
||||||
Tx tx(writer.context(), "Select All", DoesntModifyDocument);
|
Tx tx(writer.context(), "Select All", DoesntModifyDocument);
|
||||||
tx(new cmd::SetMask(document, &newMask));
|
tx(new cmd::SetMask(document, &newMask));
|
||||||
tx.commit();
|
|
||||||
|
|
||||||
document->resetTransformation();
|
document->resetTransformation();
|
||||||
document->generateMaskBoundaries();
|
tx.commit();
|
||||||
|
|
||||||
if (Preferences::instance().selection.autoShowSelectionEdges()) {
|
if (Preferences::instance().selection.autoShowSelectionEdges()) {
|
||||||
DocumentPreferences& docPref = Preferences::instance().document(document);
|
DocumentPreferences& docPref = Preferences::instance().document(document);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -189,9 +189,11 @@ void MaskByColorCommand::onExecute(Context* context)
|
|||||||
set_config_int("MaskColor", "Tolerance", m_sliderTolerance->getValue());
|
set_config_int("MaskColor", "Tolerance", m_sliderTolerance->getValue());
|
||||||
set_config_bool("MaskColor", "Preview", m_checkPreview->isSelected());
|
set_config_bool("MaskColor", "Preview", m_checkPreview->isSelected());
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
document->generateMaskBoundaries();
|
||||||
|
}
|
||||||
|
|
||||||
// Update boundaries and editors.
|
// Update boundaries and editors.
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
|
|
||||||
// Save window configuration.
|
// Save window configuration.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -83,10 +84,8 @@ void MaskContentCommand::onExecute(Context* context)
|
|||||||
|
|
||||||
Tx tx(writer.context(), "Select Content", DoesntModifyDocument);
|
Tx tx(writer.context(), "Select Content", DoesntModifyDocument);
|
||||||
tx(new cmd::SetMask(document, &newMask));
|
tx(new cmd::SetMask(document, &newMask));
|
||||||
tx.commit();
|
|
||||||
|
|
||||||
document->resetTransformation();
|
document->resetTransformation();
|
||||||
document->generateMaskBoundaries();
|
tx.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select marquee tool
|
// Select marquee tool
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2015-2018 David Capello
|
// Copyright (C) 2015-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -143,7 +144,6 @@ void ModifySelectionCommand::onExecute(Context* context)
|
|||||||
tx(new cmd::SetMask(document, mask.get()));
|
tx(new cmd::SetMask(document, mask.get()));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -88,7 +89,6 @@ void MoveMaskCommand::onExecute(Context* context)
|
|||||||
tx.commit();
|
tx.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -53,7 +54,6 @@ void ReselectMaskCommand::onExecute(Context* context)
|
|||||||
tx.commit();
|
tx.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
document->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -243,7 +244,6 @@ void RotateCommand::onExecute(Context* context)
|
|||||||
job.startJob();
|
job.startJob();
|
||||||
job.waitJob();
|
job.waitJob();
|
||||||
}
|
}
|
||||||
reader.document()->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(reader.document());
|
update_screen_for_document(reader.document());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2015-2018 David Capello
|
// Copyright (C) 2015-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -109,7 +109,6 @@ void SelectTileCommand::onExecute(Context* ctx)
|
|||||||
tx(new cmd::SetMask(doc, mask.get()));
|
tx(new cmd::SetMask(doc, mask.get()));
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
|
||||||
doc->generateMaskBoundaries();
|
|
||||||
update_screen_for_document(doc);
|
update_screen_for_document(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -180,6 +180,12 @@ void Doc::notifySelectionChanged()
|
|||||||
notify_observers<DocEvent&>(&DocObserver::onSelectionChanged, ev);
|
notify_observers<DocEvent&>(&DocObserver::onSelectionChanged, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Doc::notifySelectionBoundariesChanged()
|
||||||
|
{
|
||||||
|
DocEvent ev(this);
|
||||||
|
notify_observers<DocEvent&>(&DocObserver::onSelectionBoundariesChanged, ev);
|
||||||
|
}
|
||||||
|
|
||||||
bool Doc::isModified() const
|
bool Doc::isModified() const
|
||||||
{
|
{
|
||||||
return !m_undo->isSavedState();
|
return !m_undo->isSavedState();
|
||||||
@ -252,8 +258,7 @@ void Doc::generateMaskBoundaries(const Mask* mask)
|
|||||||
mask->bounds().y);
|
mask->bounds().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move this to the exact place where selection is modified.
|
notifySelectionBoundariesChanged();
|
||||||
notifySelectionChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -261,7 +266,9 @@ void Doc::generateMaskBoundaries(const Mask* mask)
|
|||||||
|
|
||||||
void Doc::setMask(const Mask* mask)
|
void Doc::setMask(const Mask* mask)
|
||||||
{
|
{
|
||||||
m_mask.reset(new Mask(*mask));
|
ASSERT(mask);
|
||||||
|
|
||||||
|
m_mask->copyFrom(mask);
|
||||||
m_flags |= kMaskVisible;
|
m_flags |= kMaskVisible;
|
||||||
|
|
||||||
resetTransformation();
|
resetTransformation();
|
||||||
@ -271,7 +278,6 @@ bool Doc::isMaskVisible() const
|
|||||||
{
|
{
|
||||||
return
|
return
|
||||||
(m_flags & kMaskVisible) && // The mask was not hidden by the user explicitly
|
(m_flags & kMaskVisible) && // The mask was not hidden by the user explicitly
|
||||||
m_mask && // The mask does exist
|
|
||||||
!m_mask->isEmpty(); // The mask is not empty
|
!m_mask->isEmpty(); // The mask is not empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,10 +304,7 @@ void Doc::setTransformation(const Transformation& transform)
|
|||||||
|
|
||||||
void Doc::resetTransformation()
|
void Doc::resetTransformation()
|
||||||
{
|
{
|
||||||
if (m_mask)
|
m_transformation = Transformation(gfx::RectF(m_mask->bounds()));
|
||||||
m_transformation = Transformation(gfx::RectF(m_mask->bounds()));
|
|
||||||
else
|
|
||||||
m_transformation = Transformation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -96,6 +96,7 @@ namespace app {
|
|||||||
void notifyCelMoved(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
|
void notifyCelMoved(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
|
||||||
void notifyCelCopied(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
|
void notifyCelCopied(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame);
|
||||||
void notifySelectionChanged();
|
void notifySelectionChanged();
|
||||||
|
void notifySelectionBoundariesChanged();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// File related properties
|
// File related properties
|
||||||
@ -211,7 +212,7 @@ namespace app {
|
|||||||
ExtraCelRef m_extraCel;
|
ExtraCelRef m_extraCel;
|
||||||
|
|
||||||
// Current mask.
|
// Current mask.
|
||||||
std::unique_ptr<Mask> m_mask;
|
std::unique_ptr<doc::Mask> m_mask;
|
||||||
|
|
||||||
// Current transformation.
|
// Current transformation.
|
||||||
Transformation m_transformation;
|
Transformation m_transformation;
|
||||||
|
@ -68,6 +68,7 @@ namespace app {
|
|||||||
|
|
||||||
// The selection has changed.
|
// The selection has changed.
|
||||||
virtual void onSelectionChanged(DocEvent& ev) { }
|
virtual void onSelectionChanged(DocEvent& ev) { }
|
||||||
|
virtual void onSelectionBoundariesChanged(DocEvent& ev) { }
|
||||||
|
|
||||||
// Called to destroy the observable. (Here you could call "delete this".)
|
// Called to destroy the observable. (Here you could call "delete this".)
|
||||||
virtual void dispose() { }
|
virtual void dispose() { }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/doc_undo.h"
|
#include "app/doc_undo.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
#include "ui/system.h"
|
||||||
|
|
||||||
#define TX_TRACE(...)
|
#define TX_TRACE(...)
|
||||||
|
|
||||||
@ -25,17 +26,22 @@ using namespace doc;
|
|||||||
|
|
||||||
Transaction::Transaction(Context* ctx, const std::string& label, Modification modification)
|
Transaction::Transaction(Context* ctx, const std::string& label, Modification modification)
|
||||||
: m_ctx(ctx)
|
: m_ctx(ctx)
|
||||||
, m_cmds(NULL)
|
, m_doc(nullptr)
|
||||||
|
, m_undo(nullptr)
|
||||||
|
, m_cmds(nullptr)
|
||||||
|
, m_changes(Changes::kNone)
|
||||||
{
|
{
|
||||||
TX_TRACE("TX: Start <%s> (%s)\n",
|
TX_TRACE("TX: Start <%s> (%s)\n",
|
||||||
label.c_str(),
|
label.c_str(),
|
||||||
modification == ModifyDocument ? "modifies document":
|
modification == ModifyDocument ? "modifies document":
|
||||||
"doesn't modify document");
|
"doesn't modify document");
|
||||||
|
|
||||||
Doc* doc = m_ctx->activeDocument();
|
m_doc = m_ctx->activeDocument();
|
||||||
if (!doc)
|
if (!m_doc)
|
||||||
throw std::runtime_error("No active document to execute a transaction");
|
throw std::runtime_error("No active document to execute a transaction");
|
||||||
m_undo = doc->undoHistory();
|
|
||||||
|
m_doc->add_observer(this);
|
||||||
|
m_undo = m_doc->undoHistory();
|
||||||
|
|
||||||
m_cmds = new CmdTransaction(label,
|
m_cmds = new CmdTransaction(label,
|
||||||
modification == Modification::ModifyDocument,
|
modification == Modification::ModifyDocument,
|
||||||
@ -60,6 +66,8 @@ Transaction::~Transaction()
|
|||||||
|
|
||||||
// TODO logging error
|
// TODO logging error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_doc->remove_observer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to set the document range after all the transaction is
|
// Used to set the document range after all the transaction is
|
||||||
@ -73,12 +81,17 @@ void Transaction::setNewDocRange(const DocRange& range)
|
|||||||
|
|
||||||
void Transaction::commit()
|
void Transaction::commit()
|
||||||
{
|
{
|
||||||
|
ui::assert_ui_thread();
|
||||||
ASSERT(m_cmds);
|
ASSERT(m_cmds);
|
||||||
TX_TRACE("TX: Commit <%s>\n", m_cmds->label().c_str());
|
TX_TRACE("TX: Commit <%s>\n", m_cmds->label().c_str());
|
||||||
|
|
||||||
m_cmds->commit();
|
m_cmds->commit();
|
||||||
m_undo->add(m_cmds);
|
m_undo->add(m_cmds);
|
||||||
m_cmds = NULL;
|
m_cmds = nullptr;
|
||||||
|
|
||||||
|
// Process changes
|
||||||
|
if (int(m_changes) & int(Changes::kSelection))
|
||||||
|
m_doc->generateMaskBoundaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transaction::rollback()
|
void Transaction::rollback()
|
||||||
@ -89,7 +102,7 @@ void Transaction::rollback()
|
|||||||
m_cmds->undo();
|
m_cmds->undo();
|
||||||
|
|
||||||
delete m_cmds;
|
delete m_cmds;
|
||||||
m_cmds = NULL;
|
m_cmds = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transaction::execute(Cmd* cmd)
|
void Transaction::execute(Cmd* cmd)
|
||||||
@ -112,4 +125,9 @@ void Transaction::execute(Cmd* cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Transaction::onSelectionChanged(DocEvent& ev)
|
||||||
|
{
|
||||||
|
m_changes = Changes(int(m_changes) | int(Changes::kSelection));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -8,6 +9,8 @@
|
|||||||
#define APP_TRANSACTION_H_INCLUDED
|
#define APP_TRANSACTION_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/doc_observer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
@ -38,7 +41,7 @@ namespace app {
|
|||||||
// transaction.commit();
|
// transaction.commit();
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
class Transaction {
|
class Transaction : public DocObserver {
|
||||||
public:
|
public:
|
||||||
// Starts a undoable sequence of operations in a transaction that
|
// Starts a undoable sequence of operations in a transaction that
|
||||||
// can be committed or rollbacked. All the operations will be
|
// can be committed or rollbacked. All the operations will be
|
||||||
@ -67,11 +70,20 @@ namespace app {
|
|||||||
void execute(Cmd* cmd);
|
void execute(Cmd* cmd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// List of changes during the execution of this transaction
|
||||||
|
enum class Changes { kNone = 0,
|
||||||
|
kSelection = 1 };
|
||||||
|
|
||||||
void rollback();
|
void rollback();
|
||||||
|
|
||||||
|
// DocObserver impl
|
||||||
|
void onSelectionChanged(DocEvent& ev) override;
|
||||||
|
|
||||||
Context* m_ctx;
|
Context* m_ctx;
|
||||||
|
Doc* m_doc;
|
||||||
DocUndo* m_undo;
|
DocUndo* m_undo;
|
||||||
CmdTransaction* m_cmds;
|
CmdTransaction* m_cmds;
|
||||||
|
Changes m_changes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -463,7 +464,6 @@ public:
|
|||||||
}
|
}
|
||||||
// Selection ink
|
// Selection ink
|
||||||
else if (getInk()->isSelection()) {
|
else if (getInk()->isSelection()) {
|
||||||
m_document->generateMaskBoundaries();
|
|
||||||
redraw = true;
|
redraw = true;
|
||||||
|
|
||||||
// Show selection edges
|
// Show selection edges
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -1784,7 +1784,7 @@ void Timeline::onRemoveFrame(DocEvent& ev)
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::onSelectionChanged(DocEvent& ev)
|
void Timeline::onSelectionBoundariesChanged(DocEvent& ev)
|
||||||
{
|
{
|
||||||
if (m_rangeLocks == 0)
|
if (m_rangeLocks == 0)
|
||||||
clearAndInvalidateRange();
|
clearAndInvalidateRange();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018 Igara Studio S.A.
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -144,7 +144,7 @@ namespace app {
|
|||||||
void onAfterRemoveLayer(DocEvent& ev) override;
|
void onAfterRemoveLayer(DocEvent& ev) override;
|
||||||
void onAddFrame(DocEvent& ev) override;
|
void onAddFrame(DocEvent& ev) override;
|
||||||
void onRemoveFrame(DocEvent& ev) override;
|
void onRemoveFrame(DocEvent& ev) override;
|
||||||
void onSelectionChanged(DocEvent& ev) override;
|
void onSelectionBoundariesChanged(DocEvent& ev) override;
|
||||||
void onLayerNameChange(DocEvent& ev) override;
|
void onLayerNameChange(DocEvent& ev) override;
|
||||||
void onAddFrameTag(DocEvent& ev) override;
|
void onAddFrameTag(DocEvent& ev) override;
|
||||||
void onRemoveFrameTag(DocEvent& ev) override;
|
void onRemoveFrameTag(DocEvent& ev) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user