// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local private static void AssertStep(PathStepDefinition step) { if (step == null) { throw new ArgumentNullException(nameof(step)); } if (step.X > 255) { throw new ConversionException("Velocity X cannot be larger than 255"); } if (step.Y > 255) { throw new ConversionException("Velocity X cannot be larger than 255"); } }
public void SplitsIntoFrames() { var input = new PathStepDefinition[] { new PathStepDefinition { F = 10, X = 4, Y = 4 }, }; var result = _transformer.TransformPath(input); var expected = Enumerable.Range(0, 10) .Select(_ => new OutputPathStepInfo { FrameCount = 1, VelocityX = 4, VelocityY = 4 }); CollectionAssert.AreEqual(expected.ToStringCollection(), result.ToStringCollection()); }
public void LeavesJumpsAlone() { var input = new PathStepDefinition[] { new PathStepDefinition { F = 2, X = 4, Y = 4 }, new PathStepDefinition { F = 0, X = 0, Y = 0, Instruction = PathInstructionDefinition.Jump, Label = "Vel" }, new PathStepDefinition { F = 2, X = 4, Y = 4 }, }; var result = _transformer.TransformPath(input); var expected = new List <OutputPathStepInfo> { new OutputPathStepInfo { FrameCount = 1, VelocityX = 4, VelocityY = 4 }, new OutputPathStepInfo { FrameCount = 1, VelocityX = 4, VelocityY = 4 }, new OutputPathStepInfo { FrameCount = 0, VelocityX = 0, VelocityY = 0, Instruction = PathInstructionDefinition.Jump, Label = "Vel" }, new OutputPathStepInfo { FrameCount = 1, VelocityX = 4, VelocityY = 4 }, new OutputPathStepInfo { FrameCount = 1, VelocityX = 4, VelocityY = 4 } }; CollectionAssert.AreEqual(expected.ToStringCollection(), result.ToStringCollection()); }
// returns an unoptimized list of step infos public IEnumerable <OutputPathStepInfo> TransformPath(IEnumerable <PathStepDefinition> steps) { PathStepDefinition previousStep = null; //new PathStepDefinition {X = 0, Y=-0}; PathStepDefinition currentStep = null; foreach (var nextStep in steps.Concat(new List <PathStepDefinition> { new PathStepDefinition { X = 0, Y = 0, Instruction = PathInstructionDefinition.End } })) { if (currentStep == null) { currentStep = nextStep; previousStep = new PathStepDefinition { X = 0, Y = 0 }; } else { if (currentStep.Instruction == PathInstructionDefinition.Delta) { var labelEmitted = string.IsNullOrWhiteSpace(currentStep.Label); AssertStep(currentStep); for (int t = 0; t < currentStep.F; t++) { // Linear blending var inMix = -(t - currentStep.In + 0.5) / currentStep.In; var outMix = (t + 0.5 - (currentStep.F - currentStep.Out)) / currentStep.Out; inMix = Math.Max(inMix, 0); outMix = Math.Max(outMix, 0); var curMix = 1 - inMix - outMix; yield return(new OutputPathStepInfo { FrameCount = 1, VelocityX = DoubleToShort( ((currentStep.X * curMix + previousStep.X * inMix + nextStep.X * outMix) / (inMix + outMix + curMix))), VelocityY = DoubleToShort( ((currentStep.Y * curMix + previousStep.Y * inMix + nextStep.Y * outMix) / (inMix + outMix + curMix))), Label = labelEmitted ? null : currentStep.Label, }); labelEmitted = true; } } else { yield return(new OutputPathStepInfo { Label = currentStep.Label, Instruction = currentStep.Instruction, VelocityX = (short)currentStep.X, VelocityY = (short)currentStep.Y, }); } previousStep = currentStep; currentStep = nextStep; } } }