[gimp-gap] edit movepath settings support via storyboard
- From: Wolfgang Hofer <wolfgangh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp-gap] edit movepath settings support via storyboard
- Date: Sun, 8 May 2011 16:53:56 +0000 (UTC)
commit 27509333212c24847a842b45227247e1d8529985
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date: Sun May 8 18:51:33 2011 +0200
edit movepath settings support via storyboard
ChangeLog | 20 ++
gap/gap_lib.c | 40 +++
gap/gap_lib.h | 1 +
gap/gap_mov_dialog.c | 740 ++++++++++++++++++++++++++++++++++-------
gap/gap_mov_dialog.h | 11 +
gap/gap_mov_exec.c | 89 ++++--
gap/gap_story_att_trans_dlg.c | 253 ++++++++++++++-
gap/gap_story_dialog.c | 43 ++-
gap/gap_story_main.h | 17 +-
gap/gap_story_undo.c | 336 ++++++++++++++++++-
gap/gap_story_undo.h | 4 +
gap/gap_story_undo_types.h | 24 +-
12 files changed, 1403 insertions(+), 175 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f48fccb..ba66a01 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-05-08 Wolfgang Hofer <hof gimp org>
+
+- added edit button in the Storyboard attributes dialog
+ to pop up a movepath edit dialog window
+ for creation and edit of movepath settings.
+
+- handle undo / redo for edited movepath xml paramter file content
+ when edited via the new edit button in the Storyboard attributes dialog
+
+ * gap/gap_lib.c [.h]
+ * gap/gap_mov_dialog.c [.h]
+ * gap/gap_mov_exec.c
+ * gap/gap_story_att_trans_dlg.c
+ * gap/gap_story_main.h
+ * gap/gap_story_dialog.c
+ * gap/gap_story_undo.c [.h]
+ * gap/gap_story_undo_types.h
+
+
+
2011-04-27 Wolfgang Hofer <hof gimp org>
- fixed a bug in procedure gap_mov_xml_par_save that did write an invalid
diff --git a/gap/gap_lib.c b/gap/gap_lib.c
index 04fcf9d..1fdfdbe 100644
--- a/gap/gap_lib.c
+++ b/gap/gap_lib.c
@@ -1353,6 +1353,46 @@ gap_lib_alloc_ainfo_from_name(const char *imagename, GimpRunMode run_mode)
/* ============================================================================
+ * gap_lib_alloc_ainfo_unsaved_image
+ *
+ * allocate and init an ainfo structure from unsaved image.
+ * ============================================================================
+ */
+GapAnimInfo *
+gap_lib_alloc_ainfo_unsaved_image(gint32 image_id)
+{
+ GapAnimInfo *l_ainfo_ptr;
+
+ l_ainfo_ptr = (GapAnimInfo*)g_malloc(sizeof(GapAnimInfo));
+ if(l_ainfo_ptr == NULL) return(NULL);
+
+ l_ainfo_ptr->basename = NULL;
+ l_ainfo_ptr->new_filename = NULL;
+ l_ainfo_ptr->extension = NULL;
+ l_ainfo_ptr->image_id = image_id;
+
+ l_ainfo_ptr->old_filename = NULL;
+
+ l_ainfo_ptr->ainfo_type = GAP_AINFO_IMAGE;
+ l_ainfo_ptr->extension = NULL;
+
+ l_ainfo_ptr->frame_nr = 0;
+ l_ainfo_ptr->curr_frame_nr = 0;
+ l_ainfo_ptr->first_frame_nr = -1;
+ l_ainfo_ptr->last_frame_nr = -1;
+ l_ainfo_ptr->frame_cnt = 0;
+ l_ainfo_ptr->run_mode = GIMP_RUN_NONINTERACTIVE;
+ l_ainfo_ptr->frame_nr_before_curr_frame_nr = -1; /* -1 if no frame found before curr_frame_nr */
+ l_ainfo_ptr->frame_nr_after_curr_frame_nr = -1; /* -1 if no frame found after curr_frame_nr */
+
+
+ return(l_ainfo_ptr);
+
+} /* end gap_lib_alloc_ainfo_unsaved_image */
+
+
+
+/* ============================================================================
* gap_lib_alloc_ainfo
*
* allocate and init an ainfo structure from the given image.
diff --git a/gap/gap_lib.h b/gap/gap_lib.h
index 8666384..8277542 100644
--- a/gap/gap_lib.h
+++ b/gap/gap_lib.h
@@ -63,6 +63,7 @@ char* gap_lib_alloc_basename(const char *imagename, long *number);
char* gap_lib_alloc_extension(const char *imagename);
GapAnimInfo* gap_lib_alloc_ainfo_from_name(const char *imagename, GimpRunMode run_mode);
GapAnimInfo* gap_lib_alloc_ainfo(gint32 image_id, GimpRunMode run_mode);
+GapAnimInfo* gap_lib_alloc_ainfo_unsaved_image(gint32 image_id);
int gap_lib_dir_ainfo(GapAnimInfo *ainfo_ptr);
int gap_lib_chk_framerange(GapAnimInfo *ainfo_ptr);
int gap_lib_chk_framechange(GapAnimInfo *ainfo_ptr);
diff --git a/gap/gap_mov_dialog.c b/gap/gap_mov_dialog.c
old mode 100644
new mode 100755
index d674249..5deed7b
--- a/gap/gap_mov_dialog.c
+++ b/gap/gap_mov_dialog.c
@@ -296,13 +296,55 @@ typedef struct
GtkWidget *segLengthLabel;
GtkWidget *segSpeedLabel;
+ /* The movepath dialog has a RecordOnlyMode that is intended
+ * to edit and save parameter settings only.
+ *
+ * TRUE
+ * (typically called from the storyboard for update xml file settings)
+ * - invoke from any image is tolerated
+ * - rendering of frames is DISABLED
+ * (Animated preview rendering is allowed)
+ * - frame range limits are 1 upto 999999.
+ * - the moving object (source image) is fixed by the caller,
+ * stepmode is restricted to GAP_STEP_NONE
+ * - OK button triggers automatic save of the settings
+ * to XML file in overwrite mode without confirm question
+ * (but does not render anything)
+ *
+ * FALSE
+ * (typically called as PDB procedure for productive render purpose)
+ * - invoke is limited to an image that represents a frame
+ * (image with gap typical number part in the filename)
+ * - rendering of frames is enabled
+ * - frame range limits constraint to first and last frame number
+ * found in frame imagefilenames on disc.
+ * - the moving object (source image) can be selected by the user
+ * from the list of opened images in the current gimp session:
+ * all stepmodes are available.
+ *
+ */
+ gboolean isRecordOnlyMode;
+ gboolean isStandaloneGui;
+
+ t_close_movepath_edit_callback_fptr close_fptr;
+ gpointer callback_data;
+
+ gchar xml_paramfile[GAP_MOVPATH_XML_FILENAME_MAX_LENGTH];
+
} t_mov_gui_stuff;
-/* Declare a local function.
+/* Declare local functions.
*/
-
- long gap_mov_dlg_move_dialog (GapMovData *mov_ptr);
+static long p_gap_mov_dlg_move_dialog(t_mov_gui_stuff *mgp
+ , GapMovData *mov_ptr
+ , gboolean isRecordOnlyMode
+ , gboolean isStandaloneGui
+ , t_close_movepath_edit_callback_fptr close_fptr
+ , gpointer callback_data
+ , gint32 nframes
+ );
+static void p_free_mgp_resources(t_mov_gui_stuff *mgp);
static void p_update_point_index_text (t_mov_gui_stuff *mgp);
static void p_set_sensitivity_by_adjustment(GtkAdjustment *adj, gboolean sensitive);
static void p_accel_widget_sensitivity(t_mov_gui_stuff *mgp);
@@ -479,31 +521,207 @@ static t_mov_interface mov_int =
/* ============================================================================
- **********************
- * *
- * Dialog interface *
- * *
- **********************
+ ***********************
+ * *
+ * Dialog interfaces *
+ * *
+ ***********************
* ============================================================================
*/
+long
+gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
+{
+ t_mov_gui_stuff *mgp;
+ gboolean isRecordOnlyMode;
+ gboolean isStandaloneGui;
+
+
+ mgp = g_new( t_mov_gui_stuff, 1 );
+ mgp->shell = NULL;
+ mgp->pointfile_name = NULL;
+
+ isRecordOnlyMode = FALSE;
+ isStandaloneGui = TRUE;
+ p_gap_mov_dlg_move_dialog(mgp, mov_ptr, isRecordOnlyMode, isStandaloneGui, NULL, NULL, 1);
+ p_free_mgp_resources(mgp);
+ g_free(mgp);
+
+
+ if(mov_int.run == TRUE)
+ {
+ return 0; /* OK */
+ }
+ return -1; /* Cancel or error occured */
+
+}
+
-long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
+/* ----------------------------------
+ * gap_mov_dlg_edit_movepath_dialog
+ * ----------------------------------
+ * This procedure creates and shows the movepath edit dialog as widget and returns
+ * the created widget.
+ * The caller shall provide close_fptr and callback_data. This function callback
+ * will be called on close of the widget.
+ * Note that resources refered by pvals, ainfo_ptr xml_paramfile
+ * must not be freed until the edit dialog is closed.
+ *
+ * This procedure is typically called be the Storyboard transition attributes dialog
+ */
+GtkWidget *
+gap_mov_dlg_edit_movepath_dialog (gint32 frame_image_id, gint32 drawable_id
+ , const char *xml_paramfile
+ , GapAnimInfo *ainfo_ptr
+ , GapMovValues *pvals_edit
+ , t_close_movepath_edit_callback_fptr close_fptr
+ , gpointer callback_data
+ , gint32 nframes
+ )
{
- GimpDrawable *l_drawable_ptr;
- gint l_first, l_last;
- char *l_str;
t_mov_gui_stuff *mgp;
+ gboolean isRecordOnlyMode;
+ gboolean isStandaloneGui;
+ GapMovData l_mov_data;
+ gboolean isXmlLoadOk;
+ gboolean l_rc;
+
+ if(gap_debug)
+ {
+ printf("gap_mov_dlg_edit_movepath_dialog START frame_image_id:%d drawable_id:%d xml:%s\n"
+ " fptr:%d data:%d\n"
+ ,(int)frame_image_id
+ ,(int)drawable_id
+ ,xml_paramfile
+ ,(int)close_fptr
+ ,(int)callback_data
+ );
+ }
+
+ isRecordOnlyMode = TRUE;
+ isStandaloneGui = FALSE;
+
mgp = g_new( t_mov_gui_stuff, 1 );
+ mgp->shell = NULL;
+ mgp->pointfile_name = NULL;
+
+
+ pvals = pvals_edit;
+
+ pvals->dst_image_id = frame_image_id;
+ pvals->bbp_pv = gap_bluebox_bbp_new(-1);
+
+ isXmlLoadOk = FALSE;
+ mgp->xml_paramfile[0] = '\0';
+ if(xml_paramfile[0] != '\0')
+ {
+ g_snprintf(mgp->xml_paramfile, sizeof(mgp->xml_paramfile), "%s", xml_paramfile);
+ mgp->pointfile_name = g_strdup_printf("%s", xml_paramfile);
+
+ /* attempt to init settings in case the xml_paramfile
+ * already contains valid settings
+ */
+ isXmlLoadOk = gap_mov_xml_par_load(xml_paramfile
+ , pvals
+ , gimp_image_width(frame_image_id)
+ , gimp_image_height(frame_image_id)
+ );
+ }
+
+ pvals->src_image_id = gimp_drawable_get_image(drawable_id);
+ pvals->src_layer_id = drawable_id;
+
+ if(isXmlLoadOk != TRUE)
+ {
+ pvals->src_handle = GAP_HANDLE_LEFT_TOP;
+ pvals->src_selmode = GAP_MOV_SEL_IGNORE;
+ pvals->src_paintmode = GIMP_NORMAL_MODE;
+ pvals->src_force_visible = 1;
+ pvals->src_apply_bluebox = 0;
+ pvals->bbp = NULL;
+ pvals->bbp_pv = NULL;
+ pvals->clip_to_img = 0;
+
+ pvals->step_speed_factor = 1.0;
+ pvals->tracelayer_enable = FALSE;
+ pvals->trace_opacity_initial = 100.0;
+ pvals->trace_opacity_desc = 80.0;
+ pvals->tween_steps = 0;
+ pvals->tween_opacity_initial = 80.0;
+ pvals->tween_opacity_desc = 80.0;
+
+ p_reset_points();
+ }
+
+
+ l_rc = FALSE;
+ if(ainfo_ptr != NULL)
+ {
+ l_mov_data.val_ptr = pvals_edit;
+ l_mov_data.singleFramePtr = NULL;
+ l_mov_data.val_ptr->cache_src_image_id = -1;
+ l_mov_data.dst_ainfo_ptr = ainfo_ptr;
+
+ p_gap_mov_dlg_move_dialog(mgp, &l_mov_data
+ , isRecordOnlyMode, isStandaloneGui
+ , close_fptr, callback_data
+ , nframes);
+ }
+
+ if(mgp->shell != NULL)
+ {
+ gtk_window_present(GTK_WINDOW(mgp->shell));
+ }
+
if(gap_debug)
{
- printf("gap_mov_dlg_move_dialog START mgp:%d\n", (int)mgp);
+ printf("gap_mov_dlg_edit_movepath_dialog DONE\n");
+ }
+
+ return(mgp->shell);
+
+} /* end gap_mov_dlg_edit_movepath_dialog */
+
+
+/* ------------------------------------------
+ * p_gap_mov_dlg_move_dialog
+ * ------------------------------------------
+ *
+ */
+static long
+p_gap_mov_dlg_move_dialog(t_mov_gui_stuff *mgp
+ , GapMovData *mov_ptr
+ , gboolean isRecordOnlyMode
+ , gboolean isStandaloneGui
+ , t_close_movepath_edit_callback_fptr close_fptr
+ , gpointer callback_data
+ , gint32 nframes
+ )
+{
+ GimpDrawable *l_drawable_ptr;
+ gint l_first;
+ gint l_last;
+ gint l_max;
+ gint l_curr;
+ char *l_str;
+
+ if(gap_debug)
+ {
+ printf("gap_mov_dlg_move_dialog START mgp:%d isRecordOnlyMode:%d isStandaloneGui:%d\n"
+ , (int)mgp
+ , (int)isRecordOnlyMode
+ , (int)isStandaloneGui
+ );
}
if(mgp == NULL)
{
printf("error can't alloc path_preview structure\n");
return -1;
}
+ mgp->close_fptr = close_fptr;
+ mgp->callback_data = callback_data;
+ mgp->isRecordOnlyMode = isRecordOnlyMode;
+ mgp->isStandaloneGui = isStandaloneGui;
mgp->shell_initial_width = -1;
mgp->shell_initial_height = -1;
mgp->show_path = TRUE;
@@ -544,13 +762,47 @@ long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
pvals = mov_ptr->val_ptr;
- l_str = gap_base_strdup_del_underscore(mov_ptr->dst_ainfo_ptr->basename);
- mgp->pointfile_name = g_strdup_printf("%s.path_points", l_str);
- g_free(l_str);
+
+ if(mgp->pointfile_name == NULL)
+ {
+ if(mov_ptr->dst_ainfo_ptr->basename != NULL)
+ {
+ l_str = gap_base_strdup_del_underscore(mov_ptr->dst_ainfo_ptr->basename);
+ mgp->pointfile_name = g_strdup_printf("%s.movepath.xml", l_str);
+ g_free(l_str);
+ }
+ else
+ {
+ mgp->pointfile_name = g_strdup("movepath.xml");
+ }
+ }
+ if(mgp->isRecordOnlyMode)
+ {
+ l_first = 1;
+ l_max = 9999;
+ l_last = nframes;
+ l_curr = 1;
- l_first = mov_ptr->dst_ainfo_ptr->first_frame_nr;
- l_last = mov_ptr->dst_ainfo_ptr->last_frame_nr;
+ mov_ptr->dst_ainfo_ptr->first_frame_nr = 1;
+ mov_ptr->dst_ainfo_ptr->last_frame_nr = nframes;
+ mov_ptr->dst_ainfo_ptr->curr_frame_nr = 1;
+
+ pvals->src_stepmode = GAP_STEP_NONE;
+ pvals->src_selmode = GAP_MOV_SEL_IGNORE;
+ }
+ else
+ {
+ l_first = mov_ptr->dst_ainfo_ptr->first_frame_nr;
+ l_last = mov_ptr->dst_ainfo_ptr->last_frame_nr;
+ l_curr = mov_ptr->dst_ainfo_ptr->curr_frame_nr;
+ l_max = l_last;
+
+ pvals->src_image_id = -1;
+ pvals->src_layer_id = -1;
+ pvals->src_stepmode = GAP_STEP_LOOP;
+
+ }
/* init parameter values */
pvals->dst_image_id = mov_ptr->dst_ainfo_ptr->image_id;
@@ -561,25 +813,6 @@ long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
pvals->tmp_alt_framenr = -1;
pvals->tween_image_id = -1;
pvals->trace_image_id = -1;
- pvals->src_image_id = -1;
- pvals->src_layer_id = -1;
- pvals->src_paintmode = GIMP_NORMAL_MODE;
- pvals->src_handle = GAP_HANDLE_LEFT_TOP;
- pvals->src_stepmode = GAP_STEP_LOOP;
- pvals->src_selmode = GAP_MOV_SEL_IGNORE;
- pvals->src_force_visible = 1;
- pvals->src_apply_bluebox = 0;
- pvals->bbp = NULL;
- pvals->bbp_pv = NULL;
- pvals->clip_to_img = 0;
-
- pvals->step_speed_factor = 1.0;
- pvals->tracelayer_enable = FALSE;
- pvals->trace_opacity_initial = 100.0;
- pvals->trace_opacity_desc = 80.0;
- pvals->tween_steps = 0;
- pvals->tween_opacity_initial = 80.0;
- pvals->tween_opacity_desc = 80.0;
pvals->apv_mode = GAP_APV_QUICK;
pvals->apv_src_frame = -1;
@@ -594,17 +827,37 @@ long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
pvals->cache_frame_number = -1;
pvals->cache_ainfo_ptr = NULL;
- p_reset_points();
+ if(mgp->isRecordOnlyMode != TRUE)
+ {
+ pvals->src_handle = GAP_HANDLE_LEFT_TOP;
+ pvals->src_selmode = GAP_MOV_SEL_IGNORE;
+ pvals->src_paintmode = GIMP_NORMAL_MODE;
+ pvals->src_force_visible = 1;
+ pvals->src_apply_bluebox = 0;
+ pvals->bbp = NULL;
+ pvals->bbp_pv = NULL;
+ pvals->clip_to_img = 0;
+
+ pvals->step_speed_factor = 1.0;
+ pvals->tracelayer_enable = FALSE;
+ pvals->trace_opacity_initial = 100.0;
+ pvals->trace_opacity_desc = 80.0;
+ pvals->tween_steps = 0;
+ pvals->tween_opacity_initial = 80.0;
+ pvals->tween_opacity_desc = 80.0;
+
+ p_reset_points();
+ }
/* pvals->point[1].p_x = 100; */ /* default: move from 0/0 to 100/0 */
- pvals->dst_range_start = mov_ptr->dst_ainfo_ptr->curr_frame_nr;
+ pvals->dst_range_start = l_curr;
pvals->dst_range_end = l_last;
pvals->dst_layerstack = 0; /* 0 ... insert layer on top of stack */
mgp->filesel = NULL; /* fileselector is not open */
mgp->ainfo_ptr = mov_ptr->dst_ainfo_ptr;
- mgp->preview_frame_nr = mov_ptr->dst_ainfo_ptr->curr_frame_nr;
+ mgp->preview_frame_nr = l_curr;
mgp->old_preview_frame_nr = mgp->preview_frame_nr;
mgp->point_index_frame = NULL;
@@ -625,14 +878,44 @@ long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
l_drawable_ptr = p_get_prevw_drawable(mgp);
/* do DIALOG window */
- mov_dialog(l_drawable_ptr, mgp, l_first, l_last);
- p_points_to_tab(mgp);
+ mov_dialog(l_drawable_ptr, mgp, l_first, l_max);
+
+
+ if(gap_debug)
+ {
+ printf("GAP-DEBUG: END gap_mov_dlg_move_dialog\n");
+ }
+} /* end p_gap_mov_dlg_move_dialog */
+
+
+/* --------------------------------
+ * p_free_mgp_resources
+ * --------------------------------
+ */
+static void
+p_free_mgp_resources(t_mov_gui_stuff *mgp)
+{
+ if(mgp == NULL)
+ {
+ return;
+ }
+
+ if(gap_debug)
+ {
+ printf("p_free_mgp_resources START\n");
+ }
+
/* destroy the tmp image(s) */
- gimp_image_delete(pvals->tmp_image_id);
+ if(pvals->tmp_image_id >= 0)
+ {
+ gimp_image_delete(pvals->tmp_image_id);
+ pvals->tmp_image_id = -1;
+ }
if(pvals->tmp_alt_image_id >= 0)
{
gimp_image_delete(pvals->tmp_alt_image_id);
+ pvals->tmp_alt_image_id = -1;
}
/* delete the temp selection image */
@@ -644,17 +927,16 @@ long gap_mov_dlg_move_dialog (GapMovData *mov_ptr)
pvals->tmpsel_image_id = -1;
pvals->tmpsel_channel_id = -1;
+ if(mgp->pointfile_name != NULL)
+ {
+ g_free(mgp->pointfile_name);
+ mgp->pointfile_name = NULL;
+ }
+
/* remove timer if there is one */
mov_remove_timer(mgp);
- g_free(mgp);
-
-
- if(gap_debug) printf("GAP-DEBUG: END gap_mov_dlg_move_dialog\n");
-
- if(mov_int.run == TRUE) return 0;
- else return -1;
-}
+} /* end p_free_mgp_resources */
/* ============================================================================
@@ -685,8 +967,11 @@ mov_dialog ( GimpDrawable *drawable, t_mov_gui_stuff *mgp,
if(gap_debug) printf("GAP-DEBUG: START mov_dialog\n");
- gimp_ui_init ("gap_move", FALSE);
- gap_stock_init();
+ if(mgp->isStandaloneGui)
+ {
+ gimp_ui_init ("gap_move", FALSE);
+ gap_stock_init();
+ }
#ifdef MOVE_PATH_LAYOUT_BIG_PREVIEW
vertical_layout = TRUE;
@@ -700,7 +985,14 @@ mov_dialog ( GimpDrawable *drawable, t_mov_gui_stuff *mgp,
mgp->first_nr = first_nr;
mgp->last_nr = last_nr;
- gtk_window_set_title (GTK_WINDOW (dlg), _("Move Path"));
+ if(mgp->isRecordOnlyMode)
+ {
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Move Path Editor"));
+ }
+ else
+ {
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Move Path"));
+ }
gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
g_signal_connect (G_OBJECT (dlg), "destroy",
G_CALLBACK (mov_close_callback),
@@ -861,9 +1153,12 @@ mov_dialog ( GimpDrawable *drawable, t_mov_gui_stuff *mgp,
G_CALLBACK (mov_shell_window_size_allocate),
mgp);
- gtk_main ();
- gdk_flush ();
-
+ if(mgp->isStandaloneGui)
+ {
+ gtk_main ();
+ gdk_flush ();
+ }
+
if(gap_debug) printf("GAP-DEBUG: END mov_dialog\n");
return mov_int.run;
@@ -905,8 +1200,26 @@ mov_close_callback (GtkWidget *widget,
{
if(mgp)
{
+ if(mgp->shell)
+ {
+ p_points_to_tab(mgp);
+ if(mgp->close_fptr != NULL)
+ {
+
+ if(gap_debug)
+ {
+ printf("calling close_fptr close notification\n");
+ }
+ /* run the callback procedure (that was provided by the caller)
+ * to notify the caller about closing of the movepath dialog
+ */
+ (*mgp->close_fptr)(mgp->callback_data);
+ }
+ }
+
mov_remove_timer(mgp);
+
if(mgp->shell)
{
GtkWidget *l_shell;
@@ -920,11 +1233,29 @@ mov_close_callback (GtkWidget *widget,
* (for this reason the mgp->shell is set to NULL
* before the gtk_widget_destroy call)
*/
+ gtk_widget_hide (l_shell);
gtk_widget_destroy (l_shell);
+ p_free_mgp_resources(mgp);
+ }
+
+ if(mgp->isStandaloneGui)
+ {
+ if(gap_debug)
+ {
+ printf("mov_close_callback isStandaloneGui == TRUE, calling gtk_main_quit\n");
+ }
+ gtk_main_quit ();
}
}
-
- gtk_main_quit ();
+ else
+ {
+ if(gap_debug)
+ {
+ printf("mov_close_callback mgp is NULL, calling gtk_main_quit\n");
+ }
+ gtk_main_quit ();
+ }
+
} /* end mov_close_callback */
@@ -932,8 +1263,30 @@ static void
mov_ok_callback (GtkWidget *widget,
t_mov_gui_stuff *mgp)
{
+
if(pvals != NULL)
{
+ if(mgp != NULL)
+ {
+ if(mgp->isRecordOnlyMode == TRUE)
+ {
+ if(mgp->xml_paramfile[0] != '\0')
+ {
+ gint l_rc;
+ if(gap_debug)
+ {
+ printf("Saving xml_paramfile:%s\n", mgp->xml_paramfile);
+ }
+ l_rc = gap_mov_xml_par_save(mgp->xml_paramfile, pvals);
+ if(l_rc != 0)
+ {
+ printf("** Error failed to save xml_paramfile:%s\n", mgp->xml_paramfile);
+ }
+ }
+ }
+ }
+
+
if(!mov_check_valid_src_layer(mgp))
{
return;
@@ -947,6 +1300,7 @@ mov_ok_callback (GtkWidget *widget,
mov_int.run = TRUE;
+
if(pvals->point_idx_max == 0)
{
/* if we have only one point duplicate that point
@@ -973,23 +1327,51 @@ mov_upvw_callback (GtkWidget *widget,
gint32 l_new_tmp_image_id;
gint32 l_old_tmp_image_id;
- if(gap_debug) printf("mov_upvw_callback nr: %d old_nr: %d\n",
- (int)mgp->preview_frame_nr , (int)mgp->old_preview_frame_nr);
-
- l_frame_nr = (long)mgp->preview_frame_nr;
- l_filename = gap_lib_alloc_fname(mgp->ainfo_ptr->basename,
+ if(gap_debug)
+ {
+ printf("mov_upvw_callback nr: %d old_nr: %d\n"
+ , (int)mgp->preview_frame_nr
+ , (int)mgp->old_preview_frame_nr
+ );
+ }
+ l_filename = NULL;
+
+ if(mgp->ainfo_ptr->ainfo_type == GAP_AINFO_FRAMES)
+ {
+ if(gap_debug)
+ {
+ printf("mov_upvw_callback ainfo_type == GAP_AINFO_FRAMES nr: %d old_nr: %d\n"
+ , (int)mgp->preview_frame_nr
+ , (int)mgp->old_preview_frame_nr
+ );
+ }
+ l_frame_nr = (long)mgp->preview_frame_nr;
+ l_filename = gap_lib_alloc_fname(mgp->ainfo_ptr->basename,
l_frame_nr,
mgp->ainfo_ptr->extension);
+ }
+ else
+ {
+ if(gap_debug)
+ {
+ printf("mov_upvw_callback ainfo_type != GAP_AINFO_FRAMES using image_id %d\n"
+ , (int)mgp->ainfo_ptr->image_id
+ );
+ }
+ }
+
+
+ if(!mgp->instant_apply)
+ {
+ /* dont show waiting cursor at instant_apply
+ * (cursor flickering is boring on fast machines,
+ * and users with slow machines should not touch instant_apply at all)
+ */
+ mov_set_waiting_cursor(mgp);
+ }
+
if(l_filename != NULL)
{
- if(!mgp->instant_apply)
- {
- /* dont show waiting cursor at instant_apply
- * (cursor flickering is boring on fast machines,
- * and users with slow machines should not touch instant_apply at all)
- */
- mov_set_waiting_cursor(mgp);
- }
/* replace the temporary image */
if(mgp->preview_frame_nr == mgp->ainfo_ptr->curr_frame_nr)
{
@@ -1022,34 +1404,47 @@ mov_upvw_callback (GtkWidget *widget,
gimp_image_undo_disable(l_new_tmp_image_id);
g_free(l_filename);
- if (l_new_tmp_image_id >= 0)
- {
- /* use the new loaded temporary image */
- l_old_tmp_image_id = pvals->tmp_image_id;
- pvals->tmp_image_id = l_new_tmp_image_id;
+ }
+ else
+ {
+ /* in case move path dialog was not called from a frame image
+ * always show up the image from where the dialog was invoked from
+ * as frame (and ignore the preview_frame_nr setting)
+ */
+ l_new_tmp_image_id = gimp_image_duplicate(mgp->ainfo_ptr->image_id);
+ }
+
+
+
+ if (l_new_tmp_image_id >= 0)
+ {
+ /* use the new loaded temporary image */
+ l_old_tmp_image_id = pvals->tmp_image_id;
+ pvals->tmp_image_id = l_new_tmp_image_id;
- /* flatten image, and get the (only) resulting drawable */
- mgp->drawable = p_get_prevw_drawable(mgp);
+ /* flatten image, and get the (only) resulting drawable */
+ mgp->drawable = p_get_prevw_drawable(mgp);
- /* gimp_display_new(pvals->tmp_image_id); */ /* add a display for debugging only */
+ /* gimp_display_new(pvals->tmp_image_id); */ /* add a display for debugging only */
- /* re initialize preview image */
- mov_path_prevw_preview_init(mgp);
- p_point_refresh(mgp);
+ /* re initialize preview image */
+ mov_path_prevw_preview_init(mgp);
+ p_point_refresh(mgp);
- mgp->old_preview_frame_nr = mgp->preview_frame_nr;
+ mgp->old_preview_frame_nr = mgp->preview_frame_nr;
- gtk_widget_queue_draw(mgp->pv_ptr->da_widget);
- mov_path_prevw_draw ( mgp, CURSOR | PATH_LINE );
- gdk_flush();
+ gtk_widget_queue_draw(mgp->pv_ptr->da_widget);
+ mov_path_prevw_draw ( mgp, CURSOR | PATH_LINE );
+ gdk_flush();
- /* destroy the old tmp image */
- gimp_image_delete(l_old_tmp_image_id);
+ /* destroy the old tmp image */
+ gimp_image_delete(l_old_tmp_image_id);
- mgp->instant_apply_request = FALSE;
- }
- mov_set_active_cursor(mgp);
+ mgp->instant_apply_request = FALSE;
}
+
+ mov_set_active_cursor(mgp);
+
} /* end mov_upvw_callback */
@@ -2201,7 +2596,10 @@ p_points_load_from_file (GtkWidget *widget,
{
const gchar *filename;
- if(gap_debug) printf("p_points_load_from_file\n");
+ if(gap_debug)
+ {
+ printf("p_points_load_from_file\n");
+ }
if(mgp->filesel == NULL)
{
return;
@@ -2211,7 +2609,10 @@ p_points_load_from_file (GtkWidget *widget,
g_free(mgp->pointfile_name);
mgp->pointfile_name = g_strdup(filename);
- if(gap_debug) printf("p_points_load_from_file %s\n", mgp->pointfile_name);
+ if(gap_debug)
+ {
+ printf("p_points_load_from_file %s\n", mgp->pointfile_name);
+ }
gtk_widget_destroy(GTK_WIDGET(mgp->filesel));
mgp->filesel = NULL;
@@ -2232,7 +2633,10 @@ p_points_save_to_file (GtkWidget *widget,
{
const gchar *filename;
- if(gap_debug) printf("p_points_save_to_file\n");
+ if(gap_debug)
+ {
+ printf("p_points_save_to_file\n");
+ }
if(mgp->filesel == NULL)
{
return; /* filesel is already open */
@@ -2242,7 +2646,10 @@ p_points_save_to_file (GtkWidget *widget,
g_free(mgp->pointfile_name);
mgp->pointfile_name = g_strdup(filename);
- if(gap_debug) printf("p_points_save_to_file %s\n", mgp->pointfile_name);
+ if(gap_debug)
+ {
+ printf("p_points_save_to_file %s\n", mgp->pointfile_name);
+ }
gtk_widget_destroy(GTK_WIDGET(mgp->filesel));
mgp->filesel = NULL;
@@ -2694,6 +3101,11 @@ mov_install_timer(t_mov_gui_stuff *mgp)
static void
mov_remove_timer(t_mov_gui_stuff *mgp)
{
+ if(mgp == NULL)
+ {
+ return;
+ }
+
if(mgp->instant_timertag >= 0)
{
g_source_remove(mgp->instant_timertag);
@@ -2873,7 +3285,22 @@ p_points_from_tab(t_mov_gui_stuff *mgp)
static void
p_points_to_tab(t_mov_gui_stuff *mgp)
{
- if(gap_debug) printf("p_points_to_tab: idx=%d, rotation=%f\n", (int)pvals->point_idx , (float)mgp->rotation);
+ if(mgp == NULL)
+ {
+ return;
+ }
+ if(pvals == NULL)
+ {
+ return;
+ }
+
+ if(gap_debug)
+ {
+ printf("p_points_to_tab: idx=%d, rotation=%f\n"
+ , (int)pvals->point_idx
+ , (float)mgp->rotation
+ );
+ }
pvals->point[pvals->point_idx].p_x = mgp->p_x;
pvals->point[pvals->point_idx].p_y = mgp->p_y;
@@ -3235,8 +3662,17 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
gtk_widget_show(combo);
mgp->src_layer_combo = combo;
- mov_refresh_src_layer_menu(mgp);
- gtk_widget_show(combo);
+
+ if(mgp->isRecordOnlyMode)
+ {
+ gtk_widget_hide(label);
+ gtk_widget_hide(combo);
+ }
+ else
+ {
+ mov_refresh_src_layer_menu(mgp);
+ gtk_widget_show(combo);
+ }
/* Paintmode combo (menu) */
@@ -3246,7 +3682,7 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 4, 0);
gtk_widget_show(label);
- combo = gimp_int_combo_box_new (_("Normal"), GIMP_NORMAL_MODE,
+ combo = gimp_int_combo_box_new (_("Normal"), GIMP_NORMAL_MODE,
_("Dissolve"), GIMP_DISSOLVE_MODE,
_("Behind"), GIMP_BEHIND_MODE,
_("Multiply"), GIMP_MULTIPLY_MODE,
@@ -3272,10 +3708,22 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
_("Keep Paintmode"), GAP_MOV_KEEP_SRC_PAINTMODE,
NULL);
- gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
- GIMP_NORMAL_MODE, /* initial int value */
+ {
+ gint initialValue;
+ initialValue = GIMP_NORMAL_MODE;
+
+ if(pvals)
+ {
+ initialValue = pvals->src_paintmode;
+ }
+
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ initialValue,
G_CALLBACK (mov_paintmode_menu_callback),
mgp);
+
+ }
+
gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 0, 1,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
gimp_help_set_help_data(combo,
@@ -3323,7 +3771,17 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
G_CALLBACK (gimp_double_adjustment_update),
&pvals->step_speed_factor);
mgp->step_speed_factor_adj = GTK_ADJUSTMENT(adj);
-
+
+ if(mgp->isRecordOnlyMode)
+ {
+ GtkWidget *widget;
+
+ widget = g_object_get_data(G_OBJECT (adj), "label");
+ gtk_widget_hide(widget);
+ widget = g_object_get_data(G_OBJECT (adj), "spinbutton");
+ gtk_widget_hide(widget);
+
+ }
/* Loop Stepmode combo */
@@ -3341,17 +3799,35 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
_("Frame None"), GAP_STEP_FRAME_NONE,
NULL);
- gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ if(mgp->isRecordOnlyMode)
+ {
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ GAP_STEP_NONE, /* initial int value */
+ G_CALLBACK (mov_stepmode_menu_callback),
+ mgp);
+ }
+ else
+ {
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
GAP_STEP_LOOP, /* initial int value */
G_CALLBACK (mov_stepmode_menu_callback),
mgp);
-
+ }
+
gtk_table_attach(GTK_TABLE(sub_table), combo, 0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
gimp_help_set_help_data(combo,
_("How to fetch the next source layer at the next handled frame")
, NULL);
- gtk_widget_show(combo);
+ if(mgp->isRecordOnlyMode)
+ {
+ gtk_widget_hide(label);
+ gtk_widget_hide(combo);
+ }
+ else
+ {
+ gtk_widget_show(combo);
+ }
mgp->stepmode_combo = combo;
@@ -3369,11 +3845,30 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
_("Center"), GAP_HANDLE_CENTER,
NULL);
- gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
- GAP_HANDLE_LEFT_TOP, /* initial int value */
+
+ {
+ gint initialValue;
+
+ initialValue = GAP_HANDLE_LEFT_TOP;
+ if(pvals)
+ {
+ switch(pvals->src_handle)
+ {
+ case GAP_HANDLE_LEFT_TOP:
+ case GAP_HANDLE_LEFT_BOT:
+ case GAP_HANDLE_RIGHT_TOP:
+ case GAP_HANDLE_RIGHT_BOT:
+ case GAP_HANDLE_CENTER:
+ initialValue = pvals->src_handle;
+ break;
+ }
+ }
+
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ initialValue,
G_CALLBACK (mov_handmode_menu_callback),
mgp);
-
+ }
gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 1, 2,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
@@ -3393,7 +3888,7 @@ mov_src_sel_create(t_mov_gui_stuff *mgp)
* Create set of widgets for the advanced Move Path features
* A frame that contains:
* in the 1.st row
- * - 3x spionbutton for tween_steps, tween_opacity_init, tween_opacity_desc
+ * - 3x spinbutton for tween_steps, tween_opacity_init, tween_opacity_desc
* in the 2.nd row
* - checkbutton make_tracelayer
* - 2x spinbutton for trace_opacity_initial, trace_opacity_desc
@@ -3902,7 +4397,6 @@ mov_path_framerange_box_create(t_mov_gui_stuff *mgp
{
GtkWidget *master_table;
GtkWidget *table;
- //GtkObject *adj;
GtkAdjustment *adj;
GtkWidget *check_button;
gint master_rows;
@@ -5038,6 +5532,28 @@ mov_path_prevw_create ( GimpDrawable *drawable, t_mov_gui_stuff *mgp, gboolean v
G_CALLBACK (mov_instant_int_adjustment_update),
&mgp->preview_frame_nr);
mgp->preview_frame_nr_adj = GTK_ADJUSTMENT(adj);
+
+ if(mgp->ainfo_ptr->ainfo_type != GAP_AINFO_FRAMES)
+ {
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET(g_object_get_data (G_OBJECT (adj), "label"));
+ if(widget)
+ {
+ gtk_widget_hide(widget);
+ }
+ widget = GTK_WIDGET(g_object_get_data (G_OBJECT (adj), "spinbutton"));
+ if(widget)
+ {
+ gtk_widget_hide(widget);
+ }
+ widget = GTK_WIDGET(g_object_get_data (G_OBJECT (adj), "scale"));
+ if(widget)
+ {
+ gtk_widget_hide(widget);
+ }
+
+ }
gtk_table_attach( GTK_TABLE(pv_table), pv_sub_table, 0, 1, 3, 4,
@@ -5825,6 +6341,7 @@ p_get_prevw_drawable (t_mov_gui_stuff *mgp)
gint l_nlayers;
l_curr.isSingleFrame = FALSE;
+ l_curr.singleMovObjLayerId = pvals->src_layer_id;
/* check if we have a source layer (to add to the preview) */
if((pvals->src_layer_id >= 0) && (pvals->src_image_id >= 0))
@@ -5899,7 +6416,6 @@ p_get_prevw_drawable (t_mov_gui_stuff *mgp)
}
}
-
/* set offsets (in cur_ptr)
* according to handle_mode and src_img dimension (pvals)
*/
diff --git a/gap/gap_mov_dialog.h b/gap/gap_mov_dialog.h
old mode 100644
new mode 100755
index 7b73e2b..23f0577
--- a/gap/gap_mov_dialog.h
+++ b/gap/gap_mov_dialog.h
@@ -298,8 +298,19 @@ typedef struct {
} GapMovQuery;
+typedef void (*t_close_movepath_edit_callback_fptr)(gpointer callback_data);
+
long gap_mov_dlg_move_dialog (GapMovData *mov_ptr);
gint gap_mov_dlg_move_dialog_singleframe(GapMovSingleFrame *singleFramePtr);
+GtkWidget * gap_mov_dlg_edit_movepath_dialog (gint32 frame_image_id, gint32 drawable_id
+ , const char *xml_paramfile
+ , GapAnimInfo *ainfo_ptr
+ , GapMovValues *pvals
+ , t_close_movepath_edit_callback_fptr close_fptr
+ , gpointer callback_data
+ , gint32 nframes
+ );
+
#endif
diff --git a/gap/gap_mov_exec.c b/gap/gap_mov_exec.c
old mode 100644
new mode 100755
index 282bb1f..f4de61e
--- a/gap/gap_mov_exec.c
+++ b/gap/gap_mov_exec.c
@@ -2632,6 +2632,16 @@ p_mov_execute(GapMovData *mov_ptr)
* gap_mov_exec_anim_preview
* Generate an animated preview for the move path
* ============================================================================
+ * the animate preview is rendered as new multilayer image
+ * where each processed frame results in one layer.
+ * processing can be done on empty frame, multiple copies of one frame
+ * or by reading all affected frames as input (from frame images on disc)
+ * Note that animated preview can be rendered at original size
+ * or downscaled to a percentage less than 100%
+ *
+ * In case ainfo_ptr refers to an image that is not part of a sequence
+ * of frameimages (stored on disc) a copy of the invoke image (ainfo_ptr->image_id)
+ * will be used as input instead of reading frame images from disc.
*/
gint32
gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint preview_frame_nr)
@@ -2774,23 +2784,56 @@ gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint
, (int) l_pvals->apv_mlayer_image);
}
- /* APV_MODE (Wich frames to use in the preview?) */
- switch(l_pvals->apv_mode)
+ l_tmp_frame_id = -1;
+
{
gchar *l_filename;
+ gboolean useOneFrame;
- case GAP_APV_QUICK:
- /* use an empty dummy frame for all frames */
- l_tmp_frame_id = gimp_image_new(l_width, l_height,l_type);
- gimp_image_set_resolution(l_tmp_frame_id, l_xresoulution, l_yresoulution);
- gimp_image_undo_disable (l_tmp_frame_id);
- break;
- case GAP_APV_ONE_FRAME:
- /* use only one frame in the preview */
- l_filename = gap_lib_alloc_fname(ainfo_ptr->basename,
+ useOneFrame = FALSE;
+ l_filename = gap_lib_alloc_fname(ainfo_ptr->basename,
preview_frame_nr,
ainfo_ptr->extension);
- l_tmp_frame_id = gap_lib_load_image(l_filename);
+
+ /* APV_MODE (Wich frames to use in the preview?) */
+ switch(l_pvals->apv_mode)
+ {
+ case GAP_APV_QUICK:
+ /* use an empty dummy frame for all frames */
+ l_tmp_frame_id = gimp_image_new(l_width, l_height,l_type);
+ gimp_image_set_resolution(l_tmp_frame_id, l_xresoulution, l_yresoulution);
+ gimp_image_undo_disable (l_tmp_frame_id);
+ break;
+ case GAP_APV_ONE_FRAME:
+ /* use only one frame in the preview */
+ useOneFrame = TRUE;
+ break;
+ default: /* GAP_APV_EXACT */
+ /* read the original frames for the preview (slow) */
+ l_tmp_frame_id = -1;
+ if(l_filename == NULL)
+ {
+ /* the frame for preview_frame_nr resulted in NULL filename
+ * in this case we assume that there will be no valid frames available
+ * and use only one frame (as copy of the invoker image)
+ * for rendering the animated preview
+ */
+ useOneFrame = TRUE;
+ }
+ break;
+ }
+
+ if(useOneFrame)
+ {
+ if((l_filename != NULL)
+ && (preview_frame_nr != ainfo_ptr->curr_frame_nr))
+ {
+ l_tmp_frame_id = gap_lib_load_image(l_filename);
+ }
+ if(l_tmp_frame_id < 0)
+ {
+ l_tmp_frame_id = gimp_image_duplicate(ainfo_ptr->image_id);
+ }
gimp_image_undo_disable (l_tmp_frame_id);
if((l_pvals->apv_scalex != 100.0) || (l_pvals->apv_scaley != 100.0))
{
@@ -2798,13 +2841,15 @@ gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint
l_size_y = (gimp_image_height(l_tmp_frame_id) * l_pvals->apv_scaley) / 100;
gimp_image_scale(l_tmp_frame_id, l_size_x, l_size_y);
}
+ }
+
+
+ if(l_filename != NULL)
+ {
g_free(l_filename);
- break;
- default: /* GAP_APV_EXACT */
- /* read the original frames for the preview (slow) */
- l_tmp_frame_id = -1;
- break;
+ }
}
+
l_pvals->apv_src_frame = l_tmp_frame_id;
if(gap_debug)
@@ -2854,11 +2899,11 @@ gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint
return(l_mlayer_image_id);
} /* end gap_mov_exec_anim_preview */
+
/* ============================================================================
- * p_con_keyframe
+ * p_conv_keyframe
* ============================================================================
*/
-
gint
gap_mov_exec_conv_keyframe_to_rel(gint abs_keyframe, GapMovValues *pvals)
{
@@ -3928,12 +3973,6 @@ gap_mov_exec_move_path_singleframe(GimpRunMode run_mode, gint32 image_id
printf("Execution Error: could not load MovePath settings from file: %s\n",
singleFramePtr->xml_paramfile);
}
-
- //if(gap_debug)
- //{
- // gap_mov_xml_par_save("pvals_after_load.xml", pvals);
- //}
-
}
}
diff --git a/gap/gap_story_att_trans_dlg.c b/gap/gap_story_att_trans_dlg.c
old mode 100644
new mode 100755
index fdb9990..3816484
--- a/gap/gap_story_att_trans_dlg.c
+++ b/gap/gap_story_att_trans_dlg.c
@@ -52,6 +52,8 @@
#include "gap_timeconv.h"
#include "gap_layer_copy.h"
#include "gap_accel_da.h"
+#include "gap_mov_dialog.h"
+#include "gap_mov_exec.h"
#include "gap-intl.h"
@@ -223,6 +225,11 @@ static void p_attw_movepath_filesel_pw_close_cb ( GtkWidget *widget
, GapStbAttrWidget *attw);
static void p_attw_movepath_filesel_button_cb ( GtkWidget *w
, GapStbAttrWidget *attw);
+
+static void p_create_movepath_edit_resources(GapStbAttrWidget *attw);
+static void p_edit_movepath_closed_callback(gpointer ptr);
+static void p_attw_movepath_edit_button_cb ( GtkWidget *w
+ , GapStbAttrWidget *attw);
static void p_attw_movepath_file_validity_check(GapStbAttrWidget *attw);
static void p_attw_movepath_file_entry_update_cb(GtkWidget *widget, GapStbAttrWidget *attw);
static void p_attw_comment_entry_update_cb(GtkWidget *widget, GapStbAttrWidget *attw);
@@ -324,6 +331,13 @@ p_attw_prop_response(GtkWidget *widget
/* force close in case file selection dialog is still open */
p_attw_movepath_filesel_pw_close_cb(attw->movepath_filesel, attw);
}
+
+ if(attw->movepath_edit_dialog != NULL)
+ {
+ /* force close of the movepath edit dialog that is still open */
+ gtk_widget_destroy(attw->movepath_edit_dialog);
+ attw->movepath_edit_dialog = NULL;
+ }
p_delete_gfx_images(attw);
if(attw->go_timertag >= 0)
@@ -356,9 +370,10 @@ p_attw_push_undo_and_set_unsaved_changes(GapStbAttrWidget *attw)
{
if((attw->stb_elem_refptr != NULL) && (attw->stb_refptr != NULL))
{
- gap_stb_undo_push_clip(attw->tabw
+ gap_stb_undo_push_clip_with_file_snapshot(attw->tabw
, GAP_STB_FEATURE_PROPERTIES_TRANSITION
, attw->stb_elem_refptr->story_id
+ , &attw->stb_elem_refptr->att_movepath_file_xml
);
attw->stb_refptr->unsaved_changes = TRUE;
@@ -589,6 +604,17 @@ p_attw_update_sensitivity(GapStbAttrWidget *attw)
sensitive = ((attw->stb_elem_refptr->att_fit_width == TRUE)
|| (attw->stb_elem_refptr->att_fit_height == TRUE));
gtk_widget_set_sensitive(attw->keep_proportions_toggle, sensitive);
+
+ sensitive = FALSE;
+ if(attw->stb_elem_refptr->att_movepath_file_xml != NULL)
+ {
+ if(attw->stb_elem_refptr->att_movepath_file_xml[0] != '\0')
+ {
+ sensitive = TRUE;
+ }
+ }
+
+ gtk_widget_set_sensitive(attw->movepath_edit_button, sensitive);
} /* end p_attw_update_sensitivity */
@@ -2758,7 +2784,15 @@ p_attw_movepath_filesel_button_cb ( GtkWidget *w
gtk_window_present(GTK_WINDOW(attw->movepath_filesel));
return; /* filesel is already open */
}
- if(attw->stb_elem_refptr == NULL) { return; }
+ if(attw->movepath_edit_dialog != NULL)
+ {
+ gtk_window_present(GTK_WINDOW(attw->movepath_edit_dialog));
+ return; /* edit dialog is already open */
+ }
+ if(attw->stb_elem_refptr == NULL)
+ {
+ return;
+ }
filesel = gtk_file_selection_new ( _("Set Movepath Parameterfile (XML)"));
attw->movepath_filesel = filesel;
@@ -2787,6 +2821,204 @@ p_attw_movepath_filesel_button_cb ( GtkWidget *w
/* ==================================================== END MOVEPATH FILESEL stuff ====== */
+/* -----------------------------------------
+ * p_create_movepath_edit_resources
+ * -----------------------------------------
+ * create frame_image, moving object image
+ * ainfo and pvals resources that are used
+ * to call the movepath edit dialog.
+ */
+static void
+p_create_movepath_edit_resources(GapStbAttrWidget *attw)
+{
+ gint32 image_id;
+ gint32 bg_layer_id;
+ gint32 origsize_layer_id;
+
+ /* create the frame image */
+ image_id = gimp_image_new(attw->stb_refptr->master_width
+ ,attw->stb_refptr->master_height
+ ,GIMP_RGB
+ );
+ attw->movepath_frame_image_id = image_id;
+ gimp_image_undo_disable (image_id);
+
+ /* add a transparent layer */
+ bg_layer_id = gimp_layer_new(image_id
+ , "background"
+ , gimp_image_width(image_id)
+ , gimp_image_height(image_id)
+ , GIMP_RGBA_IMAGE
+ , 100.0 /* opacity */
+ , 0 /* normal mode */
+ );
+ gimp_image_add_layer (image_id, bg_layer_id, 0);
+ gap_layer_clear_to_color(bg_layer_id, 0.0, 0.0, 0.0, 0.0);
+ gimp_drawable_set_visible(bg_layer_id, TRUE);
+
+ // TODO: in case the storyboard has more tracks
+ // the frame image should be rendered by the storyboard processor at master size
+ // based on a modified storyboard that contains only tracks that render behind the current track
+
+
+ /* create an image that holds the moving object layer */
+ origsize_layer_id = attw->gfx_tab[0].orig_layer_id;
+ attw->movepath_obj_image_id = gimp_image_new( gimp_drawable_width(origsize_layer_id)
+ , gimp_drawable_height(origsize_layer_id)
+ , GIMP_RGB
+ );
+ gimp_image_undo_disable (attw->movepath_obj_image_id);
+ attw->movepath_obj_layer_id = gimp_layer_new_from_drawable(origsize_layer_id, attw->movepath_obj_image_id);
+ gimp_image_add_layer (attw->movepath_obj_image_id, attw->movepath_obj_layer_id, 0);
+ gimp_drawable_set_visible(attw->movepath_obj_layer_id, TRUE);
+
+
+ /* create default values for movepath
+ * (will be overwritten in case xml_paramfile contains already valid settings)
+ */
+ attw->pvals = gap_mov_exec_new_GapMovValues();
+ attw->pvals->dst_image_id = attw->movepath_frame_image_id;
+
+ attw->ainfo_ptr = gap_lib_alloc_ainfo_unsaved_image(attw->movepath_frame_image_id);
+
+} /* end p_create_movepath_edit_resources */
+
+
+/* -----------------------------------------
+ * p_edit_movepath_closed_callback
+ * -----------------------------------------
+ * is called on close of the movepath edit dialog
+ */
+static void
+p_edit_movepath_closed_callback(gpointer ptr)
+{
+ GapStbAttrWidget *attw;
+
+ attw = (GapStbAttrWidget *)ptr;
+
+ if(attw != NULL)
+ {
+ if(gap_debug)
+ {
+ printf("p_edit_movepath_closed_callback frame_image_id:%d obj_image_id:%d\n"
+ ,(int)attw->movepath_frame_image_id
+ ,(int)attw->movepath_obj_image_id
+ );
+ }
+ attw->movepath_edit_dialog = NULL;
+
+ if(attw->pvals != NULL)
+ {
+ g_free(attw->pvals);
+ attw->pvals = NULL;
+ }
+
+ if(attw->ainfo_ptr != NULL)
+ {
+ gap_lib_free_ainfo(&attw->ainfo_ptr);
+ attw->ainfo_ptr = NULL;
+ }
+
+ if(attw->movepath_frame_image_id >= 0)
+ {
+ gimp_image_delete(attw->movepath_frame_image_id);
+ attw->movepath_frame_image_id = -1;
+ }
+
+ if(attw->movepath_obj_image_id >= 0)
+ {
+ gimp_image_delete(attw->movepath_obj_image_id);
+ attw->movepath_obj_image_id = -1;
+ }
+ p_attw_movepath_file_validity_check(attw);
+ p_update_full_preview_gfx(attw);
+
+ /* make attributes dialog sensitive again (after movepath edit dialog was closed) */
+ gtk_widget_set_sensitive(attw->attw_prop_dialog, TRUE);
+
+ }
+
+} /* end p_edit_movepath_closed_callback */
+
+
+
+/* ---------------------------------
+ * p_attw_movepath_edit_button_cb
+ * ---------------------------------
+ * invoke the movepath editor dialog window
+ * (in case it is not yet open
+ * and the file selection dialog is not open)
+ */
+static void
+p_attw_movepath_edit_button_cb ( GtkWidget *w
+ , GapStbAttrWidget *attw)
+{
+ gint32 nframes;
+
+ if(attw->attw_prop_dialog == NULL)
+ {
+ return;
+ }
+
+ if(attw->movepath_filesel != NULL)
+ {
+ gtk_window_present(GTK_WINDOW(attw->movepath_filesel));
+ return; /* filesel is already open */
+ }
+ if(attw->stb_elem_refptr == NULL)
+ {
+ return;
+ }
+
+ if(attw->movepath_edit_dialog != NULL)
+ {
+ gtk_window_present(GTK_WINDOW(attw->movepath_edit_dialog));
+ return; /* edit dialog is already open */
+ }
+
+ if(attw->stb_elem_refptr->att_movepath_file_xml == NULL)
+ {
+ return;
+ }
+ if(attw->stb_elem_refptr->att_movepath_file_xml[0] == '\0')
+ {
+ return;
+ }
+
+ p_attw_push_undo_and_set_unsaved_changes(attw);
+ p_create_movepath_edit_resources(attw);
+
+ if(gap_debug)
+ {
+ printf("p_attw_movepath_edit_button_cb frame_image_id:%d obj_image_id:%d obj_layer_id:%d attw:%d\n"
+ ,(int)attw->movepath_frame_image_id
+ ,(int)attw->movepath_obj_image_id
+ ,(int)attw->movepath_obj_layer_id
+ ,(int)attw
+ );
+ }
+
+
+ /* make attributes dialog insensitive (while movepath edit dialog is open) */
+ gtk_widget_set_sensitive(attw->attw_prop_dialog, FALSE);
+
+ nframes = MAX(attw->stb_elem_refptr->att_arr_value_to[GAP_STB_ATT_TYPE_MOVEPATH]
+ ,attw->stb_elem_refptr->att_arr_value_from[GAP_STB_ATT_TYPE_MOVEPATH]);
+
+ attw->movepath_edit_dialog = gap_mov_dlg_edit_movepath_dialog(
+ attw->movepath_frame_image_id
+ , attw->movepath_obj_layer_id
+ , attw->stb_elem_refptr->att_movepath_file_xml
+ , attw->ainfo_ptr
+ , attw->pvals
+ , p_edit_movepath_closed_callback
+ ,(gpointer)attw
+ , nframes
+ );
+
+} /* end p_attw_movepath_edit_button_cb */
+
+
/* ------------------------------------
* p_attw_movepath_file_validity_check
* ------------------------------------
@@ -3283,6 +3515,12 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
if(tabw == NULL) { return (NULL); }
attw->movepath_filesel = NULL;
+ attw->movepath_edit_dialog = NULL;
+ attw->ainfo_ptr = NULL;
+ attw->pvals = NULL;
+ attw->movepath_frame_image_id = -1;
+ attw->movepath_obj_image_id = -1;
+ attw->movepath_obj_layer_id = -1;
if(attw->stb_elem_bck)
{
@@ -3305,6 +3543,7 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
,GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE
,NULL);
}
+ gtk_window_set_type_hint (dlg, GDK_WINDOW_TYPE_HINT_NORMAL);
attw->attw_prop_dialog = dlg;
@@ -3724,6 +3963,16 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
G_CALLBACK(p_attw_movepath_filesel_button_cb),
attw);
gtk_widget_show (button);
+
+
+ /* the movepath record/edit dialog invoker button */
+ button = gtk_button_new_with_label ("edit");
+ attw->movepath_edit_button = button;
+ gtk_table_attach_defaults (GTK_TABLE(table), button, 10, 11, row, row+1);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(p_attw_movepath_edit_button_cb),
+ attw);
+ gtk_widget_show (button);
}
diff --git a/gap/gap_story_dialog.c b/gap/gap_story_dialog.c
index db51cfc..7e68e0c 100644
--- a/gap/gap_story_dialog.c
+++ b/gap/gap_story_dialog.c
@@ -478,8 +478,8 @@ p_is_debug_menu_enabled(void)
/* ---------------------------------------
* p_is_debug_feature_item_enabled
* ---------------------------------------
- * print the list of video elements
- * to stdout (typical used for logging and debug purpose)
+ * return TRUE if the specified debug_item name
+ * is enabled (e.g. is present as text line in the debug configuration file)
*/
static gboolean
p_is_debug_feature_item_enabled(const char *debug_item)
@@ -500,10 +500,7 @@ p_is_debug_feature_item_enabled(const char *debug_item)
FILE *l_fp;
char l_buf[400];
- if(gap_debug)
- {
- printf("check for item:'%s'\n", debug_item);
- }
+ printf("debug_item:'%s'", debug_item);
l_fp = g_fopen(filename, "r");
if(l_fp)
@@ -526,12 +523,21 @@ p_is_debug_feature_item_enabled(const char *debug_item)
}
fclose(l_fp);
+ if(enable)
+ {
+ printf(" IS ENABLED\n");
+ }
+ else
+ {
+ printf(" is disabled\n");
+ }
}
}
g_free(filename);
}
+
return(enable);
} /* end p_is_debug_feature_item_enabled */
@@ -2134,7 +2140,13 @@ static void
p_tabw_process_undo(GapStbTabWidgets *tabw)
{
GapStoryBoard *stb;
+ GapStoryBoard *old_stb;
+ old_stb = p_tabw_get_stb_ptr(tabw);
+ if (old_stb)
+ {
+ p_tabw_destroy_all_popup_dlg(tabw);
+ }
stb = gap_stb_undo_pop(tabw);
if (stb)
{
@@ -2150,6 +2162,13 @@ static void
p_tabw_process_redo(GapStbTabWidgets *tabw)
{
GapStoryBoard *stb;
+ GapStoryBoard *old_stb;
+
+ old_stb = p_tabw_get_stb_ptr(tabw);
+ if (old_stb)
+ {
+ p_tabw_destroy_all_popup_dlg(tabw);
+ }
stb = gap_stb_undo_redo(tabw);
if (stb)
@@ -4020,6 +4039,12 @@ p_tabw_destroy_attw_dlg (GapStbTabWidgets *tabw, gboolean destroy_all)
if(attw->attw_prop_dialog)
{
+ if(attw->movepath_edit_dialog != NULL)
+ {
+ /* force close of the movepath edit dialog that is still open */
+ gtk_widget_destroy(attw->movepath_edit_dialog);
+ attw->movepath_edit_dialog = NULL;
+ }
gtk_widget_destroy(attw->attw_prop_dialog);
}
if(attw_prev)
@@ -5380,8 +5405,8 @@ p_menu_win_debug_log_to_stdout_cb (GtkWidget *widget, GapStbMainGlobalParams *sg
if (selection_found != TRUE)
{
printf("INFO p_menu_win_debug_log_to_stdout_cb:"
- "The file: %s does not exist or does not contain"
- "any valid selction what to print for debug purpose.\n"
+ " The file: %s does not exist or does not contain"
+ " any valid selction what to print for debug purpose.\n"
, GAP_DEBUG_STORYBOARD_CONFIG_FILE);
}
@@ -6104,7 +6129,7 @@ p_make_item_with_image(GtkWidget *parent, const gchar *stock_id,
GtkWidget *item;
item = gtk_image_menu_item_new_from_stock(stock_id
- , NULL // accelerator_group
+ , NULL /* accelerator_group */
);
gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
diff --git a/gap/gap_story_main.h b/gap/gap_story_main.h
old mode 100644
new mode 100755
index 48a908a..056ec41
--- a/gap/gap_story_main.h
+++ b/gap/gap_story_main.h
@@ -36,6 +36,7 @@
#include "gap_story_file.h"
#include "gap_story_undo_types.h"
#include "gap_player_main.h"
+#include "gap_mov_dialog.h"
#define GAP_STORY_PLUG_IN_PROC "plug_in_gap_storyboard_edit"
#define GAP_STORYBOARD_EDIT_HELP_ID "plug-in-gap-storyboard-edit"
@@ -321,10 +322,18 @@ typedef struct GapStbAttrWidget /* nickname: attw */
GtkWidget *spinbutton_overlap_dur;
GtkWidget *button_overlap_dur;
- GtkWidget *comment_entry;
- GtkWidget *movepath_file_entry;
- GtkWidget *movepath_filesel;
- gboolean movepath_file_xml_is_valid;
+ GtkWidget *comment_entry;
+
+ GtkWidget *movepath_edit_button;
+ GtkWidget *movepath_file_entry;
+ GtkWidget *movepath_filesel;
+ gboolean movepath_file_xml_is_valid;
+ GtkWidget *movepath_edit_dialog;
+ GapAnimInfo *ainfo_ptr;
+ GapMovValues *pvals;
+ gint32 movepath_frame_image_id;
+ gint32 movepath_obj_image_id;
+ gint32 movepath_obj_layer_id;
struct GapStbAttrWidget *next;
} GapStbAttrWidget;
diff --git a/gap/gap_story_undo.c b/gap/gap_story_undo.c
old mode 100644
new mode 100755
index 35a6692..fbadd42
--- a/gap/gap_story_undo.c
+++ b/gap/gap_story_undo.c
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <unistd.h>
+#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
@@ -42,6 +43,7 @@
#include "gap_story_undo.h"
#include "gap_story_dialog.h"
#include "gap_story_file.h"
+#include "gap_libgapbase.h"
extern int gap_debug; /* 1 == print debug infos , 0 dont print debug infos */
@@ -75,14 +77,33 @@ gap_stb_undo_debug_print_stack(GapStbTabWidgets *tabw)
for(undo_elem = tabw->undo_stack_list; undo_elem != NULL; undo_elem = undo_elem->next)
{
- printf(" %d %s"
+ printf(" addr:%d fPtr:%d %s"
, (int)undo_elem
+ , (int)undo_elem->filenamePtr
, gap_stb_undo_feature_to_string(undo_elem->feature_id)
);
if(undo_elem == tabw->undo_stack_ptr)
{
printf(" <-- stack_ptr");
}
+
+ if(undo_elem->fileSnapshotBefore != NULL)
+ {
+ printf(" (BEFORE: fname:%s size:%d mtime:%d)"
+ ,undo_elem->fileSnapshotBefore->filename
+ ,(int)undo_elem->fileSnapshotBefore->filesize
+ ,(int)undo_elem->fileSnapshotBefore->mtimefile
+ );
+ }
+ if(undo_elem->fileSnapshotAfter != NULL)
+ {
+ printf(" (AFTER: fname:%s size:%d mtime:%d)"
+ ,undo_elem->fileSnapshotAfter->filename
+ ,(int)undo_elem->fileSnapshotAfter->filesize
+ ,(int)undo_elem->fileSnapshotAfter->mtimefile
+ );
+ }
+
printf("\n");
fflush(stdout);
}
@@ -123,6 +144,122 @@ gap_stb_undo_feature_to_string(GapStoryFeatureEnum feature_id)
} /* end gap_stb_undo_feature_to_string */
+/* ---------------------------------------
+ * p_free_file_snapshot
+ * ---------------------------------------
+ */
+static void
+p_free_file_snapshot(GapStoryUndoFileSnapshot *fileSnapshot)
+{
+ if(fileSnapshot == NULL)
+ {
+ return;
+ }
+ if(fileSnapshot->filename)
+ {
+ g_free(fileSnapshot->filename);
+ }
+ if(fileSnapshot->filecontent)
+ {
+ g_free(fileSnapshot->filecontent);
+ }
+ g_free(fileSnapshot);
+
+} /* end p_free_file_snapshot */
+
+
+/* -----------------------------------------
+ * p_create_file_snapshot
+ * -----------------------------------------
+ */
+static GapStoryUndoFileSnapshot*
+p_create_file_snapshot(char *filename)
+{
+ GapStoryUndoFileSnapshot *fileSnapshot;
+ const char *filecontent;
+
+ fileSnapshot = NULL;
+
+ if(g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+ {
+ gint32 filesize;
+
+ filecontent = gap_file_load_file_len(filename, &filesize);
+
+ if(filecontent != NULL)
+ {
+ fileSnapshot = g_new(GapStoryUndoFileSnapshot, 1);
+ fileSnapshot->mtimefile = gap_file_get_mtime(filename);
+ fileSnapshot->filename = g_strdup(filename);
+ fileSnapshot->filecontent = filecontent;
+ fileSnapshot->filesize = filesize;
+ }
+ }
+
+ return (fileSnapshot);
+} /* end p_create_file_snapshot */
+
+
+
+/* -----------------------------------------
+ * p_replace_file_from_snapshot
+ * -----------------------------------------
+ */
+static void
+p_replace_file_from_snapshot(GapStoryUndoFileSnapshot* fileSnapshot)
+{
+ FILE *fp;
+
+ if(fileSnapshot == NULL)
+ {
+ return;
+ }
+ if(fileSnapshot->filename == NULL)
+ {
+ return;
+ }
+
+ if(g_file_test(fileSnapshot->filename, G_FILE_TEST_IS_REGULAR))
+ {
+ if(fileSnapshot->mtimefile == gap_file_get_mtime(fileSnapshot->filename))
+ {
+ /* the file still exists with same mtime stamp
+ * no further action required in this case..
+ */
+ if(gap_debug)
+ {
+ printf("p_replace_file_from_snapshot:%s skipped due to EQUAL mtime:%d\n"
+ , fileSnapshot->filename
+ ,(int)fileSnapshot->mtimefile
+ );
+ }
+ return;
+ }
+ }
+
+ if(gap_debug)
+ {
+ printf("p_replace_file_from_snapshot:%s\n", fileSnapshot->filename);
+ }
+
+ /* open write binary (create or replace) */
+ fp = g_fopen(fileSnapshot->filename, "wb");
+ if(fp != NULL)
+ {
+ fwrite(fileSnapshot->filecontent, fileSnapshot->filesize, 1, fp);
+ fclose(fp);
+ /* refresh the modification timestamp after rewrite */
+ fileSnapshot->mtimefile = gap_file_get_mtime(fileSnapshot->filename);
+ }
+
+
+} /* end p_replace_file_from_snapshot */
+
+
+
+
+
+
/* ---------------------------------------
* gap_stb_undo_pop
@@ -188,6 +325,11 @@ gap_stb_undo_pop(GapStbTabWidgets *tabw)
stb = gap_story_duplicate_full(tabw->undo_stack_ptr->stb);
+ if(tabw->undo_stack_ptr->fileSnapshotBefore != NULL)
+ {
+ p_replace_file_from_snapshot(tabw->undo_stack_ptr->fileSnapshotBefore);
+ }
+
if(gap_debug)
{
printf("gap_stb_undo_pop returning feature_id:%d %s grp_count:%.2f next:%d\n"
@@ -218,12 +360,20 @@ gap_stb_undo_pop(GapStbTabWidgets *tabw)
* feature (that now shall be undone) was applied.
*
*
- * stack_list -->latest latest
- * EEEE EEEE
- * DDDD DDDD <--- stack_ptr after redo
- * CCCC <-- stack_ptr before redo CCCC returns (EEEE)
- * BBBB BBBB
- * AAAA AAAA
+ * stack_list -->latest latest
+ * EEEE EEEE
+ * DDDD DDDD <--- stack_ptr after redo (DDDD)
+ * CCCC <-- stack_ptr before redo (DDDD) CCCC returns (EEEE)
+ * BBBB BBBB
+ * AAAA AAAA
+ * --------------------------------------------------------------------------------
+ *
+ * Example with one feature AAAA on the stack
+ *
+ * stack_ptr is NULL before redo(AAAA)
+ * stack_list -->latest latest
+ * AAAA AAAA <--- stack_ptr after redo AAAA
+ * returns (latest)
* --------------------------------------------------------------------------------
*/
GapStoryBoard *
@@ -256,6 +406,14 @@ gap_stb_undo_redo(GapStbTabWidgets *tabw)
if (redo_elem != NULL)
{
stb = gap_story_duplicate_full(redo_elem->stb);
+ if(tabw->undo_stack_ptr != NULL)
+ {
+ if(tabw->undo_stack_ptr->fileSnapshotAfter != NULL)
+ {
+ p_replace_file_from_snapshot(tabw->undo_stack_ptr->fileSnapshotAfter);
+ }
+ }
+
gap_story_dlg_tabw_undo_redo_sensitivity(tabw);
if(gap_debug)
@@ -289,10 +447,27 @@ p_free_undo_elem(GapStoryUndoElem *undo_elem)
if(gap_debug)
{
- printf("p_free_undo_elem: %d %s\n"
+ printf("p_free_undo_elem: %d %s"
, (int)undo_elem
, gap_stb_undo_feature_to_string(undo_elem->feature_id)
);
+ if(undo_elem->fileSnapshotBefore != NULL)
+ {
+ printf(" fileSnapshotBefore:%s filesize:%d mtime:%d"
+ ,undo_elem->fileSnapshotBefore->filename
+ ,(int)undo_elem->fileSnapshotBefore->filesize
+ ,(int)undo_elem->fileSnapshotBefore->mtimefile
+ );
+ }
+ if(undo_elem->fileSnapshotAfter != NULL)
+ {
+ printf(" fileSnapshotAfter:%s filesize:%d mtime:%d"
+ ,undo_elem->fileSnapshotAfter->filename
+ ,(int)undo_elem->fileSnapshotAfter->filesize
+ ,(int)undo_elem->fileSnapshotAfter->mtimefile
+ );
+ }
+ printf("\n");
fflush(stdout);
}
@@ -301,6 +476,18 @@ p_free_undo_elem(GapStoryUndoElem *undo_elem)
{
gap_story_free_storyboard(&undo_elem->stb);
}
+
+ if(undo_elem->fileSnapshotBefore != NULL)
+ {
+ p_free_file_snapshot(undo_elem->fileSnapshotBefore);
+ undo_elem->fileSnapshotBefore = NULL;
+ }
+ if(undo_elem->fileSnapshotAfter != NULL)
+ {
+ p_free_file_snapshot(undo_elem->fileSnapshotAfter);
+ undo_elem->fileSnapshotAfter = NULL;
+ }
+
g_free(undo_elem);
} /* end p_free_undo_elem */
@@ -397,28 +584,71 @@ gap_stb_undo_destroy_undo_stack(GapStbTabWidgets *tabw)
} /* end gap_stb_undo_destroy_undo_stack */
-/* ---------------------------------------
- * gap_stb_undo_push_clip
- * ---------------------------------------
+/* -----------------------------------------
+ * gap_stb_undo_push_clip_with_file_snapshot
+ * -----------------------------------------
* create a new undo element (according to specified parameters)
- * and place it at top (first) of the und stack.
+ * and place it at top (first) of the undo stack.
* if the stackpointer is NOT equal to the stack_list root,
- * the delete all undo elements from stack_list up to stackpointer.
+ * then delete all undo elements from stack_list up to stackpointer.
*
* move the stackpointer to next element. (keep the element
- * on the stack for redo purpose)
+ * on the stack list for undo purpose)
+ *
+ * if *filenamePtr points to an existing readable file, this procedure
+ * attaches a copy of the filename and its full content to the pushed element.
+ * (fileSnapshotBefore)
+ * Note that the current implementation keeps the filecontent in memory
+ * because it is intended to hold small parameterfiles (xml settings for movepath transistion)
+ * The filename Must NOT be used to store large data (as image or movie content)
+ *
+ * If the element at stack_ptr (that represents the previous procesing step)
+ * has a fileSnapshot attached then this is also recorded as fileSnapshotAfter
+ *
+ * Example
+ * =======
+ * push element EEEE, *filenamePtr points to "a.xml"
*
* stack_list -->DDDD
- * CCCC EEEE <--- stack_ptr after push (EEEE)
- * BBBB <-- stack_ptr before push(EEEE) BBBB (deletes CCCC, DDDD)
- * AAAA AAAA
+ * CCCC EEEE <--- stack_ptr after push (EEEE, a.xml)
+ * BBBB <-- stack_ptr before push(EEEE, a.xml) BBBB (deletes CCCC, DDDD)
+ * AAAA AAAA
* --------------------------------------------------------------------------------
+ *
+ * content of elem EEEE after the push EEEE operation:
+ *
+ * EEEE.fileSnapshotBefore holds filename and content of a.xml (before processing of step EEEE)
+ * EEEE.fileSnapshotAfter is NULL
+ * EEEE.filenamePtr holds addr of the pointer that points to filename "a.xml"
+ *
+ *
+ * Example continued:
+ * ==================
+ *
+ *
+ * FFFF <--- stack_ptr after push (FFFF, NULL)
+ * stack_list -->EEEE <-- stack_ptr before push(FFFF, NULL) EEEE ..... updated fileSnapshotAfter
+ * BBBB BBBB
+ * AAAA AAAA
+ * --------------------------------------------------------------------------------
+ *
+ * content of elem EEEE after the push FFFF operation:
+ *
+ * EEEE.fileSnapshotBefore holds filename and content of a.xml
+ * (before processing of step EEEE, that is relevant for undo EEEE purpose)
+ * EEEE.fileSnapshotAfter holds filename and content at time of push FFFF
+ * (e.g. after processing EEEE is finished, that is relevant for redo EEEE purpose)
+ * EEEE.filenamePtr is rest to NULL
+ *
*/
void
-gap_stb_undo_push_clip(GapStbTabWidgets *tabw, GapStoryFeatureEnum feature_id, gint32 story_id)
+gap_stb_undo_push_clip_with_file_snapshot(GapStbTabWidgets *tabw
+ , GapStoryFeatureEnum feature_id, gint32 story_id
+ , char **filenamePtr)
{
GapStoryBoard *stb;
GapStoryUndoElem *new_undo_elem;
+ GapStoryUndoElem *top_undo_elem;
if(tabw == NULL)
@@ -478,6 +708,50 @@ gap_stb_undo_push_clip(GapStbTabWidgets *tabw, GapStoryFeatureEnum feature_id, g
new_undo_elem = g_new(GapStoryUndoElem, 1);
new_undo_elem->clip_story_id = story_id;
new_undo_elem->feature_id = feature_id;
+
+ new_undo_elem->filenamePtr = NULL;
+ new_undo_elem->fileSnapshotBefore = NULL;
+ new_undo_elem->fileSnapshotAfter = NULL;
+ if(filenamePtr != NULL)
+ {
+ char *filename;
+
+ new_undo_elem->filenamePtr = filenamePtr;
+ filename = *filenamePtr;
+ if(filename != NULL)
+ {
+ new_undo_elem->fileSnapshotBefore = p_create_file_snapshot(filename);
+ }
+ }
+
+ top_undo_elem = tabw->undo_stack_list;
+ if (top_undo_elem != NULL)
+ {
+ if(top_undo_elem->filenamePtr != NULL)
+ {
+ char *filename;
+
+ /* at this point the top_undo_elem represents the previous step
+ * that just has been finished, since the next step (new_undo_elem)
+ * is ready to be pushed on the stack, and top_undo_elem->filenamePtr != NULL
+ * indicates that the previous step may have edited a file.
+ * now record this fileSnapshotAfter for redo purpose
+ * Note that both filename and content may have changed in the previous step
+ * since recording the fileSnapshotBefore.
+ */
+ filename = *top_undo_elem->filenamePtr;
+ if(filename != NULL)
+ {
+ top_undo_elem->fileSnapshotAfter = p_create_file_snapshot(filename);
+ }
+ }
+ /* clear the filenamePtr to disable multiple recording of fileSnapshotAfter
+ * Note that filenamePtr refers to a clip that may only exist until the next processing step
+ * that already can delete the clip (this can also happen in undo processing
+ * where the storyboard is replaced by a duplicate and the adress)
+ */
+ top_undo_elem->filenamePtr = NULL;
+ }
new_undo_elem->next = tabw->undo_stack_list;
@@ -490,6 +764,32 @@ gap_stb_undo_push_clip(GapStbTabWidgets *tabw, GapStoryFeatureEnum feature_id, g
gap_story_dlg_tabw_undo_redo_sensitivity(tabw);
+} /* end gap_stb_undo_push_clip_with_file_snapshot */
+
+
+
+/* ---------------------------------------
+ * gap_stb_undo_push_clip
+ * ---------------------------------------
+ * create a new undo element (according to specified parameters)
+ * and place it at top (first) of the undo stack.
+ * if the stackpointer is NOT equal to the stack_list root,
+ * the delete all undo elements from stack_list up to stackpointer.
+ *
+ * move the stackpointer to next element. (keep the element
+ * on the stack for redo purpose)
+ *
+ * stack_list -->DDDD
+ * CCCC EEEE <--- stack_ptr after push (EEEE)
+ * BBBB <-- stack_ptr before push(EEEE) BBBB (deletes CCCC, DDDD)
+ * AAAA AAAA
+ * --------------------------------------------------------------------------------
+ */
+void
+gap_stb_undo_push_clip(GapStbTabWidgets *tabw, GapStoryFeatureEnum feature_id, gint32 story_id)
+{
+ gap_stb_undo_push_clip_with_file_snapshot(tabw, feature_id, story_id, NULL);
+
} /* end gap_stb_undo_push_clip */
diff --git a/gap/gap_story_undo.h b/gap/gap_story_undo.h
old mode 100644
new mode 100755
index c911943..af76851
--- a/gap/gap_story_undo.h
+++ b/gap/gap_story_undo.h
@@ -45,6 +45,10 @@ void gap_stb_undo_push_clip(GapStbTabWidgets *tabw
, GapStoryFeatureEnum feature_id
, gint32 story_id
);
+void gap_stb_undo_push_clip_with_file_snapshot(GapStbTabWidgets *tabw
+ , GapStoryFeatureEnum feature_id, gint32 story_id
+ , char **filenamePtr);
+
void gap_stb_undo_push(GapStbTabWidgets *tabw, GapStoryFeatureEnum feature_id);
void gap_stb_undo_group_begin(GapStbTabWidgets *tabw);
void gap_stb_undo_group_end(GapStbTabWidgets *tabw);
diff --git a/gap/gap_story_undo_types.h b/gap/gap_story_undo_types.h
old mode 100644
new mode 100755
index bd9f50a..b989a66
--- a/gap/gap_story_undo_types.h
+++ b/gap/gap_story_undo_types.h
@@ -54,18 +54,32 @@ typedef enum
} GapStoryFeatureEnum;
+/* storyboard undo file snapshot element
+ */
+typedef struct GapStoryUndoFileSnapshot {
+ char *filename;
+ char *filecontent;
+ gint32 filesize;
+ gint32 mtimefile;
+} GapStoryUndoFileSnapshot;
+
+
+
/* storyboard undo element
*/
typedef struct GapStoryUndoElem {
- GapStoryFeatureEnum feature_id;
+ GapStoryFeatureEnum feature_id;
gint32 clip_story_id; /* -1 if feature modifies more than 1 clip */
- GapStoryBoard *stb; /* storyboard backup before
- * feature with feature_id was applied
+ GapStoryBoard *stb; /* storyboard backup before
+ * feature with feature_id was applied
*/
- struct GapStoryUndoElem *next;
+ GapStoryUndoFileSnapshot *fileSnapshotBefore;
+ GapStoryUndoFileSnapshot *fileSnapshotAfter;
+ char **filenamePtr;
+ struct GapStoryUndoElem *next;
} GapStoryUndoElem;
-#endif
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]