mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-17 17:42:51 +00:00
Fix rotSprite for normal layers (and keep the tile replication Ok on tilemap layers during a "transform action")
This commit is contained in:
parent
289a6ab864
commit
a1e013f4a7
@ -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
|
||||||
@ -403,7 +403,7 @@ void Doc::setTransformation(const Transformation& transform)
|
|||||||
|
|
||||||
void Doc::resetTransformation()
|
void Doc::resetTransformation()
|
||||||
{
|
{
|
||||||
m_transformation = Transformation(gfx::RectF(m_mask->bounds()));
|
m_transformation = Transformation(gfx::RectF(m_mask->bounds()), m_transformation.cornerThick());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -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
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/doc_undo.h"
|
#include "app/doc_undo.h"
|
||||||
#include "app/tools/pick_ink.h"
|
#include "app/tools/pick_ink.h"
|
||||||
|
#include "app/transformation.h"
|
||||||
#include "doc/mask.h"
|
#include "doc/mask.h"
|
||||||
#include "doc/tile.h"
|
#include "doc/tile.h"
|
||||||
#include "gfx/region.h"
|
#include "gfx/region.h"
|
||||||
@ -518,8 +519,11 @@ public:
|
|||||||
m_mask.unfreeze();
|
m_mask.unfreeze();
|
||||||
|
|
||||||
loop->setMask(&m_mask);
|
loop->setMask(&m_mask);
|
||||||
|
double cornerThick = (loop->isTilemapMode()) ?
|
||||||
|
CORNER_THICK_FOR_TILEMAP_MODE :
|
||||||
|
CORNER_THICK_FOR_PIXELS_MODE;
|
||||||
loop->getDocument()->setTransformation(
|
loop->getDocument()->setTransformation(
|
||||||
Transformation(RectF(m_mask.bounds())));
|
Transformation(RectF(m_mask.bounds()), cornerThick));
|
||||||
|
|
||||||
m_mask.clear();
|
m_mask.clear();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
@ -88,6 +88,9 @@ namespace app {
|
|||||||
// Returns the layer that will be modified if the tool paints
|
// Returns the layer that will be modified if the tool paints
|
||||||
virtual Layer* getLayer() = 0;
|
virtual Layer* getLayer() = 0;
|
||||||
|
|
||||||
|
// Returns true if the current mode is TileMap (false = Pixels)
|
||||||
|
virtual bool isTilemapMode() = 0;
|
||||||
|
|
||||||
// Returns the frame where we're paiting
|
// Returns the frame where we're paiting
|
||||||
virtual frame_t getFrame() = 0;
|
virtual frame_t getFrame() = 0;
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -24,8 +24,9 @@ Transformation::Transformation()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transformation::Transformation(const RectF& bounds)
|
Transformation::Transformation(const RectF& bounds, double cornerThick)
|
||||||
: m_bounds(bounds)
|
: m_bounds(bounds)
|
||||||
|
, m_cornerThick(cornerThick)
|
||||||
{
|
{
|
||||||
m_pivot.x = bounds.x + bounds.w/2;
|
m_pivot.x = bounds.x + bounds.w/2;
|
||||||
m_pivot.y = bounds.y + bounds.h/2;
|
m_pivot.y = bounds.y + bounds.h/2;
|
||||||
@ -86,7 +87,7 @@ RectF Transformation::transformedBounds() const
|
|||||||
// Create a union of all corners
|
// Create a union of all corners
|
||||||
RectF bounds;
|
RectF bounds;
|
||||||
for (int i=0; i<Corners::NUM_OF_CORNERS; ++i)
|
for (int i=0; i<Corners::NUM_OF_CORNERS; ++i)
|
||||||
bounds = bounds.createUnion(RectF(corners[i].x, corners[i].y, 0.001, 0.001));
|
bounds = bounds.createUnion(RectF(corners[i].x, corners[i].y, m_cornerThick, m_cornerThick));
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2020 Igara Studio S.A.
|
// Copyright (C) 2020-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
|
||||||
@ -13,6 +13,9 @@
|
|||||||
#include "gfx/rect.h"
|
#include "gfx/rect.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#define CORNER_THICK_FOR_TILEMAP_MODE 0.001
|
||||||
|
#define CORNER_THICK_FOR_PIXELS_MODE 1.0
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
// Represents a transformation that can be done by the user in the
|
// Represents a transformation that can be done by the user in the
|
||||||
@ -56,10 +59,10 @@ public:
|
|||||||
void rightBottom(const gfx::PointF& pt) { m_corners[RIGHT_BOTTOM] = pt; }
|
void rightBottom(const gfx::PointF& pt) { m_corners[RIGHT_BOTTOM] = pt; }
|
||||||
void leftBottom(const gfx::PointF& pt) { m_corners[LEFT_BOTTOM] = pt; }
|
void leftBottom(const gfx::PointF& pt) { m_corners[LEFT_BOTTOM] = pt; }
|
||||||
|
|
||||||
gfx::RectF bounds() const {
|
gfx::RectF bounds(double cornerThick) const {
|
||||||
gfx::RectF bounds;
|
gfx::RectF bounds;
|
||||||
for (int i=0; i<Corners::NUM_OF_CORNERS; ++i)
|
for (int i=0; i<Corners::NUM_OF_CORNERS; ++i)
|
||||||
bounds |= gfx::RectF(m_corners[i].x, m_corners[i].y, 0.001, 0.001);
|
bounds |= gfx::RectF(m_corners[i].x, m_corners[i].y, cornerThick, cornerThick);
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,12 +71,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Transformation();
|
Transformation();
|
||||||
Transformation(const gfx::RectF& bounds);
|
Transformation(const gfx::RectF& bounds, double cornerThick);
|
||||||
|
|
||||||
// Simple getters and setters. The angle is in radians.
|
// Simple getters and setters. The angle is in radians.
|
||||||
|
|
||||||
const gfx::RectF& bounds() const { return m_bounds; }
|
const gfx::RectF& bounds() const { return m_bounds; }
|
||||||
const gfx::PointF& pivot() const { return m_pivot; }
|
const gfx::PointF& pivot() const { return m_pivot; }
|
||||||
|
double cornerThick() const { return m_cornerThick; }
|
||||||
double angle() const { return m_angle; }
|
double angle() const { return m_angle; }
|
||||||
double skew() const { return m_skew; }
|
double skew() const { return m_skew; }
|
||||||
|
|
||||||
@ -103,6 +107,7 @@ private:
|
|||||||
gfx::PointF m_pivot = gfx::PointF(0.0, 0.0);
|
gfx::PointF m_pivot = gfx::PointF(0.0, 0.0);
|
||||||
double m_angle = 0.0;
|
double m_angle = 0.0;
|
||||||
double m_skew = 0.0;
|
double m_skew = 0.0;
|
||||||
|
double m_cornerThick = CORNER_THICK_FOR_PIXELS_MODE;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -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
|
||||||
@ -130,7 +130,10 @@ PixelsMovement::PixelsMovement(
|
|||||||
, m_fastMode(false)
|
, m_fastMode(false)
|
||||||
, m_needsRotSpriteRedraw(false)
|
, m_needsRotSpriteRedraw(false)
|
||||||
{
|
{
|
||||||
Transformation transform(mask->bounds());
|
double cornerThick = (m_site.tilemapMode() == TilemapMode::Tiles) ?
|
||||||
|
CORNER_THICK_FOR_TILEMAP_MODE :
|
||||||
|
CORNER_THICK_FOR_PIXELS_MODE;
|
||||||
|
Transformation transform(mask->bounds(), cornerThick);
|
||||||
set_pivot_from_preferences(transform);
|
set_pivot_from_preferences(transform);
|
||||||
|
|
||||||
m_initialData = transform;
|
m_initialData = transform;
|
||||||
@ -770,7 +773,7 @@ void PixelsMovement::stampImage(bool finalStamp)
|
|||||||
if (currentCel && currentCel->layer() &&
|
if (currentCel && currentCel->layer() &&
|
||||||
currentCel->layer()->isImage() &&
|
currentCel->layer()->isImage() &&
|
||||||
!currentCel->layer()->isEditableHierarchy()) {
|
!currentCel->layer()->isEditableHierarchy()) {
|
||||||
Transformation initialCelPos(gfx::Rect(m_initialMask0->bounds()));
|
Transformation initialCelPos(gfx::Rect(m_initialMask0->bounds()), m_currentData.cornerThick());
|
||||||
redrawExtraImage(&initialCelPos);
|
redrawExtraImage(&initialCelPos);
|
||||||
stampExtraCelImage();
|
stampExtraCelImage();
|
||||||
}
|
}
|
||||||
@ -1023,7 +1026,7 @@ void PixelsMovement::drawImage(
|
|||||||
ASSERT(dst);
|
ASSERT(dst);
|
||||||
|
|
||||||
auto corners = transformation.transformedCorners();
|
auto corners = transformation.transformedCorners();
|
||||||
gfx::Rect bounds = corners.bounds();
|
gfx::Rect bounds = corners.bounds(transformation.cornerThick());
|
||||||
|
|
||||||
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||||
dst->setMaskColor(doc::notile);
|
dst->setMaskColor(doc::notile);
|
||||||
@ -1071,7 +1074,7 @@ void PixelsMovement::drawImage(
|
|||||||
void PixelsMovement::drawMask(doc::Mask* mask, bool shrink)
|
void PixelsMovement::drawMask(doc::Mask* mask, bool shrink)
|
||||||
{
|
{
|
||||||
auto corners = m_currentData.transformedCorners();
|
auto corners = m_currentData.transformedCorners();
|
||||||
gfx::Rect bounds = corners.bounds();
|
gfx::Rect bounds = corners.bounds(m_currentData.cornerThick());
|
||||||
|
|
||||||
if (bounds.isEmpty()) {
|
if (bounds.isEmpty()) {
|
||||||
mask->clear();
|
mask->clear();
|
||||||
|
@ -282,6 +282,7 @@ public:
|
|||||||
Doc* getDocument() override { return m_document; }
|
Doc* getDocument() override { return m_document; }
|
||||||
Sprite* sprite() override { return m_sprite; }
|
Sprite* sprite() override { return m_sprite; }
|
||||||
Layer* getLayer() override { return m_layer; }
|
Layer* getLayer() override { return m_layer; }
|
||||||
|
bool isTilemapMode() override { return m_tilesMode; };
|
||||||
frame_t getFrame() override { return m_frame; }
|
frame_t getFrame() override { return m_frame; }
|
||||||
RgbMap* getRgbMap() override {
|
RgbMap* getRgbMap() override {
|
||||||
if (!m_rgbMap) {
|
if (!m_rgbMap) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user