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
)
64 : baseValue(NULL
), stopValue(NULL
), disabled(false)
67 this->timeline
= timeline
;
68 this->targetobj
= targetobj
;
69 this->targetprop
= targetprop
;
71 AttachUpdateHandler ();
72 AttachTargetHandler ();
74 AnimationStorage
*prev_storage
= targetobj
->AttachAnimationStorage (targetprop
, this);
76 baseValue
= targetobj
->GetValue (targetprop
);
78 baseValue
= new Value(*baseValue
);
80 baseValue
= new Value (targetprop
->GetPropertyType ());
83 Value
*v
= prev_storage
->GetResetValue ();
84 stopValue
= new Value (*v
);
89 AnimationStorage::IsCurrentStorage ()
91 if (targetobj
== NULL
|| targetprop
== NULL
)
94 if (targetobj
->GetAnimationStorageFor (targetprop
) == this)
102 AnimationStorage::SwitchTarget (DependencyObject
*target
)
104 bool wasDisabled
= disabled
;
109 AttachTargetHandler ();
110 AttachUpdateHandler ();
112 disabled
= wasDisabled
;
116 AnimationStorage::Enable ()
121 AttachTargetHandler ();
122 AttachUpdateHandler ();
124 UpdatePropertyValue ();
128 AnimationStorage::Disable ()
130 DetachUpdateHandler ();
131 DetachTargetHandler ();
136 AnimationStorage::Stop ()
138 ResetPropertyValue ();
142 AnimationStorage::GetResetValue ()
151 AnimationStorage::SetStopValue (Value
*value
)
157 stopValue
= new Value (*value
);
161 // End of public methods
165 AnimationStorage::target_object_destroyed (EventObject
*, EventArgs
*, gpointer closure
)
167 ((AnimationStorage
*)closure
)->TargetObjectDestroyed ();
171 AnimationStorage::TargetObjectDestroyed ()
173 DetachUpdateHandler ();
179 AnimationStorage::update_property_value (EventObject
*, EventArgs
*, gpointer closure
)
181 ((AnimationStorage
*)closure
)->UpdatePropertyValue ();
185 AnimationStorage::UpdatePropertyValue ()
187 if (!targetobj
) return;
189 Value
*current_value
= clock
->GetCurrentValue (baseValue
, stopValue
? stopValue
: baseValue
);
190 if (current_value
!= NULL
&& timeline
->GetTimelineStatus () == Timeline::TIMELINE_STATUS_OK
) {
191 Applier
*applier
= clock
->GetTimeManager ()->GetApplier ();
192 applier
->AddPropertyChange (targetobj
, targetprop
, new Value (*current_value
), APPLIER_PRECEDENCE_ANIMATION
);
195 delete current_value
;
199 AnimationStorage::ResetPropertyValue ()
201 if (disabled
) return;
203 if (targetobj
== NULL
|| targetprop
== NULL
)
206 if (timeline
->GetTimelineStatus () != Timeline::TIMELINE_STATUS_OK
)
209 Applier
*applier
= clock
->GetTimeManager ()->GetApplier ();
212 applier
->AddPropertyChange (targetobj
, targetprop
,
213 new Value (*GetResetValue ()),
214 APPLIER_PRECEDENCE_ANIMATION_RESET
);
218 AnimationStorage::DetachFromProperty ()
220 if (targetobj
== NULL
|| targetprop
== NULL
)
222 targetobj
->DetachAnimationStorage (targetprop
, this);
226 AnimationStorage::AttachUpdateHandler ()
229 clock
->AddHandler (Clock::CurrentTimeInvalidatedEvent
, update_property_value
, this);
234 AnimationStorage::DetachUpdateHandler ()
236 if (disabled
) return;
238 clock
->RemoveHandler (Clock::CurrentTimeInvalidatedEvent
, update_property_value
, this);
242 AnimationStorage::AttachTargetHandler ()
244 if (!targetobj
) return;
245 targetobj
->AddHandler (EventObject::DestroyedEvent
, target_object_destroyed
, this);
249 AnimationStorage::DetachTargetHandler ()
251 if (disabled
) return;
252 if (!targetobj
) return;
253 targetobj
->RemoveHandler (EventObject::DestroyedEvent
, target_object_destroyed
, this);
256 AnimationStorage::~AnimationStorage ()
258 DetachTargetHandler ();
259 DetachUpdateHandler ();
260 DetachFromProperty ();
263 clock
->DetachStorage ();
276 AnimationClock::AnimationClock (Animation
*timeline
)
279 SetObjectType (Type::ANIMATIONCLOCK
);
281 this->timeline
= timeline
;
286 AnimationClock::HookupStorage (DependencyObject
*targetobj
, DependencyProperty
*targetprop
)
288 /* Before hooking up make sure that the values our animation generates
289 (doubles, colors, points...) match the values that the property is
290 ready to receive. If not, print an informative message. */
291 Type
*property_type
= Type::Find (GetDeployment (), targetprop
->GetPropertyType());
292 if (timeline
->GetValueKind () != Type::INVALID
&& !property_type
->IsAssignableFrom (timeline
->GetValueKind ())) {
293 Type
*timeline_type
= Type::Find (GetDeployment (), timeline
->GetValueKind ());
295 const char *timeline_type_name
= (timeline_type
!= NULL
) ? timeline_type
->GetName () : "Invalid";
296 const char *property_type_name
= (property_type
!= NULL
) ? property_type
->GetName () : "Invalid";
297 g_warning ("%s.%s property value type is '%s' but animation type is '%s'.",
298 targetobj
->GetTypeName (), targetprop
->GetName(),
299 property_type_name
, timeline_type_name
);
304 char *name
= g_strdup_printf ("AnimationClock for %s, targetobj = %p/%s, targetprop = %s", GetTypeName(),
306 targetobj
->GetName(),
307 targetprop
->GetName());
314 storage
= new AnimationStorage (this, timeline
, targetobj
, targetprop
);
319 AnimationClock::GetCurrentValue (Value
* defaultOriginValue
, Value
* defaultDestinationValue
)
321 return timeline
->GetCurrentValue (defaultOriginValue
, defaultDestinationValue
, this);
325 AnimationClock::Stop ()
337 AnimationClock::Begin (TimeSpan parentTime
)
339 Clock::Begin (parentTime
);
342 AnimationClock::~AnimationClock ()
351 AnimationClock::DetachStorage ()
357 Animation::AllocateClock()
359 clock
= new AnimationClock (this);
361 AttachCompletedHandler ();
367 Animation::GetTargetValue (Value
* defaultOriginValue
)
373 Animation::GetCurrentValue (Value
* defaultOriginValue
, Value
* defaultDestinationValue
,
374 AnimationClock
* animationClock
)
381 Animation::GetNaturalDurationCore (Clock
* clock
)
383 return Duration::FromSeconds (1);
391 Storyboard::Storyboard ()
393 SetObjectType (Type::STORYBOARD
);
396 Storyboard::~Storyboard ()
399 StopWithError (/* ignore any error */ NULL
);
404 Storyboard::GetCurrentTime ()
406 return GetClock() ? GetClock()->GetCurrentTime () : 0;
410 Storyboard::GetCurrentState ()
412 return GetClock() ? GetClock()->GetClockState () : Clock::Stopped
;
416 Storyboard::GetTargetDependencyProperty ()
418 PropertyPath
*path
= GetTargetProperty (this);
419 return path
? path
->property
: NULL
;
423 Storyboard::HookupAnimationsRecurse (Clock
*clock
, DependencyObject
*targetObject
, PropertyPath
*targetPropertyPath
, GHashTable
*promoted_values
, MoonError
*error
)
425 DependencyObject
*localTargetObject
= NULL
;
426 PropertyPath
*localTargetPropertyPath
= NULL
;
428 Timeline
*timeline
= clock
->GetTimeline ();
430 /* get the target object at this level */
431 if (timeline
->HasManualTarget ())
432 localTargetObject
= timeline
->GetManualTarget ();
434 const char *targetName
= Storyboard::GetTargetName (timeline
);
436 localTargetObject
= FindName (targetName
);
439 /* get the target property path at this level */
440 localTargetPropertyPath
= Storyboard::GetTargetProperty (timeline
);
443 /* override the object and property passed from our parent here */
444 if (localTargetObject
!= NULL
)
445 targetObject
= localTargetObject
;
447 if (localTargetPropertyPath
!= NULL
)
448 targetPropertyPath
= localTargetPropertyPath
;
451 if (clock
->Is (Type::CLOCKGROUP
)) {
452 for (GList
*l
= ((ClockGroup
*)clock
)->child_clocks
; l
; l
= l
->next
) {
453 if (!HookupAnimationsRecurse ((Clock
*)l
->data
,
462 DependencyProperty
*prop
= NULL
;
463 DependencyObject
*realTargetObject
;
465 if (!targetPropertyPath
) {
466 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Target Property has not been specified.");
467 g_warning ("No target property!");
472 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "No Target or TargetName has been specified");
476 realTargetObject
= targetObject
;
478 prop
= resolve_property_path (&realTargetObject
, targetPropertyPath
, promoted_values
);
480 if (!prop
|| !realTargetObject
) {
481 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "TargetProperty could not be resolved");
482 g_warning ("No property path %s on object of type type %s!",
483 targetPropertyPath
->path
, targetObject
->GetTypeName());
487 if (clock
->Is(Type::ANIMATIONCLOCK
)) {
488 Animation
*animation
= (Animation
*)timeline
;
490 if (!animation
->Resolve (realTargetObject
, prop
)) {
491 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Storyboard value could not be converted to the correct type");
495 if (!((AnimationClock
*)clock
)->HookupStorage (realTargetObject
, prop
))
504 Storyboard::BeginWithError (MoonError
*error
)
506 if (GetHadParent ()) {
507 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Begin a Storyboard which is not the root Storyboard.");
511 /* destroy the clock hierarchy and recreate it to restart.
512 easier than making Begin work again with the existing clock
515 DetachCompletedHandler ();
519 if (Validate () == false)
522 // This creates the clock tree for the hierarchy. if a
523 // Timeline A is a child of TimelineGroup B, then Clock cA
524 // will be a child of ClockGroup cB.
526 char *name
= g_strdup_printf ("Storyboard, named '%s'", GetName());
527 clock
->SetValue (DependencyObject::NameProperty
, name
);
531 // walk the clock tree hooking up the correct properties and
532 // creating AnimationStorage's for AnimationClocks.
533 GHashTable
*promoted_values
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
534 if (!HookupAnimationsRecurse (clock
, NULL
, NULL
, promoted_values
, error
)) {
535 g_hash_table_destroy (promoted_values
);
538 g_hash_table_destroy (promoted_values
);
540 Deployment::GetCurrent()->GetSurface()->GetTimeManager()->AddClock (clock
);
542 if (GetBeginTime() == 0)
543 clock
->BeginOnTick ();
549 Storyboard::PauseWithError (MoonError
*error
)
551 if (GetHadParent ()) {
552 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Pause a Storyboard which is not the root Storyboard.");
560 Storyboard::ResumeWithError (MoonError
*error
)
562 if (GetHadParent ()) {
563 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Resume a Storyboard which is not the root Storyboard.");
571 Storyboard::SeekWithError (TimeSpan timespan
, MoonError
*error
)
573 if (GetHadParent ()) {
574 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Seek a Storyboard which is not the root Storyboard.");
578 clock
->Seek (timespan
);
582 Storyboard::SeekAlignedToLastTickWithError (TimeSpan timespan
, MoonError
*error
)
584 if (GetHadParent ()) {
585 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Seek a Storyboard which is not the root Storyboard.");
589 clock
->SeekAlignedToLastTick (timespan
);
593 Storyboard::SkipToFillWithError (MoonError
*error
)
595 if (GetHadParent ()) {
596 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot SkipToFill a Storyboard which is not the root Storyboard.");
600 clock
->SkipToFill ();
605 Storyboard::StopWithError (MoonError
*error
)
607 if (GetHadParent ()) {
608 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Cannot Stop a Storyboard which is not the root Storyboard.");
612 DetachCompletedHandler ();
618 BeginStoryboard::BeginStoryboard ()
620 SetObjectType (Type::BEGINSTORYBOARD
);
623 BeginStoryboard::~BeginStoryboard ()
628 BeginStoryboard::Fire ()
630 Storyboard
*sb
= GetStoryboard ();
632 // FIXME I'd imagine we should be bubbling this error/exception upward, no?
633 sb
->BeginWithError (NULL
);
638 DoubleAnimation::DoubleAnimation ()
640 SetObjectType (Type::DOUBLEANIMATION
);
642 doubleToCached
= NULL
;
643 doubleFromCached
= NULL
;
644 doubleByCached
= NULL
;
648 void DoubleAnimation::EnsureCache (void)
650 doubleFromCached
= GetFrom ();
651 doubleToCached
= GetTo ();
652 doubleByCached
= GetBy ();
657 DoubleAnimation::GetTargetValue (Value
*defaultOriginValue
)
660 this->EnsureCache ();
664 if (doubleFromCached
)
665 start
= *doubleFromCached
;
666 else if (defaultOriginValue
->Is(GetDeployment (), Type::DOUBLE
))
667 start
= defaultOriginValue
->AsDouble();
672 return new Value (*doubleToCached
);
673 else if (doubleByCached
)
674 return new Value (start
+ *doubleByCached
);
676 return new Value (start
);
680 DoubleAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
681 AnimationClock
* animationClock
)
684 this->EnsureCache ();
688 if (doubleFromCached
)
689 start
= *doubleFromCached
;
690 else if (defaultOriginValue
->Is(GetDeployment (), Type::DOUBLE
))
691 start
= defaultOriginValue
->AsDouble();
697 if (doubleToCached
) {
698 end
= *doubleToCached
;
700 else if (doubleByCached
) {
701 end
= start
+ *doubleByCached
;
703 else if (defaultDestinationValue
->Is(GetDeployment (), Type::DOUBLE
)) {
704 end
= defaultDestinationValue
->AsDouble();
709 double progress
= animationClock
->GetCurrentProgress ();
711 if (GetEasingFunction ())
712 progress
= GetEasingFunction()->Ease (progress
);
714 return new Value (LERP (start
, end
, progress
));
718 DoubleAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
720 if (args
->GetProperty ()->GetOwnerType() != Type::DOUBLEANIMATION
) {
721 DependencyObject::OnPropertyChanged (args
, error
);
725 // Get rid of the cache
727 doubleToCached
= NULL
;
728 doubleFromCached
= NULL
;
729 doubleByCached
= NULL
;
731 NotifyListenersOfPropertyChange (args
, error
);
734 ColorAnimation::ColorAnimation ()
736 SetObjectType (Type::COLORANIMATION
);
738 colorToCached
= NULL
;
739 colorFromCached
= NULL
;
740 colorByCached
= NULL
;
744 void ColorAnimation::EnsureCache (void)
746 colorFromCached
= GetFrom ();
747 colorToCached
= GetTo ();
748 colorByCached
= GetBy ();
753 ColorAnimation::GetTargetValue (Value
*defaultOriginValue
)
756 this->EnsureCache ();
761 start
= *colorFromCached
;
762 else if (defaultOriginValue
->Is(GetDeployment (), Type::COLOR
))
763 start
= *defaultOriginValue
->AsColor();
766 return new Value (*colorToCached
);
767 else if (colorByCached
)
768 return new Value (start
+ *colorByCached
);
770 return new Value (start
);
774 ColorAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
775 AnimationClock
* animationClock
)
778 this->EnsureCache ();
783 start
= *colorFromCached
;
784 else if (defaultOriginValue
->Is(GetDeployment (), Type::COLOR
))
785 start
= *defaultOriginValue
->AsColor();
790 end
= *colorToCached
;
792 else if (colorByCached
) {
793 end
= start
+ *colorByCached
;
795 else if (defaultDestinationValue
->Is(GetDeployment (), Type::COLOR
)) {
796 end
= *defaultDestinationValue
->AsColor();
802 double progress
= animationClock
->GetCurrentProgress ();
804 if (GetEasingFunction ())
805 progress
= GetEasingFunction()->Ease (progress
);
807 return new Value (LERP (start
, end
, progress
));
811 ColorAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
813 if (args
->GetProperty ()->GetOwnerType() != Type::COLORANIMATION
) {
814 DependencyObject::OnPropertyChanged (args
, error
);
818 // Get rid of the cache
819 colorToCached
= NULL
;
820 colorFromCached
= NULL
;
821 colorByCached
= NULL
;
824 NotifyListenersOfPropertyChange (args
, error
);
827 PointAnimation::PointAnimation ()
829 SetObjectType (Type::POINTANIMATION
);
831 pointToCached
= NULL
;
832 pointFromCached
= NULL
;
833 pointByCached
= NULL
;
837 PointAnimation::~PointAnimation ()
841 void PointAnimation::EnsureCache (void)
843 pointFromCached
= GetFrom ();
844 pointToCached
= GetTo ();
845 pointByCached
= GetBy ();
850 PointAnimation::GetTargetValue (Value
*defaultOriginValue
)
853 this->EnsureCache ();
858 start
= *pointFromCached
;
859 else if (defaultOriginValue
->Is(GetDeployment (), Type::POINT
))
860 start
= *defaultOriginValue
->AsPoint();
863 return new Value (*pointToCached
);
864 else if (pointByCached
)
865 return new Value (start
+ *pointByCached
);
867 return new Value (start
);
871 PointAnimation::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
872 AnimationClock
* animationClock
)
875 this->EnsureCache ();
880 start
= *pointFromCached
;
881 else if (defaultOriginValue
->Is(GetDeployment (), Type::POINT
))
882 start
= *defaultOriginValue
->AsPoint();
887 end
= *pointToCached
;
889 else if (pointByCached
) {
890 end
= start
+ *pointByCached
;
892 else if (defaultDestinationValue
->Is(GetDeployment (), Type::POINT
)) {
893 end
= *defaultDestinationValue
->AsPoint();
899 double progress
= animationClock
->GetCurrentProgress ();
901 if (GetEasingFunction ())
902 progress
= GetEasingFunction()->Ease (progress
);
904 return new Value (LERP (start
, end
, progress
));
908 PointAnimation::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
910 if (args
->GetProperty ()->GetOwnerType() != Type::POINTANIMATION
) {
911 DependencyObject::OnPropertyChanged (args
, error
);
915 // Get rid of the cache
916 pointToCached
= NULL
;
917 pointFromCached
= NULL
;
918 pointByCached
= NULL
;
921 NotifyListenersOfPropertyChange (args
, error
);
924 KeySpline::KeySpline ()
926 SetObjectType (Type::KEYSPLINE
);
928 quadraticsArray
= NULL
;
931 KeySpline::KeySpline (Point controlPoint1
, Point controlPoint2
)
933 SetObjectType (Type::KEYSPLINE
);
935 quadraticsArray
= NULL
;
936 SetControlPoint1 (&controlPoint1
);
937 SetControlPoint2 (&controlPoint2
);
940 KeySpline::KeySpline (double x1
, double y1
,
941 double x2
, double y2
)
943 SetObjectType (Type::KEYSPLINE
);
945 quadraticsArray
= NULL
;
947 Point p1
= Point (x1
, y1
);
948 Point p2
= Point (x2
, y2
);
950 SetControlPoint1 (&p1
);
951 SetControlPoint2 (&p2
);
954 KeySpline::~KeySpline ()
956 g_free (quadraticsArray
);
957 quadraticsArray
= NULL
;
962 KeySpline::RegenerateQuadratics ()
964 quadraticsArray
= (moon_quadratic
*) g_malloc (sizeof (moon_quadratic
) * KEYSPLINE_TOTAL_COUNT
);
966 Point c1
= *GetControlPoint1 ();
967 Point c2
= *GetControlPoint2 ();
970 src
.c0
.x
= 0; src
.c0
.y
= 0;
971 src
.c1
.x
= c1
.x
; src
.c1
.y
= c1
.y
;
972 src
.c2
.x
= c2
.x
; src
.c2
.y
= c2
.y
;
973 src
.c3
.x
= 1.0; src
.c3
.y
= 1.0;
975 moon_cubic carr
[KEYSPLINE_TOTAL_COUNT
];
977 moon_subdivide_cubic_at_level (carr
, KEYSPLINE_PRECISION_LEVEL
, &src
);
978 moon_convert_cubics_to_quadratics (quadraticsArray
, carr
, KEYSPLINE_TOTAL_COUNT
);
982 KeySpline::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
984 if (args
->GetProperty ()->GetOwnerType() != Type::KEYSPLINE
) {
985 DependencyObject::OnPropertyChanged (args
, error
);
989 g_free (quadraticsArray
);
990 quadraticsArray
= NULL
;
992 NotifyListenersOfPropertyChange (args
, error
);
996 KeySpline::GetSplineProgress (double linearProgress
)
998 if (linearProgress
>= 1.0)
1001 if (linearProgress
<= 0.0)
1004 if (quadraticsArray
== NULL
)
1005 RegenerateQuadratics ();
1007 return moon_quadratic_array_y_for_x (quadraticsArray
, linearProgress
, KEYSPLINE_TOTAL_COUNT
);
1010 KeyFrame::KeyFrame ()
1012 SetObjectType (Type::KEYFRAME
);
1015 KeyFrame::~KeyFrame ()
1020 KeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1022 g_warning ("KeyFrame::InterpolateValue has been called. The derived class %s should have overridden it.",
1028 KeyFrameComparer (gconstpointer kf1
, gconstpointer kf2
)
1030 // Assumes timespan keytimes only
1031 TimeSpan ts1
= (*(KeyFrame
**) kf1
)->resolved_keytime
;
1032 TimeSpan ts2
= (*(KeyFrame
**) kf2
)->resolved_keytime
;
1033 TimeSpan tsdiff
= ts1
- ts2
;
1037 else if (tsdiff
< 0)
1043 KeyFrameCollection::KeyFrameCollection ()
1045 SetObjectType (Type::KEYFRAME_COLLECTION
);
1047 sorted_list
= g_ptr_array_new ();
1051 KeyFrameCollection::~KeyFrameCollection ()
1053 g_ptr_array_free (sorted_list
, true);
1057 KeyFrameCollection::AddedToCollection (Value
*value
, MoonError
*error
)
1059 if (!DependencyObjectCollection::AddedToCollection (value
, error
))
1068 KeyFrameCollection::RemovedFromCollection (Value
*value
)
1070 DependencyObjectCollection::RemovedFromCollection (value
);
1076 KeyFrameCollection::Clear ()
1079 g_ptr_array_set_size (sorted_list
, 0);
1080 return DependencyObjectCollection::Clear ();
1084 KeyFrameCollection::GetKeyFrameForTime (TimeSpan t
, KeyFrame
**prev_frame
)
1086 KeyFrame
*current_keyframe
= NULL
;
1087 KeyFrame
*previous_keyframe
= NULL
;
1090 if (sorted_list
->len
== 0) {
1097 /* Crawl forward to figure out what segment to use (this assumes the list is sorted) */
1098 for (i
= 0; i
< (int) sorted_list
->len
; i
++) {
1099 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1100 TimeSpan key_end_time
= keyframe
->resolved_keytime
;
1102 if (key_end_time
>= t
|| (i
+ 1) >= (int) sorted_list
->len
)
1106 /* Crawl backward to find first non-null frame */
1107 for (; i
>= 0; i
--) {
1108 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1109 DependencyProperty
*value_prop
= keyframe
->GetDependencyProperty ("Value");
1110 if (keyframe
->GetValue (value_prop
) != NULL
) {
1111 current_keyframe
= keyframe
;
1116 /* Crawl backward some more to find first non-null prev frame */
1117 for (i
--; i
>= 0; i
--) {
1118 KeyFrame
*keyframe
= (KeyFrame
*) sorted_list
->pdata
[i
];
1119 DependencyProperty
*value_prop
= keyframe
->GetDependencyProperty ("Value");
1120 if (keyframe
->GetValue (value_prop
) != NULL
) {
1121 previous_keyframe
= keyframe
;
1126 /* Assign prev frame */
1127 if (prev_frame
!= NULL
)
1128 *prev_frame
= previous_keyframe
;
1130 return current_keyframe
;
1134 KeyFrameCollection::OnSubPropertyChanged (DependencyProperty
*prop
, DependencyObject
*obj
, PropertyChangedEventArgs
*subobj_args
)
1136 if (strcmp (subobj_args
->GetProperty ()->GetName (), "KeyTime") == 0) {
1140 Collection::OnSubPropertyChanged (prop
, obj
, subobj_args
);
1143 ColorKeyFrameCollection::ColorKeyFrameCollection ()
1145 SetObjectType (Type::COLORKEYFRAME_COLLECTION
);
1148 ColorKeyFrameCollection::~ColorKeyFrameCollection ()
1152 DoubleKeyFrameCollection::DoubleKeyFrameCollection ()
1154 SetObjectType (Type::DOUBLEKEYFRAME_COLLECTION
);
1157 DoubleKeyFrameCollection::~DoubleKeyFrameCollection ()
1161 PointKeyFrameCollection::PointKeyFrameCollection ()
1163 SetObjectType (Type::POINTKEYFRAME_COLLECTION
);
1166 PointKeyFrameCollection::~PointKeyFrameCollection ()
1170 DoubleKeyFrame::DoubleKeyFrame ()
1172 SetObjectType (Type::DOUBLEKEYFRAME
);
1176 DoubleKeyFrame::~DoubleKeyFrame ()
1180 ColorKeyFrame::ColorKeyFrame ()
1182 SetObjectType (Type::COLORKEYFRAME
);
1183 static Color c
= Color (0, 0, 0, 1);
1187 ColorKeyFrame::~ColorKeyFrame ()
1191 PointKeyFrame::PointKeyFrame ()
1193 SetObjectType (Type::POINTKEYFRAME
);
1194 SetValue (Point (0,0));
1197 PointKeyFrame::~PointKeyFrame ()
1201 DiscreteDoubleKeyFrame::DiscreteDoubleKeyFrame ()
1203 SetObjectType(Type::DISCRETEDOUBLEKEYFRAME
);
1206 DiscreteDoubleKeyFrame::~DiscreteDoubleKeyFrame ()
1211 DiscreteDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1213 double *to
= GetValue();
1215 if (to
&& keyFrameProgress
== 1.0)
1216 return new Value(*to
);
1218 return new Value (baseValue
->AsDouble());
1221 DiscreteColorKeyFrame::DiscreteColorKeyFrame ()
1223 SetObjectType(Type::DISCRETECOLORKEYFRAME
);
1226 DiscreteColorKeyFrame::~DiscreteColorKeyFrame ()
1231 DiscreteColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1233 Color
*to
= GetValue();
1235 if (to
&& keyFrameProgress
== 1.0)
1236 return new Value(*to
);
1238 return new Value (*baseValue
->AsColor());
1241 DiscretePointKeyFrame::DiscretePointKeyFrame ()
1243 SetObjectType(Type::DISCRETEPOINTKEYFRAME
);
1246 DiscretePointKeyFrame::~DiscretePointKeyFrame ()
1251 DiscretePointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1253 Point
*to
= GetValue();
1255 if (to
&& keyFrameProgress
== 1.0)
1256 return new Value(*to
);
1258 return new Value (*baseValue
->AsPoint());
1262 LinearDoubleKeyFrame::LinearDoubleKeyFrame ()
1264 SetObjectType(Type::LINEARDOUBLEKEYFRAME
);
1267 LinearDoubleKeyFrame::~LinearDoubleKeyFrame ()
1272 LinearDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1274 double *to
= GetValue();
1277 return new Value (baseValue
->AsDouble());
1281 start
= baseValue
->AsDouble();
1284 return new Value (LERP (start
, end
, keyFrameProgress
));
1287 LinearColorKeyFrame::LinearColorKeyFrame ()
1289 SetObjectType(Type::LINEARCOLORKEYFRAME
);
1292 LinearColorKeyFrame::~LinearColorKeyFrame ()
1297 LinearColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1299 Color
*to
= GetValue();
1302 return new Value (*baseValue
->AsColor());
1306 start
= *baseValue
->AsColor();
1309 return new Value (LERP (start
, end
, keyFrameProgress
));
1312 LinearPointKeyFrame::LinearPointKeyFrame ()
1314 SetObjectType(Type::LINEARPOINTKEYFRAME
);
1317 LinearPointKeyFrame::~LinearPointKeyFrame ()
1322 LinearPointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1324 Point
*to
= GetValue();
1327 return new Value (*baseValue
->AsPoint());
1331 start
= *baseValue
->AsPoint();
1334 return new Value (LERP (start
, end
, keyFrameProgress
));
1337 SplineDoubleKeyFrame::SplineDoubleKeyFrame ()
1339 SetObjectType (Type::SPLINEDOUBLEKEYFRAME
);
1342 SplineDoubleKeyFrame::~SplineDoubleKeyFrame ()
1347 SplineDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1349 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1351 double *to
= GetValue();
1354 return new Value (baseValue
->AsDouble());
1355 else if (keyFrameProgress
>= 1.0)
1356 return new Value (*to
);
1360 start
= baseValue
->AsDouble();
1363 return new Value (LERP (start
, end
, splineProgress
));
1367 SplineColorKeyFrame::SplineColorKeyFrame ()
1369 SetObjectType (Type::SPLINECOLORKEYFRAME
);
1372 SplineColorKeyFrame::~SplineColorKeyFrame ()
1377 SplineColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1379 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1381 Color
*to
= GetValue();
1384 return new Value (*baseValue
->AsColor());
1385 else if (keyFrameProgress
>= 1.0)
1386 return new Value (*to
);
1390 start
= *baseValue
->AsColor();
1393 return new Value (LERP (start
, end
, splineProgress
));
1397 SplinePointKeyFrame::SplinePointKeyFrame ()
1399 SetObjectType (Type::SPLINEPOINTKEYFRAME
);
1402 SplinePointKeyFrame::~SplinePointKeyFrame ()
1407 SplinePointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1409 double splineProgress
= GetKeySpline ()->GetSplineProgress (keyFrameProgress
);
1411 Point
*to
= GetValue();
1414 return new Value (*baseValue
->AsPoint());
1415 else if (keyFrameProgress
>= 1.0)
1416 return new Value (*to
);
1420 start
= *baseValue
->AsPoint();
1423 return new Value (LERP (start
, end
, splineProgress
));
1426 EasingColorKeyFrame::EasingColorKeyFrame ()
1428 SetObjectType (Type::EASINGCOLORKEYFRAME
);
1431 EasingColorKeyFrame::~EasingColorKeyFrame ()
1436 EasingColorKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1438 Color
*to
= GetValue();
1441 return new Value (*baseValue
->AsColor());
1442 else if (keyFrameProgress
>= 1.0)
1443 return new Value (*to
);
1447 start
= *baseValue
->AsColor();
1450 if (GetEasingFunction ())
1451 GetEasingFunction ()->Ease (keyFrameProgress
);
1453 return new Value (LERP (start
, end
, keyFrameProgress
));
1456 EasingDoubleKeyFrame::EasingDoubleKeyFrame ()
1458 SetObjectType (Type::EASINGDOUBLEKEYFRAME
);
1461 EasingDoubleKeyFrame::~EasingDoubleKeyFrame ()
1466 EasingDoubleKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1468 double *to
= GetValue();
1471 return new Value (baseValue
->AsDouble());
1472 else if (keyFrameProgress
>= 1.0)
1473 return new Value (*to
);
1477 start
= baseValue
->AsDouble();
1480 if (GetEasingFunction ())
1481 GetEasingFunction ()->Ease (keyFrameProgress
);
1483 return new Value (LERP (start
, end
, keyFrameProgress
));
1487 EasingPointKeyFrame::EasingPointKeyFrame ()
1489 SetObjectType (Type::EASINGPOINTKEYFRAME
);
1492 EasingPointKeyFrame::~EasingPointKeyFrame ()
1497 EasingPointKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
1499 Point
*to
= GetValue();
1502 return new Value (*baseValue
->AsPoint());
1503 else if (keyFrameProgress
>= 1.0)
1504 return new Value (*to
);
1508 start
= *baseValue
->AsPoint();
1511 if (GetEasingFunction ())
1512 GetEasingFunction ()->Ease (keyFrameProgress
);
1514 return new Value (LERP (start
, end
, keyFrameProgress
));
1517 /* implements the algorithm specified at the bottom of this page:
1518 http://msdn2.microsoft.com/en-us/library/ms742524.aspx
1521 KeyFrameAnimation_ResolveKeyFrames (Animation
*animation
, KeyFrameCollection
*col
)
1526 col
->resolved
= true;
1528 TimeSpan total_interpolation_time
;
1529 bool has_timespan_keyframe
= false;
1530 TimeSpan highest_keytime_timespan
= 0;
1535 for (i
= 0; i
< col
->GetCount (); i
++) {
1536 value
= col
->GetValueAt (i
);
1537 keyframe
= value
->AsKeyFrame ();
1538 keyframe
->resolved_keytime
= 0;
1539 keyframe
->resolved
= false;
1542 /* resolve TimeSpan keyframes (step 1 from url) */
1543 for (i
= 0; i
< col
->GetCount (); i
++) {
1544 value
= col
->GetValueAt (i
);
1545 keyframe
= value
->AsKeyFrame ();
1547 if (keyframe
->GetKeyTime()->HasTimeSpan()) {
1548 has_timespan_keyframe
= true;
1549 TimeSpan ts
= keyframe
->GetKeyTime()->GetTimeSpan ();
1550 if (ts
> highest_keytime_timespan
)
1551 highest_keytime_timespan
= ts
;
1553 keyframe
->resolved_keytime
= ts
;
1554 keyframe
->resolved
= true;
1558 /* calculate total animation interpolation time (step 2 from url) */
1559 Duration
*d
= animation
->GetDuration();
1560 if (d
->HasTimeSpan ()) {
1561 total_interpolation_time
= d
->GetTimeSpan ();
1563 else if (has_timespan_keyframe
) {
1564 total_interpolation_time
= highest_keytime_timespan
;
1567 total_interpolation_time
= TimeSpan_FromSeconds (1);
1570 /* use the total interpolation time to resolve percent keytime keyframes (step 3 from url) */
1571 for (i
= 0; i
< col
->GetCount (); i
++) {
1572 value
= col
->GetValueAt (i
);
1573 keyframe
= value
->AsKeyFrame ();
1575 if (keyframe
->GetKeyTime()->HasPercent()) {
1576 keyframe
->resolved_keytime
= (TimeSpan
)(total_interpolation_time
* keyframe
->GetKeyTime()->GetPercent ());
1577 keyframe
->resolved
= true;
1581 /* step 4 from url */
1584 /* if the last frame is KeyTime Uniform or Paced, resolve it
1585 to be equal to the total interpolation time */
1586 if (col
->GetCount () > 0) {
1587 value
= col
->GetValueAt (col
->GetCount () - 1);
1588 keyframe
= value
->AsKeyFrame ();
1590 kt
= keyframe
->GetKeyTime ();
1591 if (*kt
== KeyTime::Paced
|| *kt
== KeyTime::Uniform
) {
1592 keyframe
->resolved_keytime
= total_interpolation_time
;
1593 keyframe
->resolved
= true;
1597 /* if the first frame is KeyTime::Paced:
1598 ** 1. if there is only 1 frame, its KeyTime is the total interpolation time.
1599 ** 2. if there is more than 1 frame, its KeyTime is 0.
1601 ** note 1 is handled in the above block so we only have to
1604 if (col
->GetCount () > 0) {
1605 value
= col
->GetValueAt (0);
1606 keyframe
= value
->AsKeyFrame ();
1607 kt
= keyframe
->GetKeyTime ();
1609 if (!keyframe
->resolved
&& *kt
== KeyTime::Paced
) {
1610 keyframe
->resolved_keytime
= 0;
1611 keyframe
->resolved
= true;
1615 /* XXX resolve remaining KeyTime::Uniform frames (step 5 from url) */
1617 /* XXX resolve frames with unspecified keytimes (step 6 from url)
1619 -- is this possible? is the default keytime NULL? it
1620 seems to be Uniform? */
1622 /* XXX resolve remaining KeyTime::Paced frames (step 7 from url) */
1624 /* insert the nodes into the sorted list using a stable sort
1625 with resolved keytime as primary key, declaration order as
1626 secondary key (step 8 from url) */
1627 g_ptr_array_set_size (col
->sorted_list
, 0);
1629 for (i
= col
->GetCount (); i
> 0; i
--) {
1630 value
= col
->GetValueAt (i
- 1);
1631 keyframe
= value
->AsKeyFrame ();
1633 if (!keyframe
->resolved
)
1634 g_warning ("***** unresolved keyframe!");
1636 g_ptr_array_insert_sorted (col
->sorted_list
, KeyFrameComparer
, keyframe
);
1640 // Generic validator of KeyFrameCollection's. Collection vallidates
1641 // if all keyframes have valid time.
1643 generic_keyframe_validator (KeyFrameCollection
*col
)
1648 for (int i
= 0; i
< col
->GetCount (); i
++) {
1649 value
= col
->GetValueAt (i
);
1650 keyframe
= value
->AsKeyFrame ();
1651 if (keyframe
->GetKeyTime () == NULL
)
1659 DoubleAnimationUsingKeyFrames::DoubleAnimationUsingKeyFrames ()
1661 SetObjectType (Type::DOUBLEANIMATIONUSINGKEYFRAMES
);
1664 DoubleAnimationUsingKeyFrames::~DoubleAnimationUsingKeyFrames ()
1669 DoubleAnimationUsingKeyFrames::AddKeyFrame (DoubleKeyFrame
*frame
)
1671 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1673 key_frames
->Add (frame
);
1677 DoubleAnimationUsingKeyFrames::RemoveKeyFrame (DoubleKeyFrame
*frame
)
1679 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1681 key_frames
->Remove (frame
);
1685 DoubleAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1686 AnimationClock
* animationClock
)
1688 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1690 /* current segment info */
1691 TimeSpan current_time
= animationClock
->GetCurrentTime();
1692 DoubleKeyFrame
*current_keyframe
;
1693 DoubleKeyFrame
*previous_keyframe
;
1694 DoubleKeyFrame
** keyframep
= &previous_keyframe
;
1696 bool deleteBaseValue
;
1698 current_keyframe
= (DoubleKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1699 if (current_keyframe
== NULL
) {
1701 return NULL
; /* XXX */
1704 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1705 TimeSpan key_start_time
;
1707 if (previous_keyframe
== NULL
) {
1708 /* the first keyframe, start at the animation's base value */
1709 baseValue
= defaultOriginValue
;
1710 deleteBaseValue
= false;
1714 /* start at the previous keyframe's target value */
1715 baseValue
= new Value (*previous_keyframe
->GetValue ());
1716 deleteBaseValue
= true;
1717 key_start_time
= previous_keyframe
->resolved_keytime
;
1722 if (current_time
>= key_end_time
) {
1726 TimeSpan key_duration
= key_end_time
- key_start_time
;
1727 if (key_duration
== 0)
1730 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1733 /* get the current value out of that segment */
1734 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1735 if (deleteBaseValue
)
1741 DoubleAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
1743 DoubleKeyFrameCollection
*key_frames
= GetKeyFrames ();
1745 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1747 guint len
= key_frames
->sorted_list
->len
;
1749 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1751 return Duration (0);
1755 DoubleAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1757 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1762 DoubleAnimationUsingKeyFrames::Validate ()
1764 return generic_keyframe_validator (GetKeyFrames ());
1767 ColorAnimationUsingKeyFrames::ColorAnimationUsingKeyFrames()
1769 SetObjectType (Type::COLORANIMATIONUSINGKEYFRAMES
);
1772 ColorAnimationUsingKeyFrames::~ColorAnimationUsingKeyFrames ()
1777 ColorAnimationUsingKeyFrames::AddKeyFrame (ColorKeyFrame
*frame
)
1779 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1781 key_frames
->Add (frame
);
1785 ColorAnimationUsingKeyFrames::RemoveKeyFrame (ColorKeyFrame
*frame
)
1787 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1789 key_frames
->Remove (frame
);
1793 ColorAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1794 AnimationClock
* animationClock
)
1796 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1797 /* current segment info */
1798 TimeSpan current_time
= animationClock
->GetCurrentTime();
1799 ColorKeyFrame
*current_keyframe
;
1800 ColorKeyFrame
*previous_keyframe
;
1801 ColorKeyFrame
** keyframep
= &previous_keyframe
;
1803 bool deleteBaseValue
;
1805 current_keyframe
= (ColorKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1806 if (current_keyframe
== NULL
)
1807 return NULL
; /* XXX */
1809 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1810 TimeSpan key_start_time
;
1812 if (previous_keyframe
== NULL
) {
1813 /* the first keyframe, start at the animation's base value */
1814 baseValue
= defaultOriginValue
;
1815 deleteBaseValue
= false;
1819 /* start at the previous keyframe's target value */
1820 baseValue
= new Value(*previous_keyframe
->GetValue ());
1821 deleteBaseValue
= true;
1822 key_start_time
= previous_keyframe
->resolved_keytime
;
1827 if (current_time
>= key_end_time
) {
1831 TimeSpan key_duration
= key_end_time
- key_start_time
;
1832 if (key_duration
== 0)
1835 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1838 /* get the current value out of that segment */
1839 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1840 if (deleteBaseValue
)
1846 ColorAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
1848 ColorKeyFrameCollection
*key_frames
= GetKeyFrames ();
1850 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1852 guint len
= key_frames
->sorted_list
->len
;
1854 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1856 return Duration (0);
1860 ColorAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1862 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1867 ColorAnimationUsingKeyFrames::Validate ()
1869 return generic_keyframe_validator (GetKeyFrames ());
1872 PointAnimationUsingKeyFrames::PointAnimationUsingKeyFrames()
1874 SetObjectType (Type::POINTANIMATIONUSINGKEYFRAMES
);
1877 PointAnimationUsingKeyFrames::~PointAnimationUsingKeyFrames ()
1882 PointAnimationUsingKeyFrames::AddKeyFrame (PointKeyFrame
*frame
)
1884 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1886 key_frames
->Add (frame
);
1890 PointAnimationUsingKeyFrames::RemoveKeyFrame (PointKeyFrame
*frame
)
1892 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1894 key_frames
->Remove (frame
);
1898 PointAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
1899 AnimationClock
* animationClock
)
1901 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1902 /* current segment info */
1903 TimeSpan current_time
= animationClock
->GetCurrentTime();
1904 PointKeyFrame
*current_keyframe
;
1905 PointKeyFrame
*previous_keyframe
;
1906 PointKeyFrame
** keyframep
= &previous_keyframe
;
1908 bool deleteBaseValue
;
1910 current_keyframe
= (PointKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
1911 if (current_keyframe
== NULL
)
1912 return NULL
; /* XXX */
1914 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
1915 TimeSpan key_start_time
;
1917 if (previous_keyframe
== NULL
) {
1918 /* the first keyframe, start at the animation's base value */
1919 baseValue
= defaultOriginValue
;
1920 deleteBaseValue
= false;
1924 /* start at the previous keyframe's target value */
1925 baseValue
= new Value(*previous_keyframe
->GetValue ());
1926 deleteBaseValue
= true;
1927 key_start_time
= previous_keyframe
->resolved_keytime
;
1932 if (current_time
>= key_end_time
) {
1936 TimeSpan key_duration
= key_end_time
- key_start_time
;
1937 if (key_duration
== 0)
1940 progress
= (double)(current_time
- key_start_time
) / key_duration
;
1943 /* get the current value out of that segment */
1944 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
1945 if (deleteBaseValue
)
1951 PointAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
* clock
)
1953 PointKeyFrameCollection
*key_frames
= GetKeyFrames ();
1955 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
1957 guint len
= key_frames
->sorted_list
->len
;
1959 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
1961 return Duration (0);
1965 PointAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
1967 KeyFrameAnimation_ResolveKeyFrames (this, GetKeyFrames ());
1972 PointAnimationUsingKeyFrames::Validate ()
1974 return generic_keyframe_validator (GetKeyFrames ());
1977 ObjectKeyFrameCollection::ObjectKeyFrameCollection ()
1979 SetObjectType (Type::OBJECTKEYFRAME_COLLECTION
);
1982 ObjectKeyFrameCollection::~ObjectKeyFrameCollection ()
1986 ObjectKeyFrame::ObjectKeyFrame ()
1988 SetObjectType (Type::OBJECTKEYFRAME
);
1991 ObjectKeyFrame::~ObjectKeyFrame ()
1996 ObjectKeyFrame::GetValue ()
1998 return DependencyObject::GetValue (ValueProperty
);
2001 DiscreteObjectKeyFrame::DiscreteObjectKeyFrame ()
2003 SetObjectType (Type::DISCRETEOBJECTKEYFRAME
);
2006 DiscreteObjectKeyFrame::~DiscreteObjectKeyFrame ()
2011 DiscreteObjectKeyFrame::InterpolateValue (Value
*baseValue
, double keyFrameProgress
)
2013 Value
*to
= GetConvertedValue ();
2015 if (to
&& keyFrameProgress
== 1.0)
2016 return new Value (*to
);
2018 return new Value (*baseValue
);
2021 ObjectAnimationUsingKeyFrames::ObjectAnimationUsingKeyFrames ()
2023 SetObjectType (Type::OBJECTANIMATIONUSINGKEYFRAMES
);
2026 ObjectAnimationUsingKeyFrames::~ObjectAnimationUsingKeyFrames ()
2031 ObjectAnimationUsingKeyFrames::AddKeyFrame (ObjectKeyFrame
*frame
)
2033 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2035 key_frames
->Add (frame
);
2039 ObjectAnimationUsingKeyFrames::RemoveKeyFrame (ObjectKeyFrame
*frame
)
2041 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2043 key_frames
->Remove (frame
);
2047 ObjectAnimationUsingKeyFrames::Resolve (DependencyObject
*target
, DependencyProperty
*property
)
2049 ObjectKeyFrameCollection
*frames
= (ObjectKeyFrameCollection
*) GetKeyFrames ();
2050 for (int i
= 0; i
< frames
->GetCount (); i
++) {
2051 ObjectKeyFrame
*frame
= frames
->GetValueAt (i
)->AsObjectKeyFrame ();
2053 Value
*value
= frame
->GetValue ();
2054 if (!value
|| value
->GetIsNull ()) {
2055 // If the value is null, don't convert
2056 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, NULL
);
2057 } else if (value
->GetKind () == property
->GetPropertyType ()) {
2058 // If the value is of the correct type already, don't convert
2059 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, value
);
2062 Application::GetCurrent ()->ConvertKeyframeValue (target
->GetType ()->GetKind (), property
, value
, &converted
);
2064 if (converted
.GetKind () == Type::INVALID
) {
2065 printf ("Couldn't convert value.\n");
2068 frame
->SetValue (ObjectKeyFrame::ConvertedValueProperty
, converted
);
2071 KeyFrameAnimation_ResolveKeyFrames (this, frames
);
2076 ObjectAnimationUsingKeyFrames::GetCurrentValue (Value
*defaultOriginValue
, Value
*defaultDestinationValue
,
2077 AnimationClock
* animationClock
)
2079 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2081 /* current segment info */
2082 TimeSpan current_time
= animationClock
->GetCurrentTime();
2083 ObjectKeyFrame
*current_keyframe
;
2084 ObjectKeyFrame
*previous_keyframe
;
2085 ObjectKeyFrame
** keyframep
= &previous_keyframe
;
2087 bool deleteBaseValue
;
2089 current_keyframe
= (ObjectKeyFrame
*)key_frames
->GetKeyFrameForTime (current_time
, (KeyFrame
**)keyframep
);
2090 if (current_keyframe
== NULL
)
2091 return NULL
; /* XXX */
2093 TimeSpan key_end_time
= current_keyframe
->resolved_keytime
;
2094 TimeSpan key_start_time
;
2096 if (previous_keyframe
== NULL
) {
2097 /* the first keyframe, start at the animation's base value */
2098 baseValue
= defaultOriginValue
;
2099 deleteBaseValue
= false;
2102 /* start at the previous keyframe's target value */
2103 baseValue
= new Value (*previous_keyframe
->GetConvertedValue ());
2104 deleteBaseValue
= true;
2105 key_start_time
= previous_keyframe
->resolved_keytime
;
2110 if (current_time
>= key_end_time
) {
2113 TimeSpan key_duration
= key_end_time
- key_start_time
;
2114 if (key_duration
== 0)
2117 progress
= (double)(current_time
- key_start_time
) / key_duration
;
2120 /* get the current value out of that segment */
2121 Value
*rv
= current_keyframe
->InterpolateValue (baseValue
, progress
);
2123 if (deleteBaseValue
)
2130 ObjectAnimationUsingKeyFrames::GetNaturalDurationCore (Clock
*clock
)
2132 ObjectKeyFrameCollection
*key_frames
= GetKeyFrames ();
2134 KeyFrameAnimation_ResolveKeyFrames (this, key_frames
);
2136 guint len
= key_frames
->sorted_list
->len
;
2138 return ((KeyFrame
*) key_frames
->sorted_list
->pdata
[len
- 1])->resolved_keytime
;
2140 return Duration (0);
2144 ObjectAnimationUsingKeyFrames::Validate ()
2146 // Interesting question -- should we check for null here?
2147 return generic_keyframe_validator (GetKeyFrames ());