|
@@ -0,0 +1,710 @@
|
|
|
+using ClearSlideLibrary.Dom;
|
|
|
+using DocumentFormat.OpenXml;
|
|
|
+using DocumentFormat.OpenXml.Presentation;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Globalization;
|
|
|
+using System.Linq;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
+
|
|
|
+namespace ClearSlideLibrary.Animations
|
|
|
+{
|
|
|
+ public class JSONGenerator
|
|
|
+ {
|
|
|
+ public PPTSlide Slide { get; set; }
|
|
|
+
|
|
|
+ public JSONGenerator(PPTSlide slide)
|
|
|
+ {
|
|
|
+ this.Slide = slide;
|
|
|
+ }
|
|
|
+
|
|
|
+ public JSONGenerator(List<PPTSlide> slides)
|
|
|
+ {
|
|
|
+ this.Slide = slides.ElementAt(0); //TODO: add support for more than one slide
|
|
|
+ }
|
|
|
+
|
|
|
+ public string GetAnimaVariable()
|
|
|
+ {
|
|
|
+ return "var animations = " + GetAnimationsJSON() + ";";
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Fix the timing for animations that need to start without a click. Make the tree simpler by removing nodes that are empty or nested.
|
|
|
+ *
|
|
|
+ * When a node has a start type != ClickEffect , we add the Animations from this timenode to the animations list in the previous time node.
|
|
|
+ * If it is type After the previous one we need to set Delay = Length of the previous one.
|
|
|
+ *
|
|
|
+ * Removing nested nodes:
|
|
|
+ * Example 1: Node -> Node -> Node - every node has a single child. In this case we can create one time node with the timing for both.
|
|
|
+ * Example 2: We have only one node (one simple animation) and all the other are nested (inner animations) - we remove the parent time node and
|
|
|
+ * add its timing to the timing of the nested animations.
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+ private List<IAnimation> fixAnimationTimings(List<IAnimation> animations)
|
|
|
+ {
|
|
|
+ animations = fixNestedAnimations(animations);
|
|
|
+
|
|
|
+
|
|
|
+ List<IAnimation> result = new List<IAnimation>();
|
|
|
+ if (animations == null || animations.Count == 0)
|
|
|
+ return result;
|
|
|
+ //If we have only one animation and all the others are nested - add the delay to the inner animations and remove this one.
|
|
|
+ if (animations.Count == 1 && animations[0].InnerAnimations != null && animations[0].InnerAnimations.Count > 0)
|
|
|
+ {
|
|
|
+ foreach (IAnimation anim in animations[0].InnerAnimations)
|
|
|
+ anim.Start += animations[0].Start;
|
|
|
+ return fixAnimationTimings(animations[0].InnerAnimations);
|
|
|
+ }
|
|
|
+ IAnimation previousAnimation = null;
|
|
|
+ foreach (IAnimation animation in animations)
|
|
|
+ {
|
|
|
+ SimpleAnimation sAnimation = (SimpleAnimation)animation;
|
|
|
+ if (previousAnimation == null)
|
|
|
+ {
|
|
|
+ previousAnimation = sAnimation;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //These are the cases where animation starts without a click. There migth be other cases which are not handled yet.
|
|
|
+ else if (sAnimation.timingType.HasValue && (
|
|
|
+ TimeNodeValues.WithEffect.Equals(sAnimation.timingType.Value) ||
|
|
|
+ TimeNodeValues.AfterEffect.Equals(sAnimation.timingType.Value) ||
|
|
|
+ TimeNodeValues.WithGroup.Equals(sAnimation.timingType.Value) ||
|
|
|
+ TimeNodeValues.AfterGroup.Equals(sAnimation.timingType.Value)))
|
|
|
+ {
|
|
|
+ int newLenegth = 0;
|
|
|
+ if (TimeNodeValues.AfterEffect.Equals(sAnimation.timingType.Value) ||
|
|
|
+ TimeNodeValues.AfterGroup.Equals(sAnimation.timingType.Value))
|
|
|
+ {
|
|
|
+ /*If animation is a part of a group then it has delay according to the start of the parent time node (animation).
|
|
|
+ * In this case we use this delay because it is the proper way power point handles such animations.
|
|
|
+ * If by some reason there isn't such delay and the animation type is set to 'After' previous
|
|
|
+ * we set the start point to right after the previous animation ends." */
|
|
|
+
|
|
|
+ if (sAnimation.Start <= previousAnimation.Length + previousAnimation.Start)
|
|
|
+ sAnimation.Start = previousAnimation.Length + previousAnimation.Start;
|
|
|
+ if (sAnimation.InnerAnimations != null)
|
|
|
+ foreach (IAnimation anim in sAnimation.InnerAnimations)
|
|
|
+ anim.Start = anim.Start + sAnimation.Start;
|
|
|
+ newLenegth = sAnimation.Length + sAnimation.Start;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newLenegth = (sAnimation.Length + sAnimation.Start >
|
|
|
+ previousAnimation.Length + previousAnimation.Start)
|
|
|
+ ? sAnimation.Length + sAnimation.Start
|
|
|
+ : previousAnimation.Length + previousAnimation.Start;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*Joins the current animation and the previous one and recalculates the length*/
|
|
|
+ if (previousAnimation.InnerAnimations != null && previousAnimation.InnerAnimations.Count > 0)
|
|
|
+ {
|
|
|
+
|
|
|
+ previousAnimation.Length = newLenegth;
|
|
|
+ if (sAnimation.InnerAnimations == null || sAnimation.InnerAnimations.Count == 0)
|
|
|
+ previousAnimation.InnerAnimations.Add(sAnimation);
|
|
|
+ else
|
|
|
+ previousAnimation.InnerAnimations.AddRange(sAnimation.InnerAnimations);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SimpleAnimation tempAnimation = new SimpleAnimation();
|
|
|
+ tempAnimation.Length = newLenegth;
|
|
|
+ tempAnimation.timingType = ((SimpleAnimation)previousAnimation).timingType;
|
|
|
+ tempAnimation.InnerAnimations = new List<IAnimation>();
|
|
|
+
|
|
|
+ if (previousAnimation.InnerAnimations == null || previousAnimation.InnerAnimations.Count == 0)
|
|
|
+ tempAnimation.InnerAnimations.Add(previousAnimation);
|
|
|
+ else
|
|
|
+ tempAnimation.InnerAnimations.AddRange(previousAnimation.InnerAnimations);
|
|
|
+
|
|
|
+ if (sAnimation.InnerAnimations == null || sAnimation.InnerAnimations.Count == 0)
|
|
|
+ tempAnimation.InnerAnimations.Add(sAnimation);
|
|
|
+ else
|
|
|
+ tempAnimation.InnerAnimations.AddRange(sAnimation.InnerAnimations);
|
|
|
+ previousAnimation = tempAnimation;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ result.Add(previousAnimation);
|
|
|
+ previousAnimation = sAnimation;
|
|
|
+ }
|
|
|
+ result.Add(previousAnimation);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ * When the animation has only one inner animation then return the inner animation. Do this recursive until we get the real one.
|
|
|
+ */
|
|
|
+ private IAnimation getAnimationFromNested(IAnimation sAnimation)
|
|
|
+ {
|
|
|
+ if (sAnimation.InnerAnimations != null && sAnimation.InnerAnimations.Count == 1)
|
|
|
+ {
|
|
|
+ sAnimation.InnerAnimations[0].Start += sAnimation.Start;
|
|
|
+ return getAnimationFromNested(sAnimation.InnerAnimations[0]);
|
|
|
+ }
|
|
|
+ if (((SimpleAnimation)sAnimation).timingType == null && sAnimation.InnerAnimations != null)
|
|
|
+ ((SimpleAnimation)sAnimation).timingType = ((SimpleAnimation)getAnimationFromNested(sAnimation.InnerAnimations[0])).timingType;
|
|
|
+ return sAnimation;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Generating the JSON for the animations for one slide only. It has some support for nested animations but not everything works.
|
|
|
+ */
|
|
|
+
|
|
|
+ public string GetAnimationsJSON()
|
|
|
+ {
|
|
|
+ if (Slide == null)
|
|
|
+ {
|
|
|
+ return "{s1:{t:{i:1000,c:1,v:0,n:0},g:0,a:0,f:0,c:0}}";
|
|
|
+ }
|
|
|
+ String result = "";
|
|
|
+
|
|
|
+ int animations = 0;
|
|
|
+
|
|
|
+ List<IAnimation> fixedAnimations = fixAnimationTimings(Slide.Animations);
|
|
|
+ animations = fixedAnimations.Count;
|
|
|
+
|
|
|
+ if (Slide.Transition == null)
|
|
|
+ {
|
|
|
+ result = "{s1:{t:{i:0,c:1,v:0,n:0},g:0,a:0,f:0,c:##ANIMATIONS_PLACEHOLDER##}}";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ result = "{s1:{t:{i:" + (Slide.Transition.Length + Slide.Transition.Start) +
|
|
|
+ ",c:" + Slide.Transition.GetJsonString() + "},g:0,a:0,f:0,c:##ANIMATIONS_PLACEHOLDER##}}";
|
|
|
+ }
|
|
|
+ if (animations == 0)
|
|
|
+ {
|
|
|
+ result = result.Replace("##ANIMATIONS_PLACEHOLDER##", "0");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ SimpleAnimation checkEffectFirstAnim = (SimpleAnimation)fixedAnimations[0];
|
|
|
+ if (checkEffectFirstAnim.timingType.HasValue && checkEffectFirstAnim.timingType.Value != TimeNodeValues.ClickEffect)
|
|
|
+ {
|
|
|
+ result = result.Replace("n:0", "n:1");
|
|
|
+ //If it is just one Animation we change this in the transition! - the transition is like the first Animation!
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ string animationsString = "{i:" + animations + getAnimationsString(fixedAnimations, true) + "}";
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ result = result.Replace("##ANIMATIONS_PLACEHOLDER##", animationsString);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Generate JSON for animation tree. Recursive going into the tree - there is some difference in the animation string
|
|
|
+ * for the first level and the next levels.
|
|
|
+ */
|
|
|
+
|
|
|
+ private string getAnimationsString(List<IAnimation> animations, bool firstLevel)
|
|
|
+ {
|
|
|
+ String animationList = "";
|
|
|
+ int index = 0;
|
|
|
+ foreach (IAnimation animation in animations)
|
|
|
+ {
|
|
|
+ if (animation.InnerAnimations == null || animation.InnerAnimations.Count == 0)
|
|
|
+ {
|
|
|
+ if (!firstLevel)
|
|
|
+ animationList = animationList + ",c" + index++ + ":" + animation.GetJsonString();
|
|
|
+ else
|
|
|
+ animationList = animationList + ",c" + index++ + ":{i:" + (((SimpleAnimation)animation).getCalculatedLength() + animation.Start) + ",c0:" + animation.GetJsonString() + "}";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ // Nested animatons (several animations in one time node, or in different time nodes that start together!
|
|
|
+ {
|
|
|
+ String innerAnimationsString = getAnimationsString(animation.InnerAnimations, false);
|
|
|
+
|
|
|
+ animationList = animationList + ",c" + index++ + ":{i:" + (((SimpleAnimation)animation).getCalculatedLength() + animation.Start) +
|
|
|
+ innerAnimationsString + "}";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return animationList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static IAnimation GenerateTransitionAnimationObject(Transition trans)
|
|
|
+ {
|
|
|
+ if (trans == null || trans.FirstChild == null)
|
|
|
+ return null;
|
|
|
+ TransitionAnimation result = new TransitionAnimation();
|
|
|
+ if (trans.Speed != null && TransitionSpeedValues.Fast.Equals(trans.Speed.Value))
|
|
|
+ result.Length = 500;
|
|
|
+ else if (trans.Speed != null && TransitionSpeedValues.Slow.Equals(trans.Speed.Value))
|
|
|
+ result.Length = 2000;
|
|
|
+ else if (trans.Duration != null)
|
|
|
+ result.Length = int.Parse(trans.Duration.Value);
|
|
|
+ else
|
|
|
+ result.Length = 1000;
|
|
|
+
|
|
|
+ result.Start = 0;
|
|
|
+ result.InitialState = -1;
|
|
|
+ result.Repetitions = 1;
|
|
|
+ if (trans.AdvanceOnClick != null)
|
|
|
+ result.AdvanceOnClick = trans.AdvanceOnClick.Value;
|
|
|
+ else result.AdvanceOnClick = true;
|
|
|
+
|
|
|
+ if (typeof(StripsTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ StripsTransition transition = (StripsTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Strips;
|
|
|
+ if (transition.Direction != null &&
|
|
|
+ TransitionCornerDirectionValues.RightUp.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "7";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionCornerDirectionValues.LeftDown.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "9";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionCornerDirectionValues.RightDown.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "8";
|
|
|
+ else
|
|
|
+ result.AdditionalData = "6";
|
|
|
+ }
|
|
|
+ else if (typeof(PushTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ PushTransition transition = (PushTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Push;
|
|
|
+ if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Right.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "3";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Up.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "4";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Left.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "2";
|
|
|
+ else result.AdditionalData = "1";
|
|
|
+ }
|
|
|
+ else if (typeof(WipeTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ WipeTransition transition = (WipeTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Wipe;
|
|
|
+ if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Right.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "4";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Up.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "3";
|
|
|
+ else if (transition.Direction != null &&
|
|
|
+ TransitionSlideDirectionValues.Left.Equals(transition.Direction.Value))
|
|
|
+ result.AdditionalData = "2";
|
|
|
+ else result.AdditionalData = "1";
|
|
|
+ }
|
|
|
+ else if (typeof(FadeTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ FadeTransition transition = (FadeTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Fade;
|
|
|
+ if (transition.ThroughBlack != null && transition.ThroughBlack.Value)
|
|
|
+ result.Type = AnimationTypes.FadeThroughBlack;
|
|
|
+ result.AdditionalData = "1";
|
|
|
+ }
|
|
|
+ else if (typeof(CutTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ CutTransition transition = (CutTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Cut;
|
|
|
+ result.AdditionalData = "2";
|
|
|
+ if (transition.ThroughBlack != null && transition.ThroughBlack.Value)
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.CutThroughBlack;
|
|
|
+ result.AdditionalData = "3";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (typeof(DissolveTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.DissolveIn;
|
|
|
+ result.AdditionalData = "1";
|
|
|
+ }
|
|
|
+ else if (typeof(WedgeTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Wedge;
|
|
|
+ result.AdditionalData = "1";
|
|
|
+ }
|
|
|
+ else if (typeof(PullTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ PullTransition transition = (PullTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.UnCover;
|
|
|
+ if (transition.Direction != null && "d".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "9";
|
|
|
+ else if (transition.Direction != null && "r".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "11";
|
|
|
+ else if (transition.Direction != null && "u".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "12";
|
|
|
+ else if (transition.Direction != null && "ld".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "13";
|
|
|
+ else if (transition.Direction != null && "lu".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "14";
|
|
|
+ else if (transition.Direction != null && "rd".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "15";
|
|
|
+ else if (transition.Direction != null && "ru".Equals(transition.Direction.Value.ToString()))
|
|
|
+ result.AdditionalData = "16";
|
|
|
+ else result.AdditionalData = "10";
|
|
|
+ }
|
|
|
+ else if (typeof(ZoomTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ ZoomTransition transition = (ZoomTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Box;
|
|
|
+ if (transition.Direction != null && TransitionInOutDirectionValues.In == transition.Direction.Value)
|
|
|
+ result.AdditionalData = "19";
|
|
|
+ else result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ else if (typeof(ZoomTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ ZoomTransition transition = (ZoomTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Box;
|
|
|
+ if (transition.Direction != null && TransitionInOutDirectionValues.In == transition.Direction.Value)
|
|
|
+ result.AdditionalData = "19";
|
|
|
+ else result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ else if (typeof(WheelTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ WheelTransition transition = (WheelTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Wheel;
|
|
|
+ if (transition.Spokes != null && transition.Spokes.Value == 1)
|
|
|
+ result.AdditionalData = "1";
|
|
|
+ else if (transition.Spokes != null && transition.Spokes.Value == 2)
|
|
|
+ result.AdditionalData = "2";
|
|
|
+ else if (transition.Spokes != null && transition.Spokes.Value == 3)
|
|
|
+ result.AdditionalData = "3";
|
|
|
+ else if (transition.Spokes != null && transition.Spokes.Value == 8)
|
|
|
+ result.AdditionalData = "8";
|
|
|
+ else result.AdditionalData = "4";
|
|
|
+ }
|
|
|
+ else if (typeof(SplitTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ SplitTransition transition = (SplitTransition)trans.FirstChild;
|
|
|
+ result.Type = AnimationTypes.Split;
|
|
|
+ if (transition.Direction != null && TransitionInOutDirectionValues.In == transition.Direction.Value)
|
|
|
+ {
|
|
|
+ if (transition.Orientation != null && DirectionValues.Vertical.Equals(transition.Orientation.Value))
|
|
|
+ result.AdditionalData = "25";
|
|
|
+ else
|
|
|
+ result.AdditionalData = "23";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (transition.Orientation != null && DirectionValues.Vertical.Equals(transition.Orientation.Value))
|
|
|
+ result.AdditionalData = "26";
|
|
|
+ else
|
|
|
+ result.AdditionalData = "24";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (typeof(CircleTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Circle;
|
|
|
+ result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ else if (typeof(DiamondTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Diamond;
|
|
|
+ result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ else if (typeof(PlusTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Plus;
|
|
|
+ result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ else if (typeof(NewsflashTransition) == trans.FirstChild.GetType())
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Newsflash;
|
|
|
+ result.AdditionalData = "20";
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public SimpleAnimation getSimpleAnimationFromCommonTimeNodePreset(CommonTimeNode commonTimeNode, SlideSize SlideSizes)
|
|
|
+ {
|
|
|
+ SimpleAnimation result = new SimpleAnimation();
|
|
|
+ if (AnimationTypes.TypePath.Equals(commonTimeNode.PresetClass))
|
|
|
+ {
|
|
|
+ return new MotionPathAnimation(commonTimeNode, Slide.slideIndex, SlideSizes);
|
|
|
+ }
|
|
|
+ else if (AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass))
|
|
|
+ {
|
|
|
+ result.InitialState = 1;
|
|
|
+ }
|
|
|
+ else if (AnimationTypes.TypeExit.Equals(commonTimeNode.PresetClass))
|
|
|
+ {
|
|
|
+ result.InitialState = 2;
|
|
|
+ }
|
|
|
+ else if (AnimationTypes.TypeEmphasis.Equals(commonTimeNode.PresetClass))
|
|
|
+ {
|
|
|
+ result.InitialState = 3;
|
|
|
+ }
|
|
|
+ else return null;
|
|
|
+ if (commonTimeNode.PresetId == null)
|
|
|
+ return null;
|
|
|
+ result.timingType = commonTimeNode.NodeType;
|
|
|
+
|
|
|
+ //Get the speed from one of the nodes common behavior. Hopefully all nodes have the same speed (since the animation is the same).
|
|
|
+ foreach (Object xmlEl in commonTimeNode.Descendants())
|
|
|
+ if (xmlEl.GetType().Equals(typeof(CommonBehavior)))
|
|
|
+ {
|
|
|
+ CommonBehavior bhvr = ((CommonBehavior)xmlEl);
|
|
|
+
|
|
|
+ if (bhvr.CommonTimeNode != null)
|
|
|
+ {
|
|
|
+ result.FixAnimationTimings(bhvr, Slide.slideIndex);
|
|
|
+ if (result.Length <= 1)
|
|
|
+ continue;
|
|
|
+ if (result.Start == 0)
|
|
|
+ {
|
|
|
+ Condition condition = commonTimeNode.StartConditionList.FirstChild as Condition;
|
|
|
+ if (!condition.Delay.Equals("indefinite"))
|
|
|
+ result.Start = int.Parse(condition.Delay);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (result.Length <= 1)
|
|
|
+ result.Length = 100; //Default value??
|
|
|
+ if (AnimationTypes.TypeEmphasis.Equals(commonTimeNode.PresetClass))
|
|
|
+ result = handleEmphasisAnimation(commonTimeNode, result);
|
|
|
+ else
|
|
|
+ result = handleEntranceAnimation(commonTimeNode, result);
|
|
|
+
|
|
|
+
|
|
|
+ if (result.AdditionalData == null || result.AdditionalData == "0") //There are default values. Horizontal In = horizontal + in ;)
|
|
|
+ switch (commonTimeNode.PresetSubtype.Value)
|
|
|
+ {
|
|
|
+ case 0: result.AdditionalData = "0"; break;
|
|
|
+ case 4: result.AdditionalData = "3"; break; //From bottom
|
|
|
+ case 2: result.AdditionalData = "2"; break; //From right
|
|
|
+ case 1: result.AdditionalData = "1"; break; //From top
|
|
|
+ case 8: result.AdditionalData = "4"; break; //From left
|
|
|
+ case 6: result.AdditionalData = "8"; break; //Bottom right
|
|
|
+ case 3: result.AdditionalData = "7"; break; //Top right
|
|
|
+ case 9: result.AdditionalData = "6"; break; //Top right
|
|
|
+ case 12: result.AdditionalData = "9"; break; //Bottom left
|
|
|
+ case 10: result.AdditionalData = "16"; break; //Horizontal
|
|
|
+ case 5: result.AdditionalData = "17"; break; //Vertical
|
|
|
+ case 26: result.AdditionalData = "23"; break; //Horizontal in
|
|
|
+ case 42: result.AdditionalData = "24"; break; //Horizontal out
|
|
|
+ case 21: result.AdditionalData = "25"; break; //Vertical in
|
|
|
+ case 37: result.AdditionalData = "26"; break; //Vertical out
|
|
|
+ case 16: result.AdditionalData = "19"; break; //in
|
|
|
+ case 32: result.AdditionalData = "20"; break; //out
|
|
|
+ }
|
|
|
+
|
|
|
+ checkIsText(result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkIsText(SimpleAnimation result)
|
|
|
+ {
|
|
|
+ int res;
|
|
|
+ bool isTextWithEffect = int.TryParse(result.ObjectId, out res) && PPTShape.effectShapes.Contains(Slide.slideIndex + "_" + res);
|
|
|
+
|
|
|
+ int tryParse = 0;
|
|
|
+ if (!int.TryParse(result.ObjectId, out tryParse) || isTextWithEffect) {
|
|
|
+ return;//if it is like 123p -> return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (PPTShapeBase shape in Slide.ContainerShape.Elements)
|
|
|
+ if (typeof(PPTShape).Equals(shape.GetType()) && ((PPTShape)shape).IsText)
|
|
|
+ {
|
|
|
+ string shapeId = shape.NonVisualShapeProp.Id;
|
|
|
+ string shapeObjectId = "s1s" + result.ObjectId;
|
|
|
+ if (shapeId.Equals(shapeObjectId))
|
|
|
+ {
|
|
|
+ result.ObjectId = result.ObjectId + "p0";// TODO check when multiple paragraphs
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private EmphasisAnimation handleEmphasisAnimation(CommonTimeNode commonTimeNode, SimpleAnimation simpleAnim)
|
|
|
+ {
|
|
|
+ EmphasisAnimation result = new EmphasisAnimation(simpleAnim);
|
|
|
+ result.setRgbColor(commonTimeNode, Slide);
|
|
|
+
|
|
|
+ switch (commonTimeNode.PresetId.Value) //Presets for Entrance/Exit
|
|
|
+ {
|
|
|
+ case 3: result.Type = AnimationTypes.ChangeFontColor; break;
|
|
|
+ case 19: result.Type = AnimationTypes.ColorBlend; break;
|
|
|
+ case 14: result.Type = AnimationTypes.Blast; break;
|
|
|
+ case 26: result.Type = AnimationTypes.FlashBulb; break;
|
|
|
+ case 35: result.Type = AnimationTypes.Blink; break;
|
|
|
+ case 9:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Transparency;
|
|
|
+ result.Transparency = getTransparence(commonTimeNode);
|
|
|
+ } break;
|
|
|
+ case 20:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.ColorWave;
|
|
|
+ result.Length *= 2;
|
|
|
+ result.e2 = result.Length / 10;
|
|
|
+ result.e1 = 2;
|
|
|
+ } break;
|
|
|
+ case 16:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.BrushOnColor;
|
|
|
+ result.e2 = result.Length / 25;
|
|
|
+ result.e1 = 2;
|
|
|
+ } break;
|
|
|
+ case 33:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.VerticalHighlight;
|
|
|
+ result.Length *= 2;
|
|
|
+ } break;
|
|
|
+ case 27:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Flicker;
|
|
|
+ result.Length *= 2;
|
|
|
+ } break;
|
|
|
+ case 36:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Shimmer;
|
|
|
+ result.e2 = result.Length / 5;
|
|
|
+ result.Length *= 2;
|
|
|
+ foreach (Object obj in commonTimeNode.Descendants())
|
|
|
+ if (obj.GetType().Equals(typeof(AnimateScale)))
|
|
|
+ {
|
|
|
+ ((EmphasisAnimation)result).ScaleX = ((AnimateScale)obj).ToPosition.X.Value / 1000;
|
|
|
+ ((EmphasisAnimation)result).ScaleY = ((AnimateScale)obj).ToPosition.Y.Value / 1000;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+ case 28:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.GrowwithColor;
|
|
|
+ result.e2 = result.Length / 10;
|
|
|
+ result.e1 = 2;
|
|
|
+ } break;
|
|
|
+ case 32:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Teeter;
|
|
|
+ result.Length *= 2;
|
|
|
+ } break;
|
|
|
+ case 34:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Wave;
|
|
|
+ result.e2 = result.Length / 5;
|
|
|
+ result.Length *= 2;
|
|
|
+ } break;
|
|
|
+ case 8:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.Spin;
|
|
|
+ foreach (Object obj in commonTimeNode.Descendants())
|
|
|
+ if (obj.GetType().Equals(typeof(AnimateRotation)))
|
|
|
+ {
|
|
|
+ ((EmphasisAnimation)result).RotationDegrees = ((AnimateRotation)obj).By / 60000;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+ case 6:
|
|
|
+ {
|
|
|
+ result.Type = AnimationTypes.GrowShrink;
|
|
|
+ foreach (Object obj in commonTimeNode.Descendants())
|
|
|
+ if (obj.GetType().Equals(typeof(AnimateScale)))
|
|
|
+ {
|
|
|
+ ((EmphasisAnimation)result).ScaleX = ((AnimateScale)obj).ByPosition.X.Value / 1000;
|
|
|
+ ((EmphasisAnimation)result).ScaleY = ((AnimateScale)obj).ByPosition.Y.Value / 1000;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+ default: return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private SimpleAnimation handleEntranceAnimation(CommonTimeNode commonTimeNode, SimpleAnimation result)
|
|
|
+ {
|
|
|
+ switch (commonTimeNode.PresetId.Value) //Presets for Entrance/Exit
|
|
|
+ {
|
|
|
+ case 1: result.Type = AnimationTypes.Appear; break;
|
|
|
+ case 54: result.Type = AnimationTypes.Glide; break;
|
|
|
+ case 19: result.Type = AnimationTypes.Swivel; break;
|
|
|
+ case 42: result.Type = AnimationTypes.Ascend; break;
|
|
|
+ case 3: result.Type = AnimationTypes.Blinds; break;
|
|
|
+ case 4: result.Type = AnimationTypes.Box; break;
|
|
|
+ case 25: result.Type = AnimationTypes.Boomerang; break;
|
|
|
+ case 43: result.Type = AnimationTypes.CenterRevolve; break;
|
|
|
+ case 5: result.Type = AnimationTypes.Checkerboard; break;
|
|
|
+ case 50: result.Type = AnimationTypes.Compress; break;
|
|
|
+ case 7: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.CrawlIn : AnimationTypes.CrawlOut; break;
|
|
|
+ case 47: result.Type = AnimationTypes.Descend; break;
|
|
|
+ case 48: result.Type = AnimationTypes.Sling; break;
|
|
|
+ case 29: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.EaseIn : AnimationTypes.EaseOut; break;
|
|
|
+ case 55: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.Expand : AnimationTypes.Contract; break;
|
|
|
+ case 10: result.Type = AnimationTypes.Fade; break;
|
|
|
+ case 53: result.Type = AnimationTypes.FadedZoom; break;
|
|
|
+ case 11: result.Type = AnimationTypes.FlashOnce; break;
|
|
|
+ case 2: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.FlyIn : AnimationTypes.FlyOut; break;
|
|
|
+ case 58: result.Type = AnimationTypes.Fold; break;
|
|
|
+ case 31: result.Type = AnimationTypes.GrowTurn; break;
|
|
|
+ case 12: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.PeekIn : AnimationTypes.PeekOut; break;
|
|
|
+ case 16: result.Type = AnimationTypes.Split; break;
|
|
|
+ case 35: result.Type = AnimationTypes.Pinwheel; break;
|
|
|
+ case 14: result.Type = AnimationTypes.RandomBars; break;
|
|
|
+ case 37: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.RiseUp : AnimationTypes.SinkDown; break;
|
|
|
+ case 49: result.Type = AnimationTypes.Spinner; break;
|
|
|
+ case 22: result.Type = AnimationTypes.Wipe; break;
|
|
|
+ case 18: result.Type = AnimationTypes.Strips; break;
|
|
|
+ case 26: result.Type = AnimationTypes.Bounce; result.Length = (int)((result.Length * 100) / 29); break;//time tunning
|
|
|
+ case 6: result.Type = AnimationTypes.Circle; break;
|
|
|
+ case 28: result.Type = AnimationTypes.Credits; break;
|
|
|
+ case 52: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.CurveUp : AnimationTypes.CurveDown; break;
|
|
|
+ case 8: result.Type = AnimationTypes.Diamond; break;
|
|
|
+ case 9: result.Type = AnimationTypes.Dissolve; break;
|
|
|
+ case 30: result.Type = AnimationTypes.Float; break;
|
|
|
+ case 34: result.Type = AnimationTypes.LightSpeed; result.Length = (int)((result.Length * 5) / 3); break;//time tunning
|
|
|
+ case 51: result.Type = AnimationTypes.Magnify; result.Length = (int)((result.Length * 200) / 77); break;//time tunning
|
|
|
+ case 13: result.Type = AnimationTypes.Plus; break;
|
|
|
+ case 15: result.Type = AnimationTypes.TypeEntrance.Equals(commonTimeNode.PresetClass) ? AnimationTypes.SpiralIn : AnimationTypes.SpiralOut; break;
|
|
|
+ case 17: result.Type = AnimationTypes.Stretch; break;
|
|
|
+ case 39: result.Type = AnimationTypes.Thread; break;
|
|
|
+ case 20: result.Type = AnimationTypes.Wedge; break;
|
|
|
+ case 21: result.Type = AnimationTypes.Wheel; result.AdditionalData = "" + commonTimeNode.PresetSubtype.Value; break;
|
|
|
+ case 23: result.Type = AnimationTypes.Zoom; break;
|
|
|
+
|
|
|
+ default: return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private double getTransparence(CommonTimeNode commonTimeNode)
|
|
|
+ {
|
|
|
+ if (typeof(AnimateEffect) == commonTimeNode.LastChild.LastChild.GetType())
|
|
|
+ {
|
|
|
+ AnimateEffect animEffect = (AnimateEffect)commonTimeNode.LastChild.LastChild;
|
|
|
+ string value = animEffect.PropertyList.Value;
|
|
|
+ if (value != null && value.IndexOf("opacity:") != -1)
|
|
|
+ {
|
|
|
+ string opacityStr = value.Substring(9);//we need 0.75 from "opacity: 0.75"
|
|
|
+ double opacity = double.Parse(opacityStr,CultureInfo.GetCultureInfo("en-US").NumberFormat);
|
|
|
+ return 1 - opacity;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<IAnimation> fixNestedAnimations(List<IAnimation> animations)
|
|
|
+ {
|
|
|
+ if (animations == null || animations.Count == 0)
|
|
|
+ return null;
|
|
|
+ List<IAnimation> result = new List<IAnimation>();
|
|
|
+ foreach (IAnimation anim in animations)
|
|
|
+ {
|
|
|
+ IAnimation animation = getAnimationFromNested(anim);
|
|
|
+ animation.InnerAnimations = fixNestedAnimations(animation.InnerAnimations);
|
|
|
+ result.Add(animation);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|