/// <summary>
        /// 一人称表示の設定をコピーします。
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <param name="sourceSkeletonBones"></param>
        internal static void Copy(
            GameObject source,
            GameObject destination,
            Dictionary <HumanBodyBones, Transform> sourceSkeletonBones
            )
        {
            var sourceFirstPerson      = source.GetComponent <VRMFirstPerson>();
            var destinationFirstPerson = destination.GetComponent <VRMFirstPerson>();

            if (!sourceFirstPerson)
            {
                if (destinationFirstPerson)
                {
                    Object.DestroyImmediate(destinationFirstPerson);
                }
                return;
            }

            if (sourceFirstPerson.FirstPersonBone)
            {
                destinationFirstPerson.FirstPersonBone = BoneMapper.FindCorrespondingBone(
                    sourceBone: sourceFirstPerson.FirstPersonBone,
                    source: source,
                    destination: destination,
                    sourceSkeletonBones: sourceSkeletonBones
                    );
            }

            destinationFirstPerson.FirstPersonOffset = sourceFirstPerson.FirstPersonOffset;

            foreach (VRMFirstPerson.RendererFirstPersonFlags sourceFlags in sourceFirstPerson.Renderers)
            {
                if (sourceFlags.FirstPersonFlag == FirstPersonFlag.Auto)
                {
                    continue;
                }

                Mesh sourceMesh = sourceFlags.SharedMesh;
                if (!sourceMesh)
                {
                    continue;
                }

                var sourceMeshName = sourceMesh.name;

                var index = destinationFirstPerson.Renderers.FindIndex(match: flags => {
                    Mesh destinationMesh = flags.SharedMesh;
                    return(destinationMesh && destinationMesh.name == sourceMeshName);
                });
                if (index == -1)
                {
                    continue;
                }

                var destinationFlags = destinationFirstPerson.Renderers[index];
                destinationFlags.FirstPersonFlag        = sourceFlags.FirstPersonFlag;
                destinationFirstPerson.Renderers[index] = destinationFlags;
            }
        }
