Merge branch 'main' into beta

This commit is contained in:
David Capello 2021-04-08 16:15:02 -03:00
commit ae904428fa
24 changed files with 175 additions and 37 deletions

View File

@ -96,8 +96,8 @@ void FlipCommand::onExecute(Context* ctx)
cels = get_unlocked_unique_cels(site.sprite(), range); cels = get_unlocked_unique_cels(site.sprite(), range);
} }
else if (site.cel() && else if (site.cel() &&
site.layer() && site.layer() &&
site.layer()->isEditable()) { site.layer()->canEditPixels()) {
cels.push_back(site.cel()); cels.push_back(site.cel());
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 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
@ -217,7 +217,7 @@ void RotateCommand::onExecute(Context* context)
cels = get_unlocked_unique_cels(site.sprite(), range); cels = get_unlocked_unique_cels(site.sprite(), range);
else if (site.cel() && else if (site.cel() &&
site.layer() && site.layer() &&
site.layer()->isEditable()) { site.layer()->canEditPixels()) {
cels.push_back(site.cel()); cels.push_back(site.cel());
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 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
@ -281,8 +281,7 @@ void FilterManagerImpl::applyToTarget()
} }
else if (m_site.cel() && else if (m_site.cel() &&
m_site.layer() && m_site.layer() &&
m_site.layer()->isEditable() && m_site.layer()->canEditPixels()) {
!m_site.layer()->isReference()) {
cels.push_back(m_site.cel()); cels.push_back(m_site.cel());
} }
break; break;
@ -290,8 +289,7 @@ void FilterManagerImpl::applyToTarget()
case CelsTarget::All: { case CelsTarget::All: {
for (Cel* cel : m_site.sprite()->uniqueCels()) { for (Cel* cel : m_site.sprite()->uniqueCels()) {
if (cel->layer()->isEditable() && if (cel->layer()->canEditPixels())
!cel->layer()->isReference())
cels.push_back(cel); cels.push_back(cel);
} }
break; break;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2019 Igara Studio S.A. // Copyright (C) 2018-2021 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -81,7 +81,7 @@ ConfigModule::ConfigModule()
#elif !defined(_WIN32) #elif !defined(_WIN32)
// On Linux we migrate the old configuration file name // On Linux we migrate the old configuration file name
// (.asepriterc -> ~/.config/aseprite/aseprite.ini) // (~/.asepriterc -> ~/.config/aseprite/aseprite.ini)
{ {
ResourceFinder old_rf; ResourceFinder old_rf;
old_rf.includeHomeDir(".asepriterc"); old_rf.includeHomeDir(".asepriterc");

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2018-2021 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
@ -191,6 +191,10 @@ DocumentPreferences& Preferences::document(const Doc* doc)
void Preferences::resetToolPreferences(tools::Tool* tool) void Preferences::resetToolPreferences(tools::Tool* tool)
{ {
if (tool->prefAlreadyResetFromScript())
return;
tool->markPrefAlreadyResetFromScript();
auto it = m_tools.find(tool->getId()); auto it = m_tools.find(tool->getId());
if (it != m_tools.end()) if (it != m_tools.end())
m_tools.erase(it); m_tools.erase(it);

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -105,8 +105,8 @@ void ResourceFinder::includeDataDir(const char* filename)
#else #else
// $HOME/.config/aseprite/filename // $HOME/.config/aseprite/filename
sprintf(buf, ".config/aseprite/data/%s", filename); sprintf(buf, "aseprite/data/%s", filename);
includeHomeDir(buf); includeHomeConfigDir(buf);
// $BINDIR/data/filename // $BINDIR/data/filename
sprintf(buf, "data/%s", filename); sprintf(buf, "data/%s", filename);
@ -150,6 +150,24 @@ void ResourceFinder::includeHomeDir(const char* filename)
#endif #endif
} }
#if !defined(_WIN32) && !defined(__APPLE__)
// For Linux: It's $XDG_CONFIG_HOME or $HOME/.config
void ResourceFinder::includeHomeConfigDir(const char* filename)
{
char* configHome = std::getenv("XDG_CONFIG_HOME");
if (configHome && *configHome) {
// $XDG_CONFIG_HOME/filename
addPath(base::join_path(configHome, filename));
}
else {
// $HOME/.config/filename
includeHomeDir(base::join_path(std::string(".config"), filename).c_str());
}
}
#endif // !defined(_WIN32) && !defined(__APPLE__)
void ResourceFinder::includeUserDir(const char* filename) void ResourceFinder::includeUserDir(const char* filename)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -185,7 +203,7 @@ void ResourceFinder::includeUserDir(const char* filename)
#else // !__APPLE__ #else // !__APPLE__
// $HOME/.config/aseprite/filename // $HOME/.config/aseprite/filename
includeHomeDir((std::string(".config/aseprite/") + filename).c_str()); includeHomeConfigDir((std::string("aseprite/") + filename).c_str());
#endif #endif
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 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
@ -42,6 +42,11 @@ namespace app {
void includeDataDir(const char* filename); void includeDataDir(const char* filename);
void includeHomeDir(const char* filename); void includeHomeDir(const char* filename);
#if !defined(_WIN32) && !defined(__APPLE__)
// For Linux: It's $XDG_CONFIG_HOME or $HOME/.config
void includeHomeConfigDir(const char* filename);
#endif
// Tries to add the given filename in these locations: // Tries to add the given filename in these locations:
// For Windows: // For Windows:
// - If ASEPRITE_USER_FOLDER environment variable is defined, it // - If ASEPRITE_USER_FOLDER environment variable is defined, it

View File

@ -1,4 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2021 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
@ -61,6 +62,9 @@ namespace app {
void setIntertwine(int button, Intertwine* intertwine) { m_button[button].m_intertwine = intertwine; } void setIntertwine(int button, Intertwine* intertwine) { m_button[button].m_intertwine = intertwine; }
void setTracePolicy(int button, TracePolicy trace_policy) { m_button[button].m_trace_policy = trace_policy; } void setTracePolicy(int button, TracePolicy trace_policy) { m_button[button].m_trace_policy = trace_policy; }
bool prefAlreadyResetFromScript() const { return m_prefAlreadyResetFromScript; }
void markPrefAlreadyResetFromScript() { m_prefAlreadyResetFromScript = true; }
private: private:
ToolGroup* m_group; ToolGroup* m_group;
std::string m_id; std::string m_id;
@ -68,6 +72,13 @@ namespace app {
std::string m_tips; std::string m_tips;
int m_default_brush_size; int m_default_brush_size;
// Flag used to indicate that the preferences of this tool were
// already reset from scripts when they are executed in CLI mode
// (without GUI). This is needed to reset the preferences only
// once, but if the script then modifies the preferences, they
// are not reset again.
bool m_prefAlreadyResetFromScript = false;
struct { struct {
Fill m_fill; Fill m_fill;
Ink* m_ink; Ink* m_ink;

View File

@ -409,6 +409,7 @@ void Editor::getSite(Site* site) const
// TODO we should not access timeline directly here // TODO we should not access timeline directly here
Timeline* timeline = App::instance()->timeline(); Timeline* timeline = App::instance()->timeline();
if (timeline && if (timeline &&
timeline->isVisible() &&
timeline->range().enabled()) { timeline->range().enabled()) {
site->range(timeline->range()); site->range(timeline->range());
} }

View File

@ -47,8 +47,10 @@ MovingCelCollect::MovingCelCollect(Editor* editor, Layer* layer)
if (layer && layer->isImage()) if (layer && layer->isImage())
m_mainCel = layer->cel(editor->frame()); m_mainCel = layer->cel(editor->frame());
DocRange range = App::instance()->timeline()->range(); Timeline* timeline = App::instance()->timeline();
if (!range.enabled()) { DocRange range = timeline->range();
if (!range.enabled() ||
!timeline->isVisible()) {
range.startRange(editor->layer(), editor->frame(), DocRange::kCels); range.startRange(editor->layer(), editor->frame(), DocRange::kCels);
range.endRange(editor->layer(), editor->frame()); range.endRange(editor->layer(), editor->frame());
} }
@ -86,8 +88,6 @@ MovingCelState::MovingCelState(Editor* editor,
, m_celList(collect.celList()) , m_celList(collect.celList())
, m_celOffset(0.0, 0.0) , m_celOffset(0.0, 0.0)
, m_celScale(1.0, 1.0) , m_celScale(1.0, 1.0)
, m_hasReference(false)
, m_scaled(false)
, m_handle(handle) , m_handle(handle)
, m_editor(editor) , m_editor(editor)
{ {
@ -188,6 +188,13 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
// like to update all the editors. // like to update all the editors.
document->notifyGeneralUpdate(); document->notifyGeneralUpdate();
} }
// Just a click in the current layer
else if (!m_moved & !m_scaled) {
// Deselect the whole range if we are in "Auto Select Layer"
if (editor->isAutoSelectLayer()) {
App::instance()->timeline()->clearAndInvalidateRange();
}
}
// Restore the mask visibility. // Restore the mask visibility.
if (m_maskVisible) { if (m_maskVisible) {
@ -218,6 +225,8 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
m_celOffset.y = 0; m_celOffset.y = 0;
} }
} }
if (!m_moved && intCelOffset() != gfx::Point(0, 0))
m_moved = true;
break; break;
case ScaleSEHandle: { case ScaleSEHandle: {
@ -246,6 +255,7 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
if (cel->layer()->isReference()) { if (cel->layer()->isReference()) {
celBounds.x += m_celOffset.x; celBounds.x += m_celOffset.x;
celBounds.y += m_celOffset.y; celBounds.y += m_celOffset.y;
m_moved = true;
if (m_scaled) { if (m_scaled) {
celBounds.w *= m_celScale.w; celBounds.w *= m_celScale.w;
celBounds.h *= m_celScale.h; celBounds.h *= m_celScale.h;

View File

@ -68,8 +68,9 @@ namespace app {
gfx::SizeF m_celMainSize; gfx::SizeF m_celMainSize;
gfx::SizeF m_celScale; gfx::SizeF m_celScale;
bool m_maskVisible; bool m_maskVisible;
bool m_hasReference; bool m_hasReference = false;
bool m_scaled; bool m_moved = false;
bool m_scaled = false;
HandleType m_handle; HandleType m_handle;
Editor* m_editor; Editor* m_editor;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 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
@ -36,6 +36,7 @@
#include "app/ui/keyboard_shortcuts.h" #include "app/ui/keyboard_shortcuts.h"
#include "app/ui/main_window.h" #include "app/ui/main_window.h"
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "app/ui/timeline/timeline.h"
#include "app/ui_context.h" #include "app/ui_context.h"
#include "app/util/clipboard.h" #include "app/util/clipboard.h"
#include "app/util/layer_utils.h" #include "app/util/layer_utils.h"
@ -114,10 +115,14 @@ MovingPixelsState::MovingPixelsState(Editor* editor, MouseMessage* msg, PixelsMo
ContextBar* contextBar = App::instance()->contextBar(); ContextBar* contextBar = App::instance()->contextBar();
contextBar->updateForMovingPixels(getTransformation(editor)); contextBar->updateForMovingPixels(getTransformation(editor));
contextBar->add_observer(this); contextBar->add_observer(this);
App::instance()->mainWindow()->getTimeline()->add_observer(this);
} }
MovingPixelsState::~MovingPixelsState() MovingPixelsState::~MovingPixelsState()
{ {
App::instance()->mainWindow()->getTimeline()->remove_observer(this);
ContextBar* contextBar = App::instance()->contextBar(); ContextBar* contextBar = App::instance()->contextBar();
contextBar->remove_observer(this); contextBar->remove_observer(this);
contextBar->updateForActiveTool(); contextBar->updateForActiveTool();
@ -723,6 +728,15 @@ void MovingPixelsState::onBeforeLayerChanged(Editor* editor)
dropPixels(); dropPixels();
} }
void MovingPixelsState::onBeforeRangeChanged(Timeline* timeline)
{
if (!isActiveDocument())
return;
if (m_pixelsMovement)
dropPixels();
}
void MovingPixelsState::onTransparentColorChange() void MovingPixelsState::onTransparentColorChange()
{ {
ASSERT(m_pixelsMovement); ASSERT(m_pixelsMovement);

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -15,6 +15,7 @@
#include "app/ui/editor/pixels_movement.h" #include "app/ui/editor/pixels_movement.h"
#include "app/ui/editor/standby_state.h" #include "app/ui/editor/standby_state.h"
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "app/ui/timeline/timeline_observer.h"
#include "obs/connection.h" #include "obs/connection.h"
#include "ui/timer.h" #include "ui/timer.h"
@ -29,6 +30,7 @@ namespace app {
class MovingPixelsState class MovingPixelsState
: public StandbyState : public StandbyState
, EditorObserver , EditorObserver
, TimelineObserver
, ContextBarObserver , ContextBarObserver
, PixelsMovementDelegate { , PixelsMovementDelegate {
public: public:
@ -66,6 +68,9 @@ namespace app {
virtual void onBeforeFrameChanged(Editor* editor) override; virtual void onBeforeFrameChanged(Editor* editor) override;
virtual void onBeforeLayerChanged(Editor* editor) override; virtual void onBeforeLayerChanged(Editor* editor) override;
// TimelineObserver
virtual void onBeforeRangeChanged(Timeline* timeline) override;
// ContextBarObserver // ContextBarObserver
virtual void onDropPixels(ContextBarObserver::DropAction action) override; virtual void onDropPixels(ContextBarObserver::DropAction action) override;

View File

@ -1293,16 +1293,32 @@ CelList PixelsMovement::getEditableCels()
// TODO This case is used in paste too, where the cel() can be // TODO This case is used in paste too, where the cel() can be
// nullptr (e.g. we paste the clipboard image into an empty // nullptr (e.g. we paste the clipboard image into an empty
// cel). // cel).
if (m_site.layer() && m_site.layer()->isEditableHierarchy()) if (m_site.layer() &&
m_site.layer()->canEditPixels()) {
cels.push_back(m_site.cel()); cels.push_back(m_site.cel());
}
return cels; return cels;
} }
// Current cel (m_site.cel()) can be nullptr when we paste in an // Current cel (m_site.cel()) can be nullptr when we paste in an
// empty cel (Ctrl+V) and cut (Ctrl+X) the floating pixels. // empty cel (Ctrl+V) and cut (Ctrl+X) the floating pixels.
if (m_site.cel() && if (m_site.cel() &&
m_site.cel()->layer()->isEditableHierarchy()) { m_site.cel()->layer()->canEditPixels()) {
auto it = std::find(cels.begin(), cels.end(), m_site.cel()); CelList::iterator it;
// If we are in a linked cel, remove the cel that matches the
// linked cel. In this way we avoid having two Cel in cels
// pointing to the same CelData.
if (Cel* link = m_site.cel()->link()) {
it = std::find_if(cels.begin(), cels.end(),
[link](const Cel* cel){
return (cel == link ||
cel->link() == link);
});
}
else {
it = std::find(cels.begin(), cels.end(), m_site.cel());
}
if (it != cels.end()) if (it != cels.end())
cels.erase(it); cels.erase(it);
cels.insert(cels.begin(), m_site.cel()); cels.insert(cels.begin(), m_site.cel());

View File

@ -4051,6 +4051,8 @@ void Timeline::invalidateRange()
void Timeline::clearAndInvalidateRange() void Timeline::clearAndInvalidateRange()
{ {
if (m_range.enabled()) { if (m_range.enabled()) {
notify_observers(&TimelineObserver::onBeforeRangeChanged, this);
invalidateRange(); invalidateRange();
m_range.clearRange(); m_range.clearRange();
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2018-2021 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
@ -17,6 +17,7 @@
#include "app/ui/editor/editor_observer.h" #include "app/ui/editor/editor_observer.h"
#include "app/ui/input_chain_element.h" #include "app/ui/input_chain_element.h"
#include "app/ui/timeline/ani_controls.h" #include "app/ui/timeline/ani_controls.h"
#include "app/ui/timeline/timeline_observer.h"
#include "base/debug.h" #include "base/debug.h"
#include "doc/frame.h" #include "doc/frame.h"
#include "doc/layer.h" #include "doc/layer.h"
@ -26,6 +27,7 @@
#include "doc/tag.h" #include "doc/tag.h"
#include "gfx/color.h" #include "gfx/color.h"
#include "obs/connection.h" #include "obs/connection.h"
#include "obs/observable.h"
#include "ui/scroll_bar.h" #include "ui/scroll_bar.h"
#include "ui/timer.h" #include "ui/timer.h"
#include "ui/widget.h" #include "ui/widget.h"
@ -60,6 +62,7 @@ namespace app {
class Timeline : public ui::Widget, class Timeline : public ui::Widget,
public ui::ScrollableViewDelegate, public ui::ScrollableViewDelegate,
public obs::observable<TimelineObserver>,
public ContextObserver, public ContextObserver,
public DocsObserver, public DocsObserver,
public DocObserver, public DocObserver,

View File

@ -0,0 +1,24 @@
// Aseprite
// Copyright (C) 2021 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_UI_TIMELINE_TIMELINE_OBSERVER_H_INCLUDED
#define APP_UI_TIMELINE_TIMELINE_OBSERVER_H_INCLUDED
#pragma once
namespace app {
class Timeline;
class TimelineObserver {
public:
virtual ~TimelineObserver() { }
// Called when the current timeline range is going to change.
virtual void onBeforeRangeChanged(Timeline* timeline) { }
};
} // namespace app
#endif

View File

@ -338,9 +338,14 @@ void UIContext::onGetActiveSite(Site* site) const
view->getSite(site); view->getSite(site);
if (site->sprite()) { if (site->sprite()) {
// Selected range in the timeline // Selected range in the timeline. We use it only if the
// timeline is visible. A common scenario might be
// undoing/redoing actions where the range is re-selected, that
// could enable the range even if the timeline is hidden. In
// this way we avoid using the timeline selection unexpectedly.
Timeline* timeline = App::instance()->timeline(); Timeline* timeline = App::instance()->timeline();
if (timeline && if (timeline &&
timeline->isVisible() &&
timeline->range().enabled()) { timeline->range().enabled()) {
site->range(timeline->range()); site->range(timeline->range());
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2020-2021 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,6 +25,7 @@ namespace app {
using namespace doc; using namespace doc;
// TODO the DocRange should be "iteratable" to replace this function // TODO the DocRange should be "iteratable" to replace this function
// or we can wait to C++20 coroutines and co_yield
static CelList get_cels_templ(const Sprite* sprite, static CelList get_cels_templ(const Sprite* sprite,
DocRange range, DocRange range,
const bool onlyUniqueCels, const bool onlyUniqueCels,
@ -39,8 +40,9 @@ static CelList get_cels_templ(const Sprite* sprite,
for (Layer* layer : range.selectedLayers()) { for (Layer* layer : range.selectedLayers()) {
if (!layer || if (!layer ||
!layer->isImage() || !layer->isImage() ||
(onlyUnlockedCel && !layer->isEditableHierarchy())) (onlyUnlockedCel && !layer->canEditPixels())) {
continue; continue;
}
LayerImage* layerImage = static_cast<LayerImage*>(layer); LayerImage* layerImage = static_cast<LayerImage*>(layer);
for (frame_t frame : range.selectedFrames()) { for (frame_t frame : range.selectedFrames()) {

View File

@ -1,4 +1,4 @@
Copyright (c) 2018-2020 Igara Studio S.A. Copyright (c) 2018-2021 Igara Studio S.A.
Copyright (c) 2001-2018 David Capello Copyright (c) 2001-2018 David Capello
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,5 +1,5 @@
// Aseprite Document Library // Aseprite Document Library
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
@ -180,6 +180,24 @@ bool Layer::isEditableHierarchy() const
return true; return true;
} }
// It's like isVisibleHierarchy + isEditableHierarchy. Returns true if
// the whole layer hierarchy is unlocked and visible, so the user can
// edit its pixels without unexpected side-effects (e.g. editing
// hidden layers).
bool Layer::canEditPixels() const
{
const Layer* layer = this;
while (layer) {
if (!layer->isVisible() ||
!layer->isEditable() ||
layer->isReference()) { // Cannot edit pixels from reference layers
return false;
}
layer = layer->parent();
}
return true;
}
bool Layer::hasAncestor(const Layer* ancestor) const bool Layer::hasAncestor(const Layer* ancestor) const
{ {
Layer* it = parent(); Layer* it = parent();

View File

@ -1,5 +1,5 @@
// Aseprite Document Library // Aseprite Document Library
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
@ -92,6 +92,7 @@ namespace doc {
bool isVisibleHierarchy() const; bool isVisibleHierarchy() const;
bool isEditableHierarchy() const; bool isEditableHierarchy() const;
bool canEditPixels() const;
bool hasAncestor(const Layer* ancestor) const; bool hasAncestor(const Layer* ancestor) const;
void setBackground(bool state) { switchFlags(LayerFlags::Background, state); } void setBackground(bool state) { switchFlags(LayerFlags::Background, state); }

@ -1 +1 @@
Subproject commit 1e0630d310b55abf7d16d3d89feeb13936d540f8 Subproject commit 876ef60df5fec606f8eb0638ee893e4967db4673

@ -1 +1 @@
Subproject commit ea8005303f42925fa1180d1f6e973a816c0b80af Subproject commit 16b8bb25e34bfb0193609012257502be62539d35