├── .gitignore ├── CHANGELOG.MD ├── CHANGELOG.MD.meta ├── Documentation~ ├── add-new-from-manager.gif ├── general-usage.gif └── properties-modification.gif ├── LICENSE.MD ├── LICENSE.MD.meta ├── README.md ├── README.md.meta ├── Scripts.meta ├── Scripts ├── Editor.meta └── Editor │ ├── BrunoMikoski.UnityPreset.Editor.asmdef │ ├── BrunoMikoski.UnityPreset.Editor.asmdef.meta │ ├── FolderCustomEditor.cs │ ├── FolderCustomEditor.cs.meta │ ├── FolderToPresetData.cs │ ├── FolderToPresetData.cs.meta │ ├── PresetAssetPostProcessor.cs │ ├── PresetAssetPostProcessor.cs.meta │ ├── PresetManagerCustomEditor.cs │ ├── PresetManagerCustomEditor.cs.meta │ ├── PresetManagerSettings.cs │ ├── PresetManagerSettings.cs.meta │ ├── PresetManagerStorage.cs │ ├── PresetManagerStorage.cs.meta │ ├── PresetManagerUtils.cs │ └── PresetManagerUtils.cs.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | -------------------------------------------------------------------------------- /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## TODO 8 | - When cleaning up the library the PresetManager its empty. 9 | 10 | ## [0.2.5] - 11 | ### Changed 12 | - Fixed missing information on the json 13 | 14 | ## [0.2.4] - 2020-04-27 15 | ### Changed 16 | - Fixed issue where custom folder editor would check folders outside `Assets/` 17 | 18 | ## [0.2.3] - 2020-04-23 19 | ### Changed 20 | - Fixed PresetManager auto creation sometimes causing issues 21 | - Optimized PreProcessor 22 | 23 | ## [0.2.2] - 2020-04-21 24 | ### Added 25 | - Added settings on Editor Preferences 26 | - Added option to toggle the folder custom editor 27 | - Added option to customize the maximum number of search levels when looking for assets. 28 | 29 | ## [0.2.1] - 2020-04-21 30 | ### Changed 31 | - Fixed problems when checking for new imported assets 32 | - Fixed folder custom inspector with wrong space 33 | - Fix issue when not reimporting assets after applying the changes. 34 | 35 | ## [0.2.0] - 2020-04-16 36 | ### Added 37 | - Added the `PresetManagerStorage` where the settings per folder are store and can serialized 38 | - Added option to customize each one of the Preset 'PropertyModification' per folder. 39 | 40 | ### Changed 41 | - Fixed an issue where the Preset would be applied when selecting the folder. 42 | - A lot of general qol improvements 43 | 44 | ### Removed 45 | 46 | ## [0.1.1] - 2020-04-14 47 | ### Changed 48 | - Fixed license 49 | 50 | ## [0.1.0] - 2020-04-14 51 | ### Added 52 | - Initial Versioning 53 | 54 | [0.2.5]: https://github.com/badawe/PresetManager/releases/tag/v0.2.5 55 | [0.2.4]: https://github.com/badawe/PresetManager/releases/tag/v0.2.4 56 | [0.2.3]: https://github.com/badawe/PresetManager/releases/tag/v0.2.3 57 | [0.2.2]: https://github.com/badawe/PresetManager/releases/tag/v0.2.2 58 | [0.2.1]: https://github.com/badawe/PresetManager/releases/tag/v0.2.1 59 | [0.2.0]: https://github.com/badawe/PresetManager/releases/tag/v0.2.0 60 | [0.1.1]: https://github.com/badawe/PresetManager/releases/tag/v0.1.1 61 | [0.1.0]: https://github.com/badawe/PresetManager/releases/tag/v0.1.0 62 | -------------------------------------------------------------------------------- /CHANGELOG.MD.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ad7a8ec107306e44bef442fb7818b7b 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/add-new-from-manager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunomikoski/PresetManager/0b4ffb3dd2ceeeba99dd17b7eb2a45d684b72dca/Documentation~/add-new-from-manager.gif -------------------------------------------------------------------------------- /Documentation~/general-usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunomikoski/PresetManager/0b4ffb3dd2ceeeba99dd17b7eb2a45d684b72dca/Documentation~/general-usage.gif -------------------------------------------------------------------------------- /Documentation~/properties-modification.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunomikoski/PresetManager/0b4ffb3dd2ceeeba99dd17b7eb2a45d684b72dca/Documentation~/properties-modification.gif -------------------------------------------------------------------------------- /LICENSE.MD: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Bruno Andre Mikoski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.MD.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f145d726f7c9294a95226e2186e5d6a 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Preset Manager 2 | [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://github.com/badawe/PresetManager/blob/develop/LICENSE) 3 | [![openupm](https://img.shields.io/npm/v/com.brunomikoski.presetmanager?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.brunomikoski.presetmanager/) 4 | 5 | ![](https://img.shields.io/github/followers/brunomikoski?label=Follow&style=social) ![](https://img.shields.io/twitter/follow/brunomikoski?style=social) 6 | 7 | Preset Manager is the missing per folder preset for Unity. 8 | 9 | Applies Preset to objects respecting the folder structure and settings. 10 | 11 | 12 | ## Features 13 | - Load all available Presets in the Project 14 | - When a folder is selected, verify if there's an asset that can use one of the available presets. 15 | - Display the Options per asset type 16 | - Automatically applies to new assets 17 | - You can apply the specific preset per folder. 18 | - *Allow customization of ignored properties!* 19 | - Relative changes based on specific folder 20 | 21 | ## System Requirements 22 | Unity 2018.4.0 or later versions. Feel free to try an older version, should work just fine. 23 | 24 | ## Installation 25 | 26 | ### OpenUPM 27 | The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli). 28 | 29 | ``` 30 | openupm add com.brunomikoski.presetmanager 31 | ``` 32 | 33 | ### Manifest 34 | You can also install via git URL by adding this entry in your **manifest.json** 35 | ``` 36 | "com.brunomikoski.presetmanager": "https://github.com/badawe/PresetManager.git" 37 | ``` 38 | 39 | ### Unity Package Manager 40 | ``` 41 | from Window->Package Manager, click on the + sign and Add from git: https://github.com/badawe/PresetManager.git 42 | ``` 43 | 44 | ![inspector](/Documentation~/general-usage.gif) ![Manager](/Documentation~/add-new-from-manager.gif) ![properties](/Documentation~/properties-modification.gif) 45 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93547f58fccbcf74b8fdd52e98f09f30 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd9c35fe6d831014a9fc5352096fddc7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5c3caf3358fb244d88b442c50b08022 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor/BrunoMikoski.UnityPreset.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BrunoMikoski.UnityPreset.Editor", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [ 6 | "Editor" 7 | ], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [] 14 | } -------------------------------------------------------------------------------- /Scripts/Editor/BrunoMikoski.UnityPreset.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78522585f2db3354c913b89e8db46d34 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Editor/FolderCustomEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using UnityEditor; 6 | using UnityEditor.Presets; 7 | using UnityEngine; 8 | 9 | namespace BrunoMikoski.PresetManager 10 | { 11 | [CustomEditor(typeof(DefaultAsset), true)] 12 | public class FolderCustomEditor : Editor 13 | { 14 | private bool isFolder; 15 | private string relativeFolderPath; 16 | private string absoluteFolderPath; 17 | private AssetImporter[] assetImportersType; 18 | private bool[] assetImportersTypeFoldout; 19 | private int selectedIndex = -1; 20 | 21 | private void OnEnable() 22 | { 23 | if (!PresetManagerSettings.DisplayFolderInspector) 24 | return; 25 | 26 | relativeFolderPath = AssetDatabase.GetAssetPath(target); 27 | if(!relativeFolderPath.StartsWith("Assets")) 28 | return; 29 | 30 | absoluteFolderPath = PresetManagerUtils.RelativeToAbsolutePath(relativeFolderPath); 31 | isFolder = Directory.Exists(absoluteFolderPath); 32 | 33 | if (!isFolder) 34 | return; 35 | 36 | ReadFolder(); 37 | } 38 | 39 | public override void OnInspectorGUI() 40 | { 41 | base.OnInspectorGUI(); 42 | 43 | if (!isFolder) 44 | return; 45 | 46 | if (assetImportersType == null || assetImportersType.Length == 0) 47 | return; 48 | 49 | bool wasGUIEnabled = GUI.enabled; 50 | 51 | GUI.enabled = true; 52 | DrawPresetManager(); 53 | GUI.enabled = wasGUIEnabled; 54 | } 55 | 56 | private void DrawPresetManager() 57 | { 58 | using (new GUILayout.HorizontalScope()) 59 | { 60 | GUILayout.Space(-8); 61 | 62 | EditorGUILayout.BeginVertical("Box"); 63 | EditorGUILayout.LabelField("Assets Preset Manager", EditorStyles.toolbarDropDown); 64 | EditorGUI.indentLevel++; 65 | 66 | for (var i = 0; i < assetImportersType.Length; i++) 67 | { 68 | AssetImporter assetImporter = assetImportersType[i]; 69 | assetImportersTypeFoldout[i] = EditorGUILayout.Foldout(assetImportersTypeFoldout[i], 70 | assetImporter.GetType().Name, EditorStyles.foldout); 71 | 72 | if (assetImportersTypeFoldout[i]) 73 | { 74 | ShowOptionsForImporter(assetImporter); 75 | } 76 | } 77 | EditorGUI.indentLevel--; 78 | DrawOptions(); 79 | 80 | EditorGUILayout.EndVertical(); 81 | } 82 | } 83 | 84 | private void DrawOptions() 85 | { 86 | EditorGUILayout.BeginHorizontal("Box"); 87 | bool hasAnyPresetForFolder = PresetManagerUtils.HasAnyPresetForFolder(relativeFolderPath); 88 | EditorGUI.BeginDisabledGroup(!hasAnyPresetForFolder); 89 | if (GUILayout.Button("Apply on current", EditorStyles.toolbarButton)) 90 | { 91 | PresetManagerUtils.ApplyPresetsToFolder(relativeFolderPath); 92 | } 93 | 94 | if (GUILayout.Button("Delete Folder Settings", EditorStyles.toolbarButton)) 95 | { 96 | PresetManagerUtils.ClearAllPresetsForFolder(relativeFolderPath); 97 | selectedIndex = 0; 98 | } 99 | EditorGUI.EndDisabledGroup(); 100 | 101 | 102 | EditorGUILayout.EndHorizontal(); 103 | } 104 | 105 | private void ShowOptionsForImporter(AssetImporter assetImporter) 106 | { 107 | Preset[] presets = PresetManagerUtils.GetAvailablePresetsForAssetImporter(assetImporter); 108 | string[] presetsNames = GetNamesFromList(presets, true); 109 | 110 | if (selectedIndex == -1) 111 | { 112 | if (PresetManagerUtils.TryGetAssetPresetFromFolder(relativeFolderPath, assetImporter, out PresetData appliedPreset)) 113 | selectedIndex = Array.IndexOf(presets, appliedPreset.Preset) + 1; 114 | else 115 | selectedIndex = 0; 116 | } 117 | 118 | if (selectedIndex == 0) 119 | { 120 | if (PresetManagerUtils.TryToGetParentPresetSettings(relativeFolderPath, assetImporter, 121 | out string parentRelativePath)) 122 | { 123 | EditorGUI.BeginDisabledGroup(true); 124 | EditorGUILayout.ObjectField("Inheriting settings from:", 125 | AssetDatabase.LoadAssetAtPath(parentRelativePath), typeof(DefaultAsset), false); 126 | EditorGUI.EndDisabledGroup(); 127 | } 128 | } 129 | 130 | EditorGUI.BeginChangeCheck(); 131 | 132 | using (new GUILayout.HorizontalScope()) 133 | { 134 | GUILayout.Space(20); 135 | selectedIndex = GUILayout.SelectionGrid(selectedIndex, presetsNames, 1, EditorStyles.radioButton); 136 | } 137 | 138 | 139 | if (EditorGUI.EndChangeCheck()) 140 | { 141 | if (selectedIndex > 0) 142 | { 143 | PresetManagerUtils.SetPresetForFolder(relativeFolderPath, presets[selectedIndex - 1]); 144 | } 145 | else 146 | { 147 | PresetManagerUtils.ClearPresetForFolder(relativeFolderPath); 148 | } 149 | } 150 | } 151 | 152 | private string[] GetNamesFromList(Preset[] presets, bool includeNone) 153 | { 154 | List options = new List(); 155 | if (includeNone) 156 | { 157 | options.Add("None"); 158 | } 159 | for (var i = 0; i < presets.Length; i++) 160 | { 161 | Preset preset = presets[i]; 162 | options.Add(preset.name); 163 | } 164 | 165 | return options.ToArray(); 166 | } 167 | 168 | private void ReadFolder() 169 | { 170 | string[] files = GetAllFiles(absoluteFolderPath); 171 | 172 | HashSet assetImporters = new HashSet(); 173 | HashSet assetImportersTypes = new HashSet(); 174 | 175 | for (var i = 0; i < files.Length; i++) 176 | { 177 | string absoluteFilePath = files[i]; 178 | if (absoluteFilePath.EndsWith(".meta")) 179 | continue; 180 | string relativeFilePath = PresetManagerUtils.AbsoluteToRelativePath(absoluteFilePath); 181 | 182 | AssetImporter assetImporter = AssetImporter.GetAtPath(relativeFilePath); 183 | 184 | if (assetImporter == null) 185 | continue; 186 | 187 | if (!PresetManagerUtils.HasPresetFor(assetImporter)) 188 | continue; 189 | 190 | if(assetImportersTypes.Contains(assetImporter.GetType())) 191 | continue; 192 | 193 | assetImporters.Add(assetImporter); 194 | assetImportersTypes.Add(assetImporter.GetType()); 195 | } 196 | 197 | assetImportersType = assetImporters.ToArray(); 198 | if (assetImportersTypeFoldout == null || assetImportersTypeFoldout.Length != assetImportersType.Length) 199 | assetImportersTypeFoldout = new bool[assetImportersType.Length]; 200 | } 201 | 202 | private string[] GetAllFiles(string absoluteFolderPath) 203 | { 204 | List filesPath = new List(); 205 | int level = 0; 206 | SearchForAllFiles(absoluteFolderPath, ref filesPath, ref level); 207 | return filesPath.ToArray(); 208 | } 209 | 210 | private void SearchForAllFiles(string directoryAbsolutePath, ref List filesPath, ref int level) 211 | { 212 | filesPath.AddRange(Directory.GetFiles(directoryAbsolutePath)); 213 | 214 | string[] folderPaths = Directory.GetDirectories(directoryAbsolutePath); 215 | for (int i = 0; i < folderPaths.Length; i++) 216 | { 217 | string folderPath = folderPaths[i]; 218 | string absoluteToRelativePath = PresetManagerUtils.AbsoluteToRelativePath(folderPath); 219 | 220 | if (level > PresetManagerSettings.MaximumDirectorySearch) 221 | continue; 222 | 223 | if (!PresetManagerUtils.HasAnyPresetForFolder(absoluteToRelativePath)) 224 | { 225 | level++; 226 | SearchForAllFiles(folderPath, ref filesPath, ref level); 227 | } 228 | } 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /Scripts/Editor/FolderCustomEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 04cd83d7974c16349b8e274c013f3d2b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/FolderToPresetData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEditor.Presets; 5 | using UnityEngine; 6 | 7 | namespace BrunoMikoski.PresetManager 8 | { 9 | [Serializable] 10 | public struct FolderToPresetData 11 | { 12 | [SerializeField] 13 | private string folderGUID; 14 | public string FolderGuid => folderGUID; 15 | 16 | [SerializeField] 17 | private string presetGUID; 18 | public string PresetGuid => presetGUID; 19 | 20 | public bool IsValid => !string.IsNullOrEmpty(folderGUID) && !string.IsNullOrEmpty(presetGUID); 21 | 22 | private List ignoredProperties; 23 | 24 | public FolderToPresetData(string folderGUID, string presetGUID) 25 | { 26 | this.folderGUID = folderGUID; 27 | this.presetGUID = presetGUID; 28 | 29 | ignoredProperties = new List(); 30 | 31 | } 32 | 33 | public void OverridePresetGUID(string presetGUID) 34 | { 35 | this.presetGUID = presetGUID; 36 | } 37 | 38 | public bool IsSettingEnabled(string propertyModificationPropertyPath) 39 | { 40 | if (ignoredProperties == null) 41 | return true; 42 | 43 | for (int i = 0; i < ignoredProperties.Count; i++) 44 | { 45 | string ignoredProperty = ignoredProperties[i]; 46 | if (string.Equals(ignoredProperty, propertyModificationPropertyPath, StringComparison.Ordinal)) 47 | { 48 | return false; 49 | } 50 | } 51 | 52 | return true; 53 | } 54 | 55 | public void SetSettingEnabled(string propertyModificationPropertyPath, bool settingEnabled) 56 | { 57 | if (settingEnabled) 58 | { 59 | if (ignoredProperties == null) 60 | return; 61 | 62 | ignoredProperties.Remove(propertyModificationPropertyPath); 63 | } 64 | else 65 | { 66 | if (ignoredProperties == null) 67 | ignoredProperties = new List(); 68 | 69 | ignoredProperties.Add(propertyModificationPropertyPath); 70 | } 71 | } 72 | 73 | public string[] GetModifications(Preset preset) 74 | { 75 | List finalItems = new List(); 76 | for (int i = 0; i < preset.PropertyModifications.Length; i++) 77 | { 78 | PropertyModification presetPropertyModification = preset.PropertyModifications[i]; 79 | if(ignoredProperties != null && ignoredProperties.Contains(presetPropertyModification.propertyPath)) 80 | continue; 81 | 82 | finalItems.Add(presetPropertyModification.propertyPath); 83 | } 84 | 85 | return finalItems.ToArray(); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Scripts/Editor/FolderToPresetData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a17ce6a58e8a4bdbac58bf72ac5b53e6 3 | timeCreated: 1586979707 -------------------------------------------------------------------------------- /Scripts/Editor/PresetAssetPostProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using UnityEditor; 3 | 4 | namespace BrunoMikoski.PresetManager 5 | { 6 | public class PresetAssetPostProcessor : AssetPostprocessor 7 | { 8 | private void OnPreprocessAsset() 9 | { 10 | if (!assetImporter.importSettingsMissing) 11 | return; 12 | 13 | if (IsPresetAsset(assetImporter.assetPath)) 14 | { 15 | PresetManagerUtils.ProjectPresetsChanged(); 16 | return; 17 | } 18 | 19 | string path = Path.GetDirectoryName(assetPath); 20 | if (string.IsNullOrEmpty(path)) 21 | return; 22 | 23 | PresetManagerUtils.ApplySettingsToAsset(path, assetImporter); 24 | } 25 | 26 | static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, 27 | string[] movedFromAssetPaths) 28 | { 29 | if (!PresetManagerStorage.IsInstanceAvailable()) 30 | return; 31 | 32 | if (!IsPresetAsset(importedAssets) && !IsPresetAsset(deletedAssets)) 33 | return; 34 | 35 | PresetManagerUtils.ProjectPresetsChanged(); 36 | } 37 | 38 | private static bool IsPresetAsset(params string[] assetsPath) 39 | { 40 | for (int i = 0; i < assetsPath.Length; i++) 41 | { 42 | string assetPath = assetsPath[i]; 43 | 44 | if (assetPath.EndsWith(".preset")) 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Scripts/Editor/PresetAssetPostProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee2c8e407f4c4b7e96ff170e2db2bfb1 3 | timeCreated: 1586615523 -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerCustomEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using UnityEditor; 4 | using UnityEditor.Presets; 5 | using UnityEngine; 6 | 7 | namespace BrunoMikoski.PresetManager 8 | { 9 | [CustomEditor(typeof(PresetManagerStorage))] 10 | public sealed class PresetManagerCustomEditor : Editor 11 | { 12 | private PresetManagerStorage presetManagerStorage; 13 | private bool[] foldoutPerSettings; 14 | private bool addNewSetup; 15 | 16 | [SerializeField] 17 | private DefaultAsset newSetupFolder; 18 | 19 | [SerializeField] 20 | private Preset newSetupPreset; 21 | 22 | private void OnEnable() 23 | { 24 | presetManagerStorage = (PresetManagerStorage)target; 25 | } 26 | 27 | public override void OnInspectorGUI() 28 | { 29 | List folderToPresetDatas = presetManagerStorage.FoldersPresets; 30 | for (int i = folderToPresetDatas.Count - 1; i >= 0; i--) 31 | { 32 | FolderToPresetData folderToPresetData = folderToPresetDatas[i]; 33 | 34 | if (!folderToPresetData.IsValid) 35 | continue; 36 | 37 | DrawFolderToPreset(i, folderToPresetData); 38 | } 39 | DrawExtraOptions(); 40 | } 41 | 42 | private void DrawExtraOptions() 43 | { 44 | if (!addNewSetup) 45 | addNewSetup |= GUILayout.Button("+", EditorStyles.toolbarButton); 46 | 47 | if (addNewSetup) 48 | { 49 | DrawAddNewSettings(); 50 | } 51 | } 52 | 53 | private void DrawAddNewSettings() 54 | { 55 | EditorGUILayout.BeginVertical("Box"); 56 | EditorGUILayout.LabelField($"Add new Folder to Preset config", EditorStyles.toolbarDropDown); 57 | EditorGUILayout.Space(); 58 | newSetupFolder = (DefaultAsset) EditorGUILayout.ObjectField("Folder", newSetupFolder, typeof(DefaultAsset), false); 59 | newSetupPreset = (Preset) EditorGUILayout.ObjectField("Preset", newSetupPreset, typeof(Preset), false); 60 | 61 | 62 | EditorGUILayout.BeginHorizontal(); 63 | EditorGUI.BeginDisabledGroup(newSetupFolder == null || newSetupPreset == null || !HasFolderSelected()); 64 | 65 | if (GUILayout.Button("Save", EditorStyles.toolbarButton)) 66 | { 67 | FolderToPresetData folderToPresetData = new FolderToPresetData( 68 | AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(newSetupFolder)), 69 | AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(newSetupPreset))); 70 | 71 | 72 | EditorUtility.SetDirty(presetManagerStorage); 73 | 74 | newSetupFolder = null; 75 | newSetupPreset = null; 76 | addNewSetup = false; 77 | foldoutPerSettings = null; 78 | presetManagerStorage.FoldersPresets.Add(folderToPresetData); 79 | } 80 | EditorGUI.EndDisabledGroup(); 81 | 82 | if (GUILayout.Button("Cancel", EditorStyles.toolbarButton)) 83 | { 84 | newSetupFolder = null; 85 | newSetupPreset = null; 86 | addNewSetup = false; 87 | } 88 | EditorGUILayout.EndHorizontal(); 89 | 90 | 91 | EditorGUILayout.EndVertical(); 92 | } 93 | 94 | private bool HasFolderSelected() 95 | { 96 | if (newSetupFolder == null) 97 | return false; 98 | 99 | string path = AssetDatabase.GetAssetPath(newSetupFolder); 100 | return Directory.Exists(PresetManagerUtils.RelativeToAbsolutePath(path)); 101 | } 102 | 103 | private void DrawFolderToPreset(int index, FolderToPresetData folderToPresetData) 104 | { 105 | string folderPath = AssetDatabase.GUIDToAssetPath(folderToPresetData.FolderGuid); 106 | DefaultAsset folder = AssetDatabase.LoadAssetAtPath(folderPath); 107 | string presetPath = AssetDatabase.GUIDToAssetPath(folderToPresetData.PresetGuid); 108 | Preset preset = AssetDatabase.LoadAssetAtPath(presetPath); 109 | 110 | EditorGUILayout.BeginVertical("Box"); 111 | EditorGUILayout.LabelField($"{preset.name} -> {folder.name}", EditorStyles.toolbarDropDown); 112 | 113 | DrawReferences(folderPath, folder, presetPath, preset); 114 | DrawPresetOptions(index, folderToPresetData, preset); 115 | 116 | 117 | EditorGUILayout.EndVertical(); 118 | } 119 | 120 | private void DrawPresetOptions(int index, FolderToPresetData folderToPresetData, Preset preset) 121 | { 122 | EditorGUI.indentLevel++; 123 | 124 | if (foldoutPerSettings == null) 125 | foldoutPerSettings = new bool[presetManagerStorage.FoldersPresets.Count]; 126 | 127 | foldoutPerSettings[index] = EditorGUILayout.Foldout(foldoutPerSettings[index], 128 | "Customize Parameters", EditorStyles.foldout); 129 | 130 | if (foldoutPerSettings[index]) 131 | { 132 | for (int i = 0; i < preset.PropertyModifications.Length; i++) 133 | { 134 | PropertyModification propertyModification = preset.PropertyModifications[i]; 135 | 136 | EditorGUI.BeginChangeCheck(); 137 | bool settingEnabled = folderToPresetData.IsSettingEnabled(propertyModification.propertyPath); 138 | settingEnabled = EditorGUILayout.ToggleLeft(propertyModification.propertyPath, settingEnabled); 139 | if (EditorGUI.EndChangeCheck()) 140 | { 141 | folderToPresetData.SetSettingEnabled(propertyModification.propertyPath, settingEnabled); 142 | EditorUtility.SetDirty(presetManagerStorage); 143 | } 144 | } 145 | 146 | EditorGUILayout.BeginHorizontal(); 147 | if (GUILayout.Button("Select All", EditorStyles.toolbarButton)) 148 | { 149 | ToggleAllProperties(folderToPresetData, preset, true); 150 | } 151 | 152 | if (GUILayout.Button("Unselect All", EditorStyles.toolbarButton)) 153 | { 154 | ToggleAllProperties(folderToPresetData, preset, false); 155 | } 156 | EditorGUILayout.EndHorizontal(); 157 | } 158 | 159 | if (GUILayout.Button("Delete", EditorStyles.toolbarButton)) 160 | { 161 | presetManagerStorage.FoldersPresets.Remove(folderToPresetData); 162 | } 163 | 164 | EditorGUI.indentLevel--; 165 | 166 | } 167 | 168 | private void ToggleAllProperties(FolderToPresetData folderToPresetData, Preset preset, bool enabled) 169 | { 170 | for (int i = 0; i < preset.PropertyModifications.Length; i++) 171 | { 172 | PropertyModification presetPropertyModification = preset.PropertyModifications[i]; 173 | folderToPresetData.SetSettingEnabled(presetPropertyModification.propertyPath, enabled); 174 | } 175 | 176 | EditorUtility.SetDirty(presetManagerStorage); 177 | } 178 | 179 | private void DrawReferences(string folderPath, DefaultAsset folder, string presetPath, Preset preset) 180 | { 181 | EditorGUILayout.Space(); 182 | EditorGUI.BeginDisabledGroup(true); 183 | 184 | EditorGUILayout.BeginHorizontal(); 185 | EditorGUILayout.LabelField($"{folderPath}", EditorStyles.toolbarTextField); 186 | EditorGUILayout.ObjectField(folder, typeof(DefaultAsset), false); 187 | EditorGUILayout.EndHorizontal(); 188 | 189 | 190 | EditorGUILayout.BeginHorizontal(); 191 | EditorGUILayout.LabelField($"{presetPath}", EditorStyles.toolbarTextField); 192 | EditorGUILayout.ObjectField(preset, typeof(Preset), false); 193 | EditorGUILayout.EndHorizontal(); 194 | 195 | EditorGUI.EndDisabledGroup(); 196 | } 197 | } 198 | } -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerCustomEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42ca71db651f424b9de2e145f948b36c 3 | timeCreated: 1587062489 -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerSettings.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace BrunoMikoski.PresetManager 4 | { 5 | public class PresetManagerSettings 6 | { 7 | public static bool DisplayFolderInspector 8 | { 9 | get => EditorPrefs.GetBool(nameof(DisplayFolderInspector), true); 10 | set => EditorPrefs.SetBool(nameof(DisplayFolderInspector), value); 11 | } 12 | 13 | public static int MaximumDirectorySearch 14 | { 15 | get => EditorPrefs.GetInt(nameof(MaximumDirectorySearch), 3); 16 | set => EditorPrefs.SetInt(nameof(MaximumDirectorySearch), value); 17 | } 18 | 19 | //I refuse to use this terrible Settings Provider thingy from unity, so until the new preferences package 20 | //is available, this warning will happen :( 21 | //https://docs.unity3d.com/2018.3/Documentation/ScriptReference/SettingsProvider.html 22 | 23 | [PreferenceItem("Preset Manager")] 24 | public static void PreferencesGUI() 25 | { 26 | EditorGUI.BeginChangeCheck(); 27 | bool displayFolderInspector = EditorGUILayout.Toggle("Show Folder Inspector", DisplayFolderInspector); 28 | int maximumDirectorySearch = 29 | EditorGUILayout.IntField("Maximum Recursive Search Levels", MaximumDirectorySearch); 30 | 31 | if (EditorGUI.EndChangeCheck()) 32 | { 33 | DisplayFolderInspector = displayFolderInspector; 34 | MaximumDirectorySearch = maximumDirectorySearch; 35 | } 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 378b26e0864440a4b3a65393dbfb3ea0 3 | timeCreated: 1587584930 -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using UnityEditor; 5 | using UnityEditor.Presets; 6 | using UnityEngine; 7 | 8 | namespace BrunoMikoski.PresetManager 9 | { 10 | public struct PresetData 11 | { 12 | public Preset Preset; 13 | public string[] TargetParameters; 14 | 15 | public PresetData(Preset preset, string[] targetParameters) 16 | { 17 | Preset = preset; 18 | TargetParameters = targetParameters; 19 | } 20 | } 21 | 22 | 23 | public class PresetManagerStorage : ScriptableObject 24 | { 25 | private const string DEFAULT_STORAGE_PATH = "Assets/PresetManager/PresetManager.asset"; 26 | 27 | [SerializeField] 28 | private List foldersPresets = new List(); 29 | public List FoldersPresets => foldersPresets; 30 | 31 | private static PresetManagerStorage instance; 32 | public static PresetManagerStorage Instance 33 | { 34 | get 35 | { 36 | GetOrCreateInstance(); 37 | return instance; 38 | } 39 | } 40 | 41 | public static bool IsInstanceAvailable() 42 | { 43 | return Instance != null; 44 | } 45 | 46 | private static void GetOrCreateInstance() 47 | { 48 | if (instance != null) 49 | return; 50 | 51 | string[] avaialbleGUIDs = AssetDatabase.FindAssets("t:PresetManagerStorage"); 52 | if (avaialbleGUIDs.Length == 0) 53 | { 54 | string directoryPath = Path.GetDirectoryName(Path.GetFullPath(DEFAULT_STORAGE_PATH)); 55 | 56 | if (!Directory.Exists(directoryPath)) 57 | Directory.CreateDirectory(directoryPath); 58 | 59 | instance = CreateInstance(); 60 | 61 | AssetDatabase.CreateAsset(instance, DEFAULT_STORAGE_PATH); 62 | AssetDatabase.SaveAssets(); 63 | } 64 | else 65 | { 66 | instance = AssetDatabase.LoadAssetAtPath( 67 | AssetDatabase.GUIDToAssetPath(avaialbleGUIDs[0])); 68 | 69 | ValidateInstances(); 70 | } 71 | } 72 | 73 | private static void ValidateInstances() 74 | { 75 | for (int i = Instance.foldersPresets.Count - 1; i >= 0; i--) 76 | { 77 | FolderToPresetData instanceFoldersPreset = Instance.foldersPresets[i]; 78 | if (!instanceFoldersPreset.IsValid) 79 | Instance.foldersPresets.RemoveAt(i); 80 | } 81 | } 82 | 83 | public bool HasAnyPresetForFolder(string relativeFolderPath) 84 | { 85 | return TryGetPresetsForFolder(relativeFolderPath, out PresetData[] presets); 86 | } 87 | 88 | public bool TryGetPresetFolderPathFromFolder(string relativeFolderPath, AssetImporter assetImporter, 89 | out string ownerFolder) 90 | { 91 | ownerFolder = string.Empty; 92 | if (TryGetPresetsForFolder(relativeFolderPath, out PresetData[] presets)) 93 | { 94 | for (int i = 0; i < presets.Length; i++) 95 | { 96 | PresetData currentPreset = presets[i]; 97 | if (currentPreset.Preset.CanBeAppliedTo(assetImporter)) 98 | { 99 | ownerFolder = relativeFolderPath; 100 | return true; 101 | } 102 | } 103 | } 104 | 105 | return false; 106 | } 107 | 108 | public bool TryGetAssetPresetFromFolder(string relativeFolderPath, AssetImporter assetImporter, out PresetData preset) 109 | { 110 | if (TryGetPresetsForFolder(relativeFolderPath, out PresetData[] presets)) 111 | { 112 | for (int i = 0; i < presets.Length; i++) 113 | { 114 | PresetData currentPreset = presets[i]; 115 | if (currentPreset.Preset.CanBeAppliedTo(assetImporter)) 116 | { 117 | preset = currentPreset; 118 | return true; 119 | } 120 | } 121 | } 122 | 123 | preset = default; 124 | return false; 125 | } 126 | 127 | public bool TryGetPresetsForFolder(string relativeFolderPath, out PresetData[] preset) 128 | { 129 | List presetsList = new List(); 130 | string folderGUID = AssetDatabase.AssetPathToGUID(relativeFolderPath); 131 | for (int i = 0; i < foldersPresets.Count; i++) 132 | { 133 | FolderToPresetData folderToPresetReference = foldersPresets[i]; 134 | if (string.Equals(folderToPresetReference.FolderGuid, folderGUID, StringComparison.Ordinal)) 135 | { 136 | string presetPath = AssetDatabase.GUIDToAssetPath(folderToPresetReference.PresetGuid); 137 | Preset loadedPreset = AssetDatabase.LoadAssetAtPath(presetPath); 138 | if (loadedPreset != null) 139 | { 140 | presetsList.Add(new PresetData(loadedPreset, 141 | folderToPresetReference.GetModifications(loadedPreset))); 142 | } 143 | } 144 | } 145 | 146 | preset = presetsList.ToArray(); 147 | return presetsList.Count > 0; 148 | } 149 | 150 | public void SetPresetForFolder(string relativeFolderPath, Preset preset) 151 | { 152 | if (TryGetFolderPresetIndex(relativeFolderPath, out int targetIndex)) 153 | { 154 | foldersPresets[targetIndex].OverridePresetGUID(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(preset))); 155 | } 156 | else 157 | { 158 | foldersPresets.Add(new FolderToPresetData(AssetDatabase.AssetPathToGUID(relativeFolderPath), 159 | AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(preset)))); 160 | } 161 | 162 | EditorUtility.SetDirty(this); 163 | } 164 | 165 | private bool TryGetFolderPresetIndex(string relativeFolderPath, out int index) 166 | { 167 | string folderGUID = AssetDatabase.AssetPathToGUID(relativeFolderPath); 168 | for (int i = 0; i < foldersPresets.Count; i++) 169 | { 170 | FolderToPresetData folderToPresetReference = foldersPresets[i]; 171 | if (string.Equals(folderToPresetReference.FolderGuid, folderGUID, StringComparison.Ordinal)) 172 | { 173 | index = i; 174 | return true; 175 | } 176 | } 177 | 178 | index = -1; 179 | return false; 180 | } 181 | 182 | public void ClearPresetForFolder(string relativeFolderPath) 183 | { 184 | string folderPathGUID = AssetDatabase.AssetPathToGUID(relativeFolderPath); 185 | for (int i = 0; i < foldersPresets.Count; i++) 186 | { 187 | FolderToPresetData folderToPresetReference = foldersPresets[i]; 188 | 189 | if (string.Equals(folderToPresetReference.FolderGuid, folderPathGUID, StringComparison.Ordinal)) 190 | { 191 | foldersPresets.RemoveAt(i); 192 | EditorUtility.SetDirty(this); 193 | } 194 | } 195 | } 196 | 197 | public void ClearAllPresetForFolder(string relativeFolderPath) 198 | { 199 | string folderPathGUID = AssetDatabase.AssetPathToGUID(relativeFolderPath); 200 | for (int i = foldersPresets.Count - 1; i >= 0; i--) 201 | { 202 | FolderToPresetData folderToPresetReference = foldersPresets[i]; 203 | 204 | if (string.Equals(folderToPresetReference.FolderGuid, folderPathGUID, StringComparison.Ordinal)) 205 | { 206 | foldersPresets.RemoveAt(i); 207 | } 208 | } 209 | 210 | EditorUtility.SetDirty(this); 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerStorage.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f397b1982baf4ffc9f1ff526cd860aa7 3 | timeCreated: 1586978949 -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using UnityEditor; 5 | using UnityEditor.Presets; 6 | using UnityEngine; 7 | 8 | namespace BrunoMikoski.PresetManager 9 | { 10 | public static class PresetManagerUtils 11 | { 12 | private static List projectPresets; 13 | private static List ProjectPresets 14 | { 15 | get 16 | { 17 | if (projectPresets == null) 18 | LoadProjectPresets(); 19 | return projectPresets; 20 | } 21 | } 22 | 23 | private static void LoadProjectPresets() 24 | { 25 | string[] presetsGUIDs = AssetDatabase.FindAssets("t:Preset"); 26 | 27 | projectPresets = new List(); 28 | for (var i = 0; i < presetsGUIDs.Length; i++) 29 | { 30 | projectPresets.Add( 31 | AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(presetsGUIDs[i]))); 32 | } 33 | } 34 | 35 | public static Preset[] GetAvailablePresetsForAssetImporter(AssetImporter assetImporter) 36 | { 37 | List resultPresets = new List(); 38 | for (int i = 0; i < ProjectPresets.Count; i++) 39 | { 40 | Preset preset = ProjectPresets[i]; 41 | if (!preset.CanBeAppliedTo(assetImporter)) 42 | continue; 43 | 44 | resultPresets.Add(preset); 45 | } 46 | 47 | return resultPresets.ToArray(); 48 | } 49 | 50 | public static bool HasAnyPresetForFolder(string relativeFolderPath) 51 | { 52 | return PresetManagerStorage.Instance.HasAnyPresetForFolder(relativeFolderPath); 53 | } 54 | 55 | public static bool HasPresetFor(AssetImporter assetImporter) 56 | { 57 | for (int i = 0; i < ProjectPresets.Count; i++) 58 | { 59 | Preset preset = ProjectPresets[i]; 60 | if (!preset.CanBeAppliedTo(assetImporter)) 61 | continue; 62 | 63 | return true; 64 | } 65 | 66 | return false; 67 | } 68 | 69 | public static bool TryGetAssetPresetFromFolder(string relativeFolderPath, AssetImporter assetImporter, 70 | out PresetData preset) 71 | { 72 | return PresetManagerStorage.Instance.TryGetAssetPresetFromFolder(relativeFolderPath, assetImporter, out preset); 73 | } 74 | 75 | public static void SetPresetForFolder(string relativeFolderPath, Preset preset) 76 | { 77 | PresetManagerStorage.Instance.SetPresetForFolder(relativeFolderPath, preset); 78 | } 79 | 80 | public static void ClearPresetForFolder(string relativeFolderPath) 81 | { 82 | PresetManagerStorage.Instance.ClearPresetForFolder(relativeFolderPath); 83 | } 84 | 85 | public static void ClearAllPresetsForFolder(string relativeFolderPath) 86 | { 87 | PresetManagerStorage.Instance.ClearAllPresetForFolder(relativeFolderPath); 88 | } 89 | 90 | public static void ProjectPresetsChanged() 91 | { 92 | projectPresets = null; 93 | } 94 | 95 | public static bool TryToGetParentPresetSettings(string relativeFolderPath, AssetImporter assetImporter, 96 | out string relativeParentPath) 97 | { 98 | DirectoryInfo currentDirectory = new DirectoryInfo(RelativeToAbsolutePath(relativeFolderPath)).Parent; 99 | 100 | relativeParentPath = string.Empty; 101 | while (currentDirectory != null && !string.Equals(currentDirectory.FullName, Directory.GetCurrentDirectory(), StringComparison.Ordinal)) 102 | { 103 | if (PresetManagerStorage.Instance.TryGetPresetFolderPathFromFolder(AbsoluteToRelativePath(currentDirectory.FullName), 104 | assetImporter, out string ownerFolderPath)) 105 | { 106 | relativeParentPath = ownerFolderPath; 107 | break; 108 | } 109 | currentDirectory = currentDirectory.Parent; 110 | } 111 | 112 | return !string.IsNullOrEmpty(relativeParentPath); 113 | } 114 | 115 | public static bool TryToGetParentPresetSettings(string relativeFolderPath, AssetImporter assetImporter, 116 | out PresetData preset) 117 | { 118 | DirectoryInfo currentDirectory = new DirectoryInfo(RelativeToAbsolutePath(relativeFolderPath)).Parent; 119 | 120 | preset = default; 121 | while (currentDirectory != null && !string.Equals(currentDirectory.FullName, Directory.GetCurrentDirectory(), StringComparison.Ordinal)) 122 | { 123 | if (PresetManagerStorage.Instance.TryGetAssetPresetFromFolder(AbsoluteToRelativePath(currentDirectory.FullName), 124 | assetImporter, out preset)) 125 | break; 126 | currentDirectory = currentDirectory.Parent; 127 | } 128 | 129 | return preset.Preset != null; 130 | } 131 | 132 | 133 | public static string AbsoluteToRelativePath(string absoluteFilePath) 134 | { 135 | return "Assets" + absoluteFilePath.Substring(Application.dataPath.Length); 136 | } 137 | 138 | public static string RelativeToAbsolutePath(string relativeFilePath) 139 | { 140 | return Path.GetFullPath(relativeFilePath); 141 | } 142 | 143 | public static void ApplySettingsToAsset(string relativeFolderPath, AssetImporter assetImporter) 144 | { 145 | if (TryGetAssetPresetFromFolder(relativeFolderPath, assetImporter, out PresetData preset)) 146 | { 147 | ApplyPresetToAssetImporter(assetImporter, preset); 148 | } 149 | else 150 | { 151 | if(TryToGetParentPresetSettings(relativeFolderPath, assetImporter, out preset)) 152 | { 153 | ApplyPresetToAssetImporter(assetImporter, preset); 154 | } 155 | } 156 | } 157 | 158 | private static void ApplyPresetToAssetImporter(AssetImporter assetImporter, PresetData preset) 159 | { 160 | if (preset.Preset.ApplyTo(assetImporter, preset.TargetParameters)) 161 | { 162 | assetImporter.SaveAndReimport(); 163 | EditorUtility.SetDirty(assetImporter); 164 | } 165 | } 166 | 167 | [MenuItem("Assets/Apply Presets")] 168 | public static void ApplyPresetsToSelectFolder() 169 | { 170 | var folderPath = AssetDatabase.GetAssetPath(Selection.activeInstanceID); 171 | if (string.IsNullOrEmpty(folderPath)) 172 | { 173 | var getActiveFolderPath = typeof(ProjectWindowUtil).GetMethod( 174 | "GetActiveFolderPath", 175 | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); 176 | if (getActiveFolderPath != null) 177 | folderPath = (string)getActiveFolderPath.Invoke(null, null); 178 | } 179 | if(!AssetDatabase.IsValidFolder(folderPath)) return; 180 | ApplyPresetsToFolder(folderPath); 181 | } 182 | 183 | public static void ApplyPresetsToFolder(string relativeFolderPath) 184 | { 185 | projectPresets = null; 186 | string[] assetPaths = GetAllAssetsAtDirectory(relativeFolderPath); 187 | for (int i = 0; i < assetPaths.Length; i++) 188 | { 189 | AssetImporter assetImporter = AssetImporter.GetAtPath(assetPaths[i]); 190 | ApplySettingsToAsset(relativeFolderPath, assetImporter); 191 | } 192 | 193 | string[] subFolder = AssetDatabase.GetSubFolders(relativeFolderPath); 194 | for (var i = 0; i < subFolder.Length; i++) 195 | { 196 | string subFolderPath = subFolder[i]; 197 | ApplyPresetsToFolder(subFolderPath); 198 | } 199 | } 200 | 201 | 202 | public static string[] GetAllAssetsAtDirectory(string relativeDirectoryPath) 203 | { 204 | string[] fileEntries = Directory.GetFiles(RelativeToAbsolutePath(relativeDirectoryPath)); 205 | List resuts = new List(); 206 | 207 | for (var i = 0; i < fileEntries.Length; i++) 208 | { 209 | string fileEntry = fileEntries[i]; 210 | if (fileEntry.EndsWith(".meta")) 211 | continue; 212 | 213 | resuts.Add(AbsoluteToRelativePath(fileEntry)); 214 | } 215 | 216 | return resuts.ToArray(); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /Scripts/Editor/PresetManagerUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49af4a32bfc547eabe72a4877dbb785d 3 | timeCreated: 1586596661 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.brunomikoski.presetmanager", 3 | "displayName": "Preset Manager", 4 | "version": "0.2.5", 5 | "unity": "2018.4", 6 | "description": "The missing folder based preset for assets.", 7 | "keywords": [ 8 | "asset importer", 9 | "preset", 10 | "folder" 11 | ], 12 | "category": "editor extensions", 13 | "homepage": "https://github.com/brunomikoski/PresetManager", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/brunomikoski/PresetManager.git" 17 | }, 18 | "bugs": "https://github.com/brunomikoski/PresetManager/issues", 19 | "author": { 20 | "name": "Bruno Mikoski", 21 | "url": "https://www.brunomikoski.com" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a56cfa97eb19e37449a915ba45a468d8 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------