using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using UnityEditor.SceneManagement;
namespace MLAgents
{
///
/// PropertyDrawer for ResetParameters. Defines how ResetParameters are displayed in the
/// Inspector.
///
[CustomPropertyDrawer(typeof(ResetParameters))]
public class ResetParameterDrawer : PropertyDrawer
{
private ResetParameters _parameters;
// The height of a line in the Unity Inspectors
private const float LineHeight = 17f;
// This is the prefix for the key when you add a reset parameter
private const string NewKeyPrefix = "Param-";
///
/// Computes the height of the Drawer depending on the property it is showing
///
/// The property that is being drawn.
/// The label of the property being drawn.
/// The vertical space needed to draw the property.
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
LazyInitializeParameters(property, label);
return (_parameters.Count + 2) * LineHeight;
}
///
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
LazyInitializeParameters(property, label);
position.height = LineHeight;
EditorGUI.LabelField(position, label);
position.y += LineHeight;
var width = position.width / 2 - 24;
var keyRect = new Rect(position.x + 20, position.y, width, position.height);
var valueRect = new Rect(position.x + width + 30, position.y, width, position.height);
DrawAddRemoveButtons(keyRect, valueRect);
EditorGUI.BeginProperty(position, label, property);
foreach (var parameter in _parameters)
{
var key = parameter.Key;
var value = parameter.Value;
keyRect.y += LineHeight;
valueRect.y += LineHeight;
EditorGUI.BeginChangeCheck();
var newKey = EditorGUI.TextField(keyRect, key);
if (EditorGUI.EndChangeCheck())
{
MarkSceneAsDirty();
try
{
_parameters.Remove(key);
_parameters.Add(newKey, value);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
break;
}
EditorGUI.BeginChangeCheck();
value = EditorGUI.FloatField(valueRect, value);
if (EditorGUI.EndChangeCheck())
{
MarkSceneAsDirty();
_parameters[key] = value;
break;
}
}
EditorGUI.EndProperty();
}
///
/// Draws the Add and Remove buttons.
///
/// The rectangle for the Add New button.
/// The rectangle for the Remove Last button.
private void DrawAddRemoveButtons(Rect addRect, Rect removeRect)
{
// This is the Add button
if (_parameters.Count == 0)
{
addRect.width *= 2;
}
if (GUI.Button(addRect,
new GUIContent("Add New", "Add a new item to the default reset parameters"),
EditorStyles.miniButton))
{
MarkSceneAsDirty();
AddParameter();
}
// If there are no items in the ResetParameters, Hide the Remove button
if (_parameters.Count == 0)
{
return;
}
// This is the Remove button
if (GUI.Button(removeRect,
new GUIContent(
"Remove Last", "Remove the last item from the default reset parameters"),
EditorStyles.miniButton))
{
MarkSceneAsDirty();
RemoveLastParameter();
}
}
///
/// Signals that the property has been modified and requires the scene to be saved for
/// the changes to persist. Only works when the Editor is not playing.
///
private static void MarkSceneAsDirty()
{
if (!EditorApplication.isPlaying)
{
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
}
///
/// Ensures that the state of the Drawer is synchronized with the property.
///
/// The SerializedProperty of the ResetParameters
/// to make the custom GUI for.
/// The label of this property.
private void LazyInitializeParameters(SerializedProperty property, GUIContent label)
{
if (_parameters != null)
{
return;
}
var target = property.serializedObject.targetObject;
_parameters = fieldInfo.GetValue(target) as ResetParameters;
if (_parameters == null)
{
_parameters = new ResetParameters();
fieldInfo.SetValue(target, _parameters);
}
}
///
/// Removes the last ResetParameter from the ResetParameters
///
private void RemoveLastParameter()
{
if (_parameters.Count > 0)
{
string key = _parameters.Keys.ToList()[_parameters.Count - 1];
_parameters.Remove(key);
}
}
///
/// Adds a new ResetParameter to the ResetParameters with a default name.
///
private void AddParameter()
{
string key = NewKeyPrefix + _parameters.Count;
var value = default(float);
try
{
_parameters.Add(key, value);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
}
}
}