public virtual int AddSlot(ConcreteSlotValueType concreteValueType)
        {
            var    index = this.GetInputSlots <ISlot>().Count() + 1;
            string name  = NodeUtils.GetDuplicateSafeNameForSlot(this, concreteValueType.ToString());

            AddSlot(MaterialSlot.CreateMaterialSlot(concreteValueType.ToSlotValueType(), index, name, NodeUtils.GetHLSLSafeName(name), SlotType.Input, Vector4.zero));
            return(index);
        }
        private void AddEntry(ReorderableList list)
        {
            // Need to get all current slots to get the next valid ID
            List <MaterialSlot> slots = new List <MaterialSlot>();

            m_Node.GetSlots(slots);
            int[] slotIDs   = slots.Select(s => s.id).OrderByDescending(s => s).ToArray();
            int   newSlotID = slotIDs.Length > 0 ? slotIDs[0] + 1 : 0;

            string name = NodeUtils.GetDuplicateSafeNameForSlot(m_Node, "New");

            // Create a new slot and add it
            var newSlot = MaterialSlot.CreateMaterialSlot(SlotValueType.Vector1, newSlotID, name, NodeUtils.GetHLSLSafeName(name), m_SlotType, Vector4.zero);

            m_Node.AddSlot(newSlot);

            // Select the new slot, then validate the node
            m_SelectedIndex = list.list.Count - 1;
            m_Node.owner.owner.RegisterCompleteObjectUndo("Adding Slot");
            m_Node.ValidateNode();
        }
        private void AddCallbacks()
        {
            m_ReorderableList.drawHeaderCallback = (Rect rect) =>
            {
                var labelRect = new Rect(rect.x, rect.y, rect.width - 10, rect.height);
                EditorGUI.LabelField(labelRect, label);
            };

            // Draw Element
            m_ReorderableList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                rect.y += 2;

                // Slot is guaranteed to exist in this UI state
                MaterialSlot oldSlot = m_Node.FindSlot <MaterialSlot>((int)m_ReorderableList.list[index]);

                EditorGUI.BeginChangeCheck();

                var displayName       = EditorGUI.DelayedTextField(new Rect(rect.x, rect.y, labelWidth, EditorGUIUtility.singleLineHeight), oldSlot.RawDisplayName(), labelStyle);
                var shaderOutputName  = NodeUtils.GetHLSLSafeName(displayName);
                var concreteValueType = (ConcreteSlotValueType)EditorGUI.EnumPopup(new Rect(rect.x + labelWidth, rect.y, rect.width - labelWidth, EditorGUIUtility.singleLineHeight), oldSlot.concreteValueType);

                if (displayName != oldSlot.RawDisplayName())
                {
                    displayName = NodeUtils.GetDuplicateSafeNameForSlot(m_Node, displayName);
                }

                if (EditorGUI.EndChangeCheck())
                {
                    // Cant modify existing slots so need to create new and copy values
                    var newSlot = MaterialSlot.CreateMaterialSlot(concreteValueType.ToSlotValueType(), oldSlot.id, displayName, shaderOutputName, m_SlotType, Vector4.zero);
                    newSlot.CopyValuesFrom(oldSlot);
                    m_Node.AddSlot(newSlot);

                    // Need to get all current slots as everything after the edited slot in the list must be added again
                    List <MaterialSlot> slots = new List <MaterialSlot>();
                    if (m_SlotType == SlotType.Input)
                    {
                        m_Node.GetInputSlots <MaterialSlot>(slots);
                    }
                    else
                    {
                        m_Node.GetOutputSlots <MaterialSlot>(slots);
                    }

                    // Iterate all the slots
                    foreach (MaterialSlot slot in slots)
                    {
                        // Because the list doesnt match the slot IDs (reordering)
                        // Need to get the index in the list of every slot
                        int listIndex = 0;
                        for (int i = 0; i < m_ReorderableList.list.Count; i++)
                        {
                            if ((int)m_ReorderableList.list[i] == slot.id)
                            {
                                listIndex = i;
                            }
                        }

                        // Then for everything after the edited slot
                        if (listIndex <= index)
                        {
                            continue;
                        }

                        // Remove and re-add
                        m_Node.AddSlot(slot);
                    }

                    RecreateList();
                    m_Node.ValidateNode();
                }
            };

            // Element height
            m_ReorderableList.elementHeightCallback = (int indexer) =>
            {
                return(m_ReorderableList.elementHeight);
            };

            // Add callback delegates
            m_ReorderableList.onSelectCallback  += SelectEntry;
            m_ReorderableList.onAddCallback     += AddEntry;
            m_ReorderableList.onRemoveCallback  += RemoveEntry;
            m_ReorderableList.onReorderCallback += ReorderEntries;
        }