Merge branch 'main' into beta

This commit is contained in:
David Capello 2022-02-08 12:56:26 -03:00
commit 1f4e3bcd11
17 changed files with 109 additions and 33 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2017 David Capello
//
// This program is distributed under the terms of
@ -65,6 +65,7 @@ public:
private:
void onChange() {
stopPreview();
m_filter.setBrightness(m_brightness.getValue() / 100.0);
m_filter.setContrast(m_contrast.getValue() / 100.0);
restartPreview();

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -55,6 +55,8 @@ public:
protected:
void onCurveChange() {
stopPreview();
// The color curve in the filter is the same refereced by the
// editor. But anyway, we have to re-set the same curve in the
// filter to regenerate the map used internally by the filter

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -136,6 +136,8 @@ private:
std::shared_ptr<ConvolutionMatrix> matrix = m_stock.getByName(selected->text().c_str());
Target newTarget = matrix->getDefaultTarget();
stopPreview();
m_filter.setMatrix(matrix);
setNewTarget(newTarget);

View File

@ -81,6 +81,12 @@ private:
newSize.w = base::clamp(newSize.w, 1, 100);
newSize.h = base::clamp(newSize.h, 1, 100);
// If we had a previous filter preview running in the background,
// we explicitly request it be stopped. Otherwise, changing the
// size of the filter would cause a race condition on
// MedianFilter::m_channel field.
stopPreview();
m_filter.setSize(newSize.w, newSize.h);
restartPreview();
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2017-2018 David Capello
//
// This program is distributed under the terms of
@ -95,6 +95,8 @@ private:
}
void onChangeMode() {
stopPreview();
Preferences::instance().hueSaturation.mode(mode());
m_filter.setMode(mode());
m_sliders.setColorType(isHsl() ?
@ -105,6 +107,8 @@ private:
}
void onChangeControls() {
stopPreview();
m_sliders.syncRelHsvHslSliders();
if (isHsl()) {

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -137,21 +137,26 @@ private:
}
void onColorChange(const app::Color& color) {
stopPreview();
m_filter.color(color);
restartPreview();
}
void onBgColorChange(const app::Color& color) {
stopPreview();
m_filter.bgColor(color);
restartPreview();
}
void onPlaceChange(OutlineFilter::Place place) {
stopPreview();
m_filter.place(place);
restartPreview();
}
void onMatrixTypeChange() {
stopPreview();
OutlineFilter::Matrix matrix = OutlineFilter::Matrix::None;
switch (m_panel.outlineType()->selectedItem()) {
case CIRCLE: matrix = OutlineFilter::Matrix::Circle; break;
@ -165,6 +170,8 @@ private:
}
void onMatrixPixelChange(const int index) {
stopPreview();
int matrix = (int)m_filter.matrix();
matrix ^= (1 << (8-index));
m_filter.matrix((OutlineFilter::Matrix)matrix);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -101,16 +101,19 @@ public:
private:
void onFromChange(const app::Color& color) {
stopPreview();
m_filter.setFrom(color);
restartPreview();
}
void onToChange(const app::Color& color) {
stopPreview();
m_filter.setTo(color);
restartPreview();
}
void onToleranceChange() {
stopPreview();
m_filter.setTolerance(m_toleranceSlider->getValue());
restartPreview();
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2022 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
@ -40,7 +41,7 @@ namespace app {
bool doModal();
// Starts (or restart) the preview procedure. You should call this
// method each time the user modifies parameters of the Filter.
// method after the user modifies parameters of the Filter.
void restartPreview();
protected:
@ -61,9 +62,11 @@ namespace app {
// mode overriding this method.
virtual void setupTiledMode(TiledMode tiledMode) { }
private:
// Stops the filter preview background thread, you should call
// this before you modify the parameters of the Filter.
void stopPreview();
private:
const char* m_cfgSection;
FilterManagerImpl* m_filterMgr;
ui::Box m_hbox;

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A.
// Copyright (C) 2018-2022 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -10,6 +10,6 @@
// Increment this value if the scripting API is modified between two
// released Aseprite versions.
#define API_VERSION 16
#define API_VERSION 17
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
@ -138,7 +138,8 @@ app::Color Color_new(lua_State* L, int index)
// Convert { index } into a Color
if (lua_getfield(L, index, "index") != LUA_TNIL) {
color = app::Color::fromIndex(lua_tonumber(L, -1));
int i = lua_tointeger(L, -1);
color = app::Color::fromIndex(i);
lua_pop(L, 1);
return color;
}
@ -296,7 +297,7 @@ int Color_get_gray(lua_State* L)
int Color_get_index(lua_State* L)
{
auto color = get_obj<app::Color>(L, 1);
lua_pushnumber(L, color->getIndex());
lua_pushinteger(L, color->getIndex());
return 1;
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A.
// Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2015-2018 David Capello
//
// This program is distributed under the terms of
@ -376,6 +376,8 @@ int Sprite_deleteLayer(lua_State* L)
}
}
if (layer) {
if (sprite != layer->sprite())
return luaL_error(L, "the layer doesn't belong to the sprite");
Tx tx;
tx(new cmd::RemoveLayer(layer));
tx.commit();
@ -502,11 +504,11 @@ int Sprite_newCel(lua_State* L)
int Sprite_deleteCel(lua_State* L)
{
auto sprite = get_docobj<Sprite>(L, 1);
(void)sprite; // unused
auto cel = may_get_docobj<doc::Cel>(L, 2);
if (!cel) {
if (auto layer = may_get_docobj<doc::Layer>(L, 2)) {
if (sprite != layer->sprite())
return luaL_error(L, "the layer doesn't belong to the sprite");
doc::frame_t frame = get_frame_number_from_arg(L, 3);
if (layer->isImage())
cel = static_cast<doc::LayerImage*>(layer)->cel(frame);
@ -549,6 +551,8 @@ int Sprite_deleteTag(lua_State* L)
tag = sprite->tags().getByName(tagName);
}
if (tag) {
if (sprite != tag->owner()->sprite())
return luaL_error(L, "the tag doesn't belong to the sprite");
Tx tx;
tx(new cmd::RemoveTag(sprite, tag));
tx.commit();
@ -583,6 +587,8 @@ int Sprite_deleteSlice(lua_State* L)
slice = sprite->slices().getByName(sliceName);
}
if (slice) {
if (sprite != slice->owner()->sprite())
return luaL_error(L, "the slice doesn't belong to the sprite");
Tx tx;
tx(new cmd::RemoveSlice(sprite, slice));
tx.commit();

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
@ -160,10 +160,12 @@ bool ColorShades::onProcessMessage(ui::Message* msg)
break;
case ui::kMouseUpMessage: {
auto button = static_cast<ui::MouseMessage*>(msg)->button();
if (m_click == ClickWholeShade) {
setSelected(true);
ClickEvent ev(static_cast<ui::MouseMessage*>(msg)->button());
ClickEvent ev(button);
Click(ev);
closeWindow();
@ -180,9 +182,18 @@ bool ColorShades::onProcessMessage(ui::Message* msg)
m_dragIndex = -1;
invalidate();
ClickEvent ev(button);
Click(ev);
// Relayout the context bar if we have removed an entry.
if (m_hotIndex < 0)
//
// TODO it looks like this should be handled in some kind of
// Change() event in the ColorBar
if (m_hotIndex < 0 &&
parent() &&
parent()->parent()) {
parent()->parent()->layout();
}
}
if (hasCapture())

View File

@ -60,6 +60,12 @@ void DelayedMouseMove::onMouseUp(const ui::MouseMessage* msg)
commitMouseMove();
}
void DelayedMouseMove::stopTimer()
{
if (m_timer.isRunning())
m_timer.stop();
}
void DelayedMouseMove::commitMouseMove()
{
if (m_timer.isRunning())

View File

@ -50,6 +50,11 @@ namespace app {
bool onMouseMove(const ui::MouseMessage* msg);
void onMouseUp(const ui::MouseMessage* msg);
// Forces stopping the timer so we don't receive a Tick event in
// case that we've just removed/delete some structure that is
// needed in onCommitMouseMove().
void stopTimer();
const gfx::PointF& spritePos() const;
private:

View File

@ -400,6 +400,11 @@ bool MovingPixelsState::onMouseMove(Editor* editor, MouseMessage* msg)
void MovingPixelsState::onCommitMouseMove(Editor* editor,
const gfx::PointF& spritePos)
{
ASSERT(m_pixelsMovement);
if (!m_pixelsMovement->isDragging())
return;
m_pixelsMovement->setFastMode(true);
// Get the customization for the pixels movement (snap to grid, angle snap, etc.).
@ -857,6 +862,10 @@ void MovingPixelsState::removeAsEditorObserver()
void MovingPixelsState::removePixelsMovement()
{
// Avoid receiving a onCommitMouseMove() message when
// m_pixelsMovement is already nullptr.
m_delayedMouseMove.stopTimer();
m_pixelsMovement.reset();
m_ctxConn.disconnect();
m_opaqueConn.disconnect();

View File

@ -375,13 +375,22 @@ void MainWindow::onResize(ui::ResizeEvent& ev)
{
app::gen::MainWindow::onResize(ev);
ui::Display* display = this->display();
if ((display) &&
(display->scale()*ui::guiscale() > 2) &&
(!m_scalePanic) &&
(display->size().w / ui::guiscale() < 320 ||
display->size().h / ui::guiscale() < 260)) {
showNotification(m_scalePanic = new ScreenScalePanic);
os::Window* nativeWindow = (display() ? display()->nativeWindow(): nullptr);
if (nativeWindow && nativeWindow->screen()) {
const int scale = nativeWindow->scale()*ui::guiscale();
// We can check for the available workarea to know that the user
// can resize the window to its full size and there will be enough
// room to display some common dialogs like (for example) the
// Preferences dialog.
if ((scale > 2) &&
(!m_scalePanic)) {
const gfx::Size wa = nativeWindow->screen()->workarea().size();
if ((wa.w / scale < 256 ||
wa.h / scale < 256)) {
showNotification(m_scalePanic = new ScreenScalePanic);
}
}
}
}

View File

@ -144,18 +144,19 @@ void render_rgba_radial_gradient(
return;
}
// If there is no vector defining the gradient (just one point),
// the "gradient" will be just "c0"
if (p0 == p1) {
img->clear(c0);
return;
}
base::Vector2d<double>
u(p0.x, p0.y),
v(p1.x, p1.y), w;
w = (v - u) / 2;
// If there is no vector defining the gradient (just one point),
// the "gradient" will be just a solid color ("c1")
if (std::fabs(w.x) <= 0.000001 ||
std::fabs(w.y) <= 0.000001) {
img->clear(c1);
return;
}
// As we use non-premultiplied RGB values, we need correct RGB
// values on each stop. So in case that one color has alpha=0
// (complete transparent), use the RGB values of the