├── .gitignore ├── DropdownSubtypesOf ├── DropdownSubtypesOf.cs ├── DropdownSubtypesOfExample.cs ├── Editor │ └── DropdownSubtypesDrawer.cs ├── readme.md └── screenshot.png ├── SingleBound ├── Editor │ ├── NotLessThanDrawer.cs │ └── NotMoreThanDrawer.cs ├── NotLessThan.cs ├── NotMoreThan.cs ├── SingleBound.cs ├── SingleBoundExamples.cs └── readme.md ├── inspector-before.png ├── license.md └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.meta 3 | *# 4 | *~ 5 | -------------------------------------------------------------------------------- /DropdownSubtypesOf/DropdownSubtypesOf.cs: -------------------------------------------------------------------------------- 1 | 2 | using UnityEngine; 3 | using System; 4 | 5 | /* 6 | 7 | this attribute says you want a dropdox of all subtypes of basetype, 8 | which will be stored as a string in the property. 9 | 10 | usage: 11 | 12 | [DropdownSubtypesOf(typeof(BaseType))] 13 | [SerializeField] private string m_type; 14 | 15 | m_type will contain the string name of the type selected in the dropdown. 16 | 17 | */ 18 | public class DropdownSubtypesOf : PropertyAttribute 19 | { 20 | public DropdownSubtypesOf(Type baseType) 21 | { 22 | BaseType = baseType; 23 | } 24 | 25 | public Type BaseType { get; private set; } 26 | 27 | ////////////////////////////////////////////////// 28 | 29 | ////////////////////////////////////////////////// 30 | } -------------------------------------------------------------------------------- /DropdownSubtypesOf/DropdownSubtypesOfExample.cs: -------------------------------------------------------------------------------- 1 | 2 | using UnityEngine; 3 | using System; 4 | 5 | public class DropdownSubtypesOfExample : MonoBehaviour 6 | { 7 | [DropdownSubtypesOf(typeof(PropertyAttribute))] 8 | public string MyType; 9 | } -------------------------------------------------------------------------------- /DropdownSubtypesOf/Editor/DropdownSubtypesDrawer.cs: -------------------------------------------------------------------------------- 1 | 2 | using UnityEditor; 3 | using UnityEngine; 4 | using System; 5 | using System.Linq; 6 | using System.Collections.Generic; 7 | 8 | // draws a dropdown containing all subtypes 9 | // of the base type contained in DropdownSubtypesOf. 10 | [CustomPropertyDrawer (typeof (DropdownSubtypesOf))] 11 | public class DropdownSubtypesDrawer : PropertyDrawer 12 | { 13 | public static IEnumerable FindSubclassesOf(System.Type t) 14 | { 15 | var subclasses = new List(); 16 | foreach(var asm in System.AppDomain.CurrentDomain.GetAssemblies()) 17 | { 18 | foreach (var type in asm.GetTypes()) 19 | { 20 | if (type.IsAbstract == false && t.IsAssignableFrom(type)) 21 | { 22 | subclasses.Add(type); 23 | } 24 | } 25 | } 26 | return subclasses; 27 | } 28 | 29 | 30 | 31 | 32 | public override void OnGUI (Rect position, 33 | SerializedProperty prop, 34 | GUIContent label) 35 | { 36 | if(prop.propertyType != SerializedPropertyType.String) 37 | { 38 | throw new UnityException("property " + prop 39 | + " must be string to use with DropdownSubtypesOf"); 40 | } 41 | 42 | 43 | var popupRect = EditorGUI.PrefixLabel(position, 44 | GUIUtility.GetControlID(FocusType.Passive), 45 | label); 46 | 47 | var baseType = SubtypesAttribute.BaseType; 48 | 49 | var subclasses = FindSubclassesOf(baseType).Select(t => t.Name).ToArray(); 50 | 51 | var currentClassName = prop.stringValue; 52 | var currentClassIndex = subclasses.Length - 1; 53 | for(; currentClassIndex >= 0; --currentClassIndex) 54 | { 55 | if (subclasses[currentClassIndex] == currentClassName) 56 | { 57 | break; 58 | } 59 | } 60 | 61 | int newClassIndex = EditorGUI.Popup(popupRect, currentClassIndex, subclasses); 62 | 63 | prop.stringValue = newClassIndex < 0 ? "" : subclasses[newClassIndex]; 64 | } 65 | 66 | 67 | ////////////////////////////////////////////////// 68 | 69 | private DropdownSubtypesOf SubtypesAttribute 70 | { 71 | get { return attribute as DropdownSubtypesOf; } 72 | } 73 | 74 | ////////////////////////////////////////////////// 75 | 76 | } -------------------------------------------------------------------------------- /DropdownSubtypesOf/readme.md: -------------------------------------------------------------------------------- 1 | Presents a dropdown/popup of all subtypes of a base class. 2 | The chosen class is stored as a string. 3 | 4 | usage: 5 | 6 | [DropdownSubtypesOf(typeof(BaseType))] 7 | public string MyType; 8 | 9 | ![dropdownsubtypesof example screenshot](screenshot.png "Appearance") 10 | 11 | 12 | -------------------------------------------------------------------------------- /DropdownSubtypesOf/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenpn/ChestOfPropertyDrawers/7626f6b49d59cc32b9f92c3bfaac3e29cbc6d470/DropdownSubtypesOf/screenshot.png -------------------------------------------------------------------------------- /SingleBound/Editor/NotLessThanDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System; 4 | 5 | // presents a normal edit box, but bounds it 6 | [CustomPropertyDrawer(typeof(NotLessThan))] 7 | public class NotLessThanDrawer : PropertyDrawer 8 | { 9 | 10 | public override void OnGUI (Rect position, 11 | SerializedProperty prop, 12 | GUIContent label) 13 | { 14 | var bound = attribute as NotLessThan; 15 | 16 | try 17 | { 18 | if (prop.propertyType == SerializedPropertyType.Integer) 19 | { 20 | prop.intValue = Mathf.Max(EditorGUI.IntField(position, label, prop.intValue), 21 | bound.IntBound); 22 | } 23 | else if (prop.propertyType == SerializedPropertyType.Float) 24 | { 25 | prop.floatValue = Mathf.Max(EditorGUI.FloatField(position, label, prop.floatValue), 26 | bound.FloatBound); 27 | } 28 | else 29 | { 30 | throw new UnityException("must be int or float to use with NotLessThan"); 31 | } 32 | } 33 | catch (UnityException e) 34 | { 35 | throw new UnityException("error on NotLessThan attribute of property " 36 | + prop.name + "\n" + e.ToString()); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /SingleBound/Editor/NotMoreThanDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System; 4 | 5 | // presents a normal edit box, but bounds it 6 | [CustomPropertyDrawer(typeof(NotMoreThan))] 7 | public class NotMoreThanDrawer : PropertyDrawer 8 | { 9 | 10 | public override void OnGUI (Rect position, 11 | SerializedProperty prop, 12 | GUIContent label) 13 | { 14 | var bound = attribute as NotMoreThan; 15 | 16 | try 17 | { 18 | if (prop.propertyType == SerializedPropertyType.Integer) 19 | { 20 | prop.intValue = Mathf.Min(EditorGUI.IntField(position, label, prop.intValue), 21 | bound.IntBound); 22 | } 23 | else if (prop.propertyType == SerializedPropertyType.Float) 24 | { 25 | prop.floatValue = Mathf.Min(EditorGUI.FloatField( 26 | position, label, prop.floatValue), 27 | bound.FloatBound); 28 | } 29 | else 30 | { 31 | throw new UnityException( 32 | "must be int or float property to use with NotMoreThan"); 33 | } 34 | } 35 | catch (UnityException e) 36 | { 37 | throw new UnityException("error on NotMoreThan attribute of property " 38 | + prop.name + "\n" + e.ToString()); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /SingleBound/NotLessThan.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | /* 5 | 6 | will stop the the user entering a value below this bound 7 | 8 | */ 9 | public class NotLessThan : SingleBound 10 | { 11 | public NotLessThan(int lowerBound) { IntBound = lowerBound; } 12 | public NotLessThan(float lowerBound) { FloatBound = lowerBound; } 13 | } -------------------------------------------------------------------------------- /SingleBound/NotMoreThan.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | /* 5 | 6 | will stop the the user entering a value above this bound 7 | 8 | */ 9 | public class NotMoreThan : SingleBound 10 | { 11 | public NotMoreThan(int upperBound) { IntBound = upperBound; } 12 | public NotMoreThan(float upperBound) { FloatBound = upperBound; } 13 | } -------------------------------------------------------------------------------- /SingleBound/SingleBound.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | public abstract class SingleBound : PropertyAttribute 5 | { 6 | // record what type was set, so we can cry if someone mismatches a bound and a property 7 | 8 | public int IntBound 9 | { 10 | get 11 | { 12 | if (FixedType != typeof(int)) 13 | { 14 | throw new UnityException(FixedType.ToString() 15 | + " is set, asked for int in " + GetType()); 16 | } 17 | return m_intBound; 18 | } 19 | protected set 20 | { 21 | FixedType = typeof(int); 22 | m_intBound = value; 23 | } 24 | } 25 | 26 | public float FloatBound 27 | { 28 | get 29 | { 30 | if (FixedType != typeof(float)) 31 | { 32 | throw new UnityException(FixedType.ToString() 33 | + " is set, asked for float in " + GetType()); 34 | } 35 | return m_floatBound; 36 | } 37 | protected set 38 | { 39 | FixedType = typeof(float); 40 | m_floatBound = value; 41 | } 42 | } 43 | 44 | ////////////////////////////////////////////////// 45 | 46 | private Type FixedType { get; set; } 47 | private float m_floatBound; 48 | private int m_intBound; 49 | 50 | ////////////////////////////////////////////////// 51 | } -------------------------------------------------------------------------------- /SingleBound/SingleBoundExamples.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | public class SingleBoundExamples : MonoBehaviour 5 | { 6 | [NotMoreThan(3.0f)] 7 | public float NotMoreThan3f; 8 | 9 | [NotMoreThan(10)] 10 | public int NotMoreThan10; 11 | 12 | [NotLessThan(4f)] 13 | public float NotLessThan4f = 5f; 14 | 15 | [NotLessThan(-3)] 16 | public int NotLessThanMinus3; 17 | } -------------------------------------------------------------------------------- /SingleBound/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Bounds a float or an int to either a maximum or mimimum. For when you don't know a sensible value for the other half of a ranged property. 3 | 4 | Presents int or float field just like normal, except value is bound. 5 | 6 | Extensive error checking to make sure attributes and properties are always same type. 7 | 8 | If anyone knows how to reduce duplication of code in the drawers, please have a hack! 9 | 10 | usage: 11 | 12 | [NotLessThan(3)] 13 | int MyInt = 10; 14 | 15 | [NotMoreThan(100.0f)] 16 | float MyFloat = 45.0f; -------------------------------------------------------------------------------- /inspector-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenpn/ChestOfPropertyDrawers/7626f6b49d59cc32b9f92c3bfaac3e29cbc6d470/inspector-before.png -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | tldr: http://www.tldrlegal.com/license/apache-license-2.0-(apache-2.0) 2 | 3 | Entire repro Copyright 2013 Andrew Fray 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | A collection of open-source Unity3D property drawers 2 | 3 | http://blogs.unity3d.com/2012/09/07/property-drawers-in-unity-4/ 4 | http://docs.unity3d.com/Documentation/ScriptReference/PropertyDrawer.html 5 | 6 | Property drawers are a new feature in Unity 4 to help you make custom inspectors without writing editor code. By just adding attributes to your behaviour's fields, you can turn the left image into the right: 7 | 8 | ![Drawers before and after](inspector-before.png) 9 | 10 | Each directory contains one drawer, and some documentation. 11 | 12 | ##Installation 13 | 14 | Download the zip from the ZIP button above, expand into your Assets directory. 15 | 16 | ##More Drawers 17 | 18 | Got an idea for a drawer? No time? Suggest it in the issues page! 19 | https://github.com/tenpn/ChestOfPropertyDrawers/issues 20 | 21 | ###Pull Requests 22 | 23 | Pull requests more than welcome, but new drawers must be grainular enough to be of use to multiple projects. 24 | 25 | New pull requests should be in this format: 26 | 27 | ``` 28 | AttributeName 29 | |- Editor 30 | |- PropertyDrawer.cs 31 | |- Attribute.cs 32 | |- ExampleUsage.cs 33 | |- readme.md 34 | ``` 35 | 36 | If you can embed pictures in your readmes, all the better. 37 | 38 | ##Other Stuff 39 | 40 | Partially-inspired by this Japanese(?) repro: 41 | https://github.com/anchan828/property-drawer-collection 42 | 43 | For licensing, see [license file](license.md) 44 | --------------------------------------------------------------------------------