From 3103f541313da939c1637b86f9277532154dbfd6 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 4 Aug 2015 12:26:58 -0300 Subject: [PATCH] Change zoom scale to avoid similar zoom levels - Renamed Editor::offset() with padding() - Changed padding size (and added Editor::calcExtraPadding() function) - Added Zoom::linearScale() and Zoom::fromLinearScale() --- src/app/commands/cmd_fullscreen_preview.cpp | 4 +- src/app/ui/editor/editor.cpp | 74 +++++++++++-------- src/app/ui/editor/editor.h | 13 ++-- src/app/ui/editor/zooming_state.cpp | 24 +++--- src/render/zoom.cpp | 81 +++++++++++++++++---- src/render/zoom.h | 9 ++- 6 files changed, 138 insertions(+), 67 deletions(-) diff --git a/src/app/commands/cmd_fullscreen_preview.cpp b/src/app/commands/cmd_fullscreen_preview.cpp index 96721d4e6..f3f1482f7 100644 --- a/src/app/commands/cmd_fullscreen_preview.cpp +++ b/src/app/commands/cmd_fullscreen_preview.cpp @@ -72,8 +72,8 @@ public: gfx::Point scroll = view->getViewScroll(); m_oldMousePos = ui::get_mouse_position(); - m_pos.x = -scroll.x + vp.x + editor->offsetX(); - m_pos.y = -scroll.y + vp.y + editor->offsetY(); + m_pos.x = -scroll.x + vp.x + editor->padding().x; + m_pos.y = -scroll.y + vp.y + editor->padding().y; setFocusStop(true); captureMouse(); diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 665eae8ca..43e6e47de 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -153,8 +153,7 @@ Editor::Editor(Document* document, EditorFlags flags) , m_brushPreview(this) , m_quicktool(NULL) , m_selectionMode(tools::SelectionMode::DEFAULT) - , m_offset_x(0) - , m_offset_y(0) + , m_padding(0, 0) , m_mask_timer(100, this) , m_offset_count(0) , m_customizationDelegate(NULL) @@ -346,8 +345,8 @@ void Editor::setDefaultScroll() setEditorScroll( gfx::Point( - m_offset_x - vp.w/2 + (m_sprite->width()/2), - m_offset_y - vp.h/2 + (m_sprite->height()/2)), false); + m_padding.x - vp.w/2 + m_zoom.apply(m_sprite->width())/2, + m_padding.y - vp.h/2 + m_zoom.apply(m_sprite->height())/2), false); } // Sets the scroll position of the editor @@ -390,8 +389,8 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite gfx::Rect rc = m_sprite->bounds().createIntersection(spriteRectToDraw); rc = m_zoom.apply(rc); - int dest_x = dx + m_offset_x + rc.x; - int dest_y = dy + m_offset_y + rc.y; + int dest_x = dx + m_padding.x + rc.x; + int dest_y = dy + m_padding.y + rc.y; // Clip from graphics/screen const gfx::Rect& clip = g->getClipBounds(); @@ -536,8 +535,8 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc) gfx::Rect client = getClientBounds(); gfx::Rect spriteRect( - client.x + m_offset_x, - client.y + m_offset_y, + client.x + m_padding.x, + client.y + m_padding.y, m_zoom.apply(m_sprite->width()), m_zoom.apply(m_sprite->height())); gfx::Rect enclosingRect = spriteRect; @@ -680,8 +679,8 @@ void Editor::drawMask(Graphics* g) ASSERT(m_document->getMaskBoundaries()); - int x = m_offset_x; - int y = m_offset_y; + int x = m_padding.x; + int y = m_padding.y; for (const auto& seg : *m_document->getMaskBoundaries()) { CheckedDrawMode checked(g, m_offset_count); @@ -954,8 +953,8 @@ gfx::Point Editor::screenToEditor(const gfx::Point& pt) Point scroll = view->getViewScroll(); return gfx::Point( - m_zoom.remove(pt.x - vp.x + scroll.x - m_offset_x), - m_zoom.remove(pt.y - vp.y + scroll.y - m_offset_y)); + m_zoom.remove(pt.x - vp.x + scroll.x - m_padding.x), + m_zoom.remove(pt.y - vp.y + scroll.y - m_padding.y)); } Point Editor::editorToScreen(const gfx::Point& pt) @@ -965,8 +964,8 @@ Point Editor::editorToScreen(const gfx::Point& pt) Point scroll = view->getViewScroll(); return Point( - (vp.x - scroll.x + m_offset_x + m_zoom.apply(pt.x)), - (vp.y - scroll.y + m_offset_y + m_zoom.apply(pt.y))); + (vp.x - scroll.x + m_padding.x + m_zoom.apply(pt.x)), + (vp.y - scroll.y + m_padding.y + m_zoom.apply(pt.y))); } Rect Editor::screenToEditor(const Rect& rc) @@ -1022,8 +1021,8 @@ void Editor::centerInSpritePoint(const gfx::Point& spritePos) Rect vp = view->getViewportBounds(); gfx::Point scroll( - m_offset_x - (vp.w/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.x), - m_offset_y - (vp.h/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.y)); + m_padding.x - (vp.w/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.x), + m_padding.y - (vp.h/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.y)); updateEditor(); setEditorScroll(scroll, false); @@ -1263,13 +1262,9 @@ void Editor::onPreferredSize(PreferredSizeEvent& ev) gfx::Size sz(0, 0); if (m_sprite) { - View* view = View::getView(this); - Rect vp = view->getViewportBounds(); - int offset_x = std::max(vp.w/2, vp.w - m_sprite->width()/2); - int offset_y = std::max(vp.h/2, vp.h - m_sprite->height()/2); - - sz.w = m_zoom.apply(m_sprite->width()) + offset_x*2; - sz.h = m_zoom.apply(m_sprite->height()) + offset_y*2; + gfx::Point padding = calcExtraPadding(m_zoom); + sz.w = m_zoom.apply(m_sprite->width()) + padding.x*2; + sz.h = m_zoom.apply(m_sprite->height()) + padding.y*2; } else { sz.w = 4; @@ -1281,13 +1276,7 @@ void Editor::onPreferredSize(PreferredSizeEvent& ev) void Editor::onResize(ui::ResizeEvent& ev) { Widget::onResize(ev); - - View* view = View::getView(this); - if (view) { - Rect vp = view->getViewportBounds(); - m_offset_x = std::max(vp.w/2, vp.w - m_sprite->width()/2); - m_offset_y = std::max(vp.h/2, vp.h - m_sprite->height()/2); - } + m_padding = calcExtraPadding(m_zoom); } void Editor::onPaint(ui::PaintEvent& ev) @@ -1412,13 +1401,20 @@ void Editor::setZoomAndCenterInMouse(Zoom zoom, subpixelPos.x = (0.5 + screenPos.x - screenPos2.x) / m_zoom.scale(); subpixelPos.y = (0.5 + screenPos.y - screenPos2.y) / m_zoom.scale(); + if (zoom.scale() > m_zoom.scale()) { + double t = 1.0 / zoom.scale(); + if (subpixelPos.x >= 0.5-t && subpixelPos.x <= 0.5+t) subpixelPos.x = 0.5; + if (subpixelPos.y >= 0.5-t && subpixelPos.y <= 0.5+t) subpixelPos.y = 0.5; + } + ASSERT(subpixelPos.x >= -1.0 && subpixelPos.x <= 1.0); ASSERT(subpixelPos.y >= -1.0 && subpixelPos.y <= 1.0); } + gfx::Point padding = calcExtraPadding(zoom); gfx::Point scrollPos( - m_offset_x - (screenPos.x-vp.x) + zoom.apply(spritePos.x+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.x)), - m_offset_y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y))); + padding.x - (screenPos.x-vp.x) + zoom.apply(spritePos.x+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.x)), + padding.y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y))); if ((m_zoom != zoom) || (screenPos != view->getViewScroll())) { bool blitValidRegion = (m_zoom == zoom); @@ -1574,4 +1570,18 @@ ImageBufferPtr Editor::getRenderImageBuffer() return m_renderBuffer; } +// static +gfx::Point Editor::calcExtraPadding(const Zoom& zoom) +{ + View* view = View::getView(this); + if (view) { + Rect vp = view->getViewportBounds(); + return gfx::Point( + std::max(vp.w/2, vp.w - zoom.apply(m_sprite->width())), + std::max(vp.h/2, vp.h - zoom.apply(m_sprite->height()))); + } + else + return gfx::Point(0, 0); +} + } // namespace app diff --git a/src/app/ui/editor/editor.h b/src/app/ui/editor/editor.h index 89d87848b..1f925a10e 100644 --- a/src/app/ui/editor/editor.h +++ b/src/app/ui/editor/editor.h @@ -116,13 +116,9 @@ namespace app { void setFrame(frame_t frame); const render::Zoom& zoom() const { return m_zoom; } - int offsetX() const { return m_offset_x; } - int offsetY() const { return m_offset_y; } + const gfx::Point& padding() const { return m_padding; } void setZoom(render::Zoom zoom) { m_zoom = zoom; } - void setOffsetX(int x) { m_offset_x = x; } - void setOffsetY(int y) { m_offset_y = y; } - void setDefaultScroll(); void setEditorScroll(const gfx::Point& scroll, bool blitValidRegion); void setEditorZoom(render::Zoom zoom); @@ -238,6 +234,8 @@ namespace app { // routine. void drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, int dx, int dy); + gfx::Point calcExtraPadding(const render::Zoom& zoom); + // Stack of states. The top element in the stack is the current state (m_state). EditorStatesHistory m_statesHistory; @@ -264,9 +262,8 @@ namespace app { tools::SelectionMode m_selectionMode; bool m_autoSelectLayer; - // Offset for the sprite - int m_offset_x; - int m_offset_y; + // Extra space around the sprite. + gfx::Point m_padding; // Marching ants stuff ui::Timer m_mask_timer; diff --git a/src/app/ui/editor/zooming_state.cpp b/src/app/ui/editor/zooming_state.cpp index 1a09852c3..db352bdfb 100644 --- a/src/app/ui/editor/zooming_state.cpp +++ b/src/app/ui/editor/zooming_state.cpp @@ -14,12 +14,17 @@ #include "app/app.h" #include "app/ui/editor/editor.h" #include "app/ui/status_bar.h" -#include "gfx/rect.h" #include "doc/sprite.h" +#include "gfx/rect.h" +#include "she/display.h" +#include "ui/manager.h" #include "ui/message.h" #include "ui/system.h" +#include "ui/theme.h" #include "ui/view.h" +#include + namespace app { using namespace ui; @@ -65,16 +70,17 @@ bool ZoomingState::onMouseUp(Editor* editor, MouseMessage* msg) bool ZoomingState::onMouseMove(Editor* editor, MouseMessage* msg) { gfx::Point pt = (msg->position() - m_startPos); - render::Zoom zoom(1, 1); - double scale = m_startZoom.scale() + pt.x / 16.0; - if (scale < 1.0) - scale = 1.0 / -(scale-2.0); - zoom = render::Zoom::fromScale(scale); + int threshold = 8 * guiscale() * editor->getManager()->getDisplay()->scale(); - editor->setZoomAndCenterInMouse( - zoom, m_startPos, Editor::ZoomBehavior::MOUSE); + if (m_moved || std::sqrt(pt.x*pt.x + pt.y*pt.y) > threshold) { + m_moved = true; - m_moved = true; + int newScale = m_startZoom.linearScale() + pt.x / threshold; + render::Zoom newZoom = render::Zoom::fromLinearScale(newScale); + + editor->setZoomAndCenterInMouse( + newZoom, m_startPos, Editor::ZoomBehavior::MOUSE); + } return true; } diff --git a/src/render/zoom.cpp b/src/render/zoom.cpp index 2e0b40461..0e3f8e040 100644 --- a/src/render/zoom.cpp +++ b/src/render/zoom.cpp @@ -1,5 +1,5 @@ // Aseprite Render Library -// Copyright (c) 2001-2014 David Capello +// Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -12,35 +12,86 @@ namespace render { +static int scales[][2] = { + { 1, 64 }, + { 1, 32 }, + { 1, 16 }, + { 1, 8 }, + { 1, 6 }, + { 1, 4 }, + { 1, 3 }, + { 1, 2 }, + { 1, 1 }, // 100% + { 2, 1 }, + { 3, 1 }, + { 4, 1 }, + { 6, 1 }, + { 8, 1 }, + { 16, 1 }, + { 32, 1 }, + { 64, 1 }, +}; + +static int scales_size = sizeof(scales) / sizeof(scales[0]); + void Zoom::in() { - if (m_den > 1) { - m_den--; - } - else if (m_num < 64) { - m_num++; + int i = linearScale(); + if (i < scales_size-1) { + ++i; + m_num = scales[i][0]; + m_den = scales[i][1]; } } void Zoom::out() { - if (m_num > 1) { - m_num--; + int i = linearScale(); + if (i > 0) { + --i; + m_num = scales[i][0]; + m_den = scales[i][1]; } - else if (m_den < 32) { - m_den++; +} + +int Zoom::linearScale() +{ + for (int i=0; i= 1.0) { - return Zoom(int(scale), 1); - } - else { - return Zoom(1, int(1.0 / scale)); + return fromLinearScale(findClosestLinearScale(scale)); +} + +// static +Zoom Zoom::fromLinearScale(int i) +{ + i = MID(0, i, scales_size-1); + return Zoom(scales[i][0], scales[i][1]); +} + +// static +int Zoom::findClosestLinearScale(double scale) +{ + for (int i=0; i= min && scale <= max) + return i; } + if (scale < 1.0) + return 0; + else + return scales_size-1; } } // namespace render diff --git a/src/render/zoom.h b/src/render/zoom.h index ee77327a2..b64681d22 100644 --- a/src/render/zoom.h +++ b/src/render/zoom.h @@ -1,5 +1,5 @@ // Aseprite Render Library -// Copyright (c) 2001-2014 David Capello +// Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -44,6 +44,10 @@ namespace render { void in(); void out(); + // Returns an linear zoom scale. This position can be incremented + // or decremented to get a new zoom value. + int linearScale(); + bool operator==(const Zoom& other) const { return m_num == other.m_num && m_den == other.m_den; } @@ -53,8 +57,11 @@ namespace render { } static Zoom fromScale(double scale); + static Zoom fromLinearScale(int i); private: + static int findClosestLinearScale(double scale); + int m_num; int m_den; };