private void GenerateOrderedStateAndSubAnimationCode(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, string animationType, AbsoluteOrRelative absoluteOrRelative) { List <AnimatedStateSave> remainingStates = new List <AnimatedStateSave>(); remainingStates.AddRange(animation.States); List <AnimationReferenceSave> remainingSubAnimations = new List <AnimationReferenceSave>(); remainingSubAnimations.AddRange(animation.Animations); double nextStateTime; double nextAnimationTime; AnimatedStateSave previousState = null; AnimatedStateSave currentState = null; while (remainingStates.Count > 0 || remainingSubAnimations.Count > 0) { if (remainingStates.Count > 0) { nextStateTime = remainingStates[0].Time; } else { nextStateTime = double.PositiveInfinity; } if (remainingSubAnimations.Count > 0) { nextAnimationTime = remainingSubAnimations[0].Time; } else { nextAnimationTime = double.PositiveInfinity; } if (nextAnimationTime < nextStateTime) { CreateInstructionForSubAnimation(currentBlock, remainingSubAnimations[0], absoluteOrRelative, animation, context); remainingSubAnimations.RemoveAt(0); } else { currentState = remainingStates[0]; CreateInstructionForInterpolation(context, currentBlock, animationType, previousState, currentState, absoluteOrRelative, animation.PropertyNameInCode()); previousState = currentState; remainingStates.RemoveAt(0); } } }
public static AnimatedKeyframeViewModel FromSave(AnimatedStateSave save) { AnimatedKeyframeViewModel toReturn = new AnimatedKeyframeViewModel(); toReturn.StateName = save.StateName; toReturn.Time = save.Time; toReturn.InterpolationType = save.InterpolationType; toReturn.Easing = save.Easing; return(toReturn); }
public AnimatedStateSave ToAnimatedStateSave() { AnimatedStateSave toReturn = new AnimatedStateSave(); if (string.IsNullOrEmpty(StateName)) { throw new InvalidOperationException("Could not convert this to a AnimatedStateSave because it doesn't have a valid StateName"); } toReturn.StateName = this.StateName; toReturn.Time = this.Time; toReturn.InterpolationType = this.InterpolationType; toReturn.Easing = this.Easing; return(toReturn); }
private void CreateInstructionForInterpolationAbsolute(StateCodeGeneratorContext context, ICodeBlock currentBlock, string animationType, AnimatedStateSave previousState, AnimatedStateSave currentState, string animationName) { if (previousState == null) { string variableStateName = null; variableStateName = "CurrentVariableState"; if (currentState.StateName.Contains("/")) { var split = currentState.StateName.Split('/'); animationType = split[0]; } if (animationType != "VariableState") { variableStateName = "Current" + animationType + "State"; } // todo: Change this on categories //System.Action action = () => this.CurrentState = fromState; string enumValue = currentState.StateName; if (enumValue.Contains("/")) { enumValue = enumValue.Split('/')[1]; } currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( ()=> this." + variableStateName + " = " + animationType + "." + enumValue + ");"); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime;"); currentBlock.Line("toReturn.Target = target;"); } else { var previousCategory = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandiate => stateCandiate.Name == previousState.StateName)); var currentCategory = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandiate => stateCandiate.Name == currentState.StateName)); // Now that we interpolateTo a single state, we don't // need to pass in the StateSave object: //bool differentCategories = previousCategory != currentCategory; // November 3, 2015 // Gum uses a "cumulative // state" system, so that each // keyframe in an animation will // tween with variables both before // and after. // The code as of the time of the writing // of this comment does InterpolateBetween // two states, which does not consider the state // of the object and only tweens variables common // to the two states. This makes the runtime behave // different than Glue, and it also makes the runtime // behave in confusing ways as authors don't often think // about the individual variables that may be set in a state. // We can solve this by instead doing Interpolate to between the // current state of the instance and the state that we are interpolating // to. Going to accomplish this by getting rid of the "from" state: //string fromState = null; string toState = null; string enumValue = currentState.StateName; if (currentState.StateName.Contains("/")) { currentCategory = context.Element.Categories.FirstOrDefault(item => item.Name == currentState.StateName.Split('/')[0]); enumValue = currentState.StateName.Split('/')[1]; } //if (differentCategories) //{ //fromState = "this.ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + previousState.StateName + "\")"; //toState = "this.ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + currentState.StateName + "\")"; //} //else //{ //fromState = animationType + "." + previousState.StateName; if (currentCategory == null) { toState = "VariableState." + enumValue; } else { toState = currentCategory.Name + "." + enumValue; } //} string previousStateTime = ToFloatString(previousState.Time); string interpolationTime = ToFloatString(currentState.Time - previousState.Time); string easing = "FlatRedBall.Glue.StateInterpolation.Easing." + previousState.Easing; string interpolationType = "FlatRedBall.Glue.StateInterpolation.InterpolationType." + previousState.InterpolationType; var line = "var toReturn = new FlatRedBall.Instructions.DelegateInstruction( () => this.InterpolateTo(" + string.Format("{0}, {1}, {2}, {3}, {4}));", toState, interpolationTime, interpolationType, easing, animationName); currentBlock.Line(line); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + previousStateTime + ";"); } currentBlock.Line("yield return toReturn;"); //System.Action action = () => this.InterpolateTo(fromState, toState, timeToTake, interpolationType, easing); }
private void CreateInstructionForInterpolationRelative(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimatedStateSave previousState, AnimatedStateSave currentState) { if (previousState != null) { currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction(() =>"); { currentBlock = currentBlock.Block(); // Is the start clone necessary? currentBlock.Line("var relativeStart = ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + previousState.StateName + "\").Clone();"); currentBlock.Line("var relativeEnd = ElementSave.AllStates.FirstOrDefault(item => item.Name == \"" + currentState.StateName + "\").Clone();"); currentBlock.Line("Gum.DataTypes.Variables.StateSaveExtensionMethods.SubtractFromThis(relativeEnd, relativeStart);"); currentBlock.Line("var difference = relativeEnd;"); string categoryName = "VariableState"; var category = context.Element.Categories.FirstOrDefault(item => item.States.Any(stateCandidate => stateCandidate.Name == currentState.StateName)); string enumValue = currentState.StateName; if (currentState.StateName.Contains('/')) { var split = currentState.StateName.Split('/'); category = context.Element.Categories.FirstOrDefault(item => item.Name == split[0]); enumValue = split[1]; } if (category != null) { categoryName = category.Name; } currentBlock.Line("Gum.DataTypes.Variables.StateSave first = GetCurrentValuesOnState(" + categoryName + "." + enumValue + ");"); currentBlock.Line("Gum.DataTypes.Variables.StateSave second = first.Clone();"); currentBlock.Line("Gum.DataTypes.Variables.StateSaveExtensionMethods.AddIntoThis(second, difference);"); string interpolationTime = ToFloatString(currentState.Time - previousState.Time); string easing = "FlatRedBall.Glue.StateInterpolation.Easing." + previousState.Easing; string interpolationType = "FlatRedBall.Glue.StateInterpolation.InterpolationType." + previousState.InterpolationType; currentBlock.Line( string.Format("FlatRedBall.Glue.StateInterpolation.Tweener tweener = new FlatRedBall.Glue.StateInterpolation.Tweener(from: 0, to: 1, duration: {0}, type: {1}, easing: {2});", interpolationTime, interpolationType, easing)); currentBlock.Line("tweener.Owner = this;"); currentBlock.Line("tweener.PositionChanged = newPosition => this.InterpolateBetween(first, second, newPosition);"); currentBlock.Line("tweener.Start();"); currentBlock.Line("StateInterpolationPlugin.TweenerManager.Self.Add(tweener);"); currentBlock = currentBlock.End(); } currentBlock.Line(");"); string previousStateTime = ToFloatString(previousState.Time); currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + previousStateTime + ";"); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("yield return toReturn;"); } }
private void CreateInstructionForInterpolation(StateCodeGeneratorContext context, ICodeBlock currentBlock, string animationType, AnimatedStateSave previousState, AnimatedStateSave currentState, AbsoluteOrRelative absoluteOrRelative, string animationName) { currentBlock = currentBlock.Block(); if (absoluteOrRelative == AbsoluteOrRelative.Absolute) { CreateInstructionForInterpolationAbsolute(context, currentBlock, animationType, previousState, currentState, animationName); } else { CreateInstructionForInterpolationRelative(context, currentBlock, previousState, currentState); } currentBlock = currentBlock.End(); }