C#之#region和<summary>的使用

本文探讨了C#中使用#region指令来组织代码的方法及其潜在的问题,并介绍了如何利用<summary>注释来提高代码可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用#region就是将一些有关联的代码组织在一起,然后折叠起来。这样你就在一个函数中看不到很长的令人头痛的代码段。例如:

publicvoid DoSomething()
{
bool shouldIDoSomething;

#region Decide if I should do something

if(needToDoSomething && haventDoneSomethingThisDay)
shouldIDoSomething =true;
else
{
// do some other logic to decide and set shouldIDoSomething to some value
}

#endregion

if(shouldIDoSomething)
{
done++;
}
}

当然这段代码很简单。在实际项目中,你可能看到上百行甚至更多的代码在一个#region中。如果把它折叠起来。看起来就会很整洁。是吧?

publicvoid DoSomething()
{
bool shouldIDoSomething;

[Decide if I should do something]

if(shouldIDoSomething)
{
done++;
}
}

只是把一些代码和一些变量组合起来放在#region中。如果你在仔细想想,其实我们相当与创建了一个新的函数,只是将这些方法内置到当前函数中。一个函数只做单一的一件事情,这是Clean Code这本书的一个原则。为什么我们不把它提取为一个函数呢,这样一来,一个函数就只做一件事情了。

小段总结1: #region 不适合在大方法中使用,当你在一个方法中使用#region 的时候,停下来想想你刚刚写了什么代码?大多数时候,你可以将这些代码段独立成一个函数。

#region Get Name
public void GetName(){
}
#endregion

#region Set Name
public string SetName(string name){
    return name;
}
#endregion

折叠之后——

[Get Name]
[Set Name]

小段总结2:可以将一组相关的函数提取到一个职责单一的新类中。
那我们到底怎么使用 #region 呢。将东西用它来分组,它是非常有用的。在我写的类中或多或少有几个#region,用来对类中不同的结构进行分组。比如: fields, properties, methods, events, types等。如果你打开我写的类文件,你会看到结构如下:

public class SomeClass
{
[Events]

[Fields]

[Properties]

[Methods]
}

* 总的来说:*我将#region看成能控制阅读源代码的复杂度的一种方式。因为你可以将一些相关的代码放在一个区域(#region)里面。但是,这不是你随便就创建新方法或者新类的借口。其实Region并不能消除复杂度,它只是在你阅读代码的时候,隐藏了部分代码。你必须通过写出小巧,清晰,重点突出的方法和类,才能控制代码的复杂度。当你做到这些的时候,你甚至会发现#region是不必要的。

< summary >

C#中的< summary>用来标记应当用于描述类型或类型成员。

< summary> 标记的文本是唯一有关 IntelliSense 中的类型的信息源,它也显示在 Object Browser Window 中,使用 /doc 进行编译可以将文档注释处理到文件中。 若要基于编译器生成的文件创建最终文档,可以创建一个自定义工具,也可
以使用 Sandcastle等工具。

生成< summary>注释的方法很简单,在方法之前输入 /// 就会自动生成。如下(实际代码演示):


    /// <summary>

    /// 这里是测试信息。

    /// </summary>

    /// <param name="timeline"></param>

    /// <param name="cardtype"></param>

    /// <param name="jdtime"></param>

    /// <returns></returns>

