public bool isTrackEnabled(ImportedAnimationTrack track) { AdditionalTrackOptions options; if (this.TrackOptions.TryGetValue(track, out options)) { return options.Enabled; } throw new Exception("Track not found"); }
public void setTrackEnabled(ImportedAnimationTrack track, bool enabled) { AdditionalTrackOptions options; if (this.TrackOptions.TryGetValue(track, out options)) { options.Enabled = enabled; return; } throw new Exception("Track not found"); }
public static ImportedAnimationKeyframe[] animationGetOriginalKeyframes(Dictionary<string, ImportedAnimationTrack> animationNodeDic, string trackName, ImportedAnimation anim, out ImportedAnimationTrack animationNode) { ImportedAnimationKeyframe[] origKeyframes; if (animationNodeDic.TryGetValue(trackName, out animationNode)) { origKeyframes = animationNode.Keyframes; } else { animationNode = new ImportedAnimationTrack(); anim.TrackList.Add(animationNode); animationNode.Name = trackName; origKeyframes = new ImportedAnimationKeyframe[0]; } return origKeyframes; }
private void ImportAnimation(Section section) { ImportedAnimation workspaceAnimation = new ImportedAnimation(); workspaceAnimation.TrackList = new List<ImportedAnimationTrack>(section.children.Count); foreach (Section animSection in section.children) { if (animSection.type == "Animation") { string trackName = null; float[][][] keyDataArray = new float[5][][]; foreach (Section keySection in animSection.children) { if (keySection.type == "AnimationKey") { LinkedListNode<object> keyNode = keySection.data.First; int keyType = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; int numKeys = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; float[][] keyData = new float[numKeys][]; for (int i = 0; i < numKeys; i++) { int keyIdx = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; int numFloats = ConvertInt32(keyNode.Value); keyNode = keyNode.Next; keyData[i] = new float[numFloats]; for (int j = 0; j < numFloats; j++) { keyData[i][j] = ConvertFloat(keyNode.Value); keyNode = keyNode.Next; } } keyDataArray[keyType] = keyData; } else if (keySection.type == "ref") { trackName = keySection.name; } else { Report.ReportLog("Warning: unexpected section " + animSection.type); } } if (trackName == null) { throw new Exception("animation doesn't have a track name"); } if ((keyDataArray[0] == null) || (keyDataArray[2] == null)) { throw new Exception("animation " + trackName + " doesn't have the correct key types"); } if (keyDataArray[1] == null) { keyDataArray[1] = new float[keyDataArray[0].Length][]; for (int i = 0; i < keyDataArray[1].Length; i++) { keyDataArray[1][i] = new float[] { 1, 1, 1 }; } } if ((keyDataArray[0].Length != keyDataArray[1].Length) || (keyDataArray[0].Length != keyDataArray[2].Length)) { throw new Exception("animation " + trackName + " doesn't have the same number of keys for each type"); } ImportedAnimationKeyframe[] keyframes = new ImportedAnimationKeyframe[keyDataArray[0].Length]; for (int i = 0; i < keyframes.Length; i++) { float[] rotation = keyDataArray[0][i]; float[] scaling = keyDataArray[1][i]; float[] translation = keyDataArray[2][i]; keyframes[i] = new ImportedAnimationKeyframe(); keyframes[i].Rotation = new Quaternion(rotation[0], rotation[1], rotation[2], -rotation[3]); keyframes[i].Scaling = new Vector3(scaling[0], scaling[1], scaling[2]); keyframes[i].Translation = new Vector3(translation[0], translation[1], -translation[2]); } if (keyframes.Length > 0) { ImportedAnimationTrack track = new ImportedAnimationTrack(); track.Name = trackName; track.Keyframes = keyframes; workspaceAnimation.TrackList.Add(track); } } else { Report.ReportLog("Warning: unexpected section " + animSection.type); } } if (workspaceAnimation.TrackList.Count > 0) { AnimationList.Add(workspaceAnimation); } }
private void ImportAnimation(List<Document.Animation> animations, ImportedAnimation wsAnimation) { Dictionary<string, List<KeyValuePair<string, Document.Source>>> trackList = new Dictionary<string, List<KeyValuePair<string, Document.Source>>>(); for (int i = 0; i < animations.Count; i++) { int typeIdx = animations[i].channel.target.IndexOf('/'); if (typeIdx < 0) { throw new Exception("Couldn't find transform type for ANIMATION " + animations[i].id); } string frameName = DecodeName(animations[i].channel.target.Substring(0, typeIdx)); typeIdx++; string type = animations[i].channel.target.Substring(typeIdx, animations[i].channel.target.Length - typeIdx); for (int j = 0; j < animations[i].sampler.inputs.Count; j++) { if (animations[i].sampler.inputs[j].semantic == "OUTPUT") { Document.Source source = (Document.Source)animations[i].sampler.inputs[j].source; List<KeyValuePair<string, Document.Source>> track; if (!trackList.TryGetValue(frameName, out track)) { track = new List<KeyValuePair<string, Document.Source>>(); trackList.Add(frameName, track); } track.Add(new KeyValuePair<string, Document.Source>(type, source)); break; } } } foreach (KeyValuePair<string, List<KeyValuePair<string, Document.Source>>> track in trackList) { int numFrames = 0; for (int i = 0; i < track.Value.Count; i++) { int count = track.Value[i].Value.accessor.count; if (count > numFrames) { numFrames = count; } } ImportedAnimationKeyframe[] keyframes = new ImportedAnimationKeyframe[numFrames]; for (int i = 0; i < numFrames; i++) { Vector3 translate = new Vector3(0, 0, 0); Vector3 scale = new Vector3(1, 1, 1); float rotX = 0; float rotY = 0; float rotZ = 0; foreach (KeyValuePair<string, Document.Source> transform in track.Value) { Document.Source source = transform.Value; Document.Array<float> array = (Document.Array<float>)source.array; int arrayIdx = source.accessor.offset + (source.accessor.stride * i); if (arrayIdx < array.Count) { float val = array[arrayIdx]; switch (transform.Key) { case "translate.X": translate[0] = val; break; case "translate.Y": if (Z_UP) { translate[2] = -val; } else { translate[1] = val; } break; case "translate.Z": if (Z_UP) { translate[1] = val; } else { translate[2] = val; } break; case "rotateX.ANGLE": rotX = val; break; case "rotateY.ANGLE": rotY = val; break; case "rotateZ.ANGLE": rotZ = val; break; case "scale.X": scale[0] = val; break; case "scale.Y": if (Z_UP) { scale[2] = val; } else { scale[1] = val; } break; case "scale.Z": if (Z_UP) { scale[1] = val; } else { scale[2] = val; } break; default: throw new Exception("Unknown transform type " + transform.Key + " for ANIMATION " + animations[i].id); } } } Matrix rotMatrix = Matrix.Identity; Matrix rotXMatrix = Matrix.RotationAxis(new Vector3(1, 0, 0), (float)(rotX * Math.PI / 180)); Matrix rotYMatrix = Matrix.RotationAxis(new Vector3(0, 1, 0), (float)(rotY * Math.PI / 180)); Matrix rotZMatrix = Matrix.RotationAxis(new Vector3(0, 0, 1), (float)(rotZ * Math.PI / 180)); rotMatrix = rotMatrix * rotZMatrix; rotMatrix = rotMatrix * rotYMatrix; rotMatrix = rotMatrix * rotXMatrix; if (Z_UP) { rotMatrix = ZUpToYUpMatrix * rotMatrix; } Vector3 dummyScale; Quaternion rotation; Vector3 dummyTranslate; if (!rotMatrix.Decompose(out dummyScale, out rotation, out dummyTranslate)) { throw new Exception("Failed to decompose matrix"); } keyframes[i] = new ImportedAnimationKeyframe(); keyframes[i].Rotation = rotation; keyframes[i].Scaling = scale; keyframes[i].Translation = translate; } ImportedAnimationTrack importedTrack = new ImportedAnimationTrack(); importedTrack.Name = track.Key; importedTrack.Keyframes = keyframes; wsAnimation.TrackList.Add(importedTrack); } }
public static void ReplaceAnimation(ReplaceAnimationMethod replaceMethod, int insertPos, List<KeyValuePair<string, ImportedAnimationKeyframe[]>> newTrackList, ImportedAnimation iAnim, Dictionary<string, ImportedAnimationTrack> animationNodeDic, bool negateQuaternionFlips) { if (replaceMethod == ReplaceAnimationMethod.Replace) { foreach (var newTrack in newTrackList) { ImportedAnimationTrack iTrack = new ImportedAnimationTrack(); iAnim.TrackList.Add(iTrack); iTrack.Name = newTrack.Key; iTrack.Keyframes = newTrack.Value; } } else if (replaceMethod == ReplaceAnimationMethod.Merge) { foreach (var newTrack in newTrackList) { ImportedAnimationTrack animationNode; ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationKeyframe[] destKeyframes; int newEnd = insertPos + newTrack.Value.Length; if (origKeyframes.Length < insertPos) { destKeyframes = new ImportedAnimationKeyframe[newEnd]; FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length); FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos); } else { if (origKeyframes.Length < newEnd) { destKeyframes = new ImportedAnimationKeyframe[newEnd]; } else { destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length]; FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, newEnd, destKeyframes, newEnd, origKeyframes.Length - newEnd); } FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos); } FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length); animationNode.Keyframes = destKeyframes; } } else if (replaceMethod == ReplaceAnimationMethod.Insert) { foreach (var newTrack in newTrackList) { ImportedAnimationTrack animationNode; ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationKeyframe[] destKeyframes; int newEnd = insertPos + newTrack.Value.Length; if (origKeyframes.Length < insertPos) { destKeyframes = new ImportedAnimationKeyframe[newEnd]; FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length); FbxUtility.animationNormalizeTrack(origKeyframes, destKeyframes, insertPos); } else { destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length]; FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, insertPos); FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, insertPos, destKeyframes, newEnd, origKeyframes.Length - insertPos); } FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, insertPos, newTrack.Value.Length); animationNode.Keyframes = destKeyframes; } } else if (replaceMethod == ReplaceAnimationMethod.Append) { foreach (var newTrack in newTrackList) { ImportedAnimationTrack animationNode; ImportedAnimationKeyframe[] origKeyframes = FbxUtility.animationGetOriginalKeyframes(animationNodeDic, newTrack.Key, iAnim, out animationNode); ImportedAnimationKeyframe[] destKeyframes = new ImportedAnimationKeyframe[origKeyframes.Length + newTrack.Value.Length]; FbxUtility.animationCopyKeyframeTransformArray(origKeyframes, 0, destKeyframes, 0, origKeyframes.Length); FbxUtility.animationCopyKeyframeTransformArray(newTrack.Value, 0, destKeyframes, origKeyframes.Length, newTrack.Value.Length); animationNode.Keyframes = destKeyframes; } } else { Report.ReportLog("Error: Unexpected animation replace method " + replaceMethod + ". Skipping this animation"); } if (negateQuaternionFlips) { foreach (var newTrack in iAnim.TrackList) { Quaternion lastQ = Quaternion.Identity; for (int i = 0, lastUsed_keyIndex = -1; i < newTrack.Keyframes.Length; i++) { ImportedAnimationKeyframe iKeyframe = newTrack.Keyframes[i]; if (iKeyframe == null) continue; Quaternion q = iKeyframe.Rotation; if (lastUsed_keyIndex >= 0) { 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; iKeyframe.Rotation = q; } } lastQ = q; lastUsed_keyIndex = i; } } } }
private void ProcessDragDropAnimations(TreeNode node) { if (node.Tag is DragSource) { if ((node.Parent != null) && !node.Checked && node.StateImageIndex != (int)CheckState.Indeterminate) { return; } DragSource source = (DragSource)node.Tag; if (source.Type == typeof(WorkspaceAnimation)) { var srcEditor = (ImportedEditor)Gui.Scripting.Variables[source.Variable]; WorkspaceAnimation wsAnimation = srcEditor.Animations[(int)source.Id]; using (var dragOptions = new FormREADragDrop(Editor)) { int resampleCount = -1; if (wsAnimation.importedAnimation is ImportedKeyframedAnimation) { dragOptions.labelAnimationConvertion.Text = "\"" + node.Text + "\"" + dragOptions.labelAnimationConvertion.Text; dragOptions.labelAnimationConvertion.Visible = true; } else if (wsAnimation.importedAnimation is ImportedSampledAnimation) { List <ImportedAnimationSampledTrack> samTrackList = ((ImportedSampledAnimation)wsAnimation.importedAnimation).TrackList; int normalizeLength = samTrackList[0].Scalings.Length; foreach (ImportedAnimationSampledTrack track in samTrackList) { if (track.Scalings.Length != track.Rotations.Length || track.Rotations.Length != track.Translations.Length) { dragOptions.labelNormalizationWarning.Text = "\"" + node.Text + "\"" + dragOptions.labelNormalizationWarning.Text; dragOptions.labelNormalizationWarning.Visible = true; break; } } } dragOptions.numericResample.Value = resampleCount; dragOptions.comboBoxMethod.SelectedIndex = (int)ReplaceAnimationMethod.ReplacePresent; if (dragOptions.ShowDialog() == DialogResult.OK) { if (wsAnimation.importedAnimation is ImportedKeyframedAnimation) { Gui.Scripting.RunScript(EditorVar + ".ConvertAnimation(animation=" + source.Variable + ".Animations[" + (int)source.Id + "])"); FormWorkspace.UpdateAnimationNode(node, wsAnimation); } // repeating only final choices for repeatability of the script List <ImportedAnimationSampledTrack> trackList = ((ImportedSampledAnimation)wsAnimation.importedAnimation).TrackList; for (int i = 0; i < trackList.Count; i++) { ImportedAnimationTrack track = trackList[i]; if (!wsAnimation.isTrackEnabled(track)) { Gui.Scripting.RunScript(source.Variable + ".setTrackEnabled(animationId=" + (int)source.Id + ", id=" + i + ", enabled=false)"); } } Gui.Scripting.RunScript(EditorVar + ".ReplaceAnimation(animation=" + source.Variable + ".Animations[" + (int)source.Id + "], skeleton=" + source.Variable + ".Frames, resampleCount=" + dragOptions.numericResample.Value + ", linear=" + dragOptions.radioButtonInterpolationLinear.Checked + ", method=\"" + dragOptions.comboBoxMethod.SelectedItem + "\", insertPos=" + dragOptions.numericPosition.Value + ", negateQuaternionFlips=" + dragOptions.checkBoxNegateQuaternionFlips.Checked + ")"); UnloadREA(); LoadREA(); } } } } else { foreach (TreeNode child in node.Nodes) { ProcessDragDropAnimations(child); } } }