diff --git a/data/pref.xml b/data/pref.xml
index ef2766d51..743611925 100644
--- a/data/pref.xml
+++ b/data/pref.xml
@@ -121,6 +121,11 @@
+
+
+
+
+
@@ -183,6 +188,9 @@
+
@@ -330,6 +338,9 @@
+
diff --git a/data/strings/en.ini b/data/strings/en.ini
index 639426ed3..19dfab80a 100644
--- a/data/strings/en.ini
+++ b/data/strings/en.ini
@@ -1244,6 +1244,11 @@ rewind_on_stop_tooltip = << Export
diff --git a/data/widgets/open_sequence.xml b/data/widgets/open_sequence.xml
index 857f25ee8..be47668f0 100644
--- a/data/widgets/open_sequence.xml
+++ b/data/widgets/open_sequence.xml
@@ -1,4 +1,5 @@
+
@@ -9,6 +10,7 @@
+
diff --git a/data/widgets/options.xml b/data/widgets/options.xml
index 816527613..8a0c8f425 100644
--- a/data/widgets/options.xml
+++ b/data/widgets/options.xml
@@ -258,6 +258,8 @@
pref="general.autoshow_timeline" />
+
@@ -424,6 +426,14 @@
+
+
+
+
+
+
+
+
ui { this, true, "ui" };
+ Param type { this, app::SpriteSheetType::None, "type" };
+ Param frameBounds { this, gfx::Rect(0, 0, 0, 0), "frameBounds" };
+ Param padding { this, gfx::Size(0, 0), "padding" };
+ Param partialTiles { this, false, "partialTiles" };
+};
+
class ImportSpriteSheetWindow : public app::gen::ImportSpriteSheet
, public SelectBoxDelegate {
public:
@@ -127,6 +135,17 @@ public:
return m_padding;
}
+ void updateParams(ImportSpriteSheetParams& params) {
+ params.type(sheetTypeValue());
+ params.frameBounds(frameBounds());
+ params.partialTiles(partialTilesValue());
+
+ if (paddingEnabledValue())
+ params.padding(paddingThickness());
+ else
+ params.padding(gfx::Size(0, 0));
+ }
+
protected:
void onSheetTypeChange() {
@@ -370,7 +389,7 @@ private:
DocumentPreferences* m_docPref;
};
-class ImportSpriteSheetCommand : public Command {
+class ImportSpriteSheetCommand : public CommandWithNewParams {
public:
ImportSpriteSheetCommand();
@@ -379,29 +398,44 @@ protected:
};
ImportSpriteSheetCommand::ImportSpriteSheetCommand()
- : Command(CommandId::ImportSpriteSheet(), CmdRecordableFlag)
+ : CommandWithNewParams(CommandId::ImportSpriteSheet(), CmdRecordableFlag)
{
}
void ImportSpriteSheetCommand::onExecute(Context* context)
{
- ImportSpriteSheetWindow window(context);
+ Doc* document;
+ auto& params = this->params();
- window.openWindowInForeground();
- if (!window.ok())
- return;
+#ifdef ENABLE_UI
+ if (context->isUIAvailable() && params.ui()) {
+ // TODO use params as input values for the ImportSpriteSheetWindow
- Doc* document = window.document();
- DocumentPreferences* docPref = window.docPref();
- gfx::Rect frameBounds = window.frameBounds();
- gfx::Size padThickness = window.paddingThickness();
- bool partialTiles = window.partialTilesValue();
- bool paddingEnable = window.paddingEnabledValue();
- auto sheetType = window.sheetTypeValue();
+ ImportSpriteSheetWindow window(context);
+ window.openWindowInForeground();
+ if (!window.ok())
+ return;
- ASSERT(document);
- if (!document)
- return;
+ document = window.document();
+ if (!document)
+ return;
+
+ window.updateParams(params);
+
+ DocumentPreferences* docPref = window.docPref();
+ docPref->importSpriteSheet.type(params.type());
+ docPref->importSpriteSheet.bounds(params.frameBounds());
+ docPref->importSpriteSheet.partialTiles(params.partialTiles());
+ docPref->importSpriteSheet.paddingBounds(params.padding());
+ docPref->importSpriteSheet.paddingEnabled(window.paddingEnabledValue());
+ }
+ else // We import the sprite sheet from the active document if there is no UI
+#endif
+ {
+ document = context->activeDocument();
+ if (!document)
+ return;
+ }
// The list of frames imported from the sheet
std::vector animation;
@@ -409,39 +443,44 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
try {
Sprite* sprite = document->sprite();
frame_t currentFrame = context->activeSite().frame();
+ gfx::Rect frameBounds = params.frameBounds();
+ const gfx::Size padding = params.padding();
render::Render render;
render.setNewBlend(Preferences::instance().experimental.newBlend());
+ if (frameBounds.isEmpty())
+ frameBounds = sprite->bounds();
+
// Each sprite in the sheet
std::vector tileRects;
int widthStop = sprite->width();
int heightStop = sprite->height();
- if (partialTiles) {
+ if (params.partialTiles()) {
widthStop += frameBounds.w-1;
heightStop += frameBounds.h-1;
}
- switch (sheetType) {
+ switch (params.type()) {
case app::SpriteSheetType::Horizontal:
- for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
+ for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
tileRects.push_back(gfx::Rect(x, frameBounds.y, frameBounds.w, frameBounds.h));
}
break;
case app::SpriteSheetType::Vertical:
- for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
+ for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
tileRects.push_back(gfx::Rect(frameBounds.x, y, frameBounds.w, frameBounds.h));
}
break;
case app::SpriteSheetType::Rows:
- for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
- for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
+ for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
+ for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
}
}
break;
case app::SpriteSheetType::Columns:
- for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
- for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
+ for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
+ for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
}
}
@@ -502,21 +541,15 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
api.setSpriteSize(sprite, frameBounds.w, frameBounds.h);
tx.commit();
-
- ASSERT(docPref);
- if (docPref) {
- docPref->importSpriteSheet.type(sheetType);
- docPref->importSpriteSheet.bounds(frameBounds);
- docPref->importSpriteSheet.partialTiles(partialTiles);
- docPref->importSpriteSheet.paddingBounds(padThickness);
- docPref->importSpriteSheet.paddingEnabled(paddingEnable);
- }
}
catch (...) {
throw;
}
- update_screen_for_document(document);
+#ifdef ENABLE_UI
+ if (context->isUIAvailable())
+ update_screen_for_document(document);
+#endif
}
Command* CommandFactory::createImportSpriteSheetCommand()
diff --git a/src/app/commands/cmd_open_file.cpp b/src/app/commands/cmd_open_file.cpp
index a2d1aaf1a..04473312f 100644
--- a/src/app/commands/cmd_open_file.cpp
+++ b/src/app/commands/cmd_open_file.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019-2020 Igara Studio S.A.
+// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@@ -78,7 +78,7 @@ OpenFileCommand::OpenFileCommand()
: Command(CommandId::OpenFile(), CmdRecordableFlag)
, m_repeatCheckbox(false)
, m_oneFrame(false)
- , m_seqDecision(SequenceDecision::Ask)
+ , m_seqDecision(gen::SequenceDecision::ASK)
{
}
@@ -90,12 +90,18 @@ void OpenFileCommand::onLoadParams(const Params& params)
m_oneFrame = params.get_as("oneframe");
std::string sequence = params.get("sequence");
- if (m_oneFrame || sequence == "skip")
- m_seqDecision = SequenceDecision::Skip;
- else if (sequence == "agree")
- m_seqDecision = SequenceDecision::Agree;
- else
- m_seqDecision = SequenceDecision::Ask;
+ if (m_oneFrame ||
+ sequence == "skip" ||
+ sequence == "no") {
+ m_seqDecision = gen::SequenceDecision::NO;
+ }
+ else if (sequence == "agree" ||
+ sequence == "yes") {
+ m_seqDecision = gen::SequenceDecision::YES;
+ }
+ else {
+ m_seqDecision = gen::SequenceDecision::ASK;
+ }
}
void OpenFileCommand::onExecute(Context* context)
@@ -143,14 +149,25 @@ void OpenFileCommand::onExecute(Context* context)
FILE_LOAD_CREATE_PALETTE |
(m_repeatCheckbox ? FILE_LOAD_SEQUENCE_ASK_CHECKBOX: 0);
+ if (context->isUIAvailable() &&
+ m_seqDecision == gen::SequenceDecision::ASK) {
+ if (Preferences::instance().openFile.openSequence() == gen::SequenceDecision::ASK) {
+ // Do nothing (ask by default, or whatever the command params
+ // specified)
+ }
+ else {
+ m_seqDecision = Preferences::instance().openFile.openSequence();
+ }
+ }
+
switch (m_seqDecision) {
- case SequenceDecision::Ask:
+ case gen::SequenceDecision::ASK:
flags |= FILE_LOAD_SEQUENCE_ASK;
break;
- case SequenceDecision::Agree:
+ case gen::SequenceDecision::YES:
flags |= FILE_LOAD_SEQUENCE_YES;
break;
- case SequenceDecision::Skip:
+ case gen::SequenceDecision::NO:
flags |= FILE_LOAD_SEQUENCE_NONE;
break;
}
@@ -179,12 +196,12 @@ void OpenFileCommand::onExecute(Context* context)
else {
if (fop->isSequence()) {
if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_YES) {
- m_seqDecision = SequenceDecision::Agree;
+ m_seqDecision = gen::SequenceDecision::YES;
flags &= ~FILE_LOAD_SEQUENCE_ASK;
flags |= FILE_LOAD_SEQUENCE_YES;
}
else if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_NONE) {
- m_seqDecision = SequenceDecision::Skip;
+ m_seqDecision = gen::SequenceDecision::NO;
flags &= ~FILE_LOAD_SEQUENCE_ASK;
flags |= FILE_LOAD_SEQUENCE_NONE;
}
diff --git a/src/app/commands/cmd_open_file.h b/src/app/commands/cmd_open_file.h
index cae919200..5437611f4 100644
--- a/src/app/commands/cmd_open_file.h
+++ b/src/app/commands/cmd_open_file.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2020 Igara Studio S.A.
+// Copyright (C) 2020-2021 Igara Studio S.A.
// Copyright (C) 2016-2018 David Capello
//
// This program is distributed under the terms of
@@ -10,6 +10,7 @@
#pragma once
#include "app/commands/command.h"
+#include "app/pref/preferences.h"
#include "base/paths.h"
#include
@@ -18,17 +19,13 @@ namespace app {
class OpenFileCommand : public Command {
public:
- enum class SequenceDecision {
- Ask, Agree, Skip,
- };
-
OpenFileCommand();
const base::paths& usedFiles() const {
return m_usedFiles;
}
- SequenceDecision seqDecision() const {
+ gen::SequenceDecision seqDecision() const {
return m_seqDecision;
}
@@ -42,7 +39,7 @@ namespace app {
bool m_repeatCheckbox;
bool m_oneFrame;
base::paths m_usedFiles;
- SequenceDecision m_seqDecision;
+ gen::SequenceDecision m_seqDecision;
};
} // namespace app
diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp
index 6ef44c3b7..c1d2f6408 100644
--- a/src/app/commands/cmd_options.cpp
+++ b/src/app/commands/cmd_options.cpp
@@ -236,6 +236,7 @@ public:
}
// Alerts
+ openSequence()->setSelectedItemIndex(int(m_pref.openFile.openSequence()));
resetAlerts()->Click.connect([this]{ onResetAlerts(); });
// Cursor
@@ -686,6 +687,9 @@ public:
m_curPref->bg.color1(checkedBgColor1()->getColor());
m_curPref->bg.color2(checkedBgColor2()->getColor());
+ // Alerts preferences
+ m_pref.openFile.openSequence(gen::SequenceDecision(openSequence()->getSelectedItemIndex()));
+
int undo_size_limit_value;
undo_size_limit_value = undoSizeLimit()->textInt();
undo_size_limit_value = base::clamp(undo_size_limit_value, 0, 999999);
diff --git a/src/app/commands/commands_list.h b/src/app/commands/commands_list.h
index 7725c4769..5da840102 100644
--- a/src/app/commands/commands_list.h
+++ b/src/app/commands/commands_list.h
@@ -24,6 +24,7 @@ FOR_EACH_COMMAND(ExportSpriteSheet)
FOR_EACH_COMMAND(FlattenLayers)
FOR_EACH_COMMAND(Flip)
FOR_EACH_COMMAND(HueSaturation)
+FOR_EACH_COMMAND(ImportSpriteSheet)
FOR_EACH_COMMAND(InvertColor)
FOR_EACH_COMMAND(LayerFromBackground)
FOR_EACH_COMMAND(LoadPalette)
@@ -90,7 +91,6 @@ FOR_EACH_COMMAND(GotoPreviousLayer)
FOR_EACH_COMMAND(GotoPreviousTab)
FOR_EACH_COMMAND(GridSettings)
FOR_EACH_COMMAND(Home)
-FOR_EACH_COMMAND(ImportSpriteSheet)
FOR_EACH_COMMAND(InvertMask)
FOR_EACH_COMMAND(KeyboardShortcuts)
FOR_EACH_COMMAND(Launch)
diff --git a/src/app/commands/new_params.cpp b/src/app/commands/new_params.cpp
index a7f8be407..9f1171e67 100644
--- a/src/app/commands/new_params.cpp
+++ b/src/app/commands/new_params.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019-2020 Igara Studio S.A.
+// Copyright (C) 2019-2021 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -25,6 +25,7 @@
#include "filters/outline_filter.h"
#include "filters/tiled_mode.h"
#include "gfx/rect.h"
+#include "gfx/size.h"
#ifdef ENABLE_SCRIPTING
#include "app/script/engine.h"
@@ -62,6 +63,19 @@ void Param::fromString(const std::string& value)
setValue(value);
}
+template<>
+void Param::fromString(const std::string& value)
+{
+ gfx::Size size;
+ std::vector parts;
+ base::split_string(value, parts, ",");
+ if (parts.size() == 2) {
+ size.w = base::convert_to(parts[0]);
+ size.h = base::convert_to(parts[1]);
+ }
+ setValue(size);
+}
+
template<>
void Param::fromString(const std::string& value)
{
@@ -253,6 +267,12 @@ void Param::fromLua(lua_State* L, int index)
setValue(std::string());
}
+template<>
+void Param::fromLua(lua_State* L, int index)
+{
+ setValue(script::convert_args_into_size(L, index));
+}
+
template<>
void Param::fromLua(lua_State* L, int index)
{
diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp
index abff10d6b..68b6cbc34 100644
--- a/src/app/file/file.cpp
+++ b/src/app/file/file.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2018-2020 Igara Studio S.A.
+// Copyright (C) 2018-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@@ -261,10 +261,19 @@ FileOp* FileOp::createLoadDocumentOperation(Context* context,
window.openWindowInForeground();
+ // Don't show this alert again.
+ if (window.dontShow()->isSelected()) {
+ Preferences::instance().openFile.openSequence(
+ window.closer() == window.agree() ?
+ gen::SequenceDecision::YES:
+ gen::SequenceDecision::NO);
+ }
+
// If the user selected the "do the same for other files"
// checkbox, we've to save what the user want to do for the
// following files.
- if (window.repeat()->isSelected()) {
+ if (window.repeat()->isSelected() ||
+ window.dontShow()->isSelected()) {
if (window.closer() == window.agree())
fop->m_seq.flags = FILE_LOAD_SEQUENCE_YES;
else
diff --git a/src/app/file/tga_format.cpp b/src/app/file/tga_format.cpp
index 2e58b01bc..bc2a4a7e8 100644
--- a/src/app/file/tga_format.cpp
+++ b/src/app/file/tga_format.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019-2020 Igara Studio S.A.
+// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@@ -52,7 +52,8 @@ class TgaFormat : public FileFormat {
FILE_SUPPORT_GRAY |
FILE_SUPPORT_INDEXED |
FILE_SUPPORT_SEQUENCES |
- FILE_SUPPORT_GET_FORMAT_OPTIONS;
+ FILE_SUPPORT_GET_FORMAT_OPTIONS |
+ FILE_SUPPORT_PALETTE_WITH_ALPHA;
}
bool onLoad(FileOp* fop) override;
@@ -148,8 +149,10 @@ bool TgaFormat::onLoad(FileOp* fop)
tga::getr(c),
tga::getg(c),
tga::getb(c));
- if (tga::geta(c) < 255)
+ if (tga::geta(c) < 255) {
fop->sequenceSetAlpha(i, tga::geta(c));
+ fop->sequenceSetHasAlpha(true); // Is a transparent sprite
+ }
}
}
// Generate grayscale palette
diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp
index 89da8b436..7e8f50a84 100644
--- a/src/app/script/sprite_class.cpp
+++ b/src/app/script/sprite_class.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2018-2020 Igara Studio S.A.
+// Copyright (C) 2018-2021 Igara Studio S.A.
// Copyright (C) 2015-2018 David Capello
//
// This program is distributed under the terms of
@@ -21,6 +21,7 @@
#include "app/cmd/remove_tag.h"
#include "app/cmd/set_grid_bounds.h"
#include "app/cmd/set_mask.h"
+#include "app/cmd/set_pixel_ratio.h"
#include "app/cmd/set_sprite_size.h"
#include "app/cmd/set_transparent_color.h"
#include "app/color_spaces.h"
@@ -782,6 +783,23 @@ int Sprite_set_gridBounds(lua_State* L)
return 0;
}
+int Sprite_get_pixelRatio(lua_State* L)
+{
+ const auto sprite = get_docobj(L, 1);
+ push_obj(L, sprite->pixelRatio());
+ return 1;
+}
+
+int Sprite_set_pixelRatio(lua_State* L)
+{
+ auto sprite = get_docobj(L, 1);
+ const gfx::Size pixelRatio = convert_args_into_size(L, 2);
+ Tx tx;
+ tx(new cmd::SetPixelRatio(sprite, pixelRatio));
+ tx.commit();
+ return 0;
+}
+
const luaL_Reg Sprite_methods[] = {
{ "__eq", Sprite_eq },
{ "resize", Sprite_resize },
@@ -835,6 +853,7 @@ const Property Sprite_properties[] = {
{ "gridBounds", Sprite_get_gridBounds, Sprite_set_gridBounds },
{ "color", UserData_get_color, UserData_set_color },
{ "data", UserData_get_text, UserData_set_text },
+ { "pixelRatio", Sprite_get_pixelRatio, Sprite_set_pixelRatio },
{ nullptr, nullptr, nullptr }
};
diff --git a/src/app/script/values.cpp b/src/app/script/values.cpp
index dd9e843d2..efade25d2 100644
--- a/src/app/script/values.cpp
+++ b/src/app/script/values.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019-2020 Igara Studio S.A.
+// Copyright (C) 2019-2021 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -187,11 +187,12 @@ FOR_ENUM(app::gen::PivotPosition)
FOR_ENUM(app::gen::PixelConnectivity)
FOR_ENUM(app::gen::RightClickMode)
FOR_ENUM(app::gen::SelectionMode)
+FOR_ENUM(app::gen::SequenceDecision)
FOR_ENUM(app::gen::StopAtGrid)
FOR_ENUM(app::gen::SymmetryMode)
FOR_ENUM(app::gen::TimelinePosition)
-FOR_ENUM(app::gen::WindowColorProfile)
FOR_ENUM(app::gen::ToGrayAlgorithm)
+FOR_ENUM(app::gen::WindowColorProfile)
FOR_ENUM(app::tools::FreehandAlgorithm)
FOR_ENUM(app::tools::RotationAlgorithm)
FOR_ENUM(doc::AniDir)
diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp
index b5a15a662..f2506c12a 100644
--- a/src/app/ui/editor/tool_loop_impl.cpp
+++ b/src/app/ui/editor/tool_loop_impl.cpp
@@ -288,9 +288,8 @@ public:
RgbMap* getRgbMap() override {
if (!m_rgbMap) {
Sprite::RgbMapFor forLayer =
- ((!m_layer ||
- m_layer->isBackground() ||
- m_sprite->pixelFormat() == IMAGE_RGB) ?
+ (((m_layer && m_layer->isBackground()) ||
+ (m_sprite->pixelFormat() == IMAGE_RGB)) ?
Sprite::RgbMapFor::OpaqueLayer:
Sprite::RgbMapFor::TransparentLayer);
m_rgbMap = m_sprite->rgbMap(m_frame, forLayer);
diff --git a/src/app/ui/timeline/timeline.cpp b/src/app/ui/timeline/timeline.cpp
index 1d01d66a6..ada655282 100644
--- a/src/app/ui/timeline/timeline.cpp
+++ b/src/app/ui/timeline/timeline.cpp
@@ -325,18 +325,24 @@ void Timeline::updateUsingEditor(Editor* editor)
m_aniControls.updateUsingEditor(editor);
+ DocRange oldRange;
if (editor != m_editor) {
// Save active m_tagFocusBand into the old focused editor
if (m_editor)
m_editor->setTagFocusBand(m_tagFocusBand);
m_tagFocusBand = -1;
}
+ else {
+ oldRange = m_range;
+ }
detachDocument();
- if (m_range.enabled() &&
- m_rangeLocks == 0) {
- m_range.clearRange();
+ if (Preferences::instance().timeline.keepSelection())
+ m_range = oldRange;
+ else {
+ // The range is reset in detachDocument()
+ ASSERT(!m_range.enabled());
}
// We always update the editor. In this way the timeline keeps in
@@ -2990,14 +2996,17 @@ gfx::Rect Timeline::getRangeBounds(const Range& range) const
}
break;
case Range::kFrames: {
- for (auto frame : range.selectedFrames())
+ for (auto frame : range.selectedFrames()) {
rc |= getPartBounds(Hit(PART_HEADER_FRAME, 0, frame));
+ rc |= getPartBounds(Hit(PART_CEL, 0, frame));
+ }
break;
}
case Range::kLayers:
for (auto layer : range.selectedLayers()) {
layer_t layerIdx = getLayerIndex(layer);
rc |= getPartBounds(Hit(PART_ROW_TEXT, layerIdx));
+ rc |= getPartBounds(Hit(PART_CEL, layerIdx, m_sprite->lastFrame()));
}
break;
}
@@ -3006,11 +3015,28 @@ gfx::Rect Timeline::getRangeBounds(const Range& range) const
gfx::Rect Timeline::getRangeClipBounds(const Range& range) const
{
- gfx::Rect clipBounds;
+ gfx::Rect celBounds = getCelsBounds();
+ gfx::Rect clipBounds, unionBounds;
switch (range.type()) {
- case Range::kCels: clipBounds = getCelsBounds(); break;
- case Range::kFrames: clipBounds = getFrameHeadersBounds(); break;
- case Range::kLayers: clipBounds = getLayerHeadersBounds(); break;
+ case Range::kCels:
+ clipBounds = celBounds;
+ break;
+ case Range::kFrames: {
+ clipBounds = getFrameHeadersBounds();
+
+ unionBounds = (clipBounds | celBounds);
+ clipBounds.y = unionBounds.y;
+ clipBounds.h = unionBounds.h;
+ break;
+ }
+ case Range::kLayers: {
+ clipBounds = getLayerHeadersBounds();
+
+ unionBounds = (clipBounds | celBounds);
+ clipBounds.x = unionBounds.x;
+ clipBounds.w = unionBounds.w;
+ break;
+ }
}
return clipBounds;
}
@@ -3940,6 +3966,8 @@ void Timeline::setViewScroll(const gfx::Point& pt)
gfx::Rect rc;
if (m_tagBands > 0)
rc |= getPartBounds(Hit(PART_TAG_BAND));
+ if (m_range.enabled())
+ rc |= getRangeBounds(m_range).enlarge(outlineWidth());
rc |= getFrameHeadersBounds();
rc |= getCelsBounds();
rc.offset(origin());
@@ -4153,8 +4181,10 @@ void Timeline::onNewInputPriority(InputChainElement* element,
return;
if (element != this && m_rangeLocks == 0) {
- m_range.clearRange();
- invalidate();
+ if (!Preferences::instance().timeline.keepSelection()) {
+ m_range.clearRange();
+ invalidate();
+ }
}
}
}
diff --git a/src/app/util/open_batch.h b/src/app/util/open_batch.h
index 39b43bc25..c2e611348 100644
--- a/src/app/util/open_batch.h
+++ b/src/app/util/open_batch.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2020 Igara Studio S.A.
+// Copyright (C) 2020-2021 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -29,14 +29,14 @@ namespace app {
params.set("oneframe", "true");
else {
switch (m_lastDecision) {
- case OpenFileCommand::SequenceDecision::Ask:
+ case gen::SequenceDecision::ASK:
params.set("sequence", "ask");
params.set("repeat_checkbox", "true");
break;
- case OpenFileCommand::SequenceDecision::Skip:
+ case gen::SequenceDecision::NO:
params.set("sequence", "skip");
break;
- case OpenFileCommand::SequenceDecision::Agree:
+ case gen::SequenceDecision::YES:
params.set("sequence", "agree");
break;
}
@@ -49,7 +49,7 @@ namespace app {
// Future decision for other files in the CLI
auto d = m_cmd.seqDecision();
- if (d != OpenFileCommand::SequenceDecision::Ask)
+ if (d != gen::SequenceDecision::ASK)
m_lastDecision = d;
}
@@ -59,7 +59,7 @@ namespace app {
private:
OpenFileCommand m_cmd;
- OpenFileCommand::SequenceDecision m_lastDecision = OpenFileCommand::SequenceDecision::Ask;
+ gen::SequenceDecision m_lastDecision = gen::SequenceDecision::ASK;
};
} // namespace app