系列文章目录
麦田物语第六天
一、(Editor)实现 ListView 添加删除同步信息功能
在本节课中我们实现Editor的最后两个功能,添加(AddButton)和删除(DeleteButton),我们通过.Q的方式找到这两个按钮,然后为其添加相应的按钮点击事件,实现添加和删除的功能。
在添加按钮的事件中,我们需要创建一个对象,添加到itemList中,同时为其添加名字和序号,切记最后一定要rebuild左侧的ListView,这样才能更新添加后的界面。
在删除按钮的事件中,我们需要在itemList中移除当前我们右侧激活的物体,但是移除之后我们右侧的数据都会为空,因此我们要将右侧的数据进行隐藏,同时记得Rebuild。
代码如下
public void CreateGUI()
{
//获得按键
root.Q<Button>("AddButton").clicked += OnAddItemClicked;
root.Q<Button>("DeleteButton").clicked += OnDeleteItemClicked;
}
#region 按键事件
private void OnDeleteItemClicked()
{
itemList.Remove(activeItem);
itemListView.Rebuild();
itemDetailsSection.visible = false;
}
private void OnAddItemClicked()
{
ItemDetails newItem = new ItemDetails();
newItem.itemName = "New ITEM";
newItem.itemID = 1000 + itemList.Count;
itemList.Add(newItem);
itemListView.Rebuild();
}
#endregion
二、总结
这次总结是对以上几个博客的总结,我们之前的所有代码都是部分编写的,因此我把属于每个部分的代码剔除出来粘贴,下面是总的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
public class ItemEditor : EditorWindow
{
private ItemDataList_SO dataBase;
private List<ItemDetails> itemList = new List<ItemDetails>();
private VisualTreeAsset itemRowTemplate;
private ScrollView itemDetailsSection;
private ItemDetails activeItem;
//默认预览图片
private Sprite defaultIcon;
private VisualElement iconPreview;
//获得VisualElement
private ListView itemListView;
[MenuItem("M STUDIO/ItemEditor")]
public static void ShowExample()
{
ItemEditor wnd = GetWindow<ItemEditor>();
wnd.titleContent = new GUIContent("ItemEditor");
}
public void CreateGUI()
{
// Each editor window contains a root VisualElement object
VisualElement root = rootVisualElement;
// VisualElements objects can contain other VisualElement following a tree hierarchy.
// VisualElement label = new Label("Hello World! From C#");
// root.Add(label);
// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UI Builder/ItemEditor.uxml");
VisualElement labelFromUXML = visualTree.Instantiate();
root.Add(labelFromUXML);
//拿到模版数据
itemRowTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UI Builder/ItemRowTemplate.uxml");
//拿默认Icon图片
defaultIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/M Studio/Art/Items/Icons/icon_M.png");
//变量赋值
itemListView = root.Q<VisualElement>("ItemList").Q<ListView>("ListView");
itemDetailsSection = root.Q<ScrollView>("ItemDetails");
iconPreview = itemDetailsSection.Q<VisualElement>("Icon");
//获得按键
root.Q<Button>("AddButton").clicked += OnAddItemClicked;
root.Q<Button>("DeleteButton").clicked += OnDeleteClicked;
//加载数据
LoadDataBase();
//生成ListView
GenerateListView();
}
#region 按键事件
private void OnDeleteClicked()
{
itemList.Remove(activeItem);
itemListView.Rebuild();
itemDetailsSection.visible = false;
}
private void OnAddItemClicked()
{
ItemDetails newItem = new ItemDetails();
newItem.itemName = "NEW ITEM";
newItem.itemID = 1001 + itemList.Count;
itemList.Add(newItem);
itemListView.Rebuild();
}
#endregion
private void LoadDataBase()
{
var dataArray = AssetDatabase.FindAssets("ItemDataList_SO");
//var dataArray = AssetDatabase.FindAssets("t:ItemDataList_SO"); //不同版本写法不一样
//if (dataArray.Length >= 1) //不同版本写法不同
if (dataArray.Length > 1)
{
var path = AssetDatabase.GUIDToAssetPath(dataArray[0]);
dataBase = AssetDatabase.LoadAssetAtPath(path, typeof(ItemDataList_SO)) as ItemDataList_SO;
}
itemList = dataBase.itemDetailsList;
//如果不标记则无法保存数据
EditorUtility.SetDirty(dataBase);
// Debug.Log(itemList[0].itemID);
}
private void GenerateListView()
{
Func<VisualElement> makeItem = () => itemRowTemplate.CloneTree();
Action<VisualElement, int> bindItem = (e, i) =>
{
if (i < itemList.Count)
{
if (itemList[i].itemIcon != null)
e.Q<VisualElement>("Icon").style.backgroundImage = itemList[i].itemIcon.texture;
e.Q<Label>("Name").text = itemList[i] == null ? "NO ITEM" : itemList[i].itemName;
}
};
itemListView.fixedItemHeight = 50; //根据需要高度调整数值
itemListView.itemsSource = itemList;
itemListView.makeItem = makeItem;
itemListView.bindItem = bindItem;
itemListView.onSelectionChange += OnListSelectionChange;
//右侧信息面板不可见
itemDetailsSection.visible = false;
}
private void OnListSelectionChange(IEnumerable<object> selectedItem)
{
activeItem = (ItemDetails)selectedItem.First();
GetItemDetails();
itemDetailsSection.visible = true;
}
private void GetItemDetails()
{
itemDetailsSection.MarkDirtyRepaint();
itemDetailsSection.Q<IntegerField>("ItemID").value = activeItem.itemID;
itemDetailsSection.Q<IntegerField>("ItemID").RegisterValueChangedCallback(evt =>
{
activeItem.itemID = evt.newValue;
});
itemDetailsSection.Q<TextField>("ItemName").value = activeItem.itemName;
itemDetailsSection.Q<TextField>("ItemName").RegisterValueChangedCallback(evt =>
{
activeItem.itemName = evt.newValue;
itemListView.Rebuild();
});
iconPreview.style.backgroundImage = activeItem.itemIcon == null ? defaultIcon.texture : activeItem.itemIcon.texture;
itemDetailsSection.Q<ObjectField>("ItemIcon").value = activeItem.itemIcon;
itemDetailsSection.Q<ObjectField>("ItemIcon").RegisterValueChangedCallback(evt =>
{
Sprite newIcon = evt.newValue as Sprite;
activeItem.itemIcon = newIcon;
iconPreview.style.backgroundImage = newIcon == null ? defaultIcon.texture : newIcon.texture;
itemListView.Rebuild();
});
//其他所有变量的绑定
itemDetailsSection.Q<ObjectField>("ItemSprite").value = activeItem.itemOnWorldSprite;
itemDetailsSection.Q<ObjectField>("ItemSprite").RegisterValueChangedCallback(evt =>
{
activeItem.itemOnWorldSprite = (Sprite)evt.newValue;
});
itemDetailsSection.Q<EnumField>("ItemType").Init(activeItem.itemType);
itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>
{
activeItem.itemType = (ItemType)evt.newValue;
});
itemDetailsSection.Q<TextField>("Description").value = activeItem.itemDescription;
itemDetailsSection.Q<TextField>("Description").RegisterValueChangedCallback(evt =>
{
activeItem.itemDescription = evt.newValue;
});
itemDetailsSection.Q<IntegerField>("ItemUseRadius").value = activeItem.itemUseRadius;
itemDetailsSection.Q<IntegerField>("ItemUseRadius").RegisterValueChangedCallback(evt =>
{
activeItem.itemUseRadius = evt.newValue;
});
itemDetailsSection.Q<Toggle>("CanPickedup").value = activeItem.canPickedup;
itemDetailsSection.Q<Toggle>("CanPickedup").RegisterValueChangedCallback(evt =>
{
activeItem.canPickedup = evt.newValue;
});
itemDetailsSection.Q<Toggle>("CanDropped").value = activeItem.canDropped;
itemDetailsSection.Q<Toggle>("CanDropped").RegisterValueChangedCallback(evt =>
{
activeItem.canDropped = evt.newValue;
});
itemDetailsSection.Q<Toggle>("CanCarried").value = activeItem.canCarried;
itemDetailsSection.Q<Toggle>("CanCarried").RegisterValueChangedCallback(evt =>
{
activeItem.canCarried = evt.newValue;
});
itemDetailsSection.Q<IntegerField>("Price").value = activeItem.itemPrice;
itemDetailsSection.Q<IntegerField>("Price").RegisterValueChangedCallback(evt =>
{
activeItem.itemPrice = evt.newValue;
});
itemDetailsSection.Q<Slider>("SellPercentage").value = activeItem.sellPercentage;
itemDetailsSection.Q<Slider>("SellPercentage").RegisterValueChangedCallback(evt =>
{
activeItem.sellPercentage = evt.newValue;
});
}
}