actor: Simplify setters of animatable properties

Instead of checking the duration of the current easing state we should
check if there's a transition in progress, and update it
unconditionally.

If there is no easing state, or the easing state has a duration of zero
milliseconds, then create_transition() should bail out early and set the
requested final state.

This allows us to write:

  clutter_actor_save_easing_state (actor);
  clutter_actor_set_x (actor, 200);
  clutter_actor_restore_easing_state (actor);

  [...]

  clutter_actor_set_x (actor, 100);

and have the second set_x() update the easing in progress, instead of
being ignored.

https://bugzilla.gnome.org/show_bug.cgi?id=672945
This commit is contained in:
Emmanuele Bassi 2012-03-28 11:52:01 +01:00
parent 0f7dab15d8
commit fa8d431941

View File

@ -4014,15 +4014,11 @@ clutter_actor_set_rotation_angle (ClutterActor *self,
ClutterRotateAxis axis, ClutterRotateAxis axis,
gdouble angle) gdouble angle)
{ {
ClutterTransformInfo *info; const ClutterTransformInfo *info;
const double *cur_angle_p = NULL;
info = _clutter_actor_get_transform_info (self);
if (clutter_actor_get_easing_duration (self) != 0)
{
ClutterTransition *transition;
GParamSpec *pspec = NULL; GParamSpec *pspec = NULL;
double *cur_angle_p = NULL;
info = _clutter_actor_get_transform_info_or_defaults (self);
switch (axis) switch (axis)
{ {
@ -4045,21 +4041,12 @@ clutter_actor_set_rotation_angle (ClutterActor *self,
g_assert (pspec != NULL); g_assert (pspec != NULL);
g_assert (cur_angle_p != NULL); g_assert (cur_angle_p != NULL);
transition = _clutter_actor_get_transition (self, pspec); if (_clutter_actor_get_transition (self, pspec) == NULL)
if (transition == NULL) _clutter_actor_create_transition (self, pspec, *cur_angle_p, angle);
{
transition = _clutter_actor_create_transition (self, pspec,
*cur_angle_p,
angle);
}
else else
_clutter_actor_update_transition (self, pspec, angle); _clutter_actor_update_transition (self, pspec, angle);
self->priv->transform_valid = FALSE;
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
}
else
clutter_actor_set_rotation_angle_internal (self, axis, angle);
} }
/*< private > /*< private >
@ -4119,29 +4106,6 @@ clutter_actor_set_rotation_center_internal (ClutterActor *self,
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
} }
static void
clutter_actor_animate_scale_factor (ClutterActor *self,
double old_factor,
double new_factor,
GParamSpec *pspec)
{
ClutterTransition *transition;
transition = _clutter_actor_get_transition (self, pspec);
if (transition == NULL)
{
transition = _clutter_actor_create_transition (self, pspec,
old_factor,
new_factor);
}
else
_clutter_actor_update_transition (self, pspec, new_factor);
self->priv->transform_valid = FALSE;
clutter_actor_queue_redraw (self);
}
static void static void
clutter_actor_set_scale_factor_internal (ClutterActor *self, clutter_actor_set_scale_factor_internal (ClutterActor *self,
double factor, double factor,
@ -4167,39 +4131,37 @@ clutter_actor_set_scale_factor (ClutterActor *self,
ClutterRotateAxis axis, ClutterRotateAxis axis,
gdouble factor) gdouble factor)
{ {
GObject *obj = G_OBJECT (self); const ClutterTransformInfo *info;
ClutterTransformInfo *info; const double *scale_p = NULL;
GParamSpec *pspec; GParamSpec *pspec = NULL;
info = _clutter_actor_get_transform_info (self); info = _clutter_actor_get_transform_info_or_defaults (self);
g_object_freeze_notify (obj);
switch (axis) switch (axis)
{ {
case CLUTTER_X_AXIS: case CLUTTER_X_AXIS:
pspec = obj_props[PROP_SCALE_X]; pspec = obj_props[PROP_SCALE_X];
scale_p = &info->scale_x;
if (clutter_actor_get_easing_duration (self) != 0)
clutter_actor_animate_scale_factor (self, info->scale_x, factor, pspec);
else
clutter_actor_set_scale_factor_internal (self, factor, pspec);
break; break;
case CLUTTER_Y_AXIS: case CLUTTER_Y_AXIS:
pspec = obj_props[PROP_SCALE_Y]; pspec = obj_props[PROP_SCALE_Y];
scale_p = &info->scale_y;
if (clutter_actor_get_easing_duration (self) != 0)
clutter_actor_animate_scale_factor (self, info->scale_y, factor, pspec);
else
clutter_actor_set_scale_factor_internal (self, factor, pspec);
break; break;
default: case CLUTTER_Z_AXIS:
g_assert_not_reached (); break;
} }
g_object_thaw_notify (obj); g_assert (pspec != NULL);
g_assert (scale_p != NULL);
if (_clutter_actor_get_transition (self, pspec) == NULL)
_clutter_actor_create_transition (self, pspec, *scale_p, factor);
else
_clutter_actor_update_transition (self, pspec, factor);
clutter_actor_queue_redraw (self);
} }
static inline void static inline void
@ -9488,33 +9450,19 @@ clutter_actor_set_width (ClutterActor *self,
{ {
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (clutter_actor_get_easing_duration (self) != 0) if (_clutter_actor_get_transition (self, obj_props[PROP_WIDTH]) == NULL)
{ {
ClutterTransition *transition; float cur_size = clutter_actor_get_width (self);
transition = _clutter_actor_get_transition (self, obj_props[PROP_WIDTH]); _clutter_actor_create_transition (self,
if (transition == NULL)
{
float old_width = clutter_actor_get_width (self);
transition = _clutter_actor_create_transition (self,
obj_props[PROP_WIDTH], obj_props[PROP_WIDTH],
old_width, cur_size,
width); width);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_WIDTH], width); _clutter_actor_update_transition (self, obj_props[PROP_WIDTH], width);
clutter_actor_queue_relayout (self); clutter_actor_queue_relayout (self);
}
else
{
g_object_freeze_notify (G_OBJECT (self));
clutter_actor_set_width_internal (self, width);
g_object_thaw_notify (G_OBJECT (self));
}
} }
/** /**
@ -9538,33 +9486,19 @@ clutter_actor_set_height (ClutterActor *self,
{ {
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (clutter_actor_get_easing_duration (self) != 0) if (_clutter_actor_get_transition (self, obj_props[PROP_HEIGHT]) == NULL)
{ {
ClutterTransition *transition; float cur_size = clutter_actor_get_height (self);
transition = _clutter_actor_get_transition (self, obj_props[PROP_HEIGHT]); _clutter_actor_create_transition (self,
if (transition == NULL)
{
float old_height = clutter_actor_get_height (self);
transition = _clutter_actor_create_transition (self,
obj_props[PROP_HEIGHT], obj_props[PROP_HEIGHT],
old_height, cur_size,
height); height);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_HEIGHT], height); _clutter_actor_update_transition (self, obj_props[PROP_HEIGHT], height);
clutter_actor_queue_relayout (self); clutter_actor_queue_relayout (self);
}
else
{
g_object_freeze_notify (G_OBJECT (self));
clutter_actor_set_height_internal (self, height);
g_object_thaw_notify (G_OBJECT (self));
}
} }
static inline void static inline void
@ -9631,31 +9565,20 @@ void
clutter_actor_set_x (ClutterActor *self, clutter_actor_set_x (ClutterActor *self,
gfloat x) gfloat x)
{ {
const ClutterLayoutInfo *linfo;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
linfo = _clutter_actor_get_layout_info_or_defaults (self); if (_clutter_actor_get_transition (self, obj_props[PROP_X]) == NULL)
if (clutter_actor_get_easing_duration (self) != 0)
{ {
ClutterTransition *transition; float cur_position = clutter_actor_get_x (self);
transition = _clutter_actor_get_transition (self, obj_props[PROP_X]); _clutter_actor_create_transition (self, obj_props[PROP_X],
if (transition == NULL) cur_position,
{
transition = _clutter_actor_create_transition (self,
obj_props[PROP_X],
linfo->fixed_x,
x); x);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_X], x); _clutter_actor_update_transition (self, obj_props[PROP_X], x);
clutter_actor_queue_relayout (self); clutter_actor_queue_relayout (self);
}
else
clutter_actor_set_x_internal (self, x);
} }
/** /**
@ -9676,32 +9599,19 @@ void
clutter_actor_set_y (ClutterActor *self, clutter_actor_set_y (ClutterActor *self,
gfloat y) gfloat y)
{ {
const ClutterLayoutInfo *linfo;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
linfo = _clutter_actor_get_layout_info_or_defaults (self); if (_clutter_actor_get_transition (self, obj_props[PROP_Y]) == NULL)
if (clutter_actor_get_easing_duration (self) != 0)
{ {
ClutterTransition *transition; float cur_position = clutter_actor_get_y (self);
transition = _clutter_actor_get_transition (self, obj_props[PROP_Y]); _clutter_actor_create_transition (self, obj_props[PROP_Y],
if (transition == NULL) cur_position,
{
transition = _clutter_actor_create_transition (self,
obj_props[PROP_Y],
linfo->fixed_y,
y); y);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_Y], y); _clutter_actor_update_transition (self, obj_props[PROP_Y], y);
clutter_actor_queue_relayout (self);
}
else
clutter_actor_set_y_internal (self, y);
clutter_actor_queue_relayout (self); clutter_actor_queue_relayout (self);
} }
@ -10028,31 +9938,18 @@ void
clutter_actor_set_opacity (ClutterActor *self, clutter_actor_set_opacity (ClutterActor *self,
guint8 opacity) guint8 opacity)
{ {
ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
priv = self->priv; if (_clutter_actor_get_transition (self, obj_props[PROP_OPACITY]) == NULL)
if (clutter_actor_get_easing_duration (self) != 0)
{ {
ClutterTransition *transition; _clutter_actor_create_transition (self, obj_props[PROP_OPACITY],
self->priv->opacity,
transition = _clutter_actor_get_transition (self, obj_props[PROP_OPACITY]);
if (transition == NULL)
{
transition = _clutter_actor_create_transition (self,
obj_props[PROP_OPACITY],
priv->opacity,
opacity); opacity);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_OPACITY], opacity); _clutter_actor_update_transition (self, obj_props[PROP_OPACITY], opacity);
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
}
else
clutter_actor_set_opacity_internal (self, opacity);
} }
/* /*
@ -10350,30 +10247,22 @@ void
clutter_actor_set_depth (ClutterActor *self, clutter_actor_set_depth (ClutterActor *self,
gfloat depth) gfloat depth)
{ {
const ClutterTransformInfo *tinfo;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
tinfo = _clutter_actor_get_transform_info_or_defaults (self); if (_clutter_actor_get_transition (self, obj_props[PROP_DEPTH]) == NULL)
if (clutter_actor_get_easing_duration (self) != 0)
{ {
ClutterTransition *transition; const ClutterTransformInfo *info;
transition = _clutter_actor_get_transition (self, obj_props[PROP_DEPTH]); info = _clutter_actor_get_transform_info_or_defaults (self);
if (transition == NULL)
{ _clutter_actor_create_transition (self, obj_props[PROP_DEPTH],
transition = _clutter_actor_create_transition (self, obj_props[PROP_DEPTH], info->depth,
tinfo->depth,
depth); depth);
} }
else else
_clutter_actor_update_transition (self, obj_props[PROP_DEPTH], depth); _clutter_actor_update_transition (self, obj_props[PROP_DEPTH], depth);
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
}
else
clutter_actor_set_depth_internal (self, depth);
} }
/** /**
@ -12999,6 +12888,10 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GObject *obj = G_OBJECT (actor);
g_object_freeze_notify (obj);
switch (prop_id) switch (prop_id)
{ {
case PROP_X: case PROP_X:
@ -13060,9 +12953,11 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
break; break;
default: default:
g_object_set_property (G_OBJECT (actor), pspec->name, value); g_object_set_property (obj, pspec->name, value);
break; break;
} }
g_object_thaw_notify (obj);
} }
static void static void
@ -16634,14 +16529,9 @@ clutter_actor_set_background_color (ClutterActor *self,
} }
bg_color_pspec = obj_props[PROP_BACKGROUND_COLOR]; bg_color_pspec = obj_props[PROP_BACKGROUND_COLOR];
if (clutter_actor_get_easing_duration (self) != 0) if (_clutter_actor_get_transition (self, bg_color_pspec) == NULL)
{ {
ClutterTransition *transition; _clutter_actor_create_transition (self, bg_color_pspec,
transition = _clutter_actor_get_transition (self, bg_color_pspec);
if (transition == NULL)
{
transition = _clutter_actor_create_transition (self, bg_color_pspec,
&priv->bg_color, &priv->bg_color,
color); color);
} }
@ -16649,9 +16539,6 @@ clutter_actor_set_background_color (ClutterActor *self,
_clutter_actor_update_transition (self, bg_color_pspec, color); _clutter_actor_update_transition (self, bg_color_pspec, color);
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
}
else
clutter_actor_set_background_color_internal (self, color);
} }
/** /**
@ -17186,9 +17073,18 @@ _clutter_actor_create_transition (ClutterActor *actor,
info = _clutter_actor_get_animation_info (actor); info = _clutter_actor_get_animation_info (actor);
/* XXX - this will go away in 2.0
*
* if no state has been pushed, we assume that the easing state is
* in "compatibility mode": all transitions have a duration of 0
* msecs, which means that they happen immediately. in Clutter 2.0
* this will turn into a g_assert(info->states != NULL), as every
* actor will start with a predefined easing state
*/
if (info->states == NULL) if (info->states == NULL)
{ {
clutter_actor_save_easing_state (actor); clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 0);
call_restore = TRUE; call_restore = TRUE;
} }
@ -17232,6 +17128,24 @@ _clutter_actor_create_transition (ClutterActor *actor,
goto out; goto out;
} }
/* if the current easing state has a duration of 0, then we don't
* bother to create the transition, and we just set the final value
* directly on the actor; we don't go through the Animatable
* interface because we know we got here through an animatable
* property.
*/
if (info->cur_state->easing_duration == 0)
{
clutter_actor_set_animatable_property (actor,
pspec->param_id,
&final,
pspec);
g_value_unset (&initial);
g_value_unset (&final);
goto out;
}
interval = clutter_interval_new_with_values (ptype, &initial, &final); interval = clutter_interval_new_with_values (ptype, &initial, &final);
g_value_unset (&initial); g_value_unset (&initial);