Files
2026-02-21 16:45:37 +08:00

146 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace UIWidgets
{
public class Templates<T> where T : MonoBehaviour, ITemplatable
{
private Dictionary<string, T> templates = new Dictionary<string, T>();
private Dictionary<string, Stack<T>> cache = new Dictionary<string, Stack<T>>();
private bool findTemplatesCalled;
private Action<T> onCreateCallback;
public Templates(Action<T> onCreateCallback = null)
{
this.onCreateCallback = onCreateCallback;
}
public void FindTemplates()
{
findTemplatesCalled = true;
Resources.FindObjectsOfTypeAll<T>().ForEach(AddTemplate);
}
private void AddTemplate(T template)
{
Add(template.name, template);
template.gameObject.SetActive(false);
}
public void ClearCache()
{
cache.Keys.ForEach(ClearCache);
}
public void ClearCache(string name)
{
if (cache.ContainsKey(name))
{
cache[name].ForEach(DestroyCached);
cache[name].Clear();
cache[name].TrimExcess();
}
}
private void DestroyCached(T cached)
{
if (cached != null && cached.gameObject != null)
{
UnityEngine.Object.Destroy(cached.gameObject);
}
}
public bool Exists(string name)
{
return templates.ContainsKey(name);
}
public T Get(string name)
{
if (!Exists(name))
{
throw new ArgumentException("Not found template with name '" + name + "'");
}
return templates[name];
}
public void Delete(string name)
{
if (Exists(name))
{
templates.Remove(name);
ClearCache(name);
}
}
public void Add(string name, T template, bool replace = true)
{
if (Exists(name))
{
if (!replace)
{
throw new ArgumentException("Template with name '" + name + "' already exists.");
}
ClearCache(name);
templates[name] = template;
}
else
{
templates.Add(name, template);
}
template.IsTemplate = true;
template.TemplateName = name;
}
public T Instance(string name)
{
if (!findTemplatesCalled)
{
FindTemplates();
}
if (!Exists(name))
{
throw new ArgumentException("Not found template with name '" + name + "'");
}
if (templates[name] == null)
{
templates.Clear();
FindTemplates();
}
T val;
if (cache.ContainsKey(name) && cache[name].Count > 0)
{
val = cache[name].Pop();
}
else
{
val = UnityEngine.Object.Instantiate(templates[name]);
val.TemplateName = name;
val.IsTemplate = false;
if (onCreateCallback != null)
{
onCreateCallback(val);
}
}
Transform transform = val.transform;
T val2 = templates[name];
transform.SetParent(val2.transform.parent, false);
return val;
}
public void ToCache(T instance)
{
instance.gameObject.SetActive(false);
if (!cache.ContainsKey(instance.TemplateName))
{
cache[instance.TemplateName] = new Stack<T>();
}
cache[instance.TemplateName].Push(instance);
}
}
}