Merge branch 'main' into beta

This commit is contained in:
David Capello 2021-04-12 17:11:28 -03:00
commit a012dac020
18 changed files with 249 additions and 85 deletions

View File

@ -121,6 +121,11 @@
<value id="HSV" value="1" />
<value id="HSL" value="2" />
</enum>
<enum id="SequenceDecision">
<value id="ASK" value="0" />
<value id="YES" value="1" />
<value id="NO" value="2" />
</enum>
</types>
<global>
@ -183,6 +188,9 @@
<section id="tags">
<option id="user_data_visibility" type="bool" default="false" />
</section>
<section id="timeline">
<option id="keep_selection" type="bool" default="false" />
</section>
<section id="cursor">
<option id="use_native_cursor" type="bool" default="false" />
<option id="cursor_scale" type="int" default="1" />
@ -330,6 +338,9 @@
<section id="advanced_mode">
<option id="show_alert" type="bool" default="true" />
</section>
<section id="open_file">
<option id="open_sequence" type="SequenceDecision" default="SequenceDecision::ASK" />
</section>
<section id="save_file">
<option id="show_file_format_doesnt_support_alert" type="bool" default="true" />
<option id="show_export_animation_in_sequence_alert" type="bool" default="true" />

View File

@ -1244,6 +1244,11 @@ rewind_on_stop_tooltip = <<<END
The 'Stop' button should rewind the animation
where it was started.
END
keep_timeline_selection = Keep selection
keep_timeline_selection_tooltip = <<<END
Keep the selected range of layers/frames/cels
when we edit the canvas.
END
default_first_frame = Default First Frame:
ui_mouse_cursor = UI Mouse Cursor
native_cursor = Use native mouse cursors
@ -1297,6 +1302,10 @@ the current frame & layer will be modified
to focus the undid/redid change.
END
undo_allow_nonlinear_history = Allow non-linear history
open_sequence_alert = Open a sequence of static files as an animation
open_sequence_alert_ask = Ask
open_sequence_alert_no = No
open_sequence_alert_yes = Yes
file_format_doesnt_support_alert = Show warning when saving a file with unsupported features
export_animation_in_sequence_alert = Show warning when saving an animation as a sequence of static images
overwrite_files_on_export_alert = Show warning when overwriting files on File > Export

View File

@ -1,4 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2021 by Igara Studio S.A. -->
<!-- Copyright (C) 2016 by David Capello -->
<gui>
<window id="open_sequence" text="@.title">
@ -9,6 +10,7 @@
</view>
<separator horizontal="true" />
<check id="repeat" text="@.repeat" />
<check id="dont_show" text="@general.dont_show" />
<hbox>
<boxfiller />
<hbox homogeneous="true">

View File

@ -258,6 +258,8 @@
pref="general.autoshow_timeline" />
<check text="@.rewind_on_stop" id="rewind_on_stop" tooltip="@.rewind_on_stop_tooltip"
pref="general.rewind_on_stop" />
<check text="@.keep_timeline_selection" id="keep_selection" tooltip="@.keep_timeline_selection_tooltip"
pref="timeline.keep_selection" />
<hbox>
<label text="@.default_first_frame" />
<expr id="first_frame" />
@ -424,6 +426,14 @@
<!-- Alerts -->
<vbox id="section_alerts">
<separator text="@.section_alerts" horizontal="true" />
<hbox>
<label text="@.open_sequence_alert" />
<combobox id="open_sequence">
<listitem text="@.open_sequence_alert_ask" value="0" />
<listitem text="@.open_sequence_alert_yes" value="1" />
<listitem text="@.open_sequence_alert_no" value="2" />
</combobox>
</hbox>
<check id="file_format_doesnt_support_alert" text="@.file_format_doesnt_support_alert"
pref="save_file.show_file_format_doesnt_support_alert" />
<check id="export_animation_in_sequence_alert" text="@.export_animation_in_sequence_alert"

View File

@ -235,7 +235,6 @@ if(ENABLE_UI)
commands/cmd_goto_tab.cpp
commands/cmd_grid.cpp
commands/cmd_home.cpp
commands/cmd_import_sprite_sheet.cpp
commands/cmd_invert_mask.cpp
commands/cmd_keyboard_shortcuts.cpp
commands/cmd_launch.cpp
@ -521,6 +520,7 @@ add_library(app-lib
commands/cmd_export_sprite_sheet.cpp
commands/cmd_flatten_layers.cpp
commands/cmd_flip.cpp
commands/cmd_import_sprite_sheet.cpp
commands/cmd_layer_from_background.cpp
commands/cmd_load_palette.cpp
commands/cmd_merge_down_layer.cpp

View File

@ -12,7 +12,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/commands.h"
#include "app/commands/params.h"
#include "app/commands/new_params.h"
#include "app/context.h"
#include "app/context_access.h"
#include "app/doc_access.h"
@ -44,6 +44,14 @@ namespace app {
using namespace ui;
struct ImportSpriteSheetParams : public NewParams {
Param<bool> ui { this, true, "ui" };
Param<app::SpriteSheetType> type { this, app::SpriteSheetType::None, "type" };
Param<gfx::Rect> frameBounds { this, gfx::Rect(0, 0, 0, 0), "frameBounds" };
Param<gfx::Size> padding { this, gfx::Size(0, 0), "padding" };
Param<bool> 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<ImportSpriteSheetParams> {
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<ImageRef> 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<gfx::Rect> 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()

View File

@ -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<bool>("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;
}

View File

@ -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 <string>
@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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<std::string>::fromString(const std::string& value)
setValue(value);
}
template<>
void Param<gfx::Size>::fromString(const std::string& value)
{
gfx::Size size;
std::vector<std::string> parts;
base::split_string(value, parts, ",");
if (parts.size() == 2) {
size.w = base::convert_to<int>(parts[0]);
size.h = base::convert_to<int>(parts[1]);
}
setValue(size);
}
template<>
void Param<gfx::Rect>::fromString(const std::string& value)
{
@ -253,6 +267,12 @@ void Param<std::string>::fromLua(lua_State* L, int index)
setValue(std::string());
}
template<>
void Param<gfx::Size>::fromLua(lua_State* L, int index)
{
setValue(script::convert_args_into_size(L, index));
}
template<>
void Param<gfx::Rect>::fromLua(lua_State* L, int index)
{

View File

@ -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

View File

@ -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

View File

@ -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<Sprite>(L, 1);
push_obj<gfx::Size>(L, sprite->pixelRatio());
return 1;
}
int Sprite_set_pixelRatio(lua_State* L)
{
auto sprite = get_docobj<Sprite>(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<Sprite>, UserData_set_color<Sprite> },
{ "data", UserData_get_text<Sprite>, UserData_set_text<Sprite> },
{ "pixelRatio", Sprite_get_pixelRatio, Sprite_set_pixelRatio },
{ nullptr, nullptr, nullptr }
};

View File

@ -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)

View File

@ -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);

View File

@ -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();
}
}
}
}

View File

@ -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