in SupportingScripts/Editor/Scripts/TileLayerListDrawer.cs [42:145]
private ReorderableList GetList(SerializedProperty tileLayerListProperty)
{
if (_reorderableList == null)
{
var internalListProperty = tileLayerListProperty.FindPropertyRelative("_list");
var tileLayerInternalList = (List<TLayer>)internalListProperty.GetValue();
var tileLayerList = (TileLayerList<TLayer>)tileLayerListProperty.GetValue();
if (internalListProperty == null || tileLayerList == null || tileLayerInternalList == null)
{
throw new NotSupportedException(
$"The property {tileLayerListProperty.name} of type {tileLayerListProperty.type} must be a TileLayerList.");
}
// Object that owns the list property (MapRenderer).
var ownerObject = tileLayerListProperty.serializedObject;
_reorderableList =
new ReorderableList(
ownerObject,
internalListProperty,
draggable: true,
displayHeader: true,
displayAddButton: true,
displayRemoveButton: true)
{
drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, Title),
elementHeightCallback = (int index) => EditorGUI.GetPropertyHeight(internalListProperty.GetArrayElementAtIndex(index)),
// The full type name would be displayed if we didn't override this and show the shorter one.
drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) =>
{
rect.width -= 40;
SerializedProperty serializedElement = internalListProperty.GetArrayElementAtIndex(index);
EditorGUI.PropertyField(rect, serializedElement);
},
onCanAddCallback = (ReorderableList reorderableList) => reorderableList.count < MaximumCount,
onRemoveCallback =
(ReorderableList reorderableList) =>
{
var tileLayer = tileLayerList[reorderableList.index];
if (tileLayer != null)
{
// This will cause the tileLayer to remove itself from the list, internally.
Undo.DestroyObjectImmediate(tileLayer);
}
else
{
// If the item is null (some invalid/broken component),
// remove it directly from the list. ReorderableList doesn't.
Undo.RecordObject(ownerObject.targetObject, "Remove tile layer from list");
tileLayerInternalList.RemoveAt(reorderableList.index);
}
// Commit changes to the MapRenderer back to the SerializedObject.
ownerObject.Update();
},
onAddDropdownCallback =
(Rect buttonRect, ReorderableList reorderableList) =>
{
// Get all the eligible types.
GetValidTileLayerComponents(internalListProperty, out var types, out var typeNames);
// Create the menu.
var menu = new GenericMenu();
for (int typeIndex = 0; typeIndex < typeNames.Length; ++typeIndex)
{
menu.AddItem(
// Display the shorter name
new GUIContent(typeNames[typeIndex]),
false,
(userDataTypeIndex) =>
{
var mapRenderer = (MapRenderer)ownerObject.targetObject;
var newLayer = (TLayer)Undo.AddComponent(mapRenderer.gameObject, types[(int)userDataTypeIndex]);
if (newLayer == null)
{
// Maybe show a message box to indicate the layer was unable to be added. This shouldn't
// happen though since we already filter out types that have already been added with
// DisallowMultipleComponent. But maybe there are other reasons component creation fails?
}
// Commit changes to the MapRenderer back to the SerializedObject.
ownerObject.Update();
},
userData: typeIndex);
}
if (typeNames.Length == 0)
{
menu.AddDisabledItem(new GUIContent("None"));
}
menu.ShowAsContext();
}
};
}
return _reorderableList;
}