mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-16 04:13:50 +00:00
Fix eyedropper to pick colors/tiles correctly from flipped tiles
* Added a new app::Color type for tiles, to store the flags of the picked tile. * Fixed color bar/status bar with a new draw_tile() to draw tiles with flip flags.
This commit is contained in:
parent
d3a8a10517
commit
3606a54826
@ -84,13 +84,21 @@ Color Color::fromGray(int g, int a)
|
||||
// static
|
||||
Color Color::fromIndex(int index)
|
||||
{
|
||||
ASSERT(index >= 0 || index == doc::notile);
|
||||
ASSERT(index >= 0);
|
||||
|
||||
Color color(Color::IndexType);
|
||||
color.m_value.index = index;
|
||||
return color;
|
||||
}
|
||||
|
||||
// static
|
||||
Color Color::fromTile(doc::tile_t tile)
|
||||
{
|
||||
Color color(Color::TileType);
|
||||
color.m_value.tile = tile;
|
||||
return color;
|
||||
}
|
||||
|
||||
// static
|
||||
Color Color::fromImage(PixelFormat pixelFormat, color_t c)
|
||||
{
|
||||
@ -115,9 +123,12 @@ Color Color::fromImage(PixelFormat pixelFormat, color_t c)
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
case IMAGE_TILEMAP:
|
||||
color = Color::fromIndex(c);
|
||||
break;
|
||||
|
||||
case IMAGE_TILEMAP:
|
||||
color = Color::fromTile(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return color;
|
||||
@ -869,12 +880,28 @@ int Color::getIndex() const
|
||||
case Color::IndexType:
|
||||
return m_value.index;
|
||||
|
||||
case Color::TileType:
|
||||
return doc::tile_geti(m_value.tile);
|
||||
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
doc::tile_t Color::getTile() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
case Color::TileType:
|
||||
return m_value.tile;
|
||||
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return doc::notile;
|
||||
}
|
||||
|
||||
int Color::getAlpha() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "doc/color.h"
|
||||
#include "doc/pixel_format.h"
|
||||
#include "doc/tile.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -30,6 +31,7 @@ namespace app {
|
||||
HslType,
|
||||
GrayType,
|
||||
IndexType,
|
||||
TileType,
|
||||
};
|
||||
|
||||
enum HumanReadableString {
|
||||
@ -46,6 +48,7 @@ namespace app {
|
||||
static Color fromHsl(double h, double s, double l, int a = 255); // h=[0,360], s=[0,1], v=[0,1]
|
||||
static Color fromGray(int g, int a = 255);
|
||||
static Color fromIndex(int index);
|
||||
static Color fromTile(doc::tile_t tile);
|
||||
|
||||
static Color fromImage(doc::PixelFormat pixelFormat, doc::color_t c);
|
||||
static Color fromImageGetPixel(doc::Image* image, int x, int y);
|
||||
@ -79,6 +82,7 @@ namespace app {
|
||||
double getHslLightness() const;
|
||||
int getGray() const;
|
||||
int getIndex() const;
|
||||
doc::tile_t getTile() const;
|
||||
int getAlpha() const;
|
||||
|
||||
// Setters
|
||||
@ -107,6 +111,7 @@ namespace app {
|
||||
int g, a;
|
||||
} gray;
|
||||
int index;
|
||||
doc::tile_t tile;
|
||||
} m_value;
|
||||
};
|
||||
|
||||
|
@ -63,10 +63,14 @@ bool get_cel_pixel(const Cel* cel,
|
||||
if (!image->bounds().contains(tilePos))
|
||||
return false;
|
||||
|
||||
const doc::tile_index ti =
|
||||
const doc::tile_index t =
|
||||
get_pixel(image, tilePos.x, tilePos.y);
|
||||
|
||||
PICKER_TRACE("PICKER: tile index=%d\n", ti);
|
||||
// TODO take care of flip flags
|
||||
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
|
||||
PICKER_TRACE("PICKER: tile=%d index=%d\n", t, ti);
|
||||
|
||||
doc::ImageRef tile = layerTilemap->tileset()->get(ti);
|
||||
if (!tile)
|
||||
@ -143,7 +147,7 @@ void ColorPicker::pickColor(const Site& site,
|
||||
const gfx::Point tilePos = site.grid().canvasToTile(gfx::Point(pos));
|
||||
if (cels.front()->image()->bounds().contains(tilePos)) {
|
||||
m_tile = doc::get_pixel(cels.front()->image(), tilePos.x, tilePos.y);
|
||||
m_color = app::Color::fromIndex(m_tile);
|
||||
m_color = app::Color::fromTile(m_tile);
|
||||
}
|
||||
}
|
||||
else if (site.tilemapMode() == TilemapMode::Pixels) {
|
||||
@ -166,7 +170,7 @@ void ColorPicker::pickColor(const Site& site,
|
||||
const gfx::Point tilePos = site.grid().canvasToTile(gfx::Point(pos));
|
||||
if (cel->image()->bounds().contains(tilePos)) {
|
||||
m_tile = doc::get_pixel(cel->image(), tilePos.x, tilePos.y);
|
||||
m_color = app::Color::fromIndex(m_tile);
|
||||
m_color = app::Color::fromTile(m_tile);
|
||||
}
|
||||
}
|
||||
else if (site.tilemapMode() == TilemapMode::Pixels) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -212,20 +212,22 @@ void draw_tile(ui::Graphics* g,
|
||||
if (tile == doc::notile)
|
||||
return;
|
||||
|
||||
doc::Tileset* ts = site.tileset();
|
||||
const doc::Tileset* ts = site.tileset();
|
||||
if (!ts)
|
||||
return;
|
||||
|
||||
doc::tile_index ti = doc::tile_geti(tile);
|
||||
const doc::tile_index ti = doc::tile_geti(tile);
|
||||
if (ti < 0 || ti >= ts->size())
|
||||
return;
|
||||
|
||||
doc::ImageRef tileImage = ts->get(ti);
|
||||
const doc::ImageRef tileImage = ts->get(ti);
|
||||
if (!tileImage)
|
||||
return;
|
||||
|
||||
const int w = tileImage->width();
|
||||
const int h = tileImage->height();
|
||||
const doc::tile_index tf = doc::tile_getf(tile);
|
||||
|
||||
int w = tileImage->width();
|
||||
int h = tileImage->height();
|
||||
os::SurfaceRef surface = os::instance()->makeRgbaSurface(w, h);
|
||||
convert_image_to_surface(tileImage.get(), get_current_palette(),
|
||||
surface.get(), 0, 0, 0, 0, w, h);
|
||||
@ -239,8 +241,41 @@ void draw_tile(ui::Graphics* g,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
}
|
||||
|
||||
g->drawSurface(surface.get(), gfx::Rect(0, 0, w, h), rc,
|
||||
os::Sampling(), &paint);
|
||||
gfx::Matrix m;
|
||||
|
||||
if (tf & doc::tile_f_dflip) {
|
||||
gfx::Matrix rot;
|
||||
rot.setRotate(90.0f);
|
||||
rot.postConcat(gfx::Matrix::MakeScale(-1.0f, 1.0f));
|
||||
m.preConcat(rot);
|
||||
std::swap(w, h);
|
||||
}
|
||||
|
||||
if (tf & doc::tile_f_xflip) {
|
||||
gfx::Matrix flip;
|
||||
flip.setScale(-1.0f, 1.0f, w/float(2.0f), 0.0f);
|
||||
m.postConcat(flip);
|
||||
}
|
||||
|
||||
if (tf & doc::tile_f_yflip) {
|
||||
gfx::Matrix flip;
|
||||
flip.setScale(1.0f, -1.0f, 0.0f, h/float(2.0f));
|
||||
m.postConcat(flip);
|
||||
}
|
||||
|
||||
m.postConcat(gfx::Matrix::MakeScale(float(rc.w) / w,
|
||||
float(rc.h) / h));
|
||||
|
||||
// TODO integrate getInternalDeltaX/Y translation in ui::Graphics
|
||||
m.postConcat(gfx::Matrix::MakeTrans(rc.x+g->getInternalDeltaX(),
|
||||
rc.y+g->getInternalDeltaY()));
|
||||
|
||||
g->save();
|
||||
g->setMatrix(m);
|
||||
g->drawRgbaSurface(surface.get(),
|
||||
-g->getInternalDeltaX(),
|
||||
-g->getInternalDeltaY());
|
||||
g->restore();
|
||||
}
|
||||
|
||||
void draw_tile_button(ui::Graphics* g,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
@ -856,8 +856,8 @@ tools::ToolLoop* create_tool_loop(
|
||||
// Get fg/bg colors
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex?
|
||||
params.bg = app::Color::fromIndex(colorbar->getBgTile());
|
||||
params.fg = app::Color::fromTile(colorbar->getFgTile());
|
||||
params.bg = app::Color::fromTile(colorbar->getBgTile());
|
||||
}
|
||||
else {
|
||||
params.fg = colorbar->getFgColor();
|
||||
@ -1051,8 +1051,8 @@ tools::ToolLoop* create_tool_loop_preview(
|
||||
// Get fg/bg colors
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex?
|
||||
params.bg = app::Color::fromIndex(colorbar->getBgTile());
|
||||
params.fg = app::Color::fromTile(colorbar->getFgTile());
|
||||
params.bg = app::Color::fromTile(colorbar->getBgTile());
|
||||
}
|
||||
else {
|
||||
params.fg = colorbar->getFgColor();
|
||||
|
@ -472,6 +472,11 @@ public:
|
||||
}
|
||||
|
||||
IndicatorsGeneration& add(const app::Color& color) {
|
||||
// For Color::TileType, use the tile version
|
||||
if (color.getType() == app::Color::TileType) {
|
||||
return add(color.getTile());
|
||||
}
|
||||
|
||||
auto theme = SkinTheme::get(m_indicators);
|
||||
|
||||
// Eyedropper icon
|
||||
|
@ -700,13 +700,14 @@ void Sprite::pickCels(const gfx::PointF& pos,
|
||||
const Grid grid = cel->grid();
|
||||
|
||||
tile_t tile = notile;
|
||||
gfx::Point tilePos = grid.canvasToTile(gfx::Point(pos));
|
||||
const gfx::Point tilePos = grid.canvasToTile(gfx::Point(pos));
|
||||
if (image->bounds().contains(tilePos.x, tilePos.y))
|
||||
tile = image->getPixel(tilePos.x, tilePos.y);
|
||||
if (tile == notile)
|
||||
continue;
|
||||
|
||||
image = tileset->get(tile).get();
|
||||
const tile_index ti = tile_geti(tile);
|
||||
image = tileset->get(ti).get();
|
||||
if (!image)
|
||||
continue;
|
||||
|
||||
|
@ -529,15 +529,16 @@ void composite_image_general_with_tile_flags(
|
||||
int(std::ceil(area.dstBounds().w)),
|
||||
int(std::ceil(area.dstBounds().h)));
|
||||
gfx::Rect srcBounds = area.srcBounds();
|
||||
const gfx::Rect srcImgBounds = src->bounds();
|
||||
const gfx::Size srcMinSize = src->size();
|
||||
|
||||
dstBounds &= dst->bounds();
|
||||
|
||||
if (tileFlags & tile_f_xflip) {
|
||||
srcBounds.x = src->bounds().x2()-srcBounds.w-srcBounds.x;
|
||||
srcBounds.x = sx*srcImgBounds.x2() - srcBounds.x2();
|
||||
}
|
||||
if (tileFlags & tile_f_yflip) {
|
||||
srcBounds.y = src->bounds().y2()-srcBounds.h-srcBounds.y;
|
||||
srcBounds.y = sy*srcImgBounds.y2() - srcBounds.y2();
|
||||
}
|
||||
|
||||
int dstY = dstBounds.y;
|
||||
@ -558,7 +559,7 @@ void composite_image_general_with_tile_flags(
|
||||
srcX = (srcBounds.x2()-1-x) / sx;
|
||||
}
|
||||
else {
|
||||
srcX = srcBounds.x+x / sx;
|
||||
srcX = (srcBounds.x+x) / sx;
|
||||
}
|
||||
if (tileFlags & tile_f_yflip) {
|
||||
srcY = (srcBounds.y2()-1-y) / sy;
|
||||
|
Loading…
Reference in New Issue
Block a user