diff options
Diffstat (limited to '')
-rw-r--r-- | app/tools/tool_manager.c | 966 |
1 files changed, 966 insertions, 0 deletions
diff --git a/app/tools/tool_manager.c b/app/tools/tool_manager.c new file mode 100644 index 0000000..3b8bc88 --- /dev/null +++ b/app/tools/tool_manager.c @@ -0,0 +1,966 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "libgimpconfig/gimpconfig.h" + +#include "tools-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimplist.h" +#include "core/gimpimage.h" +#include "core/gimptoolgroup.h" +#include "core/gimptoolinfo.h" +#include "core/gimptooloptions.h" +#include "core/gimptoolpreset.h" + +#include "display/gimpdisplay.h" + +#include "widgets/gimpcairo-wilber.h" + +#include "gimptool.h" +#include "gimptoolcontrol.h" +#include "tool_manager.h" + + +typedef struct _GimpToolManager GimpToolManager; + +struct _GimpToolManager +{ + Gimp *gimp; + + GimpTool *active_tool; + GSList *tool_stack; + + GimpToolGroup *active_tool_group; + + GQuark image_clean_handler_id; + GQuark image_dirty_handler_id; + GQuark image_saving_handler_id; +}; + + +/* local function prototypes */ + +static void tool_manager_set (Gimp *gimp, + GimpToolManager *tool_manager); +static GimpToolManager * tool_manager_get (Gimp *gimp); + +static void tool_manager_select_tool (GimpToolManager *tool_manager, + GimpTool *tool); + +static void tool_manager_set_active_tool_group (GimpToolManager *tool_manager, + GimpToolGroup *tool_group); + +static void tool_manager_tool_changed (GimpContext *user_context, + GimpToolInfo *tool_info, + GimpToolManager *tool_manager); +static void tool_manager_preset_changed (GimpContext *user_context, + GimpToolPreset *preset, + GimpToolManager *tool_manager); +static void tool_manager_image_clean_dirty (GimpImage *image, + GimpDirtyMask dirty_mask, + GimpToolManager *tool_manager); +static void tool_manager_image_saving (GimpImage *image, + GimpToolManager *tool_manager); +static void tool_manager_tool_ancestry_changed (GimpToolInfo *tool_info, + GimpToolManager *tool_manager); +static void tool_manager_group_active_tool_changed (GimpToolGroup *tool_group, + GimpToolManager *tool_manager); + +static void tool_manager_cast_spell (GimpToolInfo *tool_info); + + +/* public functions */ + +void +tool_manager_init (Gimp *gimp) +{ + GimpToolManager *tool_manager; + GimpContext *user_context; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = g_slice_new0 (GimpToolManager); + + tool_manager->gimp = gimp; + tool_manager->active_tool = NULL; + tool_manager->tool_stack = NULL; + tool_manager->active_tool_group = NULL; + tool_manager->image_clean_handler_id = 0; + tool_manager->image_dirty_handler_id = 0; + tool_manager->image_saving_handler_id = 0; + + tool_manager_set (gimp, tool_manager); + + tool_manager->image_clean_handler_id = + gimp_container_add_handler (gimp->images, "clean", + G_CALLBACK (tool_manager_image_clean_dirty), + tool_manager); + + tool_manager->image_dirty_handler_id = + gimp_container_add_handler (gimp->images, "dirty", + G_CALLBACK (tool_manager_image_clean_dirty), + tool_manager); + + tool_manager->image_saving_handler_id = + gimp_container_add_handler (gimp->images, "saving", + G_CALLBACK (tool_manager_image_saving), + tool_manager); + + user_context = gimp_get_user_context (gimp); + + g_signal_connect (user_context, "tool-changed", + G_CALLBACK (tool_manager_tool_changed), + tool_manager); + g_signal_connect (user_context, "tool-preset-changed", + G_CALLBACK (tool_manager_preset_changed), + tool_manager); + + tool_manager_tool_changed (user_context, + gimp_context_get_tool (user_context), + tool_manager); +} + +void +tool_manager_exit (Gimp *gimp) +{ + GimpToolManager *tool_manager; + GimpContext *user_context; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + tool_manager_set (gimp, NULL); + + user_context = gimp_get_user_context (gimp); + + g_signal_handlers_disconnect_by_func (user_context, + tool_manager_tool_changed, + tool_manager); + g_signal_handlers_disconnect_by_func (user_context, + tool_manager_preset_changed, + tool_manager); + + gimp_container_remove_handler (gimp->images, + tool_manager->image_clean_handler_id); + gimp_container_remove_handler (gimp->images, + tool_manager->image_dirty_handler_id); + gimp_container_remove_handler (gimp->images, + tool_manager->image_saving_handler_id); + + if (tool_manager->active_tool) + { + g_signal_handlers_disconnect_by_func ( + tool_manager->active_tool->tool_info, + tool_manager_tool_ancestry_changed, + tool_manager); + + g_clear_object (&tool_manager->active_tool); + } + + tool_manager_set_active_tool_group (tool_manager, NULL); + + g_slice_free (GimpToolManager, tool_manager); +} + +GimpTool * +tool_manager_get_active (Gimp *gimp) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + + tool_manager = tool_manager_get (gimp); + + return tool_manager->active_tool; +} + +void +tool_manager_push_tool (Gimp *gimp, + GimpTool *tool) +{ + GimpToolManager *tool_manager; + GimpDisplay *focus_display = NULL; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + g_return_if_fail (GIMP_IS_TOOL (tool)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + focus_display = tool_manager->active_tool->focus_display; + + tool_manager->tool_stack = g_slist_prepend (tool_manager->tool_stack, + tool_manager->active_tool); + + g_object_ref (tool_manager->tool_stack->data); + } + + tool_manager_select_tool (tool_manager, tool); + + if (focus_display) + tool_manager_focus_display_active (gimp, focus_display); +} + +void +tool_manager_pop_tool (Gimp *gimp) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->tool_stack) + { + GimpTool *tool = tool_manager->tool_stack->data; + + tool_manager->tool_stack = g_slist_remove (tool_manager->tool_stack, + tool); + + tool_manager_select_tool (tool_manager, tool); + + g_object_unref (tool); + } +} + +gboolean +tool_manager_initialize_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); + g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + GimpTool *tool = tool_manager->active_tool; + + if (gimp_tool_initialize (tool, display)) + { + GimpImage *image = gimp_display_get_image (display); + + tool->drawable = gimp_image_get_active_drawable (image); + + return TRUE; + } + } + + return FALSE; +} + +void +tool_manager_control_active (Gimp *gimp, + GimpToolAction action, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + GimpTool *tool = tool_manager->active_tool; + + if (display && gimp_tool_has_display (tool, display)) + { + gimp_tool_control (tool, action, display); + } + else if (action == GIMP_TOOL_ACTION_HALT) + { + if (gimp_tool_control_is_active (tool->control)) + gimp_tool_control_halt (tool->control); + } + } +} + +void +tool_manager_button_press_active (Gimp *gimp, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonPressType press_type, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + gimp_tool_button_press (tool_manager->active_tool, + coords, time, state, press_type, + display); + } +} + +void +tool_manager_button_release_active (Gimp *gimp, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + gimp_tool_button_release (tool_manager->active_tool, + coords, time, state, + display); + } +} + +void +tool_manager_motion_active (Gimp *gimp, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + gimp_tool_motion (tool_manager->active_tool, + coords, time, state, + display); + } +} + +gboolean +tool_manager_key_press_active (Gimp *gimp, + GdkEventKey *kevent, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_key_press (tool_manager->active_tool, + kevent, + display); + } + + return FALSE; +} + +gboolean +tool_manager_key_release_active (Gimp *gimp, + GdkEventKey *kevent, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_key_release (tool_manager->active_tool, + kevent, + display); + } + + return FALSE; +} + +void +tool_manager_focus_display_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool && + ! gimp_tool_control_is_active (tool_manager->active_tool->control)) + { + gimp_tool_set_focus_display (tool_manager->active_tool, + display); + } +} + +void +tool_manager_modifier_state_active (Gimp *gimp, + GdkModifierType state, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool && + ! gimp_tool_control_is_active (tool_manager->active_tool->control)) + { + gimp_tool_set_modifier_state (tool_manager->active_tool, + state, + display); + } +} + +void +tool_manager_active_modifier_state_active (Gimp *gimp, + GdkModifierType state, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + gimp_tool_set_active_modifier_state (tool_manager->active_tool, + state, + display); + } +} + +void +tool_manager_oper_update_active (Gimp *gimp, + const GimpCoords *coords, + GdkModifierType state, + gboolean proximity, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool && + ! gimp_tool_control_is_active (tool_manager->active_tool->control)) + { + gimp_tool_oper_update (tool_manager->active_tool, + coords, state, proximity, + display); + } +} + +void +tool_manager_cursor_update_active (Gimp *gimp, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool && + ! gimp_tool_control_is_active (tool_manager->active_tool->control)) + { + gimp_tool_cursor_update (tool_manager->active_tool, + coords, state, + display); + } +} + +const gchar * +tool_manager_can_undo_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_can_undo (tool_manager->active_tool, + display); + } + + return NULL; +} + +const gchar * +tool_manager_can_redo_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_can_redo (tool_manager->active_tool, + display); + } + + return NULL; +} + +gboolean +tool_manager_undo_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_undo (tool_manager->active_tool, + display); + } + + return FALSE; +} + +gboolean +tool_manager_redo_active (Gimp *gimp, + GimpDisplay *display) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_redo (tool_manager->active_tool, + display); + } + + return FALSE; +} + +GimpUIManager * +tool_manager_get_popup_active (Gimp *gimp, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display, + const gchar **ui_path) +{ + GimpToolManager *tool_manager; + + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); + + tool_manager = tool_manager_get (gimp); + + if (tool_manager->active_tool) + { + return gimp_tool_get_popup (tool_manager->active_tool, + coords, state, + display, + ui_path); + } + + return NULL; +} + + +/* private functions */ + +static GQuark tool_manager_quark = 0; + +static void +tool_manager_set (Gimp *gimp, + GimpToolManager *tool_manager) +{ + if (! tool_manager_quark) + tool_manager_quark = g_quark_from_static_string ("gimp-tool-manager"); + + g_object_set_qdata (G_OBJECT (gimp), tool_manager_quark, tool_manager); +} + +static GimpToolManager * +tool_manager_get (Gimp *gimp) +{ + if (! tool_manager_quark) + tool_manager_quark = g_quark_from_static_string ("gimp-tool-manager"); + + return g_object_get_qdata (G_OBJECT (gimp), tool_manager_quark); +} + +static void +tool_manager_select_tool (GimpToolManager *tool_manager, + GimpTool *tool) +{ + Gimp *gimp = tool_manager->gimp; + + /* reset the previously selected tool, but only if it is not only + * temporarily pushed to the tool stack + */ + if (tool_manager->active_tool) + { + if (! tool_manager->tool_stack || + tool_manager->active_tool != tool_manager->tool_stack->data) + { + GimpTool *active_tool = tool_manager->active_tool; + GimpDisplay *display; + + /* NULL image returns any display (if there is any) */ + display = gimp_tool_has_image (active_tool, NULL); + + tool_manager_control_active (gimp, GIMP_TOOL_ACTION_HALT, display); + tool_manager_focus_display_active (gimp, NULL); + } + } + + g_set_object (&tool_manager->active_tool, tool); +} + +static void +tool_manager_set_active_tool_group (GimpToolManager *tool_manager, + GimpToolGroup *tool_group) +{ + if (tool_group != tool_manager->active_tool_group) + { + if (tool_manager->active_tool_group) + { + g_signal_handlers_disconnect_by_func ( + tool_manager->active_tool_group, + tool_manager_group_active_tool_changed, + tool_manager); + } + + g_set_weak_pointer (&tool_manager->active_tool_group, tool_group); + + if (tool_manager->active_tool_group) + { + g_signal_connect ( + tool_manager->active_tool_group, "active-tool-changed", + G_CALLBACK (tool_manager_group_active_tool_changed), + tool_manager); + } + } +} + +static void +tool_manager_tool_changed (GimpContext *user_context, + GimpToolInfo *tool_info, + GimpToolManager *tool_manager) +{ + GimpTool *new_tool = NULL; + + if (! tool_info) + return; + + if (! g_type_is_a (tool_info->tool_type, GIMP_TYPE_TOOL)) + { + g_warning ("%s: tool_info->tool_type is no GimpTool subclass", + G_STRFUNC); + return; + } + + /* FIXME: gimp_busy HACK */ + if (user_context->gimp->busy) + { + /* there may be contexts waiting for the user_context's "tool-changed" + * signal, so stop emitting it. + */ + g_signal_stop_emission_by_name (user_context, "tool-changed"); + + if (G_TYPE_FROM_INSTANCE (tool_manager->active_tool) != + tool_info->tool_type) + { + g_signal_handlers_block_by_func (user_context, + tool_manager_tool_changed, + tool_manager); + + /* explicitly set the current tool */ + gimp_context_set_tool (user_context, + tool_manager->active_tool->tool_info); + + g_signal_handlers_unblock_by_func (user_context, + tool_manager_tool_changed, + tool_manager); + } + + return; + } + + g_return_if_fail (tool_manager->tool_stack == NULL); + + if (tool_manager->active_tool) + { + GimpTool *active_tool = tool_manager->active_tool; + GimpDisplay *display; + + /* NULL image returns any display (if there is any) */ + display = gimp_tool_has_image (active_tool, NULL); + + /* commit the old tool's operation before creating the new tool + * because creating a tool might mess with the old tool's + * options (old and new tool might be the same) + */ + if (display) + tool_manager_control_active (user_context->gimp, GIMP_TOOL_ACTION_COMMIT, + display); + + g_signal_handlers_disconnect_by_func (active_tool->tool_info, + tool_manager_tool_ancestry_changed, + tool_manager); + } + + g_signal_connect (tool_info, "ancestry-changed", + G_CALLBACK (tool_manager_tool_ancestry_changed), + tool_manager); + + tool_manager_tool_ancestry_changed (tool_info, tool_manager); + + new_tool = g_object_new (tool_info->tool_type, + "tool-info", tool_info, + NULL); + + tool_manager_select_tool (tool_manager, new_tool); + + g_object_unref (new_tool); + + /* ??? */ + tool_manager_cast_spell (tool_info); +} + +static void +tool_manager_copy_tool_options (GObject *src, + GObject *dest) +{ + GList *diff; + + diff = gimp_config_diff (src, dest, G_PARAM_READWRITE); + + if (diff) + { + GList *list; + + g_object_freeze_notify (dest); + + for (list = diff; list; list = list->next) + { + GParamSpec *prop_spec = list->data; + + if (g_type_is_a (prop_spec->owner_type, GIMP_TYPE_TOOL_OPTIONS) && + ! (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + GValue value = G_VALUE_INIT; + + g_value_init (&value, prop_spec->value_type); + + g_object_get_property (src, prop_spec->name, &value); + g_object_set_property (dest, prop_spec->name, &value); + + g_value_unset (&value); + } + } + + g_object_thaw_notify (dest); + + g_list_free (diff); + } +} + +static void +tool_manager_preset_changed (GimpContext *user_context, + GimpToolPreset *preset, + GimpToolManager *tool_manager) +{ + GimpToolInfo *preset_tool; + + if (! preset || user_context->gimp->busy) + return; + + preset_tool = gimp_context_get_tool (GIMP_CONTEXT (preset->tool_options)); + + /* first, select the preset's tool, even if it's already the active + * tool + */ + gimp_context_set_tool (user_context, preset_tool); + + /* then, copy the context properties the preset remembers, possibly + * changing some tool options due to the "link brush stuff to brush + * defaults" settings in gimptooloptions.c + */ + gimp_context_copy_properties (GIMP_CONTEXT (preset->tool_options), + user_context, + gimp_tool_preset_get_prop_mask (preset)); + + /* finally, copy all tool options properties, overwriting any + * changes resulting from setting the context properties above, we + * really want exactly what is in the preset and nothing else + */ + tool_manager_copy_tool_options (G_OBJECT (preset->tool_options), + G_OBJECT (preset_tool->tool_options)); +} + +static void +tool_manager_image_clean_dirty (GimpImage *image, + GimpDirtyMask dirty_mask, + GimpToolManager *tool_manager) +{ + GimpTool *tool = tool_manager->active_tool; + + if (tool && + ! gimp_tool_control_get_preserve (tool->control) && + (gimp_tool_control_get_dirty_mask (tool->control) & dirty_mask)) + { + GimpDisplay *display = gimp_tool_has_image (tool, image); + + if (display) + { + tool_manager_control_active ( + image->gimp, + gimp_tool_control_get_dirty_action (tool->control), + display); + } + } +} + +static void +tool_manager_image_saving (GimpImage *image, + GimpToolManager *tool_manager) +{ + GimpTool *tool = tool_manager->active_tool; + + if (tool && + ! gimp_tool_control_get_preserve (tool->control)) + { + GimpDisplay *display = gimp_tool_has_image (tool, image); + + if (display) + tool_manager_control_active (image->gimp, GIMP_TOOL_ACTION_COMMIT, + display); + } +} + +static void +tool_manager_tool_ancestry_changed (GimpToolInfo *tool_info, + GimpToolManager *tool_manager) +{ + GimpViewable *parent; + + parent = gimp_viewable_get_parent (GIMP_VIEWABLE (tool_info)); + + if (parent) + { + gimp_tool_group_set_active_tool_info (GIMP_TOOL_GROUP (parent), + tool_info); + } + + tool_manager_set_active_tool_group (tool_manager, GIMP_TOOL_GROUP (parent)); +} + +static void +tool_manager_group_active_tool_changed (GimpToolGroup *tool_group, + GimpToolManager *tool_manager) +{ + gimp_context_set_tool (tool_manager->gimp->user_context, + gimp_tool_group_get_active_tool_info (tool_group)); +} + +static void +tool_manager_cast_spell (GimpToolInfo *tool_info) +{ + typedef struct + { + const gchar *sequence; + GCallback func; + } Spell; + + static const Spell spells[] = + { + { .sequence = "gimp-warp-tool\0" + "gimp-iscissors-tool\0" + "gimp-gradient-tool\0" + "gimp-vector-tool\0" + "gimp-ellipse-select-tool\0" + "gimp-rect-select-tool\0", + .func = gimp_cairo_wilber_toggle_pointer_eyes + } + }; + + static const gchar *spell_progress[G_N_ELEMENTS (spells)]; + const gchar *tool_name; + gint i; + + tool_name = gimp_object_get_name (GIMP_OBJECT (tool_info)); + + for (i = 0; i < G_N_ELEMENTS (spells); i++) + { + if (! spell_progress[i]) + spell_progress[i] = spells[i].sequence; + + while (spell_progress[i]) + { + if (! strcmp (tool_name, spell_progress[i])) + { + spell_progress[i] += strlen (spell_progress[i]) + 1; + + if (! *spell_progress[i]) + { + spell_progress[i] = NULL; + + spells[i].func (); + } + + break; + } + else + { + if (spell_progress[i] == spells[i].sequence) + spell_progress[i] = NULL; + else + spell_progress[i] = spells[i].sequence; + } + } + } +} |