public static void animationNormalizeTrack(ImportedAnimationSampledTrack origSamples, ImportedAnimationSampledTrack destSamples, int count) { Vector3? scaleKeyCopy; Quaternion?rotateKeyCopy; Vector3? translateKeyCopy; float? morphKeyCopy; if (origSamples.Scalings.Length > 0) { scaleKeyCopy = origSamples.Scalings[origSamples.Scalings.Length - 1]; rotateKeyCopy = origSamples.Rotations[origSamples.Rotations.Length - 1]; translateKeyCopy = origSamples.Translations[origSamples.Translations.Length - 1]; morphKeyCopy = origSamples.Curve[origSamples.Curve.Length - 1]; } else { scaleKeyCopy = new Vector3(1, 1, 1); rotateKeyCopy = Quaternion.Identity; translateKeyCopy = new Vector3(0, 0, 0); morphKeyCopy = 0; } for (int j = origSamples.Scalings.Length; j < count; j++) { destSamples.Scalings[j] = scaleKeyCopy; destSamples.Rotations[j] = rotateKeyCopy; destSamples.Translations[j] = translateKeyCopy; destSamples.Curve[j] = morphKeyCopy; } }
public static ImportedAnimationSampledTrack animationGetOriginalSamples(Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, string trackName, List <ImportedAnimationSampledTrack> animationNodeList) { ImportedAnimationSampledTrack animationNode; if (!animationNodeDic.TryGetValue(trackName, out animationNode)) { animationNode = new ImportedAnimationSampledTrack(); animationNodeList.Add(animationNode); animationNode.Name = trackName; } return(animationNode); }
public static void animationCopySampleTransformArray(ImportedAnimationSampledTrack src, int srcIdx, ImportedAnimationSampledTrack dest, int destIdx, int count) { for (int i = 0; i < count; i++) { Vector3?scaleKey = src.Scalings[srcIdx + i]; dest.Scalings[destIdx + i] = scaleKey; Quaternion?rotateKey = src.Rotations[srcIdx + i]; dest.Rotations[destIdx + i] = rotateKey; Vector3?translateKey = src.Translations[srcIdx + i]; dest.Translations[destIdx + i] = translateKey; } }
public static ImportedAnimationSampledTrack animationGetOriginalSamples(Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, string trackName, ImportedSampledAnimation anim, out ImportedAnimationSampledTrack animationNode) { animationNode = animationGetOriginalSamples(animationNodeDic, trackName, anim.TrackList); ImportedAnimationSampledTrack origKeyframes; if (animationNode.Scalings != null) { origKeyframes = animationNode; } else { origKeyframes = new ImportedAnimationSampledTrack(); origKeyframes.Scalings = new Vector3?[0]; origKeyframes.Rotations = new Quaternion?[0]; origKeyframes.Translations = new Vector3?[0]; } return(origKeyframes); }
public static void animationCopySampleTransformArray(ImportedAnimationSampledTrack src, ImportedAnimationSampledTrack dest, int destOffset) { for (int i = 0; i < src.Scalings.Length; i++) { Vector3?scaleKey = src.Scalings[i]; dest.Scalings[i + destOffset] = scaleKey; } for (int i = 0; i < src.Rotations.Length; i++) { Quaternion?rotateKey = src.Rotations[i]; dest.Rotations[i + destOffset] = rotateKey; } for (int i = 0; i < src.Translations.Length; i++) { Vector3?translateKey = src.Translations[i]; dest.Translations[i + destOffset] = translateKey; } }
private void treeView_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Node.Tag is ImportedSubmesh) { TreeNode submeshNode = e.Node; ImportedSubmesh submesh = (ImportedSubmesh)submeshNode.Tag; TreeNode meshNode = submeshNode.Parent; DragSource dragSrc = (DragSource)meshNode.Tag; var srcEditor = (ImportedEditor)Gui.Scripting.Variables[dragSrc.Variable]; srcEditor.Meshes[(int)dragSrc.Id].setSubmeshEnabled(submesh, submeshNode.Checked); } else if (e.Node.Tag is ImportedMorphKeyframe) { TreeNode keyframeNode = e.Node; ImportedMorphKeyframe keyframe = (ImportedMorphKeyframe)keyframeNode.Tag; TreeNode morphNode = keyframeNode.Parent; DragSource dragSrc = (DragSource)morphNode.Tag; var srcEditor = (ImportedEditor)Gui.Scripting.Variables[dragSrc.Variable]; srcEditor.Morphs[(int)dragSrc.Id].setMorphKeyframeEnabled(keyframe, keyframeNode.Checked); } else if (e.Node.Tag is ImportedAnimationKeyframedTrack) { TreeNode trackNode = e.Node; ImportedAnimationKeyframedTrack track = (ImportedAnimationKeyframedTrack)trackNode.Tag; TreeNode animationNode = trackNode.Parent; DragSource dragSrc = (DragSource)animationNode.Tag; var srcEditor = (ImportedEditor)Gui.Scripting.Variables[dragSrc.Variable]; srcEditor.Animations[(int)dragSrc.Id].setTrackEnabled(track, trackNode.Checked); } else if (e.Node.Tag is ImportedAnimationSampledTrack) { TreeNode trackNode = e.Node; ImportedAnimationSampledTrack track = (ImportedAnimationSampledTrack)trackNode.Tag; TreeNode animationNode = trackNode.Parent; DragSource dragSrc = (DragSource)animationNode.Tag; var srcEditor = (ImportedEditor)Gui.Scripting.Variables[dragSrc.Variable]; srcEditor.Animations[(int)dragSrc.Id].setTrackEnabled(track, trackNode.Checked); } }
public static void UpdateAnimationNode(TreeNode node, WorkspaceAnimation animation) { int id = (int)((DragSource)node.Tag).Id; if (animation.importedAnimation is ImportedKeyframedAnimation) { node.Text = "Animation" + id; List <ImportedAnimationKeyframedTrack> trackList = ((ImportedKeyframedAnimation)animation.importedAnimation).TrackList; for (int i = 0; i < trackList.Count; i++) { ImportedAnimationKeyframedTrack track = trackList[i]; TreeNode trackNode = node.Nodes[i]; trackNode.Tag = track; int numKeyframes = 0; foreach (ImportedAnimationKeyframe keyframe in track.Keyframes) { if (keyframe != null) { numKeyframes++; } } trackNode.Text = "Track: " + track.Name + ", Keyframes: " + numKeyframes; } } else if (animation.importedAnimation is ImportedSampledAnimation) { node.Text = "Animation(Reduced Keys)" + id; List <ImportedAnimationSampledTrack> trackList = ((ImportedSampledAnimation)animation.importedAnimation).TrackList; for (int i = 0; i < trackList.Count; i++) { ImportedAnimationSampledTrack track = trackList[i]; TreeNode trackNode = node.Nodes[i]; trackNode.Tag = track; int numScalings = 0; for (int k = 0; k < track.Scalings.Length; k++) { if (track.Scalings[k] != null) { numScalings++; } } int numRotations = 0; for (int k = 0; k < track.Rotations.Length; k++) { if (track.Rotations[k] != null) { numRotations++; } } int numTranslations = 0; for (int k = 0; k < track.Translations.Length; k++) { if (track.Translations[k] != null) { numTranslations++; } } trackNode.Text = "Track: " + track.Name + ", Length: " + track.Scalings.Length + ", Scalings: " + numScalings + ", Rotations: " + numRotations + ", Translations: " + numTranslations; } } }
private void AddList <T>(List <T> list, string rootName, string editorVar) { if ((list != null) && (list.Count > 0)) { TreeNode root = new TreeNode(rootName); root.Checked = true; this.treeView.AddChild(root); for (int i = 0; i < list.Count; i++) { dynamic item = list[i]; TreeNode node = new TreeNode(item is WorkspaceAnimation ? ((WorkspaceAnimation)item).importedAnimation is ImportedKeyframedAnimation ? "Animation" + i : "Animation(Reduced Keys)" + i : item.Name); node.Checked = true; node.Tag = new DragSource(editorVar, typeof(T), i); this.treeView.AddChild(root, node); if (item is WorkspaceMesh) { WorkspaceMesh mesh = item; for (int j = 0; j < mesh.SubmeshList.Count; j++) { ImportedSubmesh submesh = mesh.SubmeshList[j]; TreeNode submeshNode = new TreeNode(); submeshNode.Checked = mesh.isSubmeshEnabled(submesh); submeshNode.Tag = submesh; submeshNode.ContextMenuStrip = this.contextMenuStripSubmesh; this.treeView.AddChild(node, submeshNode); UpdateSubmeshNode(submeshNode); } } else if (item is WorkspaceMorph) { WorkspaceMorph morph = item; string extraInfo = morph.MorphedVertexIndices != null ? " (morphed vertices: " + morph.MorphedVertexIndices.Count : String.Empty; extraInfo += (extraInfo.Length == 0 ? " (" : ", ") + "keyframes: " + morph.KeyframeList.Count + ")"; node.Text += extraInfo; for (int j = 0; j < morph.KeyframeList.Count; j++) { ImportedMorphKeyframe keyframe = morph.KeyframeList[j]; TreeNode keyframeNode = new TreeNode(); keyframeNode.Checked = morph.isMorphKeyframeEnabled(keyframe); keyframeNode.Tag = keyframe; keyframeNode.ContextMenuStrip = this.contextMenuStripMorphKeyframe; this.treeView.AddChild(node, keyframeNode); UpdateMorphKeyframeNode(keyframeNode); } } else if (item is WorkspaceAnimation) { WorkspaceAnimation animation = item; if (animation.importedAnimation is ImportedKeyframedAnimation) { List <ImportedAnimationKeyframedTrack> trackList = ((ImportedKeyframedAnimation)animation.importedAnimation).TrackList; for (int j = 0; j < trackList.Count; j++) { ImportedAnimationKeyframedTrack track = trackList[j]; TreeNode trackNode = new TreeNode(); trackNode.Checked = animation.isTrackEnabled(track); trackNode.Tag = track; int numKeyframes = 0; foreach (ImportedAnimationKeyframe keyframe in track.Keyframes) { if (keyframe != null) { numKeyframes++; } } trackNode.Text = "Track: " + track.Name + ", Keyframes: " + numKeyframes; this.treeView.AddChild(node, trackNode); } } else if (animation.importedAnimation is ImportedSampledAnimation) { List <ImportedAnimationSampledTrack> trackList = ((ImportedSampledAnimation)animation.importedAnimation).TrackList; for (int j = 0; j < trackList.Count; j++) { ImportedAnimationSampledTrack track = trackList[j]; TreeNode trackNode = new TreeNode(); trackNode.Checked = animation.isTrackEnabled(track); trackNode.Tag = track; int numScalings = 0; for (int k = 0; k < track.Scalings.Length; k++) { if (track.Scalings[k] != null) { numScalings++; } } int numRotations = 0; for (int k = 0; k < track.Rotations.Length; k++) { if (track.Rotations[k] != null) { numRotations++; } } int numTranslations = 0; for (int k = 0; k < track.Translations.Length; k++) { if (track.Translations[k] != null) { numTranslations++; } } trackNode.Text = "Track: " + track.Name + ", Length: " + track.Scalings.Length + ", Scalings: " + numScalings + ", Rotations: " + numRotations + ", Translations: " + numTranslations; this.treeView.AddChild(node, trackNode); } } } } } }
public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList, ImportedSampledAnimation iAnim, Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, bool negateQuaternions, float filterTolerance) { if (replaceMethod == ReplaceAnimationMethod.Replace) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack iTrack = new ImportedAnimationSampledTrack(); iAnim.TrackList.Add(iTrack); iTrack.Name = newTrack.Key; iTrack.Scalings = newTrack.Value.Scalings; iTrack.Rotations = newTrack.Value.Rotations; iTrack.Translations = newTrack.Value.Translations; iTrack.Curve = newTrack.Value.Curve; } } else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim.TrackList); animationNode.Scalings = newTrack.Value.Scalings; animationNode.Rotations = newTrack.Value.Rotations; animationNode.Translations = newTrack.Value.Translations; animationNode.Curve = newTrack.Value.Curve; } } else if (replaceMethod == ReplaceAnimationMethod.Merge) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples; int newEnd = insertPos + newTrack.Value.Scalings.Length; if (origSamples.Scalings.Length < insertPos) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; destSamples.Curve = new float?[newEnd]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length); animationNormalizeTrack(origSamples, destSamples, insertPos); } else { if (origSamples.Scalings.Length < newEnd) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; destSamples.Curve = new float?[newEnd]; } else { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length]; destSamples.Curve = new float?[origSamples.Curve.Length]; animationCopySampleTransformArray(origSamples, newEnd, destSamples, newEnd, origSamples.Scalings.Length - newEnd); } animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos); } animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; animationNode.Curve = destSamples.Curve; } } else if (replaceMethod == ReplaceAnimationMethod.Insert) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples; int newEnd = insertPos + newTrack.Value.Scalings.Length; if (origSamples.Scalings.Length < insertPos) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; destSamples.Curve = new float?[newEnd]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length); animationNormalizeTrack(origSamples, destSamples, insertPos); } else { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length + newTrack.Value.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length + newTrack.Value.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length + newTrack.Value.Translations.Length]; destSamples.Curve = new float?[origSamples.Curve.Length + newTrack.Value.Curve.Length]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos); animationCopySampleTransformArray(origSamples, insertPos, destSamples, newEnd, origSamples.Scalings.Length - insertPos); } animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; animationNode.Curve = destSamples.Curve; } } else if (replaceMethod == ReplaceAnimationMethod.Append) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length + insertPos + newTrack.Value.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length + insertPos + newTrack.Value.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length + insertPos + newTrack.Value.Translations.Length]; destSamples.Curve = new float?[origSamples.Curve.Length + insertPos + newTrack.Value.Curve.Length]; animationCopySampleTransformArray(origSamples, destSamples, 0); bool reduced = false; for (int i = 0; i < origSamples.Scalings.Length; i++) { if (origSamples.Scalings[i] == null) { reduced = true; break; } } if (origSamples.Scalings.Length > 0 && !reduced) { animationNormalizeTrack(origSamples, destSamples, origSamples.Scalings.Length + insertPos); } animationCopySampleTransformArray(newTrack.Value, destSamples, origSamples.Scalings.Length + insertPos); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; animationNode.Curve = destSamples.Curve; } } else { Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation"); return; } if (negateQuaternions) { float thresholdPos = 180.0f - filterTolerance; float thresholdNeg = -180.0f + filterTolerance; foreach (var newTrack in iAnim.TrackList) { if (newTrack.Rotations == null) { continue; } Quaternion lastQ = Quaternion.Identity; Vector3 lastE = Vector3.Zero; Vector3 diffE = Vector3.Zero; bool flip = false; for (int i = 0, lastUsed_keyIndex = -1; i < newTrack.Rotations.Length; i++) { if (newTrack.Rotations[i] == null) { continue; } Quaternion q = newTrack.Rotations[i].Value; Vector3 e = FbxUtility.QuaternionToEuler(q); if (lastUsed_keyIndex >= 0) { if (lastE.X - diffE.X > thresholdPos && e.X < thresholdNeg) { diffE.X += 360; flip ^= true; } else if (lastE.X - diffE.X < thresholdNeg && e.X > thresholdPos) { diffE.X -= 360; flip ^= true; } e.X += diffE.X; if (lastE.Y - diffE.Y > thresholdPos && e.Y < thresholdNeg) { diffE.Y += 360; flip ^= true; } else if (lastE.Y - diffE.Y < thresholdNeg && e.Y > thresholdPos) { diffE.Y -= 360; flip ^= true; } e.Y += diffE.Y; if (lastE.Z - diffE.Z > thresholdPos && e.Z < thresholdNeg) { diffE.Z += 360; flip ^= true; } else if (lastE.Z - diffE.Z < thresholdNeg && e.Z > thresholdPos) { diffE.Z -= 360; flip ^= true; } e.Z += diffE.Z; if (flip) { q.X = -q.X; q.Y = -q.Y; q.Z = -q.Z; q.W = -q.W; newTrack.Rotations[i] = q; } bool diffX = Math.Sign(lastQ.X) != Math.Sign(q.X); bool diffY = Math.Sign(lastQ.Y) != Math.Sign(q.Y); bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z); bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W); if ((diffX || diffY || diffZ) && diffW) { q.X = -q.X; q.Y = -q.Y; q.Z = -q.Z; q.W = -q.W; newTrack.Rotations[i] = q; } } lastQ = q; lastE = e; lastUsed_keyIndex = i; } } } }
public static List <KeyValuePair <string, ImportedAnimationSampledTrack> > CopySampledAnimation(WorkspaceAnimation wsAnimation, int resampleCount, bool linear, bool EulerFilter, float filterPrecision, bool forceInterpolation = false) { List <ImportedAnimationSampledTrack> trackList = ((ImportedSampledAnimation)wsAnimation.importedAnimation).TrackList; List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList = new List <KeyValuePair <string, ImportedAnimationSampledTrack> >(trackList.Count); List <Tuple <ImportedAnimationTrack, ImportedAnimationSampledTrack> > interpolateTracks = new List <Tuple <ImportedAnimationTrack, ImportedAnimationSampledTrack> >(); foreach (var wsTrack in trackList) { if (!wsAnimation.isTrackEnabled(wsTrack)) { continue; } ImportedAnimationSampledTrack track = new ImportedAnimationSampledTrack(); bool interpolateTrack = forceInterpolation; Vector3?[] newScalings = null; Quaternion?[] newRotations = null; Vector3?[] newTranslations = null; if (!interpolateTrack) { Vector3?[] scalings = wsTrack.Scalings; if (scalings != null) { if (resampleCount < 0 || scalings.Length == resampleCount) { newScalings = new Vector3?[scalings.Length]; for (int i = 0; i < scalings.Length; i++) { Vector3?scale = scalings[i]; if (scale == null) { continue; } newScalings[i] = scale.Value; } } else { if (scalings.Length < 1) { newScalings = new Vector3?[resampleCount]; for (int i = 0; i < newScalings.Length; i++) { newScalings[i] = new Vector3(1, 1, 1); } } else { interpolateTrack = true; } } } Quaternion?[] rotations = wsTrack.Rotations; if (rotations != null) { if (resampleCount < 0 || rotations.Length == resampleCount) { newRotations = new Quaternion?[rotations.Length]; for (int i = 0; i < rotations.Length; i++) { Quaternion?rotate = rotations[i]; if (rotate == null) { continue; } newRotations[i] = rotate.Value; } } else { if (rotations.Length < 1) { newRotations = new Quaternion?[resampleCount]; for (int i = 0; i < newRotations.Length; i++) { newRotations[i] = Quaternion.Identity; } } else { interpolateTrack = true; } } } Vector3?[] translations = wsTrack.Translations; if (translations != null) { if (resampleCount < 0 || translations.Length == resampleCount) { newTranslations = new Vector3?[translations.Length]; for (int i = 0; i < translations.Length; i++) { Vector3?translate = translations[i]; if (translate == null) { continue; } newTranslations[i] = translate.Value; } } else { if (translations.Length < 1) { newTranslations = new Vector3?[resampleCount]; for (int i = 0; i < newTranslations.Length; i++) { newTranslations[i] = new Vector3(0, 0, 0); } } else { interpolateTrack = true; } } } } if (interpolateTrack) { interpolateTracks.Add(new Tuple <ImportedAnimationTrack, ImportedAnimationSampledTrack>(wsTrack, track)); } track.Scalings = newScalings; track.Rotations = newRotations; track.Translations = newTranslations; newTrackList.Add(new KeyValuePair <string, ImportedAnimationSampledTrack>(wsTrack.Name, track)); } if (interpolateTracks.Count > 0) { Fbx.InterpolateSampledTracks(interpolateTracks, resampleCount, linear, EulerFilter, filterPrecision); } return(newTrackList); }
public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List <KeyValuePair <string, ImportedAnimationSampledTrack> > newTrackList, ImportedSampledAnimation iAnim, Dictionary <string, ImportedAnimationSampledTrack> animationNodeDic, bool negateQuaternionFlips) { if (replaceMethod == ReplaceAnimationMethod.Replace) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack iTrack = new ImportedAnimationSampledTrack(); iAnim.TrackList.Add(iTrack); iTrack.Name = newTrack.Key; iTrack.Scalings = newTrack.Value.Scalings; iTrack.Rotations = newTrack.Value.Rotations; iTrack.Translations = newTrack.Value.Translations; } } else if (replaceMethod == ReplaceAnimationMethod.ReplacePresent) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim.TrackList); animationNode.Scalings = newTrack.Value.Scalings; animationNode.Rotations = newTrack.Value.Rotations; animationNode.Translations = newTrack.Value.Translations; } } else if (replaceMethod == ReplaceAnimationMethod.Merge) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples; int newEnd = insertPos + newTrack.Value.Scalings.Length; if (origSamples.Scalings.Length < insertPos) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length); animationNormalizeTrack(origSamples, destSamples, insertPos); } else { if (origSamples.Scalings.Length < newEnd) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; } else { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length]; animationCopySampleTransformArray(origSamples, newEnd, destSamples, newEnd, origSamples.Scalings.Length - newEnd); } animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos); } animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; } } else if (replaceMethod == ReplaceAnimationMethod.Insert) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples; int newEnd = insertPos + newTrack.Value.Scalings.Length; if (origSamples.Scalings.Length < insertPos) { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[newEnd]; destSamples.Rotations = new Quaternion?[newEnd]; destSamples.Translations = new Vector3?[newEnd]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, origSamples.Scalings.Length); animationNormalizeTrack(origSamples, destSamples, insertPos); } else { destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length + newTrack.Value.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length + newTrack.Value.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length + newTrack.Value.Translations.Length]; animationCopySampleTransformArray(origSamples, 0, destSamples, 0, insertPos); animationCopySampleTransformArray(origSamples, insertPos, destSamples, newEnd, origSamples.Scalings.Length - insertPos); } animationCopySampleTransformArray(newTrack.Value, 0, destSamples, insertPos, newTrack.Value.Scalings.Length); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; } } else if (replaceMethod == ReplaceAnimationMethod.Append) { foreach (var newTrack in newTrackList) { ImportedAnimationSampledTrack animationNode; ImportedAnimationSampledTrack origSamples = animationGetOriginalSamples(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationSampledTrack destSamples = new ImportedAnimationSampledTrack(); destSamples.Scalings = new Vector3?[origSamples.Scalings.Length + insertPos + newTrack.Value.Scalings.Length]; destSamples.Rotations = new Quaternion?[origSamples.Rotations.Length + insertPos + newTrack.Value.Rotations.Length]; destSamples.Translations = new Vector3?[origSamples.Translations.Length + insertPos + newTrack.Value.Translations.Length]; animationCopySampleTransformArray(origSamples, destSamples, 0); bool reduced = false; for (int i = 0; i < origSamples.Scalings.Length; i++) { if (origSamples.Scalings[i] == null) { reduced = true; break; } } if (origSamples.Scalings.Length > 0 && !reduced) { animationNormalizeTrack(origSamples, destSamples, origSamples.Scalings.Length + insertPos); } animationCopySampleTransformArray(newTrack.Value, destSamples, origSamples.Scalings.Length + insertPos); animationNode.Scalings = destSamples.Scalings; animationNode.Rotations = destSamples.Rotations; animationNode.Translations = destSamples.Translations; } } else { Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation"); return; } if (negateQuaternionFlips) { foreach (var newTrack in iAnim.TrackList) { ImportedAnimationSampledTrack keyframes = newTrack; Quaternion lastQ = Quaternion.Identity; for (int i = 0, lastUsed_keyIndex = -1; i < keyframes.Rotations.Length; i++) { if (keyframes.Rotations[i] == null) { continue; } Quaternion q = keyframes.Rotations[i].Value; if (lastUsed_keyIndex >= 0) { bool diffZ = Math.Sign(lastQ.Z) != Math.Sign(q.Z); bool diffW = Math.Sign(lastQ.W) != Math.Sign(q.W); if (diffZ && diffW) { q.X = -q.X; q.Y = -q.Y; q.Z = -q.Z; q.W = -q.W; keyframes.Rotations[i] = q; } } lastQ = q; lastUsed_keyIndex = i; } } } }