瀏覽代碼

PixelPaint: Hold shift to constrain polygonal select tool line angle

Holding shift while using the polygonal select tool now constrains the
line angle in 22.5 degree increments. This matches the behavior of the
line tool.
Tim Ledbetter 2 年之前
父節點
當前提交
ecc202c59d

+ 3 - 18
Userland/Applications/PixelPaint/Tools/LineTool.cpp

@@ -22,19 +22,6 @@
 
 namespace PixelPaint {
 
-static Gfx::IntPoint constrain_line_angle(Gfx::IntPoint start_pos, Gfx::IntPoint end_pos, float angle_increment)
-{
-    float current_angle = AK::atan2<float>(end_pos.y() - start_pos.y(), end_pos.x() - start_pos.x()) + float { M_PI * 2 };
-
-    float constrained_angle = ((int)((current_angle + angle_increment / 2) / angle_increment)) * angle_increment;
-
-    auto diff = end_pos - start_pos;
-    float line_length = AK::hypot<float>(diff.x(), diff.y());
-
-    return { start_pos.x() + (int)(AK::cos(constrained_angle) * line_length),
-        start_pos.y() + (int)(AK::sin(constrained_angle) * line_length) };
-}
-
 void LineTool::on_mousedown(Layer* layer, MouseEvent& event)
 {
     if (!layer)
@@ -95,12 +82,10 @@ void LineTool::on_mousemove(Layer* layer, MouseEvent& event)
     if (m_drawing_button == GUI::MouseButton::None)
         return;
 
-    if (layer_event.shift()) {
-        constexpr auto ANGLE_STEP = M_PI / 8;
-        m_line_end_position = constrain_line_angle(m_drag_start_position, layer_event.position(), ANGLE_STEP);
-    } else {
+    if (layer_event.shift())
+        m_line_end_position = constrain_line_angle(m_drag_start_position, layer_event.position());
+    else
         m_line_end_position = layer_event.position();
-    }
 
     if (layer_event.alt()) {
         m_line_start_position = m_drag_start_position + (m_drag_start_position - m_line_end_position);

+ 9 - 1
Userland/Applications/PixelPaint/Tools/PolygonalSelectTool.cpp

@@ -92,6 +92,8 @@ void PolygonalSelectTool::on_mousedown(Layer*, MouseEvent& event)
     m_selecting = true;
 
     auto new_point = event.layer_event().position();
+    if (!m_polygon_points.is_empty() && event.layer_event().shift())
+        new_point = Tool::constrain_line_angle(m_polygon_points.last(), new_point);
 
     // This point matches the first point exactly. Consider this polygon finished.
     if (m_polygon_points.size() > 0 && new_point == m_polygon_points.at(0)) {
@@ -115,8 +117,14 @@ void PolygonalSelectTool::on_mousedown(Layer*, MouseEvent& event)
 
 void PolygonalSelectTool::on_mousemove(Layer*, MouseEvent& event)
 {
-    if (m_selecting)
+    if (!m_selecting)
+        return;
+
+    if (event.layer_event().shift())
+        m_last_selecting_cursor_position = Tool::constrain_line_angle(m_polygon_points.last(), event.layer_event().position());
+    else
         m_last_selecting_cursor_position = event.layer_event().position();
+
     m_editor->update();
 }
 

+ 13 - 0
Userland/Applications/PixelPaint/Tools/Tool.cpp

@@ -70,4 +70,17 @@ Gfx::IntPoint Tool::editor_stroke_position(Gfx::IntPoint pixel_coords, int strok
     return position.to_type<int>();
 }
 
+Gfx::IntPoint Tool::constrain_line_angle(Gfx::IntPoint start_pos, Gfx::IntPoint end_pos, float angle_increment)
+{
+    float current_angle = AK::atan2<float>(end_pos.y() - start_pos.y(), end_pos.x() - start_pos.x()) + float { M_PI * 2 };
+
+    float constrained_angle = ((int)((current_angle + angle_increment / 2) / angle_increment)) * angle_increment;
+
+    auto diff = end_pos - start_pos;
+    float line_length = AK::hypot<float>(diff.x(), diff.y());
+
+    return { start_pos.x() + (int)(AK::cos(constrained_angle) * line_length),
+        start_pos.y() + (int)(AK::sin(constrained_angle) * line_length) };
+}
+
 }

+ 2 - 0
Userland/Applications/PixelPaint/Tools/Tool.h

@@ -95,6 +95,8 @@ protected:
     void set_primary_slider(GUI::ValueSlider* primary) { m_primary_slider = primary; }
     void set_secondary_slider(GUI::ValueSlider* secondary) { m_secondary_slider = secondary; }
 
+    static Gfx::IntPoint constrain_line_angle(Gfx::IntPoint start_pos, Gfx::IntPoint end_pos, float angle_increment = M_PI / 8);
+
     GUI::ValueSlider* m_primary_slider { nullptr };
     GUI::ValueSlider* m_secondary_slider { nullptr };
 };