public static void animationNormalizeTrack(xaAnimationKeyframe[] origKeyframes, xaAnimationKeyframe[] destKeyframes, int count) { xaAnimationKeyframe keyframeToCopy; if (origKeyframes.Length > 0) { keyframeToCopy = origKeyframes[origKeyframes.Length - 1]; } else { keyframeToCopy = new xaAnimationKeyframe(); keyframeToCopy.Rotation = Quaternion.Identity; keyframeToCopy.Scaling = new Vector3(1, 1, 1); keyframeToCopy.Translation = new Vector3(0, 0, 0); CreateUnknowns(keyframeToCopy); } for (int j = origKeyframes.Length; j < count; j++) { xaAnimationKeyframe copy = new xaAnimationKeyframe(); copy.Index = j; copy.Rotation = keyframeToCopy.Rotation; copy.Scaling = keyframeToCopy.Scaling; copy.Translation = keyframeToCopy.Translation; CreateUnknowns(copy); destKeyframes[j] = copy; } }
public static void animationCopyKeyframeTransformArray(xaAnimationKeyframe[] src, int srcIdx, xaAnimationKeyframe[] dest, int destIdx, int count) { for (int i = 0; i < count; i++) { xaAnimationKeyframe keyframe = src[srcIdx + i]; keyframe.Index = destIdx + i; dest[destIdx + i] = keyframe; } }
public static void animationCopyKeyframeTransformArray(xaAnimationKeyframe[] src, xaAnimationKeyframe[] dest, int destOffset) { for (int i = 0; i < src.Length; i++) { xaAnimationKeyframe keyframe = src[i]; keyframe.Index += destOffset; dest[keyframe.Index] = keyframe; } }
public static xaAnimationKeyframe[] animationGetOriginalKeyframes(Dictionary<string, xaAnimationTrack> animationNodeDic, string trackName, List<xaAnimationTrack> animationNodeList, out xaAnimationTrack animationNode) { animationNode = animationGetOriginalKeyframes(animationNodeDic, trackName, animationNodeList); xaAnimationKeyframe[] origKeyframes; if (animationNode.KeyframeList != null) { origKeyframes = animationNode.KeyframeList.ToArray(); } else { origKeyframes = new xaAnimationKeyframe[0]; } return origKeyframes; }
public static xaAnimationKeyframe[] animationGetOriginalKeyframes(Dictionary<string, xaAnimationTrack> animationNodeDic, string trackName, List<xaAnimationTrack> animationNodeList, out xaAnimationTrack animationNode) { xaAnimationKeyframe[] origKeyframes; if (animationNodeDic.TryGetValue(trackName, out animationNode)) { origKeyframes = animationNode.KeyframeList.ToArray(); } else { animationNode = new xaAnimationTrack(); animationNodeList.Add(animationNode); animationNode.Name = trackName; CreateUnknowns(animationNode); origKeyframes = new xaAnimationKeyframe[0]; } return origKeyframes; }
private xaAnimationKeyframe AddKeyframe(xaAnimationTrack track, int index, int i) { xaAnimationKeyframe keyframe = new xaAnimationKeyframe(); keyframe.Index = index; xa.CreateUnknowns(keyframe); if (i < track.KeyframeList.Count) { if (i > 0) { int predIdx = track.KeyframeList[i - 1].Index; float indexPosition = (float)(index - predIdx) / (track.KeyframeList[i].Index - predIdx); keyframe.Scaling = track.KeyframeList[i - 1].Scaling + (track.KeyframeList[i].Scaling - track.KeyframeList[i - 1].Scaling) * indexPosition; keyframe.Rotation = track.KeyframeList[i - 1].Rotation + (track.KeyframeList[i].Rotation - track.KeyframeList[i - 1].Rotation) * indexPosition; keyframe.Translation = track.KeyframeList[i - 1].Translation + (track.KeyframeList[i].Translation - track.KeyframeList[i - 1].Translation) * indexPosition; } else { keyframe.Scaling = track.KeyframeList[i].Scaling; keyframe.Rotation = track.KeyframeList[i].Rotation; keyframe.Translation = track.KeyframeList[i].Translation; } } else { keyframe.Scaling = track.KeyframeList[track.KeyframeList.Count - 1].Scaling; keyframe.Rotation = track.KeyframeList[track.KeyframeList.Count - 1].Rotation; keyframe.Translation = track.KeyframeList[track.KeyframeList.Count - 1].Translation; } track.KeyframeList.Insert(i, keyframe); Changed = true; return keyframe; }
public static void ReplaceAnimation(WorkspaceAnimation wsAnimation, xaParser parser, int resampleCount, ReplaceAnimationMethod replaceMethod, int insertPos) { if (parser.AnimationSection == null) { Report.ReportLog("The .xa file doesn't have an animation section. Skipping this animation"); return; } if (!(wsAnimation.importedAnimation is ImportedKeyframedAnimation)) { Report.ReportLog("The animation has incompatible keyframes."); return; } Report.ReportLog("Replacing animation ..."); List<ImportedAnimationKeyframedTrack> trackList = ((ImportedKeyframedAnimation)wsAnimation.importedAnimation).TrackList; List<KeyValuePair<string, xaAnimationKeyframe[]>> newTrackList = new List<KeyValuePair<string, xaAnimationKeyframe[]>>(trackList.Count); List<Tuple<ImportedAnimationTrack, xaAnimationKeyframe[]>> interpolateTracks = new List<Tuple<ImportedAnimationTrack,xaAnimationKeyframe[]>>(); foreach (var wsTrack in trackList) { if (!wsAnimation.isTrackEnabled(wsTrack)) continue; ImportedAnimationKeyframe[] keyframes = ((ImportedAnimationKeyframedTrack)wsTrack).Keyframes; xaAnimationKeyframe[] newKeyframes = null; int wsTrackKeyframesLength = 0; for (int i = 0; i < keyframes.Length; i++) { if (keyframes[i] != null) wsTrackKeyframesLength++; } if (resampleCount < 0 || wsTrackKeyframesLength == resampleCount) { newKeyframes = new xaAnimationKeyframe[wsTrackKeyframesLength]; int keyframeIdx = 0; for (int i = 0; i < keyframes.Length; i++) { ImportedAnimationKeyframe keyframe = keyframes[i]; if (keyframe == null) continue; newKeyframes[keyframeIdx] = new xaAnimationKeyframe(); newKeyframes[keyframeIdx].Index = i; newKeyframes[keyframeIdx].Rotation = keyframe.Rotation; xa.CreateUnknowns(newKeyframes[keyframeIdx]); newKeyframes[keyframeIdx].Translation = keyframe.Translation; newKeyframes[keyframeIdx].Scaling = keyframe.Scaling; keyframeIdx++; } } else { newKeyframes = new xaAnimationKeyframe[resampleCount]; if (wsTrackKeyframesLength < 1) { xaAnimationKeyframe keyframe = new xaAnimationKeyframe(); keyframe.Rotation = Quaternion.Identity; keyframe.Scaling = new Vector3(1, 1, 1); keyframe.Translation = new Vector3(0, 0, 0); xa.CreateUnknowns(keyframe); for (int i = 0; i < newKeyframes.Length; i++) { keyframe.Index = i; newKeyframes[i] = keyframe; } } else { interpolateTracks.Add(new Tuple<ImportedAnimationTrack, xaAnimationKeyframe[]>(wsTrack, newKeyframes)); } } newTrackList.Add(new KeyValuePair<string, xaAnimationKeyframe[]>(wsTrack.Name, newKeyframes)); } if (interpolateTracks.Count > 0) { Fbx.InterpolateKeyframes(interpolateTracks, resampleCount); } List<xaAnimationTrack> animationNodeList = parser.AnimationSection.TrackList; Dictionary<string, xaAnimationTrack> animationNodeDic = null; if (replaceMethod != ReplaceAnimationMethod.Replace) { animationNodeDic = new Dictionary<string, xaAnimationTrack>(); foreach (xaAnimationTrack animationNode in animationNodeList) { animationNodeDic.Add(animationNode.Name, animationNode); } } if (replaceMethod == ReplaceAnimationMethod.Replace) { animationNodeList.Clear(); foreach (var newTrack in newTrackList) { xaAnimationTrack animationNode = new xaAnimationTrack(); animationNodeList.Add(animationNode); animationNode.KeyframeList = new List<xaAnimationKeyframe>(newTrack.Value); animationNode.Name = newTrack.Key; xa.CreateUnknowns(animationNode); } } else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent) { foreach (var newTrack in newTrackList) { xaAnimationTrack animationNode = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList); animationNode.KeyframeList = new List<xaAnimationKeyframe>(newTrack.Value); } } else if (replaceMethod == ReplaceAnimationMethod.Merge) { foreach (var newTrack in newTrackList) { xaAnimationTrack animationNode; xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode); xaAnimationKeyframe[] destKeyframes; int newEnd = insertPos + newTrack.Value.Length; if (origKeyframes.Length < insertPos) { destKeyframes = new xaAnimationKeyframe[newEnd]; xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length); xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos); } else { if (origKeyframes.Length < newEnd) { destKeyframes = new xaAnimationKeyframe[newEnd]; } else { destKeyframes = new xaAnimationKeyframe[origKeyframes.Length]; xa.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd); } xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos); } xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length); animationNode.KeyframeList = new List<xaAnimationKeyframe>(destKeyframes); } } else if (replaceMethod == ReplaceAnimationMethod.Insert) { foreach (var newTrack in newTrackList) { xaAnimationTrack animationNode; xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode); ; xaAnimationKeyframe[] destKeyframes; int newEnd = insertPos + newTrack.Value.Length; if (origKeyframes.Length < insertPos) { destKeyframes = new xaAnimationKeyframe[newEnd]; xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length); xa.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos); } else { destKeyframes = new xaAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length]; xa.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos); xa.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos); } xa.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length); animationNode.KeyframeList = new List<xaAnimationKeyframe>(destKeyframes); } } else if (replaceMethod == ReplaceAnimationMethod.Append) { int maxKeyframes = 0; foreach (xaAnimationTrack animationNode in animationNodeList) { int numKeyframes = animationNode.KeyframeList[animationNode.KeyframeList.Count - 1].Index; if (numKeyframes > maxKeyframes) { maxKeyframes = numKeyframes; } } foreach (var newTrack in newTrackList) { xaAnimationTrack animationNode; xaAnimationKeyframe[] origKeyframes = xa.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, animationNodeList, out animationNode); xaAnimationKeyframe[] destKeyframes = new xaAnimationKeyframe[maxKeyframes + insertPos + newTrack.Value[newTrack.Value.Length - 1].Index + 1]; xa.animationCopyKeyframeTransformArray(origKeyframes, destKeyframes, 0); if (origKeyframes.Length > 0 && origKeyframes.Length == origKeyframes[origKeyframes.Length - 1].Index + 1) { xa.animationNormalizeTrack(origKeyframes, destKeyframes, origKeyframes.Length + insertPos); } xa.animationCopyKeyframeTransformArray(newTrack.Value, destKeyframes, maxKeyframes + insertPos); animationNode.KeyframeList = new List<xaAnimationKeyframe>(origKeyframes.Length + insertPos + newTrack.Value.Length); for (int i = 0; i < destKeyframes.Length; i++) { if (destKeyframes[i] == null) continue; animationNode.KeyframeList.Add(destKeyframes[i]); } } } else { Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation"); return; } }
public void CopyTrack(string track) { xaAnimationTrack src = xa.FindTrack(track, Parser); xaAnimationTrack cpy = new xaAnimationTrack(); cpy.Name = src.Name + "_copy"; cpy.Unknown1 = (byte[])src.Unknown1.Clone(); cpy.KeyframeList = new List<xaAnimationKeyframe>(src.KeyframeList.Count); foreach (xaAnimationKeyframe srcKeyframe in src.KeyframeList) { xaAnimationKeyframe cpyKeyframe = new xaAnimationKeyframe(); cpyKeyframe.Index = srcKeyframe.Index; cpyKeyframe.Rotation = srcKeyframe.Rotation; cpyKeyframe.Unknown1 = (byte[])srcKeyframe.Unknown1.Clone(); cpyKeyframe.Translation = srcKeyframe.Translation; cpyKeyframe.Scaling = srcKeyframe.Scaling; cpy.KeyframeList.Add(cpyKeyframe); } Parser.AnimationSection.TrackList.Add(cpy); Changed = true; }
public static void CreateUnknowns(xaAnimationKeyframe keyframe) { keyframe.Unknown1 = new byte[8]; }
protected xaAnimationSection ParseAnimationSection() { if (reader.ReadByte() == 0) { return null; } xaAnimationSection section = new xaAnimationSection(); int numClips; if (Format == 0x03) { numClips = 1024; } else { numClips = 512; } section.ClipList = new List<xaAnimationClip>(numClips); for (int i = 0; i < numClips; i++) { xaAnimationClip clip = new xaAnimationClip(); section.ClipList.Add(clip); clip.Name = reader.ReadName(64); clip.Speed = reader.ReadSingle(); clip.Unknown1 = reader.ReadBytes(4); clip.Start = reader.ReadSingle(); clip.End = reader.ReadSingle(); clip.Unknown2 = reader.ReadBytes(1); clip.Unknown3 = reader.ReadBytes(1); clip.Unknown4 = reader.ReadBytes(1); clip.Next = reader.ReadInt32(); clip.Unknown5 = reader.ReadBytes(1); clip.Unknown6 = reader.ReadBytes(4); clip.Unknown7 = reader.ReadBytes(16); } int numTracks = reader.ReadInt32(); section.TrackList = new List<xaAnimationTrack>(numTracks); for (int i = 0; i < numTracks; i++) { xaAnimationTrack track = new xaAnimationTrack(); section.TrackList.Add(track); track.Name = reader.ReadName(); int numKeyframes = reader.ReadInt32(); track.Unknown1 = reader.ReadBytes(4); track.KeyframeList = new List<xaAnimationKeyframe>(numKeyframes); for (int j = 0; j < numKeyframes; j++) { xaAnimationKeyframe keyframe = new xaAnimationKeyframe(); track.KeyframeList.Add(keyframe); keyframe.Index = reader.ReadInt32(); keyframe.Rotation = reader.ReadQuaternion(); keyframe.Unknown1 = reader.ReadBytes(8); keyframe.Translation = reader.ReadVector3(); keyframe.Scaling = reader.ReadVector3(); } } return section; }