258 lines
11 KiB
C#
258 lines
11 KiB
C#
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace PathBerserker2d
|
|
{
|
|
[InitializeOnLoad]
|
|
internal class PathBerserker2dSettingsProvider : SettingsProvider
|
|
{
|
|
static int settingsLoadTryCount = 0;
|
|
|
|
static PathBerserker2dSettingsProvider()
|
|
{
|
|
TryLoadSettings();
|
|
if (PathBerserker2dSettings.instance == null)
|
|
{
|
|
EditorApplication.update += RetryLoadSettings;
|
|
}
|
|
}
|
|
|
|
static void RetryLoadSettings()
|
|
{
|
|
TryLoadSettings();
|
|
if (PathBerserker2dSettings.instance != null)
|
|
{
|
|
EditorApplication.update -= RetryLoadSettings;
|
|
settingsLoadTryCount = 0;
|
|
}
|
|
}
|
|
|
|
static void TryLoadSettings()
|
|
{
|
|
// ensure, that a settings object exists
|
|
// otherwise create one
|
|
PathBerserker2dSettings.instance = Resources.Load<PathBerserker2dSettings>(PathBerserker2dSettings.GlobalSettingsFile);
|
|
if (PathBerserker2dSettings.instance == null)
|
|
{
|
|
// security check
|
|
if (System.IO.File.Exists(System.IO.Path.Combine(Application.dataPath, "PathBerserker2d/Resources/", PathBerserker2dSettings.GlobalSettingsFile + ".asset")))
|
|
{
|
|
#if DEBUG
|
|
Debug.Log("Couldn't load settings file, but it does exist.");
|
|
#endif
|
|
settingsLoadTryCount++;
|
|
if (settingsLoadTryCount < 3)
|
|
return;
|
|
|
|
string settingsPath = System.IO.Path.Combine("PathBerserker2d/Resources/", PathBerserker2dSettings.GlobalSettingsFile + ".asset");
|
|
if (!EditorUtility.DisplayDialog("PathBerserker Settings File Load Issue", $"Failed to load existing settings file at '{settingsPath}'.", "Retry", "Replace")) {
|
|
CreateNewSettingsFile();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CreateNewSettingsFile();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void CreateNewSettingsFile() {
|
|
Debug.Log("Found no existing settings file. Creating a new one.");
|
|
// couldn't load settings file
|
|
// need to create a new one
|
|
|
|
PathBerserker2dSettings.instance = ScriptableObject.CreateInstance<PathBerserker2dSettings>();
|
|
PathBerserker2dSettings.instance.OnValidate();
|
|
|
|
AssetDatabase.CreateAsset(PathBerserker2dSettings.instance, System.IO.Path.Combine(PathBerserker2dSettings.GlobalSettingsFolder, PathBerserker2dSettings.GlobalSettingsFile) + ".asset");
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
public const string WindowPath = "Project/PathBerserker2d";
|
|
|
|
|
|
private SerializedObject globalSettings;
|
|
private SerializedProperty spNavLinkTypeNames;
|
|
private SerializedProperty spDrawUnselectedLinks;
|
|
private SerializedProperty spDrawUnselectedSurfaces;
|
|
private SerializedProperty spDrawUnselectedSubstractors;
|
|
private SerializedProperty spPointMappingDistance;
|
|
private SerializedProperty spNavSegmentTags;
|
|
private SerializedProperty spDrawGraphWhilePlaying;
|
|
private SerializedProperty spClosestToSegmentMaxDistance;
|
|
private SerializedProperty spPathfinderThreadCount;
|
|
private SerializedProperty spInitiateUpdateInterval;
|
|
private SerializedProperty spNavSurfaceLineWidth;
|
|
private SerializedProperty spNavAreaMarkerLineWidth;
|
|
private SerializedProperty spDrawUnselectedAreaMarkers;
|
|
private SerializedProperty spUsePolygonCollider2dPathsForBaking;
|
|
private ReorderableList linkTypeList;
|
|
private ReorderableList navSegmentTags;
|
|
|
|
public PathBerserker2dSettingsProvider(string path, SettingsScope scope = SettingsScope.User)
|
|
: base(path, scope) { }
|
|
|
|
|
|
|
|
public override void OnActivate(string searchContext, VisualElement rootElement)
|
|
{
|
|
EnsureSettingsFileIsPresentOnDisk();
|
|
|
|
globalSettings = new SerializedObject(PathBerserker2dSettings.instance);
|
|
spNavLinkTypeNames = globalSettings.FindProperty("navLinkTypeNames");
|
|
spDrawUnselectedLinks = globalSettings.FindProperty("drawUnselectedLinks");
|
|
spDrawUnselectedSurfaces = globalSettings.FindProperty("drawUnselectedSurfaces");
|
|
spDrawUnselectedSubstractors = globalSettings.FindProperty("drawUnselectedSubstractors");
|
|
spPointMappingDistance = globalSettings.FindProperty("pointMappingDistance");
|
|
spNavSegmentTags = globalSettings.FindProperty("navTags");
|
|
spDrawGraphWhilePlaying = globalSettings.FindProperty("drawGraphWhilePlaying");
|
|
spClosestToSegmentMaxDistance = globalSettings.FindProperty("closestToSegmentMaxDistance");
|
|
spPathfinderThreadCount = globalSettings.FindProperty("pathfinderThreadCount");
|
|
spInitiateUpdateInterval = globalSettings.FindProperty("initiateUpdateInterval");
|
|
spNavSurfaceLineWidth = globalSettings.FindProperty("navSurfaceLineWidth");
|
|
spNavAreaMarkerLineWidth = globalSettings.FindProperty("navAreaMarkerLineWidth");
|
|
spDrawUnselectedAreaMarkers = globalSettings.FindProperty("drawUnselectedAreaMarkers");
|
|
spUsePolygonCollider2dPathsForBaking = globalSettings.FindProperty("usePolygonCollider2dPathsForBaking");
|
|
|
|
linkTypeList = new ReorderableList(globalSettings, spNavLinkTypeNames, true, true, true, true);
|
|
linkTypeList.drawHeaderCallback = DrawLinkTypeListHeader;
|
|
linkTypeList.drawElementCallback = DrawLinkTypeListItems;
|
|
linkTypeList.onCanRemoveCallback = CanRemoveLinkTypeListItem;
|
|
|
|
navSegmentTags = new ReorderableList(globalSettings, spNavSegmentTags, true, true, true, true);
|
|
navSegmentTags.drawHeaderCallback = DrawSegmentTagListHeader;
|
|
navSegmentTags.drawElementCallback = DrawSegmentTagListItems;
|
|
navSegmentTags.onRemoveCallback = OnRemoveNavTag;
|
|
navSegmentTags.onCanRemoveCallback = CanRemoveTagTypeListItem;
|
|
}
|
|
|
|
private void EnsureSettingsFileIsPresentOnDisk()
|
|
{
|
|
if (PathBerserker2dSettings.instance != null && AssetDatabase.Contains(PathBerserker2dSettings.instance))
|
|
return;
|
|
|
|
var instance = Resources.Load<PathBerserker2dSettings>(PathBerserker2dSettings.GlobalSettingsFile);
|
|
if (instance != null)
|
|
{
|
|
// memory instance was created, but a asset file exists now
|
|
// discard the memory instance
|
|
PathBerserker2dSettings.instance = instance;
|
|
}
|
|
else
|
|
{
|
|
var path = System.IO.Path.Combine(PathBerserker2dSettings.GlobalSettingsFolder, PathBerserker2dSettings.GlobalSettingsFile) + ".asset";
|
|
AssetDatabase.CreateAsset(PathBerserker2dSettings.instance, path);
|
|
}
|
|
}
|
|
|
|
public override void OnGUI(string searchContext)
|
|
{
|
|
// Use IMGUI to display UI:
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
// pathfinding
|
|
EditorGUILayout.PropertyField(spPointMappingDistance);
|
|
EditorGUILayout.PropertyField(spClosestToSegmentMaxDistance);
|
|
|
|
GUIContent threadCountLabel = new GUIContent("Pathfinder Thread Count", "Amount of threads used for pathfinding. NOTE: WebGL doesn't support threads.");
|
|
|
|
GUI.enabled = EditorUserBuildSettings.activeBuildTarget != BuildTarget.WebGL;
|
|
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL)
|
|
EditorGUILayout.IntField(threadCountLabel, 1);
|
|
else
|
|
EditorGUILayout.PropertyField(spPathfinderThreadCount, threadCountLabel);
|
|
|
|
GUI.enabled = true;
|
|
EditorGUILayout.PropertyField(spInitiateUpdateInterval);
|
|
EditorGUILayout.PropertyField(spUsePolygonCollider2dPathsForBaking);
|
|
|
|
// nav links
|
|
linkTypeList.DoLayoutList();
|
|
|
|
|
|
// nav segments
|
|
navSegmentTags.DoLayoutList();
|
|
|
|
// visualization
|
|
EditorGUILayout.PropertyField(spDrawUnselectedLinks);
|
|
EditorGUILayout.PropertyField(spDrawUnselectedSurfaces);
|
|
EditorGUILayout.PropertyField(spDrawUnselectedSubstractors);
|
|
EditorGUILayout.PropertyField(spDrawUnselectedAreaMarkers);
|
|
EditorGUILayout.PropertyField(spDrawGraphWhilePlaying);
|
|
EditorGUILayout.PropertyField(spNavSurfaceLineWidth);
|
|
EditorGUILayout.PropertyField(spNavAreaMarkerLineWidth);
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
globalSettings.ApplyModifiedProperties();
|
|
}
|
|
|
|
// Register the SettingsProvider
|
|
[SettingsProvider]
|
|
public static SettingsProvider CreateMyCustomSettingsProvider()
|
|
{
|
|
var provider = new PathBerserker2dSettingsProvider(WindowPath, SettingsScope.Project);
|
|
|
|
provider.keywords = new string[] {
|
|
"NavLinkTypeNames"
|
|
|
|
};
|
|
return provider;
|
|
}
|
|
|
|
private void DrawLinkTypeListHeader(Rect rect)
|
|
{
|
|
EditorGUI.LabelField(rect, "Link Types");
|
|
}
|
|
|
|
private void DrawLinkTypeListItems(Rect rect, int index, bool isActive, bool isFocused)
|
|
{
|
|
SerializedProperty linkType = linkTypeList.serializedProperty.GetArrayElementAtIndex(index);
|
|
GUI.enabled = index >= PathBerserker2dSettings.buildinNavLinkTypeNames.Length;
|
|
|
|
float orgWidth = rect.width;
|
|
rect.width *= 0.7f;
|
|
|
|
EditorGUI.PropertyField(rect, linkType, new GUIContent("Type " + index));
|
|
GUI.enabled = true;
|
|
|
|
rect.x += rect.width + 5;
|
|
rect.width = orgWidth - rect.width - 5;
|
|
PathBerserker2dSettings.NavLinkTypeColors[index] = EditorGUI.ColorField(rect, PathBerserker2dSettings.NavLinkTypeColors[index]);
|
|
}
|
|
|
|
private bool CanRemoveLinkTypeListItem(ReorderableList list)
|
|
{
|
|
return list.index >= PathBerserker2dSettings.buildinNavLinkTypeNames.Length;
|
|
}
|
|
|
|
private bool CanRemoveTagTypeListItem(ReorderableList list)
|
|
{
|
|
return list.index > 0;
|
|
}
|
|
|
|
private void DrawSegmentTagListHeader(Rect rect)
|
|
{
|
|
EditorGUI.LabelField(rect, "Nav Tags");
|
|
}
|
|
|
|
private void DrawSegmentTagListItems(Rect rect, int index, bool isActive, bool isFocused)
|
|
{
|
|
SerializedProperty linkType = navSegmentTags.serializedProperty.GetArrayElementAtIndex(index);
|
|
|
|
float orgWidth = rect.width;
|
|
rect.width *= 0.7f;
|
|
EditorGUI.PropertyField(rect, linkType, new GUIContent("Tag " + index));
|
|
|
|
rect.x += rect.width + 5;
|
|
rect.width = orgWidth - rect.width - 5;
|
|
PathBerserker2dSettings.NavTagColors[index] = EditorGUI.ColorField(rect, PathBerserker2dSettings.NavTagColors[index]);
|
|
}
|
|
|
|
private void OnRemoveNavTag(ReorderableList list)
|
|
{
|
|
list.serializedProperty.DeleteArrayElementAtIndex(list.index);
|
|
}
|
|
}
|
|
} |