public static SkinBindingRecipe Merge(FigureRecipeMerger.Reindexer reindexer, SkinBindingRecipe parentSkinBinding, SkinBindingRecipe[] childSkinBindings)
    {
        List <string>            mergedBones = new List <string>(parentSkinBinding.BoneNames);
        Dictionary <string, int> mergedBonesIndicesByName = Enumerable.Range(0, mergedBones.Count)
                                                            .ToDictionary(idx => mergedBones[idx], idx => idx);

        PackedLists <BoneWeight> mergedBoneWeights = parentSkinBinding.BoneWeights;

        foreach (SkinBindingRecipe childSkinBinding in childSkinBindings)
        {
            var remappedChildBoneWeights = childSkinBinding.BoneWeights
                                           .Map(boneWeight => {
                string boneName = childSkinBinding.BoneNames[boneWeight.Index];

                if (!mergedBonesIndicesByName.TryGetValue(boneName, out int mergedBoneIdx))
                {
                    mergedBoneIdx = mergedBones.Count;
                    mergedBonesIndicesByName[boneName] = mergedBoneIdx;
                    mergedBones.Add(boneName);
                }

                return(new BoneWeight(mergedBoneIdx, boneWeight.Weight));
            });
            mergedBoneWeights = PackedLists <BoneWeight> .Concat(mergedBoneWeights, remappedChildBoneWeights);
        }

        return(new SkinBindingRecipe {
            BoneNames = mergedBones.ToArray(),
            BoneWeights = mergedBoneWeights,
            FaceGroupToNodeMap = parentSkinBinding.FaceGroupToNodeMap
        });
    }
 public SkinBindingRecipe MergeSkinBinding()
 {
     return(SkinBindingRecipe.Merge(
                reindexer,
                parent.SkinBinding,
                children.Select(child => child.SkinBinding).ToArray()));
 }
    public FigureRecipe Merge()
    {
        GeometryRecipe       mergedGeometry    = MergeGeometry();
        List <ChannelRecipe> mergedChannels    = MergeChannels();
        List <FormulaRecipe> mergedFormulas    = MergeFormulas();
        List <BoneRecipe>    mergedBones       = MergeBones();
        List <MorphRecipe>   mergedMorphs      = MergeMorphs(mergedFormulas);
        AutomorpherRecipe    mergedAutomorpher = MergeAutomorpher();
        SkinBindingRecipe    mergedSkinBinding = MergeSkinBinding();
        List <UvSetRecipe>   mergedUvSets      = MergeUvSets();

        return(new FigureRecipe {
            Name = parent.Name,
            Geometry = mergedGeometry,
            Channels = mergedChannels,
            Formulas = mergedFormulas,
            Bones = mergedBones,
            Morphs = mergedMorphs,
            Automorpher = mergedAutomorpher,
            SkinBinding = mergedSkinBinding,
            UvSets = mergedUvSets
        });
    }
    public void Import(DsonTypes.SkinBinding skinBinding)
    {
        int vertexCount = skinBinding.vertex_count;

        List <List <BoneWeight> > boneWeightsByVertex = new List <List <BoneWeight> >(vertexCount);

        for (int i = 0; i < vertexCount; ++i)
        {
            boneWeightsByVertex.Add(new List <BoneWeight>());
        }

        DsonTypes.WeightedJoint[] joints = skinBinding.joints;

        string[] boneNames = new string[joints.Length];

        for (int boneIdx = 0; boneIdx < joints.Length; ++boneIdx)
        {
            DsonTypes.WeightedJoint joint = joints[boneIdx];

            if (joint.node_weights == null)
            {
                throw new InvalidOperationException("expected scale_weights to be non-null");
            }
            if (joint.scale_weights != null)
            {
                throw new InvalidOperationException("expected scale_weights to be null");
            }
            if (joint.local_weights != null)
            {
                throw new InvalidOperationException("expected local_weights to be null");
            }
            if (joint.bulge_weights != null)
            {
                throw new InvalidOperationException("expected bulge_weights to be null");
            }

            DsonTypes.Node jointNode = joint.node.ReferencedObject;
            boneNames[boneIdx] = jointNode.name;

            foreach (DsonTypes.IndexedFloat elem in joint.node_weights.values)
            {
                boneWeightsByVertex[elem.index].Add(new BoneWeight(boneIdx, (float)elem.value));
            }
        }

        Dictionary <string, string> faceGroupToNodeMap = new Dictionary <string, string>();

        if (skinBinding.selection_map.Length != 1)
        {
            throw new InvalidOperationException("expected only one face-group-to-node map");
        }
        foreach (DsonTypes.StringPair pair in skinBinding.selection_map[0].mappings)
        {
            faceGroupToNodeMap.Add(pair.from, pair.to);
        }

        SkinBindingRecipe recipe = new SkinBindingRecipe {
            BoneNames          = boneNames,
            BoneWeights        = PackedLists <BoneWeight> .Pack(boneWeightsByVertex),
            FaceGroupToNodeMap = faceGroupToNodeMap
        };

        recipes.Add(recipe);
    }