一、脚本编程
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System;
using System.Linq;
public class ItemEditor : EditorWindow
{
private ItemDataList_SO dataBase;
private List<ItemDetails> itemList = new List<ItemDetails>();
//
private VisualTreeAsset itemRowTemplate;
private ListView itemlistView;
private ItemDetails activeItem;
private ScrollView itemDetailsSection;
//默认浏览图片
private Sprite defultIcon;
private VisualElement iconPreview;
[MenuItem("Lzj/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;
// 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/ItemRowTemplates.uxml");
//拿到默认Icon图片
defultIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/M Studio/Art/Items/Icons/Lzj.jpg");
//变量赋值,获得控制权
itemlistView = root.Q<VisualElement>("ItemList").Q<ListView>("ListView");
itemDetailsSection = root.Q <ScrollView>("ItemDetails");
iconPreview = itemDetailsSection.Q<VisualElement>("Icon");
//加载数据
LoadDataBase();
//生成ListView
GenerateListView();
}
private void LoadDataBase()
{
var dataArray = AssetDatabase.FindAssets("ItemDataList_SO");
if (dataArray.Length > 1)
{
var path=AssetDatabase.GUIDToAssetPath(dataArray[0]);
dataBase = AssetDatabase.LoadAssetAtPath(path, typeof(ItemDataList_SO)) as ItemDataList_SO ;
}
itemList = dataBase.itemDataList;
EditorUtility.SetDirty(dataBase);
}
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 += OnListSelectionChane;
//右侧信息不可见
itemDetailsSection.visible= false;
}
private void OnListSelectionChane(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();
});
itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>
{
activeItem.itemType = (ItemType)Enum.Parse(typeof(ItemType), evt.newValue.ToString());
});
iconPreview.style.backgroundImage = activeItem.itemIcon == null ? defultIcon.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 ?defultIcon.texture: newIcon.texture;
itemlistView.Rebuild();
});
itemDetailsSection.Q<ObjectField>("ItemSprite").value = activeItem.itemOnWorldSprite;
itemDetailsSection.Q<ObjectField>("ItemSprite").RegisterValueChangedCallback(evt =>
{
Sprite newIcon = evt.newValue as Sprite;
activeItem.itemOnWorldSprite = newIcon;
});
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>("CanPickup").value = activeItem.canPickup;
itemDetailsSection.Q<Toggle>("CanPickup").RegisterValueChangedCallback(evt=>
{
activeItem.canPickup=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;
});
}
}
二、初步了解脚本编程和API接口
1、声明变量,规划控制权
private ItemDetails activeItem;
private ScrollView itemDetailsSection;
//默认浏览图片
private Sprite defultIcon;
private VisualElement iconPreview;
//获得Visual Element
ScrollView 是一种 C# 中的数据类型,表示一个可滚动的视图控件。它通常用于显示大量数据或需要滚动查看的内容,比如长文字、图片列表等。在 Xamarin.Forms 开发中,ScrollView 也被广泛应用于移动应用程序的开发。
ScrollView 提供了一种简单的方式来扩展内容区域,当内容超出 ScrollView 的边界时,用户可以使用滚动条或手势来滑动视图以查看更多内容。ScrollView 还支持滚动到指定位置、支持滚动事件等特性。
在 C# 中,我们可以通过在代码中创建 ScrollView 实例,并设置其中的一些属性和事件来自定义它的行为和外观。比如,下面的示例演示了如何创建一个包含多个 Label 控件的 ScrollView 对象:
函数赋值方式为:
2、赋予控制权
//拿到默认Icon图片
defultIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/M Studio/Art/Items/Icons/Lzj.jpg");
//变量赋值,获得控制权
itemDetailsSection = root.Q <ScrollView>("ItemDetails");
iconPreview = itemDetailsSection.Q<VisualElement>("Icon");
3、
itemlistView.onSelectionChange += OnListSelectionChane;
//右侧信息不可见
itemDetailsSection.visible= false;
itemlistView表示一个 Unity 引擎中的 ScrollView 控件实例,通常用于在界面上显示一个滚动区域。.onSelectionChange是 ScrollView 的事件之一,可用于监听 ScrollView 中选中项的变化。+=表示添加事件处理函数,即将OnListSelectionChane方法添加到.onSelectionChange事件上,以便在 ScrollView 中选中项发生变化时调用该方法。OnListSelectionChane是一个方法名,表示当 ScrollView 中选中项发生变化时要执行的回调方法,具体内容需要根据实际需求来编写。itemDetailsSection表示一个 UIElements 中的 VisualElement 实例,通常用于在界面上显示一些信息或控件。.visible是 VisualElement 实例的属性之一,用于设置该元素是否可见。当该属性设置为false时,表示该元素在 UI 界面上不可见,即不会被渲染出来。
综上,这段代码的作用是:将 OnListSelectionChane 方法添加到 ScrollView 中选中项发生变化的事件处理函数中,并设置 itemDetailsSection 不可见。该代码片段通常用于初始化代码中,其目的是在 UI 界面上首次加载时隐藏 itemDetailsSection 区域,等用户从 ScrollView 选择一项后再根据选中项显示相应的详细信息。
4、
private void OnListSelectionChane(IEnumerable<object> selectedItem)
{
activeItem=(ItemDetails)selectedItem.First();
GetItemDetails();
itemDetailsSection.visible = true;
}
三、未完问题待续(不知道有没有掘友知道其他解决方法)
1、不知道为什么枚举变量调用无法实现
itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>
{
activeItem.itemType = (ItemType)Enum.Parse(typeof(ItemType), evt.newValue.ToString());
});
2、枚举变量同步数据问题终于解决了:
itemDetailsSection.Q<EnumField>("ItemType").Init(activeItem.itemType);
itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
var 容器 = itemDetailsSection.Q<EnumField>("ItemType").value;
itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>
{
activeItem.itemType = (ItemType)Enum.Parse(typeof(ItemType), evt.newValue.ToString());
});
阅读更多作者文章:
# Unity3D 游戏开发:用户界面(Editor)使用Unity Editor和ListView生成自定义物品管理界面(15)