private void ProcessDenses(Clip clip, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos) { DenseClip dense = clip.DenseClip; int streamCount = clip.StreamedClip.CurveCount; float[] slopeValues = new float[4]; // no slopes - 0 values for (int frameIndex = 0; frameIndex < dense.FrameCount; frameIndex++) { float time = frameIndex / dense.SampleRate; int frameOffset = frameIndex * dense.CurveCount; for (int curveIndex = 0; curveIndex < dense.CurveCount;) { int index = streamCount + curveIndex; GenericBinding binding = bindings.FindBinding(index); string path = GetCurvePath(tos, binding.Path); int framePosition = frameOffset + curveIndex; if (binding.IsTransform) { AddTransformCurve(time, binding.TransformType, dense.SampleArray, slopeValues, slopeValues, framePosition, path); curveIndex += binding.TransformType.GetDimension(); } else if (binding.CustomType == BindingCustomType.None) { AddDefaultCurve(binding, path, time, dense.SampleArray[framePosition]); curveIndex++; } else { AddCustomCurve(bindings, binding, path, time, dense.SampleArray[framePosition]); curveIndex++; } } } }
private BindingKey ResolveBindingForGeneric(BindingKey explicitKey, Type bindingType) { var genericBindingKey = BindingKey.Get (bindingType.GetGenericTypeDefinition (), explicitKey.Qualifier); var genericBindingType = bindingType.GetGenericTypeDefinition (); var genericTypeArguments = bindingType.GetGenericArguments (); IBindingConfig genericBindingConfig; Type genericConcreteType = GetGenericImplementation (genericBindingKey, genericBindingType, out genericBindingConfig); // Have 'implementedBy OR explicit binding' if (genericConcreteType != null) { OpenGenericBinding.For (genericBindingType).To (genericConcreteType); // validate binding Type concreteType = genericConcreteType.MakeGenericType (genericTypeArguments); var binding = new GenericBinding () { BindingConfig = new BindingConfig(concreteType), BindingKey = explicitKey.ToImplicit(), ConcreteType = concreteType }; if (genericBindingConfig != null) { binding.BindingConfig.Lifestyle = genericBindingConfig.Lifestyle; } injector.Register (binding); return binding.BindingKey; } return null; }
private void GetLive2dPath(GenericBinding binding, out string target, out string id) { var path = binding.path; id = null; target = null; if (path != 0 && bonePathHash.TryGetValue(path, out var boneName)) { // Console.WriteLine("bonePathHash {0} -> {1}", path, boneName); var index = boneName.LastIndexOf('/'); id = boneName.Substring(index + 1); target = boneName.Substring(0, index); if (target == "Parameters") { if (!boneName.StartsWith("Param") && !boneName.StartsWith("PARAM")) { Console.WriteLine("bonePathHash {0} -> {1}", path, boneName); } target = "Parameter"; } else if (target == "Parts") { if (!boneName.StartsWith("Parts") && !boneName.StartsWith("PARTS")) { Console.WriteLine("bonePathHash {0} -> {1}", path, boneName); } target = "PartOpacity"; } } else { if (path != 0) { Console.WriteLine("bonePathHash NOT FOUND! {0}", path); } binding.script.TryGet(out MonoScript script); switch (script.m_ClassName) { case "CubismRenderController": target = "Model"; id = "Opacity"; break; case "CubismEyeBlinkController": target = "Model"; id = "EyeBlink"; break; case "CubismMouthController": target = "Model"; id = "LipSync"; break; } } }
private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos, float sampleRate) { float[] curveValues = new float[4]; float[] inSlopeValues = new float[4]; float[] outSlopeValues = new float[4]; float interval = 1.0f / sampleRate; // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) // last one (index [count - 1]) is +Infinity // it is made for slope processing, but we don't need them for (int frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Length;) { StreamedCurveKey curve = frame.Curves[curveIndex]; GenericBinding binding = bindings.FindBinding(curve.Index); string path = GetCurvePath(tos, binding.Path); if (binding.IsTransform) { GetPreviousFrame(streamFrames, curve.Index, frameIndex, out int prevFrameIndex, out int prevCurveIndex); int dimension = binding.TransformType.GetDimension(); for (int key = 0; key < dimension; key++) { StreamedCurveKey keyCurve = frame.Curves[curveIndex]; StreamedFrame prevFrame = streamFrames[prevFrameIndex]; StreamedCurveKey prevKeyCurve = prevFrame.Curves[prevCurveIndex + key]; float deltaTime = frame.Time - prevFrame.Time; curveValues[key] = keyCurve.Value; inSlopeValues[key] = prevKeyCurve.CalculateNextInSlope(deltaTime, keyCurve.Value); outSlopeValues[key] = keyCurve.OutSlope; curveIndex = GetNextCurve(frame, curveIndex); } AddTransformCurve(frame.Time, binding.TransformType, curveValues, inSlopeValues, outSlopeValues, 0, path); } else if (binding.CustomType == BindingCustomType.None) { AddDefaultCurve(binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } else { AddCustomCurve(bindings, binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } } } }
private void AddGameObjectCurve(GenericBinding binding, string path, float time, float value) { if (binding.Attribute == CRC.CalculateDigestAscii(Layout.GameObject.IsActiveName)) { FloatCurve curve = new FloatCurve(path, Layout.GameObject.IsActiveName, ClassIDType.GameObject, default); AddFloatKeyframe(curve, time, value); return; } else { // that means that dev exported animation clip with missing component FloatCurve curve = new FloatCurve(path, MissedPropertyPrefix + binding.Attribute, ClassIDType.GameObject, default); AddFloatKeyframe(curve, time, value); } }
private bool AddTOS(IReadOnlyDictionary <uint, string> src, Dictionary <uint, string> dest) { int tosCount = ClipBindingConstant.GenericBindings.Length; for (int i = 0; i < tosCount; i++) { ref GenericBinding binding = ref ClipBindingConstant.GenericBindings[i]; if (src.TryGetValue(binding.Path, out string path)) { dest[binding.Path] = path; if (dest.Count == tosCount) { return(true); } } }
private void GetLive2dPath(GenericBinding binding, out string target, out string id) { var path = binding.path; id = null; target = null; if (path != 0 && bonePathHash.TryGetValue(path, out var boneName)) { var index = boneName.LastIndexOf('/'); id = boneName.Substring(index + 1); target = boneName.Substring(0, index); if (target == "Parameters") { target = "Parameter"; } else if (target == "Parts") { target = "PartOpacity"; } } else { binding.script.TryGet(out MonoScript script); switch (script.m_ClassName) { case "CubismRenderController": target = "Model"; id = "Opacity"; break; case "CubismEyeBlinkController": target = "Model"; id = "EyeBlink"; break; case "CubismMouthController": target = "Model"; id = "LipSync"; break; } } }
private void AddDefaultCurve(GenericBinding binding, string path, float time, float value) { switch (binding.ClassID) { case ClassIDType.GameObject: { AddGameObjectCurve(binding, path, time, value); } break; case ClassIDType.MonoBehaviour: { AddScriptCurve(binding, path, time, value); } break; default: AddEngineCurve(binding, path, time, value); break; } }
private void AddCustomCurve(AnimationClipBindingConstant bindings, GenericBinding binding, string path, float time, float value) { switch (binding.CustomType) { case BindingCustomType.AnimatorMuscle: AddAnimatorMuscleCurve(binding, time, value); break; default: string attribute = m_customCurveResolver.ToAttributeName(Layout, binding.CustomType, binding.Attribute, path); if (binding.IsPPtrCurve) { PPtrCurve curve = new PPtrCurve(path, attribute, binding.ClassID, binding.Script.CastTo <MonoScript>()); AddPPtrKeyframe(curve, bindings, time, (int)value); } else { FloatCurve curve = new FloatCurve(path, attribute, binding.ClassID, binding.Script.CastTo <MonoScript>()); AddFloatKeyframe(curve, time, value); } break; } }
private void ProcessConstant(Clip clip, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos, float lastFrame) { ConstantClip constant = clip.ConstantClip; int streamCount = clip.StreamedClip.CurveCount; int denseCount = clip.DenseClip.CurveCount; float[] slopeValues = new float[4]; // no slopes - 0 values // only first and last frames float time = 0.0f; for (int i = 0; i < 2; i++, time += lastFrame) { for (int curveIndex = 0; curveIndex < constant.Constants.Length;) { int index = streamCount + denseCount + curveIndex; GenericBinding binding = bindings.FindBinding(index); string path = GetCurvePath(tos, binding.Path); if (binding.IsTransform) { AddTransformCurve(time, binding.TransformType, constant.Constants, slopeValues, slopeValues, curveIndex, path); curveIndex += binding.TransformType.GetDimension(); } else if (binding.CustomType == BindingCustomType.None) { AddDefaultCurve(binding, path, time, constant.Constants[curveIndex]); curveIndex++; } else { AddCustomCurve(bindings, binding, path, time, constant.Constants[curveIndex]); curveIndex++; } } } }
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)); }
private void AddAnimatorMuscleCurve(GenericBinding binding, float time, float value) { FloatCurve curve = new FloatCurve(string.Empty, binding.GetHumanoidMuscle(Layout.Info.Version).ToAttributeString(), ClassIDType.Animator, default); AddFloatKeyframe(curve, time, value); }
private void AddEngineCurve(GenericBinding binding, string path, float time, float value) { #warning TODO: FloatCurve curve = new FloatCurve(path, TypeTreePropertyPrefix + binding.Attribute, binding.ClassID, default); AddFloatKeyframe(curve, time, value); }
private void AddScriptCurve(GenericBinding binding, string path, float time, float value) { #warning TODO: FloatCurve curve = new FloatCurve(path, ScriptPropertyPrefix + binding.Attribute, ClassIDType.MonoBehaviour, binding.Script.CastTo <MonoScript>()); AddFloatKeyframe(curve, time, value); }