2025-04-27 11:41:11 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
using QFramework;
|
|
|
|
|
|
using System.Collections.Generic;
|
2025-04-28 09:12:21 +08:00
|
|
|
|
using UnityEngine.EventSystems;
|
|
|
|
|
|
using System;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
using TMPro;
|
|
|
|
|
|
using System.Xml;
|
2025-05-29 18:31:39 +08:00
|
|
|
|
using System.Linq;
|
2025-04-27 11:41:11 +08:00
|
|
|
|
|
|
|
|
|
|
namespace QFramework.Example
|
|
|
|
|
|
{
|
|
|
|
|
|
public class UIImageSelectMapData : UIPanelData
|
|
|
|
|
|
{
|
|
|
|
|
|
public class OptionItem
|
|
|
|
|
|
{
|
|
|
|
|
|
public string pic;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
public string name;
|
|
|
|
|
|
}
|
|
|
|
|
|
public class Row
|
|
|
|
|
|
{
|
|
|
|
|
|
public string name;
|
|
|
|
|
|
public List<OptionItem> items = new List<OptionItem>();
|
2025-04-27 11:41:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
public string scoreName;
|
|
|
|
|
|
public float totalScore;
|
|
|
|
|
|
public float rightScore;
|
|
|
|
|
|
public float wrongScore;
|
|
|
|
|
|
public string rightLabel;
|
|
|
|
|
|
public string wrongLabel;
|
|
|
|
|
|
public string finishedEvent;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
public bool random = false;
|
|
|
|
|
|
public List<Row> rows = new List<Row>();
|
2025-04-27 11:41:11 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
public partial class UIImageSelectMap : UIPanel
|
|
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ݽṹ
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
class RightDataItem
|
|
|
|
|
|
{
|
|
|
|
|
|
public GameObject rightObj;
|
|
|
|
|
|
public bool isRight = false;
|
|
|
|
|
|
}
|
2025-04-27 11:41:11 +08:00
|
|
|
|
ResLoader loader;
|
2025-04-28 10:17:57 +08:00
|
|
|
|
GameObject moveObj;
|
|
|
|
|
|
GameObject enterRight;
|
|
|
|
|
|
GameObject leftDragObj;
|
|
|
|
|
|
Dictionary<GameObject, UIImageSelectMapData.OptionItem> itemDatas = new Dictionary<GameObject, UIImageSelectMapData.OptionItem>();
|
2025-05-29 15:08:28 +08:00
|
|
|
|
Dictionary<GameObject, RightDataItem> leftAndRightMap = new Dictionary<GameObject, RightDataItem>();
|
2025-05-29 18:31:39 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ӳ<EFBFBD><D3B3>
|
|
|
|
|
|
Dictionary<GameObject, UIImageSelectMapData.Row> rowMap = new Dictionary<GameObject, UIImageSelectMapData.Row>();
|
|
|
|
|
|
|
2025-04-27 11:41:11 +08:00
|
|
|
|
protected override void OnInit(IUIData uiData = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
mData = uiData as UIImageSelectMapData ?? new UIImageSelectMapData();
|
2025-05-29 15:08:28 +08:00
|
|
|
|
TypeEventSystem.Global.Register<OnModuleQuit>(OnModuleQuitHandler);
|
2025-04-27 11:41:11 +08:00
|
|
|
|
// 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();
|
2025-04-28 10:17:57 +08:00
|
|
|
|
itemDatas.Clear();
|
2025-05-29 15:08:28 +08:00
|
|
|
|
leftAndRightMap.Clear();
|
2025-05-29 18:31:39 +08:00
|
|
|
|
rowMap.Clear(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>
|
2025-05-29 15:08:28 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var row in mData.rows)
|
2025-04-27 11:41:11 +08:00
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
GameObject rowObj = GameObject.Instantiate(RightRowItem.gameObject, RightContent);
|
2025-05-29 18:31:39 +08:00
|
|
|
|
var typeText = rowObj.transform.Find("Type").GetComponent<TextMeshProUGUI>();
|
|
|
|
|
|
typeText.text = row.name.Replace("\\n", "\n");
|
|
|
|
|
|
rowObj.name = row.name.Replace("\\n", "\n");
|
2025-05-29 15:08:28 +08:00
|
|
|
|
Transform itemContent = rowObj.transform.Find("Items");
|
2025-05-29 18:31:39 +08:00
|
|
|
|
|
|
|
|
|
|
// <20>洢<EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ӳ<EFBFBD><D3B3>
|
|
|
|
|
|
rowMap.Add(rowObj, row);
|
|
|
|
|
|
|
2025-05-29 15:08:28 +08:00
|
|
|
|
foreach (var item in row.items)
|
2025-04-27 11:41:11 +08:00
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
var rightObj = GameObject.Instantiate(RightItem, itemContent);
|
|
|
|
|
|
var nameText = rightObj.transform.Find("Name").GetComponent<TextMeshProUGUI>();
|
|
|
|
|
|
nameText.text = item.name;
|
|
|
|
|
|
nameText.color = Color.white;
|
2025-05-29 18:31:39 +08:00
|
|
|
|
rightObj.name = item.name;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
rightObj.transform.Find("PicBg/Pic").GetComponent<Image>().color = new Color(1, 1, 1, 0);
|
|
|
|
|
|
rightObj.OnPointerEnterEvent(RightOnEnter);
|
|
|
|
|
|
rightObj.OnPointerExitEvent(RightOnExit);
|
|
|
|
|
|
rightObj.OnPointerClickEvent(RightOnClick);
|
|
|
|
|
|
|
|
|
|
|
|
var leftObj = GameObject.Instantiate(LeftItem, LeftContent);
|
2025-05-29 18:31:39 +08:00
|
|
|
|
leftObj.name = row.name + "|" + item.name;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
var path = Global.deviceIconsPath + item.pic;
|
|
|
|
|
|
loader.Add2Load(path.ToNetImageResName(), (success, res) =>
|
2025-04-27 11:41:11 +08:00
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
if (success)
|
|
|
|
|
|
{
|
|
|
|
|
|
leftObj.GetComponent<Image>().sprite = Utility.GetSprite(res.Asset as Texture2D);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
leftObj.OnBeginDragEvent(LeftOnBeginDrag);
|
|
|
|
|
|
leftObj.OnDragEvent(LeftOnDrag);
|
|
|
|
|
|
leftObj.OnEndDragEvent(LeftOnEndDrag);
|
|
|
|
|
|
itemDatas.Add(leftObj.gameObject, item);
|
|
|
|
|
|
}
|
2025-04-27 11:41:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-29 15:08:28 +08:00
|
|
|
|
if (mData.random)
|
2025-04-27 11:41:11 +08:00
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
Utility.ShuffleChildObjects(LeftContent);
|
|
|
|
|
|
}
|
2025-04-27 11:41:11 +08:00
|
|
|
|
|
|
|
|
|
|
loader.LoadAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-29 15:08:28 +08:00
|
|
|
|
private void OnModuleQuitHandler(OnModuleQuit quit)
|
|
|
|
|
|
{
|
|
|
|
|
|
Hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-28 14:50:00 +08:00
|
|
|
|
private void RightOnClick(PointerEventData data)
|
|
|
|
|
|
{
|
|
|
|
|
|
Transform trans = data.pointerClick.transform;
|
2025-05-29 15:08:28 +08:00
|
|
|
|
if (leftAndRightMap.ContainsKey(trans.gameObject))
|
2025-04-28 14:50:00 +08:00
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
leftAndRightMap[trans.gameObject].rightObj.SetActive(true);
|
|
|
|
|
|
trans.GetComponent<Image>().color = Color.white;
|
|
|
|
|
|
trans.Find("PicBg/Pic").GetComponent<Image>().color = new Color(1, 1, 1, 0);
|
2025-04-28 14:50:00 +08:00
|
|
|
|
|
2025-05-29 15:08:28 +08:00
|
|
|
|
enterRight.transform.Find("Name").GetComponent<TextMeshProUGUI>().color = Color.white;
|
|
|
|
|
|
leftAndRightMap.Remove(trans.gameObject);
|
2025-04-28 14:50:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-28 10:17:57 +08:00
|
|
|
|
private void RightOnExit(PointerEventData data)
|
2025-04-28 09:12:21 +08:00
|
|
|
|
{
|
2025-04-28 10:17:57 +08:00
|
|
|
|
enterRight = null;
|
2025-04-28 09:12:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-28 10:17:57 +08:00
|
|
|
|
private void RightOnEnter(PointerEventData data)
|
|
|
|
|
|
{
|
|
|
|
|
|
enterRight = data.pointerEnter.gameObject;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LeftOnBeginDrag(PointerEventData data)
|
|
|
|
|
|
{
|
|
|
|
|
|
leftDragObj = data.pointerDrag;
|
2025-04-28 14:50:00 +08:00
|
|
|
|
moveObj = GameObject.Instantiate(leftDragObj, gameObject.transform);
|
|
|
|
|
|
moveObj.name = moveObj.name.Replace("(Clone)", "");
|
|
|
|
|
|
moveObj.GetComponent<RectTransform>().sizeDelta = LeftContent.GetComponent<GridLayoutGroup>().cellSize;
|
2025-04-28 10:17:57 +08:00
|
|
|
|
moveObj.GetComponent<Image>().raycastTarget = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LeftOnEndDrag(PointerEventData data)
|
|
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
if (enterRight == null || leftAndRightMap.ContainsKey(enterRight))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
TextMeshProUGUI nameText = enterRight.transform.Find("Name").GetComponent<TextMeshProUGUI>();
|
2025-05-30 13:31:50 +08:00
|
|
|
|
|
|
|
|
|
|
Image Frame = enterRight.transform.Find("Frame").GetComponent<Image>();
|
2025-05-29 18:31:39 +08:00
|
|
|
|
bool isRight = false;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1>ȷ<EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
UIImageSelectMapData.Row categoryRow = GetCategoryRow(enterRight);
|
|
|
|
|
|
if (categoryRow == null)
|
2025-04-28 10:17:57 +08:00
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
Debug.LogError("<22><EFBFBD><DEB7>ҵ<EFBFBD><D2B5><EFBFBD>Ӧ<EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-05-29 15:08:28 +08:00
|
|
|
|
|
2025-05-29 18:31:39 +08:00
|
|
|
|
var draggedItem = itemDatas[leftDragObj];
|
|
|
|
|
|
bool foundMatch = CheckItemInCategory(draggedItem, categoryRow);
|
2025-05-29 15:08:28 +08:00
|
|
|
|
|
2025-05-29 18:31:39 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD>UI<55><49><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (foundMatch)
|
|
|
|
|
|
{
|
2025-05-30 13:31:50 +08:00
|
|
|
|
Frame.color = Color.green;
|
2025-05-29 18:31:39 +08:00
|
|
|
|
nameText.color = Color.green;
|
|
|
|
|
|
isRight = true;
|
|
|
|
|
|
Debug.Log($"<22><>ȷƥ<C8B7><C6A5>: {draggedItem.name} <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> {categoryRow.name}");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-05-30 13:31:50 +08:00
|
|
|
|
Frame.color = Color.red;
|
2025-05-29 18:31:39 +08:00
|
|
|
|
nameText.color = Color.red;
|
|
|
|
|
|
Debug.Log($"<22><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>: {draggedItem.name} <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> {categoryRow.name}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC>ʾ
|
|
|
|
|
|
Image img = enterRight.transform.Find("PicBg/Pic").GetComponent<Image>();
|
|
|
|
|
|
img.sprite = moveObj.GetComponent<Image>().sprite;
|
|
|
|
|
|
img.color = Color.white;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>¼ƥ<C2BC><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
leftAndRightMap.Add(enterRight, new RightDataItem { rightObj = leftDragObj, isRight = isRight });
|
|
|
|
|
|
leftDragObj.SetActive(false);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>鵱ǰ<E9B5B1><C7B0><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (isRight && CheckCategoryCompletion(categoryRow))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(mData.finishedEvent))
|
2025-05-29 15:08:28 +08:00
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
StringEventSystem.Global.Send(mData.finishedEvent);
|
|
|
|
|
|
Debug.Log($"<22><><EFBFBD><EFBFBD> {categoryRow.name} <20><><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>");
|
2025-05-29 15:08:28 +08:00
|
|
|
|
}
|
2025-04-28 10:17:57 +08:00
|
|
|
|
}
|
2025-05-29 18:31:39 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ק<EFBFBD><D7A7><EFBFBD><EFBFBD>
|
2025-05-29 15:08:28 +08:00
|
|
|
|
GameObject.Destroy(moveObj);
|
|
|
|
|
|
moveObj = null;
|
|
|
|
|
|
leftDragObj = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-29 18:31:39 +08:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
private UIImageSelectMapData.Row GetCategoryRow(GameObject targetObj)
|
2025-05-29 15:08:28 +08:00
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
Transform parentTransform = targetObj.transform.parent;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>
|
|
|
|
|
|
while (parentTransform != null && parentTransform != RightContent.transform)
|
2025-04-28 10:17:57 +08:00
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
if (rowMap.ContainsKey(parentTransform.gameObject))
|
2025-05-29 15:08:28 +08:00
|
|
|
|
{
|
2025-05-29 18:31:39 +08:00
|
|
|
|
return rowMap[parentTransform.gameObject];
|
2025-05-29 15:08:28 +08:00
|
|
|
|
}
|
2025-05-29 18:31:39 +08:00
|
|
|
|
parentTransform = parentTransform.parent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>Ƿ<EFBFBD><C7B7>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
private bool CheckItemInCategory(UIImageSelectMapData.OptionItem item, UIImageSelectMapData.Row categoryRow)
|
|
|
|
|
|
{
|
|
|
|
|
|
return categoryRow.items.Exists(i => i.pic == item.pic || i.name == item.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
|
|
|
|
|
|
private bool CheckCategoryCompletion(UIImageSelectMapData.Row categoryRow)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (categoryRow == null)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>Ҹ÷<D2B8><C3B7><EFBFBD><EFBFBD><EFBFBD>Ҫƥ<D2AA><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>
|
|
|
|
|
|
int required = categoryRow.items.Count;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>Ҹ÷<D2B8><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷƥ<C8B7><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>
|
|
|
|
|
|
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);
|
2025-04-28 10:17:57 +08:00
|
|
|
|
}
|
2025-05-29 18:31:39 +08:00
|
|
|
|
|
|
|
|
|
|
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
return actual >= required;
|
2025-04-28 10:17:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LeftOnDrag(PointerEventData data)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (moveObj)
|
|
|
|
|
|
{
|
|
|
|
|
|
moveObj.transform.position = Input.mousePosition;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-27 11:41:11 +08:00
|
|
|
|
protected override void OnShow()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnHide()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnClose()
|
|
|
|
|
|
{
|
2025-05-29 15:08:28 +08:00
|
|
|
|
TypeEventSystem.Global.UnRegister<OnModuleQuit>(OnModuleQuitHandler);
|
2025-04-27 11:41:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-29 18:31:39 +08:00
|
|
|
|
}
|