private static bool TransferBonesOverride(CharaCustomFunctionController __instance, SkinnedMeshRenderer src, SkinnedMeshRenderer dst) { // Clean up no longer used implanted bones foreach (var kvp in _implantedBones.ToList()) { kvp.Value.Usages.Remove(dst); kvp.Value.Usages.RemoveWhere(x => x == null); if (kvp.Value.Usages.Count == 0) { if (kvp.Value.ImplantedBones != null) { Logger.LogDebug($"Removing {kvp.Value.ImplantedBones.Count} no longer used implanted bones"); foreach (var implantedBone in kvp.Value.ImplantedBones) { if (implantedBone != null) { Destroy(implantedBone.gameObject); } } } _implantedBones.Remove(kvp.Key); } } var bodyBoneDict = __instance.ChaControl.GetBodyBoneDict(); /* try dst.GetBoneDict() if there are any missing bones */ // Figure out the root object of the instantiated uncensor object and use it to figure out which renderers should share the instantiated bones var topmostParent = src.GetTopmostParent(); // Cache results of bone implanting and reuse them on renderers from the same instantiated uncensor object if (!_implantedBones.TryGetValue(topmostParent, out var implantedBonesData)) { implantedBonesData = TryImplantBones(topmostParent.gameObject, bodyBoneDict); if (implantedBonesData == null) { return(true); } _implantedBones[topmostParent] = implantedBonesData; } implantedBonesData.Usages.Add(dst); if (implantedBonesData.ImplantedBones == null || implantedBonesData.ImplantedBones.Count == 0) { return(true); } var existingBoneDict = dst.GetBoneDict(); var bodyBonesDict = (Dictionary <string, GameObject>)null; var boneCount = src.bones.Length; var reassignedBoneArr = new Transform[boneCount]; for (var i = 0; i < boneCount; i++) { var rendererBone = src.bones[i]; if (rendererBone == null) // Extra safety check, should never happen { Logger.LogWarning($"Renderer has a null bone! BoneIndex: {i} Renderer: {src.GetFullPath()}"); } else if (implantedBonesData.ImplantedBones.Contains(rendererBone)) // Copy implanted bones as they are { reassignedBoneArr[i] = rendererBone; } else if (existingBoneDict.TryGetValue(rendererBone.name, out var baseBone)) // Use the equivalent bone from the target renderer if found { reassignedBoneArr[i] = baseBone.transform; } else { // This branch shouldn't happen in most cases so do a lazy init to avoid the reflection cost if (bodyBonesDict == null) { bodyBonesDict = bodyBoneDict; } // Use the equivalent bone from the body skeleton if found if (bodyBonesDict.TryGetValue(rendererBone.name, out var bodyBone)) { reassignedBoneArr[i] = bodyBone.transform; } else { Logger.LogWarning( "Renderer is using a bone that is not in the base skeleton and is not implanted. It will be set to null. You need to add a BoneImplantProcess component to your object.\n" + $"Renderer: {src.GetFullPath()}\n" + $"Bone: {rendererBone.GetFullPath()}\n" + $"BoneIndex: {i}"); } } } dst.bones = reassignedBoneArr; return(false); }