static void gimp_warp_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); if (proximity) { gimp_draw_tool_pause (draw_tool); if (! tool->display || display == tool->display) { wt->cursor_x = coords->x; wt->cursor_y = coords->y; } if (! gimp_draw_tool_is_active (draw_tool)) gimp_draw_tool_start (draw_tool, display); gimp_draw_tool_resume (draw_tool); } else if (gimp_draw_tool_is_active (draw_tool)) { gimp_draw_tool_stop (draw_tool); } }
gboolean gimp_warp_tool_undo (GimpTool *tool, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); GeglNode *to_delete; GeglNode *previous; const gchar *type; if (! wt->render_node) return FALSE; to_delete = gegl_node_get_producer (wt->render_node, "aux", NULL); type = gegl_node_get_operation (to_delete); if (strcmp (type, "gegl:warp")) return FALSE; previous = gegl_node_get_producer (to_delete, "input", NULL); gegl_node_disconnect (to_delete, "input"); gegl_node_connect_to (previous, "output", wt->render_node, "aux"); wt->redo_stack = g_list_prepend (wt->redo_stack, g_object_ref (to_delete)); gegl_node_remove_child (wt->graph, to_delete); gimp_warp_tool_update_stroke (wt, to_delete); return TRUE; }
const gchar * gimp_warp_tool_get_redo_desc (GimpTool *tool, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); if (! wt->render_node || ! wt->redo_stack) return NULL; return _("Warp Tool Stroke"); }
void gimp_warp_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); gimp_draw_tool_pause (GIMP_DRAW_TOOL (wt)); gimp_tool_control_halt (tool->control); g_source_remove (wt->stroke_timer); wt->stroke_timer = 0; g_signal_handlers_disconnect_by_func (wt->current_stroke, gimp_warp_tool_stroke_changed, wt); #ifdef WARP_DEBUG g_printerr ("%s\n", gegl_path_to_string (wt->current_stroke)); #endif g_object_unref (wt->current_stroke); wt->current_stroke = NULL; if (release_type == GIMP_BUTTON_RELEASE_CANCEL) { gimp_warp_tool_undo (tool, display); /* the just undone stroke has no business on the redo stack */ g_object_unref (wt->redo_stack->data); wt->redo_stack = g_list_remove_link (wt->redo_stack, wt->redo_stack); } else { if (wt->redo_stack) { /* the redo stack becomes invalid by actually doing a stroke */ g_list_free_full (wt->redo_stack, (GDestroyNotify) g_object_unref); wt->redo_stack = NULL; } gimp_tool_push_status (tool, tool->display, _("Press ENTER to commit the transform")); } gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); /* update the undo actions / menu items */ gimp_image_flush (gimp_display_get_image (GIMP_TOOL (wt)->display)); }
static void gimp_warp_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GeglNode *new_op; gint off_x, off_y; if (tool->display && display != tool->display) { gimp_tool_pop_status (tool, tool->display); gimp_warp_tool_halt (wt); } if (! tool->display) { if (! gimp_warp_tool_start (wt, display)) return; } wt->current_stroke = gegl_path_new (); new_op = gegl_node_new_child (NULL, "operation", "gegl:warp", "behavior", options->behavior, "strength", options->effect_strength, "size", options->effect_size, "hardness", options->effect_hardness, "stroke", wt->current_stroke, NULL); gimp_warp_tool_add_op (wt, new_op); g_object_unref (new_op); g_signal_connect (wt->current_stroke, "changed", G_CALLBACK (gimp_warp_tool_stroke_changed), wt); gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y); gegl_path_append (wt->current_stroke, 'M', coords->x - off_x, coords->y - off_y); wt->stroke_timer = g_timeout_add (STROKE_PERIOD, (GSourceFunc) gimp_warp_tool_stroke_timer, wt); gimp_tool_control_activate (tool->control); }
static void gimp_warp_tool_draw (GimpDrawTool *draw_tool) { GimpWarpTool *wt = GIMP_WARP_TOOL (draw_tool); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); gimp_draw_tool_add_arc (draw_tool, FALSE, wt->cursor_x - options->effect_size * 0.5, wt->cursor_y - options->effect_size * 0.5, options->effect_size, options->effect_size, 0.0, 2.0 * G_PI); }
static void gimp_warp_tool_motion (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); wt->cursor_x = coords->x; wt->cursor_y = coords->y; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); }
const gchar * gimp_warp_tool_get_undo_desc (GimpTool *tool, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); GeglNode *to_delete; const gchar *type; if (! wt->render_node) return NULL; to_delete = gegl_node_get_producer (wt->render_node, "aux", NULL); type = gegl_node_get_operation (to_delete); if (strcmp (type, "gegl:warp")) return NULL; return _("Warp Tool Stroke"); }
static void gimp_warp_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); switch (action) { case GIMP_TOOL_ACTION_PAUSE: case GIMP_TOOL_ACTION_RESUME: break; case GIMP_TOOL_ACTION_HALT: gimp_warp_tool_halt (wt); break; } GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); }
gboolean gimp_warp_tool_redo (GimpTool *tool, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); GeglNode *to_add; if (! wt->render_node || ! wt->redo_stack) return FALSE; to_add = wt->redo_stack->data; gimp_warp_tool_add_op (wt, to_add); g_object_unref (to_add); wt->redo_stack = g_list_remove_link (wt->redo_stack, wt->redo_stack); gimp_warp_tool_update_stroke (wt, to_add); return TRUE; }
static gboolean gimp_warp_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpWarpTool *wt = GIMP_WARP_TOOL (tool); switch (kevent->keyval) { case GDK_KEY_BackSpace: return TRUE; case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: if (wt->image_map) { gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_map_commit (wt->image_map, GIMP_PROGRESS (tool)); g_object_unref (wt->image_map); wt->image_map = NULL; gimp_tool_control_pop_preserve (tool->control); gimp_image_flush (gimp_display_get_image (display)); } /* fall thru */ case GDK_KEY_Escape: gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; default: break; } return FALSE; }