WuhuIslandTesting/Library/PackageCache/com.unity.splines@1.0.1/Editor/GUI/SplineInstantiateEditor.cs
2025-01-07 02:06:59 +01:00

522 lines
22 KiB
C#

using System;
using UnityEditor;
using UnityEditor.Splines;
using UnityEngine;
using UnityEngine.Splines;
class SplineInstantiateGizmoDrawer
{
[DrawGizmo(GizmoType.Selected | GizmoType.Active)]
static void DrawSplineInstantiateGizmos(SplineInstantiate scr, GizmoType gizmoType)
{
var instances = scr.instances;
foreach(var instance in instances)
{
var pos = instance.transform.position;
Handles.color = Color.red;
Handles.DrawAAPolyLine(3f,new []{ pos, pos + 0.25f * instance.transform.right });
Handles.color = Color.green;
Handles.DrawAAPolyLine(3f,new []{pos, pos + 0.25f * instance.transform.up});
Handles.color = Color.blue;
Handles.DrawAAPolyLine(3f,new []{pos, pos + 0.25f * instance.transform.forward});
}
}
}
[CustomPropertyDrawer (typeof(SplineInstantiate.InstantiableItem))]
class InstantiableItemDrawer : PropertyDrawer
{
static readonly string k_ProbabilityTooltip = L10n.Tr("Probability for that element to appear.");
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
{
var prefabProperty = property.FindPropertyRelative("prefab");
var probaProperty = property.FindPropertyRelative("probability");
var headerLine = ReserveSpace(EditorGUIUtility.singleLineHeight, ref rect);
using(new SplineInstantiateEditor.LabelWidthScope(0f))
EditorGUI.ObjectField(ReserveLineSpace(headerLine.width - 100, ref headerLine), prefabProperty, new GUIContent(""));
ReserveLineSpace(10, ref headerLine);
EditorGUI.LabelField(ReserveLineSpace(15, ref headerLine), new GUIContent("%", k_ProbabilityTooltip));
probaProperty.floatValue = EditorGUI.FloatField(ReserveLineSpace(60, ref headerLine), probaProperty.floatValue);
}
static Rect ReserveSpace(float height, ref Rect total)
{
Rect current = total;
current.height = height;
total.y += height;
return current;
}
static Rect ReserveLineSpace(float width, ref Rect total)
{
Rect current = total;
current.width = width;
total.x += width;
return current;
}
}
[CustomPropertyDrawer (typeof(SplineInstantiate.AlignAxis))]
class ItemAxisDrawer : PropertyDrawer
{
static int s_LastUpAxis;
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
{
var enumValue = property.intValue;
if(property.name == "m_Up")
{
property.intValue = (int)( (SplineInstantiate.AlignAxis)EditorGUI.EnumPopup(rect, label, (SplineInstantiate.AlignAxis)enumValue));
s_LastUpAxis = property.intValue;
}
else
{
property.intValue = (int)((SplineInstantiate.AlignAxis)EditorGUI.EnumPopup(rect, label, (SplineInstantiate.AlignAxis)enumValue,
(item) =>
{
int axisItem = (int)(SplineInstantiate.AlignAxis)item;
return !(axisItem == s_LastUpAxis || axisItem == (s_LastUpAxis + 3) % 6);
}));
}
}
}
[CustomEditor(typeof(SplineInstantiate),false)]
[CanEditMultipleObjects]
class SplineInstantiateEditor : SplineComponentEditor
{
enum SpawnType
{
Exact,
Random
}
SerializedProperty m_SplineContainer;
SerializedProperty m_ItemsToInstantiate;
SerializedProperty m_InstantiateMethod;
SerializedProperty m_Space;
SerializedProperty m_UpAxis;
SerializedProperty m_ForwardAxis;
SerializedProperty m_Spacing;
SerializedProperty m_PositionOffset;
SerializedProperty m_RotationOffset;
SerializedProperty m_ScaleOffset;
SerializedProperty m_AutoRefresh;
static readonly string[] k_SpacingTypesLabels = new []
{
L10n.Tr("Count"),
L10n.Tr("Spacing (Spline)"),
L10n.Tr("Spacing (Linear)")
};
static readonly string k_Helpbox = L10n.Tr("Instantiated Objects need a SplineContainer target to be created.");
//Setup Section
static readonly string k_Setup = L10n.Tr("Instantiated Object Setup");
static readonly string k_ObjectUp = L10n.Tr("Up Axis");
static readonly string k_ObjectUpTooltip = L10n.Tr("Object axis to use as Up Direction when instantiating on the Spline (default is Y).");
static readonly string k_ObjectForward = L10n.Tr("Forward Axis");
static readonly string k_ObjectForwardTooltip = L10n.Tr("Object axis to use as Forward Direction when instantiating on the Spline (default is Z).");
static readonly string k_AlignTo = L10n.Tr("Align To");
static readonly string k_AlignToTooltip = L10n.Tr("Define the space to use to orientate the instantiated object.");
static readonly string k_Instantiation = L10n.Tr("Instantiation");
static readonly string k_Method = L10n.Tr("Instantiate Method");
static readonly string k_MethodTooltip = L10n.Tr("How instances are generated along the spline.");
static readonly string k_Max = L10n.Tr("Max");
static readonly string k_Min = L10n.Tr("Min");
SpawnType m_SpacingType;
//Offsets
static readonly string k_Offset = L10n.Tr("Offsets");
static readonly string k_PositionOffset = L10n.Tr("Position Offset");
static readonly string k_PositionOffsetTooltip = L10n.Tr("Whether or not to use a position offset.");
static readonly string k_RotationOffset = L10n.Tr("Rotation Offset");
static readonly string k_RotationOffsetTooltip = L10n.Tr("Whether or not to use a rotation offset.");
static readonly string k_ScaleOffset = L10n.Tr("Scale Offset");
static readonly string k_ScaleOffsetTooltip = L10n.Tr("Whether or not to use a scale offset.");
//Generation
static readonly string k_Generation = L10n.Tr("Generation");
static readonly string k_AutoRefresh = L10n.Tr("Auto Refresh Generation");
static readonly string k_AutoRefreshTooltip = L10n.Tr("Automatically refresh the instances when the spline or the values are changed.");
static readonly string k_Randomize = L10n.Tr("Randomize");
static readonly string k_RandomizeTooltip = L10n.Tr("Compute a new randomization of the instances along the spline.");
static readonly string k_Regenerate = L10n.Tr("Regenerate");
static readonly string k_RegenerateTooltip = L10n.Tr("Regenerate the instances along the spline (only available when the content is not automatically refreshed).");
static readonly string k_Clear = L10n.Tr("Clear");
static readonly string k_ClearTooltip = L10n.Tr("Clear the instances along the spline (only available when the content is not automatically refreshed).");
bool m_PositionFoldout;
bool m_RotationFoldout;
bool m_ScaleFoldout;
enum OffsetType
{
Exact,
Random
};
protected override void OnEnable()
{
base.OnEnable();
m_SplineContainer = serializedObject.FindProperty("m_Container");
m_ItemsToInstantiate = serializedObject.FindProperty("m_ItemsToInstantiate");
m_InstantiateMethod = serializedObject.FindProperty("m_Method");
m_Space = serializedObject.FindProperty("m_Space");
m_UpAxis = serializedObject.FindProperty("m_Up");
m_ForwardAxis = serializedObject.FindProperty("m_Forward");
m_Spacing = serializedObject.FindProperty("m_Spacing");
m_PositionOffset = serializedObject.FindProperty("m_PositionOffset");
m_RotationOffset = serializedObject.FindProperty("m_RotationOffset");
m_ScaleOffset = serializedObject.FindProperty("m_ScaleOffset");
m_AutoRefresh = serializedObject.FindProperty("m_AutoRefresh");
m_SpacingType = m_Spacing.vector2Value.x == m_Spacing.vector2Value.y ? SpawnType.Exact : SpawnType.Random;
EditorSplineUtility.afterSplineWasModified += OnSplineModified;
}
void OnDisable()
{
EditorSplineUtility.afterSplineWasModified -= OnSplineModified;
}
void OnSplineModified(Spline spline)
{
if (EditorApplication.isPlayingOrWillChangePlaymode)
return;
( (SplineInstantiate)target ).SetSplineDirty(spline);
}
public override void OnInspectorGUI()
{
serializedObject.Update();
var splineInstantiate = ((SplineInstantiate)target);
var dirtyInstances = false;
var updateInstances = false;
EditorGUILayout.PropertyField(m_SplineContainer);
if(m_SplineContainer.objectReferenceValue == null)
EditorGUILayout.HelpBox(k_Helpbox, MessageType.Warning);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_ItemsToInstantiate);
dirtyInstances = EditorGUI.EndChangeCheck();
DoSetupSection();
dirtyInstances |= DoInstantiateSection();
updateInstances |= DisplayOffsets();
HorizontalLine( Color.grey );
EditorGUILayout.LabelField(k_Generation, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(m_AutoRefresh, new GUIContent(k_AutoRefresh, k_AutoRefreshTooltip));
EditorGUI.indentLevel--;
serializedObject.ApplyModifiedProperties();
EditorGUILayout.Separator();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.Space();
if(GUILayout.Button(new GUIContent(k_Randomize, k_RandomizeTooltip), GUILayout.MaxWidth(100f)))
splineInstantiate.Randomize();
if(GUILayout.Button(new GUIContent(k_Regenerate, k_RegenerateTooltip), GUILayout.MaxWidth(100f)))
updateInstances = true;
if(GUILayout.Button(new GUIContent(k_Clear, k_ClearTooltip), GUILayout.MaxWidth(100f)))
splineInstantiate.Clear();
EditorGUILayout.Space();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Separator();
if(dirtyInstances)
splineInstantiate.SetDirty();
if(updateInstances)
splineInstantiate.UpdateInstances();
}
void DoSetupSection()
{
HorizontalLine(Color.grey);
EditorGUILayout.LabelField(k_Setup, EditorStyles.boldLabel);
GUILayout.Space(5f);
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_UpAxis, new GUIContent(k_ObjectUp, k_ObjectUpTooltip));
EditorGUILayout.PropertyField(m_ForwardAxis, new GUIContent(k_ObjectForward, k_ObjectForwardTooltip));
if(EditorGUI.EndChangeCheck())
{
//Insuring axis integrity
if(m_ForwardAxis.intValue == m_UpAxis.intValue || m_ForwardAxis.intValue == ( m_UpAxis.intValue + 3 ) % 6)
m_ForwardAxis.intValue = ( m_ForwardAxis.intValue + 1 ) % 6;
}
EditorGUILayout.PropertyField(m_Space, new GUIContent(k_AlignTo, k_AlignToTooltip));
EditorGUI.indentLevel--;
}
bool DoInstantiateSection()
{
var dirty = false;
Vector2 spacingV2 = m_Spacing.vector2Value;
HorizontalLine( Color.grey );
EditorGUILayout.LabelField(k_Instantiation, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_InstantiateMethod, new GUIContent(k_Method, k_MethodTooltip), EditorStyles.boldFont );
if(EditorGUI.EndChangeCheck())
{
if(m_SpacingType == SpawnType.Random && m_InstantiateMethod.intValue == (int)SplineInstantiate.Method.LinearDistance)
m_Spacing.vector2Value = new Vector2(spacingV2.x, float.NaN);
dirty = true;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(new GUIContent(k_SpacingTypesLabels[m_InstantiateMethod.intValue]));
EditorGUI.indentLevel--;
GUILayout.Space(2f);
EditorGUI.BeginChangeCheck();
float spacingX = m_Spacing.vector2Value.x;
var isExact = m_SpacingType == SpawnType.Exact;
if(isExact || m_InstantiateMethod.intValue != (int)SplineInstantiate.Method.LinearDistance)
{
using(new LabelWidthScope(30f))
spacingX = (SplineInstantiate.Method)m_InstantiateMethod.intValue == SplineInstantiate.Method.InstanceCount ?
EditorGUILayout.IntField(new GUIContent(isExact ? L10n.Tr("Dist") : k_Min), (int)m_Spacing.vector2Value.x, GUILayout.MinWidth(50f)) :
EditorGUILayout.FloatField(new GUIContent(isExact ? L10n.Tr("Dist") : k_Min), m_Spacing.vector2Value.x, GUILayout.MinWidth(50f));
}
if(isExact)
{
spacingV2 = new Vector2(spacingX, spacingX);
}
else if(m_InstantiateMethod.intValue != (int)SplineInstantiate.Method.LinearDistance)
{
using(new LabelWidthScope(30f))
{
var spacingY = (SplineInstantiate.Method)m_InstantiateMethod.intValue == SplineInstantiate.Method.InstanceCount ?
EditorGUILayout.IntField(new GUIContent(k_Max), (int)m_Spacing.vector2Value.y, GUILayout.MinWidth(50f)) :
EditorGUILayout.FloatField(new GUIContent(k_Max), m_Spacing.vector2Value.y, GUILayout.MinWidth(50f));
if(spacingX > m_Spacing.vector2Value.y)
spacingY = spacingX;
else if(spacingY < m_Spacing.vector2Value.x)
spacingX = spacingY;
spacingV2 = new Vector2(spacingX, spacingY);
}
}
if(EditorGUI.EndChangeCheck())
m_Spacing.vector2Value = spacingV2;
EditorGUI.BeginChangeCheck();
if(m_InstantiateMethod.intValue != (int)SplineInstantiate.Method.LinearDistance)
m_SpacingType = (SpawnType)EditorGUILayout.EnumPopup(m_SpacingType, GUILayout.MinWidth(30f));
else
m_SpacingType = (SpawnType)EditorGUILayout.Popup(m_SpacingType == SpawnType.Exact ? 0 : 1,
new []{"Exact", "Auto"}, GUILayout.MinWidth(30f));
if(EditorGUI.EndChangeCheck())
{
if(m_SpacingType == SpawnType.Exact)
m_Spacing.vector2Value = new Vector2(spacingV2.x, spacingV2.x);
else if(m_InstantiateMethod.intValue == (int)SplineInstantiate.Method.LinearDistance)
m_Spacing.vector2Value = new Vector2(spacingV2.x, float.NaN);
dirty = true;
}
EditorGUILayout.EndHorizontal();
return dirty;
}
bool DoOffsetProperties(
SerializedProperty offsetProperty, GUIContent content, bool foldoutValue, out bool newFoldoutValue)
{
bool changed = false;
newFoldoutValue = foldoutValue;
EditorGUILayout.BeginHorizontal();
using(new LabelWidthScope(0f))
{
var setupProperty = offsetProperty.FindPropertyRelative("setup");
var setup = (SplineInstantiate.Vector3Offset.Setup)setupProperty.intValue;
var hasOffset = ( setup & SplineInstantiate.Vector3Offset.Setup.HasOffset ) != 0;
EditorGUI.BeginChangeCheck();
hasOffset = EditorGUILayout.Toggle(hasOffset, GUILayout.MaxWidth(20f));
if(EditorGUI.EndChangeCheck())
{
if(hasOffset)
setup |= SplineInstantiate.Vector3Offset.Setup.HasOffset;
else
setup &= ~SplineInstantiate.Vector3Offset.Setup.HasOffset;
setupProperty.intValue = (int)setup;
changed = true;
}
EditorGUILayout.Space(10f);
using(new EditorGUI.DisabledScope(!hasOffset))
{
newFoldoutValue = Foldout(foldoutValue, content, hasOffset) && hasOffset;
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
if(newFoldoutValue)
{
EditorGUILayout.BeginHorizontal();
var hasCustomSpace = ( setup & SplineInstantiate.Vector3Offset.Setup.HasCustomSpace ) != 0;
EditorGUI.BeginChangeCheck();
var space = m_Space.intValue < 1 ? "Spline Element" : m_Space.intValue == 1 ? "Spline Object" : "World";
hasCustomSpace = EditorGUILayout.Toggle(new GUIContent("Override space", L10n.Tr("Override current space (" + space + ")")), hasCustomSpace);
if(EditorGUI.EndChangeCheck())
{
if(hasCustomSpace)
setup |= SplineInstantiate.Vector3Offset.Setup.HasCustomSpace;
else
setup &= ~SplineInstantiate.Vector3Offset.Setup.HasCustomSpace;
setupProperty.intValue = (int)setup;
changed = true;
}
var spaceProperty = offsetProperty.FindPropertyRelative("space");
using(new EditorGUI.DisabledScope(!hasCustomSpace))
{
var type = (SplineInstantiate.OffsetSpace)spaceProperty.intValue;
EditorGUI.BeginChangeCheck();
type = (SplineInstantiate.OffsetSpace)EditorGUILayout.EnumPopup(type);
if(EditorGUI.EndChangeCheck())
{
spaceProperty.intValue = (int)type;
changed = true;
}
}
EditorGUILayout.EndHorizontal();
var minProperty = offsetProperty.FindPropertyRelative("min");
var maxProperty = offsetProperty.FindPropertyRelative("max");
var minPropertyValue = minProperty.vector3Value;
var maxPropertyValue = maxProperty.vector3Value;
float min, max;
SerializedProperty randomProperty;
for(int i = 0; i < 3; i++)
{
string label = i == 0 ? "X" : i == 1 ? "Y" : "Z";
EditorGUILayout.BeginHorizontal();
using(new LabelWidthScope(30f))
EditorGUILayout.LabelField(label);
randomProperty = offsetProperty.FindPropertyRelative("random"+label);
GUILayout.FlexibleSpace();
if(randomProperty.boolValue)
{
EditorGUI.BeginChangeCheck();
using(new LabelWidthScope(30f))
{
min = EditorGUILayout.FloatField("from", minPropertyValue[i], GUILayout.MinWidth(95f), GUILayout.MaxWidth(95f));
max = EditorGUILayout.FloatField(" to", maxPropertyValue[i], GUILayout.MinWidth(95f), GUILayout.MaxWidth(95f));
}
if(EditorGUI.EndChangeCheck())
{
if(min > maxPropertyValue[i])
maxPropertyValue[i] = min;
if(max < minPropertyValue[i])
minPropertyValue[i] = max;
minPropertyValue[i] = min;
maxPropertyValue[i] = max;
minProperty.vector3Value = minPropertyValue;
maxProperty.vector3Value = maxPropertyValue;
changed = true;
}
}
else
{
EditorGUI.BeginChangeCheck();
using(new LabelWidthScope(30f))
min = EditorGUILayout.FloatField("is ", minPropertyValue[i], GUILayout.MinWidth(193f), GUILayout.MaxWidth(193f));
if(EditorGUI.EndChangeCheck())
{
minPropertyValue[i] = min;
if(min > maxPropertyValue[i])
maxPropertyValue[i] = min;
minProperty.vector3Value = minPropertyValue;
maxProperty.vector3Value = maxPropertyValue;
changed = true;
}
}
EditorGUI.BeginChangeCheck();
var isOffsetRandom = randomProperty.boolValue ? OffsetType.Random : OffsetType.Exact;
using(new LabelWidthScope(0f))
isOffsetRandom = (OffsetType)EditorGUILayout.EnumPopup(isOffsetRandom,GUILayout.MinWidth(100f), GUILayout.MaxWidth(200f));
if(EditorGUI.EndChangeCheck())
{
randomProperty.boolValue = isOffsetRandom == OffsetType.Random;
changed = true;
}
EditorGUILayout.EndHorizontal();
}
}
}
}
return changed;
}
bool DisplayOffsets()
{
HorizontalLine( Color.grey );
var updateNeeded = DoOffsetProperties(m_PositionOffset, new GUIContent(k_PositionOffset, k_PositionOffsetTooltip), m_PositionFoldout, out m_PositionFoldout);
updateNeeded |= DoOffsetProperties(m_RotationOffset, new GUIContent(k_RotationOffset, k_RotationOffsetTooltip), m_RotationFoldout, out m_RotationFoldout);
updateNeeded |= DoOffsetProperties(m_ScaleOffset, new GUIContent(k_ScaleOffset, k_ScaleOffsetTooltip), m_ScaleFoldout, out m_ScaleFoldout);
return updateNeeded;
}
}