diff --git a/app/actions/tools-actions.c b/app/actions/tools-actions.c index b78681c16d..54baea36bc 100644 --- a/app/actions/tools-actions.c +++ b/app/actions/tools-actions.c @@ -224,6 +224,13 @@ static const GimpEnumActionEntry tools_mybrush_radius_actions[] = NULL } }; +static const GimpDoubleActionEntry tools_mybrush_pixel_size_actions[] = +{ + { "tools-mypaint-brush-pixel-size-set", GIMP_ICON_TOOL_MYPAINT_BRUSH, + "Set MyPaint Brush Diameter in pixel", NULL, NULL, + 1.0, NULL } +}; + static const GimpEnumActionEntry tools_mybrush_hardness_actions[] = { { "tools-mypaint-brush-hardness-set", GIMP_ICON_TOOL_MYPAINT_BRUSH, @@ -697,6 +704,10 @@ tools_actions_setup (GimpActionGroup *group) tools_mybrush_radius_actions, G_N_ELEMENTS (tools_mybrush_radius_actions), tools_mybrush_radius_cmd_callback); + gimp_action_group_add_double_actions (group, NULL, + tools_mybrush_pixel_size_actions, + G_N_ELEMENTS (tools_mybrush_pixel_size_actions), + tools_mybrush_pixel_size_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_mybrush_hardness_actions, G_N_ELEMENTS (tools_mybrush_hardness_actions), diff --git a/app/actions/tools-commands.c b/app/actions/tools-commands.c index b840e7f3c3..e15eab59db 100644 --- a/app/actions/tools-commands.c +++ b/app/actions/tools-commands.c @@ -466,6 +466,42 @@ tools_mybrush_radius_cmd_callback (GimpAction *action, } } +void +tools_mybrush_pixel_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpContext *context; + GimpToolInfo *tool_info; + gdouble dvalue; + return_if_no_context (context, data); + + dvalue = g_variant_get_double (value); + /* Dividing by 2.0 because the parameter is the size of the brush, + * hence the diameter and this tool uses the radius as parameter. + * Furthermore MyPaint brush radius is stored as a natural logarithm + * radius. + */ + dvalue = log (dvalue / 2.0); + + tool_info = gimp_context_get_tool (context); + + if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options)) + { + GParamSpec *pspec; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (tool_info->tool_options), + "radius"); + dvalue = CLAMP (dvalue, + G_PARAM_SPEC_DOUBLE (pspec)->minimum, + G_PARAM_SPEC_DOUBLE (pspec)->maximum); + + g_object_set (G_OBJECT (tool_info->tool_options), + "radius", dvalue, + NULL); + } +} + void tools_mybrush_hardness_cmd_callback (GimpAction *action, GVariant *value, diff --git a/app/actions/tools-commands.h b/app/actions/tools-commands.h index 38ab455b25..fa77369e32 100644 --- a/app/actions/tools-commands.h +++ b/app/actions/tools-commands.h @@ -68,6 +68,9 @@ void tools_airbrush_flow_cmd_callback (GimpAction *action, void tools_mybrush_radius_cmd_callback (GimpAction *action, GVariant *value, gpointer data); +void tools_mybrush_pixel_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); void tools_mybrush_hardness_cmd_callback (GimpAction *action, GVariant *value, gpointer data); diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c index 62f00634b1..8df1c60cae 100644 --- a/app/display/gimpdisplayshell-tool-events.c +++ b/app/display/gimpdisplayshell-tool-events.c @@ -48,6 +48,7 @@ #include "widgets/gimpdevicemanager.h" #include "widgets/gimpdevices.h" #include "widgets/gimpdialogfactory.h" +#include "widgets/gimpdoubleaction.h" #include "widgets/gimpenumaction.h" #include "widgets/gimpuimanager.h" #include "widgets/gimpwidgets-utils.h" @@ -143,9 +144,9 @@ static void gimp_display_shell_untransform_event_coords (GimpDisplayShell GimpCoords *image_coords, gboolean *update_software_cursor); -static void gimp_display_shell_activate_enum_action (GimpUIManager *manager, +static void gimp_display_shell_activate_action (GimpUIManager *manager, const gchar *action_desc, - gint value); + GVariant *value); /* public functions */ @@ -1805,18 +1806,31 @@ gimp_display_shell_handle_scrolling (GimpDisplayShell *shell, /* TODO: different logics with "lock brush to view". */ /* TODO 2: scale aware? */ - action = gimp_tool_control_get_action_size (active_tool->control); - + action = gimp_tool_control_get_action_pixel_size (active_tool->control); if (action) { GimpImageWindow *window = gimp_display_shell_get_window (shell); GimpUIManager *manager = gimp_image_window_get_ui_manager (window); - /* Special trick with these enum actions. If using any - * positive value, we get the GIMP_ACTION_SELECT_SET behavior - * which sets to the given value. - */ - gimp_display_shell_activate_enum_action (manager, action, size); + gimp_display_shell_activate_action (manager, action, + g_variant_new_double ((gdouble) size)); + } + else + { + action = gimp_tool_control_get_action_size (active_tool->control); + + if (action) + { + GimpImageWindow *window = gimp_display_shell_get_window (shell); + GimpUIManager *manager = gimp_image_window_get_ui_manager (window); + + /* Special trick with these enum actions. If using any + * positive value, we get the GIMP_ACTION_SELECT_SET behavior + * which sets to the given value. + */ + gimp_display_shell_activate_action (manager, action, + g_variant_new_int32 (size)); + } } } else @@ -2257,9 +2271,9 @@ gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell, } static void -gimp_display_shell_activate_enum_action (GimpUIManager *manager, - const gchar *action_desc, - gint value) +gimp_display_shell_activate_action (GimpUIManager *manager, + const gchar *action_desc, + GVariant *value) { gchar *group_name; gchar *action_name; @@ -2278,8 +2292,11 @@ gimp_display_shell_activate_enum_action (GimpUIManager *manager, if (GIMP_IS_ENUM_ACTION (action) && GIMP_ENUM_ACTION (action)->value_variable) { - gimp_action_emit_activate (action, - g_variant_new_int32 (value)); + gimp_action_emit_activate (action, value); + } + else if (GIMP_IS_DOUBLE_ACTION (action)) + { + gimp_action_emit_activate (action, value); } } diff --git a/app/tools/gimpmybrushtool.c b/app/tools/gimpmybrushtool.c index 4576b894e3..2a7378802f 100644 --- a/app/tools/gimpmybrushtool.c +++ b/app/tools/gimpmybrushtool.c @@ -94,11 +94,13 @@ gimp_mybrush_tool_init (GimpMybrushTool *mybrush_tool) { GimpTool *tool = GIMP_TOOL (mybrush_tool); - gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_INK); - gimp_tool_control_set_action_size (tool->control, - "tools/tools-mypaint-brush-radius-set"); - gimp_tool_control_set_action_hardness (tool->control, - "tools/tools-mypaint-brush-hardness-set"); + gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_INK); + gimp_tool_control_set_action_size (tool->control, + "tools/tools-mypaint-brush-radius-set"); + gimp_tool_control_set_action_pixel_size (tool->control, + "tools/tools-mypaint-brush-pixel-size-set"); + gimp_tool_control_set_action_hardness (tool->control, + "tools/tools-mypaint-brush-hardness-set"); gimp_paint_tool_enable_color_picker (GIMP_PAINT_TOOL (mybrush_tool), GIMP_COLOR_PICK_TARGET_FOREGROUND); @@ -125,11 +127,18 @@ gimp_mybrush_tool_get_outline (GimpPaintTool *paint_tool, gdouble y) { GimpMybrushOptions *options = GIMP_MYBRUSH_TOOL_GET_OPTIONS (paint_tool); - GimpMybrush *brush = gimp_context_get_mybrush (GIMP_CONTEXT (options)); GimpCanvasItem *item = NULL; GimpDisplayShell *shell = gimp_display_get_shell (display); + gdouble radius; - gdouble radius = exp (options->radius) + 2 * options->radius * gimp_mybrush_get_offset_by_random (brush); + /* Radius size as used by libmypaint is logarithmic. + * The drawn outline in the MyBrush tool is more of a general idea of + * the brush size. With each brush having its own logic, actual drawn + * dabs may be quite different, smaller but also bigger. And there are + * some random elements in there too. + * See also mypaint-brush.c code in libmypaint. + */ + radius = exp (options->radius); radius = MAX (MAX (4 / shell->scale_x, 4 / shell->scale_y), radius); item = gimp_mybrush_tool_create_cursor (paint_tool, display, x, y, radius); diff --git a/app/tools/gimptoolcontrol.c b/app/tools/gimptoolcontrol.c index d8b138683f..b6103f5395 100644 --- a/app/tools/gimptoolcontrol.c +++ b/app/tools/gimptoolcontrol.c @@ -98,6 +98,8 @@ gimp_tool_control_finalize (GObject *object) g_free (control->action_object_1); g_free (control->action_object_2); + g_free (control->action_pixel_size); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -725,3 +727,24 @@ gimp_tool_control_get_action_object_2 (GimpToolControl *control) return control->action_object_2; } + +void +gimp_tool_control_set_action_pixel_size (GimpToolControl *control, + const gchar *action) +{ + g_return_if_fail (GIMP_IS_TOOL_CONTROL (control)); + + if (action != control->action_pixel_size) + { + g_free (control->action_pixel_size); + control->action_pixel_size = g_strdup (action); + } +} + +const gchar * +gimp_tool_control_get_action_pixel_size (GimpToolControl *control) +{ + g_return_val_if_fail (GIMP_IS_TOOL_CONTROL (control), NULL); + + return control->action_pixel_size; +} diff --git a/app/tools/gimptoolcontrol.h b/app/tools/gimptoolcontrol.h index 855180698f..6617258cba 100644 --- a/app/tools/gimptoolcontrol.h +++ b/app/tools/gimptoolcontrol.h @@ -79,15 +79,31 @@ struct _GimpToolControl GimpToolCursorType toggle_tool_cursor; GimpCursorModifier toggle_cursor_modifier; - gchar *action_opacity; gchar *action_size; gchar *action_aspect; gchar *action_angle; + gchar *action_spacing; + + gchar *action_opacity; gchar *action_hardness; gchar *action_force; + gchar *action_object_1; gchar *action_object_2; + + /* Enum actions have a +-/min/max values which are not necessarily so + * useful. They also have a variable value which works as a per mille + * between the min and max, so it's hard to use, especially for + * actions which have a huge max or which can have negative values. + * For instance, aspect and angle can be negative. As for size and + * spacing, their max value can be huge. Finally "size" can be + * negative for the MyPaint brush tool, which uses a logarithmic + * radius as base value. + * For this reason, we also register specialized actions with clear + * unit if needed. + */ + gchar *action_pixel_size; }; struct _GimpToolControlClass @@ -251,4 +267,9 @@ void gimp_tool_control_set_action_object_2 (GimpToolControl *control, const gchar * gimp_tool_control_get_action_object_2 (GimpToolControl *control); +void gimp_tool_control_set_action_pixel_size (GimpToolControl *control, + const gchar *action); +const gchar * gimp_tool_control_get_action_pixel_size (GimpToolControl *control); + + #endif /* __GIMP_TOOL_CONTROL_H__ */