238 lines
10 KiB
C#
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 |