summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authoravallee@chromium.org <avallee@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-12 19:49:02 +0000
committeravallee@chromium.org <avallee@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-12 19:49:02 +0000
commitd0fe0b652a8854759461d0a94a1b21893fb47637 (patch)
tree2c65293370803cd7283e368b434444bf9d951aad /ui
parentd5b04b8351b3a757bbaeb3bc0b56a374a049826f (diff)
downloadchromium_src-d0fe0b652a8854759461d0a94a1b21893fb47637.zip
chromium_src-d0fe0b652a8854759461d0a94a1b21893fb47637.tar.gz
chromium_src-d0fe0b652a8854759461d0a94a1b21893fb47637.tar.bz2
Make inverse transform animations easier to create, using ScopedLayerAnimationSettings.
https://codereview.chromium.org/22861008/ Introduces inverse animations which allow layers to counter-animate against a base layer. However, manually building the animation elements is repetitive and error prone, this change makes these animations simpler to write. Users should use it in this manner: // Input values Layer *base, *inversed1, *inversed2; gfx::Transform new_transform; void foo() { ui::ScopedLayerAnimationSettings settings(base->GetAnimator()); settings.SetInverselyAnimatedBaseLayer(base); settings.AddInverselyAnimatedLayer(inversed1); settings.AddInverselyAnimatedLayer(inversed2); base->SetTransform(new_transform); } BUG=270857 Review URL: https://chromiumcodereview.appspot.com/23622004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222839 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/compositor/layer_animation_element.cc23
-rw-r--r--ui/compositor/layer_animation_element.h5
-rw-r--r--ui/compositor/layer_animation_sequence.cc14
-rw-r--r--ui/compositor/layer_animation_sequence.h6
-rw-r--r--ui/compositor/layer_animator_unittest.cc28
-rw-r--r--ui/compositor/scoped_layer_animation_settings.cc85
-rw-r--r--ui/compositor/scoped_layer_animation_settings.h11
7 files changed, 165 insertions, 7 deletions
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc
index 51a1c48..7931141 100644
--- a/ui/compositor/layer_animation_element.cc
+++ b/ui/compositor/layer_animation_element.cc
@@ -575,10 +575,19 @@ class InverseTransformTransition : public ThreadedLayerAnimationElement {
const LayerAnimationElement* uninverted_transition)
: ThreadedLayerAnimationElement(*uninverted_transition),
base_transform_(base_transform),
- uninverted_transition_(CheckAndCast(uninverted_transition)) {
+ uninverted_transition_(
+ CheckAndCast<const ThreadedTransformTransition*>(
+ uninverted_transition)) {
}
virtual ~InverseTransformTransition() {}
+ static InverseTransformTransition* Clone(const LayerAnimationElement* other) {
+ const InverseTransformTransition* other_inverse =
+ CheckAndCast<const InverseTransformTransition*>(other);
+ return new InverseTransformTransition(
+ other_inverse->base_transform_, other_inverse->uninverted_transition_);
+ }
+
protected:
virtual void OnStart(LayerAnimationDelegate* delegate) OVERRIDE {
gfx::Transform start(delegate->GetTransformForAnimation());
@@ -658,11 +667,11 @@ class InverseTransformTransition : public ThreadedLayerAnimationElement {
return properties;
}
- static const ThreadedTransformTransition* CheckAndCast(
- const LayerAnimationElement* element) {
+ template <typename T>
+ static T CheckAndCast(const LayerAnimationElement* element) {
const AnimatableProperties& properties = element->properties();
DCHECK(properties.find(TRANSFORM) != properties.end());
- return static_cast<const ThreadedTransformTransition*>(element);
+ return static_cast<T>(element);
}
gfx::Transform effective_start_;
@@ -862,6 +871,12 @@ LayerAnimationElement* LayerAnimationElement::CreateInverseTransformElement(
}
// static
+LayerAnimationElement* LayerAnimationElement::CloneInverseTransformElement(
+ const LayerAnimationElement* other) {
+ return InverseTransformTransition::Clone(other);
+}
+
+// static
LayerAnimationElement*
LayerAnimationElement::CreateInterpolatedTransformElement(
InterpolatedTransform* interpolated_transform,
diff --git a/ui/compositor/layer_animation_element.h b/ui/compositor/layer_animation_element.h
index b027764..9b969f1f 100644
--- a/ui/compositor/layer_animation_element.h
+++ b/ui/compositor/layer_animation_element.h
@@ -74,6 +74,11 @@ class COMPOSITOR_EXPORT LayerAnimationElement {
const gfx::Transform& base_transform,
const LayerAnimationElement* uninverted_transition);
+
+ // Duplicates elements as created by CreateInverseTransformElement.
+ static LayerAnimationElement* CloneInverseTransformElement(
+ const LayerAnimationElement* other);
+
// Creates an element that transitions to another in a way determined by an
// interpolated transform. The element accepts ownership of the interpolated
// transform. NB: at every step, the interpolated transform clobbers the
diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc
index f1c7eba..f336035 100644
--- a/ui/compositor/layer_animation_sequence.cc
+++ b/ui/compositor/layer_animation_sequence.cc
@@ -242,6 +242,18 @@ void LayerAnimationSequence::OnAnimatorDestroyed() {
}
}
+size_t LayerAnimationSequence::size() const {
+ return elements_.size();
+}
+
+LayerAnimationElement* LayerAnimationSequence::FirstElement() const {
+ if (elements_.empty()) {
+ return NULL;
+ }
+
+ return elements_[0].get();
+}
+
void LayerAnimationSequence::NotifyScheduled() {
FOR_EACH_OBSERVER(LayerAnimationObserver,
observers_,
@@ -260,7 +272,7 @@ void LayerAnimationSequence::NotifyAborted() {
OnLayerAnimationAborted(this));
}
-LayerAnimationElement* LayerAnimationSequence::CurrentElement() {
+LayerAnimationElement* LayerAnimationSequence::CurrentElement() const {
if (elements_.empty())
return NULL;
diff --git a/ui/compositor/layer_animation_sequence.h b/ui/compositor/layer_animation_sequence.h
index a2972f7..854785a 100644
--- a/ui/compositor/layer_animation_sequence.h
+++ b/ui/compositor/layer_animation_sequence.h
@@ -125,6 +125,10 @@ class COMPOSITOR_EXPORT LayerAnimationSequence
// by this sequence. Returns 0.0 if no elements have been progressed.
double last_progressed_fraction() const { return last_progressed_fraction_; }
+ size_t size() const;
+
+ LayerAnimationElement* FirstElement() const;
+
private:
friend class LayerAnimatorTestController;
@@ -143,7 +147,7 @@ class COMPOSITOR_EXPORT LayerAnimationSequence
void NotifyAborted();
// The currently animating element.
- LayerAnimationElement* CurrentElement();
+ LayerAnimationElement* CurrentElement() const;
// The union of all the properties modified by all elements in the sequence.
LayerAnimationElement::AnimatableProperties properties_;
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index 5f5871f..8506455 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -10,6 +10,7 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_delegate.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
@@ -2375,4 +2376,31 @@ TEST(LayerAnimatorTest, TestSetterRespectEnqueueStrategy) {
EXPECT_EQ(start_opacity, delegate.GetOpacityForAnimation());
}
+TEST(LayerAnimatorTest, TestScopedCounterAnimation) {
+ Layer parent, child;
+ parent.Add(&child);
+
+ gfx::Transform parent_begin, parent_end;
+
+ parent_end.Scale3d(2.0, 0.5, 1.0);
+
+ // Parent animates from identity to the end value. The counter animation will
+ // start at the end value and animate back to identity.
+ gfx::Transform child_begin(parent_end);
+
+ child.SetTransform(child_begin);
+ parent.SetTransform(parent_begin);
+
+ ScopedLayerAnimationSettings settings(parent.GetAnimator());
+ settings.SetInverselyAnimatedBaseLayer(&parent);
+ settings.AddInverselyAnimatedLayer(&child);
+
+ parent.SetTransform(parent_end);
+
+ EXPECT_TRUE(child.GetTargetTransform().IsIdentity())
+ << child.GetTargetTransform().ToString();
+ EXPECT_TRUE(child.GetAnimator()->is_animating());
+
+}
+
} // namespace ui
diff --git a/ui/compositor/scoped_layer_animation_settings.cc b/ui/compositor/scoped_layer_animation_settings.cc
index b45d94c..5c5a1bb 100644
--- a/ui/compositor/scoped_layer_animation_settings.cc
+++ b/ui/compositor/scoped_layer_animation_settings.cc
@@ -4,7 +4,9 @@
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
namespace {
@@ -15,12 +17,75 @@ const int kDefaultTransitionDurationMs = 200;
namespace ui {
+// InvertingObserver -----------------------------------------------------------
+class InvertingObserver : public ImplicitAnimationObserver {
+ public:
+ InvertingObserver()
+ : base_layer_(NULL) {
+ }
+
+ virtual ~InvertingObserver() {}
+
+ void SetLayer(Layer* base_layer) { base_layer_ = base_layer; }
+
+ Layer* layer() { return base_layer_; }
+
+ void AddInverselyAnimatedLayer(Layer* inverse_layer) {
+ inverse_layers_.push_back(inverse_layer);
+ }
+
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {}
+
+ virtual void OnLayerAnimationScheduled(
+ LayerAnimationSequence* sequence) OVERRIDE {
+ DCHECK(base_layer_ != NULL)
+ << "Must set base layer with ScopedLayerAnimationSettings::"
+ << "SetInverslyAnimatedBaseLayer";
+ gfx::Transform base_transform = base_layer_->transform();
+ scoped_ptr<LayerAnimationElement> inverse = GetInverseElement(sequence,
+ base_transform);
+ LayerAnimationElement::CloneInverseTransformElement(inverse.get());
+
+ for (std::vector<Layer*>::const_iterator i =
+ inverse_layers_.begin(); i != inverse_layers_.end(); ++i) {
+ (*i)->GetAnimator()->StartAnimation(new LayerAnimationSequence(
+ LayerAnimationElement::CloneInverseTransformElement(
+ inverse.get())));
+ }
+ }
+ private:
+ scoped_ptr<LayerAnimationElement> GetInverseElement(
+ LayerAnimationSequence* sequence,
+ gfx::Transform base) const {
+ const size_t expected_size = 1;
+ DCHECK_EQ(expected_size, sequence->size()) <<
+ "Inverse supported only for single element sequences.";
+
+ LayerAnimationElement* element = sequence->FirstElement();
+ LayerAnimationElement::AnimatableProperties transform_property;
+ transform_property.insert(LayerAnimationElement::TRANSFORM);
+ DCHECK(transform_property == element->properties())
+ << "Only transform animations are currently invertible.";
+
+ scoped_ptr<LayerAnimationElement> to_return(
+ LayerAnimationElement::CreateInverseTransformElement(base, element));
+ return to_return.Pass();
+ }
+
+ Layer* base_layer_;
+ // child layers
+ std::vector<Layer*> inverse_layers_;
+};
+
+
+// ScoperLayerAnimationSettings ------------------------------------------------
ScopedLayerAnimationSettings::ScopedLayerAnimationSettings(
LayerAnimator* animator)
: animator_(animator),
old_transition_duration_(animator->transition_duration_),
old_tween_type_(animator->tween_type()),
- old_preemption_strategy_(animator->preemption_strategy()) {
+ old_preemption_strategy_(animator->preemption_strategy()),
+ inverse_observer_(new InvertingObserver()) {
SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
}
@@ -35,6 +100,10 @@ ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() {
animator_->observers_.RemoveObserver(*i);
(*i)->SetActive(true);
}
+
+ if (inverse_observer_->layer()) {
+ animator_->observers_.RemoveObserver(inverse_observer_.get());
+ }
}
void ScopedLayerAnimationSettings::AddObserver(
@@ -70,4 +139,18 @@ ScopedLayerAnimationSettings::GetPreemptionStrategy() const {
return animator_->preemption_strategy();
}
+void ScopedLayerAnimationSettings::SetInverselyAnimatedBaseLayer(Layer* base) {
+ if (inverse_observer_->layer() && !base) {
+ animator_->RemoveObserver(inverse_observer_.get());
+ } else if (base && !(inverse_observer_->layer())) {
+ animator_->AddObserver(inverse_observer_.get());
+ }
+ inverse_observer_->SetLayer(base);
+}
+
+void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer(
+ Layer* inverse_layer) {
+ inverse_observer_->AddInverselyAnimatedLayer(inverse_layer);
+}
+
} // namespace ui
diff --git a/ui/compositor/scoped_layer_animation_settings.h b/ui/compositor/scoped_layer_animation_settings.h
index 7f8e1c7..4e94eee 100644
--- a/ui/compositor/scoped_layer_animation_settings.h
+++ b/ui/compositor/scoped_layer_animation_settings.h
@@ -7,6 +7,7 @@
#include <set>
+#include "base/memory/scoped_vector.h"
#include "base/time/time.h"
#include "ui/base/animation/tween.h"
@@ -17,6 +18,7 @@ namespace ui {
class ImplicitAnimationObserver;
class LayerAnimationObserver;
+class InvertingObserver;
// Scoped settings allow you to temporarily change the animator's settings and
// these changes are reverted when the object is destroyed. NOTE: when the
@@ -38,12 +40,21 @@ class COMPOSITOR_EXPORT ScopedLayerAnimationSettings {
void SetPreemptionStrategy(LayerAnimator::PreemptionStrategy strategy);
LayerAnimator::PreemptionStrategy GetPreemptionStrategy() const;
+ // Sets the base layer whose animation will be countered.
+ void SetInverselyAnimatedBaseLayer(Layer* base);
+
+ // Adds the layer to be counter-animated when a transform animation is
+ // scheduled on the animator_. Must call SetInverselyAnimatedBaseLayer with
+ // the layer associated with animator_ before animating.
+ void AddInverselyAnimatedLayer(Layer* inverse_layer);
+
private:
LayerAnimator* animator_;
base::TimeDelta old_transition_duration_;
Tween::Type old_tween_type_;
LayerAnimator::PreemptionStrategy old_preemption_strategy_;
std::set<ImplicitAnimationObserver*> observers_;
+ scoped_ptr<InvertingObserver> inverse_observer_;
DISALLOW_COPY_AND_ASSIGN(ScopedLayerAnimationSettings);
};