예제 #1
0
        public virtual bool ShouldUseConfigForAssetImporter(AssetImporter assetImporter)
        {
            if (!IsEnabled)
            {
                return(false);
            }

            var assetPath = assetImporter.assetPath;

            if (!AssetPreprocessorUtils.DoesRegexStringListMatchString(FilterOutBadRegexStrings(MatchRegexList, nameof(MatchRegexList)), assetPath))
            {
                return(false);
            }

            // Check that the Asset path does NOT match any ignore regex strings.
            if (AssetPreprocessorUtils.DoesRegexStringListMatchString(FilterOutBadRegexStrings(IgnoreRegexList, nameof(IgnoreRegexList)), assetPath))
            {
                return(false);
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPreprocessTexture.html
        /// </summary>
        private void OnPreprocessTexture()
        {
            var textureImporter = (TextureImporter)assetImporter;

            var assetPath    = textureImporter.assetPath;
            var textureName  = AssetPreprocessorUtils.GetAssetNameFromPath(textureImporter.assetPath);
            var texture      = AssetDatabase.LoadAssetAtPath <Texture2D>(assetPath);
            var platformName = EditorUserBuildSettings.activeBuildTarget.ToString();

            var configs = AssetPreprocessorUtils.GetScriptableObjectsOfType <TexturePreprocessorConfig>();

            if (configs.Count == 0)
            {
                Debug.Log($"Could not find a {nameof(TexturePreprocessorConfig)} in project.");

                return;
            }

            configs = configs
                      .Where(conf => conf.ShouldUseConfigForAssetImporter(assetImporter))
                      .ToList();

            configs.Sort((config1, config2) => config1.ConfigSortOrder.CompareTo(config2.ConfigSortOrder));

            TexturePreprocessorConfig config = null;

            for (var i = 0; i < configs.Count; i++)
            {
                var configToTest = configs[i];

                if (!AssetPreprocessorUtils.DoesRegexStringListMatchString(configToTest.PlatformsRegexList, platformName))
                {
                    continue;
                }

                // Found matching config.
                config = configToTest;

                break;
            }

            // If could not find a matching config, don't process the texture.
            if (config == null)
            {
                return;
            }

            var currentPlatform         = EditorUserBuildSettings.activeBuildTarget.ToString();
            var currentPlatformSettings = textureImporter.GetPlatformTextureSettings(currentPlatform);

            var hasAlpha          = textureImporter.DoesSourceTextureHaveAlpha();
            var nativeTextureSize = GetOriginalTextureSize(textureImporter);
            var nativeSize        = Mathf.NextPowerOfTwo(Mathf.Max(nativeTextureSize.width, nativeTextureSize.height));
            var currentFormat     = currentPlatformSettings.format.ToString();

            // Handle when native size for texture is too small. Happens for baked light maps and reflection maps.
            // Need to reimport asset once to get correct native texture size.
            if (nativeSize <= 4)
            {
                AssetDatabase.Refresh();
                return;
            }

            Debug.Log($"Processing: {textureName} | Native size: {nativeSize} | Current format: {currentFormat}", texture);
            Debug.Log($"Using: {config.name}", config);

            // If already contains correct texture format, skip adjusting import settings.
            var matchingSkipRegex     = config.SkipIfCurrentTextureFormatMatchesRegexList.Find(regexString => new Regex(regexString).IsMatch(currentFormat));
            var alreadyContainsFormat = matchingSkipRegex != null;

            if (!config.ForcePreprocess && alreadyContainsFormat)
            {
                Debug.Log($"Skipping preprocess. Current format matching skip regex: '{matchingSkipRegex}'", texture);
                return;
            }

            if (config.EnableReadWrite && !textureImporter.isReadable)
            {
                Debug.Log("Enabling Read/Write.", texture);
                textureImporter.isReadable = true;
            }

            var maxTextureSize      = config.MaxTextureSize;
            var multipliedNativeRes = Mathf.RoundToInt(nativeSize * config.NativeTextureSizeMultiplier);
            var textureSize         = Mathf.Min(multipliedNativeRes, maxTextureSize);

            var format = hasAlpha ? config.RGBAFormat : config.RGBFormat;

            if (config.ForceLinear)
            {
                textureImporter.sRGBTexture = false;
            }

            if (config.ForceFilterMode)
            {
                textureImporter.anisoLevel = config.AnisoLevel;
                textureImporter.filterMode = config.FilterMode;
            }

            textureImporter.mipmapEnabled    = config.GenerateMipMaps;
            textureImporter.streamingMipmaps = config.EnableMipMapStreaming;

            SetTextureImporterPlatformSetting(config, textureImporter, texture, textureName, textureSize, format);
        }
예제 #3
0
        /// <summary>
        /// https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPreprocessAudio.html
        ///
        /// IMPORTANT:
        /// Use OnPostprocessAudio() hook instead of OnPreprocessAudio() since OnPostprocessAudio gives a reference to
        /// the AudioClip, which is needed for AudioClip.length.
        /// </summary>
        private void OnPostprocessAudio(AudioClip audioClip)
        {
            var importer = assetImporter as AudioImporter;

            if (importer == null)
            {
                return;
            }

            var assetPath    = importer.assetPath;
            var assetName    = AssetPreprocessorUtils.GetAssetNameFromPath(importer.assetPath);
            var platformName = EditorUserBuildSettings.activeBuildTarget.ToString();

            if (audioClip == null)
            {
                Debug.LogError($"{typeof(AudioClip)} is null. Path: {assetPath}");

                return;
            }

            var configs = AssetPreprocessorUtils.GetScriptableObjectsOfType <AudioPreprocessorConfig>();

            if (configs.Count == 0)
            {
                Debug.Log($"Could not find a {nameof(AudioPreprocessorConfig)} in project.");

                return;
            }

            configs = configs
                      .Where(conf => conf.ShouldUseConfigForAssetImporter(assetImporter))
                      .ToList();

            configs.Sort((config1, config2) => config1.ConfigSortOrder.CompareTo(config2.ConfigSortOrder));

            AudioPreprocessorConfig config = null;

            for (var i = 0; i < configs.Count; i++)
            {
                var configToTest = configs[i];

                if (!AssetPreprocessorUtils.DoesRegexStringListMatchString(configToTest.PlatformsRegexList, platformName))
                {
                    continue;
                }

                // Check that the AudioClip length is under the config's limit for clip length.
                if (audioClip.length > configToTest.MaxClipLengthInSeconds)
                {
                    continue;
                }

                // Found matching config.
                config = configToTest;

                Debug.Log($"Processing: {assetName}", audioClip);
                Debug.Log($"Using: {config.name}", config);
                break;
            }

            // If could not find a matching config, don't process the asset.
            if (config == null)
            {
                return;
            }

            var hasSampleSettingsOverrides = false;

            if (importer.loadInBackground != config.LoadInBackground)
            {
                importer.loadInBackground  = config.LoadInBackground;
                hasSampleSettingsOverrides = true;
            }

            if (importer.preloadAudioData != config.PreloadAudioData)
            {
                importer.preloadAudioData  = config.PreloadAudioData;
                hasSampleSettingsOverrides = true;
            }

            if (importer.forceToMono != config.ForceToMono)
            {
                importer.forceToMono       = config.ForceToMono;
                hasSampleSettingsOverrides = true;
            }

            if (importer.ambisonic != config.Ambisonic)
            {
                importer.ambisonic         = config.Ambisonic;
                hasSampleSettingsOverrides = true;
            }

            var sampleSettings = importer.GetOverrideSampleSettings(platformName);

            if (sampleSettings.loadType != config.AudioClipLoadType)
            {
                sampleSettings.loadType    = config.AudioClipLoadType;
                hasSampleSettingsOverrides = true;
            }

            if (sampleSettings.compressionFormat != config.AudioCompressionFormat)
            {
                sampleSettings.compressionFormat = config.AudioCompressionFormat;
                hasSampleSettingsOverrides       = true;
            }

            if (System.Math.Abs(sampleSettings.quality - config.Quality) > 0.01f)
            {
                sampleSettings.quality     = config.Quality;
                hasSampleSettingsOverrides = true;
            }

            if (sampleSettings.sampleRateSetting != config.AudioSampleRateSetting)
            {
                sampleSettings.sampleRateSetting = config.AudioSampleRateSetting;
                hasSampleSettingsOverrides       = true;
            }

            if (hasSampleSettingsOverrides || config.ForcePreprocess)
            {
                config.PlatformsRegexList.ForEach(platformRegexString => importer.SetOverrideSampleSettings(platformRegexString, sampleSettings));

                // Be sure to set the platform override for the current platform string, in case the current platform was
                // NOT a perfect match to one of the platform regex strings.
                importer.SetOverrideSampleSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), sampleSettings);
            }
        }