//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System; using System.Collections.Generic; using System.IO; using System.Reflection; /// <summary> /// Helper class containing generic functions used throughout the UI library. /// </summary> static public class NGUITools { static AudioListener mListener; static bool mLoaded = false; static float mGlobalVolume = 1f; /// <summary> /// Globally accessible volume affecting all sounds played via NGUITools.PlaySound(). /// </summary> static public float soundVolume { get { if (!mLoaded) { mLoaded = true; mGlobalVolume = PlayerPrefs.GetFloat("Sound", 1f); } return mGlobalVolume; } set { if (mGlobalVolume != value) { mLoaded = true; mGlobalVolume = value; PlayerPrefs.SetFloat("Sound", value); } } } /// <summary> /// Helper function -- whether the disk access is allowed. /// </summary> static public bool fileAccess { get { return Application.platform != RuntimePlatform.WindowsWebPlayer && Application.platform != RuntimePlatform.OSXWebPlayer; } } /// <summary> /// Play the specified audio clip. /// </summary> static public AudioSource PlaySound (AudioClip clip) { return PlaySound(clip, 1f, 1f); } /// <summary> /// Play the specified audio clip with the specified volume. /// </summary> static public AudioSource PlaySound (AudioClip clip, float volume) { return PlaySound(clip, volume, 1f); } static float mLastTimestamp = 0f; static AudioClip mLastClip; /// <summary> /// Play the specified audio clip with the specified volume and pitch. /// </summary> static public AudioSource PlaySound (AudioClip clip, float volume, float pitch) { float time = Time.time; if (mLastClip == clip && mLastTimestamp + 0.1f > time) return null; mLastClip = clip; mLastTimestamp = time; volume *= soundVolume; if (clip != null && volume > 0.01f) { if (mListener == null || !NGUITools.GetActive(mListener)) { AudioListener[] listeners = GameObject.FindObjectsOfType(typeof(AudioListener)) as AudioListener[]; if (listeners != null) { for (int i = 0; i < listeners.Length; ++i) { if (NGUITools.GetActive(listeners[i])) { mListener = listeners[i]; break; } } } if (mListener == null) { Camera cam = Camera.main; if (cam == null) cam = GameObject.FindObjectOfType(typeof(Camera)) as Camera; if (cam != null) mListener = cam.gameObject.AddComponent<AudioListener>(); } } if (mListener != null && mListener.enabled && NGUITools.GetActive(mListener.gameObject)) { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 AudioSource source = mListener.audio; #else AudioSource source = mListener.GetComponent<AudioSource>(); #endif if (source == null) source = mListener.gameObject.AddComponent<AudioSource>(); #if !UNITY_FLASH source.priority = 50; source.pitch = pitch; #endif source.PlayOneShot(clip, volume); return source; } } return null; } /// <summary> /// New WWW call can fail if the crossdomain policy doesn't check out. Exceptions suck. It's much more elegant to check for null instead. /// </summary> // static public WWW OpenURL (string url) // { //#if UNITY_FLASH // Debug.LogError("WWW is not yet implemented in Flash"); // return null; //#else // WWW www = null; // try { www = new WWW(url); } // catch (System.Exception ex) { Debug.LogError(ex.Message); } // return www; //#endif // } // /// <summary> // /// New WWW call can fail if the crossdomain policy doesn't check out. Exceptions suck. It's much more elegant to check for null instead. // /// </summary> // static public WWW OpenURL (string url, WWWForm form) // { // if (form == null) return OpenURL(url); //#if UNITY_FLASH // Debug.LogError("WWW is not yet implemented in Flash"); // return null; //#else // WWW www = null; // try { www = new WWW(url, form); } // catch (System.Exception ex) { Debug.LogError(ex != null ? ex.Message : "<null>"); } // return www; //#endif // } /// <summary> /// Same as Random.Range, but the returned value is between min and max, inclusive. /// Unity's Random.Range is less than max instead, unless min == max. /// This means Range(0,1) produces 0 instead of 0 or 1. That's unacceptable. /// </summary> static public int RandomRange (int min, int max) { if (min == max) return min; return UnityEngine.Random.Range(min, max + 1); } /// <summary> /// Returns the hierarchy of the object in a human-readable format. /// </summary> static public string GetHierarchy (GameObject obj) { if (obj == null) return ""; string path = obj.name; while (obj.transform.parent != null) { obj = obj.transform.parent.gameObject; path = obj.name + "\\" + path; } return path; } /// <summary> /// Find all active objects of specified type. /// </summary> static public T[] FindActive<T> () where T : Component { return GameObject.FindObjectsOfType(typeof(T)) as T[]; } /// <summary> /// Find the camera responsible for drawing the objects on the specified layer. /// </summary> static public Camera FindCameraForLayer (int layer) { int layerMask = 1 << layer; Camera cam; for (int i = 0; i < UICamera.list.size; ++i) { cam = UICamera.list.buffer[i].cachedCamera; if (cam && (cam.cullingMask & layerMask) != 0) return cam; } cam = Camera.main; if (cam && (cam.cullingMask & layerMask) != 0) return cam; #if UNITY_4_3 || UNITY_FLASH Camera[] cameras = NGUITools.FindActive<Camera>(); for (int i = 0, imax = cameras.Length; i < imax; ++i) #else Camera[] cameras = new Camera[Camera.allCamerasCount]; int camerasFound = Camera.GetAllCameras(cameras); for (int i = 0; i < camerasFound; ++i) #endif { cam = cameras[i]; if (cam && cam.enabled && (cam.cullingMask & layerMask) != 0) return cam; } return null; } /// <summary> /// Add a collider to the game object containing one or more widgets. /// </summary> static public void AddWidgetCollider (GameObject go) { AddWidgetCollider(go, false); } /// <summary> /// Add a collider to the game object containing one or more widgets. /// </summary> static public void AddWidgetCollider (GameObject go, bool considerInactive) { if (go != null) { // 3D collider Collider col = go.GetComponent<Collider>(); BoxCollider box = col as BoxCollider; if (box != null) { UpdateWidgetCollider(box, considerInactive); return; } // Is there already another collider present? If so, do nothing. if (col != null) return; // 2D collider BoxCollider2D box2 = go.GetComponent<BoxCollider2D>(); if (box2 != null) { UpdateWidgetCollider(box2, considerInactive); return; } UICamera ui = UICamera.FindCameraForLayer(go.layer); if (ui != null && (ui.eventType == UICamera.EventType.World_2D || ui.eventType == UICamera.EventType.UI_2D)) { box2 = go.AddComponent<BoxCollider2D>(); box2.isTrigger = true; #if UNITY_EDITOR UnityEditor.Undo.RegisterCreatedObjectUndo(box2, "Add Collider"); #endif UIWidget widget = go.GetComponent<UIWidget>(); if (widget != null) widget.autoResizeBoxCollider = true; UpdateWidgetCollider(box2, considerInactive); return; } else { box = go.AddComponent<BoxCollider>(); #if UNITY_EDITOR UnityEditor.Undo.RegisterCreatedObjectUndo(box, "Add Collider"); #endif box.isTrigger = true; UIWidget widget = go.GetComponent<UIWidget>(); if (widget != null) widget.autoResizeBoxCollider = true; UpdateWidgetCollider(box, considerInactive); } } return; } /// <summary> /// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions. /// </summary> static public void UpdateWidgetCollider (GameObject go) { UpdateWidgetCollider(go, false); } /// <summary> /// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions. /// </summary> static public void UpdateWidgetCollider (GameObject go, bool considerInactive) { if (go != null) { BoxCollider bc = go.GetComponent<BoxCollider>(); if (bc != null) { UpdateWidgetCollider(bc, considerInactive); return; } BoxCollider2D box2 = go.GetComponent<BoxCollider2D>(); if (box2 != null) UpdateWidgetCollider(box2, considerInactive); } } /// <summary> /// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions. /// </summary> static public void UpdateWidgetCollider (BoxCollider box, bool considerInactive) { if (box != null) { GameObject go = box.gameObject; UIWidget w = go.GetComponent<UIWidget>(); if (w != null) { Vector4 dr = w.drawRegion; if (dr.x != 0f || dr.y != 0f || dr.z != 1f || dr.w != 1f) { Vector4 region = w.drawingDimensions; box.center = new Vector3((region.x + region.z) * 0.5f, (region.y + region.w) * 0.5f); box.size = new Vector3(region.z - region.x, region.w - region.y); } else { Vector3[] corners = w.localCorners; box.center = Vector3.Lerp(corners[0], corners[2], 0.5f); box.size = corners[2] - corners[0]; } } else { Bounds b = NGUIMath.CalculateRelativeWidgetBounds(go.transform, considerInactive); box.center = b.center; box.size = new Vector3(b.size.x, b.size.y, 0f); } #if UNITY_EDITOR NGUITools.SetDirty(box); #endif } } /// <summary> /// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions. /// </summary> static public void UpdateWidgetCollider (BoxCollider2D box, bool considerInactive) { if (box != null) { GameObject go = box.gameObject; UIWidget w = go.GetComponent<UIWidget>(); if (w != null) { Vector3[] corners = w.localCorners; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 box.center = Vector3.Lerp(corners[0], corners[2], 0.5f); #else box.offset = Vector3.Lerp(corners[0], corners[2], 0.5f); #endif box.size = corners[2] - corners[0]; } else { Bounds b = NGUIMath.CalculateRelativeWidgetBounds(go.transform, considerInactive); #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 box.center = b.center; #else box.offset = b.center; #endif box.size = new Vector2(b.size.x, b.size.y); } #if UNITY_EDITOR NGUITools.SetDirty(box); #endif } } /// <summary> /// Helper function that returns the string name of the type. /// </summary> static public string GetTypeName<T> () { string s = typeof(T).ToString(); if (s.StartsWith("UI")) s = s.Substring(2); else if (s.StartsWith("UnityEngine.")) s = s.Substring(12); return s; } /// <summary> /// Helper function that returns the string name of the type. /// </summary> static public string GetTypeName (UnityEngine.Object obj) { if (obj == null) return "Null"; string s = obj.GetType().ToString(); if (s.StartsWith("UI")) s = s.Substring(2); else if (s.StartsWith("UnityEngine.")) s = s.Substring(12); return s; } /// <summary> /// Convenience method that works without warnings in both Unity 3 and 4. /// </summary> static public void RegisterUndo (UnityEngine.Object obj, string name) { #if UNITY_EDITOR UnityEditor.Undo.RecordObject(obj, name); NGUITools.SetDirty(obj); #endif } /// <summary> /// Convenience function that marks the specified object as dirty in the Unity Editor. /// </summary> static public void SetDirty (UnityEngine.Object obj) { #if UNITY_EDITOR if (obj) { //if (obj is Component) Debug.Log(NGUITools.GetHierarchy((obj as Component).gameObject), obj); //else if (obj is GameObject) Debug.Log(NGUITools.GetHierarchy(obj as GameObject), obj); //else Debug.Log("Hmm... " + obj.GetType(), obj); UnityEditor.EditorUtility.SetDirty(obj); } #endif } /// <summary> /// Add a new child game object. /// </summary> static public GameObject AddChild (GameObject parent) { return AddChild(parent, true); } /// <summary> /// Add a new child game object. /// </summary> static public GameObject AddChild (GameObject parent, bool undo) { GameObject go = new GameObject(); #if UNITY_EDITOR if (undo) UnityEditor.Undo.RegisterCreatedObjectUndo(go, "Create Object"); #endif if (parent != null) { Transform t = go.transform; t.parent = parent.transform; t.localPosition = Vector3.zero; t.localRotation = Quaternion.identity; t.localScale = Vector3.one; go.layer = parent.layer; } return go; } /// <summary> /// Instantiate an object and add it to the specified parent. /// </summary> static public GameObject AddChild (GameObject parent, GameObject prefab) { GameObject go = GameObject.Instantiate(prefab) as GameObject; #if UNITY_EDITOR UnityEditor.Undo.RegisterCreatedObjectUndo(go, "Create Object"); #endif if (go != null && parent != null) { Transform t = go.transform; t.parent = parent.transform; t.localPosition = Vector3.zero; t.localRotation = Quaternion.identity; t.localScale = Vector3.one; go.layer = parent.layer; } return go; } /// <summary> /// Calculate the game object's depth based on the widgets within, and also taking panel depth into consideration. /// </summary> static public int CalculateRaycastDepth (GameObject go) { UIWidget w = go.GetComponent<UIWidget>(); if (w != null) return w.raycastDepth; UIWidget[] widgets = go.GetComponentsInChildren<UIWidget>(); if (widgets.Length == 0) return 0; int depth = int.MaxValue; for (int i = 0, imax = widgets.Length; i < imax; ++i) { if (widgets[i].enabled) depth = Mathf.Min(depth, widgets[i].raycastDepth); } return depth; } /// <summary> /// Gathers all widgets and calculates the depth for the next widget. /// </summary> static public int CalculateNextDepth (GameObject go) { int depth = -1; UIWidget[] widgets = go.GetComponentsInChildren<UIWidget>(); for (int i = 0, imax = widgets.Length; i < imax; ++i) depth = Mathf.Max(depth, widgets[i].depth); return depth + 1; } /// <summary> /// Gathers all widgets and calculates the depth for the next widget. /// </summary> static public int CalculateNextDepth (GameObject go, bool ignoreChildrenWithColliders) { if (ignoreChildrenWithColliders) { int depth = -1; UIWidget[] widgets = go.GetComponentsInChildren<UIWidget>(); for (int i = 0, imax = widgets.Length; i < imax; ++i) { UIWidget w = widgets[i]; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (w.cachedGameObject != go && (w.collider != null || w.GetComponent<Collider2D>() != null)) continue; #else if (w.cachedGameObject != go && (w.GetComponent<Collider>() != null || w.GetComponent<Collider2D>() != null)) continue; #endif depth = Mathf.Max(depth, w.depth); } return depth + 1; } return CalculateNextDepth(go); } /// <summary> /// Adjust the widgets' depth by the specified value. /// Returns '0' if nothing was adjusted, '1' if panels were adjusted, and '2' if widgets were adjusted. /// </summary> static public int AdjustDepth (GameObject go, int adjustment) { if (go != null) { UIPanel panel = go.GetComponent<UIPanel>(); if (panel != null) { UIPanel[] panels = go.GetComponentsInChildren<UIPanel>(true); for (int i = 0; i < panels.Length; ++i) { UIPanel p = panels[i]; #if UNITY_EDITOR RegisterUndo(p, "Depth Change"); #endif p.depth = p.depth + adjustment; } return 1; } else { panel = FindInParents<UIPanel>(go); if (panel == null) return 0; UIWidget[] widgets = go.GetComponentsInChildren<UIWidget>(true); for (int i = 0, imax = widgets.Length; i < imax; ++i) { UIWidget w = widgets[i]; if (w.panel != panel) continue; #if UNITY_EDITOR RegisterUndo(w, "Depth Change"); #endif w.depth = w.depth + adjustment; } return 2; } } return 0; } /// <summary> /// Bring all of the widgets on the specified object forward. /// </summary> static public void BringForward (GameObject go) { int val = AdjustDepth(go, 1000); if (val == 1) NormalizePanelDepths(); else if (val == 2) NormalizeWidgetDepths(); } /// <summary> /// Push all of the widgets on the specified object back, making them appear behind everything else. /// </summary> static public void PushBack (GameObject go) { int val = AdjustDepth(go, -1000); if (val == 1) NormalizePanelDepths(); else if (val == 2) NormalizeWidgetDepths(); } /// <summary> /// Normalize the depths of all the widgets and panels in the scene, making them start from 0 and remain in order. /// </summary> static public void NormalizeDepths () { NormalizeWidgetDepths(); NormalizePanelDepths(); } /// <summary> /// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order. /// </summary> static public void NormalizeWidgetDepths () { NormalizeWidgetDepths(FindActive<UIWidget>()); } /// <summary> /// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order. /// </summary> static public void NormalizeWidgetDepths (GameObject go) { NormalizeWidgetDepths(go.GetComponentsInChildren<UIWidget>()); } /// <summary> /// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order. /// </summary> static public void NormalizeWidgetDepths (UIWidget[] list) { int size = list.Length; if (size > 0) { Array.Sort(list, UIWidget.FullCompareFunc); int start = 0; int current = list[0].depth; for (int i = 0; i < size; ++i) { UIWidget w = list[i]; if (w.depth == current) { w.depth = start; } else { current = w.depth; w.depth = ++start; } } } } /// <summary> /// Normalize the depths of all the panels in the scene, making them start from 0 and remain in order. /// </summary> static public void NormalizePanelDepths () { UIPanel[] list = FindActive<UIPanel>(); int size = list.Length; if (size > 0) { Array.Sort(list, UIPanel.CompareFunc); int start = 0; int current = list[0].depth; for (int i = 0; i < size; ++i) { UIPanel p = list[i]; if (p.depth == current) { p.depth = start; } else { current = p.depth; p.depth = ++start; } } } } /// <summary> /// Create a new UI. /// </summary> static public UIPanel CreateUI (bool advanced3D) { return CreateUI(null, advanced3D, -1); } /// <summary> /// Create a new UI. /// </summary> static public UIPanel CreateUI (bool advanced3D, int layer) { return CreateUI(null, advanced3D, layer); } /// <summary> /// Create a new UI. /// </summary> static public UIPanel CreateUI (Transform trans, bool advanced3D, int layer) { // Find the existing UI Root UIRoot root = (trans != null) ? NGUITools.FindInParents<UIRoot>(trans.gameObject) : null; if (root == null && UIRoot.list.Count > 0) { foreach (UIRoot r in UIRoot.list) { if (r.gameObject.layer == layer) { root = r; break; } } } // Try to find an existing panel if (root == null) { for (int i = 0, imax = UIPanel.list.Count; i < imax; ++i) { UIPanel p = UIPanel.list[i]; GameObject go = p.gameObject; if (go.hideFlags == HideFlags.None && go.layer == layer) { trans.parent = p.transform; trans.localScale = Vector3.one; return p; } } } // If we are working with a different UI type, we need to treat it as a brand-new one instead if (root != null) { UICamera cam = root.GetComponentInChildren<UICamera>(); #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (cam != null && cam.camera.isOrthoGraphic == advanced3D) #else if (cam != null && cam.GetComponent<Camera>().orthographic == advanced3D) #endif { trans = null; root = null; } } // If no root found, create one if (root == null) { GameObject go = NGUITools.AddChild(null, false); root = go.AddComponent<UIRoot>(); // Automatically find the layers if none were specified if (layer == -1) layer = LayerMask.NameToLayer("UI"); if (layer == -1) layer = LayerMask.NameToLayer("2D UI"); go.layer = layer; if (advanced3D) { go.name = "UI Root (3D)"; root.scalingStyle = UIRoot.Scaling.Constrained; } else { go.name = "UI Root"; root.scalingStyle = UIRoot.Scaling.Flexible; } } // Find the first panel UIPanel panel = root.GetComponentInChildren<UIPanel>(); if (panel == null) { // Find other active cameras in the scene Camera[] cameras = NGUITools.FindActive<Camera>(); float depth = -1f; bool colorCleared = false; int mask = (1 << root.gameObject.layer); for (int i = 0; i < cameras.Length; ++i) { Camera c = cameras[i]; // If the color is being cleared, we won't need to if (c.clearFlags == CameraClearFlags.Color || c.clearFlags == CameraClearFlags.Skybox) colorCleared = true; // Choose the maximum depth depth = Mathf.Max(depth, c.depth); // Make sure this camera can't see the UI c.cullingMask = (c.cullingMask & (~mask)); } // Create a camera that will draw the UI Camera cam = NGUITools.AddChild<Camera>(root.gameObject, false); cam.gameObject.AddComponent<UICamera>(); cam.clearFlags = colorCleared ? CameraClearFlags.Depth : CameraClearFlags.Color; cam.backgroundColor = Color.grey; cam.cullingMask = mask; cam.depth = depth + 1f; if (advanced3D) { cam.nearClipPlane = 0.1f; cam.farClipPlane = 4f; cam.transform.localPosition = new Vector3(0f, 0f, -700f); } else { cam.orthographic = true; cam.orthographicSize = 1; cam.nearClipPlane = -10; cam.farClipPlane = 10; } // Make sure there is an audio listener present AudioListener[] listeners = NGUITools.FindActive<AudioListener>(); if (listeners == null || listeners.Length == 0) cam.gameObject.AddComponent<AudioListener>(); // Add a panel to the root panel = root.gameObject.AddComponent<UIPanel>(); #if UNITY_EDITOR UnityEditor.Selection.activeGameObject = panel.gameObject; #endif } if (trans != null) { // Find the root object while (trans.parent != null) trans = trans.parent; if (NGUITools.IsChild(trans, panel.transform)) { // Odd hierarchy -- can't reparent panel = trans.gameObject.AddComponent<UIPanel>(); } else { // Reparent this root object to be a child of the panel trans.parent = panel.transform; trans.localScale = Vector3.one; trans.localPosition = Vector3.zero; SetChildLayer(panel.cachedTransform, panel.cachedGameObject.layer); } } return panel; } /// <summary> /// Helper function that recursively sets all children with widgets' game objects layers to the specified value. /// </summary> static public void SetChildLayer (Transform t, int layer) { for (int i = 0; i < t.childCount; ++i) { Transform child = t.GetChild(i); child.gameObject.layer = layer; SetChildLayer(child, layer); } } /// <summary> /// Add a child object to the specified parent and attaches the specified script to it. /// </summary> static public T AddChild<T> (GameObject parent) where T : Component { GameObject go = AddChild(parent); go.name = GetTypeName<T>(); return go.AddComponent<T>(); } /// <summary> /// Add a child object to the specified parent and attaches the specified script to it. /// </summary> static public T AddChild<T> (GameObject parent, bool undo) where T : Component { GameObject go = AddChild(parent, undo); go.name = GetTypeName<T>(); return go.AddComponent<T>(); } /// <summary> /// Add a new widget of specified type. /// </summary> static public T AddWidget<T> (GameObject go) where T : UIWidget { int depth = CalculateNextDepth(go); // Create the widget and place it above other widgets T widget = AddChild<T>(go); widget.width = 100; widget.height = 100; widget.depth = depth; return widget; } /// <summary> /// Add a new widget of specified type. /// </summary> static public T AddWidget<T> (GameObject go, int depth) where T : UIWidget { // Create the widget and place it above other widgets T widget = AddChild<T>(go); widget.width = 100; widget.height = 100; widget.depth = depth; return widget; } /// <summary> /// Add a sprite appropriate for the specified atlas sprite. /// It will be sliced if the sprite has an inner rect, and a regular sprite otherwise. /// </summary> static public UISprite AddSprite (GameObject go, UIAtlas atlas, string spriteName) { UISpriteData sp = (atlas != null) ? atlas.GetSprite(spriteName) : null; UISprite sprite = AddWidget<UISprite>(go); sprite.type = (sp == null || !sp.hasBorder) ? UISprite.Type.Simple : UISprite.Type.Sliced; sprite.atlas = atlas; sprite.spriteName = spriteName; return sprite; } /// <summary> /// Get the rootmost object of the specified game object. /// </summary> static public GameObject GetRoot (GameObject go) { Transform t = go.transform; for (; ; ) { Transform parent = t.parent; if (parent == null) break; t = parent; } return t.gameObject; } /// <summary> /// Finds the specified component on the game object or one of its parents. /// </summary> static public T FindInParents<T> (GameObject go) where T : Component { if (go == null) return null; // Commented out because apparently it causes Unity 4.5.3 to lag horribly: // http://www.tasharen.com/forum/index.php?topic=10882.0 //#if UNITY_4_3 #if UNITY_FLASH object comp = go.GetComponent<T>(); #else T comp = go.GetComponent<T>(); #endif if (comp == null) { Transform t = go.transform.parent; while (t != null && comp == null) { comp = t.gameObject.GetComponent<T>(); t = t.parent; } } #if UNITY_FLASH return (T)comp; #else return comp; #endif //#else // return go.GetComponentInParent<T>(); //#endif } /// <summary> /// Finds the specified component on the game object or one of its parents. /// </summary> static public T FindInParents<T> (Transform trans) where T : Component { if (trans == null) return null; #if UNITY_4_3 #if UNITY_FLASH object comp = trans.GetComponent<T>(); #else T comp = trans.GetComponent<T>(); #endif if (comp == null) { Transform t = trans.transform.parent; while (t != null && comp == null) { comp = t.gameObject.GetComponent<T>(); t = t.parent; } } #if UNITY_FLASH return (T)comp; #else return comp; #endif #else return trans.GetComponentInParent<T>(); #endif } /// <summary> /// Destroy the specified object, immediately if in edit mode. /// </summary> static public void Destroy (UnityEngine.Object obj) { if (obj != null) { if (obj is Transform) obj = (obj as Transform).gameObject; if (Application.isPlaying) { if (obj is GameObject) { GameObject go = obj as GameObject; go.transform.parent = null; } UnityEngine.Object.Destroy(obj); } else UnityEngine.Object.DestroyImmediate(obj); } } /// <summary> /// Destroy the specified object immediately, unless not in the editor, in which case the regular Destroy is used instead. /// </summary> static public void DestroyImmediate (UnityEngine.Object obj) { if (obj != null) { if (Application.isEditor) UnityEngine.Object.DestroyImmediate(obj); else UnityEngine.Object.Destroy(obj); } } /// <summary> /// Call the specified function on all objects in the scene. /// </summary> static public void Broadcast (string funcName) { GameObject[] gos = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[]; for (int i = 0, imax = gos.Length; i < imax; ++i) gos[i].SendMessage(funcName, SendMessageOptions.DontRequireReceiver); } /// <summary> /// Call the specified function on all objects in the scene. /// </summary> static public void Broadcast (string funcName, object param) { GameObject[] gos = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[]; for (int i = 0, imax = gos.Length; i < imax; ++i) gos[i].SendMessage(funcName, param, SendMessageOptions.DontRequireReceiver); } /// <summary> /// Determines whether the 'parent' contains a 'child' in its hierarchy. /// </summary> static public bool IsChild (Transform parent, Transform child) { if (parent == null || child == null) return false; while (child != null) { if (child == parent) return true; child = child.parent; } return false; } /// <summary> /// Activate the specified object and all of its children. /// </summary> static void Activate (Transform t) { Activate(t, false); } /// <summary> /// Activate the specified object and all of its children. /// </summary> static void Activate (Transform t, bool compatibilityMode) { SetActiveSelf(t.gameObject, true); if (compatibilityMode) { // If there is even a single enabled child, then we're using a Unity 4.0-based nested active state scheme. for (int i = 0, imax = t.childCount; i < imax; ++i) { Transform child = t.GetChild(i); if (child.gameObject.activeSelf) return; } // If this point is reached, then all the children are disabled, so we must be using a Unity 3.5-based active state scheme. for (int i = 0, imax = t.childCount; i < imax; ++i) { Transform child = t.GetChild(i); Activate(child, true); } } } /// <summary> /// Deactivate the specified object and all of its children. /// </summary> static void Deactivate (Transform t) { SetActiveSelf(t.gameObject, false); } /// <summary> /// SetActiveRecursively enables children before parents. This is a problem when a widget gets re-enabled /// and it tries to find a panel on its parent. /// </summary> static public void SetActive (GameObject go, bool state) { SetActive(go, state, true); } /// <summary> /// SetActiveRecursively enables children before parents. This is a problem when a widget gets re-enabled /// and it tries to find a panel on its parent. /// </summary> static public void SetActive (GameObject go, bool state, bool compatibilityMode) { if (go) { if (state) { Activate(go.transform, compatibilityMode); #if UNITY_EDITOR if (Application.isPlaying) #endif CallCreatePanel(go.transform); } else Deactivate(go.transform); } } /// <summary> /// Ensure that all widgets have had their panels created, forcing the update right away rather than on the following frame. /// </summary> [System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerStepThrough] static void CallCreatePanel (Transform t) { UIWidget w = t.GetComponent<UIWidget>(); if (w != null) w.CreatePanel(); for (int i = 0, imax = t.childCount; i < imax; ++i) CallCreatePanel(t.GetChild(i)); } /// <summary> /// Activate or deactivate children of the specified game object without changing the active state of the object itself. /// </summary> static public void SetActiveChildren (GameObject go, bool state) { Transform t = go.transform; if (state) { for (int i = 0, imax = t.childCount; i < imax; ++i) { Transform child = t.GetChild(i); Activate(child); } } else { for (int i = 0, imax = t.childCount; i < imax; ++i) { Transform child = t.GetChild(i); Deactivate(child); } } } /// <summary> /// Helper function that returns whether the specified MonoBehaviour is active. /// </summary> [System.Obsolete("Use NGUITools.GetActive instead")] static public bool IsActive (Behaviour mb) { return mb != null && mb.enabled && mb.gameObject.activeInHierarchy; } /// <summary> /// Helper function that returns whether the specified MonoBehaviour is active. /// </summary> [System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerStepThrough] static public bool GetActive (Behaviour mb) { return mb && mb.enabled && mb.gameObject.activeInHierarchy; } /// <summary> /// Unity4 has changed GameObject.active to GameObject.activeself. /// </summary> [System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerStepThrough] static public bool GetActive (GameObject go) { return go && go.activeInHierarchy; } /// <summary> /// Unity4 has changed GameObject.active to GameObject.SetActive. /// </summary> [System.Diagnostics.DebuggerHidden] [System.Diagnostics.DebuggerStepThrough] static public void SetActiveSelf (GameObject go, bool state) { go.SetActive(state); } /// <summary> /// Recursively set the game object's layer. /// </summary> static public void SetLayer (GameObject go, int layer) { go.layer = layer; Transform t = go.transform; for (int i = 0, imax = t.childCount; i < imax; ++i) { Transform child = t.GetChild(i); SetLayer(child.gameObject, layer); } } /// <summary> /// Helper function used to make the vector use integer numbers. /// </summary> static public Vector3 Round (Vector3 v) { v.x = Mathf.Round(v.x); v.y = Mathf.Round(v.y); v.z = Mathf.Round(v.z); return v; } /// <summary> /// Make the specified selection pixel-perfect. /// </summary> static public void MakePixelPerfect (Transform t) { UIWidget w = t.GetComponent<UIWidget>(); if (w != null) w.MakePixelPerfect(); if (t.GetComponent<UIAnchor>() == null && t.GetComponent<UIRoot>() == null) { #if UNITY_EDITOR RegisterUndo(t, "Make Pixel-Perfect"); #endif t.localPosition = Round(t.localPosition); t.localScale = Round(t.localScale); } // Recurse into children for (int i = 0, imax = t.childCount; i < imax; ++i) MakePixelPerfect(t.GetChild(i)); } /// <summary> /// Save the specified binary data into the specified file. /// </summary> static public bool Save (string fileName, byte[] bytes) { #if UNITY_WEBPLAYER || UNITY_FLASH || UNITY_METRO || UNITY_WP8 || UNITY_WP_8_1 return false; #else if (!NGUITools.fileAccess) return false; string path = ""; if (bytes == null) { if (File.Exists(path)) File.Delete(path); return true; } FileStream file = null; try { file = File.Create(path); } catch (System.Exception ex) { Debug.LogError(ex.Message); return false; } file.Write(bytes, 0, bytes.Length); file.Close(); return true; #endif } /// <summary> /// Load all binary data from the specified file. /// </summary> static public byte[] Load (string fileName) { #if UNITY_WEBPLAYER || UNITY_FLASH || UNITY_METRO || UNITY_WP8 || UNITY_WP_8_1 return null; #else if (!NGUITools.fileAccess) return null; string path = ""; if (File.Exists(path)) { return File.ReadAllBytes(path); } return null; #endif } /// <summary> /// Pre-multiply shaders result in a black outline if this operation is done in the shader. It's better to do it outside. /// </summary> static public Color ApplyPMA (Color c) { if (c.a != 1f) { c.r *= c.a; c.g *= c.a; c.b *= c.a; } return c; } /// <summary> /// Inform all widgets underneath the specified object that the parent has changed. /// </summary> static public void MarkParentAsChanged (GameObject go) { UIRect[] rects = go.GetComponentsInChildren<UIRect>(); for (int i = 0, imax = rects.Length; i < imax; ++i) rects[i].ParentHasChanged(); } /// <summary> /// Access to the clipboard via undocumented APIs. /// </summary> static public string clipboard { get { TextEditor te = new TextEditor(); te.Paste(); return te.content.text; } set { TextEditor te = new TextEditor(); te.content = new GUIContent(value); te.OnFocus(); te.Copy(); } } [System.Obsolete("Use NGUIText.EncodeColor instead")] static public string EncodeColor (Color c) { return NGUIText.EncodeColor24(c); } [System.Obsolete("Use NGUIText.ParseColor instead")] static public Color ParseColor (string text, int offset) { return NGUIText.ParseColor24(text, offset); } [System.Obsolete("Use NGUIText.StripSymbols instead")] static public string StripSymbols (string text) { return NGUIText.StripSymbols(text); } /// <summary> /// Extension for the game object that checks to see if the component already exists before adding a new one. /// If the component is already present it will be returned instead. /// </summary> static public T AddMissingComponent<T> (this GameObject go) where T : Component { #if UNITY_FLASH object comp = go.GetComponent<T>(); #else T comp = go.GetComponent<T>(); #endif if (comp == null) { #if UNITY_EDITOR if (!Application.isPlaying) RegisterUndo(go, "Add " + typeof(T)); #endif comp = go.AddComponent<T>(); } #if UNITY_FLASH return (T)comp; #else return comp; #endif } // Temporary variable to avoid GC allocation static Vector3[] mSides = new Vector3[4]; /// <summary> /// Get sides relative to the specified camera. The order is left, top, right, bottom. /// </summary> static public Vector3[] GetSides (this Camera cam) { return cam.GetSides(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), null); } /// <summary> /// Get sides relative to the specified camera. The order is left, top, right, bottom. /// </summary> static public Vector3[] GetSides (this Camera cam, float depth) { return cam.GetSides(depth, null); } /// <summary> /// Get sides relative to the specified camera. The order is left, top, right, bottom. /// </summary> static public Vector3[] GetSides (this Camera cam, Transform relativeTo) { return cam.GetSides(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), relativeTo); } /// <summary> /// Get sides relative to the specified camera. The order is left, top, right, bottom. /// </summary> static public Vector3[] GetSides (this Camera cam, float depth, Transform relativeTo) { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (cam.isOrthoGraphic) #else if (cam.orthographic) #endif { float os = cam.orthographicSize; float x0 = -os; float x1 = os; float y0 = -os; float y1 = os; Rect rect = cam.rect; Vector2 size = screenSize; float aspect = size.x / size.y; aspect *= rect.width / rect.height; x0 *= aspect; x1 *= aspect; // We want to ignore the scale, as scale doesn't affect the camera's view region in Unity Transform t = cam.transform; Quaternion rot = t.rotation; Vector3 pos = t.position; int w = Mathf.RoundToInt(size.x); int h = Mathf.RoundToInt(size.y); if ((w & 1) == 1) pos.x -= 1f / size.x; if ((h & 1) == 1) pos.y += 1f / size.y; mSides[0] = rot * (new Vector3(x0, 0f, depth)) + pos; mSides[1] = rot * (new Vector3(0f, y1, depth)) + pos; mSides[2] = rot * (new Vector3(x1, 0f, depth)) + pos; mSides[3] = rot * (new Vector3(0f, y0, depth)) + pos; } else { mSides[0] = cam.ViewportToWorldPoint(new Vector3(0f, 0.5f, depth)); mSides[1] = cam.ViewportToWorldPoint(new Vector3(0.5f, 1f, depth)); mSides[2] = cam.ViewportToWorldPoint(new Vector3(1f, 0.5f, depth)); mSides[3] = cam.ViewportToWorldPoint(new Vector3(0.5f, 0f, depth)); } if (relativeTo != null) { for (int i = 0; i < 4; ++i) mSides[i] = relativeTo.InverseTransformPoint(mSides[i]); } return mSides; } /// <summary> /// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> static public Vector3[] GetWorldCorners (this Camera cam) { float depth = Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f); return cam.GetWorldCorners(depth, null); } /// <summary> /// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> static public Vector3[] GetWorldCorners (this Camera cam, float depth) { return cam.GetWorldCorners(depth, null); } /// <summary> /// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> static public Vector3[] GetWorldCorners (this Camera cam, Transform relativeTo) { return cam.GetWorldCorners(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), relativeTo); } /// <summary> /// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> static public Vector3[] GetWorldCorners (this Camera cam, float depth, Transform relativeTo) { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (cam.isOrthoGraphic) #else if (cam.orthographic) #endif { float os = cam.orthographicSize; float x0 = -os; float x1 = os; float y0 = -os; float y1 = os; Rect rect = cam.rect; Vector2 size = screenSize; float aspect = size.x / size.y; aspect *= rect.width / rect.height; x0 *= aspect; x1 *= aspect; // We want to ignore the scale, as scale doesn't affect the camera's view region in Unity Transform t = cam.transform; Quaternion rot = t.rotation; Vector3 pos = t.position; mSides[0] = rot * (new Vector3(x0, y0, depth)) + pos; mSides[1] = rot * (new Vector3(x0, y1, depth)) + pos; mSides[2] = rot * (new Vector3(x1, y1, depth)) + pos; mSides[3] = rot * (new Vector3(x1, y0, depth)) + pos; } else { mSides[0] = cam.ViewportToWorldPoint(new Vector3(0f, 0f, depth)); mSides[1] = cam.ViewportToWorldPoint(new Vector3(0f, 1f, depth)); mSides[2] = cam.ViewportToWorldPoint(new Vector3(1f, 1f, depth)); mSides[3] = cam.ViewportToWorldPoint(new Vector3(1f, 0f, depth)); } if (relativeTo != null) { for (int i = 0; i < 4; ++i) mSides[i] = relativeTo.InverseTransformPoint(mSides[i]); } return mSides; } /// <summary> /// Convenience function that converts Class + Function combo into Class.Function representation. /// </summary> static public string GetFuncName (object obj, string method) { if (obj == null) return "<null>"; string type = obj.GetType().ToString(); int period = type.LastIndexOf('/'); if (period > 0) type = type.Substring(period + 1); return string.IsNullOrEmpty(method) ? type : type + "/" + method; } #if UNITY_EDITOR || !UNITY_FLASH /// <summary> /// Execute the specified function on the target game object. /// </summary> static public void Execute<T> (GameObject go, string funcName) where T : Component { T[] comps = go.GetComponents<T>(); foreach (T comp in comps) { #if !UNITY_EDITOR && (UNITY_WEBPLAYER || UNITY_FLASH || UNITY_METRO || UNITY_WP8 || UNITY_WP_8_1) comp.SendMessage(funcName, SendMessageOptions.DontRequireReceiver); #else MethodInfo method = comp.GetType().GetMethod(funcName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) method.Invoke(comp, null); #endif } } /// <summary> /// Execute the specified function on the target game object and all of its children. /// </summary> static public void ExecuteAll<T> (GameObject root, string funcName) where T : Component { Execute<T>(root, funcName); Transform t = root.transform; for (int i = 0, imax = t.childCount; i < imax; ++i) ExecuteAll<T>(t.GetChild(i).gameObject, funcName); } /// <summary> /// Immediately start, update, and create all the draw calls from newly instantiated UI. /// This is useful if you plan on doing something like immediately taking a screenshot then destroying the UI. /// </summary> static public void ImmediatelyCreateDrawCalls (GameObject root) { ExecuteAll<UIWidget>(root, "Start"); ExecuteAll<UIPanel>(root, "Start"); ExecuteAll<UIWidget>(root, "Update"); ExecuteAll<UIPanel>(root, "Update"); ExecuteAll<UIPanel>(root, "LateUpdate"); } #endif #if UNITY_EDITOR static int mSizeFrame = -1; static System.Reflection.MethodInfo s_GetSizeOfMainGameView; static Vector2 mGameSize = Vector2.one; /// <summary> /// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden. /// </summary> static public Vector2 screenSize { get { int frame = Time.frameCount; if (mSizeFrame != frame || !Application.isPlaying) { mSizeFrame = frame; if (s_GetSizeOfMainGameView == null) { System.Type type = System.Type.GetType("UnityEditor.GameView,UnityEditor"); s_GetSizeOfMainGameView = type.GetMethod("GetSizeOfMainGameView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); } mGameSize = (Vector2)s_GetSizeOfMainGameView.Invoke(null, null); } return mGameSize; } } #else /// <summary> /// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden. /// </summary> static public Vector2 screenSize { get { return new Vector2(Screen.width, Screen.height); } } #endif } 这个代码是Unity5.3.3f1版本的,现在升级到Unity 2017.4.0f1 (64-bit)版本 以下是报错信息Assets/NGUI/Scripts/Internal/NGUITools.cs(1438,37): error CS1519: Unexpected symbol `<' in class, struct, or interface member declaration ,把修改后的完整代码给我
07-08
using System.Collections.Generic; using UnityEngine; using Resources.UtilsScripts.SingletonMono; using UnityEngine.Events; using UnityEngine.Serialization; namespace Work.xiepeng.BasicFunctionsOfCar.Scripts.Management { public class MainDriverSeatAdjustmentManagementXp : SingletonMonoBaseXp<MainDriverSeatAdjustmentManagementXp> { #region 状态 // 独立的状态枚举(按功能组) public enum SeatMoveStatus { None, Left, Right } public enum CushionAngleStatus { None, Up, Down } public enum SeatHeightStatus { None, Up, Down } public enum BackrestAngleStatus { None, Forward, Backward } #endregion [SerializeField] [Header("座椅")] private Transform seatTransdorm; [SerializeField] [Header("坐垫")] private Transform cushionTransform; [SerializeField] [Header("靠背")] private Transform backrestTransform; #region 运动参数配置 [Header("运动速度")] [Tooltip("座椅左右移动速度(单位/秒)")] [SerializeField] private float seatMoveSpeed = 0.5f; [Tooltip("坐垫角度调节速度(度/秒)")] [SerializeField] private float cushionAngleSpeed = 10f; [Tooltip("座椅升降速度(单位/秒)")] [SerializeField] private float seatHeightSpeed = 0.1f; [Tooltip("靠背旋转速度(度/秒)")] [SerializeField] private float backrestRotateSpeed = 20f; [Header("运动范围")] [Tooltip("座椅左右移动范围:最小Z值")] [SerializeField] private float seatMinZ = -0.4f; [Tooltip("座椅左右移动范围:最大Z值")] [SerializeField] private float seatMaxZ = 0.7f; [Tooltip("坐垫角度范围:最小X角度")] [SerializeField] private float cushionMinAngleX = -11f; [Tooltip("坐垫角度范围:最大X角度")] [SerializeField] private float cushionMaxAngleX = 0f; [Tooltip("座椅升降范围:最小Y值")] [SerializeField] private float seatMinY = -0.05f; [Tooltip("座椅升降范围:最大Y值")] [SerializeField] private float seatMaxY = 0.1f; [Tooltip("靠背旋转范围:最小X角度")] [SerializeField] private float backrestMinAngleX = -30f; [Tooltip("靠背旋转范围:最大X角度")] [SerializeField] private float backrestMaxAngleX = 30f; #endregion #region 事件系统 // 状态变更事件(参数:新状态) public UnityEvent<SeatMoveStatus> onSeatMoveStatusChanged = new(); public UnityEvent<CushionAngleStatus> onCushionAngleStatusChanged = new(); public UnityEvent<SeatHeightStatus> onSeatHeightStatusChanged = new(); public UnityEvent<BackrestAngleStatus> onBackrestAngleStatusChanged = new(); // 状态冲突事件(参数:尝试设置的状态,当前状态) public UnityEvent<SeatMoveStatus, SeatMoveStatus> onSeatMoveConflict = new(); public UnityEvent<CushionAngleStatus, CushionAngleStatus> onCushionAngleConflict = new(); public UnityEvent<SeatHeightStatus, SeatHeightStatus> onSeatHeightConflict = new(); public UnityEvent<BackrestAngleStatus, BackrestAngleStatus> onBackrestConflict = new(); #endregion #region 状态管理 // 独立的状态变量 [Header("状态配置")] [SerializeField] private SeatMoveStatus _seatMoveStatus = SeatMoveStatus.None; [SerializeField] private CushionAngleStatus _cushionAngleStatus = CushionAngleStatus.None; [SerializeField] private SeatHeightStatus _seatHeightStatus = SeatHeightStatus.None; [SerializeField] private BackrestAngleStatus _backrestAngleStatus = BackrestAngleStatus.None; // 公开属性用于访问当前状态 public SeatMoveStatus SeatMoveStatus => _seatMoveStatus; public CushionAngleStatus CushionAngleStatus => _cushionAngleStatus; public SeatHeightStatus SeatHeightStatus => _seatHeightStatus; public BackrestAngleStatus BackrestAngleStatus => _backrestAngleStatus; // 设置各功能组状态的方法 public void SetSeatMoveStatus(SeatMoveStatus newStatus) { if (_seatMoveStatus == newStatus) return; // 同一功能组内互斥逻辑 if (newStatus != SeatMoveStatus.None && _seatMoveStatus != SeatMoveStatus.None) { onSeatMoveConflict?.Invoke(newStatus, _seatMoveStatus); Debug.LogWarning($"座椅移动冲突: 无法从 {_seatMoveStatus} 切换到 {newStatus}"); return; } var previousStatus = _seatMoveStatus; _seatMoveStatus = newStatus; onSeatMoveStatusChanged?.Invoke(newStatus); // 记录操作时间(用于自动复位) if (newStatus != SeatMoveStatus.None) { RecordActionTime(SeatActionType.Move); } } public void SetCushionAngleStatus(CushionAngleStatus newStatus) { if (_cushionAngleStatus == newStatus) return; if (newStatus != CushionAngleStatus.None && _cushionAngleStatus != CushionAngleStatus.None) { onCushionAngleConflict?.Invoke(newStatus, _cushionAngleStatus); Debug.LogWarning($"坐垫角度冲突: 无法从 {_cushionAngleStatus} 切换到 {newStatus}"); return; } var previousStatus = _cushionAngleStatus; _cushionAngleStatus = newStatus; onCushionAngleStatusChanged?.Invoke(newStatus); if (newStatus != CushionAngleStatus.None) { RecordActionTime(SeatActionType.Cushion); } } public void SetSeatHeightStatus(SeatHeightStatus newStatus) { if (_seatHeightStatus == newStatus) return; if (newStatus != SeatHeightStatus.None && _seatHeightStatus != SeatHeightStatus.None) { onSeatHeightConflict?.Invoke(newStatus, _seatHeightStatus); Debug.LogWarning($"座椅高度冲突: 无法从 {_seatHeightStatus} 切换到 {newStatus}"); return; } var previousStatus = _seatHeightStatus; _seatHeightStatus = newStatus; onSeatHeightStatusChanged?.Invoke(newStatus); if (newStatus != SeatHeightStatus.None) { RecordActionTime(SeatActionType.Height); } } public void SetBackrestAngleStatus(BackrestAngleStatus newStatus) { if (_backrestAngleStatus == newStatus) return; if (newStatus != BackrestAngleStatus.None && _backrestAngleStatus != BackrestAngleStatus.None) { onBackrestConflict?.Invoke(newStatus, _backrestAngleStatus); Debug.LogWarning($"靠背角度冲突: 无法从 {_backrestAngleStatus} 切换到 {newStatus}"); return; } var previousStatus = _backrestAngleStatus; _backrestAngleStatus = newStatus; onBackrestAngleStatusChanged?.Invoke(newStatus); if (newStatus != BackrestAngleStatus.None) { RecordActionTime(SeatActionType.Backrest); } } #endregion #region 状态控制API /// <summary> /// 座椅向左运动 /// </summary> public void MoveSeatLeft() { SetSeatMoveStatus(SeatMoveStatus.Left); } /// <summary> /// 座椅向右运动 /// </summary> public void MoveSeatRight() { SetSeatMoveStatus(SeatMoveStatus.Right); } /// <summary> /// 停止座椅移动 /// </summary> public void StopSeatMove() { SetSeatMoveStatus(SeatMoveStatus.None); } /// <summary> /// 坐垫角度向上调节 /// </summary> public void AdjustSeatAngleUp() { SetCushionAngleStatus(CushionAngleStatus.Up); } /// <summary> /// 坐垫角度向下调节 /// </summary> public void AdjustSeatAngleDown() { SetCushionAngleStatus(CushionAngleStatus.Down); } /// <summary> /// 停止坐垫角度调节 /// </summary> public void StopCushionAngleAdjustment() { SetCushionAngleStatus(CushionAngleStatus.None); } /// <summary> /// 座椅上升 /// </summary> public void RaiseSeat() { SetSeatHeightStatus(SeatHeightStatus.Up); } /// <summary> /// 座椅下降 /// </summary> public void LowerSeat() { SetSeatHeightStatus(SeatHeightStatus.Down); } /// <summary> /// 停止座椅高度调节 /// </summary> public void StopSeatHeightAdjustment() { SetSeatHeightStatus(SeatHeightStatus.None); } /// <summary> /// 靠背向前调节 /// </summary> public void TiltBackrestForward() { SetBackrestAngleStatus(BackrestAngleStatus.Forward); } /// <summary> /// 靠背向后调节 /// </summary> public void TiltBackrestBackwards() { SetBackrestAngleStatus(BackrestAngleStatus.Backward); } /// <summary> /// 停止靠背调节 /// </summary> public void StopBackrestAdjustment() { SetBackrestAngleStatus(BackrestAngleStatus.None); } /// <summary> /// 停止所有调节 /// </summary> public void StopAllAdjustments() { StopSeatMove(); StopCushionAngleAdjustment(); StopSeatHeightAdjustment(); StopBackrestAdjustment(); } #endregion #region 并行运动逻辑 private void Update() { // 自动复位检查 CheckAutoReset(); // 并行处理所有运动状态 ProcessSeatMove(); ProcessCushionAngle(); ProcessSeatHeight(); ProcessBackrestAngle(); } private void ProcessSeatMove() { switch (_seatMoveStatus) { case SeatMoveStatus.Left: MoveSeatZ(seatMoveSpeed * Time.deltaTime); break; case SeatMoveStatus.Right: MoveSeatZ(-seatMoveSpeed * Time.deltaTime); break; case SeatMoveStatus.None: default: // 无操作 break; } } private void ProcessCushionAngle() { switch (_cushionAngleStatus) { case CushionAngleStatus.Up: RotateCushionX(-cushionAngleSpeed * Time.deltaTime); break; case CushionAngleStatus.Down: RotateCushionX(cushionAngleSpeed * Time.deltaTime); break; case CushionAngleStatus.None: default: // 无操作 break; } } private void ProcessSeatHeight() { switch (_seatHeightStatus) { case SeatHeightStatus.Up: MoveSeatY(seatHeightSpeed * Time.deltaTime); break; case SeatHeightStatus.Down: MoveSeatY(-seatHeightSpeed * Time.deltaTime); break; case SeatHeightStatus.None: default: // 无操作 break; } } private void ProcessBackrestAngle() { switch (_backrestAngleStatus) { case BackrestAngleStatus.Forward: RotateBackrestX(backrestRotateSpeed * Time.deltaTime); break; case BackrestAngleStatus.Backward: RotateBackrestX(-backrestRotateSpeed * Time.deltaTime); break; case BackrestAngleStatus.None: default: // 无操作 break; } } #endregion #region 运动辅助方法 /// <summary> /// 座椅Z轴移动(左右) /// </summary> private void MoveSeatZ(float delta) { if (seatTransdorm == null) return; Vector3 localPos = seatTransdorm.localPosition; float newZ = Mathf.Clamp(localPos.z + delta, seatMinZ, seatMaxZ); // 检查是否到达边界 if (Mathf.Approximately(newZ, seatMinZ) || Mathf.Approximately(newZ, seatMaxZ)) { StopSeatMove(); } seatTransdorm.localPosition = new Vector3( localPos.x, localPos.y, newZ ); } /// <summary> /// 座椅Y轴移动(升降) /// </summary> private void MoveSeatY(float delta) { if (seatTransdorm == null) return; Vector3 localPos = seatTransdorm.localPosition; float newY = Mathf.Clamp(localPos.y + delta, seatMinY, seatMaxY); // 检查是否到达边界 if (Mathf.Approximately(newY, seatMinY) || Mathf.Approximately(newY, seatMaxY)) { StopSeatHeightAdjustment(); } seatTransdorm.localPosition = new Vector3( localPos.x, newY, localPos.z ); } /// <summary> /// 坐垫X轴旋转(角度调节) /// </summary> private void RotateCushionX(float deltaAngle) { if (cushionTransform == null) return; Vector3 localEuler = cushionTransform.localEulerAngles; float currentX = NormalizeAngle(localEuler.x); float newX = Mathf.Clamp(currentX + deltaAngle, cushionMinAngleX, cushionMaxAngleX); // 检查是否到达边界 if (Mathf.Approximately(newX, cushionMinAngleX) || Mathf.Approximately(newX, cushionMaxAngleX)) { StopCushionAngleAdjustment(); } cushionTransform.localEulerAngles = new Vector3( newX, localEuler.y, localEuler.z ); } /// <summary> /// 靠背X轴旋转 /// </summary> private void RotateBackrestX(float deltaAngle) { if (backrestTransform == null) return; Vector3 localEuler = backrestTransform.localEulerAngles; float currentX = NormalizeAngle(localEuler.x); float newX = Mathf.Clamp(currentX + deltaAngle, backrestMinAngleX, backrestMaxAngleX); // 检查是否到达边界 if (Mathf.Approximately(newX, backrestMinAngleX) || Mathf.Approximately(newX, backrestMaxAngleX)) { StopBackrestAdjustment(); } backrestTransform.localEulerAngles = new Vector3( newX, localEuler.y, localEuler.z ); } /// <summary> /// 角度归一化(-180到180度) /// </summary> private float NormalizeAngle(float angle) { while (angle > 180) angle -= 360; while (angle < -180) angle += 360; return angle; } #endregion #region 生命周期 protected override void Awake() { base.Awake(); // 确保初始状态 StopAllAdjustments(); } #endregion #region 调试工具 [Header("调试工具")] [SerializeField] private bool enableDebugLog = true; /// <summary> /// 编辑器调试方法:打印当前状态 /// </summary> [ContextMenu("打印当前状态")] private void DebugPrintStatus() { Debug.Log($"座椅状态: " + $"移动: {_seatMoveStatus}, " + $"坐垫角度: {_cushionAngleStatus}, " + $"高度: {_seatHeightStatus}, " + $"靠背: {_backrestAngleStatus}"); } #endregion #region 自动复位 // 定义动作类型 private enum SeatActionType { Move, Cushion, Height, Backrest } [Header("自动复位配置")] [Tooltip("启用自动复位")] [SerializeField] private bool _enableAutoReset = false; [Tooltip("自动复位时间(秒)")] [SerializeField] private float _autoResetTime = 5f; // 独立记录每个功能的最后操作时间 private Dictionary<SeatActionType, float> _lastActionTimes = new Dictionary<SeatActionType, float>() { { SeatActionType.Move, 0f }, { SeatActionType.Cushion, 0f }, { SeatActionType.Height, 0f }, { SeatActionType.Backrest, 0f } }; // 记录操作时间 private void RecordActionTime(SeatActionType actionType) { _lastActionTimes[actionType] = Time.time; } // 检查自动复位 private void CheckAutoReset() { if (!_enableAutoReset) return; float currentTime = Time.time; // 检查座椅移动 if (_seatMoveStatus != SeatMoveStatus.None && currentTime - _lastActionTimes[SeatActionType.Move] >= _autoResetTime) { StopSeatMove(); } // 检查坐垫角度 if (_cushionAngleStatus != CushionAngleStatus.None && currentTime - _lastActionTimes[SeatActionType.Cushion] >= _autoResetTime) { StopCushionAngleAdjustment(); } // 检查座椅高度 if (_seatHeightStatus != SeatHeightStatus.None && currentTime - _lastActionTimes[SeatActionType.Height] >= _autoResetTime) { StopSeatHeightAdjustment(); } // 检查靠背角度 if (_backrestAngleStatus != BackrestAngleStatus.None && currentTime - _lastActionTimes[SeatActionType.Backrest] >= _autoResetTime) { StopBackrestAdjustment(); } } #endregion } }代码报错帮我调整一下
06-05
//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System.Collections.Generic; /// <summary> /// UI Panel is responsible for collecting, sorting and updating widgets in addition to generating widgets' geometry. /// </summary> [ExecuteInEditMode] [AddComponentMenu("NGUI/UI/NGUI Panel")] public class UIPanel : UIRect { /// <summary> /// List of active panels. /// </summary> static public List<UIPanel> list = new List<UIPanel>(); public enum RenderQueue { Automatic, StartAt, Explicit, } public delegate void OnGeometryUpdated (); /// <summary> /// Notification triggered when the panel's geometry get rebuilt. It's mainly here for debugging purposes. /// </summary> public OnGeometryUpdated onGeometryUpdated; /// <summary> /// Whether this panel will show up in the panel tool (set this to 'false' for dynamically created temporary panels) /// </summary> public bool showInPanelTool = true; /// <summary> /// Whether normals and tangents will be generated for all meshes /// </summary> public bool generateNormals = false; /// <summary> /// Whether widgets drawn by this panel are static (won't move). This will improve performance. /// </summary> public bool widgetsAreStatic = false; /// <summary> /// Whether widgets will be culled while the panel is being dragged. /// Having this on improves performance, but turning it off will reduce garbage collection. /// </summary> public bool cullWhileDragging = true; /// <summary> /// Optimization flag. Makes the assumption that the panel's geometry /// will always be on screen and the bounds don't need to be re-calculated. /// </summary> public bool alwaysOnScreen = false; /// <summary> /// By default, non-clipped panels use the camera's bounds, and the panel's position has no effect. /// If you want the panel's position to actually be used with anchors, set this field to 'true'. /// </summary> public bool anchorOffset = false; /// <summary> /// Whether the soft border will be used as padding. /// </summary> public bool softBorderPadding = true; /// <summary> /// By default all panels manage render queues of their draw calls themselves by incrementing them /// so that the geometry is drawn in the proper order. You can alter this behaviour. /// </summary> public RenderQueue renderQueue = RenderQueue.Automatic; /// <summary> /// Render queue used by the panel. The default value of '3000' is the equivalent of "Transparent". /// This property is only used if 'renderQueue' is set to something other than "Automatic". /// </summary> public int startingRenderQueue = 3000; /// <summary> /// List of widgets managed by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIWidget> widgets = new List<UIWidget>(); /// <summary> /// List of draw calls created by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIDrawCall> drawCalls = new List<UIDrawCall>(); /// <summary> /// Matrix that will transform the specified world coordinates to relative-to-panel coordinates. /// </summary> [System.NonSerialized] public Matrix4x4 worldToLocal = Matrix4x4.identity; /// <summary> /// Cached clip range passed to the draw call's shader. /// </summary> [System.NonSerialized] public Vector4 drawCallClipRange = new Vector4(0f, 0f, 1f, 1f); public delegate void OnClippingMoved (UIPanel panel); /// <summary> /// Event callback that's triggered when the panel's clip region gets moved. /// </summary> public OnClippingMoved onClipMove; // Clip texture feature contributed by the community: http://www.tasharen.com/forum/index.php?topic=9268.0 [HideInInspector][SerializeField] Texture2D mClipTexture = null; // Panel's alpha (affects the alpha of all widgets) [HideInInspector][SerializeField] float mAlpha = 1f; // Clipping rectangle [HideInInspector][SerializeField] UIDrawCall.Clipping mClipping = UIDrawCall.Clipping.None; [HideInInspector][SerializeField] Vector4 mClipRange = new Vector4(0f, 0f, 300f, 200f); [HideInInspector][SerializeField] Vector2 mClipSoftness = new Vector2(4f, 4f); [HideInInspector][SerializeField] int mDepth = 0; [HideInInspector][SerializeField] int mSortingOrder = 0; // Whether a full rebuild of geometry buffers is required bool mRebuild = false; bool mResized = false; [SerializeField] Vector2 mClipOffset = Vector2.zero; float mCullTime = 0f; float mUpdateTime = 0f; int mMatrixFrame = -1; int mAlphaFrameID = 0; int mLayer = -1; // Values used for visibility checks static float[] mTemp = new float[4]; Vector2 mMin = Vector2.zero; Vector2 mMax = Vector2.zero; bool mHalfPixelOffset = false; bool mSortWidgets = false; bool mUpdateScroll = false; /// <summary> /// Helper property that returns the first unused depth value. /// </summary> static public int nextUnusedDepth { get { int highest = int.MinValue; for (int i = 0, imax = list.Count; i < imax; ++i) highest = Mathf.Max(highest, list[i].depth); return (highest == int.MinValue) ? 0 : highest + 1; } } /// <summary> /// Whether the rectangle can be anchored. /// </summary> public override bool canBeAnchored { get { return mClipping != UIDrawCall.Clipping.None; } } /// <summary> /// Panel's alpha affects everything drawn by the panel. /// </summary> public override float alpha { get { return mAlpha; } set { float val = Mathf.Clamp01(value); if (mAlpha != val) { mAlphaFrameID = -1; mResized = true; mAlpha = val; SetDirty(); } } } /// <summary> /// Panels can have their own depth value that will change the order with which everything they manage gets drawn. /// </summary> public int depth { get { return mDepth; } set { if (mDepth != value) { mDepth = value; #if UNITY_EDITOR NGUITools.SetDirty(this); #endif list.Sort(CompareFunc); } } } /// <summary> /// Sorting order value for the panel's draw calls, to be used with Unity's 2D system. /// </summary> public int sortingOrder { get { return mSortingOrder; } set { if (mSortingOrder != value) { mSortingOrder = value; #if UNITY_EDITOR NGUITools.SetDirty(this); #endif UpdateDrawCalls(); } } } /// <summary> /// Function that can be used to depth-sort panels. /// </summary> static public int CompareFunc (UIPanel a, UIPanel b) { if (a != b && a != null && b != null) { if (a.mDepth < b.mDepth) return -1; if (a.mDepth > b.mDepth) return 1; return (a.GetInstanceID() < b.GetInstanceID()) ? -1 : 1; } return 0; } /// <summary> /// Panel's width in pixels. /// </summary> public float width { get { return GetViewSize().x; } } /// <summary> /// Panel's height in pixels. /// </summary> public float height { get { return GetViewSize().y; } } /// <summary> /// Whether the panel's drawn geometry needs to be offset by a half-pixel. /// </summary> public bool halfPixelOffset { get { return mHalfPixelOffset; } } /// <summary> /// Whether the camera is used to draw UI geometry. /// </summary> #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 public bool usedForUI { get { return (anchorCamera != null && mCam.isOrthoGraphic); } } #else public bool usedForUI { get { return (anchorCamera != null && mCam.orthographic); } } #endif /// <summary> /// Directx9 pixel offset, used for drawing. /// </summary> public Vector3 drawCallOffset { get { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (anchorCamera != null && mCam.isOrthoGraphic) #else if (anchorCamera != null && mCam.orthographic) #endif { Vector2 size = GetWindowSize(); float pixelSize = (root != null) ? root.pixelSizeAdjustment : 1f; float mod = (pixelSize / size.y) / mCam.orthographicSize; bool x = mHalfPixelOffset; bool y = mHalfPixelOffset; if ((Mathf.RoundToInt(size.x) & 1) == 1) x = !x; if ((Mathf.RoundToInt(size.y) & 1) == 1) y = !y; return new Vector3(x ? -mod : 0f, y ? mod : 0f); } return Vector3.zero; } } /// <summary> /// Clipping method used by all draw calls. /// </summary> public UIDrawCall.Clipping clipping { get { return mClipping; } set { if (mClipping != value) { mResized = true; mClipping = value; mMatrixFrame = -1; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } UIPanel mParentPanel = null; /// <summary> /// Reference to the parent panel, if any. /// </summary> public UIPanel parentPanel { get { return mParentPanel; } } /// <summary> /// Number of times the panel's contents get clipped. /// </summary> public int clipCount { get { int count = 0; UIPanel p = this; while (p != null) { if (p.mClipping == UIDrawCall.Clipping.SoftClip || p.mClipping == UIDrawCall.Clipping.TextureMask) ++count; p = p.mParentPanel; } return count; } } /// <summary> /// Whether the panel will actually perform clipping of children. /// </summary> public bool hasClipping { get { return mClipping == UIDrawCall.Clipping.SoftClip || mClipping == UIDrawCall.Clipping.TextureMask; } } /// <summary> /// Whether the panel will actually perform clipping of children. /// </summary> public bool hasCumulativeClipping { get { return clipCount != 0; } } [System.Obsolete("Use 'hasClipping' or 'hasCumulativeClipping' instead")] public bool clipsChildren { get { return hasCumulativeClipping; } } /// <summary> /// Clipping area offset used to make it possible to move clipped panels (scroll views) efficiently. /// Scroll views move by adjusting the clip offset by one value, and the transform position by the inverse. /// This makes it possible to not have to rebuild the geometry, greatly improving performance. /// </summary> public Vector2 clipOffset { get { return mClipOffset; } set { if (Mathf.Abs(mClipOffset.x - value.x) > 0.001f || Mathf.Abs(mClipOffset.y - value.y) > 0.001f) { mClipOffset = value; InvalidateClipping(); // Call the event delegate if (onClipMove != null) onClipMove(this); #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Invalidate the panel's clipping, calling child panels in turn. /// </summary> void InvalidateClipping () { mResized = true; mMatrixFrame = -1; mCullTime = (mCullTime == 0f) ? 0.001f : RealTime.time + 0.15f; for (int i = 0, imax = list.Count; i < imax; ++i) { UIPanel p = list[i]; if (p != this && p.parentPanel == this) p.InvalidateClipping(); } } /// <summary> /// Texture used to clip the region. /// </summary> public Texture2D clipTexture { get { return mClipTexture; } set { if (mClipTexture != value) { mClipTexture = value; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Clipping position (XY) and size (ZW). /// Note that you should not be modifying this property at run-time to reposition the clipping. Adjust clipOffset instead. /// </summary> [System.Obsolete("Use 'finalClipRegion' or 'baseClipRegion' instead")] public Vector4 clipRange { get { return baseClipRegion; } set { baseClipRegion = value; } } /// <summary> /// Clipping position (XY) and size (ZW). /// Note that you should not be modifying this property at run-time to reposition the clipping. Adjust clipOffset instead. /// </summary> public Vector4 baseClipRegion { get { return mClipRange; } set { if (Mathf.Abs(mClipRange.x - value.x) > 0.001f || Mathf.Abs(mClipRange.y - value.y) > 0.001f || Mathf.Abs(mClipRange.z - value.z) > 0.001f || Mathf.Abs(mClipRange.w - value.w) > 0.001f) { mResized = true; mCullTime = (mCullTime == 0f) ? 0.001f : RealTime.time + 0.15f; mClipRange = value; mMatrixFrame = -1; UIScrollView sv = GetComponent<UIScrollView>(); if (sv != null) sv.UpdatePosition(); if (onClipMove != null) onClipMove(this); #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Final clipping region after the offset has been taken into consideration. XY = center, ZW = size. /// </summary> public Vector4 finalClipRegion { get { Vector2 size = GetViewSize(); if (mClipping != UIDrawCall.Clipping.None) { return new Vector4(mClipRange.x + mClipOffset.x, mClipRange.y + mClipOffset.y, size.x, size.y); } return new Vector4(0f, 0f, size.x, size.y); } } /// <summary> /// Clipping softness is used if the clipped style is set to "Soft". /// </summary> public Vector2 clipSoftness { get { return mClipSoftness; } set { if (mClipSoftness != value) { mClipSoftness = value; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } // Temporary variable to avoid GC allocation static Vector3[] mCorners = new Vector3[4]; /// <summary> /// Local-space corners of the panel's clipping rectangle. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> public override Vector3[] localCorners { get { if (mClipping == UIDrawCall.Clipping.None) { Vector3[] corners = worldCorners; Transform wt = cachedTransform; for (int i = 0; i < 4; ++i) corners[i] = wt.InverseTransformPoint(corners[i]); return corners; } else { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; mCorners[0] = new Vector3(x0, y0); mCorners[1] = new Vector3(x0, y1); mCorners[2] = new Vector3(x1, y1); mCorners[3] = new Vector3(x1, y0); } return mCorners; } } /// <summary> /// World-space corners of the panel's clipping rectangle. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> public override Vector3[] worldCorners { get { if (mClipping != UIDrawCall.Clipping.None) { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; Transform wt = cachedTransform; mCorners[0] = wt.TransformPoint(x0, y0, 0f); mCorners[1] = wt.TransformPoint(x0, y1, 0f); mCorners[2] = wt.TransformPoint(x1, y1, 0f); mCorners[3] = wt.TransformPoint(x1, y0, 0f); } else if (anchorCamera != null) { Vector3[] corners = mCam.GetWorldCorners(cameraRayDistance); //if (anchorOffset && (mCam == null || mCam.transform.parent != cachedTransform)) //{ // Vector3 off = cachedTransform.position; // for (int i = 0; i < 4; ++i) // corners[i] += off; //} return corners; } else { Vector2 size = GetViewSize(); float x0 = -0.5f * size.x; float y0 = -0.5f * size.y; float x1 = x0 + size.x; float y1 = y0 + size.y; mCorners[0] = new Vector3(x0, y0); mCorners[1] = new Vector3(x0, y1); mCorners[2] = new Vector3(x1, y1); mCorners[3] = new Vector3(x1, y0); if (anchorOffset && (mCam == null || mCam.transform.parent != cachedTransform)) { Vector3 off = cachedTransform.position; for (int i = 0; i < 4; ++i) mCorners[i] += off; } } return mCorners; } } /// <summary> /// Get the sides of the rectangle relative to the specified transform. /// The order is left, top, right, bottom. /// </summary> public override Vector3[] GetSides (Transform relativeTo) { if (mClipping != UIDrawCall.Clipping.None) { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; float hx = (x0 + x1) * 0.5f; float hy = (y0 + y1) * 0.5f; Transform wt = cachedTransform; mSides[0] = wt.TransformPoint(x0, hy, 0f); mSides[1] = wt.TransformPoint(hx, y1, 0f); mSides[2] = wt.TransformPoint(x1, hy, 0f); mSides[3] = wt.TransformPoint(hx, y0, 0f); if (relativeTo != null) { for (int i = 0; i < 4; ++i) mSides[i] = relativeTo.InverseTransformPoint(mSides[i]); } return mSides; } else if (anchorCamera != null && anchorOffset) { Vector3[] sides = mCam.GetSides(cameraRayDistance); Vector3 off = cachedTransform.position; for (int i = 0; i < 4; ++i) sides[i] += off; if (relativeTo != null) { for (int i = 0; i < 4; ++i) sides[i] = relativeTo.InverseTransformPoint(sides[i]); } return sides; } return base.GetSides(relativeTo); } /// <summary> /// Invalidating the panel should reset its alpha. /// </summary> public override void Invalidate (bool includeChildren) { mAlphaFrameID = -1; base.Invalidate(includeChildren); } /// <summary> /// Widget's final alpha, after taking the panel's alpha into account. /// </summary> public override float CalculateFinalAlpha (int frameID) { #if UNITY_EDITOR if (mAlphaFrameID != frameID || !Application.isPlaying) #else if (mAlphaFrameID != frameID) #endif { mAlphaFrameID = frameID; UIRect pt = parent; finalAlpha = (parent != null) ? pt.CalculateFinalAlpha(frameID) * mAlpha : mAlpha; } return finalAlpha; } /// <summary> /// Set the panel's rectangle. /// </summary> public override void SetRect (float x, float y, float width, float height) { int finalWidth = Mathf.FloorToInt(width + 0.5f); int finalHeight = Mathf.FloorToInt(height + 0.5f); finalWidth = ((finalWidth >> 1) << 1); finalHeight = ((finalHeight >> 1) << 1); Transform t = cachedTransform; Vector3 pos = t.localPosition; pos.x = Mathf.Floor(x + 0.5f); pos.y = Mathf.Floor(y + 0.5f); if (finalWidth < 2) finalWidth = 2; if (finalHeight < 2) finalHeight = 2; baseClipRegion = new Vector4(pos.x, pos.y, finalWidth, finalHeight); if (isAnchored) { t = t.parent; if (leftAnchor.target) leftAnchor.SetHorizontal(t, x); if (rightAnchor.target) rightAnchor.SetHorizontal(t, x + width); if (bottomAnchor.target) bottomAnchor.SetVertical(t, y); if (topAnchor.target) topAnchor.SetVertical(t, y + height); #if UNITY_EDITOR NGUITools.SetDirty(this); #endif } } /// <summary> /// Returns whether the specified rectangle is visible by the panel. The coordinates must be in world space. /// </summary> #if UNITY_FLASH public bool IsVisible (Vector3 aa, Vector3 bb, Vector3 cc, Vector3 dd) #else public bool IsVisible (Vector3 a, Vector3 b, Vector3 c, Vector3 d) #endif { UpdateTransformMatrix(); // Transform the specified points from world space to local space #if UNITY_FLASH // http://www.tasharen.com/forum/index.php?topic=11390.0 Vector3 a = worldToLocal.MultiplyPoint3x4(aa); Vector3 b = worldToLocal.MultiplyPoint3x4(bb); Vector3 c = worldToLocal.MultiplyPoint3x4(cc); Vector3 d = worldToLocal.MultiplyPoint3x4(dd); #else a = worldToLocal.MultiplyPoint3x4(a); b = worldToLocal.MultiplyPoint3x4(b); c = worldToLocal.MultiplyPoint3x4(c); d = worldToLocal.MultiplyPoint3x4(d); #endif mTemp[0] = a.x; mTemp[1] = b.x; mTemp[2] = c.x; mTemp[3] = d.x; float minX = Mathf.Min(mTemp); float maxX = Mathf.Max(mTemp); mTemp[0] = a.y; mTemp[1] = b.y; mTemp[2] = c.y; mTemp[3] = d.y; float minY = Mathf.Min(mTemp); float maxY = Mathf.Max(mTemp); if (maxX < mMin.x) return false; if (maxY < mMin.y) return false; if (minX > mMax.x) return false; if (minY > mMax.y) return false; return true; } /// <summary> /// Returns whether the specified world position is within the panel's bounds determined by the clipping rect. /// </summary> public bool IsVisible (Vector3 worldPos) { if (mAlpha < 0.001f) return false; if (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip) return true; UpdateTransformMatrix(); Vector3 pos = worldToLocal.MultiplyPoint3x4(worldPos); if (pos.x < mMin.x) return false; if (pos.y < mMin.y) return false; if (pos.x > mMax.x) return false; if (pos.y > mMax.y) return false; return true; } /// <summary> /// Returns whether the specified widget is visible by the panel. /// </summary> public bool IsVisible (UIWidget w) { UIPanel p = this; Vector3[] corners = null; while (p != null) { if ((p.mClipping == UIDrawCall.Clipping.None || p.mClipping == UIDrawCall.Clipping.ConstrainButDontClip) && !w.hideIfOffScreen) { p = p.mParentPanel; continue; } if (corners == null) corners = w.worldCorners; if (!p.IsVisible(corners[0], corners[1], corners[2], corners[3])) return false; p = p.mParentPanel; } return true; } /// <summary> /// Whether the specified widget is going to be affected by this panel in any way. /// </summary> public bool Affects (UIWidget w) { if (w == null) return false; UIPanel expected = w.panel; if (expected == null) return false; UIPanel p = this; while (p != null) { if (p == expected) return true; if (!p.hasCumulativeClipping) return false; p = p.mParentPanel; } return false; } /// <summary> /// Causes all draw calls to be re-created on the next update. /// </summary> [ContextMenu("Force Refresh")] public void RebuildAllDrawCalls () { mRebuild = true; } /// <summary> /// Invalidate the panel's draw calls, forcing them to be rebuilt on the next update. /// This call also affects all children. /// </summary> public void SetDirty () { for (int i = 0, imax = drawCalls.Count; i < imax; ++i) drawCalls[i].isDirty = true; Invalidate(true); } /// <summary> /// Cache components. /// </summary> void Awake () { mGo = gameObject; mTrans = transform; mHalfPixelOffset = (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.XBOX360 || Application.platform == RuntimePlatform.WindowsWebPlayer || Application.platform == RuntimePlatform.WindowsEditor); // Only DirectX 9 needs the half-pixel offset if (mHalfPixelOffset && SystemInfo.graphicsDeviceVersion.Contains("Direct3D")) mHalfPixelOffset = (SystemInfo.graphicsShaderLevel < 40); } /// <summary> /// Find the parent panel, if we have one. /// </summary> void FindParent () { Transform parent = cachedTransform.parent; mParentPanel = (parent != null) ? NGUITools.FindInParents<UIPanel>(parent.gameObject) : null; } /// <summary> /// Find the parent panel, if we have one. /// </summary> public override void ParentHasChanged () { base.ParentHasChanged(); FindParent(); } /// <summary> /// Layer is used to ensure that if it changes, widgets get moved as well. /// </summary> protected override void OnStart () { mLayer = mGo.layer; } /// <summary> /// Reset the frame IDs. /// </summary> protected override void OnEnable () { mRebuild = true; mAlphaFrameID = -1; mMatrixFrame = -1; OnStart(); base.OnEnable(); mMatrixFrame = -1; } /// <summary> /// Mark all widgets as having been changed so the draw calls get re-created. /// </summary> protected override void OnInit () { if (list.Contains(this)) return; base.OnInit(); FindParent(); // Apparently having a rigidbody helps #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (rigidbody == null && mParentPanel == null) #else if (GetComponent<Rigidbody>() == null && mParentPanel == null) #endif { UICamera uic = (anchorCamera != null) ? mCam.GetComponent<UICamera>() : null; if (uic != null) { if (uic.eventType == UICamera.EventType.UI_3D || uic.eventType == UICamera.EventType.World_3D) { Rigidbody rb = gameObject.AddComponent<Rigidbody>(); rb.isKinematic = true; rb.useGravity = false; } // It's unclear if this helps 2D physics or not, so leaving it disabled for now. // Note that when enabling this, the 'if (rigidbody == null)' statement above should be adjusted as well. //else //{ // Rigidbody2D rb = gameObject.AddComponent<Rigidbody2D>(); // rb.isKinematic = true; //} } } mRebuild = true; mAlphaFrameID = -1; mMatrixFrame = -1; list.Add(this); list.Sort(CompareFunc); } /// <summary> /// Destroy all draw calls we've created when this script gets disabled. /// </summary> protected override void OnDisable () { for (int i = 0, imax = drawCalls.Count; i < imax; ++i) { UIDrawCall dc = drawCalls[i]; UIDrawCall.Destroy(dc); } drawCalls.Clear(); list.Remove(this); mAlphaFrameID = -1; mMatrixFrame = -1; if (list.Count == 0) { UIDrawCall.ReleaseAll(); mUpdateFrame = -1; } base.OnDisable(); } /// <summary> /// Update the world-to-local transform matrix as well as clipping bounds. /// </summary> void UpdateTransformMatrix () { int fc = Time.frameCount; if (mMatrixFrame != fc) { mMatrixFrame = fc; worldToLocal = cachedTransform.worldToLocalMatrix; Vector2 size = GetViewSize() * 0.5f; float x = mClipOffset.x + mClipRange.x; float y = mClipOffset.y + mClipRange.y; mMin.x = x - size.x; mMin.y = y - size.y; mMax.x = x + size.x; mMax.y = y + size.y; } } /// <summary> /// Update the edges after the anchors have been updated. /// </summary> protected override void OnAnchor () { // No clipping = no edges to anchor if (mClipping == UIDrawCall.Clipping.None) return; Transform trans = cachedTransform; Transform parent = trans.parent; Vector2 size = GetViewSize(); Vector2 offset = trans.localPosition; float lt, bt, rt, tt; // Attempt to fast-path if all anchors match if (leftAnchor.target == bottomAnchor.target && leftAnchor.target == rightAnchor.target && leftAnchor.target == topAnchor.target) { Vector3[] sides = leftAnchor.GetSides(parent); if (sides != null) { lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute; rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute; bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute; tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute; } else { // Anchored to a single transform Vector2 lp = GetLocalPos(leftAnchor, parent); lt = lp.x + leftAnchor.absolute; bt = lp.y + bottomAnchor.absolute; rt = lp.x + rightAnchor.absolute; tt = lp.y + topAnchor.absolute; } } else { // Left anchor point if (leftAnchor.target) { Vector3[] sides = leftAnchor.GetSides(parent); if (sides != null) { lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute; } else { lt = GetLocalPos(leftAnchor, parent).x + leftAnchor.absolute; } } else lt = mClipRange.x - 0.5f * size.x; // Right anchor point if (rightAnchor.target) { Vector3[] sides = rightAnchor.GetSides(parent); if (sides != null) { rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute; } else { rt = GetLocalPos(rightAnchor, parent).x + rightAnchor.absolute; } } else rt = mClipRange.x + 0.5f * size.x; // Bottom anchor point if (bottomAnchor.target) { Vector3[] sides = bottomAnchor.GetSides(parent); if (sides != null) { bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute; } else { bt = GetLocalPos(bottomAnchor, parent).y + bottomAnchor.absolute; } } else bt = mClipRange.y - 0.5f * size.y; // Top anchor point if (topAnchor.target) { Vector3[] sides = topAnchor.GetSides(parent); if (sides != null) { tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute; } else { tt = GetLocalPos(topAnchor, parent).y + topAnchor.absolute; } } else tt = mClipRange.y + 0.5f * size.y; } // Take the offset into consideration lt -= offset.x + mClipOffset.x; rt -= offset.x + mClipOffset.x; bt -= offset.y + mClipOffset.y; tt -= offset.y + mClipOffset.y; // Calculate the new position, width and height float newX = Mathf.Lerp(lt, rt, 0.5f); float newY = Mathf.Lerp(bt, tt, 0.5f); float w = rt - lt; float h = tt - bt; float minx = Mathf.Max(2f, mClipSoftness.x); float miny = Mathf.Max(2f, mClipSoftness.y); if (w < minx) w = minx; if (h < miny) h = miny; // Update the clipping range baseClipRegion = new Vector4(newX, newY, w, h); } static int mUpdateFrame = -1; /// <summary> /// Update all panels and draw calls. /// </summary> void LateUpdate () { #if UNITY_EDITOR if (mUpdateFrame != Time.frameCount || !Application.isPlaying) #else if (mUpdateFrame != Time.frameCount) #endif { mUpdateFrame = Time.frameCount; // Update each panel in order for (int i = 0, imax = list.Count; i < imax; ++i) list[i].UpdateSelf(); int rq = 3000; // Update all draw calls, making them draw in the right order for (int i = 0, imax = list.Count; i < imax; ++i) { UIPanel p = list[i]; if (p.renderQueue == RenderQueue.Automatic) { p.startingRenderQueue = rq; p.UpdateDrawCalls(); rq += p.drawCalls.Count; } else if (p.renderQueue == RenderQueue.StartAt) { p.UpdateDrawCalls(); if (p.drawCalls.Count != 0) rq = Mathf.Max(rq, p.startingRenderQueue + p.drawCalls.Count); } else // Explicit { p.UpdateDrawCalls(); if (p.drawCalls.Count != 0) rq = Mathf.Max(rq, p.startingRenderQueue + 1); } } } } /// <summary> /// Update the panel, all of its widgets and draw calls. /// </summary> void UpdateSelf () { mUpdateTime = RealTime.time; UpdateTransformMatrix(); UpdateLayers(); UpdateWidgets(); if (mRebuild) { mRebuild = false; FillAllDrawCalls(); } else { for (int i = 0; i < drawCalls.Count; ) { UIDrawCall dc = drawCalls[i]; if (dc.isDirty && !FillDrawCall(dc)) { UIDrawCall.Destroy(dc); drawCalls.RemoveAt(i); continue; } ++i; } } if (mUpdateScroll) { mUpdateScroll = false; UIScrollView sv = GetComponent<UIScrollView>(); if (sv != null) sv.UpdateScrollbars(); } } /// <summary> /// Immediately sort all child widgets. /// </summary> public void SortWidgets () { mSortWidgets = false; widgets.Sort(UIWidget.PanelCompareFunc); } /// <summary> /// Fill the geometry fully, processing all widgets and re-creating all draw calls. /// </summary> void FillAllDrawCalls () { for (int i = 0; i < drawCalls.Count; ++i) { if (drawCalls[i] != null) UIDrawCall.Destroy(drawCalls[i]); } drawCalls.Clear(); Material mat = null; Texture tex = null; Shader sdr = null; UIDrawCall dc = null; int count = 0; if (mSortWidgets) SortWidgets(); for (int i = 0; i < widgets.Count; ++i) { UIWidget w = widgets[i]; if (w.isVisible && w.hasVertices) { //Debug.LogError("999999999"); Material mt = w.material; Texture tx = w.mainTexture; Shader sd = w.shader; if (mat != mt || tex != tx || sdr != sd && !w.IsMyWidget)// { if (dc != null && dc.verts.size != 0) { drawCalls.Add(dc); dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; count = 0; dc = null; } mat = mt; tex = tx; sdr = sd; } if (mat != null || sdr != null || tex != null || w.IsMyWidget)//wycm || w.IsMyWidget { if (dc == null || w.IsMyWidget) { if (w.IsMyWidget) { dc = new UIDrawCall(); //UIDrawCall.Create(this, null, null, null, w.gameObject.name, true); drawCalls.Add(dc); } else { 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; ++count; if (w.IsMyWidget) { //dc = UIDrawCall.Create(this, null, null, null, w.gameObject.name, true); //dc = new UIDrawCall(); dc.IsMyWidget = true; //w.drawCall.renderQueue = startingRenderQueue + i; dc.MyWidget = w; //dc.panel = this; //drawCalls.Add(dc); Debug.LogError("IsMyWidget"); //w.drawCall = dc; //w.resetdeth(startingRenderQueue + i); } else { 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); if (w.mOnRender != null) { if (mOnRender == null) mOnRender = w.mOnRender; else mOnRender += w.mOnRender; } } } } else w.drawCall = null; } if (dc != null && dc.verts.size != 0) { drawCalls.Add(dc); dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; } } UIDrawCall.OnRenderCallback mOnRender; /// <summary> /// Fill the geometry for the specified draw call. /// </summary> bool FillDrawCall (UIDrawCall dc) { if (dc != null) { dc.isDirty = false; int count = 0; 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) { ++count; 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); if (w.mOnRender != null) { if (mOnRender == null) mOnRender = w.mOnRender; else mOnRender += w.mOnRender; } } else w.drawCall = null; } ++i; } if (dc.verts.size != 0) { dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; return true; } } return false; } /// <summary> /// Update all draw calls associated with the panel. /// </summary> void UpdateDrawCalls () { Transform trans = cachedTransform; bool isUI = usedForUI; if (clipping != UIDrawCall.Clipping.None) { drawCallClipRange = finalClipRegion; drawCallClipRange.z *= 0.5f; drawCallClipRange.w *= 0.5f; } else drawCallClipRange = Vector4.zero; int w = Screen.width; int h = Screen.height; // Legacy functionality if (drawCallClipRange.z == 0f) drawCallClipRange.z = w * 0.5f; if (drawCallClipRange.w == 0f) drawCallClipRange.w = h * 0.5f; // DirectX 9 half-pixel offset if (halfPixelOffset) { drawCallClipRange.x -= 0.5f; drawCallClipRange.y += 0.5f; } Vector3 pos; if (isUI) { Transform parent = cachedTransform.parent; pos = cachedTransform.localPosition; if (clipping != UIDrawCall.Clipping.None) { pos.x = Mathf.RoundToInt(pos.x); pos.y = Mathf.RoundToInt(pos.y); } if (parent != null) pos = parent.TransformPoint(pos); pos += drawCallOffset; } else pos = trans.position; Quaternion rot = trans.rotation; Vector3 scale = trans.lossyScale; for (int i = 0; i < drawCalls.Count; ++i) { UIDrawCall dc = drawCalls[i]; if (dc.IsMyWidget) { dc.renderQueue = startingRenderQueue + i; if (dc.MyWidget != null) dc.MyWidget.resetdeth(startingRenderQueue + i); } else { Transform t = dc.cachedTransform; t.position = pos; t.rotation = rot; t.localScale = scale; dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i; dc.alwaysOnScreen = alwaysOnScreen && (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip); dc.sortingOrder = mSortingOrder; dc.clipTexture = mClipTexture; } } } /// <summary> /// Update the widget layers if the panel's layer has changed. /// </summary> void UpdateLayers () { // Always move widgets to the panel's layer if (mLayer != cachedGameObject.layer) { mLayer = mGo.layer; for (int i = 0, imax = widgets.Count; i < imax; ++i) { UIWidget w = widgets[i]; if (w && w.parent == this) w.gameObject.layer = mLayer; } ResetAnchors(); for (int i = 0; i < drawCalls.Count; ++i) drawCalls[i].gameObject.layer = mLayer; } } bool mForced = false; /// <summary> /// Update all of the widgets belonging to this panel. /// </summary> void UpdateWidgets() { #if UNITY_EDITOR bool forceVisible = cullWhileDragging ? false : (Application.isPlaying && mCullTime > mUpdateTime); #else bool forceVisible = cullWhileDragging ? false : (mCullTime > mUpdateTime); #endif bool changed = false; if (mForced != forceVisible) { mForced = forceVisible; mResized = true; } bool clipped = hasCumulativeClipping; // Update all widgets for (int i = 0, imax = widgets.Count; i < imax; ++i) { UIWidget w = widgets[i]; // If the widget is visible, update it if (w.panel == this && w.enabled) { #if UNITY_EDITOR // When an object is dragged from Project view to Scene view, its Z is... // odd, to say the least. Force it if possible. if (!Application.isPlaying) { Transform t = w.cachedTransform; if (t.hideFlags != HideFlags.HideInHierarchy) { t = (t.parent != null && t.parent.hideFlags == HideFlags.HideInHierarchy) ? t.parent : null; } if (t != null) { for (; ; ) { if (t.parent == null) break; if (t.parent.hideFlags == HideFlags.HideInHierarchy) t = t.parent; else break; } if (t != null) { Vector3 pos = t.localPosition; pos.x = Mathf.Round(pos.x); pos.y = Mathf.Round(pos.y); pos.z = 0f; if (Vector3.SqrMagnitude(t.localPosition - pos) > 0.0001f) t.localPosition = pos; } } } #endif int frame = Time.frameCount; // First update the widget's transform if (w.UpdateTransform(frame) || mResized) { // Only proceed to checking the widget's visibility if it actually moved bool vis = forceVisible || (w.CalculateCumulativeAlpha(frame) > 0.001f); w.UpdateVisibility(vis, forceVisible || ((clipped || w.hideIfOffScreen) ? IsVisible(w) : true)); } // Update the widget's geometry if necessary if (w.UpdateGeometry(frame)) { changed = true; if (!mRebuild) { if (w.drawCall != null) { w.drawCall.isDirty = true; } else { // Find an existing draw call, if possible FindDrawCall(w); } } } } } // Inform the changed event listeners if (changed && onGeometryUpdated != null) onGeometryUpdated(); mResized = false; } /// <summary> /// Insert the specified widget into one of the existing draw calls if possible. /// If it's not possible, and a new draw call is required, 'null' is returned /// because draw call creation is a delayed operation. /// </summary> public UIDrawCall FindDrawCall (UIWidget w) { Material mat = w.material; Texture tex = w.mainTexture; int depth = w.depth; for (int i = 0; i < drawCalls.Count; ++i) { UIDrawCall dc = drawCalls[i]; int dcStart = (i == 0) ? int.MinValue : drawCalls[i - 1].depthEnd + 1; int dcEnd = (i + 1 == drawCalls.Count) ? int.MaxValue : drawCalls[i + 1].depthStart - 1; if (dcStart <= depth && dcEnd >= depth) { if (dc.baseMaterial == mat && dc.mainTexture == tex) { if (w.isVisible) { w.drawCall = dc; if (w.hasVertices) dc.isDirty = true; return dc; } } else mRebuild = true; return null; } } mRebuild = true; return null; } /// <summary> /// Make the following widget be managed by the panel. /// </summary> public void AddWidget (UIWidget w) { mUpdateScroll = true; if (widgets.Count == 0) { widgets.Add(w); } else if (mSortWidgets) { widgets.Add(w); SortWidgets(); } else if (UIWidget.PanelCompareFunc(w, widgets[0]) == -1) { widgets.Insert(0, w); } else { for (int i = widgets.Count; i > 0; ) { if (UIWidget.PanelCompareFunc(w, widgets[--i]) == -1) continue; widgets.Insert(i+1, w); break; } } FindDrawCall(w); } /// <summary> /// Remove the widget from its current draw call, invalidating everything as needed. /// </summary> public void RemoveWidget (UIWidget w) { if (widgets.Remove(w) && w.drawCall != null) { int depth = w.depth; if (depth == w.drawCall.depthStart || depth == w.drawCall.depthEnd) mRebuild = true; w.drawCall.isDirty = true; w.drawCall = null; } } /// <summary> /// Immediately refresh the panel. /// </summary> public void Refresh () { mRebuild = true; mUpdateFrame = -1; if (list.Count > 0) list[0].LateUpdate(); } // <summary> /// Calculate the offset needed to be constrained within the panel's bounds. /// </summary> public virtual Vector3 CalculateConstrainOffset (Vector2 min, Vector2 max) { Vector4 cr = finalClipRegion; float offsetX = cr.z * 0.5f; float offsetY = cr.w * 0.5f; Vector2 minRect = new Vector2(min.x, min.y); Vector2 maxRect = new Vector2(max.x, max.y); Vector2 minArea = new Vector2(cr.x - offsetX, cr.y - offsetY); Vector2 maxArea = new Vector2(cr.x + offsetX, cr.y + offsetY); if (softBorderPadding && clipping == UIDrawCall.Clipping.SoftClip) { minArea.x += mClipSoftness.x; minArea.y += mClipSoftness.y; maxArea.x -= mClipSoftness.x; maxArea.y -= mClipSoftness.y; } return NGUIMath.ConstrainRect(minRect, maxRect, minArea, maxArea); } /// <summary> /// Constrain the current target position to be within panel bounds. /// </summary> public bool ConstrainTargetToBounds (Transform target, ref Bounds targetBounds, bool immediate) { Vector3 min = targetBounds.min; Vector3 max = targetBounds.max; float ps = 1f; if (mClipping == UIDrawCall.Clipping.None) { UIRoot rt = root; if (rt != null) ps = rt.pixelSizeAdjustment; } if (ps != 1f) { min /= ps; max /= ps; } Vector3 offset = CalculateConstrainOffset(min, max) * ps; if (offset.sqrMagnitude > 0f) { if (immediate) { target.localPosition += offset; targetBounds.center += offset; SpringPosition sp = target.GetComponent<SpringPosition>(); if (sp != null) sp.enabled = false; } else { SpringPosition sp = SpringPosition.Begin(target.gameObject, target.localPosition + offset, 13f); sp.ignoreTimeScale = true; sp.worldSpace = false; } return true; } return false; } /// <summary> /// Constrain the specified target to be within the panel's bounds. /// </summary> public bool ConstrainTargetToBounds (Transform target, bool immediate) { Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(cachedTransform, target); return ConstrainTargetToBounds(target, ref bounds, immediate); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans) { return Find(trans, false, -1); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans, bool createIfMissing) { return Find(trans, createIfMissing, -1); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans, bool createIfMissing, int layer) { UIPanel panel = NGUITools.FindInParents<UIPanel>(trans); if (panel != null) return panel; while (trans.parent != null) trans = trans.parent; return createIfMissing ? NGUITools.CreateUI(trans, false, layer) : null; } /// <summary> /// Get the size of the game window in pixels. /// </summary> public Vector2 GetWindowSize () { UIRoot rt = root; Vector2 size = NGUITools.screenSize; if (rt != null) size *= rt.GetPixelSizeAdjustment(Mathf.RoundToInt(size.y)); return size; } /// <summary> /// Panel's size -- which is either the clipping rect, or the screen dimensions. /// </summary> public Vector2 GetViewSize () { if (mClipping != UIDrawCall.Clipping.None) return new Vector2(mClipRange.z, mClipRange.w); Vector2 size = NGUITools.screenSize; //UIRoot rt = root; //if (rt != null) size *= rt.pixelSizeAdjustment; return size; } #if UNITY_EDITOR /// <summary> /// Draw a visible pink outline for the clipped area. /// </summary> void OnDrawGizmos () { if (anchorCamera == null) return; bool clip = (mClipping != UIDrawCall.Clipping.None); Transform t = clip ? transform : mCam.transform; Vector3[] corners = worldCorners; for (int i = 0; i < 4; ++i) corners[i] = t.InverseTransformPoint(corners[i]); Vector3 pos = Vector3.Lerp(corners[0], corners[2], 0.5f); Vector3 size = corners[2] - corners[0]; GameObject go = UnityEditor.Selection.activeGameObject; bool isUsingThisPanel = (go != null) && (NGUITools.FindInParents<UIPanel>(go) == this); bool isSelected = (UnityEditor.Selection.activeGameObject == gameObject); bool detailedView = (isSelected && isUsingThisPanel); bool detailedClipped = detailedView && mClipping == UIDrawCall.Clipping.SoftClip; Gizmos.matrix = t.localToWorldMatrix; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (isUsingThisPanel && !clip && mCam.isOrthoGraphic) #else if (isUsingThisPanel && !clip && mCam.orthographic) #endif { UIRoot rt = root; if (rt != null && rt.scalingStyle != UIRoot.Scaling.Flexible) { float width = rt.manualWidth; float height = rt.manualHeight; float x0 = -0.5f * width; float y0 = -0.5f * height; float x1 = x0 + width; float y1 = y0 + height; corners[0] = new Vector3(x0, y0); corners[1] = new Vector3(x0, y1); corners[2] = new Vector3(x1, y1); corners[3] = new Vector3(x1, y0); Vector3 szPos = Vector3.Lerp(corners[0], corners[2], 0.5f); Vector3 szSize = corners[2] - corners[0]; Gizmos.color = new Color(0f, 0.75f, 1f); Gizmos.DrawWireCube(szPos, szSize); } } Gizmos.color = (isUsingThisPanel && !detailedClipped) ? new Color(1f, 0f, 0.5f) : new Color(0.5f, 0f, 0.5f); Gizmos.DrawWireCube(pos, size); if (detailedView) { if (detailedClipped) { Gizmos.color = new Color(1f, 0f, 0.5f); size.x -= mClipSoftness.x * 2f; size.y -= mClipSoftness.y * 2f; Gizmos.DrawWireCube(pos, size); } } } #endif // UNITY_EDITOR } Assets/NGUI/Scripts/UI/UIPanel.cs(907,44): error CS0619: `UnityEngine.RuntimePlatform.WindowsWebPlayer' is obsolete: `WebPlayer export is no longer supported in Unity 5.4+.' 这个代码是Unity5.3.3f1版本的,现在升级到Unity 2017.4.0f1 (64-bit)版本
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值