2026-03-24 11:39:01 +08:00

452 lines
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace SuperTreeView
{
public class DemoScene2Script : MonoBehaviour
{
public TreeView mTreeView;
int mCurSelectedItemId = 0;
int mNewItemCount = 0;
void Start()
{
SpriteResMgr rm = SpriteResMgr.Instance;
mTreeView.OnTreeListAddOneItem = OnTreeListAddOneItem;
//mTreeView.OnTreeListDeleteOneItem = OnTreeListDeleteOneItem;
mTreeView.OnItemExpandBegin = OnItemExpandBegin;
mTreeView.OnItemCollapseBegin = OnItemCollapseBegin;
mTreeView.OnItemCustomEvent = OnItemCustomEvent;
mTreeView.OnTreeListRepositionFinish = OnTreeListRepositionFinish;
mTreeView.InitView();
BuildTreeAutomatically();
}
void BuildTreeAutomatically()
{
var datas = new List<string[]>
{
// --- 胸部体表标志 ---
new[] { "胸部体表标志", "胸骨柄", "XiongGuBing" },
new[] { "胸部体表标志", "胸骨上切迹", "XiongGuShangQieJi" },
new[] { "胸部体表标志", "胸骨角", "XiongGuJiao" },
new[] { "胸部体表标志", "剑突", "JianTu" },
new[] { "胸部体表标志", "1-7肋骨", "LeiGu1-7" },
new[] { "胸部体表标志", "11-12肋骨", "LeiGu11-12" },
new[] { "胸部体表标志", "肋间隙", "LeiJianXi" },
new[] { "胸部体表标志", "肩胛骨", "JianJiaGu" },
new[] { "胸部体表标志", "肩胛下角", "JianJiaXiaJiao" },
// --- 垂直线标志 ---
new[] { "垂直线标志", "前正中线", "QianZhengZhongXian" },
new[] { "垂直线标志", "(左、右)锁骨中线", "SuoGuZhongXian" },
new[] { "垂直线标志", "(左、右)胸骨线", "XiongGuXian" },
new[] { "垂直线标志", "(左、右)胸骨旁线", "XiongGuPangXian" },
new[] { "垂直线标志", "(左、右)腋前线", "YeQianXian" },
new[] { "垂直线标志", "(左、右)腋后线", "YeHouXian" },
new[] { "垂直线标志", "(左、右)腋中线", "YeZhongXian" },
new[] { "垂直线标志", "(左、右)肩胛线", "JianJiaXian" },
new[] { "垂直线标志", "后正中线", "HouZhengZhongXian" },
// --- 解剖区域 ---
new[] { "解剖区域", "(左、右)肩胛上区", "JianJiaShangQu" },
new[] { "解剖区域", "(左、右)肩胛下区", "JianJiaXiaQu" },
new[] { "解剖区域", "(左、右)肩胛间区", "JianJiaQuJian" },
// --- 动画 ---
new[] { "肺功能动画", "FeiGongNengDongHua" },
new[] { "心功能动画", "XinGongNengDongHua" },
// --- 肺部听诊 ---
new[] { "肺部听诊", "正常呼吸音", "气管呼吸音", "QiGuanHuXiYin" },
new[] { "肺部听诊", "正常呼吸音", "支气管呼吸音", "ZhiQiGuanHuXiYin" },
new[] { "肺部听诊", "正常呼吸音", "支气管肺泡呼吸音", "ZhiQiGuanFeiPaoHuXiYin" },
new[] { "肺部听诊", "正常呼吸音", "肺泡呼吸音", "FeiPaoHuXiYin" },
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "肺泡呼吸音减弱或消失", "FeiPaoHuXiYinJianRuoHuoXiaoShi" },
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "肺泡呼吸音增强", "FeiPaoHuXiYinZengQiang" },
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "呼吸音延长", "HuXiYinYanChang" },
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "断续性呼吸音", "DuanXuXingHuXiYin" },
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "粗糙性呼吸音", "CuCaoXingHuXiYin" },
new[] { "肺部听诊", "异常呼吸音", "异常支气管呼吸音", "YiChangZhiQiGuanHuXiYin" },
new[] { "肺部听诊", "异常呼吸音", "异常支气管肺泡呼吸音", "YiChangZhiQiGuanFeiPaoHuXiYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "粗湿啰音(大水泡音)", "CuShiLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "中湿啰音(中水泡音)", "ZhongShiLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "细湿啰音(小水泡音)", "XiShiLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "Velcro啰音", "VelcroLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "捻发音", "NianFaYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "高调干啰音(哨笛音)", "GaoDiaoGanLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "啰音", "低调干啰音(鼾音)", "DiDiaoGanLuoYin" },
new[] { "肺部听诊", "异常呼吸音", "胸膜摩擦音", "XiongMoMoCaYin" },
// --- 心脏听诊 ---
new[] { "心脏听诊", "心脏瓣膜听诊区", "二尖瓣区(心尖区)", "ErJianBanQu" },
new[] { "心脏听诊", "心脏瓣膜听诊区", "肺动脉瓣区", "FeiDongMaiBanQu" },
new[] { "心脏听诊", "心脏瓣膜听诊区", "主动脉瓣区", "ZhuDongMaiBanQu" },
new[] { "心脏听诊", "心脏瓣膜听诊区", "主动脉瓣第二听诊区", "ZhuDongMaiBanDiErTingZhenQu" },
new[] { "心脏听诊", "心脏瓣膜听诊区", "三尖瓣区", "SanJianBanQu" },
new[] { "心脏听诊", "心率", "XinLv" },
new[] { "心脏听诊", "心音", "第一心音", "DiYiXinYin" },
new[] { "心脏听诊", "心音", "第二心音", "DiErXinYin" },
new[] { "心脏听诊", "心音", "第三心音", "DiSanXinYin" },
new[] { "心脏听诊", "心音", "第四心音", "DiSiXinYin" },
new[] { "心脏听诊", "心音", "第一心音增强", "DiYiXinYinZengQiang" },
new[] { "心脏听诊", "心音", "第一心音减弱", "DiYiXinYinJianRuo" },
new[] { "心脏听诊", "心音", "第一心音强弱不等", "DiYiXinYinQiangRuoBuDeng" },
new[] { "心脏听诊", "心音", "第二心音增强", "DiErXinYinZengQiang" },
new[] { "心脏听诊", "心音", "第二心音减弱", "DiErXinYinJianRuo" },
new[] { "心脏听诊", "心音", "第一心音分裂", "DiYiXinYinFenLie" },
new[] { "心脏听诊", "心音", "第二心音通常分裂", "DiErXinYinTongChangFenLie" },
new[] { "心脏听诊", "心音", "第二心音固定分裂", "DiErXinYinGuDingFenLie" },
new[] { "心脏听诊", "心音", "第二心音反常分裂", "DiErXinYinFanChangFenLie" },
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "舒张早期奔马律", "ShuZhangZaoQiBenMaLv" },
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "舒张晚期奔马律", "ShuZhangWanQiBenMaLv" },
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "开瓣音", "KaiBanYin" },
new[] { "心脏听诊", "额外心音", "收缩期额外心音", "收缩中、晚期喀喇音", "ShouSuoZhongWanQiKaLaYin" },
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "二尖瓣区", "ErJianBanQu2" },
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "主动脉瓣区", "ZhuDongMaiBanQu2" },
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "肺动脉瓣区", "FeiDongMaiBanQu2" },
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "三尖瓣区", "SanJianBanQu2" },
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "二尖瓣区", "ErJianBanQu3" },
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "主动脉瓣区", "ZhuDongMaiBanQu3" },
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "肺动脉瓣区", "FeiDongMaiBanQu3" },
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "三尖瓣区", "SanJianBanQu3" },
new[] { "心脏听诊", "心脏杂音", "连续性杂音", "LianXuXingZaYin" },
new[] { "心脏听诊", "心脏杂音", "心包摩擦音", "XinBaoMoCaYin" }
};
// 【修复点】创建一个虚拟的根节点对象,作为字典的 Key避免使用 null
TreeViewItem virtualRoot = new TreeViewItem();
// 缓存结构Key=父节点对象, Value=该父节点下的子节点字典 (名称->节点对象)
var nodeCache = new Dictionary<TreeViewItem, Dictionary<string, TreeViewItem>>();
// 初始化:将虚拟根节点的子节点字典放入缓存
nodeCache[virtualRoot] = new Dictionary<string, TreeViewItem>();
foreach (var row in datas)
{
if (row.Length == 0) continue;
// 初始父节点设为虚拟根节点
TreeViewItem currentParent = virtualRoot;
// 计算需要生成的节点数量 (总长度 - 1因为最后一个是数据 Payload)
int nodeCount = row.Length - 1;
for (int i = 0; i < nodeCount; i++)
{
string nodeName = row[i];
// 判断当前节点是否携带数据:只有当它是这一行的最后一个生成节点时,才携带数据
bool isLastNodeInRow = (i == nodeCount - 1);
string payload = isLastNodeInRow ? row[row.Length - 1] : null;
// 确保当前父节点在缓存中有对应的子节点字典
if (!nodeCache.ContainsKey(currentParent))
{
nodeCache[currentParent] = new Dictionary<string, TreeViewItem>();
}
var childrenMap = nodeCache[currentParent];
TreeViewItem newNode;
// 1. 检查是否已存在同名子节点
if (childrenMap.TryGetValue(nodeName, out newNode))
{
// 节点已存在,直接复用
}
else
{
// 2. 创建新节点
if (currentParent == virtualRoot)
{
// 如果是虚拟根的直连子节点,直接添加到 mTreeView
newNode = mTreeView.AppendItem("ItemPrefab1");
}
else
{
// 否则添加到父节点的 ChildTree
newNode = currentParent.ChildTree.AppendItem("ItemPrefab1");
}
// 3. 设置信息
var script = newNode.GetComponent<ItemScript2>();
if (script != null)
{
if (!string.IsNullOrEmpty(payload))
{
// 有数据SetItemInfo("", "名称", "数据")
script.SetItemInfo("", nodeName, payload);
}
else
{
// 无数据SetItemInfo("", "名称")
script.SetItemInfo("", nodeName);
}
}
// 4. 加入缓存,方便后续行复用
childrenMap[nodeName] = newNode;
// 为新节点初始化一个空的子节点字典(预防未来可能有更深层级)
nodeCache[newNode] = new Dictionary<string, TreeViewItem>();
}
// 5. 更新父节点,进入下一层循环
currentParent = newNode;
}
}
Debug.Log("TreeView 构建完成!共处理 " + datas.Count + " 条数据。");
}
void OnItemExpandBegin(TreeViewItem item)
{
ItemScript2 st = item.GetComponent<ItemScript2>();
st.SetExpandStatus(true);
}
void OnItemCollapseBegin(TreeViewItem item)
{
ItemScript2 st = item.GetComponent<ItemScript2>();
st.SetExpandStatus(false);
}
void OnItemCustomEvent(TreeViewItem item, CustomEvent customEvent, System.Object param)
{
if (customEvent == CustomEvent.ItemClicked)
{
ItemScript2 st = item.GetComponent<ItemScript2>();
if (mCurSelectedItemId > 0)
{
if (item.ItemId == mCurSelectedItemId)
{
return;
}
TreeViewItem curSelectedItem = mTreeView.GetTreeItemById(mCurSelectedItemId);
if (curSelectedItem != null)
{
curSelectedItem.GetComponent<ItemScript2>().IsSelected = false;
}
mCurSelectedItemId = 0;
}
st.IsSelected = true;
mCurSelectedItemId = item.ItemId;
Debug.Log((string)param);
}
}
void OnTreeListAddOneItem(TreeList treeList)
{
int count = treeList.ItemCount;
TreeViewItem parentTreeItem = treeList.ParentTreeItem;
if (count > 0 && parentTreeItem != null)
{
ItemScript2 st = parentTreeItem.GetComponent<ItemScript2>();
st.SetExpandBtnVisible(true);
st.SetExpandStatus(parentTreeItem.IsExpand);
}
}
TreeViewItem CurSelectedItem
{
get
{
if (mCurSelectedItemId <= 0)
{
return null;
}
TreeViewItem item = mTreeView.GetTreeItemById(mCurSelectedItemId);
if (item == null)
{
mCurSelectedItemId = 0;
return null;
}
return item;
}
}
public void OnExpandAllBtnClicked()
{
mTreeView.ExpandAllItem();
}
public void OnCollapseAllBtnClicked()
{
mTreeView.CollapseAllItem();
}
public void OnExpandBtnClicked()
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
item.Expand();
}
public void OnCollapseBtnClicked()
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
item.Collapse();
}
public void OnInsertBeforeBtnClicked()
{
mNewItemCount++;
if (mTreeView.IsEmpty)
{
TreeViewItem childItem = mTreeView.InsertItem(0, "ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
else
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
TreeViewItem childItem = item.ParentTreeList.InsertItem(item.ItemIndex, "ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
}
public void OnInsertAfterBtnClicked()
{
mNewItemCount++;
if (mTreeView.IsEmpty)
{
TreeViewItem childItem = mTreeView.InsertItem(0, "ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
else
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
TreeViewItem childItem = item.ParentTreeList.InsertItem(item.ItemIndex + 1, "ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
}
public void OnAddChildBtnClicked()
{
mNewItemCount++;
if (mTreeView.IsEmpty)
{
TreeViewItem childItem = mTreeView.AppendItem("ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
else
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
TreeViewItem childItem = item.ChildTree.AppendItem("ItemPrefab1");
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
}
}
public void OnDeleteBtnClicked()
{
TreeViewItem item = CurSelectedItem;
if (item == null)
{
Debug.Log("Please Select a Item First");
return;
}
item.ParentTreeList.DeleteItem(item);
}
public void OnBackBtnClicked()
{
UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
}
void SetRectTransformHeight(RectTransform rt,float height)
{
Vector2 size = rt.sizeDelta;
size.y = height;
rt.sizeDelta = size;
}
void OnTreeListRepositionFinish(TreeList treeList)
{
int count = treeList.ItemCount;
if(count == 0)
{
return;
}
//draw the line linked from item to item
TreeViewItem item0 = treeList.GetItemByIndex(0);
ItemScript2 itemScript0 = item0.GetComponent<ItemScript2>();
float topY = item0.transform.localPosition.y - item0.CachedRectTransform.rect.height / 2;
RectTransform rt0 = itemScript0.mLineVertical.GetComponent<RectTransform>();
RectTransform lineRf= rt0;
for (int i = 1; i< count ; ++i)
{
TreeViewItem item = treeList.GetItemByIndex(i);
ItemScript2 itemScript = item.GetComponent<ItemScript2>();
float centerY = item.transform.localPosition.y - item.CachedRectTransform.rect.height / 2;
float dist = topY - centerY;
topY = centerY;
RectTransform rt = itemScript.mLineVertical.GetComponent<RectTransform>();
//set the line length
SetRectTransformHeight(lineRf, dist);
lineRf = rt;
}
SetRectTransformHeight(lineRf, 0);
//draw the line linked from item to item' childTree
for (int i = 0; i < count; ++i)
{
TreeViewItem item = treeList.GetItemByIndex(i);
ItemScript2 itemScript = item.GetComponent<ItemScript2>();
RectTransform rt2 = itemScript.mLineVertical_2.GetComponent<RectTransform>();
if (item.ChildItemCount > 0 && item.IsCollapseEnd == false)
{
//get the childTree's first item
TreeViewItem childItem0 = item.ChildTree.GetItemByIndex(0);
ItemScript2 childItemScript0 = childItem0.GetComponent<ItemScript2>();
Vector3 pos0 = item.transform.InverseTransformPoint(childItemScript0.mExpandBtn.transform.position);
float dist2 = rt2.localPosition.y - pos0.y;
//set the line length
SetRectTransformHeight(rt2, dist2);
}
else
{
SetRectTransformHeight(rt2, 0);
}
}
}
}
}