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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|