StationObscurum/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs

238 lines
10 KiB
C#

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnitySettingsProviderAttribute = UnityEditor.SettingsProviderAttribute;
using UnitySettingsProvider = UnityEditor.SettingsProvider;
using FishNet.Configuring;
using System.Linq;
namespace FishNet.Editing.PrefabCollectionGenerator
{
internal static class SettingsProvider
{
private static readonly Regex SlashRegex = new Regex(@"[\\//]");
private static PrefabGeneratorConfigurations _settings;
private static GUIContent _folderIcon;
private static GUIContent _deleteIcon;
private static Vector2 _scrollVector;
private static bool _showFolders;
[UnitySettingsProvider]
private static UnitySettingsProvider Create()
{
return new UnitySettingsProvider("Project/Fish-Networking/Prefab Objects Generator", SettingsScope.Project)
{
label = "Prefab Objects Generator",
guiHandler = OnGUI,
keywords = new string[]
{
"Fish",
"Networking",
"Prefab",
"Objects",
"Generator",
},
};
}
private static void OnGUI(string searchContext)
{
if (_settings == null)
_settings = Configuration.Configurations.PrefabGenerator;
if (_folderIcon == null)
_folderIcon = EditorGUIUtility.IconContent("d_FolderOpened Icon");
if (_deleteIcon == null)
_deleteIcon = EditorGUIUtility.IconContent("P4_DeletedLocal");
EditorGUI.BeginChangeCheck();
GUIStyle scrollViewStyle = new GUIStyle()
{
padding = new RectOffset(10, 10, 10, 10),
};
_scrollVector = EditorGUILayout.BeginScrollView(_scrollVector, scrollViewStyle);
_settings.Enabled = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.Enabled)), _settings.Enabled);
_settings.LogToConsole = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.LogToConsole)), _settings.LogToConsole);
_settings.FullRebuild = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.FullRebuild)), _settings.FullRebuild);
_settings.SaveChanges = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.SaveChanges)), _settings.SaveChanges);
GUILayoutOption iconWidthConstraint = GUILayout.MaxWidth(32.0f);
GUILayoutOption iconHeightConstraint = GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight);
EditorGUILayout.BeginHorizontal();
string oldAssetPath = _settings.DefaultPrefabObjectsPath;
string newAssetPath = EditorGUILayout.DelayedTextField(ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath)), oldAssetPath);
if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint))
{
if (TrySaveFilePathInsideAssetsFolder(null, Application.dataPath, "DefaultPrefabObjects", "asset", out string result))
newAssetPath = result;
else
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder."));
}
if (!newAssetPath.Equals(oldAssetPath, StringComparison.OrdinalIgnoreCase))
{
if (newAssetPath.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
{
if (File.Exists(newAssetPath))
{
EditorWindow.focusedWindow.ShowNotification(new GUIContent("Another asset already exists at the new path."));
}
else
{
Generator.IgnorePostProcess = true;
if (File.Exists(oldAssetPath))
AssetDatabase.MoveAsset(oldAssetPath, newAssetPath);
_settings.DefaultPrefabObjectsPath = newAssetPath;
Generator.IgnorePostProcess = false;
}
}
else
{
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder."));
}
}
EditorGUILayout.EndHorizontal();
int currentSearchScope = _settings.SearchScope;
SearchScopeType searchScopeType = (SearchScopeType)EditorGUILayout.EnumPopup(ValueToSearchScope(_settings.SearchScope));
_settings.SearchScope = (int)searchScopeType;
SearchScopeType ValueToSearchScope(int value) => (SearchScopeType)value;
if (_settings.SearchScope == (int)SearchScopeType.EntireProject)
{
EditorGUILayout.HelpBox("Searching the entire project for prefabs can become very slow. Consider switching the search scope to specific folders instead.", MessageType.Warning);
if (GUILayout.Button("Switch"))
_settings.SearchScope = (int)SearchScopeType.SpecificFolders;
}
//If search scope changed then update prefabs.
if (currentSearchScope != _settings.SearchScope && (SearchScopeType)_settings.SearchScope == SearchScopeType.EntireProject)
Generator.GenerateFull();
List<string> folders = null;
string foldersName = null;
if (_settings.SearchScope == (int)SearchScopeType.EntireProject)
{
folders = _settings.ExcludedFolders;
foldersName = ObjectNames.NicifyVariableName(nameof(_settings.ExcludedFolders));
}
else if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders)
{
folders = _settings.IncludedFolders;
foldersName = ObjectNames.NicifyVariableName(nameof(_settings.IncludedFolders));
}
string folderName = foldersName.Substring(0, foldersName.Length - 1);
if ((_showFolders = EditorGUILayout.Foldout(_showFolders, $"{foldersName} ({folders.Count})")) && folders != null)
{
EditorGUI.indentLevel++;
for (int i = 0; i < folders.Count; i++)
{
EditorGUILayout.BeginHorizontal();
string oldFolder = folders[i];
string newFolder = SlashRegex.Replace(EditorGUILayout.DelayedTextField(oldFolder), Path.DirectorySeparatorChar.ToString());
if (!newFolder.Equals(oldFolder, StringComparison.OrdinalIgnoreCase))
{
if (newFolder.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
folders[i] = newFolder;
else
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
}
if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint))
{
if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result))
folders[i] = result;
else
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
}
if (GUILayout.Button(_deleteIcon, iconWidthConstraint, iconHeightConstraint)) folders.RemoveAt(i);
EditorGUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders) EditorGUILayout.HelpBox("You can include subfolders by appending an asterisk (*) to a path.", MessageType.None);
if (GUILayout.Button("Browse"))
{
if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result))
{
folders.Add(result);
}
else
{
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
}
}
}
if (EditorGUI.EndChangeCheck())
Configuration.Configurations.Write(true);
if (GUILayout.Button("Generate"))
Generator.GenerateFull();
EditorGUILayout.HelpBox("Consider pressing 'Generate' after changing the settings.", MessageType.Info);
EditorGUILayout.EndScrollView();
}
private static bool TrySaveFilePathInsideAssetsFolder(string title, string directory, string name, string extension, out string result)
{
result = null;
string selectedPath = EditorUtility.SaveFilePanel(title, directory, name, extension);
if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase))
{
result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString());
return true;
}
return false;
}
private static bool TryOpenFolderPathInsideAssetsFolder(string title, string folder, string name, out string result)
{
result = null;
string selectedPath = EditorUtility.OpenFolderPanel(title, folder, name);
if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase))
{
result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString());
return true;
}
return false;
}
}
}
#endif