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); } } }
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(); }
private void GenerateAnimationEnumerables(ElementSave elementSave, ICodeBlock currentBlock) { currentBlock.Line("#region State Animations"); StateCodeGeneratorContext context = new StateCodeGeneratorContext(); context.Element = elementSave; ElementAnimationsSave animations = GetAnimationsFor(elementSave); if(animations != null) { foreach(var animation in animations.Animations) { GenerateEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Relative); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Relative); } } currentBlock.Line("#endregion"); }
private void GenerateAnimationEnumerables(ElementSave elementSave, ICodeBlock currentBlock) { currentBlock.Line("#region State Animations"); StateCodeGeneratorContext context = new StateCodeGeneratorContext(); context.Element = elementSave; ElementAnimationsSave animations = GetAnimationsFor(elementSave); if (animations != null) { foreach (var animation in animations.Animations) { GenerateGetEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateGetEnumerableFor(context, currentBlock, animation, AbsoluteOrRelative.Relative); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Absolute); GenerateAnimationMember(context, currentBlock, animation, AbsoluteOrRelative.Relative); } } currentBlock.Line("#endregion"); }
private void GenerateAnimationMember(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string propertyName = animation.PropertyNameInCode(); if (absoluteOrRelative == AbsoluteOrRelative.Relative) { propertyName += "Relative"; } string referencedInstructionProperty = propertyName + "Instructions"; // Force the property to be upper-case, since the field is lower-case: // We want to generate something like: //private FlatRedBall.Gum.Animation.GumAnimation uncategorizedAnimation; //public FlatRedBall.Gum.Animation.GumAnimation UncategorizedAnimation //{ // get // { // if (uncategorizedAnimation == null) // { // uncategorizedAnimation = new FlatRedBall.Gum.Animation.GumAnimation(1, () => UncategorizedAnimationInstructions); // uncategorizedAnimation.AddEvent("Event1", 3.0f); // } // return uncategorizedAnimation; // } //} var firstCharacterLower = propertyName.Substring(0, 1).ToLowerInvariant(); var fieldName = firstCharacterLower + propertyName.Substring(1); currentBlock.Line($"private FlatRedBall.Gum.Animation.GumAnimation {fieldName};"); currentBlock = currentBlock.Property("public FlatRedBall.Gum.Animation.GumAnimation", propertyName).Get(); float length = GetAnimationLength(context.Element, animation); string lengthAsString = ToFloatString(length); var ifBlock = currentBlock.If($"{fieldName} == null"); { ifBlock.Line( $"{fieldName} = new FlatRedBall.Gum.Animation.GumAnimation({lengthAsString}, {referencedInstructionProperty});"); foreach (var namedEvent in animation.Events) { string timeAsString = ToFloatString(namedEvent.Time); ifBlock.Line( $"{fieldName}.AddEvent(\"{namedEvent.Name}\", {timeAsString});"); } foreach (var subAnimation in animation.Animations) { if (string.IsNullOrEmpty(subAnimation.SourceObject) == false) { var isMissingInstance = context.Element.GetInstance(subAnimation.SourceObject) == null; if (isMissingInstance) { ifBlock.Line($"//Missing object {subAnimation.SourceObject}"); } else { ifBlock.Line($"{fieldName}.SubAnimations.Add({subAnimation.PropertyNameInCode()});"); } } } } currentBlock.Line($"return {fieldName};"); }
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 static void CreateInstructionForSubAnimation(ICodeBlock currentBlock, AnimationReferenceSave animationReferenceSave, AbsoluteOrRelative absoluteOrRelative, AnimationSave parentAnimation, StateCodeGeneratorContext context) { currentBlock = currentBlock.Block(); //var instruction = new FlatRedBall.Instructions.DelegateInstruction(() => //FlatRedBall.Instructions.InstructionManager.Instructions.AddRange(ClickableBushInstance.GrowAnimation)); //instruction.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + asdf; //yield return instruction; var isReferencingMissingInstance = !string.IsNullOrEmpty(animationReferenceSave.SourceObject) && context.Element.GetInstance(animationReferenceSave.SourceObject) == null; ////////////////Early Out/////////////// if (isReferencingMissingInstance) { currentBlock.Line($"// This animation references a missing instance named {animationReferenceSave.SourceObject}"); return; } /////////////End Early Out///////////// string animationName = animationReferenceSave.PropertyNameInCode(); //animationReferenceSave. FlatRedBall.IO.FileManager.RemovePath(animationReferenceSave.Name) + "Animation"; if (absoluteOrRelative == AbsoluteOrRelative.Relative) { animationName += "Relative"; } currentBlock.Line($"var instruction = new FlatRedBall.Instructions.DelegateInstruction(()=>{animationName}.Play({parentAnimation.PropertyNameInCode()}));"); currentBlock.Line("instruction.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + ToFloatString(animationReferenceSave.Time) + ";"); currentBlock.Line("yield return instruction;"); currentBlock = currentBlock.End(); }
private void GenerateGetEnumerableFor(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string animationType = "VariableState"; string animationName = animation.PropertyNameInCode(); if (absoluteOrRelative == AbsoluteOrRelative.Relative) { animationName += "Relative"; } string propertyName = animationName + "Instructions"; // Instructions used to be public - the user would grab them and add them to the InstructionManager, // but now everything is encased in an Animation object which handles stopping itself and provides a simple // Play method. const string signature = "private System.Collections.Generic.IEnumerable<FlatRedBall.Instructions.Instruction>"; if (animation.States.Count == 0 && animation.Animations.Count == 0) { currentBlock = currentBlock.Function(signature, propertyName, "object target"); currentBlock.Line("yield break;"); } else if (absoluteOrRelative == AbsoluteOrRelative.Relative && animation.States.Count < 2 && animation.Animations.Count == 0) { currentBlock = currentBlock.Function(signature, propertyName, "object target"); currentBlock.Line("yield break;"); } else { if (animation.States.Count != 0) { var firstState = context.Element.AllStates.FirstOrDefault(item => item.Name == animation.States.First().StateName); var category = context.Element.Categories.FirstOrDefault(item => item.States.Contains(firstState)); if (category != null) { animationType = category.Name; } } currentBlock = currentBlock.Function(signature, propertyName, "object target"); GenerateOrderedStateAndSubAnimationCode(context, currentBlock, animation, animationType, absoluteOrRelative); if (animation.Loops) { currentBlock = currentBlock.Block(); currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( " + "() => FlatRedBall.Instructions.InstructionManager.Instructions.AddRange(this." + propertyName + "(target)));"); string executionTime = "0.0f"; if (animation.States.Count != 0) { executionTime = ToFloatString(animation.States.Last().Time); } currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + executionTime + ";"); currentBlock.Line("toReturn.Target = target;"); currentBlock.Line("yield return toReturn;"); currentBlock = currentBlock.End(); } } }
private void GenerateAnimationMember(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string propertyName = animation.PropertyNameInCode(); if (absoluteOrRelative == AbsoluteOrRelative.Relative) { propertyName += "Relative"; } string referencedInstructionProperty = propertyName + "Instructions"; // Force the property to be upper-case, since the field is lower-case: // We want to generate something like: //private FlatRedBall.Gum.Animation.GumAnimation uncategorizedAnimation; //public FlatRedBall.Gum.Animation.GumAnimation UncategorizedAnimation //{ // get // { // if (uncategorizedAnimation == null) // { // uncategorizedAnimation = new FlatRedBall.Gum.Animation.GumAnimation(1, () => UncategorizedAnimationInstructions); // uncategorizedAnimation.AddEvent("Event1", 3.0f); // } // return uncategorizedAnimation; // } //} var firstCharacterLower = propertyName.Substring(0, 1).ToLowerInvariant(); var fieldName = firstCharacterLower + propertyName.Substring(1); currentBlock.Line($"private FlatRedBall.Gum.Animation.GumAnimation {fieldName};"); currentBlock = currentBlock.Property("public FlatRedBall.Gum.Animation.GumAnimation", propertyName).Get(); float length = GetAnimationLength(context.Element, animation); string lengthAsString = ToFloatString(length); var ifBlock = currentBlock.If($"{fieldName} == null"); { ifBlock.Line( $"{fieldName} = new FlatRedBall.Gum.Animation.GumAnimation({lengthAsString}, () => {referencedInstructionProperty});"); foreach(var namedEvent in animation.Events) { string timeAsString = ToFloatString(namedEvent.Time); ifBlock.Line( $"{fieldName}.AddEvent(\"{namedEvent.Name}\", {timeAsString});"); } foreach(var subAnimation in animation.Animations) { if(string.IsNullOrEmpty(subAnimation.SourceObject) == false) { ifBlock.Line($"{fieldName}.SubAnimations.Add({subAnimation.PropertyNameInCode()});"); } } } currentBlock.Line($"return {fieldName};"); }
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;"); } 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); // vic says - // For some reason I'm getting some weird code generation issues when generating one of my objects for the racing game // I don't have perfect repro steps, so I wanted to catch it in the debugger: //var toReturn = new FlatRedBall.Instructions.DelegateInstruction( () => this.InterpolateTo(VariableState.Shown, 0.25f, FlatRedBall.Glue.StateInterpolation.InterpolationType.Linear, FlatRedBall.Glue.StateInterpolation.Easing.Out, FadeInAnimation)); if (line.Contains("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( () => this.InterpolateTo(VariableState.Shown, 0.25f, FlatRedBall.Glue.StateInterpolation.InterpolationType.Linear, FlatRedBall.Glue.StateInterpolation.Easing.Out, FadeInAnimation));")) { int m = 3; } currentBlock.Line(line); 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("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(); }
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); remainingSubAnimations.RemoveAt(0); } else { currentState = remainingStates[0]; CreateInstructionForInterpolation(context, currentBlock, animationType, previousState, currentState, absoluteOrRelative, animation.PropertyNameInCode()); previousState = currentState; remainingStates.RemoveAt(0); } } }
private void GenerateEnumerableFor(StateCodeGeneratorContext context, ICodeBlock currentBlock, AnimationSave animation, AbsoluteOrRelative absoluteOrRelative) { string animationType = "VariableState"; string animationName = animation.PropertyNameInCode(); if(absoluteOrRelative == AbsoluteOrRelative.Relative) { animationName += "Relative"; } string propertyName = animationName + "Instructions"; // Instructions used to be public - the user would grab them and add them to the InstructionManager, // but now everything is encased in an Animation object which handles stopping itself and provides a simple // Play method. if (animation.States.Count == 0 && animation.Animations.Count == 0) { currentBlock = currentBlock.Property("private System.Collections.Generic.IEnumerable<FlatRedBall.Instructions.Instruction>", propertyName).Get(); currentBlock.Line("yield break;"); } else if(absoluteOrRelative == AbsoluteOrRelative.Relative && animation.States.Count < 2 && animation.Animations.Count == 0) { currentBlock = currentBlock.Property("private System.Collections.Generic.IEnumerable<FlatRedBall.Instructions.Instruction>", propertyName).Get(); currentBlock.Line("yield break;"); } else { if (animation.States.Count != 0) { var firstState = context.Element.AllStates.FirstOrDefault(item => item.Name == animation.States.First().StateName); var category = context.Element.Categories.FirstOrDefault(item => item.States.Contains(firstState)); if (category != null) { animationType = category.Name; } } currentBlock = currentBlock.Property("private System.Collections.Generic.IEnumerable<FlatRedBall.Instructions.Instruction>", propertyName).Get(); GenerateOrderedStateAndSubAnimationCode(context, currentBlock, animation, animationType, absoluteOrRelative); if(animation.Loops) { currentBlock = currentBlock.Block(); currentBlock.Line("var toReturn = new FlatRedBall.Instructions.DelegateInstruction( " + "() => FlatRedBall.Instructions.InstructionManager.Instructions.AddRange(this." + propertyName + "));"); string executionTime = "0.0f"; if(animation.States.Count != 0) { executionTime = ToFloatString( animation.States.Last().Time); } currentBlock.Line("toReturn.TimeToExecute = FlatRedBall.TimeManager.CurrentTime + " + executionTime + ";"); currentBlock.Line("yield return toReturn;"); currentBlock = currentBlock.End(); } } }