actor: Simplify the implicit transition handling

We can remove the update_transition() private method, and move its
functionality inside the create_transition() private method, thereby
removing lots of duplicated code, as well as redundant checks on the
existence of a transition. This will allow handling transition updates
atomically in the future.
This commit is contained in:
Emmanuele Bassi 2012-07-21 13:16:37 -04:00
parent 28c2eeef95
commit ee00e37bc4
2 changed files with 205 additions and 426 deletions

View File

@ -236,9 +236,6 @@ ClutterTransition * _clutter_actor_create_transition
...);
ClutterTransition * _clutter_actor_get_transition (ClutterActor *self,
GParamSpec *pspec);
void _clutter_actor_update_transition (ClutterActor *self,
GParamSpec *pspec,
...);
gboolean _clutter_actor_foreach_child (ClutterActor *self,
ClutterForeachCallback callback,

View File

@ -4290,10 +4290,7 @@ clutter_actor_set_translation_factor (ClutterActor *self,
g_assert (pspec != NULL);
g_assert (translate_p != NULL);
if (_clutter_actor_get_transition (self, pspec) == NULL)
_clutter_actor_create_transition (self, pspec, *translate_p, value);
else
_clutter_actor_update_transition (self, pspec, value);
}
/**
@ -4446,10 +4443,7 @@ clutter_actor_set_rotation_angle (ClutterActor *self,
g_assert (pspec != NULL);
g_assert (cur_angle_p != NULL);
if (_clutter_actor_get_transition (self, pspec) == NULL)
_clutter_actor_create_transition (self, pspec, *cur_angle_p, angle);
else
_clutter_actor_update_transition (self, pspec, angle);
}
/**
@ -4610,12 +4604,7 @@ clutter_actor_set_scale_factor (ClutterActor *self,
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
@ -9546,16 +9535,10 @@ clutter_actor_allocate (ClutterActor *self,
*/
self->priv->allocation_flags = flags;
if (_clutter_actor_get_transition (self, obj_props[PROP_ALLOCATION]) == NULL)
{
_clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION],
&priv->allocation,
&real_allocation);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_ALLOCATION],
&real_allocation);
}
/**
* clutter_actor_set_allocation:
@ -9757,15 +9740,12 @@ clutter_actor_set_position (ClutterActor *self,
gfloat y)
{
ClutterPoint new_position;
ClutterPoint cur_position;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_point_init (&new_position, x, y);
if (_clutter_actor_get_transition (self, obj_props[PROP_POSITION]) == NULL)
{
ClutterPoint cur_position;
cur_position.x = clutter_actor_get_x (self);
cur_position.y = clutter_actor_get_y (self);
@ -9773,13 +9753,6 @@ clutter_actor_set_position (ClutterActor *self,
&cur_position,
&new_position);
}
else
_clutter_actor_update_transition (self,
obj_props[PROP_POSITION],
&new_position);
clutter_actor_queue_relayout (self);
}
/**
* clutter_actor_get_fixed_position_set:
@ -10253,8 +10226,6 @@ clutter_actor_set_size (ClutterActor *self,
clutter_size_init (&new_size, width, height);
if (_clutter_actor_get_transition (self, obj_props[PROP_SIZE]) == NULL)
{
/* minor optimization: if we don't have a duration then we can
* skip the get_size() below, to avoid the chance of going through
* get_preferred_width() and get_preferred_height() just to jump to
@ -10284,11 +10255,6 @@ clutter_actor_set_size (ClutterActor *self,
&new_size);
}
}
else
_clutter_actor_update_transition (self, obj_props[PROP_SIZE], &new_size);
clutter_actor_queue_relayout (self);
}
/**
* clutter_actor_get_size:
@ -10605,13 +10571,11 @@ clutter_actor_get_height (ClutterActor *self)
void
clutter_actor_set_width (ClutterActor *self,
gfloat width)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_WIDTH]) == NULL)
{
float cur_size;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
/* minor optimization: if we don't have a duration
* then we can skip the get_width() below, to avoid
* the chance of going through get_preferred_width()
@ -10635,9 +10599,6 @@ clutter_actor_set_width (ClutterActor *self,
cur_size,
width);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_WIDTH], width);
}
/**
* clutter_actor_set_height:
@ -10657,13 +10618,11 @@ clutter_actor_set_width (ClutterActor *self,
void
clutter_actor_set_height (ClutterActor *self,
gfloat height)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_HEIGHT]) == NULL)
{
float cur_size;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
/* see the comment in clutter_actor_set_width() above */
if (clutter_actor_get_easing_duration (self) == 0)
{
@ -10683,9 +10642,6 @@ clutter_actor_set_height (ClutterActor *self,
cur_size,
height);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_HEIGHT], height);
}
static inline void
clutter_actor_set_x_internal (ClutterActor *self,
@ -10779,20 +10735,15 @@ clutter_actor_set_position_internal (ClutterActor *self,
void
clutter_actor_set_x (ClutterActor *self,
gfloat x)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_X]) == NULL)
{
float cur_position = clutter_actor_get_x (self);
g_return_if_fail (CLUTTER_IS_ACTOR (self));
_clutter_actor_create_transition (self, obj_props[PROP_X],
cur_position,
x);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_X], x);
}
/**
* clutter_actor_set_y:
@ -10811,20 +10762,15 @@ clutter_actor_set_x (ClutterActor *self,
void
clutter_actor_set_y (ClutterActor *self,
gfloat y)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_Y]) == NULL)
{
float cur_position = clutter_actor_get_y (self);
g_return_if_fail (CLUTTER_IS_ACTOR (self));
_clutter_actor_create_transition (self, obj_props[PROP_Y],
cur_position,
y);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_Y], y);
}
/**
* clutter_actor_get_x:
@ -11202,15 +11148,10 @@ clutter_actor_set_opacity (ClutterActor *self,
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_OPACITY]) == NULL)
{
_clutter_actor_create_transition (self, obj_props[PROP_OPACITY],
self->priv->opacity,
opacity);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_OPACITY], opacity);
}
/*
* clutter_actor_get_paint_opacity_internal:
@ -11527,23 +11468,17 @@ clutter_actor_set_z_position_internal (ClutterActor *self,
void
clutter_actor_set_z_position (ClutterActor *self,
gfloat z_position)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_Z_POSITION]) == NULL)
{
const ClutterTransformInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
info = _clutter_actor_get_transform_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_Z_POSITION],
info->z_position,
z_position);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_Z_POSITION],
z_position);
}
/**
* clutter_actor_get_z_position:
@ -11584,22 +11519,15 @@ clutter_actor_set_pivot_point (ClutterActor *self,
gfloat pivot_y)
{
ClutterPoint pivot = CLUTTER_POINT_INIT (pivot_x, pivot_y);
const ClutterTransformInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_PIVOT_POINT]) == NULL)
{
const ClutterTransformInfo *info;
info = _clutter_actor_get_transform_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_PIVOT_POINT],
&info->pivot,
&pivot);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_PIVOT_POINT], &pivot);
}
/**
* clutter_actor_get_pivot_point:
@ -11646,22 +11574,16 @@ clutter_actor_get_pivot_point (ClutterActor *self,
void
clutter_actor_set_pivot_point_z (ClutterActor *self,
gfloat pivot_z)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_PIVOT_POINT_Z]) == NULL)
{
const ClutterTransformInfo *info;
info = _clutter_actor_get_transform_info_or_defaults (self);
g_return_if_fail (CLUTTER_IS_ACTOR (self));
info = _clutter_actor_get_transform_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_PIVOT_POINT_Z],
info->pivot_z,
pivot_z);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_PIVOT_POINT_Z], pivot_z);
}
/**
* clutter_actor_get_pivot_point_z:
@ -11694,24 +11616,16 @@ clutter_actor_get_pivot_point_z (ClutterActor *self)
void
clutter_actor_set_depth (ClutterActor *self,
gfloat depth)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (_clutter_actor_get_transition (self, obj_props[PROP_DEPTH]) == NULL)
{
const ClutterTransformInfo *info;
info = _clutter_actor_get_transform_info_or_defaults (self);
g_return_if_fail (CLUTTER_IS_ACTOR (self));
info = _clutter_actor_get_transform_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_DEPTH],
info->z_position,
depth);
}
else
_clutter_actor_update_transition (self, obj_props[PROP_DEPTH], depth);
clutter_actor_queue_redraw (self);
}
/**
* clutter_actor_get_depth:
@ -17644,27 +17558,16 @@ void
clutter_actor_set_margin_top (ClutterActor *self,
gfloat margin)
{
ClutterLayoutInfo *info;
const ClutterLayoutInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info (self);
if (info->margin.top == margin)
return;
if (!_clutter_actor_get_transition (self, obj_props[PROP_MARGIN_TOP]))
{
info = _clutter_actor_get_layout_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_TOP],
info->margin.top, margin);
}
else
{
_clutter_actor_update_transition (self, obj_props[PROP_MARGIN_TOP],
info->margin.top,
margin);
}
}
/**
* clutter_actor_get_margin_top:
@ -17699,27 +17602,16 @@ void
clutter_actor_set_margin_bottom (ClutterActor *self,
gfloat margin)
{
ClutterLayoutInfo *info;
const ClutterLayoutInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info (self);
if (info->margin.bottom == margin)
return;
if (!_clutter_actor_get_transition (self, obj_props[PROP_MARGIN_BOTTOM]))
{
info = _clutter_actor_get_layout_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_BOTTOM],
info->margin.bottom, margin);
}
else
{
_clutter_actor_update_transition (self, obj_props[PROP_MARGIN_BOTTOM],
info->margin.bottom,
margin);
}
}
/**
* clutter_actor_get_margin_bottom:
@ -17754,27 +17646,16 @@ void
clutter_actor_set_margin_left (ClutterActor *self,
gfloat margin)
{
ClutterLayoutInfo *info;
const ClutterLayoutInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info (self);
if (info->margin.left == margin)
return;
if (!_clutter_actor_get_transition (self, obj_props[PROP_MARGIN_LEFT]))
{
info = _clutter_actor_get_layout_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_LEFT],
info->margin.left, margin);
}
else
{
_clutter_actor_update_transition (self, obj_props[PROP_MARGIN_LEFT],
info->margin.left,
margin);
}
}
/**
* clutter_actor_get_margin_left:
@ -17809,29 +17690,16 @@ void
clutter_actor_set_margin_right (ClutterActor *self,
gfloat margin)
{
ClutterLayoutInfo *info;
const ClutterLayoutInfo *info;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info (self);
if (info->margin.right == margin)
return;
info->margin.right = margin;
if (!_clutter_actor_get_transition (self, obj_props[PROP_MARGIN_RIGHT]))
{
info = _clutter_actor_get_layout_info_or_defaults (self);
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_RIGHT],
info->margin.right, margin);
}
else
{
_clutter_actor_update_transition (self, obj_props[PROP_MARGIN_RIGHT],
info->margin.right,
margin);
}
}
/**
* clutter_actor_get_margin_right:
@ -17895,34 +17763,26 @@ clutter_actor_set_background_color (ClutterActor *self,
const ClutterColor *color)
{
ClutterActorPrivate *priv;
GObject *obj;
GParamSpec *bg_color_pspec;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
obj = G_OBJECT (self);
priv = self->priv;
if (color == NULL)
{
priv->bg_color_set = FALSE;
g_object_notify_by_pspec (obj, obj_props[PROP_BACKGROUND_COLOR_SET]);
clutter_actor_queue_redraw (self);
return;
}
GObject *obj = G_OBJECT (self);
bg_color_pspec = obj_props[PROP_BACKGROUND_COLOR];
if (_clutter_actor_get_transition (self, bg_color_pspec) == NULL)
{
_clutter_actor_create_transition (self, bg_color_pspec,
&priv->bg_color,
color);
priv->bg_color_set = FALSE;
clutter_actor_queue_redraw (self);
g_object_notify_by_pspec (obj, obj_props[PROP_BACKGROUND_COLOR_SET]);
}
else
_clutter_actor_update_transition (self, bg_color_pspec, color);
clutter_actor_queue_redraw (self);
_clutter_actor_create_transition (self,
obj_props[PROP_BACKGROUND_COLOR],
&priv->bg_color,
color);
}
/**
@ -18424,85 +18284,6 @@ on_transition_stopped (ClutterTransition *transition,
}
}
void
_clutter_actor_update_transition (ClutterActor *actor,
GParamSpec *pspec,
...)
{
TransitionClosure *clos;
ClutterTimeline *timeline;
ClutterInterval *interval;
const ClutterAnimationInfo *info;
va_list var_args;
GType ptype;
GValue initial = G_VALUE_INIT;
GValue final = G_VALUE_INIT;
char *error = NULL;
info = _clutter_actor_get_animation_info_or_defaults (actor);
if (info->transitions == NULL)
return;
clos = g_hash_table_lookup (info->transitions, pspec->name);
if (clos == NULL)
return;
timeline = CLUTTER_TIMELINE (clos->transition);
va_start (var_args, pspec);
ptype = G_PARAM_SPEC_VALUE_TYPE (pspec);
g_value_init (&initial, ptype);
clutter_animatable_get_initial_state (CLUTTER_ANIMATABLE (actor),
pspec->name,
&initial);
G_VALUE_COLLECT_INIT (&final, ptype, var_args, 0, &error);
if (error != NULL)
{
g_critical ("%s: %s", G_STRLOC, error);
g_free (error);
goto out;
}
interval = clutter_transition_get_interval (clos->transition);
clutter_interval_set_initial_value (interval, &initial);
clutter_interval_set_final_value (interval, &final);
/* if we're updating with an easing duration of zero milliseconds,
* we just jump the timeline to the end and let it run its course
*/
if (info->cur_state != NULL &&
info->cur_state->easing_duration != 0)
{
guint cur_duration = clutter_timeline_get_duration (timeline);
ClutterAnimationMode cur_mode =
clutter_timeline_get_progress_mode (timeline);
if (cur_duration != info->cur_state->easing_duration)
clutter_timeline_set_duration (timeline, info->cur_state->easing_duration);
if (cur_mode != info->cur_state->easing_mode)
clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode);
clutter_timeline_rewind (timeline);
}
else
{
guint duration = clutter_timeline_get_duration (timeline);
clutter_timeline_advance (timeline, duration);
}
out:
g_value_unset (&initial);
g_value_unset (&final);
va_end (var_args);
}
/*< private >*
* _clutter_actor_create_transition:
* @actor: a #ClutterActor
@ -18518,11 +18299,17 @@ _clutter_actor_create_transition (ClutterActor *actor,
GParamSpec *pspec,
...)
{
ClutterTimeline *timeline;
ClutterInterval *interval;
ClutterAnimationInfo *info;
ClutterTransition *res = NULL;
gboolean call_restore = FALSE;
TransitionClosure *clos;
va_list var_args;
GValue initial = G_VALUE_INIT;
GValue final = G_VALUE_INIT;
GType ptype;
char *error;
g_assert (pspec != NULL);
g_assert ((pspec->flags & CLUTTER_PARAM_ANIMATABLE) != 0);
@ -18551,16 +18338,6 @@ _clutter_actor_create_transition (ClutterActor *actor,
va_start (var_args, pspec);
clos = g_hash_table_lookup (info->transitions, pspec->name);
if (clos == NULL)
{
ClutterTimeline *timeline;
ClutterInterval *interval;
GValue initial = G_VALUE_INIT;
GValue final = G_VALUE_INIT;
GType ptype;
char *error;
ptype = G_PARAM_SPEC_VALUE_TYPE (pspec);
G_VALUE_COLLECT_INIT (&initial, ptype,
@ -18576,7 +18353,6 @@ _clutter_actor_create_transition (ClutterActor *actor,
G_VALUE_COLLECT_INIT (&final, ptype,
var_args, 0,
&error);
if (error != NULL)
{
g_critical ("%s: %s", G_STRLOC, error);
@ -18603,6 +18379,9 @@ _clutter_actor_create_transition (ClutterActor *actor,
goto out;
}
clos = g_hash_table_lookup (info->transitions, pspec->name);
if (clos == NULL)
{
interval = clutter_interval_new_with_values (ptype, &initial, &final);
res = clutter_property_transition_new (pspec->name);
@ -18649,9 +18428,29 @@ _clutter_actor_create_transition (ClutterActor *actor,
}
else
{
ClutterAnimationMode cur_mode;
guint cur_duration;
CLUTTER_NOTE (ANIMATION, "Existing transition for %s:%s",
_clutter_actor_get_debug_name (actor),
pspec->name);
timeline = CLUTTER_TIMELINE (clos->transition);
cur_duration = clutter_timeline_get_duration (timeline);
if (cur_duration != info->cur_state->easing_duration)
clutter_timeline_set_duration (timeline, info->cur_state->easing_duration);
cur_mode = clutter_timeline_get_progress_mode (timeline);
if (cur_mode != info->cur_state->easing_mode)
clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode);
clutter_timeline_rewind (timeline);
interval = clutter_transition_get_interval (clos->transition);
clutter_interval_set_initial_value (interval, &initial);
clutter_interval_set_final_value (interval, &final);
res = clos->transition;
}
@ -19176,6 +18975,7 @@ clutter_actor_set_content_gravity (ClutterActor *self,
ClutterContentGravity gravity)
{
ClutterActorPrivate *priv;
ClutterActorBox from_box, to_box;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@ -19186,10 +18986,6 @@ clutter_actor_set_content_gravity (ClutterActor *self,
priv->content_box_valid = FALSE;
if (_clutter_actor_get_transition (self, obj_props[PROP_CONTENT_BOX]) == NULL)
{
ClutterActorBox from_box, to_box;
clutter_actor_get_content_box (self, &from_box);
priv->content_gravity = gravity;
@ -19199,20 +18995,6 @@ clutter_actor_set_content_gravity (ClutterActor *self,
_clutter_actor_create_transition (self, obj_props[PROP_CONTENT_BOX],
&from_box,
&to_box);
}
else
{
ClutterActorBox to_box;
priv->content_gravity = gravity;
clutter_actor_get_content_box (self, &to_box);
_clutter_actor_update_transition (self, obj_props[PROP_CONTENT_BOX],
&to_box);
}
clutter_actor_queue_redraw (self);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_GRAVITY]);
}