Exemplo n.º 1
0
        private static HashSet <System.Type> GetWhitelistForSDK(GameObject avatar)
        {
            VRC.SDKBase.VRC_AvatarDescriptor descriptor = avatar.GetComponent <VRC.SDKBase.VRC_AvatarDescriptor>();

#if VRC_SDK_VRCSDK2
            if (descriptor is VRCSDK2.VRC_AvatarDescriptor)
            {
                if (CombinedComponentTypeWhiteListSdk2 == null)
                {
                    List <string> concatenation = new List <string>(ComponentTypeWhiteListCommon);
                    concatenation.AddRange(ComponentTypeWhiteListSdk2);
                    CombinedComponentTypeWhiteListSdk2 = concatenation.ToArray();
                }
                return(ValidationUtils.WhitelistedTypes("avatar-sdk2", CombinedComponentTypeWhiteListSdk2));
            }
#endif
#if VRC_SDK_VRCSDK3
            if (descriptor is VRC.SDK3.Avatars.Components.VRCAvatarDescriptor)
            {
                if (CombinedComponentTypeWhiteListSdk3 == null)
                {
                    List <string> concatenation = new List <string>(ComponentTypeWhiteListCommon);
                    concatenation.AddRange(ComponentTypeWhiteListSdk3);
                    CombinedComponentTypeWhiteListSdk3 = concatenation.ToArray();
                }
                return(ValidationUtils.WhitelistedTypes("avatar-sdk3", CombinedComponentTypeWhiteListSdk3));
            }
#endif
            throw new System.Exception("Malformed avatar");
        }
        public override void OnGUIAvatar(VRC.SDKBase.VRC_AvatarDescriptor avatar)
        {
            EditorGUILayout.BeginVertical(VRCSdkControlPanel.boxGuiStyle);
            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.BeginVertical(GUILayout.Width(300));
            EditorGUILayout.Space();

            GUILayout.Label("Online Publishing", VRCSdkControlPanel.infoGuiStyle);
            GUILayout.Label(
                "In order for other people to see your avatar in VRChat it must be built and published to our game servers.",
                VRCSdkControlPanel.infoGuiStyle);

            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical(GUILayout.Width(200));
            EditorGUILayout.Space();

            GUI.enabled = _builder.NoGuiErrorsOrIssues() ||
                          VRC.Core.APIUser.CurrentUser.developerType == VRC.Core.APIUser.DeveloperType.Internal;
            if (GUILayout.Button(VRCSdkControlPanel.GetBuildAndPublishButtonString()))
            {
                bool buildBlocked = !VRCBuildPipelineCallbacks.OnVRCSDKBuildRequested(VRCSDKRequestedBuildType.Avatar);
                if (!buildBlocked)
                {
                    if (VRC.Core.APIUser.CurrentUser.canPublishAvatars)
                    {
                        EnvConfig.FogSettings originalFogSettings = EnvConfig.GetFogSettings();
                        EnvConfig.SetFogSettings(
                            new EnvConfig.FogSettings(EnvConfig.FogSettings.FogStrippingMode.Custom, true, true, true));

#if UNITY_ANDROID
                        EditorPrefs.SetBool("VRC.SDKBase_StripAllShaders", true);
#else
                        EditorPrefs.SetBool("VRC.SDKBase_StripAllShaders", false);
#endif

                        VRC_SdkBuilder.shouldBuildUnityPackage = VRCSdkControlPanel.FutureProofPublishEnabled;
                        VRC_SdkBuilder.ExportAndUploadAvatarBlueprint(avatar.gameObject);

                        EnvConfig.SetFogSettings(originalFogSettings);

                        // this seems to workaround a Unity bug that is clearing the formatting of two levels of Layout
                        // when we call the upload functions
                        return;
                    }
                    else
                    {
                        VRCSdkControlPanel.ShowContentPublishPermissionsDialog();
                    }
                }
            }

            EditorGUILayout.EndVertical();
            EditorGUILayout.Space();

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            GUI.enabled = true;
        }
        public override void ValidateFeatures(VRC.SDKBase.VRC_AvatarDescriptor avatar, Animator anim, AvatarPerformanceStats perfStats)
        {
            IEnumerable <Component> componentsToRemove      = AvatarValidation.FindIllegalComponents(avatar.gameObject);
            HashSet <string>        componentsToRemoveNames = new HashSet <string>();
            IEnumerable <Component> toRemove = componentsToRemove as Component[] ?? componentsToRemove.ToArray();

            foreach (Component c in toRemove)
            {
                if (componentsToRemoveNames.Contains(c.GetType().Name) == false)
                {
                    componentsToRemoveNames.Add(c.GetType().Name);
                }
            }

            if (componentsToRemoveNames.Count > 0)
            {
                _builder.OnGUIError(avatar,
                                    "The following component types are found on the Avatar and will be removed by the client: " +
                                    string.Join(", ", componentsToRemoveNames.ToArray()),
                                    delegate { ShowRestrictedComponents(toRemove); },
                                    delegate { FixRestrictedComponents(toRemove); });
            }

            List <AudioSource> audioSources =
                avatar.gameObject.GetComponentsInChildren <AudioSource>(true).ToList();

            if (audioSources.Count > 0)
            {
                _builder.OnGUIWarning(avatar,
                                      "Audio sources found on Avatar, they will be adjusted to safe limits, if necessary.",
                                      GetAvatarSubSelectAction(avatar, typeof(AudioSource)), null);
            }

            List <VRCStation> stations =
                avatar.gameObject.GetComponentsInChildren <VRCStation>(true).ToList();

            if (stations.Count > 0)
            {
                _builder.OnGUIWarning(avatar, "Stations found on Avatar, they will be adjusted to safe limits, if necessary.",
                                      GetAvatarSubSelectAction(avatar, typeof(VRCStation)), null);
            }

            if (VRCSdkControlPanel.HasSubstances(avatar.gameObject))
            {
                _builder.OnGUIWarning(avatar,
                                      "This avatar has one or more Substance materials, which is not supported and may break in-game. Please bake your Substances to regular materials.",
                                      () => { Selection.objects = VRCSdkControlPanel.GetSubstanceObjects(avatar.gameObject); },
                                      null);
            }

            CheckAvatarMeshesForLegacyBlendShapesSetting(avatar);

#if UNITY_ANDROID
            IEnumerable <Shader> illegalShaders = AvatarValidation.FindIllegalShaders(avatar.gameObject);
            foreach (Shader s in illegalShaders)
            {
                _builder.OnGUIError(avatar, "Avatar uses unsupported shader '" + s.name + "'. You can only use the shaders provided in 'VRChat/Mobile' for Quest avatars.", delegate() { Selection.activeObject
                                                                                                                                                                                             = avatar.gameObject; }, null);
            }
#endif

            foreach (AvatarPerformanceCategory perfCategory in Enum.GetValues(typeof(AvatarPerformanceCategory)))
            {
                if (perfCategory == AvatarPerformanceCategory.Overall ||
                    perfCategory == AvatarPerformanceCategory.PolyCount ||
                    perfCategory == AvatarPerformanceCategory.AABB ||
                    perfCategory == AvatarPerformanceCategory.AvatarPerformanceCategoryCount)
                {
                    continue;
                }

                Action show = null;

                switch (perfCategory)
                {
                case AvatarPerformanceCategory.AnimatorCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(Animator));
                    break;

                case AvatarPerformanceCategory.AudioSourceCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(AudioSource));
                    break;

                case AvatarPerformanceCategory.BoneCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(SkinnedMeshRenderer));
                    break;

                case AvatarPerformanceCategory.ClothCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(Cloth));
                    break;

                case AvatarPerformanceCategory.ClothMaxVertices:
                    show = GetAvatarSubSelectAction(avatar, typeof(Cloth));
                    break;

                case AvatarPerformanceCategory.LightCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(Light));
                    break;

                case AvatarPerformanceCategory.LineRendererCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(LineRenderer));
                    break;

                case AvatarPerformanceCategory.MaterialCount:
                    show = GetAvatarSubSelectAction(avatar,
                                                    new[] { typeof(MeshRenderer), typeof(SkinnedMeshRenderer) });
                    break;

                case AvatarPerformanceCategory.MeshCount:
                    show = GetAvatarSubSelectAction(avatar,
                                                    new[] { typeof(MeshRenderer), typeof(SkinnedMeshRenderer) });
                    break;

                case AvatarPerformanceCategory.ParticleCollisionEnabled:
                    show = GetAvatarSubSelectAction(avatar, typeof(ParticleSystem));
                    break;

                case AvatarPerformanceCategory.ParticleMaxMeshPolyCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(ParticleSystem));
                    break;

                case AvatarPerformanceCategory.ParticleSystemCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(ParticleSystem));
                    break;

                case AvatarPerformanceCategory.ParticleTotalCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(ParticleSystem));
                    break;

                case AvatarPerformanceCategory.ParticleTrailsEnabled:
                    show = GetAvatarSubSelectAction(avatar, typeof(ParticleSystem));
                    break;

                case AvatarPerformanceCategory.PhysicsColliderCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(Collider));
                    break;

                case AvatarPerformanceCategory.PhysicsRigidbodyCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(Rigidbody));
                    break;

                case AvatarPerformanceCategory.PolyCount:
                    show = GetAvatarSubSelectAction(avatar,
                                                    new[] { typeof(MeshRenderer), typeof(SkinnedMeshRenderer) });
                    break;

                case AvatarPerformanceCategory.SkinnedMeshCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(SkinnedMeshRenderer));
                    break;

                case AvatarPerformanceCategory.TrailRendererCount:
                    show = GetAvatarSubSelectAction(avatar, typeof(TrailRenderer));
                    break;
                }

                // we can only show these buttons if DynamicBone is installed

                Type dynamicBoneType         = typeof(AvatarValidation).Assembly.GetType("DynamicBone");
                Type dynamicBoneColliderType = typeof(AvatarValidation).Assembly.GetType("DynamicBoneCollider");
                if ((dynamicBoneType != null) && (dynamicBoneColliderType != null))
                {
                    switch (perfCategory)
                    {
                    case AvatarPerformanceCategory.DynamicBoneColliderCount:
                        show = GetAvatarSubSelectAction(avatar, dynamicBoneColliderType);
                        break;

                    case AvatarPerformanceCategory.DynamicBoneCollisionCheckCount:
                        show = GetAvatarSubSelectAction(avatar, dynamicBoneColliderType);
                        break;

                    case AvatarPerformanceCategory.DynamicBoneComponentCount:
                        show = GetAvatarSubSelectAction(avatar, dynamicBoneType);
                        break;

                    case AvatarPerformanceCategory.DynamicBoneSimulatedBoneCount:
                        show = GetAvatarSubSelectAction(avatar, dynamicBoneType);
                        break;
                    }
                }

                OnGUIPerformanceInfo(avatar, perfStats, perfCategory, show, null);
            }

            _builder.OnGUILink(avatar, "Avatar Optimization Tips", VRCSdkControlPanel.AVATAR_OPTIMIZATION_TIPS_URL);
        }