update
This commit is contained in:
9
Packages/com.arongranberg.astar/PackageTools/Editor.meta
Normal file
9
Packages/com.arongranberg.astar/PackageTools/Editor.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cbdf52f81d0d4ce7860eab2a4d018cd
|
||||
folderAsset: yes
|
||||
timeCreated: 1500391729
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
// Disable the warning: "Field 'DependencyCheck.Dependency.name' is never assigned to, and will always have its default value null"
|
||||
#pragma warning disable 649
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pathfinding.Util {
|
||||
[InitializeOnLoad]
|
||||
static class DependencyCheck {
|
||||
struct Dependency {
|
||||
public string name;
|
||||
public string version;
|
||||
}
|
||||
|
||||
static DependencyCheck() {
|
||||
var missingDependencies = new Dependency[] {
|
||||
#if !MODULE_BURST
|
||||
new Dependency {
|
||||
name = "com.unity.burst",
|
||||
version = "1.8.3",
|
||||
},
|
||||
#endif
|
||||
#if !MODULE_MATHEMATICS
|
||||
new Dependency {
|
||||
name = "com.unity.mathematics",
|
||||
version = "1.2.6",
|
||||
},
|
||||
#endif
|
||||
#if !MODULE_COLLECTIONS
|
||||
new Dependency {
|
||||
name = "com.unity.collections",
|
||||
version = "1.5.1",
|
||||
},
|
||||
#endif
|
||||
// #if !MODULE_ENTITIES
|
||||
// new Dependency {
|
||||
// name = "com.unity.entities",
|
||||
// version = "1.0.0-pre.47",
|
||||
// },
|
||||
// #endif
|
||||
};
|
||||
|
||||
if (missingDependencies.Length > 0) {
|
||||
string missing = string.Join(", ", missingDependencies.Select(p => p.name + " (" + p.version + ")"));
|
||||
bool res = EditorUtility.DisplayDialog("Missing dependencies", "The packages " + missing + " are required by the A* Pathfinding Project but they are not installed, or the installed versions are too old. Do you want to install the latest versions of the packages?", "Ok", "Cancel");
|
||||
if (res) {
|
||||
foreach (var dep in missingDependencies) {
|
||||
UnityEditor.PackageManager.Client.Add(dep.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// E.g. 2023.3.0b8
|
||||
var v = Application.unityVersion.Split('.');
|
||||
UnityEngine.Assertions.Assert.IsTrue(v.Length >= 3, "Unity version string is not in the expected format");
|
||||
var major = int.Parse(v[0]);
|
||||
var minor = int.Parse(v[1]);
|
||||
// Filter out non-digits from v[2]
|
||||
v[2] = new string(v[2].TakeWhile(char.IsDigit).ToArray());
|
||||
var patch = int.Parse(v[2]);
|
||||
if (major == 2022 && minor == 3 && patch < 21) {
|
||||
Debug.LogError("This version of Unity has a bug which causes components in the A* Pathfinding Project to randomly stop working. Please update to unity 2022.3.21 or later.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13cd4e1cd3bf242b3a58eb62092ce599
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,317 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Pathfinding {
|
||||
/// <summary>Helper for creating editors</summary>
|
||||
[CustomEditor(typeof(VersionedMonoBehaviour), true)]
|
||||
[CanEditMultipleObjects]
|
||||
public class EditorBase : Editor {
|
||||
static System.Collections.Generic.Dictionary<string, string> cachedTooltips;
|
||||
static System.Collections.Generic.Dictionary<string, string> cachedURLs;
|
||||
Dictionary<string, SerializedProperty> props = new Dictionary<string, SerializedProperty>();
|
||||
|
||||
static GUIContent content = new GUIContent();
|
||||
static GUIContent showInDocContent = new GUIContent("Show in online documentation", "");
|
||||
static GUILayoutOption[] noOptions = new GUILayoutOption[0];
|
||||
public static System.Func<string> getDocumentationURL;
|
||||
|
||||
protected HashSet<string> remainingUnhandledProperties;
|
||||
|
||||
|
||||
static void LoadMeta () {
|
||||
if (cachedTooltips == null) {
|
||||
var filePath = EditorResourceHelper.editorAssets + "/tooltips.tsv";
|
||||
|
||||
try {
|
||||
var lines = System.IO.File.ReadAllLines(filePath).Select(l => l.Split('\t', 3)).Where(l => l.Length == 3).ToArray();
|
||||
cachedURLs = lines.ToDictionary(l => l[0], l => l[1]);
|
||||
cachedTooltips = lines.ToDictionary(l => l[0], l => l[2].Replace("\\n", "\n"));
|
||||
} catch (System.Exception e) {
|
||||
Debug.LogWarning("Could not load tooltips from " + filePath + "\n" + e);
|
||||
cachedURLs = new System.Collections.Generic.Dictionary<string, string>();
|
||||
cachedTooltips = new System.Collections.Generic.Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static string LookupPath (System.Type type, string path, Dictionary<string, string> lookupData) {
|
||||
// Find the correct type if the path was not an immediate member of #type
|
||||
while (true) {
|
||||
var index = path.IndexOf('.');
|
||||
if (index == -1) break;
|
||||
var fieldName = path.Substring(0, index);
|
||||
var remaining = path.Substring(index + 1);
|
||||
var field = type.GetField(fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
|
||||
if (field != null) {
|
||||
type = field.FieldType;
|
||||
path = remaining;
|
||||
} else {
|
||||
// Could not find the correct field
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a documentation entry for the field, fall back to parent classes if necessary
|
||||
while (type != null) {
|
||||
if (lookupData.TryGetValue(type.FullName + "." + path, out var value)) {
|
||||
return value;
|
||||
}
|
||||
type = type.BaseType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
string FindTooltip (string path) {
|
||||
LoadMeta();
|
||||
return LookupPath(target.GetType(), path, cachedTooltips);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable () {
|
||||
foreach (var target in targets) if (target != null) (target as IVersionedMonoBehaviourInternal).UpgradeFromUnityThread();
|
||||
EditorApplication.contextualPropertyMenu += OnContextMenu;
|
||||
}
|
||||
|
||||
protected virtual void OnDisable () {
|
||||
EditorApplication.contextualPropertyMenu -= OnContextMenu;
|
||||
}
|
||||
|
||||
void OnContextMenu (GenericMenu menu, SerializedProperty property) {
|
||||
if (property.serializedObject != this.serializedObject) return;
|
||||
|
||||
LoadMeta();
|
||||
var url = LookupPath(target.GetType(), property.propertyPath, cachedURLs);
|
||||
|
||||
if (url != null && getDocumentationURL != null) {
|
||||
menu.AddItem(showInDocContent, false, () => Application.OpenURL(getDocumentationURL() + url));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override void OnInspectorGUI () {
|
||||
EditorGUI.indentLevel = 0;
|
||||
serializedObject.Update();
|
||||
try {
|
||||
Inspector();
|
||||
InspectorForRemainingAttributes(false, true);
|
||||
} catch (System.Exception e) {
|
||||
// This exception type should never be caught. See https://docs.unity3d.com/ScriptReference/ExitGUIException.html
|
||||
if (e is ExitGUIException) throw e;
|
||||
Debug.LogException(e, target);
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
if (targets.Length == 1 && (target as MonoBehaviour).enabled) {
|
||||
var attr = target.GetType().GetCustomAttributes(typeof(UniqueComponentAttribute), true);
|
||||
for (int i = 0; i < attr.Length; i++) {
|
||||
string tag = (attr[i] as UniqueComponentAttribute).tag;
|
||||
foreach (var other in (target as MonoBehaviour).GetComponents<MonoBehaviour>()) {
|
||||
// Note: other can be null if some scripts are missing references
|
||||
if (other == null || !other.enabled || other == target) continue;
|
||||
if (other.GetType().GetCustomAttributes(typeof(UniqueComponentAttribute), true).Where(c => (c as UniqueComponentAttribute).tag == tag).Any()) {
|
||||
EditorGUILayout.HelpBox("This component and " + other.GetType().Name + " cannot be used at the same time", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void Inspector () {
|
||||
InspectorForRemainingAttributes(true, false);
|
||||
}
|
||||
|
||||
/// <summary>Draws an inspector for all fields that are likely not handled by the editor script itself</summary>
|
||||
protected virtual void InspectorForRemainingAttributes (bool showHandled, bool showUnhandled) {
|
||||
if (remainingUnhandledProperties == null) {
|
||||
remainingUnhandledProperties = new HashSet<string>();
|
||||
|
||||
var tp = serializedObject.targetObject.GetType();
|
||||
var handledAssemblies = new List<System.Reflection.Assembly>();
|
||||
|
||||
// Find all types for which we have a [CustomEditor(type)] attribute.
|
||||
// Unity hides this field, so we have to use reflection to get it.
|
||||
var customEditorAttrs = this.GetType().GetCustomAttributes(typeof(CustomEditor), true).Cast<CustomEditor>().ToArray();
|
||||
foreach (var attr in customEditorAttrs) {
|
||||
var inspectedTypeField = attr.GetType().GetField("m_InspectedType", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
var inspectedType = inspectedTypeField.GetValue(attr) as System.Type;
|
||||
if (!handledAssemblies.Contains(inspectedType.Assembly)) {
|
||||
handledAssemblies.Add(inspectedType.Assembly);
|
||||
}
|
||||
}
|
||||
bool enterChildren = true;
|
||||
for (var prop = serializedObject.GetIterator(); prop.NextVisible(enterChildren); enterChildren = false) {
|
||||
var name = prop.propertyPath;
|
||||
var field = tp.GetField(name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (field == null) {
|
||||
// Can happen for some built-in Unity fields. They are not important
|
||||
continue;
|
||||
} else {
|
||||
var declaringType = field.DeclaringType;
|
||||
var foundOtherAssembly = false;
|
||||
var foundThisAssembly = false;
|
||||
while (declaringType != null) {
|
||||
if (handledAssemblies.Contains(declaringType.Assembly)) {
|
||||
foundThisAssembly = true;
|
||||
break;
|
||||
} else {
|
||||
foundOtherAssembly = true;
|
||||
}
|
||||
declaringType = declaringType.BaseType;
|
||||
}
|
||||
if (foundOtherAssembly && foundThisAssembly) {
|
||||
// This is a field in a class in a different assembly, which inherits from a class in one of the handled assemblies.
|
||||
// That probably means the editor script doesn't explicitly know about that field and we should show it anyway.
|
||||
remainingUnhandledProperties.Add(prop.propertyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Basically the same as DrawDefaultInspector, but with tooltips
|
||||
bool enterChildren2 = true;
|
||||
|
||||
for (var prop = serializedObject.GetIterator(); prop.NextVisible(enterChildren2); enterChildren2 = false) {
|
||||
var handled = !remainingUnhandledProperties.Contains(prop.propertyPath);
|
||||
if ((showHandled && handled) || (showUnhandled && !handled)) {
|
||||
PropertyField(prop.propertyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected SerializedProperty FindProperty (string name) {
|
||||
if (!props.TryGetValue(name, out SerializedProperty res)) res = props[name] = serializedObject.FindProperty(name);
|
||||
if (res == null) throw new System.ArgumentException(name);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected void Section (string label) {
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
|
||||
}
|
||||
|
||||
protected bool SectionEnableable (string label, string enabledProperty) {
|
||||
EditorGUILayout.Separator();
|
||||
var v = EditorGUILayout.ToggleLeft(label, FindProperty(enabledProperty).boolValue, EditorStyles.boldLabel);
|
||||
FindProperty(enabledProperty).boolValue = v;
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>Bounds field using center/size instead of center/extent</summary>
|
||||
protected void BoundsField (string propertyPath) {
|
||||
PropertyField(propertyPath + ".m_Center", "Center");
|
||||
var extentsProp = FindProperty(propertyPath + ".m_Extent");
|
||||
var r = EditorGUILayout.GetControlRect();
|
||||
var label = EditorGUI.BeginProperty(r, new GUIContent("Size"), extentsProp);
|
||||
extentsProp.vector3Value = 0.5f * EditorGUI.Vector3Field(r, label, extentsProp.vector3Value * 2.0f);
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
protected void FloatField (string propertyPath, string label = null, string tooltip = null, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
|
||||
PropertyField(propertyPath, label, tooltip);
|
||||
Clamp(propertyPath, min, max);
|
||||
}
|
||||
|
||||
protected void FloatField (SerializedProperty prop, string label = null, string tooltip = null, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
|
||||
PropertyField(prop, label, tooltip);
|
||||
Clamp(prop, min, max);
|
||||
}
|
||||
|
||||
protected bool PropertyField (string propertyPath, string label = null, string tooltip = null) {
|
||||
return PropertyField(FindProperty(propertyPath), label, tooltip, propertyPath);
|
||||
}
|
||||
|
||||
protected bool PropertyField (SerializedProperty prop, string label = null, string tooltip = null) {
|
||||
return PropertyField(prop, label, tooltip, prop.propertyPath);
|
||||
}
|
||||
|
||||
bool PropertyField (SerializedProperty prop, string label, string tooltip, string propertyPath) {
|
||||
content.text = label ?? prop.displayName;
|
||||
content.tooltip = tooltip ?? FindTooltip(propertyPath);
|
||||
EditorGUILayout.PropertyField(prop, content, true, noOptions);
|
||||
return prop.propertyType == SerializedPropertyType.Boolean ? !prop.hasMultipleDifferentValues && prop.boolValue : true;
|
||||
}
|
||||
|
||||
protected void Popup (string propertyPath, GUIContent[] options, string label = null) {
|
||||
var prop = FindProperty(propertyPath);
|
||||
|
||||
content.text = label ?? prop.displayName;
|
||||
content.tooltip = FindTooltip(propertyPath);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight, EditorStyles.popup);
|
||||
r = EditorGUI.PrefixLabel(r, EditorGUI.BeginProperty(r, content, prop));
|
||||
var tmpIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
int indexValue;
|
||||
if (prop.propertyType == SerializedPropertyType.Enum) {
|
||||
indexValue = prop.enumValueIndex;
|
||||
} else if (prop.propertyType == SerializedPropertyType.Integer) {
|
||||
indexValue = prop.intValue;
|
||||
} else if (prop.propertyType == SerializedPropertyType.Boolean) {
|
||||
indexValue = prop.boolValue ? 1 : 0;
|
||||
} else {
|
||||
throw new System.ArgumentException("Property is not an enum, integer or boolean");
|
||||
}
|
||||
indexValue = EditorGUI.Popup(r, indexValue, options);
|
||||
EditorGUI.indentLevel = tmpIndent;
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
if (prop.propertyType == SerializedPropertyType.Enum) {
|
||||
prop.enumValueIndex = indexValue;
|
||||
} else if (prop.propertyType == SerializedPropertyType.Integer) {
|
||||
prop.intValue = indexValue;
|
||||
} else if (prop.propertyType == SerializedPropertyType.Boolean) {
|
||||
prop.boolValue = indexValue != 0;
|
||||
} else {
|
||||
throw new System.ArgumentException("Property is not an enum, integer or boolean");
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
protected void IntSlider (string propertyPath, int left, int right) {
|
||||
var prop = FindProperty(propertyPath);
|
||||
|
||||
content.text = prop.displayName;
|
||||
content.tooltip = FindTooltip(propertyPath);
|
||||
EditorGUILayout.IntSlider(prop, left, right, content, noOptions);
|
||||
}
|
||||
|
||||
protected void Slider (string propertyPath, float left, float right) {
|
||||
var prop = FindProperty(propertyPath);
|
||||
|
||||
content.text = prop.displayName;
|
||||
content.tooltip = FindTooltip(propertyPath);
|
||||
EditorGUILayout.Slider(prop, left, right, content, noOptions);
|
||||
}
|
||||
|
||||
protected bool ByteAsToggle (string propertyPath, string label) {
|
||||
var prop = FindProperty(propertyPath);
|
||||
|
||||
content.text = label;
|
||||
content.tooltip = FindTooltip(propertyPath);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight, EditorStyles.popup);
|
||||
r = EditorGUI.PrefixLabel(r, EditorGUI.BeginProperty(r, content, prop));
|
||||
var tmpIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
prop.intValue = EditorGUI.Toggle(r, prop.intValue != 0) ? 1 : 0;
|
||||
EditorGUI.indentLevel = tmpIndent;
|
||||
EditorGUI.EndProperty();
|
||||
return prop.intValue != 0;
|
||||
}
|
||||
|
||||
protected void Clamp (SerializedProperty prop, float min, float max = float.PositiveInfinity) {
|
||||
if (!prop.hasMultipleDifferentValues) prop.floatValue = Mathf.Clamp(prop.floatValue, min, max);
|
||||
}
|
||||
|
||||
protected void Clamp (string name, float min, float max = float.PositiveInfinity) {
|
||||
Clamp(FindProperty(name), min, max);
|
||||
}
|
||||
|
||||
protected void ClampInt (string name, int min, int max = int.MaxValue) {
|
||||
var prop = FindProperty(name);
|
||||
|
||||
if (!prop.hasMultipleDifferentValues) prop.intValue = Mathf.Clamp(prop.intValue, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58753931a68ae48b3973d0ce32d1a760
|
||||
timeCreated: 1495461526
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,198 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Pathfinding {
|
||||
/// <summary>Simple GUI utility functions</summary>
|
||||
public static class GUIUtilityx {
|
||||
static Stack<Color> colors = new Stack<Color>();
|
||||
|
||||
public static void PushTint (Color tint) {
|
||||
colors.Push(GUI.color);
|
||||
GUI.color *= tint;
|
||||
}
|
||||
|
||||
public static void PopTint () {
|
||||
GUI.color = colors.Pop();
|
||||
}
|
||||
|
||||
public static Rect SliceRow (ref Rect rect, float height) {
|
||||
var r = new Rect(rect.x, rect.y, rect.width, height);
|
||||
rect.yMin += height + EditorGUIUtility.standardVerticalSpacing;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Rect SliceColumn (ref Rect rect, float width, float spacing = 0) {
|
||||
var r = new Rect(rect.x, rect.y, width, rect.height);
|
||||
rect.xMin += width + spacing;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Editor helper for hiding and showing a group of GUI elements.
|
||||
/// Call order in OnInspectorGUI should be:
|
||||
/// - Begin
|
||||
/// - Header/HeaderLabel (optional)
|
||||
/// - BeginFade
|
||||
/// - [your gui elements] (if BeginFade returns true)
|
||||
/// - End
|
||||
/// </summary>
|
||||
public class FadeArea {
|
||||
Rect lastRect;
|
||||
float value;
|
||||
float lastUpdate;
|
||||
GUIStyle labelStyle;
|
||||
GUIStyle areaStyle;
|
||||
bool visible;
|
||||
Editor editor;
|
||||
|
||||
/// <summary>
|
||||
/// Is this area open.
|
||||
/// This is not the same as if any contents are visible, use <see cref="BeginFade"/> for that.
|
||||
/// </summary>
|
||||
public bool open;
|
||||
|
||||
/// <summary>Animate dropdowns when they open and close</summary>
|
||||
public static bool fancyEffects;
|
||||
const float animationSpeed = 100f;
|
||||
|
||||
public FadeArea (bool open, Editor editor, GUIStyle areaStyle, GUIStyle labelStyle = null) {
|
||||
this.areaStyle = areaStyle;
|
||||
this.labelStyle = labelStyle;
|
||||
this.editor = editor;
|
||||
visible = this.open = open;
|
||||
value = open ? 1 : 0;
|
||||
}
|
||||
|
||||
void Tick () {
|
||||
if (Event.current.type == EventType.Repaint) {
|
||||
float deltaTime = Time.realtimeSinceStartup-lastUpdate;
|
||||
|
||||
// Right at the start of a transition the deltaTime will
|
||||
// not be reliable, so use a very small value instead
|
||||
// until the next repaint
|
||||
if (value == 0f || value == 1f) deltaTime = 0.001f;
|
||||
deltaTime = Mathf.Clamp(deltaTime, 0.00001F, 0.1F);
|
||||
|
||||
// Larger regions fade slightly slower
|
||||
deltaTime /= Mathf.Sqrt(Mathf.Max(lastRect.height, 100));
|
||||
|
||||
lastUpdate = Time.realtimeSinceStartup;
|
||||
|
||||
|
||||
float targetValue = open ? 1F : 0F;
|
||||
if (!Mathf.Approximately(targetValue, value)) {
|
||||
value += deltaTime*animationSpeed*Mathf.Sign(targetValue-value);
|
||||
value = Mathf.Clamp01(value);
|
||||
editor.Repaint();
|
||||
|
||||
if (!fancyEffects) {
|
||||
value = targetValue;
|
||||
}
|
||||
} else {
|
||||
value = targetValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Begin () {
|
||||
if (areaStyle != null) {
|
||||
lastRect = EditorGUILayout.BeginVertical(areaStyle);
|
||||
} else {
|
||||
lastRect = EditorGUILayout.BeginVertical();
|
||||
}
|
||||
}
|
||||
|
||||
public void HeaderLabel (string label) {
|
||||
GUILayout.Label(label, labelStyle);
|
||||
}
|
||||
|
||||
public void Header (string label) {
|
||||
Header(label, ref open);
|
||||
}
|
||||
|
||||
public void Header (string label, ref bool open) {
|
||||
if (GUILayout.Button(label, labelStyle)) {
|
||||
open = !open;
|
||||
editor.Repaint();
|
||||
}
|
||||
this.open = open;
|
||||
}
|
||||
|
||||
/// <summary>Hermite spline interpolation</summary>
|
||||
static float Hermite (float start, float end, float value) {
|
||||
return Mathf.Lerp(start, end, value * value * (3.0f - 2.0f * value));
|
||||
}
|
||||
|
||||
public bool BeginFade () {
|
||||
var hermite = Hermite(0, 1, value);
|
||||
|
||||
visible = EditorGUILayout.BeginFadeGroup(hermite);
|
||||
GUIUtilityx.PushTint(new Color(1, 1, 1, hermite));
|
||||
Tick();
|
||||
|
||||
// Another vertical group is necessary to work around
|
||||
// a kink of the BeginFadeGroup implementation which
|
||||
// causes the padding to change when value!=0 && value!=1
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
public void End () {
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (visible) {
|
||||
// Some space that cannot be placed in the GUIStyle unfortunately
|
||||
GUILayout.Space(4);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
EditorGUILayout.EndVertical();
|
||||
GUIUtilityx.PopTint();
|
||||
}
|
||||
}
|
||||
/// <summary>Handles fading effects and also some custom GUI functions such as LayerMaskField</summary>
|
||||
public static class EditorGUILayoutx {
|
||||
static Dictionary<int, string[]> layerNames = new Dictionary<int, string[]>();
|
||||
static long lastUpdateTick;
|
||||
static List<string> dummyList = new List<string>();
|
||||
|
||||
/// <summary>Displays a LayerMask field.</summary>
|
||||
/// <param name="label">Label to display</param>
|
||||
/// <param name="selected">Current LayerMask</param>
|
||||
public static LayerMask LayerMaskField (string label, LayerMask selected) {
|
||||
if (Event.current.type == EventType.Layout && System.DateTime.UtcNow.Ticks - lastUpdateTick > 10000000L) {
|
||||
layerNames.Clear();
|
||||
lastUpdateTick = System.DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
string[] currentLayerNames;
|
||||
if (!layerNames.TryGetValue(selected.value, out currentLayerNames)) {
|
||||
var layers = dummyList;
|
||||
layers.Clear();
|
||||
|
||||
int emptyLayers = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
string layerName = LayerMask.LayerToName(i);
|
||||
|
||||
if (layerName != "") {
|
||||
for (; emptyLayers > 0; emptyLayers--) layers.Add("Layer "+(i-emptyLayers));
|
||||
layers.Add(layerName);
|
||||
} else {
|
||||
emptyLayers++;
|
||||
if (((selected.value >> i) & 1) != 0 && selected.value != -1) {
|
||||
for (; emptyLayers > 0; emptyLayers--) layers.Add("Layer "+(i+1-emptyLayers));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentLayerNames = layerNames[selected.value] = layers.ToArray();
|
||||
}
|
||||
|
||||
selected.value = EditorGUILayout.MaskField(label, selected.value, currentLayerNames);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b6b4977544da4af3a4fe9e895fb6888
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pathfinding {
|
||||
[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
|
||||
public class EnumFlagDrawer : PropertyDrawer {
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
Enum targetEnum = GetBaseProperty<Enum>(property);
|
||||
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Enum enumNew = EditorGUI.EnumFlagsField(position, label, targetEnum);
|
||||
if (EditorGUI.EndChangeCheck() || !property.hasMultipleDifferentValues) {
|
||||
property.intValue = (int)Convert.ChangeType(enumNew, targetEnum.GetType());
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
static T GetBaseProperty<T>(SerializedProperty prop) {
|
||||
// Separate the steps it takes to get to this property
|
||||
string[] separatedPaths = prop.propertyPath.Split('.');
|
||||
|
||||
// Go down to the root of this serialized property
|
||||
System.Object reflectionTarget = prop.serializedObject.targetObject as object;
|
||||
// Walk down the path to get the target object
|
||||
foreach (var path in separatedPaths) {
|
||||
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
reflectionTarget = fieldInfo.GetValue(reflectionTarget);
|
||||
}
|
||||
return (T)reflectionTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 616267fcc419f44ea929599afa5c6aa2
|
||||
timeCreated: 1500392257
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
|
||||
namespace Pathfinding.Legacy {
|
||||
public static class LegacyEditorHelper {
|
||||
public static void UpgradeDialog (Object[] targets, System.Type upgradeType) {
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
var gui = EditorGUIUtility.IconContent("console.warnicon");
|
||||
gui.text = "You are using the compatibility version of this component. It is recommended that you upgrade to the newer version. This may change the component's behavior.";
|
||||
EditorGUILayout.LabelField(GUIContent.none, gui, EditorStyles.wordWrappedMiniLabel);
|
||||
if (GUILayout.Button("Upgrade")) {
|
||||
Undo.RecordObjects(targets.Select(s => (s as Component).gameObject).ToArray(), "Upgrade from Legacy Component");
|
||||
foreach (var tg in targets) {
|
||||
var comp = tg as Component;
|
||||
var components = comp.gameObject.GetComponents<Component>();
|
||||
int index = System.Array.IndexOf(components, comp);
|
||||
var newRVO = Undo.AddComponent(comp.gameObject, upgradeType);
|
||||
foreach (var field in newRVO.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) {
|
||||
field.SetValue(newRVO, field.GetValue(comp));
|
||||
}
|
||||
Undo.DestroyObjectImmediate(comp);
|
||||
for (int i = components.Length - 1; i > index; i--) UnityEditorInternal.ComponentUtility.MoveComponentUp(newRVO);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a97cec2d4f06c4d0eb0068c24cb47ca1
|
||||
timeCreated: 1490879139
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,164 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Pathfinding {
|
||||
/// <summary>
|
||||
/// Helper for enabling or disabling compiler directives.
|
||||
/// Used only in the editor.
|
||||
/// </summary>
|
||||
public static class OptimizationHandler {
|
||||
public class DefineDefinition {
|
||||
public string name;
|
||||
public string description;
|
||||
public bool enabled;
|
||||
public bool consistent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Various build targets that Unity have deprecated.
|
||||
/// There is apparently no way to figure out which these are without hard coding them.
|
||||
/// </summary>
|
||||
static readonly BuildTargetGroup[] deprecatedBuildTargets = new BuildTargetGroup[] {
|
||||
BuildTargetGroup.Unknown,
|
||||
#if UNITY_5_4_OR_NEWER
|
||||
(BuildTargetGroup)16, /* BlackBerry */
|
||||
#endif
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
(BuildTargetGroup)5, /* PS3 */
|
||||
(BuildTargetGroup)6, /* XBox360 */
|
||||
(BuildTargetGroup)15, /* WP8 */
|
||||
#endif
|
||||
#if UNITY_2017_4_OR_NEWER
|
||||
(BuildTargetGroup)2, /* WebPlayer */
|
||||
(BuildTargetGroup)20, /* PSM */
|
||||
#endif
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
(BuildTargetGroup)22, /* SamsungTV */
|
||||
(BuildTargetGroup)24, /* WiiU */
|
||||
#endif
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
(BuildTargetGroup)17, /* Tizen */
|
||||
#endif
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
(BuildTargetGroup)18, /* PSP2 */
|
||||
(BuildTargetGroup)23, /* Nintendo3DS */
|
||||
#endif
|
||||
};
|
||||
|
||||
static string GetPackageRootDirectory () {
|
||||
var rootDir = EditorResourceHelper.editorAssets + "/../../";
|
||||
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
static Dictionary<BuildTargetGroup, List<string> > GetDefineSymbols () {
|
||||
var result = new Dictionary<BuildTargetGroup, List<string> >();
|
||||
|
||||
var nonDeprecatedBuildTypes = typeof(BuildTargetGroup)
|
||||
.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)
|
||||
.Where(fieldInfo => fieldInfo.GetCustomAttributes(typeof(System.ObsoleteAttribute), false).Length == 0)
|
||||
.Select(fieldInfo => (BuildTargetGroup)fieldInfo.GetValue(null)).ToArray();
|
||||
|
||||
for (int i = 0; i < nonDeprecatedBuildTypes.Length; i++) {
|
||||
// Kept for compatibility with older versions of Unity which did not always accurately add Obsolete attributes
|
||||
// (in particular Unity 2017.4 seems to miss marking the PSM build target as obsolete, the other ones seem accurate)
|
||||
if (deprecatedBuildTargets.Contains(nonDeprecatedBuildTypes[i])) continue;
|
||||
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.GetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(nonDeprecatedBuildTypes[i]), out var defines);
|
||||
#else
|
||||
string defineString = PlayerSettings.GetScriptingDefineSymbolsForGroup(nonDeprecatedBuildTypes[i]);
|
||||
if (defineString == null) continue;
|
||||
|
||||
var defines = defineString.Split(';').Select(s => s.Trim());
|
||||
#endif
|
||||
result[nonDeprecatedBuildTypes[i]] = defines.ToList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void SetDefineSymbols (Dictionary<BuildTargetGroup, List<string> > symbols) {
|
||||
foreach (var pair in symbols) {
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
string[] symbolsArr = pair.Value.Distinct().ToArray();
|
||||
PlayerSettings.SetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(pair.Key), symbolsArr);
|
||||
#else
|
||||
var defineString = string.Join(";", pair.Value.Distinct().ToArray());
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(pair.Key, defineString);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableDefine (string name) {
|
||||
name = name.Trim();
|
||||
var newSymbols = GetDefineSymbols().ToDictionary(pair => pair.Key, pair => {
|
||||
pair.Value.Add(name);
|
||||
return pair.Value;
|
||||
});
|
||||
SetDefineSymbols(newSymbols);
|
||||
}
|
||||
|
||||
public static void DisableDefine (string name) {
|
||||
name = name.Trim();
|
||||
var newSymbols = GetDefineSymbols().ToDictionary(pair => pair.Key, pair => {
|
||||
pair.Value.Remove(name);
|
||||
return pair.Value;
|
||||
});
|
||||
SetDefineSymbols(newSymbols);
|
||||
}
|
||||
|
||||
public static void IsDefineEnabled (string name, out bool enabled, out bool consistent) {
|
||||
name = name.Trim();
|
||||
int foundEnabled = 0;
|
||||
int foundDisabled = 0;
|
||||
|
||||
foreach (var pair in GetDefineSymbols()) {
|
||||
if (pair.Value.Contains(name)) {
|
||||
foundEnabled++;
|
||||
} else {
|
||||
foundDisabled++;
|
||||
}
|
||||
}
|
||||
|
||||
enabled = foundEnabled > foundDisabled;
|
||||
consistent = (foundEnabled > 0) != (foundDisabled > 0);
|
||||
}
|
||||
|
||||
public static List<DefineDefinition> FindDefines () {
|
||||
var path = GetPackageRootDirectory()+"/defines.csv";
|
||||
|
||||
if (File.Exists(path)) {
|
||||
// Read a file consisting of lines with the format
|
||||
// NAME;Description
|
||||
// Ignore empty lines and lines which do not contain exactly 1 ';'
|
||||
var definePairs = File.ReadAllLines(path)
|
||||
.Select(line => line.Trim())
|
||||
.Where(line => line.Length > 0)
|
||||
.Select(line => line.Split(';'))
|
||||
.Where(opts => opts.Length == 2);
|
||||
|
||||
return definePairs.Select(opts => {
|
||||
var def = new DefineDefinition { name = opts[0].Trim(), description = opts[1].Trim() };
|
||||
IsDefineEnabled(def.name, out def.enabled, out def.consistent);
|
||||
return def;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
Debug.LogError("Could not find file '"+path+"'");
|
||||
return new List<DefineDefinition>();
|
||||
}
|
||||
|
||||
public static void ApplyDefines (List<DefineDefinition> defines) {
|
||||
foreach (var define in defines) {
|
||||
if (define.enabled) {
|
||||
EnableDefine(define.name);
|
||||
} else {
|
||||
DisableDefine(define.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec7eea22fd1c74193aa7d047949503e7
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "AstarPackageToolsEditor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:f4059aaf6c60a4a58a177a2609feb769"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.burst",
|
||||
"expression": "1.8.7",
|
||||
"define": "MODULE_BURST"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.mathematics",
|
||||
"expression": "1.2.6",
|
||||
"define": "MODULE_MATHEMATICS"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.collections",
|
||||
"expression": "1.5.1",
|
||||
"define": "MODULE_COLLECTIONS"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.collections",
|
||||
"expression": "0.11-preview",
|
||||
"define": "MODULE_COLLECTIONS_0_11_0_OR_NEWER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.entities",
|
||||
"expression": "1.0.0-pre.47",
|
||||
"define": "MODULE_ENTITIES"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 774e21169c4ac4ec8a01db9cdb98d33b
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
namespace Pathfinding {
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>Internal utility class for looking up editor resources</summary>
|
||||
public static class EditorResourceHelper {
|
||||
/// <summary>
|
||||
/// Path to the editor assets folder for the A* Pathfinding Project. If this path turns out to be incorrect, the script will try to find the correct path
|
||||
/// See: LoadStyles
|
||||
/// </summary>
|
||||
public static string editorAssets;
|
||||
|
||||
static EditorResourceHelper () {
|
||||
// Look up editor assets directory when first accessed
|
||||
LocateEditorAssets();
|
||||
}
|
||||
|
||||
static Material surfaceMat, lineMat;
|
||||
static Texture2D handlesAALineTex;
|
||||
public static Material GizmoSurfaceMaterial {
|
||||
get {
|
||||
if (!surfaceMat) surfaceMat = Resources.Load<Material>("aline_surface");
|
||||
return surfaceMat;
|
||||
}
|
||||
}
|
||||
|
||||
public static Material GizmoLineMaterial {
|
||||
get {
|
||||
if (!lineMat) lineMat = Resources.Load<Material>("aline_outline");
|
||||
return lineMat;
|
||||
}
|
||||
}
|
||||
|
||||
public static Texture2D HandlesAALineTexture {
|
||||
get {
|
||||
if (!handlesAALineTex) handlesAALineTex = Resources.Load<Texture2D>("handles_aaline");
|
||||
return handlesAALineTex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Locates the editor assets folder in case the user has moved it</summary>
|
||||
public static bool LocateEditorAssets () {
|
||||
var package = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(EditorResourceHelper).Assembly);
|
||||
|
||||
if (package != null) {
|
||||
editorAssets = package.assetPath + "/Editor/EditorAssets";
|
||||
if (System.IO.File.Exists(package.resolvedPath + "/Editor/EditorAssets/AstarEditorSkinLight.guiskin")) {
|
||||
return true;
|
||||
} else {
|
||||
Debug.LogError("Could not find editor assets folder in package at " + editorAssets + ". Is the package corrupt?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string projectPath = Application.dataPath;
|
||||
|
||||
if (projectPath.EndsWith("/Assets")) {
|
||||
projectPath = projectPath.Remove(projectPath.Length-("Assets".Length));
|
||||
}
|
||||
|
||||
editorAssets = "Assets/AstarPathfindingProject/Editor/EditorAssets";
|
||||
if (!System.IO.File.Exists(projectPath + editorAssets + "/AstarEditorSkinLight.guiskin") && !System.IO.File.Exists(projectPath + editorAssets + "/AstarEditorSkin.guiskin")) {
|
||||
//Initiate search
|
||||
|
||||
var sdir = new System.IO.DirectoryInfo(Application.dataPath);
|
||||
|
||||
var dirQueue = new Queue<System.IO.DirectoryInfo>();
|
||||
dirQueue.Enqueue(sdir);
|
||||
|
||||
while (dirQueue.Count > 0) {
|
||||
System.IO.DirectoryInfo dir = dirQueue.Dequeue();
|
||||
if (System.IO.File.Exists(dir.FullName + "/AstarEditorSkinLight.guiskin") || System.IO.File.Exists(dir.FullName + "/AstarEditorSkin.guiskin")) {
|
||||
// Handle windows file paths
|
||||
string path = dir.FullName.Replace('\\', '/');
|
||||
// Remove data path from string to make it relative
|
||||
path = path.Replace(projectPath, "");
|
||||
|
||||
if (path.StartsWith("/")) {
|
||||
path = path.Remove(0, 1);
|
||||
}
|
||||
|
||||
editorAssets = path;
|
||||
return true;
|
||||
}
|
||||
var dirs = dir.GetDirectories();
|
||||
for (int i = 0; i < dirs.Length; i++) {
|
||||
dirQueue.Enqueue(dirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogWarning("Could not locate editor assets folder. Make sure you have imported the package correctly.\nA* Pathfinding Project");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8127bc49e9e2d42dfa7a4e057842f165
|
||||
timeCreated: 1480419306
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pathfinding {
|
||||
/// <summary>\author http://wiki.unity3d.com/index.php/EnumFlagPropertyDrawer</summary>
|
||||
public class EnumFlagAttribute : PropertyAttribute {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1a464aa9d87d439d9b54e2ed9027f5f
|
||||
timeCreated: 1500392257
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Packages/com.arongranberg.astar/PackageTools/Migrations.cs
Normal file
56
Packages/com.arongranberg.astar/PackageTools/Migrations.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
namespace Pathfinding.Serialization {
|
||||
/// <summary>
|
||||
/// Helper struct for handling serialization backwards compatibility.
|
||||
///
|
||||
/// It stores which migrations have been completed as a bitfield.
|
||||
/// </summary>
|
||||
public struct Migrations {
|
||||
/// <summary>Bitfield of all migrations that have been run</summary>
|
||||
internal int finishedMigrations;
|
||||
/// <summary>
|
||||
/// Bitfield of all migrations that the component supports.
|
||||
/// A newly created component will be initialized with this value.
|
||||
/// </summary>
|
||||
internal int allMigrations;
|
||||
internal bool ignore;
|
||||
|
||||
/// <summary>A special migration flag which is used to mark that the version has been migrated to the bitfield format, from the legacy linear version format</summary>
|
||||
const int MIGRATE_TO_BITFIELD = 1 << 30;
|
||||
|
||||
public bool IsLegacyFormat => (finishedMigrations & MIGRATE_TO_BITFIELD) == 0;
|
||||
public int LegacyVersion => finishedMigrations;
|
||||
|
||||
public Migrations(int value) {
|
||||
this.finishedMigrations = value;
|
||||
allMigrations = MIGRATE_TO_BITFIELD;
|
||||
ignore = false;
|
||||
}
|
||||
|
||||
public bool TryMigrateFromLegacyFormat (out int legacyVersion) {
|
||||
legacyVersion = finishedMigrations;
|
||||
if (IsLegacyFormat) {
|
||||
this = new Migrations(MIGRATE_TO_BITFIELD);
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
public void MarkMigrationFinished (int flag) {
|
||||
if (IsLegacyFormat) throw new System.InvalidOperationException("Version must first be migrated to the bitfield format");
|
||||
finishedMigrations |= flag;
|
||||
}
|
||||
|
||||
public bool AddAndMaybeRunMigration (int flag, bool filter = true) {
|
||||
if ((flag & MIGRATE_TO_BITFIELD) != 0) throw new System.ArgumentException("Cannot use the MIGRATE_TO_BITFIELD flag when adding a migration");
|
||||
allMigrations |= flag;
|
||||
if (filter) {
|
||||
var res = (finishedMigrations & flag) != flag;
|
||||
MarkMigrationFinished(flag);
|
||||
return res;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
public void IgnoreMigrationAttempt () {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9ce95e385326f04391dfa2acd5f2c64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "PackageTools",
|
||||
"references": [
|
||||
"GUID:de4e6084e6d474788bb8c799d6b461eb"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
""
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.burst",
|
||||
"expression": "1.8.7",
|
||||
"define": "MODULE_BURST"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.mathematics",
|
||||
"expression": "1.2.6",
|
||||
"define": "MODULE_MATHEMATICS"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.collections",
|
||||
"expression": "1.5.1",
|
||||
"define": "MODULE_COLLECTIONS"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.collections",
|
||||
"expression": "0.11-preview",
|
||||
"define": "MODULE_COLLECTIONS_0_11_0_OR_NEWER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.entities",
|
||||
"expression": "1.0.0-pre.47",
|
||||
"define": "MODULE_ENTITIES"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4059aaf6c60a4a58a177a2609feb769
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Pathfinding {
|
||||
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class UniqueComponentAttribute : System.Attribute {
|
||||
public string tag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e256d5533142c4434897b4da38791511
|
||||
timeCreated: 1513613274
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
using Pathfinding.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pathfinding {
|
||||
/// <summary>Exposes internal methods from <see cref="Pathfinding.VersionedMonoBehaviour"/></summary>
|
||||
public interface IVersionedMonoBehaviourInternal {
|
||||
void UpgradeFromUnityThread();
|
||||
}
|
||||
|
||||
namespace Util {
|
||||
/// <summary>Used by Pathfinding.Util.BatchedEvents</summary>
|
||||
public interface IEntityIndex {
|
||||
int EntityIndex { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Base class for all components in the package</summary>
|
||||
public abstract class VersionedMonoBehaviour :
|
||||
#if MODULE_BURST && MODULE_MATHEMATICS && MODULE_COLLECTIONS
|
||||
Drawing.MonoBehaviourGizmos
|
||||
#else
|
||||
MonoBehaviour
|
||||
#endif
|
||||
, ISerializationCallbackReceiver, IVersionedMonoBehaviourInternal, Util.IEntityIndex {
|
||||
/// <summary>Version of the serialized data. Used for script upgrades.</summary>
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
int version = 0;
|
||||
|
||||
/// <summary>Internal entity index used by <see cref="BatchedEvents"/>. Should never be modified by other scripts.</summary>
|
||||
int Util.IEntityIndex.EntityIndex { get; set; }
|
||||
|
||||
protected virtual void Awake () {
|
||||
// Make sure the version field is up to date for components created during runtime.
|
||||
// Reset is not called when in play mode.
|
||||
// If the data had to be upgraded then OnAfterDeserialize would have been called earlier.
|
||||
if (Application.isPlaying) {
|
||||
if (version == 0) {
|
||||
// If version==0 then the component was created during runtime and has not been serialized previously.
|
||||
// We can mark all available migrations as finished.
|
||||
var m = new Migrations(int.MaxValue);
|
||||
OnUpgradeSerializedData(ref m, true);
|
||||
version = m.allMigrations;
|
||||
} else {
|
||||
// If version!=0 then the component may have to run migrations.
|
||||
(this as IVersionedMonoBehaviourInternal).UpgradeFromUnityThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Handle serialization backwards compatibility</summary>
|
||||
protected virtual void Reset () {
|
||||
// Set initial version when adding the component for the first time
|
||||
var m = new Migrations(int.MaxValue);
|
||||
OnUpgradeSerializedData(ref m, true);
|
||||
version = m.allMigrations;
|
||||
|
||||
DisableGizmosIcon();
|
||||
}
|
||||
|
||||
void DisableGizmosIcon () {
|
||||
#if UNITY_EDITOR && UNITY_2022_1_OR_NEWER
|
||||
// Disable the icon in the scene view by default for all scripts.
|
||||
// There's no way to set the actual default, so we have to do this instead.
|
||||
// We store the list of scripts that have been reset in the editor prefs, for each project.
|
||||
// Unity stores its gizmo preferences in the Library folder. So it will be per-user and per-project.
|
||||
// We won't be able to detect if the user deletes and then rebuilds their library folder, though.
|
||||
// Note: Unity may return false for TryGetGizmoInfo the first time it is called for a script.
|
||||
// But the second time a user adds a component (and thus resets it), this should work.
|
||||
if (UnityEditor.GizmoUtility.TryGetGizmoInfo(GetType(), out var gizmoInfo) && gizmoInfo.hasIcon) {
|
||||
var resetPaths = UnityEditor.EditorPrefs.GetString("AstarPathfindingProject.HasResetShowIconGizmos", "");
|
||||
var splits = resetPaths.Split(',');
|
||||
var id = Application.productName.Replace(",", ";") + ":" + GetType().Name;
|
||||
if (System.Array.IndexOf(splits, id) == -1) {
|
||||
resetPaths += "," + id;
|
||||
UnityEditor.GizmoUtility.SetIconEnabled(GetType(), false);
|
||||
UnityEditor.EditorPrefs.SetString("AstarPathfindingProject.HasResetShowIconGizmos", resetPaths);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Handle serialization backwards compatibility</summary>
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize () {
|
||||
}
|
||||
|
||||
/// <summary>Handle serialization backwards compatibility</summary>
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize() => UpgradeSerializedData(false);
|
||||
|
||||
protected void UpgradeSerializedData (bool isUnityThread) {
|
||||
var m = new Migrations(version);
|
||||
OnUpgradeSerializedData(ref m, isUnityThread);
|
||||
if (m.ignore) return;
|
||||
if (m.IsLegacyFormat) throw new System.Exception("Failed to migrate from the legacy format");
|
||||
if ((m.finishedMigrations & ~m.allMigrations) != 0) throw new System.Exception("Run more migrations than there are migrations to run. Finished: " + m.finishedMigrations.ToString("X") + " all: " + m.allMigrations.ToString("X"));
|
||||
if (isUnityThread && ((m.allMigrations & ~m.finishedMigrations) != 0)) throw new System.Exception("Some migrations were registered, but they did not run. Finished: " + m.finishedMigrations.ToString("X") + " all: " + m.allMigrations.ToString("X"));
|
||||
this.version = m.finishedMigrations;
|
||||
}
|
||||
|
||||
/// <summary>Handle serialization backwards compatibility</summary>
|
||||
protected virtual void OnUpgradeSerializedData (ref Migrations migrations, bool unityThread) {
|
||||
if (migrations.TryMigrateFromLegacyFormat(out var legacyVersion)) {
|
||||
if (legacyVersion > 1) throw new System.Exception("Reached base class without having migrated the legacy format, and the legacy version is not version 1.");
|
||||
}
|
||||
}
|
||||
|
||||
void IVersionedMonoBehaviourInternal.UpgradeFromUnityThread() => UpgradeSerializedData(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cce6945a1cc843b997a7abeb3a5013e
|
||||
timeCreated: 1491213149
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user