Skip to content

Instantly share code, notes, and snippets.

@RubenPineda
Last active September 9, 2020 00:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RubenPineda/51d0ca3120a89f7fe5080c05905cb80d to your computer and use it in GitHub Desktop.
Save RubenPineda/51d0ca3120a89f7fe5080c05905cb80d to your computer and use it in GitHub Desktop.
This is an updated version of ProGM's script. Now it handles Vector2, arrays and nested fields as well. You can also drag points locally. See the original code here: https://gist.github.com/ProGM/226204b2a7f99998d84d755ffa1fb39a. See also helper methods here: http://answers.unity3d.com/questions/425012/get-the-instance-the-serializedproperty-bel…
using UnityEngine;
public class DraggablePointAttribute : PropertyAttribute {
public bool local;
public DraggablePointAttribute (bool local = false) {
this.local = local;
}
}
using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Reflection;
using System.Linq;
[CustomEditor(typeof(MonoBehaviour), true)]
public class DraggablePointAttributeDrawer : Editor {
private readonly GUIStyle style = new GUIStyle();
private Transform transform;
private void OnEnable () {
style.fontStyle = FontStyle.Bold;
style.normal.textColor = Color.white;
transform = (target as MonoBehaviour).transform;
}
public void OnSceneGUI () {
if (Application.isPlaying) return;
SerializedProperty property = serializedObject.GetIterator();
CheckProperty(property);
}
private void CheckProperty (SerializedProperty property) {
while (property.Next(true)) {
if (property.propertyType == SerializedPropertyType.Vector2 || property.propertyType == SerializedPropertyType.Vector3) {
FieldInfo field = GetParent(property).GetType().GetField(property.name);
if (field == null) continue;
object[] draggablePoints = field.GetCustomAttributes(typeof(DraggablePointAttribute), false);
if (draggablePoints.Length > 0) {
DraggablePointAttribute attribute = draggablePoints[0] as DraggablePointAttribute;
DrawPoint(property, attribute.local, property.displayName);
}
}
else if (property.propertyType == SerializedPropertyType.Generic && property.isArray) {
FieldInfo field = GetParent(property).GetType().GetField(property.name);
if (field == null) continue;
object[] draggablePoints = field.GetCustomAttributes(typeof(DraggablePointAttribute), false);
if (draggablePoints.Length > 0) {
DraggablePointAttribute attribute = draggablePoints[0] as DraggablePointAttribute;
for (int i = 0; i < property.arraySize; i++) {
SerializedProperty element = property.GetArrayElementAtIndex(i);
if (element.propertyType == SerializedPropertyType.Vector2 || element.propertyType == SerializedPropertyType.Vector3) {
DrawPoint(element, attribute.local, property.displayName + " " + i);
}
}
}
}
}
}
private void DrawPoint (SerializedProperty property, bool local, string name) {
if (property.propertyType == SerializedPropertyType.Vector2) {
Vector2 drawPos = local ? (Vector2)transform.TransformPoint(property.vector2Value) : property.vector2Value;
Handles.Label(drawPos, name, style);
EditorGUI.BeginChangeCheck();
Vector2 position = Handles.PositionHandle(drawPos, Quaternion.identity);
if (EditorGUI.EndChangeCheck()) {
if (local) position = transform.InverseTransformPoint(position);
property.vector2Value = position;
serializedObject.ApplyModifiedProperties();
}
}
else {
Vector3 drawPos = local ? transform.TransformPoint(property.vector3Value) : property.vector3Value;
Handles.Label(drawPos, name, style);
EditorGUI.BeginChangeCheck();
Vector3 position = Handles.PositionHandle(drawPos, Quaternion.identity);
if (EditorGUI.EndChangeCheck()) {
if (local) position = transform.InverseTransformPoint(position);
property.vector3Value = position;
serializedObject.ApplyModifiedProperties();
}
}
}
public object GetParent (SerializedProperty prop) {
string path = prop.propertyPath.Replace(".Array.data[", "[");
object obj = prop.serializedObject.targetObject;
string[] elements = path.Split('.');
foreach (string element in elements.Take(elements.Length - 1)) {
if (element.Contains("[")) {
string elementName = element.Substring(0, element.IndexOf("["));
int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
obj = GetValue(obj, elementName, index);
}
else {
obj = GetValue(obj, element);
}
}
return obj ?? prop.serializedObject.targetObject;
}
public object GetValue (object source, string name) {
if (source == null)
return null;
Type type = source.GetType();
FieldInfo f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (f == null) {
PropertyInfo p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (p == null)
return null;
return p.GetValue(source, null);
}
return f.GetValue(source);
}
public object GetValue (object source, string name, int index) {
IEnumerable enumerable = GetValue(source, name) as IEnumerable;
if (enumerable == null) return null;
IEnumerator enm = enumerable.GetEnumerator();
while (index-- >= 0)
enm.MoveNext();
return enm.Current;
}
}
using UnityEngine;
public class Platform : MonoBehaviour {
[DraggablePoint(true)]
public Vector3 startPoint;
public PlatformMovement platformMovement;
[System.Serializable]
public class PlatformMovement {
[DraggablePoint(true)]
public Vector2[] localWaypoints;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment