using UnityEngine; using UnityEngine.UI; using QFramework; using System.Collections.Generic; using UnityEngine.EventSystems; using System; using TMPro; using System.Xml; using System.Linq; namespace QFramework.Example { public class UIImageSelectMapData : UIPanelData { public class OptionItem { public string pic; public string name; } public class Row { public string name; public List items = new List(); } public string scoreName; public float totalScore; public float rightScore; public float wrongScore; public string rightLabel; public string wrongLabel; public string finishedEvent; public bool random = false; public List rows = new List(); } public partial class UIImageSelectMap : UIPanel { /// /// 右侧数据结构 /// class RightDataItem { public GameObject rightObj; public bool isRight = false; } ResLoader loader; GameObject moveObj; GameObject enterRight; GameObject leftDragObj; Dictionary itemDatas = new Dictionary(); Dictionary leftAndRightMap = new Dictionary(); // 新增:存储分类行对象和数据的映射 Dictionary rowMap = new Dictionary(); protected override void OnInit(IUIData uiData = null) { mData = uiData as UIImageSelectMapData ?? new UIImageSelectMapData(); TypeEventSystem.Global.Register(OnModuleQuitHandler); // please add init code here loader = ResLoader.Allocate(); } protected override void OnOpen(IUIData uiData = null) { mData = uiData as UIImageSelectMapData ?? new UIImageSelectMapData(); LeftContent.RemoveAllChildren(); RightContent.RemoveAllChildren(); itemDatas.Clear(); leftAndRightMap.Clear(); rowMap.Clear(); // 清空行映射 foreach (var row in mData.rows) { GameObject rowObj = GameObject.Instantiate(RightRowItem.gameObject, RightContent); var typeText = rowObj.transform.Find("Type").GetComponent(); typeText.text = row.name.Replace("\\n", "\n"); rowObj.name = row.name.Replace("\\n", "\n"); Transform itemContent = rowObj.transform.Find("Items"); // 存储行对象和数据的映射 rowMap.Add(rowObj, row); foreach (var item in row.items) { var rightObj = GameObject.Instantiate(RightItem, itemContent); var nameText = rightObj.transform.Find("Name").GetComponent(); nameText.text = item.name; nameText.color = Color.white; rightObj.name = item.name; rightObj.transform.Find("PicBg/Pic").GetComponent().color = new Color(1, 1, 1, 0); rightObj.OnPointerEnterEvent(RightOnEnter); rightObj.OnPointerExitEvent(RightOnExit); rightObj.OnPointerClickEvent(RightOnClick); var leftObj = GameObject.Instantiate(LeftItem, LeftContent); leftObj.name = row.name + "|" + item.name; var path = Global.deviceIconsPath + item.pic; loader.Add2Load(path.ToNetImageResName(), (success, res) => { if (success) { leftObj.GetComponent().sprite = Utility.GetSprite(res.Asset as Texture2D); } }); leftObj.OnBeginDragEvent(LeftOnBeginDrag); leftObj.OnDragEvent(LeftOnDrag); leftObj.OnEndDragEvent(LeftOnEndDrag); itemDatas.Add(leftObj.gameObject, item); } } if (mData.random) { Utility.ShuffleChildObjects(LeftContent); } loader.LoadAsync(); } private void OnModuleQuitHandler(OnModuleQuit quit) { Hide(); } private void RightOnClick(PointerEventData data) { Transform trans = data.pointerClick.transform; if (leftAndRightMap.ContainsKey(trans.gameObject)) { leftAndRightMap[trans.gameObject].rightObj.SetActive(true); trans.GetComponent().color = Color.white; trans.Find("PicBg/Pic").GetComponent().color = new Color(1, 1, 1, 0); enterRight.transform.Find("Name").GetComponent().color = Color.white; leftAndRightMap.Remove(trans.gameObject); } } private void RightOnExit(PointerEventData data) { enterRight = null; } private void RightOnEnter(PointerEventData data) { enterRight = data.pointerEnter.gameObject; } private void LeftOnBeginDrag(PointerEventData data) { leftDragObj = data.pointerDrag; moveObj = GameObject.Instantiate(leftDragObj, gameObject.transform); moveObj.name = moveObj.name.Replace("(Clone)", ""); moveObj.GetComponent().sizeDelta = LeftContent.GetComponent().cellSize; moveObj.GetComponent().raycastTarget = false; } private void LeftOnEndDrag(PointerEventData data) { if (enterRight == null || leftAndRightMap.ContainsKey(enterRight)) return; //TextMeshProUGUI nameText = enterRight.transform.Find("Name").GetComponent(); //Image Frame = enterRight.transform.Find("Frame").GetComponent(); bool isRight = false; // 获取正确的分类数据 UIImageSelectMapData.Row categoryRow = GetCategoryRow(enterRight); if (categoryRow == null) { Debug.LogError("无法找到对应的分类数据"); return; } var draggedItem = itemDatas[leftDragObj]; bool foundMatch = CheckItemInCategory(draggedItem, categoryRow); // 更新UI反馈 if (foundMatch) { //Frame.color = Color.green; //nameText.color = Color.green; isRight = true; Debug.Log($"正确匹配: {draggedItem.name} 到分类 {categoryRow.name}"); } else { //Frame.color = Color.red; //nameText.color = Color.red; Debug.Log($"错误匹配: {draggedItem.name} 到分类 {categoryRow.name}"); } // 更新图片显示 //Image img = enterRight.transform.Find("PicBg/Pic").GetComponent(); //img.sprite = moveObj.GetComponent().sprite; //img.color = Color.white; // 记录匹配结果 leftAndRightMap.Add(enterRight, new RightDataItem { rightObj = leftDragObj, isRight = isRight }); leftDragObj.SetActive(false); // 检查当前分类是否完成 if (isRight && CheckCategoryCompletion(categoryRow)) { if (!string.IsNullOrEmpty(mData.finishedEvent)) { StringEventSystem.Global.Send(mData.finishedEvent); Debug.Log($"分类 {categoryRow.name} 已完成,触发完成事件"); } } // 清理拖拽对象 GameObject.Destroy(moveObj); moveObj = null; leftDragObj = null; } // 获取分类行数据 private UIImageSelectMapData.Row GetCategoryRow(GameObject targetObj) { Transform parentTransform = targetObj.transform.parent; // 查找行对象 while (parentTransform != null && parentTransform != RightContent.transform) { if (rowMap.ContainsKey(parentTransform.gameObject)) { return rowMap[parentTransform.gameObject]; } parentTransform = parentTransform.parent; } return null; } // 检查项目是否在分类中 private bool CheckItemInCategory(UIImageSelectMapData.OptionItem item, UIImageSelectMapData.Row categoryRow) { return categoryRow.items.Exists(i => i.pic == item.pic || i.name == item.name); } // 检查分类是否完成匹配 private bool CheckCategoryCompletion(UIImageSelectMapData.Row categoryRow) { if (categoryRow == null) return false; // 查找该分类需要匹配的项目数 int required = categoryRow.items.Count; // 查找该分类已正确匹配的项目数 int actual = 0; if (leftAndRightMap.Any(p => p.Value.isRight && GetCategoryRow(p.Key) == categoryRow)) { actual = leftAndRightMap.Count(p => p.Value.isRight && GetCategoryRow(p.Key) == categoryRow); } // 判断是否完成 return actual >= required; } private void LeftOnDrag(PointerEventData data) { if (moveObj) { moveObj.transform.position = Input.mousePosition; } } protected override void OnShow() { } protected override void OnHide() { } protected override void OnClose() { TypeEventSystem.Global.UnRegister(OnModuleQuitHandler); } } }