private Instruction CreateInstructionFor(object target, string velocityMemberName, object valueBefore, object valueAfter, double timeBetween, double instructionTime, Type typeOfTarget, Type typeOfValue) { Type type = typeof(Instruction <,>).MakeGenericType(typeOfTarget, typeOfValue); object[] arguments = null; if (typeOfValue == typeof(float)) { float difference = (float)valueAfter - (float)valueBefore; if (InstructionManager.IsRotationMember(InstructionManager.GetStateForVelocity(velocityMemberName))) { difference = FlatRedBall.Math.MathFunctions.AngleToAngle((float)valueBefore, (float)valueAfter); } arguments = new object[] { target, velocityMemberName, difference / (float)timeBetween, instructionTime }; } else if (typeOfValue == typeof(double)) { double difference = (double)valueAfter - (double)valueBefore; arguments = new object[] { target, velocityMemberName, difference / (double)timeBetween, instructionTime }; } else if (typeOfValue == typeof(int)) { int difference = (int)valueAfter - (int)valueBefore; arguments = new object[] { target, velocityMemberName, (int)(difference / (double)timeBetween), instructionTime }; } else if (typeOfValue == typeof(long)) { long difference = ((long)valueAfter - (long)valueBefore); arguments = new object[] { target, velocityMemberName, (long)(difference / (double)timeBetween), instructionTime }; } else if (typeOfValue == typeof(byte)) { byte difference = (byte)((byte)valueAfter - (byte)valueBefore); arguments = new object[] { target, velocityMemberName, (byte)(difference / (double)timeBetween), instructionTime }; } else if (typeOfValue == typeof(Vector2)) { Vector2 range = (Vector2)valueAfter - (Vector2)valueBefore; range.X /= (float)timeBetween; range.Y /= (float)timeBetween; arguments = new object[] { target, velocityMemberName, range, instructionTime }; } else if (typeOfValue == typeof(Vector3)) { Vector3 range = (Vector3)valueAfter - (Vector3)valueBefore; range.X /= (float)timeBetween; range.Y /= (float)timeBetween; range.Z /= (float)timeBetween; arguments = new object[] { target, velocityMemberName, range, instructionTime }; } else if (typeOfValue == typeof(Vector4)) { Vector4 range = (Vector4)valueAfter - (Vector4)valueBefore; range.X /= (float)timeBetween; range.Y /= (float)timeBetween; range.Z /= (float)timeBetween; range.W /= (float)timeBetween; arguments = new object[] { target, velocityMemberName, range, instructionTime }; } #if XBOX360 ConstructorInfo ctor = type.GetConstructor( BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeOfTarget, typeof(string), typeOfValue, typeof(double) }, null); return((Instruction)ctor.Invoke(arguments)); #else return((Instruction)Activator.CreateInstance(type, arguments)); #endif }
public InstructionList CreateVelocityListAtIndex(int keyframeIndex) { if (keyframeIndex > Count - 1) { // The user passed either the last instruction index or an out-of-bounds index, // so return an empty list. return(new InstructionList(0)); } else { #region Get keyframeAtIndex and keyframeAfter InstructionList keyframeAtIndex = this[keyframeIndex]; InstructionList keyframeAfter = null; double timeBetween; if (keyframeIndex == Count - 1) { // If it's the last keyframe, use the same keyframe to stop all velocity keyframeAfter = keyframeAtIndex; timeBetween = 1; // To prevent NaN values } else { keyframeAfter = this[keyframeIndex + 1]; timeBetween = keyframeAfter[0].TimeToExecute - keyframeAtIndex[0].TimeToExecute; } #endregion InstructionList instructionList = new InstructionList(); #region Loop through all instructions and create interpolation instructions for (int i = 0; i < keyframeAtIndex.Count; i++) { Instruction instructionAtIndex = keyframeAtIndex[i]; GenericInstruction instructionAtIndexAsGeneric = instructionAtIndex as GenericInstruction; Type typeOfTarget = instructionAtIndexAsGeneric.Target.GetType(); bool shouldInterpolate = instructionAtIndexAsGeneric.MemberValueAsObject != null && instructionAtIndexAsGeneric != null && InstructionManager.HasInterpolatorForType( instructionAtIndexAsGeneric.MemberValueAsObject.GetType()); string velocityMemberName = InstructionManager.GetVelocityForState( instructionAtIndexAsGeneric.Member); if (shouldInterpolate && !string.IsNullOrEmpty(velocityMemberName)) { Type typeOfValue = instructionAtIndexAsGeneric.MemberValueAsObject.GetType(); //bool hasInterpolated = false; GenericInstruction instructionAfterAsGeneric = keyframeAfter[i] as GenericInstruction; if (instructionAfterAsGeneric != null && instructionAtIndexAsGeneric.Target == instructionAfterAsGeneric.Target && instructionAtIndexAsGeneric.Member == instructionAfterAsGeneric.Member) { // We've found the instruction! Create a velocity instruction Instruction instruction = CreateInstructionFor( instructionAtIndexAsGeneric.Target, velocityMemberName, instructionAtIndexAsGeneric.MemberValueAsObject, instructionAfterAsGeneric.MemberValueAsObject, timeBetween, instructionAtIndexAsGeneric.TimeToExecute, typeOfTarget, typeOfValue); instruction.TimeToExecute = instructionAtIndex.TimeToExecute; instructionList.Add(instruction); } } // switch on the Type, but can't use a Switch statement } #endregion return(instructionList); } }
public void SetState(double time, bool setVelocity) { InstructionList keyframeBefore = KeyframeAtOrBefore(time); InstructionList keyframeAfter = KeyframeAtOrAfter(time); if (keyframeBefore == null && keyframeAfter == null) { return; } else if (keyframeBefore == keyframeAfter) { keyframeBefore.Execute(); } else if (keyframeBefore != null && keyframeAfter == null) { keyframeBefore.Execute(); } else if (keyframeAfter != null && keyframeBefore == null) { keyframeAfter.Execute(); } else // the two keyframes are not the same, and neither are null { double timeAfter = keyframeAfter[0].TimeToExecute; double timeBefore = keyframeBefore[0].TimeToExecute; double range = timeAfter - timeBefore; double ratioAfter = (time - timeBefore) / range; double ratioBefore = 1 - ratioAfter; for (int i = 0; i < keyframeBefore.Count; i++) { Instruction instructionBefore = keyframeBefore[i]; GenericInstruction instructionBeforeAsGeneric = instructionBefore as GenericInstruction; object memberValueAsObject = instructionBeforeAsGeneric.MemberValueAsObject; // DO MORE HERE bool shouldInterpolate = instructionBeforeAsGeneric.MemberValueAsObject != null && instructionBeforeAsGeneric != null && InstructionManager.HasInterpolatorForType( instructionBeforeAsGeneric.MemberValueAsObject.GetType()); if (shouldInterpolate) { bool hasInterpolated = false; GenericInstruction instructionAfterAsGeneric = keyframeAfter[i] as GenericInstruction; if (instructionAfterAsGeneric != null && instructionBeforeAsGeneric.Target == instructionAfterAsGeneric.Target && instructionBeforeAsGeneric.Member == instructionAfterAsGeneric.Member) { // We've found the instruction! Interpolate! instructionBeforeAsGeneric.InterpolateBetweenAndExecute(instructionAfterAsGeneric, (float)ratioBefore); hasInterpolated = true; } if (hasInterpolated == false) { // for now, fail. Eventually will want to search the entire KeyframeAfter to see if it // contains a matching instruction for interpolation throw new NotImplementedException("The keyframes instructions do not match up. Cannot interpolate."); } } else { keyframeBefore[i].Execute(); } } } }