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); }
/// <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); }
/// <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); } }
/// <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); }