예제 #4
0
        /// <summary>
        /// https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPostprocessModel.html
        /// </summary>
        /// <param name="gameObject">GameObject of the model.</param>
        private void OnPostprocessModel(GameObject model)
        {
            var modelImporter = (ModelImporter)assetImporter;
            var modelName     = AssetPreprocessorUtils.GetAssetNameFromPath(modelImporter.assetPath);

            var configs = AssetPreprocessorUtils.GetScriptableObjectsOfType <ModelPreprocessorConfig>();

            if (configs.Count == 0)
            {
                Debug.Log($"Could not find a {nameof(ModelPreprocessorConfig)} in project.");

                return;
            }

            configs = configs
                      .Where(conf => conf.ShouldUseConfigForAssetImporter(assetImporter))
                      .ToList();

            configs.Sort((config1, config2) => config1.ConfigSortOrder.CompareTo(config2.ConfigSortOrder));

            ModelPreprocessorConfig config = null;

            for (var i = 0; i < configs.Count; i++)
            {
                var configToTest = configs[i];

                // Found matching config.
                config = configToTest;

                Debug.Log($"Processing: {modelName}", model);
                Debug.Log($"Using: {config.name}", config);
                break;
            }

            // If could not find a matching config, don't process the asset.
            if (config == null)
            {
                return;
            }

            modelImporter.sortHierarchyByName = config.SortHierarchyByName;
            modelImporter.importLights        = config.ImportLights;
            modelImporter.importVisibility    = config.ImportVisibility;
            modelImporter.importCameras       = config.ImportCameras;
            modelImporter.isReadable          = config.EnableReadWrite;
            modelImporter.meshCompression     = config.MeshCompression;
            modelImporter.resampleCurves      = config.ResampleCurves;

            if (config.ForceGenerateLightmapUVs)
            {
                modelImporter.generateSecondaryUV = true;
            }

            if (modelImporter.importAnimation)
            {
                modelImporter.animationCompression = config.ModelImporterAnimationCompression;
            }

            if (modelImporter.importMaterials != config.ImportMaterials)
            {
                modelImporter.importMaterials = config.ImportMaterials;
            }

            if (modelImporter.importBlendShapes != config.ImportBlendShapes)
            {
                modelImporter.importBlendShapes = config.ImportBlendShapes;
            }

            if (config.EnableAnimationPreprocessing &&
                modelImporter.animationType != config.ModelImporterAnimationType)
            {
                modelImporter.animationType = config.ModelImporterAnimationType;
            }

            if (config.EnableAnimationPreprocessing &&
                modelImporter.animationType == ModelImporterAnimationType.Human)
            {
                var clips = modelImporter.clipAnimations.ToArray();

                // Enable the bones for ALL of the model's animation clips.
                for (var i = 0; i < clips.Length; i++)
                {
                    var clip = clips[i];

                    if (clip.maskType != ClipAnimationMaskType.CreateFromThisModel)
                    {
                        continue;
                    }

                    var serializedObject = new SerializedObject(modelImporter);

                    var transformMask = serializedObject.FindProperty($"m_ClipAnimations.Array.data[{i}].transformMask");

                    var arrayProperty = transformMask.FindPropertyRelative("Array");

                    for (var j = 0; j < arrayProperty.arraySize; j++)
                    {
                        var element = arrayProperty.GetArrayElementAtIndex(j);

                        var bonePath = element.FindPropertyRelative("m_Path").stringValue;

                        var shouldEnable = false;

                        if (AssetPreprocessorUtils.DoesRegexStringListMatchString(config.MaskBonesToEnable, bonePath))
                        {
                            if (config.EnableVerboseLogging)
                            {
                                Debug.Log($"{clip.name} - Enabling Mask bone: {bonePath}", model);
                            }

                            shouldEnable = true;
                        }

                        element.FindPropertyRelative("m_Weight").floatValue = shouldEnable ? 1 : 0;

                        serializedObject.ApplyModifiedProperties();
                    }
                }

                EditorUtility.SetDirty(model);
            }

            Debug.Log($"Processed: {model.name}", model);
        }