Exemple #2
0
        /// <summary>
        /// VRMの設定をコピーします。
        /// </summary>
        /// <param name="source">ヒエラルキーのルート、もしくはプレハブのルートであるコピー元のアバター。</param>
        /// <param name="destination">ヒエラルキーのルート、もしくはプレハブのルートであるコピー先のアバター。</param>
        /// <param name="">コピーするコンポーネント。既定値は <see cref="CopyVRMSettings.SupportedComponents">。</param>
        public static void Copy(GameObject source, GameObject destination, IEnumerable <Type> components = null)
        {
            if (components == null)
            {
                components = CopyVRMSettings.SupportedComponents;
            }

            GameObject destinationPrefab = null;

            if (!SceneManager.GetActiveScene().GetRootGameObjects().Contains(destination.gameObject))
            {
                destinationPrefab = destination;
                destination       = PrefabUtility.InstantiatePrefab(destination) as GameObject;
            }

            if (components.Contains(typeof(VRMMeta)))
            {
                CopyMeta.Copy(source: source, destination: destination);
            }
            if (components.Contains(typeof(VRMBlendShapeProxy)))
            {
                CopyVRMBlendShapes.Copy(source: source, destination: destination);
            }
            var sourceSkeletonBones = BoneMapper.GetAllSkeletonBones(avatar: source);

            if (components.Contains(typeof(VRMFirstPerson)))
            {
                CopyFirstPerson.Copy(source: source, destination: destination, sourceSkeletonBones: sourceSkeletonBones);
            }
            if (components.Contains(typeof(VRMLookAtHead)))
            {
                CopyEyeControl.Copy(source: source, destination: destination, sourceSkeletonBones: sourceSkeletonBones);
            }
            if (components.Contains(typeof(VRMSpringBone)))
            {
                CopyVRMSpringBones.Copy(source: source, destination: destination, sourceSkeletonBones: sourceSkeletonBones);
            }

            if (destinationPrefab)
            {
                PrefabUtility.ApplyPrefabInstance(destination, InteractionMode.AutomatedAction);
                UnityEngine.Object.DestroyImmediate(destination);
            }
        }
        /// <summary>
        /// VRMSpringBone、およびVRMSpringBoneColliderGroupをコピーします。
        /// </summary>
        /// <param name="sourceSpringBone"></param>
        /// <param name="destination"></param>
        /// <param name="sourceSkeletonBones"></param>
        /// <param name="transformMapping"></param>
        /// <returns>更新された <c>transformMapping</c> を返します。</returns>
        private static IDictionary <Transform, Transform> CopySpringBone(
            VRMSpringBone sourceSpringBone,
            GameObject destination,
            Dictionary <HumanBodyBones, Transform> sourceSkeletonBones,
            IDictionary <Transform, Transform> transformMapping
            )
        {
            var destinationSecondary = destination.transform.Find("secondary").gameObject;

            ComponentUtility.CopyComponent(sourceSpringBone);
            ComponentUtility.PasteComponentAsNew(destinationSecondary);
            var destinationSpringBone = destinationSecondary.GetComponents <VRMSpringBone>().Last();

            if (destinationSpringBone.m_center)
            {
                destinationSpringBone.m_center = transformMapping.ContainsKey(destinationSpringBone.m_center)
                    ? transformMapping[destinationSpringBone.m_center]
                    : (transformMapping[destinationSpringBone.m_center] = BoneMapper.FindCorrespondingBone(
                           sourceBone: destinationSpringBone.m_center,
                           source: sourceSpringBone.transform.root.gameObject,
                           destination,
                           sourceSkeletonBones
                           ));
            }

            for (var i = 0; i < destinationSpringBone.RootBones.Count; i++)
            {
                var sourceSpringBoneRoot = destinationSpringBone.RootBones[i];

                destinationSpringBone.RootBones[i] = sourceSpringBoneRoot
                    ? (transformMapping.ContainsKey(sourceSpringBoneRoot)
                        ? transformMapping[sourceSpringBoneRoot]
                        : (transformMapping[sourceSpringBoneRoot] = BoneMapper.FindCorrespondingBone(
                               sourceBone: sourceSpringBoneRoot,
                               source: sourceSpringBone.transform.root.gameObject,
                               destination,
                               sourceSkeletonBones
                               )))
                    : null;
            }

            for (var i = 0; i < destinationSpringBone.ColliderGroups.Length; i++)
            {
                var sourceColliderGroup = destinationSpringBone.ColliderGroups[i];

                var destinationColliderGroupTransform = sourceColliderGroup
                    ? (transformMapping.ContainsKey(sourceColliderGroup.transform)
                        ? transformMapping[sourceColliderGroup.transform]
                        : (transformMapping[sourceColliderGroup.transform] = BoneMapper.FindCorrespondingBone(
                               sourceBone: sourceColliderGroup.transform,
                               source: sourceSpringBone.transform.root.gameObject,
                               destination,
                               sourceSkeletonBones
                               )))
                    : null;

                VRMSpringBoneColliderGroup destinationColliderGroup = null;
                if (destinationColliderGroupTransform)
                {
                    CopyVRMSpringBones.CopySpringBoneColliderGroups(
                        sourceBone: sourceColliderGroup.transform,
                        destinationBone: destinationColliderGroupTransform
                        );
                    destinationColliderGroup
                        = destinationColliderGroupTransform.GetComponent <VRMSpringBoneColliderGroup>();
                }
                destinationSpringBone.ColliderGroups[i] = destinationColliderGroup;
            }

            return(transformMapping);
        }
        /// <summary>
        /// 視線制御の設定をコピーします。
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <param name="sourceSkeletonBones"></param>
        internal static void Copy(
            GameObject source,
            GameObject destination,
            Dictionary <HumanBodyBones, Transform> sourceSkeletonBones
            )
        {
            if (!source.GetComponent <VRMFirstPerson>())
            {
                return;
            }

            var sourceLookAtHead = source.GetComponent <VRMLookAtHead>();

            if (!sourceLookAtHead)
            {
                var destinationLookAtHead = destination.GetComponent <VRMLookAtHead>();
                if (destinationLookAtHead)
                {
                    Object.DestroyImmediate(destinationLookAtHead);
                }
                return;
            }

            var sourceBoneApplyer = source.GetComponent <VRMLookAtBoneApplyer>();

            if (sourceBoneApplyer)
            {
                ComponentUtility.CopyComponent(sourceBoneApplyer);
                var destinationBoneApplyer = destination.GetOrAddComponent <VRMLookAtBoneApplyer>();
                ComponentUtility.PasteComponentValues(destinationBoneApplyer);

                if (destinationBoneApplyer.LeftEye.Transform)
                {
                    destinationBoneApplyer.LeftEye.Transform = BoneMapper.FindCorrespondingBone(
                        sourceBone: destinationBoneApplyer.LeftEye.Transform,
                        source: source,
                        destination: destination,
                        sourceSkeletonBones: sourceSkeletonBones
                        );
                }
                if (destinationBoneApplyer.RightEye.Transform)
                {
                    destinationBoneApplyer.RightEye.Transform = BoneMapper.FindCorrespondingBone(
                        sourceBone: destinationBoneApplyer.RightEye.Transform,
                        source: source,
                        destination: destination,
                        sourceSkeletonBones: sourceSkeletonBones
                        );
                }

                var blendShapeApplyer = destination.GetComponent <VRMLookAtBlendShapeApplyer>();
                if (blendShapeApplyer)
                {
                    Object.DestroyImmediate(blendShapeApplyer);
                }
                return;
            }

            var sourceBlendShapeApplyer = source.GetComponent <VRMLookAtBlendShapeApplyer>();

            if (sourceBlendShapeApplyer)
            {
                ComponentUtility.CopyComponent(sourceBlendShapeApplyer);
                var destinationBlendShapeApplyer = destination.GetOrAddComponent <VRMLookAtBlendShapeApplyer>();
                ComponentUtility.PasteComponentValues(destinationBlendShapeApplyer);
            }
        }