2019-05-07 16:37:50 -04:00
#if UNITY_2019_1_OR_NEWER
2019-10-20 15:48:52 -04:00
using System.Collections.Generic ;
2019-05-07 16:37:50 -04:00
using UnityEditor ;
using UnityEngine ;
2019-07-05 04:55:22 -04:00
2019-09-27 11:48:18 -04:00
namespace UnityAtoms.Editor
2019-05-07 16:37:50 -04:00
{
2019-10-15 13:19:44 -04:00
/// <summary>
2019-10-15 15:08:49 -04:00
/// The base Unity Atoms property drawer. Makes it possible to create and add a new Atom via Unity's inspector. Only availble in `UNITY_2019_1_OR_NEWER`.
2019-10-15 13:19:44 -04:00
/// </summary>
/// <typeparam name="T">The type of Atom the property drawer should apply to.</typeparam>
2019-05-07 16:37:50 -04:00
public abstract class AtomDrawer < T > : PropertyDrawer where T : ScriptableObject
{
2019-10-20 15:48:52 -04:00
class DrawerData
{
public bool UserClickedToCreateAtom = false ;
public string NameOfNewAtom = "" ;
public string WarningText = "" ;
}
private Dictionary < string , DrawerData > _perPropertyViewData = new Dictionary < string , DrawerData > ( ) ;
2019-05-07 16:37:50 -04:00
public override float GetPropertyHeight ( SerializedProperty property , GUIContent label )
{
2019-10-20 15:48:52 -04:00
DrawerData drawerData = GetDrawerData ( property . propertyPath ) ;
var isCreatingSO = drawerData . UserClickedToCreateAtom & & property . objectReferenceValue = = null ;
if ( ! isCreatingSO | | drawerData . WarningText . Length < = 0 ) return base . GetPropertyHeight ( property , label ) ;
2019-05-07 16:37:50 -04:00
return base . GetPropertyHeight ( property , label ) * 2 + 4f ;
}
2019-10-20 15:48:52 -04:00
private DrawerData GetDrawerData ( string propertyPath )
{
DrawerData drawerData ;
if ( ! _perPropertyViewData . TryGetValue ( propertyPath , out drawerData ) )
{
drawerData = new DrawerData ( ) ;
_perPropertyViewData [ propertyPath ] = drawerData ;
}
return drawerData ;
}
2019-05-07 16:37:50 -04:00
public override void OnGUI ( Rect position , SerializedProperty property , GUIContent label )
{
2019-10-20 15:48:52 -04:00
EditorGUI . BeginProperty ( position , label , property ) ;
DrawerData drawerData = GetDrawerData ( property . propertyPath ) ;
var isCreatingSO = drawerData . UserClickedToCreateAtom & & property . objectReferenceValue = = null ;
var restWidth = drawerData . UserClickedToCreateAtom ? 50 : 58 ;
var gutter = drawerData . UserClickedToCreateAtom ? 2f : 6f ;
2019-05-07 16:37:50 -04:00
Rect restRect = new Rect ( ) ;
Rect warningRect = new Rect ( ) ;
2019-10-20 15:48:52 -04:00
if ( drawerData . WarningText . Length > 0 )
2019-05-07 16:37:50 -04:00
{
position = IMGUIUtils . SnipRectV ( position , EditorGUIUtility . singleLineHeight , out warningRect , 2f ) ;
}
if ( property . objectReferenceValue = = null )
{
position = IMGUIUtils . SnipRectH ( position , position . width - restWidth , out restRect , gutter ) ;
}
var defaultGUIColor = GUI . color ;
GUI . color = isCreatingSO ? Color . yellow : defaultGUIColor ;
position = EditorGUI . PrefixLabel ( position , GUIUtility . GetControlID ( FocusType . Passive ) , isCreatingSO ? new GUIContent ( "Name of New Atom" ) : label ) ;
GUI . color = defaultGUIColor ;
2019-10-20 15:48:52 -04:00
var indent = EditorGUI . indentLevel ;
EditorGUI . indentLevel = 0 ;
2019-05-07 16:37:50 -04:00
if ( isCreatingSO )
{
2019-10-20 15:48:52 -04:00
drawerData . NameOfNewAtom = EditorGUI . TextField ( position , drawerData . NameOfNewAtom ) ;
2019-05-07 16:37:50 -04:00
}
else
{
property . objectReferenceValue = EditorGUI . ObjectField ( position , property . objectReferenceValue , typeof ( T ) , false ) ;
}
if ( property . objectReferenceValue = = null )
{
if ( isCreatingSO )
{
var buttonWidth = 24 ;
Rect secondButtonRect ;
Rect firstButtonRect = IMGUIUtils . SnipRectH ( restRect , restRect . width - buttonWidth , out secondButtonRect , gutter ) ;
if ( GUI . Button ( firstButtonRect , "✓" ) )
{
2019-10-20 15:48:52 -04:00
if ( drawerData . NameOfNewAtom . Length > 0 )
2019-05-07 16:37:50 -04:00
{
try
{
// Create asset
T so = ScriptableObject . CreateInstance < T > ( ) ;
2019-10-20 15:48:52 -04:00
AssetDatabase . CreateAsset ( so , "Assets/" + drawerData . NameOfNewAtom + ".asset" ) ;
2019-05-07 16:37:50 -04:00
AssetDatabase . SaveAssets ( ) ;
// Assign the newly created SO
property . objectReferenceValue = so ;
}
catch
{
Debug . LogError ( "Not able to create Atom" ) ;
}
2019-10-20 15:48:52 -04:00
drawerData . UserClickedToCreateAtom = false ;
drawerData . WarningText = "" ;
2019-05-07 16:37:50 -04:00
}
else
{
2019-10-20 15:48:52 -04:00
drawerData . WarningText = "Name of new Atom must be specified!" ;
2019-05-07 16:37:50 -04:00
}
}
if ( GUI . Button ( secondButtonRect , "✗" ) )
{
2019-10-20 15:48:52 -04:00
drawerData . UserClickedToCreateAtom = false ;
drawerData . WarningText = "" ;
2019-05-07 16:37:50 -04:00
}
2019-10-20 15:48:52 -04:00
if ( drawerData . WarningText . Length > 0 )
2019-05-07 16:37:50 -04:00
{
2019-10-20 15:48:52 -04:00
EditorGUI . HelpBox ( warningRect , drawerData . WarningText , MessageType . Warning ) ;
2019-05-07 16:37:50 -04:00
}
}
else
{
if ( GUI . Button ( restRect , "Create" ) )
{
2019-10-20 15:48:52 -04:00
drawerData . NameOfNewAtom = "" ;
drawerData . UserClickedToCreateAtom = true ;
2019-05-07 16:37:50 -04:00
}
}
}
2019-10-20 15:48:52 -04:00
EditorGUI . indentLevel = indent ;
2019-05-07 16:37:50 -04:00
EditorGUI . EndProperty ( ) ;
}
}
}
#endif