2014-10-20 22:21:31 -03:00
|
|
|
// Aseprite Document Library
|
2016-06-07 19:38:56 -03:00
|
|
|
// Copyright (c) 2001-2016 David Capello
|
2014-10-20 22:21:31 -03:00
|
|
|
//
|
|
|
|
// This file is released under the terms of the MIT license.
|
|
|
|
// Read LICENSE.txt for more information.
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "config.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#endif
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-10-20 22:21:31 -03:00
|
|
|
#include "doc/layer.h"
|
2011-03-24 13:10:48 -03:00
|
|
|
|
2014-10-20 22:21:31 -03:00
|
|
|
#include "doc/cel.h"
|
|
|
|
#include "doc/image.h"
|
|
|
|
#include "doc/primitives.h"
|
|
|
|
#include "doc/sprite.h"
|
2011-03-24 11:50:00 -03:00
|
|
|
|
|
|
|
#include <algorithm>
|
2015-03-05 12:40:47 -03:00
|
|
|
#include <cstring>
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-10-20 22:21:31 -03:00
|
|
|
namespace doc {
|
2008-10-01 01:27:51 +00:00
|
|
|
|
2013-11-09 19:59:05 -03:00
|
|
|
Layer::Layer(ObjectType type, Sprite* sprite)
|
2015-12-10 18:34:25 -03:00
|
|
|
: WithUserData(type)
|
2014-11-16 23:03:30 -03:00
|
|
|
, m_sprite(sprite)
|
|
|
|
, m_parent(NULL)
|
|
|
|
, m_flags(LayerFlags(
|
|
|
|
int(LayerFlags::Visible) |
|
|
|
|
int(LayerFlags::Editable)))
|
2008-10-01 01:27:51 +00:00
|
|
|
{
|
2016-06-07 19:38:56 -03:00
|
|
|
ASSERT(type == ObjectType::LayerImage || type == ObjectType::LayerGroup);
|
2008-10-01 01:27:51 +00:00
|
|
|
|
2010-09-19 00:03:32 -03:00
|
|
|
setName("Layer");
|
2008-10-01 01:27:51 +00:00
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
Layer::~Layer()
|
|
|
|
{
|
|
|
|
}
|
2008-10-01 01:27:51 +00:00
|
|
|
|
2010-10-03 15:51:03 -03:00
|
|
|
int Layer::getMemSize() const
|
|
|
|
{
|
|
|
|
return sizeof(Layer);
|
|
|
|
}
|
|
|
|
|
2013-01-11 12:43:25 -03:00
|
|
|
Layer* Layer::getPrevious() const
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
if (m_parent) {
|
|
|
|
auto it =
|
|
|
|
std::find(m_parent->layers().begin(),
|
|
|
|
m_parent->layers().end(), this);
|
2009-11-17 13:12:26 +00:00
|
|
|
|
2016-06-08 16:46:15 -03:00
|
|
|
if (it != m_parent->layers().end() &&
|
|
|
|
it != m_parent->layers().begin()) {
|
2009-11-17 13:12:26 +00:00
|
|
|
it--;
|
|
|
|
return *it;
|
2008-10-01 01:27:51 +00:00
|
|
|
}
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2016-06-08 16:46:15 -03:00
|
|
|
return nullptr;
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2008-10-01 01:27:51 +00:00
|
|
|
|
2013-01-11 12:43:25 -03:00
|
|
|
Layer* Layer::getNext() const
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
if (m_parent) {
|
|
|
|
auto it =
|
|
|
|
std::find(m_parent->layers().begin(),
|
|
|
|
m_parent->layers().end(), this);
|
2009-11-17 13:12:26 +00:00
|
|
|
|
2016-06-08 16:46:15 -03:00
|
|
|
if (it != m_parent->layers().end()) {
|
2009-11-17 13:12:26 +00:00
|
|
|
it++;
|
2016-06-08 16:46:15 -03:00
|
|
|
if (it != m_parent->layers().end())
|
2012-01-05 19:45:03 -03:00
|
|
|
return *it;
|
2008-10-01 01:27:51 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-08 16:46:15 -03:00
|
|
|
return nullptr;
|
2008-10-01 01:27:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-14 15:00:11 -03:00
|
|
|
Layer* Layer::getPreviousInWholeHierarchy() const
|
|
|
|
{
|
|
|
|
// Go to children
|
2016-06-15 15:49:39 -03:00
|
|
|
if (isGroup() && isExpanded())
|
2016-06-14 15:00:11 -03:00
|
|
|
return static_cast<const LayerGroup*>(this)->lastLayer();
|
|
|
|
|
|
|
|
// Go to previous layer
|
|
|
|
if (Layer* prev = getPrevious())
|
|
|
|
return prev;
|
|
|
|
|
|
|
|
// Go to previous layer in the parent
|
|
|
|
return parent()->getPrevious();
|
|
|
|
}
|
|
|
|
|
|
|
|
Layer* Layer::getNextInWholeHierarchy() const
|
|
|
|
{
|
|
|
|
// Go to next layer
|
|
|
|
if (Layer* next = getNext()) {
|
|
|
|
// Go to children
|
2016-06-15 15:49:39 -03:00
|
|
|
while (next->isGroup() && next->isExpanded()) {
|
2016-06-14 15:00:11 -03:00
|
|
|
Layer* firstChild = static_cast<const LayerGroup*>(next)->firstLayer();
|
|
|
|
if (!firstChild)
|
|
|
|
break;
|
|
|
|
next = firstChild;
|
|
|
|
}
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go to parent
|
|
|
|
if (m_sprite && parent() != m_sprite->root())
|
|
|
|
return m_parent;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-06-15 15:27:38 -03:00
|
|
|
bool Layer::isVisibleHierarchy() const
|
|
|
|
{
|
|
|
|
const Layer* layer = this;
|
|
|
|
while (layer) {
|
|
|
|
if (!layer->isVisible())
|
|
|
|
return false;
|
|
|
|
layer = layer->parent();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Layer::isEditableHierarchy() const
|
|
|
|
{
|
|
|
|
const Layer* layer = this;
|
|
|
|
while (layer) {
|
|
|
|
if (!layer->isEditable())
|
|
|
|
return false;
|
|
|
|
layer = layer->parent();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-12-28 11:06:11 -03:00
|
|
|
Cel* Layer::cel(frame_t frame) const
|
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
return nullptr;
|
2014-12-28 11:06:11 -03:00
|
|
|
}
|
|
|
|
|
2008-10-01 01:27:51 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
2009-11-17 13:12:26 +00:00
|
|
|
// LayerImage class
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
LayerImage::LayerImage(Sprite* sprite)
|
2014-10-20 22:21:31 -03:00
|
|
|
: Layer(ObjectType::LayerImage, sprite)
|
2015-06-13 21:29:16 -03:00
|
|
|
, m_blendmode(BlendMode::NORMAL)
|
2015-06-23 11:25:00 -03:00
|
|
|
, m_opacity(255)
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
LayerImage::~LayerImage()
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2011-03-24 13:15:09 -03:00
|
|
|
destroyAllCels();
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2010-10-03 15:51:03 -03:00
|
|
|
int LayerImage::getMemSize() const
|
|
|
|
{
|
|
|
|
int size = sizeof(LayerImage);
|
|
|
|
CelConstIterator it = getCelBegin();
|
|
|
|
CelConstIterator end = getCelEnd();
|
|
|
|
|
|
|
|
for (; it != end; ++it) {
|
|
|
|
const Cel* cel = *it;
|
|
|
|
size += cel->getMemSize();
|
|
|
|
|
2014-07-30 01:28:15 -03:00
|
|
|
const Image* image = cel->image();
|
2010-10-03 15:51:03 -03:00
|
|
|
size += image->getMemSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2011-03-24 13:15:09 -03:00
|
|
|
void LayerImage::destroyAllCels()
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
2010-09-19 00:15:44 -03:00
|
|
|
CelIterator it = getCelBegin();
|
|
|
|
CelIterator end = getCelEnd();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
for (; it != end; ++it) {
|
|
|
|
Cel* cel = *it;
|
2011-03-28 00:24:27 -03:00
|
|
|
delete cel;
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2010-03-26 11:44:27 -03:00
|
|
|
m_cels.clear();
|
2009-11-17 13:12:26 +00:00
|
|
|
}
|
2008-02-29 19:29:49 +00:00
|
|
|
|
2014-12-28 11:06:11 -03:00
|
|
|
Cel* LayerImage::cel(frame_t frame) const
|
|
|
|
{
|
2015-09-15 08:18:52 -03:00
|
|
|
CelConstIterator it = findCelIterator(frame);
|
|
|
|
if (it != getCelEnd())
|
|
|
|
return *it;
|
|
|
|
else
|
|
|
|
return nullptr;
|
2014-12-28 11:06:11 -03:00
|
|
|
}
|
|
|
|
|
2014-05-02 11:28:03 -03:00
|
|
|
void LayerImage::getCels(CelList& cels) const
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
2014-05-02 11:28:03 -03:00
|
|
|
CelConstIterator it = getCelBegin();
|
|
|
|
CelConstIterator end = getCelEnd();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
for (; it != end; ++it)
|
|
|
|
cels.push_back(*it);
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-08-12 07:57:40 -03:00
|
|
|
Cel* LayerImage::getLastCel() const
|
|
|
|
{
|
|
|
|
if (!m_cels.empty())
|
|
|
|
return m_cels.back();
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-09-15 08:18:52 -03:00
|
|
|
CelConstIterator LayerImage::findCelIterator(frame_t frame) const
|
|
|
|
{
|
|
|
|
CelIterator it = const_cast<LayerImage*>(this)->findCelIterator(frame);
|
|
|
|
return CelConstIterator(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
CelIterator LayerImage::findCelIterator(frame_t frame)
|
|
|
|
{
|
|
|
|
auto first = getCelBegin();
|
|
|
|
auto end = getCelEnd();
|
|
|
|
|
|
|
|
// Here we use a binary search to find the first cel equal to "frame" (or after frame)
|
|
|
|
first = std::lower_bound(
|
|
|
|
first, end, nullptr,
|
|
|
|
[frame](Cel* cel, Cel*) -> bool {
|
|
|
|
return cel->frame() < frame;
|
|
|
|
});
|
|
|
|
|
|
|
|
// We return the iterator only if it's an exact match
|
|
|
|
if (first != end && (*first)->frame() == frame)
|
|
|
|
return first;
|
|
|
|
else
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
|
|
|
CelIterator LayerImage::findFirstCelIteratorAfter(frame_t firstAfterFrame)
|
|
|
|
{
|
|
|
|
auto first = getCelBegin();
|
|
|
|
auto end = getCelEnd();
|
|
|
|
|
|
|
|
// Here we use a binary search to find the first cel after the given frame
|
|
|
|
first = std::lower_bound(
|
|
|
|
first, end, nullptr,
|
|
|
|
[firstAfterFrame](Cel* cel, Cel*) -> bool {
|
|
|
|
return cel->frame() <= firstAfterFrame;
|
|
|
|
});
|
|
|
|
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
2015-02-09 11:40:43 -03:00
|
|
|
void LayerImage::addCel(Cel* cel)
|
2009-11-17 13:12:26 +00:00
|
|
|
{
|
2015-07-27 12:40:02 -03:00
|
|
|
ASSERT(cel);
|
2015-02-09 11:40:43 -03:00
|
|
|
ASSERT(cel->data() && "The cel doesn't contain CelData");
|
2015-07-27 12:40:02 -03:00
|
|
|
ASSERT(cel->image());
|
|
|
|
ASSERT(sprite());
|
|
|
|
ASSERT(cel->image()->pixelFormat() == sprite()->pixelFormat());
|
2015-02-09 11:40:43 -03:00
|
|
|
|
2015-09-15 08:18:52 -03:00
|
|
|
CelIterator it = findFirstCelIteratorAfter(cel->frame());
|
2009-11-17 13:12:26 +00:00
|
|
|
m_cels.insert(it, cel);
|
2014-07-30 01:28:15 -03:00
|
|
|
|
|
|
|
cel->setParentLayer(this);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2008-03-22 18:43:56 +00:00
|
|
|
/**
|
2009-11-17 13:12:26 +00:00
|
|
|
* Removes the cel from the layer.
|
2008-03-22 18:43:56 +00:00
|
|
|
*
|
2009-11-17 13:12:26 +00:00
|
|
|
* It doesn't destroy the cel, you have to delete it after calling
|
|
|
|
* this routine.
|
2008-03-22 18:43:56 +00:00
|
|
|
*/
|
2015-01-04 10:58:14 -03:00
|
|
|
void LayerImage::removeCel(Cel* cel)
|
2008-03-22 18:43:56 +00:00
|
|
|
{
|
2015-09-15 08:18:52 -03:00
|
|
|
ASSERT(cel);
|
|
|
|
CelIterator it = findCelIterator(cel->frame());
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(it != m_cels.end());
|
2008-03-22 18:43:56 +00:00
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
m_cels.erase(it);
|
2015-01-04 10:58:14 -03:00
|
|
|
|
|
|
|
cel->setParentLayer(NULL);
|
2008-03-22 18:43:56 +00:00
|
|
|
}
|
|
|
|
|
2014-12-28 20:39:11 -03:00
|
|
|
void LayerImage::moveCel(Cel* cel, frame_t frame)
|
2014-04-09 21:56:06 -03:00
|
|
|
{
|
|
|
|
removeCel(cel);
|
|
|
|
cel->setFrame(frame);
|
|
|
|
addCel(cel);
|
|
|
|
}
|
|
|
|
|
2008-03-27 14:29:33 +00:00
|
|
|
/**
|
|
|
|
* Configures some properties of the specified layer to make it as the
|
|
|
|
* "Background" of the sprite.
|
|
|
|
*
|
|
|
|
* You can't use this routine if the sprite already has a background
|
|
|
|
* layer.
|
|
|
|
*/
|
2010-09-19 00:17:21 -03:00
|
|
|
void LayerImage::configureAsBackground()
|
2008-03-27 14:29:33 +00:00
|
|
|
{
|
2014-07-30 01:28:15 -03:00
|
|
|
ASSERT(sprite() != NULL);
|
|
|
|
ASSERT(sprite()->backgroundLayer() == NULL);
|
2008-03-27 14:29:33 +00:00
|
|
|
|
2015-01-18 22:05:33 -03:00
|
|
|
switchFlags(LayerFlags::BackgroundLayerFlags, true);
|
2010-09-19 00:03:32 -03:00
|
|
|
setName("Background");
|
2008-03-27 14:29:33 +00:00
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
sprite()->root()->stackLayer(this, NULL);
|
2008-03-27 14:29:33 +00:00
|
|
|
}
|
|
|
|
|
2015-01-18 22:05:33 -03:00
|
|
|
void LayerImage::displaceFrames(frame_t fromThis, frame_t delta)
|
|
|
|
{
|
|
|
|
Sprite* sprite = this->sprite();
|
|
|
|
|
|
|
|
if (delta > 0) {
|
|
|
|
for (frame_t c=sprite->lastFrame(); c>=fromThis; --c) {
|
|
|
|
if (Cel* cel = this->cel(c))
|
|
|
|
moveCel(cel, c+delta);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (frame_t c=fromThis; c<=sprite->lastFrame(); ++c) {
|
|
|
|
if (Cel* cel = this->cel(c))
|
|
|
|
moveCel(cel, c+delta);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
2016-06-07 19:38:56 -03:00
|
|
|
// LayerGroup class
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
LayerGroup::LayerGroup(Sprite* sprite)
|
|
|
|
: Layer(ObjectType::LayerGroup, sprite)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2010-09-19 00:03:32 -03:00
|
|
|
setName("Layer Set");
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
LayerGroup::~LayerGroup()
|
2008-03-27 14:29:33 +00:00
|
|
|
{
|
2010-09-19 00:15:44 -03:00
|
|
|
destroyAllLayers();
|
2008-01-23 16:16:43 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::destroyAllLayers()
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
for (Layer* layer : m_layers)
|
2009-11-17 13:12:26 +00:00
|
|
|
delete layer;
|
2010-03-26 11:44:27 -03:00
|
|
|
m_layers.clear();
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
int LayerGroup::getMemSize() const
|
2010-10-03 15:51:03 -03:00
|
|
|
{
|
2016-06-07 19:38:56 -03:00
|
|
|
int size = sizeof(LayerGroup);
|
2010-10-03 15:51:03 -03:00
|
|
|
|
2016-06-08 16:46:15 -03:00
|
|
|
for (const Layer* layer : m_layers) {
|
2010-10-03 15:51:03 -03:00
|
|
|
size += layer->getMemSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::getCels(CelList& cels) const
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
for (const Layer* layer : m_layers)
|
|
|
|
layer->getCels(cels);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::addLayer(Layer* layer)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2009-11-17 13:12:26 +00:00
|
|
|
m_layers.push_back(layer);
|
2013-01-11 12:43:25 -03:00
|
|
|
layer->setParent(this);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::removeLayer(Layer* layer)
|
2009-05-31 16:02:32 +00:00
|
|
|
{
|
2016-06-08 16:46:15 -03:00
|
|
|
auto it = std::find(m_layers.begin(), m_layers.end(), layer);
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(it != m_layers.end());
|
2009-11-17 13:12:26 +00:00
|
|
|
m_layers.erase(it);
|
2009-05-31 16:02:32 +00:00
|
|
|
|
2013-01-11 12:43:25 -03:00
|
|
|
layer->setParent(NULL);
|
2009-05-31 16:02:32 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::stackLayer(Layer* layer, Layer* after)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2014-08-07 20:19:31 -03:00
|
|
|
ASSERT(layer != after);
|
|
|
|
if (layer == after)
|
|
|
|
return;
|
|
|
|
|
2016-06-08 16:46:15 -03:00
|
|
|
auto it = std::find(m_layers.begin(), m_layers.end(), layer);
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(it != m_layers.end());
|
2009-11-17 13:12:26 +00:00
|
|
|
m_layers.erase(it);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-11-17 13:12:26 +00:00
|
|
|
if (after) {
|
2016-06-08 16:46:15 -03:00
|
|
|
auto after_it = std::find(m_layers.begin(), m_layers.end(), after);
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(after_it != m_layers.end());
|
2009-11-17 13:12:26 +00:00
|
|
|
after_it++;
|
|
|
|
m_layers.insert(after_it, layer);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2009-11-17 13:12:26 +00:00
|
|
|
else
|
2015-09-14 17:37:21 -03:00
|
|
|
m_layers.insert(m_layers.begin(), layer);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:38:56 -03:00
|
|
|
void LayerGroup::displaceFrames(frame_t fromThis, frame_t delta)
|
2015-01-18 22:05:33 -03:00
|
|
|
{
|
|
|
|
for (Layer* layer : m_layers)
|
|
|
|
layer->displaceFrames(fromThis, delta);
|
|
|
|
}
|
|
|
|
|
2014-10-20 22:21:31 -03:00
|
|
|
} // namespace doc
|