mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-22 15:39:52 +00:00
Fix eyedropper/move tool for reference layers
This commit is contained in:
parent
bf4d6f1e4e
commit
1b053de2f2
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -30,10 +30,12 @@ ColorPicker::ColorPicker()
|
||||
}
|
||||
|
||||
void ColorPicker::pickColor(const doc::Site& site,
|
||||
const gfx::Point& _pos, Mode mode)
|
||||
const gfx::PointF& _pos,
|
||||
const render::Projection& proj,
|
||||
const Mode mode)
|
||||
{
|
||||
const doc::Sprite* sprite = site.sprite();
|
||||
gfx::Point pos = _pos;
|
||||
gfx::PointF pos = _pos;
|
||||
|
||||
m_alpha = 255;
|
||||
m_color = app::Color::fromMask();
|
||||
@ -44,17 +46,18 @@ void ColorPicker::pickColor(const doc::Site& site,
|
||||
DocumentPreferences& docPref = Preferences::instance().document(doc);
|
||||
|
||||
if (int(docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS))
|
||||
pos.x = wrap_value(pos.x, site.sprite()->width());
|
||||
pos.x = wrap_value<double>(pos.x, site.sprite()->width());
|
||||
|
||||
if (int(docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS))
|
||||
pos.y = wrap_value(pos.y, site.sprite()->height());
|
||||
pos.y = wrap_value<double>(pos.y, site.sprite()->height());
|
||||
}
|
||||
|
||||
// Get the color from the image
|
||||
if (mode == FromComposition) { // Pick from the composed image
|
||||
m_color = app::Color::fromImage(
|
||||
sprite->pixelFormat(),
|
||||
render::get_sprite_pixel(sprite, pos.x, pos.y, site.frame()));
|
||||
render::get_sprite_pixel(sprite, pos.x, pos.y,
|
||||
site.frame(), proj));
|
||||
|
||||
doc::CelList cels;
|
||||
sprite->pickCels(pos.x, pos.y, site.frame(), 128, cels);
|
||||
@ -62,12 +65,27 @@ void ColorPicker::pickColor(const doc::Site& site,
|
||||
m_layer = cels.front()->layer();
|
||||
}
|
||||
else { // Pick from the current layer
|
||||
int u, v;
|
||||
doc::Image* image = site.image(&u, &v, NULL);
|
||||
gfx::Point pt(pos.x-u, pos.y-v);
|
||||
const Cel* cel = site.cel();
|
||||
if (cel) {
|
||||
gfx::RectF celBounds;
|
||||
if (cel->layer()->isReference())
|
||||
celBounds = cel->boundsF();
|
||||
else
|
||||
celBounds = cel->bounds();
|
||||
|
||||
if (image && image->bounds().contains(pt)) {
|
||||
doc::color_t imageColor = get_pixel(image, pt.x, pt.y);
|
||||
const doc::Image* image = cel->image();
|
||||
|
||||
if (!celBounds.contains(pos))
|
||||
return;
|
||||
|
||||
pos.x = (pos.x-celBounds.x)*image->width()/celBounds.w;
|
||||
pos.y = (pos.y-celBounds.y)*image->height()/celBounds.h;
|
||||
const gfx::Point ipos(pos);
|
||||
if (!image->bounds().contains(ipos))
|
||||
return;
|
||||
|
||||
const doc::color_t imageColor =
|
||||
get_pixel(image, ipos.x, ipos.y);
|
||||
|
||||
switch (image->pixelFormat()) {
|
||||
case IMAGE_RGB:
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -16,6 +16,10 @@ namespace doc {
|
||||
class Site;
|
||||
}
|
||||
|
||||
namespace render {
|
||||
class Projection;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
class ColorPicker {
|
||||
@ -25,7 +29,9 @@ namespace app {
|
||||
ColorPicker();
|
||||
|
||||
void pickColor(const doc::Site& site,
|
||||
const gfx::Point& pos, Mode mode);
|
||||
const gfx::PointF& pos,
|
||||
const render::Projection& proj,
|
||||
const Mode mode);
|
||||
|
||||
app::Color color() const { return m_color; }
|
||||
int alpha() const { return m_alpha; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -40,7 +40,8 @@ EyedropperCommand::EyedropperCommand()
|
||||
}
|
||||
|
||||
void EyedropperCommand::pickSample(const doc::Site& site,
|
||||
const gfx::Point& pixelPos,
|
||||
const gfx::PointF& pixelPos,
|
||||
const render::Projection& proj,
|
||||
app::Color& color)
|
||||
{
|
||||
// Check if we've to grab alpha channel or the merged color.
|
||||
@ -51,6 +52,7 @@ void EyedropperCommand::pickSample(const doc::Site& site,
|
||||
ColorPicker picker;
|
||||
picker.pickColor(site,
|
||||
pixelPos,
|
||||
proj,
|
||||
(allLayers ?
|
||||
ColorPicker::FromComposition:
|
||||
ColorPicker::FromActiveLayer));
|
||||
@ -171,7 +173,7 @@ void EyedropperCommand::onExecute(Context* context)
|
||||
}
|
||||
|
||||
// Pixel position to get
|
||||
gfx::Point pixelPos = editor->screenToEditor(ui::get_mouse_position());
|
||||
gfx::PointF pixelPos = editor->screenToEditorF(ui::get_mouse_position());
|
||||
|
||||
// Start with fg/bg color
|
||||
Preferences& pref = Preferences::instance();
|
||||
@ -179,7 +181,10 @@ void EyedropperCommand::onExecute(Context* context)
|
||||
m_background ? pref.colorBar.bgColor():
|
||||
pref.colorBar.fgColor();
|
||||
|
||||
pickSample(editor->getSite(), pixelPos, color);
|
||||
pickSample(editor->getSite(),
|
||||
pixelPos,
|
||||
editor->projection(),
|
||||
color);
|
||||
|
||||
if (m_background)
|
||||
pref.colorBar.bgColor(color);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -15,6 +15,10 @@ namespace doc {
|
||||
class Site;
|
||||
}
|
||||
|
||||
namespace render {
|
||||
class Projection;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
class EyedropperCommand : public Command {
|
||||
@ -24,7 +28,8 @@ namespace app {
|
||||
|
||||
// Returns the color in the given sprite pos.
|
||||
void pickSample(const doc::Site& site,
|
||||
const gfx::Point& pixelPos,
|
||||
const gfx::PointF& pixelPos,
|
||||
const render::Projection& proj,
|
||||
app::Color& color);
|
||||
|
||||
protected:
|
||||
|
@ -14,9 +14,11 @@
|
||||
#include "app/color_utils.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/cel.h"
|
||||
@ -64,7 +66,10 @@ void MaskContentCommand::onExecute(Context* context)
|
||||
gfx::Color color;
|
||||
if (writer.layer()->isBackground()) {
|
||||
ColorPicker picker;
|
||||
picker.pickColor(*writer.site(), gfx::Point(0, 0), ColorPicker::FromComposition);
|
||||
picker.pickColor(*writer.site(),
|
||||
gfx::PointF(0.0, 0.0),
|
||||
current_editor->projection(),
|
||||
ColorPicker::FromComposition);
|
||||
color = color_utils::color_for_layer(picker.color(), writer.layer());
|
||||
}
|
||||
else
|
||||
|
@ -1232,10 +1232,11 @@ app::Color Editor::getColorByPosition(const gfx::Point& mousePos)
|
||||
{
|
||||
Site site = getSite();
|
||||
if (site.sprite()) {
|
||||
gfx::Point editorPos = screenToEditor(mousePos);
|
||||
gfx::PointF editorPos = screenToEditorF(mousePos);
|
||||
|
||||
ColorPicker picker;
|
||||
picker.pickColor(site, editorPos, ColorPicker::FromComposition);
|
||||
picker.pickColor(site, editorPos, m_proj,
|
||||
ColorPicker::FromComposition);
|
||||
return picker.color();
|
||||
}
|
||||
else
|
||||
|
@ -178,10 +178,11 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
if (clickedInk->isCelMovement()) {
|
||||
// Handle "Auto Select Layer"
|
||||
if (editor->isAutoSelectLayer()) {
|
||||
gfx::Point cursor = editor->screenToEditor(msg->position());
|
||||
|
||||
gfx::PointF cursor = editor->screenToEditorF(msg->position());
|
||||
ColorPicker picker;
|
||||
picker.pickColor(site, cursor, ColorPicker::FromComposition);
|
||||
picker.pickColor(site, cursor,
|
||||
editor->projection(),
|
||||
ColorPicker::FromComposition);
|
||||
|
||||
auto range = App::instance()->timeline()->range();
|
||||
|
||||
@ -447,7 +448,7 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
{
|
||||
tools::Ink* ink = editor->getCurrentEditorInk();
|
||||
const Sprite* sprite = editor->sprite();
|
||||
gfx::Point spritePos = editor->screenToEditor(ui::get_mouse_position());
|
||||
gfx::PointF spritePos = editor->screenToEditorF(ui::get_mouse_position());
|
||||
|
||||
if (!sprite) {
|
||||
StatusBar::instance()->clearText();
|
||||
@ -456,10 +457,15 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
else if (ink->isEyedropper()) {
|
||||
EyedropperCommand cmd;
|
||||
app::Color color = Preferences::instance().colorBar.fgColor();
|
||||
cmd.pickSample(editor->getSite(), spritePos, color);
|
||||
cmd.pickSample(editor->getSite(),
|
||||
spritePos,
|
||||
editor->projection(),
|
||||
color);
|
||||
|
||||
char buf[256];
|
||||
sprintf(buf, " :pos: %d %d", spritePos.x, spritePos.y);
|
||||
sprintf(buf, " :pos: %d %d",
|
||||
int(spritePos.x),
|
||||
int(spritePos.y));
|
||||
|
||||
StatusBar::instance()->showColor(0, buf, color);
|
||||
}
|
||||
@ -471,7 +477,8 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
char buf[1024];
|
||||
sprintf(
|
||||
buf, ":pos: %d %d :%s: %d %d",
|
||||
spritePos.x, spritePos.y,
|
||||
int(spritePos.x),
|
||||
int(spritePos.y),
|
||||
(mask ? "selsize": "size"),
|
||||
(mask ? mask->bounds().w: sprite->width()),
|
||||
(mask ? mask->bounds().h: sprite->height()));
|
||||
@ -485,8 +492,8 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
|
||||
if (editor->docPref().show.grid()) {
|
||||
auto gb = editor->docPref().grid.bounds();
|
||||
int col = (spritePos.x - (gb.x % gb.w)) / gb.w;
|
||||
int row = (spritePos.y - (gb.y % gb.h)) / gb.h;
|
||||
int col = (int(spritePos.x) - (gb.x % gb.w)) / gb.w;
|
||||
int row = (int(spritePos.y) - (gb.y % gb.h)) / gb.h;
|
||||
sprintf(
|
||||
buf+std::strlen(buf), " :grid: %d %d", col, row);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -8,6 +8,8 @@
|
||||
#define APP_WRAP_VALUE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace app {
|
||||
|
||||
template<typename T>
|
||||
@ -18,6 +20,14 @@ namespace app {
|
||||
return x % size;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double wrap_value(const double x, const double size) {
|
||||
if (x < 0.0)
|
||||
return size - std::fmod(-(x+1.0), size) - 1.0;
|
||||
else
|
||||
return std::fmod(x, size);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
@ -449,9 +449,10 @@ void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const Remap& remap)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Drawing
|
||||
|
||||
void Sprite::pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList& cels) const
|
||||
void Sprite::pickCels(double x, double y, frame_t frame, int opacityThreshold, CelList& cels) const
|
||||
{
|
||||
LayerList layers = allVisibleLayers();
|
||||
gfx::PointF pos(x, y);
|
||||
|
||||
for (int i=(int)layers.size()-1; i>=0; --i) {
|
||||
Layer* layer = layers[i];
|
||||
@ -466,13 +467,22 @@ void Sprite::pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList
|
||||
if (!image)
|
||||
continue;
|
||||
|
||||
if (!cel->bounds().contains(gfx::Point(x, y)))
|
||||
gfx::RectF celBounds;
|
||||
if (cel->layer()->isReference())
|
||||
celBounds = cel->boundsF();
|
||||
else
|
||||
celBounds = cel->bounds();
|
||||
|
||||
if (!celBounds.contains(pos))
|
||||
continue;
|
||||
|
||||
color_t color = get_pixel(image,
|
||||
x - cel->x(),
|
||||
y - cel->y());
|
||||
const gfx::Point ipos(
|
||||
(pos.x-celBounds.x)*image->width()/celBounds.w,
|
||||
(pos.y-celBounds.y)*image->height()/celBounds.h);
|
||||
if (!image->bounds().contains(ipos))
|
||||
continue;
|
||||
|
||||
const color_t color = get_pixel(image, ipos.x, ipos.y);
|
||||
bool isOpaque = true;
|
||||
|
||||
switch (image->pixelFormat()) {
|
||||
|
@ -140,7 +140,7 @@ namespace doc {
|
||||
void replaceImage(ObjectId curImageId, const ImageRef& newImage);
|
||||
void getImages(std::vector<Image*>& images) const;
|
||||
void remapImages(frame_t frameFrom, frame_t frameTo, const Remap& remap);
|
||||
void pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList& cels) const;
|
||||
void pickCels(double x, double y, frame_t frame, int opacityThreshold, CelList& cels) const;
|
||||
|
||||
////////////////////////////////////////
|
||||
// Iterators
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -16,15 +16,25 @@ namespace render {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
color_t get_sprite_pixel(const Sprite* sprite, int x, int y, frame_t frame)
|
||||
color_t get_sprite_pixel(const Sprite* sprite,
|
||||
const double x,
|
||||
const double y,
|
||||
const frame_t frame,
|
||||
const Projection& proj)
|
||||
{
|
||||
color_t color = 0;
|
||||
|
||||
if ((x >= 0) && (y >= 0) && (x < sprite->width()) && (y < sprite->height())) {
|
||||
if ((x >= 0.0) && (x < sprite->width()) &&
|
||||
(y >= 0.0) && (y < sprite->height())) {
|
||||
base::UniquePtr<Image> image(Image::create(sprite->pixelFormat(), 1, 1));
|
||||
|
||||
render::Render().renderSprite(image, sprite, frame,
|
||||
gfx::Clip(0, 0, x, y, 1, 1));
|
||||
render::Render render;
|
||||
render.setProjection(proj);
|
||||
render.renderSprite(
|
||||
image, sprite, frame,
|
||||
gfx::ClipF(0, 0,
|
||||
proj.applyX(x),
|
||||
proj.applyY(y), 1, 1));
|
||||
|
||||
color = get_pixel(image, 0, 0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -17,10 +17,16 @@ namespace doc {
|
||||
namespace render {
|
||||
using namespace doc;
|
||||
|
||||
class Projection;
|
||||
|
||||
// Gets a pixel from the sprite in the specified position. If in the
|
||||
// specified coordinates there're background this routine will
|
||||
// return the 0 color (the mask-color).
|
||||
color_t get_sprite_pixel(const Sprite* sprite, int x, int y, frame_t frame);
|
||||
color_t get_sprite_pixel(const Sprite* sprite,
|
||||
const double x,
|
||||
const double y,
|
||||
const frame_t frame,
|
||||
const Projection& proj);
|
||||
|
||||
} // namespace render
|
||||
|
||||
|
@ -576,7 +576,7 @@ void Render::renderSprite(
|
||||
{
|
||||
renderSprite(
|
||||
dstImage, sprite, frame,
|
||||
gfx::Clip(sprite->bounds()));
|
||||
gfx::ClipF(sprite->bounds()));
|
||||
}
|
||||
|
||||
void Render::renderLayer(
|
||||
@ -615,7 +615,7 @@ void Render::renderSprite(
|
||||
Image* dstImage,
|
||||
const Sprite* sprite,
|
||||
frame_t frame,
|
||||
const gfx::Clip& area)
|
||||
const gfx::ClipF& area)
|
||||
{
|
||||
m_sprite = sprite;
|
||||
|
||||
|
@ -155,7 +155,7 @@ namespace render {
|
||||
Image* dstImage,
|
||||
const Sprite* sprite,
|
||||
frame_t frame,
|
||||
const gfx::Clip& area);
|
||||
const gfx::ClipF& area);
|
||||
|
||||
// Extra functions
|
||||
void renderBackground(
|
||||
|
Loading…
x
Reference in New Issue
Block a user