-
-
Save prime31/46685036a7800e3919dc to your computer and use it in GitHub Desktop.
Generic inspector class that lets you implement OnScene/InspectorGUI in your class file instead of in a separate custom editor. It also provides attributes for getting Vector3/Vector3[]/List<Vector3> editing capabilities right in the scene view and getting buttons for any methods in your class in the inspector.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
public class ExampleUsage : MonoBehaviour | |
{ | |
// this attribute will add handles for your Vector3s so that you can drag them around in the scene view | |
[Vector3Inspectable] | |
List<Vector3> someListOfVectors; | |
// this method will appear as a button in the inspector | |
[MakeButton] | |
public void someVoidMethod() | |
{} | |
#if UNITY_EDITOR | |
void OnInspectorGUI() | |
{ | |
// do inspector stuff | |
} | |
void OnSceneGUI() | |
{ | |
// do scene stuff | |
} | |
#endif | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEditor; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using System; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
using System.Globalization; | |
// when implementing this in your MonoBehaviours, wrap your using UnityEditor and | |
// OnInspectorGUI/OnSceneGUI methods in #if UNITY_EDITOR/#endif | |
/// <summary> | |
/// for fields to work with the Vector3 inspector they must either be public or marked with SerializeField and have the Vector3Inspectable | |
/// attribute. | |
/// </summary> | |
[CustomEditor( typeof( UnityEngine.Object ), true )] | |
[CanEditMultipleObjects] | |
public class ObjectInspector : Editor | |
{ | |
MethodInfo _onInspectorGuiMethod; | |
MethodInfo _onSceneGuiMethod; | |
List<MethodInfo> _buttonMethods = new List<MethodInfo>(); | |
// Vector3 editor | |
bool _hasVector3Fields = false; | |
IEnumerable<FieldInfo> _fields; | |
public void OnEnable() | |
{ | |
var type = target.GetType(); | |
if( !typeof( IObjectInspectable ).IsAssignableFrom( type ) ) | |
return; | |
_onInspectorGuiMethod = target.GetType().GetMethod( "OnInspectorGUI", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); | |
_onSceneGuiMethod = target.GetType().GetMethod( "OnSceneGUI", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); | |
var meths = type.GetMethods( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) | |
.Where( m => m.IsDefined( typeof( MakeButtonAttribute ), false ) ); | |
foreach( var meth in meths ) | |
{ | |
_buttonMethods.Add( meth ); | |
} | |
// the vector3 editor needs to find any fields with the Vector3Inspectable attribute and validate them | |
_fields = type.GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) | |
.Where( f => f.IsDefined( typeof( Vector3Inspectable ), false ) ) | |
.Where( f => f.IsPublic || f.IsDefined( typeof( SerializeField ), false ) ); | |
_hasVector3Fields = _fields.Count() > 0; | |
} | |
public override void OnInspectorGUI() | |
{ | |
DrawDefaultInspector(); | |
if( _onInspectorGuiMethod != null ) | |
{ | |
foreach( var eachTarget in targets ) | |
_onInspectorGuiMethod.Invoke( eachTarget, new object[0] ); | |
} | |
foreach( var meth in _buttonMethods ) | |
{ | |
if( GUILayout.Button( CultureInfo.InvariantCulture.TextInfo.ToTitleCase( Regex.Replace( meth.Name, "(\\B[A-Z])", " $1" ) ) ) ) | |
foreach( var eachTarget in targets ) | |
meth.Invoke( eachTarget, new object[0] ); | |
} | |
} | |
protected virtual void OnSceneGUI() | |
{ | |
if( _onSceneGuiMethod != null ) | |
_onSceneGuiMethod.Invoke( target, new object[0] ); | |
if( _hasVector3Fields ) | |
vector3OnSceneGUI(); | |
} | |
#region Vector3 editor | |
void vector3OnSceneGUI() | |
{ | |
foreach( var field in _fields ) | |
{ | |
var value = field.GetValue( target ); | |
if( value is Vector3 ) | |
{ | |
Handles.Label( (Vector3)value, field.Name ); | |
var newValue = Handles.PositionHandle( (Vector3)value, Quaternion.identity ); | |
if( GUI.changed ) | |
{ | |
GUI.changed = false; | |
field.SetValue( target, newValue ); | |
} | |
} | |
else if( value is List<Vector3> ) | |
{ | |
var list = value as List<Vector3>; | |
var label = field.Name + ": "; | |
for( var i = 0; i < list.Count; i++ ) | |
{ | |
Handles.Label( list[i], label + i ); | |
list[i] = Handles.PositionHandle( list[i], Quaternion.identity ); | |
} | |
Handles.DrawPolyLine( list.ToArray() ); | |
} | |
else if( value is Vector3[] ) | |
{ | |
var list = value as Vector3[]; | |
var label = field.Name + ": "; | |
for( var i = 0; i < list.Length; i++ ) | |
{ | |
Handles.Label( list[i], label + i ); | |
list[i] = Handles.PositionHandle( list[i], Quaternion.identity ); | |
} | |
Handles.DrawPolyLine( list ); | |
} | |
} | |
} | |
#endregion | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ##### ##### ##### ##### ##### ##### ##### ##### | |
// ## ObjectInspectorHelpers.cs (this needs to live outside of the Editor folder) | |
// ##### ##### ##### ##### ##### ##### ##### ##### | |
using UnityEngine; | |
using System.Collections; | |
using System; | |
/// <summary> | |
/// implement this empty interface to tell the ObjectInspector that your class should be inspected | |
/// </summary> | |
public interface IObjectInspectable | |
{} | |
/// <summary> | |
/// makes any method have a button in the inspector to call it | |
/// </summary> | |
[AttributeUsageAttribute( AttributeTargets.Method )] | |
public class MakeButtonAttribute : Attribute | |
{} | |
/// <summary> | |
/// adds a vector3 editor to the scene GUI if this attribute is on any serialized Vector3, List<Vector3> | |
/// or Vector3[] fields. | |
/// </summary> | |
[AttributeUsageAttribute( AttributeTargets.Field )] | |
public class Vector3Inspectable : Attribute | |
{} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment