275 lines
10 KiB
C#
275 lines
10 KiB
C#
using Streamingle.Utils.RoughConstraints;
|
|
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
|
|
namespace Streamingle.Utils.RoughConstraintsEditor
|
|
{
|
|
[CustomEditor(typeof(RoughConstraintBase), true)]
|
|
[CanEditMultipleObjects]
|
|
public sealed class RoughConstraintEditor : UnityEditor.Editor
|
|
{
|
|
private SerializedProperty constraintActive;
|
|
private SerializedProperty locked;
|
|
private SerializedProperty weight;
|
|
private SerializedProperty sources;
|
|
private SerializedProperty damping;
|
|
private SerializedProperty updateMode;
|
|
private SerializedProperty useUnscaledTime;
|
|
private SerializedProperty snapOnEnable;
|
|
private ReorderableList sourceList;
|
|
private bool roughFollowFoldout = true;
|
|
private bool settingsFoldout = true;
|
|
|
|
private void OnEnable()
|
|
{
|
|
constraintActive = serializedObject.FindProperty("constraintActive");
|
|
locked = serializedObject.FindProperty("locked");
|
|
weight = serializedObject.FindProperty("weight");
|
|
sources = serializedObject.FindProperty("sources");
|
|
damping = serializedObject.FindProperty("damping");
|
|
updateMode = serializedObject.FindProperty("updateMode");
|
|
useUnscaledTime = serializedObject.FindProperty("useUnscaledTime");
|
|
snapOnEnable = serializedObject.FindProperty("snapOnEnable");
|
|
|
|
sourceList = new ReorderableList(serializedObject, sources, true, true, true, true)
|
|
{
|
|
drawHeaderCallback = DrawSourceHeader,
|
|
drawElementCallback = DrawSourceElement,
|
|
elementHeightCallback = _ => EditorGUIUtility.singleLineHeight + 6f,
|
|
onAddCallback = OnAddSource
|
|
};
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
DrawCommonSettings();
|
|
DrawSourceList();
|
|
DrawTypeSettings();
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void DrawCommonSettings()
|
|
{
|
|
EditorGUILayout.PropertyField(constraintActive, new GUIContent("Constraint Active"));
|
|
DrawLockField();
|
|
EditorGUILayout.Slider(weight, 0f, 1f, new GUIContent("Weight"));
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("Activate", EditorStyles.miniButton, GUILayout.Width(72f)))
|
|
{
|
|
ApplyAction("Activate Rough Constraint", ActivateConstraint);
|
|
}
|
|
|
|
if (GUILayout.Button("Zero", EditorStyles.miniButton, GUILayout.Width(56f)))
|
|
{
|
|
ZeroOffsets();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
private void DrawLockField()
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
var newValue = EditorGUILayout.Toggle(new GUIContent("Lock"), locked.boolValue);
|
|
if (!EditorGUI.EndChangeCheck())
|
|
{
|
|
return;
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
foreach (var selectedTarget in targets)
|
|
{
|
|
var constraint = (RoughConstraintBase)selectedTarget;
|
|
Undo.RecordObject(constraint, "Change Rough Constraint Lock");
|
|
constraint.SetLocked(newValue);
|
|
EditorUtility.SetDirty(constraint);
|
|
}
|
|
|
|
serializedObject.Update();
|
|
}
|
|
|
|
private void DrawSourceList()
|
|
{
|
|
EditorGUILayout.Space(2f);
|
|
sourceList.DoLayoutList();
|
|
EditorGUILayout.Space(4f);
|
|
}
|
|
|
|
private void DrawTypeSettings()
|
|
{
|
|
roughFollowFoldout = EditorGUILayout.Foldout(roughFollowFoldout, "Rough Follow", true);
|
|
if (roughFollowFoldout)
|
|
{
|
|
using (new EditorGUI.IndentLevelScope())
|
|
{
|
|
EditorGUILayout.PropertyField(damping, new GUIContent("Damping"));
|
|
EditorGUILayout.PropertyField(updateMode, new GUIContent("Update Mode"));
|
|
EditorGUILayout.PropertyField(useUnscaledTime, new GUIContent("Use Unscaled Time"));
|
|
EditorGUILayout.PropertyField(snapOnEnable, new GUIContent("Snap On Enable"));
|
|
}
|
|
}
|
|
|
|
settingsFoldout = EditorGUILayout.Foldout(settingsFoldout, GetSettingsTitle(), true);
|
|
if (!settingsFoldout)
|
|
{
|
|
return;
|
|
}
|
|
|
|
using (new EditorGUI.IndentLevelScope())
|
|
{
|
|
DrawTypeProperties();
|
|
}
|
|
}
|
|
|
|
private void DrawTypeProperties()
|
|
{
|
|
if (target is RoughPositionConstraint)
|
|
{
|
|
DrawProperties("constrainedAxis", "positionOffset", "offsetInSourceSpace");
|
|
}
|
|
else if (target is RoughRotationConstraint)
|
|
{
|
|
DrawProperties("constrainedAxis", "rotationOffset");
|
|
}
|
|
else if (target is RoughScaleConstraint)
|
|
{
|
|
DrawProperties("constrainedAxis", "scaleOffset");
|
|
}
|
|
else if (target is RoughParentConstraint)
|
|
{
|
|
DrawProperties("constrainedPositionAxis", "positionOffset", "positionOffsetInSourceSpace", "constrainedRotationAxis", "rotationOffset");
|
|
}
|
|
else if (target is RoughAimConstraint)
|
|
{
|
|
DrawProperties("aimAxis", "upAxis", "worldUpVector", "rotationOffset");
|
|
}
|
|
else if (target is RoughLookAtConstraint)
|
|
{
|
|
DrawProperties("forwardAxis", "worldUpVector", "targetPositionOffset", "rotationOffset");
|
|
}
|
|
}
|
|
|
|
private void DrawProperties(params string[] propertyNames)
|
|
{
|
|
for (var i = 0; i < propertyNames.Length; i++)
|
|
{
|
|
var property = serializedObject.FindProperty(propertyNames[i]);
|
|
if (property != null)
|
|
{
|
|
EditorGUILayout.PropertyField(property, new GUIContent(ObjectNames.NicifyVariableName(property.name)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyAction(string undoName, System.Action<RoughConstraintBase> action)
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
foreach (var selectedTarget in targets)
|
|
{
|
|
var constraint = (RoughConstraintBase)selectedTarget;
|
|
Undo.RecordObject(constraint.transform, undoName);
|
|
action(constraint);
|
|
EditorUtility.SetDirty(constraint.transform);
|
|
}
|
|
}
|
|
|
|
private void ActivateConstraint(RoughConstraintBase constraint)
|
|
{
|
|
Undo.RecordObject(constraint, "Activate Rough Constraint");
|
|
constraint.ActivateConstraint();
|
|
EditorUtility.SetDirty(constraint);
|
|
}
|
|
|
|
private void ZeroOffsets()
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
Undo.RecordObjects(targets, "Zero Rough Constraint Offsets");
|
|
|
|
SetVector3IfExists("positionOffset", Vector3.zero);
|
|
SetVector3IfExists("rotationOffset", Vector3.zero);
|
|
SetVector3IfExists("scaleOffset", Vector3.zero);
|
|
SetVector3IfExists("targetPositionOffset", Vector3.zero);
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void SetVector3IfExists(string propertyName, Vector3 value)
|
|
{
|
|
var property = serializedObject.FindProperty(propertyName);
|
|
if (property != null)
|
|
{
|
|
property.vector3Value = value;
|
|
}
|
|
}
|
|
|
|
private void DrawSourceHeader(Rect rect)
|
|
{
|
|
var objectRect = new Rect(rect.x + 14f, rect.y, rect.width - 88f, rect.height);
|
|
var weightRect = new Rect(rect.xMax - 70f, rect.y, 68f, rect.height);
|
|
|
|
EditorGUI.LabelField(objectRect, "Sources");
|
|
EditorGUI.LabelField(weightRect, "Weight");
|
|
}
|
|
|
|
private void DrawSourceElement(Rect rect, int index, bool isActive, bool isFocused)
|
|
{
|
|
var element = sources.GetArrayElementAtIndex(index);
|
|
var sourceTransform = element.FindPropertyRelative("sourceTransform");
|
|
var sourceWeight = element.FindPropertyRelative("weight");
|
|
|
|
rect.y += 3f;
|
|
rect.height = EditorGUIUtility.singleLineHeight;
|
|
|
|
if (sourceTransform == null || sourceWeight == null)
|
|
{
|
|
EditorGUI.PropertyField(rect, element, GUIContent.none);
|
|
return;
|
|
}
|
|
|
|
var weightWidth = 70f;
|
|
var gap = 6f;
|
|
var targetRect = new Rect(rect.x, rect.y, rect.width - weightWidth - gap, rect.height);
|
|
var weightRect = new Rect(targetRect.xMax + gap, rect.y, weightWidth, rect.height);
|
|
|
|
EditorGUI.PropertyField(targetRect, sourceTransform, GUIContent.none);
|
|
sourceWeight.floatValue = Mathf.Clamp01(EditorGUI.FloatField(weightRect, sourceWeight.floatValue));
|
|
}
|
|
|
|
private void OnAddSource(ReorderableList list)
|
|
{
|
|
sources.arraySize++;
|
|
var element = sources.GetArrayElementAtIndex(sources.arraySize - 1);
|
|
var sourceTransform = element.FindPropertyRelative("sourceTransform");
|
|
var sourceWeight = element.FindPropertyRelative("weight");
|
|
|
|
if (sourceTransform != null)
|
|
{
|
|
sourceTransform.objectReferenceValue = null;
|
|
}
|
|
|
|
if (sourceWeight != null)
|
|
{
|
|
sourceWeight.floatValue = 1f;
|
|
}
|
|
}
|
|
|
|
private string GetSettingsTitle()
|
|
{
|
|
if (target is RoughLookAtConstraint)
|
|
{
|
|
return "Look At";
|
|
}
|
|
|
|
var name = target.GetType().Name;
|
|
name = name.Replace("Rough", string.Empty).Replace("Constraint", string.Empty);
|
|
return ObjectNames.NicifyVariableName(name);
|
|
}
|
|
}
|
|
}
|