diff --git a/src/app/color_picker.cpp b/src/app/color_picker.cpp index 3dedc49e5..31c1a3a5c 100644 --- a/src/app/color_picker.cpp +++ b/src/app/color_picker.cpp @@ -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(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(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: diff --git a/src/app/color_picker.h b/src/app/color_picker.h index 987d0be96..9a798157e 100644 --- a/src/app/color_picker.h +++ b/src/app/color_picker.h @@ -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; } diff --git a/src/app/commands/cmd_eyedropper.cpp b/src/app/commands/cmd_eyedropper.cpp index 5075e6281..d5251f7a5 100644 --- a/src/app/commands/cmd_eyedropper.cpp +++ b/src/app/commands/cmd_eyedropper.cpp @@ -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); diff --git a/src/app/commands/cmd_eyedropper.h b/src/app/commands/cmd_eyedropper.h index 954b0ee7f..5747a9fe8 100644 --- a/src/app/commands/cmd_eyedropper.h +++ b/src/app/commands/cmd_eyedropper.h @@ -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: diff --git a/src/app/commands/cmd_mask_content.cpp b/src/app/commands/cmd_mask_content.cpp index 9b57bc2f8..f9f7ee3c0 100644 --- a/src/app/commands/cmd_mask_content.cpp +++ b/src/app/commands/cmd_mask_content.cpp @@ -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 diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 66b1f97f9..b283eedbe 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -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 diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index 31b7cd8b8..e1669efe5 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -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); } diff --git a/src/app/util/wrap_value.h b/src/app/util/wrap_value.h index 73d0b8f20..ddb02d108 100644 --- a/src/app/util/wrap_value.h +++ b/src/app/util/wrap_value.h @@ -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 + namespace app { template @@ -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 diff --git a/src/doc/sprite.cpp b/src/doc/sprite.cpp index 00e8718f8..c8f338c88 100644 --- a/src/doc/sprite.cpp +++ b/src/doc/sprite.cpp @@ -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()) { diff --git a/src/doc/sprite.h b/src/doc/sprite.h index fd1428ba7..5712cf33c 100644 --- a/src/doc/sprite.h +++ b/src/doc/sprite.h @@ -140,7 +140,7 @@ namespace doc { void replaceImage(ObjectId curImageId, const ImageRef& newImage); void getImages(std::vector& 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 diff --git a/src/render/get_sprite_pixel.cpp b/src/render/get_sprite_pixel.cpp index 99ed8b54f..8c55f3280 100644 --- a/src/render/get_sprite_pixel.cpp +++ b/src/render/get_sprite_pixel.cpp @@ -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::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); } diff --git a/src/render/get_sprite_pixel.h b/src/render/get_sprite_pixel.h index ae0b32d06..b8090ec9c 100644 --- a/src/render/get_sprite_pixel.h +++ b/src/render/get_sprite_pixel.h @@ -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 diff --git a/src/render/render.cpp b/src/render/render.cpp index e7748334d..1bba94613 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -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; diff --git a/src/render/render.h b/src/render/render.h index e70009378..7092b41f1 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -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(