mirror of https://github.com/aseprite/aseprite.git
Snap cels to grid on moving cel action (fix #4027)
This commit is contained in:
parent
384813421c
commit
d6ddaa7a27
|
@ -17,6 +17,7 @@
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
#include "app/doc_api.h"
|
#include "app/doc_api.h"
|
||||||
#include "app/doc_range.h"
|
#include "app/doc_range.h"
|
||||||
|
#include "app/snap_to_grid.h"
|
||||||
#include "app/tx.h"
|
#include "app/tx.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/editor/editor_customization_delegate.h"
|
#include "app/ui/editor/editor_customization_delegate.h"
|
||||||
|
@ -104,11 +105,22 @@ MovingCelState::MovingCelState(Editor* editor,
|
||||||
m_celMainSize = gfx::SizeF(m_cel->bounds().size());
|
m_celMainSize = gfx::SizeF(m_cel->bounds().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assume all cels are on the same layer
|
||||||
|
m_multiLayer = false;
|
||||||
|
Layer* prevLayer = m_celList.back()->layer();
|
||||||
|
|
||||||
// Record start positions of all cels in selected range
|
// Record start positions of all cels in selected range
|
||||||
for (Cel* cel : m_celList) {
|
for (Cel* cel : m_celList) {
|
||||||
Layer* layer = cel->layer();
|
Layer* layer = cel->layer();
|
||||||
ASSERT(layer);
|
ASSERT(layer);
|
||||||
|
|
||||||
|
// If this inequality is ever true, then we have
|
||||||
|
// multiple layers selected
|
||||||
|
if (layer != prevLayer)
|
||||||
|
m_multiLayer = true;
|
||||||
|
|
||||||
|
prevLayer = layer;
|
||||||
|
|
||||||
if (layer && layer->isMovable() && !layer->isBackground()) {
|
if (layer && layer->isMovable() && !layer->isBackground()) {
|
||||||
if (layer->isReference()) {
|
if (layer->isReference()) {
|
||||||
m_celStarts.push_back(cel->boundsF());
|
m_celStarts.push_back(cel->boundsF());
|
||||||
|
@ -158,6 +170,8 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||||
gfx::Point intOffset = intCelOffset();
|
gfx::Point intOffset = intCelOffset();
|
||||||
|
|
||||||
// And now we move the cel (or all selected range) to the new position.
|
// And now we move the cel (or all selected range) to the new position.
|
||||||
|
bool snapToGrid = (Preferences::instance().selection.snapToGrid() &&
|
||||||
|
editor->docPref().grid.snap());
|
||||||
for (Cel* cel : m_celList) {
|
for (Cel* cel : m_celList) {
|
||||||
// Change reference layer with subpixel precision
|
// Change reference layer with subpixel precision
|
||||||
if (cel->layer()->isReference()) {
|
if (cel->layer()->isReference()) {
|
||||||
|
@ -168,12 +182,22 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||||
celBounds.w *= m_celScale.w;
|
celBounds.w *= m_celScale.w;
|
||||||
celBounds.h *= m_celScale.h;
|
celBounds.h *= m_celScale.h;
|
||||||
}
|
}
|
||||||
|
// Do not snap individual cel origins or scale when
|
||||||
|
// multiple layers are selected
|
||||||
|
if (snapToGrid && !m_multiLayer)
|
||||||
|
snapBoundsToGrid(celBounds);
|
||||||
|
|
||||||
tx(new cmd::SetCelBoundsF(cel, celBounds));
|
tx(new cmd::SetCelBoundsF(cel, celBounds));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
gfx::RectF celBounds = cel->boundsF();
|
||||||
|
celBounds.x += intOffset.x;
|
||||||
|
celBounds.y += intOffset.y;
|
||||||
|
if (snapToGrid && !m_multiLayer)
|
||||||
|
snapBoundsToGrid(celBounds);
|
||||||
|
|
||||||
api.setCelPosition(writer.sprite(), cel,
|
api.setCelPosition(writer.sprite(), cel,
|
||||||
cel->x() + intOffset.x,
|
celBounds.x, celBounds.y);
|
||||||
cel->y() + intOffset.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,10 +251,22 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||||
void MovingCelState::onCommitMouseMove(Editor* editor,
|
void MovingCelState::onCommitMouseMove(Editor* editor,
|
||||||
const gfx::PointF& newCursorPos)
|
const gfx::PointF& newCursorPos)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
bool snapToGrid = (Preferences::instance().selection.snapToGrid() &&
|
||||||
|
editor->docPref().grid.snap());
|
||||||
|
|
||||||
switch (m_handle) {
|
switch (m_handle) {
|
||||||
|
|
||||||
case MovePixelsHandle:
|
case MovePixelsHandle:
|
||||||
m_celOffset = newCursorPos - m_cursorStart;
|
m_celOffset = newCursorPos - m_cursorStart;
|
||||||
|
// Snap the delta itself to the grid, so that the cels
|
||||||
|
// are moved or scaled in fixed steps
|
||||||
|
if (snapToGrid)
|
||||||
|
m_celOffset = snap_to_grid(
|
||||||
|
editor->getSite().gridBounds(),
|
||||||
|
gfx::Point(m_celOffset),
|
||||||
|
PreferSnapTo::ClosestGridVertex);
|
||||||
|
|
||||||
if (int(editor->getCustomizationDelegate()
|
if (int(editor->getCustomizationDelegate()
|
||||||
->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::LockAxis)) {
|
->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::LockAxis)) {
|
||||||
if (ABS(m_celOffset.x) < ABS(m_celOffset.y)) {
|
if (ABS(m_celOffset.x) < ABS(m_celOffset.y)) {
|
||||||
|
@ -246,6 +282,12 @@ void MovingCelState::onCommitMouseMove(Editor* editor,
|
||||||
|
|
||||||
case ScaleSEHandle: {
|
case ScaleSEHandle: {
|
||||||
gfx::PointF delta(newCursorPos - m_cursorStart);
|
gfx::PointF delta(newCursorPos - m_cursorStart);
|
||||||
|
if (snapToGrid)
|
||||||
|
delta = snap_to_grid(
|
||||||
|
editor->getSite().gridBounds(),
|
||||||
|
gfx::Point(delta),
|
||||||
|
PreferSnapTo::ClosestGridVertex);
|
||||||
|
|
||||||
m_celScale.w = 1.0 + (delta.x / m_celMainSize.w);
|
m_celScale.w = 1.0 + (delta.x / m_celMainSize.w);
|
||||||
m_celScale.h = 1.0 + (delta.y / m_celMainSize.h);
|
m_celScale.h = 1.0 + (delta.y / m_celMainSize.h);
|
||||||
if (m_celScale.w < 1.0/m_celMainSize.w) m_celScale.w = 1.0/m_celMainSize.w;
|
if (m_celScale.w < 1.0/m_celMainSize.w) m_celScale.w = 1.0/m_celMainSize.w;
|
||||||
|
@ -275,11 +317,17 @@ void MovingCelState::onCommitMouseMove(Editor* editor,
|
||||||
celBounds.w *= m_celScale.w;
|
celBounds.w *= m_celScale.w;
|
||||||
celBounds.h *= m_celScale.h;
|
celBounds.h *= m_celScale.h;
|
||||||
}
|
}
|
||||||
|
if (snapToGrid && !m_multiLayer)
|
||||||
|
snapBoundsToGrid(celBounds);
|
||||||
|
|
||||||
cel->setBoundsF(celBounds);
|
cel->setBoundsF(celBounds);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
celBounds.x += intOffset.x;
|
celBounds.x += intOffset.x;
|
||||||
celBounds.y += intOffset.y;
|
celBounds.y += intOffset.y;
|
||||||
|
if (snapToGrid && !m_multiLayer)
|
||||||
|
snapBoundsToGrid(celBounds);
|
||||||
|
|
||||||
cel->setBounds(gfx::Rect(celBounds));
|
cel->setBounds(gfx::Rect(celBounds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,6 +415,29 @@ gfx::RectF MovingCelState::calcFullBounds() const
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MovingCelState::snapBoundsToGrid(gfx::RectF& celBounds) const
|
||||||
|
{
|
||||||
|
if (m_scaled) {
|
||||||
|
gfx::PointF gridOffset(
|
||||||
|
snap_to_grid(
|
||||||
|
m_editor->getSite().gridBounds(),
|
||||||
|
gfx::Point(celBounds.w, celBounds.h),
|
||||||
|
PreferSnapTo::ClosestGridVertex));
|
||||||
|
|
||||||
|
celBounds.w = gridOffset.x;
|
||||||
|
celBounds.h = gridOffset.y;
|
||||||
|
}
|
||||||
|
else if (m_moved) {
|
||||||
|
gfx::PointF gridOffset(
|
||||||
|
snap_to_grid(
|
||||||
|
m_editor->getSite().gridBounds(),
|
||||||
|
gfx::Point(celBounds.origin()),
|
||||||
|
PreferSnapTo::ClosestGridVertex));
|
||||||
|
|
||||||
|
celBounds.setOrigin(gridOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MovingCelState::restoreCelStartPosition() const
|
bool MovingCelState::restoreCelStartPosition() const
|
||||||
{
|
{
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace app {
|
||||||
gfx::Point intCelOffset() const;
|
gfx::Point intCelOffset() const;
|
||||||
gfx::RectF calcFullBounds() const;
|
gfx::RectF calcFullBounds() const;
|
||||||
bool restoreCelStartPosition() const;
|
bool restoreCelStartPosition() const;
|
||||||
|
void snapBoundsToGrid(gfx::RectF& celBounds) const;
|
||||||
// ContextObserver
|
// ContextObserver
|
||||||
void onBeforeCommandExecution(CommandExecutionEvent& ev);
|
void onBeforeCommandExecution(CommandExecutionEvent& ev);
|
||||||
|
|
||||||
|
@ -79,6 +80,7 @@ namespace app {
|
||||||
bool m_hasReference = false;
|
bool m_hasReference = false;
|
||||||
bool m_moved = false;
|
bool m_moved = false;
|
||||||
bool m_scaled = false;
|
bool m_scaled = false;
|
||||||
|
bool m_multiLayer = false;
|
||||||
HandleType m_handle;
|
HandleType m_handle;
|
||||||
Editor* m_editor;
|
Editor* m_editor;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue