Add angle snap with Shift key to rotation.

This commit is contained in:
David Capello 2012-01-07 16:37:07 -03:00
parent 9684672f5f
commit a17d925847
8 changed files with 94 additions and 3 deletions

View File

@ -165,6 +165,14 @@
<!-- When you drag-and-drop the selection, pressing this
keyboard shortcut you can copy instead of move -->
<key action="CopySelection" shortcut="Ctrl" />
<!-- When you move the selection, pressing this
keyboard shortcut you can snap to grid -->
<key action="SnapToGrid" shortcut="Shift" />
<!-- When you rotate the selection, pressing this
keyboard shortcut you activate angle snap -->
<key action="AngleSnap" shortcut="Shift" />
</spriteeditor>
</keyboard>

View File

@ -128,6 +128,22 @@ public:
return false;
}
bool isSnapToGridKeyPressed() OVERRIDE {
JAccel accel = get_accel_to_snap_to_grid();
if (accel)
return jaccel_check_from_key(accel);
else
return false;
}
bool isAngleSnapKeyPressed() OVERRIDE {
JAccel accel = get_accel_to_angle_snap();
if (accel)
return jaccel_check_from_key(accel);
else
return false;
}
};
class MiniEditor : public Editor

View File

@ -65,6 +65,8 @@
#define MONITOR_TIMER_MSECS 100
#define SPRITEDITOR_ACTION_COPYSELECTION "CopySelection"
#define SPRITEDITOR_ACTION_SNAPTOGRID "SnapToGrid"
#define SPRITEDITOR_ACTION_ANGLESNAP "AngleSnap"
//////////////////////////////////////////////////////////////////////
@ -939,6 +941,24 @@ JAccel get_accel_to_copy_selection()
return NULL;
}
JAccel get_accel_to_snap_to_grid()
{
Shortcut* shortcut = get_keyboard_shortcut_for_spriteeditor(SPRITEDITOR_ACTION_SNAPTOGRID);
if (shortcut)
return shortcut->accel;
else
return NULL;
}
JAccel get_accel_to_angle_snap()
{
Shortcut* shortcut = get_keyboard_shortcut_for_spriteeditor(SPRITEDITOR_ACTION_ANGLESNAP);
if (shortcut)
return shortcut->accel;
else
return NULL;
}
tools::Tool* get_selected_quicktool(tools::Tool* currentTool)
{
if (currentTool && currentTool->getInk(0)->isSelection()) {

View File

@ -116,6 +116,8 @@ Command* get_command_from_key_message(Message* msg);
JAccel get_accel_to_execute_command(const char* command, Params* params = NULL);
JAccel get_accel_to_change_tool(tools::Tool* tool);
JAccel get_accel_to_copy_selection();
JAccel get_accel_to_snap_to_grid();
JAccel get_accel_to_angle_snap();
tools::Tool* get_selected_quicktool(tools::Tool* currentTool);

View File

@ -39,6 +39,14 @@ public:
// Returns true if the user wants to copy the selection instead of
// to move it.
virtual bool isCopySelectionKeyPressed() = 0;
// Returns true if the user wants to snap to grid when he's moving
// the selection.
virtual bool isSnapToGridKeyPressed() = 0;
// Returns true if the user wants to activate angle snap, so he can
// easily specify common angles (45, 90, 135, 180, etc.).
virtual bool isAngleSnapKeyPressed() = 0;
};
#endif // WIDGETS_EDITOR_CUSTOMIZATION_DELEGATE_H_INCLUDED

View File

@ -187,8 +187,13 @@ bool MovingPixelsState::onMouseMove(Editor* editor, Message* msg)
int x, y;
editor->screenToEditor(msg->mouse.x, msg->mouse.y, &x, &y);
PixelsMovement::MoveModifier moveModifier = PixelsMovement::NormalMovement;
if (editor->getCustomizationDelegate()->isAngleSnapKeyPressed())
moveModifier = PixelsMovement::AngleSnapMovement;
// Drag the image to that position
gfx::Rect bounds = m_pixelsMovement->moveImage(x, y);
gfx::Rect bounds = m_pixelsMovement->moveImage(x, y, moveModifier);
// If "bounds" is empty is because the cel was not moved
if (!bounds.isEmpty()) {

View File

@ -148,7 +148,7 @@ void PixelsMovement::maskImage(const Image* image, int x, int y)
update_screen_for_document(m_documentReader);
}
gfx::Rect PixelsMovement::moveImage(int x, int y)
gfx::Rect PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier)
{
DocumentWriter documentWriter(m_documentReader);
Image* image = documentWriter->getExtraCelImage();
@ -241,6 +241,32 @@ gfx::Rect PixelsMovement::moveImage(int x, int y)
- atan2((double)(-m_catchY + abs_initial_pivot.y),
(double)(+m_catchX - abs_initial_pivot.x));
// Put the angle in -180 to 180 range.
while (newAngle < -PI) newAngle += 2*PI;
while (newAngle > PI) newAngle -= 2*PI;
// Is the "angle snap" is activated, we've to snap the angle
// to common (pixel art) angles.
if ((moveModifier & AngleSnapMovement) == AngleSnapMovement) {
// TODO make this configurable
static const double keyAngles[] = {
0.0, 26.565, 45.0, 63.435, 90.0, 116.565, 135.0, 153.435, -180.0,
180.0, -153.435, -135.0, -116, -90.0, -63.435, -45.0, -26.565
};
double newAngleDegrees = 180.0 * newAngle / PI;
int closest = 0;
int last = sizeof(keyAngles) / sizeof(keyAngles[0]) - 1;
for (int i=0; i<=last; ++i) {
if (std::fabs(newAngleDegrees-keyAngles[closest]) >
std::fabs(newAngleDegrees-keyAngles[i]))
closest = i;
}
newAngle = PI * keyAngles[closest] / 180.0;
}
m_currentData.angle(newAngle);
}
break;

View File

@ -36,6 +36,12 @@ class Sprite;
class PixelsMovement
{
public:
enum MoveModifier {
NormalMovement = 1,
SnapToGridMovement = 2,
AngleSnapMovement = 4
};
// The "moveThis" image specifies the chunk of pixels to be moved.
// The "x" and "y" parameters specify the initial position of the image.
PixelsMovement(Document* document, Sprite* sprite, const Image* moveThis, int x, int y, int opacity,
@ -54,7 +60,7 @@ public:
// Moves the image to the new position (relative to the start
// position given in the ctor). Returns the rectangle that should be
// redrawn.
gfx::Rect moveImage(int x, int y);
gfx::Rect moveImage(int x, int y, MoveModifier moveModifier);
void dropImageTemporarily();
void dropImage();