예제 #5
0
        private void OnPreprocessAnimation()
        {
            var modelImporter = assetImporter as ModelImporter;

            if (modelImporter.defaultClipAnimations.Length == 0)
            {
                return;
            }

            var modelName = AssetPreprocessorUtils.GetAssetNameFromPath(modelImporter.assetPath);

            var configs = AssetPreprocessorUtils.GetScriptableObjectsOfType <ModelPreprocessorConfig>();

            if (configs.Count == 0)
            {
                Debug.Log($"Could not find a {nameof(ModelPreprocessorConfig)} in project.");

                return;
            }

            configs = configs
                      .Where(conf => conf.ShouldUseConfigForAssetImporter(assetImporter))
                      .Where(conf => conf.EnableAnimationPreprocessing)
                      .ToList();

            configs.Sort((config1, config2) => config1.ConfigSortOrder.CompareTo(config2.ConfigSortOrder));

            ModelPreprocessorConfig config = null;

            for (var i = 0; i < configs.Count; i++)
            {
                var configToTest = configs[i];

                // Found matching config.
                config = configToTest;
                break;
            }

            // If could not find a matching config, don't process the asset.
            if (config == null)
            {
                return;
            }

            if (modelImporter.clipAnimations.Length > 0 && !config.ForcePreprocess)
            {
                Debug.Log($"Skipping Animation Preprocess - {modelName} - Animation has been preprocessed already before.", config);

                return;
            }

            Debug.Log($"Processing animations for: {modelName}");
            Debug.Log($"Using: {config.name}", config);

            var clips = modelImporter.defaultClipAnimations.ToArray();

            for (var i = 0; i < clips.Length; i++)
            {
                var clip = clips[i];

                clip.keepOriginalPositionXZ  = config.KeepOriginalPositionXZ;
                clip.keepOriginalOrientation = config.KeepOriginalOrientation;
                clip.keepOriginalPositionY   = config.KeepOriginalPositionY;

                clip.maskType = config.ClipAnimationMaskType;

                clips[i] = clip;
            }

            modelImporter.clipAnimations = clips;
        }