345 lines
11 KiB
C#
345 lines
11 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System;
|
|
|
|
|
|
namespace SuperTreeView
|
|
{
|
|
|
|
public class ItemPool
|
|
{
|
|
GameObject mPrefabObj;
|
|
string mPrefabName;
|
|
int mInitCreateCount = 1;
|
|
List<TreeViewItem> mPooledItemList = new List<TreeViewItem>();
|
|
static int mCurItemIdCount = 0;
|
|
public ItemPool(GameObject prefabObj, int createCount)
|
|
{
|
|
mPrefabObj = prefabObj;
|
|
mPrefabName = mPrefabObj.name;
|
|
mInitCreateCount = createCount;
|
|
}
|
|
public void Init()
|
|
{
|
|
mPrefabObj.SetActive(false);
|
|
for (int i = 0; i < mInitCreateCount; ++i)
|
|
{
|
|
TreeViewItem tViewItem = CreateItem();
|
|
RecycleItem(tViewItem);
|
|
}
|
|
}
|
|
public TreeViewItem GetItem()
|
|
{
|
|
mCurItemIdCount++;
|
|
int count = mPooledItemList.Count;
|
|
TreeViewItem tItem = null;
|
|
if (count == 0)
|
|
{
|
|
tItem = CreateItem();
|
|
}
|
|
else
|
|
{
|
|
tItem = mPooledItemList[count - 1];
|
|
mPooledItemList.RemoveAt(count - 1);
|
|
tItem.gameObject.SetActive(true);
|
|
}
|
|
tItem.ItemId = mCurItemIdCount;
|
|
return tItem;
|
|
|
|
}
|
|
public TreeViewItem CreateItem()
|
|
{
|
|
|
|
GameObject go = GameObject.Instantiate<GameObject>(mPrefabObj);
|
|
go.SetActive(true);
|
|
TreeViewItem tViewItem = go.GetComponent<TreeViewItem>();
|
|
tViewItem.ItemPrefabName = mPrefabName;
|
|
return tViewItem;
|
|
}
|
|
public void RecycleItem(TreeViewItem item)
|
|
{
|
|
item.gameObject.SetActive(false);
|
|
mPooledItemList.Add(item);
|
|
}
|
|
}
|
|
[System.Serializable]
|
|
public class ItemPrefabConfData
|
|
{
|
|
public GameObject mItemPrefab;
|
|
public int mInitCreateCount;
|
|
}
|
|
|
|
public class TreeView : TreeList
|
|
{
|
|
//called when a item is added to a TreeList
|
|
public Action<TreeList> OnTreeListAddOneItem;
|
|
//called when a item is deleted to a TreeList
|
|
public Action<TreeList> OnTreeListDeleteOneItem;
|
|
//called when a item is begin to expand its chlidtree.
|
|
public Action<TreeViewItem> OnItemExpandBegin;
|
|
//called when a item is expanding its chlidtree.
|
|
public Action<TreeViewItem> OnItemExpanding;
|
|
//called when a item has expanded its chlidtree.
|
|
public Action<TreeViewItem> OnItemExpandEnd;
|
|
//called when a item is begin to collapse its chlidtree.
|
|
public Action<TreeViewItem> OnItemCollapseBegin;
|
|
//called when a item is collapsing its chlidtree.
|
|
public Action<TreeViewItem> OnItemCollapsing;
|
|
//called when a item has collapsed its chlidtree.
|
|
public Action<TreeViewItem> OnItemCollapseEnd;
|
|
//called when a custom event is raised. you can raise a custom event by
|
|
//call TreeViewItem:RaiseCustomEvent(CustomEvent customEvent,System.Object param)
|
|
//to notify the TreeView something happens, such as a TreeViewItem is clicked.
|
|
//This callback is a bridge to connect the TreeView and its child TreeViewItems.
|
|
public Action<TreeViewItem, CustomEvent,System.Object> OnItemCustomEvent;
|
|
//called when a TreeList reposition method finished.
|
|
public Action<TreeList> OnTreeListRepositionFinish;
|
|
|
|
[SerializeField]
|
|
float mExpandUseTime = 5f;
|
|
|
|
|
|
[SerializeField]
|
|
float mExpandClipMoveSpeed = 100f;
|
|
|
|
Dictionary<string, ItemPool> mItemPoolDict = new Dictionary<string, ItemPool>();
|
|
RectTransform mPoolRootTrans;
|
|
Dictionary<int, TreeViewItem> mTreeViewItemDict = new Dictionary<int, TreeViewItem>();
|
|
int mCurTreeItemDictVersion = 0;
|
|
|
|
List<TreeViewItem> mAllTreeViewItemList = null;
|
|
int mCurTreeItemListVersion = 0;
|
|
|
|
bool mNeedRepositionView = true;
|
|
|
|
bool mNeedRepositionAll = true;
|
|
|
|
[SerializeField]
|
|
List<ItemPrefabConfData> mItemPrefabDataList = new List<ItemPrefabConfData>();
|
|
|
|
[SerializeField]
|
|
ExpandAnimType mExpandAnimType = ExpandAnimType.Clip;
|
|
public ExpandAnimType ExpandAnimateType
|
|
{
|
|
get { return mExpandAnimType; }
|
|
set { mExpandAnimType = value; }
|
|
}
|
|
|
|
public bool NeedRepositionAll
|
|
{
|
|
get { return mNeedRepositionAll; }
|
|
set { mNeedRepositionAll = value;}
|
|
}
|
|
|
|
|
|
[SerializeField]
|
|
float mItemIndent;
|
|
[SerializeField]
|
|
float mChildTreeListPadding;
|
|
[SerializeField]
|
|
float mItemPadding;
|
|
|
|
|
|
public float ItemIndent
|
|
{
|
|
get { return mItemIndent; }
|
|
set
|
|
{
|
|
mItemIndent = value;
|
|
NeedRepositionAll = true;
|
|
}
|
|
}
|
|
|
|
public float ChildTreeListPadding
|
|
{
|
|
get { return mChildTreeListPadding; }
|
|
set
|
|
{
|
|
mChildTreeListPadding = value;
|
|
NeedRepositionAll = true;
|
|
}
|
|
}
|
|
|
|
public float ItemPadding
|
|
{
|
|
get { return mItemPadding; }
|
|
set
|
|
{
|
|
mItemPadding = value;
|
|
NeedRepositionAll = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public float ExpandUseTime
|
|
{
|
|
get { return mExpandUseTime; }
|
|
set { mExpandUseTime = value; }
|
|
}
|
|
|
|
|
|
public float ExpandClipMoveSpeed
|
|
{
|
|
get { return mExpandClipMoveSpeed; }
|
|
set { mExpandClipMoveSpeed = value; }
|
|
}
|
|
|
|
|
|
public bool NeedRepositionView
|
|
{
|
|
get { return mNeedRepositionView; }
|
|
set { mNeedRepositionView = value; }
|
|
}
|
|
|
|
public List<TreeViewItem> AllTreeViewItemList
|
|
{
|
|
get
|
|
{
|
|
if (mAllTreeViewItemList != null)
|
|
{
|
|
if (mCurTreeItemDictVersion == mCurTreeItemListVersion)
|
|
{
|
|
return mAllTreeViewItemList;
|
|
}
|
|
}
|
|
mCurTreeItemListVersion = mCurTreeItemDictVersion;
|
|
mAllTreeViewItemList = new List<TreeViewItem>(mTreeViewItemDict.Values);
|
|
return mAllTreeViewItemList;
|
|
}
|
|
}
|
|
|
|
public void InitView()
|
|
{
|
|
CachedRectTransform.anchorMax = new Vector2(0, 1);
|
|
CachedRectTransform.anchorMin = CachedRectTransform.anchorMax;
|
|
CachedRectTransform.pivot = new Vector2(0, 1);
|
|
GameObject poolObj = new GameObject();
|
|
poolObj.name = "ItemPool";
|
|
RectTransform tf = poolObj.GetComponent<RectTransform>();
|
|
if (tf == null)
|
|
{
|
|
tf = poolObj.AddComponent<RectTransform>();
|
|
}
|
|
tf.anchorMax = new Vector2(0.5f, 0.5f);
|
|
tf.anchorMin = tf.anchorMax;
|
|
tf.pivot = new Vector2(0.5f, 0.5f);
|
|
tf.SetParent(CachedRectTransform);
|
|
tf.anchoredPosition3D = Vector3.zero;
|
|
mPoolRootTrans = tf;
|
|
RootTreeView = this;
|
|
ParentTreeItem = null;
|
|
InitItemPool();
|
|
}
|
|
|
|
void InitItemPool()
|
|
{
|
|
foreach (ItemPrefabConfData data in mItemPrefabDataList)
|
|
{
|
|
if (data.mItemPrefab == null)
|
|
{
|
|
Debug.LogError("A item prefab is null ");
|
|
return;
|
|
}
|
|
string prefabName = data.mItemPrefab.name;
|
|
if (mItemPoolDict.ContainsKey(prefabName))
|
|
{
|
|
Debug.LogError("A item prefab with name " + prefabName + " has existed!");
|
|
return;
|
|
}
|
|
RectTransform rtf = data.mItemPrefab.GetComponent<RectTransform>();
|
|
if(rtf == null)
|
|
{
|
|
Debug.LogError("RectTransform component is not found in the prefab " + prefabName);
|
|
return;
|
|
}
|
|
rtf.anchorMax = new Vector2(0, 1);
|
|
rtf.anchorMin = rtf.anchorMax;
|
|
rtf.pivot = new Vector2(0, 1);
|
|
TreeViewItem tItem = data.mItemPrefab.GetComponent<TreeViewItem>();
|
|
if(tItem == null)
|
|
{
|
|
data.mItemPrefab.AddComponent<TreeViewItem>();
|
|
}
|
|
ItemPool pool = new ItemPool(data.mItemPrefab, data.mInitCreateCount);
|
|
pool.Init();
|
|
mItemPoolDict.Add(prefabName, pool);
|
|
}
|
|
}
|
|
|
|
//This method is used to get a TreeViewItem by its itemId.Every TreeViewItem has a itemId property,
|
|
//and the value is unique and not repeated.
|
|
public TreeViewItem GetTreeItemById(int itemId)
|
|
{
|
|
TreeViewItem item = null;
|
|
if (mTreeViewItemDict.TryGetValue(itemId, out item))
|
|
{
|
|
return item;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public TreeViewItem NewTreeItem(string itemPrefabName)
|
|
{
|
|
ItemPool pool = null;
|
|
if (mItemPoolDict.TryGetValue(itemPrefabName, out pool) == false)
|
|
{
|
|
return null;
|
|
}
|
|
TreeViewItem item = pool.GetItem();
|
|
mTreeViewItemDict.Add(item.ItemId, item);
|
|
mCurTreeItemDictVersion++;
|
|
return item;
|
|
}
|
|
|
|
public void RecycleTreeItem(TreeViewItem item)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return;
|
|
}
|
|
if (string.IsNullOrEmpty(item.ItemPrefabName))
|
|
{
|
|
return;
|
|
}
|
|
ItemPool pool = null;
|
|
if (mItemPoolDict.TryGetValue(item.ItemPrefabName, out pool) == false)
|
|
{
|
|
return;
|
|
}
|
|
item.ParentTreeList = null;
|
|
mTreeViewItemDict.Remove(item.ItemId);
|
|
mCurTreeItemDictVersion++;
|
|
item.CachedRectTransform.SetParent(mPoolRootTrans);
|
|
pool.RecycleItem(item);
|
|
|
|
}
|
|
|
|
|
|
void Update()
|
|
{
|
|
int count = mTreeItemList.Count;
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
TreeViewItem tItem = mTreeItemList[i];
|
|
tItem.OnUpdate();
|
|
if (tItem.NeedReposition)
|
|
{
|
|
NeedRepositionView = true;
|
|
}
|
|
}
|
|
NeedRepositionAll = false;
|
|
if (NeedRepositionView)
|
|
{
|
|
NeedRepositionView = false;
|
|
DoReposition();
|
|
if(OnTreeListRepositionFinish != null)
|
|
{
|
|
OnTreeListRepositionFinish(this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |