From af5cdfbd5861aae6b8049384bc273375330a8274 Mon Sep 17 00:00:00 2001 From: BST 1998 Andy Thomas Date: Tue, 20 Oct 1998 22:36:52 +0000 Subject: [PATCH] app/brush_select.h app/brush_select.c app/internal_procs.c Tue Oct 20 23:20:40 BST 1998 Andy Thomas * app/brush_select.h * app/brush_select.c * app/internal_procs.c * app/gimpbrushlist.c * libgimp/Makefile.am * libgimp/gimpmenu.h * libgimp/gimpmenu.c * plug-ins/script-fu/scripts/3d-outline.scm * plug-ins/script-fu/scripts/test-sphere.scm * plug-ins/script-fu/scripts/trochoid.scm * plug-ins/script-fu/script-fu-enums.h * plug-ins/script-fu/script-fu-scripts.c * plug-ins/script-fu/script-fu.c New file libgimp/gimpbrushmneu.c. Brush dialog can now be fully controlled via the PDB. New widget (not true widget) type added to libgimpui (gimp_brush_select_widget()). Plugins should easily be able to control & select brushes. Script-fu updated to use new widget. See the test script for example. Started to change some of the scripts to use the new widget types. --- ChangeLog | 25 ++ app/brush_select.c | 204 +++++++++- app/brush_select.h | 4 + app/gimpbrushlist.c | 123 ++++++ app/gui/brush-select.c | 204 +++++++++- app/gui/brush-select.h | 4 + app/internal_procs.c | 5 +- libgimp/Makefile.am | 1 + libgimp/gimpbrushmenu.c | 445 +++++++++++++++++++++ libgimp/gimpmenu.c | 96 ++++- libgimp/gimpmenu.h | 37 +- plug-ins/script-fu/script-fu-enums.h | 3 +- plug-ins/script-fu/script-fu-interface.c | 109 ++++- plug-ins/script-fu/script-fu-scripts.c | 109 ++++- plug-ins/script-fu/script-fu.c | 1 + plug-ins/script-fu/scripts/3d-outline.scm | 2 +- plug-ins/script-fu/scripts/test-sphere.scm | 3 +- plug-ins/script-fu/scripts/trochoid.scm | 8 +- 18 files changed, 1363 insertions(+), 20 deletions(-) create mode 100644 libgimp/gimpbrushmenu.c diff --git a/ChangeLog b/ChangeLog index 72e530ec2a..47d156f934 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +Tue Oct 20 23:20:40 BST 1998 Andy Thomas + + * app/brush_select.h + * app/brush_select.c + * app/internal_procs.c + * app/gimpbrushlist.c + * libgimp/Makefile.am + * libgimp/gimpmenu.h + * libgimp/gimpmenu.c + * plug-ins/script-fu/scripts/3d-outline.scm + * plug-ins/script-fu/scripts/test-sphere.scm + * plug-ins/script-fu/scripts/trochoid.scm + * plug-ins/script-fu/script-fu-enums.h + * plug-ins/script-fu/script-fu-scripts.c + * plug-ins/script-fu/script-fu.c + + New file libgimp/gimpbrushmneu.c. + + Brush dialog can now be fully controlled via the PDB. New widget (not + true widget) type added to libgimpui (gimp_brush_select_widget()). + Plugins should easily be able to control & select brushes. Script-fu + updated to use new widget. See the test script for example. + + Started to change some of the scripts to use the new widget types. + 1998-10-19 Christopher James Lahey * app/docindex.c: New Drag & Drop works now. diff --git a/app/brush_select.c b/app/brush_select.c index 14195978a9..e5bfb61cf0 100644 --- a/app/brush_select.c +++ b/app/brush_select.c @@ -270,7 +270,8 @@ brush_select_new (gchar * title, label = gtk_label_new (_("Mode:")); gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); menu = create_paint_mode_menu (paint_mode_menu_callback,(gpointer)bsp); - option_menu = gtk_option_menu_new (); + bsp->option_menu = + option_menu = gtk_option_menu_new (); gtk_box_pack_start (GTK_BOX (util_box), option_menu, FALSE, FALSE, 2); gtk_widget_show (label); @@ -284,7 +285,7 @@ brush_select_new (gchar * title, label = gtk_label_new (_("Opacity:")); gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); bsp->opacity_data = - GTK_ADJUSTMENT (gtk_adjustment_new ((active)?init_opacity:100.0, 0.0, 100.0, 1.0, 1.0, 0.0)); + GTK_ADJUSTMENT (gtk_adjustment_new ((active)?(init_opacity*100.0):100.0, 0.0, 100.0, 1.0, 1.0, 0.0)); slider = gtk_hscale_new (bsp->opacity_data); gtk_box_pack_start (GTK_BOX (util_box), slider, TRUE, TRUE, 0); gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); @@ -1221,7 +1222,7 @@ brushes_popup_invoker (Argument *args) gchar * name; gchar * title; gchar * initial_brush; - gdouble initial_opacity = 100.0; + gdouble initial_opacity = 1.0; gint initial_spacing = 20; gint initial_mode = 0; ProcRecord *prec = NULL; @@ -1316,3 +1317,200 @@ ProcRecord brushes_popup_proc = /* Exec method */ { { brushes_popup_invoker } }, }; + +static BrushSelectP +brush_get_brushselect(gchar *name) +{ + GSList *list; + BrushSelectP bsp; + + list = active_dialogs; + + while (list) + { + bsp = (BrushSelectP) list->data; + list = list->next; + + if(strcmp(name,bsp->callback_name) == 0) + { + return bsp; + } + } + + return NULL; +} + +static Argument * +brush_close_popup_invoker (Argument *args) +{ + gchar * name; + ProcRecord *prec = NULL; + BrushSelectP bsp; + + success = (name = (char *) args[0].value.pdb_pointer) != NULL; + + /* Check the proc exists */ + if(!success || (prec = procedural_db_lookup(name)) == NULL) + { + success = 0; + return procedural_db_return_args (&brushes_close_popup_proc, success); + } + + bsp = brush_get_brushselect(name); + + if(bsp) + { + active_dialogs = g_slist_remove(active_dialogs,bsp); + + if (GTK_WIDGET_VISIBLE (bsp->shell)) + gtk_widget_hide (bsp->shell); + + /* Free memory if poping down dialog which is not the main one */ + if(bsp != brush_select_dialog) + { + gtk_widget_destroy(bsp->shell); + brush_select_free(bsp); + } + } + else + { + success = FALSE; + } + + return procedural_db_return_args (&brushes_close_popup_proc, success); +} + +/* The procedure definition */ +ProcArg brush_close_popup_in_args[] = +{ + { PDB_STRING, + "callback_PDB_entry_name", + N_("The name of the callback registered for this popup"), + }, +}; + +ProcRecord brushes_close_popup_proc = +{ + "gimp_brushes_close_popup", + N_("Popdown the Gimp brush selection"), + N_("This procedure closes an opened brush selection dialog"), + "Andy Thomas", + "Andy Thomas", + "1998", + PDB_INTERNAL, + + /* Input arguments */ + sizeof(brush_close_popup_in_args) / sizeof(brush_close_popup_in_args[0]), + brush_close_popup_in_args, + + /* Output arguments */ + 0, + NULL, + + /* Exec method */ + { { brush_close_popup_invoker } }, +}; + +static Argument * +brush_set_popup_invoker (Argument *args) +{ + gchar * pdbname; + gchar * brush_name; + ProcRecord *prec = NULL; + BrushSelectP bsp; + + success = (pdbname = (char *) args[0].value.pdb_pointer) != NULL; + brush_name = (char *) args[1].value.pdb_pointer; + + /* Check the proc exists */ + if(!success || (prec = procedural_db_lookup(pdbname)) == NULL) + { + success = 0; + return procedural_db_return_args (&brushes_set_popup_proc, success); + } + + bsp = brush_get_brushselect(pdbname); + + + if(bsp) + { + GimpBrushP active = gimp_brush_list_get_brush(brush_list,brush_name); + + if(active) + { + /* Must alter the wigdets on screen as well */ + + bsp->brush = active; + brush_select_select (bsp, gimp_brush_list_get_brush_index(brush_list, active)); + + bsp->opacity_value = args[2].value.pdb_float; + bsp->spacing_value = args[3].value.pdb_int; + if(args[4].value.pdb_int >= 0 && args[4].value.pdb_int <= VALUE_MODE) + bsp->paint_mode = args[4].value.pdb_int; + + bsp->spacing_data->value = bsp->spacing_value; + gtk_signal_emit_by_name (GTK_OBJECT (bsp->spacing_data), "value_changed"); + + bsp->opacity_data->value = bsp->opacity_value * 100.0; + gtk_signal_emit_by_name (GTK_OBJECT (bsp->opacity_data), "value_changed"); + + gtk_option_menu_set_history(GTK_OPTION_MENU(bsp->option_menu),bsp->paint_mode); + + /* Can alter active_dialogs list*/ + success = TRUE; + } + } + else + { + success = FALSE; + } + + return procedural_db_return_args (&brushes_set_popup_proc, success); +} + +/* The procedure definition */ +ProcArg brush_set_popup_in_args[] = +{ + { PDB_STRING, + "callback_PDB_entry_name", + N_("The name of the callback registered for this popup"), + }, + { PDB_STRING, + "brushname", + N_("The name of the brush to set as selected"), + }, + { PDB_FLOAT, + "opacity", + N_("The initial opacity of the brush"), + }, + { PDB_INT32, + "spacing", + N_("The initial spacing of the brush (if < 0 then use brush default spacing)"), + }, + { PDB_INT32, + "initial paint mode", + N_("The initial paint mode: { NORMAL (0), DISSOLVE (1), BEHIND (2), MULTIPLY/BURN (3), SCREEN (4), OVERLAY (5) DIFFERENCE (6), ADDITION (7), SUBTRACT (8), DARKEN-ONLY (9), LIGHTEN-ONLY (10), HUE (11), SATURATION (12), COLOR (13), VALUE (14), DIVIDE/DODGE (15) }"), + }, +}; + +ProcRecord brushes_set_popup_proc = +{ + "gimp_brushes_set_popup", + N_("Sets the current brush selection in a popup"), + N_("Sets the current brush selection in a popup"), + "Andy Thomas", + "Andy Thomas", + "1998", + PDB_INTERNAL, + + /* Input arguments */ + sizeof(brush_set_popup_in_args) / sizeof(brush_set_popup_in_args[0]), + brush_set_popup_in_args, + + /* Output arguments */ + 0, + NULL, + + /* Exec method */ + { { brush_set_popup_invoker } }, +}; diff --git a/app/brush_select.h b/app/brush_select.h index 1c8ec4ebef..f894a6fc43 100644 --- a/app/brush_select.h +++ b/app/brush_select.h @@ -35,6 +35,7 @@ struct _BrushSelect { GtkAdjustment *spacing_data; GtkAdjustment *sbar_data; GtkWidget *edit_button; + GtkWidget *option_menu; int width, height; int cell_width, cell_height; int scroll_offset; @@ -74,5 +75,8 @@ GtkWidget * create_paint_mode_menu (MenuItemCallback, gpointer); /* PDB entry */ extern ProcRecord brushes_popup_proc; +extern ProcRecord brushes_close_popup_proc; +extern ProcRecord brushes_set_popup_proc; +extern ProcRecord brushes_get_brush_data_proc; #endif /* __BRUSH_SELECT_H__ */ diff --git a/app/gimpbrushlist.c b/app/gimpbrushlist.c index b4ea82499f..bb04b11906 100644 --- a/app/gimpbrushlist.c +++ b/app/gimpbrushlist.c @@ -988,3 +988,126 @@ ProcRecord brushes_list_proc = /* Exec method */ { { brushes_list_invoker } }, }; + +/*******************************/ +/* BRUSHES_GET_BRUSH_DATA */ + +static Argument * +brushes_get_brush_data_invoker (Argument *args) +{ + GimpBrushP brushp = NULL; + GSList *list; + char *name; + static Argument *return_args; + + success = (name = (char *) args[0].value.pdb_pointer) != NULL; + + if (!success) + { + /* No name use active pattern */ + success = (brushp = get_active_brush ()) != NULL; + } + else + { + list = GIMP_LIST(brush_list)->list; + success = FALSE; + + while (list) + { + brushp = (GimpBrushP) list->data; + + if (!strcmp (brushp->name, name)) + { + success = TRUE; + break; + } + + list = g_slist_next (list); + } + } + + return_args = procedural_db_return_args (&brushes_get_brush_data_proc, success); + + if (success) + { + return_args[1].value.pdb_pointer = g_strdup (brushp->name); + return_args[2].value.pdb_float = 1.0; /*opacity_value;*/ + return_args[3].value.pdb_int = brushp->spacing; + return_args[4].value.pdb_int = 0; /* paint_mode; */ + return_args[5].value.pdb_int = brushp->mask->width; + return_args[6].value.pdb_int = brushp->mask->height; + return_args[7].value.pdb_int = brushp->mask->height*brushp->mask->width; + return_args[8].value.pdb_pointer = g_malloc(return_args[7].value.pdb_int); + g_memmove(return_args[8].value.pdb_pointer, + temp_buf_data (brushp->mask), + return_args[7].value.pdb_int); + } + + return return_args; +} + +/* The procedure definition */ + +ProcArg brushes_get_brush_data_in_args[] = +{ + { PDB_STRING, + "name", + "the brush name (\"\" means current active pattern) " + } +}; + +ProcArg brushes_get_brush_data_out_args[] = +{ + { PDB_STRING, + "name", + "the brush name" + }, + { PDB_FLOAT, + "opacity", + "the brush opacity" + }, + { PDB_INT32, + "spacing", + "the brush spacing" + }, + { PDB_INT32, + "paint_mode", + "the brush paint mode" + }, + { PDB_INT32, + "width", + "the brush width" + }, + { PDB_INT32, + "height", + "the brush height" + }, + { PDB_INT32, + "length", + "length of brush mask data"}, + { PDB_INT8ARRAY, + "mask_data", + "the brush mask data"}, +}; + +ProcRecord brushes_get_brush_data_proc = +{ + "gimp_brushes_get_brush_data", + "Retrieve information about the currently active brush (including data)", + "This procedure retrieves information about the currently active brush. This includes the brush name, and the brush extents (width and height). It also returns the brush data", + "Andy Thomas", + "Andy Thomas", + "1998", + PDB_INTERNAL, + + /* Input arguments */ + sizeof(brushes_get_brush_data_in_args) / sizeof(brushes_get_brush_data_in_args[0]), + brushes_get_brush_data_in_args, + + /* Output arguments */ + sizeof(brushes_get_brush_data_out_args) / sizeof(brushes_get_brush_data_out_args[0]), + brushes_get_brush_data_out_args, + + /* Exec method */ + { { brushes_get_brush_data_invoker } }, +}; diff --git a/app/gui/brush-select.c b/app/gui/brush-select.c index 14195978a9..e5bfb61cf0 100644 --- a/app/gui/brush-select.c +++ b/app/gui/brush-select.c @@ -270,7 +270,8 @@ brush_select_new (gchar * title, label = gtk_label_new (_("Mode:")); gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); menu = create_paint_mode_menu (paint_mode_menu_callback,(gpointer)bsp); - option_menu = gtk_option_menu_new (); + bsp->option_menu = + option_menu = gtk_option_menu_new (); gtk_box_pack_start (GTK_BOX (util_box), option_menu, FALSE, FALSE, 2); gtk_widget_show (label); @@ -284,7 +285,7 @@ brush_select_new (gchar * title, label = gtk_label_new (_("Opacity:")); gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); bsp->opacity_data = - GTK_ADJUSTMENT (gtk_adjustment_new ((active)?init_opacity:100.0, 0.0, 100.0, 1.0, 1.0, 0.0)); + GTK_ADJUSTMENT (gtk_adjustment_new ((active)?(init_opacity*100.0):100.0, 0.0, 100.0, 1.0, 1.0, 0.0)); slider = gtk_hscale_new (bsp->opacity_data); gtk_box_pack_start (GTK_BOX (util_box), slider, TRUE, TRUE, 0); gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); @@ -1221,7 +1222,7 @@ brushes_popup_invoker (Argument *args) gchar * name; gchar * title; gchar * initial_brush; - gdouble initial_opacity = 100.0; + gdouble initial_opacity = 1.0; gint initial_spacing = 20; gint initial_mode = 0; ProcRecord *prec = NULL; @@ -1316,3 +1317,200 @@ ProcRecord brushes_popup_proc = /* Exec method */ { { brushes_popup_invoker } }, }; + +static BrushSelectP +brush_get_brushselect(gchar *name) +{ + GSList *list; + BrushSelectP bsp; + + list = active_dialogs; + + while (list) + { + bsp = (BrushSelectP) list->data; + list = list->next; + + if(strcmp(name,bsp->callback_name) == 0) + { + return bsp; + } + } + + return NULL; +} + +static Argument * +brush_close_popup_invoker (Argument *args) +{ + gchar * name; + ProcRecord *prec = NULL; + BrushSelectP bsp; + + success = (name = (char *) args[0].value.pdb_pointer) != NULL; + + /* Check the proc exists */ + if(!success || (prec = procedural_db_lookup(name)) == NULL) + { + success = 0; + return procedural_db_return_args (&brushes_close_popup_proc, success); + } + + bsp = brush_get_brushselect(name); + + if(bsp) + { + active_dialogs = g_slist_remove(active_dialogs,bsp); + + if (GTK_WIDGET_VISIBLE (bsp->shell)) + gtk_widget_hide (bsp->shell); + + /* Free memory if poping down dialog which is not the main one */ + if(bsp != brush_select_dialog) + { + gtk_widget_destroy(bsp->shell); + brush_select_free(bsp); + } + } + else + { + success = FALSE; + } + + return procedural_db_return_args (&brushes_close_popup_proc, success); +} + +/* The procedure definition */ +ProcArg brush_close_popup_in_args[] = +{ + { PDB_STRING, + "callback_PDB_entry_name", + N_("The name of the callback registered for this popup"), + }, +}; + +ProcRecord brushes_close_popup_proc = +{ + "gimp_brushes_close_popup", + N_("Popdown the Gimp brush selection"), + N_("This procedure closes an opened brush selection dialog"), + "Andy Thomas", + "Andy Thomas", + "1998", + PDB_INTERNAL, + + /* Input arguments */ + sizeof(brush_close_popup_in_args) / sizeof(brush_close_popup_in_args[0]), + brush_close_popup_in_args, + + /* Output arguments */ + 0, + NULL, + + /* Exec method */ + { { brush_close_popup_invoker } }, +}; + +static Argument * +brush_set_popup_invoker (Argument *args) +{ + gchar * pdbname; + gchar * brush_name; + ProcRecord *prec = NULL; + BrushSelectP bsp; + + success = (pdbname = (char *) args[0].value.pdb_pointer) != NULL; + brush_name = (char *) args[1].value.pdb_pointer; + + /* Check the proc exists */ + if(!success || (prec = procedural_db_lookup(pdbname)) == NULL) + { + success = 0; + return procedural_db_return_args (&brushes_set_popup_proc, success); + } + + bsp = brush_get_brushselect(pdbname); + + + if(bsp) + { + GimpBrushP active = gimp_brush_list_get_brush(brush_list,brush_name); + + if(active) + { + /* Must alter the wigdets on screen as well */ + + bsp->brush = active; + brush_select_select (bsp, gimp_brush_list_get_brush_index(brush_list, active)); + + bsp->opacity_value = args[2].value.pdb_float; + bsp->spacing_value = args[3].value.pdb_int; + if(args[4].value.pdb_int >= 0 && args[4].value.pdb_int <= VALUE_MODE) + bsp->paint_mode = args[4].value.pdb_int; + + bsp->spacing_data->value = bsp->spacing_value; + gtk_signal_emit_by_name (GTK_OBJECT (bsp->spacing_data), "value_changed"); + + bsp->opacity_data->value = bsp->opacity_value * 100.0; + gtk_signal_emit_by_name (GTK_OBJECT (bsp->opacity_data), "value_changed"); + + gtk_option_menu_set_history(GTK_OPTION_MENU(bsp->option_menu),bsp->paint_mode); + + /* Can alter active_dialogs list*/ + success = TRUE; + } + } + else + { + success = FALSE; + } + + return procedural_db_return_args (&brushes_set_popup_proc, success); +} + +/* The procedure definition */ +ProcArg brush_set_popup_in_args[] = +{ + { PDB_STRING, + "callback_PDB_entry_name", + N_("The name of the callback registered for this popup"), + }, + { PDB_STRING, + "brushname", + N_("The name of the brush to set as selected"), + }, + { PDB_FLOAT, + "opacity", + N_("The initial opacity of the brush"), + }, + { PDB_INT32, + "spacing", + N_("The initial spacing of the brush (if < 0 then use brush default spacing)"), + }, + { PDB_INT32, + "initial paint mode", + N_("The initial paint mode: { NORMAL (0), DISSOLVE (1), BEHIND (2), MULTIPLY/BURN (3), SCREEN (4), OVERLAY (5) DIFFERENCE (6), ADDITION (7), SUBTRACT (8), DARKEN-ONLY (9), LIGHTEN-ONLY (10), HUE (11), SATURATION (12), COLOR (13), VALUE (14), DIVIDE/DODGE (15) }"), + }, +}; + +ProcRecord brushes_set_popup_proc = +{ + "gimp_brushes_set_popup", + N_("Sets the current brush selection in a popup"), + N_("Sets the current brush selection in a popup"), + "Andy Thomas", + "Andy Thomas", + "1998", + PDB_INTERNAL, + + /* Input arguments */ + sizeof(brush_set_popup_in_args) / sizeof(brush_set_popup_in_args[0]), + brush_set_popup_in_args, + + /* Output arguments */ + 0, + NULL, + + /* Exec method */ + { { brush_set_popup_invoker } }, +}; diff --git a/app/gui/brush-select.h b/app/gui/brush-select.h index 1c8ec4ebef..f894a6fc43 100644 --- a/app/gui/brush-select.h +++ b/app/gui/brush-select.h @@ -35,6 +35,7 @@ struct _BrushSelect { GtkAdjustment *spacing_data; GtkAdjustment *sbar_data; GtkWidget *edit_button; + GtkWidget *option_menu; int width, height; int cell_width, cell_height; int scroll_offset; @@ -74,5 +75,8 @@ GtkWidget * create_paint_mode_menu (MenuItemCallback, gpointer); /* PDB entry */ extern ProcRecord brushes_popup_proc; +extern ProcRecord brushes_close_popup_proc; +extern ProcRecord brushes_set_popup_proc; +extern ProcRecord brushes_get_brush_data_proc; #endif /* __BRUSH_SELECT_H__ */ diff --git a/app/internal_procs.c b/app/internal_procs.c index c7a190d283..630a86216b 100644 --- a/app/internal_procs.c +++ b/app/internal_procs.c @@ -80,7 +80,7 @@ internal_procs_init () { gfloat pcount = 0; /* grep -c procedural_db_register internal_procs.c */ - gfloat total_pcount = 237; + gfloat total_pcount = 240; app_init_update_status("Internal Procedures", "Tool procedures", pcount/total_pcount); @@ -338,6 +338,9 @@ internal_procs_init () procedural_db_register (&brushes_set_paint_mode_proc); pcount++; procedural_db_register (&brushes_list_proc); pcount++; procedural_db_register (&brushes_popup_proc); pcount++; + procedural_db_register (&brushes_close_popup_proc); pcount++; + procedural_db_register (&brushes_set_popup_proc); pcount++; + procedural_db_register (&brushes_get_brush_data_proc); pcount++; procedural_db_register (&patterns_get_pattern_proc); pcount++; procedural_db_register (&patterns_set_pattern_proc); pcount++; procedural_db_register (&patterns_list_proc); pcount++; diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am index d857bdca07..178885e046 100644 --- a/libgimp/Makefile.am +++ b/libgimp/Makefile.am @@ -48,6 +48,7 @@ libgimp_la_SOURCES = \ libgimpui_la_SOURCES = \ gimpmenu.c \ + gimpbrushmenu.c \ gimppatternmenu.c gimpinclude_HEADERS = \ diff --git a/libgimp/gimpbrushmenu.c b/libgimp/gimpbrushmenu.c new file mode 100644 index 0000000000..72637c8097 --- /dev/null +++ b/libgimp/gimpbrushmenu.c @@ -0,0 +1,445 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * Copyright (C) 1998 Andy Thomas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include +#include + +#include "gimp.h" +#include "gimpui.h" + + +/* Idea is to have a function to call that returns a widget that + * completely controls the selection of a brush. + * you get a widget returned that you can use in a table say. + * In:- Initial brush name. Null means use current selection. + * pointer to func to call when brush changes (GRunBrushCallback). + * Returned:- Pointer to a widget that you can use in UI. + * + * Widget simply made up of a preview widget (20x20) containing the brush mask + * and a button that can be clicked on to change the brush. + */ + + +#define BSEL_DATA_KEY "__bsel_data" +#define CELL_SIZE 20 +#define BRUSH_EVENT_MASK GDK_EXPOSURE_MASK | \ + GDK_BUTTON_PRESS_MASK | \ + GDK_BUTTON_RELEASE_MASK | \ + GDK_BUTTON1_MOTION_MASK + +struct __brushes_sel { + gchar * dname; + GRunBrushCallback cback; + GtkWidget *brush_preview; + GtkWidget *device_brushpopup; + GtkWidget *device_brushpreview; + GtkWidget *button; + GtkWidget *top_hbox; + gchar *brush_name; /* Local copy */ + gdouble opacity; + gint spacing; + gint paint_mode; + gint width; + gint height; + gchar *mask_data; /* local copy */ + void *brush_popup_pnt; /* POinter use to control the popup */ + gpointer udata; +}; + +typedef struct __brushes_sel BSelect, * BSelectP; + +static void +brush_popup_open (int x, + int y, + BSelectP bsel) +{ + gint x_org, y_org; + gint scr_w, scr_h; + gchar *src, *buf; + unsigned char *b,*s; + + /* make sure the popup exists and is not visible */ + if (bsel->device_brushpopup == NULL) + { + GtkWidget *frame; + + bsel->device_brushpopup = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_policy (GTK_WINDOW (bsel->device_brushpopup), FALSE, FALSE, TRUE); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); + gtk_container_add (GTK_CONTAINER (bsel->device_brushpopup), frame); + gtk_widget_show (frame); + bsel->device_brushpreview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE); + gtk_container_add (GTK_CONTAINER (frame), bsel->device_brushpreview); + gtk_widget_show (bsel->device_brushpreview); + } + else + { + gtk_widget_hide (bsel->device_brushpopup); + } + + /* decide where to put the popup */ + gdk_window_get_origin (bsel->brush_preview->window, &x_org, &y_org); + scr_w = gdk_screen_width (); + scr_h = gdk_screen_height (); + x = x_org + x - (bsel->width >> 1); + y = y_org + y - (bsel->height >> 1); + x = (x < 0) ? 0 : x; + y = (y < 0) ? 0 : y; + x = (x + bsel->width > scr_w) ? scr_w - bsel->width : x; + y = (y + bsel->height > scr_h) ? scr_h - bsel->height : y; + gtk_preview_size (GTK_PREVIEW (bsel->device_brushpreview), bsel->width, bsel->height); + + gtk_widget_popup (bsel->device_brushpopup, x, y); + + /* Draw the brush */ + buf = g_new (gchar, bsel->width); + + memset(buf, 255, sizeof(bsel->width)); + +/* for (i = 0; i < CELL_SIZE; i++) */ +/* gtk_preview_draw_row (GTK_PREVIEW(bsel->device_brushpreview), (guchar *)buf, 0, i, CELL_SIZE); */ + + src = bsel->mask_data; + + for (y = 0; y < bsel->height; y++) + { + int j; + s = src; + b = buf; + for (j = 0; j < bsel->width ; j++) + *b++ = 255 - *s++; + + gtk_preview_draw_row (GTK_PREVIEW (bsel->device_brushpreview), (guchar *)buf, 0, y, bsel->width); + src += bsel->width; + } + g_free(buf); + + /* Draw the brush preview */ + gtk_widget_draw (bsel->device_brushpreview, NULL); +} + +static void +brush_popup_close (BSelectP bsel) +{ + if (bsel->device_brushpopup != NULL) + gtk_widget_hide (bsel->device_brushpopup); +} + +static gint +brush_preview_events (GtkWidget *widget, + GdkEvent *event, + gpointer udata) +{ + GdkEventButton *bevent; + BSelectP bsel = (BSelectP)udata; + + if(bsel->mask_data) + { + switch (event->type) + { + case GDK_EXPOSE: + break; + + case GDK_BUTTON_PRESS: + bevent = (GdkEventButton *) event; + + if (bevent->button == 1) + { + brush_popup_open (bevent->x, bevent->y, bsel); + } + break; + + case GDK_BUTTON_RELEASE: + bevent = (GdkEventButton *) event; + + if (bevent->button == 1) + { + /* Ungrab the pointer */ + gdk_pointer_ungrab (bevent->time); + + /* Close the device preview popup window */ + brush_popup_close (bsel); + } + break; + case GDK_DELETE: + break; + + default: + break; + } + } + + return FALSE; +} + +static void +brush_pre_update(GtkWidget *brush_preview, + gint brush_width, + gint brush_height, + gchar *mask_data) +{ + gint y,i; + gchar *src, *buf; + unsigned char *b,*s; + int offset_x, offset_y; + int yend; + int ystart; + gint width,height; + /* Draw the brush */ + buf = g_new (gchar, CELL_SIZE); + + /* Limit to cell size */ + width = (brush_width > CELL_SIZE) ? CELL_SIZE: brush_width; + height = (brush_height > CELL_SIZE) ? CELL_SIZE: brush_height; + + /* Set buffer to white */ + memset(buf, 255, CELL_SIZE); + for (i = 0; i < CELL_SIZE; i++) + gtk_preview_draw_row (GTK_PREVIEW(brush_preview), (guchar *)buf, 0, i, CELL_SIZE); + + offset_x = ((CELL_SIZE - width) >> 1); + offset_y = ((CELL_SIZE - height) >> 1); + + ystart = CLAMP (offset_y, 0, CELL_SIZE); + yend = CLAMP (offset_y + height, 0, CELL_SIZE); + + src = mask_data; + + for (y = ystart; y < yend; y++) + { + int j; + s = src; + b = buf; + for (j = 0; j < width ; j++) + *b++ = 255 - *s++; + + gtk_preview_draw_row (GTK_PREVIEW (brush_preview), (guchar *)buf, offset_x, y, width); + src += brush_width; + } + g_free(buf); + + /* Draw the brush preview */ + gtk_widget_draw (brush_preview, NULL); +} + +static void +brush_select_invoker(gchar *name, + gdouble opacity, + gint spacing, + gint paint_mode, + gint width, + gint height, + gchar * mask_data, + gint closing, + gpointer udata) +{ + gint mask_d_sz; + BSelectP bsel = (BSelectP)udata; + if(bsel->mask_data != NULL) + g_free(bsel->mask_data); + bsel->width = width; + bsel->height = height; + mask_d_sz = width*height; + bsel->mask_data = g_malloc(mask_d_sz); + g_memmove(bsel->mask_data,mask_data,mask_d_sz); + brush_pre_update(bsel->brush_preview,bsel->width,bsel->height,bsel->mask_data); + bsel->opacity = opacity; + bsel->spacing = spacing; + bsel->paint_mode = paint_mode; + if(bsel->cback != NULL) + (bsel->cback)(name,opacity,spacing,paint_mode,width,height,mask_data,closing,bsel->udata); + if(closing) + { + gtk_widget_set_sensitive(bsel->button,TRUE); + bsel->brush_popup_pnt = NULL; + } +} + + +static void +brush_select_callback (GtkWidget *widget, + gpointer data) +{ + BSelectP bsel = (BSelectP)data; + gtk_widget_set_sensitive(bsel->button,FALSE); + bsel->brush_popup_pnt = + gimp_interactive_selection_brush((bsel->dname)?bsel->dname:"Brush Plugin Selection", + bsel->brush_name, + bsel->opacity, + bsel->spacing, + bsel->paint_mode, + brush_select_invoker,bsel); +} + +GtkWidget * +gimp_brush_select_widget(gchar *dname, + gchar *ibrush, + gdouble opacity, + gint spacing, + gint paint_mode, + GRunBrushCallback cback, + gpointer udata) +{ + GtkWidget * frame; + GtkWidget * hbox; + GtkWidget * brush; + GtkWidget * button; + gint width,height; + gint init_spacing,init_paint_mode; + gdouble init_opacity; + gchar *mask_data; + gchar *brush_name; + + BSelectP bsel = g_new(BSelect, sizeof(BSelect)); + + hbox = gtk_hbox_new (FALSE, 3); + gtk_widget_show(hbox); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_OUT); + gtk_widget_show(frame); + + brush = gtk_preview_new (GTK_PREVIEW_GRAYSCALE); + gtk_preview_size (GTK_PREVIEW (brush), CELL_SIZE, CELL_SIZE); + gtk_widget_show(brush); + gtk_container_add (GTK_CONTAINER (frame),brush); + + gtk_widget_set_events (brush, BRUSH_EVENT_MASK); + + gtk_signal_connect (GTK_OBJECT (brush), "event", + (GtkSignalFunc) brush_preview_events, + (gpointer)bsel); + + bsel->cback = cback; + bsel->udata = udata; + bsel->mask_data = NULL; + bsel->device_brushpopup = bsel->device_brushpreview = NULL; + bsel->brush_preview = brush; + bsel->brush_name = ibrush; + bsel->dname = dname; + bsel->brush_popup_pnt = NULL; + + /* Do initial brush setup */ + brush_name = gimp_brushes_get_brush_data(ibrush, + &init_opacity, + &init_spacing, + &init_paint_mode, + &width, + &height, + &mask_data); + if(brush_name) + { + brush_pre_update(bsel->brush_preview,width,height,mask_data); + bsel->mask_data = mask_data; + bsel->brush_name = brush_name; + bsel->width = width; + bsel->height = height; + if(opacity != -1) + bsel->opacity = opacity; + else + bsel->opacity = init_opacity; + if(spacing != -1) + bsel->spacing = spacing; + else + bsel->spacing = init_spacing; + if(paint_mode != -1) + bsel->paint_mode = paint_mode; + else + bsel->paint_mode = init_paint_mode; + } + + gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); + + button = gtk_button_new_with_label ("... "); + gtk_container_add (GTK_CONTAINER (hbox), button); + gtk_widget_show(button); + + bsel->button = button; + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) brush_select_callback, + (gpointer)bsel); + + gtk_object_set_data(GTK_OBJECT(hbox),BSEL_DATA_KEY,(gpointer)bsel); + + return hbox; +} + + +gint +gimp_brush_select_widget_close_popup(GtkWidget *w) +{ + gint ret_val = FALSE; + + BSelectP bsel = (BSelectP)gtk_object_get_data(GTK_OBJECT(w),BSEL_DATA_KEY); + if(bsel && bsel->brush_popup_pnt) + { + ret_val = gimp_brush_close_popup(bsel->brush_popup_pnt); + bsel->brush_popup_pnt = NULL; + } + + return ret_val; +} + +gint +gimp_brush_select_widget_set_popup(GtkWidget *w, + gchar *bname, + gdouble opacity, + gint spacing, + gint paint_mode) +{ + gint ret_val = FALSE; + gint width,height; + gint init_spacing,init_paint_mode; + gdouble init_opacity; + gchar *mask_data; + gchar *brush_name; + + BSelectP bsel = (BSelectP)gtk_object_get_data(GTK_OBJECT(w),BSEL_DATA_KEY); + + if(bsel) + { + brush_name = gimp_brushes_get_brush_data(bname, + &init_opacity, + &init_spacing, + &init_paint_mode, + &width,&height,&mask_data); + + if(opacity == -1.0) + opacity = init_opacity; + + if(spacing == -1) + spacing = init_spacing; + + if(paint_mode == -1) + paint_mode = init_paint_mode; + + brush_select_invoker(bname,opacity,spacing,paint_mode,width,height,mask_data,0,bsel); + + if(bsel->brush_popup_pnt) + { + if(gimp_brush_set_popup(bsel->brush_popup_pnt,bname,opacity,spacing,paint_mode)) + { + ret_val = TRUE; + } + } + } + return ret_val; +} diff --git a/libgimp/gimpmenu.c b/libgimp/gimpmenu.c index db6424131f..f38f9b5db6 100644 --- a/libgimp/gimpmenu.c +++ b/libgimp/gimpmenu.c @@ -643,9 +643,12 @@ gen_temp_plugin_name (void) /* Can only be used in conjuction with gdk since we need to tie into the input * selection mech. */ -void +void * gimp_interactive_selection_brush(gchar *dialogname, gchar *brush_name, + gdouble opacity, + gint spacing, + gint paint_mode, GRunBrushCallback callback, gpointer udata) { @@ -688,9 +691,9 @@ gimp_interactive_selection_brush(gchar *dialogname, PARAM_STRING,pdbname, PARAM_STRING,dialogname, PARAM_STRING,brush_name,/*name*/ - PARAM_FLOAT, 1.0, /*Opacity*/ - PARAM_INT32, -1, /*default spacing*/ - PARAM_INT32, 0, /*paint mode*/ + PARAM_FLOAT, opacity, /*Opacity*/ + PARAM_INT32, spacing, /*default spacing*/ + PARAM_INT32, paint_mode, /*paint mode*/ PARAM_END); /* if (pdbreturn_vals[0].data.d_status != STATUS_SUCCESS) */ @@ -714,9 +717,94 @@ gimp_interactive_selection_brush(gchar *dialogname, bdata->callback = callback; bdata->udata = udata; g_hash_table_insert(gbrush_ht,pdbname,bdata); + + return pdbname; } +gchar * +gimp_brushes_get_brush_data (gchar *bname, + gdouble *opacity, + gint *spacing, + gint *paint_mode, + gint *width, + gint *height, + gchar **mask_data) +{ + GParam *return_vals; + int nreturn_vals; + gchar *ret_name = NULL; + + return_vals = gimp_run_procedure ("gimp_brushes_get_brush_data", + &nreturn_vals, + PARAM_STRING, bname, + PARAM_END); + + if (return_vals[0].data.d_status == STATUS_SUCCESS) + { + ret_name = g_strdup(return_vals[1].data.d_string); + *opacity = return_vals[2].data.d_float; + *spacing = return_vals[3].data.d_int32; + *paint_mode = return_vals[4].data.d_int32; + *width = return_vals[5].data.d_int32; + *height = return_vals[6].data.d_int32; + *mask_data = g_new (gchar,return_vals[7].data.d_int32); + g_memmove (*mask_data, return_vals[8].data.d_int32array,return_vals[7].data.d_int32); + } + + gimp_destroy_params (return_vals, nreturn_vals); + + return ret_name; +} + +gint +gimp_brush_close_popup(void * popup_pnt) +{ + GParam *return_vals; + int nreturn_vals; + gint retval; + + return_vals = gimp_run_procedure ("gimp_brushes_close_popup", + &nreturn_vals, + PARAM_STRING, popup_pnt, + PARAM_END); + + gimp_destroy_params (return_vals, nreturn_vals); + + retval = (return_vals[0].data.d_status == STATUS_SUCCESS); + + return retval; +} + +gint +gimp_brush_set_popup(void * popup_pnt, + gchar * pname, + gdouble opacity, + gint spacing, + gint paint_mode) +{ + GParam *return_vals; + int nreturn_vals; + gint retval; + + return_vals = gimp_run_procedure ("gimp_brushes_set_popup", + &nreturn_vals, + PARAM_STRING, popup_pnt, + PARAM_STRING, pname, + PARAM_FLOAT, opacity, + PARAM_INT32, spacing, + PARAM_INT32, paint_mode, + PARAM_END); + + gimp_destroy_params (return_vals, nreturn_vals); + + retval = (return_vals[0].data.d_status == STATUS_SUCCESS); + + return retval; +} + + + void * gimp_interactive_selection_pattern(gchar *dialogname, gchar *pattern_name, diff --git a/libgimp/gimpmenu.h b/libgimp/gimpmenu.h index d099a76604..5c731da24c 100644 --- a/libgimp/gimpmenu.h +++ b/libgimp/gimpmenu.h @@ -71,11 +71,46 @@ GtkWidget* gimp_drawable_menu_new (GimpConstraintFunc constraint, gpointer data, gint32 active_drawable); -void gimp_interactive_selection_brush (gchar *dialogname, +void * gimp_interactive_selection_brush (gchar *dialogname, gchar *brush_name, + gdouble opacity, + gint spacing, + gint paint_mode, GRunBrushCallback callback, gpointer udata); +GtkWidget * gimp_brush_select_widget(gchar * dname, + gchar * ibrush, + gdouble opacity, + gint spacing, + gint paint_mode, + GRunBrushCallback cback, + gpointer); + +gint gimp_brush_select_widget_close_popup(GtkWidget *w); + +gint gimp_brush_select_widget_set_popup(GtkWidget *w, + gchar *pname, + gdouble opacity, + gint spacing, + gint paint_mode); + +gchar *gimp_brushes_get_brush_data (gchar *pname, + gdouble *opacity, + gint *spacing, + gint *paint_mode, + gint *width, + gint *height, + gchar **mask_data); + +gint gimp_brush_set_popup(void * popup_pnt, + gchar * pname, + gdouble opacity, + gint spacing, + gint paint_mode); + +gint gimp_brush_close_popup(void * popup_pnt); + void * gimp_interactive_selection_pattern (gchar *dialogtitle, gchar *pattern_name, GRunPatternCallback callback, diff --git a/plug-ins/script-fu/script-fu-enums.h b/plug-ins/script-fu/script-fu-enums.h index 3ffddc997f..69636d6407 100644 --- a/plug-ins/script-fu/script-fu-enums.h +++ b/plug-ins/script-fu/script-fu-enums.h @@ -33,7 +33,8 @@ typedef enum SF_STRING, SF_ADJUSTMENT, SF_FONT, - SF_PATTERN + SF_PATTERN, + SF_BRUSH } SFArgType; typedef enum diff --git a/plug-ins/script-fu/script-fu-interface.c b/plug-ins/script-fu/script-fu-interface.c index 71f6fa9d99..4dde55db2f 100644 --- a/plug-ins/script-fu/script-fu-interface.c +++ b/plug-ins/script-fu/script-fu-interface.c @@ -68,6 +68,15 @@ typedef struct gchar *fontname; } SFFont; +typedef struct +{ + gchar *name; + gdouble opacity; + gint spacing; + gint paint_mode; +} SFBrush; + + typedef union { gint32 sfa_image; @@ -80,6 +89,7 @@ typedef union SFAdjustment sfa_adjustment; SFFont sfa_font; gchar * sfa_pattern; + SFBrush sfa_brush; } SFArgValue; typedef struct @@ -175,6 +185,15 @@ static void script_fu_pattern_preview (gchar *name, gint closing, gpointer udata); +static void script_fu_brush_preview (char *, /* Name */ + gdouble, /* opacity */ + gint, /* spacing */ + gint, /* paint_mode */ + gint, /* width */ + gint, /* height */ + gchar *, /* mask data */ + gint, /* dialog closing */ + gpointer /* user data */); @@ -339,6 +358,7 @@ script_fu_add_script (LISP a) gdouble color[3]; LISP color_list; LISP adj_list; + LISP brush_list; gchar *menu_path = NULL; /* Check the length of a */ @@ -572,8 +592,30 @@ script_fu_add_script (LISP a) args[i + 1].description = script->arg_labels[i]; break; + case SF_BRUSH: + if (!TYPEP (car (a), tc_cons)) + return my_err ("script-fu-register: brush defaults must be a list", NIL); + brush_list = car (a); + script->arg_defaults[i].sfa_brush.name = g_strdup (get_c_string (car (brush_list))); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.opacity = get_c_double (car (brush_list)); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.spacing = get_c_long (car (brush_list)); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.paint_mode = get_c_long (car (brush_list)); + script->arg_values[i].sfa_brush = script->arg_defaults[i].sfa_brush; + /* Need this since we need a copy of the string + * in the values area. We could free it later but the + * default one must hang around. + */ + + script->arg_values[i].sfa_brush.name = g_strdup(script->arg_defaults[i].sfa_brush.name); + + args[i + 1].type = PARAM_STRING; + args[i + 1].name = "brush"; + args[i + 1].description = script->arg_labels[i]; break; - + default: break; } @@ -725,6 +767,9 @@ script_fu_script_proc (char *name, case SF_PATTERN: length += strlen (params[i + 1].data.d_string) + 3; break; + case SF_BRUSH: + length += strlen (params[i + 1].data.d_string) + 3; + break; default: break; } @@ -775,6 +820,10 @@ script_fu_script_proc (char *name, g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"", params[i + 1].data.d_string); text = buffer; break; + case SF_BRUSH: + g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"", params[i + 1].data.d_string); + text = buffer; + break; default: break; } @@ -871,6 +920,11 @@ script_fu_free_script (SFScript *script) case SF_PATTERN: g_free (script->arg_defaults[i].sfa_pattern); g_free (script->arg_values[i].sfa_pattern); + break; + case SF_BRUSH: + g_free (script->arg_defaults[i].sfa_brush.name); + g_free (script->arg_values[i].sfa_brush.name); + break; default: break; } @@ -1131,6 +1185,16 @@ script_fu_interface (SFScript *script) script_fu_pattern_preview, &script->arg_values[i].sfa_pattern); break; + case SF_BRUSH: + script->args_widgets[i] = + gimp_brush_select_widget("Script-fu brush Selection", + script->arg_values[i].sfa_brush.name, + script->arg_values[i].sfa_brush.opacity, + script->arg_values[i].sfa_brush.spacing, + script->arg_values[i].sfa_brush.paint_mode, + script_fu_brush_preview, + &script->arg_values[i].sfa_brush); + break; default: break; @@ -1250,6 +1314,26 @@ script_fu_pattern_preview(gchar *name, *pname = g_strdup(name); } +static void +script_fu_brush_preview(char * name, /* Name */ + gdouble opacity, /* opacity */ + gint spacing, /* spacing */ + gint paint_mode, /* paint_mode */ + gint width, /* width */ + gint height, /* height */ + gchar * mask_data, /* mask data */ + gint closing, /* dialog closing */ + gpointer udata/* user data */) +{ + SFBrush *brush = (SFBrush *)udata; + g_free(brush->name); + brush->name = g_strdup(name); + brush->opacity = opacity; + brush->spacing = spacing; + brush->paint_mode = paint_mode; +} + + static void script_fu_font_preview (GtkWidget *preview, @@ -1320,6 +1404,9 @@ script_fu_cleanup_widgets (SFScript *script) case SF_PATTERN: gimp_pattern_select_widget_close_popup(script->args_widgets[i]); break; + case SF_BRUSH: + gimp_brush_select_widget_close_popup(script->args_widgets[i]); + break; default: break; } @@ -1386,6 +1473,10 @@ script_fu_ok_callback (GtkWidget *widget, case SF_PATTERN: length += strlen (script->arg_values[i].sfa_pattern) + 3; break; + case SF_BRUSH: + length += strlen (script->arg_values[i].sfa_brush.name) + 3; + length += 36; /* Maximum size of three ints for opacity, spacing,mode*/ + break; default: break; } @@ -1452,6 +1543,15 @@ script_fu_ok_callback (GtkWidget *widget, g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"",script->arg_values[i].sfa_pattern); text = buffer; break; + case SF_BRUSH: + g_snprintf (buffer, MAX_STRING_LENGTH, + "'(\"%s\" %f %d %d)", + script->arg_values[i].sfa_brush.name, + script->arg_values[i].sfa_brush.opacity, + script->arg_values[i].sfa_brush.spacing, + script->arg_values[i].sfa_brush.paint_mode); + text = buffer; + break; default: break; } @@ -1689,6 +1789,13 @@ script_fu_reset_callback (GtkWidget *widget, case SF_PATTERN: gimp_pattern_select_widget_set_popup(script->args_widgets[i],script->arg_defaults[i].sfa_pattern); break; + case SF_BRUSH: + gimp_brush_select_widget_set_popup(script->args_widgets[i], + script->arg_defaults[i].sfa_brush.name, + script->arg_defaults[i].sfa_brush.opacity, + script->arg_defaults[i].sfa_brush.spacing, + script->arg_defaults[i].sfa_brush.paint_mode); + break; default: break; } diff --git a/plug-ins/script-fu/script-fu-scripts.c b/plug-ins/script-fu/script-fu-scripts.c index 71f6fa9d99..4dde55db2f 100644 --- a/plug-ins/script-fu/script-fu-scripts.c +++ b/plug-ins/script-fu/script-fu-scripts.c @@ -68,6 +68,15 @@ typedef struct gchar *fontname; } SFFont; +typedef struct +{ + gchar *name; + gdouble opacity; + gint spacing; + gint paint_mode; +} SFBrush; + + typedef union { gint32 sfa_image; @@ -80,6 +89,7 @@ typedef union SFAdjustment sfa_adjustment; SFFont sfa_font; gchar * sfa_pattern; + SFBrush sfa_brush; } SFArgValue; typedef struct @@ -175,6 +185,15 @@ static void script_fu_pattern_preview (gchar *name, gint closing, gpointer udata); +static void script_fu_brush_preview (char *, /* Name */ + gdouble, /* opacity */ + gint, /* spacing */ + gint, /* paint_mode */ + gint, /* width */ + gint, /* height */ + gchar *, /* mask data */ + gint, /* dialog closing */ + gpointer /* user data */); @@ -339,6 +358,7 @@ script_fu_add_script (LISP a) gdouble color[3]; LISP color_list; LISP adj_list; + LISP brush_list; gchar *menu_path = NULL; /* Check the length of a */ @@ -572,8 +592,30 @@ script_fu_add_script (LISP a) args[i + 1].description = script->arg_labels[i]; break; + case SF_BRUSH: + if (!TYPEP (car (a), tc_cons)) + return my_err ("script-fu-register: brush defaults must be a list", NIL); + brush_list = car (a); + script->arg_defaults[i].sfa_brush.name = g_strdup (get_c_string (car (brush_list))); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.opacity = get_c_double (car (brush_list)); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.spacing = get_c_long (car (brush_list)); + brush_list = cdr (brush_list); + script->arg_defaults[i].sfa_brush.paint_mode = get_c_long (car (brush_list)); + script->arg_values[i].sfa_brush = script->arg_defaults[i].sfa_brush; + /* Need this since we need a copy of the string + * in the values area. We could free it later but the + * default one must hang around. + */ + + script->arg_values[i].sfa_brush.name = g_strdup(script->arg_defaults[i].sfa_brush.name); + + args[i + 1].type = PARAM_STRING; + args[i + 1].name = "brush"; + args[i + 1].description = script->arg_labels[i]; break; - + default: break; } @@ -725,6 +767,9 @@ script_fu_script_proc (char *name, case SF_PATTERN: length += strlen (params[i + 1].data.d_string) + 3; break; + case SF_BRUSH: + length += strlen (params[i + 1].data.d_string) + 3; + break; default: break; } @@ -775,6 +820,10 @@ script_fu_script_proc (char *name, g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"", params[i + 1].data.d_string); text = buffer; break; + case SF_BRUSH: + g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"", params[i + 1].data.d_string); + text = buffer; + break; default: break; } @@ -871,6 +920,11 @@ script_fu_free_script (SFScript *script) case SF_PATTERN: g_free (script->arg_defaults[i].sfa_pattern); g_free (script->arg_values[i].sfa_pattern); + break; + case SF_BRUSH: + g_free (script->arg_defaults[i].sfa_brush.name); + g_free (script->arg_values[i].sfa_brush.name); + break; default: break; } @@ -1131,6 +1185,16 @@ script_fu_interface (SFScript *script) script_fu_pattern_preview, &script->arg_values[i].sfa_pattern); break; + case SF_BRUSH: + script->args_widgets[i] = + gimp_brush_select_widget("Script-fu brush Selection", + script->arg_values[i].sfa_brush.name, + script->arg_values[i].sfa_brush.opacity, + script->arg_values[i].sfa_brush.spacing, + script->arg_values[i].sfa_brush.paint_mode, + script_fu_brush_preview, + &script->arg_values[i].sfa_brush); + break; default: break; @@ -1250,6 +1314,26 @@ script_fu_pattern_preview(gchar *name, *pname = g_strdup(name); } +static void +script_fu_brush_preview(char * name, /* Name */ + gdouble opacity, /* opacity */ + gint spacing, /* spacing */ + gint paint_mode, /* paint_mode */ + gint width, /* width */ + gint height, /* height */ + gchar * mask_data, /* mask data */ + gint closing, /* dialog closing */ + gpointer udata/* user data */) +{ + SFBrush *brush = (SFBrush *)udata; + g_free(brush->name); + brush->name = g_strdup(name); + brush->opacity = opacity; + brush->spacing = spacing; + brush->paint_mode = paint_mode; +} + + static void script_fu_font_preview (GtkWidget *preview, @@ -1320,6 +1404,9 @@ script_fu_cleanup_widgets (SFScript *script) case SF_PATTERN: gimp_pattern_select_widget_close_popup(script->args_widgets[i]); break; + case SF_BRUSH: + gimp_brush_select_widget_close_popup(script->args_widgets[i]); + break; default: break; } @@ -1386,6 +1473,10 @@ script_fu_ok_callback (GtkWidget *widget, case SF_PATTERN: length += strlen (script->arg_values[i].sfa_pattern) + 3; break; + case SF_BRUSH: + length += strlen (script->arg_values[i].sfa_brush.name) + 3; + length += 36; /* Maximum size of three ints for opacity, spacing,mode*/ + break; default: break; } @@ -1452,6 +1543,15 @@ script_fu_ok_callback (GtkWidget *widget, g_snprintf (buffer, MAX_STRING_LENGTH, "\"%s\"",script->arg_values[i].sfa_pattern); text = buffer; break; + case SF_BRUSH: + g_snprintf (buffer, MAX_STRING_LENGTH, + "'(\"%s\" %f %d %d)", + script->arg_values[i].sfa_brush.name, + script->arg_values[i].sfa_brush.opacity, + script->arg_values[i].sfa_brush.spacing, + script->arg_values[i].sfa_brush.paint_mode); + text = buffer; + break; default: break; } @@ -1689,6 +1789,13 @@ script_fu_reset_callback (GtkWidget *widget, case SF_PATTERN: gimp_pattern_select_widget_set_popup(script->args_widgets[i],script->arg_defaults[i].sfa_pattern); break; + case SF_BRUSH: + gimp_brush_select_widget_set_popup(script->args_widgets[i], + script->arg_defaults[i].sfa_brush.name, + script->arg_defaults[i].sfa_brush.opacity, + script->arg_defaults[i].sfa_brush.spacing, + script->arg_defaults[i].sfa_brush.paint_mode); + break; default: break; } diff --git a/plug-ins/script-fu/script-fu.c b/plug-ins/script-fu/script-fu.c index 03a5f36b90..d718418a25 100644 --- a/plug-ins/script-fu/script-fu.c +++ b/plug-ins/script-fu/script-fu.c @@ -477,6 +477,7 @@ init_constants () setvar (cintern ("SF-ADJUSTMENT"), flocons (SF_ADJUSTMENT), NIL); setvar (cintern ("SF-FONT"), flocons (SF_FONT), NIL); setvar (cintern ("SF-PATTERN"), flocons (SF_PATTERN), NIL); + setvar (cintern ("SF-BRUSH"), flocons (SF_BRUSH), NIL); /* for SF_ADJUSTMENT */ setvar (cintern ("SF-SLIDER"), flocons (SF_SLIDER), NIL); diff --git a/plug-ins/script-fu/scripts/3d-outline.scm b/plug-ins/script-fu/scripts/3d-outline.scm index 5bc19a02c8..121252fcad 100644 --- a/plug-ins/script-fu/scripts/3d-outline.scm +++ b/plug-ins/script-fu/scripts/3d-outline.scm @@ -81,7 +81,7 @@ "Hrvoje Horvat" "07 April, 1998" "" - SF-STRING "Text Pattern" "Parque #1" + SF-PATTERN "Pattern" "Parque #1" SF-STRING "Text String" "The Gimp" SF-VALUE "Font Size (in pixels)" "100" SF-STRING "Font" "Roostheavy" diff --git a/plug-ins/script-fu/scripts/test-sphere.scm b/plug-ins/script-fu/scripts/test-sphere.scm index e76981491d..9aae567b3f 100644 --- a/plug-ins/script-fu/scripts/test-sphere.scm +++ b/plug-ins/script-fu/scripts/test-sphere.scm @@ -30,7 +30,7 @@ ; -(define (script-fu-test-sphere radius light shadow bg-color sphere-color text pattern font size) +(define (script-fu-test-sphere radius light shadow bg-color sphere-color brush text pattern font size) (let* ((width (* radius 3.75)) (height (* radius 2.5)) (img (car (gimp-image-new width height RGB))) @@ -97,6 +97,7 @@ SF-TOGGLE "Shadow" TRUE SF-COLOR "Background Color" '(255 255 255) SF-COLOR "Sphere Color" '(255 0 0) + SF-BRUSH "Brush" '("Circle (03)" 100.0 44 0) SF-STRING "Text" "Script-Fu rocks!" SF-PATTERN "Pattern" "Maple Leaves" SF-FONT "Font" "-freefont-agate-normal-r-normal-*-24-*-*-*-p-*-*-*" diff --git a/plug-ins/script-fu/scripts/trochoid.scm b/plug-ins/script-fu/scripts/trochoid.scm index 0638d833f5..ceaf0c245d 100644 --- a/plug-ins/script-fu/scripts/trochoid.scm +++ b/plug-ins/script-fu/scripts/trochoid.scm @@ -8,7 +8,7 @@ ;;; Code: (define (script-fu-trochoid base-radius-f wheel-radius-f pen-pos hue-rate - erase-before-draw) + erase-before-draw brush-details) (if 'not-guile (define modulo fmod)) (define (floor x) (- x (fmod x 1))) (define *prime-table* @@ -251,7 +251,7 @@ (define (trochoid-rotate-gear total-distance img use-this-drawable center-x center-y base-radius wheel-radius pen-pos hue-rate - layer-paint-mode stroke-overwrite) + layer-paint-mode stroke-overwrite brush-details) (let* ((rad-of-wheel 0) (steps-for-circle 100.0) (wheel-spin (/ total-distance (abs wheel-radius))) @@ -331,6 +331,7 @@ background-color stroke-overwrite brush-opacity paint-mode)))) ;; start of script-fu-trochoid + (gimp-brushes-set-brush (car brush-details)) (let* ((base-radius (floor (abs base-radius-f))) ; to int (wheel-radius (floor wheel-radius-f)) ; to int (total-step-num (if (or (= 0 base-radius) (= 0 wheel-radius)) @@ -374,7 +375,7 @@ (trochoid-rotate-gear total-step-num img the-layer (/ drawable-size 2) (/ drawable-size 2) base-radius wheel-radius pen-pos hue-rate - layer-paint-mode (= 0 erase-before-draw))) + layer-paint-mode (= 0 erase-before-draw) brush-details)) (gimp-palette-set-foreground old-rgb) (gimp-brushes-set-paint-mode old-paint-mode) (gimp-image-enable-undo img) @@ -392,6 +393,7 @@ SF-ADJUSTMENT "Pen rad./wheel rad. [0.0:1.0]" '(0.8 0 1 .01 .01 2 0) SF-ADJUSTMENT "Hue Rate" '(1.0 0 1 .01 .01 2 0) SF-VALUE "Erase before draw? [0/1]" "0" + SF-BRUSH "Use brush" '("Circle (05)" 1.0 44 2) ) ;;; trochoid.scm ends here