From 9424e995fa4c7ef60555a641561c5f6e44aa2276 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 24 Apr 2013 15:17:07 -0400 Subject: [PATCH] actor: Improve conditions for skipping implicit transitions The "should this implicit transition be skipped" check should live into its own function, where we can actually explain what it does and which conditions should be respected. Instead of just blindly skipping actors that are unmapped, or haven't been painted yet, we should add a couple of escape hatches. First of all, we don't want :allocation to be implicitly animated until we have been painted (thus allocated) once; this avoids actors "flying in" into their allocation. We also want to allow implicit transitions on the opacity even if we haven't been painted yet; the internal optimization that we employ in clutter_actor_paint() and skips painting fully transparent actors is exactly that: an internal optimization. Caller code should not be aware of this change, and it should not influence code outside of ClutterActor itself. The rest of the conditions are the same: if the easing state's duration is zero, or if the actor is both unmapped and not in a cloned branch of the scene graph, then implicit transitions are pointless, as they won't be painted. https://bugzilla.gnome.org/show_bug.cgi?id=698766 --- clutter/clutter-actor.c | 59 ++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 096361559..cee624a36 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -18706,6 +18706,52 @@ clutter_actor_add_transition_internal (ClutterActor *self, clutter_timeline_start (timeline); } +static gboolean +should_skip_transition (ClutterActor *self, + GParamSpec *pspec) +{ + ClutterActorPrivate *priv = self->priv; + const ClutterAnimationInfo *info; + + /* this function is called from _clutter_actor_create_transition() which + * calls _clutter_actor_get_animation_info() first, so we're guaranteed + * to have the correct ClutterAnimationInfo pointer + */ + info = _clutter_actor_get_animation_info_or_defaults (self); + + /* if the easing state has a non-zero duration we always want an + * implicit transition to occur + */ + if (info->cur_state->easing_duration == 0) + return TRUE; + + /* we do want :opacity transitions to work even if they start from an + * unpainted actor, because of the opacity optimization that lives in + * clutter_actor_paint() + */ + if (pspec == obj_props[PROP_OPACITY] && !priv->was_painted) + return FALSE; + + /* on the other hand, if the actor hasn't been allocated yet, we want to + * skip all transitions on the :allocation, to avoid actors "flying in" + * into their new position and size + */ + if (pspec == obj_props[PROP_ALLOCATION] && priv->needs_allocation) + return TRUE; + + /* if the actor is not mapped and is not part of a branch of the scene + * graph that is being cloned, then we always skip implicit transitions + * on the account of the fact that the actor is not going to be visible + * when those transitions happen + */ + if (!CLUTTER_ACTOR_IS_MAPPED (self) && + priv->in_cloned_branch == 0 && + !clutter_actor_has_mapped_clones (self)) + return TRUE; + + return FALSE; +} + /*< private >* * _clutter_actor_create_transition: * @actor: a #ClutterActor @@ -18783,17 +18829,9 @@ _clutter_actor_create_transition (ClutterActor *actor, goto out; } - if (info->cur_state->easing_duration == 0 || - !actor->priv->was_painted || - (!CLUTTER_ACTOR_IS_MAPPED (actor) && - actor->priv->in_cloned_branch == 0 && - !clutter_actor_has_mapped_clones (actor))) + if (should_skip_transition (actor, pspec)) { - /* don't bother creating the transition if one is not necessary - * because the actor doesn't want one, or if the actor is not - * visible: we just set the final value directly on the actor. - * - * we also don't go through the Animatable interface because we + /* we don't go through the Animatable interface because we * already know we got here through an animatable property. */ CLUTTER_NOTE (ANIMATION, "Easing duration=0 was_painted=%s, immediate set for '%s::%s'", @@ -18808,6 +18846,7 @@ _clutter_actor_create_transition (ClutterActor *actor, pspec->param_id, &final, pspec); + g_value_unset (&initial); g_value_unset (&final);