VirtualFramework/Assets/Scripts/UI/UIBody3DMenuTree.cs
2025-03-11 10:33:07 +08:00

411 lines
16 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 UnityEngine;
using UnityEngine.UI;
using XMLTool;
using System.Collections.Generic;
using TMPro;
using DG.Tweening;
using System;
namespace QFramework.Example
{
public class UIBody3DMenuTreeData : UIPanelData
{
public Body3D.Body body;
}
public partial class UIBody3DMenuTree : UIPanel
{
class ObjBtnData
{
public Button btn;
public Body3D.Body body;
public ObjToggleStatus status;
public Dictionary<Body3D.Body, ObjBtnData> objBtnDataMap = new Dictionary<Body3D.Body, ObjBtnData>();
public ObjBtnData(Dictionary<Body3D.Body, ObjBtnData> objBtnDataMap, Button btn, Body3D.Body body)
{
this.objBtnDataMap = objBtnDataMap;
this.btn = btn;
this.body = body;
btn.onClick.AddListener(() =>
{
switch (status)
{
case ObjToggleStatus.None:
case ObjToggleStatus.Half:
SetStatus(ObjToggleStatus.Full);
break;
case ObjToggleStatus.Full:
SetStatus(ObjToggleStatus.None);
break;
}
});
}
public void SetStatus(ObjToggleStatus status)
{
this.status = status;
RefreshStatus();
}
public void RefreshStatus()
{
switch (status)
{
case ObjToggleStatus.None:
CheckActive();
foreach (var sub in body.subBody)
{
if (objBtnDataMap.ContainsKey(sub.Value))
{
objBtnDataMap[sub.Value].SetStatus(status);
}
}
SetUpStatus(body, true);
break;
case ObjToggleStatus.Half:
CheckActive();
SetUpStatus(body, false);
break;
case ObjToggleStatus.Full:
CheckActive();
foreach (var sub in body.subBody)
{
if (objBtnDataMap.ContainsKey(sub.Value))
{
objBtnDataMap[sub.Value].SetStatus(status);
}
}
SetUpStatus(body, true);
break;
}
RefreshUI();
}
public void CheckActive()
{
switch (status)
{
case ObjToggleStatus.None:
Utility.FindObj(body.Path).SetActive(false);
break;
case ObjToggleStatus.Half:
case ObjToggleStatus.Full:
Utility.FindObj(body.Path).SetActive(true);
break;
}
}
public void RefreshParent(ObjToggleStatus status)
{
this.status = status;
CheckActive();
RefreshUI();
}
public void SetUpStatus(Body3D.Body body, bool needCheck)
{
var parent = body.parent;
if (parent != null && objBtnDataMap.ContainsKey(parent))
{
if (needCheck)
{
bool allOn = true;
bool allNone = true;
// 遍历 body 的子元素 subBody
foreach (var sub in parent.subBody)
{
// 检查 objBtnDataMap 中是否包含当前子元素的值
if (objBtnDataMap.ContainsKey(sub.Value))
{
// 获取当前子元素对应的按钮数据的状态
var status = objBtnDataMap[sub.Value].status;
// 如果当前子元素的状态不是 Full说明不是所有子元素都是 Full 状态
if (status != ObjToggleStatus.Full)
{
allOn = false;
}
// 如果当前子元素的状态不是 None说明不是所有子元素都是 None 状态
if (status != ObjToggleStatus.None)
{
allNone = false;
}
}
else
{
// 如果 objBtnDataMap 中不包含当前子元素的值,说明不是所有状态都符合要求
allOn = false;
allNone = false;
break;
}
}
// 如果所有子元素的状态都是 Full
if (allOn)
{
// 将当前 body 的状态设置为 Full
objBtnDataMap[parent].RefreshParent(ObjToggleStatus.Full);
}
// 如果所有子元素的状态都是 None
else if (allNone)
{
// 将当前 body 的状态设置为 None
objBtnDataMap[parent].RefreshParent(ObjToggleStatus.None);
}
else
{
objBtnDataMap[parent].RefreshParent(ObjToggleStatus.Half);
}
SetUpStatus(parent, true);
}
else
{
if (objBtnDataMap.ContainsKey(parent))
{
objBtnDataMap[parent].SetStatus(ObjToggleStatus.Half);
SetUpStatus(parent, false);
}
}
}
}
public void RefreshUI()
{
switch (status)
{
case ObjToggleStatus.None:
btn.transform.Find("Full").gameObject.SetActive(false);
btn.transform.Find("Half").gameObject.SetActive(false);
break;
case ObjToggleStatus.Half:
btn.transform.Find("Full").gameObject.SetActive(false);
btn.transform.Find("Half").gameObject.SetActive(true);
break;
case ObjToggleStatus.Full:
btn.transform.Find("Full").gameObject.SetActive(true);
btn.transform.Find("Half").gameObject.SetActive(false);
break;
}
}
}
Dictionary<GameObject, GameObject> searchItemMap = new Dictionary<GameObject, GameObject>();
Dictionary<Body3D.Body, ObjBtnData> objBtnDataMap = new Dictionary<Body3D.Body, ObjBtnData>();
enum ObjToggleStatus
{
None,
Half,
Full
}
DOTweenAnimation contentAnim;
protected override void OnInit(IUIData uiData = null)
{
TypeEventSystem.Global.Register<OnModuleQuit>(OnModuleQuithandler).UnRegisterWhenGameObjectDestroyed(this);
contentAnim = RootContent.GetComponent<DOTweenAnimation>();
// please add init code here
Close.onClick.AddListener(() =>
{
Hide();
StringEventSystem.Global.Send($"On{UIBody3DMenuTree.Name}Close");
});
Input.onSelect.AddListener(str =>
{
SearchContent.gameObject.SetActive(true);
Content.gameObject.SetActive(false);
});
Input.onEndEdit.AddListener(str =>
{
if (string.IsNullOrEmpty(str))
{
SearchContent.gameObject.SetActive(false);
Content.gameObject.SetActive(true);
SearchContent.RemoveAllChildren();
}
else
{
SearchContent.gameObject.SetActive(true);
Content.gameObject.SetActive(false);
RefreshSearchContent(str);
}
});
}
private void OnModuleQuithandler(OnModuleQuit quit)
{
Hide();
}
protected override void OnOpen(IUIData uiData = null)
{
mData = uiData as UIBody3DMenuTreeData ?? new UIBody3DMenuTreeData();
contentAnim.DORestart();
Content.RemoveAllChildren();
objBtnDataMap.Clear();
BuildTreeUI(mData.body);
}
private void BuildTreeUI(Body3D.Body data, int depth = 0, Transform parent = null)
{
foreach (var bodyPair in data.subBody)
{
Body3D.Body body = bodyPair.Value;
Transform targetParent = parent != null ? parent : Content;
GameObject toggleObj = GameObject.Instantiate(Item.gameObject, targetParent);
toggleObj.name = body.Name;
Toggle uiToggle = toggleObj.transform.Find("ToggleContent/UI").GetComponent<Toggle>();
Button objBtn = toggleObj.transform.Find("ToggleContent/Obj").GetComponent<Button>();
TextMeshProUGUI label = toggleObj.transform.Find("ToggleContent/Label").GetComponentInChildren<TextMeshProUGUI>();
label.text = body.Name;
toggleObj.transform.Find("ToggleContent").GetComponent<HorizontalLayoutGroup>().padding = new RectOffset(depth * 15, 5, 2, 2);
if (depth != 0)
{
toggleObj.SetActive(false);
}
Transform subContent = toggleObj.transform.Find("SubContent");
uiToggle.onValueChanged.AddListener((isOn) =>
{
for (int i = 0; i < subContent.childCount; i++)
{
subContent.GetChild(i).gameObject.SetActive(isOn);
}
});
objBtnDataMap.Add(body, new ObjBtnData(objBtnDataMap, objBtn, body));
if (body.subBody.Count > 0)
{
uiToggle.gameObject.SetActive(true);
BuildTreeUI(body, depth + 1, subContent);
}
else
{
uiToggle.gameObject.SetActive(false);
}
}
}
private void SetSubObjActive(Body3D.Body body, bool isOn, Transform subContent)
{
// 先设置当前对象
GameObject targetObj = Utility.FindObj(body.Path);
if (targetObj != null)
{
targetObj.SetActive(isOn);
}
// 再递归设置子对象
int index = 0;
foreach (var subBodyPair in body.subBody)
{
Body3D.Body subBody = subBodyPair.Value;
if (subContent.childCount > index)
{
Transform childToggleObj = subContent.GetChild(index);
Toggle childObjToggle = childToggleObj.transform.Find("ToggleContent/Obj").GetComponent<Toggle>();
childObjToggle.isOn = isOn;
Transform childSubContent = childToggleObj.transform.Find("SubContent");
SetSubObjActive(subBody, isOn, childSubContent);
}
index++;
}
}
private void RefreshSearchContent(string str)
{
searchItemMap.Clear();
SearchContent.RemoveAllChildren();
CheckChildren(Content, str);
}
private void CheckChildren(Transform parent, string str)
{
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
Transform labelTransform = child.Find("ToggleContent/Label");
if (labelTransform != null)
{
TextMeshProUGUI textComponent = labelTransform.GetComponent<TextMeshProUGUI>();
if (textComponent != null)
{
string name = textComponent.text;
if (name.Contains(str))
{
GameObject clone = GameObject.Instantiate(SearchItem.gameObject, SearchContent);
searchItemMap.Add(clone, child.gameObject);
Transform subContent = child.Find("SubContent");
if (subContent.childCount > 0)
{
Button btn = clone.transform.Find("Button").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
child.Find("ToggleContent/Obj").GetComponent<Toggle>().isOn = true;
});
Transform buttonLabel = btn.transform.Find("Label");
if (buttonLabel != null)
{
TextMeshProUGUI buttonText = buttonLabel.GetComponent<TextMeshProUGUI>();
if (buttonText != null)
{
buttonText.text = "组" + name + ">";
}
}
CheckChildren(subContent, str);
}
else
{
Transform buttonLabel = clone.transform.Find("Button/Label");
if (buttonLabel != null)
{
TextMeshProUGUI buttonText = buttonLabel.GetComponent<TextMeshProUGUI>();
if (buttonText != null)
{
buttonText.text = name + ">";
}
}
}
}
}
}
}
}
protected override void OnShow()
{
}
public override void Hide()
{
if (contentAnim.onComplete == null)
{
contentAnim.onComplete = new UnityEngine.Events.UnityEvent();
}
contentAnim.onComplete.RemoveAllListeners();
contentAnim.DOPlayBackwards();
contentAnim.onComplete.AddListener(() =>
{
base.Hide();
});
}
protected override void OnHide()
{
}
protected override void OnClose()
{
}
}
}