using UnityEngine; using System.Collections.Generic; using UnityEngine.UI; using DevelopEngine; using AX.MessageSystem; using System; using System.IO; using System.Collections; using UnityEngine.EventSystems; //using UIManage; /// /// 树形菜单控制器 /// public class TreeViewControl__ : SingletonMono, IPointerEnterHandler { /// /// 当前树形菜单的数据源 /// [HideInInspector] public List Data = null; /// /// 树形菜单中元素的模板 /// public GameObject Template; /// /// 树形菜单中元素的根物体 /// public Transform TreeItems; /// /// 树形菜单的纵向排列间距 /// public int VerticalItemSpace = 2; /// /// 树形菜单的横向排列间距 /// public int HorizontalItemSpace = 25; /// /// 树形菜单中元素的宽度 /// public int ItemWidth = 230; /// /// 树形菜单中元素的高度 /// public int ItemHeight = 35; /// /// 所有子元素的鼠标点击回调事件 /// public delegate void ClickItemdelegate(GameObject item); public event ClickItemdelegate ClickItemEvent; //当前树形菜单中的所有元素 public List _treeViewItems; //当前树形菜单中的所有元素克隆体(刷新树形菜单时用于过滤计算) private List _treeViewItemsClone; //树形菜单当前刷新队列的元素位置索引 private int _yIndex = 0; //树形菜单当前刷新队列的元素最大层级 private int _hierarchy = 0; /// /// 标志图层数据是否被编辑过的标志位 /// public bool HasEditFlag = false; public bool ViewButtonHoverTipFlag = false; private GameObject TipText; Canvas canvas; GameObject objTemp; RectTransform rectContent; private GameObject btns; void Awake() { ClickItemEvent += ClickItemTemplate; TipText = transform.Find("TipText").gameObject; //TransformHelper.FindChild(transform, "Viewport").gameObject.AddComponent(); //TransformHelper.FindChild(transform, "Content").gameObject.AddComponent(); } void Start() { GetLayersData(); GenerateTreeView(); ChangeChildren(false); RefreshTreeView(); rectContent = TransformHelper.FindChild(transform,"Content").GetComponent(); rectTree = GetComponent(); rect = new Rect(0, -rectTree.sizeDelta.y, rectTree.sizeDelta.x, rectTree.sizeDelta.y); canvas = GameObject.Find("Canvas").GetComponent(); ItemTipText = TransformHelper.FindChild(transform, "ItemTipText").GetComponent(); width = GetComponent().sizeDelta.x; } Vector2 mosPos; Vector2 mosPos_tree; Vector2 itemPos; RectTransform tvi; private Text ItemTipText; private bool InRectFlag = false; private GameObject hoverItem; private bool hasHoverItemFlag = false; private float width; private RectTransform rectTree; private Rect rect; void Update() { if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTree, Input.mousePosition, canvas.worldCamera, out mosPos_tree)) { if (hoverItem) { btns = TransformHelper.FindChild(hoverItem.transform, "btns").gameObject; btns.SetActive(false); } ItemTipText.gameObject.SetActive(false); hasHoverItemFlag = false; if (!rect.Contains(mosPos_tree)) { return; } } if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectContent, Input.mousePosition, canvas.worldCamera, out mosPos)) { //Debug.Log("mosPos" + mosPos); if (mosPos.x >= 0 && mosPos.x <= width) { foreach (var item in _treeViewItems) { itemPos = item.GetComponent().anchoredPosition; if (item.activeSelf && mosPos.y >= itemPos.y - 22 && mosPos.y <= itemPos.y - 6)//鼠标在item范围内 { hoverItem = item; hasHoverItemFlag = true; //Debug.Log("*****************************************************in:" + hoverItem.transform.Find("TreeViewText").GetComponent().text); break; } } if (hasHoverItemFlag) { btns = TransformHelper.FindChild(hoverItem.transform, "btns").gameObject; btns.SetActive(true); ItemTipText.text = hoverItem.transform.Find("TreeViewText").GetComponent().text; ItemTipText.GetComponent().anchoredPosition = new Vector2(0, mosPos_tree.y + 106); ItemTipText.gameObject.SetActive(true); } } } } void ChangeChildren(bool value) { //复制一份菜单 _treeViewItemsClone = new List(_treeViewItems); //用复制的菜单进行刷新计算 for (int i = 0; i < _treeViewItemsClone.Count; i++) { TreeViewItem__ tvi = _treeViewItemsClone[i].GetComponent(); if (tvi.GetHierarchy() >= 1) { //ChangeChildren(tvi, value); tvi.IsExpanding = false; tvi.gameObject.SetActive(value); tvi.transform.Find("ContextButton").GetComponent().localRotation = Quaternion.Euler(0, 0, 89.99f); } else { tvi.IsExpanding = false; tvi.transform.Find("ContextButton").GetComponent().localRotation = Quaternion.Euler(0, 0, 89.99f); } } } void ChangeChildren(TreeViewItem__ tvi, bool value) { tvi.IsExpanding = value; for (int i = 0; i < tvi.GetChildrenNumber(); i++) { tvi.GetChildrenByIndex(i).gameObject.SetActive(value); ChangeChildren(tvi.GetChildrenByIndex(i), value); } } public void SetAllToggleFalse(int id) { foreach(Transform child in TreeItems) { if (child.Find("TreeViewToggle").GetComponent().isOn && child.GetComponent().ID != id) { child.Find("TreeViewToggle").GetComponent().isOn = false; } } } public void SetToggleTrue(int id) { foreach (Transform child in TreeItems) { child.Find("TreeViewToggle").GetComponent().isOn = false; if (child.GetComponent().ID == id) { child.Find("TreeViewToggle").GetComponent().isOn = true; } } } public GameObject GetToggleGame() { foreach (Transform child in TreeItems) { if (child.GetComponent().ID == TempDataManager.Instance.CurNodeID) { return child.gameObject; } } return null; } public bool CheckFileTreeItems() { foreach (Transform child in TreeItems) { if (child.GetComponent().ID == TempDataManager.Instance.CurNodeID) { var data = child.GetComponent().Name; var filepath = ExamInfoHelpClass.CurrentWorkPath + data + ".xml"; if (File.Exists(filepath)) //判断有没有对应的xml文件,设置字体大小是否自适应最佳 { return true; } else { return false; } } } return false; } public void ShowTip(bool flag) { TipText.SetActive(flag); } void test( ref List datas) { TreeViewData data = new TreeViewData(); data.ID = 0; data.Name = "第一章"; data.ParentID = -1; data.Hierarchy = 0; datas.Add(data); data = new TreeViewData(); data.ID = 1; data.Hierarchy = 1; data.Name = "1.第一节"; data.ParentID = 0; datas.Add(data); data = new TreeViewData(); data.ID = 2; data.Hierarchy = 1; data.Name = "1.第二节"; data.ParentID = 0; datas.Add(data); data = new TreeViewData(); data.ID = 3; data.Hierarchy = 2; data.Name = "1.1.第一课"; data.ParentID = 1; datas.Add(data); data = new TreeViewData(); data.ID = 4; data.Hierarchy = 2; data.Name = "1.2.第一课"; data.ParentID = 1; datas.Add(data); data = new TreeViewData(); data.ID = 5; data.Hierarchy = 2; data.Name = "1.2.第一课"; data.ParentID = 2; datas.Add(data); data = new TreeViewData(); data.ID = 6; data.Hierarchy = 2; data.Name = "1.2.第一课"; data.ParentID = 2; datas.Add(data); } void GetLayersData() { //生成数据 List datas = new List(); //var dataList = DAO.GetAllInfos(GlobalHelpClass.fixedLayersTableName); //dataList.ForEach(d => { datas.Add(d); }); //指定数据源 //test(ref datas); NodeSet.Instance.GetAllDates(ref datas); Debug.Log(datas.Equals(Data)); Data = datas; //GetLayersHierarchy(); } public Dictionary>> GetLayersHierarchy() { Dictionary>> layersDic = new Dictionary>>(); foreach(var data in Data) { if (data.Hierarchy == 0)//1级结构 { if (!layersDic.ContainsKey(data)) { layersDic.Add(data, new Dictionary>()); } } else if(data.Hierarchy == 1)//2级结构,父级结构已经都有了 { //首先根据parentID找到父层级data TreeViewData key_data = data; foreach(var key in layersDic.Keys) { if (key.ID == data.ParentID) { key_data = key; } } if (!layersDic[key_data].ContainsKey(data)) { layersDic[key_data].Add(data, new List()); } } else if(data.Hierarchy == 2)//3级结构 { TreeViewData key_data_1 = data;//找到1级结构 TreeViewData key_data_2 = data;//找到2级结构 foreach(var key_1 in layersDic.Keys) { foreach(var key_2 in layersDic[key_1].Keys) { if (key_2.ID == data.ParentID) { key_data_1 = key_1; key_data_2 = key_2; } } } if (!layersDic[key_data_1][key_data_2].Contains(data)) { layersDic[key_data_1][key_data_2].Add(data); } } } return layersDic; } public void RemoveItem(int id) { for (int i = Data.Count - 1; i >= 0; i--) { if (Data[i].ID == id) { Data.Remove(Data[i]); return; } } } /// /// 生成一个新的ID,目前默认取最后一个元素的ID+1,暂时没有考虑删除中间元素后所有ID重新赋值排序 /// /// 返回新元素的ID public int GetNewID() { int id = 0; id = Data[Data.Count - 1].ID + 1; return id; } /// /// 鼠标点击子元素事件 /// public void ClickItemAdd(GameObject item) { ClickItemEvent(item); } void ClickItemTemplate(GameObject item) { //空的事件,不这样做的话ClickItemEvent会引发空引用异常 } public int GetFirstlayerIdByCurItemID(int curId) { var data = Data.Find(d => { return (d.ID == curId); }); var parentID = data.ParentID; if (parentID == -1) { return curId; } else { return GetFirstlayerIdByCurItemID(parentID); } } public int GetSecondlayerIdByCurItemID(int curId) { var data = Data.Find(d => { return (d.ID == curId); }); var Hierarchy = data.Hierarchy; if (Hierarchy <= 1) { return curId; } else//如果Hierarchy不为1,则所选物体处于三级菜单,此时返回其父物体二级菜单的ID { return (data.ParentID); } } /// /// 返回指定名称的子元素是否被勾选 /// public bool ItemIsCheck(string itemName) { for (int i = 0; i < _treeViewItems.Count; i++) { if (_treeViewItems[i].transform.Find("TreeViewText").GetComponent().text == itemName) { return _treeViewItems[i].transform.Find("TreeViewToggle").GetComponent().isOn; } } return false; } /// /// 返回树形菜单中被勾选的所有子元素名称 /// public List ItemsIsCheck() { List items = new List(); for (int i = 0; i < _treeViewItems.Count; i++) { if (_treeViewItems[i].transform.Find("TreeViewToggle").GetComponent().isOn) { items.Add(_treeViewItems[i].transform.Find("TreeViewText").GetComponent().text); } } return items; } /// /// 生成树形菜单 /// public void GenerateTreeView() { //删除可能已经存在的树形菜单元素 if (_treeViewItems != null) { for (int i = 0; i < _treeViewItems.Count; i++) { Destroy(_treeViewItems[i]); } _treeViewItems.Clear(); } //重新创建树形菜单元素 _treeViewItems = new List(); for (int i = 0; i < Data.Count; i++) { InstanATreeViewItem(Data[i]); } //SetTreeViewItemToggle();//筛选toggle是否开启 } public GameObject InstanATreeViewItem(TreeViewData data, int index = -1, bool Flag = false) { if ((data.Name.Contains("设施信息aaaaaaaaaaaa") && data.Hierarchy == 1)) return null; GameObject item = Instantiate(Template); item.GetComponent().SetID(data); if (data.ParentID == -1) { item.GetComponent().SetHierarchy(0); item.GetComponent().SetParent(null); } else { //TreeViewItem tvi = _treeViewItems[data.ParentID].GetComponent(); TreeViewItem__ tvi = GetTreeViewItemByID(data.ParentID); item.GetComponent().SetHierarchy(tvi.GetHierarchy() + 1); item.GetComponent().SetParent(tvi); if (Flag) { tvi.InsertChildren(item.GetComponent(), index); } else { tvi.AddChildren(item.GetComponent()); } } item.transform.name = "TreeViewItem"; var textCompent = item.transform.Find("TreeViewText").GetComponent(); if (data.Name.Contains("-")) { string[] str = data.Name.Split('-'); textCompent.text = str[str.Length - 1]; } else { textCompent.text = data.Name; } var filepath = ExamInfoHelpClass.CurrentWorkPath + data.Name + ".xml"; if (File.Exists(filepath)) //判断有没有对应的xml文件,设置字体大小是否自适应最佳 { //textCompent.resizeTextForBestFit = false; } else { //textCompent.resizeTextForBestFit = true; } item.GetComponent().SetView(data.View); item.transform.SetParent(TreeItems); item.transform.localPosition = Vector3.zero; item.transform.localScale = Vector3.one; item.transform.localRotation = Quaternion.Euler(Vector3.zero); item.SetActive(true); _treeViewItems.Add(item); return item; } /// /// 开启/关闭可见属性时,维护Data数组 /// /// public void SetViewOfData(int id, bool flag) { var data = Data.Find(d => { return d.ID == id; }); data.View = flag; } /// /// 设置属性元素的toggle是否可用 /// 原则:元素存在子物体即隐藏toggle /// private void SetTreeViewItemToggle() { foreach (var item in _treeViewItems) { if (item.GetComponent().GetChildrenNumber() > 0) { item.transform.Find("TreeViewToggle").gameObject.SetActive(false); } else { item.transform.Find("TreeViewToggle").gameObject.SetActive(true); } } } private TreeViewItem__ GetTreeViewItemByID(int id) { foreach(var item in _treeViewItems) { if (item.GetComponent().ID == id) { return item.GetComponent(); } } return null; } /// /// 获取当前是否有图层被选中 /// /// public int HasItemSelected() { foreach (Transform item in TreeItems) if (item.GetComponentInChildren() && item.GetComponentInChildren().isOn) return item.GetComponent().ID; return -1; } /// /// 刷新树形菜单 /// public void RefreshTreeView() { _yIndex = 0; _hierarchy = 0; //复制一份菜单 _treeViewItemsClone = new List(_treeViewItems); //用复制的菜单进行刷新计算 for (int i = 0; i < _treeViewItemsClone.Count; i++) { //已经计算过或者不需要计算位置的元素 if (_treeViewItemsClone[i] == null || !_treeViewItemsClone[i].activeSelf) { continue; } TreeViewItem__ tvi = _treeViewItemsClone[i].GetComponent(); _treeViewItemsClone[i].GetComponent().anchoredPosition = new Vector3(tvi.GetHierarchy() * HorizontalItemSpace, _yIndex,0); _yIndex += (-(ItemHeight + VerticalItemSpace)); if (tvi.GetHierarchy() > _hierarchy) { _hierarchy = tvi.GetHierarchy(); } if (tvi.IsExpanding) { RefreshTreeViewChild(tvi); } _treeViewItemsClone[i] = null; } //重新计算滚动视野的区域 float x = _hierarchy * HorizontalItemSpace + ItemWidth; float y = Mathf.Abs(_yIndex) + ItemHeight / 2; transform.GetComponent().content.sizeDelta = new Vector2(x, y); //清空复制的菜单 _treeViewItemsClone.Clear(); } /// /// 根据名字找到对应的层级 /// public bool GetHierarchy_Name(int Hierarchy,string Name) { foreach (Transform item in TreeItems) { if (item.GetComponent().GetHierarchy()==Hierarchy && item.GetComponent().Name.Equals(Name)) { return true; } if (Hierarchy == 0 && item.GetComponent().Name.Equals(Name)) { return true; } } return false; } public void AddNode(string nodeName) { foreach (Transform item in TreeItems) { if (item.GetComponentInChildren() && item.GetComponentInChildren().isOn) { var treeViewItem = item.GetComponent(); var count = treeViewItem.GetChildrenNumber(); var filepath = ExamInfoHelpClass.CurrentWorkPath + treeViewItem.Name + ".xml"; if (!File.Exists(filepath) && treeViewItem.GetHierarchy() < treeViewItem.maxHierarchy - 1)//新建节点添加到该层级下,Add即可 { var pid = treeViewItem.ID; TreeViewData data = new TreeViewData(); data.Name = nodeName; //data.ID = GetComponent().Controler.GetNewID(); data.ID = NodeSet.Instance.GetNextID(); data.ParentID = pid; data.Hierarchy = treeViewItem.GetHierarchy() + 1; Data.Add(data); var treeViewItemObj = InstanATreeViewItem(data); treeViewItemObj.SetActive(treeViewItem.IsExpanding); //GenerateTreeView(); RefreshTreeView(); HasEditFlag = true; NodeSet.Instance.ADDXml(nodeName, data); //MessageDispatcher.SendMessage("AddNode", data); } else//新建节点添加到该节点后边,需要Insert { //if(!File.Exists(filepath) && treeViewItem.GetHierarchy() < treeViewItem.maxHierarchy - 1) //{ // var pid1 = treeViewItem.ID; // TreeViewData data1 = new TreeViewData(); // data1.Name = nodeName; // //data.ID = GetComponent().Controler.GetNewID(); // data1.ID = NodeSet.Instance.GetNextID(); // data1.ParentID = pid1; // data1.Hierarchy = treeViewItem.GetHierarchy() + 1; // Data.Add(data1); // GenerateTreeView(); // RefreshTreeView(); // HasEditFlag = true; // NodeSet.Instance.ADDXml(nodeName, data1); // //MessageDispatcher.SendMessage("AddNode", data); // return; //} var pid = treeViewItem.parentID; TreeViewData data = new TreeViewData(); data.Name = nodeName; //data.ID = GetComponent().Controler.GetNewID(); data.ID = NodeSet.Instance.GetNextID(); data.ParentID = pid; data.Hierarchy = treeViewItem.GetHierarchy(); var childList = treeViewItem.GetParent().GetChildrenList(); //Data.Add(data); var index = Data.FindIndex(d => { return d.ID == treeViewItem.ID; }); Data.Insert(index + 1, data);//插入在该节点后边 int index_item = childList.FindIndex(t => { return t.ID == treeViewItem.ID; }); InstanATreeViewItem(data, index_item + 1, true); //GenerateTreeView(); RefreshTreeView(); HasEditFlag = true; NodeSet.Instance.InsertXml(treeViewItem.ID.ToString(), data); } } } } /// /// 刷新元素的所有子元素 /// void RefreshTreeViewChild(TreeViewItem__ tvi) { for (int i = 0; i < tvi.GetChildrenNumber(); i++) { tvi.GetChildrenByIndex(i).gameObject.GetComponent().anchoredPosition = new Vector3(tvi.GetChildrenByIndex(i).GetHierarchy() * HorizontalItemSpace, _yIndex, 0); _yIndex += (-(ItemHeight + VerticalItemSpace)); if (tvi.GetChildrenByIndex(i).GetHierarchy() > _hierarchy) { _hierarchy = tvi.GetChildrenByIndex(i).GetHierarchy(); } if (tvi.GetChildrenByIndex(i).IsExpanding) { RefreshTreeViewChild(tvi.GetChildrenByIndex(i)); } int index = _treeViewItemsClone.IndexOf(tvi.GetChildrenByIndex(i).gameObject); if (index >= 0) { _treeViewItemsClone[index] = null; } } } /// /// 拖拽一个树形结构到指定位置 /// /// 新生成的(用于拖拽) /// 原来的(会被删除) public void DragTreeViewItem(TreeViewItem__ newViewItem, TreeViewItem__ oldViewItem) { if (oldViewItem.GetParent() == null||oldViewItem.GetParent().GetChildrenNumber()<=1) {//只有一个孩子就不拖拽了 Destroy(newViewItem.gameObject); // RefreshTreeView(); return; } //将原来属性结构上的各类值拷贝到新生成的树形结构上 newViewItem.name = oldViewItem.name; newViewItem.SetHierarchy(oldViewItem.GetHierarchy()); newViewItem.SetID(oldViewItem); newViewItem.SetParent(oldViewItem.GetParent()); newViewItem.SetChildrenList(oldViewItem.GetChildrenList()); //父物体的链表中,删除老的元素,在对应位置插入拖拽的元素 oldViewItem.GetParent().RemoveChildren(oldViewItem); int num = GetInsItemNum(newViewItem); newViewItem.GetParent().InsertChildren(newViewItem, num); //修改XML中的顺序 //TreeViewItem__ s = newViewItem.GetParent().GetChildrenByIndex(num + 1); if (newViewItem.GetParent().GetChildrenByIndex(num + 1) != null) { NodeSet.Instance.TranslocationXML(newViewItem.ID.ToString(), newViewItem.GetParent().GetChildrenByIndex(num + 1).ID.ToString(), false); } else if (newViewItem.GetParent().GetChildrenByIndex(num - 1) != null) { NodeSet.Instance.TranslocationXML(newViewItem.ID.ToString(), newViewItem.GetParent().GetChildrenByIndex(num - 1).ID.ToString(), true); } else { Destroy(newViewItem); RefreshTreeView(); return; } _treeViewItems.Remove(oldViewItem.gameObject); _treeViewItems.Add(newViewItem.gameObject); Destroy(oldViewItem.gameObject); StartCoroutine(DelaySet(num, newViewItem)); } IEnumerator DelaySet(int num, TreeViewItem__ newViewItem) { yield return new WaitForEndOfFrame(); //重新刷新树形结构 RefreshTreeView(); } /// /// 拖拽时,获取拖拽的元素将要被插入链表的哪个位置 /// /// /// private int GetInsItemNum(TreeViewItem__ newViewItem) { float fNewItem = newViewItem.transform.localPosition.y; TreeViewItem__[] itemArray= newViewItem.GetParent().GetChildrenList().ToArray();//获取子物体 for (int i = 0; i < itemArray.Length; i++) { if (i == 0&& fNewItem >itemArray[0].transform.localPosition.y) { return 0; } else if (i == itemArray.Length - 1 ) { if (fNewItem < itemArray[i].transform.localPosition.y) { return i+1; } } else { if (fNewItemitemArray[i+1].transform.localPosition.y) { return i+1; } } } return -1; } public void OnPointerEnter(PointerEventData eventData) { var items = _treeViewItems; foreach (var item in items) { TransformHelper.FindChild(item.transform, "btns").gameObject.SetActive(false); } } }