[gimp/wip/animation: 196/197] plug-ins: add zoom keyframing for the animation plug-in.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/animation: 196/197] plug-ins: add zoom keyframing for the animation plug-in.
- Date: Sat, 7 Oct 2017 03:14:55 +0000 (UTC)
commit 778625133dcf6adfe0f97c1923e90d05d2a4cd52
Author: Jehan <jehan girinstud io>
Date: Thu Sep 28 02:11:26 2017 +0200
plug-ins: add zoom keyframing for the animation plug-in.
It's still very edgy, but that's a start.
plug-ins/animation-play/animation-utils.c | 6 +-
plug-ins/animation-play/core/animation-camera.c | 315 ++++++++++++++++----
plug-ins/animation-play/core/animation-camera.h | 51 ++--
.../animation-play/core/animation-celanimation.c | 96 ++++--
plug-ins/animation-play/widgets/animation-dialog.c | 6 +-
.../widgets/animation-keyframe-view.c | 131 +++++++--
plug-ins/animation-play/widgets/animation-xsheet.c | 22 +-
7 files changed, 468 insertions(+), 159 deletions(-)
---
diff --git a/plug-ins/animation-play/animation-utils.c b/plug-ins/animation-play/animation-utils.c
index f4bfdd0..8b83341 100755
--- a/plug-ins/animation-play/animation-utils.c
+++ b/plug-ins/animation-play/animation-utils.c
@@ -150,12 +150,10 @@ normal_blend (gint width,
gdouble offx;
gdouble offy;
- g_return_val_if_fail (source_scale_ratio > 0.0 &&
- source_scale_ratio <= 1.0 &&
+ g_return_val_if_fail (source_scale_ratio >= 0.0 &&
source_buffer &&
(! backdrop_buffer ||
- (backdrop_scale_ratio >= 0.1 &&
- backdrop_scale_ratio <= 1.0)),
+ backdrop_scale_ratio >= 0.0),
NULL);
/* Panel image. */
diff --git a/plug-ins/animation-play/core/animation-camera.c b/plug-ins/animation-play/core/animation-camera.c
index 275085e..d3151d2 100644
--- a/plug-ins/animation-play/core/animation-camera.c
+++ b/plug-ins/animation-play/core/animation-camera.c
@@ -35,7 +35,7 @@ enum
enum
{
- OFFSETS_CHANGED,
+ CAMERA_CHANGED,
KEYFRAME_SET,
KEYFRAME_DELETED,
LAST_SIGNAL
@@ -54,10 +54,14 @@ struct _AnimationCameraPrivate
/* Panning and tilting. */
GList *offsets;
+ GList *zoom;
/* Preview */
Offset *preview_offset;
gint preview_position;
+ gdouble preview_scale;
+
+ gboolean block_signals;
};
static void animation_camera_finalize (GObject *object);
@@ -70,12 +74,13 @@ static void animation_camera_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
-static void animation_camera_emit_offsets_changed (AnimationCamera *camera,
+static void animation_camera_emit_camera_changed (AnimationCamera *camera,
gint position);
static void animation_camera_get_real (AnimationCamera *camera,
gint position,
gint *x_offset,
- gint *y_offset);
+ gint *y_offset,
+ gdouble *scale);
G_DEFINE_TYPE (AnimationCamera, animation_camera, G_TYPE_OBJECT)
@@ -93,19 +98,20 @@ animation_camera_class_init (AnimationCameraClass *klass)
object_class->set_property = animation_camera_set_property;
/**
- * AnimationCamera::offsets-changed:
+ * AnimationCamera::camera-changed:
* @camera: the #AnimationCamera.
* @position:
* @duration:
*
- * The ::offsets-changed signal will be emitted when camera offsets
- * were updated between [@position; @position + @duration[.
+ * The ::camera-changed signal will be emitted when camera offsets,
+ * zoom, or other characteristics were updated between
+ * [@position; @position + @duration[.
*/
- signals[OFFSETS_CHANGED] =
- g_signal_new ("offsets-changed",
+ signals[CAMERA_CHANGED] =
+ g_signal_new ("camera-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (AnimationCameraClass, offsets_changed),
+ G_STRUCT_OFFSET (AnimationCameraClass, camera_changed),
NULL, NULL,
NULL,
G_TYPE_NONE,
@@ -125,7 +131,7 @@ animation_camera_class_init (AnimationCameraClass *klass)
g_signal_new ("keyframe-set",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (AnimationCameraClass, offsets_changed),
+ G_STRUCT_OFFSET (AnimationCameraClass, keyframe_set),
NULL, NULL,
NULL,
G_TYPE_NONE,
@@ -144,7 +150,7 @@ animation_camera_class_init (AnimationCameraClass *klass)
g_signal_new ("keyframe-deleted",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (AnimationCameraClass, offsets_changed),
+ G_STRUCT_OFFSET (AnimationCameraClass, keyframe_deleted),
NULL, NULL,
NULL,
G_TYPE_NONE,
@@ -190,21 +196,32 @@ animation_camera_new (Animation *animation)
}
gboolean
-animation_camera_has_keyframe (AnimationCamera *camera,
- gint position)
+animation_camera_has_offset_keyframe (AnimationCamera *camera,
+ gint position)
{
g_return_val_if_fail (position >= 0 &&
position < animation_get_duration (camera->priv->animation),
FALSE);
- return (g_list_nth_data (camera->priv->offsets, position) != NULL);
+ return g_list_nth_data (camera->priv->offsets, position) != NULL;
+}
+
+gboolean
+animation_camera_has_zoom_keyframe (AnimationCamera *camera,
+ gint position)
+{
+ g_return_val_if_fail (position >= 0 &&
+ position < animation_get_duration (camera->priv->animation),
+ FALSE);
+
+ return g_list_nth_data (camera->priv->zoom, position) != NULL;
}
void
-animation_camera_set_keyframe (AnimationCamera *camera,
- gint position,
- gint x,
- gint y)
+animation_camera_set_offsets (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y)
{
GList *iter;
Offset *offset;
@@ -238,28 +255,92 @@ animation_camera_set_keyframe (AnimationCamera *camera,
offset->x = x;
offset->y = y;
- g_signal_emit (camera, signals[KEYFRAME_SET], 0, position);
- animation_camera_emit_offsets_changed (camera, position);
+ if (! camera->priv->block_signals)
+ {
+ g_signal_emit (camera, signals[KEYFRAME_SET], 0, position);
+ animation_camera_emit_camera_changed (camera, position);
+ }
+}
+
+void
+animation_camera_zoom (AnimationCamera *camera,
+ gint position,
+ gdouble scale)
+{
+ GList *iter;
+ gdouble *zoom;
+
+ g_return_if_fail (position >= 0 &&
+ position < animation_get_duration (camera->priv->animation));
+
+ iter = g_list_nth (camera->priv->zoom, position);
+
+ if (! iter)
+ {
+ gint length = g_list_length (camera->priv->zoom);
+ gint i;
+
+ for (i = length; i < position; i++)
+ {
+ camera->priv->zoom = g_list_append (camera->priv->zoom, NULL);
+ }
+ zoom = g_new (gdouble, 1);
+ camera->priv->zoom = g_list_append (camera->priv->zoom, zoom);
+ }
+ else
+ {
+ if (! iter->data)
+ {
+ iter->data = g_new (gdouble, 1);
+ }
+ zoom = iter->data;
+ }
+ *zoom = scale;
+
+ if (! camera->priv->block_signals)
+ {
+ g_signal_emit (camera, signals[KEYFRAME_SET], 0, position);
+ animation_camera_emit_camera_changed (camera, position);
+ }
}
void
-animation_camera_delete_keyframe (AnimationCamera *camera,
- gint position)
+animation_camera_delete_offset_keyframe (AnimationCamera *camera,
+ gint position)
{
- GList *offset;
+ GList *iter;
g_return_if_fail (position >= 0 &&
position < animation_get_duration (camera->priv->animation));
- offset = g_list_nth (camera->priv->offsets, position);
+ iter = g_list_nth (camera->priv->offsets, position);
+ if (iter && iter->data)
+ {
+ g_free (iter->data);
+ iter->data = NULL;
+
+ g_signal_emit (camera, signals[KEYFRAME_DELETED], 0, position);
+ animation_camera_emit_camera_changed (camera, position);
+ }
+}
- if (offset && offset->data)
+void
+animation_camera_delete_zoom_keyframe (AnimationCamera *camera,
+ gint position)
+{
+ GList *iter;
+
+ g_return_if_fail (position >= 0 &&
+ position < animation_get_duration (camera->priv->animation));
+
+ iter = g_list_nth (camera->priv->zoom, position);
+ if (iter && iter->data)
{
- g_free (offset->data);
- offset->data = NULL;
+ g_free (iter->data);
+ iter->data = NULL;
g_signal_emit (camera, signals[KEYFRAME_DELETED], 0, position);
- animation_camera_emit_offsets_changed (camera, position);
+ animation_camera_emit_camera_changed (camera, position);
}
}
@@ -267,7 +348,8 @@ void
animation_camera_preview_keyframe (AnimationCamera *camera,
gint position,
gint x,
- gint y)
+ gint y,
+ gdouble scale)
{
g_return_if_fail (position >= 0 &&
position < animation_get_duration (camera->priv->animation));
@@ -277,9 +359,10 @@ animation_camera_preview_keyframe (AnimationCamera *camera,
camera->priv->preview_offset->x = x;
camera->priv->preview_offset->y = y;
+ camera->priv->preview_scale = scale;
camera->priv->preview_position = position;
- g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
+ g_signal_emit (camera, signals[CAMERA_CHANGED], 0,
position, 1);
}
@@ -288,49 +371,70 @@ animation_camera_apply_preview (AnimationCamera *camera)
{
if (camera->priv->preview_offset)
{
- gint preview_offset_x;
- gint preview_offset_y;
- gint real_offset_x;
- gint real_offset_y;
- gint position;
+ gint preview_offset_x;
+ gint preview_offset_y;
+ gdouble preview_scale;
+ gint real_offset_x;
+ gint real_offset_y;
+ gdouble real_scale;
+ gint position;
animation_camera_get (camera, camera->priv->preview_position,
- &preview_offset_x, &preview_offset_y);
+ &preview_offset_x, &preview_offset_y,
+ &preview_scale);
animation_camera_get_real (camera, camera->priv->preview_position,
- &real_offset_x, &real_offset_y);
+ &real_offset_x, &real_offset_y,
+ &real_scale);
g_free (camera->priv->preview_offset);
camera->priv->preview_offset = NULL;
position = camera->priv->preview_position;
camera->priv->preview_position = -1;
+ /* Do not run the changed signal twice and recompute twice the
+ * same frame. Just a little internal trick. */
+ camera->priv->block_signals = TRUE;
if (preview_offset_x != real_offset_x ||
preview_offset_y != real_offset_y)
- animation_camera_set_keyframe (camera, position,
- preview_offset_x,
- preview_offset_y);
+ {
+ animation_camera_set_offsets (camera, position,
+ preview_offset_x,
+ preview_offset_y);
+ }
+ if (preview_scale != real_scale)
+ {
+ animation_camera_zoom (camera, position, preview_scale);
+ }
+ camera->priv->block_signals = FALSE;
+ g_signal_emit (camera, signals[KEYFRAME_SET], 0, position);
+ animation_camera_emit_camera_changed (camera, position);
}
}
void
animation_camera_reset_preview (AnimationCamera *camera)
{
- gboolean offsets_changed = FALSE;
+ gboolean 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;
+ gint preview_offset_x;
+ gint preview_offset_y;
+ gdouble preview_scale;
+ gint real_offset_x;
+ gint real_offset_y;
+ gdouble real_scale;
animation_camera_get (camera, camera->priv->preview_position,
- &preview_offset_x, &preview_offset_y);
+ &preview_offset_x, &preview_offset_y,
+ &preview_scale);
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);
+ &real_offset_x, &real_offset_y,
+ &real_scale);
+ changed = (preview_offset_x != real_offset_x ||
+ preview_offset_y != real_offset_y ||
+ preview_scale != real_scale);
position_changed = camera->priv->preview_position;
g_free (camera->priv->preview_offset);
@@ -339,8 +443,8 @@ animation_camera_reset_preview (AnimationCamera *camera)
camera->priv->preview_position = -1;
- if (offsets_changed)
- g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
+ if (changed)
+ g_signal_emit (camera, signals[CAMERA_CHANGED], 0,
position_changed, 1);
}
@@ -348,16 +452,20 @@ void
animation_camera_get (AnimationCamera *camera,
gint position,
gint *x_offset,
- gint *y_offset)
+ gint *y_offset,
+ gdouble *scale)
{
if (camera->priv->preview_position == position)
{
*x_offset = camera->priv->preview_offset->x;
*y_offset = camera->priv->preview_offset->y;
+ *scale = camera->priv->preview_scale;
}
else
{
- animation_camera_get_real (camera, position, x_offset, y_offset);
+ animation_camera_get_real (camera, position,
+ x_offset, y_offset,
+ scale);
}
}
@@ -367,6 +475,7 @@ static void
animation_camera_finalize (GObject *object)
{
g_list_free_full (ANIMATION_CAMERA (object)->priv->offsets, g_free);
+ g_list_free_full (ANIMATION_CAMERA (object)->priv->zoom, g_free);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -412,8 +521,8 @@ animation_camera_get_property (GObject *object,
}
static void
-animation_camera_emit_offsets_changed (AnimationCamera *camera,
- gint position)
+animation_camera_emit_camera_changed (AnimationCamera *camera,
+ gint position)
{
GList *iter;
gint prev_keyframe;
@@ -426,7 +535,11 @@ animation_camera_emit_offsets_changed (AnimationCamera *camera,
iter = g_list_nth (camera->priv->offsets, i);
for (; iter && ! iter->data; iter = iter->prev, i--)
;
+ iter = g_list_nth (camera->priv->zoom, i);
prev_keyframe = i + 1;
+ for (; iter && ! iter->data; iter = iter->prev, i--)
+ ;
+ prev_keyframe = MIN (i + 1, prev_keyframe);
}
else
{
@@ -439,15 +552,23 @@ animation_camera_emit_offsets_changed (AnimationCamera *camera,
for (; iter && ! iter->data; iter = iter->next, i++)
;
if (iter && iter->data)
- next_keyframe = i - 1;
+ {
+ next_keyframe = i - 1;
+ iter = g_list_nth (camera->priv->zoom, i);
+ for (; iter && ! iter->data; iter = iter->next, i++)
+ ;
+ next_keyframe = MAX (i - 1, next_keyframe);
+ }
else
- next_keyframe = animation_get_duration (camera->priv->animation) - 1;
+ {
+ next_keyframe = animation_get_duration (camera->priv->animation) - 1;
+ }
}
else
{
next_keyframe = animation_get_duration (camera->priv->animation) - 1;
}
- g_signal_emit (camera, signals[OFFSETS_CHANGED], 0,
+ g_signal_emit (camera, signals[CAMERA_CHANGED], 0,
prev_keyframe, next_keyframe - prev_keyframe + 1);
}
@@ -455,19 +576,21 @@ static void
animation_camera_get_real (AnimationCamera *camera,
gint position,
gint *x_offset,
- gint *y_offset)
+ gint *y_offset,
+ gdouble *scale)
{
- Offset *keyframe;
+ Offset *position_keyframe;
+ gdouble *zoom_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)
+ position_keyframe = g_list_nth_data (camera->priv->offsets, position);
+ if (position_keyframe)
{
/* There is a keyframe to this exact position. Use its values. */
- *x_offset = keyframe->x;
- *y_offset = keyframe->y;
+ *x_offset = position_keyframe->x;
+ *y_offset = position_keyframe->y;
}
else
{
@@ -531,4 +654,68 @@ animation_camera_get_real (AnimationCamera *camera,
(next_keyframe_pos - prev_keyframe_pos);
}
}
+
+ zoom_keyframe = g_list_nth_data (camera->priv->zoom, position);
+ if (zoom_keyframe)
+ {
+ /* There is a keyframe to this exact position. Use its values. */
+ *scale = *zoom_keyframe;
+ }
+ else
+ {
+ GList *iter;
+ gdouble *prev_keyframe = NULL;
+ gdouble *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->zoom) - 1);
+ iter = g_list_nth (camera->priv->zoom, 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->zoom, 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)
+ {
+ *scale = 1.0;
+ }
+ else if (prev_keyframe == NULL)
+ {
+ *scale = *next_keyframe;
+ }
+ else if (next_keyframe == NULL)
+ {
+ *scale = *prev_keyframe;
+ }
+ else
+ {
+ /* XXX No curve editing or anything like this yet.
+ * All keyframing is linear in this first version.
+ */
+ *scale = *prev_keyframe + (position - prev_keyframe_pos) *
+ (*next_keyframe - *prev_keyframe) /
+ (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 344e6a8..d4d2681 100644
--- a/plug-ins/animation-play/core/animation-camera.h
+++ b/plug-ins/animation-play/core/animation-camera.h
@@ -44,7 +44,7 @@ struct _AnimationCameraClass
GObjectClass parent_class;
/* Signals */
- void (*offsets_changed) (AnimationCamera *camera,
+ void (*camera_changed) (AnimationCamera *camera,
gint position,
gint duration);
void (*keyframe_set) (AnimationCamera *camera,
@@ -53,29 +53,38 @@ 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_offset_keyframe (AnimationCamera *camera,
+ gint position);
+gboolean animation_camera_has_zoom_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_apply_preview (AnimationCamera *camera);
-void animation_camera_reset_preview (AnimationCamera *camera);
+void animation_camera_set_offsets (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y);
+void animation_camera_zoom (AnimationCamera *camera,
+ gint position,
+ gdouble scale);
+void animation_camera_delete_offset_keyframe (AnimationCamera *camera,
+ gint position);
+void animation_camera_delete_zoom_keyframe (AnimationCamera *camera,
+ gint position);
+void animation_camera_preview_keyframe (AnimationCamera *camera,
+ gint position,
+ gint x,
+ gint y,
+ gdouble scale);
+void animation_camera_apply_preview (AnimationCamera *camera);
+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,
+ gdouble *scale);
#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 9c2ae7c..940bb55 100644
--- a/plug-ins/animation-play/core/animation-celanimation.c
+++ b/plug-ins/animation-play/core/animation-celanimation.c
@@ -133,7 +133,7 @@ static void animation_cel_animation_text (GMarkupParseContext
/* Signal handling */
-static void on_camera_offsets_changed (AnimationCamera *camera,
+static void on_camera_changed (AnimationCamera *camera,
gint position,
gint duration,
AnimationCelAnimation *animation);
@@ -187,8 +187,8 @@ animation_cel_animation_constructed (GObject *object)
{
AnimationCelAnimation *animation = ANIMATION_CEL_ANIMATION (object);
- g_signal_connect (animation->priv->camera, "offsets-changed",
- G_CALLBACK (on_camera_offsets_changed),
+ g_signal_connect (animation->priv->camera, "camera-changed",
+ G_CALLBACK (on_camera_changed),
animation);
}
@@ -653,6 +653,7 @@ animation_cel_animation_create_frame (Animation *animation,
gint preview_height;
gint offset_x;
gint offset_y;
+ gdouble scale;
cel_animation = ANIMATION_CEL_ANIMATION (animation);
image_id = animation_get_image_id (animation);
@@ -661,7 +662,7 @@ animation_cel_animation_create_frame (Animation *animation,
preview_height *= proxy_ratio;
preview_width *= proxy_ratio;
animation_camera_get (cel_animation->priv->camera,
- position, &offset_x, &offset_y);
+ position, &offset_x, &offset_y, &scale);
for (iter = cel_animation->priv->tracks; iter; iter = iter->next)
{
@@ -694,7 +695,7 @@ animation_cel_animation_create_frame (Animation *animation,
gimp_drawable_offsets (layer, &layer_offx, &layer_offy);
intermediate = normal_blend (preview_width, preview_height,
buffer, 1.0, 0, 0,
- source, proxy_ratio,
+ source, proxy_ratio * scale,
layer_offx + offset_x,
layer_offy + offset_y);
g_object_unref (source);
@@ -868,16 +869,33 @@ animation_cel_animation_serialize (Animation *animation,
for (i = 0; i < priv->duration; i++)
{
- if (animation_camera_has_keyframe (priv->camera, i))
+ if (animation_camera_has_offset_keyframe (priv->camera, i) ||
+ animation_camera_has_zoom_keyframe (priv->camera, i))
{
- gint offset_x;
- gint offset_y;
+ gint offset_x;
+ gint offset_y;
+ gdouble scale;
animation_camera_get (priv->camera,
- i, &offset_x, &offset_y);
- xml2 = g_markup_printf_escaped ("<keyframe " "position=\"%d\""
- " x=\"%d\" y=\"%d\"/>",
- i, offset_x, offset_y);
+ i, &offset_x, &offset_y, &scale);
+ if (animation_camera_has_offset_keyframe (priv->camera, i) &&
+ animation_camera_has_zoom_keyframe (priv->camera, i))
+ {
+ xml2 = g_markup_printf_escaped ("<keyframe " "position=\"%d\""
+ " x=\"%d\" y=\"%d\" scale=\"%f\"/>",
+ i, offset_x, offset_y, scale);
+ }
+ else if (animation_camera_has_offset_keyframe (priv->camera, i))
+ {
+ xml2 = g_markup_printf_escaped ("<keyframe " "position=\"%d\""
+ " x=\"%d\" y=\"%d\"/>",
+ i, offset_x, offset_y);
+ }
+ else
+ {
+ xml2 = g_markup_printf_escaped ("<keyframe " "position=\"%d\""
+ " scale=\"%f\"/>", i, scale);
+ }
tmp = xml;
xml = g_strconcat (xml, xml2, NULL);
g_free (tmp);
@@ -968,8 +986,8 @@ animation_cel_animation_update_paint_view (Animation *animation,
gchar *prev_hash;
gint num_layers;
gint32 image_id;
- gint last_layer;
- gint skin = 0;
+ gint last_layer = 0;
+ gint skin = 0;
gint i;
cel_animation = ANIMATION_CEL_ANIMATION (animation);
@@ -1289,11 +1307,13 @@ animation_cel_animation_start_element (GMarkupParseContext *context,
}
else
{
- gboolean has_x = FALSE;
- gboolean has_y = FALSE;
- gint position = -1;
- gint x;
- gint y;
+ gboolean has_x = FALSE;
+ gboolean has_y = FALSE;
+ gboolean has_scale = FALSE;
+ gint position = -1;
+ gint x = 0;
+ gint y = 0;
+ gdouble scale = 1.0;
while (*names && *values)
{
@@ -1311,12 +1331,22 @@ animation_cel_animation_start_element (GMarkupParseContext *context,
has_y = TRUE;
y = (gint) g_ascii_strtoll (*values, NULL, 10);
}
+ else if (strcmp (*names, "scale") == 0 && **values)
+ {
+ has_scale = TRUE;
+ scale = g_ascii_strtod (*values, NULL);
+ }
names++;
values++;
}
- if (position >= 0 && has_x && has_y)
- animation_camera_set_keyframe (priv->camera, position, x, y);
+ if (position >= 0)
+ {
+ if (has_x && has_y)
+ animation_camera_set_offsets (priv->camera, position, x, y);
+ if (has_scale)
+ animation_camera_zoom (priv->camera, position, scale);
+ }
}
status->state = KEYFRAME_STATE;
break;
@@ -1434,10 +1464,10 @@ animation_cel_animation_text (GMarkupParseContext *context,
/**** Signal handling ****/
static void
-on_camera_offsets_changed (AnimationCamera *camera,
- gint position,
- gint duration,
- AnimationCelAnimation *animation)
+on_camera_changed (AnimationCamera *camera,
+ gint position,
+ gint duration,
+ AnimationCelAnimation *animation)
{
g_signal_emit_by_name (animation, "frames-changed",
position, duration);
@@ -1472,13 +1502,15 @@ animation_cel_animation_get_hash (AnimationCelAnimation *animation,
gint position,
gboolean layers_only)
{
- gchar *hash = g_strdup ("");
- GList *iter;
- gint main_offset_x;
- gint main_offset_y;
+ gchar *hash = g_strdup ("");
+ GList *iter;
+ gint main_offset_x;
+ gint main_offset_y;
+ gdouble scale;
animation_camera_get (animation->priv->camera,
- position, &main_offset_x, &main_offset_y);
+ position, &main_offset_x, &main_offset_y,
+ &scale);
/* Create the new buffer layer composition. */
for (iter = animation->priv->tracks; iter; iter = iter->next)
@@ -1504,10 +1536,10 @@ animation_cel_animation_get_hash (AnimationCelAnimation *animation,
}
else
{
- hash = g_strdup_printf ("%s[%d,%d]%d;",
+ hash = g_strdup_printf ("%s[%d,%d]%fx%d;",
hash,
main_offset_x, main_offset_y,
- tattoo);
+ scale, tattoo);
}
g_free (tmp);
}
diff --git a/plug-ins/animation-play/widgets/animation-dialog.c
b/plug-ins/animation-play/widgets/animation-dialog.c
index 422de0a..185b1f7 100755
--- a/plug-ins/animation-play/widgets/animation-dialog.c
+++ b/plug-ins/animation-play/widgets/animation-dialog.c
@@ -2565,14 +2565,16 @@ da_button_motion (GtkWidget *widget,
gint position;
gint x_offset;
gint y_offset;
+ gdouble scale;
animation = ANIMATION_CEL_ANIMATION (priv->animation);
camera = ANIMATION_CAMERA (animation_cel_animation_get_main_camera (animation));
position = animation_playback_get_position (priv->playback);
- animation_camera_get (camera, position, &x_offset, &y_offset);
+ animation_camera_get (camera, position, &x_offset, &y_offset, &scale);
animation_camera_preview_keyframe (camera, position,
x_offset + (event->x - p->x) / priv->zoom,
- y_offset + (event->y - p->y) / priv->zoom);
+ y_offset + (event->y - p->y) / priv->zoom,
+ scale);
p->x = event->x;
p->y = event->y;
return TRUE;
diff --git a/plug-ins/animation-play/widgets/animation-keyframe-view.c
b/plug-ins/animation-play/widgets/animation-keyframe-view.c
index ea7eff6..f2e5308 100644
--- a/plug-ins/animation-play/widgets/animation-keyframe-view.c
+++ b/plug-ins/animation-play/widgets/animation-keyframe-view.c
@@ -37,11 +37,15 @@ struct _AnimationKeyFrameViewPrivate
gint position;
GtkWidget *offset_entry;
- GtkWidget *delete_button;
+ GtkWidget *delete_offset_button;
+
+ GtkWidget *scale_entry;
+ GtkWidget *delete_scale_button;
guint update_source;
gint update_x_offset;
gint update_y_offset;
+ gdouble update_scale;
gint update_position;
};
@@ -51,13 +55,18 @@ static void animation_keyframe_view_dispose (GObject *obj
static gboolean animation_keyframe_update_source (gpointer user_data);
+
+static void on_scale_entry_changed (GtkSpinButton *button,
+ AnimationKeyFrameView *view);
static void on_offset_entry_changed (GimpSizeEntry *entry,
AnimationKeyFrameView *view);
static void on_offsets_changed (AnimationCamera *camera,
gint position,
gint duration,
AnimationKeyFrameView *view);
-static void on_delete_clicked (GtkButton *button,
+static void on_delete_offset_clicked (GtkButton *button,
+ AnimationKeyFrameView *view);
+static void on_delete_scale_clicked (GtkButton *button,
AnimationKeyFrameView *view);
G_DEFINE_TYPE (AnimationKeyFrameView, animation_keyframe_view, GTK_TYPE_NOTEBOOK)
@@ -126,6 +135,7 @@ animation_keyframe_view_show (AnimationKeyFrameView *view,
gdouble yres;
gint x_offset;
gint y_offset;
+ gdouble scale;
camera = ANIMATION_CAMERA (animation_cel_animation_get_main_camera (animation));
@@ -136,10 +146,13 @@ animation_keyframe_view_show (AnimationKeyFrameView *view,
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);
+ animation_camera_set_offsets (view->priv->camera,
+ view->priv->update_position,
+ view->priv->update_x_offset,
+ view->priv->update_y_offset);
+ animation_camera_zoom (view->priv->camera,
+ view->priv->update_position,
+ view->priv->update_scale);
}
view->priv->camera = camera;
view->priv->position = position;
@@ -163,6 +176,9 @@ animation_keyframe_view_show (AnimationKeyFrameView *view,
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (view->priv->offset_entry),
1, yres, TRUE);
+ g_signal_handlers_disconnect_by_func (view->priv->scale_entry,
+ G_CALLBACK (on_scale_entry_changed),
+ view);
g_signal_handlers_disconnect_by_func (view->priv->offset_entry,
G_CALLBACK (on_offset_entry_changed),
view);
@@ -170,23 +186,32 @@ animation_keyframe_view_show (AnimationKeyFrameView *view,
G_CALLBACK (on_offsets_changed),
view);
animation_camera_reset_preview (camera);
- animation_camera_get (camera, position, &x_offset, &y_offset);
+ animation_camera_get (camera, position, &x_offset, &y_offset, &scale);
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);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (view->priv->scale_entry),
+ scale * 100.0);
+ g_signal_connect (view->priv->scale_entry, "value-changed",
+ G_CALLBACK (on_scale_entry_changed),
+ view);
g_signal_connect (view->priv->offset_entry, "value-changed",
G_CALLBACK (on_offset_entry_changed),
view);
- g_signal_connect (camera, "offsets-changed",
+ g_signal_connect (camera, "camera-changed",
G_CALLBACK (on_offsets_changed),
view);
gtk_widget_show (GTK_WIDGET (view));
- if (animation_camera_has_keyframe (camera, position))
- gtk_widget_show (view->priv->delete_button);
+ if (animation_camera_has_offset_keyframe (camera, view->priv->position))
+ gtk_widget_show (view->priv->delete_offset_button);
else
- gtk_widget_hide (view->priv->delete_button);
+ gtk_widget_hide (view->priv->delete_offset_button);
+ if (animation_camera_has_zoom_keyframe (camera, view->priv->position))
+ gtk_widget_show (view->priv->delete_scale_button);
+ else
+ gtk_widget_hide (view->priv->delete_scale_button);
}
}
@@ -212,9 +237,10 @@ animation_keyframe_view_constructed (GObject *object)
AnimationKeyFrameView *view = ANIMATION_KEYFRAME_VIEW (object);
GtkWidget *page;
GtkWidget *label;
+ GtkWidget *widget;
page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- label = gtk_image_new_from_icon_name ("camera-video",
+ label = gtk_image_new_from_icon_name ("gimp-tool-move",
GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_notebook_append_page (GTK_NOTEBOOK (view), page,
label);
@@ -231,11 +257,33 @@ animation_keyframe_view_constructed (GObject *object)
gtk_box_pack_start (GTK_BOX (page), view->priv->offset_entry, FALSE, FALSE, 0);
gtk_widget_show (view->priv->offset_entry);
- view->priv->delete_button = gtk_button_new_with_label (_("Reset"));
- g_signal_connect (view->priv->delete_button, "clicked",
- G_CALLBACK (on_delete_clicked),
+ view->priv->delete_offset_button = gtk_button_new_with_label (_("Reset Offsets"));
+ g_signal_connect (view->priv->delete_offset_button, "clicked",
+ G_CALLBACK (on_delete_offset_clicked),
view);
- gtk_box_pack_end (GTK_BOX (page), view->priv->delete_button, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (page), view->priv->delete_offset_button, FALSE, FALSE, 0);
+
+ gtk_widget_show (page);
+
+ page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ label = gtk_image_new_from_icon_name ("gimp-scale",
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_notebook_append_page (GTK_NOTEBOOK (view), page,
+ label);
+
+ widget = gtk_label_new (_("Zoom: "));
+ gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ view->priv->scale_entry = gtk_spin_button_new_with_range (0.0, 1000.0, 1.0);
+ gtk_box_pack_start (GTK_BOX (page), view->priv->scale_entry, FALSE, FALSE, 0);
+ gtk_widget_show (view->priv->scale_entry);
+
+ view->priv->delete_scale_button = gtk_button_new_with_label (_("Reset Zoom"));
+ g_signal_connect (view->priv->delete_scale_button, "clicked",
+ G_CALLBACK (on_delete_scale_clicked),
+ view);
+ gtk_box_pack_end (GTK_BOX (page), view->priv->delete_scale_button, FALSE, FALSE, 0);
gtk_widget_show (page);
}
@@ -252,17 +300,26 @@ animation_keyframe_update_source (gpointer user_data)
animation_camera_preview_keyframe (view->priv->camera,
view->priv->update_position,
view->priv->update_x_offset,
- view->priv->update_y_offset);
+ view->priv->update_y_offset,
+ view->priv->update_scale);
}
return G_SOURCE_REMOVE;
}
static void
-on_offset_entry_changed (GimpSizeEntry *entry,
+on_scale_entry_changed (GtkSpinButton *button G_GNUC_UNUSED,
+ AnimationKeyFrameView *view)
+{
+ on_offset_entry_changed (NULL, view);
+}
+
+static void
+on_offset_entry_changed (GimpSizeEntry *entry G_GNUC_UNUSED,
AnimationKeyFrameView *view)
{
gdouble x_offset;
gdouble y_offset;
+ gdouble scale;
/* If a timeout is pending, remove before recreating in order to
* postpone the camera update. */
@@ -271,10 +328,13 @@ on_offset_entry_changed (GimpSizeEntry *entry,
g_source_remove (view->priv->update_source);
}
+ scale = gtk_spin_button_get_value (GTK_SPIN_BUTTON (view->priv->scale_entry)) / 100.0;
x_offset = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (view->priv->offset_entry), 0);
y_offset = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (view->priv->offset_entry), 1);
+
view->priv->update_x_offset = x_offset;
view->priv->update_y_offset = y_offset;
+ view->priv->update_scale = scale;
view->priv->update_position = view->priv->position;
view->priv->update_source = g_timeout_add (10, animation_keyframe_update_source, view);
}
@@ -290,31 +350,48 @@ on_offsets_changed (AnimationCamera *camera,
{
gint x_offset;
gint y_offset;
+ gdouble scale;
g_signal_handlers_block_by_func (view->priv->offset_entry,
G_CALLBACK (on_offset_entry_changed),
view);
- animation_camera_get (camera, view->priv->position, &x_offset, &y_offset);
+ animation_camera_get (camera, view->priv->position,
+ &x_offset, &y_offset, &scale);
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);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (view->priv->scale_entry),
+ scale * 100.0);
g_signal_handlers_unblock_by_func (view->priv->offset_entry,
G_CALLBACK (on_offset_entry_changed),
view);
- if (animation_camera_has_keyframe (camera, view->priv->position))
- gtk_widget_show (view->priv->delete_button);
+ if (animation_camera_has_offset_keyframe (camera, view->priv->position))
+ gtk_widget_show (view->priv->delete_offset_button);
+ else
+ gtk_widget_hide (view->priv->delete_offset_button);
+ if (animation_camera_has_zoom_keyframe (camera, view->priv->position))
+ gtk_widget_show (view->priv->delete_scale_button);
else
- gtk_widget_hide (view->priv->delete_button);
+ gtk_widget_hide (view->priv->delete_scale_button);
}
}
static void
-on_delete_clicked (GtkButton *button,
- AnimationKeyFrameView *view)
+on_delete_offset_clicked (GtkButton *button,
+ AnimationKeyFrameView *view)
+{
+ animation_camera_delete_offset_keyframe (view->priv->camera,
+ view->priv->position);
+ gtk_widget_hide (view->priv->delete_offset_button);
+}
+
+static void
+on_delete_scale_clicked (GtkButton *button,
+ AnimationKeyFrameView *view)
{
- animation_camera_delete_keyframe (view->priv->camera,
- view->priv->position);
- gtk_widget_hide (view->priv->delete_button);
+ animation_camera_delete_zoom_keyframe (view->priv->camera,
+ view->priv->position);
+ gtk_widget_hide (view->priv->delete_scale_button);
}
diff --git a/plug-ins/animation-play/widgets/animation-xsheet.c
b/plug-ins/animation-play/widgets/animation-xsheet.c
index 19d4459..8f28f90 100755
--- a/plug-ins/animation-play/widgets/animation-xsheet.c
+++ b/plug-ins/animation-play/widgets/animation-xsheet.c
@@ -819,7 +819,8 @@ animation_xsheet_add_frames (AnimationXSheet *xsheet,
xsheet->priv->effect_buttons = g_list_append (xsheet->priv->effect_buttons,
label);
- if (animation_camera_has_keyframe (camera, i))
+ if (animation_camera_has_offset_keyframe (camera, i) ||
+ animation_camera_has_zoom_keyframe (camera, i))
{
GtkWidget *image;
@@ -1323,15 +1324,18 @@ on_camera_keyframe_deleted (AnimationCamera *camera,
gint position,
AnimationXSheet *xsheet)
{
- GtkWidget *button;
-
- button = g_list_nth_data (xsheet->priv->effect_buttons,
- position);
-
- if (button && gtk_bin_get_child (GTK_BIN (button)))
+ if (! animation_camera_has_offset_keyframe (camera, position) &&
+ ! animation_camera_has_zoom_keyframe (camera, position))
{
- gtk_container_remove (GTK_CONTAINER (button),
- gtk_bin_get_child (GTK_BIN (button)));
+ GtkWidget *button;
+
+ button = g_list_nth_data (xsheet->priv->effect_buttons,
+ position);
+ if (button && gtk_bin_get_child (GTK_BIN (button)))
+ {
+ gtk_container_remove (GTK_CONTAINER (button),
+ gtk_bin_get_child (GTK_BIN (button)));
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]