//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Collections;
using System.Collections.Generic;
using BansheeEngine;
namespace BansheeEditor
{
/** @addtogroup Inspector
* @{
*/
///
/// Displays GUI for a serializable property containing a list. List contents are displayed as rows of entries
/// that can be shown, hidden or manipulated.
///
public class InspectableList : InspectableField
{
private InspectableListGUI listGUIField;
///
/// Creates a new inspectable list GUI for the specified property.
///
/// Parent Inspector this field belongs to.
/// Name of the property, or some other value to set as the title.
/// Full path to this property (includes name of this property and all parent properties).
/// Determines how deep within the inspector nesting hierarchy is this field. Some fields may
/// contain other fields, in which case you should increase this value by one.
/// Parent layout that all the field elements will be added to.
/// Serializable property referencing the array whose contents to display.
public InspectableList(Inspector parent, string title, string path, int depth, InspectableFieldLayout layout,
SerializableProperty property)
: base(parent, title, path, SerializableProperty.FieldType.List, depth, layout, property)
{
}
///
public override GUILayoutX GetTitleLayout()
{
return listGUIField.GetTitleLayout();
}
///
public override InspectableState Refresh(int layoutIndex)
{
return listGUIField.Refresh();
}
///
protected internal override void Initialize(int layoutIndex)
{
GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
listGUIField = InspectableListGUI.Create(parent, title, path, property, arrayLayout, depth);
listGUIField.IsExpanded = parent.Persistent.GetBool(path + "_Expanded");
listGUIField.OnExpand += x => parent.Persistent.SetBool(path + "_Expanded", x);
}
///
/// Handles creation of GUI elements for a GUI list field that displays a object.
///
private class InspectableListGUI : GUIListFieldBase
{
private IList list;
private int numElements;
private Inspector parent;
private SerializableProperty property;
private string path;
///
/// Returns the parent inspector the array GUI belongs to.
///
public Inspector Inspector
{
get { return parent; }
}
///
/// Returns a property path to the array field (name of the array field and all parent object fields).
///
public string Path
{
get { return path; }
}
///
/// Constructs a new empty inspectable list GUI.
///
/// Parent Inspector this field belongs to.
/// Label to display on the list GUI title.
/// Full path to this property (includes name of this property and all parent properties).
///
/// Serializable property referencing a list.
/// Layout to which to append the list GUI elements to.
/// Determines at which depth to render the background. Useful when you have multiple
/// nested containers whose backgrounds are overlaping. Also determines background style,
/// depths divisible by two will use an alternate style.
public InspectableListGUI(Inspector parent, LocString title, string path, SerializableProperty property,
GUILayout layout, int depth)
: base(title, layout, depth)
{
this.property = property;
this.parent = parent;
this.path = path;
list = property.GetValue();
if (list != null)
numElements = list.Count;
}
///
/// Creates a new inspectable list GUI object that displays the contents of the provided serializable property.
///
/// Parent Inspector this field belongs to.
/// Label to display on the list GUI title.
/// Full path to this property (includes name of this property and all parent properties).
///
/// Serializable property referencing a list.
/// Layout to which to append the list GUI elements to.
/// Determines at which depth to render the background. Useful when you have multiple
/// nested containers whose backgrounds are overlaping. Also determines background style,
/// depths divisible by two will use an alternate style.
public static InspectableListGUI Create(Inspector parent, LocString title, string path,
SerializableProperty property, GUILayout layout, int depth)
{
InspectableListGUI listGUI = new InspectableListGUI(parent, title, path, property, layout, depth);
listGUI.BuildGUI();
return listGUI;
}
///
public override InspectableState Refresh()
{
// Check if any modifications to the array were made outside the inspector
IList newList = property.GetValue();
if (list == null && newList != null)
{
list = newList;
numElements = list.Count;
BuildGUI();
}
else if (newList == null && list != null)
{
list = null;
numElements = 0;
BuildGUI();
}
else
{
if (list != null)
{
if (numElements != list.Count)
{
numElements = list.Count;
BuildGUI();
}
}
}
return base.Refresh();
}
///
protected override GUIListFieldRow CreateRow()
{
return new InspectableListGUIRow();
}
///
protected override bool IsNull()
{
return list == null;
}
///
protected override int GetNumRows()
{
if (list != null)
return list.Count;
return 0;
}
///
protected internal override object GetValue(int seqIndex)
{
SerializableList list = property.GetList();
return list.GetProperty(seqIndex);
}
///
protected internal override void SetValue(int seqIndex, object value)
{
// Setting the value should be done through the property
throw new InvalidOperationException();
}
///
protected override void CreateList()
{
list = property.CreateListInstance(0);
property.SetValue(list);
numElements = 0;
}
///
protected override void ResizeList()
{
int size = guiSizeField.Value;
IList newList = property.CreateListInstance(size);
int maxSize = MathEx.Min(size, list.Count);
for (int i = 0; i < maxSize; i++)
newList[i] = list[i];
property.SetValue(newList);
list = newList;
numElements = list.Count;
}
///
protected override void ClearList()
{
property.SetValue