using System.Collections.Generic; using System.Text; using LibMMD.Model; namespace LibMMD.Motion { internal sealed class MmdMotionBindingMap { internal readonly List> Bones = new List>(); internal readonly List> Ik = new List>(); internal readonly List> Morphs = new List>(); internal int GrooveFallbackCenterIndex { get; private set; } = -1; internal MmdMotionBindingMap(MmdMotion motion, MmdModel model) { var groove = -1; var center = -1; var lowerBody = -1; for (var i = 0; i < model.Bones.Length; ++i) { var bone = model.Bones[i]; var name = Normalize(bone.Name); var nameEn = Normalize(bone.NameEn); if (groove < 0 && (name == "グルーブ" || nameEn == "groove")) groove = i; if (center < 0 && (name == "センター" || nameEn == "center")) center = i; if (lowerBody < 0 && (name == "下半身" || nameEn == "lowerbody")) lowerBody = i; if (motion.IsBoneRegistered(bone.Name)) Bones.Add(new KeyValuePair(bone.Name, i)); if (bone.HasIk && motion.IsIkRegistered(bone.Name)) Ik.Add(new KeyValuePair(bone.Name, i)); } var hasUsableGroove = groove >= 0 && lowerBody >= 0 && IsAncestor(model, groove, lowerBody); if (!hasUsableGroove && center >= 0 && motion.IsBoneRegistered("グルーブ")) GrooveFallbackCenterIndex = center; for (var i = 0; i < model.Morphs.Length; ++i) if (motion.IsMorphRegistered(model.Morphs[i].Name)) Morphs.Add(new KeyValuePair(model.Morphs[i].Name, i)); } private static string Normalize(string name) => string.IsNullOrWhiteSpace(name) ? string.Empty : name.Normalize(NormalizationForm.FormKC).Replace(" ", string.Empty).ToLowerInvariant(); private static bool IsAncestor(MmdModel model, int ancestor, int bone) { var remaining = model.Bones.Length; while (bone >= 0 && bone < model.Bones.Length && remaining-- > 0) { if (bone == ancestor) return true; bone = model.Bones[bone].ParentIndex; } return false; } } }