public void AddNode(Transform node) { Vector3Curve positionCurve; if(nodes.Count > 0) { int lastIndex = nodes.Count - 1; positionCurve = new Vector3Curve(nodes[lastIndex], node, curveFactor); for(float i = 0.1f; i < 1.1f; i += 0.1f) { Transform point = new GameObject("").transform; point.position = positionCurve.Evaluate(i); point.rotation = positionCurve.EvaluateRotation(i); point.parent = points; nodes.Add(point); } } else { Transform point = new GameObject("").transform; point.position = node.position; point.rotation = node.rotation; point.parent = points; nodes.Add(point); } Destroy(node.gameObject); }
/// <summary> /// 整个的UI对话框的出现,显示,消失,包含画线,消除线 /// </summary> /// <param name="lineRenderer"></param> /// <param name="origin"></param> /// <param name="middlePoint"></param> /// <param name="end"></param> /// <returns></returns> private IEnumerator RenderingLine(LineRenderer lineRenderer, Vector3 origin, Vector3 middlePoint, Vector3 end) { Vector3Curve v3Curve = new Vector3Curve(new Vector3KeyFrame(0.0f, origin), new Vector3KeyFrame(0.4f, middlePoint), new Vector3KeyFrame(1.0f, end)); yield return(StartCoroutine(RenderProgressLine(lineRenderer, v3Curve, 0.4f, this.speedOut, this.durationOut))); // Display UI var animator = CreateCanvas(); this.targetTime = Time.time + this.holdTime; while (Time.time < targetTime) { yield return(new WaitForSeconds(0.5f)); } // Close the menu and line animator.SetBool("Close", true); yield return(new WaitUntil(() => animator.GetCurrentAnimatorStateInfo(0).IsName("Closed"))); animator.gameObject.SetActive(false); // Draw back the line yield return(StartCoroutine(RenderProgressLine(lineRenderer, v3Curve, 0.4f, this.speedIn, this.durationIn))); Destroy(this.gameObject); }
private IEnumerator RenderProgressLine(LineRenderer lineRenderer, Vector3Curve v3Curve, float middleTime, AnimationCurve speed, float duration) { float interval = duration / 20.0f; for (float i = 0; i < 1.0f; i += 0.05f) { lineRenderer.SetPositions(positions); float mappedTime = speed.Evaluate(i); positions[2] = v3Curve.Evaluate(mappedTime); if (mappedTime < middleTime) { positions[1] = positions[2]; } yield return(new WaitForSeconds(duration / 20)); } float mappedTime1 = speed.Evaluate(1.0f); positions[2] = v3Curve.Evaluate(mappedTime1); if (mappedTime1 < middleTime) { positions[1] = positions[2]; } lineRenderer.SetPositions(positions); }
partial void OnClicked(int component) { Vector3Distribution distribution = Value; if (DistributionType == PropertyDistributionType.Curve) { AnimationCurve[] curves = AnimationUtility.SplitCurve3D(distribution.GetMinCurve()); if (component < curves.Length) { CurveEditorWindow.Show(curves[component], (success, curve) => { if (!success) { return; } curves[component] = curve; Vector3Curve compoundCurve = AnimationUtility.CombineCurve3D(curves); Value = new Vector3Distribution(compoundCurve); OnChanged?.Invoke(); OnConfirmed?.Invoke(); }); } } else if (DistributionType == PropertyDistributionType.RandomCurveRange) { AnimationCurve[] minCurves = AnimationUtility.SplitCurve3D(distribution.GetMinCurve()); AnimationCurve[] maxCurves = AnimationUtility.SplitCurve3D(distribution.GetMaxCurve()); if (component < minCurves.Length && component < maxCurves.Length) { CurveEditorWindow.Show(minCurves[component], maxCurves[component], (success, minCurve, maxCurve) => { if (!success) { return; } minCurves[component] = minCurve; maxCurves[component] = maxCurve; Vector3Curve minCompoundCurves = AnimationUtility.CombineCurve3D(minCurves); Vector3Curve maxCompoundCurves = AnimationUtility.CombineCurve3D(maxCurves); Value = new Vector3Distribution(minCompoundCurves, maxCompoundCurves); OnChanged?.Invoke(); OnConfirmed?.Invoke(); }); } } }
private void SetVector3CurveData(Vector3Curve vec3urve, AnimationCurve curve, string propertyName) { int cnt = curve.keys.Length; Keyframe[] srcKeys = curve.keys; if (vec3urve.keys == null) { vec3urve.keys = new Vector3KeyFrame[cnt]; } vec3urve.preWrapMode = curve.preWrapMode; vec3urve.postWrapMode = curve.postWrapMode; //vec3urve.rotationOrder = RotationOrder.Default; if (propertyName.EndsWith(".x")) { for (int i = 0; i < cnt; i++) { Keyframe keyFrame = srcKeys[i]; vec3urve.keys[i].time = keyFrame.time; vec3urve.keys[i].value.x = keyFrame.value; vec3urve.keys[i].inSlope.x = keyFrame.inTangent; vec3urve.keys[i].outSlope.x = keyFrame.outTangent; } } else if (propertyName.EndsWith(".y")) { for (int i = 0; i < cnt; i++) { Keyframe keyFrame = srcKeys[i]; vec3urve.keys[i].time = keyFrame.time; vec3urve.keys[i].value.y = keyFrame.value; vec3urve.keys[i].inSlope.y = keyFrame.inTangent; vec3urve.keys[i].outSlope.y = keyFrame.outTangent; } } else if (propertyName.EndsWith(".z")) { for (int i = 0; i < cnt; i++) { Keyframe keyFrame = srcKeys[i]; vec3urve.keys[i].time = keyFrame.time; vec3urve.keys[i].value.z = keyFrame.value; vec3urve.keys[i].inSlope.z = keyFrame.inTangent; vec3urve.keys[i].outSlope.z = keyFrame.outTangent; } } }
private void ProcessClip() { EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(_clip); foreach (var binding in bindings) { AnimationCurve curve = AnimationUtility.GetEditorCurve(_clip, binding); ProcessCurve(curve, binding); } // 某些 Curve 只有两个关键帧并且值是相同的,去掉此类 Curve 的第二个关键帧以节省空间 foreach (ClipCurveData data in _curveDic.Values) { RotationCurve rotCurve = data.rotationCurve; if (rotCurve.keys.Length == 2 && rotCurve.keys[0] == rotCurve.keys[1]) { rotCurve.keys = new RotationKeyFrame[1] { rotCurve.keys[0] } } ; Vector3Curve posCurve = data.positionCurve; if (posCurve.keys.Length == 2 && posCurve.keys[0] == posCurve.keys[1]) { posCurve.keys = new Vector3KeyFrame[1] { posCurve.keys[0] } } ; Vector3Curve scaleCurve = data.scaleCurve; if (scaleCurve.keys.Length == 2 && scaleCurve.keys[0] == scaleCurve.keys[1]) { if (scaleCurve.keys[0].value == Vector3.one) // 这种情况就不要记录曲线了 { data.scaleCurve = null; } else { scaleCurve.keys = new Vector3KeyFrame[1] { scaleCurve.keys[0] } }; } } }
private static extern AnimationCurve[] Internal_splitCurve3D(Vector3Curve compoundCurve);
/// <summary>Registers a new curve used for animating scale.</summary> /// <param name="name"> /// Unique name of the curve. This name will be used mapping the curve to the relevant bone in a skeleton, if any. /// </param> /// <param name="curve">Curve to add to the clip.</param> public void AddScaleCurve(string name, Vector3Curve curve) { Internal_addScaleCurve(mCachedPtr, name, curve); }
private static extern void Internal_TDistribution2(Vector3Distribution managedInstance, Vector3Curve curve);
/// <summary>Creates a new distribution that evaluates a curve.</summary> public Vector3Distribution(Vector3Curve curve) { Internal_TDistribution2(this, curve); }
private void Awake() { this.curve = new Vector3Curve(new Vector3KeyFrame(0, Vector3.zero), new Vector3KeyFrame(0.7f, new Vector3(0.2f, 0.9f, 0.5f)), new Vector3KeyFrame(1.0f, Vector3.one)); }
private void AddTransformCurve(float time, TransformType transType, IReadOnlyList <float> curveValues, IReadOnlyList <float> inSlopeValues, IReadOnlyList <float> outSlopeValues, int offset, string path) { switch (transType) { case TransformType.Translation: { Vector3Curve curve = new Vector3Curve(path); if (!m_translations.TryGetValue(curve, out List <KeyframeTpl <Vector3f> > transCurve)) { transCurve = new List <KeyframeTpl <Vector3f> >(); m_translations.Add(curve, transCurve); } float x = curveValues[offset + 0]; float y = curveValues[offset + 1]; float z = curveValues[offset + 2]; float inX = inSlopeValues[0]; float inY = inSlopeValues[1]; float inZ = inSlopeValues[2]; float outX = outSlopeValues[0]; float outY = outSlopeValues[1]; float outZ = outSlopeValues[2]; Vector3f value = new Vector3f(x, y, z); Vector3f inSlope = new Vector3f(inX, inY, inZ); Vector3f outSlope = new Vector3f(outX, outY, outZ); KeyframeTpl <Vector3f> transKey = new KeyframeTpl <Vector3f>(time, value, inSlope, outSlope, KeyframeTpl <Vector3f> .DefaultVector3Weight); transCurve.Add(transKey); } break; case TransformType.Rotation: { QuaternionCurve curve = new QuaternionCurve(path); if (!m_rotations.TryGetValue(curve, out List <KeyframeTpl <Quaternionf> > rotCurve)) { rotCurve = new List <KeyframeTpl <Quaternionf> >(); m_rotations.Add(curve, rotCurve); } float x = curveValues[offset + 0]; float y = curveValues[offset + 1]; float z = curveValues[offset + 2]; float w = curveValues[offset + 3]; float inX = inSlopeValues[0]; float inY = inSlopeValues[1]; float inZ = inSlopeValues[2]; float inW = inSlopeValues[3]; float outX = outSlopeValues[0]; float outY = outSlopeValues[1]; float outZ = outSlopeValues[2]; float outW = outSlopeValues[3]; Quaternionf value = new Quaternionf(x, y, z, w); Quaternionf inSlope = new Quaternionf(inX, inY, inZ, inW); Quaternionf outSlope = new Quaternionf(outX, outY, outZ, outW); KeyframeTpl <Quaternionf> rotKey = new KeyframeTpl <Quaternionf>(time, value, inSlope, outSlope, KeyframeTpl <Quaternionf> .DefaultQuaternionWeight); rotCurve.Add(rotKey); } break; case TransformType.Scaling: { Vector3Curve curve = new Vector3Curve(path); if (!m_scales.TryGetValue(curve, out List <KeyframeTpl <Vector3f> > scaleCurve)) { scaleCurve = new List <KeyframeTpl <Vector3f> >(); m_scales.Add(curve, scaleCurve); } float x = curveValues[offset + 0]; float y = curveValues[offset + 1]; float z = curveValues[offset + 2]; float inX = inSlopeValues[0]; float inY = inSlopeValues[1]; float inZ = inSlopeValues[2]; float outX = outSlopeValues[0]; float outY = outSlopeValues[1]; float outZ = outSlopeValues[2]; Vector3f value = new Vector3f(x, y, z); Vector3f inSlope = new Vector3f(inX, inY, inZ); Vector3f outSlope = new Vector3f(outX, outY, outZ); KeyframeTpl <Vector3f> scaleKey = new KeyframeTpl <Vector3f>(time, value, inSlope, outSlope, KeyframeTpl <Vector3f> .DefaultVector3Weight); scaleCurve.Add(scaleKey); } break; case TransformType.EulerRotation: { Vector3Curve curve = new Vector3Curve(path); if (!m_eulers.TryGetValue(curve, out List <KeyframeTpl <Vector3f> > eulerCurve)) { eulerCurve = new List <KeyframeTpl <Vector3f> >(); m_eulers.Add(curve, eulerCurve); } float x = curveValues[offset + 0]; float y = curveValues[offset + 1]; float z = curveValues[offset + 2]; float inX = inSlopeValues[0]; float inY = inSlopeValues[1]; float inZ = inSlopeValues[2]; float outX = outSlopeValues[0]; float outY = outSlopeValues[1]; float outZ = outSlopeValues[2]; Vector3f value = new Vector3f(x, y, z); Vector3f inSlope = new Vector3f(inX, inY, inZ); Vector3f outSlope = new Vector3f(outX, outY, outZ); KeyframeTpl <Vector3f> eulerKey = new KeyframeTpl <Vector3f>(time, value, inSlope, outSlope, KeyframeTpl <Vector3f> .DefaultVector3Weight); eulerCurve.Add(eulerKey); } break; default: throw new NotImplementedException(transType.ToString()); } }
/// <summary> /// Loads curve and event information from the provided clip, and creates a new instance of this object containing /// the required data for editing the source clip in the animation editor. /// </summary> /// <param name="clip">Clip to load.</param> /// <returns>Editor specific editable information about an animation clip.</returns> public static EditorAnimClipInfo Create(AnimationClip clip) { EditorAnimClipInfo clipInfo = new EditorAnimClipInfo(); clipInfo.clip = clip; clipInfo.isImported = IsClipImported(clip); clipInfo.sampleRate = (int)clip.SampleRate; AnimationCurves clipCurves = clip.Curves; EditorAnimClipData editorClipData = null; EditorAnimClipData lGetAnimClipData(ResourceMeta meta) { object editorData = meta.EditorData; EditorAnimClipData output = editorData as EditorAnimClipData; if (output == null) { // Old editor data stores tangents only if (editorData is EditorAnimClipTangents tangents) { output = new EditorAnimClipData(); output.tangents = tangents; } } return(output); } string resourcePath = ProjectLibrary.GetPath(clip); if (!string.IsNullOrEmpty(resourcePath)) { LibraryEntry entry = ProjectLibrary.GetEntry(resourcePath); string clipName = PathEx.GetTail(resourcePath); if (entry != null && entry.Type == LibraryEntryType.File) { FileEntry fileEntry = (FileEntry)entry; ResourceMeta[] metas = fileEntry.ResourceMetas; if (clipInfo.isImported) { for (int i = 0; i < metas.Length; i++) { if (clipName == metas[i].SubresourceName) { editorClipData = lGetAnimClipData(metas[i]); break; } } } else { if (metas.Length > 0) { editorClipData = lGetAnimClipData(metas[0]); } } } } if (editorClipData == null) { editorClipData = new EditorAnimClipData(); editorClipData.tangents = new EditorAnimClipTangents(); } int globalCurveIdx = 0; void lLoadVector3Curve(NamedVector3Curve[] curves, EditorVector3CurveTangents[] tangents, string subPath) { foreach (var curveEntry in curves) { TangentMode[] tangentsX = null; TangentMode[] tangentsY = null; TangentMode[] tangentsZ = null; if (tangents != null) { foreach (var tangentEntry in tangents) { if (tangentEntry.name == curveEntry.name) { tangentsX = tangentEntry.tangentsX; tangentsY = tangentEntry.tangentsY; tangentsZ = tangentEntry.tangentsZ; break; } } } // Convert compound curve to three per-component curves AnimationCurve[] componentCurves = AnimationUtility.SplitCurve3D(curveEntry.curve); FieldAnimCurves fieldCurves = new FieldAnimCurves(); fieldCurves.type = SerializableProperty.FieldType.Vector3; fieldCurves.curveInfos = new EdCurveDrawInfo[3]; fieldCurves.isPropertyCurve = !clipInfo.isImported; fieldCurves.curveInfos[0] = new EdCurveDrawInfo(); fieldCurves.curveInfos[0].curve = new EdAnimationCurve(componentCurves[0], tangentsX); fieldCurves.curveInfos[0].color = GetUniqueColor(globalCurveIdx++); fieldCurves.curveInfos[1] = new EdCurveDrawInfo(); fieldCurves.curveInfos[1].curve = new EdAnimationCurve(componentCurves[1], tangentsY); fieldCurves.curveInfos[1].color = GetUniqueColor(globalCurveIdx++); fieldCurves.curveInfos[2] = new EdCurveDrawInfo(); fieldCurves.curveInfos[2].curve = new EdAnimationCurve(componentCurves[2], tangentsZ); fieldCurves.curveInfos[2].color = GetUniqueColor(globalCurveIdx++); string curvePath = curveEntry.name.TrimEnd('/') + subPath; clipInfo.curves[curvePath] = fieldCurves; } }; NamedQuaternionCurve[] rotationCurves = clipCurves.Rotation; NamedVector3Curve[] eulerRotationCurves = new NamedVector3Curve[rotationCurves.Length]; if (editorClipData.eulerCurves == null || editorClipData.eulerCurves.Length != rotationCurves.Length) { // Convert rotation from quaternion to euler if we don't have original euler animation data stored. for (int i = 0; i < rotationCurves.Length; i++) { NamedQuaternionCurve quatCurve = rotationCurves[i]; Vector3Curve eulerCurve = AnimationUtility.QuaternionToEulerCurve(quatCurve.curve); eulerRotationCurves[i] = new NamedVector3Curve(quatCurve.name, quatCurve.flags, eulerCurve); } } else { for (int i = 0; i < editorClipData.eulerCurves.Length; i++) { EditorNamedVector3Curve edCurve = editorClipData.eulerCurves[i]; eulerRotationCurves[i] = new NamedVector3Curve( edCurve.name, edCurve.flags, new Vector3Curve(edCurve.keyFrames)); } } lLoadVector3Curve(clipCurves.Position, editorClipData.tangents.positionCurves, "/Position"); lLoadVector3Curve(eulerRotationCurves, editorClipData.tangents.rotationCurves, "/Rotation"); lLoadVector3Curve(clipCurves.Scale, editorClipData.tangents.scaleCurves, "/Scale"); // Find which individual float curves belong to the same field Dictionary <string, Tuple <int, int, bool>[]> floatCurveMapping = new Dictionary <string, Tuple <int, int, bool>[]>(); { int curveIdx = 0; foreach (var curveEntry in clipCurves.Generic) { string path = curveEntry.name; string pathNoSuffix = null; string pathSuffix; if (path.Length >= 2) { pathSuffix = path.Substring(path.Length - 2, 2); pathNoSuffix = path.Substring(0, path.Length - 2); } else { pathSuffix = ""; } int tangentIdx = -1; int currentTangentIdx = 0; foreach (var tangentEntry in editorClipData.tangents.floatCurves) { if (tangentEntry.name == curveEntry.name) { tangentIdx = currentTangentIdx; break; } currentTangentIdx++; } Animation.PropertySuffixInfo suffixInfo; if (Animation.PropertySuffixInfos.TryGetValue(pathSuffix, out suffixInfo)) { Tuple <int, int, bool>[] curveInfo; if (!floatCurveMapping.TryGetValue(pathNoSuffix, out curveInfo)) { curveInfo = new Tuple <int, int, bool> [4]; } curveInfo[suffixInfo.elementIdx] = Tuple.Create(curveIdx, tangentIdx, suffixInfo.isVector); floatCurveMapping[pathNoSuffix] = curveInfo; } else { Tuple <int, int, bool>[] curveInfo = new Tuple <int, int, bool> [4]; curveInfo[0] = Tuple.Create(curveIdx, tangentIdx, suffixInfo.isVector); floatCurveMapping[path] = curveInfo; } curveIdx++; } } foreach (var KVP in floatCurveMapping) { int numCurves = 0; for (int i = 0; i < 4; i++) { if (KVP.Value[i] == null) { continue; } numCurves++; } if (numCurves == 0) { continue; // Invalid curve } FieldAnimCurves fieldCurves = new FieldAnimCurves(); // Deduce type (note that all single value types are assumed to be float even if their source type is int or bool) if (numCurves == 1) { fieldCurves.type = SerializableProperty.FieldType.Float; } else if (numCurves == 2) { fieldCurves.type = SerializableProperty.FieldType.Vector2; } else if (numCurves == 3) { fieldCurves.type = SerializableProperty.FieldType.Vector3; } else // 4 curves { bool isVector = KVP.Value[0].Item3; if (isVector) { fieldCurves.type = SerializableProperty.FieldType.Vector4; } else { fieldCurves.type = SerializableProperty.FieldType.Color; } } bool isMorphCurve = false; string curvePath = KVP.Key; fieldCurves.curveInfos = new EdCurveDrawInfo[numCurves]; for (int i = 0; i < numCurves; i++) { int curveIdx = KVP.Value[i].Item1; int tangentIdx = KVP.Value[i].Item2; TangentMode[] tangents = null; if (tangentIdx != -1) { tangents = editorClipData.tangents.floatCurves[tangentIdx].tangents; } fieldCurves.curveInfos[i] = new EdCurveDrawInfo(); fieldCurves.curveInfos[i].curve = new EdAnimationCurve(clipCurves.Generic[curveIdx].curve, tangents); fieldCurves.curveInfos[i].color = GetUniqueColor(globalCurveIdx++); if (clipCurves.Generic[curveIdx].flags.HasFlag(AnimationCurveFlags.MorphFrame)) { curvePath = "MorphShapes/Frames/" + KVP.Key; isMorphCurve = true; } else if (clipCurves.Generic[curveIdx].flags.HasFlag(AnimationCurveFlags.MorphWeight)) { curvePath = "MorphShapes/Weight/" + KVP.Key; isMorphCurve = true; } } fieldCurves.isPropertyCurve = !clipInfo.isImported && !isMorphCurve; clipInfo.curves[curvePath] = fieldCurves; } // Add events clipInfo.events = clip.Events; return(clipInfo); }
private static extern void Internal_TAnimationCurve(Vector3Curve managedInstance, KeyFrameVec3[] keyframes);
/// <summary>Constructs a new named animation curve.</summary> /// <param name="name">Name of the curve.</param> /// <param name="flags">Flags that describe the animation curve.</param> /// <param name="curve">Curve containing the animation data.</param> public NamedVector3Curve(string name, AnimationCurveFlags flags, Vector3Curve curve) { this.name = name; this.flags = (AnimationCurveFlags)0; this.curve = curve; }
public void ExportGenericData(IExportContainer container, YAMLMappingNode node, IReadOnlyDictionary <uint, string> tos) { StreamedClip streamedClip = MuscleClip.Clip.StreamedClip; DenseClip denseClip = MuscleClip.Clip.DenseClip; ConstantClip constantClip = MuscleClip.Clip.ConstantClip; IReadOnlyList <StreamedFrame> streamedFrames = streamedClip.GenerateFrames(container); Dictionary <uint, Vector3Curve> translations = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, QuaternionCurve> rotations = new Dictionary <uint, QuaternionCurve>(); Dictionary <uint, Vector3Curve> scales = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, Vector3Curve> eulers = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, FloatCurve> floats = new Dictionary <uint, FloatCurve>(); int frameCount = Math.Max(denseClip.FrameCount - 1, streamedFrames.Count - 2); float[] frameCurvesValue = new float[streamedClip.CurveCount]; for (int frame = 0, streamFrame = 1; frame < frameCount; frame++, streamFrame++) { bool isAdd = true; float time; StreamedFrame streamedFrame = new StreamedFrame(); if (streamFrame < streamedFrames.Count) { streamedFrame = streamedFrames[streamFrame]; time = streamedFrame.Time; } else { time = (float)frame / SampleRate; } bool isStreamFrame = streamFrame < (streamedFrames.Count - 1); bool isDenseFrame = frame < (denseClip.FrameCount - 1); // number of stream curves which has key in current frame int streamFrameCurveCount = isStreamFrame ? streamedFrame.Curves.Count : 0; int denseFrameCurveCount = (int)denseClip.CurveCount; // total amount of curves which has key in current frame int frameCurveCount = streamFrameCurveCount + denseFrameCurveCount + constantClip.Constants.Count; int streamOffset = (int)streamedClip.CurveCount - streamFrameCurveCount; for (int curve = 0; curve < frameCurveCount;) { int curveIndex; IReadOnlyList <float> curvesValue; int offset; if (isStreamFrame && curve < streamedFrame.Curves.Count) { #warning TODO: read TCB and convert to in/out slope for (int key = curve; key < Math.Min(curve + 5, streamedFrame.Curves.Count); key++) { frameCurvesValue[key] = streamedFrame.Curves[key].Value; } curveIndex = streamedFrame.Curves[curve].Index; curvesValue = frameCurvesValue; offset = 0; } else if (isDenseFrame && curve < streamFrameCurveCount + denseFrameCurveCount) { curveIndex = curve + streamOffset; curvesValue = denseClip.SampleArray; offset = streamFrameCurveCount - frame * denseFrameCurveCount; } else if (!isDenseFrame && curve < streamFrameCurveCount + denseFrameCurveCount) { curve += denseFrameCurveCount; curveIndex = curve + streamOffset; curvesValue = constantClip.Constants; offset = streamFrameCurveCount + denseFrameCurveCount; isAdd = frame == 0 || frame == frameCount - 1; } else { curveIndex = curve + streamOffset; curvesValue = constantClip.Constants; offset = streamFrameCurveCount + denseFrameCurveCount; isAdd = frame == 0 || frame == frameCount - 1; } GenericBinding binding = ClipBindingConstant.FindBinding(curveIndex); uint pathHash = binding.Path; if (pathHash == 0) { curve++; continue; } if (!tos.TryGetValue(pathHash, out string path)) { path = "dummy" + pathHash; //Logger.Log(LogType.Debug, LogCategory.Export, $"Can't find path '{binding.Path}' in TOS for {ToLogString()}"); } switch (binding.BindingType) { case BindingType.Translation: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } float x = curvesValue[curve++ - offset]; float y = curvesValue[curve++ - offset]; float z = curvesValue[curve++ - offset]; float w = 0; if (isAdd) { Vector3f trans = new Vector3f(x, y, z); if (!translations.TryGetValue(pathHash, out Vector3Curve transCurve)) { transCurve = new Vector3Curve(path); translations[pathHash] = transCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> transKey = new KeyframeTpl <Vector3f>(time, trans, defWeight); transCurve.Curve.Curve.Add(transKey); } break; case BindingType.Rotation: // HACK: TEMP: if (curve + 4 > curvesValue.Count) { curve += 4; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; w = curvesValue[curve++ - offset]; if (isAdd) { Quaternionf rot = new Quaternionf(x, y, z, w); if (!rotations.TryGetValue(pathHash, out QuaternionCurve rotCurve)) { rotCurve = new QuaternionCurve(path); rotations[pathHash] = rotCurve; } Quaternionf defWeight = new Quaternionf(1.0f / 3.0f); KeyframeTpl <Quaternionf> rotKey = new KeyframeTpl <Quaternionf>(time, rot, defWeight); rotCurve.Curve.Curve.Add(rotKey); } break; case BindingType.Scaling: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f scale = new Vector3f(x, y, z); if (!scales.TryGetValue(pathHash, out Vector3Curve scaleCurve)) { scaleCurve = new Vector3Curve(path); scales[pathHash] = scaleCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> scaleKey = new KeyframeTpl <Vector3f>(time, scale, defWeight); scaleCurve.Curve.Curve.Add(scaleKey); } break; case BindingType.EulerRotation: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f euler = new Vector3f(x, y, z); if (!eulers.TryGetValue(pathHash, out Vector3Curve eulerCurve)) { eulerCurve = new Vector3Curve(path); eulers[pathHash] = eulerCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> eulerKey = new KeyframeTpl <Vector3f>(time, euler, defWeight); eulerCurve.Curve.Curve.Add(eulerKey); } break; case BindingType.Floats: float value = curvesValue[curve++ - offset]; if (isAdd) { Float @float = new Float(value); if (!floats.TryGetValue(pathHash, out FloatCurve floatCurve)) { floatCurve = new FloatCurve(path); floats[pathHash] = floatCurve; } Float defWeight = new Float(1.0f / 3.0f); KeyframeTpl <Float> floatKey = new KeyframeTpl <Float>(time, @float, defWeight); floatCurve.Curve.Curve.Add(floatKey); } break; default: #warning TODO: ??? curve++; //throw new NotImplementedException(binding.BindingType.ToString()); break; } } } node.Add("m_RotationCurves", rotations.Values.ExportYAML(container)); node.Add("m_CompressedRotationCurves", YAMLSequenceNode.Empty); node.Add("m_EulerCurves", eulers.Values.ExportYAML(container)); node.Add("m_PositionCurves", translations.Values.ExportYAML(container)); node.Add("m_ScaleCurves", scales.Values.ExportYAML(container)); node.Add("m_FloatCurves", floats.Values.ExportYAML(container)); }
public MemberAnimationData(EndianBinaryReader er) { Flags = er.ReadUInt32(); PathOffset = (UInt32)er.BaseStream.Position + er.ReadUInt32(); PrimitiveType = (AnimationType)er.ReadUInt32(); switch (PrimitiveType) { case AnimationType.Vector2Animation: ConstValues = new object[2]; Curves = new AnimationCurve[2]; if ((Flags & 1) != 0) { ConstValues[0] = er.ReadSingle(); //constant } else if ((Flags & 4) != 0) { er.ReadUInt32(); //nothing = empty reference } else { long offs = er.BaseStream.Position + er.ReadUInt32(); long curpos_ = er.BaseStream.Position; er.BaseStream.Position = offs; Curves[0] = new FloatAnimationCurve(er); er.BaseStream.Position = curpos_; } if ((Flags & 2) != 0) { ConstValues[1] = er.ReadSingle(); //constant } else if ((Flags & 8) != 0) { er.ReadUInt32(); //nothing = empty reference } else { long offs = er.BaseStream.Position + er.ReadUInt32(); long curpos_ = er.BaseStream.Position; er.BaseStream.Position = offs; Curves[1] = new FloatAnimationCurve(er); er.BaseStream.Position = curpos_; } break; case AnimationType.BakedTransformAnimation: Curves = new AnimationCurve[3]; if ((Flags & 0x10) != 0) { er.ReadUInt32(); //nothing = empty reference } else { //Matrix33curve reference long offs = er.BaseStream.Position + er.ReadUInt32(); long curpos_ = er.BaseStream.Position; er.BaseStream.Position = offs; Curves[0] = new Matrix33Curve(er); er.BaseStream.Position = curpos_; } if ((Flags & 8) != 0) { er.ReadUInt32(); //nothing = empty reference } else { //Vector3curve reference (translation) long offs = er.BaseStream.Position + er.ReadUInt32(); long curpos_ = er.BaseStream.Position; er.BaseStream.Position = offs; Curves[1] = new Vector3Curve(er); er.BaseStream.Position = curpos_; } if ((Flags & 0x20) != 0) { er.ReadUInt32(); //nothing = empty reference } else { //Vector3curve reference (scale) long offs = er.BaseStream.Position + er.ReadUInt32(); long curpos_ = er.BaseStream.Position; er.BaseStream.Position = offs; Curves[2] = new Vector3Curve(er); er.BaseStream.Position = curpos_; } break; default: break; } long curpos = er.BaseStream.Position; er.BaseStream.Position = PathOffset; Path = er.ReadStringNT(Encoding.ASCII); er.BaseStream.Position = curpos; }
/// <summary>Converts a curve in euler angles (in degrees) into a curve using quaternions.</summary> public static QuaternionCurve EulerToQuaternionCurve(Vector3Curve eulerCurve) { return(Internal_eulerToQuaternionCurve(eulerCurve)); }
/// <summary>Splits a Vector3 curve into three individual curves, one for each component.</summary> public static AnimationCurve[] SplitCurve3D(Vector3Curve compoundCurve) { return(Internal_splitCurve3D(compoundCurve)); }
/// <summary>Creates a new distribution that returns a random value in a range determined by two curves.</summary> public Vector3Distribution(Vector3Curve minCurve, Vector3Curve maxCurve) { Internal_TDistribution3(this, minCurve, maxCurve); }
private static extern QuaternionCurve Internal_eulerToQuaternionCurve(Vector3Curve eulerCurve);
private static extern void Internal_TDistribution3(Vector3Distribution managedInstance, Vector3Curve minCurve, Vector3Curve maxCurve);
private static extern void Internal_addScaleCurve(IntPtr thisPtr, string name, Vector3Curve curve);