1483 lines
41 KiB
C#
1483 lines
41 KiB
C#
|
||
//----------------------------------------------
|
||
// NGUI: Next-Gen UI kit
|
||
// Copyright © 2011-2015 Tasharen Entertainment
|
||
//----------------------------------------------
|
||
|
||
//#define SHOW_HIDDEN_OBJECTS
|
||
#define FUNCELL_MODIFIED
|
||
|
||
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
using Nordeus.DataStructures;
|
||
using System;
|
||
|
||
/// <summary>
|
||
/// This is an internally-created script used by the UI system. You shouldn't be attaching it manually.
|
||
/// </summary>
|
||
|
||
[ExecuteInEditMode]
|
||
[AddComponentMenu("NGUI/Internal/Draw Call")]
|
||
public class UIDrawCall : MonoBehaviour
|
||
{
|
||
static Dictionary<int ,UIDrawCall> mActiveList = new Dictionary<int, UIDrawCall>();
|
||
static Queue<UIDrawCall> mInactiveList = new Queue<UIDrawCall>();
|
||
|
||
[System.Obsolete("Use UIDrawCall.activeList")]
|
||
static public Dictionary<int, UIDrawCall> list { get { return mActiveList; } }
|
||
|
||
/// <summary>
|
||
/// List of active draw calls.
|
||
/// </summary>
|
||
|
||
static public Dictionary<int, UIDrawCall> activeList { get { return mActiveList; } }
|
||
|
||
/// <summary>
|
||
/// List of inactive draw calls. Only used at run-time in order to avoid object creation/destruction.
|
||
/// </summary>
|
||
|
||
static public Queue<UIDrawCall> inactiveList { get { return mInactiveList; } }
|
||
|
||
static private Material[] emptyMaterials = new Material[] { };
|
||
|
||
//材质球缓存
|
||
static private Dictionary<Shader, List<Material>> cacheMatList = new Dictionary<Shader, List<Material>>();
|
||
|
||
public enum Clipping : int
|
||
{
|
||
None = 0,
|
||
TextureMask = 1, // Clipped using a texture rather than math
|
||
SoftClip = 3, // Alpha-based clipping with a softened edge
|
||
ConstrainButDontClip = 4, // No actual clipping, but does have an area
|
||
}
|
||
|
||
[HideInInspector][System.NonSerialized] public int widgetCount = 0;
|
||
[HideInInspector][System.NonSerialized] public int depthStart = int.MaxValue;
|
||
[HideInInspector][System.NonSerialized] public int depthEnd = int.MinValue;
|
||
[HideInInspector][System.NonSerialized] public UIPanel manager;
|
||
[HideInInspector][System.NonSerialized] public UIPanel panel;
|
||
[HideInInspector][System.NonSerialized] public Texture2D clipTexture;
|
||
[HideInInspector][System.NonSerialized] public bool alwaysOnScreen = false;
|
||
[HideInInspector][System.NonSerialized] public BetterList<Vector3> verts = new BetterList<Vector3>();
|
||
[HideInInspector][System.NonSerialized] public BetterList<Vector3> norms = new BetterList<Vector3>();
|
||
[HideInInspector][System.NonSerialized] public BetterList<Vector4> tans = new BetterList<Vector4>();
|
||
[HideInInspector][System.NonSerialized] public BetterList<Vector2> uvs = new BetterList<Vector2>();
|
||
[HideInInspector][System.NonSerialized] public BetterList<Color32> cols = new BetterList<Color32>();
|
||
|
||
Material mMaterial; // Material used by this draw call
|
||
Texture mTexture; // Main texture used by the material
|
||
#if FUNCELL_MODIFIED
|
||
string mShaderName;
|
||
#endif
|
||
Shader mShader; // Shader used by the dynamically created material
|
||
int mClipCount = 0; // Number of times the draw call's content is getting clipped
|
||
Transform mTrans; // Cached transform
|
||
Mesh mMesh; // First generated mesh
|
||
MeshFilter mFilter; // Mesh filter for this draw call
|
||
MeshRenderer mRenderer; // Mesh renderer for this screen
|
||
Material mDynamicMat; // Instantiated material
|
||
int[] mIndices; // Cached indices
|
||
|
||
bool mRebuildMat = true;
|
||
bool mLegacyShader = false;
|
||
int mRenderQueue = 3000;
|
||
int mTriangles = 0;
|
||
|
||
/// <summary>
|
||
/// Whether the draw call has changed recently.
|
||
/// </summary>
|
||
|
||
[System.NonSerialized]
|
||
public bool isDirty = false;
|
||
|
||
[System.NonSerialized]
|
||
bool mTextureClip = false;
|
||
|
||
public delegate void OnRenderCallback (Material mat);
|
||
|
||
/// <summary>
|
||
/// Callback that will be triggered at OnWillRenderObject() time.
|
||
/// </summary>
|
||
|
||
public OnRenderCallback onRender;
|
||
|
||
#if FUNCELL_MODIFIED
|
||
//是否为灰色
|
||
private bool _isGray = false;
|
||
public bool IsGray
|
||
{
|
||
get
|
||
{
|
||
return _isGray;
|
||
}
|
||
set
|
||
{
|
||
if (_isGray != value)
|
||
{
|
||
_isGray = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
//是否为OverLay叠加
|
||
private bool _isOverlay = false;
|
||
public bool IsOverlay
|
||
{
|
||
get
|
||
{
|
||
return _isOverlay;
|
||
}
|
||
set
|
||
{
|
||
if (_isOverlay != value)
|
||
{
|
||
_isOverlay = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
//是否为流光
|
||
private bool _isFlowLight = false;
|
||
public bool IsFlowLight
|
||
{
|
||
get
|
||
{
|
||
return _isFlowLight;
|
||
}
|
||
set
|
||
{
|
||
if (_isFlowLight != value)
|
||
{
|
||
_isFlowLight = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
//流光的颜色--这里使用整形,容易比较(很坑的是Color32不能比较,所以选择这个值)
|
||
//这里使用int来表示float,有效数字为10000.
|
||
private Vector3Int _flowColor = new Vector3Int(3000, 3000, 3000);
|
||
public Vector3Int FlowColor
|
||
{
|
||
get
|
||
{
|
||
return _flowColor;
|
||
}
|
||
set
|
||
{
|
||
if (_flowColor != value)
|
||
{
|
||
_flowColor = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
//流光的参数 v1:宽度--值越大就越细 v2:速度, 光在UI上流过的速度 v3:周期,周期越大,在UI上闪过的之后等待时间越长
|
||
//这里使用int来表示float,有效数字为10000.
|
||
private Vector3Int _flowParam = new Vector3Int(60000, 15000, 40000);
|
||
public Vector3Int FlowParam
|
||
{
|
||
get
|
||
{
|
||
return _flowParam;
|
||
}
|
||
|
||
set
|
||
{
|
||
if (_flowParam != value)
|
||
{
|
||
_flowParam = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
/// <summary>
|
||
/// Render queue used by the draw call.
|
||
/// </summary>
|
||
|
||
public int renderQueue
|
||
{
|
||
get
|
||
{
|
||
return mRenderQueue;
|
||
}
|
||
set
|
||
{
|
||
if (mRenderQueue != value)
|
||
{
|
||
mRenderQueue = value;
|
||
|
||
if (mDynamicMat != null)
|
||
{
|
||
mDynamicMat.renderQueue = value;
|
||
#if UNITY_EDITOR
|
||
if (mRenderer != null) mRenderer.enabled = isActive;
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Renderer's sorting order, to be used with Unity's 2D system.
|
||
/// </summary>
|
||
|
||
public int sortingOrder
|
||
{
|
||
get { return (mRenderer != null) ? mRenderer.sortingOrder : 0; }
|
||
set { if (mRenderer != null && mRenderer.sortingOrder != value) mRenderer.sortingOrder = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Final render queue used to draw the draw call's geometry.
|
||
/// </summary>
|
||
|
||
public int finalRenderQueue
|
||
{
|
||
get
|
||
{
|
||
return (mDynamicMat != null) ? mDynamicMat.renderQueue : mRenderQueue;
|
||
}
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
|
||
/// <summary>
|
||
/// Whether the draw call is currently active.
|
||
/// </summary>
|
||
|
||
public bool isActive
|
||
{
|
||
get
|
||
{
|
||
return mActive;
|
||
}
|
||
set
|
||
{
|
||
if (mActive != value)
|
||
{
|
||
mActive = value;
|
||
|
||
if (mRenderer != null)
|
||
{
|
||
mRenderer.enabled = value;
|
||
NGUITools.SetDirty(gameObject);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
bool mActive = true;
|
||
#endif
|
||
|
||
private bool _isCachedTrans = false;
|
||
/// <summary>
|
||
/// Transform is cached for speed and efficiency.
|
||
/// </summary>
|
||
public Transform cachedTransform
|
||
{
|
||
get
|
||
{
|
||
if (!_isCachedTrans)
|
||
{
|
||
mTrans = transform;
|
||
_isCachedTrans = true;
|
||
}
|
||
return mTrans;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Material used by this screen.
|
||
/// </summary>
|
||
|
||
public Material baseMaterial
|
||
{
|
||
get
|
||
{
|
||
return mMaterial;
|
||
}
|
||
set
|
||
{
|
||
if (mMaterial != value)
|
||
{
|
||
mMaterial = value;
|
||
mRebuildMat = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Dynamically created material used by the draw call to actually draw the geometry.
|
||
/// </summary>
|
||
|
||
public Material dynamicMaterial { get { return mDynamicMat; } }
|
||
|
||
/// <summary>
|
||
/// Texture used by the material.
|
||
/// </summary>
|
||
|
||
public Texture mainTexture
|
||
{
|
||
get
|
||
{
|
||
return mTexture;
|
||
}
|
||
set
|
||
{
|
||
mTexture = value;
|
||
if (mDynamicMat != null) mDynamicMat.mainTexture = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Shader used by the material.
|
||
/// </summary>
|
||
|
||
public Shader shader
|
||
{
|
||
get
|
||
{
|
||
return mShader;
|
||
}
|
||
set
|
||
{
|
||
if (mShader != value)
|
||
{
|
||
mShader = value;
|
||
mRebuildMat = true;
|
||
if(mShader != null)
|
||
{
|
||
mShaderName = mShader.name;
|
||
}
|
||
else
|
||
{
|
||
mShaderName = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// The number of triangles in this draw call.
|
||
/// </summary>
|
||
|
||
public int triangles { get { return (mMesh != null) ? mTriangles : 0; } }
|
||
|
||
/// <summary>
|
||
/// Whether the draw call is currently using a clipped shader.
|
||
/// </summary>
|
||
|
||
public bool isClipped { get { return mClipCount != 0; } }
|
||
|
||
|
||
|
||
void FreeDynamicMat(Material mat)
|
||
{
|
||
List<Material> matList = null;
|
||
if (!cacheMatList.TryGetValue(shader, out matList))
|
||
{
|
||
matList = new List<Material>();
|
||
cacheMatList.Add(shader, matList);
|
||
}
|
||
mat.SetTexture("_MainTex", null);
|
||
if(!string.IsNullOrEmpty(mShaderName) && mShaderName.Contains("RGB"))
|
||
{
|
||
mat.SetTexture("_AlphaTex", null);
|
||
}
|
||
matList.Add(mat);
|
||
}
|
||
Material GetDynamicMat(Shader shader)
|
||
{
|
||
Material result = null;
|
||
List<Material> matList = null;
|
||
if (cacheMatList.TryGetValue(shader, out matList) && matList.Count > 0)
|
||
{
|
||
result = matList[matList.Count - 1];
|
||
matList.RemoveAt(matList.Count - 1);
|
||
}
|
||
else
|
||
{
|
||
result = new Material(shader);
|
||
result.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
|
||
}
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// Create an appropriate material for the draw call.
|
||
/// </summary>
|
||
|
||
void CreateMaterial ()
|
||
{
|
||
mTextureClip = false;
|
||
mLegacyShader = false;
|
||
mClipCount = (panel != null) ? panel.clipCount : 0;
|
||
#if FUNCELL_MODIFIED
|
||
#if NGUI_USE_RGB
|
||
string shaderName = !string.IsNullOrEmpty(mShaderName) ? mShaderName : ((mMaterial != null) ? mMaterial.shader.name : "Unlit/Transparent Colored_RGB");
|
||
#else
|
||
string shaderName = !string.IsNullOrEmpty(mShaderName) ? mShaderName : ((mMaterial != null) ? mMaterial.shader.name : "Unlit/Transparent Colored");
|
||
#endif
|
||
#else
|
||
#if NGUI_USE_RGB
|
||
string shaderName = (mShader != null) ? mShader.name : ((mMaterial != null) ? mMaterial.shader.name : "Unlit/Transparent Colored_RGB");
|
||
#else
|
||
string shaderName = (mShader != null) ? mShader.name : ((mMaterial != null) ? mMaterial.shader.name : "Unlit/Transparent Colored");
|
||
#endif
|
||
#endif
|
||
|
||
//这里的shader是编译后的,并且在包体内没有这个shader
|
||
bool mshaderInPackage = true;
|
||
if (mShader != null)
|
||
{
|
||
var sh = Shader.Find(mShader.name);
|
||
if (sh == null)
|
||
{
|
||
mshaderInPackage = false;
|
||
}
|
||
}
|
||
|
||
//如果当前shader在包体内
|
||
if (mshaderInPackage)
|
||
{
|
||
// Figure out the normal shader's name
|
||
shaderName = shaderName.Replace("GUI/Text Shader", "Unlit/Text");
|
||
|
||
if (shaderName.Length > 2)
|
||
{
|
||
if (shaderName[shaderName.Length - 2] == ' ')
|
||
{
|
||
int index = shaderName[shaderName.Length - 1];
|
||
if (index > '0' && index <= '9') shaderName = shaderName.Substring(0, shaderName.Length - 2);
|
||
}
|
||
}
|
||
|
||
if (shaderName.StartsWith("Hidden/"))
|
||
shaderName = shaderName.Substring(7);
|
||
|
||
// Legacy functionality
|
||
const string soft = " (SoftClip)";
|
||
shaderName = shaderName.Replace(soft, "");
|
||
|
||
const string textureClip = " (TextureClip)";
|
||
shaderName = shaderName.Replace(textureClip, "");
|
||
|
||
if (panel != null && panel.clipping == Clipping.TextureMask)
|
||
{
|
||
mTextureClip = true;
|
||
shader = Shader.Find("Hidden/" + shaderName + textureClip);
|
||
}
|
||
else if (mClipCount != 0)
|
||
{
|
||
shader = Shader.Find("Hidden/" + shaderName + " " + mClipCount);
|
||
if (shader == null) shader = Shader.Find(shaderName + " " + mClipCount);
|
||
|
||
// Legacy functionality
|
||
if (shader == null && mClipCount == 1)
|
||
{
|
||
mLegacyShader = true;
|
||
shader = Shader.Find(shaderName + soft);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
shader = Shader.Find(shaderName);
|
||
}
|
||
#if NGUI_USE_RGB
|
||
if (shader == null) shader = Shader.Find("Unlit/Transparent Colored_RGB");
|
||
#else
|
||
// Always fallback to the default shader
|
||
if (shader == null) shader = Shader.Find("Unlit/Transparent Colored");
|
||
#endif
|
||
}
|
||
else
|
||
{//如果不在包体内,那么就直接使用它
|
||
shader = mShader;
|
||
}
|
||
|
||
if (mMaterial != null)
|
||
{
|
||
//mDynamicMat = new Material(mMaterial);
|
||
if(shader != null)
|
||
{
|
||
mDynamicMat = GetDynamicMat(shader);
|
||
}
|
||
else
|
||
{
|
||
mDynamicMat = GetDynamicMat(mMaterial.shader);
|
||
}
|
||
//mDynamicMat.name = "[NGUI] " + mMaterial.name;
|
||
mDynamicMat.CopyPropertiesFromMaterial(mMaterial);
|
||
#if !UNITY_FLASH
|
||
string[] keywords = mMaterial.shaderKeywords;
|
||
for (int i = 0; i < keywords.Length; ++i)
|
||
{
|
||
mDynamicMat.EnableKeyword(keywords[i]);
|
||
}
|
||
#endif
|
||
// If there is a valid shader, assign it to the custom material
|
||
if (shader != null)
|
||
{
|
||
//mDynamicMat.shader = shader;
|
||
}
|
||
else if (mClipCount != 0)
|
||
{
|
||
Debug.LogError(shaderName + " shader doesn't have a clipped shader version for " + mClipCount + " clip regions");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
mDynamicMat = GetDynamicMat(shader);
|
||
//mDynamicMat = new Material(shader);
|
||
//mDynamicMat.name = "[NGUI] " + shader.name;
|
||
}
|
||
#if FUNCELL_MODIFIED
|
||
if (_isGray)
|
||
{
|
||
mDynamicMat.EnableKeyword("_USE_GRAY_ON");
|
||
mDynamicMat.DisableKeyword("_USE_GRAY_OFF");
|
||
}
|
||
else
|
||
{
|
||
mDynamicMat.DisableKeyword("_USE_GRAY_ON");
|
||
mDynamicMat.EnableKeyword("_USE_GRAY_OFF");
|
||
}
|
||
|
||
if (_isFlowLight)
|
||
{
|
||
mDynamicMat.EnableKeyword("_USE_UI_FLOW_LIGHT_ON");
|
||
mDynamicMat.DisableKeyword("_USE_UI_FLOW_LIGHT_OFF");
|
||
mDynamicMat.SetColor("_FlowColor", new Color(_flowColor.x * 0.0001f, _flowColor.y * 0.0001f, _flowColor.z * 0.0001f));
|
||
mDynamicMat.SetFloat("_FlowWidth", _flowParam.x * 0.0001f);
|
||
mDynamicMat.SetFloat("_FlowSpeed", _flowParam.y * 0.0001f);
|
||
mDynamicMat.SetFloat("_FlowPeriod", _flowParam.z * 0.0001f);
|
||
}
|
||
else
|
||
{
|
||
mDynamicMat.DisableKeyword("_USE_UI_FLOW_LIGHT_ON");
|
||
mDynamicMat.EnableKeyword("_USE_UI_FLOW_LIGHT_OFF");
|
||
}
|
||
|
||
if (_isOverlay)
|
||
{
|
||
mDynamicMat.EnableKeyword("_USE_OVERLAY_ON");
|
||
mDynamicMat.DisableKeyword("_USE_OVERLAY_OFF");
|
||
}
|
||
else
|
||
{
|
||
mDynamicMat.DisableKeyword("_USE_OVERLAY_ON");
|
||
mDynamicMat.EnableKeyword("_USE_OVERLAY_OFF");
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuild the draw call's material.
|
||
/// </summary>
|
||
|
||
Material RebuildMaterial ()
|
||
{
|
||
// Destroy the old material
|
||
if(mDynamicMat != null)
|
||
{
|
||
FreeDynamicMat(mDynamicMat);
|
||
}
|
||
//NGUITools.DestroyImmediate(mDynamicMat);
|
||
|
||
// Create a new material
|
||
CreateMaterial();
|
||
mDynamicMat.renderQueue = mRenderQueue;
|
||
|
||
// Assign the main texture
|
||
if (mTexture != null) mDynamicMat.mainTexture = mTexture;
|
||
|
||
// Update the renderer
|
||
if (mRenderer != null) mRenderer.sharedMaterials = new Material[] { mDynamicMat };
|
||
return mDynamicMat;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update the renderer's materials.
|
||
/// </summary>
|
||
|
||
void UpdateMaterials ()
|
||
{
|
||
if (panel == null) return;
|
||
|
||
// If clipping should be used, we need to find a replacement shader
|
||
if (mRebuildMat || mDynamicMat == null || mClipCount != panel.clipCount || mTextureClip != (panel.clipping == Clipping.TextureMask))
|
||
{
|
||
RebuildMaterial();
|
||
mRebuildMat = false;
|
||
}
|
||
else if (mRenderer.sharedMaterial != mDynamicMat)
|
||
{
|
||
#if UNITY_EDITOR
|
||
Debug.LogError("Hmm... This point got hit!");
|
||
#endif
|
||
mRenderer.sharedMaterials = new Material[] { mDynamicMat };
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the draw call's geometry.
|
||
/// </summary>
|
||
|
||
private void SetCallback(int[] array)
|
||
{
|
||
mIndices = array;
|
||
mMesh.triangles = mIndices;
|
||
}
|
||
|
||
Nordeus.DataStructures.VaryingIntList.ArrayAction _setCallback = null;
|
||
|
||
const int maxIndexBufferCache = 10;
|
||
private static int getindexcnt = 0;
|
||
private static int shotcnt = 0;
|
||
|
||
#if UNITY_FLASH
|
||
List<int[]> mCache = new List<int[]>(maxIndexBufferCache);
|
||
#else
|
||
//static List<int[]> mCache = new List<int[]>(maxIndexBufferCache);
|
||
//#if !OPTIMISE_NGUI_GC_ALLOC
|
||
// static List<int[]> mCache = new List<int[]>(maxIndexBufferCache);
|
||
//#else
|
||
//优化NGUI GC
|
||
public static Nordeus.DataStructures.VaryingIntList mCache = new Nordeus.DataStructures.VaryingIntList();
|
||
//优化NGUI GC
|
||
#endif
|
||
|
||
public void UpdateGeometry()
|
||
{
|
||
if (_setCallback == null) _setCallback = SetCallback;
|
||
int count = verts.size;
|
||
|
||
// Safety check to ensure we get valid values
|
||
if (count > 0 && (count == uvs.size && count == cols.size) && (count % 4) == 0)
|
||
{
|
||
// Cache all components
|
||
if (mFilter == null) mFilter = gameObject.GetComponent<MeshFilter>();
|
||
if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();
|
||
|
||
if (verts.size < 65000)
|
||
{
|
||
// Populate the index buffer
|
||
int indexCount = (count >> 1) * 3;
|
||
bool setIndices = (mIndices == null || mIndices.Length != indexCount);
|
||
|
||
// Create the mesh
|
||
if (mMesh == null)
|
||
{
|
||
mMesh = new Mesh();
|
||
mMesh.hideFlags = HideFlags.DontSave;
|
||
mMesh.name = (mMaterial != null) ? mMaterial.name : "Mesh";
|
||
mMesh.MarkDynamic();
|
||
setIndices = true;
|
||
}
|
||
#if !UNITY_FLASH
|
||
// If the buffer length doesn't match, we need to trim all buffers
|
||
bool trim = (uvs.buffer.Length != verts.buffer.Length) ||
|
||
(cols.buffer.Length != verts.buffer.Length) ||
|
||
(norms.buffer != null && norms.buffer.Length != verts.buffer.Length) ||
|
||
(tans.buffer != null && tans.buffer.Length != verts.buffer.Length);
|
||
|
||
// Non-automatic render queues rely on Z position, so it's a good idea to trim everything
|
||
if (!trim && panel != null && panel.renderQueue != UIPanel.RenderQueue.Automatic)
|
||
trim = (mMesh == null || mMesh.vertexCount != verts.buffer.Length);
|
||
|
||
// NOTE: Apparently there is a bug with Adreno devices:
|
||
// http://www.tasharen.com/forum/index.php?topic=8415.0
|
||
#if !UNITY_ANDROID
|
||
// If the number of vertices in the buffer is less than half of the full buffer, trim it
|
||
if (!trim && (verts.size << 1) < verts.buffer.Length) trim = true;
|
||
#endif
|
||
mTriangles = (verts.size >> 1);
|
||
|
||
if (trim || verts.buffer.Length > 65000)
|
||
{
|
||
if (trim || mMesh.vertexCount != verts.size)
|
||
{
|
||
mMesh.Clear();
|
||
setIndices = true;
|
||
}
|
||
|
||
//mMesh.vertices = verts.ToArray();
|
||
//mMesh.uv = uvs.ToArray();
|
||
//mMesh.uv2 = uv2s.ToArray();
|
||
//mMesh.colors32 = cols.ToArray();
|
||
FillVertsMeshData(verts);
|
||
FillUvMeshData(uvs);
|
||
FillColsMeshData(cols);
|
||
|
||
//if (norms != null) mMesh.normals = norms.ToArray();
|
||
//if (tans != null) mMesh.tangents = tans.ToArray();
|
||
if (norms != null) FillNormalMeshData(norms);
|
||
if (tans != null) FillTangentsMeshData(tans);
|
||
}
|
||
else
|
||
{
|
||
if (mMesh.vertexCount != verts.buffer.Length)
|
||
{
|
||
mMesh.Clear();
|
||
setIndices = true;
|
||
}
|
||
|
||
mMesh.vertices = verts.buffer;
|
||
mMesh.uv = uvs.buffer;
|
||
mMesh.colors32 = cols.buffer;
|
||
|
||
if (norms != null) mMesh.normals = norms.buffer;
|
||
if (tans != null) mMesh.tangents = tans.buffer;
|
||
}
|
||
#else
|
||
mTriangles = (verts.size >> 1);
|
||
|
||
if (mMesh.vertexCount != verts.size)
|
||
{
|
||
mMesh.Clear();
|
||
setIndices = true;
|
||
}
|
||
|
||
mMesh.vertices = verts.ToArray();
|
||
mMesh.uv = uvs.ToArray();
|
||
mMesh.colors32 = cols.ToArray();
|
||
|
||
if (norms != null) mMesh.normals = norms.ToArray();
|
||
if (tans != null) mMesh.tangents = tans.ToArray();
|
||
#endif
|
||
if (setIndices)
|
||
{
|
||
//优化NGUI GC
|
||
//GenerateCachedIndexBuffer(count, indexCount, SetCallback);
|
||
getindexcnt++;
|
||
if (mCache.size < indexCount)
|
||
{
|
||
mCache.MakeLargerThan(indexCount);
|
||
for (int i = mCache.size / 3 * 2; i < count; i += 4)
|
||
{
|
||
mCache.Add(i);
|
||
mCache.Add(i + 1);
|
||
mCache.Add(i + 2);
|
||
|
||
mCache.Add(i + 2);
|
||
mCache.Add(i + 3);
|
||
mCache.Add(i);
|
||
}
|
||
}
|
||
AsArrayOfLength(indexCount);
|
||
//mCache.AsArrayOfLength(indexCount, SetCallback);
|
||
//优化NGUI GC
|
||
//mIndices = GenerateCachedIndexBuffer(count, indexCount);
|
||
//mMesh.triangles = mIndices;
|
||
}
|
||
|
||
#if !UNITY_FLASH
|
||
if (trim || !alwaysOnScreen)
|
||
#endif
|
||
mMesh.RecalculateBounds();
|
||
|
||
mFilter.mesh = mMesh;
|
||
}
|
||
else
|
||
{
|
||
mTriangles = 0;
|
||
if (mFilter.mesh != null) mFilter.mesh.Clear();
|
||
Debug.LogError("Too many vertices on one panel: " + verts.size);
|
||
}
|
||
|
||
if (mRenderer == null) mRenderer = gameObject.GetComponent<MeshRenderer>();
|
||
|
||
if (mRenderer == null)
|
||
{
|
||
mRenderer = gameObject.AddComponent<MeshRenderer>();
|
||
#if UNITY_EDITOR
|
||
mRenderer.enabled = isActive;
|
||
#endif
|
||
}
|
||
UpdateMaterials();
|
||
}
|
||
else
|
||
{
|
||
if (mFilter.mesh != null) mFilter.mesh.Clear();
|
||
Debug.LogError("UIWidgets must fill the buffer with 4 vertices per quad. Found " + count);
|
||
}
|
||
|
||
verts.Clear();
|
||
uvs.Clear();
|
||
cols.Clear();
|
||
norms.Clear();
|
||
tans.Clear();
|
||
}
|
||
|
||
#region//unsafe function
|
||
public unsafe void* GetVector4BufferPointer(BetterList<Vector4> btList)
|
||
{
|
||
fixed (void* pBuffer = btList.buffer)
|
||
{
|
||
return pBuffer;
|
||
}
|
||
}
|
||
|
||
public unsafe void* GetVector3BufferPointer(BetterList<Vector3> btList)
|
||
{
|
||
fixed (void* pBuffer = btList.buffer)
|
||
{
|
||
return pBuffer;
|
||
}
|
||
}
|
||
|
||
public unsafe void* GetVector2BufferPointer(BetterList<Vector2> btList)
|
||
{
|
||
fixed (void* pBuffer = btList.buffer)
|
||
{
|
||
return pBuffer;
|
||
}
|
||
}
|
||
|
||
public unsafe void* GetColorBufferPointer(BetterList<Color32> btList)
|
||
{
|
||
fixed (void* pBuffer = btList.buffer)
|
||
{
|
||
return pBuffer;
|
||
}
|
||
}
|
||
|
||
//填充mesh 的数据
|
||
public unsafe void FillVertsMeshData(BetterList<Vector3> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetVector3BufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.vertices = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
public unsafe void FillUvMeshData(BetterList<Vector2> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetVector2BufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.uv = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
public unsafe void FillUv2MeshData(BetterList<Vector2> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetVector2BufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.uv2 = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
public unsafe void FillColsMeshData(BetterList<Color32> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetColorBufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.colors32 = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
public unsafe void FillNormalMeshData(BetterList<Vector3> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetVector3BufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.normals = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
public unsafe void FillTangentsMeshData(BetterList<Vector4> btList)
|
||
{
|
||
if (btList.size <= 0) return;
|
||
void* pBuffer = GetVector4BufferPointer(btList);
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)btList.size);
|
||
|
||
mMesh.tangents = btList.buffer;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
|
||
//优化NGUI GC
|
||
public unsafe void AsArrayOfLength(int length)
|
||
{
|
||
if (length <= 0) return;
|
||
if (length > mCache.size) length = mCache.size;
|
||
void* pBuffer = mCache.GetBufferPointer();
|
||
|
||
// Get the header
|
||
ArrayHeader* header = (ArrayHeader*)pBuffer - 1;
|
||
|
||
// Change the length
|
||
UIntPtr originalLength = header->length;
|
||
header->length = new UIntPtr((ulong)length);
|
||
|
||
// Do stuff with the changed array
|
||
//if (action != null)
|
||
//{
|
||
// action(buffer);
|
||
//}
|
||
mIndices = mCache.buffer;
|
||
mMesh.triangles = mIndices;
|
||
|
||
// Revert back to old length
|
||
header->length = originalLength;
|
||
}
|
||
//优化NGUI GC
|
||
#endregion
|
||
|
||
public static void PrintCache()
|
||
{
|
||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||
sb.AppendLine("DrawCall PrintCache:" + mCache.Count);
|
||
int sum = 0;
|
||
for (int i = 0; i < mCache.Count; i++)
|
||
{
|
||
sb.AppendLine("i=" + i + ";;len:" + mCache.buffer.Length);
|
||
sum += mCache.buffer.Length;
|
||
}
|
||
sb.AppendLine("Sum:" + sum);
|
||
sb.AppendLine("Percent:" + shotcnt + "/" + getindexcnt + "==" + ((float)shotcnt / (float)getindexcnt));
|
||
Debug.Log(sb.ToString());
|
||
}
|
||
/// <summary>
|
||
/// Generates a new index buffer for the specified number of vertices (or reuses an existing one).
|
||
/// </summary>
|
||
|
||
//优化NGUI GC
|
||
void GenerateCachedIndexBuffer(int vertexCount, int indexCount, Nordeus.DataStructures.VaryingIntList.ArrayAction action)
|
||
{
|
||
getindexcnt++;
|
||
if (mCache.size < indexCount)
|
||
{
|
||
mCache.MakeLargerThan(indexCount);
|
||
for (int i = mCache.size / 3 * 2; i < vertexCount; i += 4)
|
||
{
|
||
mCache.Add(i);
|
||
mCache.Add(i + 1);
|
||
mCache.Add(i + 2);
|
||
|
||
mCache.Add(i + 2);
|
||
mCache.Add(i + 3);
|
||
mCache.Add(i);
|
||
}
|
||
}
|
||
mCache.AsArrayOfLength(indexCount, action);
|
||
}
|
||
//优化NGUI GC
|
||
// int[] GenerateCachedIndexBuffer (int vertexCount, int indexCount)
|
||
//{
|
||
// for (int i = 0, imax = mCache.Count; i < imax; ++i)
|
||
// {
|
||
// int[] ids = mCache[i];
|
||
// if (ids != null && ids.Length == indexCount)
|
||
// return ids;
|
||
// }
|
||
|
||
// int[] rv = new int[indexCount];
|
||
// int index = 0;
|
||
|
||
// for (int i = 0; i < vertexCount; i += 4)
|
||
// {
|
||
// rv[index++] = i;
|
||
// rv[index++] = i + 1;
|
||
// rv[index++] = i + 2;
|
||
|
||
// rv[index++] = i + 2;
|
||
// rv[index++] = i + 3;
|
||
// rv[index++] = i;
|
||
// }
|
||
|
||
// if (mCache.Count > maxIndexBufferCache) mCache.RemoveAt(0);
|
||
// mCache.Add(rv);
|
||
// return rv;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// This function is called when it's clear that the object will be rendered.
|
||
/// We want to set the shader used by the material, creating a copy of the material in the process.
|
||
/// We also want to update the material's properties before it's actually used.
|
||
/// </summary>
|
||
|
||
void OnWillRenderObject ()
|
||
{
|
||
UpdateMaterials();
|
||
|
||
if (onRender != null)
|
||
{
|
||
onRender(mDynamicMat ?? mMaterial);
|
||
}
|
||
if (mDynamicMat == null || mClipCount == 0) return;
|
||
|
||
if (mTextureClip)
|
||
{
|
||
Vector4 cr = panel.drawCallClipRange;
|
||
Vector2 soft = panel.clipSoftness;
|
||
|
||
Vector2 sharpness = new Vector2(1000.0f, 1000.0f);
|
||
if (soft.x > 0f) sharpness.x = cr.z / soft.x;
|
||
if (soft.y > 0f) sharpness.y = cr.w / soft.y;
|
||
|
||
mDynamicMat.SetVector(ClipRange[0], new Vector4(-cr.x / cr.z, -cr.y / cr.w, 1f / cr.z, 1f / cr.w));
|
||
mDynamicMat.SetTexture("_ClipTex", clipTexture);
|
||
}
|
||
else if (!mLegacyShader)
|
||
{
|
||
ProcessPanelClip(panel, mDynamicMat);
|
||
}
|
||
else // Legacy functionality
|
||
{
|
||
Vector2 soft = panel.clipSoftness;
|
||
Vector4 cr = panel.drawCallClipRange;
|
||
Vector2 v0 = new Vector2(-cr.x / cr.z, -cr.y / cr.w);
|
||
Vector2 v1 = new Vector2(1f / cr.z, 1f / cr.w);
|
||
|
||
Vector2 sharpness = new Vector2(1000.0f, 1000.0f);
|
||
if (soft.x > 0f) sharpness.x = cr.z / soft.x;
|
||
if (soft.y > 0f) sharpness.y = cr.w / soft.y;
|
||
|
||
mDynamicMat.mainTextureOffset = v0;
|
||
mDynamicMat.mainTextureScale = v1;
|
||
mDynamicMat.SetVector("_ClipSharpness", sharpness);
|
||
}
|
||
}
|
||
|
||
static int[] ClipRange = null;
|
||
static int[] ClipArgs = null;
|
||
|
||
public static void InitClipArgs()
|
||
{
|
||
if (ClipRange == null)
|
||
{
|
||
ClipRange = new int[]
|
||
{
|
||
Shader.PropertyToID("_ClipRange0"),
|
||
Shader.PropertyToID("_ClipRange1"),
|
||
Shader.PropertyToID("_ClipRange2"),
|
||
Shader.PropertyToID("_ClipRange4"),
|
||
};
|
||
}
|
||
|
||
if (ClipArgs == null)
|
||
{
|
||
ClipArgs = new int[]
|
||
{
|
||
Shader.PropertyToID("_ClipArgs0"),
|
||
Shader.PropertyToID("_ClipArgs1"),
|
||
Shader.PropertyToID("_ClipArgs2"),
|
||
Shader.PropertyToID("_ClipArgs3"),
|
||
};
|
||
}
|
||
|
||
}
|
||
|
||
#if FUNCELL_MODIFIED
|
||
public static void SetClippingEx(Material mat,int index, Vector4 cr, Vector2 soft, Vector4 softHide, float angle)
|
||
#else
|
||
public staticvoid SetClippingEx (int index, Vector4 cr, Vector2 soft, float angle)
|
||
#endif
|
||
{
|
||
angle *= -Mathf.Deg2Rad;
|
||
|
||
Vector2 sharpness = new Vector2(1000.0f, 1000.0f);
|
||
if (soft.x > 0f) sharpness.x = cr.z / soft.x;
|
||
if (soft.y > 0f) sharpness.y = cr.w / soft.y;
|
||
|
||
if (index < ClipRange.Length)
|
||
{
|
||
//Debug.Log("ClipRange::" + new Vector4(-cr.x / cr.z, -cr.y / cr.w, 1f / cr.z, 1f / cr.w).ToString());
|
||
//Debug.Log("ClipArgs::" + new Vector4(sharpness.x, sharpness.y, Mathf.Sin(angle), Mathf.Cos(angle)).ToString());
|
||
|
||
mat.SetVector(ClipRange[index], new Vector4(-cr.x / cr.z, -cr.y / cr.w, 1f / cr.z, 1f / cr.w));
|
||
mat.SetVector(ClipArgs[index], new Vector4(sharpness.x, sharpness.y, Mathf.Sin(angle), Mathf.Cos(angle)));
|
||
|
||
#if FUNCELL_MODIFIED
|
||
//修改只针对一层的剪切
|
||
if (index == 0)
|
||
{
|
||
//Debug.Log(";;;" + softHide);
|
||
mat.SetVector("_ClipSoftnessHide", softHide);
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
|
||
public static void ProcessPanelClip(UIPanel panel,Material mat)
|
||
{
|
||
UIPanel currentPanel = panel;
|
||
|
||
for (int i = 0; currentPanel != null;)
|
||
{
|
||
if (currentPanel.hasClipping)
|
||
{
|
||
float angle = 0f;
|
||
Vector4 cr = currentPanel.drawCallClipRange;
|
||
|
||
// Clipping regions past the first one need additional math
|
||
if (currentPanel != panel)
|
||
{
|
||
Vector3 pos = currentPanel.cachedTransform.InverseTransformPoint(panel.cachedTransform.position);
|
||
cr.x -= pos.x;
|
||
cr.y -= pos.y;
|
||
|
||
Vector3 v0 = panel.cachedTransform.rotation.eulerAngles;
|
||
Vector3 v1 = currentPanel.cachedTransform.rotation.eulerAngles;
|
||
Vector3 diff = v1 - v0;
|
||
|
||
diff.x = NGUIMath.WrapAngle(diff.x);
|
||
diff.y = NGUIMath.WrapAngle(diff.y);
|
||
diff.z = NGUIMath.WrapAngle(diff.z);
|
||
|
||
if (Mathf.Abs(diff.x) > 0.001f || Mathf.Abs(diff.y) > 0.001f)
|
||
Debug.LogWarning("Panel can only be clipped properly if X and Y rotation is left at 0", panel);
|
||
|
||
angle = diff.z;
|
||
}
|
||
#if FUNCELL_MODIFIED
|
||
SetClippingEx(mat,i++, cr, currentPanel.clipSoftness, currentPanel.ClipSoftnessHide, angle);
|
||
#else
|
||
// Pass the clipping parameters to the shader
|
||
SetClippingEx(mat,i++, cr, currentPanel.clipSoftness, angle);
|
||
#endif
|
||
}
|
||
currentPanel = currentPanel.parentPanel;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the shader clipping parameters.
|
||
/// </summary>
|
||
#if FUNCELL_MODIFIED
|
||
void SetClipping (int index, Vector4 cr, Vector2 soft, Vector4 softHide, float angle)
|
||
#else
|
||
void SetClipping (int index, Vector4 cr, Vector2 soft, float angle)
|
||
#endif
|
||
{
|
||
#if FUNCELL_MODIFIED
|
||
SetClippingEx(mDynamicMat, index, cr, soft, softHide, angle);
|
||
#else
|
||
SetClippingEx(mDynamicMat, index, cr, soft, angle);
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// Cache the property IDs.
|
||
/// </summary>
|
||
|
||
void Awake ()
|
||
{
|
||
InitClipArgs();
|
||
#if FUNCELL_MODIFIED
|
||
if (mShader != null)
|
||
{
|
||
mShaderName = mShader.name;
|
||
}
|
||
else
|
||
{
|
||
mShaderName = null;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// The material should be rebuilt when the draw call is enabled.
|
||
/// </summary>
|
||
|
||
void OnEnable () { mRebuildMat = true; }
|
||
|
||
/// <summary>
|
||
/// Clear all references.
|
||
/// </summary>
|
||
|
||
void OnDisable ()
|
||
{
|
||
depthStart = int.MaxValue;
|
||
depthEnd = int.MinValue;
|
||
panel = null;
|
||
manager = null;
|
||
mMaterial = null;
|
||
mTexture = null;
|
||
clipTexture = null;
|
||
|
||
if (mRenderer != null)
|
||
mRenderer.sharedMaterials = emptyMaterials;
|
||
|
||
if (mDynamicMat != null)
|
||
{
|
||
FreeDynamicMat(mDynamicMat);
|
||
}
|
||
//NGUITools.DestroyImmediate(mDynamicMat);
|
||
mDynamicMat = null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Cleanup.
|
||
/// </summary>
|
||
|
||
void OnDestroy ()
|
||
{
|
||
NGUITools.DestroyImmediate(mMesh);
|
||
mMesh = null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return an existing draw call.
|
||
/// </summary>
|
||
|
||
static public UIDrawCall Create (UIPanel panel, Material mat, Texture tex, Shader shader)
|
||
{
|
||
#if UNITY_EDITOR
|
||
string name = null;
|
||
if (tex != null) name = tex.name;
|
||
else if (shader != null) name = shader.name;
|
||
else if (mat != null) name = mat.name;
|
||
return Create(name, panel, mat, tex, shader);
|
||
#else
|
||
return Create(null, panel, mat, tex, shader);
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create a new draw call, reusing an old one if possible.
|
||
/// </summary>
|
||
|
||
static UIDrawCall Create (string name, UIPanel pan, Material mat, Texture tex, Shader shader)
|
||
{
|
||
UIDrawCall dc = Create(name);
|
||
dc.gameObject.layer = pan.cachedGameObject.layer;
|
||
dc.baseMaterial = mat;
|
||
dc.mainTexture = tex;
|
||
dc.shader = shader;
|
||
dc.renderQueue = pan.startingRenderQueue;
|
||
dc.sortingOrder = pan.sortingOrder;
|
||
dc.manager = pan;
|
||
return dc;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create a new draw call, reusing an old one if possible.
|
||
/// </summary>
|
||
|
||
static UIDrawCall Create (string name)
|
||
{
|
||
#if SHOW_HIDDEN_OBJECTS && UNITY_EDITOR
|
||
name = (name != null) ? "_UIDrawCall [" + name + "]" : "DrawCall";
|
||
#endif
|
||
if (mInactiveList.Count > 0)
|
||
{
|
||
UIDrawCall dc = mInactiveList.Dequeue();
|
||
mActiveList.Add(dc.GetHashCode(), dc);
|
||
|
||
if (name != null) dc.name = name;
|
||
NGUITools.SetActive(dc.gameObject, true);
|
||
return dc;
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
// If we're in the editor, create the game object with hide flags set right away
|
||
GameObject go = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags(name,
|
||
#if SHOW_HIDDEN_OBJECTS
|
||
HideFlags.DontSave | HideFlags.NotEditable, typeof(UIDrawCall));
|
||
#else
|
||
HideFlags.HideAndDontSave, typeof(UIDrawCall));
|
||
#endif
|
||
UIDrawCall newDC = go.GetComponent<UIDrawCall>();
|
||
#else
|
||
GameObject go = new GameObject(name);
|
||
DontDestroyOnLoad(go);
|
||
UIDrawCall newDC = go.AddComponent<UIDrawCall>();
|
||
#endif
|
||
// Create the draw call
|
||
mActiveList.Add(newDC.GetHashCode(), newDC);
|
||
return newDC;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Clear all draw calls.
|
||
/// </summary>
|
||
|
||
static public void ClearAll ()
|
||
{
|
||
bool playing = Application.isPlaying;
|
||
|
||
var iter = mActiveList.GetEnumerator();
|
||
try
|
||
{
|
||
while(iter.MoveNext())
|
||
{
|
||
UIDrawCall dc = iter.Current.Value;
|
||
|
||
if (dc)
|
||
{
|
||
if (playing) NGUITools.SetActive(dc.gameObject, false);
|
||
else NGUITools.DestroyImmediate(dc.gameObject);
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
iter.Dispose();
|
||
}
|
||
mActiveList.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Immediately destroy all draw calls.
|
||
/// </summary>
|
||
|
||
static public void ReleaseAll ()
|
||
{
|
||
ClearAll();
|
||
ReleaseInactive();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Immediately destroy all inactive draw calls (draw calls that have been recycled and are waiting to be re-used).
|
||
/// </summary>
|
||
|
||
static public void ReleaseInactive()
|
||
{
|
||
while(mInactiveList.Count > 0)
|
||
{
|
||
var dc = mInactiveList.Dequeue();
|
||
if (dc) NGUITools.DestroyImmediate(dc.gameObject);
|
||
}
|
||
mInactiveList.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Count all draw calls managed by the specified panel.
|
||
/// </summary>
|
||
|
||
static public int Count (UIPanel panel)
|
||
{
|
||
int count = 0;
|
||
if(panel != null)
|
||
{
|
||
var iter = mActiveList.GetEnumerator();
|
||
try
|
||
{
|
||
while (iter.MoveNext())
|
||
{
|
||
if (iter.Current.Value.manager == panel)
|
||
{
|
||
++count;
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
iter.Dispose();
|
||
}
|
||
}
|
||
return count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Destroy the specified draw call.
|
||
/// </summary>
|
||
|
||
static public void Destroy(UIDrawCall dc)
|
||
{
|
||
if (dc)
|
||
{
|
||
dc.onRender = null;
|
||
if (Application.isPlaying)
|
||
{
|
||
if (mActiveList.Remove(dc.GetHashCode()))
|
||
{
|
||
NGUITools.SetActive(dc.gameObject, false);
|
||
mInactiveList.Enqueue(dc);
|
||
//优化NGUI GC
|
||
dc.FreeCache();
|
||
//优化NGUI GC
|
||
}
|
||
}
|
||
else
|
||
{
|
||
mActiveList.Remove(dc.GetHashCode());
|
||
#if SHOW_HIDDEN_OBJECTS && UNITY_EDITOR
|
||
if (UnityEditor.Selection.activeGameObject == dc.gameObject)
|
||
UnityEditor.Selection.activeGameObject = null;
|
||
#endif
|
||
NGUITools.DestroyImmediate(dc.gameObject);
|
||
}
|
||
}
|
||
}
|
||
|
||
//清理缓存
|
||
public void FreeCache()
|
||
{
|
||
CachedGeometries.Free(verts);
|
||
CachedGeometries.Free(uvs);
|
||
CachedGeometries.Free(cols);
|
||
verts = null;
|
||
uvs = null;
|
||
cols = null;
|
||
}
|
||
//检查缓存
|
||
public void CheckCacke(int vecCount)
|
||
{
|
||
if (verts == null || verts.buffer == null || verts.buffer.Length < vecCount)
|
||
{
|
||
FreeCache();
|
||
CachedGeometries.Get(vecCount, ref verts);
|
||
CachedGeometries.Get(vecCount, ref uvs);
|
||
CachedGeometries.Get(vecCount, ref cols);
|
||
}
|
||
}
|
||
}
|