[gimp/wip/animation: 169/197] plug-ins: add a camera preview concept to update only the current frame.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/animation: 169/197] plug-ins: add a camera preview concept to update only the current frame.
- Date: Sat, 7 Oct 2017 03:12:39 +0000 (UTC)
commit 8d02bc5fcbf5a0bdb3014dc0de49dd054d7bf8dd
Author: Jehan <jehan girinstud io>
Date: Mon Jun 26 17:50:26 2017 +0200
plug-ins: add a camera preview concept to update only the current frame.
When moving the camera, it is useless to start big processing over all
impacted frames (because of interpolation of camera moves) immediately.
Just wait for when the user confirms the keyframe. Right now, that only
happens when switching to another frame.
plug-ins/animation-play/core/animation-camera.c | 216 +++++++++++++-------
plug-ins/animation-play/core/animation-camera.h | 33 ++--
.../animation-play/core/animation-celanimation.c | 1 +
.../widgets/animation-keyframe-view.c | 120 ++++++-----
4 files changed, 233 insertions(+), 137 deletions(-)
---
diff --git a/plug-ins/animation-play/core/animation-camera.c b/plug-ins/animation-play/core/animation-camera.c
index b42a264..26a2780 100644
--- a/plug-ins/animation-play/core/animation-camera.c
+++ b/plug-ins/animation-play/core/animation-camera.c
@@ -54,6 +54,10 @@ struct _AnimationCameraPrivate
/* Panning and tilting. */
GList *offsets;
+
+ /* Preview */
+ Offset *preview_offset;
+ gint preview_position;
};
static void animation_camera_finalize (GObject *object);
@@ -68,6 +72,10 @@ static void animation_camera_get_property (GObject *object,
static void animation_camera_emit_offsets_changed (AnimationCamera *camera,
gint position);
+static void animation_camera_get_real (AnimationCamera *camera,
+ gint position,
+ gint *x_offset,
+ gint *y_offset);
G_DEFINE_TYPE (AnimationCamera, animation_camera, G_TYPE_OBJECT)
@@ -159,6 +167,7 @@ animation_camera_init (AnimationCamera *view)
view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view,
ANIMATION_TYPE_CAMERA,
AnimationCameraPrivate);
+ view->priv->preview_position = -1;
}
/************ Public Functions ****************/
@@ -246,84 +255,71 @@ animation_camera_delete_keyframe (AnimationCamera *camera,
}
void
+animation_camera_preview_keyframe (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (position >= 0 &&
+ position < animation_get_duration (camera->priv->animation));
+
+ if (! camera->priv->preview_offset)
+ camera->priv->preview_offset = g_new (Offset, 1);
+
+ camera->priv->preview_offset->x = x;
+ camera->priv->preview_offset->y = y;
+ camera->priv->preview_position = position;
+
+ g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
+ position, 1);
+}
+
+void
+animation_camera_reset_preview (AnimationCamera *camera)
+{
+ gboolean offsets_changed = FALSE;
+ gint position_changed;
+
+ if (camera->priv->preview_offset)
+ {
+ gint preview_offset_x;
+ gint preview_offset_y;
+ gint real_offset_x;
+ gint real_offset_y;
+
+ animation_camera_get (camera, camera->priv->preview_position,
+ &preview_offset_x, &preview_offset_y);
+ animation_camera_get_real (camera, camera->priv->preview_position,
+ &real_offset_x, &real_offset_y);
+ offsets_changed = (preview_offset_x != real_offset_x ||
+ preview_offset_y != real_offset_y);
+ position_changed = camera->priv->preview_position;
+
+ g_free (camera->priv->preview_offset);
+ camera->priv->preview_offset = NULL;
+ }
+
+ camera->priv->preview_position = -1;
+
+ if (offsets_changed)
+ g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
+ position_changed, 1);
+}
+
+void
animation_camera_get (AnimationCamera *camera,
gint position,
gint *x_offset,
gint *y_offset)
{
- Offset *keyframe;
-
- g_return_if_fail (position >= 0 &&
- position < animation_get_duration (camera->priv->animation));
-
- keyframe = g_list_nth_data (camera->priv->offsets, position);
- if (keyframe)
+ if (camera->priv->preview_position == position)
{
- /* There is a keyframe to this exact position. Use its values. */
- *x_offset = keyframe->x;
- *y_offset = keyframe->y;
+ *x_offset = camera->priv->preview_offset->x;
+ *y_offset = camera->priv->preview_offset->y;
}
else
{
- GList *iter;
- Offset *prev_keyframe = NULL;
- Offset *next_keyframe = NULL;
- gint prev_keyframe_pos;
- gint next_keyframe_pos;
- gint i;
-
- /* This position is not a keyframe. */
- if (position > 0)
- {
- i = MIN (position - 1, g_list_length (camera->priv->offsets) - 1);
- iter = g_list_nth (camera->priv->offsets, i);
- for (; iter && ! iter->data; iter = iter->prev, i--)
- ;
- if (iter && iter->data)
- {
- prev_keyframe_pos = i;
- prev_keyframe = iter->data;
- }
- }
- if (position < animation_get_duration (camera->priv->animation) - 1)
- {
- i = position + 1;
- iter = g_list_nth (camera->priv->offsets, i);
- for (; iter && ! iter->data; iter = iter->next, i++)
- ;
- if (iter && iter->data)
- {
- next_keyframe_pos = i;
- next_keyframe = iter->data;
- }
- }
-
- if (prev_keyframe == NULL && next_keyframe == NULL)
- {
- *x_offset = *y_offset = 0;
- }
- else if (prev_keyframe == NULL)
- {
- *x_offset = next_keyframe->x;
- *y_offset = next_keyframe->y;
- }
- else if (next_keyframe == NULL)
- {
- *x_offset = prev_keyframe->x;
- *y_offset = prev_keyframe->y;
- }
- else
- {
- /* XXX No curve editing or anything like this yet.
- * All keyframing is linear in this first version.
- */
- *x_offset = prev_keyframe->x + (position - prev_keyframe_pos) *
- (next_keyframe->x - prev_keyframe->x) /
- (next_keyframe_pos - prev_keyframe_pos);
- *y_offset = prev_keyframe->y + (position - prev_keyframe_pos) *
- (next_keyframe->y - prev_keyframe->y) /
- (next_keyframe_pos - prev_keyframe_pos);
- }
+ animation_camera_get_real (camera, position, x_offset, y_offset);
}
}
@@ -416,3 +412,85 @@ animation_camera_emit_offsets_changed (AnimationCamera *camera,
g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
prev_keyframe, next_keyframe - prev_keyframe + 1);
}
+
+static void
+animation_camera_get_real (AnimationCamera *camera,
+ gint position,
+ gint *x_offset,
+ gint *y_offset)
+{
+ Offset *keyframe;
+
+ g_return_if_fail (position >= 0 &&
+ position < animation_get_duration (camera->priv->animation));
+
+ keyframe = g_list_nth_data (camera->priv->offsets, position);
+ if (keyframe)
+ {
+ /* There is a keyframe to this exact position. Use its values. */
+ *x_offset = keyframe->x;
+ *y_offset = keyframe->y;
+ }
+ else
+ {
+ GList *iter;
+ Offset *prev_keyframe = NULL;
+ Offset *next_keyframe = NULL;
+ gint prev_keyframe_pos;
+ gint next_keyframe_pos;
+ gint i;
+
+ /* This position is not a keyframe. */
+ if (position > 0)
+ {
+ i = MIN (position - 1, g_list_length (camera->priv->offsets) - 1);
+ iter = g_list_nth (camera->priv->offsets, i);
+ for (; iter && ! iter->data; iter = iter->prev, i--)
+ ;
+ if (iter && iter->data)
+ {
+ prev_keyframe_pos = i;
+ prev_keyframe = iter->data;
+ }
+ }
+ if (position < animation_get_duration (camera->priv->animation) - 1)
+ {
+ i = position + 1;
+ iter = g_list_nth (camera->priv->offsets, i);
+ for (; iter && ! iter->data; iter = iter->next, i++)
+ ;
+ if (iter && iter->data)
+ {
+ next_keyframe_pos = i;
+ next_keyframe = iter->data;
+ }
+ }
+
+ if (prev_keyframe == NULL && next_keyframe == NULL)
+ {
+ *x_offset = *y_offset = 0;
+ }
+ else if (prev_keyframe == NULL)
+ {
+ *x_offset = next_keyframe->x;
+ *y_offset = next_keyframe->y;
+ }
+ else if (next_keyframe == NULL)
+ {
+ *x_offset = prev_keyframe->x;
+ *y_offset = prev_keyframe->y;
+ }
+ else
+ {
+ /* XXX No curve editing or anything like this yet.
+ * All keyframing is linear in this first version.
+ */
+ *x_offset = prev_keyframe->x + (position - prev_keyframe_pos) *
+ (next_keyframe->x - prev_keyframe->x) /
+ (next_keyframe_pos - prev_keyframe_pos);
+ *y_offset = prev_keyframe->y + (position - prev_keyframe_pos) *
+ (next_keyframe->y - prev_keyframe->y) /
+ (next_keyframe_pos - prev_keyframe_pos);
+ }
+ }
+}
diff --git a/plug-ins/animation-play/core/animation-camera.h b/plug-ins/animation-play/core/animation-camera.h
index 63e4e09..0301679 100644
--- a/plug-ins/animation-play/core/animation-camera.h
+++ b/plug-ins/animation-play/core/animation-camera.h
@@ -53,23 +53,28 @@ struct _AnimationCameraClass
gint position);
};
-GType animation_camera_get_type (void) G_GNUC_CONST;
+GType animation_camera_get_type (void) G_GNUC_CONST;
-AnimationCamera * animation_camera_new (Animation *animation);
+AnimationCamera * animation_camera_new (Animation *animation);
-gboolean animation_camera_has_keyframe (AnimationCamera *camera,
- gint position);
+gboolean animation_camera_has_keyframe (AnimationCamera *camera,
+ gint position);
-void animation_camera_set_keyframe (AnimationCamera *camera,
- gint position,
- gint x,
- gint y);
-void animation_camera_delete_keyframe (AnimationCamera *camera,
- gint position);
+void animation_camera_set_keyframe (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y);
+void animation_camera_delete_keyframe (AnimationCamera *camera,
+ gint position);
+void animation_camera_preview_keyframe (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y);
+void animation_camera_reset_preview (AnimationCamera *camera);
-void animation_camera_get (AnimationCamera *camera,
- gint position,
- gint *x_offset,
- gint *y_offset);
+void animation_camera_get (AnimationCamera *camera,
+ gint position,
+ gint *x_offset,
+ gint *y_offset);
#endif /* __ANIMATION_CAMERA_H__ */
diff --git a/plug-ins/animation-play/core/animation-celanimation.c
b/plug-ins/animation-play/core/animation-celanimation.c
index 00bdeb8..1439fee 100644
--- a/plug-ins/animation-play/core/animation-celanimation.c
+++ b/plug-ins/animation-play/core/animation-celanimation.c
@@ -770,6 +770,7 @@ animation_cel_animation_serialize (Animation *animation,
priv = ANIMATION_CEL_ANIMATION (animation)->priv;
+ animation_camera_reset_preview (priv->camera);
animation_get_size (animation, &width, &height);
xml = g_strdup_printf ("<animation type=\"cels\" framerate=\"%f\" "
" duration=\"%d\" onion-skins=\"%d\""
diff --git a/plug-ins/animation-play/widgets/animation-keyframe-view.c
b/plug-ins/animation-play/widgets/animation-keyframe-view.c
index 6ff661a..6ce4d65 100644
--- a/plug-ins/animation-play/widgets/animation-keyframe-view.c
+++ b/plug-ins/animation-play/widgets/animation-keyframe-view.c
@@ -75,6 +75,8 @@ animation_keyframe_view_init (AnimationKeyFrameView *view)
view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view,
ANIMATION_TYPE_KEYFRAME_VIEW,
AnimationKeyFrameViewPrivate);
+ view->priv->position = -1;
+ view->priv->update_position = -1;
}
/************ Public Functions ****************/
@@ -121,46 +123,60 @@ animation_keyframe_view_show (AnimationKeyFrameView *view,
camera = ANIMATION_CAMERA (animation_cel_animation_get_main_camera (animation));
- view->priv->camera = camera;
- view->priv->position = position;
-
- image_id = animation_get_image_id (ANIMATION (animation));
- gimp_image_get_resolution (image_id, &xres, &yres);
-
- animation_get_size (ANIMATION (animation), &width, &height);
- gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 0, (gdouble) -GIMP_MAX_IMAGE_SIZE,
- (gdouble) GIMP_MAX_IMAGE_SIZE);
- gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 1, (gdouble) -GIMP_MAX_IMAGE_SIZE,
- (gdouble) GIMP_MAX_IMAGE_SIZE);
- gimp_size_entry_set_size (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 0, 0.0, (gdouble) width);
- gimp_size_entry_set_size (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 1, 0.0, (gdouble) height);
- gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 0, xres, TRUE);
- gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 1, yres, TRUE);
-
- g_signal_handlers_disconnect_by_func (view->priv->offset_entry,
- G_CALLBACK (on_offset_entry_changed),
- view);
- g_signal_handlers_disconnect_by_func (view->priv->camera,
- G_CALLBACK (on_offsets_changed),
- view);
- animation_camera_get (camera, position, &x_offset, &y_offset);
- gimp_size_entry_set_value (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 0, (gdouble) x_offset);
- gimp_size_entry_set_value (GIMP_SIZE_ENTRY (view->priv->offset_entry),
- 1, (gdouble) y_offset);
- g_signal_connect (view->priv->offset_entry, "value-changed",
- G_CALLBACK (on_offset_entry_changed),
- view);
- g_signal_connect (camera, "offsets-changed",
- G_CALLBACK (on_offsets_changed),
- view);
- gtk_widget_show (GTK_WIDGET (view));
+ if (view->priv->position != position ||
+ view->priv->camera != camera)
+ {
+ if (view->priv->camera == camera &&
+ view->priv->update_position != -1)
+ {
+ /* We jumped to another position. Apply the ongoing preview. */
+ animation_camera_set_keyframe (view->priv->camera,
+ view->priv->update_position,
+ view->priv->update_x_offset,
+ view->priv->update_y_offset);
+ }
+ view->priv->camera = camera;
+ view->priv->position = position;
+
+ image_id = animation_get_image_id (ANIMATION (animation));
+ gimp_image_get_resolution (image_id, &xres, &yres);
+
+ animation_get_size (ANIMATION (animation), &width, &height);
+ gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 0, (gdouble) -GIMP_MAX_IMAGE_SIZE,
+ (gdouble) GIMP_MAX_IMAGE_SIZE);
+ gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 1, (gdouble) -GIMP_MAX_IMAGE_SIZE,
+ (gdouble) GIMP_MAX_IMAGE_SIZE);
+ gimp_size_entry_set_size (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 0, 0.0, (gdouble) width);
+ gimp_size_entry_set_size (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 1, 0.0, (gdouble) height);
+ gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 0, xres, TRUE);
+ gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 1, yres, TRUE);
+
+ g_signal_handlers_disconnect_by_func (view->priv->offset_entry,
+ G_CALLBACK (on_offset_entry_changed),
+ view);
+ g_signal_handlers_disconnect_by_func (view->priv->camera,
+ G_CALLBACK (on_offsets_changed),
+ view);
+ animation_camera_reset_preview (camera);
+ animation_camera_get (camera, position, &x_offset, &y_offset);
+ gimp_size_entry_set_value (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 0, (gdouble) x_offset);
+ gimp_size_entry_set_value (GIMP_SIZE_ENTRY (view->priv->offset_entry),
+ 1, (gdouble) y_offset);
+ g_signal_connect (view->priv->offset_entry, "value-changed",
+ G_CALLBACK (on_offset_entry_changed),
+ view);
+ g_signal_connect (camera, "offsets-changed",
+ G_CALLBACK (on_offsets_changed),
+ view);
+ gtk_widget_show (GTK_WIDGET (view));
+ }
}
void
@@ -210,10 +226,14 @@ animation_keyframe_update_source (gpointer user_data)
AnimationKeyFrameView *view = user_data;
view->priv->update_source = 0;
- animation_camera_set_keyframe (view->priv->camera,
- view->priv->update_position,
- view->priv->update_x_offset,
- view->priv->update_y_offset);
+ /* Only update the preview if we are currently showing this frame. */
+ if (view->priv->position == view->priv->update_position)
+ {
+ animation_camera_preview_keyframe (view->priv->camera,
+ view->priv->update_position,
+ view->priv->update_x_offset,
+ view->priv->update_y_offset);
+ }
return G_SOURCE_REMOVE;
}
@@ -224,19 +244,11 @@ on_offset_entry_changed (GimpSizeEntry *entry,
gdouble x_offset;
gdouble y_offset;
- /* If a timeout is pending, remove then recreate it in order to
+ /* If a timeout is pending, remove before recreating in order to
* postpone the camera update. */
if (view->priv->update_source)
{
g_source_remove (view->priv->update_source);
- if (view->priv->position != view->priv->update_position)
- {
- /* Do not postpone the update for another position. */
- animation_camera_set_keyframe (view->priv->camera,
- view->priv->update_position,
- view->priv->update_x_offset,
- view->priv->update_y_offset);
- }
}
x_offset = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (view->priv->offset_entry), 0);
@@ -244,7 +256,7 @@ on_offset_entry_changed (GimpSizeEntry *entry,
view->priv->update_x_offset = x_offset;
view->priv->update_y_offset = y_offset;
view->priv->update_position = view->priv->position;
- view->priv->update_source = g_timeout_add (100, animation_keyframe_update_source, view);
+ view->priv->update_source = g_timeout_add (10, animation_keyframe_update_source, view);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]