mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-20 18:40:57 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
ae904428fa
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
24
src/app/ui/timeline/timeline_observer.h
Normal file
24
src/app/ui/timeline/timeline_observer.h
Normal 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
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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); }
|
||||||
|
2
src/flic
2
src/flic
@ -1 +1 @@
|
|||||||
Subproject commit 1e0630d310b55abf7d16d3d89feeb13936d540f8
|
Subproject commit 876ef60df5fec606f8eb0638ee893e4967db4673
|
2
src/tga
2
src/tga
@ -1 +1 @@
|
|||||||
Subproject commit ea8005303f42925fa1180d1f6e973a816c0b80af
|
Subproject commit 16b8bb25e34bfb0193609012257502be62539d35
|
Loading…
x
Reference in New Issue
Block a user