Snap cels to grid on moving cel action (fix #4027)

This commit is contained in:
Liebranca 2024-09-09 05:03:54 -03:00 committed by David Capello
parent 384813421c
commit d6ddaa7a27
2 changed files with 75 additions and 2 deletions

View File

@ -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;

View File

@ -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;