Cage tool: allow to add handle by clicking on an edge

This commit is contained in:
Michael Muré 2011-05-03 00:45:39 +02:00
parent cc247b3e66
commit 989b85988b
3 changed files with 113 additions and 20 deletions

3
NEWS
View file

@ -13,7 +13,8 @@ Changes in GIMP 2.7.3
UI:
- foo
- Cage tool: allow to add handle to the cage when clicking on an edge
- Cage tool: allow to remove selected handles from the cage by hitting delete
Core:

View file

@ -118,6 +118,10 @@ static gint gimp_cage_tool_is_on_handle (GimpCageTool *ct,
gdouble x,
gdouble y,
gint handle_size);
static gint gimp_cage_tool_is_on_edge (GimpCageTool *ct,
gdouble x,
gdouble y,
gint handle_size);
static void gimp_cage_tool_remove_last_handle (GimpCageTool *ct);
static void gimp_cage_tool_compute_coef (GimpCageTool *ct,
@ -300,6 +304,7 @@ gimp_cage_tool_start (GimpCageTool *ct,
ct->config = g_object_new (GIMP_TYPE_CAGE_CONFIG, NULL);
ct->hovering_handle = -1;
ct->hovering_edge = -1;
ct->cage_complete = FALSE;
ct->tool_state = CAGE_STATE_INIT;
@ -486,19 +491,24 @@ gimp_cage_tool_oper_update (GimpTool *tool,
{
GimpCageTool *ct = GIMP_CAGE_TOOL (tool);
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
gint handle = -1;
if (ct->config)
handle = gimp_cage_tool_is_on_handle (ct,
draw_tool,
display,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
{
ct->hovering_handle = gimp_cage_tool_is_on_handle (ct,
draw_tool,
display,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
ct->hovering_edge = gimp_cage_tool_is_on_edge (ct,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
}
gimp_draw_tool_pause (draw_tool);
ct->hovering_handle = handle;
ct->cursor_x = coords->x;
ct->cursor_y = coords->y;
@ -516,6 +526,7 @@ gimp_cage_tool_button_press (GimpTool *tool,
GimpCageTool *ct = GIMP_CAGE_TOOL (tool);
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
gint handle = -1;
gint edge = -1;
if (display != tool->display)
gimp_cage_tool_start (ct, display);
@ -523,12 +534,19 @@ gimp_cage_tool_button_press (GimpTool *tool,
gimp_tool_control_activate (tool->control);
if (ct->config)
handle = gimp_cage_tool_is_on_handle (ct,
draw_tool,
display,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
{
handle = gimp_cage_tool_is_on_handle (ct,
draw_tool,
display,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
edge = gimp_cage_tool_is_on_edge (ct,
coords->x,
coords->y,
GIMP_TOOL_HANDLE_SIZE_CIRCLE);
}
ct->movement_start_x = coords->x;
ct->movement_start_y = coords->y;
@ -548,7 +566,7 @@ gimp_cage_tool_button_press (GimpTool *tool,
case CAGE_STATE_WAIT:
if (ct->cage_complete == FALSE)
{
if (handle == -1)
if (handle == -1 && edge == -1)
{
/* User clicked on the background, we add a new handle
* and move it
@ -569,7 +587,7 @@ gimp_cage_tool_button_press (GimpTool *tool,
gimp_cage_config_select_point (ct->config, 0);
ct->tool_state = CAGE_STATE_CLOSING;
}
else if (handle > 0)
else if (handle >= 0)
{
/* User clicked on a handle, so we move it */
@ -591,12 +609,20 @@ gimp_cage_tool_button_press (GimpTool *tool,
ct->tool_state = CAGE_STATE_MOVE_HANDLE;
}
else if (edge >= 0)
{
/* User clicked on an edge, we add a new handle here and select it */
gimp_cage_config_insert_cage_point (ct->config, edge, coords->x, coords->y);
gimp_cage_config_select_point (ct->config, edge);
ct->tool_state = CAGE_STATE_MOVE_HANDLE;
}
}
else
{
/* Cage already closed */
if (handle == -1)
if (handle == -1 && edge == -1)
{
/* User clicked on the background, we start a rubber
* band selection
@ -605,8 +631,7 @@ gimp_cage_tool_button_press (GimpTool *tool,
ct->selection_start_y = coords->y;
ct->tool_state = CAGE_STATE_SELECTING;
}
if (handle >= 0)
else if (handle >= 0)
{
/* User clicked on a handle, so we move it */
@ -628,6 +653,14 @@ gimp_cage_tool_button_press (GimpTool *tool,
ct->tool_state = CAGE_STATE_MOVE_HANDLE;
}
else if (edge >= 0)
{
/* User clicked on an edge, we add a new handle here and select it */
gimp_cage_config_insert_cage_point (ct->config, edge, coords->x, coords->y);
gimp_cage_config_select_point (ct->config, edge);
ct->tool_state = CAGE_STATE_MOVE_HANDLE;
}
}
break;
@ -798,6 +831,7 @@ gimp_cage_tool_cursor_update (GimpTool *tool,
GimpDisplay *display)
{
GimpCageTool *ct = GIMP_CAGE_TOOL (tool);
GimpCageOptions *options = GIMP_CAGE_TOOL_GET_OPTIONS (ct);
GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_PLUS;
if (tool->display)
@ -806,6 +840,10 @@ gimp_cage_tool_cursor_update (GimpTool *tool,
{
modifier = GIMP_CURSOR_MODIFIER_MOVE;
}
else if (ct->hovering_edge != -1 && options->cage_mode == GIMP_CAGE_MODE_CAGE_CHANGE)
{
modifier = GIMP_CURSOR_MODIFIER_PLUS;
}
else
{
if (ct->cage_complete)
@ -976,6 +1014,59 @@ gimp_cage_tool_is_on_handle (GimpCageTool *ct,
return -1;
}
static gint
gimp_cage_tool_is_on_edge (GimpCageTool *ct,
gdouble x,
gdouble y,
gint handle_size)
{
GimpCageOptions *options = GIMP_CAGE_TOOL_GET_OPTIONS (ct);
GimpCageConfig *config = ct->config;
gint i;
guint n_cage_vertices;
GimpVector2 A, B, C, AB, BC, AC;
gdouble lAB, lBC, lAC, lEB, lEC;
g_return_val_if_fail (GIMP_IS_CAGE_TOOL (ct), -1);
n_cage_vertices = gimp_cage_config_get_n_points (config);
if (n_cage_vertices < 2)
return -1;
A = gimp_cage_config_get_point_coordinate (config,
options->cage_mode,
n_cage_vertices-1);
B = gimp_cage_config_get_point_coordinate (config,
options->cage_mode,
0);
C.x = x;
C.y = y;
for (i = 0; i < n_cage_vertices; i++)
{
gimp_vector2_sub (&AB, &A, &B);
gimp_vector2_sub (&BC, &B, &C);
gimp_vector2_sub (&AC, &A, &C);
lAB = gimp_vector2_length (&AB);
lBC = gimp_vector2_length (&BC);
lAC = gimp_vector2_length (&AC);
lEB = lAB / 2 + (SQR (lBC) - SQR (lAC)) / (2 * lAB);
lEC = sqrt (SQR (lBC) - SQR (lEB));
if ((lEC < handle_size / 2) && (abs (SQR (lBC) - SQR (lAC)) <= SQR (lAB)))
return i;
A = B;
B = gimp_cage_config_get_point_coordinate (config,
options->cage_mode,
(i+1) % n_cage_vertices);
}
return -1;
}
static void
gimp_cage_tool_remove_last_handle (GimpCageTool *ct)
{

View file

@ -56,6 +56,7 @@ struct _GimpCageTool
gdouble selection_start_y; /* Where the selection started */
gint hovering_handle; /* Handle which the cursor is above */
gint hovering_edge; /* Edge which the cursor is above */
gboolean cage_complete; /* Cage closed or not */
GeglBuffer *coef; /* Gegl where the coefficient of the transformation are stored */