public WriteToBuffers ( BetterList |
||
v | BetterList |
|
u | BetterList |
|
c | BetterList |
|
n | BetterList |
|
t | BetterList |
|
리턴 | void |
private void FillAllDrawCalls() { for (int i = 0; i < this.drawCalls.get_Count(); i++) { UIDrawCall.Destroy(this.drawCalls.get_Item(i)); } this.drawCalls.Clear(); Material material = null; Texture texture = null; Shader shader = null; UIDrawCall uIDrawCall = null; int num = 0; if (this.mSortWidgets) { this.SortWidgets(); } for (int j = 0; j < this.widgets.get_Count(); j++) { UIWidget uIWidget = this.widgets.get_Item(j); if (uIWidget.isVisible && uIWidget.hasVertices) { Material material2 = uIWidget.material; Texture mainTexture = uIWidget.mainTexture; Shader shader2 = uIWidget.shader; if (material != material2 || texture != mainTexture || shader != shader2) { if (uIDrawCall != null && uIDrawCall.verts.size != 0) { this.drawCalls.Add(uIDrawCall); uIDrawCall.UpdateGeometry(num); uIDrawCall.onRender = this.mOnRender; this.mOnRender = null; num = 0; uIDrawCall = null; } material = material2; texture = mainTexture; shader = shader2; } if (material != null || shader != null || texture != null) { if (uIDrawCall == null) { uIDrawCall = UIDrawCall.Create(this, material, texture, shader); uIDrawCall.depthStart = uIWidget.depth; uIDrawCall.depthEnd = uIDrawCall.depthStart; uIDrawCall.panel = this; } else { int depth = uIWidget.depth; if (depth < uIDrawCall.depthStart) { uIDrawCall.depthStart = depth; } if (depth > uIDrawCall.depthEnd) { uIDrawCall.depthEnd = depth; } } uIWidget.drawCall = uIDrawCall; num++; if (this.generateNormals) { uIWidget.WriteToBuffers(uIDrawCall.verts, uIDrawCall.uvs, uIDrawCall.cols, uIDrawCall.norms, uIDrawCall.tans); } else { uIWidget.WriteToBuffers(uIDrawCall.verts, uIDrawCall.uvs, uIDrawCall.cols, null, null); } if (uIWidget.mOnRender != null) { if (this.mOnRender == null) { this.mOnRender = uIWidget.mOnRender; } else { this.mOnRender = (UIDrawCall.OnRenderCallback)Delegate.Combine(this.mOnRender, uIWidget.mOnRender); } } } } else { uIWidget.drawCall = null; } } if (uIDrawCall != null && uIDrawCall.verts.size != 0) { this.drawCalls.Add(uIDrawCall); uIDrawCall.UpdateGeometry(num); uIDrawCall.onRender = this.mOnRender; this.mOnRender = null; } }
/// <summary> /// Convenience function that figures out the panel's correct change flag by searching the parents. /// </summary> int GetChangeFlag(UINode start) { int flag = start.changeFlag; if (flag == -1) { Transform trans = start.trans.parent; UINode sub; // Keep going until we find a set flag for (;;) { // Check the parent's flag #if USE_SIMPLE_DICTIONARY if (trans != null && mChildren.TryGetValue(trans, out sub)) { #else if (trans != null && mChildren.Contains(trans)) { sub = (UINode)mChildren[trans]; #endif flag = sub.changeFlag; trans = trans.parent; // If the flag hasn't been set either, add this child to the hierarchy if (flag == -1) { mHierarchy.Add(sub); } else { break; } } else { flag = 0; break; } } // Update the parent flags for (int i = 0, imax = mHierarchy.size; i < imax; ++i) { UINode pc = mHierarchy.buffer[i]; pc.changeFlag = flag; } mHierarchy.Clear(); } return(flag); } /// <summary> /// Run through all managed transforms and see if they've changed. /// </summary> void UpdateTransforms() { bool transformsChanged = false; bool shouldCull = false; #if UNITY_EDITOR shouldCull = (clipping != UIDrawCall.Clipping.None) && (!Application.isPlaying || (cullWhileDragging || mUpdateTime > mCullTime)); if (!Application.isPlaying || !widgetsAreStatic || mWidgetsAdded || shouldCull != mCulled) #else shouldCull = (clipping != UIDrawCall.Clipping.None) && (mUpdateTime > mCullTime); if (!widgetsAreStatic || mWidgetsAdded || shouldCull != mCulled) #endif { #if USE_SIMPLE_DICTIONARY foreach (KeyValuePair <Transform, UINode> child in mChildren) { UINode node = child.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode node = (UINode)mChildren[i]; #endif if (node.trans == null) { mRemoved.Add(node.trans); continue; } if (node.HasChanged()) { node.changeFlag = 1; transformsChanged = true; #if UNITY_EDITOR Vector3 s = node.trans.lossyScale; float min = Mathf.Abs(Mathf.Min(s.x, s.y)); if (min == 0f) { Debug.LogError("Scale of 0 is invalid! Zero cannot be divided by, which causes problems. Use a small value instead, such as 0.01\n" + node.trans.lossyScale, node.trans); } #endif } else { node.changeFlag = -1; } } // Clean up the deleted transforms for (int i = 0, imax = mRemoved.Count; i < imax; ++i) { mChildren.Remove(mRemoved[i]); } mRemoved.Clear(); } // If the children weren't culled but should be, check their visibility if (!mCulled && shouldCull) { mCheckVisibility = true; } // If something has changed, propagate the changes *down* the tree hierarchy (to children). // An alternative (but slower) approach would be to do a pc.trans.GetComponentsInChildren<UIWidget>() // in the loop above, and mark each one as dirty. if (mCheckVisibility || transformsChanged || mRebuildAll) { #if USE_SIMPLE_DICTIONARY foreach (KeyValuePair <Transform, UINode> child in mChildren) { UINode pc = child.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode pc = (UINode)mChildren[i]; #endif if (pc.widget != null) { int visibleFlag = 1; // No sense in checking the visibility if we're not culling anything (as the visibility is always 'true') if (shouldCull || transformsChanged) { // If the change flag has not yet been determined... if (pc.changeFlag == -1) { pc.changeFlag = GetChangeFlag(pc); } // Is the widget visible? if (shouldCull) { visibleFlag = (mCheckVisibility || pc.changeFlag == 1) ? (IsVisible(pc.widget) ? 1 : 0) : pc.visibleFlag; } } // If visibility changed, mark the node as changed as well if (pc.visibleFlag != visibleFlag) { pc.changeFlag = 1; } // If the node has changed and the widget is visible (or was visible before) if (pc.changeFlag == 1 && (visibleFlag == 1 || pc.visibleFlag != 0)) { // Update the visibility flag pc.visibleFlag = visibleFlag; Material mat = pc.widget.material; // Add this material to the list of changed materials if (!mChanged.Contains(mat)) { mChanged.Add(mat); } } } } } mCulled = shouldCull; mCheckVisibility = false; mWidgetsAdded = false; } /// <summary> /// Update all widgets and rebuild their geometry if necessary. /// </summary> void UpdateWidgets() { #if USE_SIMPLE_DICTIONARY foreach (KeyValuePair <Transform, UINode> c in mChildren) { UINode pc = c.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode pc = (UINode)mChildren[i]; #endif UIWidget w = pc.widget; // If the widget is visible, update it if (pc.visibleFlag == 1 && w != null && w.UpdateGeometry(this, ref worldToLocal, (pc.changeFlag == 1), generateNormals)) { // We will need to refill this buffer if (!mChanged.Contains(w.material)) { mChanged.Add(w.material); } } pc.changeFlag = 0; } } #endif /// <summary> /// Update the clipping rect in the shaders and draw calls' positions. /// </summary> public void UpdateDrawcalls() { Vector4 range = Vector4.zero; if (mClipping != UIDrawCall.Clipping.None) { range = new Vector4(mClipRange.x, mClipRange.y, mClipRange.z * 0.5f, mClipRange.w * 0.5f); } if (range.z == 0f) { range.z = Screen.width * 0.5f; } if (range.w == 0f) { range.w = Screen.height * 0.5f; } RuntimePlatform platform = Application.platform; if (platform == RuntimePlatform.WindowsPlayer || //platform == RuntimePlatform.WindowsWebPlayer || platform == RuntimePlatform.WindowsEditor) { range.x -= 0.5f; range.y += 0.5f; } Transform t = cachedTransform; UIDrawCall dc; Transform dt; for (int i = 0, imax = mDrawCalls.size; i < imax; ++i) { dc = mDrawCalls.buffer[i]; dc.clipping = mClipping; dc.clipRange = range; dc.clipSoftness = mClipSoftness; dc.depthPass = depthPass && mClipping == UIDrawCall.Clipping.None; // Set the draw call's transform to match the panel's. // Note that parenting directly to the panel causes unity to crash as soon as you hit Play. dt = dc.transform; dt.position = t.position; dt.rotation = t.rotation; dt.localScale = t.lossyScale; } } /// <summary> /// Set the draw call's geometry responsible for the specified material. /// </summary> void Fill(Material mat) { int highest = -100; // Fill the buffers for the specified material for (int i = 0; i < mWidgets.size;) { UIWidget w = mWidgets.buffer[i]; if (w == null) { mWidgets.RemoveAt(i); continue; } #if OLD_UNITY else if (w.visibleFlag == 1 && w.material == mat) #else else if (w.material == mat && w.isVisible) #endif { if (w.panel == this) { int depth = w.depth; if (depth > highest) { highest = depth; } if (generateNormals) { w.WriteToBuffers(mVerts, mUvs, mCols, mNorms, mTans); } else { w.WriteToBuffers(mVerts, mUvs, mCols, null, null); } } else { mWidgets.RemoveAt(i); continue; } } ++i; } if (mVerts.size > 0) { // Rebuild the draw call's mesh UIDrawCall dc = GetDrawCall(mat, true); dc.depthPass = depthPass && mClipping == UIDrawCall.Clipping.None; dc.depth = sortByDepth ? highest : 0; dc.Set(mVerts, generateNormals ? mNorms : null, generateNormals ? mTans : null, mUvs, mCols); dc.mainTexture = mat.mainTexture; } else { // There is nothing to draw for this material -- eliminate the draw call UIDrawCall dc = GetDrawCall(mat, false); if (dc != null) { mDrawCalls.Remove(dc); NGUITools.DestroyImmediate(dc.gameObject); } } // Cleanup mVerts.Clear(); mNorms.Clear(); mTans.Clear(); mUvs.Clear(); mCols.Clear(); } /// <summary> /// Main update function /// </summary> void LateUpdate() { mUpdateTime = Time.realtimeSinceStartup; UpdateTransformMatrix(); #if OLD_UNITY UpdateTransforms(); #endif // Always move widgets to the panel's layer if (mLayer != cachedGameObject.layer) { mLayer = mGo.layer; UICamera uic = UICamera.FindCameraForLayer(mLayer); mCam = (uic != null) ? uic.cachedCamera : NGUITools.FindCameraForLayer(mLayer); SetChildLayer(cachedTransform, mLayer); for (int i = 0, imax = drawCalls.size; i < imax; ++i) { mDrawCalls.buffer[i].gameObject.layer = mLayer; } } #if OLD_UNITY UpdateWidgets(); #else #if UNITY_EDITOR bool forceVisible = cullWhileDragging ? false : (clipping == UIDrawCall.Clipping.None) || (Application.isPlaying && mCullTime > mUpdateTime); #else bool forceVisible = cullWhileDragging ? false : (clipping == UIDrawCall.Clipping.None) || (mCullTime > mUpdateTime); #endif // Update all widgets for (int i = 0, imax = mWidgets.size; i < imax; ++i) { UIWidget w = mWidgets[i]; // If the widget is visible, update it if (w.UpdateGeometry(this, forceVisible)) { // We will need to refill this buffer if (!mChanged.Contains(w.material)) { mChanged.Add(w.material); } } } #endif // Inform the changed event listeners if (mChanged.size != 0 && onChange != null) { onChange(); } // If the depth has changed, we need to re-sort the widgets if (mDepthChanged) { mDepthChanged = false; mWidgets.Sort(UIWidget.CompareFunc); } // Fill the draw calls for all of the changed materials for (int i = 0, imax = mChanged.size; i < imax; ++i) { Fill(mChanged.buffer[i]); } // Update the clipping rects UpdateDrawcalls(); mChanged.Clear(); #if OLD_UNITY mRebuildAll = false; #endif #if UNITY_EDITOR mScreenSize = new Vector2(Screen.width, Screen.height); #endif }
/// <summary> /// Fill the geometry fully, processing all widgets and re-creating all draw calls. /// </summary> static public void Fill() { UIDrawCall.ClearAll(); int index = 0; UIPanel pan = null; Material mat = null; Texture tex = null; Shader sdr = null; UIDrawCall dc = null; for (int i = 0; i < UIWidget.list.size;) { UIWidget w = UIWidget.list[i]; if (w == null) { UIWidget.list.RemoveAt(i); continue; } if (w.isVisible && w.hasVertices) { UIPanel pn = w.panel; Material mt = w.material; Texture tx = w.mainTexture; Shader sd = w.shader; if (pan != pn || mat != mt || tex != tx || sdr != sd) { if (pan != null && mVerts.size != 0) { pan.SubmitDrawCall(dc); dc = null; } pan = pn; mat = mt; tex = tx; sdr = sd; } if (pan != null && (mat != null || sdr != null || tex != null)) { if (dc == null) { dc = UIDrawCall.Create(index++, pan, mat, tex, sdr); dc.depthStart = w.raycastDepth; dc.depthEnd = dc.depthStart; dc.panel = pan; } else { int rd = w.raycastDepth; if (rd < dc.depthStart) { dc.depthStart = rd; } if (rd > dc.depthEnd) { dc.depthEnd = rd; } } w.drawCall = dc; if (pan.generateNormals) { w.WriteToBuffers(mVerts, mUvs, mCols, mNorms, mTans); } else { w.WriteToBuffers(mVerts, mUvs, mCols, null, null); } } } else { w.drawCall = null; } ++i; } if (mVerts.size != 0) { pan.SubmitDrawCall(dc); } }
/// <summary> /// Fill the geometry fully, processing all widgets and re-creating all draw calls. /// </summary> static void Fill() { for (int i = UIDrawCall.list.size; i > 0;) { DestroyDrawCall(UIDrawCall.list[--i], i); } int index = 0; UIPanel pan = null; Material mat = null; UIDrawCall dc = null; for (int i = 0; i < UIWidget.list.size;) { UIWidget w = UIWidget.list[i]; if (w == null) { UIWidget.list.RemoveAt(i); continue; } if (w.isVisible && w.hasVertices) { if (pan != w.panel || mat != w.material) { if (pan != null && mat != null && mVerts.size != 0) { pan.SubmitDrawCall(dc); dc = null; } pan = w.panel; mat = w.material; } if (pan != null && mat != null) { if (dc == null) { dc = pan.GetDrawCall(index++, mat); } w.drawCall = dc; if (pan.generateNormals) { w.WriteToBuffers(mVerts, mUvs, mCols, mNorms, mTans); } else { w.WriteToBuffers(mVerts, mUvs, mCols, null, null); } } } else { w.drawCall = null; } ++i; } if (mVerts.size != 0) { pan.SubmitDrawCall(dc); } }
void FillAllDrawCalls() { for (int i = 0; i < drawCalls.Count; ++i) { UIDrawCall.Destroy(drawCalls[i]); } drawCalls.Clear(); Material mat = null; Texture tex = null; Shader sdr = null; UIDrawCall dc = null; #if OPTIMISE_NGUI_GC_ALLOC int verticesCount = 0; #endif if (mSortWidgets) { SortWidgets(); } for (int i = 0; i < widgets.Count; ++i) { UIWidget w = widgets[i]; if (w.isVisible && w.hasVertices) { Material mt = w.material; Texture tx = w.mainTexture; Shader sd = w.shader; if (mat != mt || tex != tx || sdr != sd) { #if OPTIMISE_NGUI_GC_ALLOC if (dc != null && verticesCount != 0) #else if (dc != null && dc.verts.size != 0) #endif { drawCalls.Add(dc); #if OPTIMISE_NGUI_GC_ALLOC FillDrawCallBuffers(dc, verticesCount); verticesCount = 0; #endif dc.UpdateGeometry(); dc = null; } mat = mt; tex = tx; sdr = sd; } if (mat != null || sdr != null || tex != null) { if (dc == null) { dc = UIDrawCall.Create(this, mat, tex, sdr); dc.depthStart = w.depth; dc.depthEnd = dc.depthStart; dc.panel = this; } else { int rd = w.depth; if (rd < dc.depthStart) { dc.depthStart = rd; } if (rd > dc.depthEnd) { dc.depthEnd = rd; } } w.drawCall = dc; #if !OPTIMISE_NGUI_GC_ALLOC if (generateNormals) { w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, dc.norms, dc.tans); } else { w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, null, null); } #else widgetsInDrawCall.Add(w); verticesCount += w.geometry.verts.size; #endif } } else { w.drawCall = null; } } #if OPTIMISE_NGUI_GC_ALLOC if (dc != null && verticesCount != 0) #else if (dc != null && dc.verts.size != 0) #endif { drawCalls.Add(dc); #if OPTIMISE_NGUI_GC_ALLOC FillDrawCallBuffers(dc, verticesCount); #endif dc.UpdateGeometry(); } }
/// <summary> /// Fill the geometry for the specified draw call. /// </summary> bool FillDrawCall(UIDrawCall dc) { if (dc != null) { dc.isDirty = false; #if OPTIMISE_NGUI_GC_ALLOC int verticesCount = 0; #endif for (int i = 0; i < widgets.Count;) { UIWidget w = widgets[i]; if (w == null) { #if UNITY_EDITOR Debug.LogError("This should never happen"); #endif widgets.RemoveAt(i); continue; } if (w.drawCall == dc) { if (w.isVisible && w.hasVertices) { #if !OPTIMISE_NGUI_GC_ALLOC if (generateNormals) { w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, dc.norms, dc.tans); } else { w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, null, null); } #else widgetsInDrawCall.Add(w); verticesCount += w.geometry.verts.size; #endif } else { w.drawCall = null; } } ++i; } #if !OPTIMISE_NGUI_GC_ALLOC if (dc.verts.size != 0) { #else if (verticesCount != 0) { FillDrawCallBuffers(dc, verticesCount); #endif dc.UpdateGeometry(); return(true); } } return(false); } }
/// <summary> /// Convenience function that figures out the panel's correct change flag by searching the parents. /// </summary> int GetChangeFlag(UINode start) { int flag = start.changeFlag; if (flag == -1) { Transform trans = start.trans.parent; UINode sub; // Keep going until we find a set flag for (;;) { // Check the parent's flag #if UNITY_FLASH if (trans != null && mChildren.TryGetValue(trans, out sub)) { #else if (trans != null && mChildren.Contains(trans)) { sub = (UINode)mChildren[trans]; #endif flag = sub.changeFlag; trans = trans.parent; // If the flag hasn't been set either, add this child to the hierarchy if (flag == -1) { mHierarchy.Add(sub); } else { break; } } else { flag = 0; break; } } // Update the parent flags for (int i = 0, imax = mHierarchy.size; i < imax; ++i) { UINode pc = mHierarchy.buffer[i]; pc.changeFlag = flag; } mHierarchy.Clear(); } return(flag); } /// <summary> /// Update the world-to-local transform matrix as well as clipping bounds. /// </summary> void UpdateTransformMatrix() { float time = Time.realtimeSinceStartup; if (time == 0f || mMatrixTime != time) { mMatrixTime = time; mWorldToLocal = cachedTransform.worldToLocalMatrix; if (mClipping != UIDrawCall.Clipping.None) { Vector2 size = new Vector2(mClipRange.z, mClipRange.w); if (size.x == 0f) { size.x = (mCam == null) ? Screen.width : mCam.pixelWidth; } if (size.y == 0f) { size.y = (mCam == null) ? Screen.height : mCam.pixelHeight; } size *= 0.5f; mMin.x = mClipRange.x - size.x; mMin.y = mClipRange.y - size.y; mMax.x = mClipRange.x + size.x; mMax.y = mClipRange.y + size.y; } } } /// <summary> /// Run through all managed transforms and see if they've changed. /// </summary> void UpdateTransforms() { mChangedLastFrame = false; bool transformsChanged = false; #if UNITY_EDITOR bool shouldCull = !Application.isPlaying || Time.realtimeSinceStartup > mCullTime; if (!Application.isPlaying || !widgetsAreStatic || mWidgetsAdded || shouldCull != mCulled) #else bool shouldCull = Time.realtimeSinceStartup > mCullTime; if (!widgetsAreStatic || mWidgetsAdded || shouldCull != mCulled) #endif { #if UNITY_FLASH foreach (KeyValuePair <Transform, UINode> child in mChildren) { UINode node = child.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode node = (UINode)mChildren[i]; #endif if (node.trans == null) { mRemoved.Add(node.trans); continue; } if (node.HasChanged()) { node.changeFlag = 1; transformsChanged = true; } else { node.changeFlag = -1; } } // Clean up the deleted transforms for (int i = 0, imax = mRemoved.Count; i < imax; ++i) { mChildren.Remove(mRemoved[i]); } mRemoved.Clear(); } // If the children weren't culled but should be, check their visibility if (!mCulled && shouldCull) { mCheckVisibility = true; } // If something has changed, propagate the changes *down* the tree hierarchy (to children). // An alternative (but slower) approach would be to do a pc.trans.GetComponentsInChildren<UIWidget>() // in the loop above, and mark each one as dirty. if (mCheckVisibility || transformsChanged || mRebuildAll) { #if UNITY_FLASH foreach (KeyValuePair <Transform, UINode> child in mChildren) { UINode pc = child.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode pc = (UINode)mChildren[i]; #endif if (pc.widget != null) { int visibleFlag = 1; // No sense in checking the visibility if we're not culling anything (as the visibility is always 'true') if (shouldCull || transformsChanged) { // If the change flag has not yet been determined... if (pc.changeFlag == -1) { pc.changeFlag = GetChangeFlag(pc); } // Is the widget visible? if (shouldCull) { visibleFlag = (mCheckVisibility || pc.changeFlag == 1) ? (IsVisible(pc.widget) ? 1 : 0) : pc.visibleFlag; } } // If visibility changed, mark the node as changed as well if (pc.visibleFlag != visibleFlag) { pc.changeFlag = 1; } // If the node has changed and the widget is visible (or was visible before) if (pc.changeFlag == 1 && (visibleFlag == 1 || pc.visibleFlag != 0)) { // Update the visibility flag pc.visibleFlag = visibleFlag; Material mat = pc.widget.material; // Add this material to the list of changed materials if (!mChanged.Contains(mat)) { mChanged.Add(mat); mChangedLastFrame = true; } } } } } mCulled = shouldCull; mCheckVisibility = false; mWidgetsAdded = false; } /// <summary> /// Update all widgets and rebuild their geometry if necessary. /// </summary> void UpdateWidgets() { #if UNITY_FLASH foreach (KeyValuePair <Transform, UINode> c in mChildren) { UINode pc = c.Value; #else for (int i = 0, imax = mChildren.Count; i < imax; ++i) { UINode pc = (UINode)mChildren[i]; #endif UIWidget w = pc.widget; // If the widget is visible, update it if (pc.visibleFlag == 1 && w != null && w.UpdateGeometry(ref mWorldToLocal, (pc.changeFlag == 1), generateNormals)) { // We will need to refill this buffer if (!mChanged.Contains(w.material)) { mChanged.Add(w.material); mChangedLastFrame = true; } } pc.changeFlag = 0; } } /// <summary> /// Update the clipping rect in the shaders and draw calls' positions. /// </summary> public void UpdateDrawcalls() { Vector4 range = Vector4.zero; if (mClipping != UIDrawCall.Clipping.None) { range = new Vector4(mClipRange.x, mClipRange.y, mClipRange.z * 0.5f, mClipRange.w * 0.5f); } if (range.z == 0f) { range.z = Screen.width * 0.5f; } if (range.w == 0f) { range.w = Screen.height * 0.5f; } RuntimePlatform platform = Application.platform; if (platform == RuntimePlatform.WindowsPlayer || platform == RuntimePlatform.WindowsWebPlayer || platform == RuntimePlatform.WindowsEditor) { range.x -= 0.5f; range.y += 0.5f; } Transform t = cachedTransform; for (int i = 0, imax = mDrawCalls.size; i < imax; ++i) { UIDrawCall dc = mDrawCalls.buffer[i]; dc.clipping = mClipping; dc.clipRange = range; dc.clipSoftness = mClipSoftness; dc.depthPass = depthPass; // Set the draw call's transform to match the panel's. // Note that parenting directly to the panel causes unity to crash as soon as you hit Play. Transform dt = dc.transform; dt.position = t.position; dt.rotation = t.rotation; dt.localScale = t.lossyScale; } } /// <summary> /// Set the draw call's geometry responsible for the specified material. /// </summary> void Fill(Material mat) { // Cleanup deleted widgets for (int i = mWidgets.size; i > 0;) { if (mWidgets[--i] == null) { mWidgets.RemoveAt(i); } } // Fill the buffers for the specified material for (int i = 0, imax = mWidgets.size; i < imax; ++i) { UIWidget w = mWidgets.buffer[i]; if (w.visibleFlag == 1 && w.material == mat) { UINode node = GetNode(w.cachedTransform); if (node != null) { if (generateNormals) { w.WriteToBuffers(mVerts, mUvs, mCols, mNorms, mTans); } else { w.WriteToBuffers(mVerts, mUvs, mCols, null, null); } } else { Debug.LogError("No transform found for " + NGUITools.GetHierarchy(w.gameObject), this); } } } if (mVerts.size > 0) { // Rebuild the draw call's mesh UIDrawCall dc = GetDrawCall(mat, true); dc.depthPass = depthPass; dc.Set(mVerts, generateNormals ? mNorms : null, generateNormals ? mTans : null, mUvs, mCols); } else { // There is nothing to draw for this material -- eliminate the draw call UIDrawCall dc = GetDrawCall(mat, false); if (dc != null) { mDrawCalls.Remove(dc); NGUITools.DestroyImmediate(dc.gameObject); } } // Cleanup mVerts.Clear(); mNorms.Clear(); mTans.Clear(); mUvs.Clear(); mCols.Clear(); } /// <summary> /// Main update function /// </summary> void LateUpdate() { UpdateTransformMatrix(); UpdateTransforms(); // Always move widgets to the panel's layer if (mLayer != gameObject.layer) { mLayer = gameObject.layer; UICamera uic = UICamera.FindCameraForLayer(mLayer); mCam = (uic != null) ? uic.cachedCamera : NGUITools.FindCameraForLayer(mLayer); SetChildLayer(cachedTransform, mLayer); for (int i = 0, imax = drawCalls.size; i < imax; ++i) { mDrawCalls.buffer[i].gameObject.layer = mLayer; } } UpdateWidgets(); // If the depth has changed, we need to re-sort the widgets if (mDepthChanged) { mDepthChanged = false; mWidgets.Sort(UIWidget.CompareFunc); } // Fill the draw calls for all of the changed materials for (int i = 0, imax = mChanged.size; i < imax; ++i) { Fill(mChanged.buffer[i]); } // Update the clipping rects UpdateDrawcalls(); mChanged.Clear(); mRebuildAll = false; #if UNITY_EDITOR mScreenSize = new Vector2(Screen.width, Screen.height); #endif }