1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * animation.cpp: Animation engine
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
22 #include "application.h"
23 #include "timemanager.h"
24 #include "animation.h"
30 #define LERP(f,t,p) ((f) + ((t) - (f)) * (p))
32 #define KEYSPLINE_PRECISION_LEVEL 4
34 // This is 2 to power of KEYSPLINE_PRECISION_LEVEL
35 #define KEYSPLINE_TOTAL_COUNT 16
37 KeyTime
KeyTime::Paced (KeyTime::PACED
);
38 KeyTime
KeyTime::Uniform (KeyTime::UNIFORM
);
41 AnimationStorage sits between an DependencyObject and a DependencyProperty.
42 The AnimationClock creates a storage for DO, and the storage attaches itself to
43 a DP. The DP keeps a list (hashtable) keyed by the DO pointer.
45 The storage can be deleted when
46 - The DP when it's clearing its list of storage objects. This happens when the DP
48 - The AnimationClock is destroyed.
49 - A new storage is created for the same dependencyobject. In this case, the previous
50 storage that was on the list for the DO is replaced.
52 This means the storage can disappear but both the DependencyProperty and the
53 DependencyObject (and AnimationClock) that it referenced might still be
54 alive. It is very important that when the storage is removed, the
55 corresponding references to it be cleared, too - this means removing it
56 from the DP list when it is deleted by the clock, or removing it from the clock
57 when it's deleted by the DP, as well as clearing any event handlers that could
58 still fire up after it's dead.
62 AnimationStorage::AnimationStorage (AnimationClock
*clock
, Animation
*timeline
,
63 DependencyObject
*targetobj
, DependencyProperty
*targetprop
)
65 this->nonResetableFlag
= false;
67 this->timeline
= timeline
;
68 this->targetobj
= targetobj
;
69 this->targetprop
= targetprop
;
71 clock
->AddHandler (clock
->CurrentTimeInvalidatedEvent
, update_property_value
, this);
72 AttachTargetHandler ();
74 AnimationStorage
*prev_storage
= targetprop
->AttachAnimationStorage (targetobj
, this);
76 baseValue
= new Value(*targetobj
->GetValue (targetprop
));
79 Value
*v
= prev_storage
->GetResetValue ();
80 stopValue
= new Value (*v
);
81 prev_storage
->FlagAsNonResetable ();
89 AnimationStorage::target_object_destroyed (EventObject
*, EventArgs
*, gpointer closure
)
91 ((AnimationStorage
*)closure
)->TargetObjectDestroyed ();
95 AnimationStorage::TargetObjectDestroyed ()
97 if (targetprop
!= NULL
)
98 targetprop
->DetachAnimationStorage (targetobj
, this);
100 DetachUpdateHandler ();
104 AnimationStorage::FlagAsNonResetable ()
106 nonResetableFlag
= true;
110 AnimationStorage::IsCurrentStorage ()
112 if (targetobj
== NULL
|| targetprop
== NULL
)
115 if (targetprop
->GetAnimationStorageFor (targetobj
) == this)
122 AnimationStorage::GetStopValue ()
131 AnimationStorage::update_property_value (EventObject
*, EventArgs
*, gpointer closure
)
133 ((AnimationStorage
*)closure
)->UpdatePropertyValue ();
137 AnimationStorage::UpdatePropertyValue ()
139 if (targetobj
== NULL
)
142 Value
*current_value
= clock
->GetCurrentValue (baseValue
, NULL
/*XXX*/);
143 if (current_value
!= NULL
&& timeline
->GetTimelineStatus () == Timeline::TIMELINE_STATUS_OK
) {
144 Applier
*applier
= clock
->GetTimeManager ()->GetApplier ();
145 applier
->AddPropertyChange (targetobj
, targetprop
, new Value (*current_value
), APPLIER_PRECEDENCE_ANIMATION
);
148 delete current_value
;
152 AnimationStorage::ResetPropertyValue ()
154 if (nonResetableFlag
)
157 if (targetobj
== NULL
)
160 if (timeline
->GetTimelineStatus () != Timeline::TIMELINE_STATUS_OK
)
163 Applier
*applier
= clock
->GetTimeManager ()->GetApplier ();
166 applier
->AddPropertyChange (targetobj
, targetprop
, new Value (*stopValue
), APPLIER_PRECEDENCE_ANIMATION_RESET
);
168 applier
->AddPropertyChange (targetobj
, targetprop
, new Value (*baseValue
), APPLIER_PRECEDENCE_ANIMATION_RESET
);
172 AnimationStorage::DetachFromProperty (void)
174 if (targetobj
!= NULL
&& targetprop
!= NULL
) {
175 targetprop
->DetachAnimationStorage (targetobj
, this);
181 AnimationStorage::DetachTarget ()
183 DetachUpdateHandler ();
185 DetachTargetHandler ();
191 AnimationStorage::DetachUpdateHandler ()
194 clock
->RemoveHandler (Clock::CurrentTimeInvalidatedEvent
, update_property_value
, this);
198 AnimationStorage::ReAttachUpdateHandler ()
201 clock
->AddHandler (Clock::CurrentTimeInvalidatedEvent
, update_property_value
, this);
205 AnimationStorage::AttachTargetHandler ()
207 if (!targetobj
) return;
208 targetobj
->AddHandler (EventObject::DestroyedEvent
, target_object_destroyed
, this);
212 AnimationStorage::DetachTargetHandler ()
214 if (!targetobj
) return;
215 targetobj
->RemoveHandler (EventObject::DestroyedEvent
, target_object_destroyed
, this);
219 AnimationStorage::GetResetValue ()
227 AnimationStorage::~AnimationStorage ()
239 DetachUpdateHandler ();
241 if (targetobj
!= NULL
) {
242 DetachTargetHandler ();
243 DetachFromProperty ();
247 clock
->DetachFromStorage ();
251 AnimationClock::AnimationClock (Animation
*timeline
)
254 SetObjectType (Type::ANIMATIONCLOCK
);
256 this->timeline
= timeline
;
261 AnimationClock::HookupStorage (DependencyObject
*targetobj
, DependencyProperty
*targetprop
)
263 /* Before hooking up make sure that the values our animation generates
264 (doubles, colors, points...) match the values that the property is
265 ready to receive. If not, print an informative message. */
266 Type
*property_type
= Type::Find (targetprop
->GetPropertyType());
267 if (timeline
->GetValueKind () != Type::INVALID
&& !property_type
->IsAssignableFrom (timeline
->GetValueKind ())) {
268 Type
*timeline_type
= Type::Find (timeline
->GetValueKind ());
270 const char *timeline_type_name
= (timeline_type
!= NULL
) ? timeline_type
->GetName () : "Invalid";
271 const char *property_type_name
= (property_type
!= NULL
) ? property_type
->GetName () : "Invalid";
272 g_warning ("%s.%s property value type is '%s' but animation type is '%s'.",
273 targetobj
->GetTypeName (), targetprop
->GetName(),
274 property_type_name
, timeline_type_name
);
279 char *name
= g_strdup_printf ("AnimationClock for %s, targetobj = %p/%s, targetprop = %s", GetTypeName(),
281 targetobj
->GetName(),
282 targetprop
->GetName());
287 storage
= new AnimationStorage (this, timeline
, targetobj
, targetprop
);
292 AnimationClock::GetCurrentValue (Value
* defaultOriginValue
, Value
* defaultDestinationValue
)
294 return timeline
->GetCurrentValue (defaultOriginValue
, defaultDestinationValue
, this);
298 AnimationClock::Stop ()
301 storage
->ResetPropertyValue ();
302 storage
->DetachUpdateHandler ();
303 if (storage
->IsCurrentStorage ())
304 storage
->DetachFromProperty ();
311 AnimationClock::Begin (TimeSpan parentTime
)
313 Clock::Begin (parentTime
);
316 AnimationClock::~AnimationClock ()
320 if (storage
->IsLonely ())
323 if (state
== Clock::Stopped
)
326 if (storage
->IsCurrentStorage ()) {
327 storage
->DetachFromProperty ();
336 AnimationClock::DetachFromStorage ()
342 Animation::AllocateClock()
344 clock
= new AnimationClock (this);
346 AttachCompletedHandler ();
352 Animation::GetTargetValue (Value
* defaultOriginValue
)
358 Animation::GetCurrentValue (Value
* defaultOriginValue
, Value
* defaultDestinationValue
,
359 AnimationClock
* animationClock
)
366 Animation::GetNaturalDurationCore (Clock
* clock
)
368 return Duration::FromSeconds (1);
376 Storyboard::Storyboard ()
378 SetObjectType (Type::STORYBOARD
);
381 Storyboard::~Storyboard ()
384 //printf ("Clock %p (ref=%d)\n", root_clock, root_clock->refcount);
385 StopWithError (/* ignore any error */ NULL
);
386 TeardownClockGroup ();
391 Storyboard::GetCurrentTime ()
393 return GetClock() ? GetClock()->GetCurrentTime () : 0;
397 Storyboard::GetCurrentState ()
399 return GetClock() ? GetClock()->GetClockState () : Clock::Stopped
;
403 Storyboard::GetTargetDependencyProperty ()
405 PropertyPath
*path
= GetTargetProperty (this);
406 return path
? path
->property
: NULL
;
410 Storyboard::HookupAnimationsRecurse (Clock
*clock
, DependencyObject
*targetObject
, PropertyPath
*targetPropertyPath
, MoonError
*error
)
412 DependencyObject
*localTargetObject
= NULL
;
413 PropertyPath
*localTargetPropertyPath
= NULL
;
415 Timeline
*timeline
= clock
->GetTimeline ();
417 /* get the target object at this level */
418 if (timeline
->HasManualTarget ())
419 localTargetObject
= timeline
->GetManualTarget ();
421 const char *targetName
= Storyboard::GetTargetName (timeline
);
423 localTargetObject
= FindName (targetName
);
426 /* get the target property path at this level */
427 localTargetPropertyPath
= Storyboard::GetTargetProperty (timeline
);
430 /* override the object and property passed from our parent here */
431 if (localTargetObject
!= NULL
)
432 targetObject
= localTargetObject
;
434 if (localTargetPropertyPath
!= NULL
)
435 targetPropertyPath
= localTargetPropertyPath
;
438 if (clock
->Is (Type::CLOCKGROUP
)) {
439 for (GList
*l
= ((ClockGroup
*)clock
)->child_clocks
; l
; l
= l
->next
) {
440 if (!HookupAnimationsRecurse ((Clock
*)l
->data
,
448 DependencyProperty
*prop
= NULL
;
449 DependencyObject
*realTargetObject
;
451 if (!targetPropertyPath
) {
452 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Target Property has not been specified.");
453 g_warning ("No target property!");
458 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "No Target or TargetName has been specified");
462 realTargetObject
= targetObject
;
464 prop
= resolve_property_path (&realTargetObject
, targetPropertyPath
);
466 if (!prop
|| !realTargetObject
) {
467 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "TargetProperty could not be resolved");
468 g_warning ("No property path %s on object of type type %s!",
469 targetPropertyPath
->path
, targetObject
->GetTypeName());
473 if (clock
->Is(Type::ANIMATIONCLOCK
)) {
474 Animation
*animation
= (Animation
*)timeline
;
476 if (!animation
->Resolve (realTargetObject
, prop
)) {
477 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Storyboard value could not be converted to the correct type");
481 if (!((AnimationClock
*)clock
)->HookupStorage (realTargetObject
, prop
))
490 Storyboard::TeardownClockGroup ()
493 Clock
*c
= GetClock ();
494 ClockGroup
*group
= c
->GetParentClock();
496 group
->RemoveChild (c
);
502 Storyboard::BeginWithError (MoonError
*error
)
504 if (GetHadParent ()) {
505 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Begin a Storyboard which is not the root Storyboard.");
509 /* destroy the clock hierarchy and recreate it to restart.
510 easier than making Begin work again with the existing clock
513 DetachCompletedHandler ();
514 TeardownClockGroup ();
517 if (Validate () == false)
520 // This creates the clock tree for the hierarchy. if a
521 // Timeline A is a child of TimelineGroup B, then Clock cA
522 // will be a child of ClockGroup cB.
523 Clock
*root_clock
= AllocateClock ();
524 char *name
= g_strdup_printf ("Storyboard, named '%s'", GetName());
525 root_clock
->SetValue (DependencyObject::NameProperty
, name
);
528 // walk the clock tree hooking up the correct properties and
529 // creating AnimationStorage's for AnimationClocks.
530 if (!HookupAnimationsRecurse (root_clock
, NULL
, NULL
, error
))
533 Deployment::GetCurrent()->GetSurface()->GetTimeManager()->AddClock (root_clock
);
535 if (GetBeginTime() == 0)
536 root_clock
->BeginOnTick ();
542 Storyboard::PauseWithError (MoonError
*error
)
544 if (GetHadParent ()) {
545 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Pause a Storyboard which is not the root Storyboard.");
553 Storyboard::ResumeWithError (MoonError
*error
)
555 if (GetHadParent ()) {
556 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Resume a Storyboard which is not the root Storyboard.");
564 Storyboard::SeekWithError (TimeSpan timespan
, MoonError
*error
)
566 if (GetHadParent ()) {
567 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Seek a Storyboard which is not the root Storyboard.");
571 clock
->Seek (timespan
);
575 Storyboard::SeekAlignedToLastTickWithError (TimeSpan timespan
, MoonError
*error
)
577 if (GetHadParent ()) {
578 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Seek a Storyboard which is not the root Storyboard.");
582 clock
->SeekAlignedToLastTick (timespan
);
586 Storyboard::SkipToFillWithError (MoonError
*error
)
588 if (GetHadParent ()) {
589 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot SkipToFill a Storyboard which is not the root Storyboard.");
593 clock
->SkipToFill ();
598 Storyboard::StopWithError (MoonError
*error
)
600 if (GetHadParent ()) {
601 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Stop a Storyboard which is not the root Storyboard.");
605 DetachCompletedHandler ();
607 TeardownClockGroup ();
611 BeginStoryboard::BeginStoryboard ()
613 SetObjectType (Type::BEGINSTORYBOARD
);
616 BeginStoryboard::~BeginStoryboard ()
621 BeginStoryboard::Fire ()
623 Storyboard
*sb
= GetStoryboard ();
625 // FIXME I'd imagine we should be bubbling this error/exception upward, no?
626 sb
->BeginWithError (NULL
);
631 DoubleAnimation::DoubleAnimation ()
633 SetObjectType (Type::DOUBLEANIMATION
);
635 doubleToCached
= NULL
;
636 doubleFromCached
= NULL
;
637 doubleByCached
= NULL
;
641 void DoubleAnimation::EnsureCache (void)
643 doubleFromCached
= GetFrom ();
644 doubleToCached
= GetTo ();
645 doubleByCached
= GetBy ();
650 DoubleAnimation::GetTargetValue (Value
*defaultOriginValue
)
653 this->EnsureCache ();
657 if (doubleFromCached
)
658 start
= *doubleFromCached
;
659 else if (defaultOriginValue
->Is(Type::DOUBLE
))
660 start
= defaultOriginValue
->AsDouble();
665 return new Value (*doubleToCached
);
666 else if (doubleByCached
)
667 return new Value (start
+ *doubleByCached
);
669 return new Value (start
);
673 DoubleAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
674 AnimationClock
* animationClock
)
677 this->EnsureCache ();
681 if (doubleFromCached
)
682 start
= *doubleFromCached
;
683 else if (defaultOriginValue
->Is(Type::DOUBLE
))
684 start
= defaultOriginValue
->AsDouble();
690 if (doubleToCached
) {
691 end
= *doubleToCached
;
693 else if (doubleByCached
) {
694 end
= start
+ *doubleByCached
;
700 double progress
= animationClock
->GetCurrentProgress ();
702 if (GetEasingFunction ())
703 progress
= GetEasingFunction()->Ease (progress
);
705 return new Value (LERP (start
, end
, progress
));
709 DoubleAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
711 if (args
->GetProperty ()->GetOwnerType() != Type::DOUBLEANIMATION
) {
712 DependencyObject::OnPropertyChanged (args
, error
);
716 // Get rid of the cache
718 doubleToCached
= NULL
;
719 doubleFromCached
= NULL
;
720 doubleByCached
= NULL
;
722 NotifyListenersOfPropertyChange (args
, error
);
725 ColorAnimation::ColorAnimation ()
727 SetObjectType (Type::COLORANIMATION
);
729 colorToCached
= NULL
;
730 colorFromCached
= NULL
;
731 colorByCached
= NULL
;
735 void ColorAnimation::EnsureCache (void)
737 colorFromCached
= GetFrom ();
738 colorToCached
= GetTo ();
739 colorByCached
= GetBy ();
744 ColorAnimation::GetTargetValue (Value
*defaultOriginValue
)
747 this->EnsureCache ();
752 start
= *colorFromCached
;
753 else if (defaultOriginValue
->Is(Type::COLOR
))
754 start
= *defaultOriginValue
->AsColor();
757 return new Value (*colorToCached
);
758 else if (colorByCached
)
759 return new Value (start
+ *colorByCached
);
761 return new Value (start
);
765 ColorAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
766 AnimationClock
* animationClock
)
769 this->EnsureCache ();
774 start
= *colorFromCached
;
775 else if (defaultOriginValue
->Is(Type::COLOR
))
776 start
= *defaultOriginValue
->AsColor();
781 end
= *colorToCached
;
783 else if (colorByCached
) {
784 end
= start
+ *colorByCached
;
790 double progress
= animationClock
->GetCurrentProgress ();
792 if (GetEasingFunction ())
793 progress
= GetEasingFunction()->Ease (progress
);
795 return new Value (LERP (start
, end
, progress
));
799 ColorAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
801 if (args
->GetProperty ()->GetOwnerType() != Type::COLORANIMATION
) {
802 DependencyObject::OnPropertyChanged (args
, error
);
806 // Get rid of the cache
807 colorToCached
= NULL
;
808 colorFromCached
= NULL
;
809 colorByCached
= NULL
;
812 NotifyListenersOfPropertyChange (args
, error
);
815 PointAnimation::PointAnimation ()
817 SetObjectType (Type::POINTANIMATION
);
819 pointToCached
= NULL
;
820 pointFromCached
= NULL
;
821 pointByCached
= NULL
;
825 PointAnimation::~PointAnimation ()
829 void PointAnimation::EnsureCache (void)
831 pointFromCached
= GetFrom ();
832 pointToCached
= GetTo ();
833 pointByCached
= GetBy ();
838 PointAnimation::GetTargetValue (Value
*defaultOriginValue
)
841 this->EnsureCache ();
846 start
= *pointFromCached
;
847 else if (defaultOriginValue
->Is(Type::POINT
))
848 start
= *defaultOriginValue
->AsPoint();
851 return new Value (*pointToCached
);
852 else if (pointByCached
)
853 return new Value (start
+ *pointByCached
);
855 return new Value (start
);
859 PointAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
860 AnimationClock
* animationClock
)
863 this->EnsureCache ();
868 start
= *pointFromCached
;
869 else if (defaultOriginValue
->Is(Type::POINT
))
870 start
= *defaultOriginValue
->AsPoint();
875 end
= *pointToCached
;
877 else if (pointByCached
) {
878 end
= start
+ *pointByCached
;
884 double progress
= animationClock
->GetCurrentProgress ();
886 if (GetEasingFunction ())
887 progress
= GetEasingFunction()->Ease (progress
);
889 return new Value (LERP (start
, end
, progress
));
893 PointAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
895 if (args
->GetProperty ()->GetOwnerType() != Type::POINTANIMATION
) {
896 DependencyObject::OnPropertyChanged (args
, error
);
900 // Get rid of the cache
901 pointToCached
= NULL
;
902 pointFromCached
= NULL
;
903 pointByCached
= NULL
;
906 NotifyListenersOfPropertyChange (args
, error
);
909 KeySpline::KeySpline ()
911 SetObjectType (Type::KEYSPLINE
);
913 quadraticsArray
= NULL
;
916 KeySpline::KeySpline (Point controlPoint1
, Point controlPoint2
)
918 SetObjectType (Type::KEYSPLINE
);
920 quadraticsArray
= NULL
;
921 SetControlPoint1 (&controlPoint1
);
922 SetControlPoint2 (&controlPoint2
);
925 KeySpline::KeySpline (double x1
, double y1
,
926 double x2
, double y2
)
928 SetObjectType (Type::KEYSPLINE
);
930 quadraticsArray
= NULL
;
932 Point p1
= Point (x1
, y1
);
933 Point p2
= Point (x2
, y2
);
935 SetControlPoint1 (&p1
);
936 SetControlPoint2 (&p2
);
939 KeySpline::~KeySpline ()
941 g_free (quadraticsArray
);
942 quadraticsArray
= NULL
;
947 KeySpline::RegenerateQuadratics ()
949 quadraticsArray
= (moon_quadratic
*) g_malloc (sizeof (moon_quadratic
) * KEYSPLINE_TOTAL_COUNT
);
951 Point c1
= *GetControlPoint1 ();
952 Point c2
= *GetControlPoint2 ();
955 src
.c0
.x
= 0; src
.c0
.y
= 0;
956 src
.c1
.x
= c1
.x
; src
.c1
.y
= c1
.y
;
957 src
.c2
.x
= c2
.x
; src
.c2
.y
= c2
.y
;
958 src
.c3
.x
= 1.0; src
.c3
.y
= 1.0;
960 moon_cubic carr
[KEYSPLINE_TOTAL_COUNT
];
962 moon_subdivide_cubic_at_level (carr
, KEYSPLINE_PRECISION_LEVEL
, &src
);
963 moon_convert_cubics_to_quadratics (quadraticsArray
, carr
, KEYSPLINE_TOTAL_COUNT
);
967 KeySpline::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
969 if (args
->GetProperty ()->GetOwnerType() != Type::KEYSPLINE
) {
970 DependencyObject::OnPropertyChanged (args
, error
);
974 g_free (quadraticsArray
);
975 quadraticsArray
= NULL
;
977 NotifyListenersOfPropertyChange (args
, error
);
981 KeySpline::GetSplineProgress (double linearProgress
)
983 if (linearProgress
>= 1.0)
986 if (linearProgress
<= 0.0)
989 if (quadraticsArray
== NULL
)
990 RegenerateQuadratics ();
992 return moon_quadratic_array_y_for_x (quadraticsArray
, linearProgress
, KEYSPLINE_TOTAL_COUNT
);
995 KeyFrame::KeyFrame ()
997 SetObjectType (Type::KEYFRAME
);
1000 KeyFrame::~KeyFrame ()
1005 KeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1007 g_warning ("KeyFrame::InterpolateValue has been called. The derived class %s should have overridden it.",
1013 KeyFrameComparer (gconstpointer kf1
, gconstpointer kf2
)
1015 // Assumes timespan keytimes only
1016 TimeSpan ts1
= (*(KeyFrame
**) kf1
)->resolved_keytime
;
1017 TimeSpan ts2
= (*(KeyFrame
**) kf2
)->resolved_keytime
;
1018 TimeSpan tsdiff
= ts1
- ts2
;
1022 else if (tsdiff
< 0)
1028 KeyFrameCollection::KeyFrameCollection ()
1030 SetObjectType (Type::KEYFRAME_COLLECTION
);
1032 sorted_list
= g_ptr_array_new ();
1036 KeyFrameCollection::~KeyFrameCollection ()
1038 g_ptr_array_free (sorted_list
, true);
1042 KeyFrameCollection::AddedToCollection (Value
*value
, MoonError
*error
)
1044 if (!DependencyObjectCollection::AddedToCollection (value
, error
))
1053 KeyFrameCollection::RemovedFromCollection (Value
*value
)
1055 DependencyObjectCollection::RemovedFromCollection (value
);
1061 KeyFrameCollection::Clear ()
1064 g_ptr_array_set_size (sorted_list
, 0);
1065 return DependencyObjectCollection::Clear ();
1069 KeyFrameCollection::GetKeyFrameForTime (TimeSpan t
, KeyFrame
**prev_frame
)
1071 KeyFrame
*current_keyframe
= NULL
;
1072 KeyFrame
*previous_keyframe
= NULL
;
1075 if (sorted_list
->len
== 0) {
1082 /* Crawl forward to figure out what segment to use (this assumes the list is sorted) */
1083 for (i
= 0; i
< (int) sorted_list
->len
; i
++) {
1084 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1085 TimeSpan key_end_time
= keyframe
->resolved_keytime
;
1087 if (key_end_time
>= t
|| (i
+ 1) >= (int) sorted_list
->len
)
1091 /* Crawl backward to find first non-null frame */
1092 for (; i
>= 0; i
--) {
1093 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1094 DependencyProperty
*value_prop
= keyframe
->GetDependencyProperty ("Value");
1095 if (keyframe
->GetValue (value_prop
) != NULL
) {
1096 current_keyframe
= keyframe
;
1101 /* Crawl backward some more to find first non-null prev frame */
1102 for (i
--; i
>= 0; i
--) {
1103 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1104 DependencyProperty
*value_prop
= keyframe
->GetDependencyProperty ("Value");
1105 if (keyframe
->GetValue (value_prop
) != NULL
) {
1106 previous_keyframe
= keyframe
;
1111 /* Assign prev frame */
1112 if (prev_frame
!= NULL
)
1113 *prev_frame
= previous_keyframe
;
1115 return current_keyframe
;
1119 KeyFrameCollection::OnSubPropertyChanged (DependencyProperty
*prop
, DependencyObject
*obj
, PropertyChangedEventArgs
*subobj_args
)
1121 if (strcmp (subobj_args
->GetProperty ()->GetName (), "KeyTime") == 0) {
1125 Collection::OnSubPropertyChanged (prop
, obj
, subobj_args
);
1128 ColorKeyFrameCollection::ColorKeyFrameCollection ()
1130 SetObjectType (Type::COLORKEYFRAME_COLLECTION
);
1133 ColorKeyFrameCollection::~ColorKeyFrameCollection ()
1137 DoubleKeyFrameCollection::DoubleKeyFrameCollection ()
1139 SetObjectType (Type::DOUBLEKEYFRAME_COLLECTION
);
1142 DoubleKeyFrameCollection::~DoubleKeyFrameCollection ()
1146 PointKeyFrameCollection::PointKeyFrameCollection ()
1148 SetObjectType (Type::POINTKEYFRAME_COLLECTION
);
1151 PointKeyFrameCollection::~PointKeyFrameCollection ()
1155 DoubleKeyFrame::DoubleKeyFrame ()
1157 SetObjectType (Type::DOUBLEKEYFRAME
);
1161 DoubleKeyFrame::~DoubleKeyFrame ()
1165 ColorKeyFrame::ColorKeyFrame ()
1167 SetObjectType (Type::COLORKEYFRAME
);
1168 static Color c
= Color (0, 0, 0, 1);
1172 ColorKeyFrame::~ColorKeyFrame ()
1176 PointKeyFrame::PointKeyFrame ()
1178 SetObjectType (Type::POINTKEYFRAME
);
1179 SetValue (Point (0,0));
1182 PointKeyFrame::~PointKeyFrame ()
1186 DiscreteDoubleKeyFrame::DiscreteDoubleKeyFrame ()
1188 SetObjectType(Type::DISCRETEDOUBLEKEYFRAME
);
1191 DiscreteDoubleKeyFrame::~DiscreteDoubleKeyFrame ()
1196 DiscreteDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1198 double *to
= GetValue();
1200 if (to
&& keyFrameProgress
== 1.0)
1201 return new Value(*to
);
1203 return new Value (baseValue
->AsDouble());
1206 DiscreteColorKeyFrame::DiscreteColorKeyFrame ()
1208 SetObjectType(Type::DISCRETECOLORKEYFRAME
);
1211 DiscreteColorKeyFrame::~DiscreteColorKeyFrame ()
1216 DiscreteColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1218 Color
*to
= GetValue();
1220 if (to
&& keyFrameProgress
== 1.0)
1221 return new Value(*to
);
1223 return new Value (*baseValue
->AsColor());
1226 DiscretePointKeyFrame::DiscretePointKeyFrame ()
1228 SetObjectType(Type::DISCRETEPOINTKEYFRAME
);
1231 DiscretePointKeyFrame::~DiscretePointKeyFrame ()
1236 DiscretePointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1238 Point
*to
= GetValue();
1240 if (to
&& keyFrameProgress
== 1.0)
1241 return new Value(*to
);
1243 return new Value (*baseValue
->AsPoint());
1247 LinearDoubleKeyFrame::LinearDoubleKeyFrame ()
1249 SetObjectType(Type::LINEARDOUBLEKEYFRAME
);
1252 LinearDoubleKeyFrame::~LinearDoubleKeyFrame ()
1257 LinearDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1259 double *to
= GetValue();
1262 return new Value (baseValue
->AsDouble());
1266 start
= baseValue
->AsDouble();
1269 return new Value (LERP (start
, end
, keyFrameProgress
));
1272 LinearColorKeyFrame::LinearColorKeyFrame ()
1274 SetObjectType(Type::LINEARCOLORKEYFRAME
);
1277 LinearColorKeyFrame::~LinearColorKeyFrame ()
1282 LinearColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1284 Color
*to
= GetValue();
1287 return new Value (*baseValue
->AsColor());
1291 start
= *baseValue
->AsColor();
1294 return new Value (LERP (start
, end
, keyFrameProgress
));
1297 LinearPointKeyFrame::LinearPointKeyFrame ()
1299 SetObjectType(Type::LINEARPOINTKEYFRAME
);
1302 LinearPointKeyFrame::~LinearPointKeyFrame ()
1307 LinearPointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1309 Point
*to
= GetValue();
1312 return new Value (*baseValue
->AsPoint());
1316 start
= *baseValue
->AsPoint();
1319 return new Value (LERP (start
, end
, keyFrameProgress
));
1322 SplineDoubleKeyFrame::SplineDoubleKeyFrame ()
1324 SetObjectType (Type::SPLINEDOUBLEKEYFRAME
);
1327 SplineDoubleKeyFrame::~SplineDoubleKeyFrame ()
1332 SplineDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1334 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1336 double *to
= GetValue();
1339 return new Value (baseValue
->AsDouble());
1340 else if (keyFrameProgress
>= 1.0)
1341 return new Value (*to
);
1345 start
= baseValue
->AsDouble();
1348 return new Value (LERP (start
, end
, splineProgress
));
1352 SplineColorKeyFrame::SplineColorKeyFrame ()
1354 SetObjectType (Type::SPLINECOLORKEYFRAME
);
1357 SplineColorKeyFrame::~SplineColorKeyFrame ()
1362 SplineColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1364 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1366 Color
*to
= GetValue();
1369 return new Value (*baseValue
->AsColor());
1370 else if (keyFrameProgress
>= 1.0)
1371 return new Value (*to
);
1375 start
= *baseValue
->AsColor();
1378 return new Value (LERP (start
, end
, splineProgress
));
1382 SplinePointKeyFrame::SplinePointKeyFrame ()
1384 SetObjectType (Type::SPLINEPOINTKEYFRAME
);
1387 SplinePointKeyFrame::~SplinePointKeyFrame ()
1392 SplinePointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1394 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1396 Point
*to
= GetValue();
1399 return new Value (*baseValue
->AsPoint());
1400 else if (keyFrameProgress
>= 1.0)
1401 return new Value (*to
);
1405 start
= *baseValue
->AsPoint();
1408 return new Value (LERP (start
, end
, splineProgress
));
1411 EasingColorKeyFrame::EasingColorKeyFrame ()
1413 SetObjectType (Type::EASINGCOLORKEYFRAME
);
1416 EasingColorKeyFrame::~EasingColorKeyFrame ()
1421 EasingColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1423 Color
*to
= GetValue();
1426 return new Value (*baseValue
->AsColor());
1427 else if (keyFrameProgress
>= 1.0)
1428 return new Value (*to
);
1432 start
= *baseValue
->AsColor();
1435 if (GetEasingFunction ())
1436 GetEasingFunction ()->Ease (keyFrameProgress
);
1438 return new Value (LERP (start
, end
, keyFrameProgress
));
1441 EasingDoubleKeyFrame::EasingDoubleKeyFrame ()
1443 SetObjectType (Type::EASINGDOUBLEKEYFRAME
);
1446 EasingDoubleKeyFrame::~EasingDoubleKeyFrame ()
1451 EasingDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1453 double *to
= GetValue();
1456 return new Value (baseValue
->AsDouble());
1457 else if (keyFrameProgress
>= 1.0)
1458 return new Value (*to
);
1462 start
= baseValue
->AsDouble();
1465 if (GetEasingFunction ())
1466 GetEasingFunction ()->Ease (keyFrameProgress
);
1468 return new Value (LERP (start
, end
, keyFrameProgress
));
1472 EasingPointKeyFrame::EasingPointKeyFrame ()
1474 SetObjectType (Type::EASINGPOINTKEYFRAME
);
1477 EasingPointKeyFrame::~EasingPointKeyFrame ()
1482 EasingPointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1484 Point
*to
= GetValue();
1487 return new Value (*baseValue
->AsPoint());
1488 else if (keyFrameProgress
>= 1.0)
1489 return new Value (*to
);
1493 start
= *baseValue
->AsPoint();
1496 if (GetEasingFunction ())
1497 GetEasingFunction ()->Ease (keyFrameProgress
);
1499 return new Value (LERP (start
, end
, keyFrameProgress
));
1502 /* implements the algorithm specified at the bottom of this page:
1503 http://msdn2.microsoft.com/en-us/library/ms742524.aspx
1506 KeyFrameAnimation_ResolveKeyFrames (Animation
*animation
, KeyFrameCollection
*col
)
1511 col
->resolved
= true;
1513 TimeSpan total_interpolation_time
;
1514 bool has_timespan_keyframe
= false;
1515 TimeSpan highest_keytime_timespan
= 0;
1520 for (i
= 0; i
< col
->GetCount (); i
++) {
1521 value
= col
->GetValueAt (i
);
1522 keyframe
= value
->AsKeyFrame ();
1523 keyframe
->resolved_keytime
= 0;
1524 keyframe
->resolved
= false;
1527 /* resolve TimeSpan keyframes (step 1 from url) */
1528 for (i
= 0; i
< col
->GetCount (); i
++) {
1529 value
= col
->GetValueAt (i
);
1530 keyframe
= value
->AsKeyFrame ();
1532 if (keyframe
->GetKeyTime()->HasTimeSpan()) {
1533 has_timespan_keyframe
= true;
1534 TimeSpan ts
= keyframe
->GetKeyTime()->GetTimeSpan ();
1535 if (ts
> highest_keytime_timespan
)
1536 highest_keytime_timespan
= ts
;
1538 keyframe
->resolved_keytime
= ts
;
1539 keyframe
->resolved
= true;
1543 /* calculate total animation interpolation time (step 2 from url) */
1544 Duration
*d
= animation
->GetDuration();
1545 if (d
->HasTimeSpan ()) {
1546 total_interpolation_time
= d
->GetTimeSpan ();
1548 else if (has_timespan_keyframe
) {
1549 total_interpolation_time
= highest_keytime_timespan
;
1552 total_interpolation_time
= TimeSpan_FromSeconds (1);
1555 /* use the total interpolation time to resolve percent keytime keyframes (step 3 from url) */
1556 for (i
= 0; i
< col
->GetCount (); i
++) {
1557 value
= col
->GetValueAt (i
);
1558 keyframe
= value
->AsKeyFrame ();
1560 if (keyframe
->GetKeyTime()->HasPercent()) {
1561 keyframe
->resolved_keytime
= (TimeSpan
)(total_interpolation_time
* keyframe
->GetKeyTime()->GetPercent ());
1562 keyframe
->resolved
= true;
1566 /* step 4 from url */
1569 /* if the last frame is KeyTime Uniform or Paced, resolve it
1570 to be equal to the total interpolation time */
1571 if (col
->GetCount () > 0) {
1572 value
= col
->GetValueAt (col
->GetCount () - 1);
1573 keyframe
= value
->AsKeyFrame ();
1575 kt
= keyframe
->GetKeyTime ();
1576 if (*kt
== KeyTime::Paced
|| *kt
== KeyTime::Uniform
) {
1577 keyframe
->resolved_keytime
= total_interpolation_time
;
1578 keyframe
->resolved
= true;
1582 /* if the first frame is KeyTime::Paced:
1583 ** 1. if there is only 1 frame, its KeyTime is the total interpolation time.
1584 ** 2. if there is more than 1 frame, its KeyTime is 0.
1586 ** note 1 is handled in the above block so we only have to
1589 if (col
->GetCount () > 0) {
1590 value
= col
->GetValueAt (0);
1591 keyframe
= value
->AsKeyFrame ();
1592 kt
= keyframe
->GetKeyTime ();
1594 if (!keyframe
->resolved
&& *kt
== KeyTime::Paced
) {
1595 keyframe
->resolved_keytime
= 0;
1596 keyframe
->resolved
= true;
1600 /* XXX resolve remaining KeyTime::Uniform frames (step 5 from url) */
1602 /* XXX resolve frames with unspecified keytimes (step 6 from url)
1604 -- is this possible? is the default keytime NULL? it
1605 seems to be Uniform? */
1607 /* XXX resolve remaining KeyTime::Paced frames (step 7 from url) */
1609 /* insert the nodes into the sorted list using a stable sort
1610 with resolved keytime as primary key, declaration order as
1611 secondary key (step 8 from url) */
1612 g_ptr_array_set_size (col
->sorted_list
, 0);
1614 for (i
= col
->GetCount (); i
> 0; i
--) {
1615 value
= col
->GetValueAt (i
- 1);
1616 keyframe
= value
->AsKeyFrame ();
1618 if (!keyframe
->resolved
)
1619 g_warning ("***** unresolved keyframe!");
1621 g_ptr_array_insert_sorted (col
->sorted_list
, KeyFrameComparer
, keyframe
);
1625 // Generic validator of KeyFrameCollection's. Collection vallidates
1626 // if all keyframes have valid time.
1628 generic_keyframe_validator (KeyFrameCollection
*col
)
1633 for (int i
= 0; i
< col
->GetCount (); i
++) {
1634 value
= col
->GetValueAt (i
);
1635 keyframe
= value
->AsKeyFrame ();
1636 if (keyframe
->GetKeyTime () == NULL
)
1644 DoubleAnimationUsingKeyFrames::DoubleAnimationUsingKeyFrames ()
1646 SetObjectType (Type::DOUBLEANIMATIONUSINGKEYFRAMES
);
1649 DoubleAnimationUsingKeyFrames::~DoubleAnimationUsingKeyFrames ()
1654 DoubleAnimationUsingKeyFrames::AddKeyFrame (DoubleKeyFrame
*frame
)
1656 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1658 key_frames
->Add (frame
);
1662 DoubleAnimationUsingKeyFrames::RemoveKeyFrame (DoubleKeyFrame
*frame
)
1664 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1666 key_frames
->Remove (frame
);
1670 DoubleAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1671 AnimationClock
* animationClock
)
1673 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1675 /* current segment info */
1676 TimeSpan current_time
= animationClock
->GetCurrentTime();
1677 DoubleKeyFrame
*current_keyframe
;
1678 DoubleKeyFrame
*previous_keyframe
;
1679 DoubleKeyFrame
** keyframep
= &previous_keyframe
;
1681 bool deleteBaseValue
;
1683 current_keyframe
= (DoubleKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1684 if (current_keyframe
== NULL
) {
1686 return NULL
; /* XXX */
1689 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1690 TimeSpan key_start_time
;
1692 if (previous_keyframe
== NULL
) {
1693 /* the first keyframe, start at the animation's base value */
1694 baseValue
= defaultOriginValue
;
1695 deleteBaseValue
= false;
1699 /* start at the previous keyframe's target value */
1700 baseValue
= new Value (*previous_keyframe
->GetValue ());
1701 deleteBaseValue
= true;
1702 key_start_time
= previous_keyframe
->resolved_keytime
;
1707 if (current_time
>= key_end_time
) {
1711 TimeSpan key_duration
= key_end_time
- key_start_time
;
1712 if (key_duration
== 0)
1715 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1718 /* get the current value out of that segment */
1719 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1720 if (deleteBaseValue
)
1726 DoubleAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
1728 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1730 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1732 guint len
= key_frames
->sorted_list
->len
;
1734 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1736 return Duration (0);
1740 DoubleAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1742 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1747 DoubleAnimationUsingKeyFrames::Validate ()
1749 return generic_keyframe_validator (GetKeyFrames ());
1752 ColorAnimationUsingKeyFrames::ColorAnimationUsingKeyFrames()
1754 SetObjectType (Type::COLORANIMATIONUSINGKEYFRAMES
);
1757 ColorAnimationUsingKeyFrames::~ColorAnimationUsingKeyFrames ()
1762 ColorAnimationUsingKeyFrames::AddKeyFrame (ColorKeyFrame
*frame
)
1764 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1766 key_frames
->Add (frame
);
1770 ColorAnimationUsingKeyFrames::RemoveKeyFrame (ColorKeyFrame
*frame
)
1772 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1774 key_frames
->Remove (frame
);
1778 ColorAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1779 AnimationClock
* animationClock
)
1781 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1782 /* current segment info */
1783 TimeSpan current_time
= animationClock
->GetCurrentTime();
1784 ColorKeyFrame
*current_keyframe
;
1785 ColorKeyFrame
*previous_keyframe
;
1786 ColorKeyFrame
** keyframep
= &previous_keyframe
;
1788 bool deleteBaseValue
;
1790 current_keyframe
= (ColorKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1791 if (current_keyframe
== NULL
)
1792 return NULL
; /* XXX */
1794 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1795 TimeSpan key_start_time
;
1797 if (previous_keyframe
== NULL
) {
1798 /* the first keyframe, start at the animation's base value */
1799 baseValue
= defaultOriginValue
;
1800 deleteBaseValue
= false;
1804 /* start at the previous keyframe's target value */
1805 baseValue
= new Value(*previous_keyframe
->GetValue ());
1806 deleteBaseValue
= true;
1807 key_start_time
= previous_keyframe
->resolved_keytime
;
1812 if (current_time
>= key_end_time
) {
1816 TimeSpan key_duration
= key_end_time
- key_start_time
;
1817 if (key_duration
== 0)
1820 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1823 /* get the current value out of that segment */
1824 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1825 if (deleteBaseValue
)
1831 ColorAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
1833 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1835 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1837 guint len
= key_frames
->sorted_list
->len
;
1839 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1841 return Duration (0);
1845 ColorAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1847 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1852 ColorAnimationUsingKeyFrames::Validate ()
1854 return generic_keyframe_validator (GetKeyFrames ());
1857 PointAnimationUsingKeyFrames::PointAnimationUsingKeyFrames()
1859 SetObjectType (Type::POINTANIMATIONUSINGKEYFRAMES
);
1862 PointAnimationUsingKeyFrames::~PointAnimationUsingKeyFrames ()
1867 PointAnimationUsingKeyFrames::AddKeyFrame (PointKeyFrame
*frame
)
1869 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1871 key_frames
->Add (frame
);
1875 PointAnimationUsingKeyFrames::RemoveKeyFrame (PointKeyFrame
*frame
)
1877 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1879 key_frames
->Remove (frame
);
1883 PointAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1884 AnimationClock
* animationClock
)
1886 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1887 /* current segment info */
1888 TimeSpan current_time
= animationClock
->GetCurrentTime();
1889 PointKeyFrame
*current_keyframe
;
1890 PointKeyFrame
*previous_keyframe
;
1891 PointKeyFrame
** keyframep
= &previous_keyframe
;
1893 bool deleteBaseValue
;
1895 current_keyframe
= (PointKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1896 if (current_keyframe
== NULL
)
1897 return NULL
; /* XXX */
1899 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1900 TimeSpan key_start_time
;
1902 if (previous_keyframe
== NULL
) {
1903 /* the first keyframe, start at the animation's base value */
1904 baseValue
= defaultOriginValue
;
1905 deleteBaseValue
= false;
1909 /* start at the previous keyframe's target value */
1910 baseValue
= new Value(*previous_keyframe
->GetValue ());
1911 deleteBaseValue
= true;
1912 key_start_time
= previous_keyframe
->resolved_keytime
;
1917 if (current_time
>= key_end_time
) {
1921 TimeSpan key_duration
= key_end_time
- key_start_time
;
1922 if (key_duration
== 0)
1925 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1928 /* get the current value out of that segment */
1929 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1930 if (deleteBaseValue
)
1936 PointAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
* clock
)
1938 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1940 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1942 guint len
= key_frames
->sorted_list
->len
;
1944 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1946 return Duration (0);
1950 PointAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1952 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1957 PointAnimationUsingKeyFrames::Validate ()
1959 return generic_keyframe_validator (GetKeyFrames ());
1962 ObjectKeyFrameCollection::ObjectKeyFrameCollection ()
1964 SetObjectType (Type::OBJECTKEYFRAME_COLLECTION
);
1967 ObjectKeyFrameCollection::~ObjectKeyFrameCollection ()
1971 ObjectKeyFrame::ObjectKeyFrame ()
1973 SetObjectType (Type::OBJECTKEYFRAME
);
1976 ObjectKeyFrame::~ObjectKeyFrame ()
1981 ObjectKeyFrame::GetValue ()
1983 return DependencyObject::GetValue (ValueProperty
);
1986 DiscreteObjectKeyFrame::DiscreteObjectKeyFrame ()
1988 SetObjectType (Type::DISCRETEOBJECTKEYFRAME
);
1991 DiscreteObjectKeyFrame::~DiscreteObjectKeyFrame ()
1996 DiscreteObjectKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1998 Value
*to
= GetConvertedValue ();
2000 if (to
&& keyFrameProgress
== 1.0)
2001 return new Value (*to
);
2003 return new Value (*baseValue
);
2006 ObjectAnimationUsingKeyFrames::ObjectAnimationUsingKeyFrames ()
2008 SetObjectType (Type::OBJECTANIMATIONUSINGKEYFRAMES
);
2011 ObjectAnimationUsingKeyFrames::~ObjectAnimationUsingKeyFrames ()
2016 ObjectAnimationUsingKeyFrames::AddKeyFrame (ObjectKeyFrame
*frame
)
2018 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2020 key_frames
->Add (frame
);
2024 ObjectAnimationUsingKeyFrames::RemoveKeyFrame (ObjectKeyFrame
*frame
)
2026 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2028 key_frames
->Remove (frame
);
2032 ObjectAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
2034 ObjectKeyFrameCollection
*frames
= (ObjectKeyFrameCollection
*) GetKeyFrames ();
2035 for (int i
= 0; i
< frames
->GetCount (); i
++) {
2036 ObjectKeyFrame
*frame
= frames
->GetValueAt (i
)->AsObjectKeyFrame ();
2038 Value
*value
= frame
->GetValue ();
2039 if (!value
|| value
->GetIsNull ()) {
2040 // If the value is null, don't convert
2041 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, NULL
);
2042 } else if (value
->GetKind () == property
->GetPropertyType ()) {
2043 // If the value is of the correct type already, don't convert
2044 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, value
);
2047 Application::GetCurrent ()->ConvertKeyframeValue (target
->GetType ()->GetKind (), property
, value
, &converted
);
2049 if (converted
.GetKind () == Type::INVALID
) {
2050 printf ("Couldn't convert value.\n");
2053 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, converted
);
2056 KeyFrameAnimation_ResolveKeyFrames (this, frames
);
2061 ObjectAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
2062 AnimationClock
* animationClock
)
2064 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2066 /* current segment info */
2067 TimeSpan current_time
= animationClock
->GetCurrentTime();
2068 ObjectKeyFrame
*current_keyframe
;
2069 ObjectKeyFrame
*previous_keyframe
;
2070 ObjectKeyFrame
** keyframep
= &previous_keyframe
;
2072 bool deleteBaseValue
;
2074 current_keyframe
= (ObjectKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
2075 if (current_keyframe
== NULL
)
2076 return NULL
; /* XXX */
2078 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
2079 TimeSpan key_start_time
;
2081 if (previous_keyframe
== NULL
) {
2082 /* the first keyframe, start at the animation's base value */
2083 baseValue
= defaultOriginValue
;
2084 deleteBaseValue
= false;
2087 /* start at the previous keyframe's target value */
2088 baseValue
= new Value (*previous_keyframe
->GetConvertedValue ());
2089 deleteBaseValue
= true;
2090 key_start_time
= previous_keyframe
->resolved_keytime
;
2095 if (current_time
>= key_end_time
) {
2098 TimeSpan key_duration
= key_end_time
- key_start_time
;
2099 if (key_duration
== 0)
2102 progress
= (double)(current_time
- key_start_time
) / key_duration
;
2105 /* get the current value out of that segment */
2106 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
2108 if (deleteBaseValue
)
2115 ObjectAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
2117 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2119 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
2121 guint len
= key_frames
->sorted_list
->len
;
2123 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
2125 return Duration (0);
2129 ObjectAnimationUsingKeyFrames::Validate ()
2131 // Interesting question -- should we check for null here?
2132 return generic_keyframe_validator (GetKeyFrames ());