mirror of https://github.com/aseprite/aseprite.git
Support resizing a reference cel with Move tool
This commit is contained in:
parent
6ce73a831a
commit
609946c33f
|
|
@ -33,10 +33,16 @@ namespace app {
|
|||
|
||||
using namespace ui;
|
||||
|
||||
MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
||||
MovingCelState::MovingCelState(Editor* editor,
|
||||
MouseMessage* msg,
|
||||
const HandleType handle)
|
||||
: m_reader(UIContext::instance(), 500)
|
||||
, m_celOffset(0.0, 0.0)
|
||||
, m_celScale(1.0, 1.0)
|
||||
, m_canceled(false)
|
||||
, m_hasReference(false)
|
||||
, m_scaled(false)
|
||||
, m_handle(handle)
|
||||
{
|
||||
ContextWriter writer(m_reader);
|
||||
Document* document = editor->document();
|
||||
|
|
@ -44,11 +50,14 @@ MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
|||
LayerImage* layer = static_cast<LayerImage*>(editor->layer());
|
||||
ASSERT(layer->isImage());
|
||||
|
||||
Cel* currentCel = layer->cel(editor->frame());
|
||||
ASSERT(currentCel); // The cel cannot be null
|
||||
m_cel = layer->cel(editor->frame());
|
||||
ASSERT(m_cel); // The cel cannot be null
|
||||
|
||||
if (!range.enabled())
|
||||
range = DocumentRange(currentCel);
|
||||
range = DocumentRange(m_cel);
|
||||
|
||||
if (m_cel)
|
||||
m_celMainSize = m_cel->boundsF().size();
|
||||
|
||||
// Record start positions of all cels in selected range
|
||||
for (Cel* cel : get_unique_cels(writer.sprite(), range)) {
|
||||
|
|
@ -68,7 +77,6 @@ MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
|||
}
|
||||
|
||||
m_cursorStart = editor->screenToEditorF(msg->position());
|
||||
m_celOffset = gfx::PointF(0, 0);
|
||||
editor->captureMouse();
|
||||
|
||||
// Hide the mask (temporarily, until mouse-up event)
|
||||
|
|
@ -85,7 +93,7 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
|||
|
||||
// Here we put back the cel into its original coordinate (so we can
|
||||
// add an undoer before).
|
||||
if ((m_hasReference && m_celOffset != gfx::PointF(0, 0)) ||
|
||||
if ((m_hasReference && (m_celOffset != gfx::PointF(0, 0) || m_scaled)) ||
|
||||
(!m_hasReference && gfx::Point(m_celOffset) != gfx::Point(0, 0))) {
|
||||
// Put the cels in the original position.
|
||||
for (size_t i=0; i<m_celList.size(); ++i) {
|
||||
|
|
@ -111,6 +119,10 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
|||
gfx::RectF celBounds = cel->boundsF();
|
||||
celBounds.x += m_celOffset.x;
|
||||
celBounds.y += m_celOffset.y;
|
||||
if (m_scaled) {
|
||||
celBounds.w *= m_celScale.w;
|
||||
celBounds.h *= m_celScale.h;
|
||||
}
|
||||
transaction.execute(new cmd::SetCelBoundsF(cel, celBounds));
|
||||
}
|
||||
else {
|
||||
|
|
@ -150,15 +162,35 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
|||
{
|
||||
gfx::PointF newCursorPos = editor->screenToEditorF(msg->position());
|
||||
|
||||
m_celOffset = newCursorPos - m_cursorStart;
|
||||
switch (m_handle) {
|
||||
|
||||
if (int(editor->getCustomizationDelegate()
|
||||
->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::LockAxis)) {
|
||||
if (ABS(m_celOffset.x) < ABS(m_celOffset.y)) {
|
||||
m_celOffset.x = 0;
|
||||
}
|
||||
else {
|
||||
m_celOffset.y = 0;
|
||||
case MoveHandle:
|
||||
m_celOffset = newCursorPos - m_cursorStart;
|
||||
if (int(editor->getCustomizationDelegate()
|
||||
->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::LockAxis)) {
|
||||
if (ABS(m_celOffset.x) < ABS(m_celOffset.y)) {
|
||||
m_celOffset.x = 0;
|
||||
}
|
||||
else {
|
||||
m_celOffset.y = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ScaleSEHandle: {
|
||||
gfx::PointF delta(newCursorPos - m_cursorStart);
|
||||
m_celScale.w = 1.0 + (delta.x / m_celMainSize.w);
|
||||
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.h < 1.0/m_celMainSize.h) m_celScale.h = 1.0/m_celMainSize.h;
|
||||
|
||||
if (int(editor->getCustomizationDelegate()
|
||||
->getPressedKeyAction(KeyContext::ScalingSelection) & KeyAction::MaintainAspectRatio)) {
|
||||
m_celScale.w = m_celScale.h = MAX(m_celScale.w, m_celScale.h);
|
||||
}
|
||||
|
||||
m_scaled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +200,11 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
|||
celBounds.x += m_celOffset.x;
|
||||
celBounds.y += m_celOffset.y;
|
||||
|
||||
if (m_scaled) {
|
||||
celBounds.w *= m_celScale.w;
|
||||
celBounds.h *= m_celScale.h;
|
||||
}
|
||||
|
||||
if (cel->layer()->isReference())
|
||||
cel->setBoundsF(celBounds);
|
||||
else
|
||||
|
|
@ -184,22 +221,29 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
|||
bool MovingCelState::onUpdateStatusBar(Editor* editor)
|
||||
{
|
||||
if (m_hasReference) {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %.2f %.2f :offset: %.2f %.2f",
|
||||
m_cursorStart.x,
|
||||
m_cursorStart.y,
|
||||
m_celOffset.x,
|
||||
m_celOffset.y);
|
||||
if (m_scaled && m_cel) {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %.2f %.2f :offset: %.2f %.2f :size: %.2f%% %.2f%%",
|
||||
m_cursorStart.x, m_cursorStart.y,
|
||||
m_celOffset.x, m_celOffset.y,
|
||||
100.0*m_celScale.w*m_celMainSize.w/m_cel->image()->width(),
|
||||
100.0*m_celScale.h*m_celMainSize.h/m_cel->image()->height());
|
||||
}
|
||||
else {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %.2f %.2f :offset: %.2f %.2f",
|
||||
m_cursorStart.x, m_cursorStart.y,
|
||||
m_celOffset.x, m_celOffset.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %3d %3d :offset: %3d %3d",
|
||||
int(m_cursorStart.x),
|
||||
int(m_cursorStart.y),
|
||||
int(m_celOffset.x),
|
||||
int(m_celOffset.y));
|
||||
int(m_cursorStart.x), int(m_cursorStart.y),
|
||||
int(m_celOffset.x), int(m_celOffset.y));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "app/ui/editor/standby_state.h"
|
||||
|
||||
#include "app/context_access.h"
|
||||
#include "app/ui/editor/handle_type.h"
|
||||
#include "doc/cel_list.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -24,7 +25,9 @@ namespace app {
|
|||
|
||||
class MovingCelState : public StandbyState {
|
||||
public:
|
||||
MovingCelState(Editor* editor, ui::MouseMessage* msg);
|
||||
MovingCelState(Editor* editor,
|
||||
ui::MouseMessage* msg,
|
||||
const HandleType handle);
|
||||
|
||||
virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
|
|
@ -34,13 +37,18 @@ namespace app {
|
|||
|
||||
private:
|
||||
ContextReader m_reader;
|
||||
Cel* m_cel;
|
||||
CelList m_celList;
|
||||
std::vector<gfx::RectF> m_celStarts;
|
||||
gfx::PointF m_cursorStart;
|
||||
gfx::PointF m_celOffset;
|
||||
gfx::SizeF m_celMainSize;
|
||||
gfx::SizeF m_celScale;
|
||||
bool m_canceled;
|
||||
bool m_maskVisible;
|
||||
bool m_hasReference;
|
||||
bool m_scaled;
|
||||
HandleType m_handle;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
|
|
|||
|
|
@ -117,7 +117,9 @@ void StandbyState::onActiveToolChange(Editor* editor, tools::Tool* tool)
|
|||
// If the user change from a selection tool to a non-selection tool,
|
||||
// or viceversa, we've to show or hide the transformation handles.
|
||||
bool needDecorators = (tool && tool->getInk(0)->isSelection());
|
||||
if (m_transformSelectionHandlesAreVisible != needDecorators) {
|
||||
if (m_transformSelectionHandlesAreVisible != needDecorators ||
|
||||
!editor->layer() ||
|
||||
!editor->layer()->isReference()) {
|
||||
m_transformSelectionHandlesAreVisible = false;
|
||||
editor->invalidate();
|
||||
}
|
||||
|
|
@ -222,7 +224,11 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
|||
}
|
||||
else {
|
||||
// Change to MovingCelState
|
||||
editor->setState(EditorStatePtr(new MovingCelState(editor, msg)));
|
||||
HandleType handle = MoveHandle;
|
||||
if (resizeCelBounds(editor).contains(msg->position()))
|
||||
handle = ScaleSEHandle;
|
||||
|
||||
editor->setState(EditorStatePtr(new MovingCelState(editor, msg, handle)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -418,7 +424,10 @@ bool StandbyState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
|
|||
return true;
|
||||
}
|
||||
else if (ink->isCelMovement()) {
|
||||
editor->showMouseCursor(kMoveCursor);
|
||||
if (resizeCelBounds(editor).contains(mouseScreenPos))
|
||||
editor->showMouseCursor(kSizeSECursor);
|
||||
else
|
||||
editor->showMouseCursor(kMoveCursor);
|
||||
return true;
|
||||
}
|
||||
else if (ink->isSlice()) {
|
||||
|
|
@ -603,6 +612,22 @@ void StandbyState::onPivotChange(Editor* editor)
|
|||
}
|
||||
}
|
||||
|
||||
gfx::Rect StandbyState::resizeCelBounds(Editor* editor) const
|
||||
{
|
||||
gfx::Rect bounds;
|
||||
Cel* refCel = (editor->layer() &&
|
||||
editor->layer()->isReference() ?
|
||||
editor->layer()->cel(editor->frame()): nullptr);
|
||||
if (refCel) {
|
||||
bounds = editor->editorToScreen(refCel->boundsF());
|
||||
bounds.w /= 4;
|
||||
bounds.h /= 4;
|
||||
bounds.x += 3*bounds.w;
|
||||
bounds.y += 3*bounds.h;
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Decorator
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ namespace app {
|
|||
private:
|
||||
void transformSelection(Editor* editor, ui::MouseMessage* msg, HandleType handle);
|
||||
void onPivotChange(Editor* editor);
|
||||
gfx::Rect resizeCelBounds(Editor* editor) const;
|
||||
|
||||
Decorator* m_decorator;
|
||||
obs::scoped_connection m_pivotVisConn;
|
||||
|
|
|
|||
Loading…
Reference in New Issue