Exemplo n.º 1
0
        private static void RemoveMissingComponents()
        {
            var i18n  = VRCQuestToolsSettings.I18nResource;
            var obj   = Selection.activeGameObject;
            var count = VRCSDKUtility.CountMissingComponentsInChildren(obj, true);

            Debug.Log($"[{VRCQuestTools.Name}] {obj.name} has {count} missing scripts in children");
            if (count == 0)
            {
                EditorUtility.DisplayDialog(VRCQuestTools.Name, i18n.NoMissingComponentsMessage(obj.name), "OK");
                return;
            }

            var needsToUnpackPrefab = PrefabUtility.IsPartOfPrefabInstance(obj);
            var message             = i18n.MissingRemoverConfirmationMessage(obj.name);

            if (needsToUnpackPrefab)
            {
                message += $" ({i18n.UnpackPrefabMessage})";
            }
            if (!EditorUtility.DisplayDialog(VRCQuestTools.Name, message, "OK", i18n.CancelLabel))
            {
                return;
            }

            if (needsToUnpackPrefab)
            {
                Undo.SetCurrentGroupName("Remove Missing Components");

                // Somehow unpacking is needed to apply changes to the scene file.
                PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.OutermostRoot, InteractionMode.UserAction);
                Debug.Log($"[{VRCQuestTools.Name}] {obj.name} has been unpacked");
            }
            VRCSDKUtility.RemoveMissingComponentsInChildren(obj, true);
        }
Exemplo n.º 2
0
#pragma warning restore SA1600 // Elements should be documented

        /// <summary>
        /// Covert the avatar for Quest.
        /// </summary>
        /// <param name="avatar">Avatar to convert.</param>
        /// <param name="assetsDirectory">Root directory to save.</param>
        /// <param name="generateQuestTextures">Whether to generate textures.</param>
        /// <param name="maxTextureSize">Max textures size. 0 for no limits.</param>
        /// <param name="remover">ComponentRemover object.</param>
        /// <param name="progressCallback">Callback to show progress.</param>
        /// <returns>Converted avatar.</returns>
        internal virtual Tuple <VRChatAvatar, string> ConvertForQuest(VRChatAvatar avatar, string assetsDirectory, bool generateQuestTextures, int maxTextureSize, ComponentRemover remover, ProgressCallback progressCallback)
        {
            // Convert materials and generate textures.
            var convertedMaterials = ConvertMaterialsForToonLit(avatar.Materials, assetsDirectory);

            if (generateQuestTextures)
            {
                var generatedTextures = GenrateToonLitTextures(avatar.Materials, assetsDirectory, maxTextureSize, progressCallback.onTextureProgress);
                foreach (var tex in generatedTextures)
                {
                    if (convertedMaterials.ContainsKey(tex.Key))
                    {
                        convertedMaterials[tex.Key].mainTexture = tex.Value;
                    }
                }
                AssetDatabase.SaveAssets();
            }

            // Duplicate the original gameobject.
            var questAvatarObject = UnityEngine.Object.Instantiate(avatar.AvatarDescriptor.gameObject);

            // Convert animator controllers and their animation clips.
            if (avatar.HasAnimatedMaterials)
            {
                var convertedAnimationClips      = ConvertAnimationClipsForQuest(avatar.GetRuntimeAnimatorControllers(), assetsDirectory, convertedMaterials, progressCallback.onAnimationClipProgress);
                var convertedAnimatorControllers = ConvertAnimatorControllersForQuest(avatar.GetRuntimeAnimatorControllers(), assetsDirectory, convertedAnimationClips, progressCallback.onRuntimeAnimatorProgress);

                // Apply converted animator controllers.
#if VRC_SDK_VRCSDK3
                var layers = questAvatarObject.GetComponent <VRC.SDK3.Avatars.Components.VRCAvatarDescriptor>().baseAnimationLayers;
                for (int i = 0; i < layers.Length; i++)
                {
                    if (!layers[i].isDefault && layers[i].animatorController != null)
                    {
                        if (convertedAnimatorControllers.ContainsKey(layers[i].animatorController))
                        {
                            layers[i].animatorController = convertedAnimatorControllers[layers[i].animatorController];
                        }
                    }
                }
#endif

                foreach (var animator in questAvatarObject.GetComponentsInChildren <Animator>(true))
                {
                    if (animator.runtimeAnimatorController != null)
                    {
                        if (convertedAnimatorControllers.ContainsKey(animator.runtimeAnimatorController))
                        {
                            animator.runtimeAnimatorController = convertedAnimatorControllers[animator.runtimeAnimatorController];
                        }
                    }
                }
            }

            // Apply converted materials to renderers.
            // Apply AFTER animator controllers because original animation clips overwrite sharedMaterials.
            foreach (var renderer in questAvatarObject.GetComponentsInChildren <Renderer>(true))
            {
                renderer.sharedMaterials = renderer.sharedMaterials.Select(m =>
                {
                    if (m == null)
                    {
                        return(null);
                    }
                    if (convertedMaterials.ContainsKey(m))
                    {
                        return(convertedMaterials[m]);
                    }
                    return(m);
                }).ToArray();
            }

            VRCSDKUtility.RemoveMissingComponentsInChildren(questAvatarObject, true);
            remover.RemoveUnsupportedComponentsInChildren(questAvatarObject, true);

            questAvatarObject.name = avatar.AvatarDescriptor.gameObject.name + " (Quest)";
            questAvatarObject.SetActive(true);
            var prefabName = $"{assetsDirectory}/{questAvatarObject.name}.prefab";
            return(new Tuple <VRChatAvatar, string>(new VRChatAvatar(questAvatarObject.GetComponent <VRC_AvatarDescriptor>()), prefabName));
        }