internal KeyframeData(KeyframeDataJsonRepresentation <TKeyframeParameters> data, SkeletonTemplate <TBoneAttributes> skeleton) { this.bone = skeleton[data.Bone]; this.parameters = data.Parameters; if (this.bone == null) { throw new InvalidDataException("Keyframe data must specify valid bone."); } }
internal SkeletonTemplate(IEnumerable <BoneJsonRepresentation <TBoneAttributes> > bones) { var boneList = new List <BoneTemplate <TBoneAttributes> >(); this.bones = boneList.AsReadOnly(); this.boneDictionary = new Dictionary <string, BoneTemplate <TBoneAttributes> >(); // ReSharper disable PossibleMultipleEnumeration // see assignment of leftOverBones to bones at end of loop below if (bones.IsNullOrEmpty()) { return; } int id = 0; List <BoneJsonRepresentation <TBoneAttributes> > leftOverBones; bool pickedUpBone; // loop over bones repeatedly until all parent-child relations // are found (and all bones picked up) or unreachable bones are detected // as a result boneList and this.bones will contain all bones partially ordered // from spines to extremeties // performs in O(n) if bones are given in such an order, up to O(n^2) if bones // are given in reverse do { leftOverBones = new List <BoneJsonRepresentation <TBoneAttributes> >(); pickedUpBone = false; foreach (var bone in bones) { BoneTemplate <TBoneAttributes> parent = null; if (!string.IsNullOrEmpty(bone.Parent) && !this.boneDictionary.TryGetValue(bone.Parent, out parent)) { // found bone with unknown parent leftOverBones.Add(bone); continue; } var b = new BoneTemplate <TBoneAttributes>(id++, bone.Name, parent, bone.Attributes); boneList.Add(b); this.boneDictionary.Add(bone.Name, b); pickedUpBone = true; } bones = leftOverBones; } while (leftOverBones.Count > 0 && pickedUpBone); // ReSharper restore PossibleMultipleEnumeration if (leftOverBones.Count > 0) { if (leftOverBones.Count == 1) { throw new InvalidDataException("Found 1 bone with unknown parent."); } throw new InvalidDataException( string.Format("Found {0} bones with unknown parents.", leftOverBones.Count)); } boneList.TrimExcess(); }