private ReorderableList GetList()

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;
